derp: add PeerPresentFlags bitmask to Watch messages

Updates tailscale/corp#17816

Change-Id: Ib5baf6c981a6a4c279f8bbfef02048cfbfb3323b
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2024-06-22 09:17:51 -07:00
committed by Brad Fitzpatrick
parent d7a4f9d31c
commit 5ffb2668ef
4 changed files with 85 additions and 17 deletions

View File

@@ -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)
}