Browse Source

Peers and paths

Adam Ierymenko 5 years ago
parent
commit
90d4d79828

+ 7 - 8
go/native/GoGlue.cpp

@@ -336,14 +336,16 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath)
 		gn->run = true;
 		gn->run = true;
 
 
 		gn->backgroundTaskThread = std::thread([gn] {
 		gn->backgroundTaskThread = std::thread([gn] {
-			int64_t lastScannedMulticastGroups = 0;
+			int64_t lastCheckedTaps = 0;
 			while (gn->run) {
 			while (gn->run) {
 				std::this_thread::sleep_for(std::chrono::milliseconds(500));
 				std::this_thread::sleep_for(std::chrono::milliseconds(500));
 				const int64_t now = OSUtils::now();
 				const int64_t now = OSUtils::now();
+
 				if (now >= gn->nextBackgroundTaskDeadline)
 				if (now >= gn->nextBackgroundTaskDeadline)
 					gn->node->processBackgroundTasks(nullptr,now,&(gn->nextBackgroundTaskDeadline));
 					gn->node->processBackgroundTasks(nullptr,now,&(gn->nextBackgroundTaskDeadline));
-				if ((now - lastScannedMulticastGroups) > 5000) {
-					lastScannedMulticastGroups = now;
+
+				if ((now - lastCheckedTaps) > 10000) {
+					lastCheckedTaps = now;
 					std::vector<MulticastGroup> added,removed;
 					std::vector<MulticastGroup> added,removed;
 					std::lock_guard<std::mutex> tl(gn->taps_l);
 					std::lock_guard<std::mutex> tl(gn->taps_l);
 					for(auto t=gn->taps.begin();t!=gn->taps.end();++t) {
 					for(auto t=gn->taps.begin();t!=gn->taps.end();++t) {
@@ -354,6 +356,8 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath)
 							goHandleTapAddedMulticastGroup(gn,(ZT_GoTap *)t->second.get(),t->first,g->mac().toInt(),g->adi());
 							goHandleTapAddedMulticastGroup(gn,(ZT_GoTap *)t->second.get(),t->first,g->mac().toInt(),g->adi());
 						for(auto g=removed.begin();g!=removed.end();++g)
 						for(auto g=removed.begin();g!=removed.end();++g)
 							goHandleTapRemovedMulticastGroup(gn,(ZT_GoTap *)t->second.get(),t->first,g->mac().toInt(),g->adi());
 							goHandleTapRemovedMulticastGroup(gn,(ZT_GoTap *)t->second.get(),t->first,g->mac().toInt(),g->adi());
+
+						t->second->syncRoutes();
 					}
 					}
 				}
 				}
 			}
 			}
@@ -705,8 +709,3 @@ extern "C" int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targe
 	}
 	}
 	return reinterpret_cast<EthernetTap *>(tap)->removeRoute(target,via,metric);
 	return reinterpret_cast<EthernetTap *>(tap)->removeRoute(target,via,metric);
 }
 }
-
-extern "C" int ZT_GoTap_syncRoutes(ZT_GoTap *tap)
-{
-	return reinterpret_cast<EthernetTap *>(tap)->syncRoutes();
-}

+ 0 - 2
go/native/GoGlue.h

@@ -95,8 +95,6 @@ int ZT_GoTap_addRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int target
 
 
 int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int targetNetmaskBits,int viaAf,const void *viaIp,unsigned int metric);
 int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int targetNetmaskBits,int viaAf,const void *viaIp,unsigned int metric);
 
 
-int ZT_GoTap_syncRoutes(ZT_GoTap *tap);
-
 /****************************************************************************/
 /****************************************************************************/
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 11 - 0
go/pkg/zerotier/address.go

@@ -31,6 +31,17 @@ func NewAddressFromString(s string) (Address, error) {
 	return Address(a & 0xffffffffff), err
 	return Address(a & 0xffffffffff), err
 }
 }
 
 
+// NewAddressFromBytes reads a 5-byte 40-bit address.
+func NewAddressFromBytes(b []byte) (Address, error) {
+	if len(b) < 5 {
+		return Address(0), ErrInvalidZeroTierAddress
+	}
+	return Address((uint64(b[0]) << 32) | (uint64(b[1]) << 24) | (uint64(b[2]) << 16) | (uint64(b[3]) << 8) | uint64(b[4])), nil
+}
+
+// IsReserved returns true if this address is reserved and therefore is not valid for a real node.
+func (a Address) IsReserved() bool { return a == 0 || (a>>32) == 0xff }
+
 // String returns this address's 10-digit hex identifier
 // String returns this address's 10-digit hex identifier
 func (a Address) String() string {
 func (a Address) String() string {
 	return fmt.Sprintf("%.10x", uint64(a))
 	return fmt.Sprintf("%.10x", uint64(a))

+ 1 - 0
go/pkg/zerotier/errors.go

@@ -23,6 +23,7 @@ const (
 	ErrNodeInitFailed            Err = "unable to initialize core Node instance"
 	ErrNodeInitFailed            Err = "unable to initialize core Node instance"
 	ErrInvalidMACAddress         Err = "invalid MAC address"
 	ErrInvalidMACAddress         Err = "invalid MAC address"
 	ErrInvalidZeroTierAddress    Err = "invalid ZeroTier address"
 	ErrInvalidZeroTierAddress    Err = "invalid ZeroTier address"
+	ErrInvalidNetworkID          Err = "invalid network ID"
 	ErrInvalidParameter          Err = "invalid parameter"
 	ErrInvalidParameter          Err = "invalid parameter"
 	ErrTapInitFailed             Err = "unable to create native Tap instance"
 	ErrTapInitFailed             Err = "unable to create native Tap instance"
 	ErrUncrecognizedIdentityType Err = "unrecognized identity type"
 	ErrUncrecognizedIdentityType Err = "unrecognized identity type"

+ 9 - 3
go/pkg/zerotier/identity.go

@@ -123,9 +123,15 @@ func (id *Identity) PrivateKeyString() string {
 // PublicKeyString returns the address and public key (identity.public contents).
 // PublicKeyString returns the address and public key (identity.public contents).
 // An empty string is returned if this identity is invalid or not initialized.
 // An empty string is returned if this identity is invalid or not initialized.
 func (id *Identity) String() string {
 func (id *Identity) String() string {
-	if len(id.publicKey) == IdentityTypeC25519PublicKeySize {
-		s := fmt.Sprintf("%.10x:0:%x", id.address, id.publicKey)
-		return s
+	switch id.idtype {
+	case IdentityTypeC25519:
+		if len(id.publicKey) == IdentityTypeC25519PublicKeySize {
+			return fmt.Sprintf("%.10x:0:%x", id.address, id.publicKey)
+		}
+	case IdentityTypeP384:
+		if len(id.publicKey) == IdentityTypeP384PublicKeySize {
+			return fmt.Sprintf("%.10x:1:%s", uint64(id.address), base32StdLowerCase.EncodeToString(id.publicKey))
+		}
 	}
 	}
 	return ""
 	return ""
 }
 }

+ 1 - 1
go/pkg/zerotier/misc.go

@@ -21,7 +21,7 @@ import (
 	"unsafe"
 	"unsafe"
 )
 )
 
 
-var base32StdLowerCase = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567")
+var base32StdLowerCase = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567").WithPadding(base32.NoPadding)
 
 
 // TimeMs returns the time in milliseconds since epoch.
 // TimeMs returns the time in milliseconds since epoch.
 func TimeMs() int64 { return int64(time.Now().UnixNano()) / int64(1000000) }
 func TimeMs() int64 { return int64(time.Now().UnixNano()) / int64(1000000) }

+ 18 - 2
go/pkg/zerotier/network.go

@@ -14,6 +14,7 @@
 package zerotier
 package zerotier
 
 
 import (
 import (
+	"encoding/binary"
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
@@ -28,17 +29,32 @@ type NetworkID uint64
 // NewNetworkIDFromString parses a network ID in string form
 // NewNetworkIDFromString parses a network ID in string form
 func NewNetworkIDFromString(s string) (NetworkID, error) {
 func NewNetworkIDFromString(s string) (NetworkID, error) {
 	if len(s) != 16 {
 	if len(s) != 16 {
-		return NetworkID(0), ErrInvalidZeroTierAddress
+		return NetworkID(0), ErrInvalidNetworkID
 	}
 	}
 	n, err := strconv.ParseUint(s, 16, 64)
 	n, err := strconv.ParseUint(s, 16, 64)
 	return NetworkID(n), err
 	return NetworkID(n), err
 }
 }
 
 
+// NewNetworkIDFromBytes reads an 8-byte / 64-bit network ID.
+func NewNetworkIDFromBytes(b []byte) (NetworkID, error) {
+	if len(b) < 8 {
+		return NetworkID(0), ErrInvalidNetworkID
+	}
+	return NetworkID(binary.BigEndian.Uint64(b)), nil
+}
+
 // String returns this network ID's 16-digit hex identifier
 // String returns this network ID's 16-digit hex identifier
 func (n NetworkID) String() string {
 func (n NetworkID) String() string {
 	return fmt.Sprintf("%.16x", uint64(n))
 	return fmt.Sprintf("%.16x", uint64(n))
 }
 }
 
 
+// Bytes returns this network ID as an 8-byte / 64-bit big-endian value.
+func (n NetworkID) Bytes() []byte {
+	var b [8]byte
+	binary.BigEndian.PutUint64(b[:], uint64(n))
+	return b[:]
+}
+
 // MarshalJSON marshals this NetworkID as a string
 // MarshalJSON marshals this NetworkID as a string
 func (n NetworkID) MarshalJSON() ([]byte, error) {
 func (n NetworkID) MarshalJSON() ([]byte, error) {
 	return []byte("\"" + n.String() + "\""), nil
 	return []byte("\"" + n.String() + "\""), nil
@@ -56,7 +72,7 @@ func (n *NetworkID) UnmarshalJSON(j []byte) error {
 	return err
 	return err
 }
 }
 
 
-// NetworkConfig represents the network's current state
+// NetworkConfig represents the network's current configuration as distributed by its network controller.
 type NetworkConfig struct {
 type NetworkConfig struct {
 	// ID is this network's 64-bit globally unique identifier
 	// ID is this network's 64-bit globally unique identifier
 	ID NetworkID
 	ID NetworkID

+ 47 - 5
go/pkg/zerotier/node.go

@@ -266,9 +266,9 @@ func (n *Node) RemoveDynamicRoot(dnsName string) {
 	C.free(unsafe.Pointer(dn))
 	C.free(unsafe.Pointer(dn))
 }
 }
 
 
-// ListRoots retrieves a list of root servers on this node and their preferred and online status.
-func (n *Node) ListRoots() []Root {
-	var roots []Root
+// Roots retrieves a list of root servers on this node and their preferred and online status.
+func (n *Node) Roots() []*Root {
+	var roots []*Root
 	rl := C.ZT_Node_listRoots(unsafe.Pointer(n.zn), C.int64_t(TimeMs()))
 	rl := C.ZT_Node_listRoots(unsafe.Pointer(n.zn), C.int64_t(TimeMs()))
 	if rl != nil {
 	if rl != nil {
 		for i := 0; i < int(rl.count); i++ {
 		for i := 0; i < int(rl.count); i++ {
@@ -282,7 +282,7 @@ func (n *Node) ListRoots() []Root {
 						addrs = append(addrs, a)
 						addrs = append(addrs, a)
 					}
 					}
 				}
 				}
-				roots = append(roots, Root{
+				roots = append(roots, &Root{
 					DNSName:   C.GoString(root.dnsName),
 					DNSName:   C.GoString(root.dnsName),
 					Identity:  id,
 					Identity:  id,
 					Addresses: addrs,
 					Addresses: addrs,
@@ -291,11 +291,53 @@ func (n *Node) ListRoots() []Root {
 				})
 				})
 			}
 			}
 		}
 		}
-		defer C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(rl))
+		C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(rl))
 	}
 	}
 	return roots
 	return roots
 }
 }
 
 
+// Peers retrieves a list of current peers
+func (n *Node) Peers() []*Peer {
+	var peers []*Peer
+	pl := C.ZT_Node_peers(unsafe.Pointer(n.zn))
+	if pl != nil {
+		for i := uintptr(0); i < uintptr(pl.peerCount); i++ {
+			p := (*C.ZT_Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(pl.peers)) + (i * C.sizeof_ZT_Peer)))
+			p2 := new(Peer)
+			p2.Address = Address(p.address)
+			p2.Version = [3]int{int(p.versionMajor), int(p.versionMinor), int(p.versionRev)}
+			p2.Latency = int(p.latency)
+			p2.Role = int(p.role)
+			p2.Paths = make([]Path, 0, int(p.pathCount))
+			for j := uintptr(0); j < uintptr(p.pathCount); j++ {
+				pt := &p.paths[j]
+				a := sockaddrStorageToUDPAddr(&pt.address)
+				if a != nil {
+					p2.Paths = append(p2.Paths, Path{
+						IP:                     a.IP,
+						Port:                   a.Port,
+						LastSend:               int64(pt.lastSend),
+						LastReceive:            int64(pt.lastReceive),
+						TrustedPathID:          uint64(pt.trustedPathId),
+						Latency:                float32(pt.latency),
+						PacketDelayVariance:    float32(pt.packetDelayVariance),
+						ThroughputDisturbCoeff: float32(pt.throughputDisturbCoeff),
+						PacketErrorRatio:       float32(pt.packetErrorRatio),
+						PacketLossRatio:        float32(pt.packetLossRatio),
+						Stability:              float32(pt.stability),
+						Throughput:             uint64(pt.throughput),
+						MaxThroughput:          uint64(pt.maxThroughput),
+						Allocation:             float32(pt.allocation),
+					})
+				}
+			}
+			peers = append(peers, p2)
+		}
+		C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(pl))
+	}
+	return peers
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////
 
 
 func (n *Node) multicastSubscribe(nwid uint64, mg *MulticastGroup) {
 func (n *Node) multicastSubscribe(nwid uint64, mg *MulticastGroup) {

+ 34 - 0
go/pkg/zerotier/path.go

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)2019 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2023-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+package zerotier
+
+import "net"
+
+// Path is a path to another peer on the network
+type Path struct {
+	IP                     net.IP
+	Port                   int
+	LastSend               int64
+	LastReceive            int64
+	TrustedPathID          uint64
+	Latency                float32
+	PacketDelayVariance    float32
+	ThroughputDisturbCoeff float32
+	PacketErrorRatio       float32
+	PacketLossRatio        float32
+	Stability              float32
+	Throughput             uint64
+	MaxThroughput          uint64
+	Allocation             float32
+}

+ 23 - 0
go/pkg/zerotier/peer.go

@@ -0,0 +1,23 @@
+/*
+ * Copyright (c)2019 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2023-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+package zerotier
+
+// Peer is another ZeroTier node
+type Peer struct {
+	Address Address
+	Version [3]int
+	Latency int
+	Role    int
+	Paths   []Path
+}

+ 2 - 2
include/ZeroTierCore.h

@@ -1171,12 +1171,12 @@ typedef struct
 	/**
 	/**
 	 * Time of last send in milliseconds or 0 for never
 	 * Time of last send in milliseconds or 0 for never
 	 */
 	 */
-	uint64_t lastSend;
+	int64_t lastSend;
 
 
 	/**
 	/**
 	 * Time of last receive in milliseconds or 0 for never
 	 * Time of last receive in milliseconds or 0 for never
 	 */
 	 */
-	uint64_t lastReceive;
+	int64_t lastReceive;
 
 
 	/**
 	/**
 	 * Is this a trusted path? If so this will be its nonzero ID.
 	 * Is this a trusted path? If so this will be its nonzero ID.