diff --git a/client/internal/peer/status.go b/client/internal/peer/status.go index 96b6d930f..067a9b58b 100644 --- a/client/internal/peer/status.go +++ b/client/internal/peer/status.go @@ -782,17 +782,18 @@ func (d *Status) UpdatePeerFQDN(peerPubKey, fqdn string) error { // to show up in the status. The mark persists until the peer is removed. func (d *Status) MarkPeerQuantumResistant(peerPubKey string) error { d.mux.Lock() - defer d.mux.Unlock() - peerState, ok := d.peers[peerPubKey] if !ok { + d.mux.Unlock() return errors.New("peer doesn't exist") } d.pqMarked[peerPubKey] = struct{}{} peerState.RosenpassEnabled = true d.peers[peerPubKey] = peerState + d.mux.Unlock() + d.notifyStateChange() return nil } diff --git a/client/internal/peer/status_test.go b/client/internal/peer/status_test.go index d0de41fb6..a7458f12c 100644 --- a/client/internal/peer/status_test.go +++ b/client/internal/peer/status_test.go @@ -616,3 +616,22 @@ func TestStatus_PQMarkClearedOnRemove(t *testing.T) { require.NoError(t, err) assert.False(t, st.RosenpassEnabled, "a re-added peer must not inherit the removed peer's PQ mark") } + +// TestStatus_PQMarkWakesSubscribers checks that a PSK landing after the connection came up +// reaches status subscribers, which otherwise keep showing the peer as not protected. +func TestStatus_PQMarkWakesSubscribers(t *testing.T) { + const key = "eDQmZp9jhQGX7XdYpHGaFSpAouldr3Sbf7MZRcGTGGQ=" + status := NewRecorder("https://mgm") + require.NoError(t, status.AddPeer(key, "peer.netbird.cloud", "100.64.0.2", "")) + + id, changes := status.SubscribeToStateChanges() + defer status.UnsubscribeFromStateChanges(id) + + require.NoError(t, status.MarkPeerQuantumResistant(key)) + + select { + case <-changes: + default: + assert.Fail(t, "marking a peer quantum resistant must notify status subscribers") + } +}