Просмотр исходного кода

control/controlclient, tailcfg: add 6 more patchable Node fields [capver 36]

Change-Id: Iae997a9a98a5dd841bc41fa91227d5a7dd476a25
Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 3 лет назад
Родитель
Сommit
7c7e23d87a
3 измененных файлов с 139 добавлено и 2 удалено
  1. 28 0
      control/controlclient/map.go
  2. 89 1
      control/controlclient/map_test.go
  3. 22 1
      tailcfg/tailcfg.go

+ 28 - 0
control/controlclient/map.go

@@ -268,6 +268,24 @@ func undeltaPeers(mapRes *tailcfg.MapResponse, prev []*tailcfg.Node) {
 				if ec.Endpoints != nil {
 				if ec.Endpoints != nil {
 					n.Endpoints = ec.Endpoints
 					n.Endpoints = ec.Endpoints
 				}
 				}
+				if ec.Key != nil {
+					n.Key = *ec.Key
+				}
+				if ec.DiscoKey != nil {
+					n.DiscoKey = *ec.DiscoKey
+				}
+				if v := ec.Online; v != nil {
+					n.Online = ptrCopy(v)
+				}
+				if v := ec.LastSeen; v != nil {
+					n.LastSeen = ptrCopy(v)
+				}
+				if v := ec.KeyExpiry; v != nil {
+					n.KeyExpiry = *v
+				}
+				if v := ec.Capabilities; v != nil {
+					n.Capabilities = *v
+				}
 			}
 			}
 		}
 		}
 	}
 	}
@@ -277,6 +295,16 @@ func undeltaPeers(mapRes *tailcfg.MapResponse, prev []*tailcfg.Node) {
 	mapRes.PeersRemoved = nil
 	mapRes.PeersRemoved = nil
 }
 }
 
 
+// ptrCopy returns a pointer to a newly allocated shallow copy of *v.
+func ptrCopy[T any](v *T) *T {
+	if v == nil {
+		return nil
+	}
+	ret := new(T)
+	*ret = *v
+	return ret
+}
+
 func nodesSorted(v []*tailcfg.Node) bool {
 func nodesSorted(v []*tailcfg.Node) bool {
 	for i, n := range v {
 	for i, n := range v {
 		if i > 0 && n.ID <= v[i-1].ID {
 		if i > 0 && n.ID <= v[i-1].ID {

+ 89 - 1
control/controlclient/map_test.go

@@ -12,6 +12,7 @@ import (
 	"testing"
 	"testing"
 	"time"
 	"time"
 
 
+	"go4.org/mem"
 	"tailscale.com/tailcfg"
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/key"
 	"tailscale.com/types/netmap"
 	"tailscale.com/types/netmap"
@@ -192,7 +193,90 @@ func TestUndeltaPeers(t *testing.T) {
 			},
 			},
 			want: peers(n(1, "foo", withDERP("127.3.3.40:2"), withEP("1.2.3.4:56"))),
 			want: peers(n(1, "foo", withDERP("127.3.3.40:2"), withEP("1.2.3.4:56"))),
 		},
 		},
-	}
+		{
+			name: "change_key",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID: 1,
+					Key:    ptrTo(key.NodePublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:   1,
+				Name: "foo",
+				Key:  key.NodePublicFromRaw32(mem.B(append(make([]byte, 31), 'A'))),
+			}),
+		},
+		{
+			name: "change_disco_key",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID:   1,
+					DiscoKey: ptrTo(key.DiscoPublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:       1,
+				Name:     "foo",
+				DiscoKey: key.DiscoPublicFromRaw32(mem.B(append(make([]byte, 31), 'A'))),
+			}),
+		},
+		{
+			name: "change_online",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID: 1,
+					Online: ptrTo(true),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:     1,
+				Name:   "foo",
+				Online: ptrTo(true),
+			}),
+		},
+		{
+			name: "change_last_seen",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID:   1,
+					LastSeen: ptrTo(time.Unix(123, 0).UTC()),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:       1,
+				Name:     "foo",
+				LastSeen: ptrTo(time.Unix(123, 0).UTC()),
+			}),
+		},
+		{
+			name: "change_key_expiry",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID:    1,
+					KeyExpiry: ptrTo(time.Unix(123, 0).UTC()),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:        1,
+				Name:      "foo",
+				KeyExpiry: time.Unix(123, 0).UTC(),
+			}),
+		},
+		{
+			name: "change_capabilities",
+			prev: peers(n(1, "foo")),
+			mapRes: &tailcfg.MapResponse{
+				PeersChangedPatch: []*tailcfg.PeerChange{{
+					NodeID:       1,
+					Capabilities: ptrTo([]string{"foo"}),
+				}},
+			}, want: peers(&tailcfg.Node{
+				ID:           1,
+				Name:         "foo",
+				Capabilities: []string{"foo"},
+			}),
+		}}
 
 
 	for _, tt := range tests {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
@@ -207,6 +291,10 @@ func TestUndeltaPeers(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func ptrTo[T any](v T) *T {
+	return &v
+}
+
 func formatNodes(nodes []*tailcfg.Node) string {
 func formatNodes(nodes []*tailcfg.Node) string {
 	var sb strings.Builder
 	var sb strings.Builder
 	for i, n := range nodes {
 	for i, n := range nodes {

+ 22 - 1
tailcfg/tailcfg.go

@@ -70,7 +70,8 @@ type CapabilityVersion int
 //	32: 2022-04-17: client knows FilterRule.CapMatch
 //	32: 2022-04-17: client knows FilterRule.CapMatch
 //	33: 2022-07-20: added MapResponse.PeersChangedPatch (DERPRegion + Endpoints)
 //	33: 2022-07-20: added MapResponse.PeersChangedPatch (DERPRegion + Endpoints)
 //	34: 2022-08-02: client understands CapabilityFileSharingTarget
 //	34: 2022-08-02: client understands CapabilityFileSharingTarget
-const CurrentCapabilityVersion CapabilityVersion = 34
+//	36: 2022-08-02: added PeersChangedPatch.{Key,DiscoKey,Online,LastSeen,KeyExpiry,Capabilities}
+const CurrentCapabilityVersion CapabilityVersion = 36
 
 
 type StableID string
 type StableID string
 
 
@@ -1763,6 +1764,26 @@ type PeerChange struct {
 	// Endpoints, if non-empty, means that NodeID's UDP Endpoints
 	// Endpoints, if non-empty, means that NodeID's UDP Endpoints
 	// have changed to these.
 	// have changed to these.
 	Endpoints []string `json:",omitempty"`
 	Endpoints []string `json:",omitempty"`
+
+	// Key, if non-nil, means that the NodeID's wireguard public key changed.
+	Key *key.NodePublic `json:",omitempty"`
+
+	// DiscoKey, if non-nil, means that the NodeID's discokey changed.
+	DiscoKey *key.DiscoPublic `json:",omitempty"`
+
+	// Online, if non-nil, means that the NodeID's online status changed.
+	Online *bool `json:",omitempty"`
+
+	// LastSeen, if non-nil, means that the NodeID's online status changed.
+	LastSeen *time.Time `json:",omitempty"`
+
+	// KeyExpiry, if non-nil, changes the NodeID's key expiry.
+	KeyExpiry *time.Time `json:",omitempty"`
+
+	// Capabilities, if non-nil, means that the NodeID's capabilities changed.
+	// It's a pointer to a slice for "omitempty", to allow differentiating
+	// a change to empty from no change.
+	Capabilities *[]string `json:",omitempty"`
 }
 }
 
 
 // DerpMagicIP is a fake WireGuard endpoint IP address that means to
 // DerpMagicIP is a fake WireGuard endpoint IP address that means to