diff options
author | Grant Limberg <glimberg@gmail.com> | 2015-07-28 19:18:33 -0700 |
---|---|---|
committer | Grant Limberg <glimberg@gmail.com> | 2015-07-28 19:18:33 -0700 |
commit | 508d31513a0848236258542930cf577d95afda99 (patch) | |
tree | 453b31d874e6ec0dee3105191142efc8a326a30d /node | |
parent | bc0954381ccdca065987512a45d5dd6ace6cca9d (diff) | |
parent | 7578b5629849f6c286c353dce713b0816b1cc4a9 (diff) | |
download | infinitytier-508d31513a0848236258542930cf577d95afda99.tar.gz infinitytier-508d31513a0848236258542930cf577d95afda99.zip |
Merge branch 'adamierymenko-dev' into android-jni
Diffstat (limited to 'node')
-rw-r--r-- | node/Constants.hpp | 18 | ||||
-rw-r--r-- | node/IncomingPacket.cpp | 36 | ||||
-rw-r--r-- | node/InetAddress.cpp | 2 | ||||
-rw-r--r-- | node/Multicaster.cpp | 16 | ||||
-rw-r--r-- | node/Network.cpp | 13 | ||||
-rw-r--r-- | node/NetworkConfig.cpp | 23 | ||||
-rw-r--r-- | node/NetworkConfig.hpp | 26 | ||||
-rw-r--r-- | node/NetworkController.hpp | 8 | ||||
-rw-r--r-- | node/Node.cpp | 1 | ||||
-rw-r--r-- | node/Peer.cpp | 4 | ||||
-rw-r--r-- | node/SelfAwareness.cpp | 15 | ||||
-rw-r--r-- | node/SelfAwareness.hpp | 6 | ||||
-rw-r--r-- | node/Switch.cpp | 30 | ||||
-rw-r--r-- | node/Switch.hpp | 4 | ||||
-rw-r--r-- | node/Topology.hpp | 8 |
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 |