From e3e5a25605464511403949df55e7777e2a013b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Papp?= Date: Tue, 11 Aug 2026 17:55:19 +0200 Subject: [PATCH] [client] Read the relay transport before the sweeper wraps the connection sweptConn embeds net.Conn, so it does not promote Protocol() from the concrete relay connection. Asserting transportConn on the wrapper always failed and left c.transport empty. Read the transport off the dialed connection first, then wrap it. --- shared/relay/client/client.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/relay/client/client.go b/shared/relay/client/client.go index cec8393a0..a398b0e70 100644 --- a/shared/relay/client/client.go +++ b/shared/relay/client/client.go @@ -427,13 +427,16 @@ func (c *Client) connect(ctx context.Context) (*RelayAddr, error) { return nil, fmt.Errorf("dial via FQDN: %w", err) } } - conn = c.sweeper.WrapConn(conn) - c.relayConn = conn - c.datagramFallbackTriggered.Store(false) + // Read the transport off the concrete connection: the sweeper's wrapper + // embeds net.Conn only, so it does not promote Protocol(). if tc, ok := conn.(transportConn); ok { c.transport = tc.Protocol() } + conn = c.sweeper.WrapConn(conn) + c.relayConn = conn + c.datagramFallbackTriggered.Store(false) + instanceURL, err := c.handShake(ctx) if err != nil { cErr := conn.Close()