From 02f856dedd67d1c293938baefee188cf4d1e659d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 11 Nov 2022 15:06:34 +0100 Subject: [PATCH] Add functions for incoming multi-stream connections (#2982) They're unused in practice, but there's no reason to not allow ingoing multi-stream connections in the underlying state machine. cc https://github.com/paritytech/smoldot/issues/2802 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- src/libp2p/collection.rs | 3 ++- src/libp2p/collection/multi_stream.rs | 16 +++++++++------ src/libp2p/peers.rs | 29 +++++++++++++++++++++++++++ src/network/service.rs | 24 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/libp2p/collection.rs b/src/libp2p/collection.rs index 2bb24e2d92..b1167b0d12 100644 --- a/src/libp2p/collection.rs +++ b/src/libp2p/collection.rs @@ -406,11 +406,11 @@ where /// /// Must be passed the moment (as a `TNow`) when the connection as been established, in order /// to determine when the handshake timeout expires. - // TODO: add an is_initiator parameter? right now we're always implicitly the initiator pub fn insert_multi_stream( &mut self, now: TNow, handshake_kind: MultiStreamHandshakeKind, + is_initiator: bool, user_data: TConn, ) -> (ConnectionId, MultiStreamConnectionTask) where @@ -421,6 +421,7 @@ where let connection_task = MultiStreamConnectionTask::new( self.randomness_seeds.gen(), + is_initiator, now, handshake_kind, self.max_inbound_substreams, diff --git a/src/libp2p/collection/multi_stream.rs b/src/libp2p/collection/multi_stream.rs index 312ea4efe2..c300e18c93 100644 --- a/src/libp2p/collection/multi_stream.rs +++ b/src/libp2p/collection/multi_stream.rs @@ -140,6 +140,7 @@ where // a function only called from the parent module. pub(super) fn new( randomness_seed: [u8; 32], + is_initiator: bool, now: TNow, handshake_kind: MultiStreamHandshakeKind, max_inbound_substreams: usize, @@ -151,7 +152,6 @@ where // In the WebRTC handshake, the Noise prologue must be set to `"libp2p-webrtc-noise:"` // followed with the multihash-encoded fingerprints of the initiator's certificate // and the receiver's certificate. - // TODO: we currently assume that the local node is always the initiator // See . let noise_prologue = { let MultiStreamHandshakeKind::WebRtc { @@ -165,10 +165,13 @@ where + remote_tls_certificate_multihash.len(), ); out.extend_from_slice(PREFIX); - // Since smoldot always acts as a client (at least right now), we don't need to change - // the order of fingerprints. - out.extend_from_slice(&local_tls_certificate_multihash); - out.extend_from_slice(&remote_tls_certificate_multihash); + if is_initiator { + out.extend_from_slice(&local_tls_certificate_multihash); + out.extend_from_slice(&remote_tls_certificate_multihash); + } else { + out.extend_from_slice(&remote_tls_certificate_multihash); + out.extend_from_slice(&local_tls_certificate_multihash); + } out }; @@ -176,7 +179,8 @@ where connection: MultiStreamConnectionTaskInner::Handshake { handshake: Some(noise::HandshakeInProgress::new(noise::Config { key: &noise_key, - is_initiator: false, // TODO: is_initiator? + // It's the "server" that initiates the Noise handshake. + is_initiator: !is_initiator, prologue: &noise_prologue, })), opened_substream: None, diff --git a/src/libp2p/peers.rs b/src/libp2p/peers.rs index 6df9ce7218..59b0272dc1 100644 --- a/src/libp2p/peers.rs +++ b/src/libp2p/peers.rs @@ -977,6 +977,34 @@ where (connection_id, connection_task) } + /// Inserts a multi-stream incoming connection in the state machine. + /// + /// This connection hasn't finished handshaking and the [`PeerId`] of the remote isn't known + /// yet. + /// + /// Must be passed the moment (as a `TNow`) when the connection as been established, in order + /// to determine when the handshake timeout expires. + pub fn add_multi_stream_incoming_connection( + &mut self, + when_connected: TNow, + handshake_kind: MultiStreamHandshakeKind, + user_data: TConn, + ) -> (ConnectionId, MultiStreamConnectionTask) + where + TSubId: Clone + PartialEq + Eq + Hash, + { + self.inner.insert_multi_stream( + when_connected, + handshake_kind, + false, + Connection { + peer_index: None, + user_data, + outbound: false, + }, + ) + } + /// Inserts a multi-stream outgoing connection in the state machine. /// /// This connection hasn't finished handshaking, and the [`PeerId`] of the remote isn't known @@ -1003,6 +1031,7 @@ where let (connection_id, connection_task) = self.inner.insert_multi_stream( when_connected, handshake_kind, + true, Connection { peer_index: Some(peer_index), user_data, diff --git a/src/network/service.rs b/src/network/service.rs index a5e990cf40..34b36f9821 100644 --- a/src/network/service.rs +++ b/src/network/service.rs @@ -496,6 +496,30 @@ where ) } + /// Adds a multi-stream incoming connection to the state machine. + /// + /// This connection hasn't finished handshaking and the [`PeerId`] of the remote isn't known + /// yet. + /// + /// Must be passed the moment (as a `TNow`) when the connection as been established, in order + /// to determine when the handshake timeout expires. + /// + /// The `remote_addr` is the address used to reach back the remote. In the case of TCP, it + /// contains the TCP dialing port of the remote. The remote can ask, through the `identify` + /// libp2p protocol, its own address, in which case we send it. + pub fn add_multi_stream_incoming_connection( + &mut self, + when_connected: TNow, + handshake_kind: MultiStreamHandshakeKind, + remote_addr: multiaddr::Multiaddr, + ) -> (ConnectionId, MultiStreamConnectionTask) + where + TSubId: Clone + PartialEq + Eq + Hash, + { + self.inner + .add_multi_stream_incoming_connection(when_connected, handshake_kind, remote_addr) + } + pub fn pull_message_to_connection( &mut self, ) -> Option<(ConnectionId, CoordinatorToConnection)> {