More work in progress

This commit is contained in:
Adam Ierymenko 2019-08-14 12:48:45 -07:00
parent 573d3eea87
commit 8f5f7f1baa
No known key found for this signature in database
GPG Key ID: 1657198823E52A61
8 changed files with 210 additions and 186 deletions

View File

@ -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),

View File

@ -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

View File

@ -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);

View File

@ -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),

View File

@ -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)
{ {

View File

@ -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

View File

@ -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

View File

@ -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