diff --git a/go/native/GoGlue.cpp b/go/native/GoGlue.cpp index f65182a7d..0def57cfc 100644 --- a/go/native/GoGlue.cpp +++ b/go/native/GoGlue.cpp @@ -96,7 +96,7 @@ struct ZT_GoNode_Impl static const std::string defaultHomePath(OSUtils::platformDefaultHomePath()); const char *ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str(); -/****************************************************************************/ +// -------------------------------------------------------------------------------------------------------------------- /* These functions are implemented in Go in pkg/zerotier/node.go */ extern "C" int goPathCheckFunc(void *,const ZT_Identity *,int,const void *,int); @@ -300,7 +300,7 @@ static int ZT_GoNode_PathLookupFunction( return 0; } -/****************************************************************************/ +// -------------------------------------------------------------------------------------------------------------------- extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr) { diff --git a/go/pkg/zerotier/localconfig.go b/go/pkg/zerotier/localconfig.go index 389d8f795..17bd1d0e2 100644 --- a/go/pkg/zerotier/localconfig.go +++ b/go/pkg/zerotier/localconfig.go @@ -98,7 +98,7 @@ func (lc *LocalConfig) Read(p string, saveDefaultsIfNotExist bool, isTotallyNewN lc.Network = make(map[NetworkID]NetworkLocalSettings) if isTotallyNewNode { - lc.Settings.PrimaryPort = 893 + lc.Settings.PrimaryPort = 793 } else { lc.Settings.PrimaryPort = 9993 } diff --git a/go/pkg/zerotier/misc.go b/go/pkg/zerotier/misc.go index fe44380e9..fca5648f6 100644 --- a/go/pkg/zerotier/misc.go +++ b/go/pkg/zerotier/misc.go @@ -30,7 +30,7 @@ const LogoChar = "⏁" var Base32StdLowerCase = base32.NewEncoding("abcdefghijklmnopqrstuvwxyz234567").WithPadding(base32.NoPadding) // unassignedPrivilegedPorts are ports below 1024 that do not appear to be assigned by IANA. -// The new 2.0+ ZeroTier default is 893, which we will eventually seek to have assigned. These +// The new 2.0+ ZeroTier default is 793, which we will eventually seek to have assigned. These // are searched as backups if this port is already in use on a system. var unassignedPrivilegedPorts = []int{ 4, diff --git a/go/pkg/zerotier/node.go b/go/pkg/zerotier/node.go index e1da9b2aa..396b9ad4d 100644 --- a/go/pkg/zerotier/node.go +++ b/go/pkg/zerotier/node.go @@ -635,7 +635,7 @@ func (n *Node) Peers() []*Peer { return peers } -////////////////////////////////////////////////////////////////////////////// +// -------------------------------------------------------------------------------------------------------------------- func (n *Node) multicastSubscribe(nwid uint64, mg *MulticastGroup) { C.ZT_Node_multicastSubscribe(unsafe.Pointer(n.zn), nil, C.uint64_t(nwid), C.uint64_t(mg.MAC), C.ulong(mg.ADI)) diff --git a/go/pkg/zerotier/selftest.go b/go/pkg/zerotier/selftest.go index d9b89d324..c992745f8 100644 --- a/go/pkg/zerotier/selftest.go +++ b/go/pkg/zerotier/selftest.go @@ -16,24 +16,8 @@ package zerotier //#include "../../native/GoGlue.h" import "C" -import "fmt" - // SelfTest runs a series of tests on the ZeroTier core and the Go service code, returning true on success. // Results are sent to stdout. func SelfTest() bool { - fmt.Print("Running ZeroTier core tests...\n\n") - - if C.ZT_TestOther() != 0 { - return false - } - fmt.Println() - if C.ZT_TestCrypto() != 0 { - return false - } - fmt.Println() - if C.ZT_TestIdentity() != 0 { - return false - } - return true } diff --git a/include/ZeroTierCore.h b/include/ZeroTierCore.h index 54bc60bd3..03a8783ca 100644 --- a/include/ZeroTierCore.h +++ b/include/ZeroTierCore.h @@ -69,7 +69,12 @@ extern "C" { * treat privileged ports in a special way. The old default was 9993 and * this is likely to be seen in the wild quite a bit. */ -#define ZT_DEFAULT_PORT 893 +#define ZT_DEFAULT_PORT 793 + +/** + * Size of a standard I/O buffer as returned by getBuffer(). + */ +#define ZT_BUF_SIZE 16384 /** * Minimum MTU allowed on virtual networks @@ -1728,6 +1733,25 @@ struct ZT_Node_Callbacks ZT_PathLookupFunction pathLookupFunction; }; +/** + * Get a buffer for reading data to be passed back into the core via one of the processX() functions + * + * The size of the returned buffer is 16384 bytes (ZT_BUF_SIZE). + * + * Buffers retrieved with this method MUST be returned to the core via either one of the processX() + * functions (with isZtBuffer set to true) or freeBuffer(). Buffers should not be freed directly using free(). + * + * @return Pointer to I/O buffer + */ +ZT_SDK_API void *ZT_getBuffer(); + +/** + * Free an unused buffer obtained via getBuffer + * + * @param b Buffer to free + */ +ZT_SDK_API void ZT_freeBuffer(void *b); + /** * Create a new ZeroTier node * @@ -1766,6 +1790,7 @@ ZT_SDK_API void ZT_Node_delete(ZT_Node *node,void *tptr); * @param remoteAddress Origin of packet * @param packetData Packet data * @param packetLength Packet length + * @param isZtBuffer If non-zero then packetData is a buffer obtained with ZT_getBuffer() * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @return OK (0) or error code if a fatal error condition has occurred */ @@ -1777,6 +1802,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, + int isZtBuffer, volatile int64_t *nextBackgroundTaskDeadline); /** @@ -1792,6 +1818,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( * @param vlanId 10-bit VLAN ID or 0 if none * @param frameData Frame payload data * @param frameLength Frame payload length + * @param isZtBuffer If non-zero then packetData is a buffer obtained with ZT_getBuffer() * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @return OK (0) or error code if a fatal error condition has occurred */ @@ -1806,6 +1833,7 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( unsigned int vlanId, const void *frameData, unsigned int frameLength, + int isZtBuffer, volatile int64_t *nextBackgroundTaskDeadline); /** diff --git a/node/Buf.hpp b/node/Buf.hpp index ba4caf055..2bdc973f5 100644 --- a/node/Buf.hpp +++ b/node/Buf.hpp @@ -177,9 +177,9 @@ public: /** * Create a new uninitialized buffer with undefined contents (use clear() to zero if needed) */ - ZT_ALWAYS_INLINE Buf() noexcept {} + ZT_ALWAYS_INLINE Buf() noexcept : __nextInPool(0),__refCount(0) {} - ZT_ALWAYS_INLINE Buf(const Buf &b2) noexcept { memcpy(unsafeData,b2.unsafeData,ZT_BUF_MEM_SIZE); } + ZT_ALWAYS_INLINE Buf(const Buf &b2) noexcept : __nextInPool(0),__refCount(0) { memcpy(unsafeData,b2.unsafeData,ZT_BUF_MEM_SIZE); } ZT_ALWAYS_INLINE Buf &operator=(const Buf &b2) noexcept { diff --git a/node/Node.cpp b/node/Node.cpp index 732ce0129..98583599b 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -30,6 +30,8 @@ #include "Expect.hpp" #include "VL1.hpp" #include "VL2.hpp" +#include "Buf.hpp" + namespace ZeroTier { @@ -158,16 +160,12 @@ ZT_ResultCode Node::processWirePacket( int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, - const void *packetData, + SharedPtr &packetData, unsigned int packetLength, volatile int64_t *nextBackgroundTaskDeadline) { _now = now; - // TODO: add buffer life cycle methods - SharedPtr tmp(new Buf()); - packetLength &= ZT_BUF_MEM_MASK; - memcpy(tmp->unsafeData,packetData,packetLength); - RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),tmp,packetLength); + RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),packetData,packetLength); return ZT_RESULT_OK; } @@ -179,14 +177,14 @@ ZT_ResultCode Node::processVirtualNetworkFrame( uint64_t destMac, unsigned int etherType, unsigned int vlanId, - const void *frameData, + SharedPtr &frameData, unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline) { _now = now; SharedPtr nw(this->network(nwid)); if (nw) { - //RR->sw->onLocalEthernet(tptr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); + RR->vl2->onLocalEthernet(tPtr,nw,MAC(sourceMac),MAC(destMac),etherType,vlanId,frameData,frameLength); return ZT_RESULT_OK; } else { return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; @@ -815,6 +813,21 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des extern "C" { +void *ZT_getBuffer() +{ + try { + return (void *)(new ZeroTier::Buf()); // __refCount is left at zero + } catch ( ... ) { + return nullptr; // can only happen on out of memory condition + } +} + +ZT_SDK_API void ZT_freeBuffer(void *b) +{ + if (b) + delete ((ZeroTier::Buf *)b); +} + enum ZT_ResultCode ZT_Node_new(ZT_Node **node,void *uptr,void *tptr,const struct ZT_Node_Callbacks *callbacks,int64_t now) { *node = (ZT_Node *)0; @@ -846,10 +859,18 @@ enum ZT_ResultCode ZT_Node_processWirePacket( const struct sockaddr_storage *remoteAddress, const void *packetData, unsigned int packetLength, + int isZtBuffer, volatile int64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processWirePacket(tptr,now,localSocket,remoteAddress,packetData,packetLength,nextBackgroundTaskDeadline); + ZeroTier::SharedPtr buf; + if (isZtBuffer) { + buf.set((ZeroTier::Buf *)packetData); + } else { + buf.set(new ZeroTier::Buf()); + memcpy(buf->unsafeData,packetData,std::min((unsigned int)ZT_BUF_MEM_SIZE,packetLength)); + } + return reinterpret_cast(node)->processWirePacket(tptr,now,localSocket,remoteAddress,buf,packetLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { @@ -868,10 +889,18 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( unsigned int vlanId, const void *frameData, unsigned int frameLength, + int isZtBuffer, volatile int64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextBackgroundTaskDeadline); + ZeroTier::SharedPtr buf; + if (isZtBuffer) { + buf.set((ZeroTier::Buf *)frameData); + } else { + buf.set(new ZeroTier::Buf()); + memcpy(buf->unsafeData,frameData,std::min((unsigned int)ZT_BUF_MEM_SIZE,frameLength)); + } + return reinterpret_cast(node)->processVirtualNetworkFrame(tptr,now,nwid,sourceMac,destMac,etherType,vlanId,buf,frameLength,nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch ( ... ) { diff --git a/node/Node.hpp b/node/Node.hpp index c564c75c5..f87cadbd5 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -24,6 +24,7 @@ #include "Salsa20.hpp" #include "NetworkController.hpp" #include "Hashtable.hpp" +#include "Buf.hpp" #include #include @@ -72,7 +73,7 @@ public: int64_t now, int64_t localSocket, const struct sockaddr_storage *remoteAddress, - const void *packetData, + SharedPtr &packetData, unsigned int packetLength, volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode processVirtualNetworkFrame( @@ -83,7 +84,7 @@ public: uint64_t destMac, unsigned int etherType, unsigned int vlanId, - const void *frameData, + SharedPtr &frameData, unsigned int frameLength, volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);