diff options
-rw-r--r-- | include/ZeroTierOne.h | 24 | ||||
-rw-r--r-- | node/Network.hpp | 1 | ||||
-rw-r--r-- | node/Node.cpp | 227 | ||||
-rw-r--r-- | node/Node.hpp | 45 |
4 files changed, 273 insertions, 24 deletions
diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 63b3603a..e4a0996d 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -125,7 +125,17 @@ enum ZT1_ResultCode /** * Data store is not writable or has failed */ - ZT1_RESULT_ERROR_DATA_STORE_FAILED = 3 + ZT1_RESULT_ERROR_DATA_STORE_FAILED = 3, + + /** + * Internal error (e.g. unexpected exception, build problem, link problem, etc.) + */ + ZT1_RESULT_ERROR_INTERNAL = 4, + + /** + * Invalid packet or failed authentication + */ + ZT1_RESULT_PACKET_INVALID = 5 }; /** @@ -562,7 +572,7 @@ typedef void (*ZT1_VirtualNetworkFrameFunction)(ZT1_Node *,uint64_t,uint64_t,uin * @param node Result: pointer is set to new node instance on success * @param dataStoreGetFunction Function called to get objects from persistent storage * @param dataStorePutFunction Function called to put objects in persistent storage - * @param networkConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change + * @param virtualNetworkConfigCallback Function to be called when virtual LANs are created, deleted, or their config parameters change * @param statusCallback Function to receive status updates and non-fatal error notices * @return OK (0) or error code if a fatal error condition has occurred */ @@ -572,7 +582,7 @@ enum ZT1_ResultCode ZT1_Node_new( ZT1_DataStorePutFunction *dataStorePutFunction, ZT1_WirePacketSendFunction *wirePacketSendFunction, ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction, - ZT1_VirtualNetworkConfigCallback *networkConfigCallback, + ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback, ZT1_StatusCallback *statusCallback); /** @@ -634,10 +644,7 @@ enum ZT1_ResultCode ZT1_Node_processVirtualNetworkFrame( * @param nextCallDeadline Result: set to deadline for next call to one of the three processXXX() methods * @return OK (0) or error code if a fatal error condition has occurred */ -enum ZT1_Resultcode ZT1_Node_processNothing( - ZT1_Node *node, - uint64_t now, - uint64_t *nextCallDeadline); +enum ZT1_Resultcode ZT1_Node_processNothing(ZT1_Node *node,uint64_t now,uint64_t *nextCallDeadline); /** * Join a network @@ -751,9 +758,10 @@ ZT1_VirtualNetworkList *ZT1_Node_listNetworks(ZT1_Node *node); * * Use this to free the return values of listNetworks(), listPeers(), etc. * + * @param node Node instance * @param qr Query result buffer */ -void ZT1_Node_freeQueryResult(void *qr); +void ZT1_Node_freeQueryResult(ZT1_Node *node,void *qr); /** * Set a network configuration master instance for this node diff --git a/node/Network.hpp b/node/Network.hpp index dfbe4f8b..547b33f2 100644 --- a/node/Network.hpp +++ b/node/Network.hpp @@ -40,7 +40,6 @@ #include "Constants.hpp" #include "NonCopyable.hpp" #include "Utils.hpp" -#include "EthernetTap.hpp" #include "Address.hpp" #include "Mutex.hpp" #include "SharedPtr.hpp" diff --git a/node/Node.cpp b/node/Node.cpp index 0808062f..3a73b461 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -25,6 +25,9 @@ * LLC. Start here: http://www.zerotier.com/ */ +#include "../version.h" + +#include "Constants.hpp" #include "Node.hpp" #include "RuntimeEnvironment.hpp" #include "NetworkConfigMaster.hpp" @@ -46,14 +49,14 @@ Node::Node( ZT1_DataStorePutFunction *dataStorePutFunction, ZT1_WirePacketSendFunction *wirePacketSendFunction, ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction, - ZT1_VirtualNetworkConfigCallback *networkConfigCallback, + ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback, ZT1_StatusCallback *statusCallback) : RR(new RuntimeEnvironment(this)), _dataStoreGetFunction(dataStoreGetFunction), _dataStorePutFunction(dataStorePutFunction), _wirePacketSendFunction(wirePacketSendFunction), _virtualNetworkFrameFunction(virtualNetworkFrameFunction), - _networkConfigCallback(networkConfigCallback), + _virtualNetworkConfigCallback(virtualNetworkConfigCallback), _statusCallback(statusCallback), _networks(), _networks_m(), @@ -91,12 +94,49 @@ Node::~Node() delete RR; } +ZT1_ResultCode Node::processWirePacket( + uint64_t now, + const struct sockaddr_storage *remoteAddress, + int linkDesperation, + const void *packetData, + unsigned int packetLength, + uint64_t *nextCallDeadline) +{ + _now = now; +} + +ZT1_ResultCode Node::processVirtualNetworkFrame( + uint64_t now, + uint64_t nwid, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void *frameData, + unsigned int frameLength, + uint64_t *nextCallDeadline) +{ + _now = now; +} + +ZT1_Resultcode Node::processNothing(uint64_t now,uint64_t *nextCallDeadline) +{ + _now = now; +} + ZT1_ResultCode Node::join(uint64_t nwid) { + Mutex::Lock _l(_networks_m); + SharedPtr<Network> &nw = _networks[nwid]; + if (!nw) + nw = new Network(); + return ZT1_RESULT_OK; } ZT1_ResultCode Node::leave(uint64_t nwid) { + Mutex::Lock _l(_networks_m); + _networks.erase(nwid); } ZT1_ResultCode Node::multicastSubscribe(ZT1_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) @@ -135,3 +175,186 @@ void Node::setNetconfMaster(void *networkConfigMasterInstance) } } // namespace ZeroTier + +extern "C" { + +enum ZT1_ResultCode ZT1_Node_new( + ZT1_Node **node, + ZT1_DataStoreGetFunction *dataStoreGetFunction, + ZT1_DataStorePutFunction *dataStorePutFunction, + ZT1_WirePacketSendFunction *wirePacketSendFunction, + ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction, + ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback, + ZT1_StatusCallback *statusCallback) +{ + *node = (ZT1_Node *)0; + try { + *node = reinterpret_cast<ZT1_Node *>(new ZeroTier::Node(dataStoreGetFunction,dataStorePutFunction,wirePacketSendFunction,virtualNetworkFrameFunction,virtualNetworkConfigCallback,statusCallback)); + return ZT1_RESULT_OK; + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch (std::runtime_error &exc) { + return ZT1_RESULT_ERROR_DATA_STORE_FAILED; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_ResultCode ZT1_Node_processWirePacket( + ZT1_Node *node, + uint64_t now, + const struct sockaddr_storage *remoteAddress, + int linkDesperation, + const void *packetData, + unsigned int packetLength, + uint64_t *nextCallDeadline) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->processWirePacket(now,remoteAddress,linkDesperation,packetData,packetLength,nextCallDeadline); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_PACKET_INVALID; + } +} + +enum ZT1_ResultCode ZT1_Node_processVirtualNetworkFrame( + ZT1_Node *node, + uint64_t now, + uint64_t nwid, + uint64_t sourceMac, + uint64_t destMac, + unsigned int etherType, + unsigned int vlanId, + const void *frameData, + unsigned int frameLength, + uint64_t *nextCallDeadline) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->processVirtualNetworkFrame(now,nwid,sourceMac,destMac,etherType,vlanId,frameData,frameLength,nextCallDeadline); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_Resultcode ZT1_Node_processNothing(ZT1_Node *node,uint64_t now,uint64_t *nextCallDeadline) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->processNothing(now,nextCallDeadline); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_ResultCode ZT1_Node_join(ZT1_Node *node,uint64_t nwid) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->join(nwid); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_ResultCode ZT1_Node_leave(ZT1_Node *node,uint64_t nwid) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->leave(nwid); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_ResultCode ZT1_Node_multicastSubscribe(ZT1_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->multicastSubscribe(nwid,multicastGroup,multicastAdi); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +enum ZT1_ResultCode ZT1_Node_multicastUnsubscribe(ZT1_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->multicastUnsubscribe(nwid,multicastGroup,multicastAdi); + } catch (std::bad_alloc &exc) { + return ZT1_RESULT_ERROR_OUT_OF_MEMORY; + } catch ( ... ) { + return ZT1_RESULT_ERROR_INTERNAL; + } +} + +void ZT1_Node_status(ZT1_Node *node,ZT1_NodeStatus *status) +{ + try { + reinterpret_cast<ZeroTier::Node *>(node)->status(status); + } catch ( ... ) {} +} + +ZT1_PeerList *ZT1_Node_peers(ZT1_Node *node) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->peers(); + } catch ( ... ) { + return (ZT1_PeerList *)0; + } +} + +ZT1_VirtualNetworkConfig *ZT1_Node_networkConfig(ZT1_Node *node,uint64_t nwid) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->networkConfig(nwid); + } catch ( ... ) { + return (ZT1_VirtualNetworkConfig *)0; + } +} + +ZT1_VirtualNetworkList *ZT1_Node_listNetworks(ZT1_Node *node) +{ + try { + return reinterpret_cast<ZeroTier::Node *>(node)->listNetworks(); + } catch ( ... ) { + return (ZT1_VirtualNetworkList *)0; + } +} + +void ZT1_Node_freeQueryResult(ZT1_Node *node,void *qr) +{ + try { + reinterpret_cast<ZeroTier::Node *>(node)->freeQueryResult(qr); + } catch ( ... ) {} +} + +void ZT1_Node_setNetconfMaster(ZT1_Node *node,void *networkConfigMasterInstance) +{ + try { + reinterpret_cast<ZeroTier::Node *>(node)->setNetconfMaster(networkConfigMasterInstance); + } catch ( ... ) {} +} + +void ZT1_version(int *major,int *minor,int *revision,unsigned long *featureFlags) +{ + if (major) *major = ZEROTIER_ONE_VERSION_MAJOR; + if (minor) *minor = ZEROTIER_ONE_VERSION_MINOR; + if (revision) *revision = ZEROTIER_ONE_VERSION_REVISION; + if (featureFlags) { + *featureFlags = + ZT1_FEATURE_FLAG_THREAD_SAFE | +#ifdef ZT_OFFICIAL_BUILD + ZT1_FEATURE_FLAG_OFFICIAL +#endif + ; + } +} + +} // extern "C" diff --git a/node/Node.hpp b/node/Node.hpp index 0f11f3b7..e376648a 100644 --- a/node/Node.hpp +++ b/node/Node.hpp @@ -41,11 +41,11 @@ #include "InetAddress.hpp" #include "Mutex.hpp" #include "MAC.hpp" +#include "Network.hpp" namespace ZeroTier { class RuntimeEnvironment; -class Network; /** * Implementation of Node object as defined in CAPI @@ -60,7 +60,7 @@ public: ZT1_DataStorePutFunction *dataStorePutFunction, ZT1_WirePacketSendFunction *wirePacketSendFunction, ZT1_VirtualNetworkFrameFunction *virtualNetworkFrameFunction, - ZT1_VirtualNetworkConfigCallback *networkConfigCallback, + ZT1_VirtualNetworkConfigCallback *virtualNetworkConfigCallback, ZT1_StatusCallback *statusCallback); ~Node(); @@ -68,7 +68,6 @@ public: // Public API Functions ---------------------------------------------------- ZT1_ResultCode processWirePacket( - ZT1_Node *node, uint64_t now, const struct sockaddr_storage *remoteAddress, int linkDesperation, @@ -76,7 +75,6 @@ public: unsigned int packetLength, uint64_t *nextCallDeadline); ZT1_ResultCode processVirtualNetworkFrame( - ZT1_Node *node, uint64_t now, uint64_t nwid, uint64_t sourceMac, @@ -86,10 +84,7 @@ public: const void *frameData, unsigned int frameLength, uint64_t *nextCallDeadline); - ZT1_Resultcode processNothing( - ZT1_Node *node, - uint64_t now, - uint64_t *nextCallDeadline); + ZT1_Resultcode processNothing(uint64_t now,uint64_t *nextCallDeadline); ZT1_ResultCode join(uint64_t nwid); ZT1_ResultCode leave(uint64_t nwid); ZT1_ResultCode multicastSubscribe(ZT1_Node *node,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi = 0); @@ -114,6 +109,30 @@ public: inline int desperation() const throw() { return (int)((_now - _timeOfLastPrivilgedPacket) / ZT_DESPERATION_INCREMENT); } /** + * Called to update last packet receive time whenever a packet is received + * + * @param fromPrivilegedPeer If true, peer is a supernode or federated hub (a.k.a. an upstream link) + */ + inline void packetReceived(bool fromPrivilegedPeer) + throw() + { + const uint64_t n = _now; + _timeOfLastPacketReceived = n; + if (fromPrivilegedPeer) + _timeOfLastPrivilgedPacket = n; + } + + /** + * @return Most recent time of any packet receipt + */ + inline uint64_t timeOfLastPacketReceived() const throw() { return _timeOfLastPacketReceived; } + + /** + * @return Timestamp of last packet received from a supernode or hub (upstream link) + */ + inline uint64_t timeOfLastPrivilgedPacket() const throw() { return _timeOfLastPrivilgedPacket; } + + /** * Enqueue a ZeroTier message to be sent * * @param addr Destination address @@ -159,11 +178,11 @@ public: * @param nwid Network ID * @return Network instance */ - inline Network *network(uint64_t nwid) + inline SharedPtr<Network> network(uint64_t nwid) { Mutex::Lock _l(_networks_m); - std::map< uint64_t,Network * >::iterator nw(_networks.find(nwid)); - return ((nw == _networks.end()) ? (Network *)0 : nw->second); + std::map< uint64_t,SharedPtr<Network> >::iterator nw(_networks.find(nwid)); + return ((nw == _networks.end()) ? SharedPtr<Network>() : nw->second); } private: @@ -173,13 +192,13 @@ private: ZT1_DataStorePutFunction *_dataStorePutFunction; ZT1_WirePacketSendFunction *_wirePacketSendFunction; ZT1_VirtualNetworkFrameFunction *_virtualNetworkFrameFunction; - ZT1_VirtualNetworkConfigCallback *_networkConfigCallback; + ZT1_VirtualNetworkConfigCallback *_virtualNetworkConfigCallback; ZT1_StatusCallback *_statusCallback; //Dictionary _localConfig; // persisted as local.conf //Mutex _localConfig_m; - std::map< uint64_t,Network * > _networks; + std::map< uint64_t,SharedPtr<Network> > _networks; Mutex _networks_m; volatile uint64_t _now; // time of last run() |