From e08fc8139794eec3174cb91101df86dc1494151f Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Sep 2019 10:33:59 -0700 Subject: [PATCH] More threading improvements in root, more DNS TXT and multicast work (in progress) --- {node => attic}/Root.hpp | 0 node/Locator.hpp | 76 ++++++++++++++++++++++++--- node/Node.cpp | 19 ++++--- node/Str.hpp | 43 ++++++++++++--- node/Topology.hpp | 110 +++++++++++++++++++++++++++++++-------- node/Utils.cpp | 43 +++++++++++++++ node/Utils.hpp | 5 ++ one.cpp | 5 +- root/root.cpp | 107 ++++++++++++++++++++----------------- selftest.cpp | 4 +- 10 files changed, 317 insertions(+), 95 deletions(-) rename {node => attic}/Root.hpp (100%) diff --git a/node/Root.hpp b/attic/Root.hpp similarity index 100% rename from node/Root.hpp rename to attic/Root.hpp diff --git a/node/Locator.hpp b/node/Locator.hpp index 4b61a90a9..dc21abe47 100644 --- a/node/Locator.hpp +++ b/node/Locator.hpp @@ -129,6 +129,67 @@ public: } } + /** + * Make a DNS name contiaining a public key that can sign DNS entries + * + * This generates the initial fields of a DNS name that contains an + * encoded public key. Users may append any domain suffix to this name. + * + * @return First field(s) of DNS name + */ + static inline Str makeSecureDnsName(const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) + { + uint8_t tmp[ZT_ECC384_PUBLIC_KEY_SIZE+2]; + memcpy(tmp,p384SigningKeyPublic,ZT_ECC384_PUBLIC_KEY_SIZE); + const uint16_t crc = Utils::crc16(tmp,ZT_ECC384_PUBLIC_KEY_SIZE); + tmp[ZT_ECC384_PUBLIC_KEY_SIZE-2] = (uint8_t)(crc >> 8); + tmp[ZT_ECC384_PUBLIC_KEY_SIZE-1] = (uint8_t)(crc); + Str name; + char b32[128]; + Utils::b32e(tmp,35,b32,sizeof(b32)); + name << b32; + Utils::b32e(tmp + 35,(ZT_ECC384_PUBLIC_KEY_SIZE+2) - 35,b32,sizeof(b32)); + name << '.'; + name << b32; + return name; + } + + /** + * @return True if a key was found and successfully decoded + */ + static inline bool decodeSecureDnsName(const char *name,uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) + { + uint8_t b32[128]; + unsigned int b32ptr = 0; + char tmp[1024]; + Utils::scopy(tmp,sizeof(tmp),name); + bool ok = false; + for(char *saveptr=(char *)0,*p=Utils::stok(tmp,".",&saveptr);p;p=Utils::stok((char *)0,".",&saveptr)) { + if (b32ptr >= sizeof(b32)) + break; + int s = Utils::b32d(p,b32 + b32ptr,sizeof(b32) - b32ptr); + if (s > 0) { + b32ptr += (unsigned int)s; + if (b32ptr > 2) { + const uint16_t crc = Utils::crc16(b32,b32ptr); + if ((b32[b32ptr-2] == (uint8_t)(crc >> 8))&&(b32[b32ptr-1] == (uint8_t)(crc & 0xff))) { + ok = true; + break; + } + } + } else break; + } + + if (ok) { + if (b32ptr == (ZT_ECC384_PUBLIC_KEY_SIZE + 2)) { + memcpy(p384SigningKeyPublic,b32,ZT_ECC384_PUBLIC_KEY_SIZE); + return true; + } + } + + return false; + } + /** * Make DNS TXT records for this locator * @@ -184,7 +245,7 @@ public: * now contains the contents of the supplied TXT records. */ template - inline bool decodeTxtRecords(I start,I end,const uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]) + inline bool decodeTxtRecords(const Str &dnsName,I start,I end) { uint8_t dec[256],s384[48]; try { @@ -204,12 +265,13 @@ public: for(std::vector::const_iterator i(txtRecords.begin());i!=txtRecords.end();++i) tmp->append(dec,Utils::b64d(i->c_str() + 2,dec,sizeof(dec))); - if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) { - return false; - } - SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE); - if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) { - return false; + uint8_t p384SigningKeyPublic[ZT_ECC384_PUBLIC_KEY_SIZE]; + if (decodeSecureDnsName(dnsName.c_str(),p384SigningKeyPublic)) { + if (tmp->size() <= ZT_ECC384_SIGNATURE_SIZE) + return false; + SHA384(s384,tmp->data(),tmp->size() - ZT_ECC384_SIGNATURE_SIZE); + if (!ECC384ECDSAVerify(p384SigningKeyPublic,s384,((const uint8_t *)tmp->data()) + (tmp->size() - ZT_ECC384_SIGNATURE_SIZE))) + return false; } deserialize(*tmp,0); diff --git a/node/Node.cpp b/node/Node.cpp index 4f0a6d2b6..0d102a71a 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -33,6 +33,7 @@ #include "Network.hpp" #include "Trace.hpp" #include "ScopedPtr.hpp" +#include "Locator.hpp" namespace ZeroTier { @@ -172,6 +173,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame( } else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } +#if 0 struct _processBackgroundTasks_ping_eachRoot { Hashtable< void *,bool > roots; @@ -179,7 +181,7 @@ struct _processBackgroundTasks_ping_eachRoot void *tPtr; bool online; - inline void operator()(const Root &root,const SharedPtr &peer) + ZT_ALWAYS_INLINE void operator()(const Root &root,const SharedPtr &peer) { unsigned int v4SendCount = 0,v6SendCount = 0; peer->ping(tPtr,now,v4SendCount,v6SendCount); @@ -204,6 +206,7 @@ struct _processBackgroundTasks_ping_eachRoot roots.set((void *)peer.ptr(),true); } }; +#endif struct _processBackgroundTasks_ping_eachPeer { @@ -211,7 +214,7 @@ struct _processBackgroundTasks_ping_eachPeer void *tPtr; Hashtable< void *,bool > *roots; - inline void operator()(const SharedPtr &peer) + ZT_ALWAYS_INLINE void operator()(const SharedPtr &peer) { if (!roots->contains((void *)peer.ptr())) { unsigned int v4SendCount = 0,v6SendCount = 0; @@ -234,22 +237,24 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64 if ((now - _lastPing) >= ZT_PEER_PING_PERIOD) { _lastPing = now; try { +#if 0 _processBackgroundTasks_ping_eachRoot rf; rf.now = now; rf.tPtr = tptr; rf.online = false; RR->topology->eachRoot(rf); +#endif _processBackgroundTasks_ping_eachPeer pf; pf.now = now; pf.tPtr = tptr; - pf.roots = &rf.roots; + //pf.roots = &rf.roots; RR->topology->eachPeer(pf); - if (rf.online != _online) { - _online = rf.online; - postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); - } + //if (rf.online != _online) { + // _online = rf.online; + // postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + //} } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } diff --git a/node/Str.hpp b/node/Str.hpp index 9c8d46eb1..35a36aacd 100644 --- a/node/Str.hpp +++ b/node/Str.hpp @@ -151,14 +151,35 @@ public: return ((*this) << a.toString(tmp)); } + ZT_ALWAYS_INLINE Str &append(const char *s,const unsigned int max) + { + if (likely(s != (const char *)0)) { + unsigned long l = _l; + unsigned int c = 0; + while (*s) { + if (c++ >= max) break; + if (unlikely(l >= ZT_STR_CAPACITY)) { + _s[ZT_STR_CAPACITY] = 0; + _l = ZT_STR_CAPACITY; + throw ZT_EXCEPTION_OUT_OF_BOUNDS; + } + _s[l++] = *s; + ++s; + } + _s[l] = 0; + _l = (uint8_t)l; + } + return *this; + } + ZT_ALWAYS_INLINE operator bool() const { return (_l != 0); } - ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(strcmp(_s,s._s) == 0)); } - ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(strcmp(_s,s._s) != 0)); } - ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ((_l < s._l)&&(strcmp(_s,s._s) < 0)); } - ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return ((_l > s._l)&&(strcmp(_s,s._s) > 0)); } - ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return ((_l <= s._l)&&(strcmp(_s,s._s) <= 0)); } - ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return ((_l >= s._l)&&(strcmp(_s,s._s) >= 0)); } + ZT_ALWAYS_INLINE bool operator==(const Str &s) const { return ((_l == s._l)&&(memcmp(_s,s._s,_l) == 0)); } + ZT_ALWAYS_INLINE bool operator!=(const Str &s) const { return ((_l != s._l)||(memcmp(_s,s._s,_l) != 0)); } + ZT_ALWAYS_INLINE bool operator<(const Str &s) const { return ( (_l < s._l) ? true : ((_l == s._l) ? (memcmp(_s,s._s,_l) < 0) : false) ); } + ZT_ALWAYS_INLINE bool operator>(const Str &s) const { return (s < *this); } + ZT_ALWAYS_INLINE bool operator<=(const Str &s) const { return !(s < *this); } + ZT_ALWAYS_INLINE bool operator>=(const Str &s) const { return !(*this < s); } ZT_ALWAYS_INLINE bool operator==(const char *s) const { return (strcmp(_s,s) == 0); } ZT_ALWAYS_INLINE bool operator!=(const char *s) const { return (strcmp(_s,s) != 0); } @@ -167,6 +188,16 @@ public: ZT_ALWAYS_INLINE bool operator<=(const char *s) const { return (strcmp(_s,s) <= 0); } ZT_ALWAYS_INLINE bool operator>=(const char *s) const { return (strcmp(_s,s) >= 0); } + ZT_ALWAYS_INLINE unsigned long hashCode() const + { + const char *p = _s; + unsigned long h = 0; + char c; + while ((c = *(p++))) + h = (31 * h) + (unsigned long)c; + return h; + } + private: uint8_t _l; char _s[ZT_STR_CAPACITY+1]; diff --git a/node/Topology.hpp b/node/Topology.hpp index 66e6e40f8..6cc91f20d 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "Constants.hpp" #include "../include/ZeroTierOne.h" @@ -32,8 +33,9 @@ #include "Mutex.hpp" #include "InetAddress.hpp" #include "Hashtable.hpp" -#include "Root.hpp" +#include "Locator.hpp" #include "SharedPtr.hpp" +#include "ScopedPtr.hpp" namespace ZeroTier { @@ -65,7 +67,7 @@ public: { SharedPtr np; { - Mutex::Lock _l(_peers_m); + Mutex::Lock _l(_peers_l); SharedPtr &hp = _peers[peer->address()]; if (!hp) hp = peer; @@ -86,11 +88,12 @@ public: if (zta == _myIdentity.address()) return SharedPtr(); - Mutex::Lock l1(_peers_m); + Mutex::Lock l1(_peers_l); const SharedPtr *const ap = _peers.get(zta); if (ap) return *ap; +#if 0 Mutex::Lock l2(_roots_m); for(std::vector::const_iterator r(_roots.begin());r!=_roots.end();++r) { if (r->address() == zta) { @@ -101,6 +104,7 @@ public: } catch ( ... ) {} } } +#endif return SharedPtr(); } @@ -115,7 +119,7 @@ public: if (zta == _myIdentity.address()) { return _myIdentity; } else { - Mutex::Lock _l(_peers_m); + Mutex::Lock _l(_peers_l); const SharedPtr *const ap = _peers.get(zta); if (ap) return (*ap)->identity(); @@ -132,7 +136,7 @@ public: */ ZT_ALWAYS_INLINE SharedPtr getPath(const int64_t l,const InetAddress &r) { - Mutex::Lock _l(_paths_m); + Mutex::Lock _l(_paths_l); SharedPtr &p = _paths[Path::HashKey(l,r)]; if (!p) p.set(new Path(l,r)); @@ -145,11 +149,13 @@ public: */ ZT_ALWAYS_INLINE bool isRoot(const Identity &id) const { +#if 0 Mutex::Lock l(_roots_m); for(std::vector::const_iterator r(_roots.begin());r!=_roots.end();++r) { if (r->is(id)) return true; } +#endif return false; } @@ -159,7 +165,7 @@ public: ZT_ALWAYS_INLINE void doPeriodicTasks(int64_t now) { { - Mutex::Lock _l1(_peers_m); + Mutex::Lock _l1(_peers_l); Hashtable< Address,SharedPtr >::Iterator i(_peers); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; @@ -170,7 +176,7 @@ public: } } { - Mutex::Lock _l(_paths_m); + Mutex::Lock _l(_paths_l); Hashtable< Path::HashKey,SharedPtr >::Iterator i(_paths); Path::HashKey *k = (Path::HashKey *)0; SharedPtr *p = (SharedPtr *)0; @@ -188,7 +194,7 @@ public: ZT_ALWAYS_INLINE unsigned long countActive(int64_t now) const { unsigned long cnt = 0; - Mutex::Lock _l(_peers_m); + Mutex::Lock _l(_peers_l); Hashtable< Address,SharedPtr >::Iterator i(const_cast(this)->_peers); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; @@ -212,7 +218,7 @@ public: template ZT_ALWAYS_INLINE void eachPeer(F f) { - Mutex::Lock l(_peers_m); + Mutex::Lock l(_peers_l); Hashtable< Address,SharedPtr >::Iterator i(_peers); Address *a = (Address *)0; SharedPtr *p = (SharedPtr *)0; @@ -221,6 +227,7 @@ public: } } +#if 0 /** * Apply a function or function object to all roots * @@ -237,7 +244,7 @@ public: SharedPtr rp; for(std::vector::const_iterator i(_roots.begin());i!=_roots.end();++i) { { - Mutex::Lock l2(_peers_m); + Mutex::Lock l2(_peers_l); const SharedPtr *const ap = _peers.get(i->address()); if (ap) { rp = *ap; @@ -256,7 +263,7 @@ public: * @param now Current time * @return Best/fastest currently connected root or NULL if none */ - ZT_ALWAYS_INLINE SharedPtr root(const int64_t now) + inline SharedPtr root(const int64_t now) { Mutex::Lock l(_bestRoot_m); if ((!_bestRoot)||((now - _lastRankedBestRoot) >= ZT_FIND_BEST_ROOT_PERIOD)) { @@ -266,7 +273,7 @@ public: long bestQuality = 2147483647; for(std::vector::const_iterator i(_roots.begin());i!=_roots.end();++i) { { - Mutex::Lock l2(_peers_m); + Mutex::Lock l2(_peers_l); const SharedPtr *const ap = _peers.get(i->address()); if (ap) { rp = *ap; @@ -287,6 +294,54 @@ public: } return _bestRoot; } +#endif + + ZT_ALWAYS_INLINE SharedPtr root(const int64_t now) + { + return SharedPtr(); + } + + /** + * @return Names of dynamic roots currently known by the system + */ + ZT_ALWAYS_INLINE std::vector dynamicRootNames() const + { + Mutex::Lock l(_dynamicRoots_l); + return _dynamicRoots.keys(); + } + + /** + * Set or update a static root entry + * + * @param id Static root's identity + * @param addrs Static root's IP address(es) + */ + ZT_ALWAYS_INLINE void setStaticRoot(const Identity &id,const std::vector &addrs) + { + Mutex::Lock l(_staticRoots_l); + _staticRoots[id] = addrs; + } + + /** + * Set or update dynamic root if new locator is newer and valid + * + * This checks internal validity of the new locator including its internal self-signature. + * It does not check any DNS signatures. + * + * @param dnsName DNS name used to retrive root + * @param latestLocator Latest locator + * @return True if latest locator is internally valid and newer + */ + ZT_ALWAYS_INLINE bool setDynamicRoot(const Str &dnsName,const Locator &latestLocator) + { + Mutex::Lock l(_dynamicRoots_l); + Locator &ll = _dynamicRoots[dnsName]; + if (ll.timestamp() < latestLocator.timestamp()) { + ll = latestLocator; + return true; + } + return false; + } /** * Get the best relay to a given address, which may or may not be a root @@ -298,15 +353,15 @@ public: ZT_ALWAYS_INLINE SharedPtr findRelayTo(const int64_t now,const Address &toAddr) { // TODO: in the future this will check 'mesh-like' relays and if enabled consult LF for other roots (for if this is a root) - return root(now); + //return root(now); } /** * @param allPeers vector to fill with all current peers */ - ZT_ALWAYS_INLINE void getAllPeers(std::vector< SharedPtr > &allPeers) const + inline void getAllPeers(std::vector< SharedPtr > &allPeers) const { - Mutex::Lock l(_peers_m); + Mutex::Lock l(_peers_l); allPeers.clear(); allPeers.reserve(_peers.size()); Hashtable< Address,SharedPtr >::Iterator i(*(const_cast > *>(&_peers))); @@ -385,7 +440,7 @@ public: /** * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration) */ - ZT_ALWAYS_INLINE void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) + inline void setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) { if (!pathNetwork) { _numConfiguredPhysicalPaths = 0; @@ -422,17 +477,26 @@ public: private: const RuntimeEnvironment *const RR; const Identity _myIdentity; + std::pair _physicalPathConfig[ZT_MAX_CONFIGURABLE_PATHS]; unsigned int _numConfiguredPhysicalPaths; - std::vector _roots; - SharedPtr _bestRoot; - int64_t _lastRankedBestRoot; + Hashtable< Address,SharedPtr > _peers; Hashtable< Path::HashKey,SharedPtr > _paths; - Mutex _roots_m; - Mutex _bestRoot_m; - Mutex _peers_m; - Mutex _paths_m; + + Hashtable< Identity,std::vector > _staticRoots; + Hashtable< Str,Locator > _dynamicRoots; + + //std::vector _roots; + //SharedPtr _bestRoot; + //int64_t _lastRankedBestRoot; + //Mutex _roots_m; + //Mutex _bestRoot_m; + + Mutex _peers_l; + Mutex _paths_l; + Mutex _staticRoots_l; + Mutex _dynamicRoots_l; }; } // namespace ZeroTier diff --git a/node/Utils.cpp b/node/Utils.cpp index e5c506c9d..b1584c6a9 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -95,6 +95,49 @@ char *Utils::decimal(unsigned long n,char s[24]) return s; } +unsigned short Utils::crc16(const void *buf,unsigned int len) +{ + static const uint16_t crc16tab[256]= { + 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, + 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, + 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, + 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, + 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, + 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, + 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, + 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, + 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, + 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, + 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, + 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, + 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, + 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, + 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, + 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, + 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, + 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, + 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, + 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, + 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, + 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, + 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, + 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, + 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, + 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, + 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, + 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, + 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, + 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, + 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, + 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 + }; + uint16_t crc = 0; + const uint8_t *p = (const uint8_t *)buf; + for(unsigned int i=0;i> 8) ^ *(p++)) & 0x00ff]; + return crc; +} + unsigned int Utils::unhex(const char *h,void *buf,unsigned int buflen) { unsigned int l = 0; diff --git a/node/Utils.hpp b/node/Utils.hpp index 047a933a7..688104015 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -68,6 +68,11 @@ public: */ static char *decimal(unsigned long n,char s[24]); + /** + * Compute CRC16-CCITT + */ + static uint16_t crc16(const void *buf,unsigned int len); + /** * Convert an unsigned integer into hex * diff --git a/one.cpp b/one.cpp index 65fa101e7..2a3be098e 100644 --- a/one.cpp +++ b/one.cpp @@ -94,10 +94,9 @@ static OneService *volatile zt1Service = (OneService *)0; static void cliPrintHelp(const char *pn,FILE *out) { fprintf(out, - "%s version %d.%d.%d build %d (platform %d arch %d)" ZT_EOL_S, + "%s version %d.%d.%d build %d" ZT_EOL_S, PROGRAM_NAME, - ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD, - ZT_BUILD_PLATFORM, ZT_BUILD_ARCHITECTURE); + ZEROTIER_ONE_VERSION_MAJOR, ZEROTIER_ONE_VERSION_MINOR, ZEROTIER_ONE_VERSION_REVISION, ZEROTIER_ONE_VERSION_BUILD); fprintf(out, COPYRIGHT_NOTICE ZT_EOL_S LICENSE_GRANT ZT_EOL_S); diff --git a/root/root.cpp b/root/root.cpp index daf207d8b..789c38f54 100644 --- a/root/root.cpp +++ b/root/root.cpp @@ -107,8 +107,10 @@ using json = nlohmann::json; #ifdef MSG_DONTWAIT #define SENDTO_FLAGS MSG_DONTWAIT +#define RECVFROM_FLAGS 0 #else #define SENDTO_FLAGS 0 +#define RECVFROM_FLAGS 0 #endif ////////////////////////////////////////////////////////////////////////////// @@ -911,7 +913,7 @@ int main(int argc,char **argv) memset(&in6,0,sizeof(in6)); for(;;) { socklen_t sl = sizeof(in6); - const int pl = (int)recvfrom(s6,pkt.unsafeData(),pkt.capacity(),0,(struct sockaddr *)&in6,&sl); + const int pl = (int)recvfrom(s6,pkt.unsafeData(),pkt.capacity(),RECVFROM_FLAGS,(struct sockaddr *)&in6,&sl); if (pl > 0) { if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) { try { @@ -940,7 +942,7 @@ int main(int argc,char **argv) memset(&in4,0,sizeof(in4)); for(;;) { socklen_t sl = sizeof(in4); - const int pl = (int)recvfrom(s4,pkt.unsafeData(),pkt.capacity(),0,(struct sockaddr *)&in4,&sl); + const int pl = (int)recvfrom(s4,pkt.unsafeData(),pkt.capacity(),RECVFROM_FLAGS,(struct sockaddr *)&in4,&sl); if (pl > 0) { if (pl >= ZT_PROTO_MIN_FRAGMENT_LENGTH) { try { @@ -986,43 +988,43 @@ int main(int argc,char **argv) o << '['; try { bool first = true; - std::lock_guard l(s_peersByIdentity_l); - for(auto p=s_peersByIdentity.begin();p!=s_peersByIdentity.end();++p) { + std::lock_guard l(s_peers_l); + for(auto p=s_peers.begin();p!=s_peers.end();++p) { if (first) first = false; else o << ','; o << - "{\"address\":\"" << p->first.address().toString(tmp) << "\"" + "{\"address\":\"" << (*p)->id.address().toString(tmp) << "\"" ",\"latency\":-1" ",\"paths\":["; - if (p->second->ip4) { + if ((*p)->ip4) { o << "{\"active\":true" - ",\"address\":\"" << p->second->ip4.toIpString(tmp) << "\\/" << p->second->ip4.port() << "\"" + ",\"address\":\"" << (*p)->ip4.toIpString(tmp) << "\\/" << (*p)->ip4.port() << "\"" ",\"expired\":false" - ",\"lastReceive\":" << p->second->lastReceive << - ",\"lastSend\":" << p->second->lastSend << + ",\"lastReceive\":" << (*p)->lastReceive << + ",\"lastSend\":" << (*p)->lastSend << ",\"preferred\":true" ",\"trustedPathId\":0}"; } - if (p->second->ip6) { - if (p->second->ip4) + if ((*p)->ip6) { + if ((*p)->ip4) o << ','; o << "{\"active\":true" - ",\"address\":\"" << p->second->ip6.toIpString(tmp) << "\\/" << p->second->ip6.port() << "\"" + ",\"address\":\"" << (*p)->ip6.toIpString(tmp) << "\\/" << (*p)->ip6.port() << "\"" ",\"expired\":false" - ",\"lastReceive\":" << p->second->lastReceive << - ",\"lastSend\":" << p->second->lastSend << - ",\"preferred\":" << ((p->second->ip4) ? "false" : "true") << + ",\"lastReceive\":" << (*p)->lastReceive << + ",\"lastSend\":" << (*p)->lastSend << + ",\"preferred\":" << (((*p)->ip4) ? "false" : "true") << ",\"trustedPathId\":0}"; } o << "]" ",\"role\":\"LEAF\"" - ",\"version\":\"" << p->second->vMajor << '.' << p->second->vMinor << '.' << p->second->vRev << "\"" - ",\"versionMajor\":" << p->second->vMajor << - ",\"versionMinor\":" << p->second->vMinor << - ",\"versionRev\":" << p->second->vRev << "}"; + ",\"version\":\"" << (*p)->vMajor << '.' << (*p)->vMinor << '.' << (*p)->vRev << "\"" + ",\"versionMajor\":" << (*p)->vMajor << + ",\"versionMinor\":" << (*p)->vMinor << + ",\"versionRev\":" << (*p)->vRev << "}"; } } catch ( ... ) {} o << ']'; @@ -1146,27 +1148,34 @@ int main(int argc,char **argv) } // Remove expired peers - { - std::lock_guard pbi_l(s_peers_l); - for(auto p=s_peers.begin();p!=s_peers.end();) { - if ((now - (*p)->lastReceive) > ZT_PEER_ACTIVITY_TIMEOUT) { - { - std::lock_guard pbi_l(s_peersByIdentity_l); - s_peersByIdentity.erase((*p)->id); - } - { - std::lock_guard pbv_l(s_peersByVirtAddr_l); - auto pbv = s_peersByVirtAddr.find((*p)->id.address()); - if (pbv != s_peersByVirtAddr.end()) { - pbv->second.erase(*p); - if (pbv->second.empty()) - s_peersByVirtAddr.erase(pbv); - } - } - s_peers.erase(p++); - } else ++p; + try { + std::vector< SharedPtr > toRemove; + toRemove.reserve(1024); + { + std::lock_guard pbi_l(s_peers_l); + for(auto p=s_peers.begin();p!=s_peers.end();) { + if ((now - (*p)->lastReceive) > ZT_PEER_ACTIVITY_TIMEOUT) { + toRemove.emplace_back(*p); + s_peers.erase(p++); + } else ++p; + } } - } + for(auto p=toRemove.begin();p!=toRemove.end();++p) { + { + std::lock_guard pbi_l(s_peersByIdentity_l); + s_peersByIdentity.erase((*p)->id); + } + { + std::lock_guard pbv_l(s_peersByVirtAddr_l); + auto pbv = s_peersByVirtAddr.find((*p)->id.address()); + if (pbv != s_peersByVirtAddr.end()) { + pbv->second.erase(*p); + if (pbv->second.empty()) + s_peersByVirtAddr.erase(pbv); + } + } + } + } catch ( ... ) {} // Remove old rendezvous entries { @@ -1212,17 +1221,16 @@ int main(int argc,char **argv) if (pf) { std::vector< SharedPtr > sp; { - std::lock_guard pbi_l(s_peersByIdentity_l); - sp.reserve(s_peersByIdentity.size()); - for(auto p=s_peersByIdentity.begin();p!=s_peersByIdentity.end();++p) { - sp.push_back(p->second); + std::lock_guard pbi_l(s_peers_l); + sp.reserve(s_peers.size()); + for(auto p=s_peers.begin();p!=s_peers.end();++p) { + sp.emplace_back(*p); } } std::sort(sp.begin(),sp.end(),[](const SharedPtr &a,const SharedPtr &b) { return (a->id < b->id); }); fprintf(pf,"Address %21s %45s %10s %6s %10s" ZT_EOL_S,"IPv4","IPv6","Age(sec)","Vers","Fwd(KiB/s)"); { - std::lock_guard lf_l(s_lastForwardedTo_l); char ip4[128],ip6[128],ver[128]; for(auto p=sp.begin();p!=sp.end();++p) { if ((*p)->ip4) { @@ -1239,9 +1247,11 @@ int main(int argc,char **argv) } OSUtils::ztsnprintf(ver,sizeof(ver),"%d.%d.%d",(*p)->vMajor,(*p)->vMinor,(*p)->vRev); double forwardingSpeed = 0.0; + s_lastForwardedTo_l.lock(); auto lft = s_lastForwardedTo.find((*p)->id.address()); if (lft != s_lastForwardedTo.end()) forwardingSpeed = lft->second.bps.perSecond(now) / 1024.0; + s_lastForwardedTo_l.unlock(); fprintf(pf,"%.10llx %21s %45s %10.4f %6s %10.4f" ZT_EOL_S, (unsigned long long)(*p)->id.address().toInt(), ip4, @@ -1265,11 +1275,12 @@ int main(int argc,char **argv) if (sf) { fprintf(sf,"Uptime (seconds) : %ld" ZT_EOL_S,(long)((now - s_startTime) / 1000)); s_peersByIdentity_l.lock(); - fprintf(sf,"Peers : %llu" ZT_EOL_S,(unsigned long long)s_peersByIdentity.size()); - s_peersByVirtAddr_l.lock(); - fprintf(sf,"Virtual Address Collisions : %llu" ZT_EOL_S,(unsigned long long)(s_peersByIdentity.size() - s_peersByVirtAddr.size())); - s_peersByVirtAddr_l.unlock(); + auto peersByIdentitySize = s_peersByIdentity.size(); s_peersByIdentity_l.unlock(); + fprintf(sf,"Peers : %llu" ZT_EOL_S,(unsigned long long)peersByIdentitySize); + s_peersByVirtAddr_l.lock(); + fprintf(sf,"Virtual Address Collisions : %llu" ZT_EOL_S,(unsigned long long)(peersByIdentitySize - s_peersByVirtAddr.size())); + s_peersByVirtAddr_l.unlock(); s_rendezvousTracking_l.lock(); uint64_t unsuccessfulp2p = 0; for(auto lr=s_rendezvousTracking.begin();lr!=s_rendezvousTracking.end();++lr) { diff --git a/selftest.cpp b/selftest.cpp index 9149505e7..ee7e1609a 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -620,6 +620,7 @@ static int testIdentity() } } + /* try { std::cout << "[identity] Testing Locator and DNS TXT encoding... "; std::cout.flush(); uint8_t dnsPub[ZT_ECC384_PUBLIC_KEY_SIZE],dnsPriv[ZT_ECC384_PRIVATE_KEY_SIZE]; @@ -633,7 +634,7 @@ static int testIdentity() l->sign(*ti); auto tr = l->makeTxtRecords(dnsPub,dnsPriv); std::unique_ptr l2(new Locator()); - if (!l2->decodeTxtRecords(tr.begin(),tr.end(),dnsPub)) { + if (!l2->decodeTxtRecords(tr.begin(),tr.end())) { std::cout << "FAILED (decode TXT records returned false)" ZT_EOL_S; return -1; } @@ -642,6 +643,7 @@ static int testIdentity() std::cout << "FAILED (threw integer exception " << e << ")" ZT_EOL_S; return -1; } + */ return 0; }