diff --git a/node/IncomingPacket.cpp b/node/IncomingPacket.cpp index 2487a8aa8..1a60d13ac 100644 --- a/node/IncomingPacket.cpp +++ b/node/IncomingPacket.cpp @@ -216,6 +216,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut InetAddress externalSurfaceAddress; uint64_t planetWorldId = 0; uint64_t planetWorldTimestamp = 0; + std::vector< std::pair > moonIdsAndTimestamps; { unsigned int ptr = ZT_PROTO_VERB_HELLO_IDX_IDENTITY + id.deserialize(*this,ZT_PROTO_VERB_HELLO_IDX_IDENTITY); @@ -228,6 +229,16 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut planetWorldId = at(ptr); ptr += 8; planetWorldTimestamp = at(ptr); } + + // Get moon IDs and timestamps if present + if ((ptr + 2) <= size()) { + unsigned int numMoons = at(ptr); ptr += 2; + for(unsigned int i=0;i(at(ptr),at(ptr + 8))); + ptr += 16; + } + } } if (fromAddress != id.address()) { @@ -356,15 +367,24 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,const bool alreadyAut tmpa.serialize(outp); } + const unsigned int worldUpdateSizeAt = outp.size(); + outp.addSize(2); // make room for 16-bit size field if ((planetWorldId)&&(RR->topology->planetWorldTimestamp() > planetWorldTimestamp)&&(planetWorldId == RR->topology->planetWorldId())) { - World w(RR->topology->planet()); - const unsigned int sizeAt = outp.size(); - outp.addSize(2); // make room for 16-bit size field - w.serialize(outp,false); - outp.setAt(sizeAt,(uint16_t)(outp.size() - (sizeAt + 2))); - } else { - outp.append((uint16_t)0); // no planet update needed + RR->topology->planet().serialize(outp,false); } + if (moonIdsAndTimestamps.size() > 0) { + std::vector moons(RR->topology->moons()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + for(std::vector< std::pair >::const_iterator i(moonIdsAndTimestamps.begin());i!=moonIdsAndTimestamps.end();++i) { + if (i->first == m->id()) { + if (m->timestamp() > i->second) + m->serialize(outp,false); + break; + } + } + } + } + outp.setAt(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2))); outp.armor(peer->key(),true); _path->send(RR,outp.data(),outp.size(),now); @@ -411,11 +431,11 @@ bool IncomingPacket::_doOK(const RuntimeEnvironment *RR,const SharedPtr &p if (ptr < size()) ptr += externalSurfaceAddress.deserialize(*this,ptr); - // Handle planet or moon updates + // Handle planet or moon updates if present (older versions don't send this) if ((ptr + 2) <= size()) { - World worldUpdate; const unsigned int worldLen = at(ptr); ptr += 2; - if (worldLen > 0) { + const unsigned int endOfWorlds = ptr + worldLen; + while (ptr < endOfWorlds) { World w; w.deserialize(*this,ptr); RR->topology->addWorld(w,true); diff --git a/node/Packet.hpp b/node/Packet.hpp index 0be19f8a4..26e87af8c 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -536,12 +536,17 @@ public: * <[1] software major version> * <[1] software minor version> * <[2] software revision> - * <[8] timestamp (ms since epoch)> + * <[8] timestamp for determining latench> * <[...] binary serialized identity (see Identity)> * <[1] destination address type> * [<[...] destination address to which packet was sent>] - * <[8] 64-bit world ID of current world> - * <[8] 64-bit timestamp of current world> + * <[8] 64-bit world ID of current planet> + * <[8] 64-bit timestamp of current planet> + * <[2] 16-bit number of moons> + * [<[1] 8-bit type ID of moon>] + * [<[8] 64-bit world ID of moon>] + * [<[8] 64-bit timestamp of moon>] + * [... additional moons ...] * * This is the only message that ever must be sent in the clear, since it * is used to push an identity to a new peer. @@ -567,7 +572,7 @@ public: * <[1] destination address type (for this OK, not copied from HELLO)> * [<[...] destination address>] * <[2] 16-bit length of world update or 0 if none> - * [[...] world update] + * [[...] updates to planets and/or moons] * * ERROR has no payload. */ diff --git a/node/Peer.cpp b/node/Peer.cpp index 40356034c..441a5b333 100644 --- a/node/Peer.cpp +++ b/node/Peer.cpp @@ -345,6 +345,7 @@ SharedPtr Peer::getBestPath(uint64_t now,bool includeExpired) void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,uint64_t now) { Packet outp(_id.address(),RR->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); @@ -352,8 +353,18 @@ void Peer::sendHELLO(const InetAddress &localAddr,const InetAddress &atAddress,u outp.append(now); RR->identity.serialize(outp,false); atAddress.serialize(outp); + outp.append((uint64_t)RR->topology->planetWorldId()); outp.append((uint64_t)RR->topology->planetWorldTimestamp()); + + std::vector moons(RR->topology->moons()); + outp.append((uint16_t)moons.size()); + for(std::vector::const_iterator m(moons.begin());m!=moons.end();++m) { + outp.append((uint8_t)m->type()); + outp.append((uint64_t)m->id()); + outp.append((uint64_t)m->timestamp()); + } + RR->node->expectReplyTo(outp.packetId()); outp.armor(_key,false); // HELLO is sent in the clear RR->node->putPacket(localAddr,atAddress,outp.data(),outp.size()); diff --git a/node/Topology.hpp b/node/Topology.hpp index 479812482..6369c5cd6 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -201,6 +201,15 @@ public: return _upstreamAddresses; } + /** + * @return Current moons + */ + inline std::vector moons() const + { + Mutex::Lock _l(_lock); + return _moons; + } + /** * @return Current planet */ diff --git a/node/World.hpp b/node/World.hpp index c4682a694..06dcb9813 100644 --- a/node/World.hpp +++ b/node/World.hpp @@ -176,6 +176,8 @@ public: for(std::vector::const_iterator ep(r->stableEndpoints.begin());ep!=r->stableEndpoints.end();++ep) ep->serialize(b); } + if (_type == TYPE_MOON) + b.append((uint16_t)0); // no attached dictionary (for future use) if (forSign) b.append((uint64_t)0xf7f7f7f7f7f7f7f7ULL); } @@ -214,6 +216,8 @@ public: p += r.stableEndpoints.back().deserialize(b,p); } } + if (_type == TYPE_MOON) + p += b.template at(p) + 2; return (p - startAt); }