summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp7
-rw-r--r--node/Node.cpp53
-rw-r--r--node/Topology.cpp3
3 files changed, 61 insertions, 2 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 8a8c70f2..53754712 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -410,6 +410,13 @@
#define ZT_UPDATE_HTTP_TIMEOUT 120
/**
+ * Delay between fetches of the root topology update URL
+ *
+ * 86400000 = check once every 24 hours (this doesn't change often)
+ */
+#define ZT_UPDATE_ROOT_TOPOLOGY_CHECK_INTERVAL 86400000
+
+/**
* Sanity limit on maximum bridge routes
*
* If the number of bridge routes exceeds this, we cull routes from the
diff --git a/node/Node.cpp b/node/Node.cpp
index e031dbdb..5d7de540 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -77,6 +77,7 @@
#include "IpcConnection.hpp"
#include "AntiRecursion.hpp"
#include "RoutingTable.hpp"
+#include "HttpClient.hpp"
namespace ZeroTier {
@@ -220,8 +221,10 @@ struct _NodeImpl
RuntimeEnvironment renv;
unsigned int udpPort,tcpPort;
+
std::string reasonForTerminationStr;
volatile Node::ReasonForTermination reasonForTermination;
+
volatile bool started;
volatile bool running;
volatile bool resynchronize;
@@ -405,6 +408,47 @@ static void _CBztTraffic(const SharedPtr<Socket> &fromSock,void *arg,const InetA
_r->sw->onRemotePacket(fromSock,from,data);
}
+static void _cbHandleGetRootTopology(void *arg,int code,const std::string &url,bool onDisk,const std::string &body)
+{
+ RuntimeEnvironment *_r = (RuntimeEnvironment *)arg;
+ if (_r->shutdownInProgress)
+ return;
+
+ if ((code != 200)||(body.length() == 0)) {
+ TRACE("failed to retrieve %s",ZT_DEFAULTS.rootTopologyUpdateURL.c_str());
+ return;
+ }
+
+ try {
+ Dictionary rt(body);
+ if (!Topology::authenticateRootTopology(rt)) {
+ LOG("discarded invalid root topology update from %s (signature check failed)",url.c_str());
+ return;
+ }
+
+ {
+ std::string rootTopologyPath(_r->homePath + ZT_PATH_SEPARATOR_S + "root-topology");
+ std::string rootTopology;
+ if (Utils::readFile(rootTopologyPath.c_str(),rootTopology)) {
+ Dictionary alreadyHave(rootTopology);
+ if (alreadyHave == rt) {
+ TRACE("retrieved root topology from %s but no change (same)",url.c_str());
+ return;
+ } else if (alreadyHave.signatureTimestamp() > rt.signatureTimestamp()) {
+ TRACE("retrieved root topology from %s but no change (ours is newer)",url.c_str());
+ return;
+ }
+ }
+ Utils::writeFile(rootTopologyPath.c_str(),body);
+ }
+
+ _r->topology->setSupernodes(Dictionary(rt.get("supernodes")));
+ } catch ( ... ) {
+ LOG("discarded invalid root topology update from %s (format invalid)",url.c_str());
+ return;
+ }
+}
+
Node::ReasonForTermination Node::run()
throw()
{
@@ -508,8 +552,7 @@ Node::ReasonForTermination Node::run()
Dictionary rt(rootTopology);
if (!Topology::authenticateRootTopology(rt))
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"root-topology failed signature verification check");
- Dictionary supernodes(rt.get("supernodes"));
- _r->topology->setSupernodes(supernodes);
+ _r->topology->setSupernodes(Dictionary(rt.get("supernodes")));
} catch ( ... ) {
return impl->terminateBecause(Node::NODE_UNRECOVERABLE_ERROR,"invalid root-topology format");
}
@@ -555,6 +598,7 @@ Node::ReasonForTermination Node::run()
uint64_t lastMulticastCheck = 0;
uint64_t lastSupernodePingCheck = 0;
uint64_t lastBeacon = 0;
+ uint64_t lastRootTopologyFetch = 0;
long lastDelayDelta = 0;
uint64_t networkConfigurationFingerprint = 0;
@@ -711,6 +755,11 @@ Node::ReasonForTermination Node::run()
_r->sm->send(ZT_DEFAULTS.v4Broadcast,false,false,bcn,ZT_PROTO_BEACON_LENGTH);
}
+ if ((now - lastRootTopologyFetch) >= ZT_UPDATE_ROOT_TOPOLOGY_CHECK_INTERVAL) {
+ lastRootTopologyFetch = now;
+ HttpClient::GET(ZT_DEFAULTS.rootTopologyUpdateURL,HttpClient::NO_HEADERS,60,&_cbHandleGetRootTopology,_r);
+ }
+
// Sleep for loop interval or until something interesting happens.
try {
unsigned long delay = std::min((unsigned long)ZT_MAX_SERVICE_LOOP_INTERVAL,_r->sw->doTimerTasks());
diff --git a/node/Topology.cpp b/node/Topology.cpp
index 6fcb17af..109cbca2 100644
--- a/node/Topology.cpp
+++ b/node/Topology.cpp
@@ -57,6 +57,9 @@ void Topology::setSupernodes(const std::map< Identity,std::vector< std::pair<Ine
{
Mutex::Lock _l(_supernodes_m);
+ if (_supernodes == sn)
+ return; // no change
+
_supernodes = sn;
_supernodeAddresses.clear();
_supernodePeers.clear();