feat: implement circuit-v2 client transport for relayed connections - #270
Merged
Conversation
Relayed peers were never reachable as connections. The relay client exchanges (makeReservation, connectViaRelay, handleStop) returned a bare StreamIO that nothing upgraded, no Transport accepted a p2p-circuit multiaddr, and the stop handler handed the raw stream to an application callback with no security handshake. A relayed Connection therefore could not exist in the pool. specs/relay/circuit-v2 states that once the hop/stop CONNECT exchange succeeds "the original stream becomes the relayed connection", which clients upgrade "with a security protocol and a multiplexer, just like they would e.g. upgrade a TCP connection". Add LibP2P.NAT.Relay.Transport, a Transport that claims p2p-circuit addresses: - transportDial reaches the relay, negotiates hop, sends CONNECT and returns the stream as a RawConnection, so the existing upgradeOutbound pipeline applies Noise and Yamux unchanged. - transportListen reserves on the relay and exposes inbound stop streams through listenerAccept, routing them into Switch.Listen.handleInbound so gating, resource limits, pooling, notifiers and teardown all apply. listenerAddr reports the reservation address, which puts the circuit address into switchListenAddrs for Identify to advertise. - Relayed connections are recognised by p2p-circuit in connRemoteAddr via the existing Relay.isRelayedAddr; Connection gains no new field. registerNATHandlers now registers the transport and returns the circuit state alongside the relay state. NATConfig loses ncOnRelayedStream: the stop stream is a connection, not an application stream, so there is no longer anything for that callback to own. The relay's advertised limit is still discarded (#269) and reservations are not refreshed before expiry (#268). Unblocks #258. Closes #266.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #266. Unblocks #258.
Problem
A relayed peer could never become a
Connection. The client-side relay exchanges returned a bareStreamIOthat nothing upgraded, noTransportaccepted ap2p-circuitmultiaddr, andregisterRelayStopHandlerhanded the raw stop stream to an application callback with no security handshake.That blocks #258: every acceptance criterion there that distinguishes a direct connection from a relay connection presupposes a relayed
ConnectioninswConnPool.Spec
specs/relay/circuit-v2: once thehop/stopCONNECT exchange succeeds, "the original stream becomes the relayed connection", which clients upgrade "with a security protocol and a multiplexer, just like they would e.g. upgrade a TCP connection".Change
New
LibP2P.NAT.Relay.Transport:hop, send CONNECT, return the stream as aRawConnection.dialNewInnerthen runs the existingupgradeOutbound, so Noise + Yamux apply unchanged.transportListenon<relayAddr>/p2p/<relay>/p2p-circuitmakes the reservation and exposes inboundstopstreams throughlistenerAccept. They flow intoSwitch.Listen.handleInbound, so gating, upgrade, resource limits, pooling, notifiers and teardown all apply without new code.listenerAddrreports the reservation address, which puts the circuit address intoswitchListenAddrsfor Identify to advertise.connRemoteAddrcontainsp2p-circuit(existingRelay.isRelayedAddr).Connectiongains no new field, so the address stays the single source of truth.registerNATHandlersnow registers the transport and returns(RelayState, CircuitState).Breaking change
NATConfig.ncOnRelayedStreamis removed. The stop stream is now a connection, not an application-owned stream, so there is nothing left for that callback to own.registerNATHandlersreturns a tuple.Tests
LibP2P.NAT.Relay.TransportSpec— address parsing andtransportCanDialin isolation, plus four end-to-end tests over three in-process switches on loopback TCP (relay R, target B reserving on R, dialer A):Connectionto B, and B sees the matching inbound relayed connectionRegistrationSpec's raw-byte bridging test is replaced by the above, which exercises the same path plus the security and muxer upgrade. Full suite: 1145 examples, 0 failures.Deliberately not in scope