This commit is contained in:
Adam Ierymenko 2019-09-20 18:48:48 -07:00
parent e0ddbc2f28
commit b34aa10bf8
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
15 changed files with 668 additions and 300 deletions

View file

@ -20,7 +20,6 @@
#include "../../node/MAC.hpp"
#include "../../node/Address.hpp"
#include "../../osdep/OSUtils.hpp"
#include "../../osdep/BlockingQueue.hpp"
#include "../../osdep/EthernetTap.hpp"
#include <string.h>
@ -89,10 +88,6 @@ struct ZT_GoNode_Impl
Node *node;
volatile int64_t nextBackgroundTaskDeadline;
int (*goPathCheckFunc)(ZT_GoNode *,ZT_Node *,uint64_t ztAddress,const void *);
int (*goPathLookupFunc)(ZT_GoNode *,ZT_Node *,int desiredAddressFamily,void *);
int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize);
std::string path;
std::atomic_bool run;
@ -102,12 +97,19 @@ struct ZT_GoNode_Impl
std::map< uint64_t,std::shared_ptr<EthernetTap> > taps;
std::mutex taps_l;
BlockingQueue<ZT_GoNodeEvent> eq;
std::thread backgroundTaskThread;
};
//////////////////////////////////////////////////////////////////////////////
/****************************************************************************/
/* These functions are implemented in Go in pkg/ztnode/node-callbacks.go */
extern "C" int goPathCheckFunc(ZT_GoNode *,uint64_t,int,const void *,int);
extern "C" int goPathLookupFunc(ZT_GoNode *,uint64_t,int,int *,uint8_t [16],int *);
extern "C" void goStateObjectPutFunc(ZT_GoNode *,int,const uint64_t [2],const void *,int);
extern "C" int goStateObjectGetFunc(ZT_GoNode *,int,const uint64_t [2],void *,unsigned int);
extern "C" void goDNSResolverFunc(ZT_GoNode *,const uint8_t *,int,const char *,uintptr_t);
extern "C" int goVirtualNetworkConfigFunc(ZT_GoNode *,ZT_GoTap *,uint64_t,int,const ZT_VirtualNetworkConfig *);
extern "C" void goZtEvent(ZT_GoNode *,int,const void *);
static int ZT_GoNode_VirtualNetworkConfigFunction(
ZT_Node *node,
@ -118,13 +120,7 @@ static int ZT_GoNode_VirtualNetworkConfigFunction(
enum ZT_VirtualNetworkConfigOperation op,
const ZT_VirtualNetworkConfig *cfg)
{
ZT_GoNodeEvent ev;
ev.type = ZT_GONODE_EVENT_NETWORK_CONFIG_UPDATE;
ev.data.nconf.op = op;
if (cfg)
ev.data.nconf.conf = *cfg;
reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
return 0;
return goVirtualNetworkConfigFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoTap *>(*nptr),nwid,op,cfg);
}
static void ZT_GoNode_VirtualNetworkFrameFunction(
@ -151,10 +147,7 @@ static void ZT_GoNode_EventCallback(
enum ZT_Event et,
const void *data)
{
ZT_GoNodeEvent ev;
ev.type = ZT_GONODE_EVENT_ZTEVENT;
ev.data.zt.type = et;
reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
goZtEvent(reinterpret_cast<ZT_GoNode *>(uptr),et,data);
}
static void ZT_GoNode_StatePutFunction(
@ -166,18 +159,7 @@ static void ZT_GoNode_StatePutFunction(
const void *data,
int len)
{
if (len < ZT_MAX_STATE_OBJECT_SIZE) { // sanity check
ZT_GoNodeEvent ev;
ev.type = (len >= 0) ? ZT_GONODE_EVENT_STATE_PUT : ZT_GONODE_EVENT_STATE_DELETE;
if (len > 0) {
memcpy(ev.data.sobj.data,data,len);
ev.data.sobj.len = (unsigned int)len;
}
ev.data.sobj.objType = objType;
ev.data.sobj.id[0] = id[0];
ev.data.sobj.id[1] = id[1];
reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
}
goStateObjectPutFunc(reinterpret_cast<ZT_GoNode *>(uptr),objType,id,data,len);
}
static int ZT_GoNode_StateGetFunction(
@ -189,7 +171,12 @@ static int ZT_GoNode_StateGetFunction(
void *buf,
unsigned int buflen)
{
return reinterpret_cast<ZT_GoNode *>(uptr)->goStateObjectGetFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,(int)objType,id,buf,buflen);
return goStateObjectGetFunc(
reinterpret_cast<ZT_GoNode *>(uptr),
(int)objType,
id,
buf,
buflen);
}
static ZT_ALWAYS_INLINE void doUdpSend(ZT_SOCKET sock,const struct sockaddr_storage *addr,const void *data,const unsigned int len,const unsigned int ipTTL)
@ -254,7 +241,23 @@ static int ZT_GoNode_PathCheckFunction(
int64_t localSocket,
const struct sockaddr_storage *sa)
{
return reinterpret_cast<ZT_GoNode *>(uptr)->goPathCheckFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,ztAddress,sa);
switch(sa->ss_family) {
case AF_INET:
return goPathCheckFunc(
reinterpret_cast<ZT_GoNode *>(uptr),
ztAddress,
AF_INET,
&(reinterpret_cast<const struct sockaddr_in *>(sa)->sin_addr.s_addr),
Utils::ntoh((uint16_t)reinterpret_cast<const struct sockaddr_in *>(sa)->sin_port));
case AF_INET6:
return goPathCheckFunc(
reinterpret_cast<ZT_GoNode *>(uptr),
ztAddress,
AF_INET6,
reinterpret_cast<const struct sockaddr_in6 *>(sa)->sin6_addr.s6_addr,
Utils::ntoh((uint16_t)reinterpret_cast<const struct sockaddr_in6 *>(sa)->sin6_port));
}
return 0;
}
static int ZT_GoNode_PathLookupFunction(
@ -265,7 +268,32 @@ static int ZT_GoNode_PathLookupFunction(
int desiredAddressFamily,
struct sockaddr_storage *sa)
{
return reinterpret_cast<ZT_GoNode *>(uptr)->goPathLookupFunc(reinterpret_cast<ZT_GoNode *>(uptr),reinterpret_cast<ZT_GoNode *>(uptr)->node,desiredAddressFamily,sa);
int family = 0;
uint8_t ip[16];
int port = 0;
const int result = goPathLookupFunc(
reinterpret_cast<ZT_GoNode *>(uptr),
ztAddress,
desiredAddressFamily,
&family,
ip,
&port
);
if (result != 0) {
switch(family) {
case AF_INET:
reinterpret_cast<struct sockaddr_in *>(sa)->sin_family = AF_INET;
memcpy(&(reinterpret_cast<struct sockaddr_in *>(sa)->sin_addr.s_addr),ip,4);
reinterpret_cast<struct sockaddr_in *>(sa)->sin_port = Utils::hton((uint16_t)port);
return 1;
case AF_INET6:
reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_family = AF_INET6;
memcpy(reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_addr.s6_addr,ip,16);
reinterpret_cast<struct sockaddr_in6 *>(sa)->sin6_port = Utils::hton((uint16_t)port);
return 1;
}
}
return 0;
}
static void ZT_GoNode_DNSResolver(
@ -277,19 +305,14 @@ static void ZT_GoNode_DNSResolver(
const char *name,
uintptr_t requestId)
{
ZT_GoNodeEvent ev;
ev.type = ZT_GONODE_EVENT_DNS_GET_TXT;
Utils::scopy(ev.data.dns.dnsName,sizeof(ev.data.dns.dnsName),name);
reinterpret_cast<ZT_GoNode *>(uptr)->eq.post(ev);
uint8_t t[256];
for(unsigned int i=0;(i<numTypes)&&(i<256);++i) t[i] = (uint8_t)types[i];
goDNSResolverFunc(reinterpret_cast<ZT_GoNode *>(uptr),t,(int)numTypes,name,requestId);
}
//////////////////////////////////////////////////////////////////////////////
/****************************************************************************/
extern "C" ZT_GoNode *ZT_GoNode_new(
const char *workingPath,
int (*goPathCheckFunc)(ZT_GoNode *,ZT_Node *,uint64_t ztAddress,const void *),
int (*goPathLookupFunc)(ZT_GoNode *,ZT_Node *,int desiredAddressFamily,void *),
int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize))
extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath)
{
try {
struct ZT_Node_Callbacks cb;
@ -307,9 +330,6 @@ extern "C" ZT_GoNode *ZT_GoNode_new(
const int64_t now = OSUtils::now();
gn->node = new Node(reinterpret_cast<void *>(gn),nullptr,&cb,now);
gn->nextBackgroundTaskDeadline = now;
gn->goPathCheckFunc = goPathCheckFunc;
gn->goPathLookupFunc = goPathLookupFunc;
gn->goStateObjectGetFunc = goStateObjectGetFunc;
gn->path = workingPath;
gn->run = true;
@ -333,10 +353,6 @@ extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
{
gn->run = false;
ZT_GoNodeEvent sd;
sd.type = ZT_GONODE_EVENT_SHUTDOWN;
gn->eq.post(sd);
gn->threads_l.lock();
for(auto t=gn->threads.begin();t!=gn->threads.end();++t) {
t->second.run = false;
@ -358,11 +374,6 @@ extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
delete gn;
}
extern "C" ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn)
{
return gn->node;
}
// Sets flags and socket options common to both IPv4 and IPv6 UDP sockets
static void setCommonUdpSocketSettings(ZT_SOCKET udpSock,const char *dev)
{
@ -521,11 +532,6 @@ extern "C" int ZT_GoNode_phyStopListen(ZT_GoNode *gn,const char *dev,const char
return 0;
}
extern "C" void ZT_GoNode_waitForEvent(ZT_GoNode *gn,ZT_GoNodeEvent *ev)
{
gn->eq.get(*ev);
}
static void tapFrameHandler(void *uptr,void *tptr,uint64_t nwid,const MAC &from,const MAC &to,unsigned int etherType,unsigned int vlanId,const void *data,unsigned int len)
{
ZT_GoNode *const gn = reinterpret_cast<ZT_GoNode *>(uptr);
@ -561,3 +567,78 @@ extern "C" void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid)
gn->taps.erase(existingTap);
}
}
/****************************************************************************/
extern "C" void ZT_GoTap_setEnabled(ZT_GoTap *tap,int enabled)
{
reinterpret_cast<EthernetTap *>(tap)->setEnabled(enabled != 0);
}
extern "C" int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int port)
{
switch(af) {
case AF_INET:
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,4,(unsigned int)port)) ? 1 : 0);
case AF_INET6:
return (reinterpret_cast<EthernetTap *>(tap)->addIp(InetAddress(ip,16,(unsigned int)port)) ? 1 : 0);
}
return 0;
}
extern "C" int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int port)
{
switch(af) {
case AF_INET:
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,4,(unsigned int)port)) ? 1 : 0);
case AF_INET6:
return (reinterpret_cast<EthernetTap *>(tap)->removeIp(InetAddress(ip,16,(unsigned int)port)) ? 1 : 0);
}
return 0;
}
extern "C" int ZT_GoTap_ips(ZT_GoTap *tap,void *buf,unsigned int bufSize)
{
auto ips = reinterpret_cast<EthernetTap *>(tap)->ips();
unsigned int p = 0;
uint8_t *const b = reinterpret_cast<uint8_t *>(buf);
for(auto ip=ips.begin();ip!=ips.end();++ip) {
if ((p + 7) > bufSize)
break;
const uint8_t *const ipd = reinterpret_cast<const uint8_t *>(ip->rawIpData());
const unsigned int port = ip->port();
if (ip->isV4()) {
b[p++] = AF_INET;
b[p++] = ipd[0];
b[p++] = ipd[1];
b[p++] = ipd[2];
b[p++] = ipd[3];
b[p++] = (uint8_t)((port >> 8) & 0xff);
b[p++] = (uint8_t)(port & 0xff);
} else if (ip->isV6()) {
if ((p + 19) <= bufSize) {
b[p++] = AF_INET6;
for(int j=0;j<16;++j)
b[p++] = ipd[j];
b[p++] = (uint8_t)((port >> 8) & 0xff);
b[p++] = (uint8_t)(port & 0xff);
}
}
}
return (int)p;
}
extern "C" void ZT_GoTap_deviceName(ZT_GoTap *tap,char nbuf[256])
{
Utils::scopy(nbuf,256,reinterpret_cast<EthernetTap *>(tap)->deviceName().c_str());
}
extern "C" void ZT_GoTap_setFriendlyName(ZT_GoTap *tap,const char *friendlyName)
{
reinterpret_cast<EthernetTap *>(tap)->setFriendlyName(friendlyName);
}
extern "C" void ZT_GoTap_setMtu(ZT_GoTap *tap,unsigned int mtu)
{
reinterpret_cast<EthernetTap *>(tap)->setMtu(mtu);
}