libp2p_swarm/behaviour/
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 libp2p_core::{transport::PortUse, Endpoint, Multiaddr};
25use libp2p_identity::PeerId;
26
27use crate::{
28    behaviour::{self, NetworkBehaviour, ToSwarm},
29    connection::ConnectionId,
30    ConnectionDenied, THandler, THandlerInEvent, THandlerOutEvent,
31};
32
33/// Implementation of [`NetworkBehaviour`] that can be either of two implementations.
34impl<L, R> NetworkBehaviour for Either<L, R>
35where
36    L: NetworkBehaviour,
37    R: NetworkBehaviour,
38{
39    type ConnectionHandler = Either<THandler<L>, THandler<R>>;
40    type ToSwarm = Either<L::ToSwarm, R::ToSwarm>;
41
42    fn handle_pending_inbound_connection(
43        &mut self,
44        id: ConnectionId,
45        local_addr: &Multiaddr,
46        remote_addr: &Multiaddr,
47    ) -> Result<(), ConnectionDenied> {
48        match self {
49            Either::Left(a) => a.handle_pending_inbound_connection(id, local_addr, remote_addr),
50            Either::Right(b) => b.handle_pending_inbound_connection(id, local_addr, remote_addr),
51        }
52    }
53
54    fn handle_established_inbound_connection(
55        &mut self,
56        connection_id: ConnectionId,
57        peer: PeerId,
58        local_addr: &Multiaddr,
59        remote_addr: &Multiaddr,
60    ) -> Result<THandler<Self>, ConnectionDenied> {
61        let handler = match self {
62            Either::Left(inner) => Either::Left(inner.handle_established_inbound_connection(
63                connection_id,
64                peer,
65                local_addr,
66                remote_addr,
67            )?),
68            Either::Right(inner) => Either::Right(inner.handle_established_inbound_connection(
69                connection_id,
70                peer,
71                local_addr,
72                remote_addr,
73            )?),
74        };
75
76        Ok(handler)
77    }
78
79    fn handle_pending_outbound_connection(
80        &mut self,
81        connection_id: ConnectionId,
82        maybe_peer: Option<PeerId>,
83        addresses: &[Multiaddr],
84        effective_role: Endpoint,
85    ) -> Result<Vec<Multiaddr>, ConnectionDenied> {
86        let addresses = match self {
87            Either::Left(inner) => inner.handle_pending_outbound_connection(
88                connection_id,
89                maybe_peer,
90                addresses,
91                effective_role,
92            )?,
93            Either::Right(inner) => inner.handle_pending_outbound_connection(
94                connection_id,
95                maybe_peer,
96                addresses,
97                effective_role,
98            )?,
99        };
100
101        Ok(addresses)
102    }
103
104    fn handle_established_outbound_connection(
105        &mut self,
106        connection_id: ConnectionId,
107        peer: PeerId,
108        addr: &Multiaddr,
109        role_override: Endpoint,
110        port_use: PortUse,
111    ) -> Result<THandler<Self>, ConnectionDenied> {
112        let handler = match self {
113            Either::Left(inner) => Either::Left(inner.handle_established_outbound_connection(
114                connection_id,
115                peer,
116                addr,
117                role_override,
118                port_use,
119            )?),
120            Either::Right(inner) => Either::Right(inner.handle_established_outbound_connection(
121                connection_id,
122                peer,
123                addr,
124                role_override,
125                port_use,
126            )?),
127        };
128
129        Ok(handler)
130    }
131
132    fn on_swarm_event(&mut self, event: behaviour::FromSwarm) {
133        match self {
134            Either::Left(b) => b.on_swarm_event(event),
135            Either::Right(b) => b.on_swarm_event(event),
136        }
137    }
138
139    fn on_connection_handler_event(
140        &mut self,
141        peer_id: PeerId,
142        connection_id: ConnectionId,
143        event: THandlerOutEvent<Self>,
144    ) {
145        match (self, event) {
146            (Either::Left(left), Either::Left(event)) => {
147                left.on_connection_handler_event(peer_id, connection_id, event);
148            }
149            (Either::Right(right), Either::Right(event)) => {
150                right.on_connection_handler_event(peer_id, connection_id, event);
151            }
152            _ => unreachable!(),
153        }
154    }
155
156    fn poll(
157        &mut self,
158        cx: &mut Context<'_>,
159    ) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
160        let event = match self {
161            Either::Left(behaviour) => futures::ready!(behaviour.poll(cx))
162                .map_out(Either::Left)
163                .map_in(Either::Left),
164            Either::Right(behaviour) => futures::ready!(behaviour.poll(cx))
165                .map_out(Either::Right)
166                .map_in(Either::Right),
167        };
168
169        Poll::Ready(event)
170    }
171}