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 crate::handler::{
22    ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, FullyNegotiatedInbound,
23    InboundUpgradeSend, ListenUpgradeError, SubstreamProtocol,
24};
25use crate::upgrade::SendWrapper;
26use either::Either;
27use futures::future;
28use std::task::{Context, Poll};
29
30impl<LIP, RIP, LIOI, RIOI>
31    FullyNegotiatedInbound<Either<SendWrapper<LIP>, SendWrapper<RIP>>, Either<LIOI, RIOI>>
32where
33    RIP: InboundUpgradeSend,
34    LIP: InboundUpgradeSend,
35{
36    pub(crate) fn transpose(
37        self,
38    ) -> Either<FullyNegotiatedInbound<LIP, LIOI>, FullyNegotiatedInbound<RIP, RIOI>> {
39        match self {
40            FullyNegotiatedInbound {
41                protocol: future::Either::Left(protocol),
42                info: Either::Left(info),
43            } => Either::Left(FullyNegotiatedInbound { protocol, info }),
44            FullyNegotiatedInbound {
45                protocol: future::Either::Right(protocol),
46                info: Either::Right(info),
47            } => Either::Right(FullyNegotiatedInbound { protocol, info }),
48            _ => unreachable!(),
49        }
50    }
51}
52
53impl<LIP, RIP, LIOI, RIOI>
54    ListenUpgradeError<Either<LIOI, RIOI>, Either<SendWrapper<LIP>, SendWrapper<RIP>>>
55where
56    RIP: InboundUpgradeSend,
57    LIP: InboundUpgradeSend,
58{
59    fn transpose(self) -> Either<ListenUpgradeError<LIOI, LIP>, ListenUpgradeError<RIOI, RIP>> {
60        match self {
61            ListenUpgradeError {
62                error: Either::Left(error),
63                info: Either::Left(info),
64            } => Either::Left(ListenUpgradeError { error, info }),
65            ListenUpgradeError {
66                error: Either::Right(error),
67                info: Either::Right(info),
68            } => Either::Right(ListenUpgradeError { error, info }),
69            _ => unreachable!(),
70        }
71    }
72}
73
74/// Implementation of a [`ConnectionHandler`] that represents either of two [`ConnectionHandler`]
75/// implementations.
76impl<L, R> ConnectionHandler for Either<L, R>
77where
78    L: ConnectionHandler,
79    R: ConnectionHandler,
80{
81    type FromBehaviour = Either<L::FromBehaviour, R::FromBehaviour>;
82    type ToBehaviour = Either<L::ToBehaviour, R::ToBehaviour>;
83    type InboundProtocol = Either<SendWrapper<L::InboundProtocol>, SendWrapper<R::InboundProtocol>>;
84    type OutboundProtocol =
85        Either<SendWrapper<L::OutboundProtocol>, SendWrapper<R::OutboundProtocol>>;
86    type InboundOpenInfo = Either<L::InboundOpenInfo, R::InboundOpenInfo>;
87    type OutboundOpenInfo = Either<L::OutboundOpenInfo, R::OutboundOpenInfo>;
88
89    fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
90        match self {
91            Either::Left(a) => a
92                .listen_protocol()
93                .map_upgrade(|u| Either::Left(SendWrapper(u)))
94                .map_info(Either::Left),
95            Either::Right(b) => b
96                .listen_protocol()
97                .map_upgrade(|u| Either::Right(SendWrapper(u)))
98                .map_info(Either::Right),
99        }
100    }
101
102    fn on_behaviour_event(&mut self, event: Self::FromBehaviour) {
103        match (self, event) {
104            (Either::Left(handler), Either::Left(event)) => handler.on_behaviour_event(event),
105            (Either::Right(handler), Either::Right(event)) => handler.on_behaviour_event(event),
106            _ => unreachable!(),
107        }
108    }
109
110    fn connection_keep_alive(&self) -> bool {
111        match self {
112            Either::Left(handler) => handler.connection_keep_alive(),
113            Either::Right(handler) => handler.connection_keep_alive(),
114        }
115    }
116
117    fn poll(
118        &mut self,
119        cx: &mut Context<'_>,
120    ) -> Poll<
121        ConnectionHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::ToBehaviour>,
122    > {
123        let event = match self {
124            Either::Left(handler) => futures::ready!(handler.poll(cx))
125                .map_custom(Either::Left)
126                .map_protocol(|p| Either::Left(SendWrapper(p)))
127                .map_outbound_open_info(Either::Left),
128            Either::Right(handler) => futures::ready!(handler.poll(cx))
129                .map_custom(Either::Right)
130                .map_protocol(|p| Either::Right(SendWrapper(p)))
131                .map_outbound_open_info(Either::Right),
132        };
133
134        Poll::Ready(event)
135    }
136
137    fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll<Option<Self::ToBehaviour>> {
138        let event = match self {
139            Either::Left(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Left),
140            Either::Right(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Right),
141        };
142
143        Poll::Ready(event)
144    }
145
146    fn on_connection_event(
147        &mut self,
148        event: ConnectionEvent<
149            Self::InboundProtocol,
150            Self::OutboundProtocol,
151            Self::InboundOpenInfo,
152            Self::OutboundOpenInfo,
153        >,
154    ) {
155        match event {
156            ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => {
157                match (fully_negotiated_inbound.transpose(), self) {
158                    (Either::Left(fully_negotiated_inbound), Either::Left(handler)) => handler
159                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
160                            fully_negotiated_inbound,
161                        )),
162                    (Either::Right(fully_negotiated_inbound), Either::Right(handler)) => handler
163                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
164                            fully_negotiated_inbound,
165                        )),
166                    _ => unreachable!(),
167                }
168            }
169            ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => {
170                match (fully_negotiated_outbound.transpose(), self) {
171                    (Either::Left(fully_negotiated_outbound), Either::Left(handler)) => handler
172                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
173                            fully_negotiated_outbound,
174                        )),
175                    (Either::Right(fully_negotiated_outbound), Either::Right(handler)) => handler
176                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
177                            fully_negotiated_outbound,
178                        )),
179                    _ => unreachable!(),
180                }
181            }
182            ConnectionEvent::DialUpgradeError(dial_upgrade_error) => {
183                match (dial_upgrade_error.transpose(), self) {
184                    (Either::Left(dial_upgrade_error), Either::Left(handler)) => handler
185                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
186                    (Either::Right(dial_upgrade_error), Either::Right(handler)) => handler
187                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
188                    _ => unreachable!(),
189                }
190            }
191            ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => {
192                match (listen_upgrade_error.transpose(), self) {
193                    (Either::Left(listen_upgrade_error), Either::Left(handler)) => handler
194                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
195                            listen_upgrade_error,
196                        )),
197                    (Either::Right(listen_upgrade_error), Either::Right(handler)) => handler
198                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
199                            listen_upgrade_error,
200                        )),
201                    _ => unreachable!(),
202                }
203            }
204            ConnectionEvent::AddressChange(address_change) => match self {
205                Either::Left(handler) => {
206                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
207                }
208                Either::Right(handler) => {
209                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
210                }
211            },
212            ConnectionEvent::LocalProtocolsChange(supported_protocols) => match self {
213                Either::Left(handler) => handler.on_connection_event(
214                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
215                ),
216                Either::Right(handler) => handler.on_connection_event(
217                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
218                ),
219            },
220            ConnectionEvent::RemoteProtocolsChange(supported_protocols) => match self {
221                Either::Left(handler) => handler.on_connection_event(
222                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
223                ),
224                Either::Right(handler) => handler.on_connection_event(
225                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
226                ),
227            },
228        }
229    }
230}