From f0003ea92277039f70dd6f16920dd2db9fb2fb1e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 27 Jul 2015 17:02:43 -0700 Subject: Push remote surface as reported by peers along with known interface direct paths to assist with (some) NAT traversal. (trying this, may back out if not effective) --- node/Peer.cpp | 19 +++++++++++++++++++ node/SelfAwareness.hpp | 14 ++++++++++++++ node/Topology.hpp | 8 ++++---- 3 files changed, 37 insertions(+), 4 deletions(-) (limited to 'node') diff --git a/node/Peer.cpp b/node/Peer.cpp index 73c20228..804e6e39 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 @@ -229,6 +230,24 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_ _lastDirectPathPush = now; std::vector dps(RR->node->directPaths()); + + /* Also push paths reported to us by non-root-server peers. This assists + * with NAT traversal behind NATs that engage in strange or randomized + * port assignment behavior. */ + std::vector
rootAddresses(RR->topology->rootAddresses()); + std::vector< std::pair > surface(RR->sa->getReportedSurface()); + for(std::vector< std::pair >::const_iterator s(surface.begin());s!=surface.end();++s) { + bool alreadyHave = false; + for(std::vector::const_iterator p(dps.begin());p!=dps.end();++p) { + if (p->address() == s->second) { + alreadyHave = true; + break; + } + } + if ((!alreadyHave)&&(std::find(rootAddresses.begin(),rootAddresses.end(),s->first) == rootAddresses.end())) + dps.push_back(Path(s->second,0,Path::TRUST_NORMAL)); + } + #ifdef ZT_TRACE { std::string ps; diff --git a/node/SelfAwareness.hpp b/node/SelfAwareness.hpp index 4780fa5b..9fcefa62 100644 --- a/node/SelfAwareness.hpp +++ b/node/SelfAwareness.hpp @@ -29,6 +29,7 @@ #define ZT_SELFAWARENESS_HPP #include +#include #include "InetAddress.hpp" #include "Address.hpp" @@ -65,6 +66,19 @@ public: */ void clean(uint64_t now); + /** + * @return List of external surface addresses as reported by peers + */ + inline std::vector< std::pair > getReportedSurface() const + { + std::vector< std::pair > r; + Mutex::Lock _l(_phy_m); + r.reserve(_phy.size()); + for(std::map< PhySurfaceKey,PhySurfaceEntry >::const_iterator p(_phy.begin());p!=_phy.end();) + r.push_back(std::pair(p->first.reporter,p->second.mySurface)); + return r; + } + private: struct PhySurfaceKey { 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 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 -- cgit v1.2.3