Browse Source

Continuing work on new buffer type...

Adam Ierymenko 5 years ago
parent
commit
d5b9a54c55

+ 2 - 0
node/CMakeLists.txt

@@ -70,10 +70,12 @@ set(core_src
 	Peer.cpp
 	Poly1305.cpp
 	Protocol.cpp
+	Revocation.cpp
 	Salsa20.cpp
 	SelfAwareness.cpp
 	SHA512.cpp
 	Switch.cpp
+	Tag.cpp
 	Topology.cpp
 	Trace.cpp
 	Utils.cpp

+ 1 - 1
node/Capability.cpp

@@ -122,7 +122,7 @@ int Capability::unmarshal(const uint8_t *data,int len)
 	return p;
 }
 
-int Capability::marshalVirtualNetworkRules(uint8_t data[ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX],const ZT_VirtualNetworkRule *const rules,const unsigned int ruleCount)
+int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetworkRule *const rules,const unsigned int ruleCount)
 {
 	int p = 0;
 	for(unsigned int i=0;i<ruleCount;++i) {

+ 1 - 1
node/Capability.hpp

@@ -159,7 +159,7 @@ public:
 	int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],bool forSign = false) const;
 	int unmarshal(const uint8_t *data,int len);
 
-	static int marshalVirtualNetworkRules(uint8_t data[ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX],const ZT_VirtualNetworkRule *rules,unsigned int ruleCount);
+	static int marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount);
 	static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount);
 
 	// Provides natural sort order by ID

+ 0 - 4
node/Constants.hpp

@@ -233,10 +233,6 @@
 
 // Exceptions thrown in core ZT code
 #define ZT_EXCEPTION_OUT_OF_BOUNDS 100
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE 200
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW 201
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN 202
-#define ZT_EXCEPTION_INVALID_SERIALIZED_DATA_BAD_ENCODING 203
 
 /* Ethernet frame types that might be relevant to us */
 #define ZT_ETHERTYPE_IPV4 0x0800

+ 1 - 1
node/InetAddress.cpp

@@ -313,7 +313,7 @@ bool InetAddress::isNetwork() const
 	return false;
 }
 
-int InetAddress::marshal(uint8_t data[19]) const
+int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const
 {
 	unsigned int port;
 	switch(ss_family) {

+ 1 - 1
node/InetAddress.hpp

@@ -494,7 +494,7 @@ public:
 	explicit ZT_ALWAYS_INLINE operator bool() const { return (ss_family != 0); }
 
 	static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_INETADDRESS_MARSHAL_SIZE_MAX; }
-	int marshal(uint8_t data[19]) const;
+	int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const;
 	int unmarshal(const uint8_t *restrict data,const int len);
 
 	bool operator==(const InetAddress &a) const;

+ 69 - 40
node/NetworkConfig.cpp

@@ -43,7 +43,8 @@ NetworkConfig::NetworkConfig() :
 
 bool NetworkConfig::toDictionary(Dictionary &d,bool includeLegacy) const
 {
-	ScopedPtr< Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY> > tmp(new Buffer<ZT_NETWORKCONFIG_DICT_CAPACITY>());
+	uint8_t tmp[16384];
+	std::vector<uint8_t> buf;
 	char tmp2[128];
 
 	d.clear();
@@ -64,62 +65,90 @@ bool NetworkConfig::toDictionary(Dictionary &d,bool includeLegacy) const
 	// Then add binary blobs
 
 	if (this->com) {
-		tmp->clear();
-		this->com.serialize(*tmp);
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,*tmp)) return false;
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_COM,(const char *)tmp,this->com.marshal(tmp)))
+			return false;
 	}
 
-	tmp->clear();
-	for(unsigned int i=0;i<this->capabilityCount;++i)
-		this->capabilities[i].serialize(*tmp);
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,*tmp)) return false;
+	buf.clear();
+	for(unsigned int i=0;i<this->capabilityCount;++i) {
+		int l = this->capabilities[i].marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
+	}
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
-	tmp->clear();
-	for(unsigned int i=0;i<this->tagCount;++i)
-		this->tags[i].serialize(*tmp);
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,*tmp)) return false;
+	buf.clear();
+	for(unsigned int i=0;i<this->tagCount;++i) {
+		int l = this->tags[i].marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
+	}
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_TAGS,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
-	tmp->clear();
-	for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i)
-		this->certificatesOfOwnership[i].serialize(*tmp);
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,*tmp)) return false;
+	buf.clear();
+	for(unsigned int i=0;i<this->certificateOfOwnershipCount;++i) {
+		int l = this->certificatesOfOwnership[i].marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
+	}
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATES_OF_OWNERSHIP,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
-	tmp->clear();
-	for(unsigned int i=0;i<this->specialistCount;++i)
-		tmp->append((uint64_t)this->specialists[i]);
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,*tmp)) return false;
+	buf.clear();
+	for(unsigned int i=0;i<this->specialistCount;++i) {
+		Utils::storeBigEndian<uint64_t>(tmp,this->specialists[i]);
+		buf.insert(buf.end(),tmp,tmp + 8);
+	}
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_SPECIALISTS,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
-	tmp->clear();
+	buf.clear();
 	for(unsigned int i=0;i<this->routeCount;++i) {
-		reinterpret_cast<const InetAddress *>(&(this->routes[i].target))->serialize(*tmp);
-		reinterpret_cast<const InetAddress *>(&(this->routes[i].via))->serialize(*tmp);
-		tmp->append((uint16_t)this->routes[i].flags);
-		tmp->append((uint16_t)this->routes[i].metric);
+		int l = asInetAddress(this->routes[i].target).marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
+		l = asInetAddress(this->routes[i].via).marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
 	}
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,*tmp)) return false;
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_ROUTES,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
-	tmp->clear();
-	for(unsigned int i=0;i<this->staticIpCount;++i)
-		this->staticIps[i].serialize(*tmp);
-	if (tmp->size()) {
-		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,*tmp)) return false;
+	buf.clear();
+	for(unsigned int i=0;i<this->staticIpCount;++i) {
+		int l = this->staticIps[i].marshal(tmp);
+		if (l < 0)
+			return false;
+		buf.insert(buf.end(),tmp,tmp + l);
+	}
+	if (!buf.empty()) {
+		if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_STATIC_IPS,(const char *)buf.data(),(int)buf.size()))
+			return false;
 	}
 
 	if (this->ruleCount) {
-		tmp->clear();
-		Capability::serializeRules(*tmp,rules,ruleCount);
-		if (tmp->size()) {
-			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,*tmp)) return false;
+		buf.resize(ruleCount * ZT_VIRTUALNETWORKRULE_MARSHAL_SIZE_MAX);
+		int l = Capability::marshalVirtualNetworkRules(buf.data(),rules,ruleCount);
+		if (l > 0) {
+			if (!d.add(ZT_NETWORKCONFIG_DICT_KEY_RULES,(const char *)buf.data(),l))
+				return false;
 		}
 	}
 

+ 1 - 1
node/Protocol.cpp

@@ -27,7 +27,7 @@ namespace Protocol {
 
 namespace {
 
-const uint8_t ZEROES32[32] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+const uint64_t ZEROES32[4] = { 0,0,0,0 };
 
 /**
  * Deterministically mangle a 256-bit crypto key based on packet

+ 89 - 0
node/Revocation.cpp

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c)2013-2020 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2024-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+#include "Revocation.hpp"
+
+namespace ZeroTier {
+
+bool Revocation::sign(const Identity &signer)
+{
+	uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX+32];
+	if (signer.hasPrivate()) {
+		_signedBy = signer.address();
+		_signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature));
+		return true;
+	}
+	return false;
+}
+
+int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],bool forSign) const
+{
+	int p = 0;
+	if (forSign) {
+		for(int k=0;k<8;++k)
+			data[p++] = 0x7f;
+	}
+	Utils::storeBigEndian<uint32_t>(data + p,0); p += 4;
+	Utils::storeBigEndian<uint32_t>(data + p,_id); p += 4;
+	Utils::storeBigEndian<uint64_t>(data + p,_networkId); p += 8;
+	Utils::storeBigEndian<uint32_t>(data + p,0); p += 4;
+	Utils::storeBigEndian<uint32_t>(data + p,_credentialId); p += 4;
+	Utils::storeBigEndian<uint64_t>(data + p,(uint64_t)_threshold); p += 8;
+	Utils::storeBigEndian<uint64_t>(data + p,_flags); p += 8;
+	_target.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
+	_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
+	data[p++] = (uint8_t)_type;
+	if (!forSign) {
+		data[p++] = 1;
+		Utils::storeBigEndian<uint16_t>(data + p,(uint16_t)_signatureLength);
+		memcpy(data + p,_signature,_signatureLength);
+		p += (int)_signatureLength;
+	}
+	data[p++] = 0;
+	data[p++] = 0;
+	if (forSign) {
+		for(int k=0;k<8;++k)
+			data[p++] = 0x7f;
+	}
+	return p;
+}
+
+int Revocation::unmarshal(const uint8_t *restrict data,const int len)
+{
+	if (len < 54)
+		return -1;
+	// 4 bytes reserved
+	_id = Utils::loadBigEndian<uint32_t>(data + 4);
+	_networkId = Utils::loadBigEndian<uint64_t>(data + 8);
+	// 4 bytes reserved
+	_credentialId = Utils::loadBigEndian<uint32_t>(data + 20);
+	_threshold = (int64_t)Utils::loadBigEndian<uint64_t>(data + 24);
+	_flags = Utils::loadBigEndian<uint64_t>(data + 32);
+	_target.setTo(data + 40);
+	_signedBy.setTo(data + 45);
+	_type = (ZT_CredentialType)data[50];
+	// 1 byte reserved
+	_signatureLength = Utils::loadBigEndian<uint16_t>(data + 52);
+	int p = 54 + (int)_signatureLength;
+	if ((_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)||(p > len))
+		return -1;
+	memcpy(_signature,data + 54,_signatureLength);
+	if ((p + 2) > len)
+		return -1;
+	p += 2 + Utils::loadBigEndian<uint16_t>(data + p);
+	if (p > len)
+		return -1;
+	return p;
+}
+
+} // namespace ZeroTier

+ 6 - 72
node/Revocation.hpp

@@ -31,6 +31,8 @@
  */
 #define ZT_REVOCATION_FLAG_FAST_PROPAGATE 0x1ULL
 
+#define ZT_REVOCATION_MARSHAL_SIZE_MAX (4 + 4 + 8 + 4 + 4 + 8 + 8 + 5 + 5 + 1 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
+
 namespace ZeroTier {
 
 class RuntimeEnvironment;
@@ -95,17 +97,7 @@ public:
 	 * @param signer Signing identity, must have private key
 	 * @return True if signature was successful
 	 */
-	ZT_ALWAYS_INLINE bool sign(const Identity &signer)
-	{
-		if (signer.hasPrivate()) {
-			Buffer<sizeof(Revocation) + 64> tmp;
-			_signedBy = signer.address();
-			this->serialize(tmp,true);
-			_signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
-			return true;
-		}
-		return false;
-	}
+	bool sign(const Identity &signer);
 
 	/**
 	 * Verify this revocation's signature
@@ -115,67 +107,9 @@ public:
 	 */
 	ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
-	{
-		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
-
-		b.append((uint32_t)0); // 4 unused bytes, currently set to 0
-		b.append(_id);
-		b.append(_networkId);
-		b.append((uint32_t)0); // 4 unused bytes, currently set to 0
-		b.append(_credentialId);
-		b.append(_threshold);
-		b.append(_flags);
-		_target.appendTo(b);
-		_signedBy.appendTo(b);
-		b.append((uint8_t)_type);
-
-		if (!forSign) {
-			b.append((uint8_t)1);
-			b.append((uint16_t)_signatureLength);
-			b.append(_signature,_signatureLength);
-		}
-
-		// This is the size of any additional fields, currently 0.
-		b.append((uint16_t)0);
-
-		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
-	}
-
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
-	{
-		*this = Revocation();
-
-		unsigned int p = startAt;
-
-		p += 4; // 4 bytes, currently unused
-		_id = b.template at<uint32_t>(p); p += 4;
-		_networkId = b.template at<uint64_t>(p); p += 8;
-		p += 4; // 4 bytes, currently unused
-		_credentialId = b.template at<uint32_t>(p); p += 4;
-		_threshold = b.template at<uint64_t>(p); p += 8;
-		_flags = b.template at<uint64_t>(p); p += 8;
-		_target.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
-		_type = (ZT_CredentialType)b[p++];
-
-		if (b[p++] == 1) {
-			_signatureLength = b.template at<uint16_t>(p);
-			if (_signatureLength > sizeof(_signature))
-				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
-			memcpy(_signature,b.field(p,_signatureLength),_signatureLength);
-		} else {
-			p += 2 + b.template at<uint16_t>(p);
-		}
-
-		p += 2 + b.template at<uint16_t>(p);
-		if (p > b.size())
-			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
-
-		return (p - startAt);
-	}
+	static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_REVOCATION_MARSHAL_SIZE_MAX; }
+	int marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],bool forSign = false) const;
+	int unmarshal(const uint8_t *restrict data,const int len);
 
 private:
 	uint32_t _id;

+ 81 - 0
node/Tag.cpp

@@ -0,0 +1,81 @@
+/*
+ * Copyright (c)2013-2020 ZeroTier, Inc.
+ *
+ * Use of this software is governed by the Business Source License included
+ * in the LICENSE.TXT file in the project's root directory.
+ *
+ * Change Date: 2024-01-01
+ *
+ * On the date above, in accordance with the Business Source License, use
+ * of this software will be governed by version 2.0 of the Apache License.
+ */
+/****/
+
+#include "Tag.hpp"
+
+namespace ZeroTier {
+
+bool Tag::sign(const Identity &signer)
+{
+	uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX];
+	if (signer.hasPrivate()) {
+		_signedBy = signer.address();
+		_signatureLength = signer.sign(buf,(unsigned int)marshal(buf,true),_signature,sizeof(_signature));
+		return true;
+	}
+	return false;
+}
+
+int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX],bool forSign) const
+{
+	int p = 0;
+	if (forSign) {
+		for(int k=0;k<8;++k)
+			data[p++] = 0x7f;
+	}
+	Utils::storeBigEndian<uint64_t>(data + p,_networkId); p += 8;
+	Utils::storeBigEndian<uint64_t>(data + p,(uint64_t)_ts); p += 8;
+	Utils::storeBigEndian<uint32_t>(data + p,_id); p += 4;
+	Utils::storeBigEndian<uint32_t>(data + p,_value); p += 4;
+	_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
+	_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH;
+	if (!forSign) {
+		data[p++] = 1;
+		Utils::storeBigEndian<uint16_t>(data + p,(uint16_t)_signatureLength); p += 2;
+		memcpy(data + p,_signature,_signatureLength);
+		p += (int)_signatureLength;
+	}
+	data[p++] = 0;
+	data[p++] = 0;
+	if (forSign) {
+		for(int k=0;k<8;++k)
+			data[p++] = 0x7f;
+	}
+	return p;
+}
+
+int Tag::unmarshal(const uint8_t *data,int len)
+{
+	if (len < 37)
+		return -1;
+	_networkId = Utils::loadBigEndian<uint64_t>(data);
+	_ts = (int64_t)Utils::loadBigEndian<uint64_t>(data + 8);
+	_id = Utils::loadBigEndian<uint32_t>(data + 16);
+	_value = Utils::loadBigEndian<uint32_t>(data + 20);
+	_issuedTo.setTo(data + 24);
+	_signedBy.setTo(data + 29);
+	// 1 byte reserved
+	_signatureLength = Utils::loadBigEndian<uint16_t>(data + 35);
+	int p = 37 + (int)_signatureLength;
+	if ((_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)||(p > len))
+		return -1;
+	memcpy(_signature,data + p,_signatureLength);
+	if ((p + 2) > len)
+		return -1;
+	p += 2 + Utils::loadBigEndian<uint16_t>(data + p);
+	if (p > len)
+		return -1;
+	return p;
+}
+
+} // namespace ZeroTier

+ 6 - 65
node/Tag.hpp

@@ -25,6 +25,8 @@
 #include "Address.hpp"
 #include "Identity.hpp"
 
+#define ZT_TAG_MARSHAL_SIZE_MAX (8 + 8 + 4 + 4 + 5 + 5 + 1 + 2 + ZT_SIGNATURE_BUFFER_SIZE + 2)
+
 namespace ZeroTier {
 
 class RuntimeEnvironment;
@@ -95,17 +97,7 @@ public:
 	 * @param signer Signing identity, must have private key
 	 * @return True if signature was successful
 	 */
-	inline bool sign(const Identity &signer)
-	{
-		if (signer.hasPrivate()) {
-			Buffer<sizeof(Tag) + 64> tmp;
-			_signedBy = signer.address();
-			this->serialize(tmp,true);
-			_signatureLength = signer.sign(tmp.data(),tmp.size(),_signature,sizeof(_signature));
-			return true;
-		}
-		return false;
-	}
+	bool sign(const Identity &signer);
 
 	/**
 	 * Check this tag's signature
@@ -115,60 +107,9 @@ public:
 	 */
 	ZT_ALWAYS_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return _verify(RR,tPtr,*this); }
 
-	template<unsigned int C>
-	inline void serialize(Buffer<C> &b,const bool forSign = false) const
-	{
-		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
-
-		b.append(_networkId);
-		b.append(_ts);
-		b.append(_id);
-		b.append(_value);
-
-		_issuedTo.appendTo(b);
-		_signedBy.appendTo(b);
-		if (!forSign) {
-			b.append((uint8_t)1);
-			b.append((uint16_t)_signatureLength);
-			b.append(_signature,_signatureLength);
-		}
-
-		b.append((uint16_t)0); // length of additional fields, currently 0
-
-		if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
-	}
-
-	template<unsigned int C>
-	inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
-	{
-		unsigned int p = startAt;
-
-		*this = Tag();
-
-		_networkId = b.template at<uint64_t>(p); p += 8;
-		_ts = b.template at<uint64_t>(p); p += 8;
-		_id = b.template at<uint32_t>(p); p += 4;
-
-		_value = b.template at<uint32_t>(p); p += 4;
-
-		_issuedTo.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
-		_signedBy.setTo(b.field(p,ZT_ADDRESS_LENGTH),ZT_ADDRESS_LENGTH); p += ZT_ADDRESS_LENGTH;
-		if (b[p++] == 1) {
-			_signatureLength = b.template at<uint16_t>(p);
-			if (_signatureLength > sizeof(_signature))
-				throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_CRYPTOGRAPHIC_TOKEN;
-			p += 2;
-			memcpy(_signature,b.field(p,_signatureLength),_signatureLength); p += _signatureLength;
-		} else {
-			p += 2 + b.template at<uint16_t>(p);
-		}
-
-		p += 2 + b.template at<uint16_t>(p);
-		if (p > b.size())
-			throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
-
-		return (p - startAt);
-	}
+	static ZT_ALWAYS_INLINE int marshalSizeMax() { return ZT_TAG_MARSHAL_SIZE_MAX; }
+	int marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX],bool forSign = false) const;
+	int unmarshal(const uint8_t *data,int len);
 
 	// Provides natural sort order by ID
 	ZT_ALWAYS_INLINE bool operator<(const Tag &t) const { return (_id < t._id); }

+ 5 - 5
node/Utils.hpp

@@ -212,14 +212,14 @@ static ZT_ALWAYS_INLINE unsigned long hexStrToULong(const char *s) { return strt
 static ZT_ALWAYS_INLINE long hexStrToLong(const char *s) { return strtol(s,(char **)0,16); }
 #endif
 
-static ZT_ALWAYS_INLINE unsigned int strToUInt(const char *s) { return (unsigned int)strtoul(s,(char **)0,10); }
+static ZT_ALWAYS_INLINE unsigned int strToUInt(const char *s) { return (unsigned int)strtoul(s,nullptr,10); }
 
 static ZT_ALWAYS_INLINE unsigned long long strToU64(const char *s)
 {
 #ifdef __WINDOWS__
 	return (unsigned long long)_strtoui64(s,(char **)0,10);
 #else
-	return strtoull(s,(char **)0,10);
+	return strtoull(s,nullptr,10);
 #endif
 }
 
@@ -228,16 +228,16 @@ static ZT_ALWAYS_INLINE long long hexStrTo64(const char *s)
 #ifdef __WINDOWS__
 	return (long long)_strtoi64(s,(char **)0,16);
 #else
-	return strtoll(s,(char **)0,16);
+	return strtoll(s,nullptr,16);
 #endif
 }
 
 static ZT_ALWAYS_INLINE unsigned long long hexStrToU64(const char *s)
 {
 #ifdef __WINDOWS__
-	return (unsigned long long)_strtoui64(s,(char **)0,16);
+	return (unsigned long long)_strtoui64(s,nullptr,16);
 #else
-	return strtoull(s,(char **)0,16);
+	return strtoull(s,nullptr,16);
 #endif
 }