mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-23 23:02:23 +00:00
More work in progress
This commit is contained in:
parent
573d3eea87
commit
8f5f7f1baa
@ -239,7 +239,7 @@ public:
|
|||||||
class CapabilityIterator
|
class CapabilityIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
|
inline CapabilityIterator(Membership &m,const NetworkConfig &nconf) :
|
||||||
_hti(m._remoteCaps),
|
_hti(m._remoteCaps),
|
||||||
_k((uint32_t *)0),
|
_k((uint32_t *)0),
|
||||||
_c((Capability *)0),
|
_c((Capability *)0),
|
||||||
|
@ -161,8 +161,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct Key
|
struct Key
|
||||||
{
|
{
|
||||||
Key() : nwid(0),mg() {}
|
inline Key() : nwid(0),mg() {}
|
||||||
Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
|
inline Key(uint64_t n,const MulticastGroup &g) : nwid(n),mg(g) {}
|
||||||
|
|
||||||
uint64_t nwid;
|
uint64_t nwid;
|
||||||
MulticastGroup mg;
|
MulticastGroup mg;
|
||||||
@ -174,8 +174,8 @@ private:
|
|||||||
|
|
||||||
struct MulticastGroupMember
|
struct MulticastGroupMember
|
||||||
{
|
{
|
||||||
MulticastGroupMember() {}
|
inline MulticastGroupMember() {}
|
||||||
MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {}
|
inline MulticastGroupMember(const Address &a,uint64_t ts) : address(a),timestamp(ts) {}
|
||||||
|
|
||||||
inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); }
|
inline bool operator<(const MulticastGroupMember &a) const { return (address < a.address); }
|
||||||
inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); }
|
inline bool operator==(const MulticastGroupMember &a) const { return (address == a.address); }
|
||||||
@ -190,7 +190,7 @@ private:
|
|||||||
|
|
||||||
struct MulticastGroupStatus
|
struct MulticastGroupStatus
|
||||||
{
|
{
|
||||||
MulticastGroupStatus() : lastExplicitGather(0) {}
|
inline MulticastGroupStatus() : lastExplicitGather(0) {}
|
||||||
|
|
||||||
uint64_t lastExplicitGather;
|
uint64_t lastExplicitGather;
|
||||||
std::list<OutboundMulticast> txQueue; // pending outbound multicasts
|
std::list<OutboundMulticast> txQueue; // pending outbound multicasts
|
||||||
|
@ -194,7 +194,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||||||
// those that need pinging.
|
// those that need pinging.
|
||||||
struct _PingPeersThatNeedPing
|
struct _PingPeersThatNeedPing
|
||||||
{
|
{
|
||||||
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &alwaysContact,int64_t now) :
|
inline _PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &alwaysContact,int64_t now) :
|
||||||
RR(renv),
|
RR(renv),
|
||||||
_tPtr(tPtr),
|
_tPtr(tPtr),
|
||||||
_alwaysContact(alwaysContact),
|
_alwaysContact(alwaysContact),
|
||||||
@ -284,7 +284,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64
|
|||||||
|
|
||||||
// (1) Get peers we should remain connected to and (2) get networks that need config.
|
// (1) Get peers we should remain connected to and (2) get networks that need config.
|
||||||
Hashtable< Address,std::vector<InetAddress> > alwaysContact;
|
Hashtable< Address,std::vector<InetAddress> > alwaysContact;
|
||||||
RR->topology->getUpstreamsToContact(alwaysContact);
|
RR->topology->getAlwaysContact(alwaysContact);
|
||||||
std::vector< std::pair< SharedPtr<Network>,bool > > networkConfigNeeded;
|
std::vector< std::pair< SharedPtr<Network>,bool > > networkConfigNeeded;
|
||||||
{
|
{
|
||||||
Mutex::Lock l(_networks_m);
|
Mutex::Lock l(_networks_m);
|
||||||
|
@ -58,7 +58,7 @@ class Revocation : public Credential
|
|||||||
public:
|
public:
|
||||||
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
|
static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; }
|
||||||
|
|
||||||
Revocation() :
|
inline Revocation() :
|
||||||
_id(0),
|
_id(0),
|
||||||
_credentialId(0),
|
_credentialId(0),
|
||||||
_networkId(0),
|
_networkId(0),
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
* @param tgt Target node whose credential(s) are being revoked
|
* @param tgt Target node whose credential(s) are being revoked
|
||||||
* @param ct Credential type being revoked
|
* @param ct Credential type being revoked
|
||||||
*/
|
*/
|
||||||
Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
inline Revocation(const uint32_t i,const uint64_t nwid,const uint32_t cid,const uint64_t thr,const uint64_t fl,const Address &tgt,const Credential::Type ct) :
|
||||||
_id(i),
|
_id(i),
|
||||||
_credentialId(cid),
|
_credentialId(cid),
|
||||||
_networkId(nwid),
|
_networkId(nwid),
|
||||||
|
34
node/Str.hpp
34
node/Str.hpp
@ -37,16 +37,22 @@
|
|||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A short non-allocating replacement for std::string
|
||||||
|
*/
|
||||||
class Str
|
class Str
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Str() { _l = 0; _s[0] = 0; }
|
typedef char * iterator;
|
||||||
Str(const Str &s)
|
typedef const char * const_iterator;
|
||||||
|
|
||||||
|
inline Str() { _l = 0; _s[0] = 0; }
|
||||||
|
inline Str(const Str &s)
|
||||||
{
|
{
|
||||||
_l = s._l;
|
_l = s._l;
|
||||||
memcpy(_s,s._s,_l+1);
|
memcpy(_s,s._s,_l+1);
|
||||||
}
|
}
|
||||||
Str(const char *s)
|
inline Str(const char *s)
|
||||||
{
|
{
|
||||||
_l = 0;
|
_l = 0;
|
||||||
_s[0] = 0;
|
_s[0] = 0;
|
||||||
@ -75,7 +81,11 @@ public:
|
|||||||
|
|
||||||
inline void clear() { _l = 0; _s[0] = 0; }
|
inline void clear() { _l = 0; _s[0] = 0; }
|
||||||
inline const char *c_str() const { return _s; }
|
inline const char *c_str() const { return _s; }
|
||||||
inline unsigned int length() const { return _l; }
|
inline unsigned int length() const { return (unsigned int)_l; }
|
||||||
|
inline iterator begin() { return (iterator)_s; }
|
||||||
|
inline iterator end() { return (iterator)(_s + (unsigned long)_l); }
|
||||||
|
inline const_iterator begin() const { return (const_iterator)_s; }
|
||||||
|
inline const_iterator end() const { return (const_iterator)(_s + (unsigned long)_l); }
|
||||||
|
|
||||||
inline Str &operator<<(const char *s)
|
inline Str &operator<<(const char *s)
|
||||||
{
|
{
|
||||||
@ -83,8 +93,8 @@ public:
|
|||||||
unsigned long l = _l;
|
unsigned long l = _l;
|
||||||
while (*s) {
|
while (*s) {
|
||||||
if (unlikely(l >= ZT_STR_CAPACITY)) {
|
if (unlikely(l >= ZT_STR_CAPACITY)) {
|
||||||
_s[l] = 0;
|
_s[ZT_STR_CAPACITY] = 0;
|
||||||
_l = (uint8_t)l;
|
_l = ZT_STR_CAPACITY;
|
||||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||||
}
|
}
|
||||||
_s[l++] = *s;
|
_s[l++] = *s;
|
||||||
@ -97,14 +107,12 @@ public:
|
|||||||
inline Str &operator<<(const Str &s) { return ((*this) << s._s); }
|
inline Str &operator<<(const Str &s) { return ((*this) << s._s); }
|
||||||
inline Str &operator<<(const char c)
|
inline Str &operator<<(const char c)
|
||||||
{
|
{
|
||||||
if (likely(c != 0)) {
|
if (unlikely(_l >= ZT_STR_CAPACITY)) {
|
||||||
if (unlikely(_l >= ZT_STR_CAPACITY)) {
|
_s[ZT_STR_CAPACITY] = 0;
|
||||||
_s[_l] = 0;
|
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
|
||||||
}
|
|
||||||
_s[_l++] = c;
|
|
||||||
_s[_l] = 0;
|
|
||||||
}
|
}
|
||||||
|
_s[(unsigned long)(_l++)] = c;
|
||||||
|
_s[(unsigned long)_l] = 0;
|
||||||
}
|
}
|
||||||
inline Str &operator<<(const unsigned long n)
|
inline Str &operator<<(const unsigned long n)
|
||||||
{
|
{
|
||||||
|
@ -95,13 +95,9 @@ public:
|
|||||||
{
|
{
|
||||||
if (zta == RR->identity.address())
|
if (zta == RR->identity.address())
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
{
|
Mutex::Lock _l(_peers_m);
|
||||||
Mutex::Lock _l(_peers_m);
|
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
||||||
const SharedPtr<Peer> *const ap = _peers.get(zta);
|
return ((ap) ? *ap : SharedPtr<Peer>());
|
||||||
if (ap)
|
|
||||||
return *ap;
|
|
||||||
}
|
|
||||||
return SharedPtr<Peer>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -157,38 +153,29 @@ public:
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current best upstream peer
|
|
||||||
*
|
|
||||||
* @return Upstream or NULL if none available
|
|
||||||
*/
|
|
||||||
inline SharedPtr<Peer> getUpstreamPeer() const
|
inline SharedPtr<Peer> getUpstreamPeer() const
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
return SharedPtr<Peer>();
|
return SharedPtr<Peer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isUpstream(const Identity &id) const
|
inline bool isUpstream(const Identity &id) const
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ZT_PeerRole role(const Address &ztaddr) const
|
inline ZT_PeerRole role(const Address &ztaddr) const
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
return ZT_PEER_ROLE_LEAF;
|
return ZT_PEER_ROLE_LEAF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
inline void getAlwaysContact(Hashtable< Address,std::vector<InetAddress> > &eps) const
|
||||||
* Gets upstreams to contact and their stable endpoints (if known)
|
|
||||||
*
|
|
||||||
* @param eps Hash table to fill with addresses and their stable endpoints
|
|
||||||
*/
|
|
||||||
inline void getUpstreamsToContact(Hashtable< Address,std::vector<InetAddress> > &eps) const
|
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Vector of active upstream addresses (including roots)
|
|
||||||
*/
|
|
||||||
inline std::vector<Address> upstreamAddresses() const
|
inline std::vector<Address> upstreamAddresses() const
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
164
node/Utils.cpp
164
node/Utils.cpp
@ -85,6 +85,71 @@ char *Utils::decimal(unsigned long n,char s[24])
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Utils::unhex(const char *h,void *buf,unsigned int buflen)
|
||||||
|
{
|
||||||
|
unsigned int l = 0;
|
||||||
|
while (l < buflen) {
|
||||||
|
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||||
|
if (!hc) break;
|
||||||
|
|
||||||
|
uint8_t c = 0;
|
||||||
|
if ((hc >= 48)&&(hc <= 57)) // 0..9
|
||||||
|
c = hc - 48;
|
||||||
|
else if ((hc >= 97)&&(hc <= 102)) // a..f
|
||||||
|
c = hc - 87;
|
||||||
|
else if ((hc >= 65)&&(hc <= 70)) // A..F
|
||||||
|
c = hc - 55;
|
||||||
|
|
||||||
|
hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||||
|
if (!hc) break;
|
||||||
|
|
||||||
|
c <<= 4;
|
||||||
|
if ((hc >= 48)&&(hc <= 57))
|
||||||
|
c |= hc - 48;
|
||||||
|
else if ((hc >= 97)&&(hc <= 102))
|
||||||
|
c |= hc - 87;
|
||||||
|
else if ((hc >= 65)&&(hc <= 70))
|
||||||
|
c |= hc - 55;
|
||||||
|
|
||||||
|
reinterpret_cast<uint8_t *>(buf)[l++] = c;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Utils::unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen)
|
||||||
|
{
|
||||||
|
unsigned int l = 0;
|
||||||
|
const char *hend = h + hlen;
|
||||||
|
while (l < buflen) {
|
||||||
|
if (h == hend) break;
|
||||||
|
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||||
|
if (!hc) break;
|
||||||
|
|
||||||
|
uint8_t c = 0;
|
||||||
|
if ((hc >= 48)&&(hc <= 57))
|
||||||
|
c = hc - 48;
|
||||||
|
else if ((hc >= 97)&&(hc <= 102))
|
||||||
|
c = hc - 87;
|
||||||
|
else if ((hc >= 65)&&(hc <= 70))
|
||||||
|
c = hc - 55;
|
||||||
|
|
||||||
|
if (h == hend) break;
|
||||||
|
hc = *(reinterpret_cast<const uint8_t *>(h++));
|
||||||
|
if (!hc) break;
|
||||||
|
|
||||||
|
c <<= 4;
|
||||||
|
if ((hc >= 48)&&(hc <= 57))
|
||||||
|
c |= hc - 48;
|
||||||
|
else if ((hc >= 97)&&(hc <= 102))
|
||||||
|
c |= hc - 87;
|
||||||
|
else if ((hc >= 65)&&(hc <= 70))
|
||||||
|
c |= hc - 55;
|
||||||
|
|
||||||
|
reinterpret_cast<uint8_t *>(buf)[l++] = c;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
void Utils::getSecureRandom(void *buf,unsigned int bytes)
|
void Utils::getSecureRandom(void *buf,unsigned int bytes)
|
||||||
{
|
{
|
||||||
static Mutex globalLock;
|
static Mutex globalLock;
|
||||||
@ -105,8 +170,12 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
|
|||||||
if (!s20Initialized) {
|
if (!s20Initialized) {
|
||||||
s20Initialized = true;
|
s20Initialized = true;
|
||||||
uint64_t s20Key[4];
|
uint64_t s20Key[4];
|
||||||
s20Key[0] = (uint64_t)time(0); // system clock
|
s20Key[0] = (uint64_t)time(nullptr);
|
||||||
|
#ifdef __WINDOWS__
|
||||||
s20Key[1] = (uint64_t)buf; // address of buf
|
s20Key[1] = (uint64_t)buf; // address of buf
|
||||||
|
#else
|
||||||
|
s20Key[1] = (uint64_t)getpid();
|
||||||
|
#endif
|
||||||
s20Key[2] = (uint64_t)s20Key; // address of s20Key[]
|
s20Key[2] = (uint64_t)s20Key; // address of s20Key[]
|
||||||
s20Key[3] = (uint64_t)&s20; // address of s20
|
s20Key[3] = (uint64_t)&s20; // address of s20
|
||||||
s20.init(s20Key,s20Key);
|
s20.init(s20Key,s20Key);
|
||||||
@ -171,6 +240,42 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes)
|
|||||||
#endif // __WINDOWS__ or not
|
#endif // __WINDOWS__ or not
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)
|
||||||
|
{
|
||||||
|
if (length < 0 || length > (1 << 28)) {
|
||||||
|
result[0] = (char)0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
if (length > 0) {
|
||||||
|
int buffer = data[0];
|
||||||
|
int next = 1;
|
||||||
|
int bitsLeft = 8;
|
||||||
|
while (count < bufSize && (bitsLeft > 0 || next < length)) {
|
||||||
|
if (bitsLeft < 5) {
|
||||||
|
if (next < length) {
|
||||||
|
buffer <<= 8;
|
||||||
|
buffer |= data[next++] & 0xFF;
|
||||||
|
bitsLeft += 8;
|
||||||
|
} else {
|
||||||
|
int pad = 5 - bitsLeft;
|
||||||
|
buffer <<= pad;
|
||||||
|
bitsLeft += pad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int index = 0x1F & (buffer >> (bitsLeft - 5));
|
||||||
|
bitsLeft -= 5;
|
||||||
|
result[count++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count < bufSize) {
|
||||||
|
result[count] = (char)0;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
result[0] = (char)0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int Utils::b32d(const char *encoded,uint8_t *result,int bufSize)
|
int Utils::b32d(const char *encoded,uint8_t *result,int bufSize)
|
||||||
{
|
{
|
||||||
int buffer = 0;
|
int buffer = 0;
|
||||||
@ -211,42 +316,6 @@ int Utils::b32d(const char *encoded,uint8_t *result,int bufSize)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize)
|
|
||||||
{
|
|
||||||
if (length < 0 || length > (1 << 28)) {
|
|
||||||
result[0] = (char)0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int count = 0;
|
|
||||||
if (length > 0) {
|
|
||||||
int buffer = data[0];
|
|
||||||
int next = 1;
|
|
||||||
int bitsLeft = 8;
|
|
||||||
while (count < bufSize && (bitsLeft > 0 || next < length)) {
|
|
||||||
if (bitsLeft < 5) {
|
|
||||||
if (next < length) {
|
|
||||||
buffer <<= 8;
|
|
||||||
buffer |= data[next++] & 0xFF;
|
|
||||||
bitsLeft += 8;
|
|
||||||
} else {
|
|
||||||
int pad = 5 - bitsLeft;
|
|
||||||
buffer <<= pad;
|
|
||||||
bitsLeft += pad;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int index = 0x1F & (buffer >> (bitsLeft - 5));
|
|
||||||
bitsLeft -= 5;
|
|
||||||
result[count++] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (count < bufSize) {
|
|
||||||
result[count] = (char)0;
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
result[0] = (char)0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Utils::b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen)
|
unsigned int Utils::b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen)
|
||||||
{
|
{
|
||||||
static const char base64en[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };
|
static const char base64en[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };
|
||||||
@ -326,4 +395,25 @@ unsigned int Utils::b64d(const char *in,unsigned char *out,unsigned int outlen)
|
|||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ROL64(x,k) (((x) << (k)) | ((x) >> (64 - (k))))
|
||||||
|
uint64_t Utils::random()
|
||||||
|
{
|
||||||
|
// https://en.wikipedia.org/wiki/Xorshift#xoshiro256**
|
||||||
|
static Mutex l;
|
||||||
|
static uint64_t s[4] = { Utils::getSecureRandom64(),Utils::getSecureRandom64(),Utils::getSecureRandom64(),Utils::getSecureRandom64() };
|
||||||
|
|
||||||
|
l.lock();
|
||||||
|
const uint64_t result = ROL64(s[1] * 5,7) * 9;
|
||||||
|
const uint64_t t = s[1] << 17;
|
||||||
|
s[2] ^= s[0];
|
||||||
|
s[3] ^= s[1];
|
||||||
|
s[1] ^= s[2];
|
||||||
|
s[0] ^= s[3];
|
||||||
|
s[2] ^= t;
|
||||||
|
s[3] = ROL64(s[3],45);
|
||||||
|
l.unlock();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
145
node/Utils.hpp
145
node/Utils.hpp
@ -48,6 +48,11 @@ namespace ZeroTier {
|
|||||||
class Utils
|
class Utils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Hexadecimal characters 0-f
|
||||||
|
*/
|
||||||
|
static const char HEXCHARS[16];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a time-invariant binary comparison
|
* Perform a time-invariant binary comparison
|
||||||
*
|
*
|
||||||
@ -65,7 +70,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Securely zero memory, avoiding compiler optimizations and such
|
* Zero memory, ensuring to avoid any compiler optimizations or other things that may stop this.
|
||||||
*/
|
*/
|
||||||
static void burn(void *ptr,unsigned int len);
|
static void burn(void *ptr,unsigned int len);
|
||||||
|
|
||||||
@ -158,78 +163,8 @@ public:
|
|||||||
return save;
|
return save;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int unhex(const char *h,void *buf,unsigned int buflen)
|
static unsigned int unhex(const char *h,void *buf,unsigned int buflen);
|
||||||
{
|
static unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen);
|
||||||
unsigned int l = 0;
|
|
||||||
while (l < buflen) {
|
|
||||||
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
|
|
||||||
if (!hc) break;
|
|
||||||
|
|
||||||
uint8_t c = 0;
|
|
||||||
if ((hc >= 48)&&(hc <= 57)) // 0..9
|
|
||||||
c = hc - 48;
|
|
||||||
else if ((hc >= 97)&&(hc <= 102)) // a..f
|
|
||||||
c = hc - 87;
|
|
||||||
else if ((hc >= 65)&&(hc <= 70)) // A..F
|
|
||||||
c = hc - 55;
|
|
||||||
|
|
||||||
hc = *(reinterpret_cast<const uint8_t *>(h++));
|
|
||||||
if (!hc) break;
|
|
||||||
|
|
||||||
c <<= 4;
|
|
||||||
if ((hc >= 48)&&(hc <= 57))
|
|
||||||
c |= hc - 48;
|
|
||||||
else if ((hc >= 97)&&(hc <= 102))
|
|
||||||
c |= hc - 87;
|
|
||||||
else if ((hc >= 65)&&(hc <= 70))
|
|
||||||
c |= hc - 55;
|
|
||||||
|
|
||||||
reinterpret_cast<uint8_t *>(buf)[l++] = c;
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen)
|
|
||||||
{
|
|
||||||
unsigned int l = 0;
|
|
||||||
const char *hend = h + hlen;
|
|
||||||
while (l < buflen) {
|
|
||||||
if (h == hend) break;
|
|
||||||
uint8_t hc = *(reinterpret_cast<const uint8_t *>(h++));
|
|
||||||
if (!hc) break;
|
|
||||||
|
|
||||||
uint8_t c = 0;
|
|
||||||
if ((hc >= 48)&&(hc <= 57))
|
|
||||||
c = hc - 48;
|
|
||||||
else if ((hc >= 97)&&(hc <= 102))
|
|
||||||
c = hc - 87;
|
|
||||||
else if ((hc >= 65)&&(hc <= 70))
|
|
||||||
c = hc - 55;
|
|
||||||
|
|
||||||
if (h == hend) break;
|
|
||||||
hc = *(reinterpret_cast<const uint8_t *>(h++));
|
|
||||||
if (!hc) break;
|
|
||||||
|
|
||||||
c <<= 4;
|
|
||||||
if ((hc >= 48)&&(hc <= 57))
|
|
||||||
c |= hc - 48;
|
|
||||||
else if ((hc >= 97)&&(hc <= 102))
|
|
||||||
c |= hc - 87;
|
|
||||||
else if ((hc >= 65)&&(hc <= 70))
|
|
||||||
c |= hc - 55;
|
|
||||||
|
|
||||||
reinterpret_cast<uint8_t *>(buf)[l++] = c;
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float normalize(float value, int64_t bigMin, int64_t bigMax, int32_t targetMin, int32_t targetMax)
|
|
||||||
{
|
|
||||||
int64_t bigSpan = bigMax - bigMin;
|
|
||||||
int64_t smallSpan = targetMax - targetMin;
|
|
||||||
float valueScaled = (value - (float)bigMin) / (float)bigSpan;
|
|
||||||
return (float)targetMin + valueScaled * (float)smallSpan;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate secure random bytes
|
* Generate secure random bytes
|
||||||
@ -242,13 +177,36 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void getSecureRandom(void *buf,unsigned int bytes);
|
static void getSecureRandom(void *buf,unsigned int bytes);
|
||||||
|
|
||||||
static int b32d(const char *encoded, uint8_t *result, int bufSize);
|
/**
|
||||||
|
* Get a 64-bit unsigned secure random number
|
||||||
|
*/
|
||||||
|
static inline uint64_t getSecureRandom64()
|
||||||
|
{
|
||||||
|
uint64_t x;
|
||||||
|
getSecureRandom(&x,sizeof(x));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
static int b32e(const uint8_t *data,int length,char *result,int bufSize);
|
static int b32e(const uint8_t *data,int length,char *result,int bufSize);
|
||||||
|
static int b32d(const char *encoded, uint8_t *result, int bufSize);
|
||||||
|
|
||||||
static inline unsigned int b64MaxEncodedSize(const unsigned int s) { return ((((s + 2) / 3) * 4) + 1); }
|
static inline unsigned int b64MaxEncodedSize(const unsigned int s) { return ((((s + 2) / 3) * 4) + 1); }
|
||||||
static unsigned int b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen);
|
static unsigned int b64e(const uint8_t *in,unsigned int inlen,char *out,unsigned int outlen);
|
||||||
static unsigned int b64d(const char *in,uint8_t *out,unsigned int outlen);
|
static unsigned int b64d(const char *in,uint8_t *out,unsigned int outlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a non-cryptographic random integer
|
||||||
|
*/
|
||||||
|
static uint64_t random();
|
||||||
|
|
||||||
|
static inline float normalize(float value, int64_t bigMin, int64_t bigMax, int32_t targetMin, int32_t targetMax)
|
||||||
|
{
|
||||||
|
int64_t bigSpan = bigMax - bigMin;
|
||||||
|
int64_t smallSpan = targetMax - targetMin;
|
||||||
|
float valueScaled = (value - (float)bigMin) / (float)bigSpan;
|
||||||
|
return (float)targetMin + valueScaled * (float)smallSpan;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokenize a string (alias for strtok_r or strtok_s depending on platform)
|
* Tokenize a string (alias for strtok_r or strtok_s depending on platform)
|
||||||
*
|
*
|
||||||
@ -350,23 +308,8 @@ public:
|
|||||||
return (T)(v * ((~((T)0))/((T)255))) >> ((sizeof(T) - 1) * 8);
|
return (T)(v * ((~((T)0))/((T)255))) >> ((sizeof(T) - 1) * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a memory buffer is all-zero
|
|
||||||
*
|
|
||||||
* @param p Memory to scan
|
|
||||||
* @param len Length of memory
|
|
||||||
* @return True if memory is all zero
|
|
||||||
*/
|
|
||||||
static inline bool isZero(const void *p,unsigned int len)
|
|
||||||
{
|
|
||||||
for(unsigned int i=0;i<len;++i) {
|
|
||||||
if (((const unsigned char *)p)[i])
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Byte swappers for big/little endian conversion
|
// Byte swappers for big/little endian conversion
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
static inline uint8_t hton(uint8_t n) { return n; }
|
static inline uint8_t hton(uint8_t n) { return n; }
|
||||||
static inline int8_t hton(int8_t n) { return n; }
|
static inline int8_t hton(int8_t n) { return n; }
|
||||||
static inline uint16_t hton(uint16_t n) { return htons(n); }
|
static inline uint16_t hton(uint16_t n) { return htons(n); }
|
||||||
@ -375,7 +318,6 @@ public:
|
|||||||
static inline int32_t hton(int32_t n) { return (int32_t)htonl((uint32_t)n); }
|
static inline int32_t hton(int32_t n) { return (int32_t)htonl((uint32_t)n); }
|
||||||
static inline uint64_t hton(uint64_t n)
|
static inline uint64_t hton(uint64_t n)
|
||||||
{
|
{
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
return bswap64(n);
|
return bswap64(n);
|
||||||
@ -393,13 +335,15 @@ public:
|
|||||||
((n & 0x00FF000000000000ULL) >> 40) |
|
((n & 0x00FF000000000000ULL) >> 40) |
|
||||||
((n & 0xFF00000000000000ULL) >> 56)
|
((n & 0xFF00000000000000ULL) >> 56)
|
||||||
);
|
);
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
return n;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline int64_t hton(int64_t n) { return (int64_t)hton((uint64_t)n); }
|
static inline int64_t hton(int64_t n) { return (int64_t)hton((uint64_t)n); }
|
||||||
|
#else
|
||||||
|
template<typename T>
|
||||||
|
static inline T hton(T n) { return n; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
static inline uint8_t ntoh(uint8_t n) { return n; }
|
static inline uint8_t ntoh(uint8_t n) { return n; }
|
||||||
static inline int8_t ntoh(int8_t n) { return n; }
|
static inline int8_t ntoh(int8_t n) { return n; }
|
||||||
static inline uint16_t ntoh(uint16_t n) { return ntohs(n); }
|
static inline uint16_t ntoh(uint16_t n) { return ntohs(n); }
|
||||||
@ -408,7 +352,6 @@ public:
|
|||||||
static inline int32_t ntoh(int32_t n) { return (int32_t)ntohl((uint32_t)n); }
|
static inline int32_t ntoh(int32_t n) { return (int32_t)ntohl((uint32_t)n); }
|
||||||
static inline uint64_t ntoh(uint64_t n)
|
static inline uint64_t ntoh(uint64_t n)
|
||||||
{
|
{
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
return bswap64(n);
|
return bswap64(n);
|
||||||
@ -426,17 +369,13 @@ public:
|
|||||||
((n & 0x00FF000000000000ULL) >> 40) |
|
((n & 0x00FF000000000000ULL) >> 40) |
|
||||||
((n & 0xFF00000000000000ULL) >> 56)
|
((n & 0xFF00000000000000ULL) >> 56)
|
||||||
);
|
);
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
return n;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static inline int64_t ntoh(int64_t n) { return (int64_t)ntoh((uint64_t)n); }
|
static inline int64_t ntoh(int64_t n) { return (int64_t)ntoh((uint64_t)n); }
|
||||||
|
#else
|
||||||
/**
|
template<typename T>
|
||||||
* Hexadecimal characters 0-f
|
static inline T ntoh(T n) { return n; }
|
||||||
*/
|
#endif
|
||||||
static const char HEXCHARS[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
Loading…
Reference in New Issue
Block a user