summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--attic/DBM.cpp243
-rw-r--r--attic/DBM.hpp168
-rw-r--r--controller/EmbeddedNetworkController.cpp26
-rw-r--r--controller/JSONDB.cpp10
-rw-r--r--include/ZeroTierOne.h40
-rw-r--r--node/Address.hpp4
-rw-r--r--node/Constants.hpp12
-rw-r--r--node/Dictionary.hpp4
-rw-r--r--node/Identity.hpp5
-rw-r--r--node/IncomingPacket.cpp21
-rw-r--r--node/InetAddress.cpp8
-rw-r--r--node/MAC.hpp2
-rw-r--r--node/MulticastGroup.hpp2
-rw-r--r--node/Network.cpp29
-rw-r--r--node/NetworkConfig.cpp2
-rw-r--r--node/Node.cpp172
-rw-r--r--node/Node.hpp8
-rw-r--r--node/Path.hpp17
-rw-r--r--node/Peer.cpp190
-rw-r--r--node/Peer.hpp68
-rw-r--r--node/RuntimeEnvironment.hpp19
-rw-r--r--node/Switch.cpp94
-rw-r--r--node/Topology.cpp79
-rw-r--r--node/Topology.hpp29
-rw-r--r--node/Utils.cpp5
-rw-r--r--node/Utils.hpp3
-rw-r--r--one.cpp20
-rw-r--r--osdep/BSDEthernetTap.cpp16
-rw-r--r--osdep/Binder.hpp4
-rw-r--r--osdep/Http.cpp4
-rw-r--r--osdep/LinuxEthernetTap.cpp10
-rw-r--r--osdep/OSUtils.cpp6
-rw-r--r--osdep/OSXEthernetTap.cpp14
-rw-r--r--osdep/PortMapper.cpp4
-rw-r--r--osdep/WindowsEthernetTap.cpp10
-rw-r--r--selftest.cpp2
-rw-r--r--service/ClusterDefinition.hpp2
-rw-r--r--service/OneService.cpp268
-rw-r--r--service/SoftwareUpdater.cpp2
-rw-r--r--windows/ZeroTierOne/ZeroTierOne.vcxproj2
-rw-r--r--windows/ZeroTierOne/ZeroTierOne.vcxproj.filters6
41 files changed, 599 insertions, 1031 deletions
diff --git a/attic/DBM.cpp b/attic/DBM.cpp
deleted file mode 100644
index 54f017e0..00000000
--- a/attic/DBM.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * You can be released from the requirements of the license by purchasing
- * a commercial license. Buying such a license is mandatory as soon as you
- * develop commercial closed-source software that incorporates or links
- * directly against ZeroTier software without disclosing the source code
- * of your own application.
- */
-
-#include "DBM.hpp"
-
-#include "../version.h"
-
-#include "../node/Salsa20.hpp"
-#include "../node/Poly1305.hpp"
-#include "../node/SHA512.hpp"
-
-#include "../osdep/OSUtils.hpp"
-
-#define ZT_STORED_OBJECT_TYPE__CLUSTER_NODE_STATUS (ZT_STORED_OBJECT__MAX_TYPE_ID + 1)
-#define ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION (ZT_STORED_OBJECT__MAX_TYPE_ID + 2)
-
-namespace ZeroTier {
-
-// We generate the cluster ID from our address and version info since this is
-// not at all designed to allow interoperation between versions (or endians)
-// in the same cluster.
-static inline uint64_t _mkClusterId(const Address &myAddress)
-{
- uint64_t x = ZEROTIER_ONE_VERSION_MAJOR;
- x <<= 8;
- x += ZEROTIER_ONE_VERSION_MINOR;
- x <<= 8;
- x += ZEROTIER_ONE_VERSION_REVISION;
- x <<= 40;
- x ^= myAddress.toInt();
-#if __BYTE_ORDER == __BIG_ENDIAN
- ++x;
-#endif;
- return x;
-}
-
-void DBM::onUpdate(uint64_t from,const _MapKey &k,const _MapValue &v,uint64_t rev)
-{
- char p[4096];
- char tmp[ZT_DBM_MAX_VALUE_SIZE];
- if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p))) {
- // Reduce unnecessary disk writes
- FILE *f = fopen(p,"r");
- if (f) {
- long n = (long)fread(tmp,1,sizeof(tmp),f);
- fclose(f);
- if ((n == (long)v.len)&&(!memcmp(v.data,tmp,n)))
- return;
- }
-
- // Write to disk if file has changed or was not already present
- f = fopen(p,"w");
- if (f) {
- if (fwrite(data,len,1,f) != 1)
- fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p);
- fclose(f);
- if (type == ZT_STORED_OBJECT_IDENTITY_SECRET)
- OSUtils::lockDownFile(p,false);
- } else {
- fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p);
- }
- }
-}
-
-void DBM::onDelete(uint64_t from,const _MapKey &k)
-{
- char p[4096];
- if (_persistentPath((ZT_StoredObjectType)k.type,k.key,p,sizeof(p)))
- OSUtils::rm(p);
-}
-
-DBM::_vsdm_cryptor::_vsdm_cryptor(const Identity &secretIdentity)
-{
- uint8_t s512[64];
- SHA512::hash(h512,secretIdentity.privateKeyPair().priv.data,ZT_C25519_PRIVATE_KEY_LEN);
- memcpy(_key,s512,sizeof(_key));
-}
-
-void DBM::_vsdm_cryptor::encrypt(void *d,unsigned long l)
-{
- if (l >= 24) { // sanity check
- uint8_t key[32];
- uint8_t authKey[32];
- uint8_t auth[16];
-
- uint8_t *const iv = reinterpret_cast<uint8_t *>(d) + (l - 16);
- Utils::getSecureRandom(iv,16);
- memcpy(key,_key,32);
- for(unsigned long i=0;i<8;++i)
- _key[i] ^= iv[i];
-
- Salsa20 s20(key,iv + 8);
- memset(authKey,0,32);
- s20.crypt12(authKey,authKey,32);
- s20.crypt12(d,d,l - 24);
-
- Poly1305::compute(auth,d,l - 24,authKey);
- memcpy(reinterpret_cast<uint8_t *>(d) + (l - 24),auth,8);
- }
-}
-
-bool DBM::_vsdm_cryptor::decrypt(void *d,unsigned long l)
-{
- if (l >= 24) { // sanity check
- uint8_t key[32];
- uint8_t authKey[32];
- uint8_t auth[16];
-
- uint8_t *const iv = reinterpret_cast<uint8_t *>(d) + (l - 16);
- memcpy(key,_key,32);
- for(unsigned long i=0;i<8;++i)
- _key[i] ^= iv[i];
-
- Salsa20 s20(key,iv + 8);
- memset(authKey,0,32);
- s20.crypt12(authKey,authKey,32);
-
- Poly1305::compute(auth,d,l - 24,authKey);
- if (!Utils::secureEq(reinterpret_cast<uint8_t *>(d) + (l - 24),auth,8))
- return false;
-
- s20.crypt12(d,d,l - 24);
-
- return true;
- }
- return false;
-}
-
-DBM::DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node) :
- _basePath(basePath),
- _node(node),
- _startTime(OSUtils::now()),
- _m(_mkClusterId(secretIdentity.address()),clusterMemberId,false,_vsdm_cryptor(secretIdentity),_vsdm_watcher(this))
-{
-}
-
-DBM::~DBM()
-{
-}
-
-void DBM::put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len)
-{
- char p[4096];
- if (_m.put(_MapKey(key,(uint16_t)type),Value(OSUtils::now(),(uint16_t)len,data))) {
- if (_persistentPath(type,key,p,sizeof(p))) {
- FILE *f = fopen(p,"w");
- if (f) {
- if (fwrite(data,len,1,f) != 1)
- fprintf(stderr,"WARNING: error writing to %s (I/O error)" ZT_EOL_S,p);
- fclose(f);
- if (type == ZT_STORED_OBJECT_IDENTITY_SECRET)
- OSUtils::lockDownFile(p,false);
- } else {
- fprintf(stderr,"WARNING: error writing to %s (cannot open)" ZT_EOL_S,p);
- }
- }
- }
-}
-
-bool DBM::get(const ZT_StoredObjectType type,const uint64_t key,Value &value)
-{
- char p[4096];
- if (_m.get(_MapKey(key,(uint16_t)type),value))
- return true;
- if (_persistentPath(type,key,p,sizeof(p))) {
- FILE *f = fopen(p,"r");
- if (f) {
- long n = (long)fread(value.data,1,sizeof(value.data),f);
- value.len = (n > 0) ? (uint16_t)n : (uint16_t)0;
- fclose(f);
- value.ts = OSUtils::getLastModified(p);
- _m.put(_MapKey(key,(uint16_t)type),value);
- return true;
- }
- }
- return false;
-}
-
-void DBM::del(const ZT_StoredObjectType type,const uint64_t key)
-{
- char p[4096];
- _m.del(_MapKey(key,(uint16_t)type));
- if (_persistentPath(type,key,p,sizeof(p)))
- OSUtils::rm(p);
-}
-
-void DBM::clean()
-{
-}
-
-bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen)
-{
- switch(type) {
- case ZT_STORED_OBJECT_IDENTITY_PUBLIC:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.public",_basePath.c_str());
- return true;
- case ZT_STORED_OBJECT_IDENTITY_SECRET:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "identity.secret",_basePath.c_str());
- return true;
- case ZT_STORED_OBJECT_IDENTITY:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "iddb.d" ZT_PATH_SEPARATOR_S "%.10llx",_basePath.c_str(),key);
- return true;
- case ZT_STORED_OBJECT_NETWORK_CONFIG:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.conf",_basePath.c_str(),key);
- return true;
- case ZT_STORED_OBJECT_PLANET:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "planet",_basePath.c_str());
- return true;
- case ZT_STORED_OBJECT_MOON:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "moons.d" ZT_PATH_SEPARATOR_S "%.16llx.moon",_basePath.c_str(),key);
- return true;
- case (ZT_StoredObjectType)ZT_STORED_OBJECT_TYPE__CLUSTER_DEFINITION:
- Utils::snprintf(p,maxlen,"%s" ZT_PATH_SEPARATOR_S "cluster",_basePath.c_str());
- return true;
- default:
- return false;
- }
-}
-
-} // namespace ZeroTier
diff --git a/attic/DBM.hpp b/attic/DBM.hpp
deleted file mode 100644
index c6d5b8c0..00000000
--- a/attic/DBM.hpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * ZeroTier One - Network Virtualization Everywhere
- * Copyright (C) 2011-2017 ZeroTier, Inc. https://www.zerotier.com/
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * You can be released from the requirements of the license by purchasing
- * a commercial license. Buying such a license is mandatory as soon as you
- * develop commercial closed-source software that incorporates or links
- * directly against ZeroTier software without disclosing the source code
- * of your own application.
- */
-
-#ifndef ZT_DBM_HPP___
-#define ZT_DBM_HPP___
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <stdexcept>
-
-#include "../node/Constants.hpp"
-#include "../node/Mutex.hpp"
-#include "../node/Utils.hpp"
-#include "../node/Identity.hpp"
-#include "../node/Peer.hpp"
-
-#include "../ext/vsdm/vsdm.hpp"
-
-// The Peer is the largest structure we persist here
-#define ZT_DBM_MAX_VALUE_SIZE sizeof(Peer)
-
-namespace ZeroTier {
-
-class Node;
-class DBM;
-
-class DBM
-{
-public:
- ZT_PACKED_STRUCT(struct Value
- {
- Value(const uint64_t t,const uint16_t l,const void *d) :
- ts(t),
- l(l)
- {
- memcpy(data,d,l);
- }
- uint64_t ts;
- uint16_t len;
- uint8_t data[ZT_DBM_MAX_VALUE_SIZE];
- });
-
-private:
- ZT_PACKED_STRUCT(struct _MapKey
- {
- _MapKey() : obj(0),type(0) {}
- _MapKey(const uint16_t t,const uint64_t o) : obj(o),type(t) {}
- uint64_t obj;
- uint16_t type;
- inline bool operator==(const _MapKey &k) const { return ((obj == k.obj)&&(type == k.type)); }
- });
- struct _MapHasher
- {
- inline std::size_t operator()(const _MapKey &k) const { return (std::size_t)((k.obj ^ (k.obj >> 32)) + (uint64_t)k.type); }
- };
-
- void onUpdate(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev);
- void onDelete(uint64_t from,const _MapKey &k);
-
- class _vsdm_watcher
- {
- public:
- _vsdm_watcher(DBM *p) : _parent(p) {}
- inline void add(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); }
- inline void update(uint64_t from,const _MapKey &k,const Value &v,uint64_t rev) { _parent->onUpdate(from,k,v,rev); }
- inline void del(uint64_t from,const _MapKey &k) { _parent->onDelete(from,k); }
- private:
- DBM *_parent;
- };
- class _vsdm_serializer
- {
- public:
- static inline unsigned long objectSize(const _MapKey &k) { return 10; }
- static inline unsigned long objectSize(const Value &v) { return (10 + v.len); }
- static inline const char *objectData(const _MapKey &k) { return reinterpret_cast<const char *>(&k); }
- static inline const char *objectData(const Value &v) { return reinterpret_cast<const char *>(&v); }
- static inline bool objectDeserialize(const char *d,unsigned long l,_MapKey &k)
- {
- if (l == 10) {
- memcpy(&k,d,10);
- return true;
- }
- return false;
- }
- static inline bool objectDeserialize(const char *d,unsigned long l,Value &v)
- {
- if ((l >= 10)&&(l <= (10 + ZT_DBM_MAX_VALUE_SIZE))) {
- memcpy(&v,d,l);
- return true;
- }
- return false;
- }
- };
- class _vsdm_cryptor
- {
- public:
- _vsdm_cryptor(const Identity &secretIdentity);
- static inline unsigned long overhead() { return 24; }
- void encrypt(void *d,unsigned long l);
- bool decrypt(void *d,unsigned long l);
- uint8_t _key[32];
- };
-
- typedef vsdm< _MapKey,Value,16384,_vsdm_watcher,_vsdm_serializer,_vsdm_cryptor,_MapHasher > _Map;
-
- friend class _Map;
-
-public:
- ZT_PACKED_STRUCT(struct ClusterPeerStatus
- {
- uint64_t startTime;
- uint64_t currentTime;
- uint64_t clusterPeersConnected;
- uint64_t ztPeersConnected;
- uint16_t platform;
- uint16_t arch;
- });
-
- DBM(const Identity &secretIdentity,uint64_t clusterMemberId,const std::string &basePath,Node *node);
-
- ~DBM();
-
- void put(const ZT_StoredObjectType type,const uint64_t key,const void *data,unsigned int len);
-
- bool get(const ZT_StoredObjectType type,const uint64_t key,Value &value);
-
- void del(const ZT_StoredObjectType type,const uint64_t key);
-
- void clean();
-
-private:
- bool DBM::_persistentPath(const ZT_StoredObjectType type,const uint64_t key,char *p,unsigned int maxlen);
-
- const std::string _basePath;
- Node *const _node;
- uint64_t _startTime;
- _Map _m;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/controller/EmbeddedNetworkController.cpp b/controller/EmbeddedNetworkController.cpp
index e2eaa788..85c759e7 100644
--- a/controller/EmbeddedNetworkController.cpp
+++ b/controller/EmbeddedNetworkController.cpp
@@ -122,12 +122,12 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
break;
case ZT_NETWORK_RULE_MATCH_MAC_SOURCE:
r["type"] = "MATCH_MAC_SOURCE";
- Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
r["mac"] = tmp;
break;
case ZT_NETWORK_RULE_MATCH_MAC_DEST:
r["type"] = "MATCH_MAC_DEST";
- Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)rule.v.mac[0],(unsigned int)rule.v.mac[1],(unsigned int)rule.v.mac[2],(unsigned int)rule.v.mac[3],(unsigned int)rule.v.mac[4],(unsigned int)rule.v.mac[5]);
r["mac"] = tmp;
break;
case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE:
@@ -179,7 +179,7 @@ static json _renderRule(ZT_VirtualNetworkRule &rule)
break;
case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS:
r["type"] = "MATCH_CHARACTERISTICS";
- Utils::snprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",rule.v.characteristics);
r["mask"] = tmp;
break;
case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE:
@@ -514,7 +514,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
_db.eachMember(nwid,[&responseBody](uint64_t networkId,uint64_t nodeId,const json &member) {
if ((member.is_object())&&(member.size() > 0)) {
char tmp[128];
- Utils::snprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0));
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s%.10llx\":%llu",(responseBody.length() > 1) ? ",\"" : "\"",(unsigned long long)nodeId,(unsigned long long)OSUtils::jsonInt(member["revision"],0));
responseBody.append(tmp);
}
});
@@ -548,7 +548,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
for(std::vector<uint64_t>::const_iterator i(networkIds.begin());i!=networkIds.end();++i) {
if (responseBody.length() > 1)
responseBody.push_back(',');
- Utils::snprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"\"%.16llx\"",(unsigned long long)*i);
responseBody.append(tmp);
}
responseBody.push_back(']');
@@ -562,7 +562,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
// Controller status
char tmp[4096];
- Utils::snprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"{\n\t\"controller\": true,\n\t\"apiVersion\": %d,\n\t\"clock\": %llu\n}\n",ZT_NETCONF_CONTROLLER_API_VERSION,(unsigned long long)OSUtils::now());
responseBody = tmp;
responseContentType = "application/json";
return 200;
@@ -603,14 +603,14 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
if ((path.size() >= 2)&&(path[1].length() == 16)) {
uint64_t nwid = Utils::hexStrToU64(path[1].c_str());
char nwids[24];
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
+ Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
if (path.size() >= 3) {
if ((path.size() == 4)&&(path[2] == "member")&&(path[3].length() == 10)) {
uint64_t address = Utils::hexStrToU64(path[3].c_str());
char addrs[24];
- Utils::snprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address);
+ Utils::ztsnprintf(addrs,sizeof(addrs),"%.10llx",(unsigned long long)address);
json member;
_db.getNetworkMember(nwid,address,member);
@@ -748,7 +748,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
if (!nwid)
return 503;
}
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
+ Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",(unsigned long long)nwid);
json network;
_db.getNetwork(nwid,network);
@@ -995,7 +995,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
_queue.post(qe);
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"{\"clock\":%llu,\"ping\":%s}",(unsigned long long)now,OSUtils::jsonDump(b).c_str());
responseBody = tmp;
responseContentType = "application/json";
@@ -1083,7 +1083,7 @@ void EmbeddedNetworkController::threadMain()
auto ms = this->_memberStatus.find(_MemberStatusKey(networkId,nodeId));
if (ms != _memberStatus.end())
lrt = ms->second.lastRequestTime;
- Utils::snprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu",
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s\"%.16llx-%.10llx\":%llu",
(first) ? "" : ",",
(unsigned long long)networkId,
(unsigned long long)nodeId,
@@ -1093,7 +1093,7 @@ void EmbeddedNetworkController::threadMain()
});
}
char tmp2[256];
- Utils::snprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime);
+ Utils::ztsnprintf(tmp2,sizeof(tmp2),"},\"clock\":%llu,\"startTime\":%llu}",(unsigned long long)now,(unsigned long long)_startTime);
pong.append(tmp2);
_db.writeRaw("pong",pong);
}
@@ -1126,7 +1126,7 @@ void EmbeddedNetworkController::_request(
ms.lastRequestTime = now;
}
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid);
+ Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid);
if (!_db.getNetworkAndMember(nwid,identity.address().toInt(),network,member,ns)) {
_sender->ncSendError(nwid,requestPacketId,identity.address(),NetworkController::NC_ERROR_OBJECT_NOT_FOUND);
return;
diff --git a/controller/JSONDB.cpp b/controller/JSONDB.cpp
index e0dd1742..acf23700 100644
--- a/controller/JSONDB.cpp
+++ b/controller/JSONDB.cpp
@@ -94,7 +94,7 @@ bool JSONDB::writeRaw(const std::string &n,const std::string &obj)
std::string body;
std::map<std::string,std::string> reqHeaders;
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%lu",(unsigned long)obj.length());
reqHeaders["Content-Length"] = tmp;
reqHeaders["Content-Type"] = "application/json";
const unsigned int sc = Http::PUT(0,ZT_JSONDB_HTTP_TIMEOUT,reinterpret_cast<const struct sockaddr *>(&_httpAddr),(_basePath+"/"+n).c_str(),reqHeaders,obj.data(),(unsigned long)obj.length(),headers,body);
@@ -164,7 +164,7 @@ bool JSONDB::getNetworkMember(const uint64_t networkId,const uint64_t nodeId,nlo
void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkConfig)
{
char n[64];
- Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId);
+ Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId);
writeRaw(n,OSUtils::jsonDump(networkConfig));
{
Mutex::Lock _l(_networks_m);
@@ -176,7 +176,7 @@ void JSONDB::saveNetwork(const uint64_t networkId,const nlohmann::json &networkC
void JSONDB::saveNetworkMember(const uint64_t networkId,const uint64_t nodeId,const nlohmann::json &memberConfig)
{
char n[256];
- Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId);
+ Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId);
writeRaw(n,OSUtils::jsonDump(memberConfig));
{
Mutex::Lock _l(_networks_m);
@@ -202,7 +202,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId)
}
char n[256];
- Utils::snprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId);
+ Utils::ztsnprintf(n,sizeof(n),"network/%.16llx",(unsigned long long)networkId);
if (_httpAddr) {
// Deletion is currently done by Central in harnessed mode
@@ -229,7 +229,7 @@ nlohmann::json JSONDB::eraseNetwork(const uint64_t networkId)
nlohmann::json JSONDB::eraseNetworkMember(const uint64_t networkId,const uint64_t nodeId,bool recomputeSummaryInfo)
{
char n[256];
- Utils::snprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId);
+ Utils::ztsnprintf(n,sizeof(n),"network/%.16llx/member/%.10llx",(unsigned long long)networkId,(unsigned long long)nodeId);
if (_httpAddr) {
// Deletion is currently done by the caller in Central harnessed mode
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h
index 9c295cee..133ae340 100644
--- a/include/ZeroTierOne.h
+++ b/include/ZeroTierOne.h
@@ -1072,9 +1072,9 @@ typedef struct
* identity of a node and its address, the identity (public and secret)
* must be saved at a minimum.
*
- * The reference service implementation currently persists identity,
- * peer identities (for a period of time), planet, moons, and network
- * configurations. Other state is treated as ephemeral.
+ * State objects actually have two IDs (uint64_t[2]). If only one is
+ * listed the second ([1]) should be zero and is ignored in storage
+ * and replication.
*
* All state objects should be replicated in cluster mode. The reference
* clustering implementation uses a rumor mill algorithm in which state
@@ -1115,25 +1115,28 @@ enum ZT_StateObjectType
* Canonical path: <HOME>/peers.d/<ADDRESS> (10-digit hex address)
* Persistence: optional, can be purged at any time
*/
- ZT_STATE_OBJECT_PEER = 3,
+ ZT_STATE_OBJECT_PEER_STATE = 3,
/**
- * The identity of a known peer
+ * Network configuration
*
* Object ID: peer address
- * Canonical path: <HOME>/iddb.d/<ADDRESS> (10-digit hex address)
- * Persistence: optional, can be purged at any time, recommended ttl 30-60 days
+ * Canonical path: <HOME>/networks.d/<NETWORKID>.conf (16-digit hex ID)
+ * Persistence: required if network memberships should persist
*/
- ZT_STATE_OBJECT_PEER_IDENTITY = 4,
+ ZT_STATE_OBJECT_NETWORK_CONFIG = 4,
/**
- * Network configuration
+ * Network membership (network X peer intersection)
*
- * Object ID: peer address
- * Canonical path: <HOME>/networks.d/<NETWORKID>.conf (16-digit hex ID)
- * Persistence: required if network memberships should persist
+ * If these are persisted they must be restored after peer states and
+ * network configs. Otherwise they are ignored.
+ *
+ * Object ID: [0] network ID, [1] peer address
+ * Canonical path: <HOME>/networks.d/<NETWORKID>/members.d/<ADDRESS>
+ * Persistence: optional (not usually needed)
*/
- ZT_STATE_OBJECT_NETWORK_CONFIG = 5,
+ ZT_STATE_OBJECT_NETWORK_MEMBERSHIP = 5,
/**
* The planet (there is only one per... well... planet!)
@@ -1248,7 +1251,7 @@ typedef void (*ZT_StatePutFunction)(
void *, /* User ptr */
void *, /* Thread ptr */
enum ZT_StateObjectType, /* State object type */
- uint64_t, /* State object ID (if applicable) */
+ const uint64_t [2], /* State object ID (if applicable) */
const void *, /* State object data */
int); /* Length of data or -1 to delete */
@@ -1264,7 +1267,7 @@ typedef int (*ZT_StateGetFunction)(
void *, /* User ptr */
void *, /* Thread ptr */
enum ZT_StateObjectType, /* State object type */
- uint64_t, /* State object ID (if applicable) */
+ const uint64_t [2], /* State object ID (if applicable) */
void *, /* Buffer to store state object data */
unsigned int); /* Length of data buffer in bytes */
@@ -1450,7 +1453,8 @@ void ZT_Node_delete(ZT_Node *node);
*
* Unless clustering is being implemented this function doesn't need to be
* used after startup. It could be called in response to filesystem changes
- * to allow some degree of live configurability by filesystem observation.
+ * to allow some degree of live configurability by filesystem observation
+ * but this kind of thing is entirely optional.
*
* The return value of this function indicates whether the update was accepted
* as new. A return value of ZT_RESULT_OK indicates that the node gleaned new
@@ -1468,7 +1472,7 @@ void ZT_Node_delete(ZT_Node *node);
* @param node Node instance
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @param type State object type
- * @param id State object ID
+ * @param id State object ID (if object type has only one ID, second should be zero)
* @param data State object data
* @param len Length of state object data in bytes
* @return ZT_RESULT_OK if object was accepted or ZT_RESULT_OK_IGNORED if non-informative, error if object was invalid
@@ -1477,7 +1481,7 @@ enum ZT_ResultCode ZT_Node_processStateUpdate(
ZT_Node *node,
void *tptr,
ZT_StateObjectType type,
- uint64_t id,
+ const uint64_t id[2],
const void *data,
unsigned int len);
diff --git a/node/Address.hpp b/node/Address.hpp
index 9d2d1734..98e32858 100644
--- a/node/Address.hpp
+++ b/node/Address.hpp
@@ -144,7 +144,7 @@ public:
inline std::string toString() const
{
char buf[16];
- Utils::snprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a);
+ Utils::ztsnprintf(buf,sizeof(buf),"%.10llx",(unsigned long long)_a);
return std::string(buf);
};
@@ -154,7 +154,7 @@ public:
*/
inline void toString(char *buf,unsigned int len) const
{
- Utils::snprintf(buf,len,"%.10llx",(unsigned long long)_a);
+ Utils::ztsnprintf(buf,len,"%.10llx",(unsigned long long)_a);
}
/**
diff --git a/node/Constants.hpp b/node/Constants.hpp
index fbbba76e..274b9564 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -216,7 +216,12 @@
/**
* How often Topology::clean() and Network::clean() and similar are called, in ms
*/
-#define ZT_HOUSEKEEPING_PERIOD 120000
+#define ZT_HOUSEKEEPING_PERIOD 60000
+
+/**
+ * How often in ms to write peer state to storage and/or cluster (approximate)
+ */
+#define ZT_PEER_STATE_WRITE_PERIOD 10000
/**
* How long to remember peer records in RAM if they haven't been used
@@ -323,11 +328,6 @@
#define ZT_PEER_PATH_EXPIRATION ((ZT_PEER_PING_PERIOD * 4) + 3000)
/**
- * Send a full HELLO every this often (ms)
- */
-#define ZT_PEER_SEND_FULL_HELLO_EVERY (ZT_PEER_PING_PERIOD * 2)
-
-/**
* How often to retry expired paths that we're still remembering
*/
#define ZT_PEER_EXPIRED_PATH_TRIAL_PERIOD (ZT_PEER_PING_PERIOD * 10)
diff --git a/node/Dictionary.hpp b/node/Dictionary.hpp
index 4413d628..0b000f13 100644
--- a/node/Dictionary.hpp
+++ b/node/Dictionary.hpp
@@ -391,7 +391,7 @@ public:
inline bool add(const char *key,uint64_t value)
{
char tmp[32];
- Utils::snprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%llx",(unsigned long long)value);
return this->add(key,tmp,-1);
}
@@ -401,7 +401,7 @@ public:
inline bool add(const char *key,const Address &a)
{
char tmp[32];
- Utils::snprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",(unsigned long long)a.toInt());
return this->add(key,tmp,-1);
}
diff --git a/node/Identity.hpp b/node/Identity.hpp
index b1c7d6f4..79e17f4d 100644
--- a/node/Identity.hpp
+++ b/node/Identity.hpp
@@ -91,7 +91,10 @@ public:
~Identity()
{
- delete _privateKey;
+ if (_privateKey) {
+ Utils::burn(_privateKey,sizeof(C25519::Private));
+ delete _privateKey;
+ }
}
inline Identity &operator=(const Identity &id)
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index 9140c502..0548387b 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -42,7 +42,6 @@
#include "Salsa20.hpp"
#include "SHA512.hpp"
#include "World.hpp"
-#include "Cluster.hpp"
#include "Node.hpp"
#include "CertificateOfMembership.hpp"
#include "CertificateOfRepresentation.hpp"
@@ -586,12 +585,6 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar
} else {
// Request unknown WHOIS from upstream from us (if we have one)
RR->sw->requestWhois(tPtr,addr);
-#ifdef ZT_ENABLE_CLUSTER
- // Distribute WHOIS queries across a cluster if we do not know the ID.
- // This may result in duplicate OKs to the querying peer, which is fine.
- if (RR->cluster)
- RR->cluster->sendDistributedQuery(*this);
-#endif
}
}
@@ -1056,12 +1049,6 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
outp.armor(peer->key(),true,_path->nextOutgoingCounter());
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
}
-
- // If we are a member of a cluster, distribute this GATHER across it
-#ifdef ZT_ENABLE_CLUSTER
- if ((RR->cluster)&&(gatheredLocally < gatherLimit))
- RR->cluster->sendDistributedQuery(*this);
-#endif
}
peer->received(tPtr,_path,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,trustEstablished);
@@ -1212,8 +1199,8 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
(!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known
(RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path
{
- if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0)
- peer->setClusterPreferred(a);
+ //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0)
+ // peer->setClusterPreferred(a);
if (++countPerScope[(int)a.ipScope()][0] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
@@ -1229,8 +1216,8 @@ bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPt
(!( ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) == 0) && (peer->hasActivePathTo(now,a)) )) && // not already known
(RR->node->shouldUsePathForZeroTierTraffic(tPtr,peer->address(),_path->localAddress(),a)) ) // should use path
{
- if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0)
- peer->setClusterPreferred(a);
+ //if ((flags & ZT_PUSH_DIRECT_PATHS_FLAG_CLUSTER_REDIRECT) != 0)
+ // peer->setClusterPreferred(a);
if (++countPerScope[(int)a.ipScope()][1] <= ZT_PUSH_DIRECT_PATHS_MAX_PER_SCOPE_AND_FAMILY) {
TRACE("attempting to contact %s at pushed direct path %s",peer->address().toString().c_str(),a.toString().c_str());
peer->attemptToContactAt(tPtr,InetAddress(),a,now,false,0);
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index 0fbb2d68..17d7c72e 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -152,7 +152,7 @@ std::string InetAddress::toString() const
char buf[128];
switch(ss_family) {
case AF_INET:
- Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d",
+ Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d/%d",
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
@@ -161,7 +161,7 @@ std::string InetAddress::toString() const
);
return std::string(buf);
case AF_INET6:
- Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d",
+ Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%d",
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
@@ -190,7 +190,7 @@ std::string InetAddress::toIpString() const
char buf[128];
switch(ss_family) {
case AF_INET:
- Utils::snprintf(buf,sizeof(buf),"%d.%d.%d.%d",
+ Utils::ztsnprintf(buf,sizeof(buf),"%d.%d.%d.%d",
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[0],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[1],
(int)(reinterpret_cast<const unsigned char *>(&(reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr)))[2],
@@ -198,7 +198,7 @@ std::string InetAddress::toIpString() const
);
return std::string(buf);
case AF_INET6:
- Utils::snprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
+ Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[0]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[1]),
(int)(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr[2]),
diff --git a/node/MAC.hpp b/node/MAC.hpp
index e7717d99..db50aeb1 100644
--- a/node/MAC.hpp
+++ b/node/MAC.hpp
@@ -178,7 +178,7 @@ public:
*/
inline void toString(char *buf,unsigned int len) const
{
- Utils::snprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]);
+ Utils::ztsnprintf(buf,len,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)(*this)[0],(int)(*this)[1],(int)(*this)[2],(int)(*this)[3],(int)(*this)[4],(int)(*this)[5]);
}
/**
diff --git a/node/MulticastGroup.hpp b/node/MulticastGroup.hpp
index 4240db67..7cbec2e0 100644
--- a/node/MulticastGroup.hpp
+++ b/node/MulticastGroup.hpp
@@ -100,7 +100,7 @@ public:
inline std::string toString() const
{
char buf[64];
- Utils::snprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi);
+ Utils::ztsnprintf(buf,sizeof(buf),"%.2x%.2x%.2x%.2x%.2x%.2x/%.8lx",(unsigned int)_mac[0],(unsigned int)_mac[1],(unsigned int)_mac[2],(unsigned int)_mac[3],(unsigned int)_mac[4],(unsigned int)_mac[5],(unsigned long)_adi);
return std::string(buf);
}
diff --git a/node/Network.cpp b/node/Network.cpp
index 74d81941..bccc0397 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -42,7 +42,6 @@
#include "NetworkController.hpp"
#include "Node.hpp"
#include "Peer.hpp"
-#include "Cluster.hpp"
// Uncomment to make the rules engine dump trace info to stdout
//#define ZT_RULES_ENGINE_DEBUGGING 1
@@ -52,7 +51,7 @@ namespace ZeroTier {
namespace {
#ifdef ZT_RULES_ENGINE_DEBUGGING
-#define FILTER_TRACE(f,...) { Utils::snprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); }
+#define FILTER_TRACE(f,...) { Utils::ztsnprintf(dpbuf,sizeof(dpbuf),f,##__VA_ARGS__); dlog.push_back(std::string(dpbuf)); }
static const char *_rtn(const ZT_VirtualNetworkRuleType rt)
{
switch(rt) {
@@ -701,10 +700,13 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
this->setConfiguration(tPtr,*nconf,false);
_lastConfigUpdate = 0; // still want to re-request since it's likely outdated
} else {
+ uint64_t tmp[2];
+ tmp[0] = nwid; tmp[1] = 0;
+
bool got = false;
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dict = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try {
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1);
+ int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,dict->unsafeData(),ZT_NETWORKCONFIG_DICT_CAPACITY - 1);
if (n > 1) {
NetworkConfig *nconf = new NetworkConfig();
try {
@@ -720,7 +722,7 @@ Network::Network(const RuntimeEnvironment *renv,void *tPtr,uint64_t nwid,void *u
delete dict;
if (!got)
- RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,"\n",1);
+ RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,"\n",1);
}
if (!_portInitialized) {
@@ -1065,11 +1067,6 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
return 0;
}
-#ifdef ZT_ENABLE_CLUSTER
- if ((source)&&(RR->cluster))
- RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start);
-#endif
-
// New properly verified chunks can be flooded "virally" through the network
if (fastPropagate) {
Address *a = (Address *)0;
@@ -1097,11 +1094,6 @@ uint64_t Network::handleConfigChunk(void *tPtr,const uint64_t packetId,const Add
if ((!c)||(_incomingConfigChunks[i].ts < c->ts))
c = &(_incomingConfigChunks[i]);
}
-
-#ifdef ZT_ENABLE_CLUSTER
- if ((source)&&(RR->cluster))
- RR->cluster->broadcastNetworkConfigChunk(chunk.field(start,chunk.size() - start),chunk.size() - start);
-#endif
} else {
TRACE("discarded single-chunk unsigned legacy config: this is only allowed if the sender is the controller itself");
return 0;
@@ -1186,8 +1178,11 @@ int Network::setConfiguration(void *tPtr,const NetworkConfig &nconf,bool saveToD
if (saveToDisk) {
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *d = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
try {
- if (nconf.toDictionary(*d,false))
- RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,_id,d->data(),d->sizeBytes());
+ if (nconf.toDictionary(*d,false)) {
+ uint64_t tmp[2];
+ tmp[0] = _id; tmp[1] = 0;
+ RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,d->data(),d->sizeBytes());
+ }
} catch ( ... ) {}
delete d;
}
@@ -1262,7 +1257,7 @@ void Network::requestConfiguration(void *tPtr)
nconf->rules[13].t = (uint8_t)ZT_NETWORK_RULE_ACTION_DROP;
nconf->type = ZT_NETWORK_TYPE_PUBLIC;
- Utils::snprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
+ Utils::ztsnprintf(nconf->name,sizeof(nconf->name),"adhoc-%.04x-%.04x",(int)startPortRange,(int)endPortRange);
this->setConfiguration(tPtr,*nconf,false);
delete nconf;
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index c39f6cab..65101c3a 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -94,7 +94,7 @@ bool NetworkConfig::toDictionary(Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> &d,b
if (ets.length() > 0)
ets.push_back(',');
char tmp2[16];
- Utils::snprintf(tmp2,sizeof(tmp2),"%x",et);
+ Utils::ztsnprintf(tmp2,sizeof(tmp2),"%x",et);
ets.append(tmp2);
}
et = 0;
diff --git a/node/Node.cpp b/node/Node.cpp
index 37586834..4ffe496c 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -45,7 +45,6 @@
#include "Address.hpp"
#include "Identity.hpp"
#include "SelfAwareness.hpp"
-#include "Cluster.hpp"
#include "Network.hpp"
const struct sockaddr_storage ZT_SOCKADDR_NULL = {0};
@@ -69,6 +68,7 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
throw std::runtime_error("callbacks struct version mismatch");
memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks));
+ // Initialize non-cryptographic PRNG from a good random source
Utils::getSecureRandom((void *)_prngState,sizeof(_prngState));
_online = false;
@@ -77,31 +77,36 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
memset(_expectingRepliesTo,0,sizeof(_expectingRepliesTo));
memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification));
- char tmp[512];
- std::string tmp2;
- int n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,0,tmp,sizeof(tmp) - 1);
+ uint64_t idtmp[2];
+ idtmp[0] = 0; idtmp[1] = 0;
+ char tmp[1024];
+ 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))
+ if (RR->identity.fromString(tmp)) {
+ RR->publicIdentityStr = RR->identity.toString(false);
+ RR->secretIdentityStr = RR->identity.toString(true);
+ } else {
n = -1;
+ }
}
+
+ idtmp[0] = RR->identity.address().toInt(); idtmp[1] = 0;
if (n <= 0) {
RR->identity.generate();
- tmp2 = RR->identity.toString(true);
- stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length());
- tmp2 = RR->identity.toString(false);
- stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length());
+ RR->publicIdentityStr = RR->identity.toString(false);
+ RR->secretIdentityStr = RR->identity.toString(true);
+ stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp,RR->secretIdentityStr.data(),(unsigned int)RR->secretIdentityStr.length());
+ stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length());
} else {
- n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp,sizeof(tmp) - 1);
+ n = stateObjectGet(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,tmp,sizeof(tmp) - 1);
if (n > 0) {
tmp[n] = (char)0;
- if (RR->identity.toString(false) != tmp)
+ if (RR->publicIdentityStr != tmp)
n = -1;
}
- if (n <= 0) {
- tmp2 = RR->identity.toString(false);
- stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,RR->identity.address().toInt(),tmp2.data(),(unsigned int)tmp2.length());
- }
+ if (n <= 0)
+ stateObjectPut(tptr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr.data(),(unsigned int)RR->publicIdentityStr.length());
}
try {
@@ -122,37 +127,34 @@ Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint6
Node::~Node()
{
- Mutex::Lock _l(_networks_m);
-
- _networks.clear(); // destroy all networks before shutdown
-
+ {
+ Mutex::Lock _l(_networks_m);
+ _networks.clear(); // destroy all networks before shutdown
+ }
delete RR->sa;
delete RR->topology;
delete RR->mc;
delete RR->sw;
-
-#ifdef ZT_ENABLE_CLUSTER
- delete RR->cluster;
-#endif
}
ZT_ResultCode Node::processStateUpdate(
void *tptr,
ZT_StateObjectType type,
- uint64_t id,
+ const uint64_t id[2],
const void *data,
unsigned int len)
{
ZT_ResultCode r = ZT_RESULT_OK_IGNORED;
switch(type) {
- case ZT_STATE_OBJECT_PEER:
- if (len) {
- }
- break;
-
- case ZT_STATE_OBJECT_PEER_IDENTITY:
+ case ZT_STATE_OBJECT_PEER_STATE:
if (len) {
+ const SharedPtr<Peer> p(RR->topology->getPeer(tptr,Address(id[0])));
+ if (p) {
+ r = (p->applyStateUpdate(data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED;
+ } else {
+ r = (Peer::createFromStateUpdate(RR,tptr,data,len)) ? ZT_RESULT_OK : ZT_RESULT_OK_IGNORED;
+ }
}
break;
@@ -160,9 +162,9 @@ ZT_ResultCode Node::processStateUpdate(
if (len <= (ZT_NETWORKCONFIG_DICT_CAPACITY - 1)) {
if (len < 2) {
Mutex::Lock _l(_networks_m);
- SharedPtr<Network> &nw = _networks[id];
+ SharedPtr<Network> &nw = _networks[id[0]];
if (!nw) {
- nw = SharedPtr<Network>(new Network(RR,tptr,id,(void *)0,(const NetworkConfig *)0));
+ nw = SharedPtr<Network>(new Network(RR,tptr,id[0],(void *)0,(const NetworkConfig *)0));
r = ZT_RESULT_OK;
}
} else {
@@ -172,7 +174,7 @@ ZT_ResultCode Node::processStateUpdate(
try {
if (nconf->fromDictionary(*dict)) {
Mutex::Lock _l(_networks_m);
- SharedPtr<Network> &nw = _networks[id];
+ SharedPtr<Network> &nw = _networks[id[0]];
if (nw) {
switch (nw->setConfiguration(tptr,*nconf,false)) {
default:
@@ -186,7 +188,7 @@ ZT_ResultCode Node::processStateUpdate(
break;
}
} else {
- nw = SharedPtr<Network>(new Network(RR,tptr,id,(void *)0,nconf));
+ nw = SharedPtr<Network>(new Network(RR,tptr,id[0],(void *)0,nconf));
}
} else {
r = ZT_RESULT_ERROR_BAD_PARAMETER;
@@ -205,9 +207,14 @@ ZT_ResultCode Node::processStateUpdate(
}
break;
+ case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP:
+ if (len) {
+ }
+ break;
+
case ZT_STATE_OBJECT_PLANET:
case ZT_STATE_OBJECT_MOON:
- if (len <= ZT_WORLD_MAX_SERIALIZED_LENGTH) {
+ if ((len)&&(len <= ZT_WORLD_MAX_SERIALIZED_LENGTH)) {
World w;
try {
w.deserialize(Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH>(data,len));
@@ -381,9 +388,9 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint
}
if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
+ _lastHousekeepingRun = now;
try {
- _lastHousekeepingRun = now;
- RR->topology->clean(now);
+ RR->topology->doPeriodicTasks(tptr,now);
RR->sa->clean(now);
RR->mc->clean(now);
} catch ( ... ) {
@@ -392,18 +399,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint
}
try {
-#ifdef ZT_ENABLE_CLUSTER
- // If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior
- if (RR->cluster) {
- RR->sw->doTimerTasks(tptr,now);
- RR->cluster->doPeriodicTasks();
- *nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate
- } else {
-#endif
- *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
-#ifdef ZT_ENABLE_CLUSTER
- }
-#endif
+ *nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
} catch ( ... ) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}
@@ -444,7 +440,9 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
_networks.erase(nwid);
}
- RR->node->stateObjectDelete(tptr,ZT_STATE_OBJECT_NETWORK_CONFIG,nwid);
+ uint64_t tmp[2];
+ tmp[0] = nwid; tmp[1] = 0;
+ RR->node->stateObjectDelete(tptr,ZT_STATE_OBJECT_NETWORK_CONFIG,tmp);
return ZT_RESULT_OK;
}
@@ -615,76 +613,6 @@ void Node::setNetconfMaster(void *networkControllerInstance)
RR->localNetworkController->init(RR->identity,this);
}
-/*
-ZT_ResultCode Node::clusterInit(
- unsigned int myId,
- const struct sockaddr_storage *zeroTierPhysicalEndpoints,
- unsigned int numZeroTierPhysicalEndpoints,
- int x,
- int y,
- int z,
- void (*sendFunction)(void *,unsigned int,const void *,unsigned int),
- void *sendFunctionArg,
- int (*addressToLocationFunction)(void *,const struct sockaddr_storage *,int *,int *,int *),
- void *addressToLocationFunctionArg)
-{
-#ifdef ZT_ENABLE_CLUSTER
- if (RR->cluster)
- return ZT_RESULT_ERROR_BAD_PARAMETER;
-
- std::vector<InetAddress> eps;
- for(unsigned int i=0;i<numZeroTierPhysicalEndpoints;++i)
- eps.push_back(InetAddress(zeroTierPhysicalEndpoints[i]));
- std::sort(eps.begin(),eps.end());
- RR->cluster = new Cluster(RR,myId,eps,x,y,z,sendFunction,sendFunctionArg,addressToLocationFunction,addressToLocationFunctionArg);
-
- return ZT_RESULT_OK;
-#else
- return ZT_RESULT_ERROR_UNSUPPORTED_OPERATION;
-#endif
-}
-
-ZT_ResultCode Node::clusterAddMember(unsigned int memberId)
-{
-#ifdef ZT_ENABLE_CLUSTER
- if (!RR->cluster)
- return ZT_RESULT_ERROR_BAD_PARAMETER;
- RR->cluster->addMember((uint16_t)memberId);
- return ZT_RESULT_OK;
-#else
- return ZT_RESULT_ERROR_UNSUPPORTED_OPERATION;
-#endif
-}
-
-void Node::clusterRemoveMember(unsigned int memberId)
-{
-#ifdef ZT_ENABLE_CLUSTER
- if (RR->cluster)
- RR->cluster->removeMember((uint16_t)memberId);
-#endif
-}
-
-void Node::clusterHandleIncomingMessage(const void *msg,unsigned int len)
-{
-#ifdef ZT_ENABLE_CLUSTER
- if (RR->cluster)
- RR->cluster->handleIncomingStateMessage(msg,len);
-#endif
-}
-
-void Node::clusterStatus(ZT_ClusterStatus *cs)
-{
- if (!cs)
- return;
-#ifdef ZT_ENABLE_CLUSTER
- if (RR->cluster)
- RR->cluster->status(*cs);
- else
-#endif
- memset(cs,0,sizeof(ZT_ClusterStatus));
-}
-*/
-
/****************************************************************************/
/* Node methods used only within node/ */
/****************************************************************************/
@@ -743,7 +671,7 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
va_end(ap);
tmp2[sizeof(tmp2)-1] = (char)0;
- Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
+ Utils::ztsnprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
postEvent((void *)0,ZT_EVENT_TRACE,tmp1);
}
#endif // ZT_TRACE
@@ -913,7 +841,7 @@ enum ZT_ResultCode ZT_Node_processStateUpdate(
ZT_Node *node,
void *tptr,
ZT_StateObjectType type,
- uint64_t id,
+ const uint64_t id[2],
const void *data,
unsigned int len)
{
diff --git a/node/Node.hpp b/node/Node.hpp
index f407c60c..17050d24 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -85,7 +85,7 @@ public:
ZT_ResultCode processStateUpdate(
void *tptr,
ZT_StateObjectType type,
- uint64_t id,
+ const uint64_t id[2],
const void *data,
unsigned int len);
ZT_ResultCode processWirePacket(
@@ -197,9 +197,9 @@ public:
inline bool online() const throw() { return _online; }
- inline int stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id,void *const data,const unsigned int maxlen) { return _cb.stateGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,maxlen); }
- inline void stateObjectPut(void *const tPtr,ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,data,(int)len); }
- inline void stateObjectDelete(void *const tPtr,ZT_StateObjectType type,const uint64_t id) { _cb.statePutFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
+ 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<ZT_Node *>(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<ZT_Node *>(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<ZT_Node *>(this),_uPtr,tPtr,type,id,(const void *)0,-1); }
#ifdef ZT_TRACE
void postTrace(const char *module,unsigned int line,const char *fmt,...);
diff --git a/node/Path.hpp b/node/Path.hpp
index 32bceae0..a6f56d31 100644
--- a/node/Path.hpp
+++ b/node/Path.hpp
@@ -300,6 +300,23 @@ public:
inline uint64_t lastIn() const { return _lastIn; }
/**
+ * @return Time last trust-established packet was received
+ */
+ inline uint64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
+
+ /**
+ * @param lo Last out send
+ * @param li Last in send
+ * @param lt Last trust established packet received
+ */
+ inline void updateFromRemoteState(const uint64_t lo,const uint64_t li,const uint64_t lt)
+ {
+ _lastOut = lo;
+ _lastIn = li;
+ _lastTrustEstablishedPacketReceived = lt;
+ }
+
+ /**
* Return and increment outgoing packet counter (used with Packet::armor())
*
* @return Next value that should be used for outgoing packet counter (only least significant 3 bits are used)
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 01905833..18d05875 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -32,13 +32,14 @@
#include "Switch.hpp"
#include "Network.hpp"
#include "SelfAwareness.hpp"
-#include "Cluster.hpp"
#include "Packet.hpp"
namespace ZeroTier {
Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Identity &peerIdentity) :
RR(renv),
+ _lastWroteState(0),
+ _lastReceivedStateTimestamp(0),
_lastReceive(0),
_lastNontrivialReceive(0),
_lastTriedMemorizedPath(0),
@@ -76,6 +77,7 @@ void Peer::received(
{
const uint64_t now = RR->node->now();
+/*
#ifdef ZT_ENABLE_CLUSTER
bool isClusterSuboptimalPath = false;
if ((RR->cluster)&&(hops == 0)) {
@@ -121,6 +123,7 @@ void Peer::received(
}
}
#endif
+*/
_lastReceive = now;
switch (verb) {
@@ -143,7 +146,9 @@ void Peer::received(
path->updateLinkQuality((unsigned int)(packetId & 7));
if (hops == 0) {
+ // If this is a direct packet (no hops), update existing paths or learn new ones
bool pathAlreadyKnown = false;
+
{
Mutex::Lock _l(_paths_m);
if ((path->address().ss_family == AF_INET)&&(_v4Path.p)) {
@@ -153,9 +158,6 @@ void Peer::received(
const struct sockaddr_in *const ll = reinterpret_cast<const struct sockaddr_in *>(&(_v4Path.p->localAddress()));
if ((r->sin_addr.s_addr == l->sin_addr.s_addr)&&(r->sin_port == l->sin_port)&&(rl->sin_addr.s_addr == ll->sin_addr.s_addr)&&(rl->sin_port == ll->sin_port)) {
_v4Path.lr = now;
-#ifdef ZT_ENABLE_CLUSTER
- _v4Path.localClusterSuboptimal = isClusterSuboptimalPath;
-#endif
pathAlreadyKnown = true;
}
} else if ((path->address().ss_family == AF_INET6)&&(_v6Path.p)) {
@@ -165,9 +167,6 @@ void Peer::received(
const struct sockaddr_in6 *const ll = reinterpret_cast<const struct sockaddr_in6 *>(&(_v6Path.p->localAddress()));
if ((!memcmp(r->sin6_addr.s6_addr,l->sin6_addr.s6_addr,16))&&(r->sin6_port == l->sin6_port)&&(!memcmp(rl->sin6_addr.s6_addr,ll->sin6_addr.s6_addr,16))&&(rl->sin6_port == ll->sin6_port)) {
_v6Path.lr = now;
-#ifdef ZT_ENABLE_CLUSTER
- _v6Path.localClusterSuboptimal = isClusterSuboptimalPath;
-#endif
pathAlreadyKnown = true;
}
}
@@ -177,11 +176,11 @@ void Peer::received(
Mutex::Lock _l(_paths_m);
_PeerPath *potentialNewPeerPath = (_PeerPath *)0;
if (path->address().ss_family == AF_INET) {
- if ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || ((_v4Path.p->address() != _v4ClusterPreferred)&&(path->preferenceRank() >= _v4Path.p->preferenceRank())) ) {
+ if ( (!_v4Path.p) || (!_v4Path.p->alive(now)) || (path->preferenceRank() >= _v4Path.p->preferenceRank()) ) {
potentialNewPeerPath = &_v4Path;
}
} else if (path->address().ss_family == AF_INET6) {
- if ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || ((_v6Path.p->address() != _v6ClusterPreferred)&&(path->preferenceRank() >= _v6Path.p->preferenceRank())) ) {
+ if ( (!_v6Path.p) || (!_v6Path.p->alive(now)) || (path->preferenceRank() >= _v6Path.p->preferenceRank()) ) {
potentialNewPeerPath = &_v6Path;
}
}
@@ -189,11 +188,7 @@ void Peer::received(
if (verb == Packet::VERB_OK) {
potentialNewPeerPath->lr = now;
potentialNewPeerPath->p = path;
-#ifdef ZT_ENABLE_CLUSTER
- potentialNewPeerPath->localClusterSuboptimal = isClusterSuboptimalPath;
- if (RR->cluster)
- RR->cluster->broadcastHavePeer(_id);
-#endif
+ _lastWroteState = 0; // force state write now
} else {
TRACE("got %s via unknown path %s(%s), confirming...",Packet::verbString(verb),_id.address().toString().c_str(),path->address().toString().c_str());
attemptToContactAt(tPtr,path->localAddress(),path->address(),now,true,path->nextOutgoingCounter());
@@ -203,13 +198,7 @@ void Peer::received(
}
} else if (this->trustEstablished(now)) {
// Send PUSH_DIRECT_PATHS if hops>0 (relayed) and we have a trust relationship (common network membership)
-#ifdef ZT_ENABLE_CLUSTER
- // Cluster mode disables normal PUSH_DIRECT_PATHS in favor of cluster-based peer redirection
- const bool haveCluster = (RR->cluster);
-#else
- const bool haveCluster = false;
-#endif
- if ( ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) && (!haveCluster) ) {
+ if ((now - _lastDirectPathPushSent) >= ZT_DIRECT_PATH_PUSH_INTERVAL) {
_lastDirectPathPushSent = now;
std::vector<InetAddress> pathsToPush;
@@ -278,6 +267,9 @@ void Peer::received(
}
}
}
+
+ if ((now - _lastWroteState) > ZT_PEER_STATE_WRITE_PERIOD)
+ writeState(tPtr,now);
}
bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force)
@@ -440,4 +432,160 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily)
return false;
}
+void Peer::writeState(void *tPtr,const uint64_t now)
+{
+ try {
+ Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> b;
+
+ b.append((uint8_t)1); // version
+ b.append(now);
+
+ _id.serialize(b);
+
+ {
+ Mutex::Lock _l(_paths_m);
+ unsigned int count = 0;
+ if (_v4Path.lr)
+ ++count;
+ if (_v6Path.lr)
+ ++count;
+ b.append((uint8_t)count);
+ if (_v4Path.lr) {
+ b.append(_v4Path.lr);
+ b.append(_v4Path.p->lastOut());
+ b.append(_v4Path.p->lastIn());
+ b.append(_v4Path.p->lastTrustEstablishedPacketReceived());
+ _v4Path.p->address().serialize(b);
+ _v4Path.p->localAddress().serialize(b);
+ }
+ if (_v6Path.lr) {
+ b.append(_v6Path.lr);
+ b.append(_v6Path.p->lastOut());
+ b.append(_v6Path.p->lastIn());
+ b.append(_v6Path.p->lastTrustEstablishedPacketReceived());
+ _v6Path.p->address().serialize(b);
+ _v6Path.p->localAddress().serialize(b);
+ }
+ }
+
+ // Save space by sending these as time since now at 100ms resolution
+ b.append((uint16_t)(std::max(now - _lastReceive,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastNontrivialReceive,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastTriedMemorizedPath,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastDirectPathPushSent,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastDirectPathPushReceive,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastCredentialRequestSent,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastWhoisRequestReceived,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastEchoRequestReceived,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastComRequestReceived,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastComRequestSent,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastCredentialsReceived,(uint64_t)6553500) / 100));
+ b.append((uint16_t)(std::max(now - _lastTrustEstablishedPacketReceived,(uint64_t)6553500) / 100));
+
+ b.append((uint8_t)_vProto);
+ b.append((uint8_t)_vMajor);
+ b.append((uint8_t)_vMinor);
+ b.append((uint16_t)_vRevision);
+
+ b.append((uint16_t)0); // length of additional fields
+
+ uint64_t tmp[2];
+ tmp[0] = _id.address().toInt(); tmp[1] = 0;
+ RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_STATE,tmp,b.data(),b.size());
+
+ _lastWroteState = now;
+ } catch ( ... ) {} // sanity check, should not be possible
+}
+
+bool Peer::applyStateUpdate(const void *data,unsigned int len)
+{
+ try {
+ Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> b(data,len);
+ unsigned int ptr = 0;
+
+ if (b[ptr++] != 1)
+ return false;
+ const uint64_t ts = b.at<uint64_t>(ptr); ptr += 8;
+ if (ts <= _lastReceivedStateTimestamp)
+ return false;
+
+ Identity id;
+ ptr += id.deserialize(b,ptr);
+ if (id != _id) // sanity check
+ return false;
+
+ const unsigned int pathCount = (unsigned int)b[ptr++];
+ {
+ Mutex::Lock _l(_paths_m);
+ for(unsigned int i=0;i<pathCount;++i) {
+ const uint64_t lr = b.at<uint64_t>(ptr); ptr += 8;
+ const uint64_t lastOut = b.at<uint64_t>(ptr); ptr += 8;
+ const uint64_t lastIn = b.at<uint64_t>(ptr); ptr += 8;
+ const uint64_t lastTrustEstablishedPacketReceived = b.at<uint64_t>(ptr); ptr += 8;
+ InetAddress addr,localAddr;
+ ptr += addr.deserialize(b,ptr);
+ ptr += localAddr.deserialize(b,ptr);
+ if (addr.ss_family == localAddr.ss_family) {
+ _PeerPath *p = (_PeerPath *)0;
+ switch(addr.ss_family) {
+ case AF_INET: p = &_v4Path; break;
+ case AF_INET6: p = &_v6Path; break;
+ }
+ if (p) {
+ if ( (!p->p) || ((p->p->address() != addr)||(p->p->localAddress() != localAddr)) ) {
+ p->p = RR->topology->getPath(localAddr,addr);
+ }
+ p->lr = lr;
+ p->p->updateFromRemoteState(lastOut,lastIn,lastTrustEstablishedPacketReceived);
+ }
+ }
+ }
+ }
+
+ _lastReceive = std::max(_lastReceive,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastNontrivialReceive = std::max(_lastNontrivialReceive,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastTriedMemorizedPath = std::max(_lastTriedMemorizedPath,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastDirectPathPushSent = std::max(_lastDirectPathPushSent,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastDirectPathPushReceive = std::max(_lastDirectPathPushReceive,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastCredentialRequestSent = std::max(_lastCredentialRequestSent,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastWhoisRequestReceived = std::max(_lastWhoisRequestReceived,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastEchoRequestReceived = std::max(_lastEchoRequestReceived,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastComRequestReceived = std::max(_lastComRequestReceived,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastComRequestSent = std::max(_lastComRequestSent,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastCredentialsReceived = std::max(_lastCredentialsReceived,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+ _lastTrustEstablishedPacketReceived = std::max(_lastTrustEstablishedPacketReceived,ts - ((uint64_t)b.at<uint16_t>(ptr) * 100ULL)); ptr += 2;
+
+ _vProto = (uint16_t)b[ptr++];
+ _vMajor = (uint16_t)b[ptr++];
+ _vMinor = (uint16_t)b[ptr++];
+ _vRevision = b.at<uint16_t>(ptr); ptr += 2;
+
+ _lastReceivedStateTimestamp = ts;
+
+ return true;
+ } catch ( ... ) {} // ignore invalid state updates
+ return false;
+}
+
+SharedPtr<Peer> Peer::createFromStateUpdate(const RuntimeEnvironment *renv,void *tPtr,const void *data,unsigned int len)
+{
+ try {
+ Identity id;
+ {
+ Buffer<ZT_PEER_MAX_SERIALIZED_STATE_SIZE> b(data,len);
+ unsigned int ptr = 0;
+ if (b[ptr++] != 1)
+ return SharedPtr<Peer>();
+ ptr += 8; // skip TS, don't care
+ id.deserialize(b,ptr);
+ }
+ if (id) {
+ const SharedPtr<Peer> p(new Peer(renv,renv->identity,id));
+ if (p->applyStateUpdate(data,len))
+ return renv->topology->addPeer(tPtr,p);
+ }
+ } catch ( ... ) {}
+ return SharedPtr<Peer>();
+}
+
} // namespace ZeroTier
diff --git a/node/Peer.hpp b/node/Peer.hpp
index 9b57f23e..f0eb3ee8 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -51,6 +51,8 @@
#include "Mutex.hpp"
#include "NonCopyable.hpp"
+#define ZT_PEER_MAX_SERIALIZED_STATE_SIZE (sizeof(Peer) + 32 + (sizeof(Path) * 2))
+
namespace ZeroTier {
/**
@@ -194,6 +196,23 @@ public:
bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily);
/**
+ * Write object state to external storage and/or cluster network
+ *
+ * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
+ * @param now Current time
+ */
+ void writeState(void *tPtr,const uint64_t now);
+
+ /**
+ * Apply a state update received from e.g. a remote cluster member
+ *
+ * @param data State update data
+ * @param len Length of state update
+ * @return True if state update was applied, false if ignored or invalid
+ */
+ bool applyStateUpdate(const void *data,unsigned int len);
+
+ /**
* Reset paths within a given IP scope and address family
*
* Resetting a path involves sending an ECHO to it and then deactivating
@@ -219,19 +238,6 @@ public:
}
/**
- * Indicate that the given address was provided by a cluster as a preferred destination
- *
- * @param addr Address cluster prefers that we use
- */
- inline void setClusterPreferred(const InetAddress &addr)
- {
- if (addr.ss_family == AF_INET)
- _v4ClusterPreferred = addr;
- else if (addr.ss_family == AF_INET6)
- _v6ClusterPreferred = addr;
- }
-
- /**
* Fill parameters with V4 and V6 addresses if known and alive
*
* @param now Current time
@@ -317,18 +323,6 @@ public:
else _latency = std::min(l,(unsigned int)65535);
}
-#ifdef ZT_ENABLE_CLUSTER
- /**
- * @param now Current time
- * @return True if this peer has at least one active direct path that is not cluster-suboptimal
- */
- inline bool hasLocalClusterOptimalPath(uint64_t now) const
- {
- Mutex::Lock _l(_paths_m);
- return ( ((_v4Path.p)&&(_v4Path.p->alive(now))&&(!_v4Path.localClusterSuboptimal)) || ((_v6Path.p)&&(_v6Path.p->alive(now))&&(!_v6Path.localClusterSuboptimal)) );
- }
-#endif
-
/**
* @return 256-bit secret symmetric encryption key
*/
@@ -446,25 +440,32 @@ public:
return false;
}
+ /**
+ * Create a peer from a remote state update
+ *
+ * @param renv Runtime environment
+ * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
+ * @param data State update data
+ * @param len State update length
+ * @return Peer or NULL if data was invalid
+ */
+ static SharedPtr<Peer> createFromStateUpdate(const RuntimeEnvironment *renv,void *tPtr,const void *data,unsigned int len);
+
private:
struct _PeerPath
{
-#ifdef ZT_ENABLE_CLUSTER
- _PeerPath() : lr(0),p(),localClusterSuboptimal(false) {}
-#else
_PeerPath() : lr(0),p() {}
-#endif
uint64_t lr; // time of last valid ZeroTier packet
SharedPtr<Path> p;
-#ifdef ZT_ENABLE_CLUSTER
- bool localClusterSuboptimal; // true if our cluster has determined that we should not be serving this peer
-#endif
};
uint8_t _key[ZT_PEER_SECRET_KEY_LENGTH];
const RuntimeEnvironment *RR;
+ uint64_t _lastWroteState;
+ uint64_t _lastReceivedStateTimestamp;
+
uint64_t _lastReceive; // direct or indirect
uint64_t _lastNontrivialReceive; // frames, things like netconf, etc.
uint64_t _lastTriedMemorizedPath;
@@ -483,9 +484,6 @@ private:
uint16_t _vMinor;
uint16_t _vRevision;
- InetAddress _v4ClusterPreferred;
- InetAddress _v6ClusterPreferred;
-
_PeerPath _v4Path; // IPv4 direct path
_PeerPath _v6Path; // IPv6 direct path
Mutex _paths_m;
diff --git a/node/RuntimeEnvironment.hpp b/node/RuntimeEnvironment.hpp
index d8e1d699..ee0c8c24 100644
--- a/node/RuntimeEnvironment.hpp
+++ b/node/RuntimeEnvironment.hpp
@@ -30,8 +30,8 @@
#include <string>
#include "Constants.hpp"
+#include "Utils.hpp"
#include "Identity.hpp"
-#include "Mutex.hpp"
namespace ZeroTier {
@@ -58,10 +58,13 @@ public:
,mc((Multicaster *)0)
,topology((Topology *)0)
,sa((SelfAwareness *)0)
-#ifdef ZT_ENABLE_CLUSTER
- ,cluster((Cluster *)0)
-#endif
{
+ Utils::getSecureRandom(&instanceId,sizeof(instanceId));
+ }
+
+ ~RuntimeEnvironment()
+ {
+ Utils::burn(reinterpret_cast<void *>(const_cast<char *>(secretIdentityStr.data())),(unsigned int)secretIdentityStr.length());
}
// Node instance that owns this RuntimeEnvironment
@@ -87,9 +90,11 @@ public:
Multicaster *mc;
Topology *topology;
SelfAwareness *sa;
-#ifdef ZT_ENABLE_CLUSTER
- Cluster *cluster;
-#endif
+
+ /**
+ * A random integer identifying this run of ZeroTier
+ */
+ uint32_t instanceId;
};
} // namespace ZeroTier
diff --git a/node/Switch.cpp b/node/Switch.cpp
index 211b706a..cbd73a83 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -43,7 +43,6 @@
#include "Peer.hpp"
#include "SelfAwareness.hpp"
#include "Packet.hpp"
-#include "Cluster.hpp"
namespace ZeroTier {
@@ -109,13 +108,7 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd
const Address destination(fragment.destination());
if (destination != RR->identity.address()) {
-#ifdef ZT_ENABLE_CLUSTER
- const bool isClusterFrontplane = ((RR->cluster)&&(RR->cluster->isClusterPeerFrontplane(fromAddr)));
-#else
- const bool isClusterFrontplane = false;
-#endif
-
- if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) && (!isClusterFrontplane) )
+ if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) )
return;
if (fragment.hops() < ZT_RELAY_MAX_HOPS) {
@@ -125,13 +118,6 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd
// It wouldn't hurt anything, just redundant and unnecessary.
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
if ((!relayTo)||(!relayTo->sendDirect(tPtr,fragment.data(),fragment.size(),now,false))) {
-#ifdef ZT_ENABLE_CLUSTER
- if ((RR->cluster)&&(!isClusterFrontplane)) {
- RR->cluster->relayViaCluster(Address(),destination,fragment.data(),fragment.size(),false);
- return;
- }
-#endif
-
// Don't know peer or no direct path -- so relay via someone upstream
relayTo = RR->topology->getUpstreamPeer();
if (relayTo)
@@ -198,13 +184,8 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd
//TRACE("<< %.16llx %s -> %s (size: %u)",(unsigned long long)packet->packetId(),source.toString().c_str(),destination.toString().c_str(),packet->size());
-#ifdef ZT_ENABLE_CLUSTER
- if ( (source == RR->identity.address()) && ((!RR->cluster)||(!RR->cluster->isClusterPeerFrontplane(fromAddr))) )
- return;
-#else
if (source == RR->identity.address())
return;
-#endif
if (destination != RR->identity.address()) {
if ( (!RR->topology->amRoot()) && (!path->trustEstablished(now)) && (source != RR->identity.address()) )
@@ -213,12 +194,7 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd
Packet packet(data,len);
if (packet.hops() < ZT_RELAY_MAX_HOPS) {
-#ifdef ZT_ENABLE_CLUSTER
- if (source != RR->identity.address()) // don't increment hops for cluster frontplane relays
- packet.incrementHops();
-#else
packet.incrementHops();
-#endif
SharedPtr<Peer> relayTo = RR->topology->getPeer(tPtr,destination);
if ((relayTo)&&(relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,false))) {
@@ -278,12 +254,6 @@ void Switch::onRemotePacket(void *tPtr,const InetAddress &localAddr,const InetAd
}
}
} else {
-#ifdef ZT_ENABLE_CLUSTER
- if ((RR->cluster)&&(source != RR->identity.address())) {
- RR->cluster->relayViaCluster(source,destination,packet.data(),packet.size(),_shouldUnite(now,source,destination));
- return;
- }
-#endif
relayTo = RR->topology->getUpstreamPeer(&source,1,true);
if (relayTo)
relayTo->sendDirect(tPtr,packet.data(),packet.size(),now,true);
@@ -770,14 +740,6 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
const uint64_t now = RR->node->now();
const Address destination(packet.destination());
-#ifdef ZT_ENABLE_CLUSTER
- uint64_t clusterMostRecentTs = 0;
- int clusterMostRecentMemberId = -1;
- uint8_t clusterPeerSecret[ZT_PEER_SECRET_KEY_LENGTH];
- if (RR->cluster)
- clusterMostRecentMemberId = RR->cluster->checkSendViaCluster(destination,clusterMostRecentTs,clusterPeerSecret);
-#endif
-
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,destination));
if (peer) {
/* First get the best path, and if it's dead (and this is not a root)
@@ -789,74 +751,37 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
viaPath = peer->getBestPath(now,false);
if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) {
-#ifdef ZT_ENABLE_CLUSTER
- if ((clusterMostRecentMemberId < 0)||(viaPath->lastIn() > clusterMostRecentTs)) {
-#endif
- if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
- peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter());
- viaPath->sent(now);
- }
-#ifdef ZT_ENABLE_CLUSTER
+ if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
+ peer->attemptToContactAt(tPtr,viaPath->localAddress(),viaPath->address(),now,false,viaPath->nextOutgoingCounter());
+ viaPath->sent(now);
}
-#endif
viaPath.zero();
}
-#ifdef ZT_ENABLE_CLUSTER
- if (clusterMostRecentMemberId >= 0) {
- if ((viaPath)&&(viaPath->lastIn() < clusterMostRecentTs))
- viaPath.zero();
- } else if (!viaPath) {
-#else
if (!viaPath) {
-#endif
peer->tryMemorizedPath(tPtr,now); // periodically attempt memorized or statically defined paths, if any are known
const SharedPtr<Peer> relay(RR->topology->getUpstreamPeer());
if ( (!relay) || (!(viaPath = relay->getBestPath(now,false))) ) {
if (!(viaPath = peer->getBestPath(now,true)))
return false;
}
-#ifdef ZT_ENABLE_CLUSTER
}
-#else
- }
-#endif
} else {
-#ifdef ZT_ENABLE_CLUSTER
- if (clusterMostRecentMemberId < 0) {
-#else
- requestWhois(tPtr,destination);
- return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly
-#endif
-#ifdef ZT_ENABLE_CLUSTER
- }
-#endif
+ requestWhois(tPtr,destination);
+ return false; // if we are not in cluster mode, there is no way we can send without knowing the peer directly
}
unsigned int chunkSize = std::min(packet.size(),(unsigned int)ZT_UDP_DEFAULT_PAYLOAD_MTU);
packet.setFragmented(chunkSize < packet.size());
-#ifdef ZT_ENABLE_CLUSTER
- const uint64_t trustedPathId = (viaPath) ? RR->topology->getOutboundPathTrust(viaPath->address()) : 0;
- if (trustedPathId) {
- packet.setTrusted(trustedPathId);
- } else {
- packet.armor((clusterMostRecentMemberId >= 0) ? clusterPeerSecret : peer->key(),encrypt,(viaPath) ? viaPath->nextOutgoingCounter() : 0);
- }
-#else
const uint64_t trustedPathId = RR->topology->getOutboundPathTrust(viaPath->address());
if (trustedPathId) {
packet.setTrusted(trustedPathId);
} else {
packet.armor(peer->key(),encrypt,viaPath->nextOutgoingCounter());
}
-#endif
-#ifdef ZT_ENABLE_CLUSTER
- if ( ((viaPath)&&(viaPath->send(RR,tPtr,packet.data(),chunkSize,now))) || ((clusterMostRecentMemberId >= 0)&&(RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,packet.data(),chunkSize))) ) {
-#else
if (viaPath->send(RR,tPtr,packet.data(),chunkSize,now)) {
-#endif
if (chunkSize < packet.size()) {
// Too big for one packet, fragment the rest
unsigned int fragStart = chunkSize;
@@ -869,14 +794,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
for(unsigned int fno=1;fno<totalFragments;++fno) {
chunkSize = std::min(remaining,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH));
Packet::Fragment frag(packet,fragStart,chunkSize,fno,totalFragments);
-#ifdef ZT_ENABLE_CLUSTER
- if (viaPath)
- viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
- else if (clusterMostRecentMemberId >= 0)
- RR->cluster->sendViaCluster(clusterMostRecentMemberId,destination,frag.data(),frag.size());
-#else
viaPath->send(RR,tPtr,frag.data(),frag.size(),now);
-#endif
fragStart += chunkSize;
remaining -= chunkSize;
}
diff --git a/node/Topology.cpp b/node/Topology.cpp
index d4b424ff..09a1a895 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -69,7 +69,9 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
_amRoot(false)
{
uint8_t tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PLANET,0,tmp,sizeof(tmp));
+ uint64_t idtmp[2];
+ idtmp[0] = 0; idtmp[1] = 0;
+ int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PLANET,idtmp,tmp,sizeof(tmp));
if (n > 0) {
try {
World cachedPlanet;
@@ -106,8 +108,6 @@ SharedPtr<Peer> Topology::addPeer(void *tPtr,const SharedPtr<Peer> &peer)
np = hp;
}
- saveIdentity(tPtr,np->identity());
-
return np;
}
@@ -126,18 +126,20 @@ SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
}
try {
- Identity id(_getIdentity(tPtr,zta));
- if (id) {
- SharedPtr<Peer> np(new Peer(RR,RR->identity,id));
- {
- Mutex::Lock _l(_peers_m);
- SharedPtr<Peer> &ap = _peers[zta];
- if (!ap)
- ap.swap(np);
+ char buf[ZT_PEER_MAX_SERIALIZED_STATE_SIZE];
+ uint64_t idbuf[2]; idbuf[0] = zta.toInt(); idbuf[1] = 0;
+ int len = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_STATE,idbuf,buf,(unsigned int)sizeof(buf));
+ if (len > 0) {
+ Mutex::Lock _l(_peers_m);
+ SharedPtr<Peer> &ap = _peers[zta];
+ if (ap)
return ap;
- }
+ ap = Peer::createFromStateUpdate(RR,tPtr,buf,len);
+ if (!ap)
+ _peers.erase(zta);
+ return ap;
}
- } catch ( ... ) {} // invalid identity on disk?
+ } catch ( ... ) {} // ignore invalid identities or other strage failures
return SharedPtr<Peer>();
}
@@ -152,15 +154,7 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
if (ap)
return (*ap)->identity();
}
- return _getIdentity(tPtr,zta);
-}
-
-void Topology::saveIdentity(void *tPtr,const Identity &id)
-{
- if (id) {
- const std::string tmp(id.toString(false));
- RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,id.address().toInt(),tmp.data(),(unsigned int)tmp.length());
- }
+ return Identity();
}
SharedPtr<Peer> Topology::getUpstreamPeer(const Address *avoid,unsigned int avoidCount,bool strictAvoid)
@@ -329,7 +323,9 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
try {
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> sbuf;
existing->serialize(sbuf,false);
- RR->node->stateObjectPut(tPtr,(existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON,existing->id(),sbuf.data(),sbuf.size());
+ uint64_t idtmp[2];
+ idtmp[0] = existing->id(); idtmp[1] = 0;
+ RR->node->stateObjectPut(tPtr,(existing->type() == World::TYPE_PLANET) ? ZT_STATE_OBJECT_PLANET : ZT_STATE_OBJECT_MOON,idtmp,sbuf.data(),sbuf.size());
} catch ( ... ) {}
_memoizeUpstreams(tPtr);
@@ -340,7 +336,9 @@ bool Topology::addWorld(void *tPtr,const World &newWorld,bool alwaysAcceptNew)
void Topology::addMoon(void *tPtr,const uint64_t id,const Address &seed)
{
char tmp[ZT_WORLD_MAX_SERIALIZED_LENGTH];
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_MOON,id,tmp,sizeof(tmp));
+ uint64_t idtmp[2];
+ idtmp[0] = id; idtmp[1] = 0;
+ int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_MOON,idtmp,tmp,sizeof(tmp));
if (n > 0) {
try {
World w;
@@ -369,7 +367,9 @@ void Topology::removeMoon(void *tPtr,const uint64_t id)
if (m->id() != id) {
nm.push_back(*m);
} else {
- RR->node->stateObjectDelete(tPtr,ZT_STATE_OBJECT_MOON,id);
+ uint64_t idtmp[2];
+ idtmp[0] = id; idtmp[1] = 0;
+ RR->node->stateObjectDelete(tPtr,ZT_STATE_OBJECT_MOON,idtmp);
}
}
_moons.swap(nm);
@@ -384,7 +384,7 @@ void Topology::removeMoon(void *tPtr,const uint64_t id)
_memoizeUpstreams(tPtr);
}
-void Topology::clean(uint64_t now)
+void Topology::doPeriodicTasks(void *tPtr,uint64_t now)
{
{
Mutex::Lock _l1(_peers_m);
@@ -393,10 +393,14 @@ void Topology::clean(uint64_t now)
Address *a = (Address *)0;
SharedPtr<Peer> *p = (SharedPtr<Peer> *)0;
while (i.next(a,p)) {
- if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) )
+ if ( (!(*p)->isAlive(now)) && (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),*a) == _upstreamAddresses.end()) ) {
_peers.erase(*a);
+ } else {
+ (*p)->writeState(tPtr,now);
+ }
}
}
+
{
Mutex::Lock _l(_paths_m);
Hashtable< Path::HashKey,SharedPtr<Path> >::Iterator i(_paths);
@@ -409,19 +413,6 @@ void Topology::clean(uint64_t now)
}
}
-Identity Topology::_getIdentity(void *tPtr,const Address &zta)
-{
- char tmp[512];
- int n = RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER_IDENTITY,zta.toInt(),tmp,sizeof(tmp) - 1);
- if (n > 0) {
- tmp[n] = (char)0;
- try {
- return Identity(tmp);
- } catch ( ... ) {} // ignore invalid IDs
- }
- return Identity();
-}
-
void Topology::_memoizeUpstreams(void *tPtr)
{
// assumes _upstreams_m and _peers_m are locked
@@ -434,10 +425,8 @@ void Topology::_memoizeUpstreams(void *tPtr)
} else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) {
_upstreamAddresses.push_back(i->identity.address());
SharedPtr<Peer> &hp = _peers[i->identity.address()];
- if (!hp) {
+ if (!hp)
hp = new Peer(RR,RR->identity,i->identity);
- saveIdentity(tPtr,i->identity);
- }
}
}
@@ -448,10 +437,8 @@ void Topology::_memoizeUpstreams(void *tPtr)
} else if (std::find(_upstreamAddresses.begin(),_upstreamAddresses.end(),i->identity.address()) == _upstreamAddresses.end()) {
_upstreamAddresses.push_back(i->identity.address());
SharedPtr<Peer> &hp = _peers[i->identity.address()];
- if (!hp) {
+ if (!hp)
hp = new Peer(RR,RR->identity,i->identity);
- saveIdentity(tPtr,i->identity);
- }
}
}
}
diff --git a/node/Topology.hpp b/node/Topology.hpp
index d06ba94b..32e38dd3 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -82,6 +82,13 @@ public:
SharedPtr<Peer> getPeer(void *tPtr,const Address &zta);
/**
+ * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
+ * @param zta ZeroTier address of peer
+ * @return Identity or NULL identity if not found
+ */
+ Identity getIdentity(void *tPtr,const Address &zta);
+
+ /**
* Get a peer only if it is presently in memory (no disk cache)
*
* This also does not update the lastUsed() time for peers, which means
@@ -117,26 +124,6 @@ public:
}
/**
- * Get the identity of a peer
- *
- * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
- * @param zta ZeroTier address of peer
- * @return Identity or NULL Identity if not found
- */
- Identity getIdentity(void *tPtr,const Address &zta);
-
- /**
- * Cache an identity
- *
- * This is done automatically on addPeer(), and so is only useful for
- * cluster identity replication.
- *
- * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
- * @param id Identity to cache
- */
- void saveIdentity(void *tPtr,const Identity &id);
-
- /**
* Get the current best upstream peer
*
* @return Root server with lowest latency or NULL if none
@@ -308,7 +295,7 @@ public:
/**
* Clean and flush database
*/
- void clean(uint64_t now);
+ void doPeriodicTasks(void *tPtr,uint64_t now);
/**
* @param now Current time
diff --git a/node/Utils.cpp b/node/Utils.cpp
index d69e5335..d2321e16 100644
--- a/node/Utils.cpp
+++ b/node/Utils.cpp
@@ -244,8 +244,7 @@ bool Utils::scopy(char *dest,unsigned int len,const char *src)
return true;
}
-unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...)
- throw(std::length_error)
+unsigned int Utils::ztsnprintf(char *buf,unsigned int len,const char *fmt,...)
{
va_list ap;
@@ -256,7 +255,7 @@ unsigned int Utils::snprintf(char *buf,unsigned int len,const char *fmt,...)
if ((n >= (int)len)||(n < 0)) {
if (len)
buf[len - 1] = (char)0;
- throw std::length_error("buf[] overflow in Utils::snprintf");
+ throw std::length_error("buf[] overflow");
}
return (unsigned int)n;
diff --git a/node/Utils.hpp b/node/Utils.hpp
index 25a90055..212ef247 100644
--- a/node/Utils.hpp
+++ b/node/Utils.hpp
@@ -244,8 +244,7 @@ public:
* @param ... Format arguments
* @throws std::length_error buf[] too short (buf[] will still be left null-terminated)
*/
- static unsigned int snprintf(char *buf,unsigned int len,const char *fmt,...)
- throw(std::length_error);
+ static unsigned int ztsnprintf(char *buf,unsigned int len,const char *fmt,...);
/**
* Count the number of bits set in an integer
diff --git a/one.cpp b/one.cpp
index 93504cfb..cbf09121 100644
--- a/one.cpp
+++ b/one.cpp
@@ -260,9 +260,9 @@ static int cli(int argc,char **argv)
if (hd) {
char p[4096];
#ifdef __APPLE__
- Utils::snprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd);
+ Utils::ztsnprintf(p,sizeof(p),"%s/Library/Application Support/ZeroTier/One/authtoken.secret",hd);
#else
- Utils::snprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd);
+ Utils::ztsnprintf(p,sizeof(p),"%s/.zeroTierOneAuthToken",hd);
#endif
OSUtils::readFile(p,authToken);
}
@@ -278,7 +278,7 @@ static int cli(int argc,char **argv)
InetAddress addr;
{
char addrtmp[256];
- Utils::snprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port);
+ Utils::ztsnprintf(addrtmp,sizeof(addrtmp),"%s/%u",ip.c_str(),port);
addr = InetAddress(addrtmp);
}
@@ -366,7 +366,7 @@ static int cli(int argc,char **argv)
std::string addr = path["address"];
const uint64_t now = OSUtils::now();
const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0;
- Utils::snprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq);
bestPath = tmp;
break;
}
@@ -378,7 +378,7 @@ static int cli(int argc,char **argv)
int64_t vmin = p["versionMinor"];
int64_t vrev = p["versionRev"];
if (vmaj >= 0) {
- Utils::snprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev);
+ Utils::ztsnprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev);
} else {
ver[0] = '-';
ver[1] = (char)0;
@@ -527,9 +527,9 @@ static int cli(int argc,char **argv)
const uint64_t seed = Utils::hexStrToU64(arg2.c_str());
if ((worldId)&&(seed)) {
char jsons[1024];
- Utils::snprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str());
+ Utils::ztsnprintf(jsons,sizeof(jsons),"{\"seed\":\"%s\"}",arg2.c_str());
char cl[128];
- Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
+ Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
requestHeaders["Content-Type"] = "application/json";
requestHeaders["Content-Length"] = cl;
unsigned int scode = Http::POST(
@@ -579,11 +579,11 @@ static int cli(int argc,char **argv)
if (eqidx != std::string::npos) {
if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) {
char jsons[1024];
- Utils::snprintf(jsons,sizeof(jsons),"{\"%s\":%s}",
+ Utils::ztsnprintf(jsons,sizeof(jsons),"{\"%s\":%s}",
arg2.substr(0,eqidx).c_str(),
(((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false"));
char cl[128];
- Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
+ Utils::ztsnprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
requestHeaders["Content-Type"] = "application/json";
requestHeaders["Content-Length"] = cl;
unsigned int scode = Http::POST(
@@ -864,7 +864,7 @@ static int idtool(int argc,char **argv)
Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wbuf;
w.serialize(wbuf);
char fn[128];
- Utils::snprintf(fn,sizeof(fn),"%.16llx.moon",w.id());
+ Utils::ztsnprintf(fn,sizeof(fn),"%.16llx.moon",w.id());
OSUtils::writeFile(fn,wbuf.data(),wbuf.size());
printf("wrote %s (signed world with timestamp %llu)" ZT_EOL_S,fn,(unsigned long long)now);
}
diff --git a/osdep/BSDEthernetTap.cpp b/osdep/BSDEthernetTap.cpp
index 5bb5fbd1..f07f9e5a 100644
--- a/osdep/BSDEthernetTap.cpp
+++ b/osdep/BSDEthernetTap.cpp
@@ -114,8 +114,8 @@ BSDEthernetTap::BSDEthernetTap(
std::vector<std::string> devFiles(OSUtils::listDirectory("/dev"));
for(int i=9993;i<(9993+128);++i) {
- Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
- Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
+ Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
+ Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
if (std::find(devFiles.begin(),devFiles.end(),std::string(tmpdevname)) == devFiles.end()) {
long cpid = (long)vfork();
if (cpid == 0) {
@@ -152,8 +152,8 @@ BSDEthernetTap::BSDEthernetTap(
/* Other BSDs like OpenBSD only have a limited number of tap devices that cannot be renamed */
for(int i=0;i<64;++i) {
- Utils::snprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
- Utils::snprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
+ Utils::ztsnprintf(tmpdevname,sizeof(tmpdevname),"tap%d",i);
+ Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/%s",tmpdevname);
_fd = ::open(devpath,O_RDWR);
if (_fd > 0) {
_dev = tmpdevname;
@@ -171,9 +171,9 @@ BSDEthernetTap::BSDEthernetTap(
}
// Configure MAC address and MTU, bring interface up
- Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
- Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu);
- Utils::snprintf(metstr,sizeof(metstr),"%u",_metric);
+ Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
+ Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu);
+ Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric);
long cpid = (long)vfork();
if (cpid == 0) {
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
@@ -385,7 +385,7 @@ void BSDEthernetTap::setMtu(unsigned int mtu)
long cpid = (long)vfork();
if (cpid == 0) {
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%u",mtu);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
_exit(-1);
} else if (cpid > 0) {
diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp
index a0b47367..b1fe5921 100644
--- a/osdep/Binder.hpp
+++ b/osdep/Binder.hpp
@@ -180,7 +180,7 @@ public:
const unsigned long pid = (unsigned long)getpid();
// Get all device names
- Utils::snprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
+ Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/dev",pid);
FILE *procf = fopen(fn,"r");
if (procf) {
while (fgets(tmp,sizeof(tmp),procf)) {
@@ -196,7 +196,7 @@ public:
}
// Get IPv6 addresses (and any device names we don't already know)
- Utils::snprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
+ Utils::ztsnprintf(fn,sizeof(fn),"/proc/%lu/net/if_inet6",pid);
procf = fopen(fn,"r");
if (procf) {
while (fgets(tmp,sizeof(tmp),procf)) {
diff --git a/osdep/Http.cpp b/osdep/Http.cpp
index f1d3bfe2..3c556f44 100644
--- a/osdep/Http.cpp
+++ b/osdep/Http.cpp
@@ -244,10 +244,10 @@ unsigned int Http::_do(
try {
char tmp[1024];
- Utils::snprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s %s HTTP/1.1\r\n",method,path);
handler.writeBuf.append(tmp);
for(std::map<std::string,std::string>::const_iterator h(requestHeaders.begin());h!=requestHeaders.end();++h) {
- Utils::snprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s: %s\r\n",h->first.c_str(),h->second.c_str());
handler.writeBuf.append(tmp);
}
handler.writeBuf.append("\r\n");
diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp
index ccaa92ef..fc5199f1 100644
--- a/osdep/LinuxEthernetTap.cpp
+++ b/osdep/LinuxEthernetTap.cpp
@@ -97,7 +97,7 @@ LinuxEthernetTap::LinuxEthernetTap(
char procpath[128],nwids[32];
struct stat sbuf;
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid);
+ Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid);
Mutex::Lock _l(__tapCreateLock); // create only one tap at a time, globally
@@ -134,7 +134,7 @@ LinuxEthernetTap::LinuxEthernetTap(
std::map<std::string,std::string>::const_iterator gdmEntry = globalDeviceMap.find(nwids);
if (gdmEntry != globalDeviceMap.end()) {
Utils::scopy(ifr.ifr_name,sizeof(ifr.ifr_name),gdmEntry->second.c_str());
- Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
+ Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
recalledDevice = (stat(procpath,&sbuf) != 0);
}
@@ -142,8 +142,8 @@ LinuxEthernetTap::LinuxEthernetTap(
#ifdef __SYNOLOGY__
int devno = 50;
do {
- Utils::snprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++);
- Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
+ Utils::ztsnprintf(ifr.ifr_name,sizeof(ifr.ifr_name),"eth%d",devno++);
+ Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
} while (stat(procpath,&sbuf) == 0); // try zt#++ until we find one that does not exist
#else
char devno = 0;
@@ -158,7 +158,7 @@ LinuxEthernetTap::LinuxEthernetTap(
_base32_5_to_8(reinterpret_cast<const uint8_t *>(tmp2) + 5,tmp3 + 10);
tmp3[15] = (char)0;
memcpy(ifr.ifr_name,tmp3,16);
- Utils::snprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
+ Utils::ztsnprintf(procpath,sizeof(procpath),"/proc/sys/net/ipv4/conf/%s",ifr.ifr_name);
} while (stat(procpath,&sbuf) == 0);
#endif
}
diff --git a/osdep/OSUtils.cpp b/osdep/OSUtils.cpp
index ac9452e1..06508e77 100644
--- a/osdep/OSUtils.cpp
+++ b/osdep/OSUtils.cpp
@@ -134,7 +134,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
if (date.QuadPart > 0) {
date.QuadPart -= adjust.QuadPart;
if ((uint64_t)((date.QuadPart / 10000000) * 1000) < olderThan) {
- Utils::snprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
+ Utils::ztsnprintf(tmp, sizeof(tmp), "%s\\%s", path, ffd.cFileName);
if (DeleteFileA(tmp))
++cleaned;
}
@@ -157,7 +157,7 @@ long OSUtils::cleanDirectory(const char *path,const uint64_t olderThan)
break;
if (dptr) {
if ((strcmp(dptr->d_name,"."))&&(strcmp(dptr->d_name,".."))&&(dptr->d_type == DT_REG)) {
- Utils::snprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%s/%s",path,dptr->d_name);
if (stat(tmp,&st) == 0) {
uint64_t mt = (uint64_t)(st.st_mtime);
if ((mt > 0)&&((mt * 1000) < olderThan)) {
@@ -464,7 +464,7 @@ std::string OSUtils::jsonString(const nlohmann::json &jv,const char *dfl)
return jv;
} else if (jv.is_number()) {
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%llu",(uint64_t)jv);
return tmp;
} else if (jv.is_boolean()) {
return ((bool)jv ? std::string("1") : std::string("0"));
diff --git a/osdep/OSXEthernetTap.cpp b/osdep/OSXEthernetTap.cpp
index f5e1c43f..e082408e 100644
--- a/osdep/OSXEthernetTap.cpp
+++ b/osdep/OSXEthernetTap.cpp
@@ -336,7 +336,7 @@ OSXEthernetTap::OSXEthernetTap(
char devpath[64],ethaddr[64],mtustr[32],metstr[32],nwids[32];
struct stat stattmp;
- Utils::snprintf(nwids,sizeof(nwids),"%.16llx",nwid);
+ Utils::ztsnprintf(nwids,sizeof(nwids),"%.16llx",nwid);
Mutex::Lock _gl(globalTapCreateLock);
@@ -391,13 +391,13 @@ OSXEthernetTap::OSXEthernetTap(
// Open the first unused tap device if we didn't recall a previous one.
if (!recalledDevice) {
for(int i=0;i<64;++i) {
- Utils::snprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
+ Utils::ztsnprintf(devpath,sizeof(devpath),"/dev/zt%d",i);
if (stat(devpath,&stattmp))
throw std::runtime_error("no more TAP devices available");
_fd = ::open(devpath,O_RDWR);
if (_fd > 0) {
char foo[16];
- Utils::snprintf(foo,sizeof(foo),"zt%d",i);
+ Utils::ztsnprintf(foo,sizeof(foo),"zt%d",i);
_dev = foo;
break;
}
@@ -413,9 +413,9 @@ OSXEthernetTap::OSXEthernetTap(
}
// Configure MAC address and MTU, bring interface up
- Utils::snprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
- Utils::snprintf(mtustr,sizeof(mtustr),"%u",_mtu);
- Utils::snprintf(metstr,sizeof(metstr),"%u",_metric);
+ Utils::ztsnprintf(ethaddr,sizeof(ethaddr),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
+ Utils::ztsnprintf(mtustr,sizeof(mtustr),"%u",_mtu);
+ Utils::ztsnprintf(metstr,sizeof(metstr),"%u",_metric);
long cpid = (long)vfork();
if (cpid == 0) {
::execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"lladdr",ethaddr,"mtu",mtustr,"metric",metstr,"up",(const char *)0);
@@ -636,7 +636,7 @@ void OSXEthernetTap::setMtu(unsigned int mtu)
long cpid = (long)vfork();
if (cpid == 0) {
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%u",mtu);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%u",mtu);
execl("/sbin/ifconfig","/sbin/ifconfig",_dev.c_str(),"mtu",tmp,(const char *)0);
_exit(-1);
} else if (cpid > 0) {
diff --git a/osdep/PortMapper.cpp b/osdep/PortMapper.cpp
index 99286172..df868e7a 100644
--- a/osdep/PortMapper.cpp
+++ b/osdep/PortMapper.cpp
@@ -205,7 +205,7 @@ public:
memset(externalip,0,sizeof(externalip));
memset(&urls,0,sizeof(urls));
memset(&data,0,sizeof(data));
- Utils::snprintf(inport,sizeof(inport),"%d",localPort);
+ Utils::ztsnprintf(inport,sizeof(inport),"%d",localPort);
if ((UPNP_GetValidIGD(devlist,&urls,&data,lanaddr,sizeof(lanaddr)))&&(lanaddr[0])) {
#ifdef ZT_PORTMAPPER_TRACE
@@ -220,7 +220,7 @@ public:
int tryPort = (int)localPort + tries;
if (tryPort >= 65535)
tryPort = (tryPort - 65535) + 1025;
- Utils::snprintf(outport,sizeof(outport),"%u",tryPort);
+ Utils::ztsnprintf(outport,sizeof(outport),"%u",tryPort);
// First check and see if this port is already mapped to the
// same unique name. If so, keep this mapping and don't try
diff --git a/osdep/WindowsEthernetTap.cpp b/osdep/WindowsEthernetTap.cpp
index c5d82d8e..b96ad791 100644
--- a/osdep/WindowsEthernetTap.cpp
+++ b/osdep/WindowsEthernetTap.cpp
@@ -484,7 +484,7 @@ WindowsEthernetTap::WindowsEthernetTap(
char tag[24];
// We "tag" registry entries with the network ID to identify persistent devices
- Utils::snprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
+ Utils::ztsnprintf(tag,sizeof(tag),"%.16llx",(unsigned long long)nwid);
Mutex::Lock _l(_systemTapInitLock);
@@ -601,10 +601,10 @@ WindowsEthernetTap::WindowsEthernetTap(
if (_netCfgInstanceId.length() > 0) {
char tmps[64];
- unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1;
+ unsigned int tmpsl = Utils::ztsnprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac[0],(unsigned int)mac[1],(unsigned int)mac[2],(unsigned int)mac[3],(unsigned int)mac[4],(unsigned int)mac[5]) + 1;
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"NetworkAddress",REG_SZ,tmps,tmpsl);
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MAC",REG_SZ,tmps,tmpsl);
- tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu);
+ tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu);
RegSetKeyValueA(nwAdapters,_mySubkeyName.c_str(),"MTU",REG_SZ,tmps,tmpsl);
DWORD tmp = 0;
@@ -879,7 +879,7 @@ void WindowsEthernetTap::setMtu(unsigned int mtu)
HKEY nwAdapters;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ | KEY_WRITE, &nwAdapters) == ERROR_SUCCESS) {
char tmps[64];
- unsigned int tmpsl = Utils::snprintf(tmps, sizeof(tmps), "%d", mtu);
+ unsigned int tmpsl = Utils::ztsnprintf(tmps, sizeof(tmps), "%d", mtu);
RegSetKeyValueA(nwAdapters, _mySubkeyName.c_str(), "MTU", REG_SZ, tmps, tmpsl);
RegCloseKey(nwAdapters);
}
@@ -902,7 +902,7 @@ void WindowsEthernetTap::threadMain()
HANDLE wait4[3];
OVERLAPPED tapOvlRead,tapOvlWrite;
- Utils::snprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
+ Utils::ztsnprintf(tapPath,sizeof(tapPath),"\\\\.\\Global\\%s.tap",_netCfgInstanceId.c_str());
try {
while (_run) {
diff --git a/selftest.cpp b/selftest.cpp
index 8175d708..ff171aa3 100644
--- a/selftest.cpp
+++ b/selftest.cpp
@@ -831,7 +831,7 @@ static int testOther()
memset(key, 0, sizeof(key));
memset(value, 0, sizeof(value));
for(unsigned int q=0;q<32;++q) {
- Utils::snprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000));
+ Utils::ztsnprintf(key[q],16,"%.8lx",(unsigned long)(rand() % 1000) + (q * 1000));
int r = rand() % 128;
for(int x=0;x<r;++x)
value[q][x] = ("0123456789\0\t\r\n= ")[rand() % 16];
diff --git a/service/ClusterDefinition.hpp b/service/ClusterDefinition.hpp
index 9947e46b..b6317ff7 100644
--- a/service/ClusterDefinition.hpp
+++ b/service/ClusterDefinition.hpp
@@ -72,7 +72,7 @@ public:
return;
char myAddressStr[64];
- Utils::snprintf(myAddressStr,sizeof(myAddressStr),"%.10llx",myAddress);
+ Utils::ztsnprintf(myAddressStr,sizeof(myAddressStr),"%.10llx",myAddress);
std::vector<std::string> lines(OSUtils::split(cf.c_str(),"\r\n","",""));
for(std::vector<std::string>::iterator l(lines.begin());l!=lines.end();++l) {
diff --git a/service/OneService.cpp b/service/OneService.cpp
index 644454bc..b5b11111 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -154,9 +154,6 @@ namespace ZeroTier { typedef BSDEthernetTap EthernetTap; }
// How often to check for local interface addresses
#define ZT_LOCAL_INTERFACE_CHECK_INTERVAL 60000
-// Clean files from iddb.d that are older than this (60 days)
-#define ZT_IDDB_CLEANUP_AGE 5184000000ULL
-
// Maximum write buffer size for outgoing TCP connections (sanity limit)
#define ZT_TCP_MAX_WRITEQ_SIZE 33554432
@@ -210,10 +207,10 @@ static void _networkToJson(nlohmann::json &nj,const ZT_VirtualNetworkConfig *nc,
case ZT_NETWORK_TYPE_PUBLIC: ntype = "PUBLIC"; break;
}
- Utils::snprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",nc->nwid);
nj["id"] = tmp;
nj["nwid"] = tmp;
- Utils::snprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff));
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(unsigned int)((nc->mac >> 40) & 0xff),(unsigned int)((nc->mac >> 32) & 0xff),(unsigned int)((nc->mac >> 24) & 0xff),(unsigned int)((nc->mac >> 16) & 0xff),(unsigned int)((nc->mac >> 8) & 0xff),(unsigned int)(nc->mac & 0xff));
nj["mac"] = tmp;
nj["name"] = nc->name;
nj["status"] = nstatus;
@@ -260,12 +257,12 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
case ZT_PEER_ROLE_PLANET: prole = "PLANET"; break;
}
- Utils::snprintf(tmp,sizeof(tmp),"%.10llx",peer->address);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",peer->address);
pj["address"] = tmp;
pj["versionMajor"] = peer->versionMajor;
pj["versionMinor"] = peer->versionMinor;
pj["versionRev"] = peer->versionRev;
- Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",peer->versionMajor,peer->versionMinor,peer->versionRev);
pj["version"] = tmp;
pj["latency"] = peer->latency;
pj["role"] = prole;
@@ -289,7 +286,7 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
static void _moonToJson(nlohmann::json &mj,const World &world)
{
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%.16llx",world.id());
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",world.id());
mj["id"] = tmp;
mj["timestamp"] = world.timestamp();
mj["signature"] = Utils::hex(world.signature().data,(unsigned int)world.signature().size());
@@ -312,8 +309,8 @@ class OneServiceImpl;
static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,enum ZT_VirtualNetworkConfigOperation op,const ZT_VirtualNetworkConfig *nwconf);
static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData);
-static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len);
-static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen);
+static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len);
+static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen);
static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl);
static void SnodeVirtualNetworkFrameFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t nwid,void **nuptr,uint64_t sourceMac,uint64_t destMac,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len);
static int SnodePathCheckFunction(ZT_Node *node,void *uptr,void *tptr,uint64_t ztaddr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *remoteAddr);
@@ -414,7 +411,6 @@ public:
const std::string _homePath;
std::string _authToken;
std::string _controllerDbPath;
- const std::string _iddbPath;
const std::string _networksPath;
const std::string _moonsPath;
@@ -513,7 +509,6 @@ public:
OneServiceImpl(const char *hp,unsigned int port) :
_homePath((hp) ? hp : ".")
,_controllerDbPath(_homePath + ZT_PATH_SEPARATOR_S "controller.d")
- ,_iddbPath(_homePath + ZT_PATH_SEPARATOR_S "iddb.d")
,_networksPath(_homePath + ZT_PATH_SEPARATOR_S "networks.d")
,_moonsPath(_homePath + ZT_PATH_SEPARATOR_S "moons.d")
,_controller((EmbeddedNetworkController *)0)
@@ -687,7 +682,7 @@ public:
// Save primary port to a file so CLIs and GUIs can learn it easily
char portstr[64];
- Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]);
+ Utils::ztsnprintf(portstr,sizeof(portstr),"%u",_ports[0]);
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S "zerotier-one.port").c_str(),std::string(portstr));
// Attempt to bind to a secondary port chosen from our ZeroTier address.
@@ -725,13 +720,16 @@ public:
}
if (_ports[2]) {
char uniqueName[64];
- Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]);
+ Utils::ztsnprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]);
_portMapper = new PortMapper(_ports[2],uniqueName);
}
}
}
#endif
+ // Delete legacy iddb.d if present (cleanup)
+ OSUtils::rmDashRf((_homePath + ZT_PATH_SEPARATOR_S "iddb.d").c_str());
+
// Network controller is now enabled by default for desktop and server
_controller = new EmbeddedNetworkController(_node,_controllerDbPath.c_str());
_node->setNetconfMaster((void *)_controller);
@@ -781,7 +779,6 @@ public:
uint64_t lastBindRefresh = 0;
uint64_t lastUpdateCheck = clockShouldBe;
uint64_t lastLocalInterfaceAddressCheck = (clockShouldBe - ZT_LOCAL_INTERFACE_CHECK_INTERVAL) + 15000; // do this in 15s to give portmapper time to configure and other things time to settle
- uint64_t lastCleanedIddb = 0;
uint64_t lastTcpCheck = 0;
for(;;) {
_run_m.lock();
@@ -797,12 +794,6 @@ public:
const uint64_t now = OSUtils::now();
- // Clean iddb.d on start and every 24 hours
- if ((now - lastCleanedIddb) > 86400000) {
- lastCleanedIddb = now;
- OSUtils::cleanDirectory(_iddbPath.c_str(),now - ZT_IDDB_CLEANUP_AGE);
- }
-
// Attempt to detect sleep/wake events by detecting delay overruns
bool restarted = false;
if ((now > clockShouldBe)&&((now - clockShouldBe) > 10000)) {
@@ -1027,7 +1018,7 @@ public:
return NULL;
}
- virtual Node * getNode()
+ virtual Node *getNode()
{
return _node;
}
@@ -1069,7 +1060,7 @@ public:
n->second.settings = settings;
char nlcpath[4096];
- Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid);
+ Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_networksPath.c_str(),nwid);
FILE *out = fopen(nlcpath,"w");
if (out) {
fprintf(out,"allowManaged=%d\n",(int)n->second.settings.allowManaged);
@@ -1188,7 +1179,7 @@ public:
ZT_NodeStatus status;
_node->status(&status);
- Utils::snprintf(tmp,sizeof(tmp),"%.10llx",status.address);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.10llx",status.address);
res["address"] = tmp;
res["publicIdentity"] = status.publicIdentity;
res["online"] = (bool)(status.online != 0);
@@ -1197,7 +1188,7 @@ public:
res["versionMinor"] = ZEROTIER_ONE_VERSION_MINOR;
res["versionRev"] = ZEROTIER_ONE_VERSION_REVISION;
res["versionBuild"] = ZEROTIER_ONE_VERSION_BUILD;
- Utils::snprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%d.%d.%d",ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
res["version"] = tmp;
res["clock"] = OSUtils::now();
@@ -1220,34 +1211,20 @@ public:
res["planetWorldId"] = planet.id();
res["planetWorldTimestamp"] = planet.timestamp();
-/*
-#ifdef ZT_ENABLE_CLUSTER
- json cj;
- ZT_ClusterStatus cs;
- _node->clusterStatus(&cs);
- if (cs.clusterSize >= 1) {
- json cja = json::array();
- for(unsigned int i=0;i<cs.clusterSize;++i) {
- json cjm;
- cjm["id"] = (int)cs.members[i].id;
- cjm["msSinceLastHeartbeat"] = cs.members[i].msSinceLastHeartbeat;
- cjm["alive"] = (bool)(cs.members[i].alive != 0);
- cjm["x"] = cs.members[i].x;
- cjm["y"] = cs.members[i].y;
- cjm["z"] = cs.members[i].z;
- cjm["load"] = cs.members[i].load;
- cjm["peers"] = cs.members[i].peers;
- cja.push_back(cjm);
+ {
+ json cj(json::object());
+ Mutex::Lock _l(_tcpConnections_m);
+ Mutex::Lock _l2(_localConfig_m);
+ for(std::vector<InetAddress>::const_iterator ca(_clusterBackplaneAddresses.begin());ca!=_clusterBackplaneAddresses.end();++ca) {
+ uint64_t up = 0;
+ for(std::vector<TcpConnection *>::const_iterator c(_tcpConnections.begin());c!=_tcpConnections.end();++c) {
+ if (((*c)->remoteAddr == *ca)&&((*c)->clusterMemberId)&&((*c)->lastReceive > up))
+ up = (*c)->lastReceive;
+ }
+ cj[ca->toString()] = up;
}
- cj["members"] = cja;
- cj["myId"] = (int)cs.myId;
- cj["clusterSize"] = cs.clusterSize;
+ res["cluster"] = cj;
}
- res["cluster"] = cj;
-#else
- res["cluster"] = json();
-#endif
-*/
scode = 200;
} else if (ps[0] == "moon") {
@@ -1373,7 +1350,7 @@ public:
if ((scode != 200)&&(seed != 0)) {
char tmp[64];
- Utils::snprintf(tmp,sizeof(tmp),"%.16llx",id);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"%.16llx",id);
res["id"] = tmp;
res["roots"] = json::array();
res["timestamp"] = 0;
@@ -1617,7 +1594,7 @@ public:
std::string h = controllerDbHttpHost;
_controllerDbPath.append(h);
char dbp[128];
- Utils::snprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort);
+ Utils::ztsnprintf(dbp,sizeof(dbp),"%d",(int)controllerDbHttpPort);
_controllerDbPath.push_back(':');
_controllerDbPath.append(dbp);
if (controllerDbHttpPath.is_string()) {
@@ -1711,7 +1688,7 @@ public:
if (syncRoutes) {
char tapdev[64];
#ifdef __WINDOWS__
- Utils::snprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value);
+ Utils::ztsnprintf(tapdev,sizeof(tapdev),"%.16llx",(unsigned long long)n.tap->luid().Value);
#else
Utils::scopy(tapdev,sizeof(tapdev),n.tap->deviceName().c_str());
#endif
@@ -1877,16 +1854,15 @@ public:
return false;
}
- void replicateStateObject(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,TcpConnection *tc)
+ void replicateStateObject(const ZT_StateObjectType type,const uint64_t id[2],const void *const data,const unsigned int len,TcpConnection *tc)
{
- char buf[34];
-
+ char buf[42];
Mutex::Lock _l2(tc->writeq_m);
if (tc->writeq.length() == 0)
_phy.setNotifyWritable(tc->sock,true);
- const unsigned int mlen = len + 34;
+ const unsigned int mlen = len + 42;
tc->writeq.push_back((char)((mlen >> 16) & 0xff));
tc->writeq.push_back((char)((mlen >> 8) & 0xff));
@@ -1895,78 +1871,89 @@ public:
Utils::getSecureRandom(buf,16);
buf[24] = (char)CLUSTER_MESSAGE_STATE_OBJECT;
buf[25] = (char)type;
- buf[26] = (char)((id >> 56) & 0xff);
- buf[27] = (char)((id >> 48) & 0xff);
- buf[28] = (char)((id >> 40) & 0xff);
- buf[29] = (char)((id >> 32) & 0xff);
- buf[30] = (char)((id >> 24) & 0xff);
- buf[31] = (char)((id >> 16) & 0xff);
- buf[32] = (char)((id >> 8) & 0xff);
- buf[33] = (char)(id & 0xff);
+ buf[26] = (char)((id[0] >> 56) & 0xff);
+ buf[27] = (char)((id[0] >> 48) & 0xff);
+ buf[28] = (char)((id[0] >> 40) & 0xff);
+ buf[29] = (char)((id[0] >> 32) & 0xff);
+ buf[30] = (char)((id[0] >> 24) & 0xff);
+ buf[31] = (char)((id[0] >> 16) & 0xff);
+ buf[32] = (char)((id[0] >> 8) & 0xff);
+ buf[33] = (char)(id[0] & 0xff);
+ buf[34] = (char)((id[1] >> 56) & 0xff);
+ buf[35] = (char)((id[1] >> 48) & 0xff);
+ buf[36] = (char)((id[1] >> 40) & 0xff);
+ buf[37] = (char)((id[1] >> 32) & 0xff);
+ buf[38] = (char)((id[1] >> 24) & 0xff);
+ buf[39] = (char)((id[1] >> 16) & 0xff);
+ buf[40] = (char)((id[1] >> 8) & 0xff);
+ buf[41] = (char)(id[1] & 0xff);
const unsigned long startpos = (unsigned long)tc->writeq.length();
- tc->writeq.append(buf,34);
+ tc->writeq.append(buf,42);
tc->writeq.append(reinterpret_cast<const char *>(data),len);
char *const outdata = const_cast<char *>(tc->writeq.data()) + startpos;
encryptClusterMessage(outdata,mlen);
+ tc->writeq.append(outdata,mlen);
}
- void replicateStateObjectToCluster(const ZT_StateObjectType type,const uint64_t id,const void *const data,const unsigned int len,const uint64_t everyoneBut)
- {
- std::vector<uint64_t> sentTo;
- if (everyoneBut)
- sentTo.push_back(everyoneBut);
- Mutex::Lock _l(_tcpConnections_m);
- for(std::vector<TcpConnection *>::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) {
- TcpConnection *const c = *ci;
- if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) {
- sentTo.push_back(c->clusterMemberId);
- replicateStateObject(type,id,data,len,c);
- }
- }
- }
-
- void writeStateObject(enum ZT_StateObjectType type,uint64_t id,const void *data,int len)
+ void writeStateObject(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{
- char p[4096];
+ char buf[65535];
+ char p[1024];
+ FILE *f;
bool secure = false;
+
switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
break;
case ZT_STATE_OBJECT_IDENTITY_SECRET:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
secure = true;
break;
- case ZT_STATE_OBJECT_PEER_IDENTITY:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id);
- break;
+ //case ZT_STATE_OBJECT_PEER_STATE:
+ // break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id);
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id[0]);
secure = true;
break;
+ //case ZT_STATE_OBJECT_NETWORK_MEMBERSHIP:
+ // break;
case ZT_STATE_OBJECT_PLANET:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
break;
case ZT_STATE_OBJECT_MOON:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id);
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id[0]);
break;
default:
p[0] = (char)0;
break;
}
+
if (p[0]) {
if (len >= 0) {
- FILE *f = fopen(p,"w");
+ // Check to see if we've already written this first. This reduces
+ // redundant writes and I/O overhead on most platforms and has
+ // little effect on others.
+ f = fopen(p,"r");
+ bool redundant = false;
if (f) {
- if (fwrite(data,len,1,f) != 1)
- fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p);
+ long l = (long)fread(buf,1,sizeof(buf),f);
fclose(f);
- if (secure)
- OSUtils::lockDownFile(p,false);
- } else {
- fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p);
+ redundant = ((l == (long)len)&&(memcmp(data,buf,l) == 0));
+ }
+ if (!redundant) {
+ f = fopen(p,"w");
+ if (f) {
+ if (fwrite(data,len,1,f) != 1)
+ fprintf(stderr,"WARNING: unable to write to file: %s (I/O error)" ZT_EOL_S,p);
+ fclose(f);
+ if (secure)
+ OSUtils::lockDownFile(p,false);
+ } else {
+ fprintf(stderr,"WARNING: unable to write to file: %s (unable to open)" ZT_EOL_S,p);
+ }
}
} else {
OSUtils::rm(p);
@@ -1985,8 +1972,12 @@ public:
if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) {
if (f->length() == 21) {
const uint64_t nwid = Utils::hexStrToU64(f->substr(0,16).c_str());
- if (nwid)
- replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,nwid,buf.data(),(int)buf.length(),tc);
+ if (nwid) {
+ uint64_t tmp[2];
+ tmp[0] = nwid;
+ tmp[1] = 0;
+ replicateStateObject(ZT_STATE_OBJECT_NETWORK_CONFIG,tmp,buf.data(),(int)buf.length(),tc);
+ }
}
}
}
@@ -1996,8 +1987,12 @@ public:
if (OSUtils::readFile((_homePath + ZT_PATH_SEPARATOR_S + *f).c_str(),buf)) {
if (f->length() == 21) {
const uint64_t moonId = Utils::hexStrToU64(f->substr(0,16).c_str());
- if (moonId)
- replicateStateObject(ZT_STATE_OBJECT_MOON,moonId,buf.data(),(int)buf.length(),tc);
+ if (moonId) {
+ uint64_t tmp[2];
+ tmp[0] = moonId;
+ tmp[1] = 0;
+ replicateStateObject(ZT_STATE_OBJECT_MOON,tmp,buf.data(),(int)buf.length(),tc);
+ }
}
}
}
@@ -2022,7 +2017,7 @@ public:
&_nextBackgroundTaskDeadline);
if (ZT_ResultCode_isFatal(rc)) {
char tmp[256];
- Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc);
Mutex::Lock _l(_termReason_m);
_termReason = ONE_UNRECOVERABLE_ERROR;
_fatalErrorMessage = tmp;
@@ -2235,7 +2230,7 @@ public:
&_nextBackgroundTaskDeadline);
if (ZT_ResultCode_isFatal(rc)) {
char tmp[256];
- Utils::snprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc);
+ Utils::ztsnprintf(tmp,sizeof(tmp),"fatal error code from processWirePacket: %d",(int)rc);
Mutex::Lock _l(_termReason_m);
_termReason = ONE_UNRECOVERABLE_ERROR;
_fatalErrorMessage = tmp;
@@ -2313,8 +2308,9 @@ public:
break;
case CLUSTER_MESSAGE_STATE_OBJECT:
- if (mlen >= (25 + 9)) { // type + object ID + [data]
- const uint64_t objId = (
+ if (mlen > 42) { // type + object ID + [data]
+ uint64_t objId[2];
+ objId[0] = (
((uint64_t)data[26] << 56) |
((uint64_t)data[27] << 48) |
((uint64_t)data[28] << 40) |
@@ -2324,10 +2320,18 @@ public:
((uint64_t)data[32] << 8) |
(uint64_t)data[33]
);
- if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34)) == ZT_RESULT_OK) {
- writeStateObject((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34));
- replicateStateObjectToCluster((ZT_StateObjectType)data[25],objId,data + 34,(unsigned int)(mlen - 34),tc->clusterMemberId);
- }
+ objId[1] = (
+ ((uint64_t)data[34] << 56) |
+ ((uint64_t)data[35] << 48) |
+ ((uint64_t)data[36] << 40) |
+ ((uint64_t)data[37] << 32) |
+ ((uint64_t)data[38] << 24) |
+ ((uint64_t)data[39] << 16) |
+ ((uint64_t)data[40] << 8) |
+ (uint64_t)data[41]
+ );
+ if (_node->processStateUpdate((void *)0,(ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42)) == ZT_RESULT_OK)
+ writeStateObject((ZT_StateObjectType)data[25],objId,data + 42,(unsigned int)(mlen - 42));
}
break;
@@ -2402,7 +2406,7 @@ public:
if (!n.tap) {
try {
char friendlyName[128];
- Utils::snprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
+ Utils::ztsnprintf(friendlyName,sizeof(friendlyName),"ZeroTier One [%.16llx]",nwid);
n.tap = new EthernetTap(
_homePath.c_str(),
@@ -2416,7 +2420,7 @@ public:
*nuptr = (void *)&n;
char nlcpath[256];
- Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid);
+ Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid);
std::string nlcbuf;
if (OSUtils::readFile(nlcpath,nlcbuf)) {
Dictionary<4096> nc;
@@ -2502,7 +2506,7 @@ public:
#endif
if (op == ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY) {
char nlcpath[256];
- Utils::snprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid);
+ Utils::ztsnprintf(nlcpath,sizeof(nlcpath),"%s" ZT_PATH_SEPARATOR_S "networks.d" ZT_PATH_SEPARATOR_S "%.16llx.local.conf",_homePath.c_str(),nwid);
OSUtils::rm(nlcpath);
}
} else {
@@ -2543,33 +2547,41 @@ public:
}
}
- inline void nodeStatePutFunction(enum ZT_StateObjectType type,uint64_t id,const void *data,int len)
+ inline void nodeStatePutFunction(enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{
writeStateObject(type,id,data,len);
- replicateStateObjectToCluster(type,id,data,len,0);
+
+ std::vector<uint64_t> sentTo;
+ {
+ Mutex::Lock _l(_tcpConnections_m);
+ for(std::vector<TcpConnection *>::const_iterator ci(_tcpConnections.begin());ci!=_tcpConnections.end();++ci) {
+ TcpConnection *const c = *ci;
+ if ((c->type == TcpConnection::TCP_CLUSTER_BACKPLANE)&&(c->clusterMemberId != 0)&&(std::find(sentTo.begin(),sentTo.end(),c->clusterMemberId) == sentTo.end())) {
+ sentTo.push_back(c->clusterMemberId);
+ replicateStateObject(type,id,data,len,c);
+ }
+ }
+ }
}
- inline int nodeStateGetFunction(enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen)
+ inline int nodeStateGetFunction(enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen)
{
char p[4096];
switch(type) {
case ZT_STATE_OBJECT_IDENTITY_PUBLIC:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.public",_homePath.c_str());
break;
case ZT_STATE_OBJECT_IDENTITY_SECRET:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
- break;
- case ZT_STATE_OBJECT_PEER_IDENTITY:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "iddb.d/%.10llx",_homePath.c_str(),(unsigned long long)id);
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "identity.secret",_homePath.c_str());
break;
case ZT_STATE_OBJECT_NETWORK_CONFIG:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id);
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "networks.d/%.16llx.conf",_homePath.c_str(),(unsigned long long)id);
break;
case ZT_STATE_OBJECT_PLANET:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "planet",_homePath.c_str());
break;
case ZT_STATE_OBJECT_MOON:
- Utils::snprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id);
+ Utils::ztsnprintf(p,sizeof(p),"%s" ZT_PATH_SEPARATOR_S "moons.d/%.16llx.moon",_homePath.c_str(),(unsigned long long)id);
break;
default:
return -1;
@@ -2765,7 +2777,7 @@ public:
default: scodestr = "Error"; break;
}
- Utils::snprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n",
+ Utils::ztsnprintf(tmpn,sizeof(tmpn),"HTTP/1.1 %.3u %s\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nContent-Type: %s\r\nContent-Length: %lu\r\nConnection: close\r\n\r\n",
scode,
scodestr,
contentType.c_str(),
@@ -2866,9 +2878,9 @@ static int SnodeVirtualNetworkConfigFunction(ZT_Node *node,void *uptr,void *tptr
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeVirtualNetworkConfigFunction(nwid,nuptr,op,nwconf); }
static void SnodeEventCallback(ZT_Node *node,void *uptr,void *tptr,enum ZT_Event event,const void *metaData)
{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeEventCallback(event,metaData); }
-static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,const void *data,int len)
+static void SnodeStatePutFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],const void *data,int len)
{ reinterpret_cast<OneServiceImpl *>(uptr)->nodeStatePutFunction(type,id,data,len); }
-static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,uint64_t id,void *data,unsigned int maxlen)
+static int SnodeStateGetFunction(ZT_Node *node,void *uptr,void *tptr,enum ZT_StateObjectType type,const uint64_t id[2],void *data,unsigned int maxlen)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeStateGetFunction(type,id,data,maxlen); }
static int SnodeWirePacketSendFunction(ZT_Node *node,void *uptr,void *tptr,const struct sockaddr_storage *localAddr,const struct sockaddr_storage *addr,const void *data,unsigned int len,unsigned int ttl)
{ return reinterpret_cast<OneServiceImpl *>(uptr)->nodeWirePacketSendFunction(localAddr,addr,data,len,ttl); }
diff --git a/service/SoftwareUpdater.cpp b/service/SoftwareUpdater.cpp
index d94beab5..e0519827 100644
--- a/service/SoftwareUpdater.cpp
+++ b/service/SoftwareUpdater.cpp
@@ -284,7 +284,7 @@ bool SoftwareUpdater::check(const uint64_t now)
if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) {
_lastCheckTime = now;
char tmp[512];
- const unsigned int len = Utils::snprintf(tmp,sizeof(tmp),
+ const unsigned int len = Utils::ztsnprintf(tmp,sizeof(tmp),
"%c{\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MAJOR "\":%d,"
"\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_MINOR "\":%d,"
"\"" ZT_SOFTWARE_UPDATE_JSON_VERSION_REVISION "\":%d,"
diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj b/windows/ZeroTierOne/ZeroTierOne.vcxproj
index 9715f3d9..c966d64b 100644
--- a/windows/ZeroTierOne/ZeroTierOne.vcxproj
+++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj
@@ -50,7 +50,6 @@
<ClCompile Include="..\..\node\Capability.cpp" />
<ClCompile Include="..\..\node\CertificateOfMembership.cpp" />
<ClCompile Include="..\..\node\CertificateOfOwnership.cpp" />
- <ClCompile Include="..\..\node\Cluster.cpp" />
<ClCompile Include="..\..\node\Identity.cpp" />
<ClCompile Include="..\..\node\IncomingPacket.cpp" />
<ClCompile Include="..\..\node\InetAddress.cpp" />
@@ -134,7 +133,6 @@
<ClInclude Include="..\..\node\C25519.hpp" />
<ClInclude Include="..\..\node\CertificateOfMembership.hpp" />
<ClInclude Include="..\..\node\CertificateOfOwnership.hpp" />
- <ClInclude Include="..\..\node\Cluster.hpp" />
<ClInclude Include="..\..\node\CMWC4096.hpp" />
<ClInclude Include="..\..\node\Constants.hpp" />
<ClInclude Include="..\..\node\Credential.hpp" />
diff --git a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters
index cca10f97..086c1043 100644
--- a/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters
+++ b/windows/ZeroTierOne/ZeroTierOne.vcxproj.filters
@@ -168,9 +168,6 @@
<ClCompile Include="..\..\node\Path.cpp">
<Filter>Source Files\node</Filter>
</ClCompile>
- <ClCompile Include="..\..\node\Cluster.cpp">
- <Filter>Source Files\node</Filter>
- </ClCompile>
<ClCompile Include="..\..\ext\miniupnpc\connecthostport.c">
<Filter>Source Files\ext\miniupnpc</Filter>
</ClCompile>
@@ -404,9 +401,6 @@
<ClInclude Include="..\..\node\BinarySemaphore.hpp">
<Filter>Header Files\node</Filter>
</ClInclude>
- <ClInclude Include="..\..\node\Cluster.hpp">
- <Filter>Header Files\node</Filter>
- </ClInclude>
<ClInclude Include="..\..\node\Hashtable.hpp">
<Filter>Header Files\node</Filter>
</ClInclude>