From 4d76fd3c80a836a1469461a945338b29c878cd53 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Sat, 11 Jul 2026 15:14:22 +0200 Subject: [PATCH] [client] Extract stateDump into its own state_dump package Move the debug state dumper out of the peer package into client/internal/peer/state_dump with an exported StateDump type and NewStateDump constructor. Update conn.go, wg_watcher.go and the watcher test to reference it through the package. --- client/internal/peer/conn.go | 5 ++-- .../peer/{ => state_dump}/state_dump.go | 30 +++++++++---------- client/internal/peer/wg_watcher.go | 5 ++-- client/internal/peer/wg_watcher_test.go | 7 +++-- 4 files changed, 25 insertions(+), 22 deletions(-) rename client/internal/peer/{ => state_dump}/state_dump.go (74%) diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index c3afa8ded..5833ca6a3 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -22,6 +22,7 @@ import ( "github.com/netbirdio/netbird/client/internal/peer/guard" icemaker "github.com/netbirdio/netbird/client/internal/peer/ice" "github.com/netbirdio/netbird/client/internal/peer/id" + "github.com/netbirdio/netbird/client/internal/peer/state_dump" "github.com/netbirdio/netbird/client/internal/peer/status" "github.com/netbirdio/netbird/client/internal/peer/worker" "github.com/netbirdio/netbird/client/internal/portforward" @@ -155,7 +156,7 @@ type Conn struct { wg sync.WaitGroup // debug purpose - dumpState *stateDump + dumpState *state_dump.StateDump endpointUpdater *EndpointUpdater @@ -177,7 +178,7 @@ func NewConn(config ConnConfig, services ServiceDependencies) (*Conn, error) { connLog := log.WithField("peer", config.Key) - dumpState := newStateDump(config.Key, connLog, services.StatusRecorder) + dumpState := state_dump.NewStateDump(config.Key, connLog, services.StatusRecorder) var conn = &Conn{ Log: connLog, config: config, diff --git a/client/internal/peer/state_dump.go b/client/internal/peer/state_dump/state_dump.go similarity index 74% rename from client/internal/peer/state_dump.go rename to client/internal/peer/state_dump/state_dump.go index 2a5b71739..632346528 100644 --- a/client/internal/peer/state_dump.go +++ b/client/internal/peer/state_dump/state_dump.go @@ -1,4 +1,4 @@ -package peer +package state_dump import ( "context" @@ -10,7 +10,7 @@ import ( "github.com/netbirdio/netbird/client/internal/peer/status" ) -type stateDump struct { +type StateDump struct { log *log.Entry status *status.Recorder key string @@ -28,15 +28,15 @@ type stateDump struct { mu sync.Mutex } -func newStateDump(key string, log *log.Entry, statusRecorder *status.Recorder) *stateDump { - return &stateDump{ +func NewStateDump(key string, log *log.Entry, statusRecorder *status.Recorder) *StateDump { + return &StateDump{ log: log, status: statusRecorder, key: key, } } -func (s *stateDump) Start(ctx context.Context) { +func (s *StateDump) Start(ctx context.Context) { ticker := time.NewTicker(10 * time.Minute) defer ticker.Stop() @@ -50,25 +50,25 @@ func (s *stateDump) Start(ctx context.Context) { } } -func (s *stateDump) RemoteOffer() { +func (s *StateDump) RemoteOffer() { s.mu.Lock() defer s.mu.Unlock() s.remoteOffer++ } -func (s *stateDump) RemoteCandidate() { +func (s *StateDump) RemoteCandidate() { s.mu.Lock() defer s.mu.Unlock() s.remoteCandidate++ } -func (s *stateDump) SendOffer() { +func (s *StateDump) SendOffer() { s.mu.Lock() defer s.mu.Unlock() s.sentOffer++ } -func (s *stateDump) dumpState() { +func (s *StateDump) dumpState() { s.mu.Lock() defer s.mu.Unlock() @@ -82,41 +82,41 @@ func (s *stateDump) dumpState() { status, s.sentOffer, s.remoteOffer, s.remoteAnswer, s.remoteCandidate, s.p2pConnected, s.switchToRelay, s.wgCheckSuccess, s.relayConnected, s.localProxies) } -func (s *stateDump) RemoteAnswer() { +func (s *StateDump) RemoteAnswer() { s.mu.Lock() defer s.mu.Unlock() s.remoteAnswer++ } -func (s *stateDump) P2PConnected() { +func (s *StateDump) P2PConnected() { s.mu.Lock() defer s.mu.Unlock() s.p2pConnected++ } -func (s *stateDump) SwitchToRelay() { +func (s *StateDump) SwitchToRelay() { s.mu.Lock() defer s.mu.Unlock() s.switchToRelay++ } -func (s *stateDump) WGcheckSuccess() { +func (s *StateDump) WGcheckSuccess() { s.mu.Lock() defer s.mu.Unlock() s.wgCheckSuccess++ } -func (s *stateDump) RelayConnected() { +func (s *StateDump) RelayConnected() { s.mu.Lock() defer s.mu.Unlock() s.relayConnected++ } -func (s *stateDump) NewLocalProxy() { +func (s *StateDump) NewLocalProxy() { s.mu.Lock() defer s.mu.Unlock() diff --git a/client/internal/peer/wg_watcher.go b/client/internal/peer/wg_watcher.go index 10c22153f..f09cf1098 100644 --- a/client/internal/peer/wg_watcher.go +++ b/client/internal/peer/wg_watcher.go @@ -9,6 +9,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/client/iface/configurer" + "github.com/netbirdio/netbird/client/internal/peer/state_dump" ) const ( @@ -28,7 +29,7 @@ type WGWatcher struct { log *log.Entry wgIfaceStater WGInterfaceStater peerKey string - stateDump *stateDump + stateDump *state_dump.StateDump enabled bool muEnabled sync.Mutex @@ -38,7 +39,7 @@ type WGWatcher struct { resetCh chan struct{} } -func NewWGWatcher(log *log.Entry, wgIfaceStater WGInterfaceStater, peerKey string, stateDump *stateDump) *WGWatcher { +func NewWGWatcher(log *log.Entry, wgIfaceStater WGInterfaceStater, peerKey string, stateDump *state_dump.StateDump) *WGWatcher { return &WGWatcher{ log: log, wgIfaceStater: wgIfaceStater, diff --git a/client/internal/peer/wg_watcher_test.go b/client/internal/peer/wg_watcher_test.go index 452ab9de6..c76337fd8 100644 --- a/client/internal/peer/wg_watcher_test.go +++ b/client/internal/peer/wg_watcher_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/netbirdio/netbird/client/iface/configurer" + "github.com/netbirdio/netbird/client/internal/peer/state_dump" "github.com/netbirdio/netbird/client/internal/peer/status" ) @@ -58,7 +59,7 @@ func TestWGWatcher_CheckSuccessCallback(t *testing.T) { // platforms with coarse clock resolution (Windows), where two time.Now() calls // microseconds apart can return the same instant and read as a timed-out handshake. stats := &mockHandshakeStats{handshake: time.Now().Add(-time.Hour)} - watcher := NewWGWatcher(mlog, stats, "", newStateDump("peer", mlog, &status.Recorder{})) + watcher := NewWGWatcher(mlog, stats, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{})) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -106,7 +107,7 @@ func TestWGWatcher_EnableWgWatcher(t *testing.T) { mlog := log.WithField("peer", "tet") mocWgIface := &MocWgIface{} - watcher := NewWGWatcher(mlog, mocWgIface, "", newStateDump("peer", mlog, &status.Recorder{})) + watcher := NewWGWatcher(mlog, mocWgIface, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{})) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -139,7 +140,7 @@ func TestWGWatcher_ReEnable(t *testing.T) { mlog := log.WithField("peer", "tet") mocWgIface := &MocWgIface{} - watcher := NewWGWatcher(mlog, mocWgIface, "", newStateDump("peer", mlog, &status.Recorder{})) + watcher := NewWGWatcher(mlog, mocWgIface, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{})) ctx, cancel := context.WithCancel(context.Background()) ok := watcher.PrepareInitialHandshake()