WIP: rebase fork onto upstream/main (v1.103.0) #15
+7
-18
@@ -4710,19 +4710,18 @@ func (b *LocalBackend) pingPeerAPI(ctx context.Context, ip netip.Addr) (peer tai
|
||||
var zero tailcfg.NodeView
|
||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
// PeerByTailscaleIP needs an up-to-date Peers slice.
|
||||
nm := b.NetMapWithPeers()
|
||||
if nm == nil {
|
||||
return zero, "", errors.New("no netmap")
|
||||
cn := b.currentNode()
|
||||
var ok bool
|
||||
if nid, addrOK := cn.NodeByAddr(ip); addrOK {
|
||||
peer, ok = cn.PeerByID(nid)
|
||||
}
|
||||
peer, ok := nm.PeerByTailscaleIP(ip)
|
||||
if !ok {
|
||||
return zero, "", fmt.Errorf("no peer found with Tailscale IP %v", ip)
|
||||
}
|
||||
if peer.Expired() {
|
||||
return zero, "", errors.New("peer's node key has expired")
|
||||
}
|
||||
base := peerAPIBase(nm, peer)
|
||||
base := peerAPIBase(cn.NetMap(), peer)
|
||||
if base == "" {
|
||||
return zero, "", fmt.Errorf("no PeerAPI base found for peer %v (%v)", peer.ID(), ip)
|
||||
}
|
||||
@@ -7968,22 +7967,12 @@ func (b *LocalBackend) DebugPeerRelayServers() set.Set[netip.Addr] {
|
||||
}
|
||||
|
||||
// DebugPeerDiscoKeys returns the disco public keys this node has learned for
|
||||
// each of its peers from the most recent network map. Intended for tests
|
||||
// each of its current peers. Intended for tests
|
||||
// (the production [ipnstate.PeerStatus] purposefully does not surface disco
|
||||
// keys; surfacing them via the [ipnstate.Status] API would also pollute
|
||||
// every PeerStatus consumer with a non-comparable struct field).
|
||||
func (b *LocalBackend) DebugPeerDiscoKeys() map[key.NodePublic]key.DiscoPublic {
|
||||
nm := b.currentNode().NetMap()
|
||||
if nm == nil {
|
||||
return nil
|
||||
}
|
||||
m := make(map[key.NodePublic]key.DiscoPublic, len(nm.Peers))
|
||||
for _, p := range nm.Peers {
|
||||
if dk := p.DiscoKey(); !dk.IsZero() {
|
||||
m[p.Key()] = dk
|
||||
}
|
||||
}
|
||||
return m
|
||||
return b.currentNode().peerDiscoKeys()
|
||||
}
|
||||
|
||||
// ControlKnobs returns the node's control knobs.
|
||||
|
||||
@@ -345,6 +345,30 @@ func (nb *nodeBackend) Peers() []tailcfg.NodeView {
|
||||
return slicesx.MapValues(nb.peers)
|
||||
}
|
||||
|
||||
// PeerByID returns the current state of the peer (not self) node with
|
||||
// the given ID, or ok=false if it is not a current peer.
|
||||
func (nb *nodeBackend) PeerByID(id tailcfg.NodeID) (_ tailcfg.NodeView, ok bool) {
|
||||
nb.mu.Lock()
|
||||
defer nb.mu.Unlock()
|
||||
n, ok := nb.peers[id]
|
||||
return n, ok
|
||||
}
|
||||
|
||||
// peerDiscoKeys returns the disco public keys of all current peers,
|
||||
// keyed by their node public keys. Peers without a disco key are
|
||||
// omitted.
|
||||
func (nb *nodeBackend) peerDiscoKeys() map[key.NodePublic]key.DiscoPublic {
|
||||
nb.mu.Lock()
|
||||
defer nb.mu.Unlock()
|
||||
m := make(map[key.NodePublic]key.DiscoPublic, len(nb.peers))
|
||||
for _, p := range nb.peers {
|
||||
if dk := p.DiscoKey(); !dk.IsZero() {
|
||||
m[p.Key()] = dk
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (nb *nodeBackend) PeersForTest() []tailcfg.NodeView {
|
||||
nb.mu.Lock()
|
||||
defer nb.mu.Unlock()
|
||||
@@ -363,28 +387,22 @@ func (nb *nodeBackend) CollectServices() bool {
|
||||
|
||||
// AppendMatchingPeers returns base with all peers that match pred appended.
|
||||
//
|
||||
// It acquires b.mu to read the netmap but releases it before calling pred.
|
||||
// It acquires nb.mu to snapshot the peers but releases it before
|
||||
// calling pred.
|
||||
func (nb *nodeBackend) AppendMatchingPeers(base []tailcfg.NodeView, pred func(tailcfg.NodeView) bool) []tailcfg.NodeView {
|
||||
var peers []tailcfg.NodeView
|
||||
|
||||
nb.mu.Lock()
|
||||
if nb.netMap != nil {
|
||||
// All fields on b.netMap are immutable, so this is
|
||||
// safe to copy and use outside the lock.
|
||||
peers = nb.netMap.Peers
|
||||
}
|
||||
peers := slicesx.MapValues(nb.peers)
|
||||
nb.mu.Unlock()
|
||||
|
||||
// Sort by node ID for deterministic results; the map iteration
|
||||
// above is randomly ordered.
|
||||
slices.SortFunc(peers, func(a, b tailcfg.NodeView) int {
|
||||
return cmp.Compare(a.ID(), b.ID())
|
||||
})
|
||||
|
||||
ret := base
|
||||
for _, peer := range peers {
|
||||
// The peers in b.netMap don't contain updates made via
|
||||
// UpdateNetmapDelta. So only use PeerView in b.netMap for its NodeID,
|
||||
// and then look up the latest copy in b.peers which is updated in
|
||||
// response to UpdateNetmapDelta edits.
|
||||
nb.mu.Lock()
|
||||
peer, ok := nb.peers[peer.ID()]
|
||||
nb.mu.Unlock()
|
||||
if ok && pred(peer) {
|
||||
if pred(peer) {
|
||||
ret = append(ret, peer)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user