Imported Upstream version 1.2.4
This commit is contained in:
parent
bb232b9d52
commit
4722a0b75a
398 changed files with 38633 additions and 24919 deletions
543
node/Node.cpp
543
node/Node.cpp
|
@ -37,7 +37,6 @@
|
|||
#include "Identity.hpp"
|
||||
#include "SelfAwareness.hpp"
|
||||
#include "Cluster.hpp"
|
||||
#include "DeferredPackets.hpp"
|
||||
|
||||
const struct sockaddr_storage ZT_SOCKADDR_NULL = {0};
|
||||
|
||||
|
@ -47,70 +46,48 @@ namespace ZeroTier {
|
|||
/* Public Node interface (C++, exposed via CAPI bindings) */
|
||||
/****************************************************************************/
|
||||
|
||||
Node::Node(
|
||||
uint64_t now,
|
||||
void *uptr,
|
||||
ZT_DataStoreGetFunction dataStoreGetFunction,
|
||||
ZT_DataStorePutFunction dataStorePutFunction,
|
||||
ZT_WirePacketSendFunction wirePacketSendFunction,
|
||||
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
|
||||
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback) :
|
||||
Node::Node(void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now) :
|
||||
_RR(this),
|
||||
RR(&_RR),
|
||||
_uPtr(uptr),
|
||||
_dataStoreGetFunction(dataStoreGetFunction),
|
||||
_dataStorePutFunction(dataStorePutFunction),
|
||||
_wirePacketSendFunction(wirePacketSendFunction),
|
||||
_virtualNetworkFrameFunction(virtualNetworkFrameFunction),
|
||||
_virtualNetworkConfigFunction(virtualNetworkConfigFunction),
|
||||
_pathCheckFunction(pathCheckFunction),
|
||||
_eventCallback(eventCallback),
|
||||
_networks(),
|
||||
_networks_m(),
|
||||
_prngStreamPtr(0),
|
||||
_now(now),
|
||||
_lastPingCheck(0),
|
||||
_lastHousekeepingRun(0)
|
||||
{
|
||||
if (callbacks->version != 0)
|
||||
throw std::runtime_error("callbacks struct version mismatch");
|
||||
memcpy(&_cb,callbacks,sizeof(ZT_Node_Callbacks));
|
||||
|
||||
Utils::getSecureRandom((void *)_prngState,sizeof(_prngState));
|
||||
|
||||
_online = false;
|
||||
|
||||
// Use Salsa20 alone as a high-quality non-crypto PRNG
|
||||
{
|
||||
char foo[32];
|
||||
Utils::getSecureRandom(foo,32);
|
||||
_prng.init(foo,256,foo);
|
||||
memset(_prngStream,0,sizeof(_prngStream));
|
||||
_prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
|
||||
}
|
||||
memset(_expectingRepliesToBucketPtr,0,sizeof(_expectingRepliesToBucketPtr));
|
||||
memset(_expectingRepliesTo,0,sizeof(_expectingRepliesTo));
|
||||
memset(_lastIdentityVerification,0,sizeof(_lastIdentityVerification));
|
||||
|
||||
{
|
||||
std::string idtmp(dataStoreGet("identity.secret"));
|
||||
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
|
||||
TRACE("identity.secret not found, generating...");
|
||||
RR->identity.generate();
|
||||
idtmp = RR->identity.toString(true);
|
||||
if (!dataStorePut("identity.secret",idtmp,true))
|
||||
throw std::runtime_error("unable to write identity.secret");
|
||||
}
|
||||
RR->publicIdentityStr = RR->identity.toString(false);
|
||||
RR->secretIdentityStr = RR->identity.toString(true);
|
||||
idtmp = dataStoreGet("identity.public");
|
||||
if (idtmp != RR->publicIdentityStr) {
|
||||
if (!dataStorePut("identity.public",RR->publicIdentityStr,false))
|
||||
throw std::runtime_error("unable to write identity.public");
|
||||
}
|
||||
std::string idtmp(dataStoreGet(tptr,"identity.secret"));
|
||||
if ((!idtmp.length())||(!RR->identity.fromString(idtmp))||(!RR->identity.hasPrivate())) {
|
||||
TRACE("identity.secret not found, generating...");
|
||||
RR->identity.generate();
|
||||
idtmp = RR->identity.toString(true);
|
||||
if (!dataStorePut(tptr,"identity.secret",idtmp,true))
|
||||
throw std::runtime_error("unable to write identity.secret");
|
||||
}
|
||||
RR->publicIdentityStr = RR->identity.toString(false);
|
||||
RR->secretIdentityStr = RR->identity.toString(true);
|
||||
idtmp = dataStoreGet(tptr,"identity.public");
|
||||
if (idtmp != RR->publicIdentityStr) {
|
||||
if (!dataStorePut(tptr,"identity.public",RR->publicIdentityStr,false))
|
||||
throw std::runtime_error("unable to write identity.public");
|
||||
}
|
||||
|
||||
try {
|
||||
RR->sw = new Switch(RR);
|
||||
RR->mc = new Multicaster(RR);
|
||||
RR->topology = new Topology(RR);
|
||||
RR->topology = new Topology(RR,tptr);
|
||||
RR->sa = new SelfAwareness(RR);
|
||||
RR->dp = new DeferredPackets(RR);
|
||||
} catch ( ... ) {
|
||||
delete RR->dp;
|
||||
delete RR->sa;
|
||||
delete RR->topology;
|
||||
delete RR->mc;
|
||||
|
@ -118,7 +95,7 @@ Node::Node(
|
|||
throw;
|
||||
}
|
||||
|
||||
postEvent(ZT_EVENT_UP);
|
||||
postEvent(tptr,ZT_EVENT_UP);
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
|
@ -127,18 +104,18 @@ Node::~Node()
|
|||
|
||||
_networks.clear(); // ensure that networks are destroyed before shutdow
|
||||
|
||||
RR->dpEnabled = 0;
|
||||
delete RR->dp;
|
||||
delete RR->sa;
|
||||
delete RR->topology;
|
||||
delete RR->mc;
|
||||
delete RR->sw;
|
||||
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
delete RR->cluster;
|
||||
#endif
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::processWirePacket(
|
||||
void *tptr,
|
||||
uint64_t now,
|
||||
const struct sockaddr_storage *localAddress,
|
||||
const struct sockaddr_storage *remoteAddress,
|
||||
|
@ -147,11 +124,12 @@ ZT_ResultCode Node::processWirePacket(
|
|||
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
_now = now;
|
||||
RR->sw->onRemotePacket(*(reinterpret_cast<const InetAddress *>(localAddress)),*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
|
||||
RR->sw->onRemotePacket(tptr,*(reinterpret_cast<const InetAddress *>(localAddress)),*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::processVirtualNetworkFrame(
|
||||
void *tptr,
|
||||
uint64_t now,
|
||||
uint64_t nwid,
|
||||
uint64_t sourceMac,
|
||||
|
@ -165,20 +143,22 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
|
|||
_now = now;
|
||||
SharedPtr<Network> nw(this->network(nwid));
|
||||
if (nw) {
|
||||
RR->sw->onLocalEthernet(nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
|
||||
RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength);
|
||||
return ZT_RESULT_OK;
|
||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Closure used to ping upstream and active/online peers
|
||||
class _PingPeersThatNeedPing
|
||||
{
|
||||
public:
|
||||
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,uint64_t now,const std::vector<NetworkConfig::Relay> &relays) :
|
||||
_PingPeersThatNeedPing(const RuntimeEnvironment *renv,void *tPtr,Hashtable< Address,std::vector<InetAddress> > &upstreamsToContact,uint64_t now) :
|
||||
lastReceiveFromUpstream(0),
|
||||
RR(renv),
|
||||
_tPtr(tPtr),
|
||||
_upstreamsToContact(upstreamsToContact),
|
||||
_now(now),
|
||||
_relays(relays),
|
||||
_world(RR->topology->world())
|
||||
_bestCurrentUpstream(RR->topology->getUpstreamPeer())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -186,92 +166,56 @@ public:
|
|||
|
||||
inline void operator()(Topology &t,const SharedPtr<Peer> &p)
|
||||
{
|
||||
bool upstream = false;
|
||||
InetAddress stableEndpoint4,stableEndpoint6;
|
||||
const std::vector<InetAddress> *const upstreamStableEndpoints = _upstreamsToContact.get(p->address());
|
||||
if (upstreamStableEndpoints) {
|
||||
bool contacted = false;
|
||||
|
||||
// If this is a world root, pick (if possible) both an IPv4 and an IPv6 stable endpoint to use if link isn't currently alive.
|
||||
for(std::vector<World::Root>::const_iterator r(_world.roots().begin());r!=_world.roots().end();++r) {
|
||||
if (r->identity == p->identity()) {
|
||||
upstream = true;
|
||||
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)r->stableEndpoints.size();++k) {
|
||||
const InetAddress &addr = r->stableEndpoints[ptr++ % r->stableEndpoints.size()];
|
||||
if (!stableEndpoint4) {
|
||||
if (addr.ss_family == AF_INET)
|
||||
stableEndpoint4 = addr;
|
||||
}
|
||||
if (!stableEndpoint6) {
|
||||
if (addr.ss_family == AF_INET6)
|
||||
stableEndpoint6 = addr;
|
||||
// Upstreams must be pinged constantly over both IPv4 and IPv6 to allow
|
||||
// them to perform three way handshake introductions for both stacks.
|
||||
|
||||
if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET)) {
|
||||
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
|
||||
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
||||
if (addr.ss_family == AF_INET) {
|
||||
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
|
||||
contacted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!upstream) {
|
||||
// If I am a root server, only ping other root servers -- roots don't ping "down"
|
||||
// since that would just be a waste of bandwidth and could potentially cause route
|
||||
// flapping in Cluster mode.
|
||||
if (RR->topology->amRoot())
|
||||
return;
|
||||
|
||||
// Check for network preferred relays, also considered 'upstream' and thus always
|
||||
// pinged to keep links up. If they have stable addresses we will try them there.
|
||||
for(std::vector<NetworkConfig::Relay>::const_iterator r(_relays.begin());r!=_relays.end();++r) {
|
||||
if (r->address == p->address()) {
|
||||
stableEndpoint4 = r->phy4;
|
||||
stableEndpoint6 = r->phy6;
|
||||
upstream = true;
|
||||
break;
|
||||
} else contacted = true;
|
||||
if (!p->doPingAndKeepalive(_tPtr,_now,AF_INET6)) {
|
||||
for(unsigned long k=0,ptr=(unsigned long)RR->node->prng();k<(unsigned long)upstreamStableEndpoints->size();++k) {
|
||||
const InetAddress &addr = (*upstreamStableEndpoints)[ptr++ % upstreamStableEndpoints->size()];
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
p->sendHELLO(_tPtr,InetAddress(),addr,_now,0);
|
||||
contacted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else contacted = true;
|
||||
|
||||
if (upstream) {
|
||||
// "Upstream" devices are roots and relays and get special treatment -- they stay alive
|
||||
// forever and we try to keep (if available) both IPv4 and IPv6 channels open to them.
|
||||
bool needToContactIndirect = true;
|
||||
if (p->doPingAndKeepalive(_now,AF_INET)) {
|
||||
needToContactIndirect = false;
|
||||
} else {
|
||||
if (stableEndpoint4) {
|
||||
needToContactIndirect = false;
|
||||
p->sendHELLO(InetAddress(),stableEndpoint4,_now);
|
||||
}
|
||||
}
|
||||
if (p->doPingAndKeepalive(_now,AF_INET6)) {
|
||||
needToContactIndirect = false;
|
||||
} else {
|
||||
if (stableEndpoint6) {
|
||||
needToContactIndirect = false;
|
||||
p->sendHELLO(InetAddress(),stableEndpoint6,_now);
|
||||
}
|
||||
}
|
||||
|
||||
if (needToContactIndirect) {
|
||||
// If this is an upstream and we have no stable endpoint for either IPv4 or IPv6,
|
||||
// send a NOP indirectly if possible to see if we can get to this peer in any
|
||||
// way whatsoever. This will e.g. find network preferred relays that lack
|
||||
// stable endpoints by using root servers.
|
||||
Packet outp(p->address(),RR->identity.address(),Packet::VERB_NOP);
|
||||
RR->sw->send(outp,true,0);
|
||||
if ((!contacted)&&(_bestCurrentUpstream)) {
|
||||
const SharedPtr<Path> up(_bestCurrentUpstream->getBestPath(_now,true));
|
||||
if (up)
|
||||
p->sendHELLO(_tPtr,up->localAddress(),up->address(),_now,up->nextOutgoingCounter());
|
||||
}
|
||||
|
||||
lastReceiveFromUpstream = std::max(p->lastReceive(),lastReceiveFromUpstream);
|
||||
} else if (p->activelyTransferringFrames(_now)) {
|
||||
// Normal nodes get their preferred link kept alive if the node has generated frame traffic recently
|
||||
p->doPingAndKeepalive(_now,0);
|
||||
_upstreamsToContact.erase(p->address()); // erase from upstreams to contact so that we can WHOIS those that remain
|
||||
} else if (p->isActive(_now)) {
|
||||
p->doPingAndKeepalive(_tPtr,_now,-1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const RuntimeEnvironment *RR;
|
||||
uint64_t _now;
|
||||
const std::vector<NetworkConfig::Relay> &_relays;
|
||||
World _world;
|
||||
void *_tPtr;
|
||||
Hashtable< Address,std::vector<InetAddress> > &_upstreamsToContact;
|
||||
const uint64_t _now;
|
||||
const SharedPtr<Peer> _bestCurrentUpstream;
|
||||
};
|
||||
|
||||
ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
ZT_ResultCode Node::processBackgroundTasks(void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
_now = now;
|
||||
Mutex::Lock bl(_backgroundTasksLock);
|
||||
|
@ -282,35 +226,37 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
|
|||
try {
|
||||
_lastPingCheck = now;
|
||||
|
||||
// Get relays and networks that need config without leaving the mutex locked
|
||||
std::vector< NetworkConfig::Relay > networkRelays;
|
||||
// Get networks that need config without leaving mutex locked
|
||||
std::vector< SharedPtr<Network> > needConfig;
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
|
||||
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!n->second->hasConfig())) {
|
||||
if (((now - n->second->lastConfigUpdate()) >= ZT_NETWORK_AUTOCONF_DELAY)||(!n->second->hasConfig()))
|
||||
needConfig.push_back(n->second);
|
||||
}
|
||||
if (n->second->hasConfig()) {
|
||||
std::vector<NetworkConfig::Relay> r(n->second->config().relays());
|
||||
networkRelays.insert(networkRelays.end(),r.begin(),r.end());
|
||||
}
|
||||
n->second->sendUpdatesToMembers(tptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Request updated configuration for networks that need it
|
||||
for(std::vector< SharedPtr<Network> >::const_iterator n(needConfig.begin());n!=needConfig.end();++n)
|
||||
(*n)->requestConfiguration();
|
||||
(*n)->requestConfiguration(tptr);
|
||||
|
||||
// Do pings and keepalives
|
||||
_PingPeersThatNeedPing pfunc(RR,now,networkRelays);
|
||||
Hashtable< Address,std::vector<InetAddress> > upstreamsToContact;
|
||||
RR->topology->getUpstreamsToContact(upstreamsToContact);
|
||||
_PingPeersThatNeedPing pfunc(RR,tptr,upstreamsToContact,now);
|
||||
RR->topology->eachPeer<_PingPeersThatNeedPing &>(pfunc);
|
||||
|
||||
// Run WHOIS to create Peer for any upstreams we could not contact (including pending moon seeds)
|
||||
Hashtable< Address,std::vector<InetAddress> >::Iterator i(upstreamsToContact);
|
||||
Address *upstreamAddress = (Address *)0;
|
||||
std::vector<InetAddress> *upstreamStableEndpoints = (std::vector<InetAddress> *)0;
|
||||
while (i.next(upstreamAddress,upstreamStableEndpoints))
|
||||
RR->sw->requestWhois(tptr,*upstreamAddress);
|
||||
|
||||
// Update online status, post status change as event
|
||||
const bool oldOnline = _online;
|
||||
_online = (((now - pfunc.lastReceiveFromUpstream) < ZT_PEER_ACTIVITY_TIMEOUT)||(RR->topology->amRoot()));
|
||||
if (oldOnline != _online)
|
||||
postEvent(_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
postEvent(tptr,_online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
@ -333,12 +279,12 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
|
|||
#ifdef ZT_ENABLE_CLUSTER
|
||||
// If clustering is enabled we have to call cluster->doPeriodicTasks() very often, so we override normal timer deadline behavior
|
||||
if (RR->cluster) {
|
||||
RR->sw->doTimerTasks(now);
|
||||
RR->sw->doTimerTasks(tptr,now);
|
||||
RR->cluster->doPeriodicTasks();
|
||||
*nextBackgroundTaskDeadline = now + ZT_CLUSTER_PERIODIC_TASK_PERIOD; // this is really short so just tick at this rate
|
||||
} else {
|
||||
#endif
|
||||
*nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
|
||||
*nextBackgroundTaskDeadline = now + (uint64_t)std::max(std::min(timeUntilNextPingCheck,RR->sw->doTimerTasks(tptr,now)),(unsigned long)ZT_CORE_TIMER_TASK_GRANULARITY);
|
||||
#ifdef ZT_ENABLE_CLUSTER
|
||||
}
|
||||
#endif
|
||||
|
@ -349,38 +295,47 @@ ZT_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *nextB
|
|||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::join(uint64_t nwid,void *uptr)
|
||||
ZT_ResultCode Node::join(uint64_t nwid,void *uptr,void *tptr)
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
SharedPtr<Network> nw = _network(nwid);
|
||||
if(!nw)
|
||||
_networks.push_back(std::pair< uint64_t,SharedPtr<Network> >(nwid,SharedPtr<Network>(new Network(RR,nwid,uptr))));
|
||||
std::sort(_networks.begin(),_networks.end()); // will sort by nwid since it's the first in a pair<>
|
||||
if(!nw) {
|
||||
const std::pair< uint64_t,SharedPtr<Network> > nn(nwid,SharedPtr<Network>(new Network(RR,tptr,nwid,uptr)));
|
||||
_networks.insert(std::upper_bound(_networks.begin(),_networks.end(),nn),nn);
|
||||
}
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::leave(uint64_t nwid,void **uptr)
|
||||
ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
|
||||
{
|
||||
ZT_VirtualNetworkConfig ctmp;
|
||||
std::vector< std::pair< uint64_t,SharedPtr<Network> > > newn;
|
||||
void **nUserPtr = (void **)0;
|
||||
Mutex::Lock _l(_networks_m);
|
||||
|
||||
for(std::vector< std::pair< uint64_t,SharedPtr<Network> > >::const_iterator n(_networks.begin());n!=_networks.end();++n) {
|
||||
if (n->first != nwid)
|
||||
if (n->first != nwid) {
|
||||
newn.push_back(*n);
|
||||
else {
|
||||
} else {
|
||||
if (uptr)
|
||||
*uptr = n->second->userPtr();
|
||||
*uptr = *n->second->userPtr();
|
||||
n->second->destroy();
|
||||
nUserPtr = n->second->userPtr();
|
||||
}
|
||||
}
|
||||
_networks.swap(newn);
|
||||
|
||||
if (nUserPtr)
|
||||
RR->node->configureVirtualNetworkPort(tptr,nwid,nUserPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp);
|
||||
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::multicastSubscribe(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));
|
||||
if (nw) {
|
||||
nw->multicastSubscribe(MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
|
||||
nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
|
||||
return ZT_RESULT_OK;
|
||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
@ -394,6 +349,18 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
|
|||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::orbit(void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
|
||||
{
|
||||
RR->topology->addMoon(tptr,moonWorldId,Address(moonSeed));
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::deorbit(void *tptr,uint64_t moonWorldId)
|
||||
{
|
||||
RR->topology->removeMoon(tptr,moonWorldId);
|
||||
return ZT_RESULT_OK;
|
||||
}
|
||||
|
||||
uint64_t Node::address() const
|
||||
{
|
||||
return RR->identity.address().toInt();
|
||||
|
@ -402,8 +369,6 @@ uint64_t Node::address() const
|
|||
void Node::status(ZT_NodeStatus *status) const
|
||||
{
|
||||
status->address = RR->identity.address().toInt();
|
||||
status->worldId = RR->topology->worldId();
|
||||
status->worldTimestamp = RR->topology->worldTimestamp();
|
||||
status->publicIdentity = RR->publicIdentityStr.c_str();
|
||||
status->secretIdentity = RR->secretIdentityStr.c_str();
|
||||
status->online = _online ? 1 : 0;
|
||||
|
@ -424,8 +389,6 @@ ZT_PeerList *Node::peers() const
|
|||
for(std::vector< std::pair< Address,SharedPtr<Peer> > >::iterator pi(peers.begin());pi!=peers.end();++pi) {
|
||||
ZT_Peer *p = &(pl->peers[pl->peerCount++]);
|
||||
p->address = pi->second->address().toInt();
|
||||
p->lastUnicastFrame = pi->second->lastUnicastFrame();
|
||||
p->lastMulticastFrame = pi->second->lastMulticastFrame();
|
||||
if (pi->second->remoteVersionKnown()) {
|
||||
p->versionMajor = pi->second->remoteVersionMajor();
|
||||
p->versionMinor = pi->second->remoteVersionMinor();
|
||||
|
@ -436,18 +399,19 @@ ZT_PeerList *Node::peers() const
|
|||
p->versionRev = -1;
|
||||
}
|
||||
p->latency = pi->second->latency();
|
||||
p->role = RR->topology->isRoot(pi->second->identity()) ? ZT_PEER_ROLE_ROOT : ZT_PEER_ROLE_LEAF;
|
||||
p->role = RR->topology->role(pi->second->identity().address());
|
||||
|
||||
std::vector<Path> paths(pi->second->paths());
|
||||
Path *bestPath = pi->second->getBestPath(_now);
|
||||
std::vector< SharedPtr<Path> > paths(pi->second->paths(_now));
|
||||
SharedPtr<Path> bestp(pi->second->getBestPath(_now,false));
|
||||
p->pathCount = 0;
|
||||
for(std::vector<Path>::iterator path(paths.begin());path!=paths.end();++path) {
|
||||
memcpy(&(p->paths[p->pathCount].address),&(path->address()),sizeof(struct sockaddr_storage));
|
||||
p->paths[p->pathCount].lastSend = path->lastSend();
|
||||
p->paths[p->pathCount].lastReceive = path->lastReceived();
|
||||
p->paths[p->pathCount].active = path->active(_now) ? 1 : 0;
|
||||
p->paths[p->pathCount].preferred = ((bestPath)&&(*path == *bestPath)) ? 1 : 0;
|
||||
p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust(path->address());
|
||||
for(std::vector< SharedPtr<Path> >::iterator path(paths.begin());path!=paths.end();++path) {
|
||||
memcpy(&(p->paths[p->pathCount].address),&((*path)->address()),sizeof(struct sockaddr_storage));
|
||||
p->paths[p->pathCount].lastSend = (*path)->lastOut();
|
||||
p->paths[p->pathCount].lastReceive = (*path)->lastIn();
|
||||
p->paths[p->pathCount].trustedPathId = RR->topology->getOutboundPathTrust((*path)->address());
|
||||
p->paths[p->pathCount].linkQuality = (int)(*path)->linkQuality();
|
||||
p->paths[p->pathCount].expired = 0;
|
||||
p->paths[p->pathCount].preferred = ((*path) == bestp) ? 1 : 0;
|
||||
++p->pathCount;
|
||||
}
|
||||
}
|
||||
|
@ -508,12 +472,28 @@ void Node::clearLocalInterfaceAddresses()
|
|||
_directPaths.clear();
|
||||
}
|
||||
|
||||
int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
|
||||
{
|
||||
try {
|
||||
if (RR->identity.address().toInt() != dest) {
|
||||
Packet outp(Address(dest),RR->identity.address(),Packet::VERB_USER_MESSAGE);
|
||||
outp.append(typeId);
|
||||
outp.append(data,len);
|
||||
outp.compress();
|
||||
RR->sw->send(tptr,outp,true);
|
||||
return 1;
|
||||
}
|
||||
} catch ( ... ) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Node::setNetconfMaster(void *networkControllerInstance)
|
||||
{
|
||||
RR->localNetworkController = reinterpret_cast<NetworkController *>(networkControllerInstance);
|
||||
RR->localNetworkController->init(RR->identity,this);
|
||||
}
|
||||
|
||||
ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
ZT_ResultCode Node::circuitTestBegin(void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
{
|
||||
if (test->hopCount > 0) {
|
||||
try {
|
||||
|
@ -543,7 +523,7 @@ ZT_ResultCode Node::circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)
|
|||
for(unsigned int a=0;a<test->hops[0].breadth;++a) {
|
||||
outp.newInitializationVector();
|
||||
outp.setDestination(Address(test->hops[0].addresses[a]));
|
||||
RR->sw->send(outp,true,0);
|
||||
RR->sw->send(tptr,outp,true);
|
||||
}
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL; // probably indicates FIFO too big for packet
|
||||
|
@ -639,29 +619,17 @@ void Node::clusterStatus(ZT_ClusterStatus *cs)
|
|||
memset(cs,0,sizeof(ZT_ClusterStatus));
|
||||
}
|
||||
|
||||
void Node::backgroundThreadMain()
|
||||
{
|
||||
++RR->dpEnabled;
|
||||
for(;;) {
|
||||
try {
|
||||
if (RR->dp->process() < 0)
|
||||
break;
|
||||
} catch ( ... ) {} // sanity check -- should not throw
|
||||
}
|
||||
--RR->dpEnabled;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Node methods used only within node/ */
|
||||
/****************************************************************************/
|
||||
|
||||
std::string Node::dataStoreGet(const char *name)
|
||||
std::string Node::dataStoreGet(void *tPtr,const char *name)
|
||||
{
|
||||
char buf[1024];
|
||||
std::string r;
|
||||
unsigned long olen = 0;
|
||||
do {
|
||||
long n = _dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
|
||||
long n = _cb.dataStoreGetFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,name,buf,sizeof(buf),(unsigned long)r.length(),&olen);
|
||||
if (n <= 0)
|
||||
return std::string();
|
||||
r.append(buf,n);
|
||||
|
@ -669,11 +637,14 @@ std::string Node::dataStoreGet(const char *name)
|
|||
return r;
|
||||
}
|
||||
|
||||
bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const InetAddress &remoteAddress)
|
||||
bool Node::shouldUsePathForZeroTierTraffic(void *tPtr,const Address &ztaddr,const InetAddress &localAddress,const InetAddress &remoteAddress)
|
||||
{
|
||||
if (!Path::isAddressValidForPath(remoteAddress))
|
||||
return false;
|
||||
|
||||
if (RR->topology->isProhibitedEndpoint(ztaddr,remoteAddress))
|
||||
return false;
|
||||
|
||||
{
|
||||
Mutex::Lock _l(_networks_m);
|
||||
for(std::vector< std::pair< uint64_t, SharedPtr<Network> > >::const_iterator i=_networks.begin();i!=_networks.end();++i) {
|
||||
|
@ -686,9 +657,7 @@ bool Node::shouldUsePathForZeroTierTraffic(const InetAddress &localAddress,const
|
|||
}
|
||||
}
|
||||
|
||||
if (_pathCheckFunction)
|
||||
return (_pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0);
|
||||
else return true;
|
||||
return ( (_cb.pathCheckFunction) ? (_cb.pathCheckFunction(reinterpret_cast<ZT_Node *>(this),_uPtr,tPtr,ztaddr.toInt(),reinterpret_cast<const struct sockaddr_storage *>(&localAddress),reinterpret_cast<const struct sockaddr_storage *>(&remoteAddress)) != 0) : true);
|
||||
}
|
||||
|
||||
#ifdef ZT_TRACE
|
||||
|
@ -720,16 +689,20 @@ void Node::postTrace(const char *module,unsigned int line,const char *fmt,...)
|
|||
tmp2[sizeof(tmp2)-1] = (char)0;
|
||||
|
||||
Utils::snprintf(tmp1,sizeof(tmp1),"[%s] %s:%u %s",nowstr,module,line,tmp2);
|
||||
postEvent(ZT_EVENT_TRACE,tmp1);
|
||||
postEvent((void *)0,ZT_EVENT_TRACE,tmp1);
|
||||
}
|
||||
#endif // ZT_TRACE
|
||||
|
||||
uint64_t Node::prng()
|
||||
{
|
||||
unsigned int p = (++_prngStreamPtr % (sizeof(_prngStream) / sizeof(uint64_t)));
|
||||
if (!p)
|
||||
_prng.encrypt12(_prngStream,_prngStream,sizeof(_prngStream));
|
||||
return _prngStream[p];
|
||||
// https://en.wikipedia.org/wiki/Xorshift#xorshift.2B
|
||||
uint64_t x = _prngState[0];
|
||||
const uint64_t y = _prngState[1];
|
||||
_prngState[0] = y;
|
||||
x ^= x << 23;
|
||||
const uint64_t z = x ^ y ^ (x >> 17) ^ (y >> 26);
|
||||
_prngState[1] = z;
|
||||
return z + y;
|
||||
}
|
||||
|
||||
void Node::postCircuitTestReport(const ZT_CircuitTestReport *report)
|
||||
|
@ -751,6 +724,120 @@ void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_
|
|||
RR->topology->setTrustedPaths(reinterpret_cast<const InetAddress *>(networks),ids,count);
|
||||
}
|
||||
|
||||
World Node::planet() const
|
||||
{
|
||||
return RR->topology->planet();
|
||||
}
|
||||
|
||||
std::vector<World> Node::moons() const
|
||||
{
|
||||
return RR->topology->moons();
|
||||
}
|
||||
|
||||
void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
|
||||
{
|
||||
if (destination == RR->identity.address()) {
|
||||
SharedPtr<Network> n(network(nwid));
|
||||
if (!n) return;
|
||||
n->setConfiguration((void *)0,nc,true);
|
||||
} else {
|
||||
Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> *dconf = new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>();
|
||||
try {
|
||||
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
|
||||
uint64_t configUpdateId = prng();
|
||||
if (!configUpdateId) ++configUpdateId;
|
||||
|
||||
const unsigned int totalSize = dconf->sizeBytes();
|
||||
unsigned int chunkIndex = 0;
|
||||
while (chunkIndex < totalSize) {
|
||||
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_UDP_DEFAULT_PAYLOAD_MTU - (ZT_PACKET_IDX_PAYLOAD + 256)));
|
||||
Packet outp(destination,RR->identity.address(),(requestPacketId) ? Packet::VERB_OK : Packet::VERB_NETWORK_CONFIG);
|
||||
if (requestPacketId) {
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
}
|
||||
|
||||
const unsigned int sigStart = outp.size();
|
||||
outp.append(nwid);
|
||||
outp.append((uint16_t)chunkLen);
|
||||
outp.append((const void *)(dconf->data() + chunkIndex),chunkLen);
|
||||
|
||||
outp.append((uint8_t)0); // no flags
|
||||
outp.append((uint64_t)configUpdateId);
|
||||
outp.append((uint32_t)totalSize);
|
||||
outp.append((uint32_t)chunkIndex);
|
||||
|
||||
C25519::Signature sig(RR->identity.sign(reinterpret_cast<const uint8_t *>(outp.data()) + sigStart,outp.size() - sigStart));
|
||||
outp.append((uint8_t)1);
|
||||
outp.append((uint16_t)ZT_C25519_SIGNATURE_LEN);
|
||||
outp.append(sig.data,ZT_C25519_SIGNATURE_LEN);
|
||||
|
||||
outp.compress();
|
||||
RR->sw->send((void *)0,outp,true);
|
||||
chunkIndex += chunkLen;
|
||||
}
|
||||
}
|
||||
delete dconf;
|
||||
} catch ( ... ) {
|
||||
delete dconf;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
|
||||
{
|
||||
if (destination == RR->identity.address()) {
|
||||
SharedPtr<Network> n(network(rev.networkId()));
|
||||
if (!n) return;
|
||||
n->addCredential((void *)0,RR->identity.address(),rev);
|
||||
} else {
|
||||
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
|
||||
outp.append((uint8_t)0x00);
|
||||
outp.append((uint16_t)0);
|
||||
outp.append((uint16_t)0);
|
||||
outp.append((uint16_t)1);
|
||||
rev.serialize(outp);
|
||||
outp.append((uint16_t)0);
|
||||
RR->sw->send((void *)0,outp,true);
|
||||
}
|
||||
}
|
||||
|
||||
void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode)
|
||||
{
|
||||
if (destination == RR->identity.address()) {
|
||||
SharedPtr<Network> n(network(nwid));
|
||||
if (!n) return;
|
||||
switch(errorCode) {
|
||||
case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||
case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||
n->setNotFound();
|
||||
break;
|
||||
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||
n->setAccessDenied();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else if (requestPacketId) {
|
||||
Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
|
||||
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
|
||||
outp.append(requestPacketId);
|
||||
switch(errorCode) {
|
||||
//case NetworkController::NC_ERROR_OBJECT_NOT_FOUND:
|
||||
//case NetworkController::NC_ERROR_INTERNAL_SERVER_ERROR:
|
||||
default:
|
||||
outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND);
|
||||
break;
|
||||
case NetworkController::NC_ERROR_ACCESS_DENIED:
|
||||
outp.append((unsigned char)Packet::ERROR_NETWORK_ACCESS_DENIED_);
|
||||
break;
|
||||
}
|
||||
outp.append(nwid);
|
||||
RR->sw->send((void *)0,outp,true);
|
||||
} // else we can't send an ERROR() in response to nothing, so discard
|
||||
}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
/****************************************************************************/
|
||||
|
@ -759,21 +846,11 @@ void Node::setTrustedPaths(const struct sockaddr_storage *networks,const uint64_
|
|||
|
||||
extern "C" {
|
||||
|
||||
enum ZT_ResultCode ZT_Node_new(
|
||||
ZT_Node **node,
|
||||
void *uptr,
|
||||
uint64_t now,
|
||||
ZT_DataStoreGetFunction dataStoreGetFunction,
|
||||
ZT_DataStorePutFunction dataStorePutFunction,
|
||||
ZT_WirePacketSendFunction wirePacketSendFunction,
|
||||
ZT_VirtualNetworkFrameFunction virtualNetworkFrameFunction,
|
||||
ZT_VirtualNetworkConfigFunction virtualNetworkConfigFunction,
|
||||
ZT_PathCheckFunction pathCheckFunction,
|
||||
ZT_EventCallback eventCallback)
|
||||
enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,uint64_t now)
|
||||
{
|
||||
*node = (ZT_Node *)0;
|
||||
try {
|
||||
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(now,uptr,dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigFunction,pathCheckFunction,eventCallback));
|
||||
*node = reinterpret_cast<ZT_Node *>(new ZeroTier::Node(uptr,tptr,callbacks,now));
|
||||
return ZT_RESULT_OK;
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -793,6 +870,7 @@ void ZT_Node_delete(ZT_Node *node)
|
|||
|
||||
enum ZT_ResultCode ZT_Node_processWirePacket(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
uint64_t now,
|
||||
const struct sockaddr_storage *localAddress,
|
||||
const struct sockaddr_storage *remoteAddress,
|
||||
|
@ -801,7 +879,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(tptr,now,localAddress,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -811,6 +889,7 @@ enum ZT_ResultCode ZT_Node_processWirePacket(
|
|||
|
||||
enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
||||
ZT_Node *node,
|
||||
void *tptr,
|
||||
uint64_t now,
|
||||
uint64_t nwid,
|
||||
uint64_t sourceMac,
|
||||
|
@ -822,7 +901,7 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
|||
volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -830,10 +909,10 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame(
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,void *tptr,uint64_t now,volatile uint64_t *nextBackgroundTaskDeadline)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(now,nextBackgroundTaskDeadline);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->processBackgroundTasks(tptr,now,nextBackgroundTaskDeadline);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -841,10 +920,10 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node,uint64_t now,vol
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
|
||||
enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid,uptr);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid,uptr,tptr);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -852,10 +931,10 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr)
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr)
|
||||
enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid,uptr);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid,uptr,tptr);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -863,10 +942,10 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr)
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
|
||||
enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node,void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(nwid,multicastGroup,multicastAdi);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(tptr,nwid,multicastGroup,multicastAdi);
|
||||
} catch (std::bad_alloc &exc) {
|
||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||
} catch ( ... ) {
|
||||
|
@ -885,6 +964,24 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
|
|||
}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_orbit(ZT_Node *node,void *tptr,uint64_t moonWorldId,uint64_t moonSeed)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->orbit(tptr,moonWorldId,moonSeed);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
ZT_ResultCode ZT_Node_deorbit(ZT_Node *node,void *tptr,uint64_t moonWorldId)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->deorbit(tptr,moonWorldId);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ZT_Node_address(ZT_Node *node)
|
||||
{
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->address();
|
||||
|
@ -947,6 +1044,15 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node)
|
|||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
int ZT_Node_sendUserMessage(ZT_Node *node,void *tptr,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(tptr,dest,typeId,data,len);
|
||||
} catch ( ... ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
|
||||
{
|
||||
try {
|
||||
|
@ -954,10 +1060,10 @@ void ZT_Node_setNetconfMaster(ZT_Node *node,void *networkControllerInstance)
|
|||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
enum ZT_ResultCode ZT_Node_circuitTestBegin(ZT_Node *node,void *tptr,ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *))
|
||||
{
|
||||
try {
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(test,reportCallback);
|
||||
return reinterpret_cast<ZeroTier::Node *>(node)->circuitTestBegin(tptr,test,reportCallback);
|
||||
} catch ( ... ) {
|
||||
return ZT_RESULT_FATAL_ERROR_INTERNAL;
|
||||
}
|
||||
|
@ -1027,13 +1133,6 @@ void ZT_Node_setTrustedPaths(ZT_Node *node,const struct sockaddr_storage *networ
|
|||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
void ZT_Node_backgroundThreadMain(ZT_Node *node)
|
||||
{
|
||||
try {
|
||||
reinterpret_cast<ZeroTier::Node *>(node)->backgroundThreadMain();
|
||||
} catch ( ... ) {}
|
||||
}
|
||||
|
||||
void ZT_version(int *major,int *minor,int *revision)
|
||||
{
|
||||
if (major) *major = ZEROTIER_ONE_VERSION_MAJOR;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue