Fix and modernize API peer list function.

This commit is contained in:
Adam Ierymenko 2020-10-22 15:53:35 -04:00
parent 31eb950750
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(UniqueID) == 16,"UniqueID contains unnecessary padding");
template<unsigned long S>
struct Blob
{
uint8_t data[S];
};
} // namespace ZeroTier
#endif

View file

@ -58,12 +58,6 @@ struct _NodeObjects
Topology topology;
};
struct _sortPeerPtrsByAddress
{
ZT_INLINE bool operator()(const SharedPtr< Peer > &a, const SharedPtr< Peer > &b) const
{ return (a->address() < b->address()); }
};
} // anonymous namespace
Node::Node(
@ -152,6 +146,7 @@ Node::Node(
Node::~Node()
{
ZT_SPEW("node destructor run");
m_networks_l.lock();
m_networks_l.unlock();
m_networks.clear();
@ -367,9 +362,7 @@ ZT_ResultCode Node::multicastUnsubscribe(
}
uint64_t Node::address() const
{
return RR->identity.address().toInt();
}
{ return RR->identity.address().toInt(); }
void Node::status(ZT_NodeStatus *status) const
{
@ -380,88 +373,109 @@ void Node::status(ZT_NodeStatus *status) const
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
{
Vector< SharedPtr< Peer > > peers, rootPeers;
RR->topology->allPeers(peers, rootPeers);
p_ZT_PeerListPrivate *pl = nullptr;
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 =
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);
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;
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;
for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) {
ZT_Peer *const p = pl->peers + pl->peerCount;
p.networks = nullptr;
p.networkCount = 0; // TODO: networks this peer belongs to
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;
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;
}
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;
}
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
@ -482,7 +496,7 @@ ZT_VirtualNetworkList *Node::networks() const
char *const buf = (char *)::malloc(sizeof(ZT_VirtualNetworkList) + (sizeof(ZT_VirtualNetworkConfig) * m_networks.size()));
if (!buf)
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->networks = (ZT_VirtualNetworkConfig *)(buf + sizeof(ZT_VirtualNetworkList));

View file

@ -1578,7 +1578,7 @@ typedef struct
/**
* SHA-384 of identity public key(s)
*/
ZT_Fingerprint fingerprint;
const ZT_Fingerprint *fingerprint;
/**
* Remote major version or -1 if not known
@ -1595,6 +1595,11 @@ typedef struct
*/
int versionRev;
/**
* Remote protocol version or -1 if not known
*/
int versionProto;
/**
* Last measured latency in milliseconds or -1 if unknown
*/
@ -1605,20 +1610,15 @@ typedef struct
*/
int root;
/**
* Number of networks in which this peer is authenticated
*/
unsigned int networkCount;
/**
* Network IDs for networks (array size: networkCount)
*/
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).
@ -1629,6 +1629,11 @@ typedef struct
*/
ZT_Path *paths;
/**
* Number of paths (size of paths[])
*/
unsigned int pathCount;
/**
* 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 {
return
}
p.Fingerprint = newFingerprintFromCFingerprint(&(cp.fingerprint))
p.Fingerprint = newFingerprintFromCFingerprint(cp.fingerprint)
p.Version[0] = int(cp.versionMajor)
p.Version[1] = int(cp.versionMinor)
p.Version[2] = int(cp.versionRev)