From 5901972958d6ef50671b7bbb89d2b365e4baf17c Mon Sep 17 00:00:00 2001
From: Adam Ierymenko <adam.ierymenko@gmail.com>
Date: Thu, 24 Oct 2013 16:57:26 -0400
Subject: [PATCH] More tying up of certificate of membership stuff in the
 client.

---
 node/CertificateOfMembership.cpp | 3 +++
 node/CertificateOfMembership.hpp | 1 +
 node/Network.cpp                 | 8 +++++---
 node/Network.hpp                 | 8 +++++---
 node/NetworkConfig.cpp           | 2 ++
 5 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp
index 82e7bc811..dd92455eb 100644
--- a/node/CertificateOfMembership.cpp
+++ b/node/CertificateOfMembership.cpp
@@ -86,6 +86,9 @@ void CertificateOfMembership::fromString(const char *s)
 	_signedBy.zero();
 	memset(_signature.data,0,_signature.size());
 
+	if (!*s)
+		return;
+
 	unsigned int colonAt = 0;
 	while ((s[colonAt])&&(s[colonAt] != ':')) ++colonAt;
 
diff --git a/node/CertificateOfMembership.hpp b/node/CertificateOfMembership.hpp
index 7f3dcbb3e..76e1cfbc6 100644
--- a/node/CertificateOfMembership.hpp
+++ b/node/CertificateOfMembership.hpp
@@ -265,6 +265,7 @@ public:
 	 *
 	 * Invalid strings will result in invalid or undefined certificate
 	 * contents. These will subsequently fail validation and comparison.
+	 * Empty strings will result in an empty certificate.
 	 *
 	 * @param s String to deserialize
 	 */
diff --git a/node/Network.cpp b/node/Network.cpp
index acc2588de..43cd83a20 100644
--- a/node/Network.cpp
+++ b/node/Network.cpp
@@ -221,12 +221,14 @@ void Network::_CBhandleTapData(void *arg,const MAC &from,const MAC &to,unsigned
 
 void Network::_pushMembershipCertificate(const Address &peer,bool force,uint64_t now)
 {
-	uint64_t timestampMaxDelta = _config->com().timestampMaxDelta();
-	if (!timestampMaxDelta)
+	uint64_t pushTimeout = _config->com().timestampMaxDelta() / 2;
+	if (!pushTimeout)
 		return; // still waiting on my own cert
+	if (pushTimeout > 1000)
+		pushTimeout -= 1000;
 
 	uint64_t &lastPushed = _lastPushedMembershipCertificate[peer];
-	if ((force)||((now - lastPushed) > (timestampMaxDelta / 2))) {
+	if ((force)||((now - lastPushed) > pushTimeout)) {
 		lastPushed = now;
 
 		Packet outp(peer,_r->identity.address(),Packet::VERB_NETWORK_MEMBERSHIP_CERTIFICATE);
diff --git a/node/Network.hpp b/node/Network.hpp
index 1b74a0487..ecee77c13 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -203,7 +203,7 @@ public:
 	inline void pushMembershipCertificate(const Address &peer,bool force,uint64_t now)
 	{
 		Mutex::Lock _l(_lock);
-		if ((_config)&&(!_config->isOpen()))
+		if ((_config)&&(!_config->isOpen())&&(_config->com()))
 			_pushMembershipCertificate(peer,force,now);
 	}
 
@@ -214,15 +214,17 @@ public:
 	 * len is reached or a null address is encountered.
 	 *
 	 * @param peers Packed array of 5-byte big-endian addresses
-	 * @param len Length of peers[] in total, MUST be a multiple of 5
+	 * @param len Length of peers[] in total (bytes, not addresses)
 	 * @param force If true, push even if we've already done so within required time frame
 	 * @param now Current time
 	 */
 	inline void pushMembershipCertificate(const void *peers,unsigned int len,bool force,uint64_t now)
 	{
 		Mutex::Lock _l(_lock);
-		if ((_config)&&(!_config->isOpen())) {
+		if ((_config)&&(!_config->isOpen())&&(_config->com())) {
 			for(unsigned int i=0;i<len;i+=ZT_ADDRESS_LENGTH) {
+				if ((i + ZT_ADDRESS_LENGTH) > len)
+					break;
 				Address a((char *)peers + i,ZT_ADDRESS_LENGTH);
 				if (a)
 					_pushMembershipCertificate(a,force,now);
diff --git a/node/NetworkConfig.cpp b/node/NetworkConfig.cpp
index 977b9aa32..f384ccf95 100644
--- a/node/NetworkConfig.cpp
+++ b/node/NetworkConfig.cpp
@@ -128,6 +128,8 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
 		if (params.size() >= 3)
 			_multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str()));
 	}
+
+	_com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string()));
 }
 
 } // namespace ZeroTier