From b3b9af0dd85ac755d41122cf2d0428d7f85e4cce Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 11:56:15 -0700 Subject: Fix for GitHub issue #170 --- node/Network.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'node') diff --git a/node/Network.cpp b/node/Network.cpp index deb05d1c..ab875889 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -498,12 +498,11 @@ bool Network::_isAllowed(const Address &peer) const std::vector Network::_allMulticastGroups() const { // Assumes _lock is locked - std::vector mgs(_myMulticastGroups); - std::vector::iterator oldend(mgs.end()); - for(std::map< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i) { - if (!std::binary_search(mgs.begin(),oldend,i->first)) - mgs.push_back(i->first); - } + std::vector mgs; + mgs.reserve(_myMulticastGroups.size() + _multicastGroupsBehindMe.size() + 1); + mgs.insert(mgs.end(),_myMulticastGroups.begin(),_myMulticastGroups.end()); + for(std::map< MulticastGroup,uint64_t >::const_iterator i(_multicastGroupsBehindMe.begin());i!=_multicastGroupsBehindMe.end();++i) + mgs.push_back(i->first); if ((_config)&&(_config->enableBroadcast())) mgs.push_back(Network::BROADCAST); std::sort(mgs.begin(),mgs.end()); -- cgit v1.2.3 From 5bc89034bcd2f4835e0ea48e72071c46e041a1fb Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 16:53:58 -0700 Subject: Always ping / contact network preferred relays (if any). --- node/Node.cpp | 35 ++++++++++++++++++++++++++++++++--- node/Peer.cpp | 4 +++- node/Peer.hpp | 3 ++- 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index c5c9873c..ecfdfad2 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -188,24 +188,53 @@ public: lastReceiveFromUpstream(0), RR(renv), _now(now), - _supernodes(RR->topology->supernodeAddresses()) {} + _supernodes(RR->topology->supernodeAddresses()), + _networkRelays() + { + std::vector< SharedPtr > nws(renv->node->allNetworks()); + for(std::vector< SharedPtr >::const_iterator nw(nws.begin());nw!=nws.end();++nw) { + SharedPtr nc((*nw)->config2()); + if (nc) + _networkRelays.insert(_networkRelays.end(),nc->relays().begin(),nc->relays().end()); + } + std::sort(_networkRelays.begin(),_networkRelays.end()); + std::unique(_networkRelays.begin(),_networkRelays.end()); + } uint64_t lastReceiveFromUpstream; inline void operator()(Topology &t,const SharedPtr &p) { if (std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end()) { + // Supernodes have fixed addresses and are always pinged p->doPingAndKeepalive(RR,_now); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); - } else if (p->alive(_now)) { - p->doPingAndKeepalive(RR,_now); + } else { + // Ping regular peers if they are alive, or if they are network + // designated relays with suggested IP address endpoints in a + // network config. + bool ison; + if (p->alive(_now)) + ison = p->doPingAndKeepalive(RR,_now); + else ison = false; + + if (!ison) { + // Note that multiple networks might designate the same peer as + // a preferred relay, so try all suggested endpoints. + for(std::vector< std::pair >::const_iterator r(_networkRelays.begin());r!=_networkRelays.end();++r) { + if (r->first == p->address()) + p->attemptToContactAt(RR,r->second,_now); + } + } } } + private: const RuntimeEnvironment *RR; uint64_t _now; std::vector
_supernodes; + std::vector< std::pair > _networkRelays; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) diff --git a/node/Peer.cpp b/node/Peer.cpp index d788d006..f5365223 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -191,7 +191,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at RR->node->putPacket(atAddress,outp.data(),outp.size()); } -void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) +bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) { Path *const bestPath = getBestPath(now); if ((bestPath)&&(bestPath->active(now))) { @@ -204,7 +204,9 @@ void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) RR->node->putPacket(bestPath->address(),"",0); bestPath->sent(now); } + return true; } + return false; } void Peer::addPath(const Path &newp) diff --git a/node/Peer.hpp b/node/Peer.hpp index 8d8b7cb4..7dc5017c 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -179,8 +179,9 @@ public: * * @param RR Runtime environment * @param now Current time + * @return True if there is an active best path (regardless of whether it needed a ping or keepalive), false if no paths */ - void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); + bool doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); /** * @return All known direct paths to this peer -- cgit v1.2.3 From 318c2f025b325023dbc320050414dd250da6de2a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 17:09:37 -0700 Subject: Call it _relays since there might be other kinds later. --- node/Node.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index ecfdfad2..a143275e 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -189,16 +189,16 @@ public: RR(renv), _now(now), _supernodes(RR->topology->supernodeAddresses()), - _networkRelays() + _relays() { std::vector< SharedPtr > nws(renv->node->allNetworks()); for(std::vector< SharedPtr >::const_iterator nw(nws.begin());nw!=nws.end();++nw) { SharedPtr nc((*nw)->config2()); if (nc) - _networkRelays.insert(_networkRelays.end(),nc->relays().begin(),nc->relays().end()); + _relays.insert(_relays.end(),nc->relays().begin(),nc->relays().end()); } - std::sort(_networkRelays.begin(),_networkRelays.end()); - std::unique(_networkRelays.begin(),_networkRelays.end()); + std::sort(_relays.begin(),_relays.end()); + std::unique(_relays.begin(),_relays.end()); } uint64_t lastReceiveFromUpstream; @@ -222,7 +222,7 @@ public: if (!ison) { // Note that multiple networks might designate the same peer as // a preferred relay, so try all suggested endpoints. - for(std::vector< std::pair >::const_iterator r(_networkRelays.begin());r!=_networkRelays.end();++r) { + for(std::vector< std::pair >::const_iterator r(_relays.begin());r!=_relays.end();++r) { if (r->first == p->address()) p->attemptToContactAt(RR,r->second,_now); } @@ -234,7 +234,7 @@ private: const RuntimeEnvironment *RR; uint64_t _now; std::vector
_supernodes; - std::vector< std::pair > _networkRelays; + std::vector< std::pair > _relays; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) -- cgit v1.2.3 From 960ceb479155146455d8c84c002b964cc0e1d47e Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 17:50:44 -0700 Subject: Rest of GitHub issue #140 implementation. --- node/Network.cpp | 2 +- node/OutboundMulticast.cpp | 4 ++-- node/Switch.cpp | 49 +++++++++++++++++++++++++++++++--------------- node/Switch.hpp | 20 ++++++++----------- 4 files changed, 44 insertions(+), 31 deletions(-) (limited to 'node') diff --git a/node/Network.cpp b/node/Network.cpp index ab875889..e513f43f 100644 --- a/node/Network.cpp +++ b/node/Network.cpp @@ -264,7 +264,7 @@ void Network::requestConfiguration() outp.append((uint64_t)_config->revision()); else outp.append((uint64_t)0); } - RR->sw->send(outp,true); + RR->sw->send(outp,true,_id); } void Network::addMembershipCertificate(const CertificateOfMembership &cert,bool forceAccept) diff --git a/node/OutboundMulticast.cpp b/node/OutboundMulticast.cpp index 80dd661c..f62046be 100644 --- a/node/OutboundMulticast.cpp +++ b/node/OutboundMulticast.cpp @@ -108,14 +108,14 @@ void OutboundMulticast::sendOnly(const RuntimeEnvironment *RR,const Address &toA _packetWithCom.newInitializationVector(); _packetWithCom.setDestination(toAddr); //TRACE(">>MC %.16llx -> %s (with COM)",(unsigned long long)this,toAddr.toString().c_str()); - RR->sw->send(_packetWithCom,true); + RR->sw->send(_packetWithCom,true,_nwid); return; } } //TRACE(">>MC %.16llx -> %s (without COM)",(unsigned long long)this,toAddr.toString().c_str()); _packetNoCom.newInitializationVector(); _packetNoCom.setDestination(toAddr); - RR->sw->send(_packetNoCom,true); + RR->sw->send(_packetNoCom,true,_nwid); } } // namespace ZeroTier diff --git a/node/Switch.cpp b/node/Switch.cpp index 4bdf2d84..d01d77ca 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -114,8 +114,6 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c if (to.isMulticast()) { // Destination is a multicast address (including broadcast) - - const uint64_t now = RR->node->now(); MulticastGroup mg(to,0); if (to.isBroadcast()) { @@ -145,7 +143,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c * multicast addresses on bridge interfaces and subscribing each slave. * But in that case this does no harm, as the sets are just merged. */ if (fromBridged) - network->learnBridgedMulticastGroup(mg,now); + network->learnBridgedMulticastGroup(mg,RR->node->now()); // Check multicast/broadcast bandwidth quotas and reject if quota exceeded if (!network->updateAndCheckMulticastBalance(mg,len)) { @@ -158,7 +156,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c RR->mc->send( ((!nconf->isPublic())&&(nconf->com())) ? &(nconf->com()) : (const CertificateOfMembership *)0, nconf->multicastLimit(), - now, + RR->node->now(), network->id(), nconf->activeBridges(), mg, @@ -180,7 +178,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c // bundle this with EXT_FRAME instead of sending two packets. Packet outp(toZT,RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); nconf->com().serialize(outp); - send(outp,true); + send(outp,true,network->id()); } if (fromBridged) { @@ -193,7 +191,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append((uint16_t)etherType); outp.append(data,len); outp.compress(); - send(outp,true); + send(outp,true,network->id()); } else { // FRAME is a shorter version that can be used when there's no bridging and no COM Packet outp(toZT,RR->identity.address(),Packet::VERB_FRAME); @@ -201,7 +199,7 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append((uint16_t)etherType); outp.append(data,len); outp.compress(); - send(outp,true); + send(outp,true,network->id()); } //TRACE("%.16llx: UNICAST: %s -> %s etherType==%s(%.4x) vlanId==%u len==%u fromBridged==%d",network->id(),from.toString().c_str(),to.toString().c_str(),etherTypeName(etherType),etherType,vlanId,len,(int)fromBridged); @@ -259,21 +257,21 @@ void Switch::onLocalEthernet(const SharedPtr &network,const MAC &from,c outp.append((uint16_t)etherType); outp.append(data,len); outp.compress(); - send(outp,true); + send(outp,true,network->id()); } } } -void Switch::send(const Packet &packet,bool encrypt) +void Switch::send(const Packet &packet,bool encrypt,uint64_t nwid) { if (packet.destination() == RR->identity.address()) { TRACE("BUG: caught attempt to send() to self, ignored"); return; } - if (!_trySend(packet,encrypt)) { + if (!_trySend(packet,encrypt,nwid)) { Mutex::Lock _l(_txQueue_m); - _txQueue.insert(std::pair< Address,TXQueueEntry >(packet.destination(),TXQueueEntry(RR->node->now(),packet,encrypt))); + _txQueue.insert(std::pair< Address,TXQueueEntry >(packet.destination(),TXQueueEntry(RR->node->now(),packet,encrypt,nwid))); } } @@ -423,7 +421,7 @@ void Switch::doAnythingWaitingForPeer(const SharedPtr &peer) Mutex::Lock _l(_txQueue_m); std::pair< std::multimap< Address,TXQueueEntry >::iterator,std::multimap< Address,TXQueueEntry >::iterator > waitingTxQueueItems(_txQueue.equal_range(peer->address())); for(std::multimap< Address,TXQueueEntry >::iterator txi(waitingTxQueueItems.first);txi!=waitingTxQueueItems.second;) { - if (_trySend(txi->second.packet,txi->second.encrypt)) + if (_trySend(txi->second.packet,txi->second.encrypt,txi->second.nwid)) _txQueue.erase(txi++); else ++txi; } @@ -505,7 +503,7 @@ unsigned long Switch::doTimerTasks(uint64_t now) { // Time out TX queue packets that never got WHOIS lookups or other info. Mutex::Lock _l(_txQueue_m); for(std::multimap< Address,TXQueueEntry >::iterator i(_txQueue.begin());i!=_txQueue.end();) { - if (_trySend(i->second.packet,i->second.encrypt)) + if (_trySend(i->second.packet,i->second.encrypt,i->second.nwid)) _txQueue.erase(i++); else if ((now - i->second.creationTime) > ZT_TRANSMIT_QUEUE_TIMEOUT) { TRACE("TX %s -> %s timed out",i->second.packet.source().toString().c_str(),i->second.packet.destination().toString().c_str()); @@ -725,7 +723,7 @@ Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlread return Address(); } -bool Switch::_trySend(const Packet &packet,bool encrypt) +bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) { SharedPtr peer(RR->topology->getPeer(packet.destination())); @@ -734,8 +732,27 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) Path *viaPath = peer->getBestPath(now); if (!viaPath) { - SharedPtr sn(RR->topology->getBestSupernode()); - if (!(sn)||(!(viaPath = sn->getBestPath(now)))) + SharedPtr relay; + + if (nwid) { + SharedPtr network(RR->node->network(nwid)); + if (network) { + SharedPtr nconf(network->config2()); + if (nconf) { + unsigned int latency = ~((unsigned int)0); + for(std::vector< std::pair >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) { + SharedPtr rp(RR->topology->getPeer(r->first)); + if ((rp->hasActiveDirectPath(now))&&(rp->latency() <= latency)) + rp.swap(relay); + } + } + } + } + + if (!relay) + relay = RR->topology->getBestSupernode(); + + if (!(relay)||(!(viaPath = relay->getBestPath(now)))) return false; } diff --git a/node/Switch.hpp b/node/Switch.hpp index e944c843..0ba4c138 100644 --- a/node/Switch.hpp +++ b/node/Switch.hpp @@ -111,8 +111,9 @@ public: * * @param packet Packet to send * @param encrypt Encrypt packet payload? (always true except for HELLO) + * @param nwid Network ID or 0 if message is not related to a specific network */ - void send(const Packet &packet,bool encrypt); + void send(const Packet &packet,bool encrypt,uint64_t nwid); /** * Send RENDEZVOUS to two peers to permit them to directly connect @@ -183,15 +184,8 @@ private: void _handleRemotePacketFragment(const InetAddress &fromAddr,const void *data,unsigned int len); void _handleRemotePacketHead(const InetAddress &fromAddr,const void *data,unsigned int len); void _handleBeacon(const InetAddress &fromAddr,const Buffer &data); - - Address _sendWhoisRequest( - const Address &addr, - const Address *peersAlreadyConsulted, - unsigned int numPeersAlreadyConsulted); - - bool _trySend( - const Packet &packet, - bool encrypt); + Address _sendWhoisRequest(const Address &addr,const Address *peersAlreadyConsulted,unsigned int numPeersAlreadyConsulted); + bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid); const RuntimeEnvironment *const RR; volatile uint64_t _lastBeacon; @@ -226,13 +220,15 @@ private: struct TXQueueEntry { TXQueueEntry() {} - TXQueueEntry(uint64_t ct,const Packet &p,bool enc) : + TXQueueEntry(uint64_t ct,const Packet &p,bool enc,uint64_t nw) : creationTime(ct), + nwid(nw), packet(p), encrypt(enc) {} uint64_t creationTime; - Packet packet; // unencrypted/untagged for TX queue + uint64_t nwid; + Packet packet; // unencrypted/unMAC'd packet -- this is done at send time bool encrypt; }; std::multimap< Address,TXQueueEntry > _txQueue; -- cgit v1.2.3 From 5341e32729e21b1880afe121e5c36bfa9cfefd00 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 19:05:27 -0700 Subject: Fix to GitHub issue #140 -- network preferred relays. Also go ahead and allow RENDEZVOUS from regular peers. --- node/IncomingPacket.cpp | 41 +++++------------ node/NetworkConfig.cpp | 8 ++-- node/Node.cpp | 119 ++++++++++++++++++++++++------------------------ node/Peer.cpp | 4 +- node/Peer.hpp | 3 +- node/Switch.cpp | 8 ++-- 6 files changed, 84 insertions(+), 99 deletions(-) (limited to 'node') diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 2ddd83a8..8b228de5 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -486,38 +486,21 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr &peer) { try { - /* - * At the moment, we only obey RENDEZVOUS if it comes from a designated - * supernode. If relay offloading is implemented to scale the net, this - * will need reconsideration. - * - * The reason is that RENDEZVOUS could technically be used to cause a - * peer to send a weird encrypted UDP packet to an arbitrary IP:port. - * The sender of RENDEZVOUS has no control over the content of this - * packet, but it's still maybe something we want to not allow just - * anyone to order due to possible DDOS or network forensic implications. - * So if we diversify relays, we'll need some way of deciding whether the - * sender is someone we should trust with a RENDEZVOUS hint. - */ - if (RR->topology->isSupernode(peer->address())) { - const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - const SharedPtr withPeer(RR->topology->getPeer(with)); - if (withPeer) { - const unsigned int port = at(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); - const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; - if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { - InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); - TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); - peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); - RR->sw->contact(withPeer,atAddr); - } else { - TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); - } + const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); + const SharedPtr withPeer(RR->topology->getPeer(with)); + if (withPeer) { + const unsigned int port = at(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); + const unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; + if ((port > 0)&&((addrlen == 4)||(addrlen == 16))) { + InetAddress atAddr(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRESS,addrlen),addrlen,port); + TRACE("RENDEZVOUS from %s says %s might be at %s, starting NAT-t",peer->address().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); + peer->received(RR,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); + RR->sw->contact(withPeer,atAddr); } else { - TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),with.toString().c_str()); + TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); } } else { - TRACE("ignored RENDEZVOUS from %s(%s): source not supernode",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("ignored RENDEZVOUS from %s(%s) to meet unknown peer %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),with.toString().c_str()); } } catch (std::exception &ex) { TRACE("dropped RENDEZVOUS from %s(%s): %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp index 82e986e2..4b9620a6 100644 --- a/node/NetworkConfig.cpp +++ b/node/NetworkConfig.cpp @@ -184,9 +184,11 @@ void NetworkConfig::_fromDictionary(const Dictionary &d) std::vector relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); for(std::vector::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { std::size_t semi(r->find(';')); // address;ip/port,... - if ((semi == ZT_ADDRESS_LENGTH)&&(r->length() > (ZT_ADDRESS_LENGTH + 1))) { - std::pair relay(Address(r->substr(0,semi)),InetAddress(r->substr(semi+1))); - if ((relay.first)&&(relay.second)) + if (semi == ZT_ADDRESS_LENGTH_HEX) { + std::pair relay( + Address(r->substr(0,semi)), + ((r->length() > (semi + 1)) ? InetAddress(r->substr(semi + 1)) : InetAddress()) ); + if ((relay.first)&&(!relay.first.isReserved())) _relays.push_back(relay); } } diff --git a/node/Node.cpp b/node/Node.cpp index a143275e..d45c5503 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -184,57 +184,42 @@ ZT1_ResultCode Node::processVirtualNetworkFrame( class _PingPeersThatNeedPing { public: - _PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now) : + _PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now,const std::vector< std::pair > &relays) : lastReceiveFromUpstream(0), RR(renv), _now(now), - _supernodes(RR->topology->supernodeAddresses()), - _relays() + _relays(relays), + _supernodes(RR->topology->supernodeAddresses()) { - std::vector< SharedPtr > nws(renv->node->allNetworks()); - for(std::vector< SharedPtr >::const_iterator nw(nws.begin());nw!=nws.end();++nw) { - SharedPtr nc((*nw)->config2()); - if (nc) - _relays.insert(_relays.end(),nc->relays().begin(),nc->relays().end()); - } - std::sort(_relays.begin(),_relays.end()); - std::unique(_relays.begin(),_relays.end()); } uint64_t lastReceiveFromUpstream; inline void operator()(Topology &t,const SharedPtr &p) { - if (std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end()) { - // Supernodes have fixed addresses and are always pinged + bool isRelay = false; + for(std::vector< std::pair >::const_iterator r(_relays.begin());r!=_relays.end();++r) { + if (r->first == p->address()) { + isRelay = true; + break; + } + } + + if ((isRelay)||(std::find(_supernodes.begin(),_supernodes.end(),p->address()) != _supernodes.end())) { p->doPingAndKeepalive(RR,_now); if (p->lastReceive() > lastReceiveFromUpstream) lastReceiveFromUpstream = p->lastReceive(); } else { - // Ping regular peers if they are alive, or if they are network - // designated relays with suggested IP address endpoints in a - // network config. - bool ison; if (p->alive(_now)) - ison = p->doPingAndKeepalive(RR,_now); - else ison = false; - - if (!ison) { - // Note that multiple networks might designate the same peer as - // a preferred relay, so try all suggested endpoints. - for(std::vector< std::pair >::const_iterator r(_relays.begin());r!=_relays.end();++r) { - if (r->first == p->address()) - p->attemptToContactAt(RR,r->second,_now); - } - } + p->doPingAndKeepalive(RR,_now); } } private: const RuntimeEnvironment *RR; uint64_t _now; + const std::vector< std::pair > &_relays; std::vector
_supernodes; - std::vector< std::pair > _relays; }; ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline) @@ -243,54 +228,70 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next Mutex::Lock bl(_backgroundTasksLock); if ((now - _lastPingCheck) >= ZT_PING_CHECK_INVERVAL) { - _lastPingCheck = now; - try { - _PingPeersThatNeedPing pfunc(RR,now); + _lastPingCheck = now; + + // Get relays and networks that need config without leaving the mutex locked + std::vector< std::pair > networkRelays; + std::vector< SharedPtr > needConfig; + { + Mutex::Lock _l(_networks_m); + for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { + SharedPtr nc(n->second->config2()); + if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!nc)) + needConfig.push_back(n->second); + if (nc) + networkRelays.insert(networkRelays.end(),nc->relays().begin(),nc->relays().end()); + } + } + + // Request updated configuration for networks that need it + for(std::vector< SharedPtr >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) + (*n)->requestConfiguration(); + + // Attempt to contact network preferred relays that we don't have direct links to + std::sort(networkRelays.begin(),networkRelays.end()); + std::unique(networkRelays.begin(),networkRelays.end()); + for(std::vector< std::pair >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) { + if (nr->second) { + SharedPtr rp(RR->topology->getPeer(nr->first)); + if ((rp)&&(!rp->hasActiveDirectPath(now))) + rp->attemptToContactAt(RR,nr->second,now); + } + } + + // Ping living or supernode/relay peers + _PingPeersThatNeedPing pfunc(RR,now,networkRelays); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); + // Update online status, post status change as event bool oldOnline = _online; _online = ((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT); if (oldOnline != _online) postEvent(_online ? ZT1_EVENT_ONLINE : ZT1_EVENT_OFFLINE); - } catch ( ... ) { - return ZT1_RESULT_FATAL_ERROR_INTERNAL; - } - try { - Mutex::Lock _l(_networks_m); - for(std::map< uint64_t,SharedPtr >::const_iterator n(_networks.begin());n!=_networks.end();++n) { - if ((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY) - n->second->requestConfiguration(); + // Send LAN beacons + if ((now - _lastBeacon) >= ZT_BEACON_INTERVAL) { + _lastBeacon = now; + char beacon[13]; + void *p = beacon; + *(reinterpret_cast(p)) = RR->prng->next32(); + p = beacon + 4; + *(reinterpret_cast(p)) = RR->prng->next32(); + RR->identity.address().copyTo(beacon + 8,5); + RR->antiRec->logOutgoingZT(beacon,13); + putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13); } } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; } - - if ((now - _lastBeacon) >= ZT_BEACON_INTERVAL) { - _lastBeacon = now; - char beacon[13]; - void *p = beacon; - *(reinterpret_cast(p)) = RR->prng->next32(); - p = beacon + 4; - *(reinterpret_cast(p)) = RR->prng->next32(); - RR->identity.address().copyTo(beacon + 8,5); - RR->antiRec->logOutgoingZT(beacon,13); - putPacket(ZT_DEFAULTS.v4Broadcast,beacon,13); - } } if ((now - _lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { - _lastHousekeepingRun = now; - try { + _lastHousekeepingRun = now; RR->topology->clean(now); RR->sa->clean(now); - } catch ( ... ) { - return ZT1_RESULT_FATAL_ERROR_INTERNAL; - } - - try { RR->mc->clean(now); } catch ( ... ) { return ZT1_RESULT_FATAL_ERROR_INTERNAL; diff --git a/node/Peer.cpp b/node/Peer.cpp index f5365223..d788d006 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -191,7 +191,7 @@ void Peer::attemptToContactAt(const RuntimeEnvironment *RR,const InetAddress &at RR->node->putPacket(atAddress,outp.data(),outp.size()); } -bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) +void Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) { Path *const bestPath = getBestPath(now); if ((bestPath)&&(bestPath->active(now))) { @@ -204,9 +204,7 @@ bool Peer::doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now) RR->node->putPacket(bestPath->address(),"",0); bestPath->sent(now); } - return true; } - return false; } void Peer::addPath(const Path &newp) diff --git a/node/Peer.hpp b/node/Peer.hpp index 7dc5017c..8d8b7cb4 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -179,9 +179,8 @@ public: * * @param RR Runtime environment * @param now Current time - * @return True if there is an active best path (regardless of whether it needed a ping or keepalive), false if no paths */ - bool doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); + void doPingAndKeepalive(const RuntimeEnvironment *RR,uint64_t now); /** * @return All known direct paths to this peer diff --git a/node/Switch.cpp b/node/Switch.cpp index d01d77ca..0aa0b664 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -741,9 +741,11 @@ bool Switch::_trySend(const Packet &packet,bool encrypt,uint64_t nwid) if (nconf) { unsigned int latency = ~((unsigned int)0); for(std::vector< std::pair >::const_iterator r(nconf->relays().begin());r!=nconf->relays().end();++r) { - SharedPtr rp(RR->topology->getPeer(r->first)); - if ((rp->hasActiveDirectPath(now))&&(rp->latency() <= latency)) - rp.swap(relay); + if (r->first != peer->address()) { + SharedPtr rp(RR->topology->getPeer(r->first)); + if ((rp)&&(rp->hasActiveDirectPath(now))&&(rp->latency() <= latency)) + rp.swap(relay); + } } } } -- cgit v1.2.3 From ecb6a1d84fc48dda029ff8ec321616fc14efd108 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 19:12:20 -0700 Subject: docs --- node/Node.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'node') diff --git a/node/Node.cpp b/node/Node.cpp index d45c5503..9f195a10 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -248,7 +248,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next // Request updated configuration for networks that need it for(std::vector< SharedPtr >::const_iterator n(needConfig.begin());n!=needConfig.end();++n) (*n)->requestConfiguration(); - + // Attempt to contact network preferred relays that we don't have direct links to std::sort(networkRelays.begin(),networkRelays.end()); std::unique(networkRelays.begin(),networkRelays.end()); @@ -259,7 +259,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next rp->attemptToContactAt(RR,nr->second,now); } } - + // Ping living or supernode/relay peers _PingPeersThatNeedPing pfunc(RR,now,networkRelays); RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc); -- cgit v1.2.3 From aab17d9f1ff250113324fcfe4cca186fda69be58 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 19:18:26 -0700 Subject: Kill obsolete amSupernode method -- we now have no differing behaviors. --- node/Topology.hpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'node') diff --git a/node/Topology.hpp b/node/Topology.hpp index 63c81016..56a9709f 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -156,11 +156,6 @@ public: return _supernodeAddresses; } - /** - * @return True if this node's identity is in the supernode set - */ - inline bool amSupernode() const { return _amSupernode; } - /** * Clean and flush database */ -- cgit v1.2.3 From a9a390a930493bba3b64a20fb20e55f304062b0a Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 1 Jun 2015 19:43:06 -0700 Subject: Apply @marning suggested SSE auto-detect to make builds easier on non-x86 platforms: https://github.com/mwarning/ZeroTierOne/commit/aa2fd044cb69b97eef1ea38d5fefd18543aae22a --- make-freebsd.mk | 21 --------------------- make-linux.mk | 21 --------------------- make-mac.mk | 3 --- node/Salsa20.hpp | 6 ++++++ selftest.cpp | 6 ++++++ 5 files changed, 12 insertions(+), 45 deletions(-) (limited to 'node') diff --git a/make-freebsd.mk b/make-freebsd.mk index 2832136e..6a0f354d 100644 --- a/make-freebsd.mk +++ b/make-freebsd.mk @@ -8,27 +8,6 @@ LIBS= include objects.mk OBJS+=osdep/BSDEthernetTap.o -# Enable SSE-optimized Salsa20 on x86 and x86_64 machines -MACHINE=$(shell uname -m) -ifeq ($(MACHINE),x86_64) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),amd64) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i686) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i586) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i386) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),x86) - DEFS+=-DZT_SALSA20_SSE -endif - # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) ZT_AUTO_UPDATE=1 diff --git a/make-linux.mk b/make-linux.mk index 6b92bfaa..892b40b6 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -9,27 +9,6 @@ LIBS= include objects.mk OBJS+=osdep/LinuxEthernetTap.o -# Enable SSE-optimized Salsa20 on x86 and x86_64 machines -MACHINE=$(shell uname -m) -ifeq ($(MACHINE),x86_64) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),amd64) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i686) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i586) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),i386) - DEFS+=-DZT_SALSA20_SSE -endif -ifeq ($(MACHINE),x86) - DEFS+=-DZT_SALSA20_SSE -endif - # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) ZT_AUTO_UPDATE=1 diff --git a/make-mac.mk b/make-mac.mk index 7d730ae5..48bfdd79 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -31,9 +31,6 @@ ifeq ($(ZT_ENABLE_NETWORK_CONTROLLER),1) OBJS+=controller/SqliteNetworkController.o endif -# Enable SSE-optimized Salsa20 -- all Intel macs support SSE2 -DEFS+=-DZT_SALSA20_SSE - # Debug mode -- dump trace output, build binary with -g ifeq ($(ZT_DEBUG),1) DEFS+=-DZT_TRACE diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp index 0c1f3be4..9631a6db 100644 --- a/node/Salsa20.hpp +++ b/node/Salsa20.hpp @@ -7,10 +7,16 @@ #ifndef ZT_SALSA20_HPP #define ZT_SALSA20_HPP +#include #include +#include #include "Constants.hpp" +#if (!defined(ZT_SALSA20_SSE)) && (defined(__SSE2__) || defined(__WINDOWS__)) +#define ZT_SALSA20_SSE 1 +#endif + #ifdef ZT_SALSA20_SSE #include #endif // ZT_SALSA20_SSE diff --git a/selftest.cpp b/selftest.cpp index a0b3c951..27c81c25 100644 --- a/selftest.cpp +++ b/selftest.cpp @@ -187,6 +187,12 @@ static int testCrypto() } std::cout << "PASS" << std::endl; +#ifdef ZT_SALSA20_SSE + std::cout << "[crypto] Salsa20 SSE: ENABLED" << std::endl; +#else + std::cout << "[crypto] Salsa20 SSE: DISABLED" << std::endl; +#endif + std::cout << "[crypto] Benchmarking Salsa20/12... "; std::cout.flush(); { unsigned char *bb = (unsigned char *)::malloc(1234567); -- cgit v1.2.3