Przeglądaj źródła

Fix and modernize API peer list function.

Adam Ierymenko 4 lat temu
rodzic
commit
bab9a7f508
4 zmienionych plików z 118 dodań i 93 usunięć
  1. 6 0
      core/Blob.hpp
  2. 98 84
      core/Node.cpp
  3. 13 8
      core/zerotier.h
  4. 1 1
      pkg/zerotier/peer.go

+ 6 - 0
core/Blob.hpp

@@ -115,6 +115,12 @@ struct UniqueID
 static_assert(sizeof(SHA384Hash) == 48,"SHA384Hash contains unnecessary padding");
 static_assert(sizeof(SHA384Hash) == 48,"SHA384Hash contains unnecessary padding");
 static_assert(sizeof(UniqueID) == 16,"UniqueID contains unnecessary padding");
 static_assert(sizeof(UniqueID) == 16,"UniqueID contains unnecessary padding");
 
 
+template<unsigned long S>
+struct Blob
+{
+	uint8_t data[S];
+};
+
 } // namespace ZeroTier
 } // namespace ZeroTier
 
 
 #endif
 #endif

+ 98 - 84
core/Node.cpp

@@ -58,12 +58,6 @@ struct _NodeObjects
 	Topology topology;
 	Topology topology;
 };
 };
 
 
-struct _sortPeerPtrsByAddress
-{
-	ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const
-	{ return (a->address() < b->address()); }
-};
-
 } // anonymous namespace
 } // anonymous namespace
 
 
 Node::Node(
 Node::Node(
@@ -152,6 +146,7 @@ Node::Node(
 Node::~Node()
 Node::~Node()
 {
 {
 	ZT_SPEW("node destructor run");
 	ZT_SPEW("node destructor run");
+
 	m_networks_l.lock();
 	m_networks_l.lock();
 	m_networks_l.unlock();
 	m_networks_l.unlock();
 	m_networks.clear();
 	m_networks.clear();
@@ -367,9 +362,7 @@ ZT_ResultCode Node::multicastUnsubscribe(
 }
 }
 
 
 uint64_t Node::address() const
 uint64_t Node::address() const
-{
-	return RR->identity.address().toInt();
-}
+{ return RR->identity.address().toInt(); }
 
 
 void Node::status(ZT_NodeStatus *status) const
 void Node::status(ZT_NodeStatus *status) const
 {
 {
@@ -380,88 +373,109 @@ void Node::status(ZT_NodeStatus *status) const
 	status->online = m_online ? 1 : 0;
 	status->online = m_online ? 1 : 0;
 }
 }
 
 
-ZT_PeerList *Node::peers() const
+struct p_ZT_PeerListPrivate : public ZT_PeerList
+{
+	// Actual containers for the memory, hidden from external users.
+	std::vector< ZT_Peer > p_peers;
+	std::list< std::vector<ZT_Path> > p_paths;
+	std::list< Identity > p_identities;
+	std::list< Blob<ZT_LOCATOR_MARSHAL_SIZE_MAX> > p_locators;
+};
+static void p_peerListFreeFunction(const void *pl)
 {
 {
-	Vector< SharedPtr< Peer > > peers, rootPeers;
-	RR->topology->allPeers(peers, rootPeers);
+	if (pl)
+		delete reinterpret_cast<p_ZT_PeerListPrivate *>(const_cast<void *>(pl));
+}
 
 
-	std::sort(peers.begin(), peers.end(), _sortPeerPtrsByAddress());
+struct p_sortPeerPtrsByAddress
+{
+	ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
+	{ return (a->address() < b->address()); }
+};
 
 
-	const unsigned int bufSize =
-		sizeof(ZT_PeerList) +
-		(sizeof(ZT_Peer) * peers.size()) +
-		((sizeof(ZT_Path) * ZT_MAX_PEER_NETWORK_PATHS) * peers.size()) +
-		(sizeof(Identity) * peers.size()) +
-		(ZT_LOCATOR_MARSHAL_SIZE_MAX * peers.size());
-	char *buf = (char *)malloc(bufSize);
-	if (!buf)
-		return nullptr;
-	Utils::zero(buf, bufSize);
-	ZT_PeerList *pl = reinterpret_cast<ZT_PeerList *>(buf);
-	buf += sizeof(ZT_PeerList);
-	pl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
-	pl->peers = reinterpret_cast<ZT_Peer *>(buf);
-	buf += sizeof(ZT_Peer) * peers.size();
-	ZT_Path *peerPath = reinterpret_cast<ZT_Path *>(buf);
-	buf += (sizeof(ZT_Path) * ZT_MAX_PEER_NETWORK_PATHS) * peers.size();
-	Identity *identities = reinterpret_cast<Identity *>(buf);
-	buf += sizeof(Identity) * peers.size();
-	uint8_t *locatorBuf = reinterpret_cast<uint8_t *>(buf);
-
-	const int64_t now = m_now;
-
-	pl->peerCount = 0;
-	for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
-		ZT_Peer *const p = pl->peers + pl->peerCount;
-
-		p->address = (*pi)->address().toInt();
-		identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
-		p->identity = identities + pl->peerCount;
-		p->fingerprint.address = p->address;
-		Utils::copy< ZT_FINGERPRINT_HASH_SIZE >(p->fingerprint.hash, (*pi)->identity().fingerprint().hash);
-		if ((*pi)->remoteVersionKnown()) {
-			p->versionMajor = (int)(*pi)->remoteVersionMajor();
-			p->versionMinor = (int)(*pi)->remoteVersionMinor();
-			p->versionRev = (int)(*pi)->remoteVersionRevision();
-		} else {
-			p->versionMajor = -1;
-			p->versionMinor = -1;
-			p->versionRev = -1;
-		}
-		p->latency = (*pi)->latency();
-		p->root = (std::find(rootPeers.begin(), rootPeers.end(), *pi) != rootPeers.end()) ? 1 : 0;
-
-		p->networkCount = 0;
-		// TODO: enumerate network memberships
-
-		Vector< SharedPtr< Path > > paths;
-		(*pi)->getAllPaths(paths);
-		p->pathCount = (unsigned int)paths.size();
-		p->paths = peerPath;
-		for (Vector< SharedPtr< Path > >::iterator path(paths.begin()); path != paths.end(); ++path) {
-			ZT_Path *const pp = peerPath++;
-			pp->endpoint.type = ZT_ENDPOINT_TYPE_IP_UDP; // only type supported right now
-			Utils::copy< sizeof(sockaddr_storage) >(&pp->endpoint.value.ss, &((*path)->address().as.ss));
-			pp->lastSend = (*path)->lastOut();
-			pp->lastReceive = (*path)->lastIn();
-			pp->alive = (*path)->alive(now) ? 1 : 0;
-			pp->preferred = (p->pathCount == 0) ? 1 : 0;
-		}
+ZT_PeerList *Node::peers() const
+{
+	p_ZT_PeerListPrivate *pl = nullptr;
+	try {
+		pl = new p_ZT_PeerListPrivate;
+		pl->freeFunction = p_peerListFreeFunction;
+
+		Vector< SharedPtr< Peer > > peers, rootPeers;
+		RR->topology->allPeers(peers, rootPeers);
+		std::sort(peers.begin(), peers.end(), p_sortPeerPtrsByAddress());
+		std::sort(rootPeers.begin(), rootPeers.end());
+		int64_t now = m_now;
+
+		for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
+			pl->p_peers.push_back(ZT_Peer());
+			ZT_Peer &p = pl->p_peers.back();
+			Peer &pp = **pi;
+
+			p.address = pp.address();
+			pl->p_identities.push_back(pp.identity());
+			p.identity = reinterpret_cast<const ZT_Identity *>(&(pl->p_identities.back()));
+			p.fingerprint = &(pl->p_identities.back().fingerprint());
+			if (pp.remoteVersionKnown()) {
+				p.versionMajor = (int)pp.remoteVersionMajor();
+				p.versionMinor = (int)pp.remoteVersionMinor();
+				p.versionRev = (int)pp.remoteVersionRevision();
+				p.versionProto = (int)pp.remoteVersionProtocol();
+			} else {
+				p.versionMajor = -1;
+				p.versionMinor = -1;
+				p.versionRev = -1;
+				p.versionProto = -1;
+			}
+			p.latency = pp.latency();
+			p.root = std::binary_search(rootPeers.begin(), rootPeers.end(), *pi) ? 1 : 0;
+
+			p.networks = nullptr;
+			p.networkCount = 0; // TODO: networks this peer belongs to
+
+			Vector< SharedPtr<Path> > ztPaths;
+			pp.getAllPaths(ztPaths);
+			if (ztPaths.empty()) {
+				pl->p_paths.push_back(std::vector< ZT_Path >());
+				std::vector< ZT_Path > &apiPaths = pl->p_paths.back();
+				apiPaths.resize(ztPaths.size());
+				for (unsigned long i = 0; i < (unsigned long)ztPaths.size(); ++i) {
+					SharedPtr< Path > &ztp = ztPaths[i];
+					ZT_Path &apip = apiPaths[i];
+					apip.endpoint.type = ZT_ENDPOINT_TYPE_IP_UDP;
+					Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss));
+					apip.lastSend = ztp->lastOut();
+					apip.lastReceive = ztp->lastIn();
+					apip.alive = ztp->alive(now) ? 1 : 0;
+					apip.preferred = (i == 0) ? 1 : 0;
+				}
+				p.paths = apiPaths.data();
+				p.pathCount = (unsigned int)apiPaths.size();
+			} else {
+				p.paths = nullptr;
+				p.pathCount = 0;
+			}
 
 
-		const SharedPtr< const Locator > loc((*pi)->locator());
-		if (loc) {
-			const int ls = loc->marshal(locatorBuf);
-			if (ls > 0) {
-				p->locatorSize = (unsigned int)ls;
-				p->locator = locatorBuf;
-				locatorBuf += ls;
+			const SharedPtr< const Locator > loc(pp.locator());
+			if (loc) {
+				pl->p_locators.push_back(Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX >());
+				Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX > &lb = pl->p_locators.back();
+				Utils::zero< ZT_LOCATOR_MARSHAL_SIZE_MAX >(lb.data);
+				const int ls = loc->marshal(lb.data);
+				if (ls > 0) {
+					p.locatorSize = (unsigned int)ls;
+					p.locator = lb.data;
+				}
 			}
 			}
 		}
 		}
 
 
-		++pl->peerCount;
-	}
+		pl->peers = pl->p_peers.data();
+		pl->peerCount = (unsigned long)pl->p_peers.size();
 
 
-	return pl;
+		return pl;
+	} catch ( ... ) {
+		delete pl;
+		return nullptr;
+	}
 }
 }
 
 
 ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
 ZT_VirtualNetworkConfig *Node::networkConfig(uint64_t nwid) const
@@ -482,7 +496,7 @@ ZT_VirtualNetworkList *Node::networks() const
 	char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_networks.size()));
 	char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_networks.size()));
 	if (!buf)
 	if (!buf)
 		return nullptr;
 		return nullptr;
-	ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf; // NOLINT(modernize-use-auto,hicpp-use-auto)
+	ZT_VirtualNetworkList *nl = (ZT_VirtualNetworkList *)buf;
 	nl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
 	nl->freeFunction = reinterpret_cast<void (*)(const void *)>(free);
 	nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
 	nl->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));
 
 

+ 13 - 8
core/zerotier.h

@@ -1578,7 +1578,7 @@ typedef struct
 	/**
 	/**
 	 * SHA-384 of identity public key(s)
 	 * SHA-384 of identity public key(s)
 	 */
 	 */
-	ZT_Fingerprint fingerprint;
+	const ZT_Fingerprint *fingerprint;
 
 
 	/**
 	/**
 	 * Remote major version or -1 if not known
 	 * Remote major version or -1 if not known
@@ -1595,6 +1595,11 @@ typedef struct
 	 */
 	 */
 	int versionRev;
 	int versionRev;
 
 
+	/**
+	 * Remote protocol version or -1 if not known
+	 */
+	int versionProto;
+
 	/**
 	/**
 	 * Last measured latency in milliseconds or -1 if unknown
 	 * Last measured latency in milliseconds or -1 if unknown
 	 */
 	 */
@@ -1605,20 +1610,15 @@ typedef struct
 	 */
 	 */
 	int root;
 	int root;
 
 
-	/**
-	 * Number of networks in which this peer is authenticated
-	 */
-	unsigned int networkCount;
-
 	/**
 	/**
 	 * Network IDs for networks (array size: networkCount)
 	 * Network IDs for networks (array size: networkCount)
 	 */
 	 */
 	uint64_t *networks;
 	uint64_t *networks;
 
 
 	/**
 	/**
-	 * Number of paths (size of paths[])
+	 * Number of networks in which this peer is authenticated
 	 */
 	 */
-	unsigned int pathCount;
+	unsigned int networkCount;
 
 
 	/**
 	/**
 	 * Known network paths to peer (array size: pathCount).
 	 * Known network paths to peer (array size: pathCount).
@@ -1629,6 +1629,11 @@ typedef struct
 	 */
 	 */
 	ZT_Path *paths;
 	ZT_Path *paths;
 
 
+	/**
+	 * Number of paths (size of paths[])
+	 */
+	unsigned int pathCount;
+
 	/**
 	/**
 	 * Size of locator in bytes or 0 if none
 	 * Size of locator in bytes or 0 if none
 	 */
 	 */

+ 1 - 1
pkg/zerotier/peer.go

@@ -37,7 +37,7 @@ func newPeerFromCPeer(cp *C.ZT_Peer) (p *Peer, err error) {
 	if err != nil {
 	if err != nil {
 		return
 		return
 	}
 	}
-	p.Fingerprint = newFingerprintFromCFingerprint(&(cp.fingerprint))
+	p.Fingerprint = newFingerprintFromCFingerprint(cp.fingerprint)
 	p.Version[0] = int(cp.versionMajor)
 	p.Version[0] = int(cp.versionMajor)
 	p.Version[1] = int(cp.versionMinor)
 	p.Version[1] = int(cp.versionMinor)
 	p.Version[2] = int(cp.versionRev)
 	p.Version[2] = int(cp.versionRev)