From 9e75d5c73239ec5ae9d1180ef4106c4bca8a9760 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Sat, 11 Jul 2026 18:29:26 +0200 Subject: [PATCH] [client] Decouple ICE and relay workers from Conn via interfaces WorkerICE and WorkerRelay took a concrete *Conn back-pointer. Replace it with small callback interfaces (iceCallbacks, relayCallbacks) covering only the methods each worker invokes on the connection. WorkerICE also receives its portForwardManager as an explicit parameter instead of reaching into conn.portForwardManager. --- client/internal/peer/conn.go | 2 +- client/internal/peer/worker_ice.go | 45 ++++++++++++++++------------ client/internal/peer/worker_relay.go | 9 ++++-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index 59e5621c6..649010b3b 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -229,7 +229,7 @@ func (conn *Conn) open(engineCtx context.Context, firstPacket []byte) error { if !IsForceRelayed() { relayIsSupportedLocally := conn.workerRelay.RelayIsSupportedLocally() - workerICE, err := NewWorkerICE(conn.ctx, conn.Log, conn.config, conn, conn.signaler, conn.iFaceDiscover, conn.statusRecorder, relayIsSupportedLocally) + workerICE, err := NewWorkerICE(conn.ctx, conn.Log, conn.config, conn, conn.signaler, conn.iFaceDiscover, conn.statusRecorder, conn.portForwardManager, relayIsSupportedLocally) if err != nil { return err } diff --git a/client/internal/peer/worker_ice.go b/client/internal/peer/worker_ice.go index 4244e1500..acc4c7972 100644 --- a/client/internal/peer/worker_ice.go +++ b/client/internal/peer/worker_ice.go @@ -20,6 +20,11 @@ import ( "github.com/netbirdio/netbird/route" ) +type iceCallbacks interface { + onICEConnectionIsReady(priority ConnPriority, iceConnInfo ICEConnInfo) + onICEStateDisconnected(sessionChanged bool) +} + type ICEConnInfo struct { RemoteConn net.Conn RosenpassPubKey []byte @@ -33,14 +38,15 @@ type ICEConnInfo struct { } type WorkerICE struct { - ctx context.Context - log *log.Entry - config ConnConfig - conn *Conn - signaler *Signaler - iFaceDiscover stdnet.ExternalIFaceDiscover - statusRecorder *status.Recorder - hasRelayOnLocally bool + ctx context.Context + log *log.Entry + config ConnConfig + conn iceCallbacks + signaler *Signaler + iFaceDiscover stdnet.ExternalIFaceDiscover + statusRecorder *status.Recorder + portForwardManager *portforward.Manager + hasRelayOnLocally bool agent *icemaker.ThreadSafeAgent agentDialerCancel context.CancelFunc @@ -65,22 +71,23 @@ type WorkerICE struct { portForwardAttempted bool } -func NewWorkerICE(ctx context.Context, log *log.Entry, config ConnConfig, conn *Conn, signaler *Signaler, ifaceDiscover stdnet.ExternalIFaceDiscover, statusRecorder *status.Recorder, hasRelayOnLocally bool) (*WorkerICE, error) { +func NewWorkerICE(ctx context.Context, log *log.Entry, config ConnConfig, conn iceCallbacks, signaler *Signaler, ifaceDiscover stdnet.ExternalIFaceDiscover, statusRecorder *status.Recorder, portForwardManager *portforward.Manager, hasRelayOnLocally bool) (*WorkerICE, error) { sessionID, err := NewICESessionID() if err != nil { return nil, err } w := &WorkerICE{ - ctx: ctx, - log: log, - config: config, - conn: conn, - signaler: signaler, - iFaceDiscover: ifaceDiscover, - statusRecorder: statusRecorder, - hasRelayOnLocally: hasRelayOnLocally, - sessionID: sessionID, + ctx: ctx, + log: log, + config: config, + conn: conn, + signaler: signaler, + iFaceDiscover: ifaceDiscover, + statusRecorder: statusRecorder, + portForwardManager: portForwardManager, + hasRelayOnLocally: hasRelayOnLocally, + sessionID: sessionID, } localUfrag, localPwd, err := icemaker.GenerateICECredentials() @@ -382,7 +389,7 @@ func (w *WorkerICE) onICECandidate(candidate ice.Candidate) { // injectPortForwardedCandidate signals an additional candidate using the pre-created port mapping. func (w *WorkerICE) injectPortForwardedCandidate(srflxCandidate ice.Candidate) { - pfManager := w.conn.portForwardManager + pfManager := w.portForwardManager if pfManager == nil { return } diff --git a/client/internal/peer/worker_relay.go b/client/internal/peer/worker_relay.go index 273d16120..72322db27 100644 --- a/client/internal/peer/worker_relay.go +++ b/client/internal/peer/worker_relay.go @@ -19,12 +19,17 @@ type RelayConnInfo struct { rosenpassAddr string } +type relayCallbacks interface { + onRelayConnectionIsReady(rci RelayConnInfo) + onRelayDisconnected() +} + type WorkerRelay struct { peerCtx context.Context log *log.Entry isController bool config ConnConfig - conn *Conn + conn relayCallbacks relayManager *relayClient.Manager relayedConn net.Conn @@ -33,7 +38,7 @@ type WorkerRelay struct { relaySupportedOnRemotePeer atomic.Bool } -func NewWorkerRelay(ctx context.Context, log *log.Entry, ctrl bool, config ConnConfig, conn *Conn, relayManager *relayClient.Manager) *WorkerRelay { +func NewWorkerRelay(ctx context.Context, log *log.Entry, ctrl bool, config ConnConfig, conn relayCallbacks, relayManager *relayClient.Manager) *WorkerRelay { r := &WorkerRelay{ peerCtx: ctx, log: log,