summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
Diffstat (limited to 'node')
-rw-r--r--node/Peer.cpp19
-rw-r--r--node/SelfAwareness.hpp14
-rw-r--r--node/Topology.hpp8
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