Peers and paths

This commit is contained in:
Adam Ierymenko 2019-09-22 17:41:15 -07:00
parent ccc9be2d4d
commit 90d4d79828
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
11 changed files with 153 additions and 23 deletions

View File

@ -336,14 +336,16 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath)
gn->run = true;
gn->backgroundTaskThread = std::thread([gn] {
int64_t lastScannedMulticastGroups = 0;
int64_t lastCheckedTaps = 0;
while (gn->run) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
const int64_t now = OSUtils::now();
if (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::lock_guard<std::mutex> tl(gn->taps_l);
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());
for(auto g=removed.begin();g!=removed.end();++g)
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);
}
extern "C" int ZT_GoTap_syncRoutes(ZT_GoTap *tap)
{
return reinterpret_cast<EthernetTap *>(tap)->syncRoutes();
}

View File

@ -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_syncRoutes(ZT_GoTap *tap);
/****************************************************************************/
#ifdef __cplusplus

View File

@ -31,6 +31,17 @@ func NewAddressFromString(s string) (Address, error) {
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
func (a Address) String() string {
return fmt.Sprintf("%.10x", uint64(a))

View File

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

View File

@ -123,9 +123,15 @@ func (id *Identity) PrivateKeyString() string {
// PublicKeyString returns the address and public key (identity.public contents).
// An empty string is returned if this identity is invalid or not initialized.
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 ""
}

View File

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

View File

@ -14,6 +14,7 @@
package zerotier
import (
"encoding/binary"
"encoding/json"
"fmt"
"net"
@ -28,17 +29,32 @@ type NetworkID uint64
// NewNetworkIDFromString parses a network ID in string form
func NewNetworkIDFromString(s string) (NetworkID, error) {
if len(s) != 16 {
return NetworkID(0), ErrInvalidZeroTierAddress
return NetworkID(0), ErrInvalidNetworkID
}
n, err := strconv.ParseUint(s, 16, 64)
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
func (n NetworkID) String() string {
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
func (n NetworkID) MarshalJSON() ([]byte, error) {
return []byte("\"" + n.String() + "\""), nil
@ -56,7 +72,7 @@ func (n *NetworkID) UnmarshalJSON(j []byte) error {
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 {
// ID is this network's 64-bit globally unique identifier
ID NetworkID

View File

@ -266,9 +266,9 @@ func (n *Node) RemoveDynamicRoot(dnsName string) {
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()))
if rl != nil {
for i := 0; i < int(rl.count); i++ {
@ -282,7 +282,7 @@ func (n *Node) ListRoots() []Root {
addrs = append(addrs, a)
}
}
roots = append(roots, Root{
roots = append(roots, &Root{
DNSName: C.GoString(root.dnsName),
Identity: id,
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
}
// 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) {

34
go/pkg/zerotier/path.go Normal file
View File

@ -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
go/pkg/zerotier/peer.go Normal file
View File

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

View File

@ -1171,12 +1171,12 @@ typedef struct
/**
* 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
*/
uint64_t lastReceive;
int64_t lastReceive;
/**
* Is this a trusted path? If so this will be its nonzero ID.