diff options
author | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-04-06 14:50:53 -0700 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@gmail.com> | 2015-04-06 14:50:53 -0700 |
commit | f4fd2d497109f9db2f4a2834262e62289fafb317 (patch) | |
tree | 32f969bbbe9b8935ddfe9df0ebd27b2c6fb12e8f /node | |
parent | a95f1e1418b0a14f29365202d0df11b76c2578bb (diff) | |
download | infinitytier-f4fd2d497109f9db2f4a2834262e62289fafb317.tar.gz infinitytier-f4fd2d497109f9db2f4a2834262e62289fafb317.zip |
Bring IncomingPacket into line with new changes.
Diffstat (limited to 'node')
-rw-r--r-- | node/IncomingPacket.cpp | 284 | ||||
-rw-r--r-- | node/Node.cpp | 47 | ||||
-rw-r--r-- | node/Node.hpp | 49 | ||||
-rw-r--r-- | node/Peer.hpp | 25 |
4 files changed, 233 insertions, 172 deletions
diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 28f6eb18..f63b33b2 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -38,8 +38,6 @@ #include "Topology.hpp" #include "Switch.hpp" #include "Peer.hpp" -#include "NodeConfig.hpp" -#include "SoftwareUpdater.hpp" #include "NetworkConfigMaster.hpp" namespace ZeroTier { @@ -70,7 +68,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) switch(verb()) { //case Packet::VERB_NOP: default: // ignore unknown verbs, but if they pass auth check they are "received" - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),verb(),0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),verb(),0,Packet::VERB_NOP); return true; case Packet::VERB_HELLO: return _doHELLO(RR); case Packet::VERB_ERROR: return _doERROR(RR,peer); @@ -101,9 +99,9 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR) bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB]; - uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID); - Packet::ErrorCode errorCode = (Packet::ErrorCode)(*this)[ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE]; + const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_ERROR_IDX_IN_RE_VERB]; + const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_IN_RE_PACKET_ID); + const Packet::ErrorCode errorCode = (Packet::ErrorCode)(*this)[ZT_PROTO_VERB_ERROR_IDX_ERROR_CODE]; //TRACE("ERROR %s from %s(%s) in-re %s",Packet::errorString(errorCode),source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb)); @@ -111,10 +109,10 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> case Packet::ERROR_OBJ_NOT_FOUND: if (inReVerb == Packet::VERB_WHOIS) { - if (RR->topology->isSupernode(source())) + if (RR->topology->isSupernode(peer->address())) RR->sw->cancelWhoisRequest(Address(field(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH)); } else if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); if ((network)&&(network->controller() == source())) network->setNotFound(); } @@ -122,32 +120,32 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> case Packet::ERROR_UNSUPPORTED_OPERATION: if (inReVerb == Packet::VERB_NETWORK_CONFIG_REQUEST) { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); if ((network)&&(network->controller() == source())) network->setNotFound(); } break; case Packet::ERROR_IDENTITY_COLLISION: - // TODO: if it comes from a supernode, regenerate a new identity - // if (RR->topology->isSupernode(source())) {} + if (RR->topology->isSupernode(peer->address())) + RR->node->postEvent(ZT1_EVENT_FATAL_ERROR_IDENTITY_COLLISION); break; case Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE: { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); if (network) { SharedPtr<NetworkConfig> nconf(network->config2()); if (nconf) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE); nconf->com().serialize(outp); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } } break; case Packet::ERROR_NETWORK_ACCESS_DENIED_: { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); + SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_ERROR_IDX_PAYLOAD))); if ((network)&&(network->controller() == source())) network->setAccessDenied(); } break; @@ -159,7 +157,7 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> default: break; } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_ERROR,inRePacketId,inReVerb); } catch (std::exception &ex) { TRACE("dropped ERROR from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -171,15 +169,20 @@ bool IncomingPacket::_doERROR(const RuntimeEnvironment *RR,const SharedPtr<Peer> bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) { try { - unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION]; - unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION]; - unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION]; - unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION); - uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP); - Identity id(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); + const unsigned int protoVersion = (*this)[ZT_PROTO_VERB_HELLO_IDX_PROTOCOL_VERSION]; + const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MAJOR_VERSION]; + const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO_IDX_MINOR_VERSION]; + const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO_IDX_REVISION); + const uint64_t timestamp = at<uint64_t>(ZT_PROTO_VERB_HELLO_IDX_TIMESTAMP); + const Identity id(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); + + if (source() != id.address()) { + TRACE("dropped HELLO from %s(%s): identity not for sending address",source().toString().c_str(),_remoteAddress.toString().c_str()); + return true; + } if (protoVersion < ZT_PROTO_VERSION_MIN) { - TRACE("dropped HELLO from %s(%s): protocol version too old",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("dropped HELLO from %s(%s): protocol version too old",id.address().toString().c_str(),_remoteAddress.toString().c_str()); return true; } @@ -193,18 +196,18 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) unsigned char key[ZT_PEER_SECRET_KEY_LENGTH]; if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) { if (dearmor(key)) { // ensure packet is authentic, otherwise drop - LOG("rejected HELLO from %s(%s): address already claimed",source().toString().c_str(),_remoteAddress.toString().c_str()); - Packet outp(source(),RR->identity.address(),Packet::VERB_ERROR); + LOG("rejected HELLO from %s(%s): address already claimed",id.address().toString().c_str(),_remoteAddress.toString().c_str()); + Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR); outp.append((unsigned char)Packet::VERB_HELLO); outp.append(packetId()); outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); outp.armor(key,true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } else { - LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str()); + LOG("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_remoteAddress.toString().c_str()); } } else { - LOG("rejected HELLO from %s(%s): key agreement failed",source().toString().c_str(),_remoteAddress.toString().c_str()); + LOG("rejected HELLO from %s(%s): key agreement failed",id.address().toString().c_str(),_remoteAddress.toString().c_str()); } return true; @@ -212,40 +215,41 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) // Identity is the same as the one we already have -- check packet integrity if (!dearmor(peer->key())) { - LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str()); + LOG("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_remoteAddress.toString().c_str()); return true; } - // If packet was valid, continue below... + // Continue at // VALID } } else { // We don't already have an identity with this address -- validate and learn it if (!id.locallyValidate()) { - TRACE("dropped HELLO from %s(%s): identity invalid",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("dropped HELLO from %s(%s): identity invalid",id.address().toString().c_str(),_remoteAddress.toString().c_str()); return true; } SharedPtr<Peer> newPeer(new Peer(RR->identity,id)); if (!dearmor(newPeer->key())) { - LOG("rejected HELLO from %s(%s): packet failed authentication",source().toString().c_str(),_remoteAddress.toString().c_str()); + LOG("rejected HELLO from %s(%s): packet failed authentication",id.address().toString().c_str(),_remoteAddress.toString().c_str()); return true; } peer = RR->topology->addPeer(newPeer); - // New peer learned, continue below... + // Continue at // VALID } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP,Utils::now()); + // VALID -- continues here + + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_HELLO,0,Packet::VERB_NOP); peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); - // If a supernode has a version higher than ours, this causes a software - // update check to run now. - if ((RR->updater)&&(RR->topology->isSupernode(peer->address()))) - RR->updater->sawRemoteVersion(vMajor,vMinor,vRevision); + // Won't get HELLO *from* supernodes, so skip this for now here. It's done in OK(HELLO). + //if (RR->topology->isSupernode(id.address())) + // RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); - Packet outp(source(),RR->identity.address(),Packet::VERB_OK); + Packet outp(id.address(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_HELLO); outp.append(packetId()); outp.append(timestamp); @@ -254,11 +258,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR); outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } catch (std::exception &ex) { - TRACE("dropped HELLO from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); + TRACE("dropped HELLO from %s(%s): %s",id.address().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { - TRACE("dropped HELLO from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("dropped HELLO from %s(%s): unexpected exception",id.address().toString().c_str(),_remoteAddress.toString().c_str()); } return true; } @@ -266,19 +270,19 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR) bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB]; - uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID); + const Packet::Verb inReVerb = (Packet::Verb)(*this)[ZT_PROTO_VERB_OK_IDX_IN_RE_VERB]; + const uint64_t inRePacketId = at<uint64_t>(ZT_PROTO_VERB_OK_IDX_IN_RE_PACKET_ID); //TRACE("%s(%s): OK(%s)",source().toString().c_str(),_remoteAddress.toString().c_str(),Packet::verbString(inReVerb)); switch(inReVerb) { case Packet::VERB_HELLO: { - unsigned int latency = std::min((unsigned int)(Utils::now() - at<uint64_t>(ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP)),(unsigned int)0xffff); - unsigned int vProto = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION]; - unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION]; - unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION]; - unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO__OK__IDX_REVISION); + const unsigned int latency = std::min((unsigned int)(RR->node->now() - at<uint64_t>(ZT_PROTO_VERB_HELLO__OK__IDX_TIMESTAMP)),(unsigned int)0xffff); + const unsigned int vProto = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_PROTOCOL_VERSION]; + const unsigned int vMajor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MAJOR_VERSION]; + const unsigned int vMinor = (*this)[ZT_PROTO_VERB_HELLO__OK__IDX_MINOR_VERSION]; + const unsigned int vRevision = at<uint16_t>(ZT_PROTO_VERB_HELLO__OK__IDX_REVISION); if (vProto < ZT_PROTO_VERSION_MIN) { TRACE("%s(%s): OK(HELLO) dropped, protocol version too old",source().toString().c_str(),_remoteAddress.toString().c_str()); @@ -290,28 +294,26 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p peer->addDirectLatencyMeasurment(latency); peer->setRemoteVersion(vProto,vMajor,vMinor,vRevision); - // If a supernode has a version higher than ours, this causes a software - // update check to run now. - if ((RR->updater)&&(RR->topology->isSupernode(peer->address()))) - RR->updater->sawRemoteVersion(vMajor,vMinor,vRevision); + if (RR->topology->isSupernode(peer->address())) + RR->node->postNewerVersionIfNewer(vMajor,vMinor,vRevision); } break; case Packet::VERB_WHOIS: { // Right now only supernodes are allowed to send OK(WHOIS) to prevent // poisoning attacks. Further decentralization will require some other // kind of trust mechanism. - if (RR->topology->isSupernode(source())) { - Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); + if (RR->topology->isSupernode(peer->address())) { + const Identity id(*this,ZT_PROTO_VERB_WHOIS__OK__IDX_IDENTITY); if (id.locallyValidate()) RR->sw->doAnythingWaitingForPeer(RR->topology->addPeer(SharedPtr<Peer>(new Peer(RR->identity,id)))); } } break; case Packet::VERB_NETWORK_CONFIG_REQUEST: { - SharedPtr<Network> nw(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID))); - if ((nw)&&(nw->controller() == source())) { - unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN); - std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen); + const SharedPtr<Network> nw(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_NETWORK_ID))); + if ((nw)&&(nw->controller() == peer->address())) { + const unsigned int dictlen = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT_LEN); + const std::string dict((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST__OK__IDX_DICT,dictlen),dictlen); if (dict.length()) { if (nw->setConfiguration(Dictionary(dict)) == 2) { // 2 == accepted and actually new /* If this configuration was indeed new, we do another @@ -325,16 +327,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p * versions <= 1.0.3, since those regenerate a new netconf * with a new revision every time. In that case this double * confirmation would create a race condition. */ - if ((peer->atLeastVersion(1,0,3))&&(nc->revision() > 0)) { - SharedPtr<NetworkConfig> nc(nw->config2()); - if ((nc)&&(nc->timestamp() > 0)) { // sanity check - Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); - outp.append((uint64_t)nw->id()); - outp.append((uint16_t)0); // no meta-data - outp.append((uint64_t)nc->revision()); - outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); - } + const SharedPtr<NetworkConfig> nc(nw->config2()); + if ((peer->atLeastVersion(1,0,3))&&(nc)&&(nc->revision() > 0)) { + Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NETWORK_CONFIG_REQUEST); + outp.append((uint64_t)nw->id()); + outp.append((uint16_t)0); // no meta-data + outp.append((uint64_t)nc->revision()); + outp.armor(peer->key(),true); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } TRACE("got network configuration for network %.16llx from %s",(unsigned long long)nw->id(),source().toString().c_str()); @@ -343,20 +343,19 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p } break; case Packet::VERB_MULTICAST_GATHER: { - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); - MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_NETWORK_ID); + const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_ADI)); TRACE("%s(%s): OK(MULTICAST_GATHER) %.16llx/%s length %u",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid,mg.toString().c_str(),size()); - - unsigned int count = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); - RR->mc->addMultiple(Utils::now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); + const unsigned int count = at<uint16_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 4); + RR->mc->addMultiple(RR->node->now(),nwid,mg,field(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS + 6,count * 5),count,at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER__OK__IDX_GATHER_RESULTS)); } break; case Packet::VERB_MULTICAST_FRAME: { - unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS]; - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); - MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI)); + const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_FLAGS]; + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_NETWORK_ID); + const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_ADI)); - TRACE("%s(%s): OK(MULTICAST_FRAME) %.16llx/%s flags %.2x",source().toString().c_str(),_remoteAddress.toString().c_str(),nwid,mg.toString().c_str(),flags); + TRACE("%s(%s): OK(MULTICAST_FRAME) %.16llx/%s flags %.2x",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),nwid,mg.toString().c_str(),flags); unsigned int offset = 0; @@ -364,7 +363,7 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p // OK(MULTICAST_FRAME) includes certificate of membership update CertificateOfMembership com; offset += com.deserialize(*this,ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS); - SharedPtr<Network> network(RR->nc->network(nwid)); + SharedPtr<Network> network(RR->node->network(nwid)); if ((network)&&(com.hasRequiredFields())) network->addMembershipCertificate(com,false); } @@ -374,14 +373,14 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr<Peer> &p offset += ZT_PROTO_VERB_MULTICAST_FRAME__OK__IDX_COM_AND_GATHER_RESULTS; unsigned int totalKnown = at<uint32_t>(offset); offset += 4; unsigned int count = at<uint16_t>(offset); offset += 2; - RR->mc->addMultiple(Utils::now(),nwid,mg,field(offset,count * 5),count,totalKnown); + RR->mc->addMultiple(RR->node->now(),nwid,mg,field(offset,count * 5),count,totalKnown); } } break; default: break; } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_OK,inRePacketId,inReVerb); } catch (std::exception &ex) { TRACE("dropped OK from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -394,14 +393,14 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> { try { if (payloadLength() == ZT_ADDRESS_LENGTH) { - SharedPtr<Peer> queried(RR->topology->getPeer(Address(payload(),ZT_ADDRESS_LENGTH))); + const SharedPtr<Peer> queried(RR->topology->getPeer(Address(payload(),ZT_ADDRESS_LENGTH))); if (queried) { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_OK); outp.append((unsigned char)Packet::VERB_WHOIS); outp.append(packetId()); queried->identity().serialize(outp,false); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } else { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); outp.append((unsigned char)Packet::VERB_WHOIS); @@ -409,12 +408,12 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,const SharedPtr<Peer> outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND); outp.append(payload(),ZT_ADDRESS_LENGTH); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } else { TRACE("dropped WHOIS from %s(%s): missing or invalid address",source().toString().c_str(),_remoteAddress.toString().c_str()); } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_WHOIS,0,Packet::VERB_NOP); } catch ( ... ) { TRACE("dropped WHOIS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str()); } @@ -437,30 +436,30 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr< * 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(source())) { - Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); - SharedPtr<Peer> withPeer(RR->topology->getPeer(with)); + if (RR->topology->isSupernode(peer->address())) { + const Address with(field(ZT_PROTO_VERB_RENDEZVOUS_IDX_ZTADDRESS,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); + const SharedPtr<Peer> withPeer(RR->topology->getPeer(with)); if (withPeer) { - unsigned int port = at<uint16_t>(ZT_PROTO_VERB_RENDEZVOUS_IDX_PORT); - unsigned int addrlen = (*this)[ZT_PROTO_VERB_RENDEZVOUS_IDX_ADDRLEN]; + const unsigned int port = at<uint16_t>(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",source().toString().c_str(),with.toString().c_str(),atAddr.toString().c_str()); - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP,Utils::now()); - RR->sw->contact(withPeer,atAddr); + 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,_linkDesperation,hops(),packetId(),Packet::VERB_RENDEZVOUS,0,Packet::VERB_NOP); + RR->sw->contact(withPeer,atAddr,_linkDesperation); } else { - TRACE("dropped corrupt RENDEZVOUS from %s(%s) (bad address or port)",source().toString().c_str(),_remoteAddress.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) to meet unknown peer %s",source().toString().c_str(),_remoteAddress.toString().c_str(),with.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()); } } else { - TRACE("ignored RENDEZVOUS from %s(%s): source not supernode",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("ignored RENDEZVOUS from %s(%s): source not supernode",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); } } catch (std::exception &ex) { - TRACE("dropped RENDEZVOUS from %s(%s): %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); + TRACE("dropped RENDEZVOUS from %s(%s): %s",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { - TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",source().toString().c_str(),_remoteAddress.toString().c_str()); + TRACE("dropped RENDEZVOUS from %s(%s): unexpected exception",peer->address().toString().c_str(),_remoteAddress.toString().c_str()); } return true; } @@ -468,7 +467,7 @@ bool IncomingPacket::_doRENDEZVOUS(const RuntimeEnvironment *RR,const SharedPtr< bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID))); + const SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID))); if (network) { if (size() > ZT_PROTO_VERB_FRAME_IDX_PAYLOAD) { if (!network->isAllowed(peer->address())) { @@ -477,17 +476,17 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> return true; } - unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); + const unsigned int etherType = at<uint16_t>(ZT_PROTO_VERB_FRAME_IDX_ETHERTYPE); if (!network->config()->permitsEtherType(etherType)) { TRACE("dropped FRAME from %s(%s): ethertype %.4x not allowed on %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned int)etherType,(unsigned long long)network->id()); return true; } - unsigned int payloadLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; - network->tapPut(MAC(peer->address(),network->id()),network->mac(),etherType,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); + const unsigned int payloadLen = size() - ZT_PROTO_VERB_FRAME_IDX_PAYLOAD; + RR->node->putFrame(network->id(),MAC(peer->address(),network->id()),network->mac(),etherType,0,field(ZT_PROTO_VERB_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_FRAME,0,Packet::VERB_NOP); } else { TRACE("dropped FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); } @@ -502,10 +501,10 @@ bool IncomingPacket::_doFRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - SharedPtr<Network> network(RR->nc->network(at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID))); + SharedPtr<Network> network(RR->node->network(at<uint64_t>(ZT_PROTO_VERB_EXT_FRAME_IDX_NETWORK_ID))); if (network) { if (size() > ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD) { - unsigned int flags = (*this)[ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS]; + const unsigned int flags = (*this)[ZT_PROTO_VERB_EXT_FRAME_IDX_FLAGS]; unsigned int comLen = 0; if ((flags & 0x01) != 0) { @@ -524,7 +523,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P // Everything after flags must be adjusted based on the length // of the certificate, if there was one... - unsigned int etherType = at<uint16_t>(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE); + const unsigned int etherType = at<uint16_t>(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_ETHERTYPE); if (!network->config()->permitsEtherType(etherType)) { TRACE("dropped EXT_FRAME from %s(%s): ethertype %.4x not allowed on network %.16llx",peer->address().toString().c_str(),_remoteAddress.toString().c_str(),(unsigned int)etherType,(unsigned long long)network->id()); return true; @@ -559,12 +558,11 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P } } - unsigned int payloadLen = size() - (comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD); - if (payloadLen) - network->tapPut(from,to,etherType,field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); + const unsigned int payloadLen = size() - (comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD); + RR->node->putFrame(network->id(),from,to,etherType,0,field(comLen + ZT_PROTO_VERB_EXT_FRAME_IDX_PAYLOAD,payloadLen),payloadLen); } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_EXT_FRAME,0,Packet::VERB_NOP); } else { TRACE("dropped EXT_FRAME from %s(%s): we are not connected to network %.16llx",source().toString().c_str(),_remoteAddress.toString().c_str(),at<uint64_t>(ZT_PROTO_VERB_FRAME_IDX_NETWORK_ID)); } @@ -579,13 +577,13 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,const SharedPtr<P bool IncomingPacket::_doMULTICAST_LIKE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - uint64_t now = Utils::now(); + const uint64_t now = RR->node->now(); // Iterate through 18-byte network,MAC,ADI tuples for(unsigned int ptr=ZT_PACKET_IDX_PAYLOAD;ptr<size();ptr+=18) RR->mc->add(now,at<uint64_t>(ptr),MulticastGroup(MAC(field(ptr + 8,6),6),at<uint32_t>(ptr + 14)),peer->address()); - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP,now); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_MULTICAST_LIKE,0,Packet::VERB_NOP); } catch (std::exception &ex) { TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -603,13 +601,13 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment while (ptr < size()) { ptr += com.deserialize(*this,ptr); if (com.hasRequiredFields()) { - SharedPtr<Network> network(RR->nc->network(com.networkId())); + SharedPtr<Network> network(RR->node->network(com.networkId())); if (network) network->addMembershipCertificate(com,false); } } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE,0,Packet::VERB_NOP); } catch (std::exception &ex) { TRACE("dropped NETWORK_MEMBERSHIP_CERTIFICATE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); } catch ( ... ) { @@ -621,22 +619,20 @@ bool IncomingPacket::_doNETWORK_MEMBERSHIP_CERTIFICATE(const RuntimeEnvironment bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID); - unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN); - Dictionary metaData((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength),metaDataLength); - uint64_t haveRevision = 0; - if ((ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength + 8) <= size()) - haveRevision = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength); + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_NETWORK_ID); + const unsigned int metaDataLength = at<uint16_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT_LEN); + const Dictionary metaData((const char *)field(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT,metaDataLength),metaDataLength); + const uint64_t haveRevision = ((ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength + 8) <= size()) ? at<uint64_t>(ZT_PROTO_VERB_NETWORK_CONFIG_REQUEST_IDX_DICT + metaDataLength) : 0ULL; const unsigned int h = hops(); - uint64_t pid = packetId(); - peer->received(RR,_fromSock,_remoteAddress,h,pid,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP,RR->node->now()); + const uint64_t pid = packetId(); + peer->received(RR,_remoteAddress,_linkDesperation,h,pid,Packet::VERB_NETWORK_CONFIG_REQUEST,0,Packet::VERB_NOP); if (RR->netconfMaster) { Dictionary netconf; switch(RR->netconfMaster->doNetworkConfigRequest((h > 0) ? InetAddress() : _remoteAddress,peer->identity(),nwid,metaData,haveRevision,netconf)) { case NetworkConfigMaster::NETCONF_QUERY_OK: { - std::string netconfStr(netconf.toString()); + const std::string netconfStr(netconf.toString()); if (netconfStr.length() > 0xffff) { // sanity check since field ix 16-bit LOG("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length()); } else { @@ -650,7 +646,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons if (outp.size() > ZT_PROTO_MAX_PACKET_LENGTH) { LOG("NETWORK_CONFIG_REQUEST failed: internal error: netconf size %u is too large",(unsigned int)netconfStr.length()); } else { - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } } break; @@ -663,7 +659,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND); outp.append(nwid); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } break; case NetworkConfigMaster::NETCONF_QUERY_ACCESS_DENIED: { Packet outp(peer->address(),RR->identity.address(),Packet::VERB_ERROR); @@ -672,7 +668,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_); outp.append(nwid); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } break; case NetworkConfigMaster::NETCONF_QUERY_INTERNAL_SERVER_ERROR: LOG("NETWORK_CONFIG_REQUEST failed: internal error: %s",netconf.get("error","(unknown)").c_str()); @@ -688,7 +684,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,cons outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); outp.append(nwid); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REQUEST from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); @@ -704,12 +700,12 @@ bool IncomingPacket::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *RR,cons unsigned int ptr = ZT_PACKET_IDX_PAYLOAD; while ((ptr + 8) <= size()) { uint64_t nwid = at<uint64_t>(ptr); - SharedPtr<Network> nw(RR->nc->network(nwid)); - if ((nw)&&(source() == nw->controller())) + SharedPtr<Network> nw(RR->node->network(nwid)); + if ((nw)&&(peer->address() == nw->controller())) nw->requestConfiguration(); ptr += 8; } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_NETWORK_CONFIG_REFRESH,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped NETWORK_CONFIG_REFRESH from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -721,9 +717,9 @@ bool IncomingPacket::_doNETWORK_CONFIG_REFRESH(const RuntimeEnvironment *RR,cons bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID); - MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI)); - unsigned int gatherLimit = at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT); + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_NETWORK_ID); + const MulticastGroup mg(MAC(field(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_MAC,6),6),at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_ADI)); + const unsigned int gatherLimit = at<uint32_t>(ZT_PROTO_VERB_MULTICAST_GATHER_IDX_GATHER_LIMIT); //TRACE("<<MC %s(%s) GATHER up to %u in %.16llx/%s",source().toString().c_str(),_remoteAddress.toString().c_str(),gatherLimit,nwid,mg.toString().c_str()); @@ -736,11 +732,11 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar outp.append((uint32_t)mg.adi()); if (RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit)) { outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_MULTICAST_GATHER,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped MULTICAST_GATHER from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -752,10 +748,10 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,const Shar bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer) { try { - uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); - unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS]; + const uint64_t nwid = at<uint64_t>(ZT_PROTO_VERB_MULTICAST_FRAME_IDX_NETWORK_ID); + const unsigned int flags = (*this)[ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FLAGS]; - SharedPtr<Network> network(RR->nc->network(nwid)); // will be NULL if not a member + const SharedPtr<Network> network(RR->node->network(nwid)); if (network) { // Offset -- size of optional fields added to position of later fields unsigned int offset = 0; @@ -789,9 +785,9 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share from.fromAddress(peer->address(),nwid); } - MulticastGroup to(MAC(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,6),6),at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI)); - unsigned int etherType = at<uint16_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE); - unsigned int payloadLen = size() - (offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME); + const MulticastGroup to(MAC(field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_MAC,6),6),at<uint32_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_DEST_ADI)); + const unsigned int etherType = at<uint16_t>(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_ETHERTYPE); + const unsigned int payloadLen = size() - (offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME); //TRACE("<<MC FRAME %.16llx/%s from %s@%s flags %.2x length %u",nwid,to.toString().c_str(),from.toString().c_str(),peer->address().toString().c_str(),flags,payloadLen); @@ -814,7 +810,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share } } - network->tapPut(from,to.mac(),etherType,field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),payloadLen); + RR->node->putFrame(network->id(),from,to.mac(),etherType,0,field(offset + ZT_PROTO_VERB_MULTICAST_FRAME_IDX_FRAME,payloadLen),payloadLen); } if (gatherLimit) { @@ -827,12 +823,12 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,const Share outp.append((unsigned char)0x02); // flag 0x02 = contains gather results if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) { outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } } // else ignore -- not a member of this network - peer->received(RR,_fromSock,_remoteAddress,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP,Utils::now()); + peer->received(RR,_remoteAddress,_linkDesperation,hops(),packetId(),Packet::VERB_MULTICAST_FRAME,0,Packet::VERB_NOP); } catch (std::exception &exc) { TRACE("dropped MULTICAST_FRAME from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),exc.what()); } catch ( ... ) { @@ -849,7 +845,7 @@ void IncomingPacket::_sendErrorNeedCertificate(const RuntimeEnvironment *RR,cons outp.append((unsigned char)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE); outp.append(nwid); outp.armor(peer->key(),true); - _fromSock->send(_remoteAddress,outp.data(),outp.size()); + RR->node->putPacket(_remoteAddress,outp.data(),outp.size(),_linkDesperation); } } // namespace ZeroTier diff --git a/node/Node.cpp b/node/Node.cpp index 4297a2ec..7e4bc642 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -44,6 +44,10 @@ namespace ZeroTier { +/****************************************************************************/ +/* Public Node interface (C++, exposed via CAPI bindings) */ +/****************************************************************************/ + Node::Node( uint64_t now, ZT1_DataStoreGetFunction dataStoreGetFunction, @@ -63,6 +67,10 @@ Node::Node( _networks_m(), _now(now) { + _newestVersionSeen[0] = ZEROTIER_ONE_VERSION_MAJOR; + _newestVersionSeen[1] = ZEROTIER_ONE_VERSION_MINOR; + _newestVersionSeen[2] = ZEROTIER_ONE_VERSION_REVISION; + try { RR->prng = new CMWC4096(); RR->sw = new Switch(RR); @@ -176,8 +184,30 @@ void Node::setNetconfMaster(void *networkConfigMasterInstance) RR->netconfMaster = reinterpret_cast<NetworkConfigMaster *>(networkConfigMasterInstance); } +/****************************************************************************/ +/* Node methods used only within node/ */ +/****************************************************************************/ + +std::string Node::dataStoreGet(const char *name) +{ +} + +void Node::postNewerVersionIfNewer(unsigned int major,unsigned int minor,unsigned int rev) +{ + if (Peer::compareVersion(major,minor,rev,_newestVersionSeen[0],_newestVersionSeen[1],_newestVersionSeen[2]) > 0) { + _newestVersionSeen[0] = major; + _newestVersionSeen[1] = minor; + _newestVersionSeen[2] = rev; + this->postEvent(ZT1_EVENT_SAW_MORE_RECENT_VERSION); + } +} + } // namespace ZeroTier +/****************************************************************************/ +/* CAPI bindings */ +/****************************************************************************/ + extern "C" { enum ZT1_ResultCode ZT1_Node_new( @@ -195,14 +225,21 @@ enum ZT1_ResultCode ZT1_Node_new( *node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(now,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigCallback,statusCallback)); return ZT1_RESULT_OK; } catch (std::bad_alloc &exc) { - return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + return ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (std::runtime_error &exc) { - return ZT1_RESULT_ERROR_DATA_STORE_FAILED; + return ZT1_RESULT_FATAL_ERROR_DATA_STORE_FAILED; } catch ( ... ) { - return ZT1_RESULT_ERROR_INTERNAL; + return ZT1_RESULT_FATAL_ERROR_INTERNAL; } } +void ZT1_Node_delete(ZT1_Node *node) +{ + try { + delete (reinterpret_cast<ZeroTier::Node *>(node)); + } catch ( ... ) {} +} + enum ZT1_ResultCode ZT1_Node_processWirePacket( ZT1_Node *node, uint64_t now, @@ -215,9 +252,9 @@ enum ZT1_ResultCode ZT1_Node_processWirePacket( try { return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,remoteAddress,linkDesperation,packetData,packetLength,nextCallDeadline); } catch (std::bad_alloc &exc) { - return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + return ZT1_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { - return ZT1_RESULT_PACKET_INVALID; + return ZT1_RESULT_ERROR_PACKET_INVALID; } } diff --git a/node/Node.hpp b/node/Node.hpp index 2dbf64b2..49871f5a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -115,12 +115,16 @@ public: */ inline bool putPacket(const InetAddress &addr,const void *data,unsigned int len,unsigned int desperation) { - return (_wirePacketSendFunction( - reinterpret_cast<ZT1_Node *>(this), - reinterpret_cast<const struct sockaddr_storage *>(&addr), - desperation, - data, - len) == 0); + try { + return (_wirePacketSendFunction( + reinterpret_cast<ZT1_Node *>(this), + reinterpret_cast<const struct sockaddr_storage *>(&addr), + desperation, + data, + len) == 0); + } catch ( ... ) { // callbacks should not throw + return false; + } } /** @@ -136,21 +140,19 @@ public: */ inline void putFrame(uint64_t nwid,const MAC &source,const MAC &dest,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len) { - _virtualNetworkFrameFunction( - reinterpret_cast<ZT1_Node *>(this), - nwid, - source.toInt(), - dest.toInt(), - etherType, - vlanId, - data, - len); + try { + _virtualNetworkFrameFunction( + reinterpret_cast<ZT1_Node *>(this), + nwid, + source.toInt(), + dest.toInt(), + etherType, + vlanId, + data, + len); + } catch ( ... ) {} // callbacks should not throw } - /** - * @param nwid Network ID - * @return Network instance - */ inline SharedPtr<Network> network(uint64_t nwid) { Mutex::Lock _l(_networks_m); @@ -160,12 +162,12 @@ public: inline bool dataStorePut(const char *name,const void *data,unsigned int len,bool secure) { return (_dataStorePutFunction(reinterpret_cast<ZT1_Node *>(this),name,data,len,(int)secure) == 0); } inline bool dataStorePut(const char *name,const std::string &data,bool secure) { return dataStorePut(name,(const void *)data.data(),(unsigned int)data.length(),secure); } + inline void dataStoreDelete(const char *name) { _dataStorePutFunction(reinterpret_cast<ZT1_Node *>(this),name,(const void *)0,0,0); } + std::string dataStoreGet(const char *name); - inline std::string dataStoreGet(const char *name) - { - } + inline void postEvent(ZT1_Event ev) { _statusCallback(reinterpret_cast<ZT1_Node *>(this),ev); } - inline void dataStoreDelete(const char *name) { _dataStorePutFunction(reinterpret_cast<ZT1_Node *>(this),name,(const void *)0,0,0); } + void postNewerVersionIfNewer(unsigned int major,unsigned int minor,unsigned int rev); private: RuntimeEnvironment *RR; @@ -184,6 +186,7 @@ private: Mutex _networks_m; volatile uint64_t _now; // time of last run() + unsigned int _newestVersionSeen[3]; // major, minor, revision }; } // namespace ZeroTier diff --git a/node/Peer.hpp b/node/Peer.hpp index fce725b2..147ce571 100644 --- a/node/Peer.hpp +++ b/node/Peer.hpp @@ -379,6 +379,31 @@ public: else return std::pair<InetAddress,InetAddress>(); } + /** + * Compare Peer version tuples + */ + static inline int compareVersion(unsigned int maj1,unsigned int min1,unsigned int rev1,unsigned int maj2,unsigned int min2,unsigned int rev2) + throw() + { + if (maj1 > maj2) + return 1; + else if (maj1 < maj2) + return -1; + else { + if (min1 > min2) + return 1; + else if (min1 < min2) + return -1; + else { + if (rev1 > rev2) + return 1; + else if (rev1 < rev2) + return -1; + else return 0; + } + } + } + private: void _announceMulticastGroups(const RuntimeEnvironment *RR,uint64_t now); |