diff --git a/CMakeLists.txt b/CMakeLists.txt index e0a037830865a3f790808a31a24ecc48b886f841..a8b1295351b04566809b680cf7ecd707c94c4b62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ if (CELLFRAME_MODULES MATCHES "srv-stake") endif() if (CELLFRAME_MODULES MATCHES "core") - SET(DAPSDK_MODULES "${DAPSDK_MODULES} core crypto") + SET(DAPSDK_MODULES "${DAPSDK_MODULES} core crypto io") endif() @@ -61,7 +61,7 @@ endif() if (CELLFRAME_MODULES MATCHES "dap-sdk-net-client") set(DAPSDK_MODULES "core crypto network-core network-client network-server") - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_core dap_crypto dap_server_core dap_server dap_client m pthread) + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_core dap_crypto dap_io dap_server dap_client m pthread) if (SUPPORT_PYTHON_PLUGINS) set(CELLFRAME_MODULES "${CELLFRAME_MODULES} core chains network cs-none srv-") endif() @@ -129,7 +129,7 @@ endif() # Networking if (CELLFRAME_MODULES MATCHES "network") message("[+] Module 'network'") - set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_server_core dap_json_rpc dap_enc_server dap_notify_srv dap_http_server dap_session + set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_io dap_json_rpc dap_enc_server dap_notify_srv dap_http_server dap_session dap_stream dap_stream_ch dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_chain_net dap_chain_net_srv dap_stream_ch_chain_voting dap_chain_mempool magic) endif() diff --git a/dap-sdk/CMakeLists.txt b/dap-sdk/CMakeLists.txt index 9a6f3fa6394bd90cbc3d3d93c2aae300b843a209..0781b5dec7acebc17ae9a3b356220bb8efc7f688 100644 --- a/dap-sdk/CMakeLists.txt +++ b/dap-sdk/CMakeLists.txt @@ -14,13 +14,18 @@ if (DAPSDK_MODULES MATCHES "crypto") add_subdirectory(crypto) endif() +# I/O subsystem +if (DAPSDK_MODULES MATCHES "io") + add_subdirectory(io) +endif() + # Networking core if (DAPSDK_MODULES MATCHES "network-core") - add_subdirectory(net/core) add_subdirectory(net/stream) endif() if (DAPSDK_MODULES MATCHES "network-pure") + add_subdirectory(io) add_subdirectory(net/core) endif() diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h index c638d9260dcd617f4d3e33d5ccd6f5f0d541cfe3..a14b12dc5cc5004caa3fde658da78503a15a8f7b 100755 --- a/dap-sdk/core/include/dap_strfuncs.h +++ b/dap-sdk/core/include/dap_strfuncs.h @@ -46,6 +46,7 @@ char *strptime( char *buff, const char *fmt, struct tm *tm ); bool dap_isstralnum(const char *c); size_t dap_strlen(const char *a_str); +char* dap_strcat2(const char* s1, const char* s2); // compare a_str1 and a_str2 int dap_strcmp(const char *a_str1, const char *a_str2); // compare a_n characters of a_str1 and a_str2 diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c index f960159e161d38242545a38c5923262a62676c45..a0e88234b22cb4d9f6754ff61a3b56fc3963cac0 100755 --- a/dap-sdk/core/src/dap_strfuncs.c +++ b/dap-sdk/core/src/dap_strfuncs.c @@ -33,6 +33,41 @@ bool dap_isstralnum(const char *c) return true; } +/** + * @brief strcat two strings with new char array in result + * + * @param s1 preallocated buffer with char string + * @param s2 char string + * @return char* + */ +char* dap_strcat2(const char* s1, const char* s2) +{ + size_t size1 = 0; + size_t size2 = 0; + if (!s1) + size1 = 0; + else + size1 = strlen(s1); + if (!s2) + size2 = 0; + else + size2 = strlen(s2); + + char* result = malloc(size1 + size2 + 1); + + if(result == NULL) + { + exit(EXIT_FAILURE); + } + + memcpy(result, s1, size1); + memcpy(result+size1, s2, size2); + free((void*)s1); + result[size1 + size2] = '\0'; + return result; +} + + /** * @brief s_strdigit diff --git a/dap-sdk/net/core/CMakeLists.txt b/dap-sdk/io/CMakeLists.txt similarity index 68% rename from dap-sdk/net/core/CMakeLists.txt rename to dap-sdk/io/CMakeLists.txt index ca3fe8666b0f24b9575ffa8e9454e9e720e8bcfd..fc87bf0605419e5222abfae71c2cbc18dffcfa2e 100644 --- a/dap-sdk/net/core/CMakeLists.txt +++ b/dap-sdk/io/CMakeLists.txt @@ -1,23 +1,23 @@ cmake_minimum_required(VERSION 3.10) -project (dap_server_core C) +project (dap_io C) set(CMAKE_C_STANDARD 11) add_definitions ("-D_GNU_SOURCE") if(WIN32) - file(GLOB DAP_SERVER_CORE_SOURCES *.c ../../../3rdparty/wepoll/*.c) - file(GLOB DAP_SERVER_CORE_HEADERS include/*.h ../../../3rdparty/wepoll/*.h) + file(GLOB DAP_IO_SOURCES *.c ../../../3rdparty/wepoll/*.c) + file(GLOB DAP_IO_HEADERS include/*.h ../../../3rdparty/wepoll/*.h) else() - file(GLOB DAP_SERVER_CORE_SOURCES *.c) - file(GLOB DAP_SERVER_CORE_HEADERS include/*.h) + file(GLOB DAP_IO_SOURCES *.c) + file(GLOB DAP_IO_HEADERS include/*.h) endif() if(WIN32) include_directories(../../../modules/net/win32) endif() -add_library(${PROJECT_NAME} STATIC ${DAP_SERVER_CORE_HEADERS} ${DAP_SERVER_CORE_SOURCES}) +add_library(${PROJECT_NAME} STATIC ${DAP_IO_HEADERS} ${DAP_IO_SOURCES}) if(DAPSDK_MODULES MATCHES "ssl-support") target_link_libraries(${PROJECT_NAME} dap_core dap_crypto wolfssl) @@ -40,7 +40,7 @@ if (WIN32) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wepoll) endif() -if (${BUILD_DAP_SERVER_CORE_TESTS} MATCHES ON) +if (${BUILD_DAP_IO_TESTS} MATCHES ON) enable_testing() add_subdirectory(test) endif() diff --git a/dap-sdk/net/core/dap_worker.c b/dap-sdk/io/dap_context.c similarity index 61% rename from dap-sdk/net/core/dap_worker.c rename to dap-sdk/io/dap_context.c index e25a00b357dc4720c8db982e7656d8b3b38fe8c3..3c7b7358469a9ddd8d53398420cb104941a08068 100644 --- a/dap-sdk/net/core/dap_worker.c +++ b/dap-sdk/io/dap_context.c @@ -2,7 +2,7 @@ * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * DeM Labs Ltd. https://demlabs.net - * Copyright (c) 2017 + * Copyright (c) 2022 * All rights reserved. This file is part of DAP SDK the open source project @@ -20,9 +20,14 @@ You should have received a copy of the GNU General Public License along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ -#include <time.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> #include <errno.h> -#include <unistd.h> +#include <stdatomic.h> + #if ! defined (_GNU_SOURCE) #define _GNU_SOURCE /* See feature_test_macros(7) */ #endif @@ -36,6 +41,28 @@ #include <ws2tcpip.h> #endif +#if defined (DAP_OS_LINUX) +#include <sys/epoll.h> +#include <sys/types.h> +#include <sys/select.h> +#include <unistd.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#elif defined (DAP_OS_BSD) +#include <sys/types.h> +#include <sys/select.h> +#include <unistd.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#elif defined (DAP_OS_WINDOWS) +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <io.h> + +#endif + #ifdef DAP_OS_DARWIN #define NOTE_READ NOTE_LOWAT @@ -45,43 +72,27 @@ #endif -#include "dap_common.h" -#include "dap_config.h" -#include "dap_math_ops.h" -#include "dap_worker.h" -#include "dap_timerfd.h" -#include "dap_events.h" -#include "dap_enc_base64.h" -#include "dap_proc_queue.h" - -#ifndef DAP_NET_CLIENT_NO_SSL -#include <wolfssl/options.h> -#include "wolfssl/ssl.h" +#if defined (DAP_EVENTS_CAPS_QUEUE_MQUEUE) +#include <sys/time.h> +#include <sys/resource.h> #endif -#define LOG_TAG "dap_worker" +#define LOG_TAG "dap_context" -static time_t s_connection_timeout = 60; // seconds +#include "dap_common.h" +#include "dap_uuid.h" +#include "dap_context.h" +#include "dap_worker.h" +#include "dap_events_socket.h" +pthread_key_t g_dap_context_pth_key; -static bool s_socket_all_check_activity( void * a_arg); -static void s_queue_add_es_callback( dap_events_socket_t * a_es, void * a_arg); -static void s_queue_delete_es_callback( dap_events_socket_t * a_es, void * a_arg); -static void s_queue_es_reassign_callback( dap_events_socket_t * a_es, void * a_arg); -static void s_queue_callback_callback( dap_events_socket_t * a_es, void * a_arg); -static void s_queue_es_io_callback( dap_events_socket_t * a_es, void * a_arg); -static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags); /** - * @brief dap_worker_init - * @param a_threads_count - * @param conn_timeout + * @brief dap_context_init * @return */ -int dap_worker_init( size_t a_conn_timeout ) +int dap_context_init() { - if ( a_conn_timeout ) - s_connection_timeout = a_conn_timeout; - #ifdef DAP_OS_UNIX struct rlimit l_fdlimit; if (getrlimit(RLIMIT_NOFILE, &l_fdlimit)) @@ -96,101 +107,75 @@ int dap_worker_init( size_t a_conn_timeout ) return 0; } -void dap_worker_deinit( ) +/** + * @brief dap_context_new + * @return + */ +dap_context_t * dap_context_new() { + dap_context_t * l_context = DAP_NEW_Z(dap_context_t); + static uint32_t s_context_id_max = 0; + l_context->id = s_context_id_max; + s_context_id_max++; + return l_context; } /** - * @brief dap_worker_thread - * @param arg + * @brief dap_context_thread_init + * @param a_context * @return */ -void *dap_worker_thread(void *arg) +int dap_context_thread_init(dap_context_t * a_context) { - dap_events_socket_t *l_cur; - dap_worker_t *l_worker = (dap_worker_t *) arg; - uint32_t l_tn = l_worker->id; - int l_errno = 0, l_selected_sockets; - socklen_t l_error_len = sizeof(l_errno); - char l_error_buf[128] = {0}; - ssize_t l_bytes_sent = 0, l_bytes_read = 0, l_sockets_max; - const struct sched_param l_shed_params = {0}; - - - dap_cpu_assign_thread_on(l_worker->id); - pthread_setspecific(l_worker->events->pth_key_worker, l_worker); + pthread_setspecific(g_dap_context_pth_key, a_context); -#ifdef DAP_OS_WINDOWS - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL)) - log_it(L_ERROR, "Couldn'r set thread priority, err: %lu", GetLastError()); -#else - pthread_setschedparam(pthread_self(),SCHED_FIFO ,&l_shed_params); -#endif +#if defined(DAP_EVENTS_CAPS_KQUEUE) + a_context->kqueue_fd = kqueue(); -#ifdef DAP_EVENTS_CAPS_EPOLL - struct epoll_event l_epoll_events[ DAP_EVENTS_SOCKET_MAX]= {{0}}; - log_it(L_INFO, "Worker #%d started with epoll fd %"DAP_FORMAT_HANDLE" and assigned to dedicated CPU unit", l_worker->id, l_worker->epoll_fd); -#elif defined(DAP_EVENTS_CAPS_KQUEUE) - l_worker->kqueue_fd = kqueue(); - - if (l_worker->kqueue_fd == -1 ){ - int l_errno = errno; - char l_errbuf[255]; - strerror_r(l_errno,l_errbuf,sizeof(l_errbuf)); - log_it (L_CRITICAL,"Can't create kqueue(): '%s' code %d",l_errbuf,l_errno); - pthread_cond_broadcast(&l_worker->started_cond); - return NULL; + if (a_context->kqueue_fd == -1 ){ + int l_errno = errno; + char l_errbuf[255]; + strerror_r(l_errno,l_errbuf,sizeof(l_errbuf)); + log_it (L_CRITICAL,"Can't create kqueue(): '%s' code %d",l_errbuf,l_errno); + return -1; } - l_worker->kqueue_events_selected_count_max = 100; - l_worker->kqueue_events_count_max = DAP_EVENTS_SOCKET_MAX; - l_worker->kqueue_events_selected = DAP_NEW_Z_SIZE(struct kevent, l_worker->kqueue_events_selected_count_max *sizeof(struct kevent)); + a_context->kqueue_events_selected_count_max = 100; + a_context->kqueue_events_count_max = DAP_EVENTS_SOCKET_MAX; + a_context->kqueue_events_selected = DAP_NEW_Z_SIZE(struct kevent, a_context->kqueue_events_selected_count_max *sizeof(struct kevent)); #elif defined(DAP_EVENTS_CAPS_POLL) - l_worker->poll_count_max = DAP_EVENTS_SOCKET_MAX; - l_worker->poll = DAP_NEW_Z_SIZE(struct pollfd,l_worker->poll_count_max*sizeof (struct pollfd)); - l_worker->poll_esocket = DAP_NEW_Z_SIZE(dap_events_socket_t*,l_worker->poll_count_max*sizeof (dap_events_socket_t*)); + a_context->poll_count_max = DAP_EVENTS_SOCKET_MAX; + a_context->poll = DAP_NEW_Z_SIZE(struct pollfd,a_context->poll_count_max*sizeof (struct pollfd)); + a_context->poll_esocket = DAP_NEW_Z_SIZE(dap_events_socket_t*,a_context->poll_count_max*sizeof (dap_events_socket_t*)); #else #error "Unimplemented socket array for this platform" #endif + return 0; +} - l_worker->queue_es_new_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); - l_worker->queue_es_delete_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); - l_worker->queue_es_io_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); - l_worker->queue_es_reassign_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); - - - l_worker->queue_es_new = dap_events_socket_create_type_queue_ptr_unsafe(l_worker, s_queue_add_es_callback); - l_worker->queue_es_delete = dap_events_socket_create_type_queue_ptr_unsafe(l_worker, s_queue_delete_es_callback); - l_worker->queue_es_io = dap_events_socket_create_type_queue_ptr_unsafe(l_worker, s_queue_es_io_callback); - l_worker->queue_es_reassign = dap_events_socket_create_type_queue_ptr_unsafe(l_worker, s_queue_es_reassign_callback ); - - - for( size_t n = 0; n < dap_events_worker_get_count(); n++) { - l_worker->queue_es_new_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_new); - l_worker->queue_es_delete_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_delete); - l_worker->queue_es_io_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_io); - l_worker->queue_es_reassign_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_reassign); - } - - l_worker->queue_callback = dap_events_socket_create_type_queue_ptr_unsafe(l_worker, s_queue_callback_callback); - l_worker->event_exit = dap_events_socket_create_type_event_unsafe(l_worker, s_event_exit_callback); +/** + * @brief dap_context_thread_loop + * @param a_context + * @return + */ +int dap_context_thread_loop(dap_context_t * a_context) +{ + int l_errno = 0, l_selected_sockets = 0; + dap_events_socket_t *l_cur = NULL; - l_worker->timer_check_activity = dap_timerfd_create(s_connection_timeout * 1000 / 2, - s_socket_all_check_activity, l_worker); - dap_worker_add_events_socket_unsafe( l_worker->timer_check_activity->events_socket, l_worker); - pthread_mutex_lock(&l_worker->started_mutex); - pthread_cond_broadcast(&l_worker->started_cond); - pthread_mutex_unlock(&l_worker->started_mutex); + socklen_t l_error_len = sizeof(l_errno); + char l_error_buf[128] = {0}; + ssize_t l_bytes_sent = 0, l_bytes_read = 0, l_sockets_max; - while (1) { + do { #ifdef DAP_EVENTS_CAPS_EPOLL - l_selected_sockets = epoll_wait(l_worker->epoll_fd, l_epoll_events, DAP_EVENTS_SOCKET_MAX, -1); + l_selected_sockets = epoll_wait(a_context->epoll_fd, l_epoll_events, DAP_EVENTS_SOCKET_MAX, -1); l_sockets_max = l_selected_sockets; #elif defined(DAP_EVENTS_CAPS_POLL) - l_selected_sockets = poll(l_worker->poll, l_worker->poll_count, -1); - l_sockets_max = l_worker->poll_count; + l_selected_sockets = poll(a_context->poll, a_context->poll_count, -1); + l_sockets_max = a_context->poll_count; #elif defined(DAP_EVENTS_CAPS_KQUEUE) - l_selected_sockets = kevent(l_worker->kqueue_fd,NULL,0,l_worker->kqueue_events_selected,l_worker->kqueue_events_selected_count_max, + l_selected_sockets = kevent(a_context->kqueue_fd,NULL,0,a_context->kqueue_events_selected,a_context->kqueue_events_selected_count_max, NULL); l_sockets_max = l_selected_sockets; #else @@ -200,10 +185,10 @@ void *dap_worker_thread(void *arg) if( errno == EINTR) continue; #ifdef DAP_OS_WINDOWS - log_it(L_ERROR, "Worker thread %d got errno %d", l_worker->id, WSAGetLastError()); + log_it(L_ERROR, "Context thread %d got errno %d", a_context->id, WSAGetLastError()); #else strerror_r(l_errno, l_error_buf, sizeof (l_error_buf) - 1); - log_it(L_ERROR, "Worker thread %d got errno:\"%s\" (%d)", l_worker->id, l_error_buf, l_errno); + log_it(L_ERROR, "Context thread %d got errno:\"%s\" (%d)", a_context->id, l_error_buf, l_errno); assert(l_errno); #endif break; @@ -225,9 +210,9 @@ void *dap_worker_thread(void *arg) l_flag_nval = false; l_flag_msg = false; #elif defined ( DAP_EVENTS_CAPS_POLL) - short l_cur_flags =l_worker->poll[n].revents; + short l_cur_flags =a_context->poll[n].revents; - if (l_worker->poll[n].fd == -1) // If it was deleted on previous iterations + if (a_context->poll[n].fd == -1) // If it was deleted on previous iterations continue; if (!l_cur_flags) // No events for this socket @@ -241,11 +226,11 @@ void *dap_worker_thread(void *arg) l_flag_nval = l_cur_flags & POLLNVAL; l_flag_pri = l_cur_flags & POLLPRI; l_flag_msg = l_cur_flags & POLLMSG; - l_cur = l_worker->poll_esocket[n]; - //log_it(L_DEBUG, "flags: returned events 0x%0X requested events 0x%0X",l_worker->poll[n].revents,l_worker->poll[n].events ); + l_cur = a_context->poll_esocket[n]; + //log_it(L_DEBUG, "flags: returned events 0x%0X requested events 0x%0X",a_context->poll[n].revents,a_context->poll[n].events ); #elif defined (DAP_EVENTS_CAPS_KQUEUE) l_flag_hup=l_flag_rdhup=l_flag_read=l_flag_write=l_flag_error=l_flag_nval=l_flag_msg =l_flag_pri = false; - struct kevent * l_kevent_selected = &l_worker->kqueue_events_selected[n]; + struct kevent * l_kevent_selected = &a_context->kqueue_events_selected[n]; if ( l_kevent_selected->filter == EVFILT_USER){ // If we have USER event it sends little different pointer dap_events_socket_w_data_t * l_es_w_data = (dap_events_socket_w_data_t *) l_kevent_selected->udata; //if(g_debug_reactor) @@ -273,7 +258,9 @@ void *dap_worker_thread(void *arg) case EVFILT_READ: l_flag_read = true; break; case EVFILT_WRITE: l_flag_write = true; break; case EVFILT_EXCEPT : l_flag_rdhup = true; break; - default: log_it(L_CRITICAL,"Unknown filter type in polling, exit thread"); return NULL; + default: + log_it(L_CRITICAL,"Unknown filter type in polling, exit thread"); + return -1; } if (l_kevent_selected->flags & EV_EOF) l_flag_rdhup = true; @@ -296,13 +283,13 @@ void *dap_worker_thread(void *arg) #else #error "Unimplemented fetch esocket after poll" #endif - if(!l_cur || (l_cur->worker && l_cur->worker != l_worker)) { + if(!l_cur || (l_cur->context && l_cur->context != a_context)) { log_it(L_WARNING, "dap_events_socket was destroyed earlier"); continue; } if(g_debug_reactor) { - log_it(L_DEBUG, "--Worker #%u esocket %p uuid 0x%016"DAP_UINT64_FORMAT_x" type %d fd=%"DAP_FORMAT_SOCKET" flags=0x%0X (%s:%s:%s:%s:%s:%s:%s:%s)--", - l_worker->id, l_cur, l_cur->uuid, l_cur->type, l_cur->socket, + log_it(L_DEBUG, "--Context #%u esocket %p uuid 0x%016"DAP_UINT64_FORMAT_x" type %d fd=%"DAP_FORMAT_SOCKET" flags=0x%0X (%s:%s:%s:%s:%s:%s:%s:%s)--", + a_context->id, l_cur, l_cur->uuid, l_cur->type, l_cur->socket, l_cur_flags, l_flag_read?"read":"", l_flag_write?"write":"", l_flag_error?"error":"", l_flag_hup?"hup":"", l_flag_rdhup?"rdhup":"", l_flag_msg?"msg":"", l_flag_nval?"nval":"", l_flag_pri?"pri":""); @@ -523,7 +510,7 @@ void *dap_worker_thread(void *arg) log_it(L_DEBUG, "Received %zd bytes for fd %d ", l_bytes_read, l_cur->fd); if(l_cur->callbacks.read_callback){ l_cur->callbacks.read_callback(l_cur, NULL); // Call callback to process read event. At the end of callback buf_in_size should be zero if everything was read well - if (l_cur->worker == NULL ){ // esocket was unassigned in callback, we don't need any ops with it now, + if (l_cur->context == NULL ){ // esocket was unassigned in callback, we don't need any ops with it now, // continue to poll another esockets continue; } @@ -606,7 +593,7 @@ void *dap_worker_thread(void *arg) l_cur->flags ^= DAP_SOCK_CONNECTING; if (l_cur->callbacks.connected_callback) l_cur->callbacks.connected_callback(l_cur); - dap_events_socket_worker_poll_update_unsafe(l_cur); + dap_context_poll_update(l_cur); } #endif } else { @@ -627,7 +614,7 @@ void *dap_worker_thread(void *arg) l_cur->flags ^= DAP_SOCK_CONNECTING; if (l_cur->callbacks.connected_callback) l_cur->callbacks.connected_callback(l_cur); - dap_events_socket_worker_poll_update_unsafe(l_cur); + dap_context_poll_update(l_cur); } } } @@ -652,7 +639,7 @@ void *dap_worker_thread(void *arg) if (l_cur->callbacks.write_callback) l_cur->callbacks.write_callback(l_cur, NULL); /* Call callback to process write event */ - if ( l_cur->worker && l_flag_write ){ // esocket wasn't unassigned in callback, we need some other ops with it + if ( l_cur->context && l_flag_write ){ // esocket wasn't unassigned in callback, we need some other ops with it switch (l_cur->type){ case DESCRIPTOR_TYPE_SOCKET_CLIENT: { l_bytes_sent = send(l_cur->socket, (const char *)l_cur->buf_out, @@ -736,7 +723,7 @@ void *dap_worker_thread(void *arg) l_es_w_data->esocket = l_cur; memcpy(&l_es_w_data->ptr, l_cur->buf_out,sizeof(l_cur)); EV_SET(l_event,l_cur->socket, l_cur->kqueue_base_filter,l_cur->kqueue_base_flags, l_cur->kqueue_base_fflags,l_cur->kqueue_data, l_es_w_data); - int l_n = kevent(l_worker->kqueue_fd,l_event,1,NULL,0,NULL); + int l_n = kevent(a_context->kqueue_fd,l_event,1,NULL,0,NULL); if (l_n == 1){ l_bytes_sent = sizeof(l_cur); }else{ @@ -818,18 +805,18 @@ void *dap_worker_thread(void *arg) { if (l_cur->buf_out_size == 0) { if(g_debug_reactor) - log_it(L_INFO, "Process signal to close %s sock %"DAP_FORMAT_SOCKET" (ptr 0x%p uuid 0x%016"DAP_UINT64_FORMAT_x") type %d [thread %u]", + log_it(L_INFO, "Process signal to close %s sock %"DAP_FORMAT_SOCKET" (ptr 0x%p uuid 0x%016"DAP_UINT64_FORMAT_x") type %d [context #%u]", l_cur->remote_addr_str ? l_cur->remote_addr_str : "", l_cur->socket, l_cur, l_cur->uuid, - l_cur->type, l_tn); + l_cur->type, a_context->id); for (ssize_t nn = n + 1; nn < l_sockets_max; nn++) { // Check for current selection if it has event duplication dap_events_socket_t *l_es_selected = NULL; #ifdef DAP_EVENTS_CAPS_EPOLL l_es_selected = (dap_events_socket_t *) l_epoll_events[nn].data.ptr; #elif defined ( DAP_EVENTS_CAPS_POLL) - l_es_selected = l_worker->poll_esocket[nn]; + l_es_selected = a_context->poll_esocket[nn]; #elif defined (DAP_EVENTS_CAPS_KQUEUE) - struct kevent * l_kevent_selected = &l_worker->kqueue_events_selected[n]; + struct kevent * l_kevent_selected = &a_context->kqueue_events_selected[n]; if ( l_kevent_selected->filter == EVFILT_USER){ // If we have USER event it sends little different pointer dap_events_socket_w_data_t * l_es_w_data = (dap_events_socket_w_data_t *) l_kevent_selected->udata; l_es_selected = l_es_w_data->esocket; @@ -851,21 +838,16 @@ void *dap_worker_thread(void *arg) //dap_events_socket_remove_and_delete_unsafe( l_cur, false); dap_events_remove_and_delete_socket_unsafe(dap_events_get_default(), l_cur, false); #ifdef DAP_EVENTS_CAPS_KQUEUE - l_worker->kqueue_events_count--; + a_context->kqueue_events_count--; #endif } else if (l_cur->buf_out_size ) { if(g_debug_reactor) - log_it(L_INFO, "Got signal to close %s sock %"DAP_FORMAT_SOCKET" [thread %u] type %d but buffer is not empty(%zu)", - l_cur->remote_addr_str ? l_cur->remote_addr_str : "", l_cur->socket, l_cur->type, l_tn, + log_it(L_INFO, "Got signal to close %s sock %"DAP_FORMAT_SOCKET" [context #%u] type %d but buffer is not empty(%zu)", + l_cur->remote_addr_str ? l_cur->remote_addr_str : "", l_cur->socket, l_cur->type, a_context->id, l_cur->buf_out_size); } } - if( l_worker->signal_exit){ - log_it(L_ATT,"Worker :%u finished", l_worker->id); - return NULL; - } - } #ifdef DAP_EVENTS_CAPS_POLL /***********************************************************/ @@ -873,313 +855,155 @@ void *dap_worker_thread(void *arg) /* to squeeze together the array and decrement the number */ /* of file descriptors. */ /***********************************************************/ - if ( l_worker->poll_compress){ - l_worker->poll_compress = false; - for (size_t i = 0; i < l_worker->poll_count ; i++) { - if ( l_worker->poll[i].fd == -1){ - if( l_worker->poll_count){ - for(size_t j = i; j < l_worker->poll_count-1; j++){ - l_worker->poll[j].fd = l_worker->poll[j+1].fd; - l_worker->poll[j].events = l_worker->poll[j+1].events; - l_worker->poll[j].revents = l_worker->poll[j+1].revents; - l_worker->poll_esocket[j] = l_worker->poll_esocket[j+1]; - if(l_worker->poll_esocket[j]) - l_worker->poll_esocket[j]->poll_index = j; + if ( a_context->poll_compress){ + a_context->poll_compress = false; + for (size_t i = 0; i < a_context->poll_count ; i++) { + if ( a_context->poll[i].fd == -1){ + if( a_context->poll_count){ + for(size_t j = i; j < a_context->poll_count-1; j++){ + a_context->poll[j].fd = a_context->poll[j+1].fd; + a_context->poll[j].events = a_context->poll[j+1].events; + a_context->poll[j].revents = a_context->poll[j+1].revents; + a_context->poll_esocket[j] = a_context->poll_esocket[j+1]; + if(a_context->poll_esocket[j]) + a_context->poll_esocket[j]->poll_index = j; } } i--; - l_worker->poll_count--; + a_context->poll_count--; } } } #endif - } // while - log_it(L_NOTICE,"Exiting thread #%u", l_worker->id); - return NULL; -} - -/** - * @brief s_new_es_callback - * @param a_es - * @param a_arg - */ -static void s_queue_add_es_callback( dap_events_socket_t * a_es, void * a_arg) -{ - dap_worker_t * l_worker = a_es->worker; - dap_events_socket_t * l_es_new =(dap_events_socket_t *) a_arg; - if (!l_es_new){ - log_it(L_ERROR,"NULL esocket accepted to add on worker #%u", l_worker->id); - return; - } - - if(g_debug_reactor) - log_it(L_NOTICE, "Received event socket %p (ident %"DAP_FORMAT_SOCKET" type %d) to add on worker", l_es_new, l_es_new->socket, l_es_new->type); - - switch( l_es_new->type){ - case DESCRIPTOR_TYPE_SOCKET_UDP: break; - case DESCRIPTOR_TYPE_SOCKET_CLIENT: break; - default:{} - } - -#ifdef DAP_EVENTS_CAPS_KQUEUE - if(l_es_new->socket!=0 && l_es_new->socket != -1 && - l_es_new->type != DESCRIPTOR_TYPE_EVENT && - l_es_new->type != DESCRIPTOR_TYPE_QUEUE && - l_es_new->type != DESCRIPTOR_TYPE_TIMER - ) -#else - if(l_es_new->socket!=0 && l_es_new->socket != INVALID_SOCKET) - -#endif - if(dap_worker_esocket_find_uuid( l_worker, l_es_new->uuid)){ - // Socket already present in worker, it's OK - return; - } - - switch( l_es_new->type){ - - case DESCRIPTOR_TYPE_SOCKET_UDP: - case DESCRIPTOR_TYPE_SOCKET_CLIENT: - case DESCRIPTOR_TYPE_SOCKET_LISTENING:{ - -#ifdef DAP_OS_UNIX -#if defined (SO_INCOMING_CPU) - int l_cpu = l_worker->id; - setsockopt(l_es_new->socket , SOL_SOCKET, SO_INCOMING_CPU, &l_cpu, sizeof(l_cpu)); -#endif -#endif - } break; - default: {} - } - - l_es_new->worker = l_worker; - l_es_new->last_time_active = time(NULL); - // We need to differ new and reassigned esockets. If its new - is_initialized is false - if ( ! l_es_new->is_initalized ){ - if (l_es_new->callbacks.new_callback) - l_es_new->callbacks.new_callback(l_es_new, NULL); - l_es_new->is_initalized = true; - } - - int l_ret = dap_worker_add_events_socket_unsafe(l_es_new,l_worker); - if ( l_ret != 0 ){ - log_it(L_CRITICAL,"Can't add event socket's handler to worker i/o poll mechanism with error %d", errno); - }else{ - // Add in worker - l_es_new->me = l_es_new; - if (l_es_new->socket!=0 && l_es_new->socket != INVALID_SOCKET){ - pthread_rwlock_wrlock(&l_worker->esocket_rwlock); - HASH_ADD(hh_worker, l_worker->esockets, uuid, sizeof(l_es_new->uuid), l_es_new ); - l_worker->event_sockets_count++; - pthread_rwlock_unlock(&l_worker->esocket_rwlock); - } - //log_it(L_DEBUG, "Added socket %d on worker %u", l_es_new->socket, w->id); - if (l_es_new->callbacks.worker_assign_callback) - l_es_new->callbacks.worker_assign_callback(l_es_new, l_worker); + } while(!a_context->signal_exit); - } + log_it(L_ATT,"Context :%u finished", a_context->id); + return 0; } -/** - * @brief s_delete_es_callback - * @param a_es - * @param a_arg - */ -static void s_queue_delete_es_callback( dap_events_socket_t * a_es, void * a_arg) -{ - assert(a_arg); - dap_events_socket_uuid_t * l_es_uuid_ptr = (dap_events_socket_uuid_t*) a_arg; - dap_events_socket_t * l_es; - if ( (l_es = dap_worker_esocket_find_uuid(a_es->worker,*l_es_uuid_ptr)) != NULL ){ - //l_es->flags |= DAP_SOCK_SIGNAL_CLOSE; // Send signal to socket to kill - dap_events_socket_remove_and_delete_unsafe(l_es,false); - }else - log_it(L_INFO, "While we were sending the delete() message, esocket %"DAP_UINT64_FORMAT_U" has been disconnected ", *l_es_uuid_ptr); - DAP_DELETE(l_es_uuid_ptr); -} /** - * @brief s_reassign_es_callback - * @param a_es - * @param a_arg + * @brief dap_context_poll_update + * @param a_esocket */ -static void s_queue_es_reassign_callback( dap_events_socket_t * a_es, void * a_arg) +int dap_context_poll_update(dap_events_socket_t * a_esocket) { - assert(a_es); - dap_worker_t * l_worker = a_es->worker; - assert(l_worker); - dap_worker_msg_reassign_t * l_msg = (dap_worker_msg_reassign_t*) a_arg; - assert(l_msg); - dap_events_socket_t * l_es_reassign; - if ( ( l_es_reassign = dap_worker_esocket_find_uuid(l_worker, l_msg->esocket_uuid))!= NULL ){ - if( l_es_reassign->was_reassigned && l_es_reassign->flags & DAP_SOCK_REASSIGN_ONCE) { - log_it(L_INFO, "Reassgment request with DAP_SOCK_REASSIGN_ONCE allowed only once, declined reassigment from %u to %u", - l_es_reassign->worker->id, l_msg->worker_new->id); + #if defined (DAP_EVENTS_CAPS_EPOLL) + int events = a_esocket->ev_base_flags | EPOLLERR; - }else{ - dap_events_socket_reassign_between_workers_unsafe(l_es_reassign,l_msg->worker_new); - } - }else{ - log_it(L_INFO, "While we were sending the reassign message, esocket %p has been disconnected", l_msg->esocket); - } - DAP_DELETE(l_msg); -} + // Check & add + if( a_esocket->flags & DAP_SOCK_READY_TO_READ ) + events |= EPOLLIN; -/** - * @brief s_queue_callback - * @param a_es - * @param a_arg - */ -static void s_queue_callback_callback( dap_events_socket_t * a_es, void * a_arg) -{ - dap_worker_msg_callback_t * l_msg = (dap_worker_msg_callback_t *) a_arg; - assert(l_msg); - assert(l_msg->callback); - l_msg->callback(a_es->worker, l_msg->arg); - DAP_DELETE(l_msg); -} + if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ) + events |= EPOLLOUT; -/** - * @brief s_event_exit_callback - * @param a_es - * @param a_flags - */ -static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags) -{ - (void) a_flags; - a_es->worker->signal_exit = true; - if(g_debug_reactor) - log_it(L_DEBUG, "Worker :%u signaled to exit", a_es->worker->id); -} - -/** - * @brief s_pipe_data_out_read_callback - * @param a_es - * @param a_arg - */ -static void s_queue_es_io_callback( dap_events_socket_t * a_es, void * a_arg) -{ - assert(a_es); - dap_worker_t * l_worker = a_es->worker; - dap_worker_msg_io_t * l_msg = a_arg; - assert(l_msg); - // Check if it was removed from the list - dap_events_socket_t *l_msg_es = dap_worker_esocket_find_uuid(l_worker, l_msg->esocket_uuid); - if ( l_msg_es == NULL){ - log_it(L_INFO, "We got i/o message for esocket %"DAP_UINT64_FORMAT_U" thats now not in list. Lost %zu data", l_msg->esocket_uuid, l_msg->data_size); - DAP_DELETE(l_msg); - return; - } + a_esocket->ev.events = events; - if (l_msg->flags_set & DAP_SOCK_CONNECTING) - if (! (l_msg_es->flags & DAP_SOCK_CONNECTING) ){ - l_msg_es->flags |= DAP_SOCK_CONNECTING; - dap_events_socket_worker_poll_update_unsafe(l_msg_es); + if( a_esocket->context){ + if ( epoll_ctl(a_esocket->context->epoll_fd, EPOLL_CTL_MOD, a_esocket->socket, &a_esocket->ev) ){ +#ifdef DAP_OS_WINDOWS + int l_errno = WSAGetLastError(); +#else + int l_errno = errno; +#endif + char l_errbuf[128]; + l_errbuf[0]=0; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR,"Can't update client socket state in the epoll_fd %"DAP_FORMAT_HANDLE": \"%s\" (%d)", + a_esocket->context->epoll_fd, l_errbuf, l_errno); + return l_errno; + } } - - if (l_msg->flags_set & DAP_SOCK_CONNECTING) - if (! (l_msg_es->flags & DAP_SOCK_CONNECTING) ){ - l_msg_es->flags ^= DAP_SOCK_CONNECTING; - dap_events_socket_worker_poll_update_unsafe(l_msg_es); + #elif defined (DAP_EVENTS_CAPS_POLL) + if( a_esocket->context && a_esocket->is_initalized){ + if (a_esocket->poll_index < a_esocket->context->poll_count ){ + struct pollfd * l_poll = &a_esocket->context->poll[a_esocket->poll_index]; + l_poll->events = a_esocket->poll_base_flags | POLLERR ; + // Check & add + if( a_esocket->flags & DAP_SOCK_READY_TO_READ ) + l_poll->events |= POLLIN; + if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ) + l_poll->events |= POLLOUT; + }else{ + log_it(L_ERROR, "Wrong poll index when remove from context (unsafe): %u when total count %u", a_esocket->poll_index, + a_esocket->context->poll_count); + return -666; + } + } + #elif defined (DAP_EVENTS_CAPS_KQUEUE) + if (a_esocket->socket != -1 ){ // Not everything we add in poll + struct kevent * l_event = &a_esocket->kqueue_event; + short l_filter =a_esocket->kqueue_base_filter; + u_short l_flags =a_esocket->kqueue_base_flags; + u_int l_fflags =a_esocket->kqueue_base_fflags; + + int l_kqueue_fd = a_esocket->context? a_esocket->context->kqueue_fd : -1; + if ( l_kqueue_fd == -1 ){ + log_it(L_ERROR, "Esocket is not assigned with anything ,exit"); + return -667; } - if (l_msg->flags_set & DAP_SOCK_READY_TO_READ) - dap_events_socket_set_readable_unsafe(l_msg_es, true); - if (l_msg->flags_unset & DAP_SOCK_READY_TO_READ) - dap_events_socket_set_readable_unsafe(l_msg_es, false); - if (l_msg->flags_set & DAP_SOCK_READY_TO_WRITE) - dap_events_socket_set_writable_unsafe(l_msg_es, true); - if (l_msg->flags_unset & DAP_SOCK_READY_TO_WRITE) - dap_events_socket_set_writable_unsafe(l_msg_es, false); - if (l_msg->data_size && l_msg->data) { - dap_events_socket_write_unsafe(l_msg_es, l_msg->data,l_msg->data_size); - DAP_DELETE(l_msg->data); - } - DAP_DELETE(l_msg); -} - -/** - * @brief s_socket_all_check_activity - * @param a_arg - */ -static bool s_socket_all_check_activity( void * a_arg) -{ - dap_worker_t *l_worker = (dap_worker_t*) a_arg; - assert(l_worker); - dap_events_socket_t *l_es = NULL, *tmp = NULL; - char l_curtimebuf[64]; - time_t l_curtime= time(NULL); - //dap_ctime_r(&l_curtime, l_curtimebuf); - //log_it(L_DEBUG,"Check sockets activity on worker #%u at %s", l_worker->id, l_curtimebuf); - pthread_rwlock_rdlock(&l_worker->esocket_rwlock); - HASH_ITER(hh_worker, l_worker->esockets, l_es, tmp ) { - pthread_rwlock_unlock(&l_worker->esocket_rwlock); - if (l_es->type == DESCRIPTOR_TYPE_SOCKET_CLIENT){ - if ( !(l_es->flags & DAP_SOCK_SIGNAL_CLOSE) && - ( l_curtime >= (l_es->last_time_active + s_connection_timeout) ) && !l_es->no_close ) { - log_it( L_INFO, "Socket %"DAP_FORMAT_SOCKET" timeout (diff %"DAP_UINT64_FORMAT_U" ), closing...", - l_es->socket, l_curtime - (time_t)l_es->last_time_active - s_connection_timeout ); - if (l_es->callbacks.error_callback) { - l_es->callbacks.error_callback(l_es, ETIMEDOUT); + // Check & add + bool l_is_error=false; + int l_errno=0; + if (a_esocket->type == DESCRIPTOR_TYPE_EVENT ){ + EV_SET(l_event, a_esocket->socket, EVFILT_USER,EV_ADD| EV_CLEAR ,0,0, &a_esocket->kqueue_event_catched_data ); + if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){ + l_is_error = true; + l_errno = errno; + } + }else{ + EV_SET(l_event, a_esocket->socket, l_filter,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); + if( a_esocket->flags & DAP_SOCK_READY_TO_READ ){ + EV_SET(l_event, a_esocket->socket, EVFILT_READ,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); + if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1 ){ + l_is_error = true; + l_errno = errno; + } + } + if( !l_is_error){ + if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ){ + EV_SET(l_event, a_esocket->socket, EVFILT_WRITE,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); + if(kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){ + l_is_error = true; + l_errno = errno; + } } - dap_events_socket_remove_and_delete_unsafe(l_es,false); } } - pthread_rwlock_rdlock(&l_worker->esocket_rwlock); - } - pthread_rwlock_unlock(&l_worker->esocket_rwlock); - return true; -} + if (l_is_error && l_errno == EBADF){ + log_it(L_ATT,"Poll update: socket %d (%p ) disconnected, rise CLOSE flag to remove from queue, lost %"DAP_UINT64_FORMAT_U":%" DAP_UINT64_FORMAT_U + " bytes",a_esocket->socket,a_esocket,a_esocket->buf_in_size,a_esocket->buf_out_size); + a_esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + a_esocket->buf_in_size = a_esocket->buf_out_size = 0; // Reset everything from buffer, we close it now all + }else if ( l_is_error && l_errno != EINPROGRESS && l_errno != ENOENT){ + char l_errbuf[128]; + l_errbuf[0]=0; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR,"Can't update client socket state on kqueue fd %d: \"%s\" (%d)", + l_kqueue_fd, l_errbuf, l_errno); + return l_errno; + } + } -/** - * @brief sap_worker_add_events_socket - * @param a_events_socket - * @param a_worker - */ -void dap_worker_add_events_socket(dap_events_socket_t * a_events_socket, dap_worker_t * a_worker) -{ -/* -#ifdef DAP_EVENTS_CAPS_KQUEUE - a_events_socket->worker = a_worker; - if(dap_worker_add_events_socket_unsafe(a_events_socket, a_worker)!=0) - a_events_socket->worker = NULL; - -#else*/ - if(g_debug_reactor) - log_it(L_DEBUG,"Worker add esocket %"DAP_FORMAT_SOCKET, a_events_socket->socket); - int l_ret = dap_events_socket_queue_ptr_send( a_worker->queue_es_new, a_events_socket ); - if(l_ret != 0 ){ - char l_errbuf[128]; - *l_errbuf = 0; - strerror_r(l_ret, l_errbuf, sizeof(l_errbuf)); - log_it(L_ERROR, "Can't send pointer in queue: \"%s\"(code %d)", l_errbuf, l_ret); - } -//#endif + #else + #error "Not defined dap_events_socket_set_writable_unsafe for your platform" + #endif + return 0; } -/** - * @brief dap_worker_add_events_socket_inter - * @param a_es_input - * @param a_events_socket - */ -void dap_worker_add_events_socket_inter(dap_events_socket_t * a_es_input, dap_events_socket_t * a_events_socket) -{ - if( dap_events_socket_queue_ptr_send_to_input( a_es_input, a_events_socket ) != 0 ){ - int l_errno = errno; - char l_errbuf[128]; - *l_errbuf = 0; - strerror_r(l_errno,l_errbuf,sizeof (l_errbuf)); - log_it(L_ERROR, "Cant send pointer to interthread queue input: \"%s\"(code %d)", l_errbuf, l_errno); - } -} /** - * @brief dap_worker_add_events_socket_unsafe - * @param a_worker + * @brief dap_context_add_events_socket_unsafe + * @param IOa_context * @param a_esocket */ -int dap_worker_add_events_socket_unsafe( dap_events_socket_t * a_esocket, dap_worker_t * a_worker ) +int dap_context_add_esocket(dap_context_t * a_context, dap_events_socket_t * a_esocket ) { + if(a_context == NULL || a_esocket == NULL) + return -1; + if(g_debug_reactor){ log_it(L_DEBUG,"Add event socket %p (socket %"DAP_FORMAT_SOCKET")", a_esocket, a_esocket->socket); } @@ -1191,41 +1015,45 @@ int dap_worker_add_events_socket_unsafe( dap_events_socket_t * a_esocket, dap_wo if(a_esocket->flags & DAP_SOCK_READY_TO_WRITE ) a_esocket->ev.events |= EPOLLOUT; a_esocket->ev.data.ptr = a_esocket; - return epoll_ctl(a_worker->epoll_fd, EPOLL_CTL_ADD, a_esocket->socket, &a_esocket->ev); + a_esocket->context = a_context; + return epoll_ctl(a_context->epoll_fd, EPOLL_CTL_ADD, a_esocket->socket, &a_esocket->ev); #elif defined (DAP_EVENTS_CAPS_POLL) - if ( a_worker->poll_count == a_worker->poll_count_max ){ // realloc - a_worker->poll_count_max *= 2; - log_it(L_WARNING, "Too many descriptors (%u), resizing array twice to %zu", a_worker->poll_count, a_worker->poll_count_max); - a_worker->poll =DAP_REALLOC(a_worker->poll, a_worker->poll_count_max * sizeof(*a_worker->poll)); - a_worker->poll_esocket =DAP_REALLOC(a_worker->poll_esocket, a_worker->poll_count_max * sizeof(*a_worker->poll_esocket)); + if ( a_context->poll_count == a_context->poll_count_max ){ // realloc + a_context->poll_count_max *= 2; + log_it(L_WARNING, "Too many descriptors (%u), resizing array twice to %zu", a_context->poll_count, a_context->poll_count_max); + a_context->poll =DAP_REALLOC(a_context->poll, a_context->poll_count_max * sizeof(*a_context->poll)); + a_context->poll_esocket =DAP_REALLOC(a_context->poll_esocket, a_context->poll_count_max * sizeof(*a_context->poll_esocket)); } - a_worker->poll[a_worker->poll_count].fd = a_esocket->socket; - a_esocket->poll_index = a_worker->poll_count; - a_worker->poll[a_worker->poll_count].events = a_esocket->poll_base_flags; + a_context->poll[a_context->poll_count].fd = a_esocket->socket; + a_esocket->poll_index = a_context->poll_count; + a_context->poll[a_context->poll_count].events = a_esocket->poll_base_flags; if( a_esocket->flags & DAP_SOCK_READY_TO_READ ) - a_worker->poll[a_worker->poll_count].events |= POLLIN; + a_context->poll[a_context->poll_count].events |= POLLIN; if( (a_esocket->flags & DAP_SOCK_READY_TO_WRITE) || (a_esocket->flags & DAP_SOCK_CONNECTING) ) - a_worker->poll[a_worker->poll_count].events |= POLLOUT; + a_context->poll[a_context->poll_count].events |= POLLOUT; - a_worker->poll_esocket[a_worker->poll_count] = a_esocket; - a_worker->poll_count++; + a_context->poll_esocket[a_context->poll_count] = a_esocket; + a_context->poll_count++; + a_esocket->context = a_context; return 0; #elif defined (DAP_EVENTS_CAPS_KQUEUE) - a_esocket->worker = a_worker; if ( a_esocket->type == DESCRIPTOR_TYPE_QUEUE ){ + a_esocket->context = a_context; return 0; } if ( a_esocket->type == DESCRIPTOR_TYPE_EVENT && a_esocket->pipe_out){ + a_esocket->context = a_context; return 0; } struct kevent l_event; u_short l_flags = a_esocket->kqueue_base_flags; u_int l_fflags = a_esocket->kqueue_base_fflags; short l_filter = a_esocket->kqueue_base_filter; - int l_kqueue_fd =a_worker->kqueue_fd; + int l_kqueue_fd =a_context->kqueue_fd; if ( l_kqueue_fd == -1 ){ log_it(L_ERROR, "Esocket is not assigned with anything ,exit"); + return -1; } // Check & add bool l_is_error=false; @@ -1277,48 +1105,427 @@ int dap_worker_add_events_socket_unsafe( dap_events_socket_t * a_esocket, dap_wo log_it(L_ERROR,"Can't update client socket state on kqueue fd %d: \"%s\" (%d)", a_esocket->socket, l_errbuf, l_errno); return l_errno; - }else + }else{ + a_esocket->context = a_context; return 0; - + } #else -#error "Unimplemented new esocket on worker callback for current platform" +#error "Unimplemented new esocket on context callback for current platform" #endif } + /** - * @brief dap_worker_exec_callback_on + * @brief dap_context_esocket_find_by_uuid + * @param a_context + * @param a_es_uuid + * @return */ -void dap_worker_exec_callback_on(dap_worker_t * a_worker, dap_worker_callback_t a_callback, void * a_arg) +dap_events_socket_t *dap_context_esocket_find_by_uuid(dap_context_t * a_context, dap_events_socket_uuid_t a_es_uuid ) { - dap_worker_msg_callback_t * l_msg = DAP_NEW_Z(dap_worker_msg_callback_t); - l_msg->callback = a_callback; - l_msg->arg = a_arg; - int l_ret=dap_events_socket_queue_ptr_send( a_worker->queue_callback,l_msg ); - if(l_ret != 0 ){ - char l_errbuf[128]; - *l_errbuf = 0; - strerror_r(l_ret,l_errbuf,sizeof (l_errbuf)); - log_it(L_ERROR, "Cant send pointer in queue: \"%s\"(code %d)", l_errbuf, l_ret); + if(a_context == NULL){ + log_it(L_ERROR, "Worker is NULL, can't fund esocket by UUID"); + return NULL; } - + dap_events_socket_t * l_ret = NULL; + if(a_context->esockets ) { + //HASH_FIND_PTR( a_worker->context->esockets, &a_es_uuid,l_ret ); + HASH_FIND(hh_worker, a_context->esockets, &a_es_uuid, sizeof(a_es_uuid), l_ret ); + } + return l_ret; } +/** + * @brief dap_context_create_esocket_queue + * @param a_context + * @param a_callback + * @return + */ + dap_events_socket_t * dap_context_create_esocket_queue(dap_context_t * a_context, dap_events_socket_callback_queue_ptr_t a_callback) +{ + dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); + if(!l_es){ + log_it(L_ERROR,"Can't allocate esocket!"); + return NULL; + } + + l_es->type = DESCRIPTOR_TYPE_QUEUE; + l_es->flags = DAP_SOCK_QUEUE_PTR; + l_es->uuid = dap_uuid_generate_uint64(); + + l_es->callbacks.queue_ptr_callback = a_callback; // Arm event callback + l_es->buf_in_size_max = DAP_QUEUE_MAX_MSGS * sizeof(void*); + l_es->buf_in = DAP_NEW_Z_SIZE(byte_t,l_es->buf_in_size_max); + l_es->buf_out = NULL; + +#if defined(DAP_EVENTS_CAPS_EPOLL) + l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; +#elif defined(DAP_EVENTS_CAPS_POLL) + l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; +#elif defined(DAP_EVENTS_CAPS_KQUEUE) + l_es->kqueue_event_catched_data.esocket = l_es; + l_es->kqueue_base_flags = EV_CLEAR; + l_es->kqueue_base_fflags = 0; + l_es->kqueue_base_filter = EVFILT_USER; + l_es->socket = arc4random(); +#else +#error "Not defined s_create_type_queue_ptr for your platform" +#endif + + +#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) || defined(DAP_EVENTS_CAPS_QUEUE_PIPE) + int l_pipe[2]; + l_errbuf[0]=0; +#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) + if( pipe2(l_pipe,O_DIRECT | O_NONBLOCK ) < 0 ){ +#elif defined(DAP_EVENTS_CAPS_QUEUE_PIPE) + if( pipe(l_pipe) < 0 ){ +#endif + l_errno = errno; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + switch (l_errno) { + case EINVAL: log_it(L_CRITICAL, "Too old linux version thats doesn't support O_DIRECT flag for pipes (%s)", l_errbuf); break; + default: log_it( L_ERROR, "Error detected, can't create pipe(): '%s' (%d)", l_errbuf, l_errno); + } + DAP_DELETE(l_es); + return NULL; + } + //else + // log_it(L_DEBUG, "Created one-way unnamed packet pipe %d->%d", l_pipe[0], l_pipe[1]); + l_es->fd = l_pipe[0]; + l_es->fd2 = l_pipe[1]; + +#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE) + // If we have no pipe2() we should set nonblock mode via fcntl + if (l_es->fd > 0 && l_es->fd2 > 0 ) { + int l_flags = fcntl(l_es->fd, F_GETFL, 0); + if (l_flags != -1){ + l_flags |= O_NONBLOCK); + fcntl(l_es->fd, F_SETFL, l_flags) == 0); + } + l_flags = fcntl(l_es->fd2, F_GETFL, 0); + if (l_flags != -1){ + l_flags |= O_NONBLOCK); + fcntl(l_es->fd2, F_SETFL, l_flags) == 0); + } + } +#endif + +#if !defined (DAP_OS_ANDROID) + FILE* l_sys_max_pipe_size_fd = fopen("/proc/sys/fs/pipe-max-size", "r"); + if (l_sys_max_pipe_size_fd) { + const int l_file_buf_size = 64; + char l_file_buf[l_file_buf_size]; + memset(l_file_buf, 0, l_file_buf_size); + fread(l_file_buf, l_file_buf_size, 1, l_sys_max_pipe_size_fd); + uint64_t l_sys_max_pipe_size = strtoull(l_file_buf, 0, 10); + fcntl(l_pipe[0], F_SETPIPE_SZ, l_sys_max_pipe_size); + fclose(l_sys_max_pipe_size_fd); + } +#endif + +#elif defined (DAP_EVENTS_CAPS_QUEUE_MQUEUE) + int l_errno; + char l_errbuf[128] = {0}, l_mq_name[64] = {0}; + struct mq_attr l_mq_attr; + static atomic_uint l_mq_last_number = 0; + + + l_mq_attr.mq_maxmsg = DAP_QUEUE_MAX_MSGS; // Don't think we need to hold more than 1024 messages + l_mq_attr.mq_msgsize = sizeof (void*); // We send only pointer on memory (???!!!), + // so use it with shared memory if you do access from another process + + l_es->mqd_id = atomic_fetch_add( &l_mq_last_number, 1); + snprintf(l_mq_name,sizeof (l_mq_name), "/%s-queue_ptr-%u", dap_get_appname(), l_es->mqd_id ); + // if ( (l_errno = mq_unlink(l_mq_name)) ) /* Mark this MQ to be deleted as the process will be terminated */ + // log_it(L_DEBUG, "mq_unlink(%s)->%d", l_mq_name, l_errno); + + if ( 0 >= (l_es->mqd = mq_open(l_mq_name, O_CREAT|O_RDWR |O_NONBLOCK, 0700, &l_mq_attr)) ) + { + log_it(L_CRITICAL,"Can't create mqueue descriptor %s: \"%s\" code %d (%s)", l_mq_name, l_errbuf, errno, + (strerror_r(errno, l_errbuf, sizeof (l_errbuf)), l_errbuf) ); + + DAP_DELETE(l_es->buf_in); + DAP_DELETE(l_es); + return NULL; + } + +#elif defined DAP_EVENTS_CAPS_MSMQ + l_es->socket = socket(AF_INET, SOCK_DGRAM, 0); + + if (l_es->socket == INVALID_SOCKET) { + log_it(L_ERROR, "Error creating socket for TYPE_QUEUE: %d", WSAGetLastError()); + DAP_DELETE(l_es); + return NULL; + } + + int buffsize = 1024; + setsockopt(l_es->socket, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int)); + + int reuse = 1; + if (setsockopt(l_es->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket, err: %d", WSAGetLastError()); + + unsigned long l_mode = 1; + ioctlsocket(l_es->socket, FIONBIO, &l_mode); + + int l_addr_len; + struct sockaddr_in l_addr; + l_addr.sin_family = AF_INET; + IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; + l_addr.sin_addr = _in_addr; + l_addr.sin_port = 0; //l_es->socket + 32768; + l_addr_len = sizeof(struct sockaddr_in); + + if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { + log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); + } else { + int dummy = 100; + getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); + l_es->port = l_addr.sin_port; + //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); + } + + MQQUEUEPROPS l_qps; + MQPROPVARIANT l_qp_var[1]; + QUEUEPROPID l_qp_id[1]; + HRESULT l_q_status[1]; + + WCHAR l_pathname[MQ_MAX_Q_NAME_LEN - 10] = { 0 }; + static atomic_uint s_queue_num = 0; + int pos = 0; +#ifdef DAP_BRAND + pos = _snwprintf_s(l_pathname, sizeof(l_pathname)/sizeof(l_pathname[0]), _TRUNCATE, L".\\PRIVATE$\\" DAP_BRAND "mq%d", l_es->mq_num = s_queue_num++); +#else + pos = _snwprintf_s(l_pathname, sizeof(l_pathname)/sizeof(l_pathname[0]), _TRUNCATE, L".\\PRIVATE$\\%hs_esmq%d", dap_get_appname(), l_es->mq_num = s_queue_num++); +#endif + if (pos < 0) { + log_it(L_ERROR, "Message queue path error"); + DAP_DELETE(l_es); + return NULL; + } + u_long l_p_id = 0; + l_qp_id[l_p_id] = PROPID_Q_PATHNAME; + l_qp_var[l_p_id].vt = VT_LPWSTR; + l_qp_var[l_p_id].pwszVal = l_pathname; + l_p_id++; + + l_qps.cProp = l_p_id; + l_qps.aPropID = l_qp_id; + l_qps.aPropVar = l_qp_var; + l_qps.aStatus = l_q_status; + + WCHAR l_direct_name[MQ_MAX_Q_NAME_LEN] = { 0 }; + WCHAR l_format_name[sizeof(l_direct_name) - 10] = { 0 }; + DWORD l_buflen = sizeof(l_format_name); + HRESULT hr = MQCreateQueue(NULL, &l_qps, l_format_name, &l_buflen); + if ((hr != MQ_OK) && (hr != MQ_ERROR_QUEUE_EXISTS) && (hr != MQ_INFORMATION_PROPERTY)) { + log_it(L_ERROR, "Can't create message queue for queue type, error: %ld", hr); + DAP_DELETE(l_es); + return NULL; + } + _snwprintf_s(l_direct_name, sizeof(l_direct_name)/sizeof(l_direct_name[0]), _TRUNCATE, L"DIRECT=OS:%ls", l_pathname); + + hr = MQOpenQueue(l_direct_name, MQ_SEND_ACCESS, MQ_DENY_NONE, &(l_es->mqh)); + if (hr == MQ_ERROR_QUEUE_NOT_FOUND) { + log_it(L_INFO, "Queue still not created, wait a bit..."); + Sleep(300); + hr = MQOpenQueue(l_direct_name, MQ_SEND_ACCESS, MQ_DENY_NONE, &(l_es->mqh)); + if (hr != MQ_OK) { + log_it(L_ERROR, "Can't open message queue for queue type, error: %ld", hr); + DAP_DELETE(l_es); + MQDeleteQueue(l_format_name); + return NULL; + } + } + hr = MQOpenQueue(l_direct_name, MQ_RECEIVE_ACCESS, MQ_DENY_NONE, &(l_es->mqh_recv)); + if (hr != MQ_OK) { + log_it(L_ERROR, "Can't open message queue for queue type, error: %ld", hr); + DAP_DELETE(l_es); + MQCloseQueue(l_es->mqh); + MQDeleteQueue(l_format_name); + return NULL; + } + hr = MQPurgeQueue(l_es->mqh_recv); + if (hr != MQ_OK) { + log_it(L_DEBUG, "Message queue %u NOT purged, possible data corruption, err %ld", l_es->mq_num, hr); + } +#elif defined (DAP_EVENTS_CAPS_KQUEUE) + // We don't create descriptor for kqueue at all +#else +#error "Not implemented s_create_type_queue_ptr() on your platform" +#endif + + if ( a_context) { + if(dap_context_add_esocket(a_context, l_es)) { +#ifdef DAP_OS_WINDOWS + errno = WSAGetLastError(); +#endif + log_it(L_ERROR, "Can't add esocket %"DAP_FORMAT_SOCKET" to polling, err %d", l_es->socket, errno); + } + } + + return l_es; +} /** - * @brief dap_worker_add_events_socket - * @param a_worker - * @param a_events_socket + * @brief s_create_type_event + * @param a_context + * @param a_callback + * @return */ -dap_worker_t *dap_worker_add_events_socket_auto( dap_events_socket_t *a_es) +dap_events_socket_t * dap_context_create_esocket_event(dap_context_t * a_context, dap_events_socket_callback_event_t a_callback) { -// struct epoll_event ev = {0}; - dap_worker_t *l_worker = dap_events_worker_get_auto( ); + dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); if (!l_es) return NULL; + l_es->buf_out_size_max = l_es->buf_in_size_max = 1; + l_es->buf_out = DAP_NEW_Z_SIZE(byte_t, l_es->buf_out_size_max); + l_es->type = DESCRIPTOR_TYPE_EVENT; + l_es->uuid = dap_uuid_generate_uint64(); + + l_es->callbacks.event_callback = a_callback; // Arm event callback +#if defined(DAP_EVENTS_CAPS_EPOLL) + l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; +#elif defined(DAP_EVENTS_CAPS_POLL) + l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; +#elif defined(DAP_EVENTS_CAPS_KQUEUE) + l_es->kqueue_base_flags = EV_CLEAR; + l_es->kqueue_base_filter = EVFILT_USER; + l_es->socket = arc4random(); + l_es->kqueue_event_catched_data.esocket = l_es; +#else +#error "Not defined s_create_type_event for your platform" +#endif - a_es->events = l_worker->events; - dap_worker_add_events_socket( a_es, l_worker); - return l_worker; +#ifdef DAP_EVENTS_CAPS_EVENT_EVENTFD + if((l_es->fd = eventfd(0,EFD_NONBLOCK) ) < 0 ){ + int l_errno = errno; + char l_errbuf[128]; + l_errbuf[0]=0; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + switch (l_errno) { + case EINVAL: log_it(L_CRITICAL, "An unsupported value was specified in flags: \"%s\" (%d)", l_errbuf, l_errno); break; + case EMFILE: log_it(L_CRITICAL, "The per-process limit on the number of open file descriptors has been reached: \"%s\" (%d)", l_errbuf, l_errno); break; + case ENFILE: log_it(L_CRITICAL, "The system-wide limit on the total number of open files has been reached: \"%s\" (%d)", l_errbuf, l_errno); break; + case ENODEV: log_it(L_CRITICAL, "Could not mount (internal) anonymous inode device: \"%s\" (%d)", l_errbuf, l_errno); break; + case ENOMEM: log_it(L_CRITICAL, "There was insufficient memory to create a new eventfd file descriptor: \"%s\" (%d)", l_errbuf, l_errno); break; + default: log_it( L_ERROR, "Error detected, can't create eventfd: '%s' (%d)", l_errbuf, l_errno); + } + DAP_DELETE(l_es); + return NULL; + }else { + l_es->fd2 = l_es->fd; + //log_it(L_DEBUG, "Created eventfd descriptor %d", l_es->fd ); + } +#elif defined DAP_OS_WINDOWS + + + l_es->socket = socket(AF_INET, SOCK_DGRAM, 0); + + if (l_es->socket == INVALID_SOCKET) { + log_it(L_ERROR, "Error creating socket for TYPE_QUEUE: %d", WSAGetLastError()); + DAP_DELETE(l_es); + return NULL; + } + + int buffsize = 1024; + setsockopt(l_es->socket, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int)); + + unsigned long l_mode = 1; + ioctlsocket(l_es->socket, FIONBIO, &l_mode); + + int reuse = 1; + if (setsockopt(l_es->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket, err: %d", WSAGetLastError()); + + int l_addr_len; + struct sockaddr_in l_addr; + l_addr.sin_family = AF_INET; + IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; + l_addr.sin_addr = _in_addr; + l_addr.sin_port = 0; //l_es->socket + 32768; + l_addr_len = sizeof(struct sockaddr_in); + + if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { + log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); + } else { + int dummy = 100; + getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); + l_es->port = l_addr.sin_port; + //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); + } +#elif defined(DAP_EVENTS_CAPS_KQUEUE) + // nothing to do +#else +#error "Not defined dap_context_create_esocket_event() on your platform" +#endif + if(a_context) + dap_context_add_esocket(a_context,l_es); + return l_es; } +/** + * @brief dap_context_create_esocket_pipe + * @param a_context + * @param a_callback + * @param a_flags + * @return + */ +dap_events_socket_t * dap_context_create_esocket_pipe(dap_context_t * a_context, dap_events_socket_callback_t a_callback, uint32_t a_flags) +{ +#ifdef DAP_OS_WINDOWS + UNUSED(a_w); + UNUSED(a_callback); + UNUSED(a_flags); + return NULL; +#else + UNUSED(a_flags); + dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); + l_es->type = DESCRIPTOR_TYPE_PIPE; + l_es->uuid = dap_uuid_generate_uint64(); + l_es->callbacks.read_callback = a_callback; // Arm event callback +#if defined(DAP_EVENTS_CAPS_EPOLL) + l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; +#elif defined(DAP_EVENTS_CAPS_POLL) + l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; +#elif defined(DAP_EVENTS_CAPS_KQUEUE) + l_es->kqueue_event_catched_data.esocket = l_es; + l_es->kqueue_base_flags = EV_ENABLE | EV_CLEAR; + l_es->kqueue_base_fflags = NOTE_DELETE | NOTE_REVOKE ; +#if !defined(DAP_OS_DARWIN) + l_es->kqueue_base_fflags |= NOTE_CLOSE | NOTE_CLOSE_WRITE ; +#endif + l_es->kqueue_base_filter = EVFILT_VNODE; +#else +#error "Not defined s_create_type_pipe for your platform" +#endif + +#if defined(DAP_EVENTS_CAPS_PIPE_POSIX) + int l_pipe[2]; + int l_errno; + char l_errbuf[128]; + l_errbuf[0]=0; + if( pipe(l_pipe) < 0 ){ + l_errno = errno; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it( L_ERROR, "Error detected, can't create pipe(): '%s' (%d)", l_errbuf, l_errno); + DAP_DELETE(l_es); + return NULL; + }//else + // log_it(L_DEBUG, "Created one-way unnamed bytestream pipe %d->%d", l_pipe[0], l_pipe[1]); + l_es->fd = l_pipe[0]; + l_es->fd2 = l_pipe[1]; +#if defined DAP_OS_UNIX + fcntl( l_pipe[0], F_SETFL, O_NONBLOCK); + fcntl( l_pipe[1], F_SETFL, O_NONBLOCK); + // this sort of fd doesn't suit ioctlsocket()... +#endif +#else +#error "No defined s_create_type_pipe() for your platform" +#endif + dap_context_add_esocket(a_context,l_es); + return l_es; +#endif +} diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/io/dap_events.c similarity index 98% rename from dap-sdk/net/core/dap_events.c rename to dap-sdk/io/dap_events.c index 25a4d7fbeaf6e2ac83d8f79f19b53d0244276edd..64f75ff883f7997c0b5106ba434b2715ae07bddb 100644 --- a/dap-sdk/net/core/dap_events.c +++ b/dap-sdk/io/dap_events.c @@ -93,6 +93,7 @@ typedef cpuset_t cpu_set_t; // Adopt BSD CPU setstructure to POSIX variant #include "dap_strfuncs.h" #include "dap_server.h" #include "dap_events.h" +#include "dap_context.h" #include "dap_events_socket.h" #include "dap_proc_thread.h" #include "dap_config.h" @@ -223,6 +224,12 @@ int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout ) if ( !s_workers || !s_threads ) return -1; + if(dap_context_init() != 0){ + log_it( L_CRITICAL, "Can't init client submodule dap_context( )" ); + goto err; + + } + dap_worker_init(a_conn_timeout); if ( dap_events_socket_init() != 0 ) { log_it( L_CRITICAL, "Can't init client submodule dap_events_socket_init( )" ); @@ -333,8 +340,8 @@ int dap_events_start( dap_events_t *a_events ) l_worker->id = i; l_worker->events = a_events; - l_worker->esockets = NULL; - pthread_rwlock_init(&l_worker->esocket_rwlock,NULL); + l_worker->context = dap_context_new(); + l_worker->context->worker = l_worker; pthread_mutex_init(& l_worker->started_mutex, NULL); pthread_cond_init( & l_worker->started_cond, NULL); diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/io/dap_events_socket.c similarity index 69% rename from dap-sdk/net/core/dap_events_socket.c rename to dap-sdk/io/dap_events_socket.c index 7dc6f1fe619fa29244046321e9417134b129de1d..7ea684c7282c11731e7f0177963ae8cb6f5fbc96 100644 --- a/dap-sdk/net/core/dap_events_socket.c +++ b/dap-sdk/io/dap_events_socket.c @@ -85,6 +85,7 @@ typedef cpuset_t cpu_set_t; // Adopt BSD CPU setstructure to POSIX variant #include "dap_events.h" #include "dap_timerfd.h" +#include "dap_context.h" #include "dap_events_socket.h" #define LOG_TAG "dap_events_socket" @@ -192,7 +193,6 @@ dap_events_socket_t *dap_events_socket_wrap_no_add( dap_events_t *a_events, return NULL; l_ret->socket = a_sock; - l_ret->events = a_events; l_ret->uuid = dap_uuid_generate_uint64(); if (a_callbacks) memcpy(&l_ret->callbacks, a_callbacks, sizeof(l_ret->callbacks) ); @@ -254,7 +254,7 @@ void dap_events_socket_assign_on_worker_inter(dap_events_socket_t * a_es_input, */ void dap_events_socket_reassign_between_workers_unsafe(dap_events_socket_t * a_es, dap_worker_t * a_worker_new) { - dap_worker_t * l_worker = a_es->worker; + dap_worker_t * l_worker = a_es->context->worker; dap_events_socket_t * l_queue_input= l_worker->queue_es_new_input[a_worker_new->id]; log_it(L_DEBUG, "Reassign between %u->%u workers: %p (%d) ", l_worker->id, a_worker_new->id, a_es, a_es->fd ); @@ -288,71 +288,7 @@ void dap_events_socket_reassign_between_workers_mt(dap_worker_t * a_worker_old, } } -/** - * @brief s_create_type_pipe - * @param a_w - * @param a_callback - * @param a_flags - * @return - */ -dap_events_socket_t * s_create_type_pipe(dap_worker_t * a_w, dap_events_socket_callback_t a_callback, uint32_t a_flags) -{ -#ifdef DAP_OS_WINDOWS - UNUSED(a_w); - UNUSED(a_callback); - UNUSED(a_flags); - return NULL; -#else - UNUSED(a_flags); - dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); - l_es->type = DESCRIPTOR_TYPE_PIPE; - l_es->worker = a_w; - l_es->events = a_w->events; - l_es->uuid = dap_uuid_generate_uint64(); - l_es->callbacks.read_callback = a_callback; // Arm event callback -#if defined(DAP_EVENTS_CAPS_EPOLL) - l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; -#elif defined(DAP_EVENTS_CAPS_POLL) - l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; -#elif defined(DAP_EVENTS_CAPS_KQUEUE) - l_es->kqueue_event_catched_data.esocket = l_es; - l_es->kqueue_base_flags = EV_ENABLE | EV_CLEAR; - l_es->kqueue_base_fflags = NOTE_DELETE | NOTE_REVOKE ; -#if !defined(DAP_OS_DARWIN) - l_es->kqueue_base_fflags |= NOTE_CLOSE | NOTE_CLOSE_WRITE ; -#endif - l_es->kqueue_base_filter = EVFILT_VNODE; -#else -#error "Not defined s_create_type_pipe for your platform" -#endif - -#if defined(DAP_EVENTS_CAPS_PIPE_POSIX) - int l_pipe[2]; - int l_errno; - char l_errbuf[128]; - l_errbuf[0]=0; - if( pipe(l_pipe) < 0 ){ - l_errno = errno; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it( L_ERROR, "Error detected, can't create pipe(): '%s' (%d)", l_errbuf, l_errno); - DAP_DELETE(l_es); - return NULL; - }//else - // log_it(L_DEBUG, "Created one-way unnamed bytestream pipe %d->%d", l_pipe[0], l_pipe[1]); - l_es->fd = l_pipe[0]; - l_es->fd2 = l_pipe[1]; -#if defined DAP_OS_UNIX - fcntl( l_pipe[0], F_SETFL, O_NONBLOCK); - fcntl( l_pipe[1], F_SETFL, O_NONBLOCK); - // this sort of fd doesn't suit ioctlsocket()... -#endif -#else -#error "No defined s_create_type_pipe() for your platform" -#endif - return l_es; -#endif -} /** * @brief dap_events_socket_create_type_pipe_mt @@ -363,7 +299,7 @@ dap_events_socket_t * s_create_type_pipe(dap_worker_t * a_w, dap_events_socket_c */ dap_events_socket_t * dap_events_socket_create_type_pipe_mt(dap_worker_t * a_w, dap_events_socket_callback_t a_callback, uint32_t a_flags) { - dap_events_socket_t * l_es = s_create_type_pipe(a_w, a_callback, a_flags); + dap_events_socket_t * l_es = dap_context_create_esocket_pipe(NULL, a_callback, a_flags); dap_worker_add_events_socket_unsafe(l_es,a_w); return l_es; } @@ -433,7 +369,7 @@ dap_events_socket_t * dap_events_socket_create(dap_events_desc_type_t a_type, da */ dap_events_socket_t * dap_events_socket_create_type_pipe_unsafe(dap_worker_t * a_w, dap_events_socket_callback_t a_callback, uint32_t a_flags) { - dap_events_socket_t * l_es = s_create_type_pipe(a_w, a_callback, a_flags); + dap_events_socket_t * l_es = dap_context_create_esocket_pipe(NULL, a_callback, a_flags); dap_worker_add_events_socket_unsafe(l_es,a_w); return l_es; } @@ -470,7 +406,6 @@ dap_events_socket_t * dap_events_socket_queue_ptr_create_input(dap_events_socket l_es->buf_in_size_max = DAP_QUEUE_MAX_MSGS * sizeof(void*); l_es->buf_in = DAP_NEW_Z_SIZE(byte_t,l_es->buf_in_size_max ); //l_es->buf_out_size = 8 * sizeof(void*); - l_es->events = a_es->events; l_es->uuid = dap_uuid_generate_uint64(); #if defined(DAP_EVENTS_CAPS_EPOLL) l_es->ev_base_flags = EPOLLERR | EPOLLRDHUP | EPOLLHUP; @@ -566,232 +501,6 @@ dap_events_socket_t * dap_events_socket_queue_ptr_create_input(dap_events_socket return l_es; } -/** - * @brief s_create_type_queue - * @param a_w - * @param a_flags - * @return - */ -dap_events_socket_t * s_create_type_queue_ptr(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback) -{ - dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); - if(!l_es){ - log_it(L_ERROR,"Can't allocate esocket!"); - return NULL; - } - - l_es->type = DESCRIPTOR_TYPE_QUEUE; - l_es->flags = DAP_SOCK_QUEUE_PTR; - l_es->uuid = dap_uuid_generate_uint64(); - if (a_w){ - l_es->events = a_w->events; - l_es->worker = a_w; - } - - l_es->callbacks.queue_ptr_callback = a_callback; // Arm event callback - l_es->buf_in_size_max = DAP_QUEUE_MAX_MSGS * sizeof(void*); - l_es->buf_in = DAP_NEW_Z_SIZE(byte_t,l_es->buf_in_size_max); - l_es->buf_out = NULL; - -#if defined(DAP_EVENTS_CAPS_EPOLL) - l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; -#elif defined(DAP_EVENTS_CAPS_POLL) - l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; -#elif defined(DAP_EVENTS_CAPS_KQUEUE) - l_es->kqueue_event_catched_data.esocket = l_es; - l_es->kqueue_base_flags = EV_CLEAR; - l_es->kqueue_base_fflags = 0; - l_es->kqueue_base_filter = EVFILT_USER; - l_es->socket = arc4random(); -#else -#error "Not defined s_create_type_queue_ptr for your platform" -#endif - - -#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) || defined(DAP_EVENTS_CAPS_QUEUE_PIPE) - int l_pipe[2]; - l_errbuf[0]=0; -#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) - if( pipe2(l_pipe,O_DIRECT | O_NONBLOCK ) < 0 ){ -#elif defined(DAP_EVENTS_CAPS_QUEUE_PIPE) - if( pipe(l_pipe) < 0 ){ -#endif - l_errno = errno; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - switch (l_errno) { - case EINVAL: log_it(L_CRITICAL, "Too old linux version thats doesn't support O_DIRECT flag for pipes (%s)", l_errbuf); break; - default: log_it( L_ERROR, "Error detected, can't create pipe(): '%s' (%d)", l_errbuf, l_errno); - } - DAP_DELETE(l_es); - return NULL; - } - //else - // log_it(L_DEBUG, "Created one-way unnamed packet pipe %d->%d", l_pipe[0], l_pipe[1]); - l_es->fd = l_pipe[0]; - l_es->fd2 = l_pipe[1]; - -#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE) - // If we have no pipe2() we should set nonblock mode via fcntl - if (l_es->fd > 0 && l_es->fd2 > 0 ) { - int l_flags = fcntl(l_es->fd, F_GETFL, 0); - if (l_flags != -1){ - l_flags |= O_NONBLOCK); - fcntl(l_es->fd, F_SETFL, l_flags) == 0); - } - l_flags = fcntl(l_es->fd2, F_GETFL, 0); - if (l_flags != -1){ - l_flags |= O_NONBLOCK); - fcntl(l_es->fd2, F_SETFL, l_flags) == 0); - } - } -#endif - -#if !defined (DAP_OS_ANDROID) - FILE* l_sys_max_pipe_size_fd = fopen("/proc/sys/fs/pipe-max-size", "r"); - if (l_sys_max_pipe_size_fd) { - const int l_file_buf_size = 64; - char l_file_buf[l_file_buf_size]; - memset(l_file_buf, 0, l_file_buf_size); - fread(l_file_buf, l_file_buf_size, 1, l_sys_max_pipe_size_fd); - uint64_t l_sys_max_pipe_size = strtoull(l_file_buf, 0, 10); - fcntl(l_pipe[0], F_SETPIPE_SZ, l_sys_max_pipe_size); - fclose(l_sys_max_pipe_size_fd); - } -#endif - -#elif defined (DAP_EVENTS_CAPS_QUEUE_MQUEUE) - int l_errno; - char l_errbuf[128] = {0}, l_mq_name[64] = {0}; - struct mq_attr l_mq_attr; - static atomic_uint l_mq_last_number = 0; - - - l_mq_attr.mq_maxmsg = DAP_QUEUE_MAX_MSGS; // Don't think we need to hold more than 1024 messages - l_mq_attr.mq_msgsize = sizeof (void*); // We send only pointer on memory (???!!!), - // so use it with shared memory if you do access from another process - - l_es->mqd_id = atomic_fetch_add( &l_mq_last_number, 1); - snprintf(l_mq_name,sizeof (l_mq_name), "/%s-queue_ptr-%u", dap_get_appname(), l_es->mqd_id ); - // if ( (l_errno = mq_unlink(l_mq_name)) ) /* Mark this MQ to be deleted as the process will be terminated */ - // log_it(L_DEBUG, "mq_unlink(%s)->%d", l_mq_name, l_errno); - - if ( 0 >= (l_es->mqd = mq_open(l_mq_name, O_CREAT|O_RDWR |O_NONBLOCK, 0700, &l_mq_attr)) ) - { - log_it(L_CRITICAL,"Can't create mqueue descriptor %s: \"%s\" code %d (%s)", l_mq_name, l_errbuf, errno, - (strerror_r(errno, l_errbuf, sizeof (l_errbuf)), l_errbuf) ); - - DAP_DELETE(l_es->buf_in); - DAP_DELETE(l_es); - return NULL; - } - -#elif defined DAP_EVENTS_CAPS_MSMQ - l_es->socket = socket(AF_INET, SOCK_DGRAM, 0); - - if (l_es->socket == INVALID_SOCKET) { - log_it(L_ERROR, "Error creating socket for TYPE_QUEUE: %d", WSAGetLastError()); - DAP_DELETE(l_es); - return NULL; - } - - int buffsize = 1024; - setsockopt(l_es->socket, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int)); - - int reuse = 1; - if (setsockopt(l_es->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) - log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket, err: %d", WSAGetLastError()); - - unsigned long l_mode = 1; - ioctlsocket(l_es->socket, FIONBIO, &l_mode); - - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = 0; //l_es->socket + 32768; - l_addr_len = sizeof(struct sockaddr_in); - - if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { - log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); - } else { - int dummy = 100; - getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); - l_es->port = l_addr.sin_port; - //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); - } - - MQQUEUEPROPS l_qps; - MQPROPVARIANT l_qp_var[1]; - QUEUEPROPID l_qp_id[1]; - HRESULT l_q_status[1]; - - WCHAR l_pathname[MQ_MAX_Q_NAME_LEN - 10] = { 0 }; - static atomic_uint s_queue_num = 0; - int pos = 0; -#ifdef DAP_BRAND - pos = _snwprintf_s(l_pathname, sizeof(l_pathname)/sizeof(l_pathname[0]), _TRUNCATE, L".\\PRIVATE$\\" DAP_BRAND "mq%d", l_es->mq_num = s_queue_num++); -#else - pos = _snwprintf_s(l_pathname, sizeof(l_pathname)/sizeof(l_pathname[0]), _TRUNCATE, L".\\PRIVATE$\\%hs_esmq%d", dap_get_appname(), l_es->mq_num = s_queue_num++); -#endif - if (pos < 0) { - log_it(L_ERROR, "Message queue path error"); - DAP_DELETE(l_es); - return NULL; - } - u_long l_p_id = 0; - l_qp_id[l_p_id] = PROPID_Q_PATHNAME; - l_qp_var[l_p_id].vt = VT_LPWSTR; - l_qp_var[l_p_id].pwszVal = l_pathname; - l_p_id++; - - l_qps.cProp = l_p_id; - l_qps.aPropID = l_qp_id; - l_qps.aPropVar = l_qp_var; - l_qps.aStatus = l_q_status; - - WCHAR l_direct_name[MQ_MAX_Q_NAME_LEN] = { 0 }; - WCHAR l_format_name[sizeof(l_direct_name) - 10] = { 0 }; - DWORD l_buflen = sizeof(l_format_name); - HRESULT hr = MQCreateQueue(NULL, &l_qps, l_format_name, &l_buflen); - if ((hr != MQ_OK) && (hr != MQ_ERROR_QUEUE_EXISTS) && (hr != MQ_INFORMATION_PROPERTY)) { - log_it(L_ERROR, "Can't create message queue for queue type, error: %ld", hr); - DAP_DELETE(l_es); - return NULL; - } - _snwprintf_s(l_direct_name, sizeof(l_direct_name)/sizeof(l_direct_name[0]), _TRUNCATE, L"DIRECT=OS:%ls", l_pathname); - - hr = MQOpenQueue(l_direct_name, MQ_SEND_ACCESS, MQ_DENY_NONE, &(l_es->mqh)); - if (hr == MQ_ERROR_QUEUE_NOT_FOUND) { - log_it(L_INFO, "Queue still not created, wait a bit..."); - Sleep(300); - hr = MQOpenQueue(l_direct_name, MQ_SEND_ACCESS, MQ_DENY_NONE, &(l_es->mqh)); - if (hr != MQ_OK) { - log_it(L_ERROR, "Can't open message queue for queue type, error: %ld", hr); - DAP_DELETE(l_es); - MQDeleteQueue(l_format_name); - return NULL; - } - } - hr = MQOpenQueue(l_direct_name, MQ_RECEIVE_ACCESS, MQ_DENY_NONE, &(l_es->mqh_recv)); - if (hr != MQ_OK) { - log_it(L_ERROR, "Can't open message queue for queue type, error: %ld", hr); - DAP_DELETE(l_es); - MQCloseQueue(l_es->mqh); - MQDeleteQueue(l_format_name); - return NULL; - } - hr = MQPurgeQueue(l_es->mqh_recv); - if (hr != MQ_OK) { - log_it(L_DEBUG, "Message queue %u NOT purged, possible data corruption, err %ld", l_es->mq_num, hr); - } -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - // We don't create descriptor for kqueue at all -#else -#error "Not implemented s_create_type_queue_ptr() on your platform" -#endif - return l_es; -} /** * @brief dap_events_socket_create_type_queue_mt @@ -802,7 +511,7 @@ dap_events_socket_t * s_create_type_queue_ptr(dap_worker_t * a_w, dap_events_soc */ dap_events_socket_t * dap_events_socket_create_type_queue_ptr_mt(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback) { - dap_events_socket_t * l_es = s_create_type_queue_ptr(a_w, a_callback); + dap_events_socket_t * l_es = dap_context_create_esocket_queue(NULL, a_callback); assert(l_es); // If no worker - don't assign if ( a_w) @@ -811,28 +520,6 @@ dap_events_socket_t * dap_events_socket_create_type_queue_ptr_mt(dap_worker_t * } -/** - * @brief dap_events_socket_create_type_queue - * @param a_w - * @param a_callback - * @return - */ -dap_events_socket_t * dap_events_socket_create_type_queue_ptr_unsafe(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback) -{ - dap_events_socket_t * l_es = s_create_type_queue_ptr(a_w, a_callback); - assert(l_es); - // If no worker - don't assign - if ( a_w) { - if(dap_worker_add_events_socket_unsafe(l_es,a_w)) { -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_ERROR, "Can't add esocket %"DAP_FORMAT_SOCKET" to polling, err %d", l_es->socket, errno); - } - } - return l_es; -} - /** * @brief dap_events_socket_queue_proc_input * @param a_esocket @@ -919,7 +606,7 @@ int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) void * l_queue_ptr = a_esocket->kqueue_event_catched_data.data; size_t l_queue_ptr_size = a_esocket->kqueue_event_catched_data.size; if(g_debug_reactor) - log_it(L_INFO,"Queue received %z bytes on input", l_queue_ptr_size); + log_it(L_INFO,"Queue received %zd bytes on input", l_queue_ptr_size); a_esocket->callbacks.queue_callback(a_esocket, l_queue_ptr, l_queue_ptr_size); #else @@ -933,101 +620,6 @@ int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) return 0; } -/** - * @brief s_create_type_event - * @param a_w - * @param a_callback - * @return - */ -dap_events_socket_t * s_create_type_event(dap_worker_t * a_w, dap_events_socket_callback_event_t a_callback) -{ - dap_events_socket_t * l_es = DAP_NEW_Z(dap_events_socket_t); if (!l_es) return NULL; - l_es->buf_out_size_max = l_es->buf_in_size_max = 1; - l_es->buf_out = DAP_NEW_Z_SIZE(byte_t, l_es->buf_out_size_max); - l_es->type = DESCRIPTOR_TYPE_EVENT; - l_es->uuid = dap_uuid_generate_uint64(); - if (a_w){ - l_es->events = a_w->events; - l_es->worker = a_w; - } - l_es->callbacks.event_callback = a_callback; // Arm event callback -#if defined(DAP_EVENTS_CAPS_EPOLL) - l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; -#elif defined(DAP_EVENTS_CAPS_POLL) - l_es->poll_base_flags = POLLIN | POLLERR | POLLRDHUP | POLLHUP; -#elif defined(DAP_EVENTS_CAPS_KQUEUE) - l_es->kqueue_base_flags = EV_CLEAR; - l_es->kqueue_base_filter = EVFILT_USER; - l_es->socket = arc4random(); - l_es->kqueue_event_catched_data.esocket = l_es; -#else -#error "Not defined s_create_type_event for your platform" -#endif - -#ifdef DAP_EVENTS_CAPS_EVENT_EVENTFD - if((l_es->fd = eventfd(0,EFD_NONBLOCK) ) < 0 ){ - int l_errno = errno; - char l_errbuf[128]; - l_errbuf[0]=0; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - switch (l_errno) { - case EINVAL: log_it(L_CRITICAL, "An unsupported value was specified in flags: \"%s\" (%d)", l_errbuf, l_errno); break; - case EMFILE: log_it(L_CRITICAL, "The per-process limit on the number of open file descriptors has been reached: \"%s\" (%d)", l_errbuf, l_errno); break; - case ENFILE: log_it(L_CRITICAL, "The system-wide limit on the total number of open files has been reached: \"%s\" (%d)", l_errbuf, l_errno); break; - case ENODEV: log_it(L_CRITICAL, "Could not mount (internal) anonymous inode device: \"%s\" (%d)", l_errbuf, l_errno); break; - case ENOMEM: log_it(L_CRITICAL, "There was insufficient memory to create a new eventfd file descriptor: \"%s\" (%d)", l_errbuf, l_errno); break; - default: log_it( L_ERROR, "Error detected, can't create eventfd: '%s' (%d)", l_errbuf, l_errno); - } - DAP_DELETE(l_es); - return NULL; - }else { - l_es->fd2 = l_es->fd; - //log_it(L_DEBUG, "Created eventfd descriptor %d", l_es->fd ); - } -#elif defined DAP_OS_WINDOWS - - - l_es->socket = socket(AF_INET, SOCK_DGRAM, 0); - - if (l_es->socket == INVALID_SOCKET) { - log_it(L_ERROR, "Error creating socket for TYPE_QUEUE: %d", WSAGetLastError()); - DAP_DELETE(l_es); - return NULL; - } - - int buffsize = 1024; - setsockopt(l_es->socket, SOL_SOCKET, SO_RCVBUF, (char *)&buffsize, sizeof(int)); - - unsigned long l_mode = 1; - ioctlsocket(l_es->socket, FIONBIO, &l_mode); - - int reuse = 1; - if (setsockopt(l_es->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) - log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket, err: %d", WSAGetLastError()); - - int l_addr_len; - struct sockaddr_in l_addr; - l_addr.sin_family = AF_INET; - IN_ADDR _in_addr = { { .S_addr = htonl(INADDR_LOOPBACK) } }; - l_addr.sin_addr = _in_addr; - l_addr.sin_port = 0; //l_es->socket + 32768; - l_addr_len = sizeof(struct sockaddr_in); - - if (bind(l_es->socket, (struct sockaddr*)&l_addr, sizeof(l_addr)) < 0) { - log_it(L_ERROR, "Bind error: %d", WSAGetLastError()); - } else { - int dummy = 100; - getsockname(l_es->socket, (struct sockaddr*)&l_addr, &dummy); - l_es->port = l_addr.sin_port; - //log_it(L_DEBUG, "Bound to port %d", l_addr.sin_port); - } -#elif defined(DAP_EVENTS_CAPS_KQUEUE) - // nothing to do -#else -#error "Not defined s_create_type_event() on your platform" -#endif - return l_es; -} /** * @brief dap_events_socket_create_type_event_mt @@ -1037,7 +629,7 @@ dap_events_socket_t * s_create_type_event(dap_worker_t * a_w, dap_events_socket_ */ dap_events_socket_t * dap_events_socket_create_type_event_mt(dap_worker_t * a_w, dap_events_socket_callback_event_t a_callback) { - dap_events_socket_t * l_es = s_create_type_event(a_w, a_callback); + dap_events_socket_t * l_es = dap_context_create_esocket_event(NULL, a_callback); // If no worker - don't assign if ( a_w) dap_events_socket_assign_on_worker_mt(l_es,a_w); @@ -1052,7 +644,8 @@ dap_events_socket_t * dap_events_socket_create_type_event_mt(dap_worker_t * a_w, */ dap_events_socket_t * dap_events_socket_create_type_event_unsafe(dap_worker_t * a_w, dap_events_socket_callback_event_t a_callback) { - dap_events_socket_t * l_es = s_create_type_event(a_w, a_callback); + + dap_events_socket_t * l_es = dap_context_create_esocket_event(NULL, a_callback); // If no worker - don't assign if ( a_w) dap_worker_add_events_socket_unsafe(l_es,a_w); @@ -1236,10 +829,8 @@ int dap_events_socket_queue_ptr_send_to_input(dap_events_socket_t * a_es_input, l_es_w_data->esocket = l_es; l_es_w_data->ptr = a_arg; EV_SET(&l_event,a_es_input->socket+arc4random() , EVFILT_USER,EV_ADD | EV_CLEAR | EV_ONESHOT, NOTE_FFCOPY | NOTE_TRIGGER ,0, l_es_w_data); - if(l_es->worker) - l_ret=kevent(l_es->worker->kqueue_fd,&l_event,1,NULL,0,NULL); - else if (l_es->proc_thread) - l_ret=kevent(l_es->proc_thread->kqueue_fd,&l_event,1,NULL,0,NULL); + if(l_es->context) + l_ret=kevent(l_es->context->kqueue_fd,&l_event,1,NULL,0,NULL); else l_ret=-100; if(l_ret != -1 ){ @@ -1274,7 +865,7 @@ int dap_events_socket_queue_ptr_send_to_input(dap_events_socket_t * a_es_input, */ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) { - int l_ret = -1024, l_errno; + int l_ret = -1024, l_errno=0; if (g_debug_reactor) log_it(L_DEBUG,"Sent ptr %p to esocket queue %p (%d)", a_arg, a_es, a_es? a_es->fd : -1); @@ -1295,7 +886,7 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) if (l_errno == EINVAL || l_errno == EINTR || l_errno == ETIMEDOUT) l_errno = EAGAIN; if (l_ret == 0) - l_ret = sizeof (a_arg); + l_ret = 0; else if (l_ret > 0) l_ret = -l_ret; @@ -1352,24 +943,18 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) EV_SET(&l_event,a_es->socket+arc4random() , EVFILT_USER,EV_ADD | EV_CLEAR | EV_ONESHOT, NOTE_FFCOPY | NOTE_TRIGGER ,0, l_es_w_data); int l_n; if(a_es->pipe_out){ // If we have pipe out - we send events directly to the pipe out kqueue fd - if(a_es->pipe_out->worker){ + if(a_es->pipe_out->context){ if( g_debug_reactor) log_it(L_DEBUG, "Sent kevent() with ptr %p to pipe_out worker on esocket %d",a_arg,a_es); - l_n = kevent(a_es->pipe_out->worker->kqueue_fd,&l_event,1,NULL,0,NULL); - }else if (a_es->pipe_out->proc_thread){ - l_n = kevent(a_es->pipe_out->proc_thread->kqueue_fd,&l_event,1,NULL,0,NULL); - if( g_debug_reactor) log_it(L_DEBUG, "Sent kevent() with ptr %p to pipe_out proc_thread on esocket %d",a_arg,a_es); + l_n = kevent(a_es->pipe_out->context->kqueue_fd,&l_event,1,NULL,0,NULL); } else { log_it(L_WARNING,"Trying to send pointer in pipe out queue thats not assigned to any worker or proc thread"); l_n = 0; DAP_DELETE(l_es_w_data); } - }else if(a_es->worker){ - l_n = kevent(a_es->worker->kqueue_fd,&l_event,1,NULL,0,NULL); + }else if(a_es->context){ + l_n = kevent(a_es->context->kqueue_fd,&l_event,1,NULL,0,NULL); if( g_debug_reactor) log_it(L_DEBUG, "Sent kevent() with ptr %p to worker on esocket %d",a_arg,a_es); - }else if (a_es->proc_thread){ - l_n = kevent(a_es->proc_thread->kqueue_fd,&l_event,1,NULL,0,NULL); - if( g_debug_reactor) log_it(L_DEBUG, "Sent kevent() with ptr %p to proc_thread on esocket %d",a_arg,a_es); }else { log_it(L_WARNING,"Trying to send pointer in queue thats not assigned to any worker or proc thread"); l_n = 0; @@ -1377,7 +962,7 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t *a_es, void *a_arg) } if(l_n != -1 ){ - return sizeof(a_arg); + return 0; }else{ l_errno = errno; log_it(L_ERROR,"Sending kevent error code %d", l_errno); @@ -1438,19 +1023,15 @@ int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value int l_n; if(a_es->pipe_out){ // If we have pipe out - we send events directly to the pipe out kqueue fd - if(a_es->pipe_out->worker) - l_n = kevent(a_es->pipe_out->worker->kqueue_fd,&l_event,1,NULL,0,NULL); - else if (a_es->pipe_out->proc_thread) - l_n = kevent(a_es->pipe_out->proc_thread->kqueue_fd,&l_event,1,NULL,0,NULL); + if(a_es->pipe_out->context) + l_n = kevent(a_es->pipe_out->context->kqueue_fd,&l_event,1,NULL,0,NULL); else { log_it(L_WARNING,"Trying to send pointer in pipe out queue thats not assigned to any worker or proc thread"); l_n = -1; } - }else if(a_es->worker) - l_n = kevent(a_es->worker->kqueue_fd,&l_event,1,NULL,0,NULL); - else if (a_es->proc_thread) - l_n = kevent(a_es->proc_thread->kqueue_fd,&l_event,1,NULL,0,NULL); - else + }else if(a_es->context) + l_n = kevent(a_es->context->kqueue_fd,&l_event,1,NULL,0,NULL); + else l_n = -1; if(l_n == -1){ @@ -1467,12 +1048,12 @@ int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value * @brief dap_events_socket_queue_on_remove_and_delete * @param a_es */ -void dap_events_socket_queue_on_remove_and_delete(dap_events_socket_t* a_es) +void dap_events_socket_delete_mt(dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid) { dap_events_socket_uuid_t * l_es_uuid_ptr= DAP_NEW_Z(dap_events_socket_uuid_t); - *l_es_uuid_ptr = a_es->uuid; + *l_es_uuid_ptr = a_es_uuid; - int l_ret= dap_events_socket_queue_ptr_send( a_es->worker->queue_es_delete, l_es_uuid_ptr ); + int l_ret= dap_events_socket_queue_ptr_send( a_worker->queue_es_delete, l_es_uuid_ptr ); if( l_ret != 0 ){ log_it(L_ERROR, "Queue send returned %d", l_ret); DAP_DELETE(l_es_uuid_ptr); @@ -1498,7 +1079,6 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da dap_events_socket_t * l_es = DAP_NEW_Z( dap_events_socket_t ); if (!l_es) return NULL; l_es->socket = a_sock; - l_es->events = a_events; l_es->server = a_server; l_es->uuid = dap_uuid_generate_uint64(); memcpy(&l_es->callbacks,a_callbacks, sizeof ( l_es->callbacks) ); @@ -1512,130 +1092,6 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da return l_es; } - -/** - * @brief dap_worker_esocket_find_uuid - * @param a_worker - * @param a_es_uuid - * @return - */ -dap_events_socket_t *dap_worker_esocket_find_uuid(dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid ) -{ - assert(a_worker); - dap_events_socket_t * l_ret = NULL; - if(a_worker->esockets ) { - pthread_rwlock_rdlock(&a_worker->esocket_rwlock); - //HASH_FIND_PTR( a_worker->esockets, &a_es_uuid,l_ret ); - HASH_FIND(hh_worker, a_worker->esockets, &a_es_uuid, sizeof(a_es_uuid), l_ret ); - pthread_rwlock_unlock(&a_worker->esocket_rwlock ); - } - return l_ret; -} - -void dap_events_socket_worker_poll_update_unsafe(dap_events_socket_t * a_esocket) -{ - #if defined (DAP_EVENTS_CAPS_EPOLL) - int events = a_esocket->ev_base_flags | EPOLLERR; - - // Check & add - if( a_esocket->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; - - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ) - events |= EPOLLOUT; - - a_esocket->ev.events = events; - - if( a_esocket->worker){ - if ( epoll_ctl(a_esocket->worker->epoll_fd, EPOLL_CTL_MOD, a_esocket->socket, &a_esocket->ev) ){ -#ifdef DAP_OS_WINDOWS - int l_errno = WSAGetLastError(); -#else - int l_errno = errno; -#endif - char l_errbuf[128]; - l_errbuf[0]=0; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it(L_ERROR,"Can't update client socket state in the epoll_fd %"DAP_FORMAT_HANDLE": \"%s\" (%d)", - a_esocket->worker->epoll_fd, l_errbuf, l_errno); - } - } - #elif defined (DAP_EVENTS_CAPS_POLL) - if( a_esocket->worker && a_esocket->is_initalized){ - if (a_esocket->poll_index < a_esocket->worker->poll_count ){ - struct pollfd * l_poll = &a_esocket->worker->poll[a_esocket->poll_index]; - l_poll->events = a_esocket->poll_base_flags | POLLERR ; - // Check & add - if( a_esocket->flags & DAP_SOCK_READY_TO_READ ) - l_poll->events |= POLLIN; - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ) - l_poll->events |= POLLOUT; - }else{ - log_it(L_ERROR, "Wrong poll index when remove from worker (unsafe): %u when total count %u", a_esocket->poll_index, - a_esocket->worker->poll_count); - } - } - #elif defined (DAP_EVENTS_CAPS_KQUEUE) - if (a_esocket->socket != -1 ){ // Not everything we add in poll - struct kevent * l_event = &a_esocket->kqueue_event; - short l_filter =a_esocket->kqueue_base_filter; - u_short l_flags =a_esocket->kqueue_base_flags; - u_int l_fflags =a_esocket->kqueue_base_fflags; - - int l_kqueue_fd = a_esocket->worker? a_esocket->worker->kqueue_fd : - a_esocket->proc_thread ? a_esocket->proc_thread->kqueue_fd : -1; - if ( l_kqueue_fd == -1 ){ - log_it(L_ERROR, "Esocket is not assigned with anything ,exit"); - } - - // Check & add - bool l_is_error=false; - int l_errno=0; - if (a_esocket->type == DESCRIPTOR_TYPE_EVENT ){ - EV_SET(l_event, a_esocket->socket, EVFILT_USER,EV_ADD| EV_CLEAR ,0,0, &a_esocket->kqueue_event_catched_data ); - if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){ - l_is_error = true; - l_errno = errno; - } - }else{ - EV_SET(l_event, a_esocket->socket, l_filter,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if( a_esocket->flags & DAP_SOCK_READY_TO_READ ){ - EV_SET(l_event, a_esocket->socket, EVFILT_READ,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1 ){ - l_is_error = true; - l_errno = errno; - } - } - if( !l_is_error){ - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ){ - EV_SET(l_event, a_esocket->socket, EVFILT_WRITE,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if(kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) == -1){ - l_is_error = true; - l_errno = errno; - } - } - } - } - if (l_is_error && l_errno == EBADF){ - log_it(L_ATT,"Poll update: socket %d (%p ) disconnected, rise CLOSE flag to remove from queue, lost %"DAP_UINT64_FORMAT_U":%" DAP_UINT64_FORMAT_U - " bytes",a_esocket->socket,a_esocket,a_esocket->buf_in_size,a_esocket->buf_out_size); - a_esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; - a_esocket->buf_in_size = a_esocket->buf_out_size = 0; // Reset everything from buffer, we close it now all - }else if ( l_is_error && l_errno != EINPROGRESS && l_errno != ENOENT){ - char l_errbuf[128]; - l_errbuf[0]=0; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it(L_ERROR,"Can't update client socket state on kqueue fd %d: \"%s\" (%d)", - l_kqueue_fd, l_errbuf, l_errno); - } - } - - #else - #error "Not defined dap_events_socket_set_writable_unsafe for your platform" - #endif - -} - /** * @brief dap_events_socket_ready_to_read * @param sc @@ -1659,8 +1115,7 @@ void dap_events_socket_set_readable_unsafe( dap_events_socket_t *a_esocket, bool EV_SET(&l_event, a_esocket->socket, EVFILT_READ, a_esocket->kqueue_base_flags | l_op_flag,a_esocket->kqueue_base_fflags , a_esocket->kqueue_data,a_esocket); - int l_kqueue_fd = a_esocket->worker? a_esocket->worker->kqueue_fd : - a_esocket->proc_thread ? a_esocket->proc_thread->kqueue_fd : -1; + int l_kqueue_fd = a_esocket->context? a_esocket->context->kqueue_fd : -1; if( l_kqueue_fd>0 ){ int l_kevent_ret = kevent(l_kqueue_fd,&l_event,1,NULL,0,NULL); int l_errno = errno; @@ -1682,10 +1137,7 @@ void dap_events_socket_set_readable_unsafe( dap_events_socket_t *a_esocket, bool }else log_it(L_WARNING,"Trying to set readable/writable event, queue or timer thats you shouldnt do"); #else - if( a_esocket->worker) - dap_events_socket_worker_poll_update_unsafe( a_esocket); - else if( a_esocket->proc_thread) - dap_proc_thread_esocket_update_poll_flags(a_esocket->proc_thread,a_esocket ); + dap_context_poll_update(a_esocket); #endif } @@ -1716,8 +1168,7 @@ void dap_events_socket_set_writable_unsafe( dap_events_socket_t *a_esocket, bool EV_SET(&l_event, a_esocket->socket, EVFILT_WRITE, a_esocket->kqueue_base_flags | l_op_flag,a_esocket->kqueue_base_fflags , a_esocket->kqueue_data,a_esocket); - int l_kqueue_fd = a_esocket->worker? a_esocket->worker->kqueue_fd : - a_esocket->proc_thread ? a_esocket->proc_thread->kqueue_fd : -1; + int l_kqueue_fd = a_esocket->context? a_esocket->context->kqueue_fd : -1; if( l_kqueue_fd>0 ){ int l_kevent_ret=kevent(l_kqueue_fd,&l_event,1,NULL,0,NULL); int l_errno = errno; @@ -1739,10 +1190,7 @@ void dap_events_socket_set_writable_unsafe( dap_events_socket_t *a_esocket, bool }else log_it(L_WARNING,"Trying to set readable/writable event, queue or timer thats you shouldnt do"); #else - if( a_esocket->worker) - dap_events_socket_worker_poll_update_unsafe(a_esocket); - else if( a_esocket->proc_thread) - dap_proc_thread_esocket_update_poll_flags(a_esocket->proc_thread,a_esocket ); + dap_context_poll_update(a_esocket); #endif } @@ -1760,7 +1208,7 @@ bool s_remove_and_delete_unsafe_delayed_delete_callback(void * a_arg) assert(l_es_handler); assert(l_worker); dap_events_socket_t * l_es; - if( (l_es = dap_worker_esocket_find_uuid(l_worker, l_es_handler->esocket_uuid)) != NULL) + if( (l_es = dap_context_esocket_find_by_uuid(l_worker->context, l_es_handler->esocket_uuid)) != NULL) //dap_events_socket_remove_and_delete_unsafe(l_es,l_es_handler->value == 1); dap_events_remove_and_delete_socket_unsafe(dap_events_get_default(), l_es, l_es_handler->value == 1); DAP_DELETE(l_es_handler); @@ -1780,7 +1228,7 @@ void dap_events_socket_remove_and_delete_unsafe_delayed( dap_events_socket_t *a_ l_es_handler->value = a_preserve_inheritor ? 1 : 0; dap_events_socket_descriptor_close(a_es); - dap_worker_t * l_worker = a_es->worker; + dap_worker_t * l_worker = a_es->context->worker; dap_events_socket_remove_from_worker_unsafe( a_es, l_worker); a_es->flags |= DAP_SOCK_SIGNAL_CLOSE; dap_timerfd_start_on_worker(l_worker, s_delayed_ops_timeout_ms, @@ -1804,7 +1252,7 @@ void dap_events_socket_remove_and_delete_unsafe( dap_events_socket_t *a_es, bool #endif //log_it( L_DEBUG, "es is going to be removed from the lists and free the memory (0x%016X)", a_es ); - dap_events_socket_remove_from_worker_unsafe(a_es, a_es->worker); + dap_events_socket_remove_from_worker_unsafe(a_es, a_es->context->worker); if( a_es->callbacks.delete_callback ) a_es->callbacks.delete_callback( a_es, NULL ); // Init internal structure @@ -1863,15 +1311,13 @@ void dap_events_socket_delete_unsafe( dap_events_socket_t * a_esocket , bool a_p */ void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap_worker_t * a_worker) { - if (!a_es->worker) { + if (!a_es->context->worker) { log_it(L_INFO, "No worker assigned to esocket %"DAP_FORMAT_SOCKET, a_es->socket); return; } - pthread_rwlock_wrlock(&a_worker->esocket_rwlock); a_worker->event_sockets_count--; - HASH_DELETE(hh_worker,a_worker->esockets, a_es); - pthread_rwlock_unlock(&a_worker->esocket_rwlock); + HASH_DELETE(hh_worker,a_worker->context->esockets, a_es); #if defined(DAP_EVENTS_CAPS_EPOLL) @@ -1888,52 +1334,52 @@ void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap struct kevent * l_event = &a_es->kqueue_event; if (a_es->kqueue_base_filter){ EV_SET(l_event, a_es->socket, a_es->kqueue_base_filter ,EV_DELETE, 0,0,a_es); - if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { + if ( kevent( a_worker->context->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { int l_errno = errno; char l_errbuf[128]; strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); log_it( L_ERROR,"Can't remove event socket's handler %d from the kqueue %d filter %d \"%s\" (%d)", a_es->socket, - a_worker->kqueue_fd,a_es->kqueue_base_filter, l_errbuf, l_errno); + a_worker->context->kqueue_fd,a_es->kqueue_base_filter, l_errbuf, l_errno); } }else{ EV_SET(l_event, a_es->socket, EVFILT_EXCEPT ,EV_DELETE, 0,0,a_es); - kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL); // If this filter is not set up - no warnings + kevent( a_worker->context->kqueue_fd,l_event,1,NULL,0,NULL); // If this filter is not set up - no warnings if(a_es->flags & DAP_SOCK_READY_TO_WRITE){ EV_SET(l_event, a_es->socket, EVFILT_WRITE ,EV_DELETE, 0,0,a_es); - if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { + if ( kevent( a_worker->context->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { int l_errno = errno; char l_errbuf[128]; strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); log_it( L_ERROR,"Can't remove event socket's handler %d from the kqueue %d filter EVFILT_WRITE \"%s\" (%d)", a_es->socket, - a_worker->kqueue_fd, l_errbuf, l_errno); + a_worker->context->kqueue_fd, l_errbuf, l_errno); } } if(a_es->flags & DAP_SOCK_READY_TO_READ){ EV_SET(l_event, a_es->socket, EVFILT_READ ,EV_DELETE, 0,0,a_es); - if ( kevent( a_worker->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { + if ( kevent( a_worker->context->kqueue_fd,l_event,1,NULL,0,NULL) == -1 ) { int l_errno = errno; char l_errbuf[128]; strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); log_it( L_ERROR,"Can't remove event socket's handler %d from the kqueue %d filter EVFILT_READ \"%s\" (%d)", a_es->socket, - a_worker->kqueue_fd, l_errbuf, l_errno); + a_worker->context->kqueue_fd, l_errbuf, l_errno); } } } } #elif defined (DAP_EVENTS_CAPS_POLL) - if (a_es->poll_index < a_worker->poll_count ){ - a_worker->poll[a_es->poll_index].fd = -1; - a_worker->poll_compress = true; + if (a_es->poll_index < a_worker->context->poll_count ){ + a_worker->context->poll[a_es->poll_index].fd = -1; + a_worker->context->poll_compress = true; }else{ log_it(L_ERROR, "Wrong poll index when remove from worker (unsafe): %u when total count %u", a_es->poll_index, a_worker->poll_count); } #else #error "Unimplemented new esocket on worker callback for current platform" #endif - a_es->worker = NULL; + a_es->context = NULL; } /** @@ -2084,7 +1530,7 @@ size_t dap_events_socket_write_f_inter(dap_events_socket_t * a_es_input, dap_eve int l_ret= dap_events_socket_queue_ptr_send_to_input(a_es_input, l_msg ); if (l_ret!=0){ - log_it(L_ERROR, "wite f inter: wasn't send pointer to queue input: code %d", l_ret); + log_it(L_ERROR, "write f inter: wasn't send pointer to queue input: code %d", l_ret); DAP_DELETE(l_msg); return 0; } diff --git a/dap-sdk/net/core/dap_net.c b/dap-sdk/io/dap_net.c similarity index 100% rename from dap-sdk/net/core/dap_net.c rename to dap-sdk/io/dap_net.c diff --git a/dap-sdk/net/core/dap_proc_queue.c b/dap-sdk/io/dap_proc_queue.c similarity index 84% rename from dap-sdk/net/core/dap_proc_queue.c rename to dap-sdk/io/dap_proc_queue.c index ae7c1daaf9ed717ab8804cf5abf2959582b92f04..5ad0766c744fad4d40e3547820dcc2bb44870051 100644 --- a/dap-sdk/net/core/dap_proc_queue.c +++ b/dap-sdk/io/dap_proc_queue.c @@ -51,7 +51,7 @@ dap_proc_queue_t * dap_proc_queue_create_ext(dap_proc_thread_t * a_thread) if (!l_queue) return NULL; - for (int i = 0; i < DAP_QUE$K_PRIMAX; i++) { + for (int i = 0; i < DAP_PROC_PRI_MAX; i++) { assert ( !(pthread_mutex_init(&l_queue->list[i].lock, 0 )) ); } @@ -78,15 +78,14 @@ dap_proc_queue_t * dap_proc_queue_create(dap_proc_thread_t * a_thread) if (!l_queue) return NULL; - for (int i = 0; i < DAP_QUE$K_PRIMAX; i++) { + for (int i = 0; i < DAP_PROC_PRI_MAX; i++) { assert ( !(pthread_mutex_init(&l_queue->list[i].lock, 0 )) ); } l_queue->proc_thread = a_thread; - l_queue->esocket = dap_events_socket_create_type_queue_ptr_unsafe(NULL,s_queue_esocket_callback); + l_queue->esocket = dap_context_create_esocket_queue(a_thread->context,s_queue_esocket_callback); l_queue->esocket->proc_thread = a_thread; l_queue->esocket->_inheritor = l_queue; - return l_queue; } @@ -104,7 +103,7 @@ int dap_proc_queue_delete(dap_proc_queue_t * a_queue) return -ENOMEM; l_msg->signal_kill = 1; /* TRUE */ - l_msg->pri = DAP_QUE$K_PRI_HIGH; /* Assume that KILL must be delivered ASAP */ + l_msg->pri = DAP_PROC_PRI_HIGH; /* Assume that KILL must be delivered ASAP */ return dap_events_socket_queue_ptr_send( a_queue->esocket, l_msg ); } @@ -157,7 +156,7 @@ static void s_queue_esocket_callback( dap_events_socket_t * a_es, void * a_msg) * So, all checks has been finished, now we can prepare new entry */ pri = l_msg->pri; /* Validate priority */ - pri = MIN(pri, DAP_QUE$K_PRIMAX - 1); + pri = MIN(pri, DAP_PROC_PRI_MAX - 1); pri = MAX(pri, 0); l_item->callback = l_msg->callback; @@ -197,7 +196,7 @@ int dap_proc_queue_add_callback(dap_worker_t * a_worker,dap_proc_queue_callback_ l_msg->callback = a_callback; l_msg->callback_arg = a_callback_arg; - l_msg->pri = DAP_QUE$K_PRI_NORMAL; + l_msg->pri = DAP_PROC_PRI_NORMAL; /* * Send message to queue with the DEFAULT priority */ @@ -219,10 +218,10 @@ int dap_proc_queue_add_callback_ext(dap_worker_t * a_worker,dap_proc_queue_callb { dap_proc_queue_msg_t *l_msg; - if ( !(a_pri < DAP_QUE$K_PRIMAX) ) /* Check that priority level is in legal range */ + if ( !(a_pri < DAP_PROC_PRI_MAX) ) /* Check that priority level is in legal range */ { - log_it(L_WARNING, "Priority level %d is incorrect (should be is in range %d-%d)", a_pri, DAP_QUE$K_PRI0 + 1, DAP_QUE$K_PRIMAX - 1); - a_pri = DAP_QUE$K_PRI_NORMAL; + log_it(L_WARNING, "Priority level %d is incorrect (should be is in range %d-%d)", a_pri, DAP_PROC_PRI_0 + 1, DAP_PROC_PRI_MAX - 1); + a_pri = DAP_PROC_PRI_NORMAL; } if ( !(l_msg = DAP_NEW_Z(dap_proc_queue_msg_t)) ) /* Allocate memory for a new message */ @@ -256,7 +255,7 @@ int dap_proc_queue_add_callback_inter( dap_events_socket_t * a_es_input, dap_pro l_msg->callback = a_callback; l_msg->callback_arg = a_callback_arg; - l_msg->pri = DAP_QUE$K_PRI_NORMAL; + l_msg->pri = DAP_PROC_PRI_NORMAL; return dap_events_socket_queue_ptr_send_to_input( a_es_input , l_msg ); } @@ -275,10 +274,10 @@ int dap_proc_queue_add_callback_inter_ext( dap_events_socket_t * a_es_input, dap { dap_proc_queue_msg_t *l_msg; - if ( !(a_pri < DAP_QUE$K_PRIMAX) ) /* Check that priority level is in legal range */ + if ( !(a_pri < DAP_PROC_PRI_MAX) ) /* Check that priority level is in legal range */ { - log_it(L_WARNING, "Priority level %d is incorrect (should be is in range %d-%d)", a_pri, DAP_QUE$K_PRI0 + 1, DAP_QUE$K_PRIMAX - 1); - a_pri = DAP_QUE$K_PRI_NORMAL; + log_it(L_WARNING, "Priority level %d is incorrect (should be is in range %d-%d)", a_pri, DAP_PROC_PRI_0 + 1, DAP_PROC_PRI_MAX - 1); + a_pri = DAP_PROC_PRI_NORMAL; } if ( !(l_msg = DAP_NEW_Z(dap_proc_queue_msg_t)) ) /* Allocate memory for a new message */ @@ -290,3 +289,31 @@ dap_proc_queue_msg_t *l_msg; return dap_events_socket_queue_ptr_send_to_input( a_es_input , l_msg ); } + +/** + * @brief dap_proc_thread_add_callback_mt + * @param a_thread + * @param a_callback + * @param a_callback_arg + * @return + */ +int dap_proc_thread_add_callback_mt(dap_proc_thread_t * a_thread, dap_proc_queue_callback_t a_callback, void * a_callback_arg, int a_pri) +{ + dap_proc_queue_msg_t *l_msg; + + if ( !(a_pri < DAP_PROC_PRI_MAX) ) /* Check that priority level is in legal range */ + { + log_it(L_WARNING, "Priority level %d is incorrect (should be is in range %d-%d)", a_pri, DAP_PROC_PRI_0 + 1, DAP_PROC_PRI_MAX - 1); + a_pri = DAP_PROC_PRI_NORMAL; + } + + if ( !(l_msg = DAP_NEW_Z(dap_proc_queue_msg_t)) ) /* Allocate memory for a new message */ + return -ENOMEM; + + l_msg->callback = a_callback; + l_msg->callback_arg = a_callback_arg; + l_msg->pri = a_pri; + + return dap_events_socket_queue_ptr_send(a_thread->proc_queue->esocket, l_msg); +} + diff --git a/dap-sdk/io/dap_proc_thread.c b/dap-sdk/io/dap_proc_thread.c new file mode 100644 index 0000000000000000000000000000000000000000..70d2e1653fd9721e0eaafccae67903c84ccee39b --- /dev/null +++ b/dap-sdk/io/dap_proc_thread.c @@ -0,0 +1,568 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd. https://demlabs.net + * Copyright (c) 2020 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <errno.h> +#include <stdatomic.h> + +#include "dap_config.h" +#include "dap_list.h" +#include "dap_events.h" +#include "dap_events_socket.h" +#include "dap_proc_thread.h" +#include "dap_server.h" + +#if defined(DAP_EVENTS_CAPS_EPOLL) && !defined(DAP_OS_WINDOWS) +#include <sys/epoll.h> +#elif defined DAP_OS_WINDOWS +#include "wepoll.h" +#elif defined (DAP_EVENTS_CAPS_POLL) +#include <poll.h> +#elif defined (DAP_EVENTS_CAPS_KQUEUE) + +#include <sys/event.h> +#include <err.h> + +#ifndef DAP_OS_DARWIN +#include <pthread_np.h> +typedef cpuset_t cpu_set_t; // Adopt BSD CPU setstructure to POSIX variant +#else +#define NOTE_READ NOTE_LOWAT +#endif + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL SO_NOSIGPIPE +#endif + +#else +#error "Unimplemented poll for this platform" +#endif + +#define LOG_TAG "dap_proc_thread" + +static size_t s_threads_count = 0; +static dap_proc_thread_t * s_threads = NULL; + +static dap_slist_t s_custom_threads = $DAP_SLIST_INITALIZER; /* Customized proc threads out of the pool */ +static pthread_rwlock_t s_custom_threads_rwlock = PTHREAD_RWLOCK_INITIALIZER; /* Lock to protect <s_custom_threads> */ + + +static void *s_proc_thread_function(void * a_arg); +static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags); + +/** + * @brief dap_proc_thread_init + * @param a_cpu_count 0 means autodetect + * @return + */ + +int dap_proc_thread_init(uint32_t a_threads_count) +{ +int l_ret = 0; + + s_threads_count = a_threads_count ? a_threads_count : dap_get_cpu_count( ); + s_threads = DAP_NEW_Z_SIZE(dap_proc_thread_t, sizeof (dap_proc_thread_t)* s_threads_count); + + for (uint32_t i = 0; i < s_threads_count; i++ ) + { + dap_proc_thread_t * l_thread = s_threads + i; + l_thread->cpu_id = i; + l_thread->context = dap_context_new(); + l_thread->context->proc_thread = l_thread; + pthread_cond_init(&l_thread->started_cond, NULL); + pthread_mutex_init( &l_thread->started_mutex,NULL); + + pthread_mutex_lock( &l_thread->started_mutex ); + + if ( (l_ret = pthread_create( &l_thread->thread_id,NULL, s_proc_thread_function, &s_threads[i] )) ) { + log_it(L_CRITICAL, "Create thread failed with code %d", l_ret); + pthread_mutex_unlock( &l_thread->started_mutex ); + return l_ret; + } + + pthread_cond_wait( &l_thread->started_cond, &l_thread->started_mutex); + pthread_mutex_unlock( &l_thread->started_mutex); + } + + return l_ret; +} + +/** + * @brief dap_proc_thread_deinit + */ +void dap_proc_thread_deinit() +{ + int l_rc = 0; + size_t l_sz = 0; + dap_proc_thread_t *l_proc_thread = NULL; + + for (uint32_t i = s_threads_count; i--; ){ + dap_events_socket_event_signal(s_threads[i].event_exit, 1); + pthread_join(s_threads[i].thread_id, NULL); + } + + // Cleaning custom proc threads + pthread_rwlock_wrlock(&s_custom_threads_rwlock); + + for ( uint32_t i = s_custom_threads.nr; i--; ) { + if ( s_dap_slist_get4head (&s_custom_threads, (void **) &l_proc_thread, &l_sz) ) + break; + + dap_events_socket_event_signal(l_proc_thread->event_exit, 1); + pthread_join(l_proc_thread->thread_id, NULL); + DAP_DELETE(l_proc_thread); + } + + pthread_rwlock_unlock(&s_custom_threads_rwlock); + + // Signal to cancel working threads and wait for finish + // TODO: Android realization +//#ifndef DAP_OS_ANDROID +// for (size_t i = 0; i < s_threads_count; i++ ){ +// pthread_cancel(s_threads[i].thread_id); +// pthread_join(s_threads[i].thread_id, NULL); +// } +//#endif + +} + +/** + * @brief dap_proc_thread_get + * @param a_cpu_id + * @return + */ +dap_proc_thread_t * dap_proc_thread_get(uint32_t a_cpu_id) +{ + return (a_cpu_id < s_threads_count) ? &s_threads[a_cpu_id] : NULL; +} + +/** + * @brief dap_proc_thread_get_auto + * @return + */ +dap_proc_thread_t * dap_proc_thread_get_auto() +{ +unsigned l_id_min = 0, l_size_min = UINT32_MAX, l_queue_size; + + for (size_t i = 0; i < s_threads_count; i++ ) + { + l_queue_size = atomic_load(&s_threads[i].proc_queue_size); + + if( l_queue_size < l_size_min ){ + l_size_min = l_queue_size; + l_id_min = i; + } + } + + return &s_threads[l_id_min]; +} + +/** + * @brief dap_proc_thread_run_custom Create custom proc thread for specified task + * @return + */ +dap_proc_thread_t * dap_proc_thread_run_custom(void) +{ + dap_proc_thread_t * l_proc_thread = DAP_NEW_Z(dap_proc_thread_t); + int l_ret; + + if (l_proc_thread == NULL) + return log_it(L_CRITICAL,"Out of memory, can't create new proc thread, errno=%d", errno), NULL; + + pthread_mutex_lock( &l_proc_thread->started_mutex ); + + if ( (l_ret = pthread_create( &l_proc_thread->thread_id ,NULL, s_proc_thread_function, l_proc_thread )) ) { + log_it(L_CRITICAL, "Create thread failed with code %d", l_ret); + DAP_DEL_Z (l_proc_thread); + }else{ + pthread_cond_wait( &l_proc_thread->started_cond, &l_proc_thread->started_mutex); + pthread_rwlock_wrlock(&s_custom_threads_rwlock); + assert ( !s_dap_slist_add2tail (&s_custom_threads, l_proc_thread, sizeof(l_proc_thread)) ); + pthread_rwlock_unlock(&s_custom_threads_rwlock); + } + + pthread_mutex_unlock( &l_proc_thread->started_mutex ); + return l_proc_thread; +} + +/** + * @brief s_proc_event_callback - get from queue next element and execute action routine, + * repeat execution depending on status is returned by action routine. + * + * @param a_esocket + * @param a_value + * + */ +static void s_proc_event_callback(dap_events_socket_t * a_esocket, uint64_t __attribute__((unused)) a_value) +{ +dap_proc_thread_t *l_thread; +dap_proc_queue_item_t *l_item; +int l_rc, l_is_anybody_in_queue, l_is_finished, l_iter_cnt, l_cur_pri; +size_t l_item_sz; +dap_proc_queue_t *l_queue; + + debug_if (g_debug_reactor, L_DEBUG, "--> Proc event callback start, a_esocket:%p ", a_esocket); + + if ( !(l_thread = (dap_proc_thread_t *) a_esocket->_inheritor) ) + { + log_it(L_ERROR, "NULL <dap_proc_thread_t> context is detected"); + return; + } + + l_iter_cnt = l_is_anybody_in_queue = 0; + /*@RRL: l_iter_cnt = DAP_QUE$K_ITER_NR; */ + l_queue = l_thread->proc_queue; + + for (l_cur_pri = (DAP_PROC_PRI_MAX - 1); l_cur_pri; l_cur_pri--, l_iter_cnt++ ) /* Run from higest to lowest ... */ + { + if ( !l_queue->list[l_cur_pri].items.nr ) /* A lockless quick check */ + continue; + + pthread_mutex_lock(&l_queue->list[l_cur_pri].lock); /* Protect list from other threads */ + l_rc = s_dap_slist_get4head (&l_queue->list[l_cur_pri].items, (void **) &l_item, &l_item_sz); + pthread_mutex_unlock(&l_queue->list[l_cur_pri].lock); + + if ( l_rc == -ENOENT ) { /* Queue is empty ? */ + debug_if (g_debug_reactor, L_DEBUG, "a_esocket:%p - nothing to do at prio: %d ", a_esocket, l_cur_pri); + continue; + } + + debug_if (g_debug_reactor, L_INFO, "Proc event callback: %p/%p, prio=%d, iteration=%d", + l_item->callback, l_item->callback_arg, l_cur_pri, l_iter_cnt); + + l_is_finished = l_item->callback(l_thread, l_item->callback_arg); + + debug_if (g_debug_reactor, L_INFO, "Proc event callback: %p/%p, prio=%d, iteration=%d - is %sfinished", + l_item->callback, l_item->callback_arg, l_cur_pri, l_iter_cnt, l_is_finished ? "" : "not "); + + if ( !(l_is_finished) ) { + /* Rearm callback to be executed again */ + pthread_mutex_lock(&l_queue->list[l_cur_pri].lock); + l_rc = s_dap_slist_add2tail (&l_queue->list[l_cur_pri].items, l_item, l_item_sz ); + pthread_mutex_unlock(&l_queue->list[l_cur_pri].lock); + + if ( l_rc ) { + log_it(L_ERROR, "Error requeue event callback: %p/%p, errno=%d", l_item->callback, l_item->callback_arg, l_rc); + DAP_DELETE(l_item); + } + } + else { + DAP_DELETE(l_item); + } + } + for (l_cur_pri = (DAP_PROC_PRI_MAX - 1); l_cur_pri; l_cur_pri--) /* Really ?! */ + l_is_anybody_in_queue += l_queue->list[l_cur_pri].items.nr; + + if ( l_is_anybody_in_queue ) /* Arm event if we have something to proc again */ + dap_events_socket_event_signal(a_esocket, 1); + + debug_if(g_debug_reactor, L_DEBUG, "<-- Proc event callback end, items rest: %d, iterations: %d", l_is_anybody_in_queue, l_iter_cnt); +} + + +/** + * @brief dap_proc_thread_assign_esocket_unsafe + * @param a_thread + * @param a_esocket + * @return + */ +int dap_proc_thread_assign_esocket_unsafe(dap_proc_thread_t * a_thread, dap_events_socket_t * a_esocket) +{ + assert(a_esocket); + assert(a_thread); + a_esocket->proc_thread = a_thread; + +#ifdef DAP_EVENTS_CAPS_EPOLL + // Init events for EPOLL + a_esocket->ev.events = a_esocket->ev_base_flags ; + if(a_esocket->flags & DAP_SOCK_READY_TO_READ ) + a_esocket->ev.events |= EPOLLIN; + if(a_esocket->flags & DAP_SOCK_READY_TO_WRITE ) + a_esocket->ev.events |= EPOLLOUT; + a_esocket->ev.data.ptr = a_esocket; + return epoll_ctl(a_thread->epoll_ctl, EPOLL_CTL_ADD, a_esocket->socket, &a_esocket->ev); +#elif defined (DAP_EVENTS_CAPS_POLL) + if ( a_thread->poll_count == a_thread->poll_count_max ){ // realloc + a_thread->poll_count_max *= 2; + log_it(L_WARNING, "Too many descriptors (%zu), resizing array twice to %zu", a_thread->poll_count, a_thread->poll_count_max); + a_thread->poll =DAP_REALLOC(a_thread->poll, a_thread->poll_count_max * sizeof(*a_thread->poll)); + a_thread->esockets =DAP_REALLOC(a_thread->esockets, a_thread->poll_count_max * sizeof(*a_thread->esockets)); + } + + a_thread->poll[a_thread->poll_count].fd = a_thread->proc_queue->esocket->fd; + a_thread->poll[a_thread->poll_count].events = a_thread->proc_queue->esocket->poll_base_flags; + a_thread->esockets[a_thread->poll_count] = a_thread->proc_queue->esocket; + a_thread->poll_count++; +#elif defined (DAP_EVENTS_CAPS_KQUEUE) +/* u_short l_flags = a_esocket->kqueue_base_flags; + u_int l_fflags = a_esocket->kqueue_base_fflags; + short l_filter = a_esocket->kqueue_base_filter; + if(a_esocket->flags & DAP_SOCK_READY_TO_READ ) + l_fflags |= NOTE_READ; + if(a_esocket->flags & DAP_SOCK_READY_TO_WRITE ) + l_fflags |= NOTE_WRITE; + + EV_SET(&a_esocket->kqueue_event , a_esocket->socket, l_filter, EV_ADD| l_flags | EV_CLEAR, l_fflags,0, a_esocket); + return kevent ( a_thread->kqueue_fd,&a_esocket->kqueue_event,1,NULL,0,NULL)==1 ? 0 : -1 ; +*/ + // Nothing to do if its input + if ( a_esocket->type == DESCRIPTOR_TYPE_QUEUE && a_esocket->pipe_out) + return 0; +#else +#error "Unimplemented new esocket on worker callback for current platform" +#endif + + return dap_context_poll_update(a_esocket); +} + + + +/** + * @brief dap_proc_thread_create_queue_ptr + * @details Call this function as others only from safe situation, or, thats better, from a_thread's context + * @param a_thread + * @param a_callback + * @return + */ +dap_events_socket_t * dap_proc_thread_create_queue_ptr(dap_proc_thread_t * a_thread, dap_events_socket_callback_queue_ptr_t a_callback) +{ + dap_events_socket_t * l_es = dap_context_create_esocket_queue(a_thread->context,a_callback); + if(l_es == NULL) + return NULL; + l_es->proc_thread = a_thread; + return l_es; +} + +/** + * @brief s_proc_thread_function + * @param a_arg + * @return + */ +static void * s_proc_thread_function(void * a_arg) +{ + + dap_proc_thread_t * l_thread = (dap_proc_thread_t*) a_arg; + assert(l_thread); + dap_context_t * l_context = l_thread->context; + assert(l_context); + dap_cpu_assign_thread_on(l_thread->cpu_id); + + struct sched_param l_shed_params; + l_shed_params.sched_priority = 0; +#if defined(DAP_OS_WINDOWS) + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) + log_it(L_ERROR, "Couldn't set thread priority, err: %lu", GetLastError()); +#elif defined (DAP_OS_LINUX) + pthread_setschedparam(pthread_self(),SCHED_BATCH ,&l_shed_params); +#elif defined (DAP_OS_BSD) + pthread_setschedparam(pthread_self(),SCHED_OTHER ,&l_shed_params); +#else +#error "Undefined set sched param" +#endif + if(dap_context_thread_init(l_thread->context)!=0){ + pthread_cond_broadcast(&l_thread->started_cond); + return NULL; + } + + l_thread->proc_queue = dap_proc_queue_create(l_thread); + + // Init proc_queue for related worker + dap_worker_t * l_worker_related = dap_events_worker_get(l_thread->cpu_id); + assert(l_worker_related); + l_worker_related->proc_queue = l_thread->proc_queue; + l_worker_related->proc_queue_input = dap_events_socket_queue_ptr_create_input(l_worker_related->proc_queue->esocket); + + dap_events_socket_assign_on_worker_mt(l_worker_related->proc_queue_input,l_worker_related); + + l_thread->proc_event = dap_context_create_esocket_event( l_context , s_proc_event_callback); + l_thread->proc_event->proc_thread = l_thread; + l_thread->event_exit = dap_context_create_esocket_event(l_context, s_event_exit_callback); + l_thread->event_exit->proc_thread = l_thread; + + l_thread->proc_event->_inheritor = l_thread; // we pass thread through it + l_thread->event_exit->_inheritor = l_thread; + + size_t l_workers_count= dap_events_worker_get_count(); + assert(l_workers_count); + l_thread->queue_assign_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); + l_thread->queue_io_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); + l_thread->queue_callback_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); + + assert(l_thread->queue_assign_input); + assert(l_thread->queue_io_input); + for (size_t n=0; n<l_workers_count; n++){ + dap_worker_t * l_worker =dap_events_worker_get(n); + l_thread->queue_assign_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_new ); + l_thread->queue_io_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_io ); + l_thread->queue_callback_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_callback ); + } + + + for (size_t n = 0; n< dap_events_worker_get_count(); n++){ + // Queue asssign + dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_assign_input[n]); + + // Queue IO + dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_io_input[n]); + + // Queue callback + dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_callback_input[n]); + } + + + //We've started! + pthread_cond_broadcast(&l_thread->started_cond); + + + + dap_context_thread_loop(l_thread->context); + + log_it(L_ATT, "Stop processing thread #%u", l_thread->cpu_id); + // cleanip inputs + for (size_t n=0; n<dap_events_worker_get_count(); n++){ + dap_events_socket_delete_unsafe(l_thread->queue_assign_input[n], false); + dap_events_socket_delete_unsafe(l_thread->queue_io_input[n], false); + dap_events_socket_delete_unsafe(l_thread->queue_callback_input[n], false); + } + + return NULL; +} + +/** + * @brief dap_proc_thread_assign_on_worker_inter + * @param a_thread + * @param a_worker + * @param a_esocket + * @return + */ +bool dap_proc_thread_assign_on_worker_inter(dap_proc_thread_t * a_thread, dap_worker_t * a_worker, dap_events_socket_t *a_esocket ) +{ + dap_events_socket_t * l_es_assign_input = a_thread->queue_assign_input[a_worker->id]; + if(g_debug_reactor) + log_it(L_DEBUG,"Remove esocket %p from proc thread and send it to worker #%u",a_esocket, a_worker->id); + + dap_events_socket_assign_on_worker_inter(l_es_assign_input, a_esocket); + // TODO Make this code platform-independent +#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT + l_es_assign_input->flags |= DAP_SOCK_READY_TO_WRITE; + dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_assign_input); +#endif + return true; +} + +/** + * @brief dap_proc_thread_esocket_write_inter + * @param a_thread + * @param a_worker + * @param a_es_uuid + * @param a_data + * @param a_data_size + * @return + */ +int dap_proc_thread_esocket_write_inter(dap_proc_thread_t * a_thread,dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid, + const void * a_data, size_t a_data_size) +{ + dap_events_socket_t * l_es_io_input = a_thread->queue_io_input[a_worker->id]; + dap_events_socket_write_inter(l_es_io_input,a_es_uuid, a_data, a_data_size); + // TODO Make this code platform-independent +#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT + l_es_io_input->flags |= DAP_SOCK_READY_TO_WRITE; + dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_io_input); +#endif + return 0; +} + + +/** + * @brief dap_proc_thread_esocket_write_f_inter + * @param a_thread + * @param a_worker + * @param a_es_uuid, + * @param a_format + * @return + */ +int dap_proc_thread_esocket_write_f_inter(dap_proc_thread_t * a_thread,dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid, + const char * a_format,...) +{ + va_list ap, ap_copy; + va_start(ap,a_format); + va_copy(ap_copy, ap); + int l_data_size = dap_vsnprintf(NULL,0,a_format,ap); + va_end(ap); + if (l_data_size <0 ){ + log_it(L_ERROR,"Can't write out formatted data '%s' with values",a_format); + va_end(ap_copy); + return 0; + } + + dap_events_socket_t * l_es_io_input = a_thread->queue_io_input[a_worker->id]; + char * l_data = DAP_NEW_SIZE(char,l_data_size+1); + if (!l_data){ + va_end(ap_copy); + return -1; + } + l_data_size = dap_vsprintf(l_data,a_format,ap_copy); + va_end(ap_copy); + + dap_events_socket_write_inter(l_es_io_input, a_es_uuid, l_data, l_data_size); + // TODO Make this code platform-independent +#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT + l_es_io_input->flags |= DAP_SOCK_READY_TO_WRITE; + dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_io_input); +#endif + DAP_DELETE(l_data); + return 0; +} + +/** + * @brief dap_proc_thread_worker_exec_callback + * @param a_thread + * @param a_worker_id + * @param a_callback + * @param a_arg + */ +void dap_proc_thread_worker_exec_callback_inter(dap_proc_thread_t * a_thread, size_t a_worker_id, dap_worker_callback_t a_callback, void * a_arg) +{ + dap_worker_msg_callback_t * l_msg = DAP_NEW_Z(dap_worker_msg_callback_t); + l_msg->callback = a_callback; + l_msg->arg = a_arg; + dap_events_socket_queue_ptr_send_to_input(a_thread->queue_callback_input[a_worker_id],l_msg ); + + // TODO Make this code platform-independent +#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT + a_thread->queue_callback_input[a_worker_id]->flags |= DAP_SOCK_READY_TO_WRITE; + dap_proc_thread_esocket_update_poll_flags(a_thread, a_thread->queue_callback_input[a_worker_id]); +#endif +} + + +static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags) +{ + (void) a_flags; + dap_proc_thread_t * l_thread = (dap_proc_thread_t *) a_es->_inheritor; + l_thread->context->signal_exit = true; + if(g_debug_reactor) + log_it(L_DEBUG, "Proc_thread :%u signaled to exit", l_thread->cpu_id); +} + + + + diff --git a/dap-sdk/net/core/dap_server.c b/dap-sdk/io/dap_server.c similarity index 98% rename from dap-sdk/net/core/dap_server.c rename to dap-sdk/io/dap_server.c index 792af686326c764b136b3fd0e88a86ab907bbb5c..84471b9c639105addb64cd7d368817654466c27b 100644 --- a/dap-sdk/net/core/dap_server.c +++ b/dap-sdk/io/dap_server.c @@ -104,7 +104,7 @@ void dap_server_delete(dap_server_t *a_server) { while (a_server->es_listeners) { dap_events_socket_t *l_es = (dap_events_socket_t *)a_server->es_listeners->data; - dap_events_socket_remove_and_delete_mt(l_es->worker, l_es->uuid); // TODO unsafe moment. Replace storage to uuids + dap_events_socket_remove_and_delete_mt(l_es->context->worker, l_es->uuid); // TODO unsafe moment. Replace storage to uuids dap_list_t *l_tmp = a_server->es_listeners; a_server->es_listeners = l_tmp->next; DAP_DELETE(l_tmp); @@ -345,7 +345,7 @@ static int s_server_run(dap_server_t * a_server, dap_events_socket_callbacks_t * */ static void s_es_server_new(dap_events_socket_t *a_es, void * a_arg) { - log_it(L_DEBUG, "Created server socket %p on worker %u", a_es, a_es->worker->id); + log_it(L_DEBUG, "Created server socket %p on worker %u", a_es, a_es->context->worker->id); dap_server_t *l_server = (dap_server_t*) a_es->_inheritor; pthread_mutex_lock( &l_server->started_mutex); pthread_mutex_unlock( &l_server->started_mutex); @@ -383,7 +383,7 @@ static void s_es_server_accept(dap_events_socket_t *a_es, SOCKET a_remote_socket dap_events_socket_t * l_es_new = NULL; log_it(L_DEBUG, "Listening socket (binded on %s:%u) got new incomming connection",l_server->address,l_server->port); log_it(L_DEBUG, "Accepted new connection (sock %"DAP_FORMAT_SOCKET" from %"DAP_FORMAT_SOCKET")", a_remote_socket, a_es->socket); - l_es_new = s_es_server_create(a_es->events,a_remote_socket,&l_server->client_callbacks,l_server); + l_es_new = s_es_server_create(dap_events_get_default(),a_remote_socket,&l_server->client_callbacks,l_server); //l_es_new->is_dont_reset_write_flag = true; // By default all income connection has this flag getnameinfo(a_remote_addr,a_remote_addr_size, l_es_new->hostaddr ,256, l_es_new->service,sizeof(l_es_new->service), diff --git a/dap-sdk/net/core/dap_timerfd.c b/dap-sdk/io/dap_timerfd.c similarity index 86% rename from dap-sdk/net/core/dap_timerfd.c rename to dap-sdk/io/dap_timerfd.c index c38f9e27e3cc6cec551b0244e544237fdee5cca0..55d6b02dd0994323c46ac4e84cc8fe9e3928fd1e 100644 --- a/dap-sdk/net/core/dap_timerfd.c +++ b/dap-sdk/io/dap_timerfd.c @@ -255,7 +255,7 @@ dap_timerfd_t* dap_timerfd_create(uint64_t a_timeout_ms, dap_timerfd_callback_t return l_timerfd; } -static void s_timerfd_reset(dap_timerfd_t *a_timerfd, dap_events_socket_t *a_event_sock) +static inline void s_timerfd_reset(dap_timerfd_t *a_timerfd, dap_events_socket_t *a_es) { #if defined DAP_OS_LINUX struct itimerspec l_ts; @@ -269,10 +269,10 @@ static void s_timerfd_reset(dap_timerfd_t *a_timerfd, dap_events_socket_t *a_eve log_it(L_WARNING, "Reset timerfd failed: timerfd_settime() errno=%d\n", errno); } #elif defined (DAP_OS_BSD) - dap_worker_add_events_socket_unsafe(a_event_sock,a_event_sock->worker); -//struct kevent * l_event = &a_event_sock->kqueue_event; -//EV_SET(l_event, 0, a_event_sock->kqueue_base_filter, a_event_sock->kqueue_base_flags,a_event_sock->kqueue_base_fflags,a_event_sock->kqueue_data,a_event_sock); -//kevent(a_event_sock->worker->kqueue_fd,l_event,1,NULL,0,NULL); + // Re-add timer in context + dap_context_t * l_context = a_es->context; + a_es->context = NULL; + dap_context_add_esocket(l_context,a_es); #elif defined (DAP_OS_WINDOWS) /*LARGE_INTEGER l_due_time; l_due_time.QuadPart = (long long)a_timerfd->timeout_ms * _MSEC; @@ -285,10 +285,13 @@ static void s_timerfd_reset(dap_timerfd_t *a_timerfd, dap_events_socket_t *a_eve #endif #ifndef DAP_OS_BSD - dap_events_socket_set_readable_unsafe(a_event_sock, true); + dap_events_socket_set_readable_unsafe(a_es, true); #endif } + + + /** * @brief s_es_callback_timer * @param a_event_sock @@ -304,6 +307,38 @@ static void s_es_callback_timer(struct dap_events_socket *a_event_sock) } } +/** + * @brief s_timerfd_reset_worker_callback + * @param a_worker + * @param a_arg + */ +static void s_timerfd_reset_worker_callback( dap_worker_t * a_worker, void * a_arg ) +{ + dap_timerfd_t *l_timerfd = (dap_timerfd_t *) a_arg; + dap_events_socket_t *l_sock = NULL; + l_sock = dap_context_esocket_find_by_uuid(a_worker->context, l_timerfd->esocket_uuid); + if (l_sock) + s_timerfd_reset(l_timerfd, l_sock); + +} + +/** + * @brief s_timerfd_reset_proc_thread_callback + * @param a_thread + * @param a_arg + * @return + */ +static bool s_timerfd_reset_proc_thread_callback( dap_proc_thread_t * a_thread, void * a_arg ) +{ + dap_timerfd_t *l_timerfd = (dap_timerfd_t *) a_arg; + dap_events_socket_t *l_sock = NULL; + l_sock = dap_context_esocket_find_by_uuid(a_thread->context, l_timerfd->esocket_uuid); + if (l_sock) + s_timerfd_reset(l_timerfd, l_sock); + return true; +} + + /** * @brief dap_timerfd_reset * @param a_tfd @@ -312,13 +347,12 @@ void dap_timerfd_reset(dap_timerfd_t *a_timerfd) { if (!a_timerfd) return; - dap_events_socket_t *l_sock = NULL; - if (a_timerfd->worker) - l_sock = dap_worker_esocket_find_uuid(a_timerfd->worker, a_timerfd->esocket_uuid); - else if (a_timerfd->proc_thread) - l_sock = a_timerfd->events_socket; - if (l_sock) - s_timerfd_reset(a_timerfd, l_sock); + if (a_timerfd->worker){ + dap_worker_exec_callback_on(a_timerfd->worker,s_timerfd_reset_worker_callback, a_timerfd); + }else if (a_timerfd->proc_thread) + dap_proc_thread_add_callback_mt(a_timerfd->proc_thread,s_timerfd_reset_proc_thread_callback, a_timerfd, DAP_PROC_PRI_NORMAL ); + else + log_it(L_WARNING,"Timer's context undefined, cant' reset it"); } /** @@ -333,6 +367,6 @@ void dap_timerfd_delete(dap_timerfd_t *a_timerfd) #ifdef _WIN32 DeleteTimerQueueTimer(hTimerQueue, (HANDLE)a_timerfd->th, NULL); #endif - if (a_timerfd->events_socket->worker) - dap_events_socket_remove_and_delete_mt(a_timerfd->events_socket->worker, a_timerfd->esocket_uuid); + if (a_timerfd->events_socket->context->worker) + dap_events_socket_remove_and_delete_mt(a_timerfd->events_socket->context->worker, a_timerfd->esocket_uuid); } diff --git a/dap-sdk/io/dap_worker.c b/dap-sdk/io/dap_worker.c new file mode 100644 index 0000000000000000000000000000000000000000..7c5293241abbdadd3077d44c04f5f9c6e7639c26 --- /dev/null +++ b/dap-sdk/io/dap_worker.c @@ -0,0 +1,442 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd. https://demlabs.net + * Copyright (c) 2017 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <time.h> +#include <errno.h> +#include <unistd.h> + +#include "dap_common.h" +#include "dap_config.h" +#include "dap_context.h" +#include "dap_math_ops.h" +#include "dap_worker.h" +#include "dap_timerfd.h" +#include "dap_events.h" +#include "dap_enc_base64.h" +#include "dap_proc_queue.h" + +#ifndef DAP_NET_CLIENT_NO_SSL +#include <wolfssl/options.h> +#include "wolfssl/ssl.h" +#endif + +#define LOG_TAG "dap_worker" + +static time_t s_connection_timeout = 60; // seconds + +static bool s_socket_all_check_activity( void * a_arg); +static void s_queue_add_es_callback( dap_events_socket_t * a_es, void * a_arg); +static void s_queue_delete_es_callback( dap_events_socket_t * a_es, void * a_arg); +static void s_queue_es_reassign_callback( dap_events_socket_t * a_es, void * a_arg); +static void s_queue_callback_callback( dap_events_socket_t * a_es, void * a_arg); +static void s_queue_es_io_callback( dap_events_socket_t * a_es, void * a_arg); +static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags); + +/** + * @brief dap_worker_init + * @param a_threads_count + * @param conn_timeout + * @return + */ +int dap_worker_init( size_t a_conn_timeout ) +{ + if ( a_conn_timeout ) + s_connection_timeout = a_conn_timeout; + + return 0; +} + +void dap_worker_deinit( ) +{ +} + +/** + * @brief dap_worker_thread + * @param arg + * @return + */ +void *dap_worker_thread(void *arg) +{ + dap_worker_t *l_worker = (dap_worker_t *) arg; + assert(l_worker); + dap_context_t * l_context = l_worker->context; + const struct sched_param l_shed_params = {0}; + + + dap_cpu_assign_thread_on(l_worker->id); + pthread_setspecific(l_worker->events->pth_key_worker, l_worker); + +#ifdef DAP_OS_WINDOWS + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL)) + log_it(L_ERROR, "Couldn'r set thread priority, err: %lu", GetLastError()); +#else + pthread_setschedparam(pthread_self(),SCHED_FIFO ,&l_shed_params); +#endif + + if(dap_context_thread_init(l_context)!=0){ + pthread_cond_broadcast(&l_worker->started_cond); + return NULL; + } + + l_worker->queue_es_new_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); + l_worker->queue_es_delete_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); + l_worker->queue_es_io_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); + l_worker->queue_es_reassign_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)* dap_events_worker_get_count() ); + + + l_worker->queue_es_new = dap_context_create_esocket_queue(l_context, s_queue_add_es_callback); + l_worker->queue_es_delete = dap_context_create_esocket_queue(l_context, s_queue_delete_es_callback); + l_worker->queue_es_io = dap_context_create_esocket_queue(l_context, s_queue_es_io_callback); + l_worker->queue_es_reassign = dap_context_create_esocket_queue(l_context, s_queue_es_reassign_callback ); + + + for( size_t n = 0; n < dap_events_worker_get_count(); n++) { + l_worker->queue_es_new_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_new); + l_worker->queue_es_delete_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_delete); + l_worker->queue_es_io_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_io); + l_worker->queue_es_reassign_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_reassign); + } + + l_worker->queue_callback = dap_context_create_esocket_queue(l_context, s_queue_callback_callback); + l_worker->event_exit = dap_context_create_esocket_event(l_context, s_event_exit_callback); + + l_worker->timer_check_activity = dap_timerfd_create(s_connection_timeout * 1000 / 2, + s_socket_all_check_activity, l_worker); + dap_worker_add_events_socket_unsafe( l_worker->timer_check_activity->events_socket, l_worker); + pthread_cond_broadcast(&l_worker->started_cond); + + dap_context_thread_loop(l_context); + log_it(L_NOTICE,"Exiting thread #%u", l_worker->id); + return NULL; +} + +/** + * @brief s_new_es_callback + * @param a_es + * @param a_arg + */ +static void s_queue_add_es_callback( dap_events_socket_t * a_es, void * a_arg) +{ + assert(a_es); + dap_context_t * l_context = a_es->context; + assert(l_context); + dap_worker_t * l_worker = l_context->worker; + assert(l_worker); + dap_events_socket_t * l_es_new =(dap_events_socket_t *) a_arg; + if (!l_es_new){ + log_it(L_ERROR,"NULL esocket accepted to add on worker #%u", l_worker->id); + return; + } + + if(g_debug_reactor) + log_it(L_NOTICE, "Received event socket %p (ident %"DAP_FORMAT_SOCKET" type %d) to add on worker", l_es_new, l_es_new->socket, l_es_new->type); + + switch( l_es_new->type){ + case DESCRIPTOR_TYPE_SOCKET_UDP: break; + case DESCRIPTOR_TYPE_SOCKET_CLIENT: break; + default:{} + } + +#ifdef DAP_EVENTS_CAPS_KQUEUE + if(l_es_new->socket!=0 && l_es_new->socket != -1 && + l_es_new->type != DESCRIPTOR_TYPE_EVENT && + l_es_new->type != DESCRIPTOR_TYPE_QUEUE && + l_es_new->type != DESCRIPTOR_TYPE_TIMER + ) +#else + if(l_es_new->socket!=0 && l_es_new->socket != INVALID_SOCKET) + +#endif + if(dap_context_esocket_find_by_uuid( l_context, l_es_new->uuid)){ + // Socket already present in worker, it's OK + return; + } + + switch( l_es_new->type){ + + case DESCRIPTOR_TYPE_SOCKET_UDP: + case DESCRIPTOR_TYPE_SOCKET_CLIENT: + case DESCRIPTOR_TYPE_SOCKET_LISTENING:{ + +#ifdef DAP_OS_UNIX +#if defined (SO_INCOMING_CPU) + int l_cpu = l_worker->id; + setsockopt(l_es_new->socket , SOL_SOCKET, SO_INCOMING_CPU, &l_cpu, sizeof(l_cpu)); +#endif +#endif + } break; + default: {} + } + + l_es_new->last_time_active = time(NULL); + // We need to differ new and reassigned esockets. If its new - is_initialized is false + if ( ! l_es_new->is_initalized ){ + if (l_es_new->callbacks.new_callback) + l_es_new->callbacks.new_callback(l_es_new, NULL); + l_es_new->is_initalized = true; + } + + int l_ret =dap_context_add_esocket(l_context,l_es_new); + if ( l_ret != 0 ){ + log_it(L_CRITICAL,"Can't add event socket's handler to worker i/o poll mechanism with error %d", errno); + }else{ + // Add in worker + l_es_new->me = l_es_new; + if (l_es_new->socket!=0 && l_es_new->socket != INVALID_SOCKET){ + HASH_ADD(hh_worker, l_worker->context->esockets, uuid, sizeof(l_es_new->uuid), l_es_new ); + l_worker->event_sockets_count++; + } + //log_it(L_DEBUG, "Added socket %d on worker %u", l_es_new->socket, w->id); + if (l_es_new->callbacks.worker_assign_callback) + l_es_new->callbacks.worker_assign_callback(l_es_new, l_worker); + + } +} + +/** + * @brief s_delete_es_callback + * @param a_es + * @param a_arg + */ +static void s_queue_delete_es_callback( dap_events_socket_t * a_es, void * a_arg) +{ + assert(a_arg); + dap_events_socket_uuid_t * l_es_uuid_ptr = (dap_events_socket_uuid_t*) a_arg; + dap_events_socket_t * l_es; + if ( (l_es = dap_context_esocket_find_by_uuid(a_es->context,*l_es_uuid_ptr)) != NULL ){ + //l_es->flags |= DAP_SOCK_SIGNAL_CLOSE; // Send signal to socket to kill + dap_events_socket_remove_and_delete_unsafe(l_es,false); + }else + log_it(L_INFO, "While we were sending the delete() message, esocket %"DAP_UINT64_FORMAT_U" has been disconnected ", *l_es_uuid_ptr); + DAP_DELETE(l_es_uuid_ptr); +} + +/** + * @brief s_reassign_es_callback + * @param a_es + * @param a_arg + */ +static void s_queue_es_reassign_callback( dap_events_socket_t * a_es, void * a_arg) +{ + assert(a_es); + dap_context_t * l_context = a_es->context; + assert(l_context); + dap_worker_t * l_worker = l_context->worker; + assert(l_worker); + dap_worker_msg_reassign_t * l_msg = (dap_worker_msg_reassign_t*) a_arg; + assert(l_msg); + dap_events_socket_t * l_es_reassign; + if ( ( l_es_reassign = dap_context_esocket_find_by_uuid(l_context, l_msg->esocket_uuid))!= NULL ){ + if( l_es_reassign->was_reassigned && l_es_reassign->flags & DAP_SOCK_REASSIGN_ONCE) { + log_it(L_INFO, "Reassgment request with DAP_SOCK_REASSIGN_ONCE allowed only once, declined reassigment from %u to %u", + l_es_reassign->context->worker->id, l_msg->worker_new->id); + + }else{ + dap_events_socket_reassign_between_workers_unsafe(l_es_reassign,l_msg->worker_new); + } + }else{ + log_it(L_INFO, "While we were sending the reassign message, esocket %p has been disconnected", l_msg->esocket); + } + DAP_DELETE(l_msg); +} + +/** + * @brief s_queue_callback + * @param a_es + * @param a_arg + */ +static void s_queue_callback_callback( dap_events_socket_t * a_es, void * a_arg) +{ + dap_worker_msg_callback_t * l_msg = (dap_worker_msg_callback_t *) a_arg; + assert(l_msg); + assert(l_msg->callback); + l_msg->callback(a_es->context->worker, l_msg->arg); + DAP_DELETE(l_msg); +} + +/** + * @brief s_event_exit_callback + * @param a_es + * @param a_flags + */ +static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags) +{ + (void) a_flags; + a_es->context->signal_exit = true; + if(g_debug_reactor) + log_it(L_DEBUG, "Worker :%u signaled to exit", a_es->context->worker->id); +} + +/** + * @brief s_pipe_data_out_read_callback + * @param a_es + * @param a_arg + */ +static void s_queue_es_io_callback( dap_events_socket_t * a_es, void * a_arg) +{ + assert(a_es); + dap_context_t * l_context = a_es->context; + assert(l_context); + dap_worker_t * l_worker = a_es->context->worker; + dap_worker_msg_io_t * l_msg = a_arg; + assert(l_msg); + // Check if it was removed from the list + dap_events_socket_t *l_msg_es = dap_context_esocket_find_by_uuid(l_worker->context, l_msg->esocket_uuid); + if ( l_msg_es == NULL){ + log_it(L_INFO, "We got i/o message for esocket %"DAP_UINT64_FORMAT_U" thats now not in list. Lost %zu data", l_msg->esocket_uuid, l_msg->data_size); + DAP_DELETE(l_msg); + return; + } + + if (l_msg->flags_set & DAP_SOCK_CONNECTING) + if (! (l_msg_es->flags & DAP_SOCK_CONNECTING) ){ + l_msg_es->flags |= DAP_SOCK_CONNECTING; + dap_context_poll_update(l_msg_es); + } + + if (l_msg->flags_set & DAP_SOCK_CONNECTING) + if (! (l_msg_es->flags & DAP_SOCK_CONNECTING) ){ + l_msg_es->flags ^= DAP_SOCK_CONNECTING; + dap_context_poll_update(l_msg_es); + } + + if (l_msg->flags_set & DAP_SOCK_READY_TO_READ) + dap_events_socket_set_readable_unsafe(l_msg_es, true); + if (l_msg->flags_unset & DAP_SOCK_READY_TO_READ) + dap_events_socket_set_readable_unsafe(l_msg_es, false); + if (l_msg->flags_set & DAP_SOCK_READY_TO_WRITE) + dap_events_socket_set_writable_unsafe(l_msg_es, true); + if (l_msg->flags_unset & DAP_SOCK_READY_TO_WRITE) + dap_events_socket_set_writable_unsafe(l_msg_es, false); + if (l_msg->data_size && l_msg->data) { + dap_events_socket_write_unsafe(l_msg_es, l_msg->data,l_msg->data_size); + DAP_DELETE(l_msg->data); + } + DAP_DELETE(l_msg); +} + +/** + * @brief s_socket_all_check_activity + * @param a_arg + */ +static bool s_socket_all_check_activity( void * a_arg) +{ + dap_worker_t *l_worker = (dap_worker_t*) a_arg; + assert(l_worker); + dap_events_socket_t *l_es = NULL, *tmp = NULL; + char l_curtimebuf[64]; + time_t l_curtime= time(NULL); + //dap_ctime_r(&l_curtime, l_curtimebuf); + //log_it(L_DEBUG,"Check sockets activity on worker #%u at %s", l_worker->id, l_curtimebuf); + HASH_ITER(hh_worker, l_worker->context->esockets, l_es, tmp ) { + if (l_es->type == DESCRIPTOR_TYPE_SOCKET_CLIENT){ + if ( !(l_es->flags & DAP_SOCK_SIGNAL_CLOSE) && + ( l_curtime >= (l_es->last_time_active + s_connection_timeout) ) && !l_es->no_close ) { + log_it( L_INFO, "Socket %"DAP_FORMAT_SOCKET" timeout (diff %"DAP_UINT64_FORMAT_U" ), closing...", + l_es->socket, l_curtime - (time_t)l_es->last_time_active - s_connection_timeout ); + if (l_es->callbacks.error_callback) { + l_es->callbacks.error_callback(l_es, ETIMEDOUT); + } + dap_events_socket_remove_and_delete_unsafe(l_es,false); + } + } + } + return true; +} + +/** + * @brief sap_worker_add_events_socket + * @param a_events_socket + * @param a_worker + */ +void dap_worker_add_events_socket(dap_events_socket_t * a_events_socket, dap_worker_t * a_worker) +{ +/*#ifdef DAP_EVENTS_CAPS_KQUEUE + a_events_socket->worker = a_worker; + if(dap_worker_add_events_socket_unsafe(a_events_socket, a_worker)!=0) + a_events_socket->worker = NULL; + +#else*/ + if(g_debug_reactor) + log_it(L_DEBUG,"Worker add esocket %"DAP_FORMAT_SOCKET, a_events_socket->socket); + int l_ret = dap_events_socket_queue_ptr_send( a_worker->queue_es_new, a_events_socket ); + if(l_ret != 0 ){ + char l_errbuf[128]; + *l_errbuf = 0; + strerror_r(l_ret, l_errbuf, sizeof(l_errbuf)); + log_it(L_ERROR, "Can't send pointer in queue: \"%s\"(code %d)", l_errbuf, l_ret); + } +//#endif +} + +/** + * @brief dap_worker_add_events_socket_inter + * @param a_es_input + * @param a_events_socket + */ +void dap_worker_add_events_socket_inter(dap_events_socket_t * a_es_input, dap_events_socket_t * a_events_socket) +{ + if( dap_events_socket_queue_ptr_send_to_input( a_es_input, a_events_socket ) != 0 ){ + int l_errno = errno; + char l_errbuf[128]; + *l_errbuf = 0; + strerror_r(l_errno,l_errbuf,sizeof (l_errbuf)); + log_it(L_ERROR, "Cant send pointer to interthread queue input: \"%s\"(code %d)", l_errbuf, l_errno); + } +} + + +/** + * @brief dap_worker_exec_callback_on + */ +void dap_worker_exec_callback_on(dap_worker_t * a_worker, dap_worker_callback_t a_callback, void * a_arg) +{ + dap_worker_msg_callback_t * l_msg = DAP_NEW_Z(dap_worker_msg_callback_t); + l_msg->callback = a_callback; + l_msg->arg = a_arg; + int l_ret=dap_events_socket_queue_ptr_send( a_worker->queue_callback,l_msg ); + if(l_ret != 0 ){ + char l_errbuf[128]; + *l_errbuf = 0; + strerror_r(l_ret,l_errbuf,sizeof (l_errbuf)); + log_it(L_ERROR, "Cant send pointer in queue: \"%s\"(code %d)", l_errbuf, l_ret); + } + +} + + +/** + * @brief dap_worker_add_events_socket + * @param a_worker + * @param a_events_socket + */ +dap_worker_t *dap_worker_add_events_socket_auto( dap_events_socket_t *a_es) +{ +// struct epoll_event ev = {0}; + dap_worker_t *l_worker = dap_events_worker_get_auto( ); + + dap_worker_add_events_socket( a_es, l_worker); + return l_worker; +} + + + diff --git a/dap-sdk/io/include/dap_context.h b/dap-sdk/io/include/dap_context.h new file mode 100644 index 0000000000000000000000000000000000000000..182a1fb4213dfc93074bc803526968ec2eb7b7f9 --- /dev/null +++ b/dap-sdk/io/include/dap_context.h @@ -0,0 +1,93 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Ltd. https://demlabs.net + * Copyright (c) 2022 + * All rights reserved. + + This file is part of DAP SDK the open source project + + DAP SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + DAP SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once + +#include <pthread.h> +#include <uthash.h> +#include "dap_common.h" +#include "dap_events_socket.h" +#include "dap_proc_queue.h" + +typedef struct dap_worker dap_worker_t; +typedef struct dap_proc_thread dap_proc_thread_t; +typedef struct dap_context { + uint32_t id; // Context ID + + // Compatibility fields, in future should be replaced with _inheritor + dap_proc_thread_t * proc_thread; // If the context belongs to proc_thread + dap_worker_t * worker; // If the context belongs to worker + +#if defined DAP_EVENTS_CAPS_MSMQ + HANDLE msmq_events[MAXIMUM_WAIT_OBJECTS]; +#endif + +#if defined DAP_EVENTS_CAPS_EPOLL + EPOLL_HANDLE epoll_fd; + struct epoll_event epoll_events[ DAP_EVENTS_SOCKET_MAX]; +#elif defined ( DAP_EVENTS_CAPS_POLL) + int poll_fd; + struct pollfd * poll; + dap_events_socket_t ** poll_esocket; + atomic_uint poll_count; + size_t poll_count_max; + bool poll_compress; // Some of fd's became NULL so arrays need to be reassigned +#elif defined (DAP_EVENTS_CAPS_KQUEUE) + int kqueue_fd; + struct kevent * kqueue_events_selected; + struct kevent * kqueue_events; + size_t kqueue_events_count; + + int kqueue_events_count_max; + int kqueue_events_selected_count_max; +#else +#error "Not defined worker for your platform" +#endif + + dap_events_socket_t *esockets; // Hashmap of event sockets + + // Signal to exit + bool signal_exit; + +} dap_context_t; + +extern pthread_key_t g_dap_context_pth_key; +static inline dap_context_t * dap_context_current(){ + return (dap_context_t*) pthread_getspecific(g_dap_context_pth_key); +} + + +int dap_context_init(); // Init + +// New context create. Thread-safe functions +dap_context_t * dap_context_new(); + +/// ALL THIS FUNCTIONS ARE UNSAFE ! CALL THEM ONLY INSIDE THEIR OWN CONTEXT!! +int dap_context_thread_init(dap_context_t * a_context); +int dap_context_thread_loop(dap_context_t * a_context); + +int dap_context_add_esocket(dap_context_t * a_context, dap_events_socket_t * a_esocket ); +int dap_context_poll_update(dap_events_socket_t * a_esocket); +dap_events_socket_t *dap_context_esocket_find_by_uuid(dap_context_t * a_context, dap_events_socket_uuid_t a_es_uuid ); +dap_events_socket_t * dap_context_create_esocket_queue(dap_context_t * a_context, dap_events_socket_callback_queue_ptr_t a_callback); +dap_events_socket_t * dap_context_create_esocket_event(dap_context_t * a_context, dap_events_socket_callback_event_t a_callback); +dap_events_socket_t * dap_context_create_esocket_pipe(dap_context_t * a_context, dap_events_socket_callback_t a_callback, uint32_t a_flags); diff --git a/dap-sdk/net/core/include/dap_events.h b/dap-sdk/io/include/dap_events.h similarity index 100% rename from dap-sdk/net/core/include/dap_events.h rename to dap-sdk/io/include/dap_events.h diff --git a/dap-sdk/net/core/include/dap_events_socket.h b/dap-sdk/io/include/dap_events_socket.h similarity index 97% rename from dap-sdk/net/core/include/dap_events_socket.h rename to dap-sdk/io/include/dap_events_socket.h index d0b406a1c7c31ee99fe3625f716dcd939b022f5a..52086076a9a63d1f9543f685d818e638686d9e48 100644 --- a/dap-sdk/net/core/include/dap_events_socket.h +++ b/dap-sdk/io/include/dap_events_socket.h @@ -115,6 +115,7 @@ typedef struct dap_events dap_events_t; typedef struct dap_events_socket dap_events_socket_t; typedef struct dap_worker dap_worker_t; typedef struct dap_proc_thread dap_proc_thread_t ; +typedef struct dap_context dap_context_t; typedef struct dap_server dap_server_t; typedef void (*dap_events_socket_callback_t) (dap_events_socket_t *,void * ); // Callback for specific client operations @@ -244,8 +245,8 @@ typedef struct dap_events_socket { // Links to related objects - dap_events_t *events; - dap_worker_t *worker; +// dap_events_t *events; + dap_context_t * context; dap_proc_thread_t * proc_thread; // If assigned on dap_proc_thread_t object dap_server_t *server; // If this socket assigned with server @@ -310,7 +311,6 @@ void dap_events_socket_deinit(void); // Deinit clients module dap_events_socket_t * dap_events_socket_create(dap_events_desc_type_t a_type, dap_events_socket_callbacks_t* a_callbacks); -dap_events_socket_t * dap_events_socket_create_type_queue_ptr_unsafe(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback); dap_events_socket_t * dap_events_socket_create_type_queue_ptr_mt(dap_worker_t * a_w, dap_events_socket_callback_queue_ptr_t a_callback); int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket); @@ -329,6 +329,7 @@ int dap_events_socket_queue_ptr_send( dap_events_socket_t * a_es, void* a_arg); int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value); void dap_events_socket_delete_unsafe( dap_events_socket_t * a_esocket , bool a_preserve_inheritor); +void dap_events_socket_delete_mt(dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid); dap_events_socket_t *dap_events_socket_wrap_no_add( dap_events_t *a_events, int a_sock, dap_events_socket_callbacks_t *a_callbacks ); @@ -341,13 +342,8 @@ void dap_events_socket_assign_on_worker_inter(dap_events_socket_t * a_es_input, void dap_events_socket_reassign_between_workers_mt(dap_worker_t * a_worker_old, dap_events_socket_t * a_es, dap_worker_t * a_worker_new); void dap_events_socket_reassign_between_workers_unsafe(dap_events_socket_t * a_es, dap_worker_t * a_worker_new); -// Non-MT functions -dap_events_socket_t * dap_worker_esocket_find_uuid(dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid); - void dap_events_socket_set_readable_unsafe(dap_events_socket_t * sc,bool is_ready); void dap_events_socket_set_writable_unsafe(dap_events_socket_t * sc,bool is_ready); -void dap_events_socket_worker_poll_update_unsafe(dap_events_socket_t * a_esocket); - size_t dap_events_socket_write_unsafe(dap_events_socket_t *sc, const void * data, size_t data_size); size_t dap_events_socket_write_f_unsafe(dap_events_socket_t *sc, const char * format,...); diff --git a/dap-sdk/net/core/include/dap_net.h b/dap-sdk/io/include/dap_net.h similarity index 100% rename from dap-sdk/net/core/include/dap_net.h rename to dap-sdk/io/include/dap_net.h diff --git a/dap-sdk/net/core/include/dap_proc_queue.h b/dap-sdk/io/include/dap_proc_queue.h similarity index 74% rename from dap-sdk/net/core/include/dap_proc_queue.h rename to dap-sdk/io/include/dap_proc_queue.h index cd75526c8c096e86a2ed689a34063ef638a22763..97ca1f262860bed2731502593bd9de38f7ef7a49 100644 --- a/dap-sdk/net/core/include/dap_proc_queue.h +++ b/dap-sdk/io/include/dap_proc_queue.h @@ -31,21 +31,21 @@ typedef bool (*dap_proc_queue_callback_t)(dap_proc_thread_t *, void *); // C // we want to stop callback execution and // not to go on next loop enum { - DAP_QUE$K_PRI0 = 0, /* Lowest priority (Idle) */ - DAP_QUE$K_PRI_IDLE = DAP_QUE$K_PRI0, /* Don't use Idle if u are not sure that understand how it works */ + DAP_PROC_PRI_0 = 0, /* Lowest priority (Idle) */ + DAP_PROC_PRI_IDLE = DAP_PROC_PRI_0, /* Don't use Idle if u are not sure that understand how it works */ - DAP_QUE$K_PRI1 = 1, /* Low priority */ - DAP_QUE$K_PRI_LOW = DAP_QUE$K_PRI1, + DAP_PROC_PRI_1 = 1, /* Low priority */ + DAP_PROC_PRI_LOW = DAP_PROC_PRI_1, - DAP_QUE$K_PRI2 = 2, - DAP_QUE$K_PRI_NORMAL = DAP_QUE$K_PRI2, /* Default priority for any queue's entry; + DAP_PROC_PRI_2 = 2, + DAP_PROC_PRI_NORMAL = DAP_PROC_PRI_2, /* Default priority for any queue's entry; has assigned implicitly */ - DAP_QUE$K_PRI3 = 3, /* Higest priority */ - DAP_QUE$K_PRI_HIGH = DAP_QUE$K_PRI3, + DAP_PROC_PRI_3 = 3, /* Higest priority */ + DAP_PROC_PRI_HIGH = DAP_PROC_PRI_3, - DAP_QUE$K_PRIMAX = 4 /* End-of-list marker */ + DAP_PROC_PRI_MAX = 4 /* End-of-list marker */ }; #define DAP_QUE$K_ITER_NR 7 @@ -63,9 +63,9 @@ typedef struct dap_proc_queue{ dap_events_socket_t *esocket; struct { - pthread_mutex_t lock; /* To coordinate access to the queuee's entries */ - dap_slist_t items; /* List of the queue' entries */ - } list [DAP_QUE$K_PRIMAX]; /* An array of list according of priority numbers */ + pthread_mutex_t lock; /* To coordinate access to the queuee's entries */ + dap_slist_t items; /* List of the queue' entries */ + } list [DAP_PROC_PRI_MAX]; /* An array of list according of priority numbers */ } dap_proc_queue_t; dap_proc_queue_t *dap_proc_queue_create(dap_proc_thread_t * a_thread); @@ -77,4 +77,5 @@ int dap_proc_queue_add_callback_inter(dap_events_socket_t * a_es_input, dap_proc int dap_proc_queue_add_callback_ext(dap_worker_t * a_worker, dap_proc_queue_callback_t a_callback, void * a_callback_arg, int a_pri); int dap_proc_queue_add_callback_inter_ext(dap_events_socket_t * a_es_input, dap_proc_queue_callback_t a_callback, void * a_callback_arg, int ); +int dap_proc_thread_add_callback_mt(dap_proc_thread_t * a_thread, dap_proc_queue_callback_t a_callback, void * a_callback_arg, int a_pri); diff --git a/dap-sdk/net/core/include/dap_proc_thread.h b/dap-sdk/io/include/dap_proc_thread.h similarity index 81% rename from dap-sdk/net/core/include/dap_proc_thread.h rename to dap-sdk/io/include/dap_proc_thread.h index fb592d30cfe66020901a7aeba41bc4c0a8b5240c..e2b1e9fb5ec8efd2d70553b04fb9245a640fc845 100644 --- a/dap-sdk/net/core/include/dap_proc_thread.h +++ b/dap-sdk/io/include/dap_proc_thread.h @@ -27,7 +27,7 @@ #include "dap_proc_queue.h" #include "dap_worker.h" #include "dap_common.h" - +#include "dap_context.h" typedef struct dap_proc_thread{ uint32_t cpu_id; pthread_t thread_id; /* TID has been returned by pthread_create() */ @@ -43,27 +43,13 @@ typedef struct dap_proc_thread{ dap_events_socket_t *queue_gdb_input; /* Inputs for request to GDB, @RRL: #6238 */ - int signal_kill; - int signal_exit; + dap_context_t * context; dap_events_socket_t * event_exit; + pthread_cond_t started_cond; + pthread_mutex_t started_mutex ; -#ifdef DAP_EVENTS_CAPS_EPOLL - EPOLL_HANDLE epoll_ctl; -#elif defined (DAP_EVENTS_CAPS_POLL) - int poll_fd; - struct pollfd * poll; - dap_events_socket_t ** esockets; - size_t poll_count; - size_t poll_count_max; -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - int kqueue_fd; - struct kevent * kqueue_events; - int kqueue_events_count_max; -#else -#error "No poll for proc thread for your platform" -#endif void * _inheritor; } dap_proc_thread_t; @@ -83,10 +69,10 @@ int dap_proc_thread_esocket_write_inter(dap_proc_thread_t * a_thread,dap_worker_ int dap_proc_thread_esocket_write_f_inter(dap_proc_thread_t * a_thread,dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid, const char * a_format,...); -int dap_proc_thread_esocket_update_poll_flags(dap_proc_thread_t * a_thread, dap_events_socket_t * a_esocket); - typedef void (*dap_proc_worker_callback_t)(dap_worker_t *,void *); -void dap_proc_thread_worker_exec_callback(dap_proc_thread_t * a_thread, size_t a_worker_id, dap_proc_worker_callback_t a_callback, void * a_arg); +void dap_proc_thread_worker_exec_callback_inter(dap_proc_thread_t * a_thread, size_t a_worker_id, dap_proc_worker_callback_t a_callback, void * a_arg); int dap_proc_thread_assign_esocket_unsafe(dap_proc_thread_t * a_thread, dap_events_socket_t * a_esocket); + + diff --git a/dap-sdk/net/core/include/dap_server.h b/dap-sdk/io/include/dap_server.h similarity index 100% rename from dap-sdk/net/core/include/dap_server.h rename to dap-sdk/io/include/dap_server.h diff --git a/dap-sdk/net/core/include/dap_timerfd.h b/dap-sdk/io/include/dap_timerfd.h similarity index 100% rename from dap-sdk/net/core/include/dap_timerfd.h rename to dap-sdk/io/include/dap_timerfd.h diff --git a/dap-sdk/net/core/include/dap_worker.h b/dap-sdk/io/include/dap_worker.h similarity index 78% rename from dap-sdk/net/core/include/dap_worker.h rename to dap-sdk/io/include/dap_worker.h index 4ddf9f9d30f40fc7e1caa1727e2d5c7ab96e2578..c9cf8201d45d171c089b95ea6f9fe59f538a647d 100644 --- a/dap-sdk/net/core/include/dap_worker.h +++ b/dap-sdk/io/include/dap_worker.h @@ -23,26 +23,24 @@ #pragma once #include <pthread.h> +#include <stdatomic.h> #include "dap_events_socket.h" #include "dap_proc_queue.h" #include "dap_common.h" #include "dap_events.h" +#include "dap_context.h" +typedef struct dap_context dap_context_t; //typedef struct dap_proc_queue dap_proc_queue_t; typedef struct dap_timerfd dap_timerfd_t; typedef struct dap_worker { - uint32_t id; + uint32_t id; dap_events_t* events; dap_proc_queue_t* proc_queue; dap_events_socket_t *proc_queue_input; - uint32_t event_sockets_count; - pthread_rwlock_t esocket_rwlock; - dap_events_socket_t *esockets; // Hashmap of event sockets - - // Signal to exit - int signal_exit; + atomic_uint event_sockets_count; // worker control queues dap_events_socket_t *queue_es_new; // Queue socket for new socket @@ -64,30 +62,8 @@ typedef struct dap_worker dap_events_socket_t *queue_gdb_input; /* Inputs for request to GDB, @RRL: #6238 */ dap_timerfd_t * timer_check_activity; -#if defined DAP_EVENTS_CAPS_MSMQ - HANDLE msmq_events[MAXIMUM_WAIT_OBJECTS]; -#endif -#if defined DAP_EVENTS_CAPS_EPOLL - EPOLL_HANDLE epoll_fd; -#elif defined ( DAP_EVENTS_CAPS_POLL) - int poll_fd; - struct pollfd * poll; - dap_events_socket_t ** poll_esocket; - atomic_uint poll_count; - size_t poll_count_max; - bool poll_compress; // Some of fd's became NULL so arrays need to be reassigned -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - int kqueue_fd; - struct kevent * kqueue_events_selected; - struct kevent * kqueue_events; - size_t kqueue_events_count; - - int kqueue_events_count_max; - int kqueue_events_selected_count_max; -#else -#error "Not defined worker for your platform" -#endif + dap_context_t *context; pthread_cond_t started_cond; pthread_mutex_t started_mutex; void * _inheritor; @@ -124,7 +100,11 @@ extern "C" { int dap_worker_init( size_t a_conn_timeout ); void dap_worker_deinit(); -int dap_worker_add_events_socket_unsafe( dap_events_socket_t * a_esocket, dap_worker_t * a_worker); +static inline int dap_worker_add_events_socket_unsafe( dap_events_socket_t * a_esocket, dap_worker_t * a_worker) +{ + return dap_context_add_esocket(a_worker->context, a_esocket); +} + void dap_worker_add_events_socket(dap_events_socket_t * a_events_socket, dap_worker_t * a_worker); void dap_worker_add_events_socket_inter(dap_events_socket_t * a_es_input, dap_events_socket_t * a_events_socket); dap_worker_t *dap_worker_add_events_socket_auto( dap_events_socket_t * a_events_socket ); diff --git a/dap-sdk/net/core/libdap-net-core.pri b/dap-sdk/io/libdap-io.pri similarity index 80% rename from dap-sdk/net/core/libdap-net-core.pri rename to dap-sdk/io/libdap-io.pri index 2aa609cf66bb8c400a58bb40c9941aca317c1dbd..37dbe8509c076376eb21f8eb626019b0cc6a9cc2 100755 --- a/dap-sdk/net/core/libdap-net-core.pri +++ b/dap-sdk/io/libdap-io.pri @@ -5,7 +5,8 @@ HEADERS += $$PWD/include/dap_events.h \ $$PWD/include/dap_proc_thread.h \ $$PWD/include/dap_server.h \ $$PWD/include/dap_timerfd.h \ - $$PWD/include/dap_worker.h + $$PWD/include/dap_context.h \ + $$PWD/include/dap_worker.h SOURCES += $$PWD/dap_events.c \ $$PWD/dap_events_socket.c \ @@ -14,6 +15,7 @@ SOURCES += $$PWD/dap_events.c \ $$PWD/dap_proc_thread.c \ $$PWD/dap_server.c \ $$PWD/dap_timerfd.c \ - $$PWD/dap_worker.c + $$PWD/dap_context.c \ + $$PWD/dap_worker.c INCLUDEPATH += $$PWD/include diff --git a/dap-sdk/io/test/CMakeLists.txt b/dap-sdk/io/test/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..a5a6ffe1a3685b504d2ff6938e80ad27c3fd855f --- /dev/null +++ b/dap-sdk/io/test/CMakeLists.txt @@ -0,0 +1,17 @@ +project(server_io_test) + +if ( NOT ( TARGET dap_test ) ) + add_subdirectory(libdap-test) +endif() + +file(GLOB DAP_IO_TEST_SOURCES *.c) +file(GLOB DAP_IO_TEST_HEADERS *.h) + +add_executable(${PROJECT_NAME} ${DAP_IO_TEST_SOURCES} ${DAP_IO_TEST_HEADERS}) + +target_link_libraries(${PROJECT_NAME} dap_test dap_core dap_crypto dap_io) + +add_test( + NAME server_io_test + COMMAND server_io_test +) diff --git a/dap-sdk/net/core/test/dap_traffic_track_test.c b/dap-sdk/io/test/dap_traffic_track_test.c similarity index 100% rename from dap-sdk/net/core/test/dap_traffic_track_test.c rename to dap-sdk/io/test/dap_traffic_track_test.c diff --git a/dap-sdk/net/core/test/dap_traffic_track_test.h b/dap-sdk/io/test/dap_traffic_track_test.h similarity index 100% rename from dap-sdk/net/core/test/dap_traffic_track_test.h rename to dap-sdk/io/test/dap_traffic_track_test.h diff --git a/dap-sdk/net/core/test/main.c b/dap-sdk/io/test/main.c similarity index 100% rename from dap-sdk/net/core/test/main.c rename to dap-sdk/io/test/main.c diff --git a/dap-sdk/net/client/CMakeLists.txt b/dap-sdk/net/client/CMakeLists.txt index 4c1645ab84c8b52b1adb456dca7bc21175fba756..a96449ad5fc2ad37f85bd075aca0e9ccbc8814c0 100644 --- a/dap-sdk/net/client/CMakeLists.txt +++ b/dap-sdk/net/client/CMakeLists.txt @@ -9,9 +9,9 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CLIENT_HEADERS} ${DAP_CLIENT_SOURCES}) if(DAPSDK_MODULES MATCHES "ssl-support") - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_enc_server dap_stream dap_session dap_stream_ch json-c wolfssl) + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server dap_enc_server dap_stream dap_session dap_stream_ch json-c wolfssl) else() - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_enc_server dap_stream dap_session dap_stream_ch json-c) + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server dap_enc_server dap_stream dap_session dap_stream_ch json-c) endif() if(UNIX AND NOT ANDROID AND NOT DARWIN) target_link_libraries(${PROJECT_NAME} rt) diff --git a/dap-sdk/net/client/dap_client_http.c b/dap-sdk/net/client/dap_client_http.c index 562f89d634f97a8158ed5c6b2a3c52c4ada70105..c321f6ab142e9920f10bf1b331aa478135a74b80 100644 --- a/dap-sdk/net/client/dap_client_http.c +++ b/dap-sdk/net/client/dap_client_http.c @@ -187,7 +187,7 @@ static bool s_timer_timeout_after_connected_check(void * a_arg) dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default()); // We're in own esocket context assert(l_worker); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid( l_worker, *l_es_uuid_ptr); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid( l_worker->context, *l_es_uuid_ptr); if(l_es){ dap_client_http_pvt_t * l_http_pvt = PVT(l_es); assert(l_http_pvt); @@ -224,7 +224,7 @@ static bool s_timer_timeout_check(void * a_arg) dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default()); // We're in own esocket context assert(l_worker); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid(l_worker->context, *l_es_uuid); if(l_es){ if (l_es->flags & DAP_SOCK_CONNECTING ){ dap_client_http_pvt_t * l_http_pvt = PVT(l_es); diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c index 75d8b06c0b2550e289243b6f775b534184c408ac..56a7fdae61c6ae27efd521d7a265e13793b3d24b 100644 --- a/dap-sdk/net/client/dap_client_pvt.c +++ b/dap-sdk/net/client/dap_client_pvt.c @@ -215,7 +215,7 @@ static void s_stream_connected(dap_client_pvt_t * a_client_pvt) dap_events_socket_uuid_t * l_es_uuid_ptr = DAP_NEW_Z(dap_events_socket_uuid_t); assert(a_client_pvt->stream_es); *l_es_uuid_ptr = a_client_pvt->stream_es->uuid; - if( dap_timerfd_start_on_worker(a_client_pvt->stream_es->worker, s_client_timeout_active_after_connect_seconds * 1000, s_stream_timer_timeout_after_connected_check ,l_es_uuid_ptr) == NULL ){ + if( dap_timerfd_start_on_worker(a_client_pvt->stream_es->context->worker, s_client_timeout_active_after_connect_seconds * 1000, s_stream_timer_timeout_after_connected_check ,l_es_uuid_ptr) == NULL ){ log_it(L_ERROR,"Can't run timer for stream after connect check for esocket uuid %"DAP_UINT64_FORMAT_U, *l_es_uuid_ptr); DAP_DEL_Z(l_es_uuid_ptr); } @@ -233,7 +233,7 @@ static bool s_stream_timer_timeout_check(void * a_arg) dap_worker_t *l_worker = dap_events_get_current_worker(dap_events_get_default()); assert(l_worker); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid(l_worker->context, *l_es_uuid_ptr); if(l_es){ if (l_es->flags & DAP_SOCK_CONNECTING ){ dap_client_pvt_t *l_client_pvt = DAP_ESOCKET_CLIENT_PVT(l_es); @@ -275,7 +275,7 @@ static bool s_stream_timer_timeout_after_connected_check(void * a_arg) dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default()); assert(l_worker); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid(l_worker->context, *l_es_uuid_ptr); if( l_es ){ dap_client_pvt_t *l_client_pvt = DAP_ESOCKET_CLIENT_PVT(l_es); if (dap_client_pvt_find(l_client_pvt->uuid)) { @@ -315,7 +315,7 @@ static bool s_enc_init_delay_before_request_timer_callback(void * a_arg) assert (a_arg); dap_events_socket_uuid_t* l_es_uuid_ptr = (dap_events_socket_uuid_t*) a_arg; dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default()); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid_ptr); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid(l_worker->context, *l_es_uuid_ptr); if(l_es){ dap_client_pvt_t *l_client_pvt = DAP_ESOCKET_CLIENT_PVT(l_es); s_stage_status_after(l_client_pvt); diff --git a/dap-sdk/net/client/test/CMakeLists.txt b/dap-sdk/net/client/test/CMakeLists.txt index 065db522c9ca6c0ce661dc47e244e3f7c16cf6dc..db92897878bba8f5c160c4ad3dd2fd24ea4d324d 100755 --- a/dap-sdk/net/client/test/CMakeLists.txt +++ b/dap-sdk/net/client/test/CMakeLists.txt @@ -10,7 +10,7 @@ file(GLOB DAP_CLIENT_TEST_HEADERS *.h) add_executable(${PROJECT_NAME} ${DAP_CLIENT_TEST_SOURCES} ${DAP_CLIENT_TEST_HEADERS}) -target_link_libraries(${PROJECT_NAME} dap_test dap_core dap_crypto dap_server_core ev pthread) +target_link_libraries(${PROJECT_NAME} dap_test dap_core dap_crypto dap_io ev pthread) add_test( NAME dap_client_test diff --git a/dap-sdk/net/core/dap_proc_thread.c b/dap-sdk/net/core/dap_proc_thread.c deleted file mode 100644 index 6a4151e277e7d370a45d2fd73560a166802337bf..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/dap_proc_thread.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Ltd. https://demlabs.net - * Copyright (c) 2020 - * All rights reserved. - - This file is part of DAP SDK the open source project - - DAP SDK is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP SDK is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <errno.h> -#include <stdatomic.h> - -#include "dap_config.h" -#include "dap_list.h" -#include "dap_events.h" -#include "dap_events_socket.h" -#include "dap_proc_thread.h" -#include "dap_server.h" - -#if defined(DAP_EVENTS_CAPS_EPOLL) && !defined(DAP_OS_WINDOWS) -#include <sys/epoll.h> -#elif defined DAP_OS_WINDOWS -#include "wepoll.h" -#elif defined (DAP_EVENTS_CAPS_POLL) -#include <poll.h> -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - -#include <sys/event.h> -#include <err.h> - -#ifndef DAP_OS_DARWIN -#include <pthread_np.h> -typedef cpuset_t cpu_set_t; // Adopt BSD CPU setstructure to POSIX variant -#else -#define NOTE_READ NOTE_LOWAT -#endif - -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL SO_NOSIGPIPE -#endif - -#else -#error "Unimplemented poll for this platform" -#endif - -#define LOG_TAG "dap_proc_thread" - -static size_t s_threads_count = 0; -static dap_proc_thread_t * s_threads = NULL; - -static dap_slist_t s_custom_threads = $DAP_SLIST_INITALIZER; /* Customized proc threads out of the pool */ -static pthread_rwlock_t s_custom_threads_rwlock = PTHREAD_RWLOCK_INITIALIZER; /* Lock to protect <s_custom_threads> */ - - -static void *s_proc_thread_function(void * a_arg); -static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags); - -/** - * @brief dap_proc_thread_init - * @param a_cpu_count 0 means autodetect - * @return - */ -static pthread_cond_t s_started_cond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t s_started_mutex = PTHREAD_MUTEX_INITIALIZER; - -int dap_proc_thread_init(uint32_t a_threads_count) -{ -int l_ret = 0; - - s_threads_count = a_threads_count ? a_threads_count : dap_get_cpu_count( ); - s_threads = DAP_NEW_Z_SIZE(dap_proc_thread_t, sizeof (dap_proc_thread_t)* s_threads_count); - - for (uint32_t i = 0; i < s_threads_count; i++ ) - { - s_threads[i].cpu_id = i; - pthread_mutex_lock( &s_started_mutex ); - - if ( (l_ret = pthread_create( &s_threads[i].thread_id,NULL, s_proc_thread_function, &s_threads[i] )) ) { - log_it(L_CRITICAL, "Create thread failed with code %d", l_ret); - pthread_mutex_unlock( &s_started_mutex ); - return l_ret; - } - - pthread_cond_wait( &s_started_cond, &s_started_mutex); - pthread_mutex_unlock( &s_started_mutex); - } - - return l_ret; -} - -/** - * @brief dap_proc_thread_deinit - */ -void dap_proc_thread_deinit() -{ -int l_rc; -size_t l_sz; -dap_proc_thread_t *l_proc_thread; - - for (uint32_t i = s_threads_count; i--; ){ - dap_events_socket_event_signal(s_threads[i].event_exit, 1); - pthread_join(s_threads[i].thread_id, NULL); - } - - // Cleaning custom proc threads - pthread_rwlock_wrlock(&s_custom_threads_rwlock); - - for ( uint32_t i = s_custom_threads.nr; i--; ) { - if ( s_dap_slist_get4head (&s_custom_threads, (void **) &l_proc_thread, &l_sz) ) - break; - - dap_events_socket_event_signal(l_proc_thread->event_exit, 1); - pthread_join(l_proc_thread->thread_id, NULL); - DAP_DELETE(l_proc_thread); - } - - pthread_rwlock_unlock(&s_custom_threads_rwlock); - - // Signal to cancel working threads and wait for finish - // TODO: Android realization -//#ifndef DAP_OS_ANDROID -// for (size_t i = 0; i < s_threads_count; i++ ){ -// pthread_cancel(s_threads[i].thread_id); -// pthread_join(s_threads[i].thread_id, NULL); -// } -//#endif - -} - -/** - * @brief dap_proc_thread_get - * @param a_cpu_id - * @return - */ -dap_proc_thread_t * dap_proc_thread_get(uint32_t a_cpu_id) -{ - return (a_cpu_id < s_threads_count) ? &s_threads[a_cpu_id] : NULL; -} - -/** - * @brief dap_proc_thread_get_auto - * @return - */ -dap_proc_thread_t * dap_proc_thread_get_auto() -{ -unsigned l_id_min = 0, l_size_min = UINT32_MAX, l_queue_size; - - for (size_t i = 0; i < s_threads_count; i++ ) - { - l_queue_size = atomic_load(&s_threads[i].proc_queue_size); - - if( l_queue_size < l_size_min ){ - l_size_min = l_queue_size; - l_id_min = i; - } - } - - return &s_threads[l_id_min]; -} - -/** - * @brief dap_proc_thread_run_custom Create custom proc thread for specified task - * @return - */ -dap_proc_thread_t * dap_proc_thread_run_custom(void) -{ -dap_proc_thread_t * l_proc_thread = DAP_NEW_Z(dap_proc_thread_t); -int l_ret; - - if (l_proc_thread == NULL) - return log_it(L_CRITICAL,"Out of memory, can't create new proc thread, errno=%d", errno), NULL; - - pthread_mutex_lock( &s_started_mutex ); - - if ( (l_ret = pthread_create( &l_proc_thread->thread_id ,NULL, s_proc_thread_function, l_proc_thread )) ) { - log_it(L_CRITICAL, "Create thread failed with code %d", l_ret); - DAP_DEL_Z (l_proc_thread); - }else{ - pthread_cond_wait( &s_started_cond, &s_started_mutex); - pthread_rwlock_wrlock(&s_custom_threads_rwlock); - assert ( !s_dap_slist_add2tail (&s_custom_threads, l_proc_thread, sizeof(l_proc_thread)) ); - pthread_rwlock_unlock(&s_custom_threads_rwlock); - } - - pthread_mutex_unlock( &s_started_mutex ); - return l_proc_thread; -} - -/** - * @brief s_proc_event_callback - get from queue next element and execute action routine, - * repeat execution depending on status is returned by action routine. - * - * @param a_esocket - * @param a_value - * - */ -static void s_proc_event_callback(dap_events_socket_t * a_esocket, uint64_t __attribute__((unused)) a_value) -{ -dap_proc_thread_t *l_thread; -dap_proc_queue_item_t *l_item; -int l_rc, l_is_anybody_in_queue, l_is_finished, l_iter_cnt, l_cur_pri; -size_t l_item_sz; -dap_proc_queue_t *l_queue; - - debug_if (g_debug_reactor, L_DEBUG, "--> Proc event callback start, a_esocket:%p ", a_esocket); - - if ( !(l_thread = (dap_proc_thread_t *) a_esocket->_inheritor) ) - { - log_it(L_ERROR, "NULL <dap_proc_thread_t> context is detected"); - return; - } - - l_iter_cnt = l_is_anybody_in_queue = 0; - /*@RRL: l_iter_cnt = DAP_QUE$K_ITER_NR; */ - l_queue = l_thread->proc_queue; - - for (l_cur_pri = (DAP_QUE$K_PRIMAX - 1); l_cur_pri; l_cur_pri--, l_iter_cnt++ ) /* Run from higest to lowest ... */ - { - if ( !l_queue->list[l_cur_pri].items.nr ) /* A lockless quick check */ - continue; - - pthread_mutex_lock(&l_queue->list[l_cur_pri].lock); /* Protect list from other threads */ - l_rc = s_dap_slist_get4head (&l_queue->list[l_cur_pri].items, (void **) &l_item, &l_item_sz); - pthread_mutex_unlock(&l_queue->list[l_cur_pri].lock); - - if ( l_rc == -ENOENT ) { /* Queue is empty ? */ - debug_if (g_debug_reactor, L_DEBUG, "a_esocket:%p - nothing to do at prio: %d ", a_esocket, l_cur_pri); - continue; - } - - debug_if (g_debug_reactor, L_INFO, "Proc event callback: %p/%p, prio=%d, iteration=%d", - l_item->callback, l_item->callback_arg, l_cur_pri, l_iter_cnt); - - l_is_finished = l_item->callback(l_thread, l_item->callback_arg); - - debug_if (g_debug_reactor, L_INFO, "Proc event callback: %p/%p, prio=%d, iteration=%d - is %sfinished", - l_item->callback, l_item->callback_arg, l_cur_pri, l_iter_cnt, l_is_finished ? "" : "not "); - - if ( !(l_is_finished) ) { - /* Rearm callback to be executed again */ - pthread_mutex_lock(&l_queue->list[l_cur_pri].lock); - l_rc = s_dap_slist_add2tail (&l_queue->list[l_cur_pri].items, l_item, l_item_sz ); - pthread_mutex_unlock(&l_queue->list[l_cur_pri].lock); - - if ( l_rc ) { - log_it(L_ERROR, "Error requeue event callback: %p/%p, errno=%d", l_item->callback, l_item->callback_arg, l_rc); - DAP_DELETE(l_item); - } - } - else { - DAP_DELETE(l_item); - } - } - for (l_cur_pri = (DAP_QUE$K_PRIMAX - 1); l_cur_pri; l_cur_pri--) /* Really ?! */ - l_is_anybody_in_queue += l_queue->list[l_cur_pri].items.nr; - - if ( l_is_anybody_in_queue ) /* Arm event if we have something to proc again */ - dap_events_socket_event_signal(a_esocket, 1); - - debug_if(g_debug_reactor, L_DEBUG, "<-- Proc event callback end, items rest: %d, iterations: %d", l_is_anybody_in_queue, l_iter_cnt); -} - - -/** - * @brief dap_proc_thread_assign_esocket_unsafe - * @param a_thread - * @param a_esocket - * @return - */ -int dap_proc_thread_assign_esocket_unsafe(dap_proc_thread_t * a_thread, dap_events_socket_t * a_esocket) -{ - assert(a_esocket); - assert(a_thread); - a_esocket->proc_thread = a_thread; - -#ifdef DAP_EVENTS_CAPS_EPOLL - // Init events for EPOLL - a_esocket->ev.events = a_esocket->ev_base_flags ; - if(a_esocket->flags & DAP_SOCK_READY_TO_READ ) - a_esocket->ev.events |= EPOLLIN; - if(a_esocket->flags & DAP_SOCK_READY_TO_WRITE ) - a_esocket->ev.events |= EPOLLOUT; - a_esocket->ev.data.ptr = a_esocket; - return epoll_ctl(a_thread->epoll_ctl, EPOLL_CTL_ADD, a_esocket->socket, &a_esocket->ev); -#elif defined (DAP_EVENTS_CAPS_POLL) - if ( a_thread->poll_count == a_thread->poll_count_max ){ // realloc - a_thread->poll_count_max *= 2; - log_it(L_WARNING, "Too many descriptors (%zu), resizing array twice to %zu", a_thread->poll_count, a_thread->poll_count_max); - a_thread->poll =DAP_REALLOC(a_thread->poll, a_thread->poll_count_max * sizeof(*a_thread->poll)); - a_thread->esockets =DAP_REALLOC(a_thread->esockets, a_thread->poll_count_max * sizeof(*a_thread->esockets)); - } - - a_thread->poll[a_thread->poll_count].fd = a_thread->proc_queue->esocket->fd; - a_thread->poll[a_thread->poll_count].events = a_thread->proc_queue->esocket->poll_base_flags; - a_thread->esockets[a_thread->poll_count] = a_thread->proc_queue->esocket; - a_thread->poll_count++; -#elif defined (DAP_EVENTS_CAPS_KQUEUE) -/* u_short l_flags = a_esocket->kqueue_base_flags; - u_int l_fflags = a_esocket->kqueue_base_fflags; - short l_filter = a_esocket->kqueue_base_filter; - if(a_esocket->flags & DAP_SOCK_READY_TO_READ ) - l_fflags |= NOTE_READ; - if(a_esocket->flags & DAP_SOCK_READY_TO_WRITE ) - l_fflags |= NOTE_WRITE; - - EV_SET(&a_esocket->kqueue_event , a_esocket->socket, l_filter, EV_ADD| l_flags | EV_CLEAR, l_fflags,0, a_esocket); - return kevent ( a_thread->kqueue_fd,&a_esocket->kqueue_event,1,NULL,0,NULL)==1 ? 0 : -1 ; -*/ - // Nothing to do if its input - if ( a_esocket->type == DESCRIPTOR_TYPE_QUEUE && a_esocket->pipe_out) - return 0; -#else -#error "Unimplemented new esocket on worker callback for current platform" -#endif - - return dap_proc_thread_esocket_update_poll_flags(a_thread,a_esocket); -} - -/** - * @brief dap_proc_thread_esocket_update_poll_flags - * @param a_thread - * @param a_esocket - * @return - */ -int dap_proc_thread_esocket_update_poll_flags(dap_proc_thread_t * a_thread, dap_events_socket_t * a_esocket) -{ -#ifdef DAP_EVENTS_CAPS_EPOLL - u_int events = a_esocket->ev_base_flags; - if( a_esocket->flags & DAP_SOCK_READY_TO_READ) { - events |= EPOLLIN; -#ifdef DAP_OS_WINDOWS - events ^= EPOLLONESHOT; -#endif - } - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE) { - events |= EPOLLOUT; -#ifdef DAP_OS_WINDOWS - events |= EPOLLONESHOT; -#endif - } - a_esocket->ev.events = events; - if( epoll_ctl(a_thread->epoll_ctl, EPOLL_CTL_MOD, a_esocket->socket, &a_esocket->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add proc queue on epoll ctl, err: %d", errno); - return -1; - } -#elif defined (DAP_EVENTS_CAPS_POLL) - if ( a_thread->poll_count == a_thread->poll_count_max ){ // realloc - a_thread->poll_count_max *= 2; - log_it(L_WARNING, "Too many descriptors (%zu), resizing array twice to %zu", a_thread->poll_count, a_thread->poll_count_max); - a_thread->poll =DAP_REALLOC(a_thread->poll, a_thread->poll_count_max * sizeof(*a_thread->poll)); - a_thread->esockets =DAP_REALLOC(a_thread->esockets, a_thread->poll_count_max * sizeof(*a_thread->esockets)); - } - a_thread->poll[a_esocket->poll_index].events= a_esocket->poll_base_flags; - if( a_esocket->flags & DAP_SOCK_READY_TO_READ) - a_thread->poll[a_esocket->poll_index].events |= POLLIN; - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE) - a_thread->poll[a_esocket->poll_index].events |= POLLOUT; - -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - - u_short l_flags = a_esocket->kqueue_base_flags; - u_int l_fflags = a_esocket->kqueue_base_fflags; - short l_filter = a_esocket->kqueue_base_filter; - int l_kqueue_fd = a_esocket->proc_thread ? a_esocket->proc_thread->kqueue_fd : -1; - if ( l_kqueue_fd == -1 ){ - log_it(L_ERROR, "Esocket is not assigned with anything ,exit"); - } - struct kevent * l_event = &a_esocket->kqueue_event; - // Check & add - int l_is_error=false; - int l_errno=0; - if (a_esocket->type == DESCRIPTOR_TYPE_EVENT || a_esocket->type == DESCRIPTOR_TYPE_QUEUE){ - EV_SET(l_event, a_esocket->socket, EVFILT_USER,EV_ADD| EV_CLEAR ,0,0, &a_esocket->kqueue_event_catched_data ); - if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL)!=0){ - l_is_error = true; - l_errno = errno; - } - }else{ - EV_SET(l_event, a_esocket->socket, l_filter,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if( a_esocket->flags & DAP_SOCK_READY_TO_READ ){ - EV_SET(l_event, a_esocket->socket, EVFILT_READ,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if( kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) != 1 ){ - l_is_error = true; - l_errno = errno; - } - } - if( !l_is_error){ - if( a_esocket->flags & DAP_SOCK_READY_TO_WRITE || a_esocket->flags &DAP_SOCK_CONNECTING ){ - EV_SET(l_event, a_esocket->socket, EVFILT_WRITE,l_flags| EV_ADD,l_fflags,a_esocket->kqueue_data,a_esocket); - if(kevent( l_kqueue_fd,l_event,1,NULL,0,NULL) != 1){ - l_is_error = true; - l_errno = errno; - } - } - } - } - - if ( l_is_error){ - char l_errbuf[128]; - l_errbuf[0]=0; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it(L_ERROR,"Can't update client socket state on kqueue fd %d: \"%s\" (%d)", - l_kqueue_fd, l_errbuf, l_errno); - } - -#else -#error "Not defined dap_proc_thread.c::s_update_poll_flags() on your platform" -#endif - return 0; -} - -/** - * @brief dap_proc_thread_create_queue_ptr - * @details Call this function as others only from safe situation, or, thats better, from a_thread's context - * @param a_thread - * @param a_callback - * @return - */ -dap_events_socket_t * dap_proc_thread_create_queue_ptr(dap_proc_thread_t * a_thread, dap_events_socket_callback_queue_ptr_t a_callback) -{ - dap_events_socket_t * l_es = dap_events_socket_create_type_queue_ptr_unsafe(NULL,a_callback); - if(l_es == NULL) - return NULL; - l_es->proc_thread = a_thread; - dap_proc_thread_assign_esocket_unsafe (a_thread, l_es); - return l_es; -} - -/** - * @brief s_proc_thread_function - * @param a_arg - * @return - */ -static void * s_proc_thread_function(void * a_arg) -{ - - dap_proc_thread_t * l_thread = (dap_proc_thread_t*) a_arg; - assert(l_thread); - dap_cpu_assign_thread_on(l_thread->cpu_id); - - struct sched_param l_shed_params; - l_shed_params.sched_priority = 0; -#if defined(DAP_OS_WINDOWS) - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) - log_it(L_ERROR, "Couldn't set thread priority, err: %lu", GetLastError()); -#elif defined (DAP_OS_LINUX) - pthread_setschedparam(pthread_self(),SCHED_BATCH ,&l_shed_params); -#elif defined (DAP_OS_BSD) - pthread_setschedparam(pthread_self(),SCHED_OTHER ,&l_shed_params); -#else -#error "Undefined set sched param" -#endif - l_thread->proc_queue = dap_proc_queue_create(l_thread); - - // Init proc_queue for related worker - dap_worker_t * l_worker_related = dap_events_worker_get(l_thread->cpu_id); - assert(l_worker_related); - l_worker_related->proc_queue = l_thread->proc_queue; - l_worker_related->proc_queue_input = dap_events_socket_queue_ptr_create_input(l_worker_related->proc_queue->esocket); - - dap_events_socket_assign_on_worker_mt(l_worker_related->proc_queue_input,l_worker_related); - - l_thread->proc_event = dap_events_socket_create_type_event_unsafe(NULL, s_proc_event_callback); - l_thread->event_exit = dap_events_socket_create_type_event_unsafe(NULL, s_event_exit_callback); - - l_thread->proc_event->_inheritor = l_thread; // we pass thread through it - l_thread->event_exit->_inheritor = l_thread; - - size_t l_workers_count= dap_events_worker_get_count(); - assert(l_workers_count); - l_thread->queue_assign_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); - l_thread->queue_io_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); - l_thread->queue_callback_input = DAP_NEW_Z_SIZE(dap_events_socket_t*, sizeof (dap_events_socket_t*)*l_workers_count ); - - assert(l_thread->queue_assign_input); - assert(l_thread->queue_io_input); - for (size_t n=0; n<l_workers_count; n++){ - dap_worker_t * l_worker =dap_events_worker_get(n); - l_thread->queue_assign_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_new ); - l_thread->queue_io_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_es_io ); - l_thread->queue_callback_input[n] = dap_events_socket_queue_ptr_create_input(l_worker->queue_callback ); - } -#ifdef DAP_EVENTS_CAPS_EPOLL - struct epoll_event l_epoll_events[ DAP_EVENTS_SOCKET_MAX]= { { 0 } }; - - // Create epoll ctl - l_thread->epoll_ctl = epoll_create( DAP_EVENTS_SOCKET_MAX ); - - // add proc queue - l_thread->proc_queue->esocket->ev.events = l_thread->proc_queue->esocket->ev_base_flags; - l_thread->proc_queue->esocket->ev.data.ptr = l_thread->proc_queue->esocket; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->proc_queue->esocket->socket , &l_thread->proc_queue->esocket->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add proc queue %zu on epoll ctl, error %d", l_thread->proc_queue->esocket->socket, errno); - return NULL; - } - - // Add proc event - l_thread->proc_event->ev.events = l_thread->proc_event->ev_base_flags ; - l_thread->proc_event->ev.data.ptr = l_thread->proc_event; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->proc_event->socket , &l_thread->proc_event->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add proc event on epoll ctl, err: %d", errno); - return NULL; - } - - // Add exit event - l_thread->event_exit->ev.events = l_thread->event_exit->ev_base_flags; - l_thread->event_exit->ev.data.ptr = l_thread->event_exit; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->event_exit->socket , &l_thread->event_exit->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add exit event on epoll ctl, err: %d", errno); - return NULL; - } - - for (size_t n = 0; n< dap_events_worker_get_count(); n++){ - // Queue asssign - l_thread->queue_assign_input[n]->ev.events = l_thread->queue_assign_input[n]->ev_base_flags ; - l_thread->queue_assign_input[n]->ev.data.ptr = l_thread->queue_assign_input[n]; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->queue_assign_input[n]->socket, &l_thread->queue_assign_input[n]->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add queue input on epoll ctl, err: %d", errno); - return NULL; - } - - // Queue IO - l_thread->queue_io_input[n]->ev.events = l_thread->queue_io_input[n]->ev_base_flags ; - l_thread->queue_io_input[n]->ev.data.ptr = l_thread->queue_io_input[n]; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->queue_io_input[n]->fd , &l_thread->queue_io_input[n]->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add proc io input on epoll ctl, err: %d", errno); - return NULL; - } - - // Queue callback - l_thread->queue_callback_input[n]->ev.events = l_thread->queue_callback_input[n]->ev_base_flags ; - l_thread->queue_callback_input[n]->ev.data.ptr = l_thread->queue_callback_input[n]; - if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->queue_callback_input[n]->fd , &l_thread->queue_callback_input[n]->ev) != 0 ){ -#ifdef DAP_OS_WINDOWS - errno = WSAGetLastError(); -#endif - log_it(L_CRITICAL, "Can't add proc io input on epoll ctl, err: %d", errno); - return NULL; - } - } -#elif defined(DAP_EVENTS_CAPS_POLL) - l_thread->poll_count_max = DAP_EVENTS_SOCKET_MAX; - l_thread->poll_count = 0; - int l_poll_compress = false; - l_thread->poll = DAP_NEW_Z_SIZE(struct pollfd,l_thread->poll_count_max *sizeof (*l_thread->poll)); - l_thread->esockets = DAP_NEW_Z_SIZE(dap_events_socket_t*,l_thread->poll_count_max *sizeof (*l_thread->esockets)); - - // Add proc queue - dap_proc_thread_assign_esocket_unsafe(l_thread,l_thread->proc_queue->esocket); - - // Add proc event - l_thread->poll[l_thread->poll_count].fd = l_thread->proc_event->fd; - l_thread->poll[l_thread->poll_count].events = l_thread->proc_event->poll_base_flags; - l_thread->esockets[l_thread->poll_count] = l_thread->proc_event; - l_thread->poll_count++; - - // Add exit event - l_thread->poll[l_thread->poll_count].fd = l_thread->event_exit->fd; - l_thread->poll[l_thread->poll_count].events = l_thread->event_exit->poll_base_flags; - l_thread->esockets[l_thread->poll_count] = l_thread->event_exit; - l_thread->poll_count++; - - for (size_t n = 0; n< dap_events_worker_get_count(); n++){ - dap_events_socket_t * l_queue_assign_input = l_thread->queue_assign_input[n]; - dap_events_socket_t * l_queue_io_input = l_thread->queue_io_input[n]; - dap_events_socket_t * l_queue_callback_input = l_thread->queue_callback_input[n]; - if (l_queue_assign_input&&l_queue_io_input){ - - // Queue assign input - l_queue_assign_input->poll_index = l_thread->poll_count; - l_thread->poll[l_thread->poll_count].fd = l_queue_assign_input->fd; - l_thread->poll[l_thread->poll_count].events = l_queue_assign_input->poll_base_flags; - l_thread->esockets[l_thread->poll_count] = l_queue_assign_input; - l_thread->poll_count++; - - // Queue io input - l_queue_io_input->poll_index = l_thread->poll_count; - l_thread->poll[l_thread->poll_count].fd = l_queue_io_input->fd; - l_thread->poll[l_thread->poll_count].events = l_queue_io_input->poll_base_flags; - l_thread->esockets[l_thread->poll_count] = l_queue_io_input; - l_thread->poll_count++; - - // Queue callback input - l_queue_callback_input->poll_index = l_thread->poll_count; - l_thread->poll[l_thread->poll_count].fd = l_queue_callback_input->fd; - l_thread->poll[l_thread->poll_count].events = l_queue_callback_input->poll_base_flags; - l_thread->esockets[l_thread->poll_count] = l_queue_callback_input; - l_thread->poll_count++; - } - } -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - // Create kqueue fd - l_thread->kqueue_fd = kqueue(); - l_thread->kqueue_events_count_max = DAP_EVENTS_SOCKET_MAX; - l_thread->kqueue_events = DAP_NEW_Z_SIZE(struct kevent, l_thread->kqueue_events_count_max *sizeof(struct kevent)); - - dap_proc_thread_assign_esocket_unsafe(l_thread,l_thread->proc_queue->esocket); - dap_proc_thread_assign_esocket_unsafe(l_thread,l_thread->proc_event); - dap_proc_thread_assign_esocket_unsafe(l_thread,l_thread->event_exit); - - for (size_t n = 0; n< dap_events_worker_get_count(); n++){ - // Queue asssign - dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_assign_input[n]); - - // Queue IO - dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_io_input[n]); - - // Queue callback - dap_proc_thread_assign_esocket_unsafe(l_thread, l_thread->queue_callback_input[n]); - } - -#else -#error "Unimplemented poll events analog for this platform" -#endif - - //We've started! - pthread_mutex_lock(&s_started_mutex); - pthread_mutex_unlock(&s_started_mutex); - pthread_cond_broadcast(&s_started_cond); - - l_thread->signal_exit = false; - - // Main loop - while (!l_thread->signal_kill && !l_thread->signal_exit){ - - int l_selected_sockets; - size_t l_sockets_max; -#ifdef DAP_EVENTS_CAPS_EPOLL - //log_it(L_DEBUG, "Epoll_wait call"); - l_selected_sockets = epoll_wait(l_thread->epoll_ctl, l_epoll_events, DAP_EVENTS_SOCKET_MAX, -1); - l_sockets_max = (size_t)l_selected_sockets; -#elif defined (DAP_EVENTS_CAPS_POLL) - l_selected_sockets = poll(l_thread->poll,l_thread->poll_count,-1); - l_sockets_max = l_thread->poll_count; -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - l_selected_sockets = kevent(l_thread->kqueue_fd,NULL,0,l_thread->kqueue_events,l_thread->kqueue_events_count_max,NULL); - l_sockets_max = l_selected_sockets; -#else -#error "Unimplemented poll wait analog for this platform" -#endif - - if(l_selected_sockets == -1) { - if( errno == EINTR) - continue; -#if defined DAP_OS_UNIX - int l_errno = errno; - char l_errbuf[128]; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it(L_ERROR, "Proc thread #%d got errno:\"%s\" (%d)", l_thread->cpu_id , l_errbuf, l_errno); -#elif DAP_OS_WINDOWS - log_it(L_ERROR, "Error occured on thread #%d, errno: %d", l_thread->cpu_id , errno); -#endif - break; - } - for(size_t n = 0; n < l_sockets_max; n++) { - dap_events_socket_t * l_cur; - int l_flag_hup, l_flag_rdhup, l_flag_read, l_flag_write, l_flag_error, - l_flag_nval,l_flag_pri,l_flag_msg; -#ifdef DAP_EVENTS_CAPS_EPOLL - l_cur = (dap_events_socket_t *) l_epoll_events[n].data.ptr; - uint32_t l_cur_events = l_epoll_events[n].events; - l_flag_hup = l_cur_events & EPOLLHUP; - l_flag_rdhup = l_cur_events & EPOLLHUP; - l_flag_write = l_cur_events & EPOLLOUT; - l_flag_read = l_cur_events & EPOLLIN; - l_flag_error = l_cur_events & EPOLLERR; - l_flag_nval = false; - l_flag_pri = false; - l_flag_msg = false; -#elif defined ( DAP_EVENTS_CAPS_POLL) - if(n>=l_thread->poll_count){ - log_it(L_WARNING,"selected_sockets(%d) is bigger then poll count (%zu)", l_selected_sockets, l_thread->poll_count); - break; - } - short l_cur_events = l_thread->poll[n].revents ; - if (!l_cur_events) - continue; - l_cur = l_thread->esockets[n]; - l_flag_hup = l_cur_events& POLLHUP; - l_flag_rdhup = l_cur_events & POLLRDHUP; - l_flag_write = (l_cur_events & POLLOUT) || (l_cur_events &POLLRDNORM)|| (l_cur_events &POLLRDBAND ) ; - l_flag_read = l_cur_events & POLLIN || (l_cur_events &POLLWRNORM)|| (l_cur_events &POLLWRBAND ); - l_flag_error = l_cur_events & POLLERR; - l_flag_nval = l_cur_events & POLLNVAL; - l_flag_pri = l_cur_events & POLLPRI; - l_flag_msg = l_cur_events & POLLMSG; -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - struct kevent * l_kevent = &l_thread->kqueue_events[n]; - l_flag_hup=l_flag_rdhup=l_flag_read=l_flag_write=l_flag_error=l_flag_nval=l_flag_msg =l_flag_pri = false; - - if (l_kevent->filter & EVFILT_USER){ - dap_events_socket_w_data_t * l_es_w_data = (dap_events_socket_w_data_t*) l_kevent->udata; - assert(l_es_w_data); - l_cur = l_es_w_data->esocket; - assert(l_cur); - memcpy(&l_cur->kqueue_event_catched_data,l_es_w_data,sizeof(*l_es_w_data)); - if(l_es_w_data != &l_cur->kqueue_event_catched_data ) - DAP_DELETE(l_es_w_data); - else if (g_debug_reactor) - log_it(L_DEBUG,"Own event signal without actual event data"); - if ( l_cur->pipe_out == NULL){ // If we're not the input for pipe or queue - // we must drop write flag and set read flag - l_flag_read = true; - }else{ - l_flag_write = true; - } - }else{ - l_cur = (dap_events_socket_t*) l_kevent->udata; - assert(l_cur); - - switch (l_kevent->filter) { - case EVFILT_TIMER: - case EVFILT_READ: l_flag_read = true; break; - case EVFILT_WRITE: l_flag_write = true; break; - case EVFILT_EXCEPT : l_flag_rdhup = true; break; - default: log_it(L_CRITICAL,"Unknown filter type in polling, exit thread"); return NULL; - } - - } - l_cur->kqueue_event_catched = l_kevent; -#ifndef DAP_OS_DARWIN - u_int l_cur_events = l_thread->kqueue_events[n].fflags; -#else - uint32_t l_cur_events = l_thread->kqueue_events[n].fflags; -#endif - -#else -#error "Unimplemented fetch esocket after poll" -#endif - assert(l_cur); - if(g_debug_reactor) - log_it(L_DEBUG, "Proc thread #%u esocket %p fd=%"DAP_FORMAT_SOCKET" type=%d flags=0x%0X (%s:%s:%s:%s:%s:%s:%s:%s)", l_thread->cpu_id, l_cur, l_cur->socket, - l_cur->type, l_cur_events, l_flag_read?"read":"", l_flag_write?"write":"", l_flag_error?"error":"", - l_flag_hup?"hup":"", l_flag_rdhup?"rdhup":"", l_flag_msg?"msg":"", l_flag_nval?"nval":"", l_flag_pri?"pri":""); - - //log_it(L_DEBUG,"Waked up esocket %p (socket %d) {read:%s,write:%s,error:%s} ", l_cur, l_cur->fd, - // l_flag_read?"true":"false", l_flag_write?"true":"false", l_flag_error?"true":"false" ); - time_t l_cur_time = time( NULL); - l_cur->last_time_active = l_cur_time; - if (l_flag_error){ -#ifdef DAP_OS_WINDOWS - int l_errno = WSAGetLastError(); -#else - int l_errno = errno; -#endif - char l_errbuf[128]; - strerror_r(l_errno, l_errbuf,sizeof (l_errbuf)); - log_it(L_ERROR,"Some error on proc thread #%u with %"DAP_FORMAT_SOCKET" socket: %s(%d)",l_thread->cpu_id, l_cur->socket, l_errbuf, l_errno); - if(l_cur->callbacks.error_callback) - l_cur->callbacks.error_callback(l_cur, errno); - } - if (l_flag_read ){ - int32_t l_bytes_read = 0; - switch (l_cur->type) { - case DESCRIPTOR_TYPE_QUEUE: - dap_events_socket_queue_proc_input_unsafe(l_cur); -#ifdef DAP_OS_WINDOWS - l_bytes_read = dap_recvfrom(l_cur->socket, NULL, 0); -#endif - break; - case DESCRIPTOR_TYPE_EVENT: - dap_events_socket_event_proc_input_unsafe (l_cur); - break; - - default: - log_it(L_ERROR, "Unprocessed descriptor type accepted in proc thread loop"); -#ifdef DAP_OS_WINDOWS - l_bytes_read = dap_recvfrom(l_cur->socket, NULL, 0); -#endif - break; - } - } - if (l_flag_write ){ - int l_errno=0; - if (l_cur->buf_out_size){ - ssize_t l_bytes_sent = -1; - switch (l_cur->type) { - case DESCRIPTOR_TYPE_QUEUE: - if (l_cur->flags & DAP_SOCK_QUEUE_PTR){ - #if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) - l_bytes_sent = write(l_cur->socket, l_cur->buf_out, sizeof (void *) ); // We send pointer by pointer - #elif defined DAP_EVENTS_CAPS_MSMQ - DWORD l_mp_id = 0; - MQMSGPROPS l_mps; - MQPROPVARIANT l_mpvar[1]; - MSGPROPID l_p_id[1]; - HRESULT l_mstatus[1]; - - l_p_id[l_mp_id] = PROPID_M_BODY; - l_mpvar[l_mp_id].vt = VT_VECTOR | VT_UI1; - l_mpvar[l_mp_id].caub.pElems = l_cur->buf_out; - l_mpvar[l_mp_id].caub.cElems = (u_long)l_cur->buf_out_size; - l_mp_id++; - - l_mps.cProp = l_mp_id; - l_mps.aPropID = l_p_id; - l_mps.aPropVar = l_mpvar; - l_mps.aStatus = l_mstatus; - HRESULT hr = MQSendMessage(l_cur->mqh, &l_mps, MQ_NO_TRANSACTION); - - if (hr != MQ_OK) { - log_it(L_ERROR, "An error occured on sending message to queue, errno: %ld", hr); - break; - } else { - if(dap_sendto(l_cur->socket, l_cur->port, NULL, 0) == SOCKET_ERROR) { - log_it(L_ERROR, "Write to sock error: %d", WSAGetLastError()); - } - l_cur->buf_out_size = 0; - dap_events_socket_set_writable_unsafe(l_cur,false); - - break; - } - #elif defined (DAP_EVENTS_CAPS_QUEUE_MQUEUE) - char * l_ptr = (char *) l_cur->buf_out; - l_bytes_sent = mq_send(l_cur->mqd, l_ptr, sizeof (l_ptr),0); - if (l_bytes_sent==0){ -// log_it(L_DEBUG,"mq_send %p success", l_ptr_in); - l_bytes_sent = sizeof (void *); - }else if (l_bytes_sent == -1 && errno == EINVAL){ // To make compatible with other - l_errno = EAGAIN; // non-blocking sockets -// log_it(L_DEBUG,"mq_send %p EAGAIN", l_ptr_in); - }else{ - l_errno = errno; - log_it(L_WARNING,"mq_send %p errno: %d", l_ptr, l_errno); - } - #elif defined (DAP_EVENTS_CAPS_KQUEUE) - - // Select socket and kqueue fd to send the event - dap_events_socket_t * l_es_output = l_cur->pipe_out ? l_cur->pipe_out : l_cur; - int l_kqueue_fd = l_es_output->worker ? l_es_output->worker->kqueue_fd : l_es_output->proc_thread ? l_es_output->proc_thread->kqueue_fd : -1; - - struct kevent l_event; - dap_events_socket_w_data_t * l_es_w_data = DAP_NEW_Z(dap_events_socket_w_data_t); - l_es_w_data->esocket = l_es_output; - - memcpy(&l_es_w_data->ptr,l_cur->buf_out,sizeof(l_es_w_data->ptr) ); - EV_SET(&l_event,l_es_output->socket, EVFILT_USER,0,NOTE_TRIGGER ,0, l_es_w_data); - - - int l_n = l_kqueue_fd==-1 ? -1 : kevent(l_kqueue_fd,&l_event,1,NULL,0,NULL); - if (l_n != -1) - l_bytes_sent = sizeof(l_es_w_data->ptr); - else{ - l_errno = errno; - log_it(L_WARNING,"queue ptr send error: kevent %p errno: %d", l_es_w_data->ptr, l_errno); - DAP_DELETE(l_es_w_data); - } - #else - #error "Not implemented dap_events_socket_queue_ptr_send() for this platform" - #endif - //int l_errno = errno; - - break; - }break; - default: - log_it(L_ERROR, "Dont process write flags for this socket %d in proc thread", l_cur->fd); - - } - l_errno = errno; - - if(l_bytes_sent>0){ - l_cur->buf_out_size -= l_bytes_sent; - //log_it(L_DEBUG,"Sent %zd bytes out, left %zd in buf out", l_bytes_sent, l_cur->buf_out); - if (l_cur->buf_out_size ){ // Shrink output buffer - - memmove(l_cur->buf_out, l_cur->buf_out+l_bytes_sent, l_cur->buf_out_size ); - }else{ -#ifndef DAP_EVENTS_CAPS_KQUEUE - l_cur->flags ^= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(l_thread, l_cur); -#else - log_it(L_WARNING,"(!) Write event receieved but nothing in buffer"); - sleep(500); // to prevent shitting the log files -#endif - } - } - - }else{ - // TODO Make this code platform-independent -#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT - log_it(L_DEBUG,"(!) Write event receieved but nothing in buffer, switching off this flag"); - l_cur->flags ^= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(l_thread, l_cur); - // TODO Make this code platform-independent -#else - log_it(L_WARNING,"(!) Write event receieved but nothing in buffer"); - sleep(500); // to prevent shitting the log files -#endif - } - - - } - if(l_cur->flags & DAP_SOCK_SIGNAL_CLOSE){ -#ifdef DAP_EVENTS_CAPS_EPOLL - log_it(L_WARNING, "Deleting esocket %d from proc thread?...", l_cur->fd); - if ( epoll_ctl( l_thread->epoll_ctl, EPOLL_CTL_DEL, l_cur->fd, &l_cur->ev) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll ctl" ); - //else - // log_it( L_DEBUG,"Removed epoll's event from proc thread #%u", l_thread->cpu_id ); - if (l_cur->callbacks.delete_callback) - l_cur->callbacks.delete_callback(l_cur, l_thread); - if(l_cur->_inheritor) - DAP_DELETE(l_cur->_inheritor); - DAP_DELETE(l_cur); -#elif defined (DAP_EVENTS_CAPS_POLL) - l_thread->poll[n].fd = -1; - l_poll_compress = true; -#elif defined (DAP_EVENTS_CAPS_KQUEUE) - if (l_cur->socket != -1 ){ - struct kevent * l_event = &l_cur->kqueue_event; - EV_SET(l_event, l_cur->socket, 0 ,EV_DELETE, 0,0,l_cur); - if ( kevent( l_thread->kqueue_fd,l_event,1,NULL,0,NULL) != 1 ) { - int l_errno = errno; - char l_errbuf[128]; - strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); - log_it( L_ERROR,"Can't remove event socket's handler %d from the epoll_fd %d \"%s\" (%d)", l_cur->socket, - l_thread->kqueue_fd, l_errbuf, l_errno); - } - } - -#else -#error "Unimplemented poll ctl analog for this platform" -#endif - } - - } -#ifdef DAP_EVENTS_CAPS_POLL - /***********************************************************/ - /* If the compress_array flag was turned on, we need */ - /* to squeeze together the array and decrement the number */ - /* of file descriptors. */ - /***********************************************************/ - if ( l_poll_compress){ - l_poll_compress = false; - for (size_t i = 0; i < l_thread->poll_count ; i++) { - if ( l_thread->poll[i].fd == -1){ - for(size_t j = i; j +1 < l_thread->poll_count; j++){ - l_thread->poll[j].fd = l_thread->poll[j+1].fd; - l_thread->poll[j].events = l_thread->poll[j+1].events; - l_thread->poll[j].revents = l_thread->poll[j+1].revents; - l_thread->esockets[j] = l_thread->esockets[j+1]; - if(l_thread->esockets[j]) - l_thread->esockets[j]->poll_index = j; - } - i--; - l_thread->poll_count--; - } - } - } -#endif - } - log_it(L_ATT, "Stop processing thread #%u", l_thread->cpu_id); - fflush(stdout); - - // cleanip inputs - for (size_t n=0; n<dap_events_worker_get_count(); n++){ - dap_events_socket_delete_unsafe(l_thread->queue_assign_input[n], false); - dap_events_socket_delete_unsafe(l_thread->queue_io_input[n], false); - dap_events_socket_delete_unsafe(l_thread->queue_callback_input[n], false); - } - - return NULL; -} - -/** - * @brief dap_proc_thread_assign_on_worker_inter - * @param a_thread - * @param a_worker - * @param a_esocket - * @return - */ -bool dap_proc_thread_assign_on_worker_inter(dap_proc_thread_t * a_thread, dap_worker_t * a_worker, dap_events_socket_t *a_esocket ) -{ - dap_events_socket_t * l_es_assign_input = a_thread->queue_assign_input[a_worker->id]; - if(g_debug_reactor) - log_it(L_DEBUG,"Remove esocket %p from proc thread and send it to worker #%u",a_esocket, a_worker->id); - - dap_events_socket_assign_on_worker_inter(l_es_assign_input, a_esocket); - // TODO Make this code platform-independent -#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT - l_es_assign_input->flags |= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_assign_input); -#endif - return true; -} - -/** - * @brief dap_proc_thread_esocket_write_inter - * @param a_thread - * @param a_worker - * @param a_es_uuid - * @param a_data - * @param a_data_size - * @return - */ -int dap_proc_thread_esocket_write_inter(dap_proc_thread_t * a_thread,dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid, - const void * a_data, size_t a_data_size) -{ - dap_events_socket_t * l_es_io_input = a_thread->queue_io_input[a_worker->id]; - dap_events_socket_write_inter(l_es_io_input,a_es_uuid, a_data, a_data_size); - // TODO Make this code platform-independent -#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT - l_es_io_input->flags |= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_io_input); -#endif - return 0; -} - - -/** - * @brief dap_proc_thread_esocket_write_f_inter - * @param a_thread - * @param a_worker - * @param a_es_uuid, - * @param a_format - * @return - */ -int dap_proc_thread_esocket_write_f_inter(dap_proc_thread_t * a_thread,dap_worker_t * a_worker, dap_events_socket_uuid_t a_es_uuid, - const char * a_format,...) -{ - va_list ap, ap_copy; - va_start(ap,a_format); - va_copy(ap_copy, ap); - int l_data_size = dap_vsnprintf(NULL,0,a_format,ap); - va_end(ap); - if (l_data_size <0 ){ - log_it(L_ERROR,"Can't write out formatted data '%s' with values",a_format); - va_end(ap_copy); - return 0; - } - - dap_events_socket_t * l_es_io_input = a_thread->queue_io_input[a_worker->id]; - char * l_data = DAP_NEW_SIZE(char,l_data_size+1); - if (!l_data){ - va_end(ap_copy); - return -1; - } - l_data_size = dap_vsprintf(l_data,a_format,ap_copy); - va_end(ap_copy); - - dap_events_socket_write_inter(l_es_io_input, a_es_uuid, l_data, l_data_size); - // TODO Make this code platform-independent -#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT - l_es_io_input->flags |= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(a_thread, l_es_io_input); -#endif - DAP_DELETE(l_data); - return 0; -} - -/** - * @brief dap_proc_thread_worker_exec_callback - * @param a_thread - * @param a_worker_id - * @param a_callback - * @param a_arg - */ -void dap_proc_thread_worker_exec_callback(dap_proc_thread_t * a_thread, size_t a_worker_id, dap_worker_callback_t a_callback, void * a_arg) -{ - dap_worker_msg_callback_t * l_msg = DAP_NEW_Z(dap_worker_msg_callback_t); - l_msg->callback = a_callback; - l_msg->arg = a_arg; - dap_events_socket_queue_ptr_send_to_input(a_thread->queue_callback_input[a_worker_id],l_msg ); - - // TODO Make this code platform-independent -#ifndef DAP_EVENTS_CAPS_EVENT_KEVENT - a_thread->queue_callback_input[a_worker_id]->flags |= DAP_SOCK_READY_TO_WRITE; - dap_proc_thread_esocket_update_poll_flags(a_thread, a_thread->queue_callback_input[a_worker_id]); -#endif -} - -static void s_event_exit_callback( dap_events_socket_t * a_es, uint64_t a_flags) -{ - (void) a_flags; - dap_proc_thread_t * l_thread = (dap_proc_thread_t *) a_es->_inheritor; - l_thread->signal_exit = true; - if(g_debug_reactor) - log_it(L_DEBUG, "Proc_thread :%u signaled to exit", l_thread->cpu_id); -} - diff --git a/dap-sdk/net/core/test/CMakeLists.txt b/dap-sdk/net/core/test/CMakeLists.txt deleted file mode 100755 index 1149697b7fd05108808487b46e94be484231cdd7..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/test/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -project(server_core_test) - -if ( NOT ( TARGET dap_test ) ) - add_subdirectory(libdap-test) -endif() - -file(GLOB DAP_SERVER_CORE_TEST_SOURCES *.c) -file(GLOB DAP_SERVER_CORE_TEST_HEADERS *.h) - -add_executable(${PROJECT_NAME} ${DAP_SERVER_CORE_TEST_SOURCES} ${DAP_SERVER_CORE_TEST_HEADERS}) - -target_link_libraries(${PROJECT_NAME} dap_test dap_core dap_crypto dap_server_core ev) - -add_test( - NAME server_core_test - COMMAND server_core_test -) diff --git a/dap-sdk/net/libdap-net.pri b/dap-sdk/net/libdap-net.pri index f753e5f14e8b91509e61f8dbe4e81e441219bf29..bd828a94f94b863d6214f6375434fb6ff0ef3e99 100755 --- a/dap-sdk/net/libdap-net.pri +++ b/dap-sdk/net/libdap-net.pri @@ -1,6 +1,5 @@ include (../net/client/libdap-net-client.pri) -include (../net/core/libdap-net-core.pri) include (../net/server/libdap-net-server.pri) include (../net/stream/libdap-net-stream.pri) diff --git a/dap-sdk/net/server/enc_server/CMakeLists.txt b/dap-sdk/net/server/enc_server/CMakeLists.txt index 4f95407a85ec0b43c836ac9f5da15bb12ae3fe64..8aaba2be3cae6e9d374e519d10c15d462df4228e 100644 --- a/dap-sdk/net/server/enc_server/CMakeLists.txt +++ b/dap-sdk/net/server/enc_server/CMakeLists.txt @@ -19,7 +19,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../3rdparty/uthash/src) if(WIN32) - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server json-c + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server json-c KERNEL32 USER32 SHELL32 @@ -41,6 +41,6 @@ if(WIN32) endif() if(UNIX) - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server json-c ) + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server json-c ) endif() diff --git a/dap-sdk/net/server/http_server/CMakeLists.txt b/dap-sdk/net/server/http_server/CMakeLists.txt index e4f3397887bd535d710929565b5021bca94cd3d7..2af0aec59f1e03d422c56188ec11e02fe7aa031d 100644 --- a/dap-sdk/net/server/http_server/CMakeLists.txt +++ b/dap-sdk/net/server/http_server/CMakeLists.txt @@ -26,7 +26,7 @@ if(DARWIN) endif() if(WIN32) - target_link_libraries(dap_http_server dap_core dap_crypto dap_server_core magic regex tre intl iconv + target_link_libraries(dap_http_server dap_core dap_crypto dap_io magic regex tre intl iconv KERNEL32 USER32 SHELL32 @@ -48,7 +48,7 @@ if(WIN32) endif() if(UNIX) - target_link_libraries(${PROJECT_NAME} dap_core dap_server_core magic json-c) + target_link_libraries(${PROJECT_NAME} dap_core dap_io magic json-c) target_include_directories(${PROJECT_NAME} PUBLIC ${IPUTILS_INCLUDE_DIRS}) endif() diff --git a/dap-sdk/net/server/http_server/dap_http_simple.c b/dap-sdk/net/server/http_server/dap_http_simple.c index c37bd1ab719d972f2e0fde41e6ce87454c1675ae..6dead19f9665feff878750090f3a08effb63fc1a 100644 --- a/dap-sdk/net/server/http_server/dap_http_simple.c +++ b/dap-sdk/net/server/http_server/dap_http_simple.c @@ -343,7 +343,7 @@ static void s_http_client_headers_read( dap_http_client_t *a_http_client, void * l_http_simple->esocket = a_http_client->esocket; l_http_simple->http_client = a_http_client; - l_http_simple->worker = a_http_client->esocket->worker; + l_http_simple->worker = a_http_client->esocket->context->worker; l_http_simple->reply_size_max = DAP_HTTP_SIMPLE_URL_PROC( a_http_client->proc )->reply_size_max; l_http_simple->reply_byte = DAP_NEW_Z_SIZE(uint8_t, DAP_HTTP_SIMPLE(a_http_client)->reply_size_max ); @@ -411,7 +411,7 @@ void s_http_client_data_read( dap_http_client_t *a_http_client, void * a_arg ) // bool isOK=true; log_it( L_INFO,"Data for http_simple_request collected" ); - dap_events_socket_remove_from_worker_unsafe(a_http_client->esocket,a_http_client->esocket->worker); + dap_events_socket_remove_from_worker_unsafe(a_http_client->esocket,a_http_client->esocket->context->worker); dap_proc_queue_add_callback_inter( l_http_simple->worker->proc_queue_input , s_proc_queue_callback, l_http_simple); } } diff --git a/dap-sdk/net/server/json_rpc/CMakeLists.txt b/dap-sdk/net/server/json_rpc/CMakeLists.txt index 30207dcaa5881382df12e9c164e4bea61e7d0771..5dcedf1f91891868501c7d969f2b6c1f3984a9b6 100644 --- a/dap-sdk/net/server/json_rpc/CMakeLists.txt +++ b/dap-sdk/net/server/json_rpc/CMakeLists.txt @@ -14,5 +14,5 @@ target_include_directories(${PROJECT_NAME} INTERFACE . include/) target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../3rdparty/uthash/src) -target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c ) +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server dap_client json-c ) #target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c) diff --git a/dap-sdk/net/server/notify_server/CMakeLists.txt b/dap-sdk/net/server/notify_server/CMakeLists.txt index 8390370099ff6c10b1d12bf7be69d16e16f23d3c..de3816c16ef052fe0e3b688b58bd0d34c373925e 100644 --- a/dap-sdk/net/server/notify_server/CMakeLists.txt +++ b/dap-sdk/net/server/notify_server/CMakeLists.txt @@ -8,5 +8,5 @@ add_library(${PROJECT_NAME} STATIC ${DAP_NOTIFY_SRV_SRCS} ${DAP_NOTIFY_SRV_HDRS} target_include_directories(${PROJECT_NAME} INTERFACE . include/) target_include_directories(${PROJECT_NAME} PUBLIC include) -target_link_libraries(${PROJECT_NAME} dap_core dap_server_core json-c ) +target_link_libraries(${PROJECT_NAME} dap_core dap_io json-c ) diff --git a/dap-sdk/net/server/notify_server/src/dap_notify_srv.c b/dap-sdk/net/server/notify_server/src/dap_notify_srv.c index 9b79bd6e7b296707299baba0b2930843223ffa11..37df9da127904d3d47e5ff5deff8956c545d82b7 100644 --- a/dap-sdk/net/server/notify_server/src/dap_notify_srv.c +++ b/dap-sdk/net/server/notify_server/src/dap_notify_srv.c @@ -182,7 +182,7 @@ static void s_notify_server_callback_queue(dap_events_socket_t * a_es, void * a_ } size_t l_str_len = a_arg? strlen((char*)a_arg): 0; if(l_str_len){ - dap_events_socket_write_mt(l_socket_handler->esocket->worker, //_inter(a_es->worker->queue_es_io_input[l_worker_id], + dap_events_socket_write_mt(l_socket_handler->esocket->context->worker, //_inter(a_es->worker->queue_es_io_input[l_worker_id], l_socket_handler->uuid, a_arg, l_str_len + 1); } @@ -206,12 +206,12 @@ static void s_notify_server_callback_new(dap_events_socket_t * a_es, void * a_ar uint64_t *l_uuid_u64 =(uint64_t*) &a_es->uuid; log_it(L_WARNING,"Trying to add notify client with uuid 0x%016"DAP_UINT64_FORMAT_X" but already present this UUID in list, updating only esocket pointer if so", *l_uuid_u64); l_hh_new->esocket = a_es; - l_hh_new->worker_id = a_es->worker->id; + l_hh_new->worker_id = a_es->context->worker->id; }else { l_hh_new = DAP_NEW_Z(dap_events_socket_handler_hh_t); l_hh_new->esocket = a_es; l_hh_new->uuid = a_es->uuid; - l_hh_new->worker_id = a_es->worker->id; + l_hh_new->worker_id = a_es->context->worker->id; a_es->no_close = true; HASH_ADD(hh, s_notify_server_clients, uuid, sizeof (l_hh_new->uuid), l_hh_new); } diff --git a/dap-sdk/net/stream/stream/CMakeLists.txt b/dap-sdk/net/stream/stream/CMakeLists.txt index 11d4b6896a85fa96512ad37d6a9c72cf06a36831..5cc4ec636542842c0eb1720158484e25beaa016c 100755 --- a/dap-sdk/net/stream/stream/CMakeLists.txt +++ b/dap-sdk/net/stream/stream/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB STREAM_HDRS include/*.h) add_library(${PROJECT_NAME} STATIC ${STREAM_SRCS} ${STREAM_HDRS}) -target_link_libraries(dap_stream dap_core dap_server_core dap_crypto +target_link_libraries(dap_stream dap_core dap_io dap_crypto dap_http_server dap_enc_server dap_session dap_stream_ch dap_client) target_include_directories(dap_stream INTERFACE .) diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c index 359d81b5348b175d8c0aa853388aa0b3ea153682..d49d08488c5dae84e10d305487dc04c99850af87 100644 --- a/dap-sdk/net/stream/stream/dap_stream.c +++ b/dap-sdk/net/stream/stream/dap_stream.c @@ -266,7 +266,7 @@ dap_stream_t *s_stream_new(dap_http_client_t *a_http_client) dap_stream_t *l_ret = DAP_NEW_Z(dap_stream_t); l_ret->esocket = a_http_client->esocket; - l_ret->stream_worker = (dap_stream_worker_t *)a_http_client->esocket->worker->_inheritor; + l_ret->stream_worker = (dap_stream_worker_t *)a_http_client->esocket->context->worker->_inheritor; l_ret->conn_http = a_http_client; l_ret->buf_defrag_size = 0; l_ret->seq_id = 0; @@ -274,7 +274,7 @@ dap_stream_t *s_stream_new(dap_http_client_t *a_http_client) // Start server keep-alive timer dap_events_socket_uuid_t *l_es_uuid = DAP_NEW_Z(dap_events_socket_uuid_t); *l_es_uuid = l_ret->esocket->uuid; - l_ret->keepalive_timer = dap_timerfd_start_on_worker(l_ret->esocket->worker, + l_ret->keepalive_timer = dap_timerfd_start_on_worker(l_ret->esocket->context->worker, STREAM_KEEPALIVE_TIMEOUT * 1000, (dap_timerfd_callback_t)s_callback_server_keepalive, l_es_uuid); @@ -889,7 +889,7 @@ static bool s_callback_keepalive(void *a_arg, bool a_server_side) return false; dap_events_socket_uuid_t * l_es_uuid = (dap_events_socket_uuid_t*) a_arg; dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default()); - dap_events_socket_t * l_es = dap_worker_esocket_find_uuid(l_worker, *l_es_uuid); + dap_events_socket_t * l_es = dap_context_esocket_find_by_uuid(l_worker->context, *l_es_uuid); if(l_es) { dap_stream_t *l_stream = NULL; if (a_server_side) { diff --git a/dap-sdk/net/stream/stream/dap_stream_worker.c b/dap-sdk/net/stream/stream/dap_stream_worker.c index 8e553a3da951ce8762c8acadceb73cb27242a873..8d1fa9e5158a0dc4251fe0b2442e4b5eaa51d4d7 100644 --- a/dap-sdk/net/stream/stream/dap_stream_worker.c +++ b/dap-sdk/net/stream/stream/dap_stream_worker.c @@ -96,7 +96,7 @@ int dap_stream_worker_init() */ static void s_ch_io_callback(dap_events_socket_t * a_es, void * a_msg) { - dap_stream_worker_t * l_stream_worker = DAP_STREAM_WORKER( a_es->worker ); + dap_stream_worker_t * l_stream_worker = DAP_STREAM_WORKER( a_es->context->worker ); dap_stream_worker_msg_io_t * l_msg = (dap_stream_worker_msg_io_t*) a_msg; assert(l_msg); diff --git a/modules/chain/btc_rpc/CMakeLists.txt b/modules/chain/btc_rpc/CMakeLists.txt index 930181f7283cee04960465242c2c5448d8ee00b7..5a8bfff563162fe9ef2eb56b524418a2bb29b1ea 100644 --- a/modules/chain/btc_rpc/CMakeLists.txt +++ b/modules/chain/btc_rpc/CMakeLists.txt @@ -14,5 +14,5 @@ target_include_directories(${PROJECT_NAME} INTERFACE . include/) target_include_directories(${PROJECT_NAME} PUBLIC include) target_link_libraries(${PROJECT_NAME} dap_core dap_json_rpc) -#target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_http_server dap_client json-c ) +#target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_http_server dap_client json-c ) #target_link_libraries(${PROJECT_NAME} dap_core)# dap_http_server json-c) diff --git a/modules/channel/chain-net-srv/CMakeLists.txt b/modules/channel/chain-net-srv/CMakeLists.txt index 08b1ea5c1996bb155320f30f87a658a9759dab1d..e9c147d210b11713e39472c28ee466d62fe1089a 100644 --- a/modules/channel/chain-net-srv/CMakeLists.txt +++ b/modules/channel/chain-net-srv/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB DAP_STREAM_CH_CHAIN_NET_SRV_HDRS include/*.h) add_library(${PROJECT_NAME} STATIC ${DAP_STREAM_CH_CHAIN_NET_SRV_SRCS} ${DAP_STREAM_CH_CHAIN_NET_SRV_HDRS}) -target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain_common dap_chain dap_chain_mempool dap_chain_net dap_chain_net_srv dap_server_core dap_stream dap_stream_ch dap_stream_ch_chain dap_stream_ch_chain_net) +target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain_common dap_chain dap_chain_mempool dap_chain_net dap_chain_net_srv dap_io dap_stream dap_stream_ch dap_stream_ch_chain dap_stream_ch_chain_net) target_include_directories(${PROJECT_NAME} INTERFACE .) target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index add1f75c8d46dddb91ef9aafedcd1434df9341eb..617dc0178693ffc00a04955e9b21a18fc194eb71 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -305,10 +305,10 @@ static bool s_sync_out_chains_proc_callback(dap_proc_thread_t *a_thread, void *a //pthread_rwlock_unlock(&l_chain->atoms_rwlock); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_chains_first_worker_callback, l_sync_request ); + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_sync_out_chains_first_worker_callback, l_sync_request ); } else { //pthread_rwlock_unlock(&l_chain->atoms_rwlock); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id,s_sync_out_chains_last_worker_callback, l_sync_request ); + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id,s_sync_out_chains_last_worker_callback, l_sync_request ); } return true; } @@ -415,9 +415,9 @@ static bool s_sync_out_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a_ar log_it(L_DEBUG, "Sync out gdb proc, requested %"DAP_UINT64_FORMAT_U" transactions from address "NODE_ADDR_FP_STR, l_ch_chain->request_db_log->items_number, NODE_ADDR_FP_ARGS_S(l_sync_request->request.node_addr)); l_sync_request->gdb.db_log = l_ch_chain->request_db_log; - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_first_worker_callback, l_sync_request ); + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_sync_out_gdb_first_worker_callback, l_sync_request ); } else { - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_last_worker_callback, l_sync_request ); + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_sync_out_gdb_last_worker_callback, l_sync_request ); } return true; } @@ -472,7 +472,7 @@ static bool s_sync_update_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB; l_sync_request->gdb.db_log = l_ch_chain->request_db_log; l_sync_request->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_update_gdb_start_worker_callback, l_sync_request); + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_sync_update_gdb_start_worker_callback, l_sync_request); return true; } @@ -743,7 +743,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) l_sync_req_tsd->request.id_end = l_last_id; l_sync_req_tsd->gdb.sync_group = l_obj->type == DAP_DB$K_OPTYPE_ADD ? dap_strdup(l_last_group) : dap_strdup_printf("%s.del", l_last_group); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_gdb_sync_tsd_worker_callback, l_sync_req_tsd); } l_last_id = l_obj->id; @@ -806,7 +806,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) // save data to global_db if(!dap_chain_global_db_obj_save(l_obj, 1)) { struct sync_request *l_sync_req_err = DAP_DUP(l_sync_request); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, + dap_proc_thread_worker_exec_callback_inter(a_thread, l_sync_request->worker->id, s_gdb_in_pkt_error_worker_callback, l_sync_req_err); } else if (s_debug_more) log_it(L_DEBUG, "Added new GLOBAL_DB synchronization record"); diff --git a/modules/global-db/dap_chain_global_db.c b/modules/global-db/dap_chain_global_db.c index 7546c2e6add927f5105944a26b7678c7d5f2b1d0..331c6a9beaf6174458929d2cde7f54eaa0c04e6c 100644 --- a/modules/global-db/dap_chain_global_db.c +++ b/modules/global-db/dap_chain_global_db.c @@ -818,8 +818,8 @@ dap_events_socket_t *l_es; l_proc_que = s_global_db_proc_thread->_inheritor; l_es = l_proc_que->esocket; - l_wrk = l_proc_que->esocket->worker; - l_proc_thd = l_proc_que->esocket->proc_thread; + l_wrk = l_proc_que->esocket->context->worker; + l_proc_thd = l_proc_que->esocket->context->proc_thread; if ( !l_wrk && !l_proc_thd ) return log_it(L_ERROR, "Both <worker> or <proc_thread> contexts are NULL"), -EINVAL; @@ -827,8 +827,6 @@ dap_events_socket_t *l_es; if ( l_wrk && l_proc_thd ) return log_it(L_ERROR, "Both <worker> or <proc_thread> contexts are NOT NULL"), -EINVAL; - /* So, at this point we should decide a what <event socket> context will be used */ - l_es = l_wrk ? l_wrk->esockets : l_proc_thd->esockets[0]; if ( !(l_db_req = DAP_NEW_Z(dap_grobal_db_req_t)) ) /* Allocate memory for new DB Request context */ return log_it(L_ERROR, "Cannot allocate memory for DB Request, errno=%d", errno), -errno; diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index 0c5b0075b36ca522fdb0b47ea8ae20b82e01ef44..ea6f12058037b9e67982566cdfd3b2d75a312dca 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -37,16 +37,16 @@ endif() add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS} ${IPUTILS_SRCS} ${IPUTILS_HEADERS}) if(WIN32) - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_server_core dap_notify_srv dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_wallet dap_chain_net_srv dap_stream_ch_chain_voting + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_io dap_notify_srv dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_wallet dap_chain_net_srv dap_stream_ch_chain_voting dap_chain_mempool dap_chain_global_db dap_chain_cs_none) endif() if(LINUX) - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_notify_srv dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_stream_ch_chain_voting dap_chain + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_notify_srv dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_stream_ch_chain_voting dap_chain dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_cs_none resolv ) elseif(BSD) - target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_notify_srv dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_stream_ch_chain_voting dap_chain + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_io dap_notify_srv dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_stream_ch_chain_voting dap_chain dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_cs_none ) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 5de75f6190e7b107d7550a4f91bfff8d84811254..cc1a2a0c7501766a0677dfbdaab0c139df51dd5c 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -302,12 +302,12 @@ int dap_chain_net_init() "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n" "net -net <chain net name> get status\n" "\tLook at current status\n" - "net -net <chain net name> stats tx [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n" + "net -net <chain net name> stats tx|tps [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n" "\tTransactions statistics. Time format is <Year>-<Month>-<Day>_<Hours>:<Minutes>:<Seconds> or just <Seconds> \n" "net -net <chain net name> [-mode {update | all}] sync {all | gdb | chains}\n" "\tSyncronyze gdb, chains or everything\n" "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n" - "net -net <chain net name> link {list | add | del | info | establish}\n" + "net -net <chain net name> link {list | add | del | info | disconnect_all}\n" "\tList, add, del, dump or establish links\n" "net -net <chain net name> ca add {-cert <cert name> | -hash <cert hash>}\n" "\tAdd certificate to list of authority cetificates in GDB group\n" @@ -1638,6 +1638,29 @@ void dap_chain_net_load_all() DAP_DELETE (l_net_dir_str); } +dap_string_t* dap_cli_list_net() +{ + dap_chain_net_item_t * l_net_item, *l_net_item_tmp; + dap_string_t *l_string_ret = dap_string_new(""); + dap_chain_net_t * l_net = NULL; + int l_net_i = 0; + dap_string_append(l_string_ret,"Available networks and chains:\n"); + pthread_rwlock_rdlock(&g_net_items_rwlock); + HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){ + l_net = l_net_item->chain_net; + dap_string_append_printf(l_string_ret, "\t%s:\n", l_net_item->name); + l_net_i++; + + dap_chain_t * l_chain = l_net->pub.chains; + while (l_chain) { + dap_string_append_printf(l_string_ret, "\t\t%s\n", l_chain->name ); + l_chain = l_chain->next; + } + } + pthread_rwlock_unlock(&g_net_items_rwlock); + return l_string_ret; +} + void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){ char* l_node_address_text_block = NULL; dap_chain_node_addr_t l_cur_node_addr = { 0 }; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 702014929cc8ec2c0cd1bf1197bacfa5360e5c1d..9ca432efacc8557c5ca633908137fdbe30462c5b 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -1988,6 +1988,13 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch if((*a_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network dap_chain_node_cli_set_reply_text(a_str_reply, "%s can't find network \"%s\"", argv[0], l_net_str); + char l_str_to_reply_chain[500] = {0}; + char *l_str_to_reply = NULL; + dap_sprintf(l_str_to_reply_chain, "%s can't find network \"%s\"\n", argv[0], l_net_str); + l_str_to_reply = dap_strcat2(l_str_to_reply,l_str_to_reply_chain); + dap_string_t* l_net_str = dap_cli_list_net(); + l_str_to_reply = dap_strcat2(l_str_to_reply,l_net_str->str); + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_to_reply); return -102; } @@ -2000,7 +2007,20 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch if((*a_chain = dap_chain_net_get_chain_by_name(*a_net, l_chain_str)) == NULL) { // Can't find such chain dap_chain_node_cli_set_reply_text(a_str_reply, "%s requires parameter '-chain' to be valid chain name in chain net %s. Current chain %s is not valid", + char l_str_to_reply_chain[500] = {0}; + char *l_str_to_reply = NULL; + dap_sprintf(l_str_to_reply_chain, "%s requires parameter '-chain' to be valid chain name in chain net %s. Current chain %s is not valid\n", argv[0], l_net_str, l_chain_str); + l_str_to_reply = dap_strcat2(l_str_to_reply,l_str_to_reply_chain); + dap_chain_t * l_chain; + dap_chain_net_t * l_chain_net = *a_net; + l_str_to_reply = dap_strcat2(l_str_to_reply,"\nAvailable chains:\n"); + DL_FOREACH(l_chain_net->pub.chains, l_chain){ + l_str_to_reply = dap_strcat2(l_str_to_reply,"\t"); + l_str_to_reply = dap_strcat2(l_str_to_reply,l_chain->name); + l_str_to_reply = dap_strcat2(l_str_to_reply,"\n"); + } + dap_chain_node_cli_set_reply_text(a_str_reply, l_str_to_reply); return -103; } } diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 6a53d0cca80f206dc8851e3d5db0b64417cfa3b2..298c91925144f909093996fc46fb59425de09cef 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -211,7 +211,7 @@ dap_chain_node_sync_status_t dap_chain_node_client_start_sync(dap_events_socket_ dap_events_socket_t * l_es = NULL; dap_events_socket_uuid_t l_es_uuid = l_me->esocket_uuid; // check if esocket still in worker - if( (l_es = dap_worker_esocket_find_uuid(l_worker, l_es_uuid)) != NULL ) { + if( (l_es = dap_context_esocket_find_by_uuid(l_worker->context, l_es_uuid)) != NULL ) { dap_client_t * l_client = dap_client_from_esocket(l_es); if (l_client ) { dap_chain_node_client_t * l_node_client = (dap_chain_node_client_t*) l_client->_inheritor; @@ -330,9 +330,9 @@ static void s_stage_connected_callback(dap_client_t *a_client, void *a_arg) l_node_client->stream_worker = l_stream->stream_worker; if (l_node_client->keep_connection) { dap_events_socket_uuid_t *l_uuid = DAP_DUP(&l_node_client->uuid); - dap_worker_exec_callback_on(l_stream->esocket->worker, s_node_client_connected_synchro_start_callback, l_uuid); + dap_worker_exec_callback_on(l_stream->esocket->context->worker, s_node_client_connected_synchro_start_callback, l_uuid); dap_events_socket_uuid_t *l_uuid_timer = DAP_DUP(&l_node_client->uuid); - l_node_client->sync_timer = dap_timerfd_start_on_worker(l_stream->esocket->worker, + l_node_client->sync_timer = dap_timerfd_start_on_worker(l_stream->esocket->context->worker, s_timer_update_states * 1000, s_timer_update_states_callback, l_uuid_timer); diff --git a/modules/net/dap_chain_node_dns_client.c b/modules/net/dap_chain_node_dns_client.c index 1122be737e9606639e4952727a6ea6d224ad2523..ee4fdc06aa3df44418e47f3eef3ca0b5df92e18a 100644 --- a/modules/net/dap_chain_node_dns_client.c +++ b/modules/net/dap_chain_node_dns_client.c @@ -68,7 +68,7 @@ static void s_dns_client_esocket_read_callback(dap_events_socket_t * a_esocket, size_t l_addr_point = DNS_HEADER_SIZE + strlen(l_dns_client->name) + 2 + 2 * sizeof(uint16_t) + DNS_ANSWER_SIZE - sizeof(uint32_t); if (l_recieved < l_addr_point + sizeof(uint32_t)) { log_it(L_WARNING, "DNS answer incomplete"); - l_dns_client->callback_error(a_esocket->worker, l_dns_client->result,l_dns_client->callbacks_arg,EIO ); + l_dns_client->callback_error(a_esocket->context->worker, l_dns_client->result,l_dns_client->callbacks_arg,EIO ); l_dns_client->is_callbacks_called = true; a_esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; a_esocket->buf_in_size = a_esocket->buf_out_size = 0; @@ -78,7 +78,7 @@ static void s_dns_client_esocket_read_callback(dap_events_socket_t * a_esocket, int l_answers_count = ntohs(*(uint16_t *)l_cur); if (l_answers_count != 1) { log_it(L_WARNING, "Incorrect DNS answer format"); - l_dns_client->callback_error(a_esocket->worker, l_dns_client->result,l_dns_client->callbacks_arg,EINVAL); + l_dns_client->callback_error(a_esocket->context->worker, l_dns_client->result,l_dns_client->callbacks_arg,EINVAL); l_dns_client->is_callbacks_called = true; a_esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; a_esocket->buf_in_size = a_esocket->buf_out_size = 0; @@ -101,7 +101,7 @@ static void s_dns_client_esocket_read_callback(dap_events_socket_t * a_esocket, } } - l_dns_client->callback_success(a_esocket->worker,l_dns_client->result,l_dns_client->callbacks_arg); + l_dns_client->callback_success(a_esocket->context->worker,l_dns_client->result,l_dns_client->callbacks_arg); l_dns_client->is_callbacks_called = true; a_esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; a_esocket->buf_in_size = a_esocket->buf_out_size = 0; @@ -116,7 +116,7 @@ static void s_dns_client_esocket_error_callback(dap_events_socket_t * a_esocket, { struct dns_client * l_dns_client = (struct dns_client*) a_esocket->_inheritor; log_it(L_ERROR,"DNS client esocket error %d", a_error); - l_dns_client->callback_error(a_esocket->worker, l_dns_client->result,l_dns_client->callbacks_arg,a_error); + l_dns_client->callback_error(a_esocket->context->worker, l_dns_client->result,l_dns_client->callbacks_arg,a_error); l_dns_client->is_callbacks_called = true; } @@ -139,11 +139,11 @@ static bool s_dns_client_esocket_timeout_callback(void * a_arg) assert(l_worker); dap_events_socket_t * l_es; - if((l_es = dap_worker_esocket_find_uuid(l_worker ,*l_es_uuid_ptr) ) != NULL){ // If we've not closed this esocket + if((l_es = dap_context_esocket_find_by_uuid(l_worker->context,*l_es_uuid_ptr) ) != NULL){ // If we've not closed this esocket struct dns_client * l_dns_client = (struct dns_client*) l_es->_inheritor; log_it(L_WARNING,"DNS request timeout, bad network?"); if(! l_dns_client->is_callbacks_called ){ - l_dns_client->callback_error(l_es->worker,l_dns_client->result,l_dns_client->callbacks_arg,ETIMEDOUT); + l_dns_client->callback_error(l_es->context->worker,l_dns_client->result,l_dns_client->callbacks_arg,ETIMEDOUT); l_dns_client->is_callbacks_called = true; } @@ -163,7 +163,7 @@ static void s_dns_client_esocket_delete_callback(dap_events_socket_t * a_esocket (void) a_arg; struct dns_client * l_dns_client = (struct dns_client*) a_esocket->_inheritor; if(! l_dns_client->is_callbacks_called ) - l_dns_client->callback_error(a_esocket->worker,l_dns_client->result,l_dns_client->callbacks_arg,EBUSY); + l_dns_client->callback_error(a_esocket->context->worker,l_dns_client->result,l_dns_client->callbacks_arg,EBUSY); if(l_dns_client->name) DAP_DELETE(l_dns_client->name); DAP_DEL_Z(l_dns_client->buf); diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 4e8d1438de9a1a76a3a3630c50237fd483df6a79..8e300c0fe411d5d10001bad0411c1fc0d070d7d4 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -124,6 +124,7 @@ dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id); uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id); dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name); dap_ledger_t * dap_chain_ledger_by_net_name( const char * a_net_name); +dap_string_t* dap_cli_list_net(); dap_chain_t * dap_chain_net_get_chain_by_name( dap_chain_net_t * l_net, const char * a_name); diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c index 72767f217f139a0cb37186a71192b4339bbb1bc4..6538a04c0ab4a28e5c1de1c0c6bd2ad23902eaed 100644 --- a/modules/service/stake/dap_chain_net_srv_stake.c +++ b/modules/service/stake/dap_chain_net_srv_stake.c @@ -346,7 +346,12 @@ bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum } } dap_list_free(l_list_out_items); - uint256_t l_fee = {}; // TODO replace with fractional mult MULT_256_FRAC_FRAC(l_outs_sum, l_stake->fee_value / 100.0); + uint256_t l_fee = uint256_0; // TODO replace with fractional mult MULT_256_FRAC_FRAC(l_outs_sum, l_stake->fee_value / 100.0); +++ + DIV_256(l_stake->fee_value, dap_chain_coins_to_balance("100.0"), &l_fee); + if (MULT_256_COIN(l_outs_sum, l_fee, &l_fee)) { + log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in dap_chain_net_srv_stake_validator()"); + l_fee = uint256_0; + } if (compare256(l_fee_sum, l_fee) == -1) { return false; } diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 529b51064ebd4356c2897d43fc52352f1d47d7f0..f04ea9ce2faeb7be6d2e3d5039446c4e100dfaec 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -142,7 +142,12 @@ static dap_chain_datum_tx_receipt_t *s_xchage_receipt_create(dap_chain_net_srv_x { uint32_t l_ext_size = sizeof(uint256_t) + DAP_CHAIN_TICKER_SIZE_MAX; uint8_t *l_ext = DAP_NEW_S_SIZE(uint8_t, l_ext_size); - uint256_t l_datoshi_buy = {}; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); + uint256_t l_datoshi_buy = uint256_0; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); +++ + DIV_256(dap_chain_coins_to_balance("1.0"), a_price->rate, &l_datoshi_buy); + if (MULT_256_COIN(a_price->datoshi_sell, l_datoshi_buy, &l_datoshi_buy)) { + log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in s_xchage_receipt_create()"); + l_datoshi_buy = uint256_0; + } memcpy(l_ext, &l_datoshi_buy, sizeof(uint256_t)); strcpy((char *)&l_ext[sizeof(uint256_t)], a_price->token_buy); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; @@ -237,7 +242,12 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha dap_enc_key_t *l_seller_key = dap_chain_wallet_get_key(a_wallet, 0); uint256_t l_value_buy = {}; // how many coins to transfer // list of transaction with 'out' items to sell - uint256_t l_datoshi_buy = {}; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); + uint256_t l_datoshi_buy = uint256_0; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); +++ + DIV_256(dap_chain_coins_to_balance("1.0"), a_price->rate, &l_datoshi_buy); + if (MULT_256_COIN(a_price->datoshi_sell, l_datoshi_buy, &l_datoshi_buy)) { + log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in s_xchange_tx_create_exchange()"); + l_datoshi_buy = uint256_0; + } dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_buy, l_seller_addr, l_datoshi_buy, &l_value_buy); if(!l_list_used_out) { @@ -414,7 +424,12 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net_sell); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; - uint256_t l_datoshi_buy = {}; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); + uint256_t l_datoshi_buy = uint256_0; // TODO rework it with fixed point MULT_256_FRAC_FRAC(a_price->datoshi_sell, 1 / a_price->rate); +++ + DIV_256(dap_chain_coins_to_balance("1.0"), a_price->rate, &l_datoshi_buy); + if (MULT_256_COIN(a_price->datoshi_sell, l_datoshi_buy, &l_datoshi_buy)) { + log_it(L_WARNING, "DANGER: MULT_256_COIN overflow! in s_xchange_order_create()"); + l_datoshi_buy = uint256_0; + } char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net_buy, SERV_DIR_SELL, l_uid, *l_node_addr, l_tx_hash, l_datoshi_buy, l_unit, a_price->token_buy, 0, (uint8_t *)&l_ext, l_ext_size, NULL, 0, a_price->wallet_key); @@ -431,7 +446,7 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a strcpy(l_price->token_sell, l_ext->token_sell); l_price->net_buy = a_net; strcpy(l_price->token_buy, a_order->price_ticker); - l_price->rate = 1; // TODO (long double)l_price->datoshi_sell / a_order->price; + DIV_256(l_price->datoshi_sell, a_order->price, &l_price->rate);//l_price->rate = dap_chain_coins_to_balance("1.0");//1; // TODO (long double)l_price->datoshi_sell / a_order->price; return l_price; } @@ -573,8 +588,8 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'price create' required parameter -rate"); return -8; } - long double l_rate = strtold(l_val_rate_str, NULL); - if (!l_rate) { + uint256_t l_rate = dap_chain_coins_to_balance(l_val_rate_str); + if (!compare256(l_rate, uint256_0)) { // if (l_rate == 0) dap_chain_node_cli_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy"); return -9; } @@ -684,7 +699,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c } else { // CMD_UPDATE const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL, *l_new_wallet_str = NULL; uint256_t l_datoshi_sell = {}; - long double l_rate = 0; + uint256_t l_rate = uint256_0; dap_chain_wallet_t *l_wallet = NULL; dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str); if (l_val_sell_str) { @@ -696,8 +711,8 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c } dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); if (l_val_rate_str) { - l_rate = strtold(l_val_rate_str, NULL); - if (!l_rate) { + l_rate = dap_chain_coins_to_balance(l_val_rate_str); + if (!compare256(l_rate, uint256_0)) { // if (l_rate == 0) dap_chain_node_cli_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy"); return -9; } @@ -784,9 +799,9 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c dap_string_t *l_reply_str = dap_string_new(""); HASH_ITER(hh, s_srv_xchange->pricelist, l_price, l_tmp) { char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_price->order_hash); - dap_string_append_printf(l_reply_str, "%s %s %s %s %s %s %Lf %s\n", l_order_hash_str, l_price->token_sell, + dap_string_append_printf(l_reply_str, "%s %s %s %s %s %s %s %s\n", l_order_hash_str, l_price->token_sell, l_price->net_sell->pub.name, l_price->token_buy, l_price->net_buy->pub.name, - dap_chain_balance_print(l_price->datoshi_sell), l_price->rate, l_price->wallet_str); + dap_chain_balance_print(l_price->datoshi_sell), dap_chain_balance_print(l_price->rate), l_price->wallet_str); DAP_DELETE(l_order_hash_str); } if (!l_reply_str->len) { @@ -851,9 +866,9 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) continue; // TODO add filters to list (tokens, network, etc.) l_price = s_xchange_price_from_order(l_net, l_order); - dap_string_append_printf(l_reply_str, "%s %s %s %s %s %s %Lf\n", l_orders[i].key, l_price->token_sell, + dap_string_append_printf(l_reply_str, "%s %s %s %s %s %s %s\n", l_orders[i].key, l_price->token_sell, l_price->net_sell->pub.name, l_price->token_buy, l_price->net_buy->pub.name, - dap_chain_balance_print(l_price->datoshi_sell), l_price->rate); + dap_chain_balance_print(l_price->datoshi_sell), dap_chain_balance_print(l_price->rate)); DAP_DELETE(l_price); } dap_chain_global_db_objs_delete(l_orders, l_orders_count); diff --git a/modules/service/xchange/include/dap_chain_net_srv_xchange.h b/modules/service/xchange/include/dap_chain_net_srv_xchange.h index 6776a7e0baa5bef0590af7fa7bf809fc8c1ee250..216f1ca0edfebb895a07ec57b0b032f1c4c924b8 100644 --- a/modules/service/xchange/include/dap_chain_net_srv_xchange.h +++ b/modules/service/xchange/include/dap_chain_net_srv_xchange.h @@ -37,7 +37,7 @@ typedef struct dap_chain_net_srv_xchange_price { uint256_t datoshi_sell; dap_chain_net_t *net_buy; char token_buy[DAP_CHAIN_TICKER_SIZE_MAX]; - long double rate; + uint256_t rate; dap_chain_hash_fast_t tx_hash; dap_chain_hash_fast_t order_hash; dap_enc_key_t *wallet_key; @@ -53,7 +53,7 @@ typedef struct dap_chain_net_srv_xchange_db_item { uint64_t net_sell_id; uint64_t net_buy_id; uint256_t datoshi_sell; - long double rate; + uint256_t rate; dap_chain_hash_fast_t tx_hash; dap_chain_hash_fast_t order_hash; char wallet_str[]; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3376bcd0556feb9e8ee0a20180d575ecb401f66b..5b9ff4421933a85b2ff6b13f0c6e9210d89309bf 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,7 +50,7 @@ target_link_libraries(dap_global_db_test -pthread -lrt) target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/modules/global-db/libdap_chain_global_db.a) target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/crypto/libdap_crypto.a) -target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/net/core/libdap_server_core.a) +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/net/core/libdap_io.a) target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/core/libdap_core.a) target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/3rdparty/cuttdb/libdap_cuttdb.a) target_link_libraries(dap_global_db_test -lsqlite3)