Peers and paths
This commit is contained in:
parent
ccc9be2d4d
commit
90d4d79828
11 changed files with 153 additions and 23 deletions
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 {
|
switch id.idtype {
|
||||||
s := fmt.Sprintf("%.10x:0:%x", id.address, id.publicKey)
|
case IdentityTypeC25519:
|
||||||
return s
|
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 ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
// Roots retrieves a list of root servers on this node and their preferred and online status.
|
||||||
func (n *Node) ListRoots() []Root {
|
func (n *Node) Roots() []*Root {
|
||||||
var 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
go/pkg/zerotier/path.go
Normal file
34
go/pkg/zerotier/path.go
Normal 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
23
go/pkg/zerotier/peer.go
Normal 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
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue