Переглянути джерело

timestamps changed from uint64_t to int64_t

There were cases in the code where time calculations and comparisons were overflowing and causing connection instability.  This will keep time calculations within expected ranges.
Grant Limberg 7 роки тому
батько
коміт
b1d60df44c

+ 7 - 7
controller/EmbeddedNetworkController.cpp

@@ -535,7 +535,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpGET(
 			} else {
 				// Get network
 
-				const uint64_t now = OSUtils::now();
+				const int64_t now = OSUtils::now();
 				JSONDB::NetworkSummaryInfo ns;
 				_db.getNetworkSummaryInfo(nwid,ns);
 				_addNetworkNonPersistedFields(network,now,ns);
@@ -602,7 +602,7 @@ unsigned int EmbeddedNetworkController::handleControlPlaneHttpPOST(
 		responseContentType = "application/json";
 		return 400;
 	}
-	const uint64_t now = OSUtils::now();
+	const int64_t now = OSUtils::now();
 
 	if (path[0] == "network") {
 
@@ -1087,7 +1087,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt)
 			}
 		}
 
-		const uint64_t now = OSUtils::now();
+		const int64_t now = OSUtils::now();
 		OSUtils::ztsnprintf(id,sizeof(id),"%.10llx-%.10llx-%.16llx-%.8lx",_signingId.address().toInt(),rt.origin,now,++idCounter);
 		d["id"] = id;
 		d["objtype"] = "trace";
@@ -1129,7 +1129,7 @@ void EmbeddedNetworkController::handleRemoteTrace(const ZT_RemoteTrace &rt)
 void EmbeddedNetworkController::onNetworkUpdate(const uint64_t networkId)
 {
 	// Send an update to all members of the network that are online
-	const uint64_t now = OSUtils::now();
+	const int64_t now = OSUtils::now();
 	Mutex::Lock _l(_memberStatus_m);
 	for(auto i=_memberStatus.begin();i!=_memberStatus.end();++i) {
 		if ((i->first.networkId == networkId)&&(i->second.online(now))&&(i->second.lastRequestMetaData))
@@ -1150,7 +1150,7 @@ void EmbeddedNetworkController::onNetworkMemberUpdate(const uint64_t networkId,c
 
 void EmbeddedNetworkController::onNetworkMemberDeauthorize(const uint64_t networkId,const uint64_t memberId)
 {
-	const uint64_t now = OSUtils::now();
+	const int64_t now = OSUtils::now();
 	Revocation rev((uint32_t)_node->prng(),networkId,0,now,ZT_REVOCATION_FLAG_FAST_PROPAGATE,Address(memberId),Revocation::CREDENTIAL_TYPE_COM);
 	rev.sign(_signingId);
 	{
@@ -1224,7 +1224,7 @@ void EmbeddedNetworkController::_request(
 	if (((!_signingId)||(!_signingId.hasPrivate()))||(_signingId.address().toInt() != (nwid >> 24))||(!_sender))
 		return;
 
-	const uint64_t now = OSUtils::now();
+	const int64_t now = OSUtils::now();
 
 	if (requestPacketId) {
 		Mutex::Lock _l(_memberStatus_m);
@@ -1360,7 +1360,7 @@ void EmbeddedNetworkController::_request(
 	// If we made it this far, they are authorized.
 	// -------------------------------------------------------------------------
 
-	uint64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
+	int64_t credentialtmd = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA;
 	if (now > ns.mostRecentDeauthTime) {
 		// If we recently de-authorized a member, shrink credential TTL/max delta to
 		// be below the threshold required to exclude it. Cap this to a min/max to

+ 4 - 4
controller/EmbeddedNetworkController.hpp

@@ -166,7 +166,7 @@ private:
 		}
 		network["objtype"] = "network";
 	}
-	inline void _addNetworkNonPersistedFields(nlohmann::json &network,uint64_t now,const JSONDB::NetworkSummaryInfo &ns)
+	inline void _addNetworkNonPersistedFields(nlohmann::json &network,int64_t now,const JSONDB::NetworkSummaryInfo &ns)
 	{
 		network["clock"] = now;
 		network["authorizedMemberCount"] = ns.authorizedMemberCount;
@@ -182,7 +182,7 @@ private:
 		// legacy fields
 		network.erase("lastModified");
 	}
-	inline void _addMemberNonPersistedFields(uint64_t nwid,uint64_t nodeId,nlohmann::json &member,uint64_t now)
+	inline void _addMemberNonPersistedFields(uint64_t nwid,uint64_t nodeId,nlohmann::json &member,int64_t now)
 	{
 		member["clock"] = now;
 		Mutex::Lock _l(_memberStatus_m);
@@ -197,7 +197,7 @@ private:
 		member.erase("lastRequestMetaData");
 	}
 
-	const uint64_t _startTime;
+	const int64_t _startTime;
 
 	volatile bool _running;
 	BlockingQueue<_RQEntry *> _queue;
@@ -230,7 +230,7 @@ private:
 		Dictionary<ZT_NETWORKCONFIG_METADATA_DICT_CAPACITY> lastRequestMetaData;
 		Identity identity;
 		InetAddress physicalAddr; // last known physical address
-		inline bool online(const uint64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); }
+		inline bool online(const int64_t now) const { return ((now - lastRequestTime) < (ZT_NETWORK_AUTOCONF_DELAY * 2)); }
 	};
 	struct _MemberStatusHash
 	{

+ 2 - 2
controller/JSONDB.cpp

@@ -323,7 +323,7 @@ void JSONDB::threadMain()
 			_networks_m.unlock();
 		}
 
-		const uint64_t now = OSUtils::now();
+		const int64_t now = OSUtils::now();
 		try {
 			Mutex::Lock _l(_networks_m);
 			for(std::vector<uint64_t>::iterator ii(todo.begin());ii!=todo.end();++ii) {
@@ -373,7 +373,7 @@ void JSONDB::threadMain()
 								} catch ( ... ) {}
 							} else {
 								try {
-									ns.mostRecentDeauthTime = std::max(ns.mostRecentDeauthTime,OSUtils::jsonInt(member["lastDeauthorizedTime"],0ULL));
+									ns.mostRecentDeauthTime = std::max(ns.mostRecentDeauthTime,(int64_t)OSUtils::jsonInt(member["lastDeauthorizedTime"],0LL));
 								} catch ( ... ) {}
 							}
 							++ns.totalMemberCount;

+ 1 - 1
controller/JSONDB.hpp

@@ -57,7 +57,7 @@ public:
 		unsigned long authorizedMemberCount;
 		unsigned long activeMemberCount;
 		unsigned long totalMemberCount;
-		uint64_t mostRecentDeauthTime;
+		int64_t mostRecentDeauthTime;
 	};
 
 	JSONDB(const std::string &basePath,EmbeddedNetworkController *parent);

+ 6 - 6
include/ZeroTierOne.h

@@ -1587,7 +1587,7 @@ struct ZT_Node_Callbacks
  * @param now Current clock in milliseconds
  * @return OK (0) or error code if a fatal error condition has occurred
  */
-ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
+ZT_SDK_API enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now);
 
 /**
  * Delete a node and free all resources it consumes
@@ -1615,12 +1615,12 @@ ZT_SDK_API void ZT_Node_delete(ZT_Node *node);
 ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
 	ZT_Node *node,
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	int64_t localSocket,
 	const struct sockaddr_storage *remoteAddress,
 	const void *packetData,
 	unsigned int packetLength,
-	volatile uint64_t *nextBackgroundTaskDeadline);
+	volatile int64_t *nextBackgroundTaskDeadline);
 
 /**
  * Process a frame from a virtual network port (tap)
@@ -1641,7 +1641,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket(
 ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
 	ZT_Node *node,
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	uint64_t nwid,
 	uint64_t sourceMac,
 	uint64_t destMac,
@@ -1649,7 +1649,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
 	unsigned int vlanId,
 	const void *frameData,
 	unsigned int frameLength,
-	volatile uint64_t *nextBackgroundTaskDeadline);
+	volatile int64_t *nextBackgroundTaskDeadline);
 
 /**
  * Perform periodic background operations
@@ -1660,7 +1660,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
  * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks()
  * @return OK (0) or error code if a fatal error condition has occurred
  */
-ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
+ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline);
 
 /**
  * Join a network

+ 1 - 1
node/CertificateOfMembership.hpp

@@ -176,7 +176,7 @@ public:
 	/**
 	 * @return Timestamp for this cert and maximum delta for timestamp
 	 */
-	inline uint64_t timestamp() const
+	inline int64_t timestamp() const
 	{
 		for(unsigned int i=0;i<_qualifierCount;++i) {
 			if (_qualifiers[i].id == COM_RESERVED_ID_TIMESTAMP)

+ 6 - 6
node/IncomingPacket.cpp

@@ -169,7 +169,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
 			// Peers can send this in response to frames if they do not have a recent enough COM from us
 			networkId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD);
 			const SharedPtr<Network> network(RR->node->network(networkId));
-			const uint64_t now = RR->node->now();
+			const int64_t now = RR->node->now();
 			if ( (network) && (network->config().com) && (peer->rateGateIncomingComRequest(now)) )
 				network->pushCredentialsNow(tPtr,peer->address(),now);
 		}	break;
@@ -202,7 +202,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,void *tPtr,const Shar
 
 bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool alreadyAuthenticated)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 
 	const uint64_t pid = packetId();
 	const Address fromAddress(source());
@@ -210,7 +210,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
 	const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION];
 	const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION];
 	const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION);
-	const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
+	const int64_t timestamp = at<int64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP);
 	Identity id;
 	unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY);
 
@@ -725,7 +725,7 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share
 
 bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 
 	uint64_t authOnNetwork[256]; // cache for approved network IDs
 	unsigned int authOnNetworkCount = 0;
@@ -1082,7 +1082,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
 
 bool IncomingPacket::_doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 
 	// First, subject this to a rate limit
 	if (!peer->rateGatePushDirectPaths(now)) {
@@ -1186,7 +1186,7 @@ bool IncomingPacket::_doREMOTE_TRACE(const RuntimeEnvironment *RR,void *tPtr,con
 
 void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void *tPtr,const SharedPtr<Peer> &peer,const uint64_t nwid)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	if (peer->rateGateOutgoingComRequest(now)) {
 		Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR);
 		outp.append((uint8_t)verb());

+ 2 - 2
node/IncomingPacket.hpp

@@ -77,7 +77,7 @@ public:
 	 * @param now Current time
 	 * @throws std::out_of_range Range error processing packet
 	 */
-	IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &path,uint64_t now) :
+	IncomingPacket(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now) :
 		Packet(data,len),
 		_receiveTime(now),
 		_path(path)
@@ -93,7 +93,7 @@ public:
 	 * @param now Current time
 	 * @throws std::out_of_range Range error processing packet
 	 */
-	inline void init(const void *data,unsigned int len,const SharedPtr<Path> &path,uint64_t now)
+	inline void init(const void *data,unsigned int len,const SharedPtr<Path> &path,int64_t now)
 	{
 		copyFrom(data,len);
 		_receiveTime = now;

+ 4 - 4
node/Membership.cpp

@@ -51,7 +51,7 @@ Membership::Membership() :
 	resetPushState();
 }
 
-void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
+void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force)
 {
 	bool sendCom = ( (nconf.com) && ( ((now - _lastPushedCom) >= ZT_CREDENTIAL_PUSH_EVERY) || (force) ) );
 
@@ -127,13 +127,13 @@ void Membership::pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const u
 
 Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironment *RR,void *tPtr,const NetworkConfig &nconf,const CertificateOfMembership &com)
 {
-	const uint64_t newts = com.timestamp();
+	const int64_t newts = com.timestamp();
 	if (newts <= _comRevocationThreshold) {
 		RR->t->credentialRejected(tPtr,com,"revoked");
 		return ADD_REJECTED;
 	}
 
-	const uint64_t oldts = _com.timestamp();
+	const int64_t oldts = _com.timestamp();
 	if (newts < oldts) {
 		RR->t->credentialRejected(tPtr,com,"old");
 		return ADD_REJECTED;
@@ -227,7 +227,7 @@ Membership::AddCredentialResult Membership::addCredential(const RuntimeEnvironme
 	}
 }
 
-void Membership::clean(const uint64_t now,const NetworkConfig &nconf)
+void Membership::clean(const int64_t now,const NetworkConfig &nconf)
 {
 	_cleanCredImpl<Tag>(nconf,_remoteTags);
 	_cleanCredImpl<Capability>(nconf,_remoteCaps);

+ 7 - 7
node/Membership.hpp

@@ -80,7 +80,7 @@ public:
 	 * @param localCapabilityIndex Index of local capability to include (in nconf.capabilities[]) or -1 if none
 	 * @param force If true, send objects regardless of last push time
 	 */
-	void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const uint64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force);
+	void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,const int64_t now,const Address &peerAddress,const NetworkConfig &nconf,int localCapabilityIndex,const bool force);
 
 	/**
 	 * Check whether we should push MULTICAST_LIKEs to this peer, and update last sent time if true
@@ -88,7 +88,7 @@ public:
 	 * @param now Current time
 	 * @return True if we should update multicasts
 	 */
-	inline bool multicastLikeGate(const uint64_t now)
+	inline bool multicastLikeGate(const int64_t now)
 	{
 		if ((now - _lastUpdatedMulticast) >= ZT_MULTICAST_ANNOUNCE_PERIOD) {
 			_lastUpdatedMulticast = now;
@@ -110,7 +110,7 @@ public:
 		return nconf.com.agreesWith(_com);
 	}
 
-	inline bool recentlyAssociated(const uint64_t now) const
+	inline bool recentlyAssociated(const int64_t now) const
 	{
 		return ((_com)&&((now - _com.timestamp()) < ZT_PEER_ACTIVITY_TIMEOUT));
 	}
@@ -180,7 +180,7 @@ public:
 	 * @param now Current time
 	 * @param nconf Current network configuration
 	 */
-	void clean(const uint64_t now,const NetworkConfig &nconf);
+	void clean(const int64_t now,const NetworkConfig &nconf);
 
 	/**
 	 * Reset last pushed time for local credentials
@@ -223,13 +223,13 @@ private:
 	}
 
 	// Last time we pushed MULTICAST_LIKE(s)
-	uint64_t _lastUpdatedMulticast;
+	int64_t _lastUpdatedMulticast;
 
 	// Last time we pushed our COM to this peer
-	uint64_t _lastPushedCom;
+	int64_t _lastPushedCom;
 
 	// Revocation threshold for COM or 0 if none
-	uint64_t _comRevocationThreshold;
+	int64_t _comRevocationThreshold;
 
 	// Remote member's latest network COM
 	CertificateOfMembership _com;

+ 4 - 4
node/Multicaster.cpp

@@ -51,7 +51,7 @@ Multicaster::~Multicaster()
 {
 }
 
-void Multicaster::addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown)
+void Multicaster::addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown)
 {
 	const unsigned char *p = (const unsigned char *)addresses;
 	const unsigned char *e = p + (5 * count);
@@ -160,7 +160,7 @@ std::vector<Address> Multicaster::getMembers(uint64_t nwid,const MulticastGroup
 void Multicaster::send(
 	void *tPtr,
 	unsigned int limit,
-	uint64_t now,
+	int64_t now,
 	uint64_t nwid,
 	bool disableCompression,
 	const std::vector<Address> &alwaysSendTo,
@@ -309,7 +309,7 @@ void Multicaster::send(
 		delete [] indexes;
 }
 
-void Multicaster::clean(uint64_t now)
+void Multicaster::clean(int64_t now)
 {
 	{
 		Mutex::Lock _l(_groups_m);
@@ -367,7 +367,7 @@ void Multicaster::addCredential(void *tPtr,const CertificateOfMembership &com,bo
 	}
 }
 
-void Multicaster::_add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
+void Multicaster::_add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member)
 {
 	// assumes _groups_m is locked
 

+ 6 - 6
node/Multicaster.hpp

@@ -98,7 +98,7 @@ public:
 	 * @param mg Multicast group
 	 * @param member New member address
 	 */
-	inline void add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
+	inline void add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const Address &member)
 	{
 		Mutex::Lock _l(_groups_m);
 		_add(tPtr,now,nwid,mg,_groups[Multicaster::Key(nwid,mg)],member);
@@ -117,7 +117,7 @@ public:
 	 * @param count Number of addresses
 	 * @param totalKnown Total number of known addresses as reported by peer
 	 */
-	void addMultiple(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
+	void addMultiple(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,const void *addresses,unsigned int count,unsigned int totalKnown);
 
 	/**
 	 * Remove a multicast group member (if present)
@@ -174,7 +174,7 @@ public:
 	void send(
 		void *tPtr,
 		unsigned int limit,
-		uint64_t now,
+		int64_t now,
 		uint64_t nwid,
 		bool disableCompression,
 		const std::vector<Address> &alwaysSendTo,
@@ -190,7 +190,7 @@ public:
 	 * @param RR Runtime environment
 	 * @param now Current time
 	 */
-	void clean(uint64_t now);
+	void clean(int64_t now);
 
 	/**
 	 * Add an authorization credential
@@ -212,7 +212,7 @@ public:
 	 * @param now Current time
 	 * @return True if GATHER and LIKE should be allowed
 	 */
-	bool cacheAuthorized(const Address &a,const uint64_t nwid,const uint64_t now) const
+	bool cacheAuthorized(const Address &a,const uint64_t nwid,const int64_t now) const
 	{
 		Mutex::Lock _l(_gatherAuth_m);
 		const uint64_t *p = _gatherAuth.get(_GatherAuthKey(nwid,a));
@@ -220,7 +220,7 @@ public:
 	}
 
 private:
-	void _add(void *tPtr,uint64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
+	void _add(void *tPtr,int64_t now,uint64_t nwid,const MulticastGroup &mg,MulticastGroupStatus &gs,const Address &member);
 
 	const RuntimeEnvironment *RR;
 

+ 5 - 5
node/Network.cpp

@@ -592,7 +592,7 @@ bool Network::filterOutgoingPacket(
 	const unsigned int etherType,
 	const unsigned int vlanId)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	Address ztFinalDest(ztDest);
 	int localCapabilityIndex = -1;
 	int accept = 0;
@@ -1164,7 +1164,7 @@ void Network::requestConfiguration(void *tPtr)
 
 bool Network::gate(void *tPtr,const SharedPtr<Peer> &peer)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	Mutex::Lock _l(_lock);
 	try {
 		if (_config) {
@@ -1192,7 +1192,7 @@ bool Network::recentlyAssociatedWith(const Address &addr)
 
 void Network::clean()
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	Mutex::Lock _l(_lock);
 
 	if (_destroyed)
@@ -1257,7 +1257,7 @@ void Network::learnBridgeRoute(const MAC &mac,const Address &addr)
 	}
 }
 
-void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now)
+void Network::learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now)
 {
 	Mutex::Lock _l(_lock);
 	const unsigned long tmp = (unsigned long)_multicastGroupsBehindMe.size();
@@ -1377,7 +1377,7 @@ void Network::_externalConfig(ZT_VirtualNetworkConfig *ec) const
 void Network::_sendUpdatesToMembers(void *tPtr,const MulticastGroup *const newMulticastGroup)
 {
 	// Assumes _lock is locked
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 
 	std::vector<MulticastGroup> groups;
 	if (newMulticastGroup)

+ 2 - 2
node/Network.hpp

@@ -305,7 +305,7 @@ public:
 	 * @param mg Multicast group
 	 * @param now Current time
 	 */
-	void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,uint64_t now);
+	void learnBridgedMulticastGroup(void *tPtr,const MulticastGroup &mg,int64_t now);
 
 	/**
 	 * Validate a credential and learn it if it passes certificate and other checks
@@ -357,7 +357,7 @@ public:
 	 * @param to Destination peer address
 	 * @param now Current time
 	 */
-	inline void pushCredentialsNow(void *tPtr,const Address &to,const uint64_t now)
+	inline void pushCredentialsNow(void *tPtr,const Address &to,const int64_t now)
 	{
 		Mutex::Lock _l(_lock);
 		_membership(to).pushCredentials(RR,tPtr,now,to,_config,-1,true);

+ 17 - 17
node/Node.cpp

@@ -54,7 +54,7 @@ namespace ZeroTier {
 /* Public Node interface (C++, exposed via CAPI bindings)                   */
 /****************************************************************************/
 
-Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
+Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
 	_RR(this),
 	RR(&_RR),
 	_uPtr(uptr),
@@ -139,12 +139,12 @@ Node::~Node()
 
 ZT_ResultCode Node::processWirePacket(
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	int64_t localSocket,
 	const struct sockaddr_storage *remoteAddress,
 	const void *packetData,
 	unsigned int packetLength,
-	volatile uint64_t *nextBackgroundTaskDeadline)
+	volatile int64_t *nextBackgroundTaskDeadline)
 {
 	_now = now;
 	RR->sw->onRemotePacket(tptr,localSocket,*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
@@ -153,7 +153,7 @@ ZT_ResultCode Node::processWirePacket(
 
 ZT_ResultCode Node::processVirtualNetworkFrame(
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	uint64_t nwid,
 	uint64_t sourceMac,
 	uint64_t destMac,
@@ -161,7 +161,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
 	unsigned int vlanId,
 	const void *frameData,
 	unsigned int frameLength,
-	volatile uint64_t *nextBackgroundTaskDeadline)
+	volatile int64_t *nextBackgroundTaskDeadline)
 {
 	_now = now;
 	SharedPtr<Network> nw(this->network(nwid));
@@ -175,7 +175,7 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
 class _PingPeersThatNeedPing
 {
 public:
-	_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &upstreamsToContact,uint64_t now) :
+	_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &upstreamsToContact,int64_t now) :
 		lastReceiveFromUpstream(0),
 		RR(renv),
 		_tPtr(tPtr),
@@ -185,7 +185,7 @@ public:
 	{
 	}
 
-	uint64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay
+	int64_t lastReceiveFromUpstream; // tracks last time we got a packet from an 'upstream' peer like a root or a relay
 
 	inline void operator()(Topology &t,const SharedPtr<Peer> &p)
 	{
@@ -234,17 +234,17 @@ private:
 	const RuntimeEnvironment *RR;
 	void *_tPtr;
 	Hashtable< Address,std::vector<InetAddress> > &_upstreamsToContact;
-	const uint64_t _now;
+	const int64_t _now;
 	const SharedPtr<Peer> _bestCurrentUpstream;
 };
 
-ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
+ZT_ResultCode Node::processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline)
 {
 	_now = now;
 	Mutex::Lock bl(_backgroundTasksLock);
 
 	unsigned long timeUntilNextPingCheck = ZT_PING_CHECK_INVERVAL;
-	const uint64_t timeSinceLastPingCheck = now - _lastPingCheck;
+	const int64_t timeSinceLastPingCheck = now - _lastPingCheck;
 	if (timeSinceLastPingCheck >= ZT_PING_CHECK_INVERVAL) {
 		try {
 			_lastPingCheck = now;
@@ -305,7 +305,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint
 	}
 
 	try {
-		*nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
+		*nextBackgroundTaskDeadline = now + (int64_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;
 	}
@@ -689,7 +689,7 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
 
 extern "C" {
 
-enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now)
+enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now)
 {
 	*node = (ZT_Node *)0;
 	try {
@@ -714,12 +714,12 @@ void ZT_Node_delete(ZT_Node *node)
 enum ZT_ResultCode ZT_Node_processWirePacket(
 	ZT_Node *node,
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	int64_t localSocket,
 	const struct sockaddr_storage *remoteAddress,
 	const void *packetData,
 	unsigned int packetLength,
-	volatile uint64_t *nextBackgroundTaskDeadline)
+	volatile int64_t *nextBackgroundTaskDeadline)
 {
 	try {
 		return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr,now,localSocket,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
@@ -733,7 +733,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
 enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
 	ZT_Node *node,
 	void *tptr,
-	uint64_t now,
+	int64_t now,
 	uint64_t nwid,
 	uint64_t sourceMac,
 	uint64_t destMac,
@@ -741,7 +741,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
 	unsigned int vlanId,
 	const void *frameData,
 	unsigned int frameLength,
-	volatile uint64_t *nextBackgroundTaskDeadline)
+	volatile int64_t *nextBackgroundTaskDeadline)
 {
 	try {
 		return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
@@ -752,7 +752,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
 	}
 }
 
-enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
+enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline)
 {
 	try {
 		return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(tptr,now,nextBackgroundTaskDeadline);

+ 13 - 13
node/Node.hpp

@@ -64,7 +64,7 @@ class World;
 class Node : public NetworkController::Sender
 {
 public:
-	Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now);
+	Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now);
 	virtual ~Node();
 
 	// Get rid of alignment warnings on 32-bit Windows and possibly improve performance
@@ -77,15 +77,15 @@ public:
 
 	ZT_ResultCode processWirePacket(
 		void *tptr,
-		uint64_t now,
+		int64_t now,
 		int64_t localSocket,
 		const struct sockaddr_storage *remoteAddress,
 		const void *packetData,
 		unsigned int packetLength,
-		volatile uint64_t *nextBackgroundTaskDeadline);
+		volatile int64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode processVirtualNetworkFrame(
 		void *tptr,
-		uint64_t now,
+		int64_t now,
 		uint64_t nwid,
 		uint64_t sourceMac,
 		uint64_t destMac,
@@ -93,8 +93,8 @@ public:
 		unsigned int vlanId,
 		const void *frameData,
 		unsigned int frameLength,
-		volatile uint64_t *nextBackgroundTaskDeadline);
-	ZT_ResultCode processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline);
+		volatile int64_t *nextBackgroundTaskDeadline);
+	ZT_ResultCode processBackgroundTasks(void *tptr,int64_t now,volatile int64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
 	ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
 	ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
@@ -114,7 +114,7 @@ public:
 
 	// Internal functions ------------------------------------------------------
 
-	inline uint64_t now() const { return _now; }
+	inline int64_t now() const { return _now; }
 
 	inline bool putPacket(void *tPtr,const int64_t localSocket,const InetAddress &addr,const void *data,unsigned int len,unsigned int ttl = 0)
 	{
@@ -243,7 +243,7 @@ public:
 	 * @param from Source address of packet
 	 * @return True if within rate limits
 	 */
-	inline bool rateGateIdentityVerification(const uint64_t now,const InetAddress &from)
+	inline bool rateGateIdentityVerification(const int64_t now,const InetAddress &from)
 	{
 		unsigned long iph = from.rateGateHash();
 		if ((now - _lastIdentityVerification[iph]) >= ZT_IDENTITY_VALIDATION_SOURCE_RATE_LIMIT) {
@@ -270,7 +270,7 @@ private:
 	uint32_t _expectingRepliesTo[ZT_EXPECTING_REPLIES_BUCKET_MASK1 + 1][ZT_EXPECTING_REPLIES_BUCKET_MASK2 + 1];
 
 	// Time of last identity verification indexed by InetAddress.rateGateHash() -- used in IncomingPacket::_doHELLO() via rateGateIdentityVerification()
-	uint64_t _lastIdentityVerification[16384];
+	int64_t _lastIdentityVerification[16384];
 
 	Hashtable< uint64_t,SharedPtr<Network> > _networks;
 	Mutex _networks_m;
@@ -281,10 +281,10 @@ private:
 	Mutex _backgroundTasksLock;
 
 	Address _remoteTraceTarget;
-	uint64_t _now;
-	uint64_t _lastPingCheck;
-	uint64_t _lastHousekeepingRun;
-	volatile uint64_t _prngState[2];
+	int64_t _now;
+	int64_t _lastPingCheck;
+	int64_t _lastHousekeepingRun;
+	volatile int64_t _prngState[2];
 	bool _online;
 };
 

+ 1 - 1
node/OutboundMulticast.hpp

@@ -96,7 +96,7 @@ public:
 	 * @param now Current time
 	 * @return True if this multicast is expired (has exceeded transmit timeout)
 	 */
-	inline bool expired(uint64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
+	inline bool expired(int64_t now) const { return ((now - _timestamp) >= ZT_MULTICAST_TRANSMIT_TIMEOUT); }
 
 	/**
 	 * @return True if this outbound multicast has been sent to enough peers

+ 1 - 1
node/Path.cpp

@@ -30,7 +30,7 @@
 
 namespace ZeroTier {
 
-bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now)
+bool Path::send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now)
 {
 	if (RR->node->putPacket(tPtr,_localSocket,_addr,data,len)) {
 		_lastOut = now;

+ 11 - 11
node/Path.hpp

@@ -179,14 +179,14 @@ public:
 	 * @param now Current time
 	 * @return True if transport reported success
 	 */
-	bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,uint64_t now);
+	bool send(const RuntimeEnvironment *RR,void *tPtr,const void *data,unsigned int len,int64_t now);
 
 	/**
 	 * Manually update last sent time
 	 *
 	 * @param t Time of send
 	 */
-	inline void sent(const uint64_t t) { _lastOut = t; }
+	inline void sent(const int64_t t) { _lastOut = t; }
 
 	/**
 	 * @return Local socket as specified by external code
@@ -206,7 +206,7 @@ public:
 	/**
 	 * @return True if path has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
 	 */
-	inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
+	inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
 
 	/**
 	 * @return Preference rank, higher == better
@@ -261,27 +261,27 @@ public:
 	/**
 	 * @return True if path appears alive
 	 */
-	inline bool alive(const uint64_t now) const { return ((now - _lastIn) <= ZT_PATH_ALIVE_TIMEOUT); }
+	inline bool alive(const int64_t now) const { return ((now - _lastIn) <= ZT_PATH_ALIVE_TIMEOUT); }
 
 	/**
 	 * @return True if this path needs a heartbeat
 	 */
-	inline bool needsHeartbeat(const uint64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
+	inline bool needsHeartbeat(const int64_t now) const { return ((now - _lastOut) >= ZT_PATH_HEARTBEAT_PERIOD); }
 
 	/**
 	 * @return Last time we sent something
 	 */
-	inline uint64_t lastOut() const { return _lastOut; }
+	inline int64_t lastOut() const { return _lastOut; }
 
 	/**
 	 * @return Last time we received anything
 	 */
-	inline uint64_t lastIn() const { return _lastIn; }
+	inline int64_t lastIn() const { return _lastIn; }
 
 	/**
 	 * @return Time last trust-established packet was received
 	 */
-	inline uint64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
+	inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
 
 	/**
 	 * Return and increment outgoing packet counter (used with Packet::armor())
@@ -291,9 +291,9 @@ public:
 	inline unsigned int nextOutgoingCounter() { return _outgoingPacketCounter++; }
 
 private:
-	volatile uint64_t _lastOut;
-	volatile uint64_t _lastIn;
-	volatile uint64_t _lastTrustEstablishedPacketReceived;
+	volatile int64_t _lastOut;
+	volatile int64_t _lastIn;
+	volatile int64_t _lastTrustEstablishedPacketReceived;
 	volatile uint64_t _incomingLinkQualityFastLog;
 	int64_t _localSocket;
 	volatile unsigned long _incomingLinkQualitySlowLogPtr;

+ 19 - 16
node/Peer.cpp

@@ -34,6 +34,7 @@
 #include "SelfAwareness.hpp"
 #include "Packet.hpp"
 #include "Trace.hpp"
+#include "InetAddress.hpp"
 
 namespace ZeroTier {
 
@@ -75,7 +76,7 @@ void Peer::received(
 	const bool trustEstablished,
 	const uint64_t networkId)
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 
 /*
 #ifdef ZT_ENABLE_CLUSTER
@@ -263,14 +264,14 @@ void Peer::received(
 	}
 }
 
-bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force)
+bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force)
 {
 	Mutex::Lock _l(_paths_m);
 
-	uint64_t v6lr = 0;
+	int64_t v6lr = 0;
 	if ( ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v6Path.p) )
 		v6lr = _v6Path.p->lastIn();
-	uint64_t v4lr = 0;
+	int64_t v4lr = 0;
 	if ( ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v4Path.p) )
 		v4lr = _v4Path.p->lastIn();
 
@@ -289,16 +290,18 @@ bool Peer::sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,
 	return false;
 }
 
-SharedPtr<Path> Peer::getBestPath(uint64_t now,bool includeExpired)
+SharedPtr<Path> Peer::getBestPath(int64_t now,bool includeExpired)
 {
 	Mutex::Lock _l(_paths_m);
 
-	uint64_t v6lr = 0;
-	if ( ( includeExpired || ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) ) && (_v6Path.p) )
+	int64_t v6lr = 0;
+	if ((includeExpired || ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION)) && (_v6Path.p)) {
 		v6lr = _v6Path.p->lastIn();
-	uint64_t v4lr = 0;
-	if ( ( includeExpired || ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) ) && (_v4Path.p) )
+	}
+	int64_t v4lr = 0;
+	if ((includeExpired || ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION)) && (_v4Path.p)) {
 		v4lr = _v4Path.p->lastIn();
+	}
 
 	if (v6lr > v4lr) {
 		return _v6Path.p;
@@ -309,7 +312,7 @@ SharedPtr<Path> Peer::getBestPath(uint64_t now,bool includeExpired)
 	return SharedPtr<Path>();
 }
 
-void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter)
+void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter)
 {
 	Packet outp(_id.address(),RR->identity.address(),Packet::VERB_HELLO);
 
@@ -357,7 +360,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
 	}
 }
 
-void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter)
+void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter)
 {
 	if ( (!sendFullHello) && (_vProto >= 5) && (!((_vMajor == 1)&&(_vMinor == 1)&&(_vRevision == 0))) ) {
 		Packet outp(_id.address(),RR->identity.address(),Packet::VERB_ECHO);
@@ -369,7 +372,7 @@ void Peer::attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAdd
 	}
 }
 
-void Peer::tryMemorizedPath(void *tPtr,uint64_t now)
+void Peer::tryMemorizedPath(void *tPtr,int64_t now)
 {
 	if ((now - _lastTriedMemorizedPath) >= ZT_TRY_MEMORIZED_PATH_INTERVAL) {
 		_lastTriedMemorizedPath = now;
@@ -379,15 +382,15 @@ void Peer::tryMemorizedPath(void *tPtr,uint64_t now)
 	}
 }
 
-bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily)
+bool Peer::doPingAndKeepalive(void *tPtr,int64_t now,int inetAddressFamily)
 {
 	Mutex::Lock _l(_paths_m);
 
 	if (inetAddressFamily < 0) {
-		uint64_t v6lr = 0;
+		int64_t v6lr = 0;
 		if ( ((now - _v6Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v6Path.p) )
 			v6lr = _v6Path.p->lastIn();
-		uint64_t v4lr = 0;
+		int64_t v4lr = 0;
 		if ( ((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION) && (_v4Path.p) )
 			v4lr = _v4Path.p->lastIn();
 
@@ -423,7 +426,7 @@ bool Peer::doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily)
 	return false;
 }
 
-void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now)
+void Peer::redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const int64_t now)
 {
 	if ((remoteAddress.ss_family != AF_INET)&&(remoteAddress.ss_family != AF_INET6)) // sanity check
 		return;

+ 38 - 38
node/Peer.hpp

@@ -120,7 +120,7 @@ public:
 	 * @param addr Remote address
 	 * @return True if we have an active path to this destination
 	 */
-	inline bool hasActivePathTo(uint64_t now,const InetAddress &addr) const
+	inline bool hasActivePathTo(int64_t now,const InetAddress &addr) const
 	{
 		Mutex::Lock _l(_paths_m);
 		return ( ((addr.ss_family == AF_INET)&&(_v4Path.p)&&(_v4Path.p->address() == addr)&&(_v4Path.p->alive(now))) || ((addr.ss_family == AF_INET6)&&(_v6Path.p)&&(_v6Path.p->address() == addr)&&(_v6Path.p->alive(now))) );
@@ -136,7 +136,7 @@ public:
 	 * @param force If true, send even if path is not alive
 	 * @return True if we actually sent something
 	 */
-	bool sendDirect(void *tPtr,const void *data,unsigned int len,uint64_t now,bool force);
+	bool sendDirect(void *tPtr,const void *data,unsigned int len,int64_t now,bool force);
 
 	/**
 	 * Get the best current direct path
@@ -148,7 +148,7 @@ public:
 	 * @param includeExpired If true, include even expired paths
 	 * @return Best current path or NULL if none
 	 */
-	SharedPtr<Path> getBestPath(uint64_t now,bool includeExpired);
+	SharedPtr<Path> getBestPath(int64_t now,bool includeExpired);
 
 	/**
 	 * Send a HELLO to this peer at a specified physical address
@@ -161,7 +161,7 @@ public:
 	 * @param now Current time
 	 * @param counter Outgoing packet counter
 	 */
-	void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,unsigned int counter);
+	void sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,unsigned int counter);
 
 	/**
 	 * Send ECHO (or HELLO for older peers) to this peer at the given address
@@ -175,7 +175,7 @@ public:
 	 * @param sendFullHello If true, always send a full HELLO instead of just an ECHO
 	 * @param counter Outgoing packet counter
 	 */
-	void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,uint64_t now,bool sendFullHello,unsigned int counter);
+	void attemptToContactAt(void *tPtr,const int64_t localSocket,const InetAddress &atAddress,int64_t now,bool sendFullHello,unsigned int counter);
 
 	/**
 	 * Try a memorized or statically defined path if any are known
@@ -185,7 +185,7 @@ public:
 	 * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
 	 * @param now Current time
 	 */
-	void tryMemorizedPath(void *tPtr,uint64_t now);
+	void tryMemorizedPath(void *tPtr,int64_t now);
 
 	/**
 	 * Send pings or keepalives depending on configured timeouts
@@ -195,7 +195,7 @@ public:
 	 * @param inetAddressFamily Keep this address family alive, or -1 for any
 	 * @return True if we have at least one direct path of the given family (or any if family is -1)
 	 */
-	bool doPingAndKeepalive(void *tPtr,uint64_t now,int inetAddressFamily);
+	bool doPingAndKeepalive(void *tPtr,int64_t now,int inetAddressFamily);
 
 	/**
 	 * Specify remote path for this peer and forget others
@@ -209,7 +209,7 @@ public:
 	 * @param remoteAddress Remote address
 	 * @param now Current time
 	 */
-	void redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const uint64_t now);
+	void redirect(void *tPtr,const int64_t localSocket,const InetAddress &remoteAddress,const int64_t now);
 
 	/**
 	 * Reset paths within a given IP scope and address family
@@ -222,7 +222,7 @@ public:
 	 * @param inetAddressFamily Family e.g. AF_INET
 	 * @param now Current time
 	 */
-	inline void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,uint64_t now)
+	inline void resetWithinScope(void *tPtr,InetAddress::IpScope scope,int inetAddressFamily,int64_t now)
 	{
 		Mutex::Lock _l(_paths_m);
 		if ((inetAddressFamily == AF_INET)&&(_v4Path.lr)&&(_v4Path.p->address().ipScope() == scope)) {
@@ -243,7 +243,7 @@ public:
 	 * @param v4 Result parameter to receive active IPv4 address, if any
 	 * @param v6 Result parameter to receive active IPv6 address, if any
 	 */
-	inline void getRendezvousAddresses(uint64_t now,InetAddress &v4,InetAddress &v6) const
+	inline void getRendezvousAddresses(int64_t now,InetAddress &v4,InetAddress &v6) const
 	{
 		Mutex::Lock _l(_paths_m);
 		if (((now - _v4Path.lr) < ZT_PEER_PATH_EXPIRATION)&&(_v4Path.p->alive(now)))
@@ -256,7 +256,7 @@ public:
 	 * @param now Current time
 	 * @return All known paths to this peer
 	 */
-	inline std::vector< SharedPtr<Path> > paths(const uint64_t now) const
+	inline std::vector< SharedPtr<Path> > paths(const int64_t now) const
 	{
 		std::vector< SharedPtr<Path> > pp;
 		Mutex::Lock _l(_paths_m);
@@ -270,17 +270,17 @@ public:
 	/**
 	 * @return Time of last receive of anything, whether direct or relayed
 	 */
-	inline uint64_t lastReceive() const { return _lastReceive; }
+	inline int64_t lastReceive() const { return _lastReceive; }
 
 	/**
 	 * @return True if we've heard from this peer in less than ZT_PEER_ACTIVITY_TIMEOUT
 	 */
-	inline bool isAlive(const uint64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
+	inline bool isAlive(const int64_t now) const { return ((now - _lastReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
 
 	/**
 	 * @return True if this peer has sent us real network traffic recently
 	 */
-	inline uint64_t isActive(uint64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
+	inline int64_t isActive(int64_t now) const { return ((now - _lastNontrivialReceive) < ZT_PEER_ACTIVITY_TIMEOUT); }
 
 	/**
 	 * @return Latency in milliseconds or 0 if unknown
@@ -298,7 +298,7 @@ public:
 	 *
 	 * @return Relay quality score computed from latency and other factors, lower is better
 	 */
-	inline unsigned int relayQuality(const uint64_t now) const
+	inline unsigned int relayQuality(const int64_t now) const
 	{
 		const uint64_t tsr = now - _lastReceive;
 		if (tsr >= ZT_PEER_ACTIVITY_TIMEOUT)
@@ -353,12 +353,12 @@ public:
 	/**
 	 * @return True if peer has received a trust established packet (e.g. common network membership) in the past ZT_TRUST_EXPIRATION ms
 	 */
-	inline bool trustEstablished(const uint64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
+	inline bool trustEstablished(const int64_t now) const { return ((now - _lastTrustEstablishedPacketReceived) < ZT_TRUST_EXPIRATION); }
 
 	/**
 	 * Rate limit gate for VERB_PUSH_DIRECT_PATHS
 	 */
-	inline bool rateGatePushDirectPaths(const uint64_t now)
+	inline bool rateGatePushDirectPaths(const int64_t now)
 	{
 		if ((now - _lastDirectPathPushReceive) <= ZT_PUSH_DIRECT_PATHS_CUTOFF_TIME)
 			++_directPathPushCutoffCount;
@@ -370,7 +370,7 @@ public:
 	/**
 	 * Rate limit gate for VERB_NETWORK_CREDENTIALS
 	 */
-	inline bool rateGateCredentialsReceived(const uint64_t now)
+	inline bool rateGateCredentialsReceived(const int64_t now)
 	{
 		if ((now - _lastCredentialsReceived) <= ZT_PEER_CREDENTIALS_CUTOFF_TIME)
 			++_credentialsCutoffCount;
@@ -382,7 +382,7 @@ public:
 	/**
 	 * Rate limit gate for sending of ERROR_NEED_MEMBERSHIP_CERTIFICATE
 	 */
-	inline bool rateGateRequestCredentials(const uint64_t now)
+	inline bool rateGateRequestCredentials(const int64_t now)
 	{
 		if ((now - _lastCredentialRequestSent) >= ZT_PEER_GENERAL_RATE_LIMIT) {
 			_lastCredentialRequestSent = now;
@@ -394,7 +394,7 @@ public:
 	/**
 	 * Rate limit gate for inbound WHOIS requests
 	 */
-	inline bool rateGateInboundWhoisRequest(const uint64_t now)
+	inline bool rateGateInboundWhoisRequest(const int64_t now)
 	{
 		if ((now - _lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) {
 			_lastWhoisRequestReceived = now;
@@ -406,7 +406,7 @@ public:
 	/**
 	 * Rate limit gate for inbound ECHO requests
 	 */
-	inline bool rateGateEchoRequest(const uint64_t now)
+	inline bool rateGateEchoRequest(const int64_t now)
 	{
 		if ((now - _lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) {
 			_lastEchoRequestReceived = now;
@@ -418,7 +418,7 @@ public:
 	/**
 	 * Rate gate incoming requests for network COM
 	 */
-	inline bool rateGateIncomingComRequest(const uint64_t now)
+	inline bool rateGateIncomingComRequest(const int64_t now)
 	{
 		if ((now - _lastComRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) {
 			_lastComRequestReceived = now;
@@ -430,7 +430,7 @@ public:
 	/**
 	 * Rate gate outgoing requests for network COM
 	 */
-	inline bool rateGateOutgoingComRequest(const uint64_t now)
+	inline bool rateGateOutgoingComRequest(const int64_t now)
 	{
 		if ((now - _lastComRequestSent) >= ZT_PEER_GENERAL_RATE_LIMIT) {
 			_lastComRequestSent = now;
@@ -484,7 +484,7 @@ public:
 	}
 
 	template<unsigned int C>
-	inline static SharedPtr<Peer> deserializeFromCache(uint64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
+	inline static SharedPtr<Peer> deserializeFromCache(int64_t now,void *tPtr,Buffer<C> &b,const RuntimeEnvironment *renv)
 	{
 		try {
 			unsigned int ptr = 0;
@@ -527,8 +527,8 @@ private:
 	struct _PeerPath
 	{
 		_PeerPath() : lr(0),sticky(0),p() {}
-		uint64_t lr; // time of last valid ZeroTier packet
-		uint64_t sticky; // time last set as sticky
+		int64_t lr; // time of last valid ZeroTier packet
+		int64_t sticky; // time last set as sticky
 		SharedPtr<Path> p;
 	};
 
@@ -536,18 +536,18 @@ private:
 
 	const RuntimeEnvironment *RR;
 
-	uint64_t _lastReceive; // direct or indirect
-	uint64_t _lastNontrivialReceive; // frames, things like netconf, etc.
-	uint64_t _lastTriedMemorizedPath;
-	uint64_t _lastDirectPathPushSent;
-	uint64_t _lastDirectPathPushReceive;
-	uint64_t _lastCredentialRequestSent;
-	uint64_t _lastWhoisRequestReceived;
-	uint64_t _lastEchoRequestReceived;
-	uint64_t _lastComRequestReceived;
-	uint64_t _lastComRequestSent;
-	uint64_t _lastCredentialsReceived;
-	uint64_t _lastTrustEstablishedPacketReceived;
+	int64_t _lastReceive; // direct or indirect
+	int64_t _lastNontrivialReceive; // frames, things like netconf, etc.
+	int64_t _lastTriedMemorizedPath;
+	int64_t _lastDirectPathPushSent;
+	int64_t _lastDirectPathPushReceive;
+	int64_t _lastCredentialRequestSent;
+	int64_t _lastWhoisRequestReceived;
+	int64_t _lastEchoRequestReceived;
+	int64_t _lastComRequestReceived;
+	int64_t _lastComRequestSent;
+	int64_t _lastCredentialsReceived;
+	int64_t _lastTrustEstablishedPacketReceived;
 
 	uint16_t _vProto;
 	uint16_t _vMajor;

+ 2 - 2
node/Revocation.hpp

@@ -85,7 +85,7 @@ public:
 	inline uint32_t id() const { return _id; }
 	inline uint32_t credentialId() const { return _credentialId; }
 	inline uint64_t networkId() const { return _networkId; }
-	inline uint64_t threshold() const { return _threshold; }
+	inline int64_t threshold() const { return _threshold; }
 	inline const Address &target() const { return _target; }
 	inline const Address &signer() const { return _signedBy; }
 	inline Credential::Type type() const { return _type; }
@@ -184,7 +184,7 @@ private:
 	uint32_t _id;
 	uint32_t _credentialId;
 	uint64_t _networkId;
-	uint64_t _threshold;
+	int64_t _threshold;
 	uint64_t _flags;
 	Address _target;
 	Address _signedBy;

+ 3 - 3
node/SelfAwareness.cpp

@@ -49,7 +49,7 @@ namespace ZeroTier {
 class _ResetWithinScope
 {
 public:
-	_ResetWithinScope(void *tPtr,uint64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
+	_ResetWithinScope(void *tPtr,int64_t now,int inetAddressFamily,InetAddress::IpScope scope) :
 		_now(now),
 		_tPtr(tPtr),
 		_family(inetAddressFamily),
@@ -70,7 +70,7 @@ SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) :
 {
 }
 
-void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now)
+void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now)
 {
 	const InetAddress::IpScope scope = myPhysicalAddress.ipScope();
 
@@ -112,7 +112,7 @@ void SelfAwareness::iam(void *tPtr,const Address &reporter,const int64_t receive
 	}
 }
 
-void SelfAwareness::clean(uint64_t now)
+void SelfAwareness::clean(int64_t now)
 {
 	Mutex::Lock _l(_phy_m);
 	Hashtable< PhySurfaceKey,PhySurfaceEntry >::Iterator i(_phy);

+ 2 - 2
node/SelfAwareness.hpp

@@ -55,14 +55,14 @@ public:
 	 * @param trusted True if this peer is trusted as an authority to inform us of external address changes
 	 * @param now Current time
 	 */
-	void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,uint64_t now);
+	void iam(void *tPtr,const Address &reporter,const int64_t receivedOnLocalSocket,const InetAddress &reporterPhysicalAddress,const InetAddress &myPhysicalAddress,bool trusted,int64_t now);
 
 	/**
 	 * Clean up database periodically
 	 *
 	 * @param now Current time
 	 */
-	void clean(uint64_t now);
+	void clean(int64_t now);
 
 	/**
 	 * If we appear to be behind a symmetric NAT, get predictions for possible external endpoints

+ 10 - 10
node/Switch.cpp

@@ -57,7 +57,7 @@ Switch::Switch(const RuntimeEnvironment *renv) :
 void Switch::onRemotePacket(void *tPtr,const int64_t localSocket,const InetAddress &fromAddr,const void *data,unsigned int len)
 {
 	try {
-		const uint64_t now = RR->node->now();
+		const int64_t now = RR->node->now();
 
 		const SharedPtr<Path> path(RR->topology->getPath(localSocket,fromAddr));
 		path->received(now);
@@ -557,14 +557,14 @@ void Switch::send(void *tPtr,Packet &packet,bool encrypt)
 	}
 }
 
-void Switch::requestWhois(void *tPtr,const uint64_t now,const Address &addr)
+void Switch::requestWhois(void *tPtr,const int64_t now,const Address &addr)
 {
 	if (addr == RR->identity.address())
 		return;
 
 	{
 		Mutex::Lock _l(_lastSentWhoisRequest_m);
-		uint64_t &last = _lastSentWhoisRequest[addr];
+		int64_t &last = _lastSentWhoisRequest[addr];
 		if ((now - last) < ZT_WHOIS_RETRY_DELAY)
 			return;
 		else last = now;
@@ -586,7 +586,7 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
 		_lastSentWhoisRequest.erase(peer->address());
 	}
 
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	for(unsigned int ptr=0;ptr<ZT_RX_QUEUE_SIZE;++ptr) {
 		RXQueueEntry *const rq = &(_rxQueue[ptr]);
 		if ((rq->timestamp)&&(rq->complete)) {
@@ -611,7 +611,7 @@ void Switch::doAnythingWaitingForPeer(void *tPtr,const SharedPtr<Peer> &peer)
 	}
 }
 
-unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
+unsigned long Switch::doTimerTasks(void *tPtr,int64_t now)
 {
 	const uint64_t timeSinceLastCheck = now - _lastCheckedQueues;
 	if (timeSinceLastCheck < ZT_WHOIS_RETRY_DELAY)
@@ -663,9 +663,9 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
 
 	{
 		Mutex::Lock _l(_lastSentWhoisRequest_m);
-		Hashtable< Address,uint64_t >::Iterator i(_lastSentWhoisRequest);
+		Hashtable< Address,int64_t >::Iterator i(_lastSentWhoisRequest);
 		Address *a = (Address *)0;
-		uint64_t *ts = (uint64_t *)0;
+		int64_t *ts = (int64_t *)0;
 		while (i.next(a,ts)) {
 			if ((now - *ts) > (ZT_WHOIS_RETRY_DELAY * 2))
 				_lastSentWhoisRequest.erase(*a);
@@ -675,7 +675,7 @@ unsigned long Switch::doTimerTasks(void *tPtr,uint64_t now)
 	return ZT_WHOIS_RETRY_DELAY;
 }
 
-bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address &destination)
+bool Switch::_shouldUnite(const int64_t now,const Address &source,const Address &destination)
 {
 	Mutex::Lock _l(_lastUniteAttempt_m);
 	uint64_t &ts = _lastUniteAttempt[_LastUniteKey(source,destination)];
@@ -689,7 +689,7 @@ bool Switch::_shouldUnite(const uint64_t now,const Address &source,const Address
 bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
 {
 	SharedPtr<Path> viaPath;
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	const Address destination(packet.destination());
 
 	const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,destination));
@@ -703,7 +703,7 @@ bool Switch::_trySend(void *tPtr,Packet &packet,bool encrypt)
 
 		viaPath = peer->getBestPath(now,false);
 		if ( (viaPath) && (!viaPath->alive(now)) && (!RR->topology->isUpstream(peer->identity())) ) {
-			if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(uint64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
+			if ((now - viaPath->lastOut()) > std::max((now - viaPath->lastIn()) * 4,(int64_t)ZT_PATH_MIN_REACTIVATE_INTERVAL)) {
 				peer->attemptToContactAt(tPtr,viaPath->localSocket(),viaPath->address(),now,false,viaPath->nextOutgoingCounter());
 				viaPath->sent(now);
 			}

+ 7 - 7
node/Switch.hpp

@@ -114,7 +114,7 @@ public:
 	 * @param now Current time
 	 * @param addr Address to look up
 	 */
-	void requestWhois(void *tPtr,const uint64_t now,const Address &addr);
+	void requestWhois(void *tPtr,const int64_t now,const Address &addr);
 
 	/**
 	 * Run any processes that are waiting for this peer's identity
@@ -136,25 +136,25 @@ public:
 	 * @param now Current time
 	 * @return Number of milliseconds until doTimerTasks() should be run again
 	 */
-	unsigned long doTimerTasks(void *tPtr,uint64_t now);
+	unsigned long doTimerTasks(void *tPtr,int64_t now);
 
 private:
-	bool _shouldUnite(const uint64_t now,const Address &source,const Address &destination);
+	bool _shouldUnite(const int64_t now,const Address &source,const Address &destination);
 	bool _trySend(void *tPtr,Packet &packet,bool encrypt); // packet is modified if return is true
 
 	const RuntimeEnvironment *const RR;
-	uint64_t _lastBeaconResponse;
-	volatile uint64_t _lastCheckedQueues;
+	int64_t _lastBeaconResponse;
+	volatile int64_t _lastCheckedQueues;
 
 	// Time we last sent a WHOIS request for each address
-	Hashtable< Address,uint64_t > _lastSentWhoisRequest;
+	Hashtable< Address,int64_t > _lastSentWhoisRequest;
 	Mutex _lastSentWhoisRequest_m;
 
 	// Packets waiting for WHOIS replies or other decode info or missing fragments
 	struct RXQueueEntry
 	{
 		RXQueueEntry() : timestamp(0) {}
-		volatile uint64_t timestamp; // 0 if entry is not in use
+		volatile int64_t timestamp; // 0 if entry is not in use
 		volatile uint64_t packetId;
 		IncomingPacket frag0; // head of packet
 		Packet::Fragment frags[ZT_MAX_PACKET_FRAGMENTS - 1]; // later fragments (if any)

+ 4 - 3
node/Topology.cpp

@@ -133,8 +133,9 @@ SharedPtr<Peer> Topology::getPeer(void *tPtr,const Address &zta)
 			if (ap)
 				return ap;
 			ap = Peer::deserializeFromCache(RR->node->now(),tPtr,buf,RR);
-			if (!ap)
+			if (!ap) {
 				_peers.erase(zta);
+			}
 			return SharedPtr<Peer>();
 		}
 	} catch ( ... ) {} // ignore invalid identities or other strage failures
@@ -157,7 +158,7 @@ Identity Topology::getIdentity(void *tPtr,const Address &zta)
 
 SharedPtr<Peer> Topology::getUpstreamPeer()
 {
-	const uint64_t now = RR->node->now();
+	const int64_t now = RR->node->now();
 	unsigned int bestq = ~((unsigned int)0);
 	const SharedPtr<Peer> *best = (const SharedPtr<Peer> *)0;
 
@@ -365,7 +366,7 @@ void Topology::removeMoon(void *tPtr,const uint64_t id)
 	_memoizeUpstreams(tPtr);
 }
 
-void Topology::doPeriodicTasks(void *tPtr,uint64_t now)
+void Topology::doPeriodicTasks(void *tPtr,int64_t now)
 {
 	{
 		Mutex::Lock _l1(_peers_m);

+ 2 - 2
node/Topology.hpp

@@ -286,13 +286,13 @@ public:
 	/**
 	 * Clean and flush database
 	 */
-	void doPeriodicTasks(void *tPtr,uint64_t now);
+	void doPeriodicTasks(void *tPtr,int64_t now);
 
 	/**
 	 * @param now Current time
 	 * @return Number of peers with active direct paths
 	 */
-	inline unsigned long countActive(uint64_t now) const
+	inline unsigned long countActive(int64_t now) const
 	{
 		unsigned long cnt = 0;
 		Mutex::Lock _l(_peers_m);

+ 3 - 3
one.cpp

@@ -364,9 +364,9 @@ static int cli(int argc,char **argv)
 								if (path["preferred"]) {
 									char tmp[256];
 									std::string addr = path["address"];
-									const uint64_t now = OSUtils::now();
+									const int64_t now = OSUtils::now();
 									const double lq = (path.count("linkQuality")) ? (double)path["linkQuality"] : -1.0;
-									OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%llu;%llu;%1.2f",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"],lq);
+									OSUtils::ztsnprintf(tmp,sizeof(tmp),"%s;%lld;%lld;%1.2f",addr.c_str(),now - (int64_t)path["lastSend"],now - (int64_t)path["lastReceive"],lq);
 									bestPath = tmp;
 									break;
 								}
@@ -864,7 +864,7 @@ static int idtool(int argc,char **argv)
 			}
 			std::sort(roots.begin(),roots.end());
 
-			const uint64_t now = OSUtils::now();
+			const int64_t now = OSUtils::now();
 			World w(World::make(t,id,now,updatesMustBeSignedBy,roots,signingKey));
 			Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> wbuf;
 			w.serialize(wbuf);

+ 3 - 3
osdep/OSUtils.hpp

@@ -200,7 +200,7 @@ public:
 	/**
 	 * @return Current time in milliseconds since epoch
 	 */
-	static inline uint64_t now()
+	static inline int64_t now()
 	{
 #ifdef __WINDOWS__
 		FILETIME ft;
@@ -210,7 +210,7 @@ public:
 		SystemTimeToFileTime(&st,&ft);
 		tmp.LowPart = ft.dwLowDateTime;
 		tmp.HighPart = ft.dwHighDateTime;
-		return ( ((tmp.QuadPart - 116444736000000000ULL) / 10000L) + st.wMilliseconds );
+		return (int64_t)( ((tmp.QuadPart - 116444736000000000LL) / 10000L) + st.wMilliseconds );
 #else
 		struct timeval tv;
 #ifdef __LINUX__
@@ -218,7 +218,7 @@ public:
 #else
 		gettimeofday(&tv,(struct timezone *)0);
 #endif
-		return ( (1000ULL * (uint64_t)tv.tv_sec) + (uint64_t)(tv.tv_usec / 1000) );
+		return ( (1000LL * (int64_t)tv.tv_sec) + (int64_t)(tv.tv_usec / 1000) );
 #endif
 	};
 

+ 1 - 1
osdep/PortMapper.cpp

@@ -131,7 +131,7 @@ public:
 
 					InetAddress publicAddress;
 					sendpublicaddressrequest(&natpmp);
-					uint64_t myTimeout = OSUtils::now() + 5000;
+					int64_t myTimeout = OSUtils::now() + 5000;
 					do {
 						fd_set fds;
 						struct timeval timeout;

+ 13 - 9
service/OneService.cpp

@@ -276,6 +276,10 @@ static void _peerToJson(nlohmann::json &pj,const ZT_Peer *peer)
 		pa.push_back(j);
 	}
 	pj["paths"] = pa;
+
+	if (peer->address == 0xda6c71a1ad) {
+		fprintf(stdout, "%s\n", pj.dump(2).c_str());
+	}
 }
 
 static void _moonToJson(nlohmann::json &mj,const World &world)
@@ -436,7 +440,7 @@ public:
 	uint64_t _lastRestart;
 
 	// Deadline for the next background task service function
-	volatile uint64_t _nextBackgroundTaskDeadline;
+	volatile int64_t _nextBackgroundTaskDeadline;
 
 	// Configured networks
 	struct NetworkState
@@ -755,12 +759,12 @@ public:
 
 			// Main I/O loop
 			_nextBackgroundTaskDeadline = 0;
-			uint64_t clockShouldBe = OSUtils::now();
+			int64_t clockShouldBe = OSUtils::now();
 			_lastRestart = clockShouldBe;
-			uint64_t lastTapMulticastGroupCheck = 0;
-			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
+			int64_t lastTapMulticastGroupCheck = 0;
+			int64_t lastBindRefresh = 0;
+			int64_t lastUpdateCheck = clockShouldBe;
+			int64_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
 			for(;;) {
 				_run_m.lock();
 				if (!_run) {
@@ -773,7 +777,7 @@ public:
 					_run_m.unlock();
 				}
 
-				const uint64_t now = OSUtils::now();
+				const int64_t now = OSUtils::now();
 
 				// Attempt to detect sleep/wake events by detecting delay overruns
 				bool restarted = false;
@@ -809,7 +813,7 @@ public:
 				}
 
 				// Run background task processor in core if it's time to do so
-				uint64_t dl = _nextBackgroundTaskDeadline;
+				int64_t dl = _nextBackgroundTaskDeadline;
 				if (dl <= now) {
 					_node->processBackgroundTasks((void *)0,now,&_nextBackgroundTaskDeadline);
 					dl = _nextBackgroundTaskDeadline;
@@ -2152,7 +2156,7 @@ public:
 				// Engage TCP tunnel fallback if we haven't received anything valid from a global
 				// IP address in ZT_TCP_FALLBACK_AFTER milliseconds. If we do start getting
 				// valid direct traffic we'll stop using it and close the socket after a while.
-				const uint64_t now = OSUtils::now();
+				const int64_t now = OSUtils::now();
 				if (((now - _lastDirectReceiveFromGlobal) > ZT_TCP_FALLBACK_AFTER)&&((now - _lastRestart) > ZT_TCP_FALLBACK_AFTER)) {
 					if (_tcpFallbackTunnel) {
 						bool flushNow = false;

+ 1 - 1
service/SoftwareUpdater.cpp

@@ -303,7 +303,7 @@ void SoftwareUpdater::handleSoftwareUpdateUserMessage(uint64_t origin,const void
 	}
 }
 
-bool SoftwareUpdater::check(const uint64_t now)
+bool SoftwareUpdater::check(const int64_t now)
 {
 	if ((now - _lastCheckTime) >= ZT_SOFTWARE_UPDATE_CHECK_PERIOD) {
 		_lastCheckTime = now;

+ 1 - 1
service/SoftwareUpdater.hpp

@@ -167,7 +167,7 @@ public:
 	 *
 	 * @return True if we've downloaded and verified an update
 	 */
-	bool check(const uint64_t now);
+	bool check(const int64_t now);
 
 	/**
 	 * @return Meta-data for downloaded update or NULL if none