From a186c9d07d6c2dc0a24badc4905fe15c6b6ef89e Mon Sep 17 00:00:00 2001 From: michel Date: Sun, 19 Jul 2026 17:48:50 +0200 Subject: [PATCH] fix: pierce the firewall on server-brokered reverse connects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the server asks us to connect to a peer (a ConnectToPeer we receive, carrying the server's correlation token), we dial that peer and must announce ourselves with a PierceFirewall quoting the token — not a PeerInit — so the remote peer can correlate its own indirect request (search-result / upload delivery). The outbound handshake now sends PierceFirewall when the peer carries a server token and PeerInit only for direct GetPeerAddress dials (token None). Direct and firewalled e2e paths are unchanged. --- soulseek-rs-lib/src/actor/peer_actor.rs | 30 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/soulseek-rs-lib/src/actor/peer_actor.rs b/soulseek-rs-lib/src/actor/peer_actor.rs index d902ccf..e3ca79a 100644 --- a/soulseek-rs-lib/src/actor/peer_actor.rs +++ b/soulseek-rs-lib/src/actor/peer_actor.rs @@ -586,19 +586,27 @@ impl PeerActor { return; }; - // Connections we initiated must announce themselves with a PeerInit - // (peer code 1); inbound peers already sent us theirs, so we stay - // silent for them. `get_buffer` prepends the length prefix the peer's - // MessageReader expects. + // Connections we initiated must announce themselves; inbound peers + // already sent us theirs, so we stay silent for them. A direct dial + // (resolved via GetPeerAddress, token None) sends a PeerInit; a dial we + // make because the server asked us to (a brokered ConnectToPeer carries + // the server's token) must instead PierceFirewall with that token so + // the remote peer can correlate its own request. `get_buffer` prepends + // the length prefix the peer's MessageReader expects. if self.outbound { - let init = MessageFactory::build_peer_init_message( - &self.own_username, - connection_type, - token.unwrap_or(0), - ); - if let Err(e) = stream.write_all(&init.get_buffer()) { + let handshake = match token { + Some(server_token) => { + MessageFactory::build_pierce_firewall_message(server_token) + } + None => MessageFactory::build_peer_init_message( + &self.own_username, + connection_type, + 0, + ), + }; + if let Err(e) = stream.write_all(&handshake.get_buffer()) { error!( - "[peer:{}] Failed to send PeerInit handshake: {}", + "[peer:{}] Failed to send outbound handshake: {}", username, e ); self.disconnect_with_error(e);