Fix and modernize API peer list function.

This commit is contained in:
Adam Ierymenko 2020-10-22 15:53:35 -04:00
commit bab9a7f508
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
4 changed files with 114 additions and 89 deletions

View file

@ -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

View file

@ -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;
} }
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)
{
if (pl)
delete reinterpret_cast<p_ZT_PeerListPrivate *>(const_cast<void *>(pl));
}
struct p_sortPeerPtrsByAddress
{
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const noexcept
{ return (a->address() < b->address()); }
};
ZT_PeerList *Node::peers() const ZT_PeerList *Node::peers() const
{ {
Vector< SharedPtr< Peer > > peers, rootPeers; p_ZT_PeerListPrivate *pl = nullptr;
RR->topology->allPeers(peers, rootPeers); try {
pl = new p_ZT_PeerListPrivate;
pl->freeFunction = p_peerListFreeFunction;
std::sort(peers.begin(), peers.end(), _sortPeerPtrsByAddress()); 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;
const unsigned int bufSize = for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
sizeof(ZT_PeerList) + pl->p_peers.push_back(ZT_Peer());
(sizeof(ZT_Peer) * peers.size()) + ZT_Peer &p = pl->p_peers.back();
((sizeof(ZT_Path) * ZT_MAX_PEER_NETWORK_PATHS) * peers.size()) + Peer &pp = **pi;
(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; 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;
pl->peerCount = 0; p.networks = nullptr;
for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) { p.networkCount = 0; // TODO: networks this peer belongs to
ZT_Peer *const p = pl->peers + pl->peerCount;
p->address = (*pi)->address().toInt(); Vector< SharedPtr<Path> > ztPaths;
identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted pp.getAllPaths(ztPaths);
p->identity = identities + pl->peerCount; if (ztPaths.empty()) {
p->fingerprint.address = p->address; pl->p_paths.push_back(std::vector< ZT_Path >());
Utils::copy< ZT_FINGERPRINT_HASH_SIZE >(p->fingerprint.hash, (*pi)->identity().fingerprint().hash); std::vector< ZT_Path > &apiPaths = pl->p_paths.back();
if ((*pi)->remoteVersionKnown()) { apiPaths.resize(ztPaths.size());
p->versionMajor = (int)(*pi)->remoteVersionMajor(); for (unsigned long i = 0; i < (unsigned long)ztPaths.size(); ++i) {
p->versionMinor = (int)(*pi)->remoteVersionMinor(); SharedPtr< Path > &ztp = ztPaths[i];
p->versionRev = (int)(*pi)->remoteVersionRevision(); ZT_Path &apip = apiPaths[i];
} else { apip.endpoint.type = ZT_ENDPOINT_TYPE_IP_UDP;
p->versionMajor = -1; Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss));
p->versionMinor = -1; apip.lastSend = ztp->lastOut();
p->versionRev = -1; apip.lastReceive = ztp->lastIn();
} apip.alive = ztp->alive(now) ? 1 : 0;
p->latency = (*pi)->latency(); apip.preferred = (i == 0) ? 1 : 0;
p->root = (std::find(rootPeers.begin(), rootPeers.end(), *pi) != rootPeers.end()) ? 1 : 0; }
p.paths = apiPaths.data();
p.pathCount = (unsigned int)apiPaths.size();
} else {
p.paths = nullptr;
p.pathCount = 0;
}
p->networkCount = 0; const SharedPtr< const Locator > loc(pp.locator());
// TODO: enumerate network memberships if (loc) {
pl->p_locators.push_back(Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX >());
Vector< SharedPtr< Path > > paths; Blob< ZT_LOCATOR_MARSHAL_SIZE_MAX > &lb = pl->p_locators.back();
(*pi)->getAllPaths(paths); Utils::zero< ZT_LOCATOR_MARSHAL_SIZE_MAX >(lb.data);
p->pathCount = (unsigned int)paths.size(); const int ls = loc->marshal(lb.data);
p->paths = peerPath; if (ls > 0) {
for (Vector< SharedPtr< Path > >::iterator path(paths.begin()); path != paths.end(); ++path) { p.locatorSize = (unsigned int)ls;
ZT_Path *const pp = peerPath++; p.locator = lb.data;
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;
}
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;
} }
} }
++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));

View file

@ -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
*/ */

View file

@ -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)