diff --git a/include/ZeroTierCore.h b/include/ZeroTierCore.h index 9daa3551d..1037d97f7 100644 --- a/include/ZeroTierCore.h +++ b/include/ZeroTierCore.h @@ -19,7 +19,11 @@ #ifndef ZT_ZEROTIER_API_H #define ZT_ZEROTIER_API_H +#ifdef __cplusplus +#include +#else #include +#endif /* For struct sockaddr_storage, which is referenced here. */ #if defined(_WIN32) || defined(_WIN64) @@ -513,45 +517,6 @@ enum ZT_Event ZT_EVENT_REMOTE_TRACE = 7 }; -/** - * A root server - */ -typedef struct { - /** - * Name of root - * - * This will be a DNS name for dynamic roots. For static roots - * it will be the ZeroTier address. The presence or absence - * of a dot is used internally as a distinguisher. - */ - const char *name; - - /** - * Serialized locator - */ - const void *locator; - - /** - * The size of locator in bytes - */ - unsigned int locatorSize; -} ZT_Root; - -/** - * List of root servers - */ -typedef struct { - /** - * Number of root servers - */ - unsigned int count; - - /** - * Array of root servers - */ - ZT_Root roots[]; -} ZT_RootList; - /** * Payload of REMOTE_TRACE event */ @@ -1010,29 +975,6 @@ enum ZT_PeerRole ZT_PEER_ROLE_PLANET = 2 // planetary root }; -/** - * DNS record types for reporting DNS results - * - * These integer IDs (other than end of results) are the same as the DNS protocol's - * internal IDs. Not all of these are used by ZeroTier, and not all DNS record types - * are listed here. These are just common ones that are used now or may be used in - * the future for some purpose. - */ -enum ZT_DNSRecordType -{ - ZT_DNS_RECORD__END_OF_RESULTS = 0, - ZT_DNS_RECORD_A = 1, - ZT_DNS_RECORD_NS = 2, - ZT_DNS_RECORD_CNAME = 5, - ZT_DNS_RECORD_PTR = 12, - ZT_DNS_RECORD_MX = 15, - ZT_DNS_RECORD_TXT = 16, - ZT_DNS_RECORD_AAAA = 28, - ZT_DNS_RECORD_LOC = 29, - ZT_DNS_RECORD_SRV = 33, - ZT_DNS_RECORD_DNAME = 39 -}; - /** * Virtual network configuration */ @@ -1541,8 +1483,9 @@ typedef int (*ZT_PathCheckFunction)( * (1) Node * (2) User pointer * (3) ZeroTier address (least significant 40 bits) - * (4) Desired address family or -1 for any - * (5) Buffer to fill with result + * (4) Identity in string form + * (5) Desired address family or -1 for any + * (6) Buffer to fill with result * * If provided this function will be occasionally called to get physical * addresses that might be tried to reach a ZeroTier address. It must @@ -1554,53 +1497,10 @@ typedef int (*ZT_PathLookupFunction)( void *, /* User ptr */ void *, /* Thread ptr */ uint64_t, /* ZeroTier address (40 bits) */ + const char *, /* Identity in string form */ int, /* Desired ss_family or -1 for any */ struct sockaddr_storage *); /* Result buffer */ -/** - * Function to request an asynchronous DNS TXT lookup - * - * Parameters: - * (1) Node - * (2) User pointer - * (3) Thread pointer - * (4) Array of DNS record types we want - * (5) Number of DNS record types in array - * (6) DNS name to fetch - * (7) DNS request ID to supply to ZT_Node_processDNSResult() - * - * DNS is not handled in the core because every platform and runtime - * typically has its own DNS functions or libraries and these may need - * to interface with OS or network services in your local environment. - * Instead this function and its result submission counterpart are - * provided so you can provide a DNS implementation. - * - * If this callback is set in your callback struct to a NULL value, - * DNS will not be available. The ZeroTier protocol is designed to - * work in the absence of DNS but you may not get optimal results. For - * example you may default to root servers that are not geographically - * optimal or your node may cease to function if a root server's IP - * changes and there's no way to signal this. - * - * This function requests resolution of a DNS record. The result - * submission method ZT_Node_processDNSResult() must be called at - * least once in response. See its documentation. - * - * Right now ZeroTier only requests resolution of TXT records, but - * it's possible that this will change in the future. - * - * It's safe to call processDNSResult() from within your handler - * for this function. - */ -typedef void (*ZT_DNSResolver)( - ZT_Node *, /* Node */ - void *, /* User ptr */ - void *, /* Thread ptr */ - const enum ZT_DNSRecordType *, /* DNS record type(s) to fetch */ - unsigned int, /* Number of DNS record type(s) */ - const char *, /* DNS name to fetch */ - uintptr_t); /* Request ID for returning results */ - /****************************************************************************/ /* C Node API */ /****************************************************************************/ @@ -1640,11 +1540,6 @@ struct ZT_Node_Callbacks */ ZT_EventCallback eventCallback; - /** - * STRONGLY RECOMMENDED: Function to request a DNS lookup - */ - ZT_DNSResolver dnsResolver; - /** * OPTIONAL: Function to check whether a given physical path should be used */ @@ -1750,60 +1645,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks( int64_t now, volatile int64_t *nextBackgroundTaskDeadline); -/** - * Submit the result(s) of a requested DNS query - * - * This MUST be called at least once after the node requsts DNS resolution. - * If there are no results or DNS is not implemented or available, just - * send one ZT_DNS_RECORD__END_OF_RESULTS to signal that no results were - * obtained. - * - * If result is non-NULL but resultLength is zero then result is assumed to - * be a C string terminated by a zero. Passing an unterminated string with a - * zero resultLength will result in a crash. - * - * The results of A and AAAA records can be returned as either strings or - * binary IP address bytes (network byte order). If the result is a string, - * resultLength must be 0 to signal that result is a C string. Otherwise for - * A resultLength must be 4 and for AAAA it must be 16 if the result is - * in binary format. - * - * The Node implementation makes an effort to ignore obviously invalid - * submissions like an AAAA record in bianry form with length 25, but this - * is not guaranteed. It's possible to crash your program by calling this - * with garbage inputs. - * - * Results may be submitted in any order and order should not be assumed - * to have any meaning. - * - * The ZT_DNS_RECORD__END_OF_RESULTS pseudo-response must be sent after all - * results have been submitted. The result and resultLength paramters are - * ignored for this type ID. - * - * It is safe to call this function from inside the DNS request callback, - * such as to return a locally cached result or a result from some kind - * of local database. It's also safe to call this function from threads - * other than the one that received the DNS request. - * - * @param node Node instance that requested DNS resolution - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param dnsRequestID Request ID supplied to DNS request callback - * @param name DNS name - * @param recordType Record type of this result - * @param result Result (content depends on record type) - * @param resultLength Length of result - * @param resultIsString If non-zero, IP results for A and AAAA records are being given as C strings not binary IPs - */ -ZT_SDK_API void ZT_Node_processDNSResult( - ZT_Node *node, - void *tptr, - uintptr_t dnsRequestID, - const char *name, - enum ZT_DNSRecordType recordType, - const void *result, - unsigned int resultLength, - int resultIsString); - /** * Join a network * @@ -1884,36 +1725,25 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tpt ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); /** - * List roots for this node + * Add a root server (has no effect if already added) * * @param node Node instance - * @param now Current time - * @return List of roots, use ZT_Node_freeQueryResult to free this when done + * @param identity Identity of this root server in string format + * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now); +ZT_SDK_API enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,const char *identity); /** - * Add or update a root + * Remove a root server * - * The node will begin trying to resolve the DNS TXT record for - * this root and possibly obtain it from other peers. + * This removes this node's root designation but does not prevent this node + * from communicating with it or close active paths to it. * * @param node Node instance - * @param name DNS name or simply the address in hex form for static roots - * @param locator Binary-serialized locator of NULL if none - * @param locatorSize Size of locator or 0 if none - * @return OK (0) or error code + * @param identity Identity in string format + * @return OK (0) or error code if a fatal error condition has occurred */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize); - -/** - * Remove a dynamic root - * - * @param node Node instance - * @param name DNS name of this dynamic root or the address in hex form for static roots - * @return OK (0) or error code - */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name); +ZT_SDK_API enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *identity); /** * Get this node's 40-bit ZeroTier address diff --git a/node/Constants.hpp b/node/Constants.hpp index 08df5abd8..f66da43ee 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -37,9 +37,9 @@ #define ZT_ADDRESS_RESERVED_PREFIX 0xff /** - * Maximum DNS or URL name size for an Endpoint (set so that max marshaled endpoint size is 128 bytes) + * Maximum DNS or URL name size for an Endpoint (set so that max marshaled endpoint size is 64 bytes) */ -#define ZT_ENDPOINT_MAX_NAME_SIZE 124 +#define ZT_ENDPOINT_MAX_NAME_SIZE 61 /** * Size of an identity hash (SHA384) diff --git a/node/ECC384.cpp b/node/ECC384.cpp index d28cf742d..b908615f1 100644 --- a/node/ECC384.cpp +++ b/node/ECC384.cpp @@ -60,13 +60,13 @@ static EccPoint curve_G = CONCAT(Curve_G_, ECC_CURVE); static uint64_t curve_n[NUM_ECC_DIGITS] = CONCAT(Curve_N_, ECC_CURVE); // Use ZeroTier's secure PRNG -static inline int getRandomNumber(uint64_t *p_vli) +static ZT_ALWAYS_INLINE int getRandomNumber(uint64_t *p_vli) { Utils::getSecureRandom(p_vli,ECC_BYTES); return 1; } -static inline void vli_clear(uint64_t *p_vli) +static ZT_ALWAYS_INLINE void vli_clear(uint64_t *p_vli) { uint i; for(i=0; ix) && vli_isZero(p_point->y)); } @@ -635,7 +635,7 @@ static inline void EccPoint_double_jacobian(uint64_t *X1, uint64_t *Y1, uint64_t } /* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */ -static inline void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z) +static ZT_ALWAYS_INLINE void apply_z(uint64_t *X1, uint64_t *Y1, uint64_t *Z) { uint64_t t1[NUM_ECC_DIGITS]; @@ -772,7 +772,7 @@ static inline void EccPoint_mult(EccPoint *p_result, EccPoint *p_point, uint64_t vli_set(p_result->y, Ry[0]); } -static inline void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t p_bytes[ECC_BYTES]) +static ZT_ALWAYS_INLINE void ecc_bytes2native(uint64_t p_native[NUM_ECC_DIGITS], const uint8_t p_bytes[ECC_BYTES]) { unsigned i; for(i=0; i b ? a : b); } diff --git a/node/Endpoint.hpp b/node/Endpoint.hpp index afb26c34b..25ebac131 100644 --- a/node/Endpoint.hpp +++ b/node/Endpoint.hpp @@ -24,7 +24,7 @@ #include "Address.hpp" #include "Utils.hpp" -#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+4) +#define ZT_ENDPOINT_MARSHAL_SIZE_MAX (ZT_ENDPOINT_MAX_NAME_SIZE+3) namespace ZeroTier { @@ -46,10 +46,10 @@ public: ZT_ALWAYS_INLINE Endpoint() { memset(reinterpret_cast(this),0,sizeof(Endpoint)); } - ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; } + explicit ZT_ALWAYS_INLINE Endpoint(const InetAddress &sa) : _t(INETADDR) { _v.sa = sa; } ZT_ALWAYS_INLINE Endpoint(const Address &zt,const uint8_t identityHash[ZT_IDENTITY_HASH_SIZE]) : _t(ZEROTIER) { _v.zt.a = zt.toInt(); memcpy(_v.zt.idh,identityHash,ZT_IDENTITY_HASH_SIZE); } ZT_ALWAYS_INLINE Endpoint(const char *name,const int port) : _t(DNSNAME) { Utils::scopy(_v.dns.name,sizeof(_v.dns.name),name); _v.dns.port = port; } - ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); } + explicit ZT_ALWAYS_INLINE Endpoint(const char *url) : _t(URL) { Utils::scopy(_v.url,sizeof(_v.url),url); } ZT_ALWAYS_INLINE const InetAddress *sockaddr() const { return (_t == INETADDR) ? reinterpret_cast(&_v.sa) : nullptr; } ZT_ALWAYS_INLINE const char *dnsName() const { return (_t == DNSNAME) ? _v.dns.name : nullptr; } @@ -61,6 +61,45 @@ public: ZT_ALWAYS_INLINE Type type() const { return _t; } + ZT_ALWAYS_INLINE bool operator==(const Endpoint &ep) const + { + if (_t == ep._t) { + switch(_t) { + case INETADDR: return (*sockaddr() == *ep.sockaddr()); + case DNSNAME: return ((_v.dns.port == ep._v.dns.port)&&(strcmp(_v.dns.name,ep._v.dns.name) == 0)); + case ZEROTIER: return ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) == 0)); + case URL: return (strcmp(_v.url,ep._v.url) == 0); + case ETHERNET: return (_v.eth == ep._v.eth); + default: return true; + } + } + return false; + } + ZT_ALWAYS_INLINE bool operator!=(const Endpoint &ep) const { return (!(*this == ep)); } + ZT_ALWAYS_INLINE bool operator<(const Endpoint &ep) const + { + if ((int)_t < (int)ep._t) { + return true; + } else if (_t == ep._t) { + int ncmp; + switch(_t) { + case INETADDR: return (*sockaddr() < *ep.sockaddr()); + case DNSNAME: + ncmp = strcmp(_v.dns.name,ep._v.dns.name); + return ((ncmp < 0) ? true : (ncmp == 0)&&(_v.dns.port < ep._v.dns.port)); + case ZEROTIER: return (_v.zt.a < ep._v.zt.a) ? true : ((_v.zt.a == ep._v.zt.a)&&(memcmp(_v.zt.idh,ep._v.zt.idh,sizeof(_v.zt.idh)) < 0)); + case URL: return (strcmp(_v.url,ep._v.url) < 0); + case ETHERNET: return (_v.eth < ep._v.eth); + default: return false; + } + } + return false; + } + ZT_ALWAYS_INLINE bool operator>(const Endpoint &ep) const { return (ep < *this); } + ZT_ALWAYS_INLINE bool operator<=(const Endpoint &ep) const { return !(ep < *this); } + ZT_ALWAYS_INLINE bool operator>=(const Endpoint &ep) const { return !(*this < ep); } + + // Marshal interface /////////////////////////////////////////////////////// static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_ENDPOINT_MARSHAL_SIZE_MAX; } inline int marshal(uint8_t data[ZT_ENDPOINT_MARSHAL_SIZE_MAX]) const { @@ -79,16 +118,16 @@ public: if (p == (ZT_ENDPOINT_MAX_NAME_SIZE+1)) return -1; } - data[p++] = (uint8_t)((_v.dns.port >> 8) & 0xff); - data[p++] = (uint8_t)(_v.dns.port & 0xff); + data[p++] = (uint8_t)(_v.dns.port >> 8U); + data[p++] = (uint8_t)_v.dns.port; return p; case ZEROTIER: data[0] = (uint8_t)ZEROTIER; - data[1] = (uint8_t)((_v.zt.a >> 32) & 0xff); - data[2] = (uint8_t)((_v.zt.a >> 24) & 0xff); - data[3] = (uint8_t)((_v.zt.a >> 16) & 0xff); - data[4] = (uint8_t)((_v.zt.a >> 8) & 0xff); - data[5] = (uint8_t)(_v.zt.a & 0xff); + data[1] = (uint8_t)(_v.zt.a >> 32U); + data[2] = (uint8_t)(_v.zt.a >> 24U); + data[3] = (uint8_t)(_v.zt.a >> 16U); + data[4] = (uint8_t)(_v.zt.a >> 8U); + data[5] = (uint8_t)_v.zt.a; memcpy(data + 6,_v.zt.idh,ZT_IDENTITY_HASH_SIZE); return (ZT_IDENTITY_HASH_SIZE + 6); case URL: @@ -104,12 +143,12 @@ public: return p; case ETHERNET: data[0] = (uint8_t)ETHERNET; - data[1] = (uint8_t)((_v.eth >> 40) & 0xff); - data[2] = (uint8_t)((_v.eth >> 32) & 0xff); - data[3] = (uint8_t)((_v.eth >> 24) & 0xff); - data[4] = (uint8_t)((_v.eth >> 16) & 0xff); - data[5] = (uint8_t)((_v.eth >> 8) & 0xff); - data[6] = (uint8_t)(_v.eth & 0xff); + data[1] = (uint8_t)(_v.eth >> 40U); + data[2] = (uint8_t)(_v.eth >> 32U); + data[3] = (uint8_t)(_v.eth >> 24U); + data[4] = (uint8_t)(_v.eth >> 16U); + data[5] = (uint8_t)(_v.eth >> 8U); + data[6] = (uint8_t)_v.eth; return 7; default: data[0] = (uint8_t)NIL; @@ -142,17 +181,17 @@ public: if ((p >= (ZT_ENDPOINT_MAX_NAME_SIZE+1))||(p >= (len-2))) return -1; } - _v.dns.port = ((int)data[p++]) << 8; - _v.dns.port |= (int)data[p++]; + _v.dns.port = (uint16_t)(((unsigned int)data[p++]) << 8U); + _v.dns.port |= (uint16_t)data[p++]; return p; case ZEROTIER: if (len < (ZT_IDENTITY_HASH_SIZE + 6)) return -1; _t = ZEROTIER; - _v.zt.a = ((uint64_t)data[1]) << 32; - _v.zt.a |= ((uint64_t)data[2]) << 24; - _v.zt.a |= ((uint64_t)data[3]) << 16; - _v.zt.a |= ((uint64_t)data[4]) << 8; + _v.zt.a = ((uint64_t)data[1]) << 32U; + _v.zt.a |= ((uint64_t)data[2]) << 24U; + _v.zt.a |= ((uint64_t)data[3]) << 16U; + _v.zt.a |= ((uint64_t)data[4]) << 8U; _v.zt.a |= (uint64_t)data[5]; memcpy(_v.zt.idh,data + 6,ZT_IDENTITY_HASH_SIZE); return (ZT_IDENTITY_HASH_SIZE + 6); @@ -175,16 +214,17 @@ public: if (len < 7) return -1; _t = ZEROTIER; - _v.eth = ((uint64_t)data[1]) << 40; - _v.eth |= ((uint64_t)data[2]) << 32; - _v.eth |= ((uint64_t)data[3]) << 24; - _v.eth |= ((uint64_t)data[4]) << 16; - _v.eth |= ((uint64_t)data[5]) << 8; + _v.eth = ((uint64_t)data[1]) << 40U; + _v.eth |= ((uint64_t)data[2]) << 32U; + _v.eth |= ((uint64_t)data[3]) << 24U; + _v.eth |= ((uint64_t)data[4]) << 16U; + _v.eth |= ((uint64_t)data[5]) << 8U; _v.eth |= (uint64_t)data[6]; return 7; } return false; } + //////////////////////////////////////////////////////////////////////////// private: Type _t; @@ -192,7 +232,7 @@ private: struct sockaddr_storage sa; struct { char name[ZT_ENDPOINT_MAX_NAME_SIZE]; - int port; + uint16_t port; } dns; struct { uint64_t a; diff --git a/node/Identity.hpp b/node/Identity.hpp index 6938bf2d4..88df4d252 100644 --- a/node/Identity.hpp +++ b/node/Identity.hpp @@ -368,7 +368,7 @@ public: /** * @return True if this identity contains something */ - ZT_ALWAYS_INLINE operator bool() const { return (_address); } + explicit ZT_ALWAYS_INLINE operator bool() const { return (_address); } ZT_ALWAYS_INLINE bool operator==(const Identity &id) const { @@ -407,7 +407,7 @@ public: // Marshal interface /////////////////////////////////////////////////////// static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_IDENTITY_MARSHAL_SIZE_MAX; } - inline int marshal(uint8_t restrict data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const + inline int marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool includePrivate = false) const { _address.copyTo(data,ZT_ADDRESS_LENGTH); switch(_type) { diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp index 5a056bec2..834bcae7e 100644 --- a/node/InetAddress.cpp +++ b/node/InetAddress.cpp @@ -11,11 +11,8 @@ */ /****/ -#include -#include -#include - -#include +#include +#include #include "Constants.hpp" #include "InetAddress.hpp" @@ -33,20 +30,20 @@ InetAddress::IpScope InetAddress::ipScope() const case AF_INET: { const uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); - switch(ip >> 24) { + switch(ip >> 24U) { case 0x00: return IP_SCOPE_NONE; // 0.0.0.0/8 (reserved, never used) case 0x06: return IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army) case 0x0a: return IP_SCOPE_PRIVATE; // 10.0.0.0/8 - case 0x0b: return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) - case 0x15: return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) - case 0x16: return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) - case 0x19: return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense) - case 0x1a: return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA) - case 0x1c: return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) - case 0x1d: return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) - case 0x1e: return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) - case 0x33: return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) - case 0x37: return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) + case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) + case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) + case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) + case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense) + case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA) + case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) + case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) + case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) + case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) + case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) case 0x38: return IP_SCOPE_PSEUDOPRIVATE; // 56.0.0.0/8 (US Postal Service) case 0x64: if ((ip & 0xffc00000) == 0x64400000) return IP_SCOPE_PRIVATE; // 100.64.0.0/10 @@ -164,7 +161,7 @@ bool InetAddress::fromString(const char *ipSlashPort) unsigned int port = 0; if (*portAt) { *(portAt++) = (char)0; - port = Utils::strToUInt(portAt) & 0xffff; + port = Utils::strToUInt(portAt) & 0xffffU; } if (strchr(buf,':')) { @@ -189,7 +186,7 @@ InetAddress InetAddress::netmask() const InetAddress r(*this); switch(r.ss_family) { case AF_INET: - reinterpret_cast(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits()))); + reinterpret_cast(&r)->sin_addr.s_addr = Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); break; case AF_INET6: { uint64_t nm[2]; @@ -211,7 +208,7 @@ InetAddress InetAddress::broadcast() const { if (ss_family == AF_INET) { InetAddress r(*this); - reinterpret_cast(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffff >> netmaskBits())); + reinterpret_cast(&r)->sin_addr.s_addr |= Utils::hton((uint32_t)(0xffffffffU >> netmaskBits())); return r; } return InetAddress(); @@ -222,7 +219,7 @@ InetAddress InetAddress::network() const InetAddress r(*this); switch(r.ss_family) { case AF_INET: - reinterpret_cast(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffff << (32 - netmaskBits()))); + reinterpret_cast(&r)->sin_addr.s_addr &= Utils::hton((uint32_t)(0xffffffffU << (32 - netmaskBits()))); break; case AF_INET6: { uint64_t nm[2]; @@ -294,7 +291,7 @@ bool InetAddress::isNetwork() const if (bits >= 32) return false; uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr); - return ((ip & (0xffffffff >> bits)) == 0); + return ((ip & (0xffffffffU >> bits)) == 0); } case AF_INET6: { unsigned int bits = netmaskBits(); @@ -304,7 +301,7 @@ bool InetAddress::isNetwork() const return false; const unsigned char *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); unsigned int p = bits / 8; - if ((ip[p++] & (0xff >> (bits % 8))) != 0) + if ((ip[p++] & (0xffU >> (bits % 8))) != 0) return false; while (p < 16) { if (ip[p++]) @@ -378,48 +375,49 @@ bool InetAddress::operator<(const InetAddress &a) const InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) { - struct sockaddr_in6 sin6; - sin6.sin6_family = AF_INET6; - sin6.sin6_addr.s6_addr[0] = 0xfe; - sin6.sin6_addr.s6_addr[1] = 0x80; - sin6.sin6_addr.s6_addr[2] = 0x00; - sin6.sin6_addr.s6_addr[3] = 0x00; - sin6.sin6_addr.s6_addr[4] = 0x00; - sin6.sin6_addr.s6_addr[5] = 0x00; - sin6.sin6_addr.s6_addr[6] = 0x00; - sin6.sin6_addr.s6_addr[7] = 0x00; - sin6.sin6_addr.s6_addr[8] = mac[0] & 0xfd; - sin6.sin6_addr.s6_addr[9] = mac[1]; - sin6.sin6_addr.s6_addr[10] = mac[2]; - sin6.sin6_addr.s6_addr[11] = 0xff; - sin6.sin6_addr.s6_addr[12] = 0xfe; - sin6.sin6_addr.s6_addr[13] = mac[3]; - sin6.sin6_addr.s6_addr[14] = mac[4]; - sin6.sin6_addr.s6_addr[15] = mac[5]; - sin6.sin6_port = Utils::hton((uint16_t)64); - return InetAddress(sin6); + InetAddress r; + sockaddr_in6 *const sin6 = reinterpret_cast(&r); + sin6->sin6_family = AF_INET6; + sin6->sin6_addr.s6_addr[0] = 0xfe; + sin6->sin6_addr.s6_addr[1] = 0x80; + sin6->sin6_addr.s6_addr[2] = 0x00; + sin6->sin6_addr.s6_addr[3] = 0x00; + sin6->sin6_addr.s6_addr[4] = 0x00; + sin6->sin6_addr.s6_addr[5] = 0x00; + sin6->sin6_addr.s6_addr[6] = 0x00; + sin6->sin6_addr.s6_addr[7] = 0x00; + sin6->sin6_addr.s6_addr[8] = mac[0] & 0xfdU; + sin6->sin6_addr.s6_addr[9] = mac[1]; + sin6->sin6_addr.s6_addr[10] = mac[2]; + sin6->sin6_addr.s6_addr[11] = 0xff; + sin6->sin6_addr.s6_addr[12] = 0xfe; + sin6->sin6_addr.s6_addr[13] = mac[3]; + sin6->sin6_addr.s6_addr[14] = mac[4]; + sin6->sin6_addr.s6_addr[15] = mac[5]; + sin6->sin6_port = Utils::hton((uint16_t)64); + return r; } InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress) { InetAddress r; - struct sockaddr_in6 *const sin6 = reinterpret_cast(&r); + sockaddr_in6 *const sin6 = reinterpret_cast(&r); sin6->sin6_family = AF_INET6; sin6->sin6_addr.s6_addr[0] = 0xfd; - sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56); - sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48); - sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40); - sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32); - sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24); - sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16); - sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8); + sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 56U); + sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 48U); + sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 40U); + sin6->sin6_addr.s6_addr[4] = (uint8_t)(nwid >> 32U); + sin6->sin6_addr.s6_addr[5] = (uint8_t)(nwid >> 24U); + sin6->sin6_addr.s6_addr[6] = (uint8_t)(nwid >> 16U); + sin6->sin6_addr.s6_addr[7] = (uint8_t)(nwid >> 8U); sin6->sin6_addr.s6_addr[8] = (uint8_t)nwid; sin6->sin6_addr.s6_addr[9] = 0x99; sin6->sin6_addr.s6_addr[10] = 0x93; - sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32); - sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24); - sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16); - sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8); + sin6->sin6_addr.s6_addr[11] = (uint8_t)(zeroTierAddress >> 32U); + sin6->sin6_addr.s6_addr[12] = (uint8_t)(zeroTierAddress >> 24U); + sin6->sin6_addr.s6_addr[13] = (uint8_t)(zeroTierAddress >> 16U); + sin6->sin6_addr.s6_addr[14] = (uint8_t)(zeroTierAddress >> 8U); sin6->sin6_addr.s6_addr[15] = (uint8_t)zeroTierAddress; sin6->sin6_port = Utils::hton((uint16_t)88); // /88 includes 0xfd + network ID, discriminating by device ID below that return r; @@ -427,19 +425,19 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid,uint64_t zeroTierAddress) InetAddress InetAddress::makeIpv66plane(uint64_t nwid,uint64_t zeroTierAddress) { - nwid ^= (nwid >> 32); + nwid ^= (nwid >> 32U); InetAddress r; - struct sockaddr_in6 *const sin6 = reinterpret_cast(&r); + sockaddr_in6 *const sin6 = reinterpret_cast(&r); sin6->sin6_family = AF_INET6; sin6->sin6_addr.s6_addr[0] = 0xfc; - sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24); - sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16); - sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8); + sin6->sin6_addr.s6_addr[1] = (uint8_t)(nwid >> 24U); + sin6->sin6_addr.s6_addr[2] = (uint8_t)(nwid >> 16U); + sin6->sin6_addr.s6_addr[3] = (uint8_t)(nwid >> 8U); sin6->sin6_addr.s6_addr[4] = (uint8_t)nwid; - sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32); - sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24); - sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16); - sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8); + sin6->sin6_addr.s6_addr[5] = (uint8_t)(zeroTierAddress >> 32U); + sin6->sin6_addr.s6_addr[6] = (uint8_t)(zeroTierAddress >> 24U); + sin6->sin6_addr.s6_addr[7] = (uint8_t)(zeroTierAddress >> 16U); + sin6->sin6_addr.s6_addr[8] = (uint8_t)(zeroTierAddress >> 8U); sin6->sin6_addr.s6_addr[9] = (uint8_t)zeroTierAddress; sin6->sin6_addr.s6_addr[15] = 0x01; sin6->sin6_port = Utils::hton((uint16_t)40); diff --git a/node/InetAddress.hpp b/node/InetAddress.hpp index 5ec3aef1b..a4dc7ebde 100644 --- a/node/InetAddress.hpp +++ b/node/InetAddress.hpp @@ -18,8 +18,9 @@ #include #include -#include "Constants.hpp" #include "../include/ZeroTierOne.h" + +#include "Constants.hpp" #include "Utils.hpp" #include "MAC.hpp" #include "Buffer.hpp" @@ -464,16 +465,16 @@ struct InetAddress : public sockaddr_storage unsigned long h = 0; switch(ss_family) { case AF_INET: - h = (Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) & 0xffffff00) >> 8; - h ^= (h >> 14); + h = (Utils::ntoh((uint32_t)reinterpret_cast(this)->sin_addr.s_addr) & 0xffffff00U) >> 8U; + h ^= (h >> 14U); break; case AF_INET6: { const uint8_t *ip = reinterpret_cast(reinterpret_cast(this)->sin6_addr.s6_addr); - h = ((unsigned long)ip[0]); h <<= 1; - h += ((unsigned long)ip[1]); h <<= 1; - h += ((unsigned long)ip[2]); h <<= 1; - h += ((unsigned long)ip[3]); h <<= 1; - h += ((unsigned long)ip[4]); h <<= 1; + h = ((unsigned long)ip[0]); h <<= 1U; + h += ((unsigned long)ip[1]); h <<= 1U; + h += ((unsigned long)ip[2]); h <<= 1U; + h += ((unsigned long)ip[3]); h <<= 1U; + h += ((unsigned long)ip[4]); h <<= 1U; h += ((unsigned long)ip[5]); } break; } @@ -483,30 +484,31 @@ struct InetAddress : public sockaddr_storage /** * @return True if address family is non-zero */ - ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); } + explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); } // Marshal interface /////////////////////////////////////////////////////// static ZT_ALWAYS_INLINE int marshalSizeMax() { return 19; } - inline int marshal(uint8_t restrict data[19]) const + inline int marshal(uint8_t data[19]) const { + unsigned int port; switch(ss_family) { case AF_INET: - const unsigned int port = Utils::ntoh((uint16_t)reinterpret_cast(this)->sin_port); + port = Utils::ntoh((uint16_t)reinterpret_cast(this)->sin_port); data[0] = 4; data[1] = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr))[0]; data[2] = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr))[1]; data[3] = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr))[2]; data[4] = reinterpret_cast(&(reinterpret_cast(this)->sin_addr.s_addr))[3]; - data[5] = (uint8_t)((port >> 8) & 0xff); - data[6] = (uint8_t)(port & 0xff); + data[5] = (uint8_t)(port >> 8U); + data[6] = (uint8_t)port; return 7; case AF_INET6: - const unsigned int port = Utils::ntoh((uint16_t)reinterpret_cast(this)->sin6_port); + port = Utils::ntoh((uint16_t)reinterpret_cast(this)->sin6_port); data[0] = 6; for(int i=0;i<16;++i) data[i+1] = reinterpret_cast(this)->sin6_addr.s6_addr[i]; - data[17] = (uint8_t)((port >> 8) & 0xff); - data[18] = (uint8_t)(port & 0xff); + data[17] = (uint8_t)(port >> 8U); + data[18] = (uint8_t)port; return 19; default: data[0] = 0; diff --git a/node/Locator.hpp b/node/Locator.hpp index 63c8061c8..e959bc0df 100644 --- a/node/Locator.hpp +++ b/node/Locator.hpp @@ -16,6 +16,7 @@ #include #include +#include #include "Constants.hpp" #include "Endpoint.hpp" @@ -35,7 +36,12 @@ namespace ZeroTier { class Locator { public: - ZT_ALWAYS_INLINE Locator() : _ts(0),_endpointCount(0),_signatureLength(0) {} + ZT_ALWAYS_INLINE Locator() { this->clear(); } + + /** + * Zero the Locator data structure + */ + ZT_ALWAYS_INLINE void clear() { memset(reinterpret_cast(this),0,sizeof(Locator)); } /** * @return Timestamp (a.k.a. revision number) set by Location signer @@ -43,31 +49,42 @@ public: ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; } /** - * Create and sign a Locator - * - * @param ts Timestamp - * @param id Identity (must include secret to allow signing) - * @param at Array of Endpoint objects specifying where this peer might be found - * @param endpointCount Number of endpoints (max: ZT_LOCATOR_MAX_ENDPOINTS) - * @return True if init and sign were successful + * @return True if locator is signed */ - inline bool create(const int64_t ts,const Identity &id,const Endpoint *restrict at,const unsigned int endpointCount) + ZT_ALWAYS_INLINE bool isSigned() const { return (_signatureLength > 0); } + + /** + * Add an endpoint to this locator if not already present + * + * @param ep Endpoint to add + * @return True if endpoint was added (or already present), false if locator is full + */ + inline bool add(const Endpoint &ep) { - if ((endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(!id.hasPrivate())) + if (_endpointCount >= ZT_LOCATOR_MAX_ENDPOINTS) + return false; + if (!std::binary_search(_at,_at + _endpointCount,ep)) { + _at[_endpointCount++] = ep; + std::sort(_at,_at + _endpointCount); + } + return true; + } + + /** + * Sign this locator + * + * @param id Identity that includes private key + * @return True if signature successful + */ + inline bool sign(const int64_t ts,const Identity &id) + { + uint8_t signData[ZT_LOCATOR_MARSHAL_SIZE_MAX]; + if (!id.hasPrivate()) return false; _ts = ts; - for(unsigned int i=0;i 0); } /** @@ -85,26 +102,19 @@ public: return id.verify(signData,signLen,_signature,_signatureLength); } - ZT_ALWAYS_INLINE operator bool() const { return (_ts != 0); } + explicit ZT_ALWAYS_INLINE operator bool() const { return (_ts != 0); } // Marshal interface /////////////////////////////////////////////////////// static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_LOCATOR_MARSHAL_SIZE_MAX; } - inline int marshal(uint8_t restrict data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const + inline int marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX],const bool excludeSignature = false) const { if ((_endpointCount > ZT_LOCATOR_MAX_ENDPOINTS)||(_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)) return -1; - data[0] = (uint8_t)((uint64_t)_ts >> 56); - data[1] = (uint8_t)((uint64_t)_ts >> 48); - data[2] = (uint8_t)((uint64_t)_ts >> 40); - data[3] = (uint8_t)((uint64_t)_ts >> 32); - data[4] = (uint8_t)((uint64_t)_ts >> 24); - data[5] = (uint8_t)((uint64_t)_ts >> 16); - data[6] = (uint8_t)((uint64_t)_ts >> 8); - data[7] = (uint8_t)((uint64_t)_ts); + Utils::putUInt64(data,(uint64_t)_ts); int p = 8; - data[p++] = (uint8_t)(_endpointCount >> 8); + data[p++] = (uint8_t)(_endpointCount >> 8U); data[p++] = (uint8_t)_endpointCount; for(unsigned int i=0;i<_endpointCount;++i) { int tmp = _at[i].marshal(data + p); @@ -114,10 +124,10 @@ public: } if (!excludeSignature) { - data[p++] = (uint8_t)(_signatureLength >> 8); + data[p++] = (uint8_t)(_signatureLength >> 8U); data[p++] = (uint8_t)_signatureLength; memcpy(data + p,_signature,_signatureLength); - p += _signatureLength; + p += (int)_signatureLength; } return p; @@ -127,21 +137,13 @@ public: if (len <= (8 + 48)) return -1; - uint64_t ts = ((uint64_t)data[0] << 56); - ts |= ((uint64_t)data[1] << 48); - ts |= ((uint64_t)data[2] << 40); - ts |= ((uint64_t)data[3] << 32); - ts |= ((uint64_t)data[4] << 24); - ts |= ((uint64_t)data[5] << 16); - ts |= ((uint64_t)data[6] << 8); - ts |= (uint64_t)data[7]; - _ts = (int64_t)ts; + _ts = (int64_t)Utils::readUInt64(data); int p = 8; if ((p + 2) > len) return -1; unsigned int ec = (int)data[p++]; - ec <<= 8; + ec <<= 8U; ec |= data[p++]; if (ec > ZT_LOCATOR_MAX_ENDPOINTS) return -1; @@ -156,7 +158,7 @@ public: if ((p + 2) > len) return -1; unsigned int sl = data[p++]; - sl <<= 8; + sl <<= 8U; sl |= data[p++]; if (sl > ZT_SIGNATURE_BUFFER_SIZE) return -1; diff --git a/node/Membership.hpp b/node/Membership.hpp index 5c92d5ea4..fd47f6dad 100644 --- a/node/Membership.hpp +++ b/node/Membership.hpp @@ -68,7 +68,7 @@ public: /** * @return Time we last pushed credentials to this member */ - inline int64_t lastPushedCredentials() const { return _lastPushedCredentials; } + ZT_ALWAYS_INLINE int64_t lastPushedCredentials() const { return _lastPushedCredentials; } /** * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true @@ -76,7 +76,7 @@ public: * @param now Current time * @return True if we should update multicasts */ - inline bool multicastLikeGate(const int64_t now) + ZT_ALWAYS_INLINE bool multicastLikeGate(const int64_t now) { if ((now - _lastUpdatedMulticast) >= ZT_MULTICAST_ANNOUNCE_PERIOD) { _lastUpdatedMulticast = now; @@ -91,7 +91,7 @@ public: * @param nconf Our network config * @return True if this peer is allowed on this network at all */ - inline bool isAllowedOnNetwork(const NetworkConfig &nconf) const + ZT_ALWAYS_INLINE bool isAllowedOnNetwork(const NetworkConfig &nconf) const { if (nconf.isPublic()) return true; // public network if (_com.timestamp() <= _comRevocationThreshold) return false; // COM has been revoked @@ -107,7 +107,7 @@ public: * @return True if this peer has a certificate of ownership for the given resource */ template - inline bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const + ZT_ALWAYS_INLINE bool peerOwnsAddress(const NetworkConfig &nconf,const T &r) const { if (_isUnspoofableAddress(nconf,r)) return true; @@ -128,7 +128,7 @@ public: * @param id Tag ID * @return Pointer to tag or NULL if not found */ - inline const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const + ZT_ALWAYS_INLINE const Tag *getTag(const NetworkConfig &nconf,const uint32_t id) const { const Tag *const t = _remoteTags.get(id); return (((t)&&(_isCredentialTimestampValid(nconf,*t))) ? t : (Tag *)0); @@ -146,7 +146,7 @@ public: * @param now Current time * @param nconf Current network configuration */ - void clean(const int64_t now,const NetworkConfig &nconf); + void clean(int64_t now,const NetworkConfig &nconf); /** * Generates a key for internal use in indexing credentials by type and credential ID @@ -156,29 +156,29 @@ public: /** * @return Bytes received so far */ - inline uint64_t receivedBytes() const { return _received; } + ZT_ALWAYS_INLINE uint64_t receivedBytes() const { return _received; } /** * @return Bytes sent so far */ - inline uint64_t sentBytes() const { return _sent; } + ZT_ALWAYS_INLINE uint64_t sentBytes() const { return _sent; } /** * @param bytes Bytes received */ - inline void logReceivedBytes(const unsigned int bytes) { _received = (uint64_t)bytes; } + ZT_ALWAYS_INLINE void logReceivedBytes(const unsigned int bytes) { _received = (uint64_t)bytes; } /** * @param bytes Bytes sent */ - inline void logSentBytes(const unsigned int bytes) { _sent = (uint64_t)bytes; } + ZT_ALWAYS_INLINE void logSentBytes(const unsigned int bytes) { _sent = (uint64_t)bytes; } private: // This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT // address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to // always return true for them. A certificate is not required for these. - inline bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const { return false; } - inline bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const + ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const MAC &m) const { return false; } + ZT_ALWAYS_INLINE bool _isUnspoofableAddress(const NetworkConfig &nconf,const InetAddress &ip) const { if ((ip.isV6())&&(nconf.ndpEmulation())) { const InetAddress sixpl(InetAddress::makeIpv66plane(nconf.networkId,nconf.issuedTo.toInt())); @@ -219,7 +219,7 @@ private: // This compares the remote credential's timestamp to the timestamp in our network config // plus or minus the permitted maximum timestamp delta. template - inline bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const + ZT_ALWAYS_INLINE bool _isCredentialTimestampValid(const NetworkConfig &nconf,const C &remoteCredential) const { const int64_t ts = remoteCredential.timestamp(); if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) { @@ -271,7 +271,7 @@ public: class CapabilityIterator { public: - inline CapabilityIterator(Membership &m,const NetworkConfig &nconf) : + ZT_ALWAYS_INLINE CapabilityIterator(Membership &m,const NetworkConfig &nconf) : _hti(m._remoteCaps), _k((uint32_t *)0), _c((Capability *)0), @@ -280,7 +280,7 @@ public: { } - inline Capability *next() + ZT_ALWAYS_INLINE Capability *next() { while (_hti.next(_k,_c)) { if (_m._isCredentialTimestampValid(_nconf,*_c)) diff --git a/node/Node.cpp b/node/Node.cpp index 577911f91..3651906a6 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -11,11 +11,11 @@ */ /****/ -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "Constants.hpp" #include "SharedPtr.hpp" @@ -40,10 +40,10 @@ namespace ZeroTier { /* Public Node interface (C++, exposed via CAPI bindings) */ /****************************************************************************/ -Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) : +Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now) : _RR(this), RR(&_RR), - _uPtr(uptr), + _uPtr(uPtr), _networks(8), _now(now), _lastPing(0), @@ -61,7 +61,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64 uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; char tmp[2048]; - int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,tmp,sizeof(tmp) - 1); + int n = stateObjectGet(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, tmp, sizeof(tmp) - 1); if (n > 0) { tmp[n] = (char)0; if (RR->identity.fromString(tmp)) { @@ -77,14 +77,14 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64 RR->identity.toString(false,RR->publicIdentityStr); RR->identity.toString(true,RR->secretIdentityStr); idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr,(unsigned int)strlen(RR->secretIdentityStr)); - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); + stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, RR->secretIdentityStr, (unsigned int)strlen(RR->secretIdentityStr)); + stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr)); } else { idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0; - n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1); + n = stateObjectGet(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, tmp, sizeof(tmp) - 1); if ((n > 0)&&(n < (int)sizeof(RR->publicIdentityStr))&&(n < (int)sizeof(tmp))) { - if (memcmp(tmp,RR->publicIdentityStr,n)) - stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr)); + if (memcmp(tmp,RR->publicIdentityStr,n) != 0) + stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr)); } } @@ -117,7 +117,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64 throw; } - postEvent(tptr,ZT_EVENT_UP); + postEvent(tPtr, ZT_EVENT_UP); } Node::~Node() @@ -130,7 +130,7 @@ Node::~Node() if (RR->topology) RR->topology->~Topology(); if (RR->sw) RR->sw->~Switch(); if (RR->t) RR->t->~Trace(); - ::free(RR->rtmem); + free(RR->rtmem); } ZT_ResultCode Node::processWirePacket( @@ -169,74 +169,42 @@ ZT_ResultCode Node::processVirtualNetworkFrame( } } -// This is passed as the argument to the DNS request handler and -// aggregates results. -struct _processBackgroundTasks_dnsResultAccumulator +// This function object is run past every peer every ZT_PEER_PING_PERIOD. +struct _processBackgroundTasks_ping_eachPeer { - _processBackgroundTasks_dnsResultAccumulator(const Str &n) : dnsName(n) {} - Str dnsName; - std::vector txtRecords; -}; - -static const ZT_DNSRecordType s_txtRecordType[1] = { ZT_DNS_RECORD_TXT }; - -struct _processBackgroundTasks_eachRootName -{ - ZT_Node_Callbacks *cb; - Node *n; - void *uPtr; - void *tPtr; - bool updateAll; - - inline bool operator()(const Str &dnsName,const Locator &loc) - { - if ((strchr(dnsName.c_str(),'.'))&&((updateAll)||(!loc))) { - _processBackgroundTasks_dnsResultAccumulator *dnsReq = new _processBackgroundTasks_dnsResultAccumulator(dnsName); - cb->dnsResolver(reinterpret_cast(n),uPtr,tPtr,s_txtRecordType,1,dnsName.c_str(),(uintptr_t)dnsReq); - } - return true; - } -}; - -struct _processBackgroundTasks_ping_eachRoot -{ - Hashtable< void *,bool > roots; - int64_t now; - void *tPtr; - bool online; - - inline bool operator()(const SharedPtr &peer,const std::vector &addrs) + ZT_ALWAYS_INLINE bool operator()(const SharedPtr &peer,const bool isRoot) { unsigned int v4SendCount = 0,v6SendCount = 0; peer->ping(tPtr,now,v4SendCount,v6SendCount); - for(std::vector::const_iterator a(addrs.begin());a!=addrs.end();++a) { - if ( ((a->isV4())&&(v4SendCount == 0)) || ((a->isV6())&&(v6SendCount == 0)) ) - peer->sendHELLO(tPtr,-1,*a,now); + + if (isRoot) { + if ((now - peer->lastReceive()) <= ZT_PEER_PING_PERIOD) + online = true; + + if (v4SendCount == 0) { + InetAddress try4; + parent->externalPathLookup(tPtr,peer->identity(),AF_INET,try4); + if (try4.ss_family == AF_INET) + peer->sendHELLO(tPtr,-1,try4,now); + } + + if (v6SendCount == 0) { + InetAddress try6; + parent->externalPathLookup(tPtr,peer->identity(),AF_INET6,try6); + if (try6.ss_family == AF_INET6) + peer->sendHELLO(tPtr,-1,try6,now); + } } - if (!online) - online = ((now - peer->lastReceive()) <= ((ZT_PEER_PING_PERIOD * 2) + 5000)); - roots.set((void *)peer.ptr(),true); + return true; } -}; - -struct _processBackgroundTasks_ping_eachPeer -{ int64_t now; + Node *parent; void *tPtr; - Hashtable< void *,bool > *roots; - - inline bool operator()(const SharedPtr &peer) - { - if (!roots->contains((void *)peer.ptr())) { - unsigned int v4SendCount = 0,v6SendCount = 0; - peer->ping(tPtr,now,v4SendCount,v6SendCount); - } - return true; - } + bool online; }; -ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline) +ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) { _now = now; Mutex::Lock bl(_backgroundTasksLock); @@ -252,41 +220,19 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) { _lastPing = now; try { - // Periodically refresh locators for dynamic roots from their DNS names. - if (_cb.dnsResolver) { - _processBackgroundTasks_eachRootName cr; - cr.cb = &_cb; - cr.n = this; - cr.uPtr = _uPtr; - cr.tPtr = tptr; - if ((now - _lastDynamicRootUpdate) >= ZT_DYNAMIC_ROOT_UPDATE_PERIOD) { - _lastDynamicRootUpdate = now; - cr.updateAll = true; - } else { - cr.updateAll = false; - } - RR->topology->eachRootName(cr); - } - - // Ping each root explicitly no matter what - _processBackgroundTasks_ping_eachRoot rf; - rf.now = now; - rf.tPtr = tptr; - rf.online = false; - RR->topology->eachRoot(rf); - - // Ping peers that are active and we want to keep alive _processBackgroundTasks_ping_eachPeer pf; pf.now = now; - pf.tPtr = tptr; - pf.roots = &rf.roots; - RR->topology->eachPeer(pf); + pf.parent = this; + pf.tPtr = tPtr; + pf.online = false; + RR->topology->eachPeerWithRoot<_processBackgroundTasks_ping_eachPeer &>(pf); - // Update online status based on whether we can reach a root - if (rf.online != _online) { - _online = rf.online; - postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + if (pf.online != _online) { + _online = pf.online; + postEvent(tPtr, _online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); } + + RR->topology->rankRoots(now); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -300,7 +246,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 uint64_t *nwid = (uint64_t *)0; SharedPtr *network = (SharedPtr *)0; while (i.next(nwid,network)) { - (*network)->doPeriodicTasks(tptr,now); + (*network)->doPeriodicTasks(tPtr, now); } } } @@ -332,7 +278,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 } try { - *nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min((unsigned long)ZT_MAX_TIMER_TASK_INTERVAL,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_MIN_TIMER_TASK_INTERVAL); + *nextBackgroundTaskDeadline = now + (int64_t)std::max(std::min((unsigned long)ZT_MAX_TIMER_TASK_INTERVAL,RR->sw->doTimerTasks(tPtr, now)), (unsigned long)ZT_MIN_TIMER_TASK_INTERVAL); } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -340,30 +286,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 return ZT_RESULT_OK; } -void Node::processDNSResult( - void *tptr, - uintptr_t dnsRequestID, - const char *name, - enum ZT_DNSRecordType recordType, - const void *result, - unsigned int resultLength, - int resultIsString) -{ - if (dnsRequestID) { - _processBackgroundTasks_dnsResultAccumulator *const acc = reinterpret_cast<_processBackgroundTasks_dnsResultAccumulator *>(dnsRequestID); - if (recordType == ZT_DNS_RECORD_TXT) { - if (result) - acc->txtRecords.emplace_back(reinterpret_cast(result)); - } else if (recordType == ZT_DNS_RECORD__END_OF_RESULTS) { - Locator loc; - if (loc.decodeTxtRecords(acc->dnsName,acc->txtRecords.begin(),acc->txtRecords.end())) { - RR->topology->setRoot(acc->dnsName,loc); - delete acc; - } - } - } -} - ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr) { Mutex::Lock _l(_networks_m); @@ -423,44 +345,25 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } -ZT_RootList *Node::listRoots(int64_t now) +ZT_ResultCode Node::addRoot(const char *identity) { - return RR->topology->apiRoots(now); -} - -enum ZT_ResultCode Node::setRoot(const char *name,const void *locator,unsigned int locatorSize) -{ - try { - Locator loc; - if ((locator)&&(locatorSize > 0)&&(locatorSize < 65535)) { - ScopedPtr< Buffer<65536> > locbuf(new Buffer<65536>()); - locbuf->append(locator,locatorSize); - loc.deserialize(*locbuf,0); - if (!loc.verify()) - return ZT_RESULT_ERROR_BAD_PARAMETER; - } - Str n; - if ((!name)||(strlen(name) == 0)) { - if (!loc) - return ZT_RESULT_ERROR_BAD_PARAMETER; /* no name and no locator */ - char tmp[16]; - loc.id().address().toString(tmp); - n = tmp; - } else { - n = name; - } - return RR->topology->setRoot(n,loc) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED; - } catch ( ... ) { + if (!identity) return ZT_RESULT_ERROR_BAD_PARAMETER; - } + Identity id; + if (!id.fromString(identity)) + return ZT_RESULT_ERROR_BAD_PARAMETER; + RR->topology->addRoot(id); + return ZT_RESULT_OK; } -enum ZT_ResultCode Node::removeRoot(const char *name) +ZT_ResultCode Node::removeRoot(const char *identity) { - try { - if (name) - RR->topology->removeRoot(Str(name)); - } catch ( ... ) {} + if (!identity) + return ZT_RESULT_ERROR_BAD_PARAMETER; + Identity id; + if (!id.fromString(identity)) + return ZT_RESULT_ERROR_BAD_PARAMETER; + RR->topology->removeRoot(id); return ZT_RESULT_OK; } @@ -631,33 +534,6 @@ void Node::setController(void *networkControllerInstance) /* Node methods used only within node/ */ /****************************************************************************/ -SharedPtr< const Locator > Node::locator() -{ - Mutex::Lock lck(_locator_m); - if (!_locator) { - Locator *l = new Locator(); - try { - RR->topology->eachRoot([l](const SharedPtr &p,const std::vector &phyAddr) -> bool { - l->add(p->identity()); - return true; - }); - { - Mutex::Lock lck2(_localInterfaceAddresses_m); - for(std::vector< ZT_InterfaceAddress >::const_iterator a(_localInterfaceAddresses.begin());a!=_localInterfaceAddresses.end();++a) { - if (a->permanent != 0) { - l->add(*reinterpret_cast(&(a->address))); - } - } - } - } catch ( ... ) { - delete l; - throw; - } - _locator.set(l); - } - return _locator; -} - bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress) { if (!Path::isAddressValidForPath(remoteAddress)) @@ -679,6 +555,13 @@ bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,cons return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),localSocket,reinterpret_cast(&remoteAddress)) != 0) : true); } +bool Node::externalPathLookup(void *tPtr,const Identity &id,int family,InetAddress &addr) +{ + char idStr[ZT_IDENTITY_STRING_BUFFER_LENGTH]; + id.toString(false,idStr); + return (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,id.address().toInt(),idStr,family,reinterpret_cast(&addr)) == ZT_RESULT_OK); +} + ZT_ResultCode Node::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig) { RR->topology->setPhysicalPathConfiguration(pathNetwork,pathConfig); @@ -870,21 +753,6 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64 } } -void ZT_Node_processDNSResult( - ZT_Node *node, - void *tptr, - uintptr_t dnsRequestID, - const char *name, - enum ZT_DNSRecordType recordType, - const void *result, - unsigned int resultLength, - int resultIsString) -{ - try { - reinterpret_cast(node)->processDNSResult(tptr,dnsRequestID,name,recordType,result,resultLength,resultIsString); - } catch ( ... ) {} -} - enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr) { try { @@ -929,19 +797,10 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint } } -ZT_RootList *ZT_Node_listRoots(ZT_Node *node,int64_t now) +enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,const char *identity) { try { - return reinterpret_cast(node)->listRoots(now); - } catch ( ... ) { - return nullptr; - } -} - -enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *locator,unsigned int locatorSize) -{ - try { - return reinterpret_cast(node)->setRoot(name,locator,locatorSize); + return reinterpret_cast(node)->addRoot(identity); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -949,10 +808,10 @@ enum ZT_ResultCode ZT_Node_setRoot(ZT_Node *node,const char *name,const void *lo } } -enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *name) +enum ZT_ResultCode ZT_Node_removeRoot(ZT_Node *node,const char *identity) { try { - return reinterpret_cast(node)->removeRoot(name); + return reinterpret_cast(node)->removeRoot(identity); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { diff --git a/node/Node.hpp b/node/Node.hpp index bf9696e38..faffabf8e 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -51,7 +51,7 @@ class Locator; class Node : public NetworkController::Sender { public: - Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now); + Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now); virtual ~Node(); // Get rid of alignment warnings on 32-bit Windows and possibly improve performance @@ -81,22 +81,13 @@ public: const void *frameData, unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline); - ZT_ResultCode processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline); - void processDNSResult( - void *tptr, - uintptr_t dnsRequestID, - const char *name, - enum ZT_DNSRecordType recordType, - const void *result, - unsigned int resultLength, - int resultIsString); + ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr); ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr); ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi); - ZT_RootList *listRoots(int64_t now); - enum ZT_ResultCode setRoot(const char *name,const void *locator,unsigned int locatorSize); - enum ZT_ResultCode removeRoot(const char *name); + ZT_ResultCode addRoot(const char *identity); + ZT_ResultCode removeRoot(const char *identity); uint64_t address() const; void status(ZT_NodeStatus *status) const; ZT_PeerList *peers() const; @@ -104,16 +95,15 @@ public: ZT_VirtualNetworkList *networks() const; void setNetworkUserPtr(uint64_t nwid,void *ptr); void freeQueryResult(void *qr); - int addLocalInterfaceAddress(const struct sockaddr_storage *addr); - void clearLocalInterfaceAddresses(); + void setInterfaceAddresses(const ZT_InterfaceAddress *addrs,unsigned int addrCount); int sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len); void setController(void *networkControllerInstance); // Internal functions ------------------------------------------------------ - inline int64_t now() const { return _now; } + ZT_ALWAYS_INLINE int64_t now() const { return _now; } - inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) + ZT_ALWAYS_INLINE bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0) { return (_cb.wirePacketSendFunction( reinterpret_cast(this), @@ -126,7 +116,7 @@ public: ttl) == 0); } - inline void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) + ZT_ALWAYS_INLINE void putFrame(void *tPtr,uint64_t nwid,void **nuptr,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { _cb.virtualNetworkFrameFunction( reinterpret_cast(this), @@ -142,7 +132,7 @@ public: len); } - inline SharedPtr network(uint64_t nwid) const + ZT_ALWAYS_INLINE SharedPtr network(uint64_t nwid) const { Mutex::Lock _l(_networks_m); const SharedPtr *n = _networks.get(nwid); @@ -151,43 +141,22 @@ public: return SharedPtr(); } - inline bool belongsToNetwork(uint64_t nwid) const - { - Mutex::Lock _l(_networks_m); - return _networks.contains(nwid); - } - - inline std::vector< SharedPtr > allNetworks() const - { - std::vector< SharedPtr > nw; - Mutex::Lock _l(_networks_m); - Hashtable< uint64_t,SharedPtr >::Iterator i(*const_cast< Hashtable< uint64_t,SharedPtr > * >(&_networks)); - uint64_t *k = (uint64_t *)0; - SharedPtr *v = (SharedPtr *)0; - while (i.next(k,v)) - nw.push_back(*v); - return nw; - } - - inline std::vector directPaths() const + ZT_ALWAYS_INLINE std::vector directPaths() const { Mutex::Lock _l(_localInterfaceAddresses_m); return _localInterfaceAddresses; } - void setInterfaceAddresses(const ZT_InterfaceAddress *addrs,unsigned int addrCount); - - SharedPtr< const Locator > locator(); - inline void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast(this),_uPtr,tPtr,ev,md); } - inline void configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,tPtr,nwid,nuptr,op,nc); } - inline bool online() const { return _online; } - inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,maxlen); } - inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } - inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } + ZT_ALWAYS_INLINE void postEvent(void *tPtr,ZT_Event ev,const void *md = (const void *)0) { _cb.eventCallback(reinterpret_cast(this),_uPtr,tPtr,ev,md); } + ZT_ALWAYS_INLINE void configureVirtualNetworkPort(void *tPtr,uint64_t nwid,void **nuptr,ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nc) { _cb.virtualNetworkConfigFunction(reinterpret_cast(this),_uPtr,tPtr,nwid,nuptr,op,nc); } + ZT_ALWAYS_INLINE bool online() const { return _online; } + ZT_ALWAYS_INLINE int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,maxlen); } + ZT_ALWAYS_INLINE void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,data,(int)len); } + ZT_ALWAYS_INLINE void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2]) { _cb.statePutFunction(reinterpret_cast(this),_uPtr,tPtr,type,id,(const void *)0,-1); } bool shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const int64_t localSocket,const InetAddress &remoteAddress); - inline bool externalPathLookup(void *tPtr,const Address &ztaddr,int family,InetAddress &addr) { return ( (_cb.pathLookupFunction) ? (_cb.pathLookupFunction(reinterpret_cast(this),_uPtr,tPtr,ztaddr.toInt(),family,reinterpret_cast(&addr)) != 0) : false ); } + bool externalPathLookup(void *tPtr,const Identity &id,int family,InetAddress &addr); ZT_ResultCode setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig); - inline const Identity &identity() const { return _RR.identity; } + ZT_ALWAYS_INLINE const Identity &identity() const { return _RR.identity; } /** * Register that we are expecting a reply to a packet ID @@ -198,9 +167,9 @@ public: * * @param packetId Packet ID to expect reply to */ - inline void expectReplyTo(const uint64_t packetId) + ZT_ALWAYS_INLINE void expectReplyTo(const uint64_t packetId) { - const unsigned long pid2 = (unsigned long)(packetId >> 32); + const unsigned long pid2 = (unsigned long)(packetId >> 32U); const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1); _expectingRepliesTo[bucket][_expectingRepliesToBucketPtr[bucket]++ & ZT_EXPECTING_REPLIES_BUCKET_MASK2] = (uint32_t)pid2; } @@ -215,7 +184,7 @@ public: * @param packetId Packet ID to check * @return True if we're expecting a reply */ - inline bool expectingReplyTo(const uint64_t packetId) const + ZT_ALWAYS_INLINE bool expectingReplyTo(const uint64_t packetId) const { const uint32_t pid2 = (uint32_t)(packetId >> 32); const unsigned long bucket = (unsigned long)(pid2 & ZT_EXPECTING_REPLIES_BUCKET_MASK1); @@ -233,7 +202,7 @@ public: * @param from Source address of packet * @return True if within rate limits */ - inline bool rateGateIdentityVerification(const int64_t now,const InetAddress &from) + ZT_ALWAYS_INLINE bool rateGateIdentityVerification(const int64_t now,const InetAddress &from) { unsigned long iph = from.rateGateHash(); if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) { @@ -247,9 +216,6 @@ public: virtual void ncSendRevocation(const Address &destination,const Revocation &rev); virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode); - inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; } - inline uint8_t getMultipathMode() { return _multipathMode; } - inline bool localControllerHasAuthorized(const int64_t now,const uint64_t nwid,const Address &addr) const { _localControllerAuthorizations_m.lock(); @@ -260,6 +226,9 @@ public: return false; } + inline void setMultipathMode(uint8_t mode) { _multipathMode = mode; } + inline uint8_t getMultipathMode() { return _multipathMode; } + private: RuntimeEnvironment _RR; RuntimeEnvironment *RR; @@ -281,10 +250,10 @@ private: struct _LocalControllerAuth { uint64_t nwid,address; - inline _LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {} - inline unsigned long hashCode() const { return (unsigned long)(nwid ^ address); } - inline bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); } - inline bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); } + ZT_ALWAYS_INLINE _LocalControllerAuth(const uint64_t nwid_,const Address &address_) : nwid(nwid_),address(address_.toInt()) {} + ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(nwid ^ address); } + ZT_ALWAYS_INLINE bool operator==(const _LocalControllerAuth &a) const { return ((a.nwid == nwid)&&(a.address == address)); } + ZT_ALWAYS_INLINE bool operator!=(const _LocalControllerAuth &a) const { return ((a.nwid != nwid)||(a.address != address)); } }; Hashtable< _LocalControllerAuth,int64_t > _localControllerAuthorizations; Hashtable< uint64_t,SharedPtr > _networks; @@ -293,7 +262,6 @@ private: Mutex _localControllerAuthorizations_m; Mutex _networks_m; - Mutex _locator_m; Mutex _localInterfaceAddresses_m; Mutex _backgroundTasksLock; diff --git a/node/Path.hpp b/node/Path.hpp index 3c7a97e16..d2fb10710 100644 --- a/node/Path.hpp +++ b/node/Path.hpp @@ -28,6 +28,7 @@ #include "Utils.hpp" #include "RingBuffer.hpp" #include "Packet.hpp" +#include "Mutex.hpp" /** * Maximum return value of preferenceRank() @@ -52,9 +53,9 @@ public: class HashKey { public: - inline HashKey() {} + ZT_ALWAYS_INLINE HashKey() {} - inline HashKey(const int64_t l,const InetAddress &r) + ZT_ALWAYS_INLINE HashKey(const int64_t l,const InetAddress &r) { if (r.ss_family == AF_INET) { _k[0] = (uint64_t)reinterpret_cast(&r)->sin_addr.s_addr; @@ -69,10 +70,10 @@ public: } } - inline unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); } + ZT_ALWAYS_INLINE unsigned long hashCode() const { return (unsigned long)(_k[0] + _k[1] + _k[2]); } - inline bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); } - inline bool operator!=(const HashKey &k) const { return (!(*this == k)); } + ZT_ALWAYS_INLINE bool operator==(const HashKey &k) const { return ( (_k[0] == k._k[0]) && (_k[1] == k._k[1]) && (_k[2] == k._k[2]) ); } + ZT_ALWAYS_INLINE bool operator!=(const HashKey &k) const { return (!(*this == k)); } private: uint64_t _k[3]; diff --git a/node/Peer.cpp b/node/Peer.cpp index c0085a3c6..e098b865b 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -691,12 +691,8 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA void Peer::ping(void *tPtr,int64_t now,unsigned int &v4SendCount,unsigned int &v6SendCount) { - v4SendCount = 0; - v6SendCount = 0; - Mutex::Lock _l(_paths_m); - // Emit traces regarding aggregate link status if (_canUseMultipath) { int alivePathCount = aggregateLinkPhysicalPathCount(); if ((now - _lastAggregateStatsReport) > ZT_PATH_AGGREGATE_STATS_REPORT_INTERVAL) { diff --git a/node/Peer.hpp b/node/Peer.hpp index 028f4787d..f2da84108 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -30,8 +30,6 @@ #include "Hashtable.hpp" #include "Mutex.hpp" -#define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2)) - namespace ZeroTier { /** @@ -45,7 +43,7 @@ private: inline Peer() {} // disabled to prevent bugs -- should not be constructed uninitialized public: - inline ~Peer() { Utils::burn(_key,sizeof(_key)); } + ZT_ALWAYS_INLINE ~Peer() { Utils::burn(_key,sizeof(_key)); } /** * Construct a new peer @@ -60,12 +58,12 @@ public: /** * @return This peer's ZT address (short for identity().address()) */ - inline const Address &address() const { return _id.address(); } + ZT_ALWAYS_INLINE const Address &address() const { return _id.address(); } /** * @return This peer's identity */ - inline const Identity &identity() const { return _id; } + ZT_ALWAYS_INLINE const Identity &identity() const { return _id; } /** * Log receipt of an authenticated packet @@ -85,13 +83,13 @@ public: void received( void *tPtr, const SharedPtr &path, - const unsigned int hops, - const uint64_t packetId, - const unsigned int payloadLength, - const Packet::Verb verb, - const uint64_t inRePacketId, - const Packet::Verb inReVerb, - const uint64_t networkId); + unsigned int hops, + uint64_t packetId, + unsigned int payloadLength, + Packet::Verb verb, + uint64_t inRePacketId, + Packet::Verb inReVerb, + uint64_t networkId); /** * Check whether we have an active path to this peer via the given address @@ -122,7 +120,7 @@ public: * @param force If true, send even if path is not alive * @return True if we actually sent something */ - inline bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force) + ZT_ALWAYS_INLINE bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force) { SharedPtr bp(getAppropriatePath(now,force)); if (bp) @@ -139,7 +137,7 @@ public: * @param verb Packet verb * @param now Current time */ - void recordOutgoingPacket(const SharedPtr &path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now); + void recordOutgoingPacket(const SharedPtr &path, uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now); /** * Record statistics on incoming packets @@ -150,7 +148,7 @@ public: * @param verb Packet verb * @param now Current time */ - void recordIncomingPacket(void *tPtr, const SharedPtr &path, const uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now); + void recordIncomingPacket(void *tPtr, const SharedPtr &path, uint64_t packetId, uint16_t payloadLength, const Packet::Verb verb, int64_t now); /** * Send an ACK to peer for the most recent packets received @@ -160,7 +158,7 @@ public: * @param atAddress Destination for the ACK packet * @param now Current time */ - void sendACK(void *tPtr, const SharedPtr &path, const int64_t localSocket,const InetAddress &atAddress,int64_t now); + void sendACK(void *tPtr, const SharedPtr &path, int64_t localSocket,const InetAddress &atAddress,int64_t now); /** * Send a QoS packet to peer so that it can evaluate the quality of this link @@ -170,7 +168,7 @@ public: * @param atAddress Destination for the QoS packet * @param now Current time */ - void sendQOS_MEASUREMENT(void *tPtr, const SharedPtr &path, const int64_t localSocket,const InetAddress &atAddress,int64_t now); + void sendQOS_MEASUREMENT(void *tPtr, const SharedPtr &path, int64_t localSocket,const InetAddress &atAddress,int64_t now); /** * Compute relative quality values and allocations for the components of the aggregate link @@ -217,7 +215,7 @@ public: /** * Send VERB_RENDEZVOUS to this and another peer via the best common IP scope and path */ - void introduce(void *const tPtr,const int64_t now,const SharedPtr &other) const; + void introduce(void *tPtr,int64_t now,const SharedPtr &other) const; /** * Send a HELLO to this peer at a specified physical address @@ -229,7 +227,7 @@ public: * @param atAddress Destination address * @param now Current time */ - void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now); + void sendHELLO(void *tPtr,int64_t localSocket,const InetAddress &atAddress,int64_t now); /** * Send pings to active paths @@ -276,17 +274,17 @@ public: /** * @return Time of last receive of anything, whether direct or relayed */ - inline int64_t lastReceive() const { return _lastReceive; } + ZT_ALWAYS_INLINE int64_t lastReceive() const { return _lastReceive; } /** * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT */ - inline bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } + ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } /** * @return Latency in milliseconds of best/aggregate path or 0xffff if unknown / no paths */ - inline unsigned int latency(const int64_t now) + ZT_ALWAYS_INLINE unsigned int latency(const int64_t now) { if (_canUseMultipath) { return (int)computeAggregateLinkMeanLatency(); @@ -298,32 +296,10 @@ public: } } - /** - * This computes a quality score for relays and root servers - * - * If we haven't heard anything from these in ZT_PEER_ACTIVITY_TIMEOUT, they - * receive the worst possible quality (max unsigned int). Otherwise the - * quality is a product of latency and the number of potential missed - * pings. This causes roots and relays to switch over a bit faster if they - * fail. - * - * @return Relay quality score computed from latency and other factors, lower is better - */ - inline unsigned int relayQuality(const int64_t now) - { - const uint64_t tsr = now - _lastReceive; - if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT) - return (~(unsigned int)0); - unsigned int l = latency(now); - if (!l) - l = 0xffff; - return (l * (((unsigned int)tsr / (ZT_PEER_PING_PERIOD + 1000)) + 1)); - } - /** * @return 256-bit secret symmetric encryption key */ - inline const unsigned char *key() const { return _key; } + ZT_ALWAYS_INLINE const unsigned char *key() const { return _key; } /** * Set the currently known remote version of this peer's client @@ -333,7 +309,7 @@ public: * @param vmin Minor version * @param vrev Revision */ - inline void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev) + ZT_ALWAYS_INLINE void setRemoteVersion(unsigned int vproto,unsigned int vmaj,unsigned int vmin,unsigned int vrev) { _vProto = (uint16_t)vproto; _vMajor = (uint16_t)vmaj; @@ -341,11 +317,11 @@ public: _vRevision = (uint16_t)vrev; } - inline unsigned int remoteVersionProtocol() const { return _vProto; } - inline unsigned int remoteVersionMajor() const { return _vMajor; } - inline unsigned int remoteVersionMinor() const { return _vMinor; } - inline unsigned int remoteVersionRevision() const { return _vRevision; } - inline bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); } + ZT_ALWAYS_INLINE unsigned int remoteVersionProtocol() const { return _vProto; } + ZT_ALWAYS_INLINE unsigned int remoteVersionMajor() const { return _vMajor; } + ZT_ALWAYS_INLINE unsigned int remoteVersionMinor() const { return _vMinor; } + ZT_ALWAYS_INLINE unsigned int remoteVersionRevision() const { return _vRevision; } + ZT_ALWAYS_INLINE bool remoteVersionKnown() const { return ((_vMajor > 0)||(_vMinor > 0)||(_vRevision > 0)); } /** * Periodically update known multipath activation constraints. This is done so that we know when and when diff --git a/node/Revocation.hpp b/node/Revocation.hpp index 211e6b814..0f4231698 100644 --- a/node/Revocation.hpp +++ b/node/Revocation.hpp @@ -45,9 +45,9 @@ class Revocation : public Credential friend class Credential; public: - static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; } + static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_REVOCATION; } - inline Revocation() : + ZT_ALWAYS_INLINE Revocation() : _id(0), _credentialId(0), _networkId(0), @@ -69,7 +69,7 @@ public: * @param tgt Target node whose credential(s) are being revoked * @param ct Credential type being revoked */ - 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) : + ZT_ALWAYS_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), _credentialId(cid), _networkId(nwid), @@ -82,16 +82,16 @@ public: { } - inline uint32_t id() const { return _id; } - inline uint32_t credentialId() const { return _credentialId; } - inline uint64_t networkId() const { return _networkId; } - inline int64_t threshold() const { return _threshold; } - inline const Address &target() const { return _target; } - inline const Address &signer() const { return _signedBy; } - inline Credential::Type type() const { return _type; } - inline const uint8_t *signature() const { return _signature; } - inline unsigned int signatureLength() const { return _signatureLength; } - inline bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); } + ZT_ALWAYS_INLINE uint32_t id() const { return _id; } + ZT_ALWAYS_INLINE uint32_t credentialId() const { return _credentialId; } + ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; } + ZT_ALWAYS_INLINE int64_t threshold() const { return _threshold; } + ZT_ALWAYS_INLINE const Address &target() const { return _target; } + ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; } + ZT_ALWAYS_INLINE Credential::Type type() const { return _type; } + ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; } + ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; } + ZT_ALWAYS_INLINE bool fastPropagate() const { return ((_flags & ZT_REVOCATION_FLAG_FAST_PROPAGATE) != 0); } /** * @param signer Signing identity, must have private key @@ -115,7 +115,7 @@ public: * @param RR Runtime environment to provide for peer lookup, etc. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } + ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } template inline void serialize(Buffer &b,const bool forSign = false) const diff --git a/node/SharedPtr.hpp b/node/SharedPtr.hpp index 2c83ec997..e719acf49 100644 --- a/node/SharedPtr.hpp +++ b/node/SharedPtr.hpp @@ -14,7 +14,6 @@ #ifndef ZT_SHAREDPTR_HPP #define ZT_SHAREDPTR_HPP -#include "Mutex.hpp" #include "AtomicCounter.hpp" namespace ZeroTier { diff --git a/node/Tag.hpp b/node/Tag.hpp index 45df513d0..9fd1a423b 100644 --- a/node/Tag.hpp +++ b/node/Tag.hpp @@ -52,9 +52,9 @@ class Tag : public Credential friend class Credential; public: - static inline Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; } + static ZT_ALWAYS_INLINE Credential::Type credentialType() { return Credential::CREDENTIAL_TYPE_TAG; } - inline Tag() : + ZT_ALWAYS_INLINE Tag() : _id(0), _value(0), _networkId(0), @@ -70,7 +70,7 @@ public: * @param id Tag ID * @param value Tag value */ - inline Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) : + ZT_ALWAYS_INLINE Tag(const uint64_t nwid,const int64_t ts,const Address &issuedTo,const uint32_t id,const uint32_t value) : _id(id), _value(value), _networkId(nwid), @@ -81,14 +81,14 @@ public: { } - inline uint32_t id() const { return _id; } - inline const uint32_t &value() const { return _value; } - inline uint64_t networkId() const { return _networkId; } - inline int64_t timestamp() const { return _ts; } - inline const Address &issuedTo() const { return _issuedTo; } - inline const Address &signer() const { return _signedBy; } - inline const uint8_t *signature() const { return _signature; } - inline unsigned int signatureLength() const { return _signatureLength; } + ZT_ALWAYS_INLINE uint32_t id() const { return _id; } + ZT_ALWAYS_INLINE const uint32_t &value() const { return _value; } + ZT_ALWAYS_INLINE uint64_t networkId() const { return _networkId; } + ZT_ALWAYS_INLINE int64_t timestamp() const { return _ts; } + ZT_ALWAYS_INLINE const Address &issuedTo() const { return _issuedTo; } + ZT_ALWAYS_INLINE const Address &signer() const { return _signedBy; } + ZT_ALWAYS_INLINE const uint8_t *signature() const { return _signature; } + ZT_ALWAYS_INLINE unsigned int signatureLength() const { return _signatureLength; } /** * Sign this tag @@ -114,7 +114,7 @@ public: * @param RR Runtime environment to allow identity lookup for signedBy * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - inline Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } + ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); } template inline void serialize(Buffer &b,const bool forSign = false) const @@ -172,23 +172,23 @@ public: } // Provides natural sort order by ID - inline bool operator<(const Tag &t) const { return (_id < t._id); } + ZT_ALWAYS_INLINE bool operator<(const Tag &t) const { return (_id < t._id); } - inline bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); } - inline bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); } + ZT_ALWAYS_INLINE bool operator==(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) == 0); } + ZT_ALWAYS_INLINE bool operator!=(const Tag &t) const { return (memcmp(this,&t,sizeof(Tag)) != 0); } // For searching sorted arrays or lists of Tags by ID struct IdComparePredicate { - inline bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); } - inline bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); } - inline bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); } - inline bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); } - inline bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); } - inline bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); } - inline bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); } - inline bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); } - inline bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); } + ZT_ALWAYS_INLINE bool operator()(const Tag &a,const Tag &b) const { return (a.id() < b.id()); } + ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const Tag &b) const { return (a < b.id()); } + ZT_ALWAYS_INLINE bool operator()(const Tag &a,const uint32_t b) const { return (a.id() < b); } + ZT_ALWAYS_INLINE bool operator()(const Tag *a,const Tag *b) const { return (a->id() < b->id()); } + ZT_ALWAYS_INLINE bool operator()(const Tag *a,const Tag &b) const { return (a->id() < b.id()); } + ZT_ALWAYS_INLINE bool operator()(const Tag &a,const Tag *b) const { return (a.id() < b->id()); } + ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const Tag *b) const { return (a < b->id()); } + ZT_ALWAYS_INLINE bool operator()(const Tag *a,const uint32_t b) const { return (a->id() < b); } + ZT_ALWAYS_INLINE bool operator()(const uint32_t a,const uint32_t b) const { return (a < b); } }; private: diff --git a/node/Topology.hpp b/node/Topology.hpp index 7ca29fefc..62ce38f46 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -55,8 +55,6 @@ public: { } - ZT_ALWAYS_INLINE ~Topology() {} - /** * Add a peer to database * @@ -173,6 +171,34 @@ public: } } + /** + * Apply a function or function object to all peers + * + * This locks the peer map during execution, so calls to get() etc. during + * eachPeer() will deadlock. + * + * @param f Function to apply + * @tparam F Function or function object type + */ + template + ZT_ALWAYS_INLINE void eachPeerWithRoot(F f) + { + Mutex::Lock l(_peers_l); + + std::vector rootPeerPtrs; + for(std::vector< SharedPtr >::iterator i(_rootPeers.begin());i!=_rootPeers.end();++i) + rootPeerPtrs.push_back((uintptr_t)i->ptr()); + std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end()); + + Hashtable< Address,SharedPtr >::Iterator i(_peers); + Address *a = (Address *)0; + SharedPtr *p = (SharedPtr *)0; + while (i.next(a,p)) { + if (!f(*((const SharedPtr *)p),std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)p->ptr()))) + break; + } + } + /** * Get the best relay to a given address, which may or may not be a root * @@ -346,14 +372,24 @@ public: return false; } + /** + * Sort roots in asecnding order of apparent latency + * + * @param now Current time + */ + ZT_ALWAYS_INLINE void rankRoots(const int64_t now) + { + Mutex::Lock l1(_peers_l); + std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now)); + } + /** * Do periodic tasks such as database cleanup */ - inline void doPeriodicTasks(const int64_t now) + ZT_ALWAYS_INLINE void doPeriodicTasks(const int64_t now) { { Mutex::Lock l1(_peers_l); - std::sort(_rootPeers.begin(),_rootPeers.end(),_RootSortComparisonOperator(now)); Hashtable< Address,SharedPtr >::Iterator i(_peers); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; diff --git a/node/Trace.cpp b/node/Trace.cpp index def920602..b6b0c2693 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -13,8 +13,8 @@ //#define ZT_TRACE -#include -#include +#include +#include #include "Trace.hpp" #include "RuntimeEnvironment.hpp" diff --git a/node/Utils.hpp b/node/Utils.hpp index 0e0c226cb..1336d6a37 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -372,6 +372,41 @@ template static ZT_ALWAYS_INLINE T ntoh(T n) { return n; } #endif +static ZT_ALWAYS_INLINE uint64_t readUInt64(const void *const p) +{ +#ifdef ZT_NO_TYPE_PUNNING + const uint8_t *const b = reinterpret_cast(p); + return ( + ((uint64_t)b[0] << 56) | + ((uint64_t)b[1] << 48) | + ((uint64_t)b[2] << 40) | + ((uint64_t)b[3] << 32) | + ((uint64_t)b[4] << 24) | + ((uint64_t)b[5] << 16) | + ((uint64_t)b[6] << 8) | + (uint64_t)b[7]); +#else + return ntoh(*reinterpret_cast(p)); +#endif +} + +static ZT_ALWAYS_INLINE void putUInt64(void *const p,const uint64_t i) +{ +#ifdef ZT_NO_TYPE_PUNNING + uint8_t *const b = reinterpret_cast(p); + p[0] = (uint8_t)(i << 56); + p[1] = (uint8_t)(i << 48); + p[2] = (uint8_t)(i << 40); + p[3] = (uint8_t)(i << 32); + p[4] = (uint8_t)(i << 24); + p[5] = (uint8_t)(i << 16); + p[6] = (uint8_t)(i << 8); + p[7] = (uint8_t)i; +#else + *reinterpret_cast(p) = Utils::hton(i); +#endif +} + } // namespace Utils } // namespace ZeroTier diff --git a/selftest.cpp b/selftest.cpp index d2862764a..1ee79ad96 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -11,10 +11,10 @@ */ /****/ -#include -#include -#include -#include +#include +#include +#include +#include #include #include