diff options
| author | Joseph Henry <[email protected]> | 2020-05-01 19:15:38 -0700 |
|---|---|---|
| committer | Joseph Henry <[email protected]> | 2020-05-01 19:15:38 -0700 |
| commit | a0b50530d37d9c13d30a68bf1d4686485be36327 (patch) | |
| tree | 50251ec3ef7f18468ec3eb2d379d835ea8c64d1f /src/Events.cpp | |
| parent | 2c709277b9632bd8e3af8b66f51d3f5a53f84e8e (diff) | |
Add portability and consistency fixes for C API, remove cruft, slight internal restructuring1.3.3
Diffstat (limited to 'src/Events.cpp')
| -rw-r--r-- | src/Events.cpp | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/Events.cpp b/src/Events.cpp new file mode 100644 index 0000000..3cbd332 --- /dev/null +++ b/src/Events.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c)2013-2020 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2024-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +/** + * @file + * + * Callback event processing logic + */ + +#include "concurrentqueue.h" + +#ifdef SDK_JNI + #include <jni.h> +#endif + +#include "Node.hpp" +#include "OSUtils.hpp" + +#include "Debug.hpp" +#include "Events.hpp" +#include "ZeroTierSockets.h" +#include "NodeService.hpp" + +#define NODE_EVENT_TYPE(code) code >= ZTS_EVENT_NODE_UP && code <= ZTS_EVENT_NODE_NORMAL_TERMINATION +#define NETWORK_EVENT_TYPE(code) code >= ZTS_EVENT_NETWORK_NOT_FOUND && code <= ZTS_EVENT_NETWORK_DOWN +#define STACK_EVENT_TYPE(code) code >= ZTS_EVENT_STACK_UP && code <= ZTS_EVENT_STACK_DOWN +#define NETIF_EVENT_TYPE(code) code >= ZTS_EVENT_NETIF_UP && code <= ZTS_EVENT_NETIF_LINK_DOWN +#define PEER_EVENT_TYPE(code) code >= ZTS_EVENT_PEER_DIRECT && code <= ZTS_EVENT_PEER_UNREACHABLE +#define PATH_EVENT_TYPE(code) code >= ZTS_EVENT_PATH_DISCOVERED && code <= ZTS_EVENT_PATH_DEAD +#define ROUTE_EVENT_TYPE(code) code >= ZTS_EVENT_ROUTE_ADDED && code <= ZTS_EVENT_ROUTE_REMOVED +#define ADDR_EVENT_TYPE(code) code >= ZTS_EVENT_ADDR_ADDED_IP4 && code <= ZTS_EVENT_ADDR_REMOVED_IP6 + +namespace ZeroTier { + +extern NodeService *service; + +// Global state variable shared between Socket, Control, Event and NodeService logic. +uint8_t _serviceStateFlags; + +// Lock to guard access to callback function pointers. +Mutex _callbackLock; + +void (*_userEventCallbackFunc)(void *); + +moodycamel::ConcurrentQueue<struct ::zts_callback_msg*> _callbackMsgQueue; + +void _enqueueEvent(int16_t eventCode, void *arg) +{ + struct ::zts_callback_msg *msg = new ::zts_callback_msg(); + + msg->node = NULL; + msg->network = NULL; + msg->netif = NULL; + msg->route = NULL; + msg->path = NULL; + msg->peer = NULL; + msg->addr = NULL; + + msg->eventCode = eventCode; + + if (NODE_EVENT_TYPE(eventCode)) { + msg->node = (struct zts_node_details*)arg; + } if (NETWORK_EVENT_TYPE(eventCode)) { + msg->network = (struct zts_network_details*)arg; + } if (NETIF_EVENT_TYPE(eventCode)) { + msg->netif = (struct zts_netif_details*)arg; + } if (ROUTE_EVENT_TYPE(eventCode)) { + msg->route = (struct zts_virtual_network_route*)arg; + } if (PATH_EVENT_TYPE(eventCode)) { + msg->path = (struct zts_physical_path*)arg; + } if (PEER_EVENT_TYPE(eventCode)) { + msg->peer = (struct zts_peer_details*)arg; + } if (ADDR_EVENT_TYPE(eventCode)) { + msg->addr = (struct zts_addr_details*)arg; + } + _callbackMsgQueue.enqueue(msg); +} + +void _freeEvent(struct ::zts_callback_msg *msg) +{ + if (!msg) { + return; + } + if (msg->node) { delete msg->node; } + if (msg->network) { delete msg->network; } + if (msg->netif) { delete msg->netif; } + if (msg->route) { delete msg->route; } + if (msg->path) { delete msg->path; } + if (msg->peer) { delete msg->peer; } + if (msg->addr) { delete msg->addr; } +} + +void _passDequeuedEventToUser(struct ::zts_callback_msg *msg) +{ +#ifdef SDK_JNI + if(_userCallbackMethodRef) { + JNIEnv *env; +#if defined(__ANDROID__) + jint rs = jvm->AttachCurrentThread(&env, NULL); +#else + jint rs = jvm->AttachCurrentThread((void **)&env, NULL); +#endif + assert (rs == JNI_OK); + uint64_t arg = 0; + uint64_t id = 0; + if (NODE_EVENT_TYPE(msg->eventCode)) { + id = msg->node ? msg->node->address : 0; + } + if (NETWORK_EVENT_TYPE(msg->eventCode)) { + id = msg->network ? msg->network->nwid : 0; + } + if (PEER_EVENT_TYPE(msg->eventCode)) { + id = msg->peer ? msg->peer->address : 0; + } + env->CallVoidMethod(objRef, _userCallbackMethodRef, id, msg->eventCode); + _freeEvent(msg); + } +#else + if (_userEventCallbackFunc) { + _userEventCallbackFunc(msg); + _freeEvent(msg); + } +#endif +} + +bool _isCallbackRegistered() +{ + _callbackLock.lock(); + bool retval = false; +#ifdef SDK_JNI + retval = (jvm && objRef && _userCallbackMethodRef); +#else + retval = _userEventCallbackFunc; +#endif + _callbackLock.unlock(); + return retval; +} + +void _clearRegisteredCallback() +{ + _callbackLock.lock(); +#ifdef SDK_JNI + objRef = NULL; + _userCallbackMethodRef = NULL; +#else + _userEventCallbackFunc = NULL; +#endif + _callbackLock.unlock(); +} + +int _canPerformServiceOperation() +{ + return service + && service->isRunning() + && service->getNode() + && service->getNode()->online() + && !_getState(ZTS_STATE_FREE_CALLED); +} + +#define RESET_FLAGS( ) _serviceStateFlags = 0; +#define SET_FLAGS(f) _serviceStateFlags |= f; +#define CLR_FLAGS(f) _serviceStateFlags &= ~f; +#define GET_FLAGS(f) ((_serviceStateFlags & f) > 0) + +void _setState(uint8_t newFlags) +{ + if ((newFlags ^ _serviceStateFlags) & ZTS_STATE_NET_SERVICE_RUNNING) { + return; // No effect. Not allowed to set this flag manually + } + SET_FLAGS(newFlags); + if ( GET_FLAGS(ZTS_STATE_NODE_RUNNING) + && GET_FLAGS(ZTS_STATE_STACK_RUNNING) + && !(GET_FLAGS(ZTS_STATE_FREE_CALLED))) + { + SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); + } + else { + CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); + } +} + +void _clrState(uint8_t newFlags) +{ + if (newFlags & ZTS_STATE_NET_SERVICE_RUNNING) { + return; // No effect. Not allowed to set this flag manually + } + CLR_FLAGS(newFlags); + if ( GET_FLAGS(ZTS_STATE_NODE_RUNNING) + && GET_FLAGS(ZTS_STATE_STACK_RUNNING) + && !(GET_FLAGS(ZTS_STATE_FREE_CALLED))) + { + SET_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); + } + else { + CLR_FLAGS(ZTS_STATE_NET_SERVICE_RUNNING); + } +} + +bool _getState(uint8_t testFlags) +{ + return testFlags & _serviceStateFlags; +} + +#if defined(__WINDOWS__) +DWORD WINAPI _runCallbacks(LPVOID thread_id) +#else +void *_runCallbacks(void *thread_id) +#endif +{ +#if defined(__APPLE__) + pthread_setname_np(ZTS_EVENT_CALLBACK_THREAD_NAME); +#endif + while (_getState(ZTS_STATE_CALLBACKS_RUNNING) || _callbackMsgQueue.size_approx() > 0) + { + struct ::zts_callback_msg *msg; + size_t sz = _callbackMsgQueue.size_approx(); + for (size_t j = 0; j < sz; j++) { + if (_callbackMsgQueue.try_dequeue(msg)) { + _callbackLock.lock(); + _passDequeuedEventToUser(msg); + _callbackLock.unlock(); + delete msg; + } + } + zts_delay_ms(ZTS_CALLBACK_PROCESSING_INTERVAL); + } +#if SDK_JNI + JNIEnv *env; + jint rs = jvm->DetachCurrentThread(); + pthread_exit(0); +#endif + return NULL; +} + +} // namespace ZeroTier |
