More threading improvements in root, more DNS TXT and multicast work (in progress)
This commit is contained in:
parent
9f9032ae36
commit
e08fc81397
10 changed files with 317 additions and 95 deletions
|
@ -129,6 +129,67 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a DNS name contiaining a public key that can sign DNS entries
|
||||
*
|
||||
* This generates the initial fields of a DNS name that contains an
|
||||
* encoded public key. Users may append any domain suffix to this name.
|
||||
*
|
||||
* @return First field(s) of DNS name
|
||||
*/
|
||||
static inline Str makeSecureDnsName(const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
|
||||
{
|
||||
uint8_t tmp[ZT_ECC384_PUBLIC_KEY_SIZE+2];
|
||||
memcpy(tmp,p384SigningKeyPublic,ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
const uint16_t crc = Utils::crc16(tmp,ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
tmp[ZT_ECC384_PUBLIC_KEY_SIZE-2] = (uint8_t)(crc >> 8);
|
||||
tmp[ZT_ECC384_PUBLIC_KEY_SIZE-1] = (uint8_t)(crc);
|
||||
Str name;
|
||||
char b32[128];
|
||||
Utils::b32e(tmp,35,b32,sizeof(b32));
|
||||
name << b32;
|
||||
Utils::b32e(tmp + 35,(ZT_ECC384_PUBLIC_KEY_SIZE+2) - 35,b32,sizeof(b32));
|
||||
name << '.';
|
||||
name << b32;
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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])
|
||||
{
|
||||
uint8_t b32[128];
|
||||
unsigned int b32ptr = 0;
|
||||
char tmp[1024];
|
||||
Utils::scopy(tmp,sizeof(tmp),name);
|
||||
bool ok = false;
|
||||
for(char *saveptr=(char *)0,*p=Utils::stok(tmp,".",&saveptr);p;p=Utils::stok((char *)0,".",&saveptr)) {
|
||||
if (b32ptr >= sizeof(b32))
|
||||
break;
|
||||
int s = Utils::b32d(p,b32 + b32ptr,sizeof(b32) - b32ptr);
|
||||
if (s > 0) {
|
||||
b32ptr += (unsigned int)s;
|
||||
if (b32ptr > 2) {
|
||||
const uint16_t crc = Utils::crc16(b32,b32ptr);
|
||||
if ((b32[b32ptr-2] == (uint8_t)(crc >> 8))&&(b32[b32ptr-1] == (uint8_t)(crc & 0xff))) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (b32ptr == (ZT_ECC384_PUBLIC_KEY_SIZE + 2)) {
|
||||
memcpy(p384SigningKeyPublic,b32,ZT_ECC384_PUBLIC_KEY_SIZE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make DNS TXT records for this locator
|
||||
*
|
||||
|
@ -184,7 +245,7 @@ public:
|
|||
* now contains the contents of the supplied TXT records.
|
||||
*/
|
||||
template<typename I>
|
||||
inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE])
|
||||
inline bool decodeTxtRecords(const Str &dnsName,I start,I end)
|
||||
{
|
||||
uint8_t dec[256],s384[48];
|
||||
try {
|
||||
|
@ -204,12 +265,13 @@ public:
|
|||
for(std::vector<Str>::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i)
|
||||
tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec)));
|
||||
|
||||
if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) {
|
||||
return false;
|
||||
}
|
||||
SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE);
|
||||
if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) {
|
||||
return false;
|
||||
uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
if (decodeSecureDnsName(dnsName.c_str(),p384SigningKeyPublic)) {
|
||||
if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE)
|
||||
return false;
|
||||
SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE);
|
||||
if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE)))
|
||||
return false;
|
||||
}
|
||||
|
||||
deserialize(*tmp,0);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Network.hpp"
|
||||
#include "Trace.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Locator.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -172,6 +173,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct _processBackgroundTasks_ping_eachRoot
|
||||
{
|
||||
Hashtable< void *,bool > roots;
|
||||
|
@ -179,7 +181,7 @@ struct _processBackgroundTasks_ping_eachRoot
|
|||
void *tPtr;
|
||||
bool online;
|
||||
|
||||
inline void operator()(const Root &root,const SharedPtr<Peer> &peer)
|
||||
ZT_ALWAYS_INLINE void operator()(const Root &root,const SharedPtr<Peer> &peer)
|
||||
{
|
||||
unsigned int v4SendCount = 0,v6SendCount = 0;
|
||||
peer->ping(tPtr,now,v4SendCount,v6SendCount);
|
||||
|
@ -204,6 +206,7 @@ struct _processBackgroundTasks_ping_eachRoot
|
|||
roots.set((void *)peer.ptr(),true);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct _processBackgroundTasks_ping_eachPeer
|
||||
{
|
||||
|
@ -211,7 +214,7 @@ struct _processBackgroundTasks_ping_eachPeer
|
|||
void *tPtr;
|
||||
Hashtable< void *,bool > *roots;
|
||||
|
||||
inline void operator()(const SharedPtr<Peer> &peer)
|
||||
ZT_ALWAYS_INLINE void operator()(const SharedPtr<Peer> &peer)
|
||||
{
|
||||
if (!roots->contains((void *)peer.ptr())) {
|
||||
unsigned int v4SendCount = 0,v6SendCount = 0;
|
||||
|
@ -234,22 +237,24 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||
if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) {
|
||||
_lastPing = now;
|
||||
try {
|
||||
#if 0
|
||||
_processBackgroundTasks_ping_eachRoot rf;
|
||||
rf.now = now;
|
||||
rf.tPtr = tptr;
|
||||
rf.online = false;
|
||||
RR->topology->eachRoot(rf);
|
||||
#endif
|
||||
|
||||
_processBackgroundTasks_ping_eachPeer pf;
|
||||
pf.now = now;
|
||||
pf.tPtr = tptr;
|
||||
pf.roots = &rf.roots;
|
||||
//pf.roots = &rf.roots;
|
||||
RR->topology->eachPeer(pf);
|
||||
|
||||
if (rf.online != _online) {
|
||||
_online = rf.online;
|
||||
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
}
|
||||
//if (rf.online != _online) {
|
||||
// _online = rf.online;
|
||||
// postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
//}
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
|
182
node/Root.hpp
182
node/Root.hpp
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
/****/
|
||||
|
||||
#ifndef ZT_ROOT_HPP
|
||||
#define ZT_ROOT_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Str.hpp"
|
||||
#include "ECC384.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A root entry pointing to a node capable of global identity lookup and indirect transit
|
||||
*
|
||||
* Root entries point to DNS records that contain TXT entries that decode to Locator objects
|
||||
* pointing to actual root nodes. A default root identity and static addresses can also be
|
||||
* provided as fallback if DNS is not available.
|
||||
*
|
||||
* Note that root identities can change if DNS returns a different result, but that DNS entries
|
||||
* are authenticated using their own signature scheme. This allows a root DNS name to serve
|
||||
* up different roots based on factors like location or relative load of different roots.
|
||||
*
|
||||
* It's also possible to create a root with no DNS and no DNS validator public key. This root
|
||||
* will be a static entry pointing to a single root identity and set of physical addresses.
|
||||
*/
|
||||
class Root
|
||||
{
|
||||
public:
|
||||
ZT_ALWAYS_INLINE Root() : _dnsPublicKeySize(0) {}
|
||||
|
||||
/**
|
||||
* Create a new root entry
|
||||
*
|
||||
* @param dn DNS name
|
||||
* @param dnspk DNS public key for record validation
|
||||
* @param dnspksize Size of DNS public key (currently always the size of a NIST P-384 point compressed public key)
|
||||
* @param dflId Default identity if DNS is not available
|
||||
* @param dflAddrs Default IP addresses if DNS is not available
|
||||
*/
|
||||
template<typename S>
|
||||
ZT_ALWAYS_INLINE Root(S dn,const uint8_t *const dnspk,const unsigned int dnspksize,const Identity &dflId,const std::vector<InetAddress> &dflAddrs) :
|
||||
_defaultIdentity(dflId),
|
||||
_defaultAddresses(dflAddrs),
|
||||
_dnsName(dn),
|
||||
_dnsPublicKeySize(dnspksize)
|
||||
{
|
||||
if (dnspksize != 0) {
|
||||
if (dnspksize > sizeof(_dnsPublicKey))
|
||||
throw ZT_EXCEPTION_INVALID_ARGUMENT;
|
||||
memcpy(_dnsPublicKey,dnspk,dnspksize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current identity (either default or latest locator)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Identity id() const
|
||||
{
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id();
|
||||
return _defaultIdentity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id Identity to check
|
||||
* @return True if identity equals this root's current identity
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool is(const Identity &id) const
|
||||
{
|
||||
return ((_lastFetchedLocator.id()) ? (id == _lastFetchedLocator.id()) : (id == _defaultIdentity));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current ZeroTier address (either default or latest locator)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Address address() const
|
||||
{
|
||||
if (_lastFetchedLocator.id())
|
||||
return _lastFetchedLocator.id().address();
|
||||
return _defaultIdentity.address();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DNS name for this root or empty string if static entry with no DNS
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const Str dnsName() const { return _dnsName; }
|
||||
|
||||
/**
|
||||
* @return Latest locator or NIL locator object if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE Locator locator() const { return _lastFetchedLocator; }
|
||||
|
||||
/**
|
||||
* @return Timestamp of latest retrieved locator or 0 if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE int64_t locatorTimestamp() const { return _lastFetchedLocator.timestamp(); }
|
||||
|
||||
/**
|
||||
* Update locator, returning true if new locator is valid and newer than existing
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool updateLocator(const Locator &loc)
|
||||
{
|
||||
if (!loc.verify())
|
||||
return false;
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this root's locator from a series of TXT records
|
||||
*/
|
||||
template<typename I>
|
||||
ZT_ALWAYS_INLINE bool updateLocatorFromTxt(I start,I end)
|
||||
{
|
||||
try {
|
||||
if (_dnsPublicKeySize != ZT_ECC384_PUBLIC_KEY_SIZE)
|
||||
return false;
|
||||
Locator loc;
|
||||
if (!loc.decodeTxtRecords(start,end,_dnsPublicKey)) // also does verify()
|
||||
return false;
|
||||
if ((loc.phy().size() > 0)&&(loc.timestamp() > _lastFetchedLocator.timestamp())) {
|
||||
_lastFetchedLocator = loc;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch ( ... ) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a random physical IP for this root with the given address family
|
||||
*
|
||||
* @param addressFamily AF_INET or AF_INET6
|
||||
* @return Address or InetAddress::NIL if no addresses exist for the given family
|
||||
*/
|
||||
ZT_ALWAYS_INLINE const InetAddress &pickPhysical(const int addressFamily) const
|
||||
{
|
||||
std::vector<const InetAddress *> pickList;
|
||||
const std::vector<InetAddress> *const av = (_lastFetchedLocator) ? &(_lastFetchedLocator.phy()) : &_defaultAddresses;
|
||||
for(std::vector<InetAddress>::const_iterator i(av->begin());i!=av->end();++i) {
|
||||
if (addressFamily == (int)i->ss_family) {
|
||||
pickList.push_back(&(*i));
|
||||
}
|
||||
}
|
||||
if (pickList.size() == 1)
|
||||
return *pickList[0];
|
||||
else if (pickList.size() > 1)
|
||||
return *pickList[(unsigned long)Utils::random() % (unsigned long)pickList.size()];
|
||||
return InetAddress::NIL;
|
||||
}
|
||||
|
||||
private:
|
||||
Identity _defaultIdentity;
|
||||
std::vector<InetAddress> _defaultAddresses;
|
||||
Str _dnsName;
|
||||
Locator _lastFetchedLocator;
|
||||
unsigned int _dnsPublicKeySize;
|
||||
uint8_t _dnsPublicKey[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
43
node/Str.hpp
43
node/Str.hpp
|
@ -151,14 +151,35 @@ public:
|
|||
return ((*this) << a.toString(tmp));
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE Str &append(const char *s,const unsigned int max)
|
||||
{
|
||||
if (likely(s != (const char *)0)) {
|
||||
unsigned long l = _l;
|
||||
unsigned int c = 0;
|
||||
while (*s) {
|
||||
if (c++ >= max) break;
|
||||
if (unlikely(l >= ZT_STR_CAPACITY)) {
|
||||
_s[ZT_STR_CAPACITY] = 0;
|
||||
_l = ZT_STR_CAPACITY;
|
||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||
}
|
||||
_s[l++] = *s;
|
||||
++s;
|
||||
}
|
||||
_s[l] = 0;
|
||||
_l = (uint8_t)l;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZT_ALWAYS_INLINE operator bool() const { return (_l != 0); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(strcmp(_s,s._s) == 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(strcmp(_s,s._s) != 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ((_l < s._l)&&(strcmp(_s,s._s) < 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return ((_l > s._l)&&(strcmp(_s,s._s) > 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return ((_l <= s._l)&&(strcmp(_s,s._s) <= 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return ((_l >= s._l)&&(strcmp(_s,s._s) >= 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(memcmp(_s,s._s,_l) == 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(memcmp(_s,s._s,_l) != 0)); }
|
||||
ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ( (_l < s._l) ? true : ((_l == s._l) ? (memcmp(_s,s._s,_l) < 0) : false) ); }
|
||||
ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return (s < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return !(s < *this); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return !(*this < s); }
|
||||
|
||||
ZT_ALWAYS_INLINE bool operator==(const char *s) const { return (strcmp(_s,s) == 0); }
|
||||
ZT_ALWAYS_INLINE bool operator!=(const char *s) const { return (strcmp(_s,s) != 0); }
|
||||
|
@ -167,6 +188,16 @@ public:
|
|||
ZT_ALWAYS_INLINE bool operator<=(const char *s) const { return (strcmp(_s,s) <= 0); }
|
||||
ZT_ALWAYS_INLINE bool operator>=(const char *s) const { return (strcmp(_s,s) >= 0); }
|
||||
|
||||
ZT_ALWAYS_INLINE unsigned long hashCode() const
|
||||
{
|
||||
const char *p = _s;
|
||||
unsigned long h = 0;
|
||||
char c;
|
||||
while ((c = *(p++)))
|
||||
h = (31 * h) + (unsigned long)c;
|
||||
return h;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _l;
|
||||
char _s[ZT_STR_CAPACITY+1];
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "../include/ZeroTierOne.h"
|
||||
|
@ -32,8 +33,9 @@
|
|||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Root.hpp"
|
||||
#include "Locator.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -65,7 +67,7 @@ public:
|
|||
{
|
||||
SharedPtr<Peer> np;
|
||||
{
|
||||
Mutex::Lock _l(_peers_m);
|
||||
Mutex::Lock _l(_peers_l);
|
||||
SharedPtr<Peer> &hp = _peers[peer->address()];
|
||||
if (!hp)
|
||||
hp = peer;
|
||||
|
@ -86,11 +88,12 @@ public:
|
|||
if (zta == _myIdentity.address())
|
||||
return SharedPtr<Peer>();
|
||||
|
||||
Mutex::Lock l1(_peers_m);
|
||||
Mutex::Lock l1(_peers_l);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||
if (ap)
|
||||
return *ap;
|
||||
|
||||
#if 0
|
||||
Mutex::Lock l2(_roots_m);
|
||||
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
|
||||
if (r->address() == zta) {
|
||||
|
@ -101,6 +104,7 @@ public:
|
|||
} catch ( ... ) {}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
@ -115,7 +119,7 @@ public:
|
|||
if (zta == _myIdentity.address()) {
|
||||
return _myIdentity;
|
||||
} else {
|
||||
Mutex::Lock _l(_peers_m);
|
||||
Mutex::Lock _l(_peers_l);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||
if (ap)
|
||||
return (*ap)->identity();
|
||||
|
@ -132,7 +136,7 @@ public:
|
|||
*/
|
||||
ZT_ALWAYS_INLINE SharedPtr<Path> getPath(const int64_t l,const InetAddress &r)
|
||||
{
|
||||
Mutex::Lock _l(_paths_m);
|
||||
Mutex::Lock _l(_paths_l);
|
||||
SharedPtr<Path> &p = _paths[Path::HashKey(l,r)];
|
||||
if (!p)
|
||||
p.set(new Path(l,r));
|
||||
|
@ -145,11 +149,13 @@ public:
|
|||
*/
|
||||
ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const
|
||||
{
|
||||
#if 0
|
||||
Mutex::Lock l(_roots_m);
|
||||
for(std::vector<Root>::const_iterator r(_roots.begin());r!=_roots.end();++r) {
|
||||
if (r->is(id))
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -159,7 +165,7 @@ public:
|
|||
ZT_ALWAYS_INLINE void doPeriodicTasks(int64_t now)
|
||||
{
|
||||
{
|
||||
Mutex::Lock _l1(_peers_m);
|
||||
Mutex::Lock _l1(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
|
@ -170,7 +176,7 @@ public:
|
|||
}
|
||||
}
|
||||
{
|
||||
Mutex::Lock _l(_paths_m);
|
||||
Mutex::Lock _l(_paths_l);
|
||||
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
|
||||
Path::HashKey *k = (Path::HashKey *)0;
|
||||
SharedPtr<Path> *p = (SharedPtr<Path> *)0;
|
||||
|
@ -188,7 +194,7 @@ public:
|
|||
ZT_ALWAYS_INLINE unsigned long countActive(int64_t now) const
|
||||
{
|
||||
unsigned long cnt = 0;
|
||||
Mutex::Lock _l(_peers_m);
|
||||
Mutex::Lock _l(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
|
@ -212,7 +218,7 @@ public:
|
|||
template<typename F>
|
||||
ZT_ALWAYS_INLINE void eachPeer(F f)
|
||||
{
|
||||
Mutex::Lock l(_peers_m);
|
||||
Mutex::Lock l(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = (Address *)0;
|
||||
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
|
||||
|
@ -221,6 +227,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Apply a function or function object to all roots
|
||||
*
|
||||
|
@ -237,7 +244,7 @@ public:
|
|||
SharedPtr<Peer> rp;
|
||||
for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
|
||||
{
|
||||
Mutex::Lock l2(_peers_m);
|
||||
Mutex::Lock l2(_peers_l);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(i->address());
|
||||
if (ap) {
|
||||
rp = *ap;
|
||||
|
@ -256,7 +263,7 @@ public:
|
|||
* @param now Current time
|
||||
* @return Best/fastest currently connected root or NULL if none
|
||||
*/
|
||||
ZT_ALWAYS_INLINE SharedPtr<Peer> root(const int64_t now)
|
||||
inline SharedPtr<Peer> root(const int64_t now)
|
||||
{
|
||||
Mutex::Lock l(_bestRoot_m);
|
||||
if ((!_bestRoot)||((now - _lastRankedBestRoot) >= ZT_FIND_BEST_ROOT_PERIOD)) {
|
||||
|
@ -266,7 +273,7 @@ public:
|
|||
long bestQuality = 2147483647;
|
||||
for(std::vector<Root>::const_iterator i(_roots.begin());i!=_roots.end();++i) {
|
||||
{
|
||||
Mutex::Lock l2(_peers_m);
|
||||
Mutex::Lock l2(_peers_l);
|
||||
const SharedPtr<Peer> *const ap = _peers.get(i->address());
|
||||
if (ap) {
|
||||
rp = *ap;
|
||||
|
@ -287,6 +294,54 @@ public:
|
|||
}
|
||||
return _bestRoot;
|
||||
}
|
||||
#endif
|
||||
|
||||
ZT_ALWAYS_INLINE SharedPtr<Peer> root(const int64_t now)
|
||||
{
|
||||
return SharedPtr<Peer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Names of dynamic roots currently known by the system
|
||||
*/
|
||||
ZT_ALWAYS_INLINE std::vector<Str> dynamicRootNames() const
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
return _dynamicRoots.keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update a static root entry
|
||||
*
|
||||
* @param id Static root's identity
|
||||
* @param addrs Static root's IP address(es)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void setStaticRoot(const Identity &id,const std::vector<InetAddress> &addrs)
|
||||
{
|
||||
Mutex::Lock l(_staticRoots_l);
|
||||
_staticRoots[id] = addrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or update dynamic root if new locator is newer and valid
|
||||
*
|
||||
* This checks internal validity of the new locator including its internal self-signature.
|
||||
* It does not check any DNS signatures.
|
||||
*
|
||||
* @param dnsName DNS name used to retrive root
|
||||
* @param latestLocator Latest locator
|
||||
* @return True if latest locator is internally valid and newer
|
||||
*/
|
||||
ZT_ALWAYS_INLINE bool setDynamicRoot(const Str &dnsName,const Locator &latestLocator)
|
||||
{
|
||||
Mutex::Lock l(_dynamicRoots_l);
|
||||
Locator &ll = _dynamicRoots[dnsName];
|
||||
if (ll.timestamp() < latestLocator.timestamp()) {
|
||||
ll = latestLocator;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the best relay to a given address, which may or may not be a root
|
||||
|
@ -298,15 +353,15 @@ public:
|
|||
ZT_ALWAYS_INLINE SharedPtr<Peer> findRelayTo(const int64_t now,const Address &toAddr)
|
||||
{
|
||||
// TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root)
|
||||
return root(now);
|
||||
//return root(now);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param allPeers vector to fill with all current peers
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
|
||||
inline void getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
|
||||
{
|
||||
Mutex::Lock l(_peers_m);
|
||||
Mutex::Lock l(_peers_l);
|
||||
allPeers.clear();
|
||||
allPeers.reserve(_peers.size());
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
|
||||
|
@ -385,7 +440,7 @@ public:
|
|||
/**
|
||||
* Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration)
|
||||
*/
|
||||
ZT_ALWAYS_INLINE void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
|
||||
inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
|
||||
{
|
||||
if (!pathNetwork) {
|
||||
_numConfiguredPhysicalPaths = 0;
|
||||
|
@ -422,17 +477,26 @@ public:
|
|||
private:
|
||||
const RuntimeEnvironment *const RR;
|
||||
const Identity _myIdentity;
|
||||
|
||||
std::pair<InetAddress,ZT_PhysicalPathConfiguration> _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
|
||||
unsigned int _numConfiguredPhysicalPaths;
|
||||
std::vector<Root> _roots;
|
||||
SharedPtr<Peer> _bestRoot;
|
||||
int64_t _lastRankedBestRoot;
|
||||
|
||||
Hashtable< Address,SharedPtr<Peer> > _peers;
|
||||
Hashtable< Path::HashKey,SharedPtr<Path> > _paths;
|
||||
Mutex _roots_m;
|
||||
Mutex _bestRoot_m;
|
||||
Mutex _peers_m;
|
||||
Mutex _paths_m;
|
||||
|
||||
Hashtable< Identity,std::vector<InetAddress> > _staticRoots;
|
||||
Hashtable< Str,Locator > _dynamicRoots;
|
||||
|
||||
//std::vector<Root> _roots;
|
||||
//SharedPtr<Peer> _bestRoot;
|
||||
//int64_t _lastRankedBestRoot;
|
||||
//Mutex _roots_m;
|
||||
//Mutex _bestRoot_m;
|
||||
|
||||
Mutex _peers_l;
|
||||
Mutex _paths_l;
|
||||
Mutex _staticRoots_l;
|
||||
Mutex _dynamicRoots_l;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
|
@ -95,6 +95,49 @@ char *Utils::decimal(unsigned long n,char s[24])
|
|||
return s;
|
||||
}
|
||||
|
||||
unsigned short Utils::crc16(const void *buf,unsigned int len)
|
||||
{
|
||||
static const uint16_t crc16tab[256]= {
|
||||
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
|
||||
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
|
||||
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
|
||||
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
|
||||
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
|
||||
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
|
||||
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
|
||||
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
|
||||
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
|
||||
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
|
||||
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
|
||||
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
|
||||
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
|
||||
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
|
||||
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
|
||||
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
|
||||
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
|
||||
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
|
||||
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
|
||||
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
|
||||
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
|
||||
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
|
||||
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
|
||||
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
|
||||
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
|
||||
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
|
||||
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
|
||||
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
|
||||
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
|
||||
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
|
||||
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
|
||||
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
|
||||
};
|
||||
uint16_t crc = 0;
|
||||
const uint8_t *p = (const uint8_t *)buf;
|
||||
for(unsigned int i=0;i<len;++i)
|
||||
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *(p++)) & 0x00ff];
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned int Utils::unhex(const char *h,void *buf,unsigned int buflen)
|
||||
{
|
||||
unsigned int l = 0;
|
||||
|
|
|
@ -68,6 +68,11 @@ public:
|
|||
*/
|
||||
static char *decimal(unsigned long n,char s[24]);
|
||||
|
||||
/**
|
||||
* Compute CRC16-CCITT
|
||||
*/
|
||||
static uint16_t crc16(const void *buf,unsigned int len);
|
||||
|
||||
/**
|
||||
* Convert an unsigned integer into hex
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue