summaryrefslogtreecommitdiff
path: root/node/Switch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'node/Switch.cpp')
-rw-r--r--node/Switch.cpp54
1 files changed, 32 insertions, 22 deletions
diff --git a/node/Switch.cpp b/node/Switch.cpp
index c2a961ae..6a4e114a 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -101,6 +101,7 @@ void Switch::onLocalEthernet(const SharedPtr<Network> &network,const MAC &from,c
Multicaster::MulticastBloomFilter bloom;
SharedPtr<Peer> propPeers[ZT_MULTICAST_PROPAGATION_BREADTH];
unsigned int np = _r->multicaster->pickNextPropagationPeers(
+ *(_r->prng),
*(_r->topology),
network->id(),
mg,
@@ -187,15 +188,20 @@ void Switch::sendHELLO(const Address &dest)
bool Switch::sendHELLO(const SharedPtr<Peer> &dest,Demarc::Port localPort,const InetAddress &addr)
{
+ uint64_t now = Utils::now();
Packet outp(dest->address(),_r->identity.address(),Packet::VERB_HELLO);
outp.append((unsigned char)ZT_PROTO_VERSION);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
- outp.append(Utils::now());
+ outp.append(now);
_r->identity.serialize(outp,false);
outp.hmacSet(dest->macKey());
- return _r->demarc->send(localPort,addr,outp.data(),outp.size(),-1);
+ if (_r->demarc->send(localPort,addr,outp.data(),outp.size(),-1)) {
+ dest->onSent(_r,false,Packet::VERB_HELLO,now);
+ return true;
+ }
+ return false;
}
bool Switch::unite(const Address &p1,const Address &p2,bool force)
@@ -249,7 +255,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
}
outp.encrypt(p1p->cryptKey());
outp.hmacSet(p1p->macKey());
- p1p->send(_r,outp.data(),outp.size(),false,Packet::VERB_RENDEZVOUS,now);
+ if (p1p->send(_r,outp.data(),outp.size(),now))
+ p1p->onSent(_r,false,Packet::VERB_RENDEZVOUS,now);
}
{ // tell p2 where to find p1
Packet outp(p2,_r->identity.address(),Packet::VERB_RENDEZVOUS);
@@ -264,7 +271,8 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force)
}
outp.encrypt(p2p->cryptKey());
outp.hmacSet(p2p->macKey());
- p2p->send(_r,outp.data(),outp.size(),false,Packet::VERB_RENDEZVOUS,now);
+ if (p2p->send(_r,outp.data(),outp.size(),now))
+ p2p->onSent(_r,false,Packet::VERB_RENDEZVOUS,now);
}
return true;
@@ -443,12 +451,11 @@ void Switch::_handleRemotePacketFragment(Demarc::Port localPort,const InetAddres
// Fragment is not for us, so try to relay it
if (fragment.hops() < ZT_RELAY_MAX_HOPS) {
fragment.incrementHops();
-
SharedPtr<Peer> relayTo = _r->topology->getPeer(destination);
- if ((!relayTo)||(!relayTo->send(_r,fragment.data(),fragment.size(),true,Packet::VERB_NOP,Utils::now()))) {
+ if ((!relayTo)||(!relayTo->send(_r,fragment.data(),fragment.size(),Utils::now()))) {
relayTo = _r->topology->getBestSupernode();
if (relayTo)
- relayTo->send(_r,fragment.data(),fragment.size(),true,Packet::VERB_NOP,Utils::now());
+ relayTo->send(_r,fragment.data(),fragment.size(),Utils::now());
}
} else {
TRACE("dropped relay [fragment](%s) -> %s, max hops exceeded",fromAddr.toString().c_str(),destination.toString().c_str());
@@ -516,18 +523,19 @@ void Switch::_handleRemotePacketHead(Demarc::Port localPort,const InetAddress &f
packet->incrementHops();
SharedPtr<Peer> relayTo = _r->topology->getPeer(destination);
- if ((relayTo)&&(relayTo->send(_r,packet->data(),packet->size(),true,Packet::VERB_NOP,Utils::now()))) {
- unite(source,destination,false); // periodically try to get them to talk directly
+ if ((relayTo)&&(relayTo->send(_r,packet->data(),packet->size(),Utils::now()))) {
+ // If we've relayed, this periodically tries to get them to
+ // talk directly to save our bandwidth.
+ unite(source,destination,false);
} else {
- // Relay via a supernode if there's no direct path, but pass
- // source to getBestSupernode() to avoid just in case this is
- // being passed from another supernode so that we don't just
- // pass it back to where it came from. This can happen if a
- // supernode for some reason lacks a direct path to a peer that
- // it wants to talk to, such as because of Internet weather.
+ // If we've received a packet not for us and we don't have
+ // a direct path to its recipient, pass it to (another)
+ // supernode. This can happen due to Internet weather -- the
+ // most direct supernode may not be reachable, yet another
+ // further away may be.
relayTo = _r->topology->getBestSupernode(&source,1,true);
if (relayTo)
- relayTo->send(_r,packet->data(),packet->size(),true,Packet::VERB_NOP,Utils::now());
+ relayTo->send(_r,packet->data(),packet->size(),Utils::now());
}
} else {
TRACE("dropped relay %s(%s) -> %s, max hops exceeded",packet->source().toString().c_str(),fromAddr.toString().c_str(),destination.toString().c_str());
@@ -584,8 +592,11 @@ Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlread
outp.append(addr.data(),ZT_ADDRESS_LENGTH);
outp.encrypt(supernode->cryptKey());
outp.hmacSet(supernode->macKey());
- supernode->send(_r,outp.data(),outp.size(),false,Packet::VERB_WHOIS,Utils::now());
- return supernode->address();
+ uint64_t now = Utils::now();
+ if (supernode->send(_r,outp.data(),outp.size(),now)) {
+ supernode->onSent(_r,false,Packet::VERB_WHOIS,now);
+ return supernode->address();
+ }
}
return Address();
}
@@ -618,8 +629,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
tmp.encrypt(peer->cryptKey());
tmp.hmacSet(peer->macKey());
- Packet::Verb verb = packet.verb();
- if (via->send(_r,tmp.data(),chunkSize,isRelay,verb,now)) {
+ if (via->send(_r,tmp.data(),chunkSize,now)) {
if (chunkSize < tmp.size()) {
// Too big for one bite, fragment the rest
unsigned int fragStart = chunkSize;
@@ -632,15 +642,15 @@ bool Switch::_trySend(const Packet &packet,bool encrypt)
for(unsigned int f=0;f<fragsRemaining;++f) {
chunkSize = std::min(remaining,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - ZT_PROTO_MIN_FRAGMENT_LENGTH));
Packet::Fragment frag(tmp,fragStart,chunkSize,f + 1,totalFragments);
- if (!via->send(_r,frag.data(),frag.size(),isRelay,verb,now)) {
+ if (!via->send(_r,frag.data(),frag.size(),now)) {
TRACE("WARNING: packet send to %s failed on later fragment #%u (check IP layer buffer sizes?)",via->address().toString().c_str(),f + 1);
- return false;
}
fragStart += chunkSize;
remaining -= chunkSize;
}
}
+ via->onSent(_r,isRelay,packet.verb(),now);
return true;
}
return false;