More Go boilerplate.

This commit is contained in:
Adam Ierymenko 2019-09-20 14:11:15 -07:00
parent ae2120eb96
commit ed2024285d
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
7 changed files with 154 additions and 11 deletions

View File

@ -2,11 +2,11 @@ cmake_minimum_required(VERSION 2.8)
project(zt_go_native)
set(src
GoNode.cpp
GoGlue.cpp
)
set(headers
GoNode.h
GoGlue.h
)
add_library(${PROJECT_NAME} STATIC ${src} ${headers})

View File

@ -11,12 +11,14 @@
*/
/****/
#include "GoNode.h"
#include "GoGlue.h"
#include "../../node/Constants.hpp"
#include "../../node/InetAddress.hpp"
#include "../../node/Node.hpp"
#include "../../node/Utils.hpp"
#include "../../node/MAC.hpp"
#include "../../node/Address.hpp"
#include "../../osdep/OSUtils.hpp"
#include "../../osdep/BlockingQueue.hpp"
#include "../../osdep/EthernetTap.hpp"
@ -55,6 +57,7 @@
#include <vector>
#include <array>
#include <set>
#include <memory>
#ifdef __WINDOWS__
#define SETSOCKOPT_FLAG_TYPE BOOL
@ -90,10 +93,18 @@ struct ZT_GoNode_Impl
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;
std::map< ZT_SOCKET,ZT_GoNodeThread > threads;
std::mutex threads_l;
std::map< uint64_t,std::shared_ptr<EthernetTap> > taps;
std::mutex taps_l;
BlockingQueue<ZT_GoNodeEvent> eq;
std::thread backgroundTaskThread;
};
//////////////////////////////////////////////////////////////////////////////
@ -273,10 +284,10 @@ static void ZT_GoNode_DNSResolver(
//////////////////////////////////////////////////////////////////////////////
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)
)
int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize))
{
try {
struct ZT_Node_Callbacks cb;
@ -296,6 +307,18 @@ extern "C" ZT_GoNode *ZT_GoNode_new(
gn->goPathCheckFunc = goPathCheckFunc;
gn->goPathLookupFunc = goPathLookupFunc;
gn->goStateObjectGetFunc = goStateObjectGetFunc;
gn->path = workingPath;
gn->run = true;
gn->backgroundTaskThread = std::thread([gn] {
while (gn->run) {
std::this_thread::sleep_for(std::chrono::milliseconds(250));
const int64_t now = OSUtils::now();
if (now >= gn->nextBackgroundTaskDeadline)
gn->node->processBackgroundTasks(nullptr,now,&(gn->nextBackgroundTaskDeadline));
}
});
return gn;
} catch ( ... ) {
fprintf(stderr,"FATAL: unable to create new instance of Node (out of memory?)" ZT_EOL_S);
@ -305,6 +328,8 @@ extern "C" ZT_GoNode *ZT_GoNode_new(
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);
@ -321,6 +346,14 @@ extern "C" void ZT_GoNode_delete(ZT_GoNode *gn)
for(auto t=th.begin();t!=th.end();++t)
t->join();
gn->taps_l.lock();
for(auto t=gn->taps.begin();t!=gn->taps.end();++t)
gn->node->leave(t->first,nullptr,nullptr);
gn->taps.clear();
gn->taps_l.unlock();
gn->backgroundTaskThread.join();
delete gn->node;
delete gn;
}
@ -491,3 +524,39 @@ extern "C" int 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);
gn->node->processVirtualNetworkFrame(tptr,OSUtils::now(),nwid,from.toInt(),to.toInt(),etherType,vlanId,data,len,&(gn->nextBackgroundTaskDeadline));
}
extern "C" ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn,uint64_t nwid)
{
try {
std::lock_guard<std::mutex> l(gn->taps_l);
auto existingTap = gn->taps.find(nwid);
if (existingTap != gn->taps.end())
return (ZT_GoTap *)existingTap->second.get();
char tmp[256];
OSUtils::ztsnprintf(tmp,sizeof(tmp),"ZeroTier Network %.16llx",(unsigned long long)nwid);
std::shared_ptr<EthernetTap> tap(EthernetTap::newInstance(nullptr,gn->path.c_str(),MAC(Address(gn->node->address()),nwid),ZT_DEFAULT_MTU,0,nwid,tmp,&tapFrameHandler,gn));
if (!tap)
return nullptr;
gn->taps[nwid] = tap;
gn->node->join(nwid,tap.get(),nullptr);
return (ZT_GoTap *)tap.get();
} catch ( ... ) {
return nullptr;
}
}
extern "C" void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid)
{
std::lock_guard<std::mutex> l(gn->taps_l);
auto existingTap = gn->taps.find(nwid);
if (existingTap != gn->taps.end()) {
gn->node->leave(nwid,nullptr,nullptr);
gn->taps.erase(existingTap);
}
}

View File

@ -20,6 +20,14 @@
#include "../../include/ZeroTierCore.h"
/****************************************************************************/
/* A pointer to an instance of EthernetTap */
typedef void ZT_GoTap;
/* ZT_GoNode is a C struct and functions that wraps ZT_Node for use via cgo. It
* performs UDP and other direct I/O in C for performance but otherwise lets
* the Go code control the node's behavior. */
struct ZT_GoNode_Impl;
typedef struct ZT_GoNode_Impl ZT_GoNode;
@ -65,6 +73,7 @@ struct ZT_GoNodeEvent_Impl
/* Network configuration update event */
struct {
ZT_GoTap *tap;
int op; /* ZT_VirtualNetworkConfigOperation */
ZT_VirtualNetworkConfig conf;
} nconf;
@ -73,27 +82,63 @@ struct ZT_GoNodeEvent_Impl
typedef struct ZT_GoNodeEvent_Impl ZT_GoNodeEvent;
#ifndef __cplusplus
/****************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************************/
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)
);
int (*goStateObjectGetFunc)(ZT_GoNode *,ZT_Node *,int objType,const uint64_t id[2],void *buf,unsigned int bufSize));
void ZT_GoNode_delete(ZT_GoNode *gn);
ZT_Node *ZT_GoNode_getNode(ZT_GoNode *gn);
/* This can be called more than once to start multiple listener threads */
int ZT_GoNode_phyStartListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port);
/* Close all listener threads for a given local IP and port */
int ZT_GoNode_phyStopListen(ZT_GoNode *gn,const char *dev,const char *ip,const int port);
int ZT_GoNode_waitForEvent(ZT_GoNode *gn,ZT_GoNodeEvent *ev);
#ifndef __cplusplus
ZT_GoTap *ZT_GoNode_join(ZT_GoNode *gn,uint64_t nwid);
void ZT_GoNode_leave(ZT_GoNode *gn,uint64_t nwid);
/****************************************************************************/
void ZT_GoTap_setEnabled(ZT_GoTap *tap,int enabled);
int ZT_GoTap_addIp(ZT_GoTap *tap,int af,const void *ip,int port);
int ZT_GoTap_removeIp(ZT_GoTap *tap,int af,const void *ip,int port);
/* The buf buffer is filled with tuplies of:
* uint8_t family
* uint8_t ip[4 or 16]
* uint16_t port (big-endian byte order)
*
* This function returns the number of such tuples in the result.
* If the buffer isn't big enough results are incomplete.
*/
int ZT_GoTap_ips(ZT_GoTap *tap,void *buf,unsigned int bufSize);
const char *ZT_GoTap_deviceName(ZT_GoTap *tap);
void ZT_GoTap_setFriendlyName(ZT_GoTap *tap,const char *friendlyName);
void ZT_GoTap_setMtu(ZT_GoTap *tap,unsigned int mtu);
/****************************************************************************/
#ifdef __cplusplus
}
#endif

View File

@ -1851,6 +1851,7 @@ ZT_SDK_API void ZT_Node_processDNSResult(
* @param node Node instance
* @param nwid 64-bit ZeroTier network ID
* @param uptr An arbitrary pointer to associate with this network (default: NULL)
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @return OK (0) or error code if a fatal error condition has occurred
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *uptr,void *tptr);
@ -1868,6 +1869,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_join(ZT_Node *node,uint64_t nwid,void *upt
* @param node Node instance
* @param nwid 64-bit network ID
* @param uptr Target pointer is set to uptr (if not NULL)
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
* @return OK (0) or error code if a fatal error condition has occurred
*/
ZT_SDK_API enum ZT_ResultCode ZT_Node_leave(ZT_Node *node,uint64_t nwid,void **uptr,void *tptr);
@ -2015,6 +2017,17 @@ ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node,uint64_t
*/
ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node);
/**
* Set the network-associated user-defined pointer for a given network
*
* This will have no effect if the network ID is not recognized.
*
* @param node Node instance
* @param nwid Network ID
* @param ptr New network-associated pointer
*/
ZT_SDK_API void ZT_Node_setNetworkUserPtr(ZT_Node *node,uint64_t nwid,void *ptr);
/**
* Free a query result buffer
*

View File

@ -41,8 +41,8 @@ public:
((((uint64_t)d) & 0xffULL) << 16) |
((((uint64_t)e) & 0xffULL) << 8) |
(((uint64_t)f) & 0xffULL) ) {}
ZT_ALWAYS_INLINE MAC(const void *bits,unsigned int len) { setTo(bits,len); }
ZT_ALWAYS_INLINE MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); }
ZT_ALWAYS_INLINE MAC(const void *bits,unsigned int len) { setTo(bits,len); }
ZT_ALWAYS_INLINE MAC(const Address &ztaddr,uint64_t nwid) { fromAddress(ztaddr,nwid); }
ZT_ALWAYS_INLINE MAC(const uint64_t m) : _m(m & 0xffffffffffffULL) {}
/**

View File

@ -598,6 +598,14 @@ ZT_VirtualNetworkList *Node::networks() const
return nl;
}
void Node::setNetworkUserPtr(uint64_t nwid,void *ptr)
{
Mutex::Lock _l(_networks_m);
const SharedPtr<Network> *const nw = _networks.get(nwid);
if (nw)
*((*nw)->userPtr()) = ptr;
}
void Node::freeQueryResult(void *qr)
{
if (qr)
@ -1011,6 +1019,13 @@ ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node)
}
}
void ZT_Node_setNetworkUserPtr(ZT_Node *node,uint64_t nwid,void *ptr)
{
try {
reinterpret_cast<ZeroTier::Node *>(node)->setNetworkUserPtr(nwid,ptr);
} catch ( ... ) {}
}
void ZT_Node_freeQueryResult(ZT_Node *node,void *qr)
{
try {

View File

@ -102,6 +102,7 @@ public:
ZT_PeerList *peers() const;
ZT_VirtualNetworkConfig *networkConfig(uint64_t nwid) const;
ZT_VirtualNetworkList *networks() const;
void setNetworkUserPtr(uint64_t nwid,void *ptr);
void freeQueryResult(void *qr);
int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
void clearLocalInterfaceAddresses();