diff --git a/CMakeLists.txt b/CMakeLists.txt index aa07e94fc..30fa484c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,49 +131,18 @@ set( zt_go_native ) -if(WIN32) - set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi) -else(WIN32) - set(libs ${libs} pthread) -endif(WIN32) - -#if(WIN32) -# add_subdirectory("windows/WinUI") -# add_subdirectory("windows/copyutil") -# add_definitions(-DNOMINMAX) -#endif(WIN32) - #if(WIN32) # set(libs ${libs} wsock32 ws2_32 rpcrt4 iphlpapi) -# set(src -# ${src} -# "windows/ZeroTierOne/ServiceBase.cpp" -# "windows/ZeroTierOne/ServiceInstaller.cpp" -# "windows/ZeroTierOne/ZeroTierOneService.cpp" -# "windows/ZeroTierOne/ZeroTierOne.rc" -# ) -# set(headers -# ${headers} -# "windows/ZeroTierOne/ServiceBase.h" -# "windows/ZeroTierOne/ServiceInstaller.h" -# "windows/ZeroTierOne/ZeroTierOneService.h" -# ) #else(WIN32) -# set(libs ${libs} pthread resolv) +# set(libs ${libs} pthread) #endif(WIN32) #if(BUILD_CENTRAL_CONTROLLER) # set(libs ${libs} rabbitmq-static ${PostgreSQL_LIBRARIES}) #endif(BUILD_CENTRAL_CONTROLLER) -#add_executable(${PROJECT_NAME} ${src} ${headers}) -#target_link_libraries(${PROJECT_NAME} ${libs}) -#target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR}) - -add_custom_command( - OUTPUT zerotier +add_custom_target(zerotier ALL WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/go - COMMAND go build -trimpath -ldflags -s -o ../build/zerotier cmd/zerotier/zerotier.go - DEPENDS zt_osdep zt_core zt_go_native + COMMAND rm -f ../build/zerotier && go build -trimpath -ldflags -s -o ../build/zerotier cmd/zerotier/zerotier.go ) -add_custom_target(build_zerotier ALL DEPENDS zerotier) +add_dependencies(zerotier zt_osdep zt_core zt_go_native) diff --git a/go/cmd/zerotier/zerotier.go b/go/cmd/zerotier/zerotier.go index b3d698871..0c12c8a84 100644 --- a/go/cmd/zerotier/zerotier.go +++ b/go/cmd/zerotier/zerotier.go @@ -20,6 +20,7 @@ import ( "os" "path" "runtime" + "runtime/debug" "strings" "zerotier/cmd/zerotier/cli" @@ -63,6 +64,18 @@ func authTokenRequired(authToken string) { } func main() { + // Reduce Go's threads to 1-2 depending on whether this is single core or + // multi-core. Note that I/O threads are in C++ and are separate and Go + // code only does service control and CLI stuff, so this reduces memory + // use and competition with I/O but shouldn't impact throughput. We also + // crank up the GC to reduce memory usage a little bit. + if runtime.NumCPU() >= 2 { + runtime.GOMAXPROCS(2) + } else { + runtime.GOMAXPROCS(1) + } + debug.SetGCPercent(25) + globalOpts := flag.NewFlagSet("global", flag.ContinueOnError) hflag := globalOpts.Bool("h", false, "") // support -h to be canonical with other Unix utilities jflag := globalOpts.Bool("j", false, "") diff --git a/go/pkg/zerotier/node.go b/go/pkg/zerotier/node.go index 47222f105..dbee8a74b 100644 --- a/go/pkg/zerotier/node.go +++ b/go/pkg/zerotier/node.go @@ -89,6 +89,8 @@ type Node struct { networksLock sync.RWMutex interfaceAddresses map[string]net.IP // physical external IPs on the machine interfaceAddressesLock sync.Mutex + online uint32 + running uint32 basePath string peersPath string networksPath string @@ -102,8 +104,6 @@ type Node struct { id *Identity namedSocketApiServer *http.Server tcpApiServer *http.Server - online uint32 - running uint32 runWaitGroup sync.WaitGroup } diff --git a/node/Constants.hpp b/node/Constants.hpp index c8f806a8f..168fb7059 100644 --- a/node/Constants.hpp +++ b/node/Constants.hpp @@ -79,7 +79,7 @@ /** * Maximum delay between timer task checks (should be a fraction of smallest housekeeping interval) */ -#define ZT_MAX_TIMER_TASK_INTERVAL 3000 +#define ZT_MAX_TIMER_TASK_INTERVAL 5000 /** * How often most internal cleanup and housekeeping tasks are performed @@ -92,7 +92,7 @@ * Note that this affects how frequently we re-request network configurations * from network controllers if we haven't received one yet. */ -#define ZT_NETWORK_HOUSEKEEPING_PERIOD 12000 +#define ZT_NETWORK_HOUSEKEEPING_PERIOD 15000 /** * Delay between WHOIS retries in ms @@ -139,7 +139,12 @@ /** * Timeout for overall peer activity (measured from last receive) */ -#define ZT_PEER_ACTIVITY_TIMEOUT ((ZT_PEER_PING_PERIOD * 2) + 5000) +#define ZT_PEER_ALIVE_TIMEOUT ((ZT_PEER_PING_PERIOD * 2) + 5000) + +/** + * Timeout for overall peer activity (measured from last receive) + */ +#define ZT_PEER_ACTIVITY_TIMEOUT (ZT_PEER_PING_PERIOD + 5000) /** * Maximum interval between sort/prioritize of paths for a peer diff --git a/node/Node.cpp b/node/Node.cpp index 1d27dba88..37a2622ab 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -170,15 +170,21 @@ struct _processBackgroundTasks_ping_eachPeer Node *parent; void *tPtr; bool online; + std::vector
rootsNotOnline; ZT_ALWAYS_INLINE void operator()(const SharedPtr &peer,const bool isRoot) { peer->ping(tPtr,now,isRoot); - if ((isRoot)&&((now - peer->lastReceive()) <= (ZT_PEER_PING_PERIOD + 5000))) - online = true; + if (isRoot) { + if (peer->active(now)) { + online = true; + } else { + rootsNotOnline.push_back(peer->address()); + } + } } }; -static uint16_t junk = 0; +static uint8_t junk = 0; // junk payload for keepalive packets struct _processBackgroundTasks_path_keepalive { int64_t now; @@ -215,6 +221,15 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int } RR->topology->rankRoots(now); + + if (pf.online) { + // If we have at least one online root, request whois for roots not online. + // This will give us updated locators for these roots which may contain new + // IP addresses. It will also auto-discover IPs for roots that were not added + // with an initial bootstrap address. + for (std::vector
::const_iterator r(pf.rootsNotOnline.begin()); r != pf.rootsNotOnline.end(); ++r) + RR->sw->requestWhois(tPtr,now,*r); + } } catch ( ... ) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -286,7 +301,7 @@ ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr) if (*nw) { unsigned long newNetworksSize = (unsigned long)_networks.size(); std::vector< SharedPtr > newNetworks; - uint64_t newNetworksMask; + uint64_t newNetworksMask,id; std::vector< SharedPtr >::const_iterator i; try_larger_network_hashtable: @@ -296,7 +311,7 @@ try_larger_network_hashtable: newNetworksMask = (uint64_t)(newNetworksSize - 1); for(i=_networks.begin();i!=_networks.end();++i) { - const uint64_t id = (*i)->id(); + id = (*i)->id(); nw = &(newNetworks[(unsigned long)((id + (id >> 32U)) & newNetworksMask)]); if (*nw) goto try_larger_network_hashtable; diff --git a/node/Peer.hpp b/node/Peer.hpp index f2b2a8faa..b993cd858 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -185,10 +185,15 @@ public: */ ZT_ALWAYS_INLINE int64_t lastReceive() const { return _lastReceive; } + /** + * @return True if we've heard from this peer in less than ZT_PEER_ALIVE_TIMEOUT + */ + ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ALIVE_TIMEOUT); } + /** * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT */ - ZT_ALWAYS_INLINE bool alive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } + ZT_ALWAYS_INLINE bool active(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); } /** * @return Latency in milliseconds of best/aggregate path or 0xffff if unknown diff --git a/node/Topology.cpp b/node/Topology.cpp index 49070cb36..b69fea236 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -22,12 +22,12 @@ struct _RootSortComparisonOperator ZT_ALWAYS_INLINE bool operator()(const SharedPtr &a,const SharedPtr &b) { const int64_t now = _now; - if (a->alive(now)) { - if (b->alive(now)) + if (a->active(now)) { + if (b->active(now)) return (a->latency() < b->latency()); return true; } - return a->bootstrap() >= b->bootstrap(); + return a->lastReceive() < b->lastReceive(); } const int64_t _now; }; diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp index 663980beb..8591fe7e0 100644 --- a/osdep/OSUtils.cpp +++ b/osdep/OSUtils.cpp @@ -11,27 +11,26 @@ */ /****/ -#include -#include -#include -#include +#include +#include +#include +#include #include -#include #include "../node/Constants.hpp" #include "../node/Utils.hpp" #ifdef __UNIX_LIKE__ #include -#include #include -#include -#include -#include #include #include #endif +#ifdef __GCC__ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef __WINDOWS__ #include #include @@ -40,8 +39,6 @@ #include #endif -#include - #include "OSUtils.hpp" namespace ZeroTier { @@ -122,64 +119,6 @@ std::vector OSUtils::listDirectory(const char *path,bool includeDir return r; } -long OSUtils::cleanDirectory(const char *path,const int64_t olderThan) -{ - long cleaned = 0; - -#ifdef __WINDOWS__ - HANDLE hFind; - WIN32_FIND_DATAA ffd; - LARGE_INTEGER date,adjust; - adjust.QuadPart = 11644473600000 * 10000; - char tmp[4096]; - if ((hFind = FindFirstFileA((std::string(path) + "\\*").c_str(),&ffd)) != INVALID_HANDLE_VALUE) { - do { - if ((strcmp(ffd.cFileName,"."))&&(strcmp(ffd.cFileName,".."))&&((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)) { - date.HighPart = ffd.ftLastWriteTime.dwHighDateTime; - date.LowPart = ffd.ftLastWriteTime.dwLowDateTime; - if (date.QuadPart > 0) { - date.QuadPart -= adjust.QuadPart; - if ((int64_t)((date.QuadPart / 10000000) * 1000) < olderThan) { - ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName); - if (DeleteFileA(tmp)) - ++cleaned; - } - } - } - } while (FindNextFileA(hFind,&ffd)); - FindClose(hFind); - } -#else - struct dirent de; - struct dirent *dptr; - struct stat st; - char tmp[4096]; - DIR *d = opendir(path); - if (!d) - return -1; - dptr = (struct dirent *)0; - for(;;) { - if (readdir_r(d,&de,&dptr)) - break; - if (dptr) { - if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) { - ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name); - if (stat(tmp,&st) == 0) { - int64_t mt = (int64_t)(st.st_mtime); - if ((mt > 0)&&((mt * 1000) < olderThan)) { - if (unlink(tmp) == 0) - ++cleaned; - } - } - } - } else break; - } - closedir(d); -#endif - - return cleaned; -} - bool OSUtils::rmDashRf(const char *path) { #ifdef __WINDOWS__ diff --git a/osdep/OSUtils.hpp b/osdep/OSUtils.hpp index bf6ca4f5f..1de747e3e 100644 --- a/osdep/OSUtils.hpp +++ b/osdep/OSUtils.hpp @@ -132,16 +132,6 @@ public: */ static std::vector listDirectory(const char *path,bool includeDirectories = false); - /** - * Clean a directory of files whose last modified time is older than this - * - * This ignores directories, symbolic links, and other special files. - * - * @param olderThan Last modified older than timestamp (ms since epoch) - * @return Number of cleaned files or negative on fatal error - */ - static long cleanDirectory(const char *path,const int64_t olderThan); - /** * Delete a directory and all its files and subdirectories recursively *