소스 검색

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)

Adam Ierymenko 10 년 전
부모
커밋
f0003ea922
3개의 변경된 파일37개의 추가작업 그리고 4개의 파일을 삭제
  1. 19 0
      node/Peer.cpp
  2. 14 0
      node/SelfAwareness.hpp
  3. 4 4
      node/Topology.hpp

+ 19 - 0
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;

+ 14 - 0
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
 	{

+ 4 - 4
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