mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-21 02:01:22 +00:00
Simplify root API
This commit is contained in:
parent
7061f13b24
commit
3b3e6d2bfc
@ -355,6 +355,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
|
||||
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||
if queriedID == 0 {
|
||||
apiSendObj(out, req, http.StatusBadRequest, nil)
|
||||
} else {
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
roots := node.Roots()
|
||||
|
@ -624,12 +624,18 @@ func (n *Node) Peers() []*Peer {
|
||||
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))
|
||||
usingAllocation := false
|
||||
for j := uintptr(0); j < uintptr(p.pathCount); j++ {
|
||||
pt := &p.paths[j]
|
||||
if pt.alive != 0 {
|
||||
a := sockaddrStorageToUDPAddr(&pt.address)
|
||||
if a != nil {
|
||||
alloc := float32(pt.allocation)
|
||||
if alloc > 0.0 {
|
||||
usingAllocation = true
|
||||
}
|
||||
p2.Paths = append(p2.Paths, Path{
|
||||
IP: a.IP,
|
||||
Port: a.Port,
|
||||
@ -644,18 +650,44 @@ func (n *Node) Peers() []*Peer {
|
||||
Stability: float32(pt.stability),
|
||||
Throughput: uint64(pt.throughput),
|
||||
MaxThroughput: uint64(pt.maxThroughput),
|
||||
Allocation: float32(pt.allocation),
|
||||
Allocation: alloc,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(p2.Paths, func(a, b int) bool { return p2.Paths[a].LastReceive < p2.Paths[b].LastReceive })
|
||||
if !usingAllocation { // if all allocations are zero fall back to single path mode that uses the preferred flag
|
||||
for i, j := 0, uintptr(0); j < uintptr(p.pathCount); j++ {
|
||||
pt := &p.paths[j]
|
||||
if pt.alive != 0 {
|
||||
if pt.preferred == 0 {
|
||||
p2.Paths[i].Allocation = 0.0
|
||||
} else {
|
||||
p2.Paths[i].Allocation = 1.0
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(p2.Paths, func(a, b int) bool {
|
||||
pa := &p2.Paths[a]
|
||||
pb := &p2.Paths[b]
|
||||
if pb.Allocation < pa.Allocation { // invert order, put highest allocation paths first
|
||||
return true
|
||||
}
|
||||
if pa.Allocation == pb.Allocation {
|
||||
return pa.LastReceive < pb.LastReceive // then sort by most recent activity
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
p2.Clock = TimeMs()
|
||||
peers = append(peers, p2)
|
||||
}
|
||||
C.ZT_Node_freeQueryResult(unsafe.Pointer(n.zn), unsafe.Pointer(pl))
|
||||
}
|
||||
sort.Slice(peers, func(a, b int) bool { return peers[a].Address < peers[b].Address })
|
||||
sort.Slice(peers, func(a, b int) bool {
|
||||
return peers[a].Address < peers[b].Address
|
||||
})
|
||||
return peers
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,13 @@ type Root struct {
|
||||
DNSName string
|
||||
Identity *Identity
|
||||
Addresses []InetAddress
|
||||
Locator []byte
|
||||
Preferred bool
|
||||
Online bool
|
||||
}
|
||||
|
||||
// Static returns true if this is a static root
|
||||
func (r *Root) Static() bool { return len(r.DNSName) == 0 }
|
||||
|
||||
// Dynamic returns true if this is a dynamic root
|
||||
func (r *Root) Dynamic() bool { return len(r.DNSName) > 0 }
|
||||
|
@ -1887,47 +1887,27 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_
|
||||
ZT_SDK_API ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now);
|
||||
|
||||
/**
|
||||
* Set a static root
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param identity Public identity of static root
|
||||
* @param addresses Physical address(es) of root
|
||||
* @param addressCount Number of physical addresses
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setStaticRoot(ZT_Node *node,const char *identity,const struct sockaddr_storage *addresses,unsigned int addressCount);
|
||||
|
||||
/**
|
||||
* Set a dynamic root
|
||||
* Add or update a root
|
||||
*
|
||||
* The node will begin trying to resolve the DNS TXT record for
|
||||
* this root and possibly obtain it from other peers.
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param dnsName DNS name whose TXT record(s) contain the latest Locator for this root
|
||||
* @param defaultLocator Binary-serialized default locator of NULL if none (used if TXT records are not retrievable)
|
||||
* @param defaultLocatorSize Size of default locator or 0 if none
|
||||
* @param name DNS name or simply the address in hex form for static roots
|
||||
* @param locator Binary-serialized locator of NULL if none
|
||||
* @param locatorSize Size of locator or 0 if none
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setDynamicRoot(ZT_Node *node,const char *dnsName,const void *defaultLocator,unsigned int defaultLocatorSize);
|
||||
|
||||
/**
|
||||
* Remove a static root
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param identity Public identity of this root
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeStaticRoot(ZT_Node *node,const char *identity);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize);
|
||||
|
||||
/**
|
||||
* Remove a dynamic root
|
||||
*
|
||||
* @param node Node instance
|
||||
* @param dnsName DNS name of this dynamic root
|
||||
* @param name DNS name of this dynamic root or the address in hex form for static roots
|
||||
* @return OK (0) or error code
|
||||
*/
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeDynamicRoot(ZT_Node *node,const char *dnsName);
|
||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name);
|
||||
|
||||
/**
|
||||
* Get this node's 40-bit ZeroTier address
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
// These are absolute maximums -- real locators are never this big
|
||||
#define ZT_LOCATOR_MAX_PHYSICAL_ADDRESSES 255
|
||||
#define ZT_LOCATOR_MAX_VIRTUAL_ADDRESSES 255
|
||||
|
||||
@ -38,19 +39,15 @@ namespace ZeroTier {
|
||||
* may be found. It can contain static physical addresses or virtual ZeroTier
|
||||
* addresses of nodes that can forward to the target node. Locator records
|
||||
* can be stored in signed DNS TXT record sets, in LF by roots, in caches,
|
||||
* etc. Version 2.x nodes can sign their own locators. Roots can create
|
||||
* signed locators using their own signature for version 1.x nodes. Locators
|
||||
* signed by the node whose location they describe always take precedence
|
||||
* over locators signed by other nodes.
|
||||
* etc.
|
||||
*/
|
||||
class Locator
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Locator() : _ts(0),_signatureLength(0) {}
|
||||
|
||||
ZT_ALWAYS_INLINE const Identity &id() const { return _id; }
|
||||
ZT_ALWAYS_INLINE const Identity &signer() const { return ((_signedBy) ? _signedBy : _id); }
|
||||
ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; }
|
||||
ZT_ALWAYS_INLINE const Identity &id() const { return _id; }
|
||||
|
||||
ZT_ALWAYS_INLINE const std::vector<InetAddress> &phy() const { return _physical; }
|
||||
ZT_ALWAYS_INLINE const std::vector<Identity> &virt() const { return _virtual; }
|
||||
@ -76,11 +73,11 @@ public:
|
||||
/**
|
||||
* Method to be called after add() is called for each address or forwarding node
|
||||
*
|
||||
* This sets timestamp and ID information and sorts and deduplicates target
|
||||
* lists but does not sign the locator. The sign() method should be used after
|
||||
* finish().
|
||||
* @param id Identity that this locator describes (must contain private key)
|
||||
* @param ts Current time
|
||||
* @return True if completion and signature were successful
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void finish(const Identity &id,const int64_t ts)
|
||||
ZT_ALWAYS_INLINE bool finish(const Identity &id,const int64_t ts)
|
||||
{
|
||||
_ts = ts;
|
||||
_id = id;
|
||||
@ -88,24 +85,10 @@ public:
|
||||
_physical.erase(std::unique(_physical.begin(),_physical.end()),_physical.end());
|
||||
std::sort(_virtual.begin(),_virtual.end());
|
||||
_virtual.erase(std::unique(_virtual.begin(),_virtual.end()),_virtual.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign this locator (must be called after finish())
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool sign(const Identity &signingId)
|
||||
{
|
||||
if (!signingId.hasPrivate())
|
||||
return false;
|
||||
if (signingId == _id) {
|
||||
_signedBy.zero();
|
||||
} else {
|
||||
_signedBy = signingId;
|
||||
}
|
||||
try {
|
||||
ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
|
||||
serialize(*tmp,true);
|
||||
_signatureLength = signingId.sign(tmp->data(),tmp->size(),_signature,ZT_SIGNATURE_BUFFER_SIZE);
|
||||
_signatureLength = id.sign(tmp->data(),tmp->size(),_signature,ZT_SIGNATURE_BUFFER_SIZE);
|
||||
return (_signatureLength > 0);
|
||||
} catch ( ... ) {
|
||||
return false;
|
||||
@ -122,8 +105,7 @@ public:
|
||||
try {
|
||||
ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
|
||||
serialize(*tmp,true);
|
||||
const bool ok = (_signedBy) ? _signedBy.verify(tmp->data(),tmp->size(),_signature,_signatureLength) : _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength);
|
||||
return ok;
|
||||
return _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength);
|
||||
} catch ( ... ) {
|
||||
return false;
|
||||
}
|
||||
@ -155,6 +137,8 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This searches for an extracts a public key from a DNS name, if one is present.
|
||||
*
|
||||
* @return True if a key was found and successfully decoded
|
||||
*/
|
||||
static inline bool decodeSecureDnsName(const char *name,uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
|
||||
@ -210,8 +194,9 @@ public:
|
||||
ScopedPtr< Buffer<65536> > tmp(new Buffer<65536>());
|
||||
serialize(*tmp,false);
|
||||
SHA384(s384,tmp->data(),tmp->size());
|
||||
ECC384ECDSASign(p384SigningKeyPrivate,s384,((uint8_t *)tmp->unsafeData()) + tmp->size());
|
||||
const unsigned int sigLocation = tmp->size();
|
||||
tmp->addSize(ZT_ECC384_SIGNATURE_SIZE);
|
||||
ECC384ECDSASign(p384SigningKeyPrivate,s384,((uint8_t *)tmp->unsafeData()) + sigLocation);
|
||||
|
||||
// Blob must be broken into multiple TXT records that must remain sortable so they are prefixed by a hex value.
|
||||
// 186-byte chunks yield 248-byte base64 chunks which leaves some margin below the limit of 255.
|
||||
@ -292,12 +277,6 @@ public:
|
||||
b.append((uint8_t)0); // version/flags, currently 0
|
||||
b.append((uint64_t)_ts);
|
||||
_id.serialize(b,false);
|
||||
if (_signedBy) {
|
||||
b.append((uint8_t)1); // number of signers, current max is 1
|
||||
_signedBy.serialize(b,false); // be sure not to include private key!
|
||||
} else {
|
||||
b.append((uint8_t)0); // signer is _id
|
||||
}
|
||||
b.append((uint8_t)_physical.size());
|
||||
for(std::vector<InetAddress>::const_iterator i(_physical.begin());i!=_physical.end();++i)
|
||||
i->serialize(b);
|
||||
@ -354,16 +333,25 @@ public:
|
||||
|
||||
ZT_ALWAYS_INLINE bool addressesEqual(const Locator &l) const { return ((_physical == l._physical)&&(_virtual == l._virtual)); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Locator &l) const { return ((_ts == l._ts)&&(_id == l._id)&&(_signedBy == l._signedBy)&&(_physical == l._physical)&&(_virtual == l._virtual)&&(_signatureLength == l._signatureLength)&&(memcmp(_signature,l._signature,_signatureLength) == 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const Locator &l) const
|
||||
{
|
||||
return (
|
||||
(_ts == l._ts)&&
|
||||
(_id == l._id)&&
|
||||
(_physical == l._physical)&&
|
||||
(_virtual == l._virtual)&&
|
||||
(_signatureLength == l._signatureLength)&&
|
||||
(memcmp(_signature,l._signature,_signatureLength) == 0));
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Locator &l) const { return (!(*this == l)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Locator &l) const
|
||||
{
|
||||
if (_id < l._id) return true;
|
||||
if (_ts < l._ts) return true;
|
||||
if (_signedBy < l._signedBy) return true;
|
||||
if (_physical < l._physical) return true;
|
||||
if (_virtual < l._virtual) return true;
|
||||
return false;
|
||||
if (_ts < l._ts) return true; else if (_ts > l._ts) return false;
|
||||
if (_id < l._id) return true; else if (_id > l._id) return false;
|
||||
if (_physical < l._physical) return true; else if (_physical > l._physical) return false;
|
||||
if (_virtual < l._virtual) return true; else if (_virtual > l._virtual) return false;
|
||||
if (_signatureLength < l._signatureLength) return true;
|
||||
return (_signatureLength == l._signatureLength) ? (memcmp(_signature,l._signature,_signatureLength) < 0) : false;
|
||||
}
|
||||
ZT_ALWAYS_INLINE bool operator>(const Locator &l) const { return (l < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Locator &l) const { return (!(l < *this)); }
|
||||
@ -374,7 +362,6 @@ public:
|
||||
private:
|
||||
int64_t _ts;
|
||||
Identity _id;
|
||||
Identity _signedBy; // signed by _id if nil/zero
|
||||
std::vector<InetAddress> _physical;
|
||||
std::vector<Identity> _virtual;
|
||||
unsigned int _signatureLength;
|
||||
|
101
node/Node.cpp
101
node/Node.cpp
@ -170,7 +170,9 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
||||
if (nw) {
|
||||
RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
|
||||
return ZT_RESULT_OK;
|
||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
} else {
|
||||
return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// This is passed as the argument to the DNS request handler and
|
||||
@ -184,7 +186,7 @@ struct _processBackgroundTasks_dnsResultAccumulator
|
||||
|
||||
static const ZT_DNSRecordType s_txtRecordType[1] = { ZT_DNS_RECORD_TXT };
|
||||
|
||||
struct _processBackgroundTasks_check_dynamicRoots
|
||||
struct _processBackgroundTasks_eachRootName
|
||||
{
|
||||
ZT_Node_Callbacks *cb;
|
||||
Node *n;
|
||||
@ -194,7 +196,7 @@ struct _processBackgroundTasks_check_dynamicRoots
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator()(const Str &dnsName,const Locator &loc)
|
||||
{
|
||||
if ((updateAll)||(!loc)) {
|
||||
if ((strchr(dnsName.c_str(),'.'))&&((updateAll)||(!loc))) {
|
||||
_processBackgroundTasks_dnsResultAccumulator *dnsReq = new _processBackgroundTasks_dnsResultAccumulator(dnsName);
|
||||
cb->dnsResolver(reinterpret_cast<ZT_Node *>(n),uPtr,tPtr,s_txtRecordType,1,dnsName.c_str(),(uintptr_t)dnsReq);
|
||||
}
|
||||
@ -258,7 +260,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||
try {
|
||||
// Periodically refresh locators for dynamic roots from their DNS names.
|
||||
if (_cb.dnsResolver) {
|
||||
_processBackgroundTasks_check_dynamicRoots cr;
|
||||
_processBackgroundTasks_eachRootName cr;
|
||||
cr.cb = &_cb;
|
||||
cr.n = this;
|
||||
cr.uPtr = _uPtr;
|
||||
@ -269,7 +271,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
||||
} else {
|
||||
cr.updateAll = false;
|
||||
}
|
||||
RR->topology->eachDynamicRoot(cr);
|
||||
RR->topology->eachRootName(cr);
|
||||
}
|
||||
|
||||
// Ping each root explicitly no matter what
|
||||
@ -363,7 +365,7 @@ void Node::processDNSResult(
|
||||
} else if (recordType == ZT_DNS_RECORD__END_OF_RESULTS) {
|
||||
Locator loc;
|
||||
if (loc.decodeTxtRecords(acc->dnsName,acc->txtRecords.begin(),acc->txtRecords.end())) {
|
||||
RR->topology->setDynamicRoot(acc->dnsName,loc);
|
||||
RR->topology->setRoot(acc->dnsName,loc);
|
||||
delete acc;
|
||||
}
|
||||
}
|
||||
@ -434,59 +436,38 @@ ZT_RootList *Node::listRoots(int64_t now)
|
||||
return RR->topology->apiRoots(now);
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::setStaticRoot(const char *identity,const struct sockaddr_storage *addresses,unsigned int addressCount)
|
||||
enum ZT_ResultCode Node::setRoot(const char *name,const void *locator,unsigned int locatorSize)
|
||||
{
|
||||
if (!identity)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
Identity id;
|
||||
if (id.fromString(identity)) {
|
||||
if (id) {
|
||||
std::vector<InetAddress> addrs;
|
||||
for(unsigned int i=0;i<addressCount;++i)
|
||||
addrs.push_back(InetAddress(addresses[i]));
|
||||
RR->topology->setStaticRoot(identity,addrs);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::setDynamicRoot(const char *dnsName,const void *defaultLocator,unsigned int defaultLocatorSize)
|
||||
{
|
||||
if (!dnsName)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
if (strlen(dnsName) >= 256)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
try {
|
||||
Locator loc;
|
||||
if ((defaultLocator)&&(defaultLocatorSize > 0)&&(defaultLocatorSize < 65535)) {
|
||||
if ((locator)&&(locatorSize > 0)&&(locatorSize < 65535)) {
|
||||
ScopedPtr< Buffer<65536> > locbuf(new Buffer<65536>());
|
||||
locbuf->append(defaultLocator,defaultLocatorSize);
|
||||
locbuf->append(locator,locatorSize);
|
||||
loc.deserialize(*locbuf,0);
|
||||
if (!loc.verify())
|
||||
loc = Locator();
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
return RR->topology->setDynamicRoot(Str(dnsName),loc) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED;
|
||||
Str n;
|
||||
if ((!name)||(strlen(name) == 0)) {
|
||||
if (!loc)
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER; /* no name and no locator */
|
||||
char tmp[16];
|
||||
loc.id().address().toString(tmp);
|
||||
n = tmp;
|
||||
} else {
|
||||
n = name;
|
||||
}
|
||||
return RR->topology->setRoot(n,loc) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED;
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::removeStaticRoot(const char *identity)
|
||||
{
|
||||
if (identity) {
|
||||
Identity id;
|
||||
if (id.fromString(identity))
|
||||
RR->topology->removeStaticRoot(id);
|
||||
}
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
enum ZT_ResultCode Node::removeDynamicRoot(const char *dnsName)
|
||||
enum ZT_ResultCode Node::removeRoot(const char *name)
|
||||
{
|
||||
try {
|
||||
if (dnsName)
|
||||
RR->topology->removeDynamicRoot(Str(dnsName));
|
||||
if (name)
|
||||
RR->topology->removeRoot(Str(name));
|
||||
} catch ( ... ) {}
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
@ -937,10 +918,10 @@ ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now)
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_setStaticRoot(ZT_Node *node,const char *identity,const struct sockaddr_storage *addresses,unsigned int addressCount)
|
||||
enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->setStaticRoot(identity,addresses,addressCount);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->setRoot(name,locator,locatorSize);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
@ -948,32 +929,10 @@ enum ZT_ResultCode ZT_Node_setStaticRoot(ZT_Node *node,const char *identity,cons
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_setDynamicRoot(ZT_Node *node,const char *dnsName,const void *defaultLocator,unsigned int defaultLocatorSize)
|
||||
enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->setDynamicRoot(dnsName,defaultLocator,defaultLocatorSize);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_removeStaticRoot(ZT_Node *node,const char *identity)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->removeStaticRoot(identity);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_removeDynamicRoot(ZT_Node *node,const char *dnsName)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->removeDynamicRoot(dnsName);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->removeRoot(name);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -93,10 +93,8 @@ public:
|
||||
ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||
ZT_RootList *listRoots(int64_t now);
|
||||
enum ZT_ResultCode setStaticRoot(const char *identity,const struct sockaddr_storage *addresses,unsigned int addressCount);
|
||||
enum ZT_ResultCode setDynamicRoot(const char *dnsName,const void *defaultLocator,unsigned int defaultLocatorSize);
|
||||
enum ZT_ResultCode removeStaticRoot(const char *identity);
|
||||
enum ZT_ResultCode removeDynamicRoot(const char *dnsName);
|
||||
enum ZT_ResultCode setRoot(const char *name,const void *locator,unsigned int locatorSize);
|
||||
enum ZT_ResultCode removeRoot(const char *name);
|
||||
uint64_t address() const;
|
||||
void status(ZT_NodeStatus *status) const;
|
||||
ZT_PeerList *peers() const;
|
||||
|
@ -66,14 +66,14 @@ private:
|
||||
|
||||
ZT_ALWAYS_INLINE void _updateDynamicRootIdentities()
|
||||
{
|
||||
// assumes _dynamicRoots_l is locked
|
||||
_dynamicRootIdentities.clear();
|
||||
Hashtable< Str,Locator >::Iterator i(_dynamicRoots);
|
||||
// assumes _roots_l is locked
|
||||
_rootIdentities.clear();
|
||||
Hashtable< Str,Locator >::Iterator i(_roots);
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
while (i.next(k,v)) {
|
||||
if (*v)
|
||||
_dynamicRootIdentities.set(v->id(),true);
|
||||
_rootIdentities.set(v->id(),true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,6 +81,10 @@ public:
|
||||
ZT_ALWAYS_INLINE Topology(const RuntimeEnvironment *renv,const Identity &myId) :
|
||||
RR(renv),
|
||||
_myIdentity(myId),
|
||||
_peers(64),
|
||||
_paths(128),
|
||||
_roots(8),
|
||||
_rootIdentities(8),
|
||||
_numConfiguredPhysicalPaths(0),
|
||||
_lastUpdatedBestRoot(0) {}
|
||||
ZT_ALWAYS_INLINE ~Topology() {}
|
||||
@ -166,17 +170,8 @@ public:
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const
|
||||
{
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
if (_dynamicRootIdentities.contains(id))
|
||||
return true;
|
||||
}
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
if (_staticRoots.contains(id))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
Mutex::Lock l(_roots_l);
|
||||
return _rootIdentities.contains(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,57 +255,28 @@ public:
|
||||
template<typename F>
|
||||
ZT_ALWAYS_INLINE void eachRoot(F f)
|
||||
{
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
Hashtable< Str,Locator >::Iterator i(_dynamicRoots);
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
while (i.next(k,v)) {
|
||||
if (*v) {
|
||||
for(std::vector<Identity>::const_iterator id(v->virt().begin());id!=v->virt().end();++id) {
|
||||
const SharedPtr<Peer> *ap;
|
||||
{
|
||||
Mutex::Lock l2(_peers_l);
|
||||
ap = _peers.get(id->address());
|
||||
}
|
||||
if (ap) {
|
||||
if (!f(*ap,v->phy()))
|
||||
return;
|
||||
} else {
|
||||
SharedPtr<Peer> p(new Peer(RR,_myIdentity,*id));
|
||||
{
|
||||
Mutex::Lock l2(_peers_l);
|
||||
_peers.set(id->address(),p);
|
||||
}
|
||||
if (!f(p,v->phy()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
Hashtable< Identity,std::vector<InetAddress> >::Iterator i(_staticRoots);
|
||||
Identity *k = (Identity *)0;
|
||||
std::vector<InetAddress> *v = (std::vector<InetAddress> *)0;
|
||||
while (i.next(k,v)) {
|
||||
if (!v->empty()) {
|
||||
Mutex::Lock l(_roots_l);
|
||||
Hashtable< Str,Locator >::Iterator i(_roots);
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
while (i.next(k,v)) {
|
||||
if (*v) {
|
||||
for(std::vector<Identity>::const_iterator id(v->virt().begin());id!=v->virt().end();++id) {
|
||||
const SharedPtr<Peer> *ap;
|
||||
{
|
||||
Mutex::Lock l2(_peers_l);
|
||||
ap = _peers.get(k->address());
|
||||
ap = _peers.get(id->address());
|
||||
}
|
||||
if (ap) {
|
||||
if (!f(*ap,*v))
|
||||
if (!f(*ap,v->phy()))
|
||||
return;
|
||||
} else {
|
||||
SharedPtr<Peer> p(new Peer(RR,_myIdentity,*k));
|
||||
SharedPtr<Peer> p(new Peer(RR,_myIdentity,*id));
|
||||
{
|
||||
Mutex::Lock l2(_peers_l);
|
||||
_peers.set(k->address(),p);
|
||||
_peers.set(id->address(),p);
|
||||
}
|
||||
if (!f(p,*v))
|
||||
if (!f(p,v->phy()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -335,49 +301,17 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update a static root entry
|
||||
*
|
||||
* @param id Static root's identity
|
||||
* @param addrs Static root's IP address(es)
|
||||
*/
|
||||
inline void setStaticRoot(const Identity &id,const std::vector<InetAddress> &addrs)
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
_staticRoots[id] = addrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a static root
|
||||
*
|
||||
* @param id Identity to remove
|
||||
*/
|
||||
inline void removeStaticRoot(const Identity &id)
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
_staticRoots.erase(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all static roots
|
||||
*/
|
||||
inline void removeStaticRoot()
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
_staticRoots.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through all dynamic roots
|
||||
* Iterate through all root names
|
||||
*
|
||||
* @param f Function of (Str,Locator)
|
||||
*/
|
||||
template<typename F>
|
||||
ZT_ALWAYS_INLINE void eachDynamicRoot(F f) const
|
||||
ZT_ALWAYS_INLINE void eachRootName(F f) const
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
Mutex::Lock l(_roots_l);
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_dynamicRoots);
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_roots);
|
||||
while (i.next(k,v)) {
|
||||
if (!f(*k,*v))
|
||||
break;
|
||||
@ -389,22 +323,22 @@ public:
|
||||
*
|
||||
* This does not check signatures or internal validity of the locator.
|
||||
*
|
||||
* @param dnsName DNS name used to retrive root
|
||||
* @param name DNS name used to retrive root or simply the address for static roots
|
||||
* @param latestLocator Latest locator
|
||||
* @return True if locator is newer or if a new entry was created
|
||||
*/
|
||||
inline bool setDynamicRoot(const Str &dnsName,const Locator &latestLocator)
|
||||
inline bool setRoot(const Str &name,const Locator &latestLocator)
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
Mutex::Lock l(_roots_l);
|
||||
if (latestLocator) {
|
||||
Locator &ll = _dynamicRoots[dnsName];
|
||||
Locator &ll = _roots[name];
|
||||
if (ll.timestamp() < latestLocator.timestamp()) {
|
||||
ll = latestLocator;
|
||||
_updateDynamicRootIdentities();
|
||||
return true;
|
||||
}
|
||||
} else if (!_dynamicRoots.contains(dnsName)) {
|
||||
_dynamicRoots[dnsName];
|
||||
} else if (!_roots.contains(name)) {
|
||||
_roots[name];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -412,39 +346,26 @@ public:
|
||||
|
||||
/**
|
||||
* Remove a dynamic root entry
|
||||
*
|
||||
* @param dnsName DNS name to remove
|
||||
*/
|
||||
inline void removeDynamicRoot(const Str &dnsName)
|
||||
inline void removeRoot(const Str &name)
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
_dynamicRoots.erase(dnsName);
|
||||
Mutex::Lock l(_roots_l);
|
||||
_roots.erase(name);
|
||||
_updateDynamicRootIdentities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all dynamic roots
|
||||
*/
|
||||
inline void clearDynamicRoots()
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
_dynamicRoots.clear();
|
||||
_dynamicRootIdentities.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Current time
|
||||
* @return ZT_RootList as returned by the external CAPI
|
||||
*/
|
||||
inline ZT_RootList *apiRoots(const int64_t now) const
|
||||
{
|
||||
Mutex::Lock l1(_staticRoots_l);
|
||||
Mutex::Lock l2(_dynamicRoots_l);
|
||||
Mutex::Lock l2(_roots_l);
|
||||
|
||||
// The memory allocated here has room for all roots plus the maximum size
|
||||
// of their DNS names, identities, and up to 16 physical addresses. Most
|
||||
// roots will have two: one V4 and one V6.
|
||||
const unsigned int totalRoots = _staticRoots.size() + _dynamicRoots.size();
|
||||
const unsigned int totalRoots = _roots.size();
|
||||
ZT_RootList *rl = reinterpret_cast<ZT_RootList *>(malloc(sizeof(ZT_RootList) + (sizeof(ZT_Root) * totalRoots) + ((sizeof(struct sockaddr_storage) * ZT_MAX_PEER_NETWORK_PATHS) * totalRoots) + ((ZT_IDENTITY_STRING_BUFFER_LENGTH + 1024) * totalRoots)));
|
||||
if (!rl) {
|
||||
return nullptr;
|
||||
@ -462,7 +383,7 @@ public:
|
||||
{
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_dynamicRoots);
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_roots);
|
||||
while (i.next(k,v)) {
|
||||
rl->roots[c].dnsName = nameBufPtr;
|
||||
const char *p = k->c_str();
|
||||
@ -494,35 +415,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Hashtable< Identity,std::vector<InetAddress> >::Iterator i(const_cast<Topology *>(this)->_staticRoots);
|
||||
Identity *k = (Identity *)0;
|
||||
std::vector<InetAddress> *v = (std::vector<InetAddress> *)0;
|
||||
while (i.next(k,v)) {
|
||||
rl->roots[c].dnsName = nullptr;
|
||||
|
||||
rl->roots[c].identity = nameBufPtr;
|
||||
k->toString(false,nameBufPtr);
|
||||
nameBufPtr += strlen(nameBufPtr) + 1;
|
||||
|
||||
rl->roots[c].addresses = addrBuf;
|
||||
unsigned int ac = 0;
|
||||
for(unsigned int j=(unsigned int)v->size();(ac<j)&&(ac<16);++ac)
|
||||
*(addrBuf++) = (*v)[ac];
|
||||
rl->roots[c].addressCount = ac;
|
||||
|
||||
_peers_l.lock();
|
||||
const SharedPtr<Peer> *psptr = _peers.get(k->address());
|
||||
if (psptr) {
|
||||
rl->roots[c].preferred = (psptr->ptr() == bestRootPtr) ? 1 : 0;
|
||||
rl->roots[c].online = (*psptr)->alive(now) ? 1 : 0;
|
||||
}
|
||||
_peers_l.unlock();
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
rl->count = c;
|
||||
|
||||
return rl;
|
||||
@ -668,18 +560,15 @@ private:
|
||||
|
||||
Hashtable< Address,SharedPtr<Peer> > _peers;
|
||||
Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
|
||||
|
||||
Hashtable< Str,Locator > _dynamicRoots;
|
||||
Hashtable< Identity,bool > _dynamicRootIdentities;
|
||||
Hashtable< Identity,std::vector<InetAddress> > _staticRoots;
|
||||
Hashtable< Str,Locator > _roots;
|
||||
Hashtable< Identity,bool > _rootIdentities;
|
||||
|
||||
int64_t _lastUpdatedBestRoot;
|
||||
SharedPtr<Peer> _bestRoot;
|
||||
|
||||
Mutex _peers_l;
|
||||
Mutex _paths_l;
|
||||
Mutex _dynamicRoots_l;
|
||||
Mutex _staticRoots_l;
|
||||
Mutex _roots_l;
|
||||
Mutex _bestRoot_l;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user