mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-19 21:46:54 +02:00
Faster hash table, various other optimizations and simplification.
This commit is contained in:
parent
cbf174f96d
commit
87da45b3f5
25 changed files with 495 additions and 380 deletions
|
@ -355,11 +355,11 @@ public:
|
|||
private:
|
||||
template<typename O>
|
||||
static ZT_INLINE unsigned long _hc(const O &obj) { return (unsigned long)obj.hashCode(); }
|
||||
static ZT_INLINE unsigned long _hc(const uint64_t i) noexcept { return (unsigned long)(i ^ (i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const uint64_t i) noexcept { return (unsigned long)(i + (i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const uint32_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static ZT_INLINE unsigned long _hc(const uint16_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static ZT_INLINE unsigned long _hc(const uint8_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static ZT_INLINE unsigned long _hc(const int64_t i) noexcept { return (unsigned long)((unsigned long long)i ^ ((unsigned long long)i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const int64_t i) noexcept { return (unsigned long)((unsigned long long)i + ((unsigned long long)i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const int32_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static ZT_INLINE unsigned long _hc(const int16_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
||||
static ZT_INLINE unsigned long _hc(const int8_t i) noexcept { return ((unsigned long)i * (unsigned long)0x9e3779b1); }
|
|
@ -70,11 +70,6 @@ public:
|
|||
*/
|
||||
ZT_INLINE void zero() noexcept { _a = 0; }
|
||||
|
||||
/**
|
||||
* @return Hash code for use with Hashtable
|
||||
*/
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)_a; }
|
||||
|
||||
/**
|
||||
* @param s String with at least 11 characters of space available (10 + terminating NULL)
|
||||
* @return Hexadecimal string
|
||||
|
@ -108,6 +103,7 @@ public:
|
|||
*/
|
||||
ZT_INLINE bool isReserved() const noexcept { return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
|
||||
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)_a; }
|
||||
ZT_INLINE operator bool() const noexcept { return (_a != 0); }
|
||||
|
||||
ZT_INLINE bool operator==(const Address &a) const noexcept { return _a == a._a; }
|
||||
|
|
|
@ -17,7 +17,7 @@ set(core_headers
|
|||
Expect.hpp
|
||||
FCV.hpp
|
||||
Fingerprint.hpp
|
||||
Hashtable.hpp
|
||||
FlatMap.hpp
|
||||
Identity.hpp
|
||||
InetAddress.hpp
|
||||
Locator.hpp
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
#include "Constants.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Path.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
@ -89,10 +89,7 @@ public:
|
|||
ERR_OUT_OF_MEMORY
|
||||
};
|
||||
|
||||
ZT_INLINE Defragmenter() :
|
||||
_messages(GCT * 2)
|
||||
{
|
||||
}
|
||||
ZT_INLINE Defragmenter() {}
|
||||
|
||||
/**
|
||||
* Process a fragment of a multi-part message
|
||||
|
@ -167,12 +164,8 @@ public:
|
|||
std::vector<std::pair<int64_t,uint64_t> > messagesByLastUsedTime;
|
||||
messagesByLastUsedTime.reserve(_messages.size());
|
||||
|
||||
typename Hashtable<uint64_t,_E>::Iterator i(_messages);
|
||||
uint64_t *mk = nullptr;
|
||||
_E *mv = nullptr;
|
||||
while (i.next(mk,mv))
|
||||
messagesByLastUsedTime.push_back(std::pair<int64_t,uint64_t>(mv->lastUsed,*mk));
|
||||
|
||||
for(typename FlatMap< uint64_t,_E >::const_iterator i(_messages.begin());i!=_messages.end();++i)
|
||||
messagesByLastUsedTime.push_back(std::pair<int64_t,uint64_t>(i->second.lastUsed,i->first));
|
||||
std::sort(messagesByLastUsedTime.begin(),messagesByLastUsedTime.end());
|
||||
|
||||
ml.writing(); // acquire write lock on _messages
|
||||
|
@ -295,7 +288,21 @@ public:
|
|||
private:
|
||||
struct _E
|
||||
{
|
||||
ZT_INLINE _E() noexcept : id(0),lastUsed(0),totalFragmentsExpected(0),fragmentsReceived(0),via(),message(),lock() {}
|
||||
ZT_INLINE _E() noexcept :
|
||||
id(0),
|
||||
lastUsed(0),
|
||||
totalFragmentsExpected(0),
|
||||
fragmentsReceived(0) {}
|
||||
|
||||
ZT_INLINE _E(const _E &e) noexcept :
|
||||
id(e.id),
|
||||
lastUsed(e.lastUsed),
|
||||
totalFragmentsExpected(e.totalFragmentsExpected),
|
||||
fragmentsReceived(e.fragmentsReceived),
|
||||
via(e.via),
|
||||
message(e.message),
|
||||
lock() {}
|
||||
|
||||
ZT_INLINE ~_E()
|
||||
{
|
||||
if (via) {
|
||||
|
@ -304,6 +311,7 @@ private:
|
|||
via->_inboundFragmentedMessages_l.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t id;
|
||||
volatile int64_t lastUsed;
|
||||
unsigned int totalFragmentsExpected;
|
||||
|
@ -313,7 +321,7 @@ private:
|
|||
Mutex lock;
|
||||
};
|
||||
|
||||
Hashtable< uint64_t,_E > _messages;
|
||||
FlatMap< uint64_t,_E > _messages;
|
||||
RWMutex _messages_l;
|
||||
};
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ std::vector<uint8_t> &Dictionary::operator[](const char *k)
|
|||
const std::vector<uint8_t> &Dictionary::operator[](const char *k) const
|
||||
{
|
||||
static const std::vector<uint8_t> emptyEntry;
|
||||
const std::vector<uint8_t> *const e = _t.get(_toKey(k));
|
||||
return (e) ? *e : emptyEntry;
|
||||
std::map< uint64_t,std::vector<uint8_t> >::const_iterator e(_t.find(_toKey(k)));
|
||||
return (e == _t.end()) ? emptyEntry : e->second;
|
||||
}
|
||||
|
||||
void Dictionary::add(const char *k,bool v)
|
||||
|
@ -170,11 +170,8 @@ void Dictionary::encode(std::vector<uint8_t> &out) const
|
|||
|
||||
out.clear();
|
||||
|
||||
Hashtable< uint64_t,std::vector<uint8_t> >::Iterator ti(const_cast<Dictionary *>(this)->_t);
|
||||
uint64_t *kk = nullptr;
|
||||
std::vector<uint8_t> *vv = nullptr;
|
||||
while (ti.next(kk,vv)) {
|
||||
str[0] = *kk;
|
||||
for(std::map< uint64_t,std::vector<uint8_t> >::const_iterator ti(_t.begin());ti!=_t.end();++ti) {
|
||||
str[0] = ti->first;
|
||||
const char *k = (const char *)str;
|
||||
|
||||
for(;;) {
|
||||
|
@ -186,7 +183,7 @@ void Dictionary::encode(std::vector<uint8_t> &out) const
|
|||
|
||||
out.push_back(61); // =
|
||||
|
||||
for(std::vector<uint8_t>::const_iterator i(vv->begin());i!=vv->end();++i) {
|
||||
for(std::vector<uint8_t>::const_iterator i(ti->second.begin());i!=ti->second.end();++i) {
|
||||
uint8_t c = *i;
|
||||
switch(c) {
|
||||
case 0:
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
#include "Utils.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -168,7 +168,7 @@ public:
|
|||
bool decode(const void *data,unsigned int len);
|
||||
|
||||
private:
|
||||
Hashtable< uint64_t,std::vector<uint8_t> > _t;
|
||||
std::map< uint64_t,std::vector<uint8_t> > _t;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
245
node/FlatMap.hpp
Normal file
245
node/FlatMap.hpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright (c)2013-2020 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: 2024-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_FLATMAP_HPP
|
||||
#define ZT_FLATMAP_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
/**
|
||||
* A very simple and fast flat hash table
|
||||
*
|
||||
* This is designed to prioritize performance over memory, though with
|
||||
* endpoint ZeroTier nodes this is used in cases where the data set is not
|
||||
* that large (e.g. networks, peers) and so memory consumption should not
|
||||
* be much.
|
||||
*
|
||||
* It creates a flat hash table that maps keys to values and doubles its
|
||||
* size whenever a collision occurs. The size is always a power of two so
|
||||
* that only very fast operations like add, XOR, and bit mask can be used
|
||||
* for hash table lookup.
|
||||
*
|
||||
* It also saves actual key/value pairs in a linked list for relatively
|
||||
* fast iteration compared to a hash table where you have to iterate through
|
||||
* a bunch of empty buckets. Iteration order should be considered undefined.
|
||||
*
|
||||
* @tparam K Key type
|
||||
* @tparam V Value type
|
||||
* @tparam IC Initial capacity (must be a power of two)
|
||||
*/
|
||||
template<typename K,typename V,unsigned long IC = 16>
|
||||
class FlatMap
|
||||
{
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef V mapped_type;
|
||||
typedef std::pair<K,V> value_type;
|
||||
typedef typename std::list< std::pair<K,V> >::iterator iterator;
|
||||
typedef typename std::list< std::pair<K,V> >::const_iterator const_iterator;
|
||||
|
||||
ZT_INLINE FlatMap() :
|
||||
_d(),
|
||||
_null(),
|
||||
_b(new iterator[IC]),
|
||||
_s(IC),
|
||||
_m(IC - 1)
|
||||
{
|
||||
}
|
||||
|
||||
ZT_INLINE FlatMap(const FlatMap &m) :
|
||||
_d(m._d),
|
||||
_null(),
|
||||
_b(new iterator[m._s]),
|
||||
_s(m._s),
|
||||
_m(m._m)
|
||||
{
|
||||
try {
|
||||
for (iterator i=_d.begin();i!=_d.end();++i)
|
||||
_b[_hc(i->first) & _m] = i;
|
||||
} catch ( ... ) {
|
||||
delete [] _b;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE ~FlatMap()
|
||||
{
|
||||
delete [] _b;
|
||||
}
|
||||
|
||||
ZT_INLINE FlatMap &operator=(const FlatMap &m)
|
||||
{
|
||||
_d = m._d;
|
||||
delete [] _b;
|
||||
_b = nullptr;
|
||||
_b = new iterator[m._s];
|
||||
_s = m._s;
|
||||
_m = m._m;
|
||||
for(iterator i=_d.begin();i!=_d.end();++i)
|
||||
_b[_hc(i->first) & _m] = i;
|
||||
}
|
||||
|
||||
ZT_INLINE void clear()
|
||||
{
|
||||
_d.clear();
|
||||
delete [] _b;
|
||||
_b = nullptr;
|
||||
_b = new iterator[IC];
|
||||
_s = IC;
|
||||
_m = IC - 1;
|
||||
}
|
||||
|
||||
ZT_INLINE V *get(const K &key) noexcept
|
||||
{
|
||||
const unsigned long hb = _hc(key) & _m;
|
||||
if ((_b[hb] != _null)&&(_b[hb]->first == key))
|
||||
return &(_b[hb]->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZT_INLINE const V *get(const K &key) const noexcept
|
||||
{
|
||||
const unsigned long hb = _hc(key) & _m;
|
||||
if ((_b[hb] != _null)&&(_b[hb]->first == key))
|
||||
return &(_b[hb]->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZT_INLINE iterator find(const K &key) noexcept
|
||||
{
|
||||
const unsigned long hb = _hc(key) & _m;
|
||||
if ((_b[hb] != _null)&&(_b[hb]->first == key))
|
||||
return _b[hb];
|
||||
return _d.end();
|
||||
}
|
||||
|
||||
ZT_INLINE const_iterator find(const K &key) const noexcept
|
||||
{
|
||||
const unsigned long hb = _hc(key) & _m;
|
||||
if ((_b[hb] != _null)&&(_b[hb]->first == key))
|
||||
return _b[hb];
|
||||
return _d.end();
|
||||
}
|
||||
|
||||
ZT_INLINE V &set(const K &key,const V &value)
|
||||
{
|
||||
unsigned long hb = _hc(key) & _m;
|
||||
if (_b[hb] == _null) {
|
||||
#ifdef __CPP11__
|
||||
_d.emplace_back(key,value);
|
||||
#else
|
||||
_d.push_back(std::pair<K,V>(key,value));
|
||||
#endif
|
||||
return (_b[hb] = --_d.end())->second;
|
||||
} else {
|
||||
if (_b[hb]->first == key) {
|
||||
_b[hb]->second = value;
|
||||
return _b[hb]->second;
|
||||
}
|
||||
#ifdef __CPP11__
|
||||
_d.emplace_back(key,value);
|
||||
#else
|
||||
_d.push_back(std::pair<K,V>(key,value));
|
||||
#endif
|
||||
_grow();
|
||||
return _b[_hc(key) & _m]->second;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE V &operator[](const K &key)
|
||||
{
|
||||
unsigned long hb = _hc(key) & _m;
|
||||
if (_b[hb] == _null) {
|
||||
#ifdef __CPP11__
|
||||
_d.emplace_back(key,V());
|
||||
#else
|
||||
_d.push_back(std::pair<K,V>(key,V()));
|
||||
#endif
|
||||
return (_b[hb] = --_d.end())->second;
|
||||
} else {
|
||||
if (_b[hb]->first == key)
|
||||
return _b[hb]->second;
|
||||
#ifdef __CPP11__
|
||||
_d.emplace_back(key,V());
|
||||
#else
|
||||
_d.push_back(std::pair<K,V>(key,V()));
|
||||
#endif
|
||||
_grow();
|
||||
return _b[_hc(key) & _m]->second;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_INLINE void erase(const iterator &i)
|
||||
{
|
||||
_b[_hc(i->first) & _m] = _null;
|
||||
_d.erase(i);
|
||||
}
|
||||
|
||||
ZT_INLINE void erase(const K &key)
|
||||
{
|
||||
iterator e(find(key));
|
||||
if (e != end())
|
||||
erase(e);
|
||||
}
|
||||
|
||||
ZT_INLINE iterator begin() noexcept { return _d.begin(); }
|
||||
ZT_INLINE iterator end() noexcept { return _d.end(); }
|
||||
ZT_INLINE const_iterator begin() const noexcept { return _d.begin(); }
|
||||
ZT_INLINE const_iterator end() const noexcept { return _d.end(); }
|
||||
|
||||
ZT_INLINE unsigned long size() const { return (unsigned long)_d.size(); }
|
||||
ZT_INLINE bool empty() const { return _d.empty(); }
|
||||
ZT_INLINE unsigned long hashSize() const { return _s; }
|
||||
|
||||
private:
|
||||
template<typename O>
|
||||
static ZT_INLINE unsigned long _hc(const O &obj) { return (unsigned long)obj.hashCode(); }
|
||||
static ZT_INLINE unsigned long _hc(const uint64_t i) noexcept { return (unsigned long)(i + (i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const int64_t i) noexcept { return (unsigned long)((uint64_t)i + ((uint64_t)i >> 32U)); }
|
||||
static ZT_INLINE unsigned long _hc(const uint32_t i) noexcept { return Utils::hash32(i); }
|
||||
|
||||
ZT_INLINE void _grow()
|
||||
{
|
||||
unsigned long hb;
|
||||
enlarge_again:
|
||||
delete [] _b;
|
||||
_b = nullptr; // in case 'new' throws
|
||||
_b = new iterator[_s <<= 1U];
|
||||
_m = _s - 1;
|
||||
for(iterator i=_d.begin();i!=_d.end();++i) {
|
||||
hb = _hc(i->first) & _m;
|
||||
if (_b[hb] == _null) {
|
||||
_b[hb] = i;
|
||||
} else {
|
||||
goto enlarge_again;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::list< std::pair<K,V> > _d;
|
||||
const iterator _null; // prototype of a "null" / default iterator
|
||||
iterator *_b;
|
||||
unsigned long _s;
|
||||
unsigned long _m;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif
|
|
@ -25,11 +25,7 @@ Membership::Membership() :
|
|||
_comRevocationThreshold(0),
|
||||
_lastPushedCredentials(0),
|
||||
_comAgreementLocalTimestamp(0),
|
||||
_comAgreementRemoteTimestamp(0),
|
||||
_revocations(4),
|
||||
_remoteTags(4),
|
||||
_remoteCaps(4),
|
||||
_remoteCoos(4)
|
||||
_comAgreementRemoteTimestamp(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -163,8 +159,8 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
|
|||
// 3/5 of the credential types have identical addCredential() code
|
||||
template<typename C>
|
||||
static ZT_INLINE Membership::AddCredentialResult _addCredImpl(
|
||||
Hashtable<uint32_t,C> &remoteCreds,
|
||||
const Hashtable<uint64_t,int64_t> &revocations,
|
||||
FlatMap<uint32_t,C> &remoteCreds,
|
||||
const FlatMap<uint64_t,int64_t> &revocations,
|
||||
const RuntimeEnvironment *const RR,
|
||||
void *const tPtr,
|
||||
const Identity &sourcePeerIdentity,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "Credential.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
#include "CertificateOfMembership.hpp"
|
||||
#include "Capability.hpp"
|
||||
#include "Tag.hpp"
|
||||
|
@ -106,11 +106,8 @@ public:
|
|||
{
|
||||
if (_isUnspoofableAddress(nconf,r))
|
||||
return true;
|
||||
uint32_t *k = nullptr;
|
||||
CertificateOfOwnership *v = nullptr;
|
||||
Hashtable< uint32_t,CertificateOfOwnership >::Iterator i(*(const_cast< Hashtable< uint32_t,CertificateOfOwnership> *>(&_remoteCoos)));
|
||||
while (i.next(k,v)) {
|
||||
if (_isCredentialTimestampValid(nconf,*v)&&(v->owns(r)))
|
||||
for(FlatMap< uint32_t,CertificateOfOwnership >::const_iterator i(_remoteCoos.begin());i!=_remoteCoos.end();++i) {
|
||||
if (_isCredentialTimestampValid(nconf,i->second)&&(i->second.owns(r)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -179,14 +176,12 @@ private:
|
|||
}
|
||||
|
||||
template<typename C>
|
||||
ZT_INLINE void _cleanCredImpl(const NetworkConfig &nconf,Hashtable<uint32_t,C> &remoteCreds)
|
||||
ZT_INLINE void _cleanCredImpl(const NetworkConfig &nconf,FlatMap<uint32_t,C> &remoteCreds)
|
||||
{
|
||||
uint32_t *k = nullptr;
|
||||
C *v = nullptr;
|
||||
typename Hashtable<uint32_t,C>::Iterator i(remoteCreds);
|
||||
while (i.next(k,v)) {
|
||||
if (!_isCredentialTimestampValid(nconf,*v))
|
||||
remoteCreds.erase(*k);
|
||||
for(typename FlatMap<uint32_t,C>::iterator i(remoteCreds.begin());i!=remoteCreds.end();) {
|
||||
if (!_isCredentialTimestampValid(nconf,i->second))
|
||||
remoteCreds.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,21 +198,19 @@ private:
|
|||
CertificateOfMembership _com;
|
||||
|
||||
// Revocations by credentialKey()
|
||||
Hashtable< uint64_t,int64_t > _revocations;
|
||||
FlatMap< uint64_t,int64_t > _revocations;
|
||||
|
||||
// Remote credentials that we have received from this member (and that are valid)
|
||||
Hashtable< uint32_t,Tag > _remoteTags;
|
||||
Hashtable< uint32_t,Capability > _remoteCaps;
|
||||
Hashtable< uint32_t,CertificateOfOwnership > _remoteCoos;
|
||||
FlatMap< uint32_t,Tag > _remoteTags;
|
||||
FlatMap< uint32_t,Capability > _remoteCaps;
|
||||
FlatMap< uint32_t,CertificateOfOwnership > _remoteCoos;
|
||||
|
||||
public:
|
||||
class CapabilityIterator
|
||||
{
|
||||
public:
|
||||
ZT_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) noexcept :
|
||||
_hti(m._remoteCaps),
|
||||
_k(nullptr),
|
||||
_c(nullptr),
|
||||
_hti(m._remoteCaps.begin()),
|
||||
_m(m),
|
||||
_nconf(nconf)
|
||||
{
|
||||
|
@ -225,17 +218,16 @@ public:
|
|||
|
||||
ZT_INLINE Capability *next() noexcept
|
||||
{
|
||||
while (_hti.next(_k,_c)) {
|
||||
if (_m._isCredentialTimestampValid(_nconf,*_c))
|
||||
return _c;
|
||||
while (_hti != _m._remoteCaps.end()) {
|
||||
FlatMap< uint32_t,Capability >::iterator i(_hti++);
|
||||
if (_m._isCredentialTimestampValid(_nconf,i->second))
|
||||
return &(i->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Hashtable< uint32_t,Capability >::Iterator _hti;
|
||||
uint32_t *_k;
|
||||
Capability *_c;
|
||||
FlatMap< uint32_t,Capability >::iterator _hti;
|
||||
Membership &_m;
|
||||
const NetworkConfig &_nconf;
|
||||
};
|
||||
|
|
110
node/Network.cpp
110
node/Network.cpp
|
@ -598,7 +598,7 @@ Network::~Network()
|
|||
// This is done in Node::leave() so we can pass tPtr properly
|
||||
//RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
|
||||
} else {
|
||||
RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
|
||||
RR->node->configureVirtualNetworkPort(nullptr,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN,&ctmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +626,7 @@ bool Network::filterOutgoingPacket(
|
|||
Mutex::Lock l1(_memberships_l);
|
||||
Mutex::Lock l2(_config_l);
|
||||
|
||||
Membership *const membership = (ztDest) ? _memberships.get(ztDest) : (Membership *)0;
|
||||
Membership *const membership = (ztDest) ? _memberships.get(ztDest) : nullptr;
|
||||
|
||||
switch(_doZtFilter(RR,rrl,_config,membership,false,ztSource,ztFinalDest,macSource,macDest,frameData,frameLen,etherType,vlanId,_config.rules,_config.ruleCount,cc,ccLength,ccWatch,qosBucket)) {
|
||||
|
||||
|
@ -745,7 +745,7 @@ int Network::filterIncomingPacket(
|
|||
Address cc;
|
||||
unsigned int ccLength = 0;
|
||||
bool ccWatch = false;
|
||||
const Capability *c = (Capability *)0;
|
||||
const Capability *c = nullptr;
|
||||
|
||||
uint8_t qosBucket = 255; // For incoming packets this is a dummy value
|
||||
|
||||
|
@ -1099,13 +1099,8 @@ void Network::doPeriodicTasks(void *tPtr,const int64_t now)
|
|||
{
|
||||
Mutex::Lock l1(_memberships_l);
|
||||
|
||||
{
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m))
|
||||
m->clean(now,_config);
|
||||
}
|
||||
for(FlatMap<Address,Membership>::iterator i(_memberships.begin());i!=_memberships.end();++i)
|
||||
i->second.clean(now,_config);
|
||||
|
||||
{
|
||||
Mutex::Lock l2(_myMulticastGroups_l);
|
||||
|
@ -1133,32 +1128,24 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
|
|||
|
||||
// Anti-DOS circuit breaker to prevent nodes from spamming us with absurd numbers of bridge routes
|
||||
while (_remoteBridgeRoutes.size() > ZT_MAX_BRIDGE_ROUTES) {
|
||||
Hashtable< Address,unsigned long > counts;
|
||||
FlatMap< Address,unsigned long > counts;
|
||||
Address maxAddr;
|
||||
unsigned long maxCount = 0;
|
||||
|
||||
MAC *m = nullptr;
|
||||
Address *a = nullptr;
|
||||
|
||||
// Find the address responsible for the most entries
|
||||
{
|
||||
Hashtable<MAC,Address>::Iterator i(_remoteBridgeRoutes);
|
||||
while (i.next(m,a)) {
|
||||
const unsigned long c = ++counts[*a];
|
||||
if (c > maxCount) {
|
||||
maxCount = c;
|
||||
maxAddr = *a;
|
||||
}
|
||||
for(FlatMap<MAC,Address>::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();++i) {
|
||||
const unsigned long c = ++counts[i->second];
|
||||
if (c > maxCount) {
|
||||
maxCount = c;
|
||||
maxAddr = i->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Kill this address from our table, since it's most likely spamming us
|
||||
{
|
||||
Hashtable<MAC,Address>::Iterator i(_remoteBridgeRoutes);
|
||||
while (i.next(m,a)) {
|
||||
if (*a == maxAddr)
|
||||
_remoteBridgeRoutes.erase(*m);
|
||||
}
|
||||
for(FlatMap<MAC,Address>::iterator i(_remoteBridgeRoutes.begin());i!=_remoteBridgeRoutes.end();) {
|
||||
if (i->second == maxAddr)
|
||||
_remoteBridgeRoutes.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1198,24 +1185,24 @@ Membership::AddCredentialResult Network::addCredential(void *tPtr,const Identity
|
|||
const Membership::AddCredentialResult result = m.addCredential(RR,tPtr,sourcePeerIdentity,_config,rev);
|
||||
|
||||
if ((result == Membership::ADD_ACCEPTED_NEW)&&(rev.fastPropagate())) {
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
if ((*a != sourcePeerIdentity.address())&&(*a != rev.signer())) {
|
||||
// TODO
|
||||
/*
|
||||
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
outp.append((uint8_t)0x00); // no COM
|
||||
outp.append((uint16_t)0); // no capabilities
|
||||
outp.append((uint16_t)0); // no tags
|
||||
outp.append((uint16_t)1); // one revocation!
|
||||
rev.serialize(outp);
|
||||
outp.append((uint16_t)0); // no certificates of ownership
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
*/
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
if ((*a != sourcePeerIdentity.address())&&(*a != rev.signer())) {
|
||||
Packet outp(*a,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
outp.append((uint8_t)0x00); // no COM
|
||||
outp.append((uint16_t)0); // no capabilities
|
||||
outp.append((uint16_t)0); // no tags
|
||||
outp.append((uint16_t)1); // one revocation!
|
||||
rev.serialize(outp);
|
||||
outp.append((uint16_t)0); // no certificates of ownership
|
||||
RR->sw->send(tPtr,outp,true);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1493,21 +1480,21 @@ void Network::_announceMulticastGroups(void *tPtr,bool force)
|
|||
// Assumes _myMulticastGroups_l and _memberships_l are locked
|
||||
const std::vector<MulticastGroup> groups(_allMulticastGroups());
|
||||
_announceMulticastGroupsTo(tPtr,controller(),groups);
|
||||
{
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
// TODO
|
||||
/*
|
||||
bool announce = m->multicastLikeGate(now); // force this to be called even if 'force' is true since it updates last push time
|
||||
if ((!announce)&&(force))
|
||||
announce = true;
|
||||
if ((announce)&&(m->isAllowedOnNetwork(_config)))
|
||||
_announceMulticastGroupsTo(tPtr,*a,groups);
|
||||
*/
|
||||
|
||||
// TODO
|
||||
/*
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
while (i.next(a,m)) {
|
||||
bool announce = m->multicastLikeGate(now); // force this to be called even if 'force' is true since it updates last push time
|
||||
if ((!announce)&&(force))
|
||||
announce = true;
|
||||
if ((announce)&&(m->isAllowedOnNetwork(_config)))
|
||||
_announceMulticastGroupsTo(tPtr,*a,groups);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void Network::_announceMulticastGroupsTo(void *tPtr,const Address &peer,const std::vector<MulticastGroup> &allMulticastGroups)
|
||||
|
@ -1542,7 +1529,8 @@ std::vector<MulticastGroup> Network::_allMulticastGroups() const
|
|||
std::vector<MulticastGroup> mgs;
|
||||
mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1);
|
||||
mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end());
|
||||
_multicastGroupsBehindMe.appendKeys(mgs);
|
||||
for(FlatMap< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i)
|
||||
mgs.push_back(i->first);
|
||||
if ((_config)&&(_config.enableBroadcast()))
|
||||
mgs.push_back(Network::BROADCAST);
|
||||
std::sort(mgs.begin(),mgs.end());
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#define ZT_NETWORK_HPP
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
|
@ -26,6 +25,7 @@
|
|||
#include "Membership.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "CertificateOfMembership.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
if (std::binary_search(_myMulticastGroups.begin(),_myMulticastGroups.end(),mg))
|
||||
return true;
|
||||
else if (includeBridgedGroups)
|
||||
return _multicastGroupsBehindMe.contains(mg);
|
||||
return (_multicastGroupsBehindMe.find(mg) != _multicastGroupsBehindMe.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -326,11 +326,8 @@ public:
|
|||
ZT_INLINE void eachMember(F f)
|
||||
{
|
||||
Mutex::Lock ml(_memberships_l);
|
||||
Hashtable<Address,Membership>::Iterator i(_memberships);
|
||||
Address *a = nullptr;
|
||||
Membership *m = nullptr;
|
||||
while (i.next(a,m)) {
|
||||
if (!f(*a,*m))
|
||||
for(FlatMap<Address,Membership>::iterator i(_memberships.begin());i!=_memberships.end();++i) {
|
||||
if (!f(i->first,i->second))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -356,8 +353,8 @@ private:
|
|||
bool _portInitialized;
|
||||
|
||||
std::vector< MulticastGroup > _myMulticastGroups; // multicast groups that we belong to (according to tap)
|
||||
Hashtable< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
Hashtable< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
FlatMap< MulticastGroup,uint64_t > _multicastGroupsBehindMe; // multicast groups that seem to be behind us and when we last saw them (if we are a bridge)
|
||||
FlatMap< MAC,Address > _remoteBridgeRoutes; // remote addresses where given MACs are reachable (for tracking devices behind remote bridges)
|
||||
|
||||
NetworkConfig _config;
|
||||
std::atomic<int64_t> _lastConfigUpdate;
|
||||
|
@ -380,7 +377,7 @@ private:
|
|||
NETCONF_FAILURE_INIT_FAILED
|
||||
} _netconfFailure;
|
||||
|
||||
Hashtable<Address,Membership> _memberships;
|
||||
FlatMap<Address,Membership> _memberships;
|
||||
|
||||
Mutex _myMulticastGroups_l;
|
||||
Mutex _remoteBridgeRoutes_l;
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "Capability.hpp"
|
||||
#include "Tag.hpp"
|
||||
#include "Dictionary.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Identity.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Trace.hpp"
|
||||
|
|
134
node/Node.cpp
134
node/Node.cpp
|
@ -82,7 +82,6 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
_cb(*callbacks),
|
||||
_uPtr(uPtr),
|
||||
_networks(),
|
||||
_networksMask(15),
|
||||
_now(now),
|
||||
_lastPing(0),
|
||||
_lastHousekeepingRun(0),
|
||||
|
@ -91,8 +90,6 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
_natMustDie(true),
|
||||
_online(false)
|
||||
{
|
||||
_networks.resize(16); // _networksMask + 1, must be power of two
|
||||
|
||||
uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
|
||||
std::vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
|
||||
bool haveIdentity = false;
|
||||
|
@ -133,15 +130,9 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
|
|||
|
||||
Node::~Node()
|
||||
{
|
||||
// Let go of all networks to leave them. Do it this way in case Network wants to
|
||||
// do anything in its destructor that locks the _networks lock to avoid a deadlock.
|
||||
std::vector< SharedPtr<Network> > networks;
|
||||
{
|
||||
RWMutex::Lock _l(_networks_m);
|
||||
networks.swap(_networks);
|
||||
}
|
||||
networks.clear();
|
||||
|
||||
_networks_m.lock();
|
||||
_networks_m.unlock();
|
||||
_networks.clear();
|
||||
_networks_m.lock();
|
||||
_networks_m.unlock();
|
||||
|
||||
|
@ -277,10 +268,8 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
|
|||
_lastHousekeepingRun = now;
|
||||
{
|
||||
RWMutex::RLock l(_networks_m);
|
||||
for(std::vector< SharedPtr<Network> >::const_iterator i(_networks.begin());i!=_networks.end();++i) {
|
||||
if ((*i))
|
||||
(*i)->doPeriodicTasks(tPtr,now);
|
||||
}
|
||||
for(FlatMap< uint64_t,SharedPtr<Network> >::const_iterator i(_networks.begin());i!=_networks.end();++i)
|
||||
i->second->doPeriodicTasks(tPtr,now);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,13 +281,10 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
|
|||
// or trust nodes without doing an extra cert check.
|
||||
{
|
||||
_localControllerAuthorizations_m.lock();
|
||||
Hashtable< _LocalControllerAuth,int64_t >::Iterator i(_localControllerAuthorizations);
|
||||
_LocalControllerAuth *k = (_LocalControllerAuth *)0;
|
||||
int64_t *v = (int64_t *)0;
|
||||
while (i.next(k,v)) {
|
||||
if ((*v - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3)) {
|
||||
_localControllerAuthorizations.erase(*k);
|
||||
}
|
||||
for(FlatMap<_LocalControllerAuth,int64_t>::iterator i(_localControllerAuthorizations.begin());i!=_localControllerAuthorizations.end();) {
|
||||
if ((i->second - now) > (ZT_NETWORK_AUTOCONF_DELAY * 3))
|
||||
_localControllerAuthorizations.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
_localControllerAuthorizations_m.unlock();
|
||||
}
|
||||
|
@ -349,72 +335,40 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
|
|||
|
||||
ZT_ResultCode Node::join(uint64_t nwid,const ZT_Fingerprint *controllerFingerprint,void *uptr,void *tptr)
|
||||
{
|
||||
RWMutex::Lock l(_networks_m);
|
||||
|
||||
const uint64_t nwidHashed = nwid + (nwid >> 32U);
|
||||
SharedPtr<Network> *nw = &(_networks[(unsigned long)(nwidHashed & _networksMask)]);
|
||||
|
||||
// Enlarge flat hash table of networks until all networks fit without collisions.
|
||||
if (*nw) {
|
||||
unsigned long newNetworksSize = (unsigned long)_networks.size();
|
||||
std::vector< SharedPtr<Network> > newNetworks;
|
||||
uint64_t newNetworksMask,id;
|
||||
std::vector< SharedPtr<Network> >::const_iterator i;
|
||||
|
||||
try_larger_network_hashtable:
|
||||
newNetworksSize <<= 1U; // must remain a power of two
|
||||
newNetworks.clear();
|
||||
newNetworks.resize(newNetworksSize);
|
||||
newNetworksMask = (uint64_t)(newNetworksSize - 1);
|
||||
|
||||
for(i=_networks.begin();i!=_networks.end();++i) {
|
||||
id = (*i)->id();
|
||||
nw = &(newNetworks[(unsigned long)((id + (id >> 32U)) & newNetworksMask)]);
|
||||
if (*nw)
|
||||
goto try_larger_network_hashtable;
|
||||
*nw = *i;
|
||||
}
|
||||
if (newNetworks[(unsigned long)(nwidHashed & newNetworksMask)])
|
||||
goto try_larger_network_hashtable;
|
||||
|
||||
_networks.swap(newNetworks);
|
||||
_networksMask = newNetworksMask;
|
||||
nw = &(_networks[(unsigned long)(nwidHashed & newNetworksMask)]);
|
||||
}
|
||||
|
||||
Fingerprint fp;
|
||||
if (controllerFingerprint)
|
||||
Utils::copy<sizeof(ZT_Fingerprint)>(fp.apiFingerprint(),controllerFingerprint);
|
||||
nw->set(new Network(RR,tptr,nwid,fp,uptr,(const NetworkConfig *)0));
|
||||
|
||||
RWMutex::Lock l(_networks_m);
|
||||
SharedPtr<Network> &nw = _networks[nwid];
|
||||
if (nw)
|
||||
return ZT_RESULT_OK;
|
||||
nw.set(new Network(RR,tptr,nwid,fp,uptr,nullptr));
|
||||
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
|
||||
{
|
||||
const uint64_t nwidHashed = nwid + (nwid >> 32U);
|
||||
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
void **nUserPtr = (void **)0;
|
||||
{
|
||||
RWMutex::RLock l(_networks_m);
|
||||
SharedPtr<Network> &nw = _networks[(unsigned long)(nwidHashed & _networksMask)];
|
||||
if (!nw)
|
||||
return ZT_RESULT_OK;
|
||||
if (uptr)
|
||||
*uptr = nw->userPtr();
|
||||
nw->externalConfig(&ctmp);
|
||||
nw->destroy();
|
||||
nUserPtr = nw->userPtr();
|
||||
}
|
||||
|
||||
if (nUserPtr)
|
||||
RR->node->configureVirtualNetworkPort(tptr,nwid,nUserPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
|
||||
|
||||
{
|
||||
RWMutex::Lock _l(_networks_m);
|
||||
_networks[(unsigned long)(nwidHashed & _networksMask)].zero();
|
||||
_networks_m.lock();
|
||||
FlatMap< uint64_t,SharedPtr<Network> >::iterator nwi(_networks.find(nwid));
|
||||
if (nwi == _networks.end()) {
|
||||
_networks_m.unlock();
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
SharedPtr<Network> nw(nwi->second);
|
||||
_networks.erase(nwi);
|
||||
_networks_m.unlock();
|
||||
|
||||
if (uptr)
|
||||
*uptr = *nw->userPtr();
|
||||
nw->externalConfig(&ctmp);
|
||||
nw->destroy();
|
||||
nw.zero();
|
||||
|
||||
RR->node->configureVirtualNetworkPort(tptr,nwid,uptr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
|
||||
|
||||
uint64_t tmp[2];
|
||||
tmp[0] = nwid; tmp[1] = 0;
|
||||
|
@ -539,30 +493,22 @@ ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
|
|||
nw->externalConfig(nc);
|
||||
return nc;
|
||||
}
|
||||
return (ZT_VirtualNetworkConfig *)0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ZT_VirtualNetworkList *Node::networks() const
|
||||
{
|
||||
RWMutex::RLock l(_networks_m);
|
||||
|
||||
unsigned long networkCount = 0;
|
||||
for(std::vector< SharedPtr<Network> >::const_iterator i(_networks.begin());i!=_networks.end();++i) {
|
||||
if ((*i))
|
||||
++networkCount;
|
||||
}
|
||||
|
||||
char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * networkCount));
|
||||
char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * _networks.size()));
|
||||
if (!buf)
|
||||
return (ZT_VirtualNetworkList *)0;
|
||||
ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf;
|
||||
nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
|
||||
|
||||
nl->networkCount = 0;
|
||||
for(std::vector< SharedPtr<Network> >::const_iterator i(_networks.begin());i!=_networks.end();++i) {
|
||||
if ((*i))
|
||||
(*i)->externalConfig(&(nl->networks[nl->networkCount++]));
|
||||
}
|
||||
for(FlatMap< uint64_t,SharedPtr<Network> >::const_iterator i(_networks.begin());i!=_networks.end();++i)
|
||||
i->second->externalConfig(&(nl->networks[nl->networkCount++]));
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
@ -650,12 +596,10 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Identity &id,const i
|
|||
{
|
||||
{
|
||||
RWMutex::RLock l(_networks_m);
|
||||
for (std::vector<SharedPtr<Network> >::iterator i(_networks.begin()); i != _networks.end(); ++i) {
|
||||
if ((*i)) {
|
||||
for (unsigned int k = 0,j = (*i)->config().staticIpCount; k < j; ++k) {
|
||||
if ((*i)->config().staticIps[k].containsAddress(remoteAddress))
|
||||
return false;
|
||||
}
|
||||
for (FlatMap< uint64_t,SharedPtr<Network> >::iterator i(_networks.begin()); i != _networks.end(); ++i) {
|
||||
for (unsigned int k = 0,j = i->second->config().staticIpCount; k < j; ++k) {
|
||||
if (i->second->config().staticIps[k].containsAddress(remoteAddress))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
#include "Path.hpp"
|
||||
#include "Salsa20.hpp"
|
||||
#include "NetworkController.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Buf.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
@ -172,7 +172,10 @@ public:
|
|||
ZT_INLINE SharedPtr<Network> network(uint64_t nwid) const noexcept
|
||||
{
|
||||
RWMutex::RLock l(_networks_m);
|
||||
return _networks[(unsigned long)((nwid + (nwid >> 32U)) & _networksMask)];
|
||||
const SharedPtr<Network> *const n = _networks.get(nwid);
|
||||
if (n)
|
||||
return *n;
|
||||
return SharedPtr<Network>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -342,7 +345,7 @@ private:
|
|||
// in each peer if that peer object is still held in memory. Calling alarm() unnecessarily on a peer
|
||||
// is harmless. This just exists as an optimization to prevent having to iterate through all peers
|
||||
// on every processBackgroundTasks call. A simple map<> is used here because there are usually only
|
||||
// a few of these, if any, and it's slightly faster and lower memory in that case than a Hashtable.
|
||||
// a few of these, if any.
|
||||
std::map<Address,int64_t> _peerAlarms;
|
||||
RWMutex _peerAlarms_l;
|
||||
|
||||
|
@ -355,17 +358,16 @@ private:
|
|||
{
|
||||
uint64_t nwid,address;
|
||||
ZT_INLINE _LocalControllerAuth(const uint64_t nwid_,const Address &address_) noexcept: nwid(nwid_),address(address_.toInt()) {}
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)(nwid ^ address); }
|
||||
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)(nwid + address); }
|
||||
ZT_INLINE bool operator==(const _LocalControllerAuth &a) const noexcept { return ((a.nwid == nwid) && (a.address == address)); }
|
||||
ZT_INLINE bool operator!=(const _LocalControllerAuth &a) const noexcept { return ((a.nwid != nwid) || (a.address != address)); }
|
||||
};
|
||||
Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations;
|
||||
FlatMap<_LocalControllerAuth,int64_t> _localControllerAuthorizations;
|
||||
Mutex _localControllerAuthorizations_m;
|
||||
|
||||
// Networks are stored in a flat hash table that is resized on any network ID collision. This makes
|
||||
// network lookup by network ID a few bitwise ops and an array index.
|
||||
std::vector< SharedPtr<Network> > _networks;
|
||||
uint64_t _networksMask;
|
||||
FlatMap< uint64_t,SharedPtr<Network> > _networks;
|
||||
RWMutex _networks_m;
|
||||
|
||||
// These are local interface addresses that have been configured via the API
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "Identity.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "Endpoint.hpp"
|
||||
#include "Locator.hpp"
|
||||
|
|
|
@ -77,7 +77,7 @@ void armor(Buf &pkt,int packetSize,const uint8_t key[ZT_PEER_SECRET_KEY_LENGTH],
|
|||
ph.mac = mac[0];
|
||||
} break;
|
||||
|
||||
case ZT_PROTO_CIPHER_SUITE__AES_GCM_NRH: {
|
||||
case ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV: {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,7 @@ private:
|
|||
};
|
||||
|
||||
SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
|
||||
RR(renv),
|
||||
_phy(256)
|
||||
RR(renv)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -70,14 +69,10 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
|||
// Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing'
|
||||
// due to multiple reports of endpoint change.
|
||||
// Don't use 'entry' after this since hash table gets modified.
|
||||
{
|
||||
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
|
||||
PhySurfaceKey *k = nullptr;
|
||||
PhySurfaceEntry *e = nullptr;
|
||||
while (i.next(k,e)) {
|
||||
if ((k->scope == scope)&&(k->reporterPhysicalAddress != reporterPhysicalAddress))
|
||||
_phy.erase(*k);
|
||||
}
|
||||
for(FlatMap<PhySurfaceKey,PhySurfaceEntry>::iterator i(_phy.begin());i!=_phy.end();) {
|
||||
if ((i->first.scope == scope)&&(i->first.reporterPhysicalAddress != reporterPhysicalAddress))
|
||||
_phy.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
|
||||
// Reset all paths within this scope and address family
|
||||
|
@ -96,36 +91,28 @@ void SelfAwareness::iam(void *tPtr,const Identity &reporter,const int64_t receiv
|
|||
void SelfAwareness::clean(int64_t now)
|
||||
{
|
||||
Mutex::Lock l(_phy_l);
|
||||
Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);
|
||||
PhySurfaceKey *k = nullptr;
|
||||
PhySurfaceEntry *e = nullptr;
|
||||
while (i.next(k,e)) {
|
||||
if ((now - e->ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
_phy.erase(*k);
|
||||
for(FlatMap<PhySurfaceKey,PhySurfaceEntry>::iterator i(_phy.begin());i!=_phy.end();) {
|
||||
if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
_phy.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
|
||||
std::multimap<unsigned long,InetAddress> SelfAwareness::externalAddresses(const int64_t now) const
|
||||
{
|
||||
std::multimap<unsigned long,InetAddress> r;
|
||||
Hashtable<InetAddress,unsigned long> counts(16);
|
||||
FlatMap<InetAddress,unsigned long,256> counts;
|
||||
|
||||
{
|
||||
Mutex::Lock l(_phy_l);
|
||||
Hashtable<PhySurfaceKey,PhySurfaceEntry>::Iterator i(const_cast<SelfAwareness *>(this)->_phy);
|
||||
PhySurfaceKey *k = nullptr;
|
||||
PhySurfaceEntry *e = nullptr;
|
||||
while (i.next(k,e)) {
|
||||
if ((now - e->ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
++counts[e->mySurface];
|
||||
for(FlatMap<PhySurfaceKey,PhySurfaceEntry>::const_iterator i(_phy.begin());i!=_phy.end();++i) {
|
||||
if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT)
|
||||
++counts[i->second.mySurface];
|
||||
}
|
||||
}
|
||||
|
||||
Hashtable<InetAddress,unsigned long>::Iterator i(counts);
|
||||
InetAddress *k = nullptr;
|
||||
unsigned long *c = nullptr;
|
||||
while (i.next(k,c))
|
||||
r.insert(std::pair<unsigned long,InetAddress>(*c,*k));
|
||||
for(FlatMap<InetAddress,unsigned long,256>::iterator i(counts.begin());i!=counts.end();++i)
|
||||
r.insert(std::pair<unsigned long,InetAddress>(i->second,i->first));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "Constants.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Mutex.hpp"
|
||||
|
||||
|
@ -92,7 +92,7 @@ private:
|
|||
};
|
||||
|
||||
const RuntimeEnvironment *RR;
|
||||
Hashtable< PhySurfaceKey,PhySurfaceEntry > _phy;
|
||||
FlatMap< PhySurfaceKey,PhySurfaceEntry > _phy;
|
||||
Mutex _phy_l;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,12 +34,11 @@
|
|||
#include "Tag.hpp"
|
||||
#include "Capability.hpp"
|
||||
#include "NetworkConfig.hpp"
|
||||
#include "LZ4.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "FCV.hpp"
|
||||
#include "SHA512.hpp"
|
||||
#include "Defragmenter.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
@ -467,54 +466,34 @@ extern "C" const char *ZTT_general()
|
|||
}
|
||||
|
||||
{
|
||||
ZT_T_PRINTF("[general] Testing Hashtable... ");
|
||||
|
||||
long cnt = 0;
|
||||
Hashtable< unsigned int,LifeCycleTracker > test,test2;
|
||||
for(unsigned int i=0;i<512;++i)
|
||||
test[i] = LifeCycleTracker(cnt);
|
||||
if (cnt != 512) {
|
||||
ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (1))" ZT_EOL_S,cnt);
|
||||
return "Hashtable test failed (1)";
|
||||
}
|
||||
test2 = test;
|
||||
if (cnt != 1024) {
|
||||
ZT_T_PRINTF("FAILED (expected 1024 objects, got %lu (2))" ZT_EOL_S,cnt);
|
||||
return "Hashtable test failed (2)";
|
||||
}
|
||||
test.clear();
|
||||
if (cnt != 512) {
|
||||
ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (3))" ZT_EOL_S,cnt);
|
||||
return "Hashtable test failed (3)";
|
||||
}
|
||||
for(unsigned int i=0;i<512;++i)
|
||||
test[i] = LifeCycleTracker(cnt);
|
||||
if (cnt != 1024) {
|
||||
ZT_T_PRINTF("FAILED (expected 1024 objects, got %lu (4))" ZT_EOL_S,cnt);
|
||||
return "Hashtable test failed (4)";
|
||||
}
|
||||
test.clear();
|
||||
test2.clear();
|
||||
if (cnt != 0) {
|
||||
ZT_T_PRINTF("FAILED (expected 0 objects, got %lu (5))" ZT_EOL_S,cnt);
|
||||
return "Hashtable test failed (5)";
|
||||
}
|
||||
|
||||
Hashtable< unsigned int,unsigned int > test3;
|
||||
for(unsigned int i=0;i<1111;++i)
|
||||
test3[i] = i;
|
||||
if (test3.size() != 1111) {
|
||||
ZT_T_PRINTF("FAILED (size() incorrect)" ZT_EOL_S);
|
||||
return "Hashtable test failed (size() incorrect)";
|
||||
}
|
||||
for(unsigned int i=0;i<1111;++i) {
|
||||
if (test3[i] != i) {
|
||||
ZT_T_PRINTF("FAILED (lookup test)" ZT_EOL_S);
|
||||
return "Hashtable test failed (lookup)";
|
||||
ZT_T_PRINTF("[general] Testing FlatMap... ");
|
||||
FlatMap<uint64_t,uint64_t> tm;
|
||||
for(uint64_t i=0;i<10000;++i)
|
||||
tm.set(i,i);
|
||||
for(uint64_t i=0;i<10000;++i) {
|
||||
uint64_t *v = tm.get(i);
|
||||
if ((!v)||(*v != i)) {
|
||||
ZT_T_PRINTF("FAILED (get() failed)" ZT_EOL_S);
|
||||
return "FlatMap::get() failed";
|
||||
}
|
||||
}
|
||||
|
||||
ZT_T_PRINTF("OK" ZT_EOL_S);
|
||||
for(FlatMap<uint64_t,uint64_t>::iterator i(tm.begin());i!=tm.end();) {
|
||||
if ((i->first & 1U) == 0)
|
||||
tm.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
if (tm.size() != 5000) {
|
||||
ZT_T_PRINTF("FAILED (erase() failed (1))" ZT_EOL_S);
|
||||
return "FlatMap::erase() failed (1)";
|
||||
}
|
||||
for(uint64_t i=0;i<10000;++i) {
|
||||
uint64_t *v = tm.get(i);
|
||||
if (((i & 1U) == 0)&&(v)) {
|
||||
ZT_T_PRINTF("FAILED (erase() failed (2))" ZT_EOL_S);
|
||||
return "FlatMap::erase() failed (2)";
|
||||
}
|
||||
}
|
||||
ZT_T_PRINTF("OK (hash size: %lu)" ZT_EOL_S,tm.hashSize());
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -36,11 +36,7 @@ struct _RootSortComparisonOperator
|
|||
|
||||
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
|
||||
RR(renv),
|
||||
_numConfiguredPhysicalPaths(0),
|
||||
_peers(256),
|
||||
_peersByIncomingProbe(256),
|
||||
_peersByIdentityHash(256),
|
||||
_paths(1024)
|
||||
_numConfiguredPhysicalPaths(0)
|
||||
{
|
||||
uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
|
||||
std::vector<uint8_t> data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_ROOTS,idtmp));
|
||||
|
@ -103,11 +99,8 @@ void Topology::getAllPeers(std::vector< SharedPtr<Peer> > &allPeers) const
|
|||
RWMutex::RLock l(_peers_l);
|
||||
allPeers.clear();
|
||||
allPeers.reserve(_peers.size());
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(*(const_cast<Hashtable< Address,SharedPtr<Peer> > *>(&_peers)));
|
||||
Address *a = nullptr;
|
||||
SharedPtr<Peer> *p = nullptr;
|
||||
while (i.next(a,p))
|
||||
allPeers.push_back(*p);
|
||||
for(FlatMap< Address,SharedPtr<Peer> >::const_iterator i(_peers.begin());i!=_peers.end();++i)
|
||||
allPeers.push_back(i->second);
|
||||
}
|
||||
|
||||
void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig)
|
||||
|
@ -205,26 +198,21 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
|
|||
{
|
||||
{
|
||||
RWMutex::Lock l1(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = nullptr;
|
||||
SharedPtr<Peer> *p = nullptr;
|
||||
while (i.next(a,p)) {
|
||||
if ( (!(*p)->alive(now)) && (_roots.count((*p)->identity()) == 0) ) {
|
||||
(*p)->save(tPtr);
|
||||
_peersByIncomingProbe.erase((*p)->incomingProbe());
|
||||
_peersByIdentityHash.erase((*p)->identity().fingerprint());
|
||||
_peers.erase(*a);
|
||||
}
|
||||
for(FlatMap< Address,SharedPtr<Peer> >::iterator i(_peers.begin());i!=_peers.end();) {
|
||||
if ( (!i->second->alive(now)) && (_roots.count(i->second->identity()) == 0) ) {
|
||||
i->second->save(tPtr);
|
||||
_peersByIncomingProbe.erase(i->second->incomingProbe());
|
||||
_peersByIdentityHash.erase(i->second->identity().fingerprint());
|
||||
_peers.erase(i++);
|
||||
} else ++i;
|
||||
}
|
||||
}
|
||||
{
|
||||
RWMutex::Lock l1(_paths_l);
|
||||
Hashtable< uint64_t,SharedPtr<Path> >::Iterator i(_paths);
|
||||
uint64_t *k = nullptr;
|
||||
SharedPtr<Path> *p = nullptr;
|
||||
while (i.next(k,p)) {
|
||||
if ((p->references() <= 1)&&(!(*p)->alive(now)))
|
||||
_paths.erase(*k);
|
||||
for(FlatMap< uint64_t,SharedPtr<Path> >::iterator i(_paths.begin());i!=_paths.end();) {
|
||||
if ((i->second.references() <= 1)&&(!i->second->alive(now)))
|
||||
_paths.erase(i++);
|
||||
else ++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,11 +220,8 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now)
|
|||
void Topology::saveAll(void *tPtr)
|
||||
{
|
||||
RWMutex::RLock l(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(_peers);
|
||||
Address *a = nullptr;
|
||||
SharedPtr<Peer> *p = nullptr;
|
||||
while (i.next(a,p))
|
||||
(*p)->save(tPtr);
|
||||
for(FlatMap< Address,SharedPtr<Peer> >::iterator i(_peers.begin());i!=_peers.end();++i)
|
||||
i->second->save(tPtr);
|
||||
}
|
||||
|
||||
void Topology::_loadCached(void *tPtr,const Address &zta,SharedPtr<Peer> &peer)
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
#include "Path.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "InetAddress.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "SharedPtr.hpp"
|
||||
#include "ScopedPtr.hpp"
|
||||
#include "Fingerprint.hpp"
|
||||
#include "FlatMap.hpp"
|
||||
|
||||
namespace ZeroTier {
|
||||
|
||||
|
@ -179,11 +179,8 @@ public:
|
|||
ZT_INLINE void eachPeer(F f) const
|
||||
{
|
||||
RWMutex::RLock l(_peers_l);
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
|
||||
Address *a = nullptr;
|
||||
SharedPtr<Peer> *p = nullptr;
|
||||
while (i.next(a,p))
|
||||
f(*((const SharedPtr<Peer> *)p));
|
||||
for(FlatMap< Address,SharedPtr<Peer> >::const_iterator i(_peers.begin());i!=_peers.end();++i)
|
||||
f(i->second);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -207,11 +204,8 @@ public:
|
|||
std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end());
|
||||
|
||||
try {
|
||||
Hashtable< Address,SharedPtr<Peer> >::Iterator i(const_cast<Topology *>(this)->_peers);
|
||||
Address *a = nullptr;
|
||||
SharedPtr<Peer> *p = nullptr;
|
||||
while (i.next(a,p))
|
||||
f(*((const SharedPtr<Peer> *)p),std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)p->ptr()));
|
||||
for(FlatMap< Address,SharedPtr<Peer> >::const_iterator i(_peers.begin());i!=_peers.end();++i)
|
||||
f(i->second,std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)i->second.ptr()));
|
||||
} catch ( ... ) {} // should not throw
|
||||
}
|
||||
|
||||
|
@ -225,11 +219,8 @@ public:
|
|||
ZT_INLINE void eachPath(F f) const
|
||||
{
|
||||
RWMutex::RLock l(_paths_l);
|
||||
Hashtable< uint64_t,SharedPtr<Path> >::Iterator i(const_cast<Topology *>(this)->_paths);
|
||||
uint64_t *k = nullptr;
|
||||
SharedPtr<Path> *p = nullptr;
|
||||
while (i.next(k,p))
|
||||
f(*((const SharedPtr<Path> *)p));
|
||||
for(FlatMap< uint64_t,SharedPtr<Path> >::const_iterator i(_paths.begin());i!=_paths.end();++i)
|
||||
f(i->second);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,10 +354,10 @@ private:
|
|||
std::pair< InetAddress,ZT_PhysicalPathConfiguration > _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS];
|
||||
unsigned int _numConfiguredPhysicalPaths;
|
||||
|
||||
Hashtable< Address,SharedPtr<Peer> > _peers;
|
||||
Hashtable< uint64_t,SharedPtr<Peer> > _peersByIncomingProbe;
|
||||
Hashtable< Fingerprint,SharedPtr<Peer> > _peersByIdentityHash;
|
||||
Hashtable< uint64_t,SharedPtr<Path> > _paths;
|
||||
FlatMap< Address,SharedPtr<Peer> > _peers;
|
||||
FlatMap< uint64_t,SharedPtr<Peer> > _peersByIncomingProbe;
|
||||
FlatMap< Fingerprint,SharedPtr<Peer> > _peersByIdentityHash;
|
||||
FlatMap< uint64_t,SharedPtr<Path> > _paths;
|
||||
std::set< Identity > _roots; // locked by _peers_l
|
||||
std::vector< SharedPtr<Peer> > _rootPeers; // locked by _peers_l
|
||||
};
|
||||
|
|
|
@ -263,6 +263,20 @@ static ZT_INLINE uint64_t hash64(uint64_t x) noexcept
|
|||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mix bits in a 32-bit integer
|
||||
*
|
||||
* @param x Integer to mix
|
||||
* @return Hashed value
|
||||
*/
|
||||
static ZT_INLINE uint32_t hash32(uint32_t x) noexcept
|
||||
{
|
||||
x = ((x >> 16U) ^ x) * 0x45d9f3b;
|
||||
x = ((x >> 16U) ^ x) * 0x45d9f3b;
|
||||
x = (x >> 16U) ^ x;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a buffer's contents are all zero
|
||||
*/
|
||||
|
|
13
node/VL1.cpp
13
node/VL1.cpp
|
@ -440,14 +440,11 @@ void VL1::_sendPendingWhois(void *const tPtr,const int64_t now)
|
|||
std::vector<Address> toSend;
|
||||
{
|
||||
Mutex::Lock wl(_whoisQueue_l);
|
||||
Hashtable<Address,_WhoisQueueItem>::Iterator wi(_whoisQueue);
|
||||
Address *a = nullptr;
|
||||
_WhoisQueueItem *wq = nullptr;
|
||||
while (wi.next(a,wq)) {
|
||||
if ((now - wq->lastRetry) >= ZT_WHOIS_RETRY_DELAY) {
|
||||
wq->lastRetry = now;
|
||||
++wq->retries;
|
||||
toSend.push_back(*a);
|
||||
for(std::map<Address,_WhoisQueueItem>::iterator wi(_whoisQueue.begin());wi!=_whoisQueue.end();++wi) {
|
||||
if ((now - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) {
|
||||
wi->second.lastRetry = now;
|
||||
++wi->second.retries;
|
||||
toSend.push_back(wi->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace ZeroTier {
|
||||
|
@ -89,7 +89,7 @@ private:
|
|||
|
||||
Defragmenter<ZT_MAX_PACKET_FRAGMENTS> _inputPacketAssembler;
|
||||
|
||||
Hashtable<Address,_WhoisQueueItem> _whoisQueue;
|
||||
std::map<Address,_WhoisQueueItem> _whoisQueue;
|
||||
Mutex _whoisQueue_l;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "Buf.hpp"
|
||||
#include "Address.hpp"
|
||||
#include "Protocol.hpp"
|
||||
#include "Hashtable.hpp"
|
||||
#include "Mutex.hpp"
|
||||
#include "FCV.hpp"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue