Browse Source

Self test for command bus encode/decode.

Adam Ierymenko 12 years ago
parent
commit
c345c699fd
3 changed files with 39 additions and 5 deletions
  1. 3 4
      node/NodeConfig.cpp
  2. 3 1
      node/NodeConfig.hpp
  3. 33 0
      selftest.cpp

+ 3 - 4
node/NodeConfig.cpp

@@ -156,15 +156,15 @@ std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > NodeConfig::encodeControlMe
 		if (((i + 1) >= payload.size())||((packet.size() + payload[i + 1].length() + 1) >= packet.capacity())) {
 			Utils::getSecureRandom(packet.field(8,8),8);
 
+			Salsa20 s20(key,256,packet.field(8,8));
+			s20.encrypt(packet.field(16,packet.size() - 16),packet.field(16,packet.size() - 16),packet.size() - 16);
+
 			memcpy(keytmp,key,32);
 			for(unsigned int i=0;i<32;++i)
 				keytmp[i] ^= 0x77; // use a different permutation of key for HMAC than for Salsa20
 			HMAC::sha256(keytmp,32,packet.field(16,packet.size() - 16),packet.size() - 16,hmac);
 			memcpy(packet.field(0,8),hmac,8);
 
-			Salsa20 s20(key,256,packet.field(8,8));
-			s20.encrypt(packet.field(16,packet.size() - 16),packet.field(16,packet.size() - 16),packet.size() - 16);
-
 			packets.push_back(packet);
 
 			packet.setSize(16); // HMAC and IV
@@ -200,7 +200,6 @@ bool NodeConfig::decodeControlMessagePacket(const void *key,const void *data,uns
 
 		const char *pl = ((const char *)packet.data()) + 20;
 		unsigned int pll = packet.size() - 20;
-		payload.clear();
 		for(unsigned int i=0;i<pll;) {
 			unsigned int eos = i;
 			while ((eos < pll)&&(pl[eos]))

+ 3 - 1
node/NodeConfig.hpp

@@ -156,11 +156,13 @@ public:
 	/**
 	 * Decode a packet from the control bus
 	 *
+	 * Note that 'payload' is appended to. Existing data is not cleared.
+	 *
 	 * @param key 32 byte key
 	 * @param data Packet data
 	 * @param len Packet length
 	 * @param conversationId Result parameter filled with conversation ID on success
-	 * @param payload Result parameter filled with payload on success
+	 * @param payload Result parameter to which results are appended
 	 * @return True on success, false on invalid packet or packet that failed authentication
 	 */
 	static bool decodeControlMessagePacket(const void *key,const void *data,unsigned int len,unsigned long &conversationId,std::vector<std::string> &payload);

+ 33 - 0
selftest.cpp

@@ -45,6 +45,7 @@
 #include "node/Peer.hpp"
 #include "node/Http.hpp"
 #include "node/Condition.hpp"
+#include "node/NodeConfig.hpp"
 
 using namespace ZeroTier;
 
@@ -266,6 +267,38 @@ static int testOther()
 	}
 	std::cout << "PASS" << std::endl;
 
+	std::cout << "[other] Testing command bus encode/decode... "; std::cout.flush();
+	try {
+		static char key[32] = { 0 };
+		for(unsigned int k=0;k<1000;++k) {
+			std::vector<std::string> original;
+			for(unsigned int i=0,j=rand() % 256,l=(rand() % 1024)+1;i<j;++i)
+				original.push_back(std::string(l,'x'));
+			std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> > packets(NodeConfig::encodeControlMessage(key,1,original));
+			//std::cout << packets.size() << ' '; std::cout.flush();
+			std::vector<std::string> after;
+			for(std::vector< Buffer<ZT_NODECONFIG_MAX_PACKET_SIZE> >::iterator i(packets.begin());i!=packets.end();++i) {
+				unsigned long convId = 9999;
+				if (!NodeConfig::decodeControlMessagePacket(key,i->data(),i->size(),convId,after)) {
+					std::cout << "FAIL (decode)" << std::endl;
+					return -1;
+				}
+				if (convId != 1) {
+					std::cout << "FAIL (conversation ID)" << std::endl;
+					return -1;
+				}
+			}
+			if (after != original) {
+				std::cout << "FAIL (compare)" << std::endl;
+				return -1;
+			}
+		}
+	} catch (std::exception &exc) {
+		std::cout << "FAIL (" << exc.what() << ")" << std::endl;
+		return -1;
+	}
+	std::cout << "PASS" << std::endl;
+
 	return 0;
 }