|
|
|
|
@ -566,7 +566,7 @@ func (s *Server) registerClient(c *sclient) { |
|
|
|
|
} |
|
|
|
|
s.keyOfAddr[c.remoteIPPort] = c.key |
|
|
|
|
s.curClients.Add(1) |
|
|
|
|
s.broadcastPeerStateChangeLocked(c.key, c.remoteIPPort, true) |
|
|
|
|
s.broadcastPeerStateChangeLocked(c.key, c.remoteIPPort, c.presentFlags(), true) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// broadcastPeerStateChangeLocked enqueues a message to all watchers
|
|
|
|
|
@ -574,12 +574,13 @@ func (s *Server) registerClient(c *sclient) { |
|
|
|
|
// presence changed.
|
|
|
|
|
//
|
|
|
|
|
// s.mu must be held.
|
|
|
|
|
func (s *Server) broadcastPeerStateChangeLocked(peer key.NodePublic, ipPort netip.AddrPort, present bool) { |
|
|
|
|
func (s *Server) broadcastPeerStateChangeLocked(peer key.NodePublic, ipPort netip.AddrPort, flags PeerPresentFlags, present bool) { |
|
|
|
|
for w := range s.watchers { |
|
|
|
|
w.peerStateChange = append(w.peerStateChange, peerConnState{ |
|
|
|
|
peer: peer, |
|
|
|
|
present: present, |
|
|
|
|
ipPort: ipPort, |
|
|
|
|
flags: flags, |
|
|
|
|
}) |
|
|
|
|
go w.requestMeshUpdate() |
|
|
|
|
} |
|
|
|
|
@ -601,7 +602,7 @@ func (s *Server) unregisterClient(c *sclient) { |
|
|
|
|
delete(s.clientsMesh, c.key) |
|
|
|
|
s.notePeerGoneFromRegionLocked(c.key) |
|
|
|
|
} |
|
|
|
|
s.broadcastPeerStateChangeLocked(c.key, netip.AddrPort{}, false) |
|
|
|
|
s.broadcastPeerStateChangeLocked(c.key, netip.AddrPort{}, 0, false) |
|
|
|
|
case *dupClientSet: |
|
|
|
|
c.debugLogf("removed duplicate client") |
|
|
|
|
if set.removeClient(c) { |
|
|
|
|
@ -700,6 +701,7 @@ func (s *Server) addWatcher(c *sclient) { |
|
|
|
|
peer: peer, |
|
|
|
|
present: true, |
|
|
|
|
ipPort: ac.remoteIPPort, |
|
|
|
|
flags: ac.presentFlags(), |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1435,11 +1437,26 @@ type sclient struct { |
|
|
|
|
peerGoneLim *rate.Limiter |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *sclient) presentFlags() PeerPresentFlags { |
|
|
|
|
var f PeerPresentFlags |
|
|
|
|
if c.info.IsProber { |
|
|
|
|
f |= PeerPresentIsProber |
|
|
|
|
} |
|
|
|
|
if c.canMesh { |
|
|
|
|
f |= PeerPresentIsMeshPeer |
|
|
|
|
} |
|
|
|
|
if f == 0 { |
|
|
|
|
return PeerPresentIsRegular |
|
|
|
|
} |
|
|
|
|
return f |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// peerConnState represents whether a peer is connected to the server
|
|
|
|
|
// or not.
|
|
|
|
|
type peerConnState struct { |
|
|
|
|
ipPort netip.AddrPort // if present, the peer's IP:port
|
|
|
|
|
peer key.NodePublic |
|
|
|
|
flags PeerPresentFlags |
|
|
|
|
present bool |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1634,9 +1651,9 @@ func (c *sclient) sendPeerGone(peer key.NodePublic, reason PeerGoneReasonType) e |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// sendPeerPresent sends a peerPresent frame, without flushing.
|
|
|
|
|
func (c *sclient) sendPeerPresent(peer key.NodePublic, ipPort netip.AddrPort) error { |
|
|
|
|
func (c *sclient) sendPeerPresent(peer key.NodePublic, ipPort netip.AddrPort, flags PeerPresentFlags) error { |
|
|
|
|
c.setWriteDeadline() |
|
|
|
|
const frameLen = keyLen + 16 + 2 |
|
|
|
|
const frameLen = keyLen + 16 + 2 + 1 // 16 byte IP + 2 byte port + 1 byte flags
|
|
|
|
|
if err := writeFrameHeader(c.bw.bw(), framePeerPresent, frameLen); err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
@ -1645,6 +1662,7 @@ func (c *sclient) sendPeerPresent(peer key.NodePublic, ipPort netip.AddrPort) er |
|
|
|
|
a16 := ipPort.Addr().As16() |
|
|
|
|
copy(payload[keyLen:], a16[:]) |
|
|
|
|
binary.BigEndian.PutUint16(payload[keyLen+16:], ipPort.Port()) |
|
|
|
|
payload[keyLen+18] = byte(flags) |
|
|
|
|
_, err := c.bw.Write(payload) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
@ -1675,7 +1693,7 @@ drainUpdates: |
|
|
|
|
} |
|
|
|
|
var err error |
|
|
|
|
if pcs.present { |
|
|
|
|
err = c.sendPeerPresent(pcs.peer, pcs.ipPort) |
|
|
|
|
err = c.sendPeerPresent(pcs.peer, pcs.ipPort, pcs.flags) |
|
|
|
|
} else { |
|
|
|
|
err = c.sendPeerGone(pcs.peer, PeerGoneReasonDisconnected) |
|
|
|
|
} |
|
|
|
|
|