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.
80#[expect(deprecated)] // TODO: Remove when {In, Out}boundOpenInfo is fully removed.
81impl<L, R> ConnectionHandler for Either<L, R>
82where
83    L: ConnectionHandler,
84    R: ConnectionHandler,
85{
86    type FromBehaviour = Either<L::FromBehaviour, R::FromBehaviour>;
87    type ToBehaviour = Either<L::ToBehaviour, R::ToBehaviour>;
88    type InboundProtocol = Either<SendWrapper<L::InboundProtocol>, SendWrapper<R::InboundProtocol>>;
89    type OutboundProtocol =
90        Either<SendWrapper<L::OutboundProtocol>, SendWrapper<R::OutboundProtocol>>;
91    type InboundOpenInfo = Either<L::InboundOpenInfo, R::InboundOpenInfo>;
92    type OutboundOpenInfo = Either<L::OutboundOpenInfo, R::OutboundOpenInfo>;
93
94    fn listen_protocol(&self) -> SubstreamProtocol<Self::InboundProtocol, Self::InboundOpenInfo> {
95        match self {
96            Either::Left(a) => a
97                .listen_protocol()
98                .map_upgrade(|u| Either::Left(SendWrapper(u)))
99                .map_info(Either::Left),
100            Either::Right(b) => b
101                .listen_protocol()
102                .map_upgrade(|u| Either::Right(SendWrapper(u)))
103                .map_info(Either::Right),
104        }
105    }
106
107    fn on_behaviour_event(&mut self, event: Self::FromBehaviour) {
108        match (self, event) {
109            (Either::Left(handler), Either::Left(event)) => handler.on_behaviour_event(event),
110            (Either::Right(handler), Either::Right(event)) => handler.on_behaviour_event(event),
111            _ => unreachable!(),
112        }
113    }
114
115    fn connection_keep_alive(&self) -> bool {
116        match self {
117            Either::Left(handler) => handler.connection_keep_alive(),
118            Either::Right(handler) => handler.connection_keep_alive(),
119        }
120    }
121
122    fn poll(
123        &mut self,
124        cx: &mut Context<'_>,
125    ) -> Poll<
126        ConnectionHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::ToBehaviour>,
127    > {
128        let event = match self {
129            Either::Left(handler) => futures::ready!(handler.poll(cx))
130                .map_custom(Either::Left)
131                .map_protocol(|p| Either::Left(SendWrapper(p)))
132                .map_outbound_open_info(Either::Left),
133            Either::Right(handler) => futures::ready!(handler.poll(cx))
134                .map_custom(Either::Right)
135                .map_protocol(|p| Either::Right(SendWrapper(p)))
136                .map_outbound_open_info(Either::Right),
137        };
138
139        Poll::Ready(event)
140    }
141
142    fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll<Option<Self::ToBehaviour>> {
143        let event = match self {
144            Either::Left(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Left),
145            Either::Right(handler) => futures::ready!(handler.poll_close(cx)).map(Either::Right),
146        };
147
148        Poll::Ready(event)
149    }
150
151    fn on_connection_event(
152        &mut self,
153        event: ConnectionEvent<
154            Self::InboundProtocol,
155            Self::OutboundProtocol,
156            Self::InboundOpenInfo,
157            Self::OutboundOpenInfo,
158        >,
159    ) {
160        match event {
161            ConnectionEvent::FullyNegotiatedInbound(fully_negotiated_inbound) => {
162                match (fully_negotiated_inbound.transpose(), self) {
163                    (Either::Left(fully_negotiated_inbound), Either::Left(handler)) => handler
164                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
165                            fully_negotiated_inbound,
166                        )),
167                    (Either::Right(fully_negotiated_inbound), Either::Right(handler)) => handler
168                        .on_connection_event(ConnectionEvent::FullyNegotiatedInbound(
169                            fully_negotiated_inbound,
170                        )),
171                    _ => unreachable!(),
172                }
173            }
174            ConnectionEvent::FullyNegotiatedOutbound(fully_negotiated_outbound) => {
175                match (fully_negotiated_outbound.transpose(), self) {
176                    (Either::Left(fully_negotiated_outbound), Either::Left(handler)) => handler
177                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
178                            fully_negotiated_outbound,
179                        )),
180                    (Either::Right(fully_negotiated_outbound), Either::Right(handler)) => handler
181                        .on_connection_event(ConnectionEvent::FullyNegotiatedOutbound(
182                            fully_negotiated_outbound,
183                        )),
184                    _ => unreachable!(),
185                }
186            }
187            ConnectionEvent::DialUpgradeError(dial_upgrade_error) => {
188                match (dial_upgrade_error.transpose(), self) {
189                    (Either::Left(dial_upgrade_error), Either::Left(handler)) => handler
190                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
191                    (Either::Right(dial_upgrade_error), Either::Right(handler)) => handler
192                        .on_connection_event(ConnectionEvent::DialUpgradeError(dial_upgrade_error)),
193                    _ => unreachable!(),
194                }
195            }
196            ConnectionEvent::ListenUpgradeError(listen_upgrade_error) => {
197                match (listen_upgrade_error.transpose(), self) {
198                    (Either::Left(listen_upgrade_error), Either::Left(handler)) => handler
199                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
200                            listen_upgrade_error,
201                        )),
202                    (Either::Right(listen_upgrade_error), Either::Right(handler)) => handler
203                        .on_connection_event(ConnectionEvent::ListenUpgradeError(
204                            listen_upgrade_error,
205                        )),
206                    _ => unreachable!(),
207                }
208            }
209            ConnectionEvent::AddressChange(address_change) => match self {
210                Either::Left(handler) => {
211                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
212                }
213                Either::Right(handler) => {
214                    handler.on_connection_event(ConnectionEvent::AddressChange(address_change))
215                }
216            },
217            ConnectionEvent::LocalProtocolsChange(supported_protocols) => match self {
218                Either::Left(handler) => handler.on_connection_event(
219                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
220                ),
221                Either::Right(handler) => handler.on_connection_event(
222                    ConnectionEvent::LocalProtocolsChange(supported_protocols),
223                ),
224            },
225            ConnectionEvent::RemoteProtocolsChange(supported_protocols) => match self {
226                Either::Left(handler) => handler.on_connection_event(
227                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
228                ),
229                Either::Right(handler) => handler.on_connection_event(
230                    ConnectionEvent::RemoteProtocolsChange(supported_protocols),
231                ),
232            },
233        }
234    }
235}