summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2016-04-05 10:47:13 -0700
committerAdam Ierymenko <adam.ierymenko@gmail.com>2016-04-05 10:47:13 -0700
commitd8b89b0c86e9454ce95a7c7ad07549ceeba916a0 (patch)
tree3273e13945af645af382edb205ae826a2f800e88
parente0ad854d19e215869139782594329e51ae0812f4 (diff)
downloadinfinitytier-d8b89b0c86e9454ce95a7c7ad07549ceeba916a0.tar.gz
infinitytier-d8b89b0c86e9454ce95a7c7ad07549ceeba916a0.zip
Fix Cluster to send from a designated endpoint address instead of wildcard.
-rw-r--r--node/Cluster.cpp15
-rw-r--r--osdep/Binder.hpp51
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;