libp2p_swarm/handler/
either.rs

1// Copyright 2021 Protocol Labs.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use std::task::{Context, Poll};
22
23use either::Either;
24use futures::future;
25
26use crate::{
27    handler::{
28        ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound,
29        InboundUpgradeSend, ListenUpgradeError, SubstreamProtocol,
30    },
31    upgrade::SendWrapper,
32};
33
34impl<LIP, RIP, LIOI, RIOI>
35    FullyNegotiatedInbound<Either<SendWrapper<LIP>, SendWrapper<RIP>>, Either<LIOI, RIOI>>
36where
37    RIP: InboundUpgradeSend,
38    LIP: InboundUpgradeSend,
39{
40    pub(crate) fn transpose(
41        self,
42    ) -> Either<FullyNegotiatedInbound<LIP, LIOI>, FullyNegotiatedInbound<RIP, RIOI>> {
43        match self {
44            FullyNegotiatedInbound {
45                protocol: future::Either::Left(protocol),
46                info: Either::Left(info),
47            } => Either::Left(FullyNegotiatedInbound { protocol, info }),
48            FullyNegotiatedInbound {
49                protocol: future::Either::Right(protocol),
50                info: Either::Right(info),
51            } => Either::Right(FullyNegotiatedInbound { protocol, info }),
52            _ => unreachable!(),
53        }
54    }
55}
56
57impl<LIP, RIP, LIOI, RIOI>
58    ListenUpgradeError<Either<LIOI, RIOI>, Either<SendWrapper<LIP>, SendWrapper<RIP>>>
59where
60    RIP: InboundUpgradeSend,
61    LIP: InboundUpgradeSend,
62{
63    fn transpose(self) -> Either<ListenUpgradeError<LIOI, LIP>, ListenUpgradeError<RIOI, RIP>> {
64        match self {
65            ListenUpgradeError {
66                error: Either::Left(error),
67                info: Either::Left(info),
68            } => Either::Left(ListenUpgradeError { error, info }),
69            ListenUpgradeError {
70                error: Either::Right(error),
71                info: Either::Right(info),
72            } => Either::Right(ListenUpgradeError { error, info }),
73            _ => unreachable!(),
74        }
75    }
76}
77
78/// Implementation of a [`ConnectionHandler`] that represents either of two [`ConnectionHandler`]
79/// implementations.
80impl<L, R> ConnectionHandler for Either<L, R>
81where
82    L: ConnectionHandler,
83    R: ConnectionHandler,
84{
85    type FromBehaviour = Either<L::FromBehaviour, R::FromBehaviour>;
86    type ToBehaviour = Either<L::ToBehaviour, R::ToBehaviour>;
87    type InboundProtocol = Either<SendWrapper<L::InboundProtocol>, SendWrapper<R::InboundProtocol>>;
88    type OutboundProtocol =
89        Either<SendWrapper<L::OutboundProtocol>, SendWrapper<R::OutboundProtocol>>;
90    type InboundOpenInfo = Either<L::InboundOpenInfo, R::InboundOpenInfo>;
91    type OutboundOpenInfo = Either<L::OutboundOpenInfo, R::OutboundOpenInfo>;
92
93    fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
94        match self {
95            Either::Left(a) => a
96                .listen_protocol()
97                .map_upgrade(|u| Either::Left(SendWrapper(u)))
98                .map_info(Either::Left),
99            Either::Right(b) => b
100                .listen_protocol()
101                .map_upgrade(|u| Either::Right(SendWrapper(u)))
102                .map_info(Either::Right),
103        }
104    }
105
106    fn on_behaviour_event(&mut self, event: Self::FromBehaviour) {
107        match (self, event) {
108            (Either::Left(handler), Either::Left(event)) => handler.on_behaviour_event(event),
109            (Either::Right(handler), Either::Right(event)) => handler.on_behaviour_event(event),
110            _ => unreachable!(),
111        }
112    }
113
114    fn connection_keep_alive(&self) -> bool {
115        match self {
116            Either::Left(handler) => handler.connection_keep_alive(),
117            Either::Right(handler) => handler.connection_keep_alive(),
118        }
119    }
120
121    fn poll(
122        &mut self,
123        cx: &mut Context<'_>,
124    ) -> Poll<
125        ConnectionHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::ToBehaviour>,
126    > {
127        let event = match self {
128            Either::Left(handler) => futures::ready!(handler.poll(cx))
129                .map_custom(Either::Left)
130                .map_protocol(|p| Either::Left(SendWrapper(p)))
131                .map_outbound_open_info(Either::Left),
132            Either::Right(handler) => futures::ready!(handler.poll(cx))
133                .map_custom(Either::Right)
134                .map_protocol(|p| Either::Right(SendWrapper(p)))
135                .map_outbound_open_info(Either::Right),
136        };
137
138        Poll::Ready(event)
139    }
140
141    fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll<Option<Self::ToBehaviour>> {
142        let event = match self {
143            Either::Left(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Left),
144            Either::Right(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Right),
145        };
146
147        Poll::Ready(event)
148    }
149
150    fn on_connection_event(
151        &mut self,
152        event: ConnectionEvent<
153            Self::InboundProtocol,
154            Self::OutboundProtocol,
155            Self::InboundOpenInfo,
156            Self::OutboundOpenInfo,
157        >,
158    ) {
159        match event {
160            ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => {
161                match (fully_negotiated_inbound.transpose(), self) {
162                    (Either::Left(fully_negotiated_inbound), Either::Left(handler)) => handler
163                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
164                            fully_negotiated_inbound,
165                        )),
166                    (Either::Right(fully_negotiated_inbound), Either::Right(handler)) => handler
167                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
168                            fully_negotiated_inbound,
169                        )),
170                    _ => unreachable!(),
171                }
172            }
173            ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => {
174                match (fully_negotiated_outbound.transpose(), self) {
175                    (Either::Left(fully_negotiated_outbound), Either::Left(handler)) => handler
176                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
177                            fully_negotiated_outbound,
178                        )),
179                    (Either::Right(fully_negotiated_outbound), Either::Right(handler)) => handler
180                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
181                            fully_negotiated_outbound,
182                        )),
183                    _ => unreachable!(),
184                }
185            }
186            ConnectionEvent::DialUpgradeError(dial_upgrade_error) => {
187                match (dial_upgrade_error.transpose(), self) {
188                    (Either::Left(dial_upgrade_error), Either::Left(handler)) => handler
189                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
190                    (Either::Right(dial_upgrade_error), Either::Right(handler)) => handler
191                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
192                    _ => unreachable!(),
193                }
194            }
195            ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => {
196                match (listen_upgrade_error.transpose(), self) {
197                    (Either::Left(listen_upgrade_error), Either::Left(handler)) => handler
198                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
199                            listen_upgrade_error,
200                        )),
201                    (Either::Right(listen_upgrade_error), Either::Right(handler)) => handler
202                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
203                            listen_upgrade_error,
204                        )),
205                    _ => unreachable!(),
206                }
207            }
208            ConnectionEvent::AddressChange(address_change) => match self {
209                Either::Left(handler) => {
210                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
211                }
212                Either::Right(handler) => {
213                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
214                }
215            },
216            ConnectionEvent::LocalProtocolsChange(supported_protocols) => match self {
217                Either::Left(handler) => handler.on_connection_event(
218                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
219                ),
220                Either::Right(handler) => handler.on_connection_event(
221                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
222                ),
223            },
224            ConnectionEvent::RemoteProtocolsChange(supported_protocols) => match self {
225                Either::Left(handler) => handler.on_connection_event(
226                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
227                ),
228                Either::Right(handler) => handler.on_connection_event(
229                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
230                ),
231            },
232        }
233    }
234}