diff options
Diffstat (limited to 'node')
-rw-r--r-- | node/Peer.cpp | 19 | ||||
-rw-r--r-- | node/SelfAwareness.hpp | 14 | ||||
-rw-r--r-- | node/Topology.hpp | 8 |
3 files changed, 37 insertions, 4 deletions
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 <algorithm> @@ -229,6 +230,24 @@ void Peer::pushDirectPaths(const RuntimeEnvironment *RR,RemotePath *path,uint64_ _lastDirectPathPush = now; std::vector<Path> 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<Address> rootAddresses(RR->topology->rootAddresses()); + std::vector< std::pair<Address,InetAddress> > surface(RR->sa->getReportedSurface()); + for(std::vector< std::pair<Address,InetAddress> >::const_iterator s(surface.begin());s!=surface.end();++s) { + bool alreadyHave = false; + for(std::vector<Path>::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 <map> +#include <vector> #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<Address,InetAddress> > getReportedSurface() const + { + std::vector< std::pair<Address,InetAddress> > 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<Address,InetAddress>(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<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 |