Browse Source

A bunch more build fixes.

Adam Ierymenko 5 years ago
parent
commit
55b0555aa0
14 changed files with 207 additions and 191 deletions
  1. 6 24
      CMakeLists.txt
  2. 1 1
      node/Buf.hpp
  3. 1 1
      node/C25519.cpp
  4. 4 2
      node/CMakeLists.txt
  5. 2 7
      node/Credential.cpp
  6. 0 1
      node/Membership.cpp
  7. 0 3
      node/Membership.hpp
  8. 87 54
      node/Node.cpp
  9. 6 5
      node/Node.hpp
  10. 11 0
      node/Tests.cpp
  11. 0 2
      node/Tests.h
  12. 2 3
      node/Topology.cpp
  13. 1 2
      node/Topology.hpp
  14. 86 86
      node/Utils.hpp

+ 6 - 24
CMakeLists.txt

@@ -7,13 +7,16 @@ else()
 	cmake_policy(VERSION 3.15)
 	cmake_policy(VERSION 3.15)
 endif()
 endif()
 
 
+set(CMAKE_CXX_STANDARD 11)
+set(default_build_type "Release")
+
 if(WIN32)
 if(WIN32)
 	set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
 	set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
 endif(WIN32)
 endif(WIN32)
 set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
 set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
 
 
-set(ZEROTIER_ONE_VERSION_MAJOR 2 CACHE INTERNAL "")
-set(ZEROTIER_ONE_VERSION_MINOR 0 CACHE INTERNAL "")
+set(ZEROTIER_ONE_VERSION_MAJOR 1 CACHE INTERNAL "")
+set(ZEROTIER_ONE_VERSION_MINOR 9 CACHE INTERNAL "")
 set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "")
 set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "")
 set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "")
 set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "")
 
 
@@ -22,11 +25,6 @@ configure_file(
 	${CMAKE_BINARY_DIR}/version.h
 	${CMAKE_BINARY_DIR}/version.h
 )
 )
 
 
-set(default_build_type "Release")
-#if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
-#	set(default_build_type "Debug")
-#endif()
-
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
 if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
 	message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
 	message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
 	set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
 	set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
@@ -54,7 +52,6 @@ if(WIN32)
 	add_definitions(-DNOMINMAX)
 	add_definitions(-DNOMINMAX)
 else(WIN32)
 else(WIN32)
 	if(APPLE)
 	if(APPLE)
-
 		message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
 		message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
 		add_compile_options(
 		add_compile_options(
 			-Wall
 			-Wall
@@ -74,9 +71,7 @@ else(WIN32)
 			-mmacosx-version-min=10.9
 			-mmacosx-version-min=10.9
 			$<$<CONFIG:RELEASE>:-flto>
 			$<$<CONFIG:RELEASE>:-flto>
 		)
 		)
-
 	else(APPLE)
 	else(APPLE)
-
 		message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
 		message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
 		add_compile_options(
 		add_compile_options(
 			-Wall
 			-Wall
@@ -90,7 +85,6 @@ else(WIN32)
 			$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
 			$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
 			$<$<CONFIG:RELWITHDEBINFO>:-g>
 			$<$<CONFIG:RELWITHDEBINFO>:-g>
 		)
 		)
-
 	endif(APPLE)
 	endif(APPLE)
 endif(WIN32)
 endif(WIN32)
 
 
@@ -103,19 +97,7 @@ if (
 	CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
 	CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
 )
 )
 	message("++ Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
 	message("++ Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
-	add_compile_options(
-		-maes
-		-mrdrnd
-		-mpclmul
-		-msse
-		-msse2
-		-msse3
-		-msse4.1
-	)
-endif()
-
-if(ZT_TRACE)
-	add_definitions(-DZT_TRACE)
+	add_compile_options(-maes -mrdrnd -mpclmul -msse -msse2)
 endif()
 endif()
 
 
 add_subdirectory(node)
 add_subdirectory(node)

+ 1 - 1
node/Buf.hpp

@@ -404,7 +404,7 @@ public:
 	 */
 	 */
 	ZT_ALWAYS_INLINE const uint8_t *rBnc(int &ii,unsigned int len) const noexcept
 	ZT_ALWAYS_INLINE const uint8_t *rBnc(int &ii,unsigned int len) const noexcept
 	{
 	{
-		const uint8_t *const b = b + ii;
+		const uint8_t *const b = unsafeData + ii;
 		return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
 		return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
 	}
 	}
 
 

+ 1 - 1
node/C25519.cpp

@@ -1054,7 +1054,7 @@ ZT_ALWAYS_INLINE crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inp
 	return x;
 	return x;
 }
 }
 
 
-oid reduce_add_sub(sc25519 *r)
+void reduce_add_sub(sc25519 *r)
 {
 {
 	crypto_uint32 pb = 0;
 	crypto_uint32 pb = 0;
 	crypto_uint32 b;
 	crypto_uint32 b;

+ 4 - 2
node/CMakeLists.txt

@@ -41,7 +41,6 @@ set(core_headers
 	SHA512.hpp
 	SHA512.hpp
 	SharedPtr.hpp
 	SharedPtr.hpp
 	Tag.hpp
 	Tag.hpp
-	Tests.h
 	Topology.hpp
 	Topology.hpp
 	Trace.hpp
 	Trace.hpp
 	TriviallyCopyable.hpp
 	TriviallyCopyable.hpp
@@ -78,7 +77,6 @@ set(core_src
 	SelfAwareness.cpp
 	SelfAwareness.cpp
 	SHA512.cpp
 	SHA512.cpp
 	Tag.cpp
 	Tag.cpp
-	Tests.cpp
 	Topology.cpp
 	Topology.cpp
 	Trace.cpp
 	Trace.cpp
 	Utils.cpp
 	Utils.cpp
@@ -89,3 +87,7 @@ set(core_src
 add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
 add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
 target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
 target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
 target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
 target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
+
+add_executable(zt_core_tests Tests.h Tests.cpp)
+target_compile_definitions(zt_core_tests PRIVATE ZT_ENABLE_TESTS=1 ZT_STANDALONE_TESTS=1)
+target_link_libraries(zt_core_tests zt_core)

+ 2 - 7
node/Credential.cpp

@@ -53,10 +53,8 @@ static ZT_ALWAYS_INLINE Credential::VerifyResult _credVerify(const RuntimeEnviro
 		return Credential::VERIFY_BAD_SIGNATURE;
 		return Credential::VERIFY_BAD_SIGNATURE;
 
 
 	const SharedPtr<Peer> peer(RR->topology->peer(tPtr,signedBy));
 	const SharedPtr<Peer> peer(RR->topology->peer(tPtr,signedBy));
-	if (!peer) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),signedBy);
+	if (!peer)
 		return Credential::VERIFY_NEED_IDENTITY;
 		return Credential::VERIFY_NEED_IDENTITY;
-	}
 
 
 	try {
 	try {
 		int l = credential.marshal(tmp,true);
 		int l = credential.marshal(tmp,true);
@@ -78,10 +76,8 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,
 		return Credential::VERIFY_BAD_SIGNATURE;
 		return Credential::VERIFY_BAD_SIGNATURE;
 
 
 	const SharedPtr<Peer> peer(RR->topology->peer(tPtr,credential._signedBy));
 	const SharedPtr<Peer> peer(RR->topology->peer(tPtr,credential._signedBy));
-	if (!peer) {
-		RR->sw->requestWhois(tPtr,RR->node->now(),credential._signedBy);
+	if (!peer)
 		return Credential::VERIFY_NEED_IDENTITY;
 		return Credential::VERIFY_NEED_IDENTITY;
-	}
 
 
 	uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
 	uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
 	unsigned int ptr = 0;
 	unsigned int ptr = 0;
@@ -123,7 +119,6 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *RR,void *
 				if (!peer->identity().verify(tmp,(unsigned int)l,credential._custody[c].signature,credential._custody[c].signatureLength))
 				if (!peer->identity().verify(tmp,(unsigned int)l,credential._custody[c].signature,credential._custody[c].signatureLength))
 					return Credential::VERIFY_BAD_SIGNATURE;
 					return Credential::VERIFY_BAD_SIGNATURE;
 			} else {
 			} else {
-				RR->sw->requestWhois(tPtr,RR->node->now(),credential._custody[c].from);
 				return Credential::VERIFY_NEED_IDENTITY;
 				return Credential::VERIFY_NEED_IDENTITY;
 			}
 			}
 		}
 		}

+ 0 - 1
node/Membership.cpp

@@ -22,7 +22,6 @@
 namespace ZeroTier {
 namespace ZeroTier {
 
 
 Membership::Membership() :
 Membership::Membership() :
-	_lastUpdatedMulticast(0),
 	_comRevocationThreshold(0),
 	_comRevocationThreshold(0),
 	_lastPushedCredentials(0),
 	_lastPushedCredentials(0),
 	_revocations(4),
 	_revocations(4),

+ 0 - 3
node/Membership.hpp

@@ -167,9 +167,6 @@ private:
 		}
 		}
 	}
 	}
 
 
-	// Last time we pushed MULTICAST_LIKE(s)
-	int64_t _lastUpdatedMulticast;
-
 	// Revocation threshold for COM or 0 if none
 	// Revocation threshold for COM or 0 if none
 	int64_t _comRevocationThreshold;
 	int64_t _comRevocationThreshold;
 
 

+ 87 - 54
node/Node.cpp

@@ -28,16 +28,54 @@
 #include "ScopedPtr.hpp"
 #include "ScopedPtr.hpp"
 #include "Locator.hpp"
 #include "Locator.hpp"
 #include "Protocol.hpp"
 #include "Protocol.hpp"
+#include "Expect.hpp"
+#include "VL1.hpp"
+#include "VL2.hpp"
 
 
 namespace ZeroTier {
 namespace ZeroTier {
 
 
+namespace {
+
+struct _NodeObjects
+{
+	ZT_ALWAYS_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) :
+		t(RR),
+		expect(),
+		vl2(RR),
+		vl1(RR),
+		sa(RR),
+		topology(RR,tPtr)
+	{
+		RR->t = &t;
+		RR->expect = &expect;
+		RR->vl2 = &vl2;
+		RR->vl1 = &vl1;
+		RR->sa = &sa;
+		RR->topology = &topology;
+	}
+	Trace t;
+	Expect expect;
+	VL2 vl2;
+	VL1 vl1;
+	SelfAwareness sa;
+	Topology topology;
+};
+
+struct _sortPeerPtrsByAddress
+{
+	ZT_ALWAYS_INLINE bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b) const { return (a->address() < b->address()); }
+};
+
+} // anonymous namespace
+
 Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
 Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
 	_RR(this),
 	_RR(this),
+	_objects(nullptr),
 	RR(&_RR),
 	RR(&_RR),
 	_cb(*callbacks),
 	_cb(*callbacks),
 	_uPtr(uPtr),
 	_uPtr(uPtr),
 	_networks(),
 	_networks(),
-	_networksMask(63),
+	_networksMask(15),
 	_now(now),
 	_now(now),
 	_lastPing(0),
 	_lastPing(0),
 	_lastHousekeepingRun(0),
 	_lastHousekeepingRun(0),
@@ -46,7 +84,7 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
 	_natMustDie(true),
 	_natMustDie(true),
 	_online(false)
 	_online(false)
 {
 {
-	_networks.resize(64); // _networksMask + 1, must be power of two
+	_networks.resize(16); // _networksMask + 1, must be power of two
 
 
 	uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
 	uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
 	std::vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
 	std::vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
@@ -74,30 +112,9 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
 			stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
 			stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
 	}
 	}
 
 
-#if 0
-	char *m = nullptr;
-	try {
-		m = reinterpret_cast<char *>(malloc(16 + sizeof(Trace) + sizeof(Switch) + sizeof(Topology) + sizeof(SelfAwareness)));
-		if (!m)
-			throw std::bad_alloc();
-		RR->rtmem = m;
-		while (((uintptr_t)m & 0xfU) != 0) ++m;
-		RR->t = new (m) Trace(RR);
-		m += sizeof(Trace);
-		RR->sw = new (m) Switch(RR);
-		m += sizeof(Switch);
-		RR->topology = new (m) Topology(RR,RR->identity,tPtr);
-		m += sizeof(Topology);
-		RR->sa = new (m) SelfAwareness(RR);
-	} catch ( ... ) {
-		if (RR->sa) RR->sa->~SelfAwareness();
-		if (RR->topology) RR->topology->~Topology();
-		if (RR->sw) RR->sw->~Switch();
-		if (RR->t) RR->t->~Trace();
-		if (m) ::free(m);
-		throw;
-	}
-#endif
+	// This constructs all the components of the ZeroTier core within a single contiguous memory container,
+	// which reduces memory fragmentation and may improve cache locality.
+	_objects = new _NodeObjects(RR,tPtr);
 
 
 	postEvent(tPtr, ZT_EVENT_UP);
 	postEvent(tPtr, ZT_EVENT_UP);
 }
 }
@@ -112,13 +129,12 @@ Node::~Node()
 		networks.swap(_networks);
 		networks.swap(_networks);
 	}
 	}
 	networks.clear();
 	networks.clear();
+
 	_networks_m.lock();
 	_networks_m.lock();
 	_networks_m.unlock();
 	_networks_m.unlock();
 
 
-	if (RR->sa) RR->sa->~SelfAwareness();
-	if (RR->topology) RR->topology->~Topology();
-	if (RR->t) RR->t->~Trace();
-	free(RR->rtmem);
+	if (_objects)
+		delete (_NodeObjects *)_objects;
 
 
 	// Let go of cached Buf objects. If other nodes happen to be running in this
 	// Let go of cached Buf objects. If other nodes happen to be running in this
 	// same process space new Bufs will be allocated as needed, but this is almost
 	// same process space new Bufs will be allocated as needed, but this is almost
@@ -129,11 +145,12 @@ Node::~Node()
 
 
 void Node::shutdown(void *tPtr)
 void Node::shutdown(void *tPtr)
 {
 {
-	RR->topology->saveAll(tPtr);
+	if (RR->topology)
+		RR->topology->saveAll(tPtr);
 }
 }
 
 
 ZT_ResultCode Node::processWirePacket(
 ZT_ResultCode Node::processWirePacket(
-	void *tptr,
+	void *tPtr,
 	int64_t now,
 	int64_t now,
 	int64_t localSocket,
 	int64_t localSocket,
 	const struct sockaddr_storage *remoteAddress,
 	const struct sockaddr_storage *remoteAddress,
@@ -142,12 +159,16 @@ ZT_ResultCode Node::processWirePacket(
 	volatile int64_t *nextBackgroundTaskDeadline)
 	volatile int64_t *nextBackgroundTaskDeadline)
 {
 {
 	_now = now;
 	_now = now;
-	//RR->sw->onRemotePacket(tptr,localSocket,*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
+	// TODO: add buffer life cycle methods
+	SharedPtr<Buf> tmp(new Buf());
+	packetLength &= ZT_BUF_MEM_MASK;
+	memcpy(tmp->unsafeData,packetData,packetLength);
+	RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),tmp,packetLength);
 	return ZT_RESULT_OK;
 	return ZT_RESULT_OK;
 }
 }
 
 
 ZT_ResultCode Node::processVirtualNetworkFrame(
 ZT_ResultCode Node::processVirtualNetworkFrame(
-	void *tptr,
+	void *tPtr,
 	int64_t now,
 	int64_t now,
 	uint64_t nwid,
 	uint64_t nwid,
 	uint64_t sourceMac,
 	uint64_t sourceMac,
@@ -389,11 +410,11 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
 	return ZT_RESULT_OK;
 	return ZT_RESULT_OK;
 }
 }
 
 
-ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
+ZT_ResultCode Node::multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
 {
 {
 	SharedPtr<Network> nw(this->network(nwid));
 	SharedPtr<Network> nw(this->network(nwid));
 	if (nw) {
 	if (nw) {
-		nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
+		nw->multicastSubscribe(tPtr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
 		return ZT_RESULT_OK;
 		return ZT_RESULT_OK;
 	} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
 	} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
 }
 }
@@ -407,18 +428,18 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
 	} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
 	} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
 }
 }
 
 
-ZT_ResultCode Node::addRoot(void *tptr,const ZT_Identity *identity,const sockaddr_storage *bootstrap)
+ZT_ResultCode Node::addRoot(void *tPtr,const ZT_Identity *identity,const sockaddr_storage *bootstrap)
 {
 {
 	if (!identity)
 	if (!identity)
 		return ZT_RESULT_ERROR_BAD_PARAMETER;
 		return ZT_RESULT_ERROR_BAD_PARAMETER;
 	InetAddress a;
 	InetAddress a;
 	if (bootstrap)
 	if (bootstrap)
 		a = bootstrap;
 		a = bootstrap;
-	RR->topology->addRoot(tptr,*reinterpret_cast<const Identity *>(identity),a);
+	RR->topology->addRoot(tPtr,*reinterpret_cast<const Identity *>(identity),a);
 	return ZT_RESULT_OK;
 	return ZT_RESULT_OK;
 }
 }
 
 
-ZT_ResultCode Node::removeRoot(void *tptr,const ZT_Identity *identity)
+ZT_ResultCode Node::removeRoot(void *tPtr,const ZT_Identity *identity)
 {
 {
 	if (!identity)
 	if (!identity)
 		return ZT_RESULT_ERROR_BAD_PARAMETER;
 		return ZT_RESULT_ERROR_BAD_PARAMETER;
@@ -440,8 +461,6 @@ void Node::status(ZT_NodeStatus *status) const
 	status->online = _online ? 1 : 0;
 	status->online = _online ? 1 : 0;
 }
 }
 
 
-struct _sortPeerPtrsByAddress { inline bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b) const { return (a->address() < b->address()); } };
-
 ZT_PeerList *Node::peers() const
 ZT_PeerList *Node::peers() const
 {
 {
 	std::vector< SharedPtr<Peer> > peers;
 	std::vector< SharedPtr<Peer> > peers;
@@ -463,7 +482,7 @@ ZT_PeerList *Node::peers() const
 		p->address = (*pi)->address().toInt();
 		p->address = (*pi)->address().toInt();
 		identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
 		identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
 		p->identity = &identities[pl->peerCount];
 		p->identity = &identities[pl->peerCount];
-		memcpy(p->identityHash,(*pi)->identity().hash(),sizeof(p->identityHash));
+		memcpy(p->identityHash,(*pi)->identity().hash().data(),ZT_IDENTITY_HASH_SIZE);
 		if ((*pi)->remoteVersionKnown()) {
 		if ((*pi)->remoteVersionKnown()) {
 			p->versionMajor = (int)(*pi)->remoteVersionMajor();
 			p->versionMajor = (int)(*pi)->remoteVersionMajor();
 			p->versionMinor = (int)(*pi)->remoteVersionMinor();
 			p->versionMinor = (int)(*pi)->remoteVersionMinor();
@@ -568,11 +587,14 @@ int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *d
 {
 {
 	try {
 	try {
 		if (RR->identity.address().toInt() != dest) {
 		if (RR->identity.address().toInt() != dest) {
+			// TODO
+			/*
 			Packet outp(Address(dest),RR->identity.address(),Packet::VERB_USER_MESSAGE);
 			Packet outp(Address(dest),RR->identity.address(),Packet::VERB_USER_MESSAGE);
 			outp.append(typeId);
 			outp.append(typeId);
 			outp.append(data,len);
 			outp.append(data,len);
 			outp.compress();
 			outp.compress();
 			RR->sw->send(tptr,outp,true);
 			RR->sw->send(tptr,outp,true);
+			*/
 			return 1;
 			return 1;
 		}
 		}
 	} catch ( ... ) {}
 	} catch ( ... ) {}
@@ -586,9 +608,7 @@ void Node::setController(void *networkControllerInstance)
 		RR->localNetworkController->init(RR->identity,this);
 		RR->localNetworkController->init(RR->identity,this);
 }
 }
 
 
-/****************************************************************************/
-/* Node methods used only within node/                                      */
-/****************************************************************************/
+// Methods used only within the core ----------------------------------------------------------------------------------
 
 
 std::vector<uint8_t> Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2])
 std::vector<uint8_t> Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2])
 {
 {
@@ -671,6 +691,8 @@ bool Node::localControllerHasAuthorized(const int64_t now,const uint64_t nwid,co
 	return false;
 	return false;
 }
 }
 
 
+// Implementation of NetworkController::Sender ------------------------------------------------------------------------
+
 void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
 void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
 {
 {
 	_localControllerAuthorizations_m.lock();
 	_localControllerAuthorizations_m.lock();
@@ -682,12 +704,15 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
 		if (!n) return;
 		if (!n) return;
 		n->setConfiguration((void *)0,nc,true);
 		n->setConfiguration((void *)0,nc,true);
 	} else {
 	} else {
-		ScopedPtr< Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> > dconf(new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>());
-		if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
+		Dictionary dconf;
+		if (nc.toDictionary(dconf,sendLegacyFormatConfig)) {
 			uint64_t configUpdateId = Utils::random();
 			uint64_t configUpdateId = Utils::random();
 			if (!configUpdateId) ++configUpdateId;
 			if (!configUpdateId) ++configUpdateId;
 
 
-			const unsigned int totalSize = dconf->sizeBytes();
+			std::vector<uint8_t> ddata;
+			dconf.encode(ddata);
+			// TODO
+			/*
 			unsigned int chunkIndex = 0;
 			unsigned int chunkIndex = 0;
 			while (chunkIndex < totalSize) {
 			while (chunkIndex < totalSize) {
 				const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
 				const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
@@ -717,6 +742,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
 				RR->sw->send((void *)0,outp,true);
 				RR->sw->send((void *)0,outp,true);
 				chunkIndex += chunkLen;
 				chunkIndex += chunkLen;
 			}
 			}
+			*/
 		}
 		}
 	}
 	}
 }
 }
@@ -728,6 +754,8 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
 		if (!n) return;
 		if (!n) return;
 		n->addCredential((void *)0,RR->identity,rev);
 		n->addCredential((void *)0,RR->identity,rev);
 	} else {
 	} else {
+		// TODO
+		/*
 		Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
 		Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
 		outp.append((uint8_t)0x00);
 		outp.append((uint8_t)0x00);
 		outp.append((uint16_t)0);
 		outp.append((uint16_t)0);
@@ -736,6 +764,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
 		rev.serialize(outp);
 		rev.serialize(outp);
 		outp.append((uint16_t)0);
 		outp.append((uint16_t)0);
 		RR->sw->send((void *)0,outp,true);
 		RR->sw->send((void *)0,outp,true);
+		*/
 	}
 	}
 }
 }
 
 
@@ -756,6 +785,8 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
 			default: break;
 			default: break;
 		}
 		}
 	} else if (requestPacketId) {
 	} else if (requestPacketId) {
+		// TODO
+		/*
 		Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
 		Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
 		outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
 		outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
 		outp.append(requestPacketId);
 		outp.append(requestPacketId);
@@ -771,14 +802,13 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
 		}
 		}
 		outp.append(nwid);
 		outp.append(nwid);
 		RR->sw->send((void *)0,outp,true);
 		RR->sw->send((void *)0,outp,true);
+		*/
 	} // else we can't send an ERROR() in response to nothing, so discard
 	} // else we can't send an ERROR() in response to nothing, so discard
 }
 }
 
 
 } // namespace ZeroTier
 } // namespace ZeroTier
 
 
-/****************************************************************************/
-/* CAPI bindings                                                            */
-/****************************************************************************/
+// C API exports
 
 
 extern "C" {
 extern "C" {
 
 
@@ -1015,9 +1045,12 @@ enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const stru
 
 
 void ZT_version(int *major,int *minor,int *revision)
 void ZT_version(int *major,int *minor,int *revision)
 {
 {
-	if (major) *major = ZEROTIER_ONE_VERSION_MAJOR;
-	if (minor) *minor = ZEROTIER_ONE_VERSION_MINOR;
-	if (revision) *revision = ZEROTIER_ONE_VERSION_REVISION;
+	if (major)
+		*major = ZEROTIER_ONE_VERSION_MAJOR;
+	if (minor)
+		*minor = ZEROTIER_ONE_VERSION_MINOR;
+	if (revision)
+		*revision = ZEROTIER_ONE_VERSION_REVISION;
 }
 }
 
 
 } // extern "C"
 } // extern "C"

+ 6 - 5
node/Node.hpp

@@ -68,7 +68,7 @@ public:
 	// Public API Functions ---------------------------------------------------------------------------------------------
 	// Public API Functions ---------------------------------------------------------------------------------------------
 
 
 	ZT_ResultCode processWirePacket(
 	ZT_ResultCode processWirePacket(
-		void *tptr,
+		void *tPtr,
 		int64_t now,
 		int64_t now,
 		int64_t localSocket,
 		int64_t localSocket,
 		const struct sockaddr_storage *remoteAddress,
 		const struct sockaddr_storage *remoteAddress,
@@ -76,7 +76,7 @@ public:
 		unsigned int packetLength,
 		unsigned int packetLength,
 		volatile int64_t *nextBackgroundTaskDeadline);
 		volatile int64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode processVirtualNetworkFrame(
 	ZT_ResultCode processVirtualNetworkFrame(
-		void *tptr,
+		void *tPtr,
 		int64_t now,
 		int64_t now,
 		uint64_t nwid,
 		uint64_t nwid,
 		uint64_t sourceMac,
 		uint64_t sourceMac,
@@ -89,10 +89,10 @@ public:
 	ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);
 	ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
 	ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
 	ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
 	ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
-	ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
+	ZT_ResultCode multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
 	ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
 	ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
-	ZT_ResultCode addRoot(void *tptr,const ZT_Identity *identity,const sockaddr_storage *bootstrap);
-	ZT_ResultCode removeRoot(void *tptr,const ZT_Identity *identity);
+	ZT_ResultCode addRoot(void *tPtr,const ZT_Identity *identity,const sockaddr_storage *bootstrap);
+	ZT_ResultCode removeRoot(void *tPtr,const ZT_Identity *identity);
 	uint64_t address() const;
 	uint64_t address() const;
 	void status(ZT_NodeStatus *status) const;
 	void status(ZT_NodeStatus *status) const;
 	ZT_PeerList *peers() const;
 	ZT_PeerList *peers() const;
@@ -331,6 +331,7 @@ public:
 
 
 private:
 private:
 	RuntimeEnvironment _RR;
 	RuntimeEnvironment _RR;
+	void *_objects;
 	RuntimeEnvironment *RR;
 	RuntimeEnvironment *RR;
 	ZT_Node_Callbacks _cb;
 	ZT_Node_Callbacks _cb;
 	void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P
 	void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P

+ 11 - 0
node/Tests.cpp

@@ -594,4 +594,15 @@ extern "C" const char *ZTT_benchmarkCrypto()
 	return nullptr;
 	return nullptr;
 }
 }
 
 
+#ifdef ZT_STANDALONE_TESTS
+int main(int argc,char **argv)
+{
+	bool ok = true;
+	ok &= ZTT_general() == nullptr;
+	ZT_T_PRINTF(ZT_EOL_S);
+	ok &= ZTT_crypto() == nullptr;
+	return ok ? 0 : 1;
+}
+#endif
+
 #endif // ZT_ENABLE_TESTS
 #endif // ZT_ENABLE_TESTS

+ 0 - 2
node/Tests.h

@@ -37,8 +37,6 @@
 #ifndef ZT_TESTS_HPP
 #ifndef ZT_TESTS_HPP
 #define ZT_TESTS_HPP
 #define ZT_TESTS_HPP
 
 
-#define ZT_ENABLE_TESTS
-
 #ifdef ZT_ENABLE_TESTS
 #ifdef ZT_ENABLE_TESTS
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 2 - 3
node/Topology.cpp

@@ -34,9 +34,8 @@ struct _RootSortComparisonOperator
 	const int64_t _now;
 	const int64_t _now;
 };
 };
 
 
-Topology::Topology(const RuntimeEnvironment *renv,const Identity &myId,void *tPtr) :
+Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
 	RR(renv),
 	RR(renv),
-	_myIdentity(myId),
 	_numConfiguredPhysicalPaths(0),
 	_numConfiguredPhysicalPaths(0),
 	_peers(256),
 	_peers(256),
 	_peersByIncomingProbe(256),
 	_peersByIncomingProbe(256),
@@ -147,7 +146,7 @@ void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathN
 
 
 void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstrap)
 void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstrap)
 {
 {
-	if (id == _myIdentity) return; // sanity check
+	if (id == RR->identity) return; // sanity check
 	RWMutex::Lock l1(_peers_l);
 	RWMutex::Lock l1(_peers_l);
 	std::pair< std::set<Identity>::iterator,bool > ir(_roots.insert(id));
 	std::pair< std::set<Identity>::iterator,bool > ir(_roots.insert(id));
 	if (ir.second) {
 	if (ir.second) {

+ 1 - 2
node/Topology.hpp

@@ -42,7 +42,7 @@ class RuntimeEnvironment;
 class Topology
 class Topology
 {
 {
 public:
 public:
-	Topology(const RuntimeEnvironment *renv,const Identity &myId,void *tPtr);
+	Topology(const RuntimeEnvironment *renv,void *tPtr);
 	~Topology();
 	~Topology();
 
 
 	/**
 	/**
@@ -355,7 +355,6 @@ private:
 	}
 	}
 
 
 	const RuntimeEnvironment *const RR;
 	const RuntimeEnvironment *const RR;
-	const Identity _myIdentity;
 
 
 	RWMutex _peers_l;
 	RWMutex _peers_l;
 	RWMutex _paths_l;
 	RWMutex _paths_l;

+ 86 - 86
node/Utils.hpp

@@ -288,92 +288,6 @@ static ZT_ALWAYS_INLINE unsigned long hashString(const void *restrict key,const
 	return h;
 	return h;
 }
 }
 
 
-/**
- * Decode a big-endian value from a byte stream
- *
- * @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
- * @param p Byte stream, must be at least sizeof(I) in size
- * @return Decoded integer
- */
-template<typename I>
-static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
-{
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	I x = (I)0;
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
-#else
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
-#endif
-	}
-	return x;
-#else
-	return ntoh(*reinterpret_cast<const I *>(p));
-#endif
-}
-
-/**
- * Save an integer in big-endian format
- *
- * @tparam I Integer type to store (usually inferred)
- * @param p Byte stream to write (must be at least sizeof(I))
- * #param i Integer to write
- */
-template<typename I>
-static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
-{
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
-#else
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
-#endif
-	}
-#else
-	*reinterpret_cast<I *>(p) = hton(i);
-#endif
-}
-
-/**
- * Copy bits from memory into an integer type without modifying their order
- *
- * @tparam I Type to load
- * @param p Byte stream, must be at least sizeof(I) in size
- * @return Loaded raw integer
- */
-template<typename I>
-static ZT_ALWAYS_INLINE I loadAsIsEndian(const void *const p) noexcept
-{
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	I x = (I)0;
-	for(unsigned int k=0;k<sizeof(I);++k)
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
-	return x;
-#else
-	return *reinterpret_cast<const I *>(p);
-#endif
-}
-
-/**
- * Copy bits from memory into an integer type without modifying their order
- *
- * @tparam I Type to store
- * @param p Byte array (must be at least sizeof(I))
- * @param i Integer to store
- */
-template<typename I>
-static ZT_ALWAYS_INLINE void storeAsIsEndian(void *const p,const I i) noexcept
-{
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	for(unsigned int k=0;k<sizeof(I);++k)
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
-#else
-	*reinterpret_cast<I *>(p) = i;
-#endif
-}
-
 #ifdef __GNUC__
 #ifdef __GNUC__
 static ZT_ALWAYS_INLINE unsigned int countBits(const uint8_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
 static ZT_ALWAYS_INLINE unsigned int countBits(const uint8_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
 static ZT_ALWAYS_INLINE unsigned int countBits(const uint16_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
 static ZT_ALWAYS_INLINE unsigned int countBits(const uint16_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
@@ -502,6 +416,92 @@ template<typename T>
 static ZT_ALWAYS_INLINE T ntoh(T n) noexcept { return n; }
 static ZT_ALWAYS_INLINE T ntoh(T n) noexcept { return n; }
 #endif
 #endif
 
 
+/**
+ * Decode a big-endian value from a byte stream
+ *
+ * @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
+ * @param p Byte stream, must be at least sizeof(I) in size
+ * @return Decoded integer
+ */
+template<typename I>
+static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
+{
+#ifdef ZT_NO_UNALIGNED_ACCESS
+	I x = (I)0;
+	for(unsigned int k=0;k<sizeof(I);++k) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
+#else
+		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
+#endif
+	}
+	return x;
+#else
+	return ntoh(*reinterpret_cast<const I *>(p));
+#endif
+}
+
+/**
+ * Save an integer in big-endian format
+ *
+ * @tparam I Integer type to store (usually inferred)
+ * @param p Byte stream to write (must be at least sizeof(I))
+ * #param i Integer to write
+ */
+template<typename I>
+static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
+{
+#ifdef ZT_NO_UNALIGNED_ACCESS
+	for(unsigned int k=0;k<sizeof(I);++k) {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
+#else
+		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
+#endif
+	}
+#else
+	*reinterpret_cast<I *>(p) = hton(i);
+#endif
+}
+
+/**
+ * Copy bits from memory into an integer type without modifying their order
+ *
+ * @tparam I Type to load
+ * @param p Byte stream, must be at least sizeof(I) in size
+ * @return Loaded raw integer
+ */
+template<typename I>
+static ZT_ALWAYS_INLINE I loadAsIsEndian(const void *const p) noexcept
+{
+#ifdef ZT_NO_UNALIGNED_ACCESS
+	I x = (I)0;
+	for(unsigned int k=0;k<sizeof(I);++k)
+		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
+	return x;
+#else
+	return *reinterpret_cast<const I *>(p);
+#endif
+}
+
+/**
+ * Copy bits from memory into an integer type without modifying their order
+ *
+ * @tparam I Type to store
+ * @param p Byte array (must be at least sizeof(I))
+ * @param i Integer to store
+ */
+template<typename I>
+static ZT_ALWAYS_INLINE void storeAsIsEndian(void *const p,const I i) noexcept
+{
+#ifdef ZT_NO_UNALIGNED_ACCESS
+	for(unsigned int k=0;k<sizeof(I);++k)
+		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
+#else
+	*reinterpret_cast<I *>(p) = i;
+#endif
+}
+
 } // namespace Utils
 } // namespace Utils
 
 
 } // namespace ZeroTier
 } // namespace ZeroTier