summaryrefslogtreecommitdiff
path: root/node/Switch.cpp
diff options
context:
space:
mode:
authorGrant Limberg <glimberg@gmail.com>2015-11-02 18:32:21 -0800
committerGrant Limberg <glimberg@gmail.com>2015-11-02 18:32:21 -0800
commit179b064b05460b706526a3249a25cd07232a42f5 (patch)
treed26dfeb2c02ce59c4a531142684695e45bb515ad /node/Switch.cpp
parent75a191a8564030f4d5e99aca76b980e2d69abd20 (diff)
parent4e9d4304761f93a1764d3ec2d2b0c38140decad8 (diff)
downloadinfinitytier-179b064b05460b706526a3249a25cd07232a42f5.tar.gz
infinitytier-179b064b05460b706526a3249a25cd07232a42f5.zip
Merge branch 'edge' into android-jni-dev
Diffstat (limited to 'node/Switch.cpp')
-rw-r--r--node/Switch.cpp75
1 files changed, 50 insertions, 25 deletions
diff --git a/node/Switch.cpp b/node/Switch.cpp
index ecae9b76..b7a9c522 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -45,6 +45,7 @@
#include "AntiRecursion.hpp"
#include "SelfAwareness.hpp"
#include "Packet.hpp"
+#include "Cluster.hpp"
namespace ZeroTier {
@@ -202,7 +203,8 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
// Destination is another ZeroTier peer on the same network
Address toZT(to.toAddress(network->id())); // since in-network MACs are derived from addresses and network IDs, we can reverse this
- const bool includeCom = network->peerNeedsOurMembershipCertificate(toZT,RR->node->now());
+ SharedPtr<Peer> toPeer(RR->topology->getPeer(toZT));
+ const bool includeCom = ( (nconf->isPrivate()) && (nconf->com()) && ((!toPeer)||(toPeer->needsOurNetworkMembershipCertificate(network->id(),RR->node->now(),true))) );
if ((fromBridged)||(includeCom)) {
Packet outp(toZT,RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(network->id());
@@ -267,9 +269,10 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
}
for(unsigned int b=0;b<numBridges;++b) {
+ SharedPtr<Peer> bridgePeer(RR->topology->getPeer(bridges[b]));
Packet outp(bridges[b],RR->identity.address(),Packet::VERB_EXT_FRAME);
outp.append(network->id());
- if (network->peerNeedsOurMembershipCertificate(bridges[b],RR->node->now())) {
+ if ( (nconf->isPrivate()) && (nconf->com()) && ((!bridgePeer)||(bridgePeer->needsOurNetworkMembershipCertificate(network->id(),RR->node->now(),true))) ) {
outp.append((unsigned char)0x01); // 0x01 -- COM included
nconf->com().serialize(outp);
} else {
@@ -292,17 +295,18 @@ void Switch::send(const Packet &packet,bool encrypt,uint64_t nwid)
return;
}
+ //TRACE(">> %s to %s (%u bytes, encrypt==%d, nwid==%.16llx)",Packet::verbString(packet.verb()),packet.destination().toString().c_str(),packet.size(),(int)encrypt,nwid);
+
if (!_trySend(packet,encrypt,nwid)) {
Mutex::Lock _l(_txQueue_m);
_txQueue.push_back(TXQueueEntry(packet.destination(),RR->node->now(),packet,encrypt,nwid));
}
}
-bool Switch::unite(const Address &p1,const Address &p2,bool force)
+bool Switch::unite(const Address &p1,const Address &p2)
{
if ((p1 == RR->identity.address())||(p2 == RR->identity.address()))
return false;
-
SharedPtr<Peer> p1p = RR->topology->getPeer(p1);
if (!p1p)
return false;
@@ -312,14 +316,6 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
const uint64_t now = RR->node->now();
- {
- Mutex::Lock _l(_lastUniteAttempt_m);
- uint64_t &luts = _lastUniteAttempt[_LastUniteKey(p1,p2)];
- if (((now - luts) < ZT_MIN_UNITE_INTERVAL)&&(!force))
- return false;
- luts = now;
- }
-
std::pair<InetAddress,InetAddress> cg(Peer::findCommonGround(*p1p,*p2p,now));
if ((!(cg.first))||(cg.first.ipScope() != cg.second.ipScope()))
return false;
@@ -446,8 +442,8 @@ unsigned long Switch::doTimerTasks(uint64_t now)
Mutex::Lock _l(_contactQueue_m);
for(std::list<ContactQueueEntry>::iterator qi(_contactQueue.begin());qi!=_contactQueue.end();) {
if (now >= qi->fireAtTime) {
- if ((!qi->peer->alive(now))||(qi->peer->hasActiveDirectPath(now))) {
- // Cancel attempt if we've already connected or peer is no longer "alive"
+ if (qi->peer->hasActiveDirectPath(now)) {
+ // Cancel if connection has succeeded
_contactQueue.erase(qi++);
continue;
} else {
@@ -543,7 +539,7 @@ unsigned long Switch::doTimerTasks(uint64_t now)
_LastUniteKey *k = (_LastUniteKey *)0;
uint64_t *v = (uint64_t *)0;
while (i.next(k,v)) {
- if ((now - *v) >= (ZT_MIN_UNITE_INTERVAL * 16))
+ if ((now - *v) >= (ZT_MIN_UNITE_INTERVAL * 8))
_lastUniteAttempt.erase(*k);
}
}
@@ -565,6 +561,11 @@ void Switch::_handleRemotePacketFragment(const InetAddress &localAddr,const Inet
// It wouldn't hurt anything, just redundant and unnecessary.
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
if ((!relayTo)||(!relayTo->send(RR,fragment.data(),fragment.size(),RR->node->now()))) {
+#ifdef ZT_ENABLE_CLUSTER
+ if ((RR->cluster)&&(RR->cluster->sendViaCluster(Address(),destination,fragment.data(),fragment.size(),false)))
+ return; // sent by way of another member of this cluster
+#endif
+
// Don't know peer or no direct path -- so relay via root server
relayTo = RR->topology->getBestRoot();
if (relayTo)
@@ -624,11 +625,17 @@ void Switch::_handleRemotePacketFragment(const InetAddress &localAddr,const Inet
void Switch::_handleRemotePacketHead(const InetAddress &localAddr,const InetAddress &fromAddr,const void *data,unsigned int len)
{
- SharedPtr<IncomingPacket> packet(new IncomingPacket(data,len,localAddr,fromAddr,RR->node->now()));
+ const uint64_t now = RR->node->now();
+ SharedPtr<IncomingPacket> packet(new IncomingPacket(data,len,localAddr,fromAddr,now));
Address source(packet->source());
Address destination(packet->destination());
+ // Catch this and toss it -- it would never work, but it could happen if we somehow
+ // mistakenly guessed an address we're bound to as a destination for another peer.
+ if (source == RR->identity.address())
+ return;
+
//TRACE("<< %.16llx %s -> %s (size: %u)",(unsigned long long)packet->packetId(),source.toString().c_str(),destination.toString().c_str(),packet->size());
if (destination != RR->identity.address()) {
@@ -637,13 +644,18 @@ void Switch::_handleRemotePacketHead(const InetAddress &localAddr,const InetAddr
packet->incrementHops();
SharedPtr<Peer> relayTo = RR->topology->getPeer(destination);
- if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),RR->node->now())))) {
- unite(source,destination,false);
+ if ((relayTo)&&((relayTo->send(RR,packet->data(),packet->size(),now)))) {
+ if (_shouldTryUnite(now,source,destination))
+ unite(source,destination);
} else {
- // Don't know peer or no direct path -- so relay via root server
+#ifdef ZT_ENABLE_CLUSTER
+ if ((RR->cluster)&&(RR->cluster->sendViaCluster(source,destination,packet->data(),packet->size(),_shouldTryUnite(now,source,destination))))
+ return; // sent by way of another member of this cluster
+#endif
+
relayTo = RR->topology->getBestRoot(&source,1,true);
if (relayTo)
- relayTo->send(RR,packet->data(),packet->size(),RR->node->now());
+ relayTo->send(RR,packet->data(),packet->size(),now);
}
} else {
TRACE("dropped relay %s(%s) -> %s, max hops exceeded",packet->source().toString().c_str(),fromAddr.toString().c_str(),destination.toString().c_str());
@@ -658,7 +670,7 @@ void Switch::_handleRemotePacketHead(const InetAddress &localAddr,const InetAddr
if (!dq.creationTime) {
// If we have no other fragments yet, create an entry and save the head
- dq.creationTime = RR->node->now();
+ dq.creationTime = now;
dq.frag0 = packet;
dq.totalFragments = 0; // 0 == unknown, waiting for Packet::Fragment
dq.haveFragments = 1; // head is first bit (left to right)
@@ -724,17 +736,20 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
return false; // sanity check: unconfigured network? why are we trying to talk to it?
}
- RemotePath *viaPath = peer->getBestPath(now);
+ Path *viaPath = peer->getBestPath(now);
SharedPtr<Peer> relay;
if (!viaPath) {
// See if this network has a preferred relay (if packet has an associated network)
if (nconf) {
- unsigned int latency = ~((unsigned int)0);
+ unsigned int bestq = ~((unsigned int)0);
for(std::vector< std::pair<Address,InetAddress> >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) {
if (r->first != peer->address()) {
SharedPtr<Peer> rp(RR->topology->getPeer(r->first));
- if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency))
+ const unsigned int q = rp->relayQuality(now);
+ if ((rp)&&(q < bestq)) { // SUBTILE: < == don't use these if they are nil quality (unsigned int max), instead use a root
+ bestq = q;
rp.swap(relay);
+ }
}
}
}
@@ -747,7 +762,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
return false; // no paths, no root servers?
}
- if ((network)&&(relay)&&(network->isAllowed(peer->address()))) {
+ if ((network)&&(relay)&&(network->isAllowed(peer))) {
// Push hints for direct connectivity to this peer if we are relaying
peer->pushDirectPaths(RR,viaPath,now,false);
}
@@ -786,4 +801,14 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid)
return false;
}
+bool Switch::_shouldTryUnite(const uint64_t now,const Address &p1,const Address &p2)
+{
+ Mutex::Lock _l(_lastUniteAttempt_m);
+ uint64_t &luts = _lastUniteAttempt[_LastUniteKey(p1,p2)];
+ if ((now - luts) < ZT_MIN_UNITE_INTERVAL)
+ return false;
+ luts = now;
+ return true;
+}
+
} // namespace ZeroTier