summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Constants.hpp18
-rw-r--r--node/IncomingPacket.cpp36
-rw-r--r--node/InetAddress.cpp2
-rw-r--r--node/Multicaster.cpp16
-rw-r--r--node/Network.cpp13
-rw-r--r--node/NetworkConfig.cpp23
-rw-r--r--node/NetworkConfig.hpp26
-rw-r--r--node/NetworkController.hpp8
-rw-r--r--node/Node.cpp1
-rw-r--r--node/Peer.cpp4
-rw-r--r--node/SelfAwareness.cpp15
-rw-r--r--node/SelfAwareness.hpp6
-rw-r--r--node/Switch.cpp30
-rw-r--r--node/Switch.hpp4
-rw-r--r--node/Topology.hpp8
15 files changed, 107 insertions, 103 deletions
diff --git a/node/Constants.hpp b/node/Constants.hpp
index d15fef13..b7aa9817 100644
--- a/node/Constants.hpp
+++ b/node/Constants.hpp
@@ -60,6 +60,13 @@
#include <endian.h>
#endif
+// Disable type punning on ARM architecture -- some ARM chips throw SIGBUS on unaligned access
+#if defined(__arm__) || defined(__ARMEL__)
+#ifndef ZT_NO_TYPE_PUNNING
+#define ZT_NO_TYPE_PUNNING
+#endif
+#endif
+
#if defined(__FreeBSD__) || defined(__OpenBSD__)
#ifndef __UNIX_LIKE__
#define __UNIX_LIKE__
@@ -158,7 +165,7 @@
/**
* Maximum number of packet fragments we'll support
- *
+ *
* The actual spec allows 16, but this is the most we'll support right
* now. Packets with more than this many fragments are dropped.
*/
@@ -216,7 +223,7 @@
/**
* Maximum number of ZT hops allowed (this is not IP hops/TTL)
- *
+ *
* The protocol allows up to 7, but we limit it to something smaller.
*/
#define ZT_RELAY_MAX_HOPS 3
@@ -246,10 +253,10 @@
/**
* How frequently to send a zero-byte UDP keepalive packet
*
- * There are NATs with timeouts as short as 30 seconds, so this turns out
+ * There are NATs with timeouts as short as 20 seconds, so this turns out
* to be needed.
*/
-#define ZT_NAT_KEEPALIVE_DELAY 25000
+#define ZT_NAT_KEEPALIVE_DELAY 19000
/**
* Delay between scans of the topology active peer DB for peers that need ping
@@ -296,6 +303,9 @@
/**
* Delay between initial direct NAT-t packet and more aggressive techniques
+ *
+ * This may also be a delay before sending the first packet if we determine
+ * that we should wait for the remote to initiate rendezvous first.
*/
#define ZT_NAT_T_TACTICAL_ESCALATION_DELAY 1000
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp
index ae99352e..b1fda8ef 100644
--- a/node/IncomingPacket.cpp
+++ b/node/IncomingPacket.cpp
@@ -392,28 +392,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p
const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN);
const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen);
if (dict.length()) {
- if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new
- /* If this configuration was indeed new, we do another
- * controller request with its revision. We do this in
- * order to (a) tell the network controller we got it (it
- * won't send a duplicate if ts == current), and (b)
- * get another one if the controller is changing rapidly
- * until we finally have the final version.
- *
- * Note that we don't do this for network controllers with
- * versions <= 1.0.3, since those regenerate a new controller
- * with a new revision every time. In that case this double
- * confirmation would create a race condition. */
- const SharedPtr<NetworkConfig> nc(nw->config2());
- if ((peer->atLeastVersion(1,0,3))&&(nc)&&(nc->revision() > 0)) {
- Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
- outp.append((uint64_t)nw->id());
- outp.append((uint16_t)0); // no meta-data
- outp.append((uint64_t)nc->revision());
- outp.armor(peer->key(),true);
- RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
- }
- }
+ nw->setConfiguration(Dictionary(dict));
TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str());
}
}
@@ -509,7 +488,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr<
InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port);
TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str());
peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP);
- RR->sw->contact(withPeer,atAddr);
+ RR->sw->rendezvous(withPeer,atAddr);
} else {
TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str());
}
@@ -692,6 +671,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
if (RR->localNetworkController) {
Dictionary netconf;
switch(RR->localNetworkController->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,RR->identity,peer->identity(),nwid,metaData,haveRevision,netconf)) {
+
case NetworkController::NETCONF_QUERY_OK: {
const std::string netconfStr(netconf.toString());
if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit
@@ -712,8 +692,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
}
}
} break;
- case NetworkController::NETCONF_QUERY_OK_BUT_NOT_NEWER: // nothing to do -- netconf has not changed
- break;
+
case NetworkController::NETCONF_QUERY_OBJECT_NOT_FOUND: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@@ -723,6 +702,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break;
+
case NetworkController::NETCONF_QUERY_ACCESS_DENIED: {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
@@ -732,12 +712,18 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons
outp.armor(peer->key(),true);
RR->node->putPacket(_remoteAddress,outp.data(),outp.size());
} break;
+
case NetworkController::NETCONF_QUERY_INTERNAL_SERVER_ERROR:
TRACE("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str());
break;
+
+ case NetworkController::NETCONF_QUERY_IGNORE:
+ break;
+
default:
TRACE("NETWORK_CONFIG_REQUEST failed: invalid return value from NetworkController::doNetworkConfigRequest()");
break;
+
}
} else {
Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR);
diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index 91bfbed6..1942c4cd 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -74,7 +74,7 @@ InetAddress::IpScope InetAddress::ipScope() const
if ((ip & 0xfff00000) == 0xac100000) return IP_SCOPE_PRIVATE; // 172.16.0.0/12
break;
case 0xc0:
- if ((ip & 0xffff0000) == 0xc9a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16
+ if ((ip & 0xffff0000) == 0xc0a80000) return IP_SCOPE_PRIVATE; // 192.168.0.0/16
break;
case 0xff: return IP_SCOPE_NONE; // 255.0.0.0/8 (broadcast, or unused/unusable)
default:
diff --git a/node/Multicaster.cpp b/node/Multicaster.cpp
index 33424e4a..489c170b 100644
--- a/node/Multicaster.cpp
+++ b/node/Multicaster.cpp
@@ -211,9 +211,11 @@ void Multicaster::send(
unsigned int count = 0;
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
- out.sendOnly(RR,*ast);
- if (++count >= limit)
- break;
+ if (*ast != RR->identity.address()) {
+ out.sendOnly(RR,*ast);
+ if (++count >= limit)
+ break;
+ }
}
unsigned long idx = 0;
@@ -264,9 +266,11 @@ void Multicaster::send(
unsigned int count = 0;
for(std::vector<Address>::const_iterator ast(alwaysSendTo.begin());ast!=alwaysSendTo.end();++ast) {
- out.sendAndLog(RR,*ast);
- if (++count >= limit)
- break;
+ if (*ast != RR->identity.address()) {
+ out.sendAndLog(RR,*ast);
+ if (++count >= limit)
+ break;
+ }
}
unsigned long idx = 0;
diff --git a/node/Network.cpp b/node/Network.cpp
index adc8e1b8..549219d7 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -38,6 +38,8 @@
#include "Buffer.hpp"
#include "NetworkController.hpp"
+#include "../version.h"
+
namespace ZeroTier {
const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL),0);
@@ -255,9 +257,18 @@ void Network::requestConfiguration()
}
TRACE("requesting netconf for network %.16llx from controller %s",(unsigned long long)_id,controller().toString().c_str());
+
+ // TODO: in the future we will include things like join tokens here, etc.
+ Dictionary metaData;
+ metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION,ZEROTIER_ONE_VERSION_MAJOR);
+ metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION,ZEROTIER_ONE_VERSION_MINOR);
+ metaData.setHex(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION,ZEROTIER_ONE_VERSION_REVISION);
+ std::string mds(metaData.toString());
+
Packet outp(controller(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append((uint64_t)_id);
- outp.append((uint16_t)0); // no meta-data
+ outp.append((uint16_t)mds.length());
+ outp.append((const void *)mds.data(),(unsigned int)mds.length());
{
Mutex::Lock _l(_lock);
if (_config)
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index ba4d338b..7898646c 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -47,7 +47,6 @@ SharedPtr<NetworkConfig> NetworkConfig::createTestNetworkConfig(const Address &s
nc->_private = false;
nc->_enableBroadcast = true;
nc->_name = "ZT_TEST_NETWORK";
- nc->_description = "Built-in dummy test network";
// Make up a V4 IP from 'self' in the 10.0.0.0/8 range -- no
// guarantee of uniqueness but collisions are unlikely.
@@ -111,7 +110,6 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)
throw std::invalid_argument("network short name too long (max: 255 characters)");
- _description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());
// In dictionary IPs are split into V4 and V6 addresses, but we don't really
// need that so merge them here.
@@ -132,26 +130,22 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
case AF_INET:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))
continue;
- else if (addr.isNetwork()) {
- // TODO: add route to network -- this is a route without an IP assignment
- continue;
- }
break;
case AF_INET6:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))
continue;
- else if (addr.isNetwork()) {
- // TODO: add route to network -- this is a route without an IP assignment
- continue;
- }
break;
default: // ignore unrecognized address types or junk/empty fields
continue;
}
- _staticIps.push_back(addr);
+ if (addr.isNetwork())
+ _localRoutes.push_back(addr);
+ else _staticIps.push_back(addr);
}
- if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES)
- throw std::invalid_argument("too many ZT-assigned IP addresses or routes");
+ if (_localRoutes.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned routes");
+ if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) throw std::invalid_argument("too many ZT-assigned IP addresses");
+ std::sort(_localRoutes.begin(),_localRoutes.end());
+ _localRoutes.erase(std::unique(_localRoutes.begin(),_localRoutes.end()),_localRoutes.end());
std::sort(_staticIps.begin(),_staticIps.end());
_staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end());
@@ -201,7 +195,7 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
if (_private != nc._private) return false;
if (_enableBroadcast != nc._enableBroadcast) return false;
if (_name != nc._name) return false;
- if (_description != nc._description) return false;
+ if (_localRoutes != nc._localRoutes) return false;
if (_staticIps != nc._staticIps) return false;
if (_gateways != nc._gateways) return false;
if (_activeBridges != nc._activeBridges) return false;
@@ -211,4 +205,3 @@ bool NetworkConfig::operator==(const NetworkConfig &nc) const
}
} // namespace ZeroTier
-
diff --git a/node/NetworkConfig.hpp b/node/NetworkConfig.hpp
index 5c7cdd7c..6111e65b 100644
--- a/node/NetworkConfig.hpp
+++ b/node/NetworkConfig.hpp
@@ -47,59 +47,48 @@
namespace ZeroTier {
+// Fields for meta-data sent with network config requests
+#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MAJOR_VERSION "majv"
+#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_MINOR_VERSION "minv"
+#define ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_NODE_REVISION "revv"
+
// These dictionary keys are short so they don't take up much room in
// netconf response packets.
// integer(hex)[,integer(hex),...]
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES "et"
-
// network ID
#define ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID "nwid"
-
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP "ts"
-
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_REVISION "r"
-
// address of member
#define ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO "id"
-
// integer(hex)
#define ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT "ml"
-
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_PRIVATE "p"
-
// text
#define ZT_NETWORKCONFIG_DICT_KEY_NAME "n"
-
// text
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
-
// IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
-
// IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
-
// serialized CertificateOfMembership
#define ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP "com"
-
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST "eb"
-
// 0/1
#define ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING "pb"
-
// node[,node,...]
#define ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES "ab"
-
// node;IP/port[,node;IP/port]
#define ZT_NETWORKCONFIG_DICT_KEY_RELAYS "rl"
-
// IP/metric[,IP/metric,...]
#define ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS "gw"
@@ -158,7 +147,7 @@ public:
inline bool isPublic() const throw() { return (!_private); }
inline bool isPrivate() const throw() { return _private; }
inline const std::string &name() const throw() { return _name; }
- inline const std::string &description() const throw() { return _description; }
+ inline const std::vector<InetAddress> &localRoutes() const throw() { return _localRoutes; }
inline const std::vector<InetAddress> &staticIps() const throw() { return _staticIps; }
inline const std::vector<InetAddress> &gateways() const throw() { return _gateways; }
inline const std::vector<Address> &activeBridges() const throw() { return _activeBridges; }
@@ -194,7 +183,7 @@ private:
bool _private;
bool _enableBroadcast;
std::string _name;
- std::string _description;
+ std::vector<InetAddress> _localRoutes;
std::vector<InetAddress> _staticIps;
std::vector<InetAddress> _gateways;
std::vector<Address> _activeBridges;
@@ -207,4 +196,3 @@ private:
} // namespace ZeroTier
#endif
-
diff --git a/node/NetworkController.hpp b/node/NetworkController.hpp
index 265ee3d4..ee481a62 100644
--- a/node/NetworkController.hpp
+++ b/node/NetworkController.hpp
@@ -52,10 +52,10 @@ public:
enum ResultCode
{
NETCONF_QUERY_OK = 0,
- NETCONF_QUERY_OK_BUT_NOT_NEWER = 1,
- NETCONF_QUERY_OBJECT_NOT_FOUND = 2,
- NETCONF_QUERY_ACCESS_DENIED = 3,
- NETCONF_QUERY_INTERNAL_SERVER_ERROR = 4
+ NETCONF_QUERY_OBJECT_NOT_FOUND = 1,
+ NETCONF_QUERY_ACCESS_DENIED = 2,
+ NETCONF_QUERY_INTERNAL_SERVER_ERROR = 3,
+ NETCONF_QUERY_IGNORE = 4
};
NetworkController() {}
diff --git a/node/Node.cpp b/node/Node.cpp
index ebe0527e..d40ceab9 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -316,6 +316,7 @@ ZT1_ResultCode Node::leave(uint64_t nwid)
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
if (n->first != nwid)
newn.push_back(*n);
+ else n->second->destroy();
}
_networks.swap(newn);
return ZT1_RESULT_OK;
diff --git a/node/Peer.cpp b/node/Peer.cpp
index 73c20228..3cf0ec4e 100644
--- a/node/Peer.cpp
+++ b/node/Peer.cpp
@@ -33,6 +33,7 @@
#include "Switch.hpp"
#include "Network.hpp"
#include "AntiRecursion.hpp"
+#include "SelfAwareness.hpp"
#include <algorithm>
@@ -225,10 +226,11 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now)
void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_t now,bool force)
{
- if ((((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force))) {
+ if (((now - _lastDirectPathPush) >= ZT_DIRECT_PATH_PUSH_INTERVAL)||(force)) {
_lastDirectPathPush = now;
std::vector<Path> dps(RR->node->directPaths());
+
#ifdef ZT_TRACE
{
std::string ps;
diff --git a/node/SelfAwareness.cpp b/node/SelfAwareness.cpp
index 00015788..716cf7f3 100644
--- a/node/SelfAwareness.cpp
+++ b/node/SelfAwareness.cpp
@@ -147,4 +147,19 @@ void SelfAwareness::clean(uint64_t now)
}
}
+bool SelfAwareness::areGlobalIPv4PortsRandomized() const
+{
+ int port = 0;
+ Mutex::Lock _l(_phy_m);
+ for(std::map< PhySurfaceKey,PhySurfaceEntry >::const_iterator p(_phy.begin());p!=_phy.end();++p) {
+ if ((p->first.scope == InetAddress::IP_SCOPE_GLOBAL)&&(p->second.mySurface.ss_family == AF_INET)) {
+ const int tmp = (int)p->second.mySurface.port();
+ if ((port)&&(tmp != port))
+ return true;
+ else port = tmp;
+ }
+ }
+ return false;
+}
+
} // namespace ZeroTier
diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp
index 4780fa5b..d3b79d18 100644
--- a/node/SelfAwareness.hpp
+++ b/node/SelfAwareness.hpp
@@ -29,6 +29,7 @@
#define ZT_SELFAWARENESS_HPP
#include <map>
+#include <vector>
#include "InetAddress.hpp"
#include "Address.hpp"
@@ -65,6 +66,11 @@ public:
*/
void clean(uint64_t now);
+ /**
+ * @return True if our external (global scope) IPv4 ports appear to be randomized by a NAT device
+ */
+ bool areGlobalIPv4PortsRandomized() const;
+
private:
struct PhySurfaceKey
{
diff --git a/node/Switch.cpp b/node/Switch.cpp
index cf4fe249..989f497a 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -43,6 +43,7 @@
#include "Topology.hpp"
#include "Peer.hpp"
#include "AntiRecursion.hpp"
+#include "SelfAwareness.hpp"
#include "Packet.hpp"
namespace ZeroTier {
@@ -385,15 +386,11 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
return true;
}
-void Switch::contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
+void Switch::rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr)
{
TRACE("sending NAT-t message to %s(%s)",peer->address().toString().c_str(),atAddr.toString().c_str());
const uint64_t now = RR->node->now();
-
- // Attempt to contact directly
peer->attemptToContactAt(RR,atAddr,now);
-
- // If we have not punched through after this timeout, open refreshing can of whupass
{
Mutex::Lock _l(_contactQueue_m);
_contactQueue.push_back(ContactQueueEntry(peer,now + ZT_NAT_T_TACTICAL_ESCALATION_DELAY,atAddr));
@@ -451,35 +448,26 @@ unsigned long Switch::doTimerTasks(uint64_t now)
{
unsigned long nextDelay = 0xffffffff; // ceiling delay, caller will cap to minimum
- { // Aggressive NAT traversal time!
+ { // Iterate through NAT traversal strategies for entries in contact queue
Mutex::Lock _l(_contactQueue_m);
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
if (now >= qi->fireAtTime) {
- if (qi->peer->hasActiveDirectPath(now)) {
- // We've successfully NAT-t'd, so cancel attempt
+ if ((!qi->peer->alive(now))||(qi->peer->hasActiveDirectPath(now))) {
+ // Cancel attempt if we've already connected or peer is no longer "alive"
_contactQueue.erase(qi++);
continue;
} else {
- // Nope, nothing yet. Time to kill some kittens.
if (qi->strategyIteration == 0) {
- // First strategy: send packet directly (we already tried this but try again)
+ // First strategy: send packet directly to destination
qi->peer->attemptToContactAt(RR,qi->inaddr,now);
- } else if (qi->strategyIteration <= 9) {
- // Strategies 1-9: try escalating ports
+ } else if (qi->strategyIteration <= 4) {
+ // Strategies 1-4: try escalating ports for symmetric NATs that remap sequentially
InetAddress tmpaddr(qi->inaddr);
int p = (int)qi->inaddr.port() + qi->strategyIteration;
if (p < 0xffff) {
tmpaddr.setPort((unsigned int)p);
qi->peer->attemptToContactAt(RR,tmpaddr,now);
- } else qi->strategyIteration = 9;
- } else if (qi->strategyIteration <= 18) {
- // Strategies 10-18: try ports below
- InetAddress tmpaddr(qi->inaddr);
- int p = (int)qi->inaddr.port() - (qi->strategyIteration - 9);
- if (p >= 1024) {
- tmpaddr.setPort((unsigned int)p);
- qi->peer->attemptToContactAt(RR,tmpaddr,now);
- } else qi->strategyIteration = 18;
+ } else qi->strategyIteration = 5;
} else {
// All strategies tried, expire entry
_contactQueue.erase(qi++);
diff --git a/node/Switch.hpp b/node/Switch.hpp
index e7f1523a..ac85606e 100644
--- a/node/Switch.hpp
+++ b/node/Switch.hpp
@@ -136,12 +136,12 @@ public:
bool unite(const Address &p1,const Address &p2,bool force);
/**
- * Send NAT traversal messages to peer at the given candidate address
+ * Attempt NAT traversal to peer at a given physical address
*
* @param peer Peer to contact
* @param atAddr Address of peer
*/
- void contact(const SharedPtr<Peer> &peer,const InetAddress &atAddr);
+ void rendezvous(const SharedPtr<Peer> &peer,const InetAddress &atAddr);
/**
* Request WHOIS on a given address
diff --git a/node/Topology.hpp b/node/Topology.hpp
index c878bcc6..1c5cca00 100644
--- a/node/Topology.hpp
+++ b/node/Topology.hpp
@@ -86,7 +86,7 @@ public:
/**
* Get a peer from its address
- *
+ *
* @param zta ZeroTier address of peer
* @return Peer or NULL if not found
*/
@@ -103,7 +103,7 @@ public:
/**
* Get the current favorite root server
- *
+ *
* @return Root server with lowest latency or NULL if none
*/
inline SharedPtr<Peer> getBestRoot()
@@ -113,11 +113,11 @@ public:
/**
* Get the best root server, avoiding root servers listed in an array
- *
+ *
* This will get the best root server (lowest latency, etc.) but will
* try to avoid the listed root servers, only using them if no others
* are available.
- *
+ *
* @param avoid Nodes to avoid
* @param avoidCount Number of nodes to avoid
* @param strictAvoid If false, consider avoided root servers anyway if no non-avoid root servers are available