diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-04-05 10:47:13 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2016-04-05 10:47:13 -0700 |
commit | d8b89b0c86e9454ce95a7c7ad07549ceeba916a0 (patch) | |
tree | 3273e13945af645af382edb205ae826a2f800e88 | |
parent | e0ad854d19e215869139782594329e51ae0812f4 (diff) | |
download | infinitytier-d8b89b0c86e9454ce95a7c7ad07549ceeba916a0.tar.gz infinitytier-d8b89b0c86e9454ce95a7c7ad07549ceeba916a0.zip |
Fix Cluster to send from a designated endpoint address instead of wildcard.
-rw-r--r-- | node/Cluster.cpp | 15 | ||||
-rw-r--r-- | osdep/Binder.hpp | 51 |
2 files changed, 60 insertions, 6 deletions
diff --git a/node/Cluster.cpp b/node/Cluster.cpp index e4c4524a..61903307 100644 --- a/node/Cluster.cpp +++ b/node/Cluster.cpp @@ -570,10 +570,19 @@ void Cluster::sendViaCluster(const Address &fromPeerAddress,const Address &toPee Mutex::Lock _l2(_members[mostRecentMemberId].lock); if (buf.size() > 0) _send(mostRecentMemberId,CLUSTER_MESSAGE_PROXY_UNITE,buf.data(),buf.size()); - if (_members[mostRecentMemberId].zeroTierPhysicalEndpoints.size() > 0) { - TRACE("sendViaCluster relaying %u bytes from %s to %s by way of %u",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId); - RR->node->putPacket(InetAddress(),_members[mostRecentMemberId].zeroTierPhysicalEndpoints.front(),data,len); + + for(std::vector<InetAddress>::const_iterator i1(_zeroTierPhysicalEndpoints.begin());i1!=_zeroTierPhysicalEndpoints.end();++i1) { + for(std::vector<InetAddress>::const_iterator i2(_members[mostRecentMemberId].zeroTierPhysicalEndpoints.begin());i2!=_members[mostRecentMemberId].zeroTierPhysicalEndpoints.end();++i2) { + if (i1->ss_family == i2->ss_family) { + TRACE("sendViaCluster relaying %u bytes from %s to %s by way of %u (%s->%s)",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId,i1->toString().c_str(),i2->toString().c_str()); + RR->node->putPacket(*i1,*i2,data,len); + return; + } + } } + + TRACE("sendViaCluster relaying %u bytes from %s to %s by way of %u failed: no common endpoints with the same address family!",len,fromPeerAddress.toString().c_str(),toPeerAddress.toString().c_str(),(unsigned int)mostRecentMemberId); + return; } } diff --git a/osdep/Binder.hpp b/osdep/Binder.hpp index 5546b9f1..2e4df20d 100644 --- a/osdep/Binder.hpp +++ b/osdep/Binder.hpp @@ -146,7 +146,7 @@ binder_hpp_interface_prefixes_dont_match: default: break; case InetAddress::IP_SCOPE_PSEUDOPRIVATE: case InetAddress::IP_SCOPE_GLOBAL: - case InetAddress::IP_SCOPE_LINK_LOCAL: + //case InetAddress::IP_SCOPE_LINK_LOCAL: case InetAddress::IP_SCOPE_SHARED: case InetAddress::IP_SCOPE_PRIVATE: for(ii=ignoreInterfacesByAddress.begin();ii!=ignoreInterfacesByAddress.end();++ii) { @@ -170,13 +170,13 @@ binder_hpp_ignore_interface: #endif + // Default to binding to wildcard if we can't enumerate addresses if (localIfAddrs.size() == 0) { localIfAddrs.push_back(InetAddress((uint32_t)0,_port)); localIfAddrs.push_back(InetAddress((const void *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,_port)); - } else { - std::sort(localIfAddrs.begin(),localIfAddrs.end()); } + // Close any bindings to anything that doesn't exist anymore for(bi=_bindings.begin();bi!=_bindings.end();++bi) { if (std::find(localIfAddrs.begin(),localIfAddrs.end(),bi->address) == localIfAddrs.end()) { _phy.close(bi->udpSock,false); @@ -185,6 +185,7 @@ binder_hpp_ignore_interface: } for(ii=localIfAddrs.begin();ii!=localIfAddrs.end();++ii) { + // Copy over bindings that still are valid for(bi=_bindings.begin();bi!=_bindings.end();++bi) { if (bi->address == *ii) { newBindings.push_back(*bi); @@ -192,6 +193,7 @@ binder_hpp_ignore_interface: } } + // Add new bindings if (bi == _bindings.end()) { udps = _phy.udpBind(reinterpret_cast<const struct sockaddr *>(&ii),(void *)0,131072); if (udps) { @@ -208,9 +210,52 @@ binder_hpp_ignore_interface: } } + // Swapping pointers and then letting the old one fall out of scope is faster than copying again _bindings.swap(newBindings); } + /** + * Send a UDP packet from the specified local interface, or all + * + * Unfortunately even by examining the routing table there is no ultimately + * robust way to tell where we might reach another host that works in all + * environments. As a result, we send packets with null (wildcard) local + * addresses from *every* bound interface. + * + * These are typically initial HELLOs, path probes, etc., since normal + * conversations will have a local endpoint address. So the cost is low and + * if the peer is not reachable via that route then the packet will go + * nowhere and nothing will happen. + * + * It will of course only send via interface bindings of the same socket + * family. No point in sending V4 via V6 or vice versa. + * + * In any case on most hosts there's only one or two interfaces that we + * will use, so none of this is particularly costly. + * + * @param local Local interface address or null address for 'all' + * @param remote Remote address + * @param data Data to send + * @param len Length of data + */ + inline bool udpSend(const InetAddress &local,const InetAddress &remote,const void *data,unsigned int len) const + { + if (local) { + for(std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) { + if (i->address == local) + return _phy.udpSend(i->udpSock,reinterpret_cast<const struct sockaddr *>(&remote),data,len); + } + return false; + } else { + bool result = false; + for(std::vector<_Binding>::const_iterator i(_bindings.begin());i!=_bindings.end();++i) { + if (i->address.ss_family == remote.ss_family) + result |= _phy.udpSend(i->udpSock,reinterpret_cast<const struct sockaddr *>(&remote),data,len); + } + return result; + } + } + private: std::vector<_Binding> _bindings; typename Phy<PHY_HANDLER_TYPE> &_phy; |