ant_libp2p_core/
connection.rs

1// Copyright 2020 Parity Technologies (UK) Ltd.
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::{
22    multiaddr::{Multiaddr, Protocol},
23    transport::PortUse,
24};
25
26/// The endpoint roles associated with a peer-to-peer communication channel.
27#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
28pub enum Endpoint {
29    /// The socket comes from a dialer.
30    Dialer,
31    /// The socket comes from a listener.
32    Listener,
33}
34
35impl std::ops::Not for Endpoint {
36    type Output = Endpoint;
37
38    fn not(self) -> Self::Output {
39        match self {
40            Endpoint::Dialer => Endpoint::Listener,
41            Endpoint::Listener => Endpoint::Dialer,
42        }
43    }
44}
45
46impl Endpoint {
47    /// Is this endpoint a dialer?
48    pub fn is_dialer(self) -> bool {
49        matches!(self, Endpoint::Dialer)
50    }
51
52    /// Is this endpoint a listener?
53    pub fn is_listener(self) -> bool {
54        matches!(self, Endpoint::Listener)
55    }
56}
57
58/// The endpoint roles associated with an established peer-to-peer connection.
59#[derive(PartialEq, Eq, Debug, Clone, Hash)]
60pub enum ConnectedPoint {
61    /// We dialed the node.
62    Dialer {
63        /// Multiaddress that was successfully dialed.
64        address: Multiaddr,
65        /// Whether the role of the local node on the connection should be
66        /// overridden. I.e. whether the local node should act as a listener on
67        /// the outgoing connection.
68        ///
69        /// This option is needed for NAT and firewall hole punching.
70        ///
71        /// - [`Endpoint::Dialer`] represents the default non-overriding option.
72        ///
73        /// - [`Endpoint::Listener`] represents the overriding option. Realization depends on the
74        ///   transport protocol. E.g. in the case of TCP, both endpoints dial each other,
75        ///   resulting in a _simultaneous open_ TCP connection. On this new connection both
76        ///   endpoints assume to be the dialer of the connection. This is problematic during the
77        ///   connection upgrade process where an upgrade assumes one side to be the listener. With
78        ///   the help of this option, both peers can negotiate the roles (dialer and listener) for
79        ///   the new connection ahead of time, through some external channel, e.g. the DCUtR
80        ///   protocol, and thus have one peer dial the other and upgrade the connection as a
81        ///   dialer and one peer dial the other and upgrade the connection _as a listener_
82        ///   overriding its role.
83        role_override: Endpoint,
84        /// Whether the port for the outgoing connection was reused from a listener
85        /// or a new port was allocated. This is useful for address translation.
86        ///
87        /// The port use is implemented on a best-effort basis. It is not guaranteed
88        /// that [`PortUse::Reuse`] actually reused a port. A good example is the case
89        /// where there is no listener available to reuse a port from.
90        port_use: PortUse,
91    },
92    /// We received the node.
93    Listener {
94        /// Local connection address.
95        local_addr: Multiaddr,
96        /// Address used to send back data to the remote.
97        send_back_addr: Multiaddr,
98    },
99}
100
101impl From<&'_ ConnectedPoint> for Endpoint {
102    fn from(endpoint: &'_ ConnectedPoint) -> Endpoint {
103        endpoint.to_endpoint()
104    }
105}
106
107impl From<ConnectedPoint> for Endpoint {
108    fn from(endpoint: ConnectedPoint) -> Endpoint {
109        endpoint.to_endpoint()
110    }
111}
112
113impl ConnectedPoint {
114    /// Turns the `ConnectedPoint` into the corresponding `Endpoint`.
115    pub fn to_endpoint(&self) -> Endpoint {
116        match self {
117            ConnectedPoint::Dialer { .. } => Endpoint::Dialer,
118            ConnectedPoint::Listener { .. } => Endpoint::Listener,
119        }
120    }
121
122    /// Returns true if we are `Dialer`.
123    pub fn is_dialer(&self) -> bool {
124        match self {
125            ConnectedPoint::Dialer { .. } => true,
126            ConnectedPoint::Listener { .. } => false,
127        }
128    }
129
130    /// Returns true if we are `Listener`.
131    pub fn is_listener(&self) -> bool {
132        match self {
133            ConnectedPoint::Dialer { .. } => false,
134            ConnectedPoint::Listener { .. } => true,
135        }
136    }
137
138    /// Returns true if the connection is relayed.
139    pub fn is_relayed(&self) -> bool {
140        match self {
141            ConnectedPoint::Dialer {
142                address,
143                role_override: _,
144                port_use: _,
145            } => address,
146            ConnectedPoint::Listener { local_addr, .. } => local_addr,
147        }
148        .iter()
149        .any(|p| p == Protocol::P2pCircuit)
150    }
151
152    /// Returns the address of the remote stored in this struct.
153    ///
154    /// For `Dialer`, this returns `address`. For `Listener`, this returns `send_back_addr`.
155    ///
156    /// Note that the remote node might not be listening on this address and hence the address might
157    /// not be usable to establish new connections.
158    pub fn get_remote_address(&self) -> &Multiaddr {
159        match self {
160            ConnectedPoint::Dialer { address, .. } => address,
161            ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
162        }
163    }
164
165    /// Modifies the address of the remote stored in this struct.
166    ///
167    /// For `Dialer`, this modifies `address`. For `Listener`, this modifies `send_back_addr`.
168    pub fn set_remote_address(&mut self, new_address: Multiaddr) {
169        match self {
170            ConnectedPoint::Dialer { address, .. } => *address = new_address,
171            ConnectedPoint::Listener { send_back_addr, .. } => *send_back_addr = new_address,
172        }
173    }
174}