summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp5
-rw-r--r--node/Node.cpp41
-rw-r--r--node/Node.hpp6
-rw-r--r--node/Peer.hpp40
-rw-r--r--node/Topology.hpp31
5 files changed, 109 insertions, 14 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index 641b25bb..394c89eb 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -254,6 +254,11 @@ error_no_ZT_ARCH
#define ZT_AUTOCONFIGURE_CHECK_DELAY 15000
/**
+ * Delay between updates of status file in home directory
+ */
+#define ZT_STATUS_OUTPUT_PERIOD 120000
+
+/**
* Minimum delay in Node service loop
*
* This is the shortest of the check delays/periods.
diff --git a/node/Node.cpp b/node/Node.cpp
index 830ee354..85029e81 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -74,8 +74,9 @@ struct _NodeImpl
RuntimeEnvironment renv;
std::string reasonForTerminationStr;
Node::ReasonForTermination reasonForTermination;
- bool started;
- bool running;
+ volatile bool started;
+ volatile bool running;
+ volatile bool updateStatusNow;
volatile bool terminateNow;
// Helper used to rapidly terminate from run()
@@ -104,6 +105,7 @@ Node::Node(const char *hp,const char *urlPrefix,const char *configAuthorityIdent
impl->reasonForTermination = Node::NODE_RUNNING;
impl->started = false;
impl->running = false;
+ impl->updateStatusNow = false;
impl->terminateNow = false;
}
@@ -236,6 +238,8 @@ Node::ReasonForTermination Node::run()
}
try {
+ std::string statusPath(_r->homePath + ZT_PATH_SEPARATOR_S + "status");
+
uint64_t lastPingCheck = 0;
uint64_t lastTopologyClean = Utils::now(); // don't need to do this immediately
uint64_t lastNetworkFingerprintCheck = 0;
@@ -243,6 +247,7 @@ Node::ReasonForTermination Node::run()
uint64_t networkConfigurationFingerprint = _r->sysEnv->getNetworkConfigurationFingerprint();
uint64_t lastMulticastCheck = 0;
uint64_t lastMulticastAnnounceAll = 0;
+ uint64_t lastStatusUpdate = 0;
long lastDelayDelta = 0;
LOG("%s starting version %s",_r->identity.address().toString().c_str(),versionString());
@@ -373,6 +378,20 @@ Node::ReasonForTermination Node::run()
_r->topology->clean(); // happens in background
}
+ if (((now - lastStatusUpdate) >= ZT_STATUS_OUTPUT_PERIOD)||(impl->updateStatusNow)) {
+ lastStatusUpdate = now;
+ impl->updateStatusNow = false;
+ FILE *statusf = ::fopen(statusPath.c_str(),"w");
+ if (statusf) {
+ try {
+ _r->topology->eachPeer(Topology::DumpPeerStatistics(statusf));
+ } catch ( ... ) {
+ TRACE("unexpected exception updating status dump");
+ }
+ ::fclose(statusf);
+ }
+ }
+
try {
unsigned long delay = std::min((unsigned long)ZT_MIN_SERVICE_LOOP_INTERVAL,_r->sw->doTimerTasks());
uint64_t start = Utils::now();
@@ -391,11 +410,6 @@ Node::ReasonForTermination Node::run()
return impl->terminateBecause(Node::NODE_NORMAL_TERMINATION,"normal termination");
}
-/**
- * Obtain a human-readable reason for node termination
- *
- * @return Reason for node termination or NULL if run() has not returned
- */
const char *Node::reasonForTermination() const
throw()
{
@@ -404,19 +418,18 @@ const char *Node::reasonForTermination() const
return ((_NodeImpl *)_impl)->reasonForTerminationStr.c_str();
}
-/**
- * Cause run() to return with NODE_NORMAL_TERMINATION
- *
- * This can be called from a signal handler or another thread to signal a
- * running node to shut down. Shutdown may take a few seconds, so run()
- * may not return instantly. Multiple calls are ignored.
- */
void Node::terminate()
throw()
{
((_NodeImpl *)_impl)->terminateNow = true;
}
+void Node::updateStatusNow()
+ throw()
+{
+ ((_NodeImpl *)_impl)->updateStatusNow = true;
+}
+
class _VersionStringMaker
{
public:
diff --git a/node/Node.hpp b/node/Node.hpp
index 1cc9a746..df6b946f 100644
--- a/node/Node.hpp
+++ b/node/Node.hpp
@@ -99,6 +99,12 @@ public:
throw();
/**
+ * Update the status file in the home directory on next service loop
+ */
+ void updateStatusNow()
+ throw();
+
+ /**
* Get the ZeroTier version in major.minor.revision string format
*
* @return Version in string form
diff --git a/node/Peer.hpp b/node/Peer.hpp
index 5da19468..ef33d519 100644
--- a/node/Peer.hpp
+++ b/node/Peer.hpp
@@ -233,6 +233,46 @@ public:
}
/**
+ * @return IPv4 direct address or null InetAddress if none
+ */
+ inline InetAddress ipv4Path() const
+ throw()
+ {
+ return _ipv4p.addr;
+ }
+
+ /**
+ * @return IPv6 direct address or null InetAddress if none
+ */
+ inline InetAddress ipv6Path() const
+ throw()
+ {
+ return _ipv4p.addr;
+ }
+
+ /**
+ * @return IPv4 direct address or null InetAddress if none
+ */
+ inline InetAddress ipv4ActivePath(uint64_t now) const
+ throw()
+ {
+ if (_ipv4p.isActive(now))
+ return _ipv4p.addr;
+ return InetAddress();
+ }
+
+ /**
+ * @return IPv6 direct address or null InetAddress if none
+ */
+ inline InetAddress ipv6ActivePath(uint64_t now) const
+ throw()
+ {
+ if (_ipv6p.isActive(now))
+ return _ipv6p.addr;
+ return InetAddress();
+ }
+
+ /**
* @return 256-bit encryption key
*/
inline const unsigned char *cryptKey() const
diff --git a/node/Topology.hpp b/node/Topology.hpp
index 95124497..7baebad0 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -28,6 +28,8 @@
#ifndef _ZT_TOPOLOGY_HPP
#define _ZT_TOPOLOGY_HPP
+#include <stdio.h>
+#include <string.h>
#include <map>
#include <set>
#include <list>
@@ -292,6 +294,35 @@ public:
std::vector< SharedPtr<Peer> > &_v;
};
+ /**
+ * Dump peer I/O statistics to an open FILE (for status reporting and debug)
+ */
+ class DumpPeerStatistics
+ {
+ public:
+ DumpPeerStatistics(FILE *out) :
+ _out(out),
+ _now(Utils::now())
+ {
+ fprintf(_out,"Peer Direct IPv4 Direct IPv6 Latency(ms)"ZT_EOL_S);
+ }
+
+ inline void operator()(Topology &t,const SharedPtr<Peer> &p)
+ {
+ InetAddress v4(p->ipv4ActivePath(_now));
+ InetAddress v6(p->ipv6ActivePath(_now));
+ fprintf(_out,"%-10s %-21s %-51s %u"ZT_EOL_S,
+ p->address().toString().c_str(),
+ ((v4) ? v4.toString().c_str() : "(none)"),
+ ((v6) ? v6.toString().c_str() : "(none)"),
+ p->latency());
+ }
+
+ private:
+ FILE *_out;
+ uint64_t _now;
+ };
+
protected:
virtual void main()
throw();