From fe20f0d7cdbf9d38c7590bb5090467ff86b0008f Mon Sep 17 00:00:00 2001
From: Adam Ierymenko <adam.ierymenko@gmail.com>
Date: Mon, 13 Jul 2015 08:33:02 -0700
Subject: [PATCH] Put back legacy code to listen for LAN announcements to
 support same network location with pre-1.0.4 clients.

---
 node/Switch.cpp | 23 +++++++++++++++++++++--
 node/Switch.hpp |  9 +++++----
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/node/Switch.cpp b/node/Switch.cpp
index 4fd5d7696..cf4fe2492 100644
--- a/node/Switch.cpp
+++ b/node/Switch.cpp
@@ -65,7 +65,8 @@ static const char *etherTypeName(const unsigned int etherType)
 #endif // ZT_TRACE
 
 Switch::Switch(const RuntimeEnvironment *renv) :
-	RR(renv)
+	RR(renv),
+	_lastBeaconResponse(0)
 {
 }
 
@@ -76,7 +77,25 @@ Switch::~Switch()
 void Switch::onRemotePacket(const InetAddress &fromAddr,const void *data,unsigned int len)
 {
 	try {
-		if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
+		if (len == 13) {
+			/* LEGACY: before VERB_PUSH_DIRECT_PATHS, peers used broadcast
+			 * announcements on the LAN to solve the 'same network problem.' We
+			 * no longer send these, but we'll listen for them for a while to
+			 * locate peers with versions <1.0.4. */
+			Address beaconAddr(reinterpret_cast<const char *>(data) + 8,5);
+			if (beaconAddr == RR->identity.address())
+				return;
+			SharedPtr<Peer> peer(RR->topology->getPeer(beaconAddr));
+			if (peer) { // we'll only respond to beacons from known peers
+				const uint64_t now = RR->node->now();
+				if ((now - _lastBeaconResponse) >= 2500) { // limit rate of responses
+					_lastBeaconResponse = now;
+					Packet outp(peer->address(),RR->identity.address(),Packet::VERB_NOP);
+					outp.armor(peer->key(),false);
+					RR->node->putPacket(fromAddr,outp.data(),outp.size());
+				}
+			}
+		} else if (len > ZT_PROTO_MIN_FRAGMENT_LENGTH) {
 			if (((const unsigned char *)data)[ZT_PACKET_FRAGMENT_IDX_FRAGMENT_INDICATOR] == ZT_PACKET_FRAGMENT_INDICATOR) {
 				_handleRemotePacketFragment(fromAddr,data,len);
 			} else if (len >= ZT_PROTO_MIN_PACKET_LENGTH) {
diff --git a/node/Switch.hpp b/node/Switch.hpp
index 89c9a56b8..e7f1523a9 100644
--- a/node/Switch.hpp
+++ b/node/Switch.hpp
@@ -99,20 +99,20 @@ public:
 
 	/**
 	 * Send a packet to a ZeroTier address (destination in packet)
-	 * 
+	 *
 	 * The packet must be fully composed with source and destination but not
 	 * yet encrypted. If the destination peer is known the packet
 	 * is sent immediately. Otherwise it is queued and a WHOIS is dispatched.
 	 *
 	 * The packet may be compressed. Compression isn't done here.
-	 * 
+	 *
 	 * Needless to say, the packet's source must be this node. Otherwise it
 	 * won't be encrypted right. (This is not used for relaying.)
 	 *
 	 * The network ID should only be specified for frames and other actual
 	 * network traffic. Other traffic such as controller requests and regular
 	 * protocol messages should specify zero.
-	 * 
+	 *
 	 * @param packet Packet to send
 	 * @param encrypt Encrypt packet payload? (always true except for HELLO)
 	 * @param nwid Related network ID or 0 if message is not in-network traffic
@@ -168,7 +168,7 @@ public:
 
 	/**
 	 * Perform retries and other periodic timer tasks
-	 * 
+	 *
 	 * This can return a very long delay if there are no pending timer
 	 * tasks. The caller should cap this comparatively vs. other values.
 	 *
@@ -184,6 +184,7 @@ private:
 	bool _trySend(const Packet &packet,bool encrypt,uint64_t nwid);
 
 	const RuntimeEnvironment *const RR;
+	uint64_t _lastBeaconResponse;
 
 	// Outsanding WHOIS requests and how many retries they've undergone
 	struct WhoisRequest