Browse Source

Extend in-band world updates to handle moons too.

Adam Ierymenko 8 years ago
parent
commit
f102fd7f92
5 changed files with 63 additions and 14 deletions
  1. 30 10
      node/IncomingPacket.cpp
  2. 9 4
      node/Packet.hpp
  3. 11 0
      node/Peer.cpp
  4. 9 0
      node/Topology.hpp
  5. 4 0
      node/World.hpp

+ 30 - 10
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<uint64_t,uint64_t> > 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<uint64_t>(ptr); ptr += 8;
 				planetWorldTimestamp = at<uint64_t>(ptr);
 			}
+
+			// Get moon IDs and timestamps if present
+			if ((ptr + 2) <= size()) {
+				unsigned int numMoons = at<uint16_t>(ptr); ptr += 2;
+				for(unsigned int i=0;i<numMoons;++i) {
+					if ((World::Type)(*this)[ptr++] == World::TYPE_MOON)
+						moonIdsAndTimestamps.push_back(std::pair<uint64_t,uint64_t>(at<uint64_t>(ptr),at<uint64_t>(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<uint16_t>(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<World> moons(RR->topology->moons());
+			for(std::vector<World>::const_iterator m(moons.begin());m!=moons.end();++m) {
+				for(std::vector< std::pair<uint64_t,uint64_t> >::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<uint16_t>(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<Peer> &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<uint16_t>(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);

+ 9 - 4
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.
 		 */

+ 11 - 0
node/Peer.cpp

@@ -345,6 +345,7 @@ SharedPtr<Path> 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<World> moons(RR->topology->moons());
+	outp.append((uint16_t)moons.size());
+	for(std::vector<World>::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());

+ 9 - 0
node/Topology.hpp

@@ -201,6 +201,15 @@ public:
 		return _upstreamAddresses;
 	}
 
+	/**
+	 * @return Current moons
+	 */
+	inline std::vector<World> moons() const
+	{
+		Mutex::Lock _l(_lock);
+		return _moons;
+	}
+
 	/**
 	 * @return Current planet
 	 */

+ 4 - 0
node/World.hpp

@@ -176,6 +176,8 @@ public:
 			for(std::vector<InetAddress>::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<uint16_t>(p) + 2;
 
 		return (p - startAt);
 	}