diff --git a/3rdparty/uthash/src/utarray.h b/3rdparty/uthash/src/utarray.h index 6ed0dcebcb170136209d3e35d6882694b0e5ec1f..6b6201820e0a0b78a289cf555d793c3626549ae6 100644 --- a/3rdparty/uthash/src/utarray.h +++ b/3rdparty/uthash/src/utarray.h @@ -38,8 +38,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define UTARRAY_UNUSED #endif -#ifndef oom -#define oom() exit(-1) +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code." +#define utarray_oom() oom() +#endif + +#ifndef utarray_oom +#define utarray_oom() exit(-1) #endif typedef void (ctor_f)(void *dst, const void *src); @@ -78,7 +83,9 @@ typedef struct { #define utarray_new(a,_icd) do { \ (a) = (UT_array*)malloc(sizeof(UT_array)); \ - if ((a) == NULL) oom(); \ + if ((a) == NULL) { \ + utarray_oom(); \ + } \ utarray_init(a,_icd); \ } while(0) @@ -92,7 +99,9 @@ typedef struct { char *utarray_tmp; \ while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ - if (utarray_tmp == NULL) oom(); \ + if (utarray_tmp == NULL) { \ + utarray_oom(); \ + } \ (a)->d=utarray_tmp; \ } \ } while(0) @@ -118,7 +127,7 @@ typedef struct { #define utarray_len(a) ((a)->i) #define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) -#define _utarray_eltptr(a,j) ((a)->d + ((a)->icd.sz * (j))) +#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) #define utarray_insert(a,p,j) do { \ if ((j) > (a)->i) utarray_resize(a,j); \ @@ -216,10 +225,10 @@ typedef struct { #define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) #define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) -#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) -#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) +#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((a)->i != utarray_eltidx(a,e)+1) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) +#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) != 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) #define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) -#define utarray_eltidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) +#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) /* last we pre-define a few icd for common utarrays of ints and strings */ static void utarray_str_cpy(void *dst, const void *src) { diff --git a/3rdparty/uthash/src/uthash.h b/3rdparty/uthash/src/uthash.h index 76bdca64199f11dbb6387633e2a651dcaee1bb4f..5e5866a353869bc8328f5d9a6fd0a41003a431a5 100644 --- a/3rdparty/uthash/src/uthash.h +++ b/3rdparty/uthash/src/uthash.h @@ -144,7 +144,7 @@ typedef unsigned char uint8_t; /* calculate the element whose hash handle address is hhp */ #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) /* calculate the hash handle from element address elp */ -#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) #define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ do { \ @@ -175,9 +175,12 @@ do { #define HASH_FIND(hh,head,keyptr,keylen,out) \ do { \ - unsigned _hf_hashv; \ - HASH_VALUE(keyptr, keylen, _hf_hashv); \ - HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ } while (0) #ifdef HASH_BLOOM @@ -519,7 +522,8 @@ do { * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. */ #ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#include <stdio.h> /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) #define HASH_FSCK(hh,head,where) \ do { \ struct UT_hash_handle *_thh; \ @@ -750,87 +754,6 @@ do { hashv += hashv >> 6; \ } while (0) -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6bu; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35u; \ - _h ^= _h >> 16; \ -} while (0) - -#define HASH_MUR(key,keylen,hashv) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (int)(keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353u; \ - uint32_t _mur_c1 = 0xcc9e2d51u; \ - uint32_t _mur_c2 = 0x1b873593u; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ - int _mur_i; \ - for (_mur_i = -_mur_nblocks; _mur_i != 0; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ - _mur_k1=0; \ - switch ((keylen) & 3U) { \ - case 0: break; \ - case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ - case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ - case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (uint32_t)(keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ -} while (0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - /* iterate over items in a known bucket to find desired item */ #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ do { \ @@ -1080,7 +1003,7 @@ do { _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ if (cond(_elt)) { \ IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ _dst_hh->key = _src_hh->key; \ _dst_hh->keylen = _src_hh->keylen; \ _dst_hh->hashv = _src_hh->hashv; \ diff --git a/3rdparty/uthash/src/utstring.h b/3rdparty/uthash/src/utstring.h index ca25c902ca585720fe6427037ac5eac74f677ea5..4cf5ffd3dd42128ee8f46c56153ad572930f6ba2 100644 --- a/3rdparty/uthash/src/utstring.h +++ b/3rdparty/uthash/src/utstring.h @@ -39,8 +39,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define UTSTRING_UNUSED #endif -#ifndef oom -#define oom() exit(-1) +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." +#define utstring_oom() oom() +#endif + +#ifndef utstring_oom +#define utstring_oom() exit(-1) #endif typedef struct { @@ -54,7 +59,9 @@ do { \ if (((s)->n - (s)->i) < (size_t)(amt)) { \ char *utstring_tmp = (char*)realloc( \ (s)->d, (s)->n + (amt)); \ - if (utstring_tmp == NULL) oom(); \ + if (!utstring_tmp) { \ + utstring_oom(); \ + } \ (s)->d = utstring_tmp; \ (s)->n += (amt); \ } \ @@ -81,9 +88,11 @@ do { \ #define utstring_new(s) \ do { \ - (s) = (UT_string*)malloc(sizeof(UT_string)); \ - if (!(s)) oom(); \ - utstring_init(s); \ + (s) = (UT_string*)malloc(sizeof(UT_string)); \ + if (!(s)) { \ + utstring_oom(); \ + } \ + utstring_init(s); \ } while(0) #define utstring_renew(s) \ diff --git a/CMakeLists.txt b/CMakeLists.txt index ffdd0d382392a60f3576763f64459b0fd9449488..78a20014107b6486344743aa1f369881256b07d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(cellframe-sdk C) cmake_minimum_required(VERSION 2.8) set(CMAKE_C_STANDARD 11) -set(CELLFRAME_SDK_NATIVE_VERSION "2.3-4") +set(CELLFRAME_SDK_NATIVE_VERSION "2.5-14") add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") set(DAPSDK_MODULES "") diff --git a/cmake/OS_Detection.cmake b/cmake/OS_Detection.cmake index f0be4d78b5fd2ccf926b81f99305cb8ec25dac70..e2801cf8ddc932e28369f4f312750cffc7af1539 100644 --- a/cmake/OS_Detection.cmake +++ b/cmake/OS_Detection.cmake @@ -54,11 +54,11 @@ if(UNIX) add_definitions ("-DDAP_OS_LINUX -DDAP_OS_UNIX") # add_definitions ("-DDAP_LOG_MT") if(DAP_DEBUG) - set(_CCOPT "-DDAP_DEBUG -Wall -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -pg -g3 -ggdb -fno-eliminate-unused-debug-symbols") + set(_CCOPT "-DDAP_DEBUG -Wall -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -pg -g3 -ggdb -fno-eliminate-unused-debug-symbols -fno-strict-aliasing") set(_LOPT "-pg") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg") else() - set(_CCOPT "-Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fPIC -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all -std=gnu11") + set(_CCOPT "-Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fPIC -fno-strict-aliasing -fno-ident -ffast-math -ftree-vectorize -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all -std=gnu11") endif() if (ANDROID) @@ -99,10 +99,10 @@ if(WIN32) add_definitions ("-DDAP_OS_WINDOWS") if(DAP_DEBUG) - set(_CCOPT "-mconsole -static -Wall -std=gnu11 -Wextra -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -g3 -ggdb -fno-eliminate-unused-debug-symbols -pg") + set(_CCOPT "-mconsole -static -Wall -std=gnu11 -Wextra -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -g3 -ggdb -fno-strict-aliasing -fno-eliminate-unused-debug-symbols -pg") set(_LOPT "-mconsole -static -pg") else() - set(_CCOPT "-static -std=gnu11 -Wall -Wextra -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fno-ident -ffast-math -ftree-vectorize -mfpmath=sse -mmmx -msse2 -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all") + set(_CCOPT "-static -std=gnu11 -Wall -Wextra -Wno-deprecated-declarations -Wno-unused-local-typedefs -Wno-unused-function -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -O3 -fno-ident -ffast-math -fno-strict-aliasing -ftree-vectorize -mfpmath=sse -mmmx -msse2 -fno-asynchronous-unwind-tables -ffunction-sections -Wl,--gc-sections -Wl,--strip-all") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT} ") diff --git a/dap-sdk/CMakeLists.txt b/dap-sdk/CMakeLists.txt index 89f2652ec8d5e66e2fb9f976a739d8db2dda8831..cc44d581e1355d8536edad52b489ecc24a46f550 100644 --- a/dap-sdk/CMakeLists.txt +++ b/dap-sdk/CMakeLists.txt @@ -1,3 +1,4 @@ +set(DAP_SDK_NATIVE_VERSION "2.0-11") # Core if (DAPSDK_MODULES MATCHES "core") # Core diff --git a/dap-sdk/core/CMakeLists.txt b/dap-sdk/core/CMakeLists.txt index b9c659ff124ce96e65668f0cc490d15f2a1bcbcb..cd185b4c47bce90ad7758654b64ad5204709c722 100755 --- a/dap-sdk/core/CMakeLists.txt +++ b/dap-sdk/core/CMakeLists.txt @@ -1,9 +1,8 @@ cmake_minimum_required(VERSION 3.0) project (dap_core) -# fix implicit declaration warnings -add_definitions ("-D_GNU_SOURCE") - +add_definitions("-D_GNU_SOURCE") +add_definitions("-DDHASH_USING_NO_STRICT_ALIASING -DHASH_FUNCTION=HASH_MUR") if(UNIX) file(GLOB CORE_SRCS src/*.c diff --git a/dap-sdk/core/include/dap_common.h b/dap-sdk/core/include/dap_common.h index 1fb9ca8e86abc5ef747ab17ca38a953b81cb93fb..ea2a41ab94901868dd8158c9735d2825258a9821 100755 --- a/dap-sdk/core/include/dap_common.h +++ b/dap-sdk/core/include/dap_common.h @@ -162,6 +162,20 @@ DAP_STATIC_INLINE void _dap_aligned_free( void *ptr ) #define DAP_PROTOCOL_VERSION 22 +#if __SIZEOF_LONG__==8 +#define DAP_UINT64_FORMAT_X "lX" +#define DAP_UINT64_FORMAT_x "lx" +#define DAP_UINT64_FORMAT_u "lu" +#define DAP_UINT64_FORMAT_U "lU" +#elif __SIZEOF_LONG__==4 +#define DAP_UINT64_FORMAT_X "llX" +#define DAP_UINT64_FORMAT_x "llx" +#define DAP_UINT64_FORMAT_u "llu" +#define DAP_UINT64_FORMAT_U "llU" +#else +#error "DAP_UINT64_FORMAT_* are undefined for your platform" +#endif + #ifndef LOWORD #define LOWORD( l ) ((uint16_t) (((uintptr_t) (l)) & 0xFFFF)) #define HIWORD( l ) ((uint16_t) ((((uintptr_t) (l)) >> 16) & 0xFFFF)) @@ -412,6 +426,12 @@ void dap_lendian_put32(uint8_t *a_buf, uint32_t a_val); uint64_t dap_lendian_get64(const uint8_t *a_buf); void dap_lendian_put64(uint8_t *a_buf, uint64_t a_val); +// crossplatform usleep +#define DAP_USEC_PER_SEC 1000000 +void dap_usleep(time_t a_microseconds); + + + #ifdef __MINGW32__ int exec_silent(const char *a_cmd); #endif diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h index 79f00942eaeb5050de51017e3d9ab36b2cd165e6..b929c3a891bf169fc475dfbc52f9a1f5a604f0db 100755 --- a/dap-sdk/core/include/dap_strfuncs.h +++ b/dap-sdk/core/include/dap_strfuncs.h @@ -112,6 +112,3 @@ char *dap_itoa128(char *a_str, int128_t a_value, int a_base); char *_strndup(const char *str, unsigned long len); #endif -#define DAP_USEC_PER_SEC 1000000 -void dap_usleep(time_t a_microseconds); - diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c index 7d7f37c4738c5a4ab9111d302a62d3e03097fe0e..800425970092a112cf1d408ccb5a8b2d3a2c36e9 100755 --- a/dap-sdk/core/src/dap_common.c +++ b/dap-sdk/core/src/dap_common.c @@ -1041,3 +1041,23 @@ void dap_lendian_put64(uint8_t *a_buf, uint64_t a_val) dap_lendian_put32(a_buf, a_val); dap_lendian_put32(a_buf + 4, a_val >> 32); } + +/** + * dap_usleep: + * @a_microseconds: number of microseconds to pause + * + * Pauses the current thread for the given number of microseconds. + */ +void dap_usleep(time_t a_microseconds) +{ +#ifdef DAP_OS_WINDOWS + Sleep (a_microseconds / 1000); +#else + struct timespec l_request, l_remaining; + l_request.tv_sec = a_microseconds / DAP_USEC_PER_SEC; + l_request.tv_nsec = 1000 * (a_microseconds % DAP_USEC_PER_SEC); + while(nanosleep(&l_request, &l_remaining) == -1 && errno == EINTR) + l_request = l_remaining; +#endif +} + diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c index 2685947f96e330bdc41bb865cfac7434e6e2d326..a766b125633417400291f7f06c78a35b2ed9a02f 100755 --- a/dap-sdk/core/src/dap_strfuncs.c +++ b/dap-sdk/core/src/dap_strfuncs.c @@ -866,22 +866,3 @@ char *_strndup(const char *str, unsigned long len) { } #endif -/** - * dap_usleep: - * @a_microseconds: number of microseconds to pause - * - * Pauses the current thread for the given number of microseconds. - */ -void dap_usleep(time_t a_microseconds) -{ -#ifdef _WIN32 - Sleep (a_microseconds / 1000); -#else - struct timespec l_request, l_remaining; - l_request.tv_sec = a_microseconds / DAP_USEC_PER_SEC; - l_request.tv_nsec = 1000 * (a_microseconds % DAP_USEC_PER_SEC); - while(nanosleep(&l_request, &l_remaining) == -1 && errno == EINTR) - l_request = l_remaining; -#endif -} - diff --git a/dap-sdk/crypto/include/dap_enc_key.h b/dap-sdk/crypto/include/dap_enc_key.h index 7e2c7c6901aba7f627e26bbfc30c31098e877631..7ef187742ec71e45813da67a55d286cddee647b0 100755 --- a/dap-sdk/crypto/include/dap_enc_key.h +++ b/dap-sdk/crypto/include/dap_enc_key.h @@ -256,6 +256,7 @@ int dap_enc_key_deserealize_pub_key(dap_enc_key_t *a_key, const uint8_t *a_buf, dap_enc_key_serealize_t* dap_enc_key_serealize(dap_enc_key_t * key); dap_enc_key_t* dap_enc_key_deserealize(const void *buf, size_t buf_size); +dap_enc_key_t* dap_enc_key_dup(dap_enc_key_t * a_key); // allocate memory for key struct dap_enc_key_t *dap_enc_key_new(dap_enc_key_type_t a_key_type); diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c index 2916d19b6707d73da4597d8231f928bc3d99400e..b9bc42688635fe060bd631c36eb9c7d60f9a03d0 100755 --- a/dap-sdk/crypto/src/dap_cert.c +++ b/dap-sdk/crypto/src/dap_cert.c @@ -207,11 +207,11 @@ dap_cert_t * dap_cert_generate_mem_with_seed(const char * a_cert_name, dap_enc_k if ( l_enc_key ){ dap_cert_t * l_cert = dap_cert_new(a_cert_name); l_cert->enc_key = l_enc_key; - log_it(L_DEBUG,"Certificate generated"); + //log_it(L_DEBUG,"Certificate generated"); //dap_cert_item_t * l_cert_item = DAP_NEW_Z(dap_cert_item_t); //snprintf(l_cert_item->name,sizeof(l_cert_item->name),"%s",a_cert_name); //HASH_ADD_STR(s_certs,name,l_cert_item); - log_it(L_DEBUG,"Certificate name %s recorded", a_cert_name); + //log_it(L_DEBUG,"Certificate name %s recorded", a_cert_name); return l_cert; } else { log_it(L_ERROR,"Can't generate key in memory!"); diff --git a/dap-sdk/crypto/src/dap_cert_file.c b/dap-sdk/crypto/src/dap_cert_file.c index cad1955c2d228d65d6a7e3399cfe6f212950b8d5..7a733e50b6550763a24c1940f5c96fdba8b97c7e 100755 --- a/dap-sdk/crypto/src/dap_cert_file.c +++ b/dap-sdk/crypto/src/dap_cert_file.c @@ -238,15 +238,15 @@ uint8_t* dap_cert_mem_save(dap_cert_t * a_cert, uint32_t *a_cert_size_out) l_hdr.type = dap_cert_FILE_TYPE_PUBLIC; if ( l_priv_key_data ){ l_hdr.type = dap_cert_FILE_TYPE_PRIVATE; - log_it(L_DEBUG,"Private key size %u",l_priv_key_data_size); + //log_it(L_DEBUG,"Private key size %u",l_priv_key_data_size); } if (l_pub_key_data){ - log_it(L_DEBUG,"Public key size %u",l_pub_key_data_size); + //log_it(L_DEBUG,"Public key size %u",l_pub_key_data_size); }else{ log_it(L_ERROR,"No public or private key in certificate, nothing to save"); goto lb_exit; } - log_it(L_DEBUG,"Key private data size %u",l_key->_inheritor_size); + //log_it(L_DEBUG,"Key private data size %u",l_key->_inheritor_size); l_hdr.version = dap_cert_FILE_VERSION; l_hdr.data_size = l_pub_key_data_size; @@ -290,7 +290,7 @@ lb_exit: DAP_DELETE(l_metadata); } - log_it(L_NOTICE,"Certificate \"%s\" successfully serialized",a_cert->name); + //log_it(L_NOTICE,"Certificate \"%s\" successfully serialized",a_cert->name); if(a_cert_size_out) *a_cert_size_out = l_data_offset; @@ -378,7 +378,7 @@ dap_cert_t* dap_cert_mem_load(const void * a_data, size_t a_data_size) l_data_offset += l_hdr.metadata_size; } dap_enc_key_update(l_ret->enc_key); - log_it(L_NOTICE,"Successfully loaded certificate %s", l_ret->name); + //log_it(L_NOTICE,"Successfully loaded certificate %s", l_ret->name); }else log_it(L_ERROR,"Unrecognizable certificate version, corrupted file or you have too old software"); diff --git a/dap-sdk/crypto/src/dap_enc_base58.c b/dap-sdk/crypto/src/dap_enc_base58.c index a8538a9b97132b8758bf6d5819c6d7d8872e01d4..acbfe8fcc550e359a81542ea00ab35564fe77636 100755 --- a/dap-sdk/crypto/src/dap_enc_base58.c +++ b/dap-sdk/crypto/src/dap_enc_base58.c @@ -27,6 +27,8 @@ #include <stdint.h> #include <string.h> #include "dap_common.h" +#include "dap_strfuncs.h" +#include "dap_string.h" #include "dap_enc_base58.h" #define LOG_TAG "dap_enc_base58" @@ -225,7 +227,7 @@ char* dap_enc_base58_from_hex_str_to_str(const char *a_in_str) return NULL; // from "0x..." to binary char *l_out_str = DAP_NEW_Z_SIZE(char, a_in_hash_len / 2 + 1); - size_t len = dap_hex2bin(l_out_str, a_in_str+2, a_in_hash_len-2); + size_t len = dap_hex2bin((uint8_t*)l_out_str, a_in_str+2, a_in_hash_len-2); // from binary to base58 char *l_base58_out = dap_enc_base58_encode_to_str(l_out_str, len/2); DAP_DELETE(l_out_str); diff --git a/dap-sdk/crypto/src/dap_enc_base64.c b/dap-sdk/crypto/src/dap_enc_base64.c index b0f1351cead5ee1bb8329ec6fd6b50dbddbfa74d..b8d0c05783fca79606da4e7d5ecc6d3f86a26626 100755 --- a/dap-sdk/crypto/src/dap_enc_base64.c +++ b/dap-sdk/crypto/src/dap_enc_base64.c @@ -288,7 +288,7 @@ char * dap_enc_strdup_from_base64(const char * a_string_base64){ if(!l_string_base64_len) return NULL; - char * l_string = DAP_NEW_Z_SIZE(byte_t, l_string_base64_len * 2); + char * l_string = DAP_NEW_Z_SIZE(char, l_string_base64_len * 2); size_t l_string_len = dap_enc_base64_decode(a_string_base64, l_string_base64_len, l_string, DAP_ENC_DATA_TYPE_B64_URLSAFE); if(!l_string_len){ diff --git a/dap-sdk/crypto/src/dap_enc_iaes.c b/dap-sdk/crypto/src/dap_enc_iaes.c index 0e4df9e74a1add551155ec2a531c2b0d27f5e567..29ef751860de7e58f12962727451d8b7b8d6981f 100755 --- a/dap-sdk/crypto/src/dap_enc_iaes.c +++ b/dap-sdk/crypto/src/dap_enc_iaes.c @@ -105,8 +105,8 @@ size_t dap_enc_iaes256_cbc_decrypt_fast(struct dap_enc_key * a_key, const void * memcpy(&feedback[0], DAP_ENC_AES_KEY(a_key)->ivec, IAES_BLOCK_SIZE); memcpy(priv_key_swapped_endian, a_key->priv_key_data, sizeof(priv_key_swapped_endian)); - swap_endian(priv_key_swapped_endian, sizeof(priv_key_swapped_endian)/sizeof(uint32_t)); - Key_Shedule_for_decrypT(priv_key_swapped_endian, round_decrypt_key); + swap_endian((uint32_t*)priv_key_swapped_endian, sizeof(priv_key_swapped_endian)/sizeof(uint32_t)); + Key_Shedule_for_decrypT((uint32_t*)priv_key_swapped_endian, round_decrypt_key); void *data = buf_out; const void *cdata = a_in; diff --git a/dap-sdk/crypto/src/dap_enc_key.c b/dap-sdk/crypto/src/dap_enc_key.c index 24e38aedf9968d1da58de509f444d66532d337f0..95b9c89200f6f94124a1657e9cc882b54fd6bebf 100755 --- a/dap-sdk/crypto/src/dap_enc_key.c +++ b/dap-sdk/crypto/src/dap_enc_key.c @@ -632,6 +632,28 @@ dap_enc_key_serealize_t* dap_enc_key_serealize(dap_enc_key_t * key) return result; } +/** + * @brief dap_enc_key_dup + * @param a_key + * @return + */ +dap_enc_key_t* dap_enc_key_dup(dap_enc_key_t * a_key) +{ + dap_enc_key_t * l_ret = DAP_NEW_S_SIZE(dap_enc_key_t,sizeof(*l_ret) ); + memcpy(l_ret,a_key,sizeof (*a_key)); + + l_ret->priv_key_data = DAP_NEW_Z_SIZE(byte_t, l_ret->priv_key_data_size); + memcpy(l_ret->priv_key_data, a_key->priv_key_data, a_key->priv_key_data_size); + l_ret->pub_key_data = DAP_NEW_Z_SIZE(byte_t, a_key->pub_key_data_size); + memcpy(l_ret->pub_key_data, a_key->pub_key_data, a_key->pub_key_data_size); + if(a_key->_inheritor_size) { + l_ret->_inheritor = DAP_NEW_Z_SIZE(byte_t, a_key->_inheritor_size ); + memcpy(l_ret->_inheritor, a_key->_inheritor, a_key->_inheritor_size); + } + + return l_ret; +} + /** * @brief dap_enc_key_deserealize * @param buf @@ -652,13 +674,13 @@ dap_enc_key_t* dap_enc_key_deserealize(const void *buf, size_t buf_size) result->_inheritor_size = in_key->inheritor_size; DAP_DEL_Z(result->priv_key_data) DAP_DEL_Z(result->pub_key_data) - result->priv_key_data = DAP_NEW_Z_SIZE(uint8_t, result->priv_key_data_size); + result->priv_key_data = DAP_NEW_Z_SIZE(byte_t, result->priv_key_data_size); memcpy(result->priv_key_data, in_key->priv_key_data, result->priv_key_data_size); - result->pub_key_data = DAP_NEW_Z_SIZE(uint8_t, result->pub_key_data_size); + result->pub_key_data = DAP_NEW_Z_SIZE(byte_t, result->pub_key_data_size); memcpy(result->pub_key_data, in_key->pub_key_data, result->pub_key_data_size); if(in_key->inheritor_size) { DAP_DEL_Z(result->_inheritor) - result->_inheritor = DAP_NEW_Z(dap_enc_key_t); + result->_inheritor = DAP_NEW_Z_SIZE(byte_t, in_key->inheritor_size ); memcpy(result->_inheritor, in_key->inheritor, in_key->inheritor_size); } else { result->_inheritor = NULL; diff --git a/dap-sdk/crypto/src/iaes/iaes256_cbc_cernal.c b/dap-sdk/crypto/src/iaes/iaes256_cbc_cernal.c index 9052a2c996371a2fa153aab5139ad5e8e61a932a..2a1b55cf02f3cb56f38a524ff7b046db38e59d4c 100755 --- a/dap-sdk/crypto/src/iaes/iaes256_cbc_cernal.c +++ b/dap-sdk/crypto/src/iaes/iaes256_cbc_cernal.c @@ -23,6 +23,12 @@ void swap_endian(uint32_t *buff, unsigned long len) void AES256_enc_cernelT(uint32_t * in, uint32_t * out, uint32_t * masterkey) { //first round includes replacement of byte order + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; + uint32_t k0, k1, k2, k3; + uint32_t k4, k5, k6, k7; + uint32_t temp; + /*r1*/ s0 = ((in[0] & 0xff) << 24) ^ ((in[0] >> 8) & 0xff) << 16 ^ ((in[0] >> 16) & 0xff) << 8 ^ (in[0] >> 24) ^ masterkey[0]; s1 = ((in[1] & 0xff) << 24) ^ ((in[1] >> 8) & 0xff) << 16 ^ ((in[1] >> 16) & 0xff) << 8 ^ (in[1] >> 24) ^ masterkey[1]; s2 = ((in[2] & 0xff) << 24) ^ ((in[2] >> 8) & 0xff) << 16 ^ ((in[2] >> 16) & 0xff) << 8 ^ (in[2] >> 24) ^ masterkey[2]; @@ -372,6 +378,8 @@ void Key_Shedule_for_decrypT(uint32_t * key, uint32_t * rounds_keys) void AES256_dec_cernelT(uint32_t * in, uint32_t * out, uint32_t * decr_key) {/*r1-xor*/ + uint32_t t0, t1, t2, t3; + uint32_t s0, s1, s2, s3; //first round includes replacement of byte order s0 = ((in[0] & 0xff) << 24) ^ ((in[0] >> 8) & 0xff) << 16 ^ ((in[0] >> 16) & 0xff) << 8 ^ (in[0] >> 24) ^ decr_key[0]; s1 = ((in[1] & 0xff) << 24) ^ ((in[1] >> 8) & 0xff) << 16 ^ ((in[1] >> 16) & 0xff) << 8 ^ (in[1] >> 24) ^ decr_key[1]; diff --git a/dap-sdk/crypto/src/iaes/iaes_tables.h b/dap-sdk/crypto/src/iaes/iaes_tables.h index c13c59b42d8fa534df18eabc0330fced076d7a55..3fa43b052281c7b06fc84f67cfecafb9868cd5e5 100755 --- a/dap-sdk/crypto/src/iaes/iaes_tables.h +++ b/dap-sdk/crypto/src/iaes/iaes_tables.h @@ -690,12 +690,5 @@ uint32_t rcon[] = 0xab000000, 0x4d000000, 0x9a000000, 0x2f000000 }; -//define AES_VAR -uint32_t k0, k1, k2, k3; -uint32_t k4, k5, k6, k7; -uint32_t temp; -uint32_t t0, t1, t2, t3; -uint32_t s0, s1, s2, s3; - #endif // TABLES_H diff --git a/dap-sdk/net/client/CMakeLists.txt b/dap-sdk/net/client/CMakeLists.txt index 82df978c4995d6b69d1640134cbebe8d2383c941..00f855bceb52d93e73d327260e24cf0b43ee6ac6 100644 --- a/dap-sdk/net/client/CMakeLists.txt +++ b/dap-sdk/net/client/CMakeLists.txt @@ -15,7 +15,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CLIENT_HEADERS} ${DAP_CLIENT_SOURCES}) target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_server_core dap_udp_server dap_http_server dap_enc_server dap_stream dap_session dap_stream_ch json-c) if(UNIX AND NOT ANDROID) - target_link_libraries(${PROJECT_NAME} ev) + target_link_libraries(${PROJECT_NAME} rt) endif() diff --git a/dap-sdk/net/client/dap_client.c b/dap-sdk/net/client/dap_client.c index b799fe8080941db2ce65225fc546f9a3312f6650..d977b219ddadbed22628cee1e67eeeb78bdbe1bb 100644 --- a/dap-sdk/net/client/dap_client.c +++ b/dap-sdk/net/client/dap_client.c @@ -443,6 +443,18 @@ dap_stream_t * dap_client_get_stream(dap_client_t * a_client) return (l_client_internal) ? l_client_internal->stream : NULL; } +/** + * @brief dap_client_get_stream_worker + * @param a_client + * @return + */ +dap_stream_worker_t * dap_client_get_stream_worker(dap_client_t * a_client) +{ + dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client); + return (l_client_internal) ? l_client_internal->stream_worker : NULL; + +} + dap_stream_ch_t * dap_client_get_stream_ch(dap_client_t * a_client, uint8_t a_ch_id) { dap_stream_ch_t * l_ch = NULL; diff --git a/dap-sdk/net/client/dap_client_http.c b/dap-sdk/net/client/dap_client_http.c index baeef39724cd923730739a3ff4fdf08422206be1..79ca6f4484c0ac269259a660ef45e9956eb04f3d 100644 --- a/dap-sdk/net/client/dap_client_http.c +++ b/dap-sdk/net/client/dap_client_http.c @@ -128,7 +128,7 @@ static void s_http_read(dap_events_socket_t * a_es, void * arg) return; } // read data - l_client_http_internal->response_size += dap_events_socket_read(a_es, + l_client_http_internal->response_size += dap_events_socket_pop_from_buf_in(a_es, l_client_http_internal->response + l_client_http_internal->response_size, l_client_http_internal->response_size_max - l_client_http_internal->response_size); @@ -208,7 +208,7 @@ static void s_http_read(dap_events_socket_t * a_es, void * arg) } else { // close connection - dap_events_socket_kill_socket(a_es); + a_es->kill_signal=true; //dap_events_socket_remove_and_delete(a_es, true); //dap_events_socket_delete(a_es, true); } } @@ -219,7 +219,7 @@ static void s_http_read(dap_events_socket_t * a_es, void * arg) * @param a_es * @param arg */ -static void s_http_error(dap_events_socket_t * a_es, void * arg) +static void s_http_error(dap_events_socket_t * a_es, int arg) { log_it(L_INFO, "http client error"); dap_client_http_internal_t * l_client_http_internal = DAP_CLIENT_HTTP(a_es); @@ -228,10 +228,10 @@ static void s_http_error(dap_events_socket_t * a_es, void * arg) return; } if(l_client_http_internal->error_callback) - l_client_http_internal->error_callback((int)arg, l_client_http_internal->obj); + l_client_http_internal->error_callback(arg, l_client_http_internal->obj); // close connection - dap_events_socket_kill_socket(a_es); + a_es->kill_signal = true; //dap_events_socket_remove_and_delete(a_es, true); //dap_events_thread_wake_up( &a_es->events->proc_thread); //dap_events_socket_delete(a_es, false); @@ -354,7 +354,7 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin setsockopt(l_socket, SOL_SOCKET, SO_SNDBUF, (void*) &buffsize, sizeof(buffsize)); setsockopt(l_socket, SOL_SOCKET, SO_RCVBUF, (void*) &buffsize, sizeof(buffsize)); #endif - dap_events_socket_t *l_ev_socket = dap_events_socket_wrap_no_add(NULL, l_socket, &l_s_callbacks); + dap_events_socket_t *l_ev_socket = dap_events_socket_wrap_no_add(dap_events_get_default(), l_socket, &l_s_callbacks); // create private struct dap_client_http_internal_t *l_client_http_internal = DAP_NEW_Z(dap_client_http_internal_t); @@ -372,7 +372,8 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin if(!l_remote_addr.sin_addr.s_addr) { if(resolve_host(a_uplink_addr, AF_INET, (struct sockaddr*) &l_remote_addr.sin_addr) < 0) { log_it(L_ERROR, "Wrong remote address '%s:%u'", a_uplink_addr, a_uplink_port); - dap_events_socket_kill_socket(l_ev_socket); + DAP_DELETE(l_ev_socket); + close(l_socket); return NULL; } } @@ -380,20 +381,18 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin l_remote_addr.sin_family = AF_INET; l_remote_addr.sin_port = htons(a_uplink_port); int l_err = 0; + dap_worker_t *l_worker = NULL; if((l_err = connect(l_socket, (struct sockaddr *) &l_remote_addr, sizeof(struct sockaddr_in))) != -1) { //s_set_sock_nonblock(a_client_pvt->stream_socket, false); log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", a_uplink_addr, a_uplink_port, l_socket); // add to dap_worker - dap_events_socket_create_after(l_ev_socket); + l_worker = dap_worker_add_events_socket_auto(l_ev_socket); } else { log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d err: %s", a_uplink_addr, a_uplink_port, l_socket, strerror(errno)); - //l_ev_socket->no_close = false; - dap_events_socket_kill_socket(l_ev_socket); - //shutdown(l_ev_socket->socket, SHUT_RDWR); - //dap_events_socket_remove_and_delete(l_ev_socket, true); - //l_ev_socket->socket = 0; + DAP_DELETE(l_ev_socket); + close(l_socket); return NULL ; } @@ -441,16 +440,14 @@ void* dap_client_http_request_custom(const char *a_uplink_addr, uint16_t a_uplin } // send header - dap_events_socket_write_f(l_ev_socket, "%s /%s%s HTTP/1.1\r\n" + dap_events_socket_write_f_mt(l_worker, l_ev_socket, "%s /%s%s HTTP/1.1\r\n" "Host: %s\r\n" "%s" "\r\n", a_method, a_path, l_get_str ? l_get_str : "", a_uplink_addr, l_request_headers->str); // send data for POST request if(!l_get_str) - dap_events_socket_write(l_ev_socket, a_request, a_request_size); - dap_events_socket_set_writable(l_ev_socket, true); - + dap_events_socket_write_mt(l_worker, l_ev_socket, a_request, a_request_size); DAP_DELETE(l_get_str); dap_string_free(l_request_headers, true); return l_client_http_internal; diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c index 56e006a5118cf9c7cfd572aac1fcc2affff89f3b..59a52c01f98d95256170fcc41b950340ddafb383 100644 --- a/dap-sdk/net/client/dap_client_pvt.c +++ b/dap-sdk/net/client/dap_client_pvt.c @@ -64,6 +64,7 @@ #include "dap_client_pvt.h" #include "dap_server.h" #include "dap_stream.h" +#include "dap_stream_worker.h" #include "dap_stream_ch.h" #include "dap_stream_ch_proc.h" #include "dap_stream_ch_pkt.h" @@ -98,7 +99,7 @@ void m_request_error(int, void *); void m_es_stream_delete(dap_events_socket_t * a_es, void * arg); void m_es_stream_read(dap_events_socket_t * a_es, void * arg); void m_es_stream_write(dap_events_socket_t * a_es, void * arg); -void m_es_stream_error(dap_events_socket_t * a_es, void * arg); +void m_es_stream_error(dap_events_socket_t * a_es, int a_arg); /** * @brief dap_client_internal_init @@ -125,6 +126,7 @@ void dap_client_pvt_new(dap_client_pvt_t * a_client_internal) a_client_internal->stage = STAGE_BEGIN; // start point of state machine a_client_internal->stage_status = STAGE_STATUS_DONE; a_client_internal->uplink_protocol_version = DAP_PROTOCOL_VERSION; + a_client_internal->events = dap_events_get_default(); // add to list dap_client_pvt_hh_add(a_client_internal); } @@ -277,16 +279,14 @@ int dap_client_pvt_disconnect(dap_client_pvt_t *a_client_pvt) // l_client_internal->stream_es->signal_close = true; // start stopping connection - if(a_client_pvt->stream_es && !dap_events_socket_kill_socket(a_client_pvt->stream_es)) { + if(a_client_pvt->stream_es ) { + dap_events_socket_remove_and_delete_mt(a_client_pvt->stream_es->worker, a_client_pvt->stream_es); int l_counter = 0; // wait for stop of connection (max 0.7 sec.) while(a_client_pvt->stream_es && l_counter < 70) { dap_usleep(DAP_USEC_PER_SEC / 100); l_counter++; } - if(l_counter >= 70) { - dap_events_socket_remove_and_delete(a_client_pvt->stream_es, true); - } } // if (l_client_internal->stream_socket ) { // close (l_client_internal->stream_socket); @@ -338,7 +338,7 @@ static void dap_client_pvt_delete_in(dap_client_pvt_t * a_client_pvt) dap_enc_key_delete(a_client_pvt->stream_key); //a_client_pvt->client = NULL; - DAP_DELETE(a_client_pvt); + // DAP_DELETE(a_client_pvt); } /* @@ -479,16 +479,22 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt) }; a_client_pvt->stream_es = dap_events_socket_wrap_no_add(a_client_pvt->events, a_client_pvt->stream_socket, &l_s_callbacks); + dap_worker_t * l_worker = dap_events_worker_get_auto(); + assert(l_worker); + assert(l_worker->_inheritor); + a_client_pvt->stream_worker = DAP_STREAM_WORKER(l_worker); // add to dap_worker - dap_events_socket_create_after(a_client_pvt->stream_es); + dap_events_socket_assign_on_worker_mt(a_client_pvt->stream_es, l_worker); a_client_pvt->stream_es->_inheritor = a_client_pvt;//->client; - a_client_pvt->stream = dap_stream_new_es(a_client_pvt->stream_es); + a_client_pvt->stream = dap_stream_new_es_client(a_client_pvt->stream_es); a_client_pvt->stream->is_client_to_uplink = true; a_client_pvt->stream->session = dap_stream_session_pure_new(); // may be from in packet? // new added, whether it is necessary? a_client_pvt->stream->session->key = a_client_pvt->stream_key; + a_client_pvt->stream->stream_worker = a_client_pvt->stream_worker; + // connect struct sockaddr_in l_remote_addr; @@ -498,7 +504,7 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt) if(inet_pton(AF_INET, a_client_pvt->uplink_addr, &(l_remote_addr.sin_addr)) < 0) { log_it(L_ERROR, "Wrong remote address '%s:%u'", a_client_pvt->uplink_addr, a_client_pvt->uplink_port); //close(a_client_pvt->stream_socket); - dap_events_socket_kill_socket(a_client_pvt->stream_es); + dap_events_socket_remove_and_delete_mt(a_client_pvt->stream_es->worker, a_client_pvt->stream_es); //a_client_pvt->stream_socket = 0; a_client_pvt->stage_status = STAGE_STATUS_ERROR; } @@ -508,14 +514,14 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt) sizeof(struct sockaddr_in))) != -1) { a_client_pvt->stream_es->flags &= ~DAP_SOCK_SIGNAL_CLOSE; //s_set_sock_nonblock(a_client_pvt->stream_socket, false); - log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", a_client_pvt->uplink_addr, - a_client_pvt->uplink_port, a_client_pvt->stream_socket); + log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d (assign on worker #%u)", a_client_pvt->uplink_addr, + a_client_pvt->uplink_port, a_client_pvt->stream_socket, l_worker->id); a_client_pvt->stage_status = STAGE_STATUS_DONE; } else { log_it(L_ERROR, "Remote address can't connected (%s:%u) with sock_id %d", a_client_pvt->uplink_addr, a_client_pvt->uplink_port); - dap_events_socket_kill_socket(a_client_pvt->stream_es); + dap_events_socket_remove_and_delete_mt(a_client_pvt->stream_es->worker, a_client_pvt->stream_es); //close(a_client_pvt->stream_socket); a_client_pvt->stream_socket = 0; a_client_pvt->stage_status = STAGE_STATUS_ERROR; @@ -546,7 +552,7 @@ static void s_stage_status_after(dap_client_pvt_t * a_client_pvt) const char *l_add_str = ""; - dap_events_socket_write_f( a_client_pvt->stream_es, "GET /%s HTTP/1.1\r\n" + dap_events_socket_write_f_mt(a_client_pvt->stream_worker->worker, a_client_pvt->stream_es, "GET /%s HTTP/1.1\r\n" "Host: %s:%d%s\r\n" "\r\n", l_full_path, a_client_pvt->uplink_addr, a_client_pvt->uplink_port, l_add_str); @@ -1289,30 +1295,30 @@ void m_es_stream_write(dap_events_socket_t * a_es, void * arg) return; } switch (l_client_pvt->stage) { - case STAGE_STREAM_STREAMING: { - size_t i; - bool ready_to_write = false; - // log_it(DEBUG,"Process channels data output (%u channels)",STREAM(sh)->channel_count); - - for(i = 0; i < l_client_pvt->stream->channel_count; i++) { - dap_stream_ch_t * ch = l_client_pvt->stream->channel[i]; - if(ch->ready_to_write) { - ch->proc->packet_out_callback(ch, NULL); - ready_to_write |= ch->ready_to_write; + case STAGE_STREAM_STREAMING: { + size_t i; + bool ready_to_write = false; + // log_it(DEBUG,"Process channels data output (%u channels)",STREAM(sh)->channel_count); + + for(i = 0; i < l_client_pvt->stream->channel_count; i++) { + dap_stream_ch_t * ch = l_client_pvt->stream->channel[i]; + if(ch->ready_to_write) { + ch->proc->packet_out_callback(ch, NULL); + ready_to_write |= ch->ready_to_write; + } } - } - //log_it(L_DEBUG,"stream_data_out (ready_to_write=%s)", ready_to_write?"true":"false"); + //log_it(L_DEBUG,"stream_data_out (ready_to_write=%s)", ready_to_write?"true":"false"); - dap_events_socket_set_writable(l_client_pvt->stream_es, ready_to_write); - //log_it(ERROR,"No stream_data_write_callback is defined"); - } - break; - default: { - } + dap_events_socket_set_writable_unsafe(l_client_pvt->stream_es, ready_to_write); + //log_it(ERROR,"No stream_data_write_callback is defined"); + } + break; + default: { + } } } -void m_es_stream_error(dap_events_socket_t * a_es, void * arg) +void m_es_stream_error(dap_events_socket_t * a_es, int a_arg) { //dap_client_t * l_client = DAP_CLIENT(a_es); //dap_client_pvt_t * l_client_pvt = (l_client) ? DAP_CLIENT_PVT(l_client) : NULL; @@ -1321,6 +1327,6 @@ void m_es_stream_error(dap_events_socket_t * a_es, void * arg) log_it(L_ERROR, "m_es_stream_error: l_client_pvt is NULL!"); return; } - log_it(L_INFO, "m_es_stream_error"); + log_it(L_INFO, "m_es_stream_error: code %d", a_arg); } diff --git a/dap-sdk/net/client/include/dap_client.h b/dap-sdk/net/client/include/dap_client.h index dc49c63796fc313f5084043988a51f75231ba117..ff2ec55fda9f9da9f5c6bb2226d49bf4b915af18 100644 --- a/dap-sdk/net/client/include/dap_client.h +++ b/dap-sdk/net/client/include/dap_client.h @@ -131,6 +131,7 @@ const char * dap_client_get_error_str(dap_client_t * a_client); const char * dap_client_get_auth_cookie(dap_client_t * a_client); dap_stream_t * dap_client_get_stream(dap_client_t * a_client); +dap_stream_worker_t * dap_client_get_stream_worker(dap_client_t * a_client); dap_stream_ch_t * dap_client_get_stream_ch(dap_client_t * a_client, uint8_t a_ch_id); const char * dap_client_get_stream_id(dap_client_t * a_client); void dap_client_set_active_channels (dap_client_t * a_client, const char * a_active_channels); diff --git a/dap-sdk/net/client/include/dap_client_http.h b/dap-sdk/net/client/include/dap_client_http.h index ebf0df092b03f074debaa5d35b05249998485cb8..ec17cdbae2c758b2f40896b1ab2b0ac2517ea314 100644 --- a/dap-sdk/net/client/include/dap_client_http.h +++ b/dap-sdk/net/client/include/dap_client_http.h @@ -22,7 +22,7 @@ #pragma once #include <stdint.h> - +#include <stddef.h> #ifdef __cplusplus extern "C" { #endif diff --git a/dap-sdk/net/client/include/dap_client_pvt.h b/dap-sdk/net/client/include/dap_client_pvt.h index 5bb82ed0c274ed7b93bea1ce0caefbbce40e47e5..6966a2cf5f3bef2125ef8189d035df71dccbf556 100644 --- a/dap-sdk/net/client/include/dap_client_pvt.h +++ b/dap-sdk/net/client/include/dap_client_pvt.h @@ -42,6 +42,7 @@ typedef struct dap_client_internal dap_events_socket_t * stream_es; int stream_socket; dap_stream_t* stream; + dap_stream_worker_t* stream_worker; dap_events_t * events; dap_enc_key_t * session_key_open; // Open assymetric keys exchange diff --git a/dap-sdk/net/core/dap_client_remote.c b/dap-sdk/net/core/dap_client_remote.c deleted file mode 100644 index 567ef6954111c59af407bca8e043c158dddbd74d..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/dap_client_remote.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#ifndef _WIN32 -#include <unistd.h> -#include <arpa/inet.h> -#include <sys/epoll.h> -#include <sys/timerfd.h> -#else -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include <pthread.h> -#endif - -#include "dap_common.h" -#include "dap_server.h" -#include "dap_client_remote.h" - -#define LOG_TAG "dap_client_remote" - -/** - * @brief dap_client_init Init clients module - * @return Zero if ok others if no - */ -int dap_client_remote_init( ) -{ - log_it( L_NOTICE, "Initialized socket client module" ); - - return 0; -} - -/** - * @brief dap_client_deinit Deinit clients module - */ -void dap_client_remote_deinit( ) -{ - - return; -} - -/** - * @brief _save_ip_and_port - * @param cl - */ -void _save_ip_and_port( dap_client_remote_t * cl ) -{ - struct sockaddr_in ip_adr_get; - socklen_t ip_adr_len = sizeof(ip_adr_get); - - int l_res = getpeername( cl->socket, (struct sockaddr * restrict)&ip_adr_get, &ip_adr_len ); - if(l_res == -1) - log_it(L_ERROR, "%s error: %s", __PRETTY_FUNCTION__, strerror(errno)); - - cl->port = ntohs( ip_adr_get.sin_port ); - strcpy( cl->s_ip, inet_ntoa(ip_adr_get.sin_addr) ); -} - -/** - * @brief dap_client_remote_create Create new client and add it to the list - * @param sh Server instance - * @param s Client's socket - * @return Pointer to the new list's node - */ -dap_client_remote_t *dap_client_remote_create( dap_server_t *sh, int s, dap_server_thread_t *t ) -{ - dap_client_remote_t *dsc = DAP_NEW_Z( dap_client_remote_t ); - - dap_random_string_fill( dsc->id, CLIENT_ID_SIZE ); - - dsc->socket = s; - dsc->server = sh; - dsc->tn = t->thread_num; - dsc->thread = t; - dsc->efd = t->epoll_fd; - dsc->time_connection = dsc->last_time_active = time( NULL) ; - - dsc->pevent.events = EPOLLIN | EPOLLOUT | EPOLLERR; - dsc->pevent.data.ptr = dsc; - - dsc->flags = DAP_SOCK_READY_TO_READ; - dsc->buf_out_offset = 0; - - _save_ip_and_port( dsc ); - - pthread_mutex_lock( &t->mutex_on_hash ); - HASH_ADD_INT( t->hclients, socket, dsc ); - pthread_mutex_unlock( &t->mutex_on_hash ); - - if ( sh->client_new_callback ) - sh->client_new_callback( dsc, NULL ); // Init internal structure - - log_it(L_DEBUG, "Create remote client: ip: %s port %d", dsc->s_ip, dsc->port ); - - //log_it(L_DEBUG, "Create new client. ID: %s", dsc->id); - return dsc; -} - -/** - * @brief safe_client_remove Removes the client from the list - * @param sc Client instance - */ -void dap_client_remote_remove( dap_client_remote_t *sc ) -{ - log_it(L_DEBUG, "dap_client_remote_remove [THREAD %u] efd %u", sc->tn , sc->efd ); - - dap_server_thread_t *t = sc->thread; - - pthread_mutex_lock( &t->mutex_on_hash ); - HASH_DEL( t->hclients, sc ); - pthread_mutex_unlock( &t->mutex_on_hash ); - - if( sc->server->client_delete_callback ) { - sc->server->client_delete_callback( sc, NULL ); // Init internal structure - } - - if( sc->_inheritor ) { - free( sc->_inheritor ); - } - - if( sc->socket ) { - log_it( L_INFO, "dap_client_remote_remove close( %d );", sc->socket ); -#ifdef _WIN32 - closesocket( sc->socket ); -#else - close( sc->socket ); -#endif - } - - free( sc ); -} - -/** - * @brief dap_server_client_find - * @param sock - * @param sh - * @return - */ -dap_client_remote_t *dap_client_remote_find( int sock, dap_server_thread_t *t ) -{ - dap_client_remote_t *ret = NULL; - - pthread_mutex_lock( &t->mutex_on_hash ); - HASH_FIND_INT( t->hclients, &sock, ret ); - pthread_mutex_unlock( &t->mutex_on_hash ); - - return ret; -} - -/** - * @brief dap_client_remote_ready_to_read - * @param sc - * @param isReady - */ -void dap_client_remote_ready_to_read( dap_client_remote_t *sc, bool is_ready ) -{ - if( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_READ) ) - return; - -// log_it( L_ERROR, "remote_ready_to_read() %u efd %X", sc->socket, sc->efd ); - - if ( is_ready ) - sc->flags |= DAP_SOCK_READY_TO_READ; - else - sc->flags ^= DAP_SOCK_READY_TO_READ; - - int events = EPOLLERR; - - if( sc->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; - - if( sc->flags & DAP_SOCK_READY_TO_WRITE ) - events |= EPOLLOUT; - - sc->pevent.events = events; - - if( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->socket, &sc->pevent) != 0 ) - log_it( L_ERROR, "epoll_ctl failed 000" ); -} - -/** - * @brief dap_client_remote_ready_to_write - * @param sc - * @param isReady - */ -void dap_client_remote_ready_to_write( dap_client_remote_t *sc, bool is_ready ) -{ - if ( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_WRITE) ) - return; - -// log_it( L_ERROR, "remote_ready_to_write() %u efd %X", sc->socket, sc->efd ); - - if ( is_ready ) - sc->flags |= DAP_SOCK_READY_TO_WRITE; - else - sc->flags ^= DAP_SOCK_READY_TO_WRITE; - - int events = EPOLLERR; - - if( sc->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; - - if( sc->flags & DAP_SOCK_READY_TO_WRITE ) - events |= EPOLLOUT; - - sc->pevent.events = events; - - if( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->socket, &sc->pevent) != 0 ) - log_it( L_ERROR, "epoll_ctl failed 001" ); -} - -/** - * @brief dap_client_write Write data to the client - * @param sc Client instance - * @param data Pointer to data - * @param data_size Size of data to write - * @return Number of bytes that were placed into the buffer - */ -size_t dap_client_remote_write( dap_client_remote_t *sc, const void * data, size_t data_size ) -{ - if ( sc->buf_out_size + data_size > sizeof(sc->buf_out) ) { - log_it( L_WARNING, "Client buffer overflow. Packet loosed" ); - return 0; - } - - memcpy( sc->buf_out + sc->buf_out_size, data, data_size ); - sc->buf_out_size += data_size; - return data_size; -} - -/** - * @brief dap_client_write_f Write formatted text to the client - * @param a_client Client instance - * @param a_format Format - * @return Number of bytes that were placed into the buffer - */ -size_t dap_client_remote_write_f( dap_client_remote_t *a_client, const char * a_format, ... ) -{ - size_t max_data_size = sizeof( a_client->buf_out ) - a_client->buf_out_size; - - va_list ap; - va_start( ap, a_format ); - - int ret = dap_vsnprintf( a_client->buf_out + a_client->buf_out_size, max_data_size, a_format, ap ); - - va_end( ap ); - - if( ret > 0 ) { - a_client->buf_out_size += (unsigned long)ret; - return (size_t)ret; - } - else { - log_it( L_ERROR, "Can't write out formatted data '%s'", a_format ); - return 0; - } -} - -/** - * @brief dap_client_read Read data from input buffer - * @param a_client Client instasnce - * @param a_data Pointer to memory where to store the data - * @param a_data_size Size of data to read - * @return Actual bytes number that were read - */ -size_t dap_client_remote_read( dap_client_remote_t *a_client, void *a_data, size_t a_data_size ) -{ - if ( a_data_size < a_client->buf_in_size ) { - - memcpy( a_data, a_client->buf_in, a_data_size ); - memmove( a_client->buf_in, a_client->buf_in + a_data_size, a_client->buf_in_size - a_data_size ); - } - else { - if ( a_data_size > a_client->buf_in_size ) { - a_data_size = a_client->buf_in_size; - } - memcpy( a_data, a_client->buf_in, a_data_size ); - } - - a_client->buf_in_size -= a_data_size; - - return a_data_size; -} - - -/** - * @brief dap_client_remote_shrink_client_buf_in Shrink input buffer (shift it left) - * @param a_client Client instance - * @param a_shrink_size Size on wich we shrink the buffer with shifting it left - */ -void dap_client_remote_shrink_buf_in( dap_client_remote_t *a_client, size_t a_shrink_size ) -{ -#if 0 - if((a_shrink_size==0)||(a_client->buf_in_size==0) ){ - return; - }else if(a_client->buf_in_size>a_shrink_size){ - size_t buf_size=a_client->buf_in_size-a_shrink_size; - void * buf = malloc(buf_size); - memcpy(buf,a_client->buf_in+ a_shrink_size,buf_size ); - memcpy(a_client->buf_in,buf,buf_size); - a_client->buf_in_size=buf_size; - free(buf); - }else { - a_client->buf_in_size=0; - } -#endif - - if ( a_shrink_size == 0 || a_client->buf_in_size == 0 ) - return; - - if ( a_client->buf_in_size > a_shrink_size ) { - - size_t buf_size = a_client->buf_in_size - a_shrink_size; - memmove( a_client->buf_in, a_client->buf_in + a_shrink_size, buf_size ); -/** - void *buf = malloc( buf_size ); - memcpy( buf, a_client->buf_in + a_shrink_size, buf_size ); - memcpy( a_client->buf_in, buf, buf_size ); - // holy shit - a_client->buf_in_size = buf_size; - free( buf ); -**/ - a_client->buf_in_size = buf_size; - } - else { - a_client->buf_in_size = 0; - } -} diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/net/core/dap_events.c index 0228f5b783da4bde285bc17092b98a73ea78e856..fd786c671c1b1831f49cb734c6239ffa6f35185e 100644 --- a/dap-sdk/net/core/dap_events.c +++ b/dap-sdk/net/core/dap_events.c @@ -31,29 +31,32 @@ #include <stddef.h> #include <stdint.h> -#ifndef _WIN32 +#ifdef DAP_OS_UNIX #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> - -#include <sys/epoll.h> +#endif #include <netdb.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> +#include <sched.h> -#if 1 +#ifdef DAP_OS_LINUX #include <sys/timerfd.h> -#elif defined(DAP_OS_ANDROID) +#endif + +#if defined(DAP_OS_ANDROID) #define NO_POSIX_SHED #define NO_TIMER +#else #endif -#else +#ifdef DAP_OS_WINDOWS #include <winsock2.h> #include <windows.h> #include <mswsock.h> @@ -63,35 +66,23 @@ #endif #include <utlist.h> -#include <sched.h> #include "dap_common.h" #include "dap_strfuncs.h" #include "dap_server.h" #include "dap_events.h" +#include "dap_events_socket.h" +#include "dap_proc_thread.h" -#define DAP_MAX_EPOLL_EVENTS 8192 - -//typedef struct open_connection_info_s { -// dap_events_socket_t *es; -// struct open_connection_info *prev; -// struct open_connection_info *next; -//} dap_events_socket_info_t; - -//dap_events_socket_info_t **s_dap_events_sockets; +#define LOG_TAG "dap_events" +static bool s_workers_init = false; static uint32_t s_threads_count = 1; -static size_t s_connection_timeout = 6000; -static struct epoll_event *g_epoll_events = NULL; -static volatile bool bEventsAreActive = true; +static dap_worker_t **s_workers = NULL; +static dap_thread_t *s_threads = NULL; +static dap_events_t * s_events_default = NULL; -bool s_workers_init = false; -dap_worker_t *s_workers = NULL; -dap_thread_t *s_threads = NULL; - -#define LOG_TAG "dap_events" - -uint32_t s_get_cpu_count( ) +uint32_t dap_get_cpu_count( ) { #ifdef _WIN32 SYSTEM_INFO si; @@ -116,44 +107,78 @@ uint32_t s_get_cpu_count( ) #endif } +void dap_cpu_assign_thread_on(uint32_t a_cpu_id) +{ +#ifndef _WIN32 +#ifndef NO_POSIX_SHED + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(a_cpu_id, &mask); + + int l_retcode; +#ifndef __ANDROID__ + l_retcode = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask); +#else + err = sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &mask); +#endif + if(l_retcode != 0) + { + char l_errbuf[128]={0}; + switch (l_retcode) { + case EFAULT: strncpy(l_errbuf,"A supplied memory address was invalid.",sizeof (l_errbuf)-1); break; + case EINVAL: strncpy(l_errbuf,"The affinity bit mask mask contains no processors that are currently physically on the system and permitted to the thread",sizeof (l_errbuf)-1); break; + case ESRCH: strncpy(l_errbuf,"No thread with the ID thread could be found",sizeof (l_errbuf)-1); break; + default: strncpy(l_errbuf,"Unknown error",sizeof (l_errbuf)-1); + } + log_it(L_CRITICAL, "Worker #%u: error pthread_setaffinity_np(): %s (%d)", l_errbuf , l_retcode); + abort(); + } +#endif +#else + + if ( !SetThreadAffinityMask( GetCurrentThread(), (DWORD_PTR)(1 << a_cpu_id) ) ) { + log_it( L_CRITICAL, "Error pthread_setaffinity_np() You really have %d or more core in CPU?", a_cpu_id ); + abort(); + } +#endif + +} + /** * @brief sa_server_init Init server module * @arg a_threads_count number of events processor workers in parallel threads * @return Zero if ok others if no */ -int32_t dap_events_init( uint32_t a_threads_count, size_t conn_timeout ) +int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout ) { - s_threads_count = a_threads_count ? a_threads_count : s_get_cpu_count( ); - - if ( conn_timeout ) - s_connection_timeout = conn_timeout; - - s_workers = (dap_worker_t *) calloc( 1, sizeof(dap_worker_t) * s_threads_count ); - s_threads = (dap_thread_t *) calloc( 1, sizeof(dap_thread_t) * s_threads_count ); - if ( !s_workers || !s_threads ) - goto err; + s_threads_count = a_threads_count ? a_threads_count : dap_get_cpu_count( ); - g_epoll_events = (struct epoll_event *)malloc( sizeof(struct epoll_event) * DAP_MAX_EPOLL_EVENTS * s_threads_count ); - if ( !g_epoll_events ) - goto err; + s_workers = DAP_NEW_Z_SIZE(dap_worker_t*,s_threads_count*sizeof (dap_worker_t*) ); + s_threads = DAP_NEW_Z_SIZE(dap_thread_t, sizeof(dap_thread_t) * s_threads_count ); + if ( !s_workers || !s_threads ) + return -1; - if ( dap_events_socket_init() != 0 ) { + s_workers_init = true; - log_it( L_CRITICAL, "Can't init client submodule dap_events_socket_init( )" ); - goto err; - } - s_workers_init = true; + 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( )" ); + goto err; + } + if (dap_proc_thread_init(s_threads_count) != 0 ){ + log_it( L_CRITICAL, "Can't init proc threads" ); + goto err; - log_it( L_NOTICE, "Initialized socket server module" ); + } + log_it( L_NOTICE, "Initialized event socket reactor for %u threads", s_threads_count ); - #ifndef _WIN32 - signal( SIGPIPE, SIG_IGN ); - #endif - return 0; + return 0; err: - dap_events_deinit( ); - return -1; + log_it(L_ERROR,"Deinit events subsystem"); + dap_events_deinit(); + dap_worker_deinit(); + return -1; } /** @@ -161,16 +186,13 @@ err: */ void dap_events_deinit( ) { - dap_events_socket_deinit( ); - - if ( g_epoll_events ) - free( g_epoll_events ); + dap_events_socket_deinit(); + dap_worker_deinit(); + if ( s_threads ) + DAP_DELETE( s_threads ); - if ( s_threads ) - free( s_threads ); - - if ( s_workers ) - free( s_workers ); + if ( s_workers ) + DAP_DELETE( s_workers ); } /** @@ -179,12 +201,17 @@ void dap_events_deinit( ) */ dap_events_t * dap_events_new( ) { - dap_events_t *ret = (dap_events_t *)calloc( 1, sizeof(dap_events_t) ); + dap_events_t *ret = DAP_NEW_Z(dap_events_t); - pthread_rwlock_init( &ret->sockets_rwlock, NULL ); - pthread_rwlock_init( &ret->servers_rwlock, NULL ); + pthread_rwlock_init( &ret->sockets_rwlock, NULL ); + if ( s_events_default == NULL) + s_events_default = ret; + return ret; +} - return ret; +dap_events_t* dap_events_get_default( ) +{ + return s_events_default; } /** @@ -193,417 +220,147 @@ dap_events_t * dap_events_new( ) */ void dap_events_delete( dap_events_t *a_events ) { - dap_events_socket_t *cur, *tmp; - - if ( a_events ) { - - HASH_ITER( hh, a_events->sockets,cur, tmp ) { - dap_events_socket_delete( cur, true ); - } + if (a_events) { + dap_events_socket_t *l_cur, *l_tmp; + HASH_ITER( hh, a_events->sockets,l_cur, l_tmp ) { + dap_events_socket_remove_and_delete_unsafe( l_cur, true ); + } - if ( a_events->_inheritor ) - free( a_events->_inheritor ); + if ( a_events->_inheritor ) + DAP_DELETE( a_events->_inheritor ); - pthread_rwlock_destroy( &a_events->servers_rwlock ); - pthread_rwlock_destroy( &a_events->sockets_rwlock ); + pthread_rwlock_destroy( &a_events->sockets_rwlock ); - free( a_events ); - } + DAP_DELETE( a_events ); + } } /** - * @brief s_socket_info_all_check_activity - * @param n_thread - * @param sh + * @brief sa_server_loop Main server loop + * @param sh Server instance + * @return Zero if ok others if not */ -static void s_socket_all_check_activity( dap_worker_t *dap_worker, dap_events_t *d_ev, time_t cur_time ) +int dap_events_start( dap_events_t *a_events ) { - dap_events_socket_t *a_es, *tmp; - - pthread_mutex_lock( &dap_worker->locker_on_count ); - DL_FOREACH_SAFE( d_ev->dlsockets, a_es, tmp ) { - - if ( a_es->type == DESCRIPTOR_TYPE_FILE) - continue; - - if ( !a_es->kill_signal && cur_time >= a_es->last_time_active + s_connection_timeout && !a_es->no_close ) { - log_it( L_INFO, "Socket %u timeout, closing...", a_es->socket ); - if (a_es->callbacks->error_callback) { - a_es->callbacks->error_callback(a_es, (void *)ETIMEDOUT); - } - - if ( epoll_ctl( dap_worker->epoll_fd, EPOLL_CTL_DEL, a_es->socket, &a_es->ev) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll_fd" ); - else - log_it( L_DEBUG,"Removed epoll's event from dap_worker #%u", dap_worker->number_thread ); - - dap_worker->event_sockets_count --; - DL_DELETE( d_ev->dlsockets, a_es ); - dap_events_socket_delete( a_es, true ); + for( uint32_t i = 0; i < s_threads_count; i++) { + dap_worker_t * l_worker = DAP_NEW_Z(dap_worker_t); + + l_worker->id = i; + l_worker->events = a_events; + l_worker->proc_queue = dap_proc_thread_get(i)->proc_queue; +#ifdef DAP_EVENTS_CAPS_EPOLL + l_worker->epoll_fd = epoll_create( DAP_MAX_EPOLL_EVENTS ); + pthread_mutex_init(& l_worker->started_mutex, NULL); + pthread_cond_init( & l_worker->started_cond, NULL); + //log_it(L_DEBUG, "Created event_fd %d for worker %u", l_worker->epoll_fd,i); + if ( l_worker->epoll_fd == -1 ) { + int l_errno = errno; + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof ( l_errbuf) ); + log_it(L_CRITICAL, "Error create epoll fd: %s (%d)", l_errbuf, l_errno); + DAP_DELETE(l_worker); + return -1; + } +#endif + s_workers[i] = l_worker; + pthread_mutex_lock(&l_worker->started_mutex); + struct timespec l_timeout; + clock_gettime(CLOCK_REALTIME, &l_timeout); + l_timeout.tv_sec+=5; + pthread_create( &s_threads[i].tid, NULL, dap_worker_thread, l_worker ); + + int l_ret; + l_ret=pthread_cond_timedwait(&l_worker->started_cond, &l_worker->started_mutex, &l_timeout); + if ( l_ret== ETIMEDOUT ){ + log_it(L_CRITICAL, "Timeout 5 seconds is out: worker #%u thread don't respond", i); + return -2; + } else if (l_ret != 0){ + log_it(L_CRITICAL, "Can't wait on condition: %d error code", l_ret); + return -3; + } } - } - pthread_mutex_unlock( &dap_worker->locker_on_count ); - + return 0; } /** - * @brief thread_worker_function - * @param arg + * @brief dap_events_wait + * @param sh * @return */ -static void *thread_worker_function(void *arg) +int dap_events_wait( dap_events_t *a_events ) { - dap_events_socket_t *cur; - dap_worker_t *w = (dap_worker_t *) arg; - time_t next_time_timeout_check = time( NULL) + s_connection_timeout / 2; - uint32_t tn = w->number_thread; - -#ifndef _WIN32 -#ifndef NO_POSIX_SHED - cpu_set_t mask; - CPU_ZERO(&mask); - CPU_SET(tn, &mask); - - int err; -#ifndef __ANDROID__ - err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask); -#else - err = sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &mask); -#endif - if(err) - { - log_it(L_CRITICAL, "Error pthread_setaffinity_np() You really have %d or more core in CPU?", *(int* )arg); - abort(); + (void) a_events; + for( uint32_t i = 0; i < s_threads_count; i ++ ) { + void *ret; + pthread_join( s_threads[i].tid, &ret ); } -#endif -#else - - if ( !SetThreadAffinityMask( GetCurrentThread(), (DWORD_PTR)(1 << tn) ) ) { - log_it( L_CRITICAL, "Error pthread_setaffinity_np() You really have %d or more core in CPU?", tn ); - abort(); - } - #endif - - log_it(L_INFO, "Worker %d started, epoll fd %d", w->number_thread, w->epoll_fd); - - struct epoll_event *events = &g_epoll_events[ DAP_MAX_EPOLL_EVENTS * tn]; - -// memset( &ev, 0, sizeof(ev) ); -// memset( &events, 0, sizeof(events) ); - - size_t total_sent; - int bytes_sent = 0; - - while(bEventsAreActive) { - - int selected_sockets = epoll_wait(w->epoll_fd, events, DAP_MAX_EPOLL_EVENTS, 1000); - - if(selected_sockets == -1) { - if( errno == EINTR) - continue; - log_it(L_ERROR, "Worker thread %d got errno: %d", w->number_thread, errno); - break; - } - - time_t cur_time = time( NULL); - for(int32_t n = 0; n < selected_sockets; n++) { - - cur = (dap_events_socket_t *) events[n].data.ptr; - - if(!cur) { - - log_it(L_ERROR, "dap_events_socket NULL"); - continue; - } - //log_it(L_DEBUG, "Worker=%d fd=%d socket=%d event=0x%x(%d)", w->number_thread, w->epoll_fd,cur->socket, events[n].events,events[n].events); - int l_sock_err = 0, l_sock_err_size = sizeof(l_sock_err); - //connection already closed (EPOLLHUP - shutdown has been made in both directions) - if(events[n].events & EPOLLHUP) { // && events[n].events & EPOLLERR) { - getsockopt(cur->socket, SOL_SOCKET, SO_ERROR, (void *)&l_sock_err, (socklen_t *)&l_sock_err_size); - //if(!(events[n].events & EPOLLIN)) - //cur->no_close = false; - if (l_sock_err) { - cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it(L_DEBUG, "Socket shutdown (EPOLLHUP): %s", strerror(l_sock_err)); - if(!(events[n].events & EPOLLERR)) - cur->callbacks->error_callback(cur, NULL); // Call callback to process error event - } - } - - if(events[n].events & EPOLLERR) { - getsockopt(cur->socket, SOL_SOCKET, SO_ERROR, (void *)&l_sock_err, (socklen_t *)&l_sock_err_size); - log_it(L_ERROR, "Socket error: %s", strerror(l_sock_err)); - cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - cur->callbacks->error_callback(cur, NULL); // Call callback to process error event - } - - cur->last_time_active = cur_time; - - if(events[n].events & EPOLLIN) { - - //log_it(DEBUG,"Comes connection in active read set"); - if(cur->buf_in_size == sizeof(cur->buf_in)) { - log_it(L_WARNING, "Buffer is full when there is smth to read. Its dropped!"); - cur->buf_in_size = 0; - } - - int32_t bytes_read = 0; - if(cur->type == DESCRIPTOR_TYPE_SOCKET) { - bytes_read = recv(cur->socket, (char *) (cur->buf_in + cur->buf_in_size), - sizeof(cur->buf_in) - cur->buf_in_size, 0); - }else if(cur->type == DESCRIPTOR_TYPE_FILE) { - bytes_read = read(cur->socket, (char *) (cur->buf_in + cur->buf_in_size), - sizeof(cur->buf_in) - cur->buf_in_size); - } - - if(bytes_read > 0) { - cur->buf_in_size += bytes_read; - //log_it(DEBUG, "Received %d bytes", bytes_read); - cur->callbacks->read_callback(cur, NULL); // Call callback to process read event. At the end of callback buf_in_size should be zero if everything was read well - } - else if(bytes_read < 0) { - log_it(L_ERROR, "Some error occured in recv() function: %s", strerror(errno)); - dap_events_socket_set_readable(cur, false); - cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - } - else if(bytes_read == 0) { - log_it(L_INFO, "Client socket disconnected"); - dap_events_socket_set_readable(cur, false); - cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - } - } - - // Socket is ready to write - if(((events[n].events & EPOLLOUT) || (cur->flags & DAP_SOCK_READY_TO_WRITE)) - && !(cur->flags & DAP_SOCK_SIGNAL_CLOSE)) { - ///log_it(DEBUG, "Main loop output: %u bytes to send",sa_cur->buf_out_size); - if(cur->callbacks->write_callback) - cur->callbacks->write_callback(cur, NULL); // Call callback to process write event - - if(cur->flags & DAP_SOCK_READY_TO_WRITE) { - - static const uint32_t buf_out_zero_count_max = 20; - cur->buf_out[cur->buf_out_size] = 0; - - if(!cur->buf_out_size) { - - //log_it(L_WARNING, "Output: nothing to send. Why we are in write socket set?"); - cur->buf_out_zero_count++; - - if(cur->buf_out_zero_count > buf_out_zero_count_max) { // How many time buf_out on write event could be empty - log_it(L_ERROR, "Output: nothing to send %u times, remove socket from the write set", - buf_out_zero_count_max); - dap_events_socket_set_writable(cur, false); - } - } - else - cur->buf_out_zero_count = 0; - } - for(total_sent = 0; total_sent < cur->buf_out_size;) { // If after callback there is smth to send - we do it - if(cur->type == DESCRIPTOR_TYPE_SOCKET) { - bytes_sent = send(cur->socket, (char *) (cur->buf_out + total_sent), - cur->buf_out_size - total_sent, MSG_DONTWAIT | MSG_NOSIGNAL); - }else if(cur->type == DESCRIPTOR_TYPE_FILE) { - bytes_sent = write(cur->socket, (char *) (cur->buf_out + total_sent), - cur->buf_out_size - total_sent); - } - - if(bytes_sent < 0) { - log_it(L_ERROR, "Some error occured in send(): %s", strerror(errno)); - cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - break; - } - total_sent += bytes_sent; - //log_it(L_DEBUG, "Output: %u from %u bytes are sent ", total_sent,sa_cur->buf_out_size); - } - //log_it(L_DEBUG,"Output: sent %u bytes",total_sent); - if (total_sent) { - pthread_mutex_lock(&cur->write_hold); - cur->buf_out_size -= total_sent; - if (cur->buf_out_size) { - memmove(cur->buf_out, &cur->buf_out[total_sent], cur->buf_out_size); - } else { - cur->flags &= ~DAP_SOCK_READY_TO_WRITE; - } - pthread_mutex_unlock(&cur->write_hold); - } - } - - if((cur->flags & DAP_SOCK_SIGNAL_CLOSE) && !cur->no_close) { - // protect against double deletion - cur->kill_signal = true; - //dap_events_socket_remove_and_delete(cur, true); - log_it(L_INFO, "Got signal to close %s, sock %u [thread %u]", cur->hostaddr, cur->socket, tn); - } - - if(cur->kill_signal) { - log_it(L_INFO, "Kill %u socket (processed).... [ thread %u ]", cur->socket, tn); - dap_events_socket_remove(cur); - dap_events_socket_delete( cur, true); - } - - /* - if(!w->event_to_kill_count) { - - pthread_mutex_unlock(&w->locker_on_count); - continue; - - do { - -// if ( cur->no_close ) { -// cur = cur->knext; -// continue; -// } - tmp = cur_del->knext; - - // delete only current events_socket because others may be active in the other workers - //if(cur_del == cur) - if(cur->kill_signal) { - log_it(L_INFO, "Kill %u socket (processed).... [ thread %u ]", cur_del->socket, tn); - DL_LIST_REMOVE_NODE(w->events->to_kill_sockets, cur, kprev, knext, w->event_to_kill_count); - dap_events_socket_remove_and_delete(cur_del, true); - } - cur_del = tmp; - - } while(cur_del); - - log_it(L_INFO, "[ Thread %u ] coneections: %u, to kill: %u", tn, w->event_sockets_count, - w->event_to_kill_count); - - pthread_mutex_unlock(&w->locker_on_count); - */ - } // for - -#ifndef NO_TIMER - if(cur_time >= next_time_timeout_check) { - s_socket_all_check_activity(w, w->events, cur_time); - next_time_timeout_check = cur_time + s_connection_timeout / 2; - } -#endif - - } // while - - return NULL; + return 0; } /** - * @brief dap_worker_get_min - * @return + * @brief dap_events_stop + * @param a_events */ -dap_worker_t *dap_worker_get_min( ) +void dap_events_stop_all( ) { - // wait for s_workers init - while(!s_workers_init) - dap_usleep(DAP_USEC_PER_SEC / 1000); - dap_worker_t *l_workers = &s_workers[dap_worker_get_index_min()]; - // wait for worker start - while(!l_workers->events) - dap_usleep(DAP_USEC_PER_SEC / 1000); - return l_workers; + // TODO implement signal to stop the workers } + /** * @brief dap_worker_get_index_min * @return */ -uint32_t dap_worker_get_index_min( ) +uint32_t dap_events_worker_get_index_min( ) { - uint32_t min = 0; - uint32_t i; + uint32_t min = 0; + uint32_t i; - for( i = 1; i < s_threads_count; i++ ) { + for( i = 1; i < s_threads_count; i++ ) { - if ( s_workers[min].event_sockets_count > s_workers[i].event_sockets_count ) - min = i; - } - - return min; -} - -/** - * @brief dap_worker_print_all - */ -void dap_worker_print_all( ) -{ - uint32_t i; - - for( i = 0; i < s_threads_count; i ++ ) { - - log_it( L_INFO, "Worker: %d, count open connections: %d", - s_workers[i].number_thread, s_workers[i].event_sockets_count ); - } -} - -/** - * @brief sa_server_loop Main server loop - * @param sh Server instance - * @return Zero if ok others if not - */ -int dap_events_start( dap_events_t *a_events ) -{ - for( uint32_t i = 0; i < s_threads_count; i++) { - - s_workers[i].epoll_fd = epoll_create( DAP_MAX_EPOLL_EVENTS ); - if ( (intptr_t)s_workers[i].epoll_fd == -1 ) { - log_it(L_CRITICAL, "Error create epoll fd"); - return -1; + if ( s_workers[min]->event_sockets_count > s_workers[i]->event_sockets_count ) + min = i; } - //s_workers[i].event_to_kill_count = 0; - s_workers[i].event_sockets_count = 0; - s_workers[i].number_thread = i; - s_workers[i].events = a_events; - - pthread_mutex_init( &s_workers[i].locker_on_count, NULL ); - pthread_create( &s_threads[i].tid, NULL, thread_worker_function, &s_workers[i] ); - } - - return 0; + return min; } -void dap_events_stop() +uint32_t dap_events_worker_get_count() { - bEventsAreActive = false; + return s_threads_count; } /** - * @brief dap_events_wait - * @param sh + * @brief dap_worker_get_min * @return */ -int dap_events_wait( dap_events_t *sh ) +dap_worker_t *dap_events_worker_get_auto( ) { - (void) sh; - - for( uint32_t i = 0; i < s_threads_count; i ++ ) { - void *ret; - pthread_join( s_threads[i].tid, &ret ); - } - - return 0; + return s_workers[dap_events_worker_get_index_min()]; } /** - * @brief dap_worker_add_events_socket - * @param a_worker - * @param a_events_socket + * @brief dap_worker_get_index + * @param a_index + * @return */ -void dap_worker_add_events_socket( dap_events_socket_t *a_es) +dap_worker_t * dap_events_worker_get(uint8_t a_index) { -// struct epoll_event ev = {0}; - dap_worker_t *l_worker = dap_worker_get_min( ); - - a_es->dap_worker = l_worker; - a_es->events = a_es->dap_worker->events; + if (a_index < s_threads_count){ + return s_workers[a_index]; + }else + return NULL; } /** - * @brief dap_events__thread_wake_up - * @param th + * @brief dap_worker_print_all */ -void dap_events_thread_wake_up( dap_thread_t *th ) +void dap_events_worker_print_all( ) { - (void) th; - //pthread_kill(th->tid,SIGUSR1); + uint32_t i; + for( i = 0; i < s_threads_count; i ++ ) { + log_it( L_INFO, "Worker: %d, count open connections: %d", + s_workers[i]->id, s_workers[i]->event_sockets_count ); + } } diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c index c73c4d00390b4104b93806d33074a6e162415820..542be22e8779cae1cdafda25d0a92702b4b987ca 100644 --- a/dap-sdk/net/core/dap_events_socket.c +++ b/dap-sdk/net/core/dap_events_socket.c @@ -1,33 +1,33 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2019 + * DeM Labs Ltd. https://demlabs.net + * Copyright (c) 2017 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + 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 is distributed in the hope that it will be useful, + 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ + #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #include <assert.h> - +#include <errno.h> #ifndef _WIN32 #include <sys/epoll.h> #include <unistd.h> @@ -43,6 +43,7 @@ #endif #include "dap_common.h" +#include "dap_worker.h" #include "dap_events.h" #include "dap_events_socket.h" @@ -55,7 +56,19 @@ */ int dap_events_socket_init( ) { - log_it(L_NOTICE,"Initialized socket client module"); + log_it(L_NOTICE,"Initialized events socket module"); +#if defined (DAP_EVENTS_CAPS_QUEUE_POSIX) +#ifdef DAP_OS_LINUX +#include <sys/time.h> +#include <sys/resource.h> + + struct rlimit l_mqueue_limit; + l_mqueue_limit.rlim_cur = 1024; + l_mqueue_limit.rlim_max = 1024; +// setrlimit(RLIMIT_MSGQUEUE,&l_mqueue_limit); +#endif +#endif + dap_timerfd_init(); return 0; } @@ -79,52 +92,449 @@ void dap_events_socket_deinit( ) 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 ) { -// assert(a_events); - assert(a_callbacks); + assert(a_events); + assert(a_callbacks); - dap_events_socket_t *ret = DAP_NEW_Z( dap_events_socket_t ); + dap_events_socket_t *ret = DAP_NEW_Z( dap_events_socket_t ); - ret->socket = a_sock; - ret->events = a_events; - ret->callbacks = a_callbacks; - ret->flags = DAP_SOCK_READY_TO_READ; - ret->no_close = false; - pthread_mutex_init(&ret->write_hold, NULL); + ret->socket = a_sock; + ret->events = a_events; + memcpy(&ret->callbacks, a_callbacks, sizeof(ret->callbacks) ); + ret->flags = DAP_SOCK_READY_TO_READ; - log_it( L_DEBUG,"Dap event socket wrapped around %d sock a_events = %X", a_sock, a_events ); + #if defined(DAP_EVENTS_CAPS_EPOLL) + ret->ev_base_flags = EPOLLERR | EPOLLRDHUP | EPOLLHUP; + #endif - return ret; + if ( a_sock!= 0 && a_sock != -1){ + pthread_rwlock_wrlock(&a_events->sockets_rwlock); + HASH_ADD(hh,a_events->sockets, socket, sizeof (int), ret); + pthread_rwlock_unlock(&a_events->sockets_rwlock); + }else + log_it(L_WARNING, "Be carefull, you've wrapped socket 0 or -1 so it wasn't added to global list. Do it yourself when possible"); + + //log_it( L_DEBUG,"Dap event socket wrapped around %d sock a_events = %X", a_sock, a_events ); + + return ret; } /** - * @brief dap_events_socket_create_after + * @brief dap_events_socket_assign_on_worker * @param a_es + * @param a_worker */ -void dap_events_socket_create_after( dap_events_socket_t *a_es ) +void dap_events_socket_assign_on_worker_mt(dap_events_socket_t * a_es, struct dap_worker * a_worker) { - if ( a_es->callbacks->new_callback ) - a_es->callbacks->new_callback( a_es, NULL ); // Init internal structure + a_es->last_ping_request = time(NULL); + // log_it(L_DEBUG, "Assigned %p on worker %u", a_es, a_worker->id); + dap_worker_add_events_socket(a_es,a_worker); +} - a_es->last_time_active = a_es->last_ping_request = time( NULL ); - dap_worker_add_events_socket( a_es ); +void dap_events_socket_reassign_between_workers_unsafe(dap_events_socket_t * a_es, dap_worker_t * a_worker_new) +{ + log_it(L_DEBUG, "reassign between workers"); + dap_events_socket_remove_from_worker_unsafe( a_es, a_es->worker ); + a_es->was_reassigned = true; + if (a_es->callbacks.worker_unassign_callback) + a_es->callbacks.worker_unassign_callback(a_es, a_es->worker); - pthread_mutex_lock( &a_es->dap_worker->locker_on_count ); + dap_events_socket_assign_on_worker_mt( a_es, a_worker_new ); +} - a_es->dap_worker->event_sockets_count ++; - DL_APPEND( a_es->events->dlsockets, a_es ); +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) +{ + dap_worker_msg_reassign_t * l_msg = DAP_NEW_Z(dap_worker_msg_reassign_t); + l_msg->esocket = a_es; + l_msg->worker_new = a_worker_new; + dap_events_socket_queue_ptr_send(a_worker_old->queue_es_reassign, l_msg); +} - pthread_rwlock_wrlock( &a_es->events->sockets_rwlock ); - HASH_ADD_INT( a_es->events->sockets, socket, a_es ); - pthread_rwlock_unlock( &a_es->events->sockets_rwlock ); +/** + * @brief dap_events_socket_assign_on_worker_unsafe + * @param a_es + * @param a_worker + */ +void dap_events_socket_assign_on_worker_unsafe(dap_events_socket_t * a_es, struct dap_worker * a_worker) +{ +#if defined(DAP_EVENTS_CAPS_EPOLL) + int l_event_fd = a_es->fd; + //log_it( L_INFO, "Create event descriptor with queue %d (%p) and add it on epoll fd %d", l_event_fd, l_es, a_w->epoll_fd); + a_es->ev.events = a_es->ev_base_flags; + a_es->ev.data.ptr = a_es; + epoll_ctl(a_worker->epoll_fd, EPOLL_CTL_ADD, l_event_fd, &a_es->ev); +#endif +} - a_es->ev.events = EPOLLIN | EPOLLERR; - a_es->ev.data.ptr = a_es; +/** + * @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) +{ + 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->callbacks.read_callback = a_callback; // Arm event callback + l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; + +#if defined(DAP_EVENTS_CAPS_PIPE_POSIX) + int l_pipe[2]; + int l_errno; + char l_errbuf[128]; + 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]; +#else +#error "No defined s_create_type_pipe() for your platform" +#endif + return l_es; +} - if ( epoll_ctl( a_es->dap_worker->epoll_fd, EPOLL_CTL_ADD, a_es->socket, &a_es->ev ) == 1 ) - log_it( L_CRITICAL, "Can't add event socket's handler to epoll_fd" ); +/** + * @brief dap_events_socket_create_type_pipe_mt + * @param a_w + * @param a_callback + * @param a_flags + * @return + */ +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_assign_on_worker_unsafe(l_es,a_w); + return l_es; +} - pthread_mutex_unlock( &a_es->dap_worker->locker_on_count ); +/** + * @brief dap_events_socket_create_type_pipe_unsafe + * @param a_w + * @param a_callback + * @param a_flags + * @return + */ +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_assign_on_worker_unsafe(l_es,a_w); + 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); + l_es->type = DESCRIPTOR_TYPE_QUEUE; + l_es->flags = DAP_SOCK_QUEUE_PTR; + 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->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; + +#ifdef DAP_EVENTS_CAPS_QUEUE_PIPE2 + int l_pipe[2]; + int l_errno; + char l_errbuf[128]; + if( pipe2(l_pipe,O_DIRECT | O_NONBLOCK ) < 0 ){ + 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]; + const int l_file_buf_size = 64; + FILE* l_sys_max_pipe_size_fd = fopen("/proc/sys/fs/pipe-max-size", "r"); + if (l_sys_max_pipe_size_fd == NULL) { + log_it(L_WARNING, "Сan't resize pipe buffer"); + } + 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); + if (l_sys_max_pipe_size && fcntl(l_pipe[0], F_SETPIPE_SZ, l_sys_max_pipe_size) == l_sys_max_pipe_size) { + log_it(L_DEBUG, "Successfully resized pipe buffer to %lld", l_sys_max_pipe_size); + } +#elif defined (DAP_EVENTS_CAPS_QUEUE_POSIX) + char l_mq_name[64]; + struct mq_attr l_mq_attr ={0}; + l_mq_attr.mq_curmsgs = 9; + l_mq_attr.mq_maxmsg = 9; // 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 + snprintf(l_mq_name,sizeof (l_mq_name),"/dap-%d-esocket-0x%p",getpid(),l_es); + + l_es->mqd = mq_open(l_mq_name,O_CREAT|O_RDWR,S_IRWXU, &l_mq_attr); + if (l_es->mqd == -1 ){ + int l_errno = errno; + char l_errbuf[128]={0}; + strerror_r(l_errno,l_errbuf,sizeof (l_errbuf) ); + DAP_DELETE(l_es); + l_es = NULL; + log_it(L_CRITICAL,"Can't create mqueue descriptor %s: \"%s\" code %d",l_mq_name, l_errbuf, l_errno); + } +#else +#error "Not implemented s_create_type_queue_ptr() on your platform" +#endif + return l_es; +} + +/** + * @brief dap_events_socket_create_type_queue_mt + * @param a_w + * @param a_callback + * @param a_flags + * @return + */ +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); + assert(l_es); + // If no worker - don't assign + if ( a_w) + dap_events_socket_assign_on_worker_mt(l_es,a_w); + return l_es; +} + + +/** + * @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) + dap_events_socket_assign_on_worker_unsafe(l_es,a_w); + return l_es; +} + +/** + * @brief dap_events_socket_queue_proc_input + * @param a_esocket + */ +int dap_events_socket_queue_proc_input_unsafe(dap_events_socket_t * a_esocket) +{ + if (a_esocket->callbacks.queue_callback){ + if (a_esocket->flags & DAP_SOCK_QUEUE_PTR){ + void * l_queue_ptr = NULL; +#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) + if(read( a_esocket->fd, &l_queue_ptr,sizeof (void *)) == sizeof (void *)) + a_esocket->callbacks.queue_ptr_callback(a_esocket, l_queue_ptr); + else if ( (errno != EAGAIN) && (errno != EWOULDBLOCK) ) // we use blocked socket for now but who knows... + log_it(L_WARNING, "Can't read packet from pipe"); +#elif defined (DAP_EVENTS_CAPS_QUEUE_POSIX) + struct timespec s_timeout; + clock_gettime(CLOCK_REALTIME, &s_timeout); + s_timeout.tv_sec+=1; + ssize_t l_ret = mq_timedreceive(a_esocket->mqd,(char*) &l_queue_ptr, sizeof (l_queue_ptr),NULL,&s_timeout ); + if (l_ret == -1){ + int l_errno = errno; + char l_errbuf[128]={0}; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR, "Error in esocket queue_ptr:\"%s\" code %d", l_errbuf, l_errno); + return -1; + } + a_esocket->callbacks.queue_ptr_callback (a_esocket, l_queue_ptr); +#else +#error "No Queue fetch mechanism implemented on your platform" +#endif + }else{ + size_t l_read = read(a_esocket->socket, a_esocket->buf_in,sizeof(a_esocket->buf_in)); + a_esocket->callbacks.queue_callback(a_esocket,a_esocket->buf_in,l_read ); + } + }else{ + log_it(L_ERROR, "Queue socket %d accepted data but callback is NULL ", a_esocket->socket); + return -1; + } + 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); + l_es->type = DESCRIPTOR_TYPE_EVENT; + if (a_w){ + l_es->events = a_w->events; + l_es->worker = a_w; + } + l_es->callbacks.event_callback = a_callback; // Arm event callback + l_es->ev_base_flags = EPOLLIN | EPOLLERR | EPOLLRDHUP | EPOLLHUP; + +#ifdef DAP_EVENTS_CAPS_EVENT_EVENTFD + if((l_es->fd = eventfd(0,0) ) < 0 ){ + int l_errno = errno; + char l_errbuf[128]; + 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 + log_it(L_DEBUG, "Created eventfd descriptor %d", l_es->fd ); +#endif + return l_es; +} + +/** + * @brief dap_events_socket_create_type_event_mt + * @param a_w + * @param a_callback + * @return + */ +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); + // If no worker - don't assign + if ( a_w) + dap_events_socket_assign_on_worker_mt(l_es,a_w); + return l_es; +} + +/** + * @brief dap_events_socket_create_type_event_unsafe + * @param a_w + * @param a_callback + * @return + */ +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); + // If no worker - don't assign + if ( a_w) + dap_events_socket_assign_on_worker_unsafe(l_es,a_w); + return l_es; +} + +/** + * @brief dap_events_socket_event_proc_input_unsafe + * @param a_esocket + */ +void dap_events_socket_event_proc_input_unsafe(dap_events_socket_t *a_esocket) +{ + if (a_esocket->callbacks.event_callback ){ +#if defined(DAP_EVENTS_CAPS_EVENT_EVENTFD ) + eventfd_t l_value; + if(eventfd_read( a_esocket->fd, &l_value)==0 ){ // would block if not ready + a_esocket->callbacks.event_callback(a_esocket, l_value); + }else if ( (errno != EAGAIN) && (errno != EWOULDBLOCK) ){ // we use blocked socket for now but who knows... + int l_errno = errno; + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_WARNING, "Can't read packet from event fd: \"%s\"(%d)", l_errbuf, l_errno); + }else + return; // do nothing +#else +#error "No Queue fetch mechanism implemented on your platform" +#endif + }else + log_it(L_ERROR, "Queue socket %d accepted data but callback is NULL ", a_esocket->socket); +} + +/** + * @brief dap_events_socket_send_event + * @param a_es + * @param a_arg + */ +int dap_events_socket_queue_ptr_send( dap_events_socket_t * a_es, void* a_arg) +{ +#if defined(DAP_EVENTS_CAPS_QUEUE_PIPE2) + int ret = write(a_es->fd2, &a_arg, sizeof(a_arg)); + int l_errno = errno; + if (ret == sizeof(a_arg) ) + return 0; + else{ + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR, "Can't send ptr to queue:\"%s\" code %d", l_errbuf, l_errno); + return l_errno; + } +#elif defined (DAP_EVENTS_CAPS_QUEUE_POSIX) + struct timespec l_timeout; + clock_gettime(CLOCK_REALTIME, &l_timeout); + l_timeout.tv_sec+=2; // Not wait more than 1 second to get and 2 to send + int ret = mq_timedsend(a_es->mqd, (const char *)&a_arg,sizeof (a_arg),0, &l_timeout ); + int l_errno = errno; + if (ret == sizeof(a_arg) ) + return 0; + else + return l_errno; +#else +#error "Not implemented dap_events_socket_queue_ptr_send() for this platform" +#endif +} + +/** + * @brief dap_events_socket_event_signal + * @param a_es + * @param a_value + * @return + */ +int dap_events_socket_event_signal( dap_events_socket_t * a_es, uint64_t a_value) +{ +#if defined(DAP_EVENTS_CAPS_EVENT_EVENTFD) + int ret = eventfd_write( a_es->fd2,a_value); + int l_errno = errno; + if (ret == 0 ) + return 0; + else if ( ret < 0) + return l_errno; + else + return 1; +#else +#error "Not implemented dap_events_socket_event_signal() for this platform" +#endif +} + +/** + * @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) +{ + int l_ret= dap_events_socket_queue_ptr_send( a_es->worker->queue_es_delete, a_es ); + if( l_ret != 0 ){ + log_it(L_ERROR, "Queue send returned %d", l_ret); + } } /** @@ -142,12 +552,15 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da assert( a_callbacks ); assert( a_server ); - log_it( L_DEBUG,"Sap event socket wrapped around %d sock", a_sock ); + //log_it( L_DEBUG,"Dap event socket wrapped around %d sock", a_sock ); dap_events_socket_t * ret = DAP_NEW_Z( dap_events_socket_t ); ret->socket = a_sock; ret->events = a_events; - ret->callbacks = a_callbacks; + ret->server = a_server; + ret->is_dont_reset_write_flag = true; + + memcpy(&ret->callbacks,a_callbacks, sizeof ( ret->callbacks) ); ret->flags = DAP_SOCK_READY_TO_READ; ret->is_pingable = true; @@ -157,9 +570,6 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da HASH_ADD_INT( a_events->sockets, socket, ret ); pthread_rwlock_unlock( &a_events->sockets_rwlock ); - if( a_callbacks->new_callback ) - a_callbacks->new_callback( ret, NULL ); // Init internal structure - return ret; } @@ -169,17 +579,17 @@ dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct da * @param sh * @return */ -dap_events_socket_t *dap_events_socket_find( int sock, struct dap_events *a_events ) +dap_events_socket_t *dap_events_socket_find_unsafe( int sock, struct dap_events *a_events ) { - dap_events_socket_t *ret = NULL; - if(!a_events) - return NULL; - pthread_rwlock_wrlock( &a_events->sockets_rwlock ); - if(a_events->sockets) - HASH_FIND_INT( a_events->sockets, &sock, ret ); - pthread_rwlock_unlock( &a_events->sockets_rwlock ); - - return ret; + // Why we have only unsafe socket? Because you need to lock sockets_rwlock when do any operations with + // socket that you've find in global list + dap_events_socket_t *ret = NULL; + if(!a_events) + return NULL; + if(a_events->sockets) + HASH_FIND_INT( a_events->sockets, &sock, ret ); + + return ret; } /** @@ -187,12 +597,13 @@ dap_events_socket_t *dap_events_socket_find( int sock, struct dap_events *a_even * @param sc * @param isReady */ -void dap_events_socket_set_readable( dap_events_socket_t *sc, bool is_ready ) +void dap_events_socket_set_readable_unsafe( dap_events_socket_t *sc, bool is_ready ) { if( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_READ) ) return; - sc->ev.events = EPOLLERR; + sc->ev.events = sc->ev_base_flags; + sc->ev.events |= EPOLLERR; if ( is_ready ) sc->flags |= DAP_SOCK_READY_TO_READ; @@ -208,11 +619,13 @@ void dap_events_socket_set_readable( dap_events_socket_t *sc, bool is_ready ) events |= EPOLLOUT; sc->ev.events = events; - - if ( epoll_ctl(sc->dap_worker->epoll_fd, EPOLL_CTL_MOD, sc->socket, &sc->ev) == -1 ) - log_it( L_ERROR,"Can't update read client socket state in the epoll_fd" ); - else - dap_events_thread_wake_up( &sc->events->proc_thread ); + if (sc->worker) + if ( epoll_ctl(sc->worker->epoll_fd, EPOLL_CTL_MOD, sc->socket, &sc->ev) == -1 ){ + int l_errno = errno; + char l_errbuf[128]; + strerror_r( l_errno, l_errbuf, sizeof (l_errbuf)); + log_it( L_ERROR,"Can't update read client socket state in the epoll_fd: \"%s\" (%d)", l_errbuf, l_errno ); + } } /** @@ -220,140 +633,247 @@ void dap_events_socket_set_readable( dap_events_socket_t *sc, bool is_ready ) * @param sc * @param isReady */ -void dap_events_socket_set_writable( dap_events_socket_t *sc, bool is_ready ) +void dap_events_socket_set_writable_unsafe( dap_events_socket_t *sc, bool a_is_ready ) { - pthread_mutex_lock(&sc->write_hold); - - if ( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_WRITE) ) { - pthread_mutex_unlock(&sc->write_hold); - return; - } - - if ( is_ready ) - sc->flags |= DAP_SOCK_READY_TO_WRITE; - else - sc->flags ^= DAP_SOCK_READY_TO_WRITE; + if ( a_is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_WRITE) ) { + return; + } - int events = EPOLLERR; + if ( a_is_ready ) + sc->flags |= DAP_SOCK_READY_TO_WRITE; + else + sc->flags ^= DAP_SOCK_READY_TO_WRITE; - if( sc->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; + int events = sc->ev_base_flags | EPOLLERR; - if( sc->flags & DAP_SOCK_READY_TO_WRITE ) - events |= EPOLLOUT; + // Check & add + if( sc->flags & DAP_SOCK_READY_TO_READ ) + events |= EPOLLIN; - pthread_mutex_unlock(&sc->write_hold); + if( sc->flags & DAP_SOCK_READY_TO_WRITE ) + events |= EPOLLOUT; - sc->ev.events = events; + sc->ev.events = events; - if ( epoll_ctl(sc->dap_worker->epoll_fd, EPOLL_CTL_MOD, sc->socket, &sc->ev) == -1 ) - log_it(L_ERROR,"Can't update write client socket state in the epoll_fd"); - else - dap_events_thread_wake_up( &sc->events->proc_thread ); + if (sc->worker) + if ( epoll_ctl(sc->worker->epoll_fd, EPOLL_CTL_MOD, sc->socket, &sc->ev) ){ + int l_errno = errno; + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR,"Can't update write client socket state in the epoll_fd %d: \"%s\" (%d)", + sc->worker->epoll_fd, l_errbuf, l_errno); + } } - /** - * @brief dap_events_socket_kill_socket + * @brief dap_events_socket_remove Removes the client from the list * @param sc Connection instance */ -int dap_events_socket_kill_socket( dap_events_socket_t *a_es ) +void dap_events_socket_remove_and_delete_unsafe( dap_events_socket_t *a_es, bool preserve_inheritor ) { - if ( !a_es ) { - log_it( L_ERROR, "dap_events_socket_kill_socket( NULL )" ); - return -1; - } + if ( !a_es ) + return; - if( !a_es->dap_worker ) { - log_it( L_WARNING, "%s: socket %u has no worker thread", __PRETTY_FUNCTION__, a_es->socket ); - a_es->kill_signal = true; - return 0; - } + //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); - uint32_t tn = a_es->dap_worker->number_thread; + if (a_es->events){ // It could be socket NOT from events + pthread_rwlock_wrlock( &a_es->events->sockets_rwlock ); + if(!dap_events_socket_find_unsafe(a_es->socket, a_es->events)){ + log_it( L_ERROR, "dap_events_socket 0x%x already deleted", a_es); + pthread_rwlock_unlock( &a_es->events->sockets_rwlock ); + return ; + } - //dap_events_t *d_ev = w->events; + if(a_es->events->sockets) + HASH_DEL( a_es->events->sockets, a_es ); + pthread_rwlock_unlock( &a_es->events->sockets_rwlock ); + } + //log_it( L_DEBUG, "dap_events_socket wrapped around %d socket is removed", a_es->socket ); - if ( a_es->kill_signal ) { - return 0; - } + if( a_es->callbacks.delete_callback ) + a_es->callbacks.delete_callback( a_es, NULL ); // Init internal structure - log_it( L_DEBUG, "KILL %u socket! (in queue) [ thread %u ]", a_es->socket, tn ); + if ( a_es->_inheritor && !preserve_inheritor ) + DAP_DELETE( a_es->_inheritor ); - a_es->kill_signal = true; - //DL_LIST_ADD_NODE_HEAD( d_ev->to_kill_sockets, a_es, kprev, knext, w->event_to_kill_count ); + if ( a_es->socket && a_es->socket != -1) { +#ifdef _WIN32 + closesocket( a_es->socket ); +#else + close( a_es->socket ); +#ifdef DAP_EVENTS_CAPS_QUEUE_PIPE2 + if( a_es->type == DESCRIPTOR_TYPE_QUEUE){ + close( a_es->fd2); + } +#endif - return 0; +#endif + } + DAP_DELETE( a_es ); } /** - * @brief dap_events_socket_remove Removes the client from the list - * @param sc Connection instance + * @brief dap_events_socket_delete + * @param a_es */ -void dap_events_socket_delete( dap_events_socket_t *a_es, bool preserve_inheritor ) +void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap_worker_t * a_worker) { - if ( !a_es ) return; - - log_it( L_DEBUG, "es is going to be removed from the lists and free the memory (0x%016X)", a_es ); - - if(!dap_events_socket_find(a_es->socket, a_es->events)){ - log_it( L_ERROR, "dap_events_socket 0x%x already deleted", a_es); - return ; - } - pthread_rwlock_wrlock( &a_es->events->sockets_rwlock ); - if(a_es->events->sockets) - HASH_DEL( a_es->events->sockets, a_es ); - pthread_rwlock_unlock( &a_es->events->sockets_rwlock ); - - log_it( L_DEBUG, "dap_events_socket wrapped around %d socket is removed", a_es->socket ); - - if( a_es->callbacks->delete_callback ) - a_es->callbacks->delete_callback( a_es, NULL ); // Init internal structure - - if ( a_es->_inheritor && !preserve_inheritor ) - DAP_DELETE( a_es->_inheritor ); + if (!a_es->worker) { + // Socket already removed from worker + return; + } + if ( epoll_ctl( a_worker->epoll_fd, EPOLL_CTL_DEL, a_es->socket, &a_es->ev) == -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 from the epoll_fd %d \"%s\" (%d)", + a_worker->epoll_fd, l_errbuf, l_errno); + } //else + // log_it( L_DEBUG,"Removed epoll's event from dap_worker #%u", a_worker->id ); + a_worker->event_sockets_count--; + if(a_worker->esockets) + HASH_DELETE(hh_worker,a_worker->esockets, a_es); + a_es->worker = NULL; +} - if ( a_es->socket ) { -#ifdef _WIN32 - closesocket( a_es->socket ); -#else - close( a_es->socket ); -#endif - } - pthread_mutex_destroy(&a_es->write_hold); - DAP_DELETE( a_es ); +/** + * @brief dap_events_socket_check_unsafe + * @param a_worker + * @param a_es + * @return + */ +bool dap_events_socket_check_unsafe(dap_worker_t * a_worker,dap_events_socket_t * a_es) +{ + if (a_es){ + if ( a_worker->esockets){ + dap_events_socket_t * l_es = NULL; + HASH_FIND(hh_worker,a_worker->esockets,&a_es, sizeof(a_es), l_es ); + return l_es == a_es; + }else + return false; + }else + return false; } /** - * @brief dap_events_socket_delete + * @brief dap_events_socket_remove_and_delete * @param a_es + * @param preserve_inheritor */ -void dap_events_socket_remove( dap_events_socket_t *a_es) +void dap_events_socket_remove_and_delete_mt(dap_worker_t * a_w, dap_events_socket_t *a_es ) { - pthread_mutex_lock(&a_es->dap_worker->locker_on_count); - if ( epoll_ctl( a_es->dap_worker->epoll_fd, EPOLL_CTL_DEL, a_es->socket, &a_es->ev) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll_fd" ); - else - log_it( L_DEBUG,"Removed epoll's event from dap_worker #%u", a_es->dap_worker->number_thread ); + if(a_w) + dap_events_socket_queue_ptr_send( a_w->queue_es_delete, a_es ); +} - DL_DELETE( a_es->events->dlsockets, a_es ); - a_es->dap_worker->event_sockets_count --; - pthread_mutex_unlock(&a_es->dap_worker->locker_on_count); +/** + * @brief dap_events_socket_set_readable_mt + * @param a_w + * @param a_es + * @param a_is_ready + */ +void dap_events_socket_set_readable_mt(dap_worker_t * a_w, dap_events_socket_t * a_es,bool a_is_ready) +{ + dap_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_worker_msg_io_t); + l_msg->esocket = a_es; + if (a_is_ready) + l_msg->flags_set = DAP_SOCK_READY_TO_READ; + else + l_msg->flags_unset = DAP_SOCK_READY_TO_READ; + + int l_ret= dap_events_socket_queue_ptr_send(a_w->queue_es_io, l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + } } -void dap_events_socket_remove_and_delete( dap_events_socket_t *a_es, bool preserve_inheritor ) +/** + * @brief dap_events_socket_set_writable_mt + * @param sc + * @param is_ready + */ +void dap_events_socket_set_writable_mt(dap_worker_t * a_w, dap_events_socket_t * a_es,bool a_is_ready) { - pthread_mutex_lock(&a_es->dap_worker->locker_on_count); - if ( epoll_ctl( a_es->dap_worker->epoll_fd, EPOLL_CTL_DEL, a_es->socket, &a_es->ev) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll_fd" ); - else - log_it( L_DEBUG,"Removed epoll's event from dap_worker #%u", a_es->dap_worker->number_thread ); + dap_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_worker_msg_io_t); + l_msg->esocket = a_es; + if (a_is_ready) + l_msg->flags_set = DAP_SOCK_READY_TO_WRITE; + else + l_msg->flags_unset = DAP_SOCK_READY_TO_WRITE; + + int l_ret= dap_events_socket_queue_ptr_send(a_w->queue_es_io, l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + } +} - DL_DELETE( a_es->events->dlsockets, a_es ); - a_es->dap_worker->event_sockets_count --; - pthread_mutex_unlock(&a_es->dap_worker->locker_on_count); +/** + * @brief dap_events_socket_write_mt + * @param sc + * @param data + * @param data_size + * @return + */ +size_t dap_events_socket_write_mt(dap_worker_t * a_w,dap_events_socket_t *a_es, const void * data, size_t l_data_size) +{ + dap_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_worker_msg_io_t); + l_msg->esocket = a_es; + l_msg->data = DAP_NEW_SIZE(void,l_data_size); + l_msg->data_size = l_data_size; + l_msg->flags_set = DAP_SOCK_READY_TO_WRITE; + memcpy( l_msg->data, data, l_data_size); + + int l_ret= dap_events_socket_queue_ptr_send(a_w->queue_es_io, l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + return 0; + } + return l_data_size; +} - dap_events_socket_delete( a_es, preserve_inheritor ); +/** + * @brief dap_events_socket_write_f_mt + * @param a_es + * @param format + * @return + */ +size_t dap_events_socket_write_f_mt(dap_worker_t * a_w,dap_events_socket_t *a_es, const char * format,...) +{ + va_list ap, ap_copy; + va_start(ap,format); + va_copy(ap_copy, ap); + int l_data_size = dap_vsnprintf(NULL,0,format,ap); + va_end(ap); + if (l_data_size <0 ){ + log_it(L_ERROR,"Can't write out formatted data '%s' with values",format); + va_end(ap_copy); + return 0; + } + dap_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_worker_msg_io_t); + l_msg->esocket = a_es; + l_msg->data = DAP_NEW_SIZE(void,l_data_size + 1); + l_msg->flags_set = DAP_SOCK_READY_TO_WRITE; + l_data_size = dap_vsprintf(l_msg->data,format,ap_copy); + va_end(ap_copy); + if (l_data_size <0 ){ + log_it(L_ERROR,"Can't write out formatted data '%s' with values",format); + DAP_DELETE(l_msg->data); + DAP_DELETE(l_msg); + return 0; + } + l_msg->data_size = l_data_size; + int l_ret= dap_events_socket_queue_ptr_send(a_w->queue_es_io, l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg->data); + DAP_DELETE(l_msg); + return 0; + } + return l_data_size; } /** @@ -363,14 +883,17 @@ void dap_events_socket_remove_and_delete( dap_events_socket_t *a_es, bool prese * @param data_size Size of data to write * @return Number of bytes that were placed into the buffer */ -size_t dap_events_socket_write(dap_events_socket_t *sc, const void * data, size_t data_size) +size_t dap_events_socket_write_unsafe(dap_events_socket_t *sc, const void * data, size_t data_size) { + if(sc->buf_out_size>sizeof(sc->buf_out)){ + log_it(L_DEBUG,"write buffer already overflow size=%u/max=%u", sc->buf_out_size, sizeof(sc->buf_out)); + return 0; + } //log_it(L_DEBUG,"dap_events_socket_write %u sock data %X size %u", sc->socket, data, data_size ); - pthread_mutex_lock(&sc->write_hold); data_size = ((sc->buf_out_size+data_size)<(sizeof(sc->buf_out)))?data_size:(sizeof(sc->buf_out)-sc->buf_out_size ); memcpy(sc->buf_out+sc->buf_out_size,data,data_size); sc->buf_out_size+=data_size; - pthread_mutex_unlock(&sc->write_hold); + dap_events_socket_set_writable_unsafe(sc, true); return data_size; } @@ -380,11 +903,10 @@ size_t dap_events_socket_write(dap_events_socket_t *sc, const void * data, size_ * @param format Format * @return Number of bytes that were placed into the buffer */ -size_t dap_events_socket_write_f(dap_events_socket_t *sc, const char * format,...) +size_t dap_events_socket_write_f_unsafe(dap_events_socket_t *sc, const char * format,...) { - log_it(L_DEBUG,"dap_events_socket_write_f %u sock", sc->socket ); + //log_it(L_DEBUG,"dap_events_socket_write_f %u sock", sc->socket ); - pthread_mutex_lock(&sc->write_hold); size_t max_data_size = sizeof(sc->buf_out)-sc->buf_out_size; va_list ap; va_start(ap,format); @@ -395,18 +917,18 @@ size_t dap_events_socket_write_f(dap_events_socket_t *sc, const char * format,.. }else{ log_it(L_ERROR,"Can't write out formatted data '%s'",format); } - pthread_mutex_unlock(&sc->write_hold); + dap_events_socket_set_writable_unsafe(sc, true); return (ret > 0) ? ret : 0; } /** - * @brief dap_events_socket_read Read data from input buffer + * @brief dap_events_socket_pop_from_buf_in Read data from input buffer * @param sc Conn instasnce * @param data Pointer to memory where to store the data * @param data_size Size of data to read * @return Actual bytes number that were read */ -size_t dap_events_socket_read(dap_events_socket_t *sc, void *data, size_t data_size) +size_t dap_events_socket_pop_from_buf_in(dap_events_socket_t *sc, void *data, size_t data_size) { // log_it(L_DEBUG,"dap_events_socket_read %u sock data %X size %u", sc->socket, data, data_size ); diff --git a/dap-sdk/net/core/dap_proc_queue.c b/dap-sdk/net/core/dap_proc_queue.c new file mode 100644 index 0000000000000000000000000000000000000000..d41f6604ca75a55e570d21031dbe733bd8ec1a00 --- /dev/null +++ b/dap-sdk/net/core/dap_proc_queue.c @@ -0,0 +1,101 @@ +/* + * 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 "dap_proc_queue.h" +#include "dap_proc_thread.h" +#define LOG_TAG "dap_proc_queue" + + +typedef struct dap_proc_queue_msg{ + dap_proc_queue_callback_t callback; + void * callback_arg; + bool signal_kill; +} dap_proc_queue_msg_t; + +static void s_queue_esocket_callback( dap_events_socket_t * a_es, void * a_msg); + +/** + * @brief dap_proc_queue_create + * @param a_thread + * @return + */ +dap_proc_queue_t * dap_proc_queue_create(dap_proc_thread_t * a_thread) +{ + dap_proc_queue_t * l_queue = DAP_NEW_Z(dap_proc_queue_t); + 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->_inheritor = l_queue; + return l_queue; +} + +/** + * @brief dap_proc_queue_delete + * @param a_queue + */ +void dap_proc_queue_delete(dap_proc_queue_t * a_queue) +{ + dap_proc_queue_msg_t * l_msg = DAP_NEW_Z(dap_proc_queue_msg_t); + l_msg->signal_kill = true; + dap_events_socket_queue_ptr_send( a_queue->esocket, l_msg ); +} + +/** + * @brief s_queue_esocket_callback + * @param a_es + * @param a_msg + */ +static void s_queue_esocket_callback( dap_events_socket_t * a_es, void * a_msg) +{ + //log_it(L_DEBUG, "New callback in list accepted"); + dap_proc_queue_t * l_queue = (dap_proc_queue_t*) a_es->_inheritor; + dap_proc_queue_msg_t * l_msg = (dap_proc_queue_msg_t*) a_msg; + + // We have callback to add in list + if (l_msg->callback){ + dap_proc_queue_item_t * l_item = DAP_NEW_Z(dap_proc_queue_item_t); + l_item->callback = l_msg->callback; + l_item->callback_arg = l_msg->callback_arg; + l_item->next=l_queue->items; + l_queue->items = l_item; + // Add on top so after call this callback will be executed first + dap_events_socket_queue_ptr_send(l_queue->proc_thread->proc_event,NULL); + //log_it( L_DEBUG, "Sent signal to proc thread that we have callbacks on board"); + } + if (l_msg->signal_kill){ // Say to kill this object and delete its inherior dap_proc_queue_t + a_es->kill_signal = true; + } + DAP_DELETE(l_msg); +} + + +void dap_proc_queue_add_callback(dap_proc_queue_t * a_queue,dap_proc_queue_callback_t a_callback, void * a_callback_arg) +{ + dap_proc_queue_msg_t * l_msg = DAP_NEW_Z(dap_proc_queue_msg_t); + l_msg->callback = a_callback; + l_msg->callback_arg = a_callback_arg; + dap_events_socket_queue_ptr_send( a_queue->esocket, l_msg ); +} + +void dap_proc_queue_add_callback_auto(dap_proc_queue_callback_t a_callback, void * a_callback_arg) +{ + dap_proc_queue_add_callback( dap_proc_thread_get_auto()->proc_queue ,a_callback,a_callback_arg); +} diff --git a/dap-sdk/net/core/dap_proc_thread.c b/dap-sdk/net/core/dap_proc_thread.c new file mode 100644 index 0000000000000000000000000000000000000000..133bf810016f99f8b82807837e288d53b99586aa --- /dev/null +++ b/dap-sdk/net/core/dap_proc_thread.c @@ -0,0 +1,269 @@ +/* + * 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 <assert.h> +#include "dap_server.h" + +#if defined(DAP_EVENTS_CAPS_WEPOLL) +#elif defined(DAP_EVENTS_CAPS_EPOLL) +#include <sys/epoll.h> +#else +#error "Unimplemented poll for this platform" +#endif + +#include "dap_events.h" +#include "dap_events_socket.h" +#include "dap_proc_thread.h" + +#define LOG_TAG "dap_proc_thread" + +static size_t s_threads_count = 0; +static dap_proc_thread_t * s_threads = NULL; +static void * s_proc_thread_function(void * a_arg); + +/** + * @brief dap_proc_thread_init + * @param a_cpu_count 0 means autodetect + * @return + */ +int dap_proc_thread_init(uint32_t a_threads_count){ + 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 (size_t i = 0; i < s_threads_count; i++ ){ + s_threads[i].cpu_id = i; + pthread_cond_init( &s_threads[i].started_cond, NULL ); + pthread_mutex_init( &s_threads[i].started_mutex, NULL ); + pthread_mutex_lock( &s_threads[i].started_mutex ); + int res = pthread_create( &s_threads[i].thread_id,NULL, s_proc_thread_function, &s_threads[i] ); + if (res) { + log_it(L_CRITICAL, "Create thread failed with code %d", res); + pthread_mutex_unlock( &s_threads[i].started_mutex ); + return -1; + } + pthread_cond_wait( &s_threads[i].started_cond, &s_threads[i].started_mutex ); + pthread_mutex_unlock( &s_threads[i].started_mutex ); + } + return 0; +} + +/** + * @brief dap_proc_thread_deinit + */ +void dap_proc_thread_deinit() +{ + // Signal to cancel working threads and wait for finish + 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); + } +} + +/** + * @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() +{ + size_t l_id_min=0; + size_t l_size_min=UINT32_MAX; + for (size_t i = 0; i < s_threads_count; i++ ){ + size_t l_queue_size = 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 s_proc_event_callback + * @param a_esocket + * @param a_value + */ +static void s_proc_event_callback(dap_events_socket_t * a_esocket, void * a_value) +{ + (void) a_value; + //log_it(L_DEBUG, "Proc event callback"); + dap_proc_thread_t * l_thread = (dap_proc_thread_t *) a_esocket->_inheritor; + dap_proc_queue_item_t * l_item = l_thread->proc_queue->items; + dap_proc_queue_item_t * l_item_old = NULL; + bool l_is_anybody_for_repeat=false; + while(l_item){ + bool l_is_finished = l_item->callback(l_thread, l_item->callback_arg); + if (l_is_finished){ + if(l_item_old){ + l_item_old->next = l_item->next; + DAP_DELETE(l_item); + l_item = l_item_old->next; + }else{ + l_thread->proc_queue->items = l_item->next; + DAP_DELETE(l_item); + l_item = l_thread->proc_queue->items; + } + + }else{ + l_item_old = l_item; + l_item=l_item->next; + } + l_is_anybody_for_repeat &= (!l_is_finished); + } + if(l_is_anybody_for_repeat) // Arm event if we have smth to proc again + dap_events_socket_event_signal(a_esocket,1); +} + +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; + pthread_setschedparam(pthread_self(),SCHED_BATCH ,&l_shed_params); + l_thread->proc_queue = dap_proc_queue_create(l_thread); + + + l_thread->proc_event = dap_events_socket_create_type_queue_ptr_unsafe(NULL, s_proc_event_callback); + l_thread->proc_event->_inheritor = l_thread; // we pass thread through it + +#ifdef DAP_EVENTS_CAPS_EPOLL + struct epoll_event l_epoll_events[DAP_MAX_EPOLL_EVENTS], l_ev; + memset(l_epoll_events, 0,sizeof (l_epoll_events)); + + // Create epoll ctl + l_thread->epoll_ctl = epoll_create( DAP_MAX_EPOLL_EVENTS ); + + // add proc queue + l_ev.events = l_thread->proc_queue->esocket->ev_base_flags; + l_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_ev) != 0 ){ + log_it(L_CRITICAL, "Can't add proc queue on epoll ctl"); + return NULL; + } + + // Add proc event + l_ev.events = l_thread->proc_event->ev_base_flags ; + l_ev.data.ptr = l_thread->proc_event; + if( epoll_ctl(l_thread->epoll_ctl, EPOLL_CTL_ADD, l_thread->proc_event->fd , &l_ev) != 0 ){ + log_it(L_CRITICAL, "Can't add proc queue on epoll ctl"); + return NULL; + } + +#else +#error "Unimplemented poll events analog for this platform" +#endif + + //We've started! + pthread_mutex_lock(&l_thread->started_mutex); + pthread_mutex_unlock(&l_thread->started_mutex); + pthread_cond_broadcast(&l_thread->started_cond); + // Main loop + while (! l_thread->signal_kill){ + +#ifdef DAP_EVENTS_CAPS_EPOLL + //log_it(L_DEBUG, "Epoll_wait call"); + int l_selected_sockets = epoll_wait(l_thread->epoll_ctl, l_epoll_events, DAP_MAX_EPOLL_EVENTS, -1); +#else +#error "Unimplemented poll wait analog for this platform" +#endif + //log_it(L_DEBUG,"Proc thread waked up"); + if(l_selected_sockets == -1) { + if( errno == EINTR) + continue; + 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); + break; + } + time_t l_cur_time = time( NULL); + for(int32_t n = 0; n < l_selected_sockets; n++) { + dap_events_socket_t * l_cur; + l_cur = (dap_events_socket_t *) l_epoll_events[n].data.ptr; + uint32_t l_cur_events = l_epoll_events[n].events; + if(!l_cur) { + log_it(L_ERROR, "dap_events_socket NULL"); + continue; + } + l_cur->last_time_active = l_cur_time; + if (l_cur_events & EPOLLERR ){ + char l_buferr[128]; + strerror_r(errno,l_buferr, sizeof (l_buferr)); + log_it(L_ERROR,"Some error happend in proc thread #%u: %s", l_thread->cpu_id, l_buferr); + } + if (l_cur_events & EPOLLERR ){ + int l_errno = errno; + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf,sizeof (l_errbuf)); + log_it(L_ERROR,"Some error with %d socket: %s(%d)", l_cur->socket, l_errbuf, l_errno); + if(l_cur->callbacks.error_callback) + l_cur->callbacks.error_callback(l_cur,errno); + } + if (l_cur_events & EPOLLIN ){ + switch (l_cur->type) { + case DESCRIPTOR_TYPE_QUEUE: + dap_events_socket_queue_proc_input_unsafe(l_cur); + 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"); } + } + } + if(l_cur->kill_signal){ +#ifdef DAP_EVENTS_CAPS_EPOLL + 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); +#else +#error "Unimplemented poll ctl analog for this platform" +#endif + } + + } + } + log_it(L_NOTICE, "Stop processing thread #%u", l_thread->cpu_id); + return NULL; +} + + diff --git a/dap-sdk/net/core/dap_server.c b/dap-sdk/net/core/dap_server.c index bbc3bbd5e526c50636b85f3bec4531814a7a8e32..6f49c8298997a1de133f432a7c9449a25fd95500 100644 --- a/dap-sdk/net/core/dap_server.c +++ b/dap-sdk/net/core/dap_server.c @@ -1,847 +1,270 @@ -/* - Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc - All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define __USE_GNU - -#include <string.h> -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <stdint.h> - -//#include <errno.h> -#include <signal.h> -#include <stdint.h> -#include <stdatomic.h> - -#ifndef _WIN32 -#include <arpa/inet.h> -#include <netinet/in.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <errno.h> -#include <netdb.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/epoll.h> -#include <sys/timerfd.h> -#else -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include <pthread.h> -#endif - -#include <sched.h> - -#if 0 -#define NI_NUMERICHOST 1 /* Don't try to look up hostname. */ -#define NI_NUMERICSERV 2 /* Don't convert port number to name. */ -#define NI_NOFQDN 4 /* Only return nodename portion. */ -#define NI_NAMEREQD 8 /* Don't return numeric addresses. */ -#define NI_DGRAM 16 /* Look up UDP service rather than TCP. */ -#endif - -#include "dap_common.h" -#include "dap_server.h" -#include "dap_strfuncs.h" - -#define LOG_TAG "server" - -#define DAP_MAX_THREAD_EVENTS 8192 -#define DAP_MAX_THREADS 16 - -#define SOCKET_TIMEOUT_TIME 300 -#define SOCKETS_TIMEOUT_CHECK_PERIOD 15 - -static uint32_t _count_threads = 0; -static uint32_t epoll_max_events = 0; -static bool bQuitSignal = false; -static bool moduleInit = false; - -static struct epoll_event *threads_epoll_events = NULL; -static dap_server_t *_current_run_server = NULL; - -static void read_write_cb( dap_client_remote_t *dap_cur, int32_t revents ); -void *thread_loop( void *arg ); - -dap_server_thread_t dap_server_threads[ DAP_MAX_THREADS ]; - -/* -=============================================== - get_epoll_max_user_watches( ) - - return max epoll() event watches -=============================================== -*/ -static uint32_t get_epoll_max_user_watches( void ) -{ - static const char *maxepollpath = "/proc/sys/fs/epoll/max_user_watches"; - uint32_t v = 0, len; - char str[32]; - - FILE *fp = fopen( maxepollpath, "r" ); - if ( !fp ) { -// printf("can't open %s\n", maxepollpath ); - return v; - } - - len = fread( &str[0], 1, 31, fp ); - if ( !len ) { - return v; - } - - str[ len ] = 0; - v = atoi( str ); - - return v; -} - -/* -=============================================== - dap_server_init( ) - - Init server module - return Zero if ok others if no -=============================================== -*/ -int32_t dap_server_init( uint32_t count_threads ) -{ - dap_server_thread_t *dap_thread; - moduleInit = true; - - #ifndef _WIN32 - signal( SIGPIPE, SIG_IGN ); - #endif - - if ( count_threads > DAP_MAX_THREADS ) - count_threads = DAP_MAX_THREADS; - - _count_threads = count_threads; - log_it( L_NOTICE, "dap_server_init() threads %u", count_threads ); - - epoll_max_events = get_epoll_max_user_watches( ); - if ( epoll_max_events > DAP_MAX_THREAD_EVENTS ) - epoll_max_events = DAP_MAX_THREAD_EVENTS; - - threads_epoll_events = (struct epoll_event *)malloc( sizeof(struct epoll_event) * _count_threads * epoll_max_events ); - if ( !threads_epoll_events ) - goto err; - - memset( threads_epoll_events, 0, sizeof(struct epoll_event) * _count_threads * epoll_max_events ); - - dap_thread = &dap_server_threads[0]; - memset( dap_thread, 0, sizeof(dap_server_thread_t) * DAP_MAX_THREADS ); - - for ( uint32_t i = 0; i < _count_threads; ++i, ++dap_thread ) { - #ifndef _WIN32 - dap_thread->epoll_fd = -1; - #else - dap_thread->epoll_fd = (void*)-1; - #endif - dap_thread->thread_num = i; - dap_thread->epoll_events = &threads_epoll_events[ i * epoll_max_events ]; - - pthread_mutex_init( &dap_thread->mutex_dlist_add_remove, NULL ); - pthread_mutex_init( &dap_thread->mutex_on_hash, NULL ); - } - - log_it( L_NOTICE, "Initialized socket server module" ); - - dap_client_remote_init( ); - - - pthread_t thread_listener[ DAP_MAX_THREADS ]; - - for( uint32_t i = 0; i < _count_threads; ++i ) { - - EPOLL_HANDLE efd = epoll_create1( 0 ); - if ( (intptr_t)efd == -1 ) { - log_it( L_ERROR, "Can't create epoll instance" ); - goto err; - } - dap_server_threads[ i ].epoll_fd = efd; - dap_server_threads[ i ].thread_num = i; - } - - for( uint32_t i = 0; i < _count_threads; ++i ) { - pthread_create( &thread_listener[i], NULL, thread_loop, &dap_server_threads[i] ); - } - - - return 0; - -err:; - - dap_server_deinit( ); - return 1; -} - -void dap_server_loop_stop( void ){ - bQuitSignal = true; -} - -/* -========================================================= - dap_server_deinit( ) - - Deinit server module -========================================================= -*/ -void dap_server_deinit( void ) -{ - if (moduleInit) { - dap_client_remote_t *dap_cur, *tmp; - dap_server_thread_t *t = &dap_server_threads[0]; - - dap_client_remote_deinit( ); - - if ( threads_epoll_events ) { - free( threads_epoll_events ); - - for ( uint32_t i = 0; i < _count_threads; ++i, ++t ) { - - HASH_ITER( hh, t->hclients, dap_cur, tmp ) - dap_client_remote_remove( dap_cur ); - - pthread_mutex_destroy( &dap_server_threads[i].mutex_on_hash ); - pthread_mutex_destroy( &dap_server_threads[i].mutex_dlist_add_remove ); - - if ( (intptr_t)dap_server_threads[ i ].epoll_fd != -1 ) { - #ifndef _WIN32 - close( dap_server_threads[ i ].epoll_fd ); - #else - epoll_close( dap_server_threads[ i ].epoll_fd ); - #endif - } - } - } - moduleInit = false; - } -} - -/* -========================================================= - dap_server_new( ) - - Creates new empty instance of dap_server_t -========================================================= -*/ -dap_server_t *dap_server_new( void ) -{ - return (dap_server_t *)calloc( 1, sizeof(dap_server_t) ); -} - -/* -========================================================= - dap_server_new( ) - - Delete server instance -========================================================= -*/ -void dap_server_delete( dap_server_t *sh ) -{ - if ( !sh ) return; - - if( sh->address ) - free( sh->address ); - - if( sh->server_delete_callback ) - sh->server_delete_callback( sh, NULL ); - - if ( sh->_inheritor ) - free( sh->_inheritor ); - - free( sh ); -} - -/* -========================================================= - set_nonblock_socket( ) -========================================================= -*/ -int32_t set_nonblock_socket( int32_t fd ) -{ -#ifdef _WIN32 - unsigned long arg = 1; - return ioctlsocket( fd, FIONBIO, &arg ); -#else - int32_t flags; - - flags = fcntl( fd, F_GETFL ); - flags |= O_NONBLOCK; - - return fcntl( fd, F_SETFL, flags ); -#endif -} - - -/* -========================================================= - get_thread_min_connections( ) - - return number thread which has minimum open connections -========================================================= -*/ -static inline uint32_t get_thread_index_min_connections( ) -{ - uint32_t min = 0; - - for( uint32_t i = 1; i < _count_threads; i ++ ) { - if ( dap_server_threads[min].connections_count > dap_server_threads[i].connections_count ) { - min = i; - } - } - - return min; -} - -/* -========================================================= - print_online( ) - -========================================================= -*/ -static inline void print_online() -{ - for( uint32_t i = 0; i < _count_threads; i ++ ) { - log_it( L_INFO, "Thread number: %u, count: %u", i, dap_server_threads[i].connections_count ); - } -} - -void dap_server_kill_socket( dap_client_remote_t *dcr ) -{ - if ( !dcr ) { - log_it( L_ERROR, "dap_server_kill_socket( NULL )" ); - return; - } - - dap_server_thread_t *dsth = &dap_server_threads[ dcr->tn ]; - - pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - - if ( dcr->kill_signal ) { - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - return; - } - - log_it( L_DEBUG, "KILL %u socket! [ thread %u ]", dcr->socket, dcr->tn ); - - dcr->kill_signal = true; - - DL_LIST_ADD_NODE_HEAD( dsth->dap_clients_to_kill, dcr, kprev, knext, dsth->to_kill_count ); - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - - return; -} - -/* -========================================================= - dap_server_add_socket( ) - -========================================================= -*/ -dap_client_remote_t *dap_server_add_socket( int32_t fd, int32_t forced_thread_n ) -{ - uint32_t tn = (forced_thread_n == -1) ? get_thread_index_min_connections( ) : forced_thread_n; - dap_server_thread_t *dsth = &dap_server_threads[ tn ]; - dap_client_remote_t *dcr = dap_client_remote_create( _current_run_server, fd, dsth ); - - if ( !dcr ) { - log_it( L_ERROR, "accept %d dap_client_remote_create() == NULL", fd ); -// pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - return dcr; - } - - log_it( L_DEBUG, "accept %d Client, thread %d", fd, tn ); - - pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - - - DL_APPEND( dsth->dap_remote_clients, dcr ); - dsth->connections_count ++; - if ( epoll_ctl( dsth->epoll_fd, EPOLL_CTL_ADD, fd, &dcr->pevent) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed 005" ); - } - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - - return dcr; -} - -/* -========================================================= - dap_server_remove_socket( ) - -========================================================= -*/ -void dap_server_remove_socket( dap_client_remote_t *dcr ) -{ - if ( !dcr ) { - log_it( L_ERROR, "dap_server_remove_socket( NULL )" ); - return; - } - - uint32_t tn = dcr->tn; - log_it( L_DEBUG, "dap_server_remove_socket %u thread %u", dcr->socket, tn ); - - dap_server_thread_t *dsth = &dap_server_threads[ tn ]; - - if ( epoll_ctl( dcr->efd, EPOLL_CTL_DEL, dcr->socket, &dcr->pevent ) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll_fd" ); - -// pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - DL_DELETE( dsth->dap_remote_clients, dcr ); - dsth->connections_count --; - -// pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - -// log_it( L_DEBUG, "dcr = %X", dcr ); -} - -static void s_socket_all_check_activity( uint32_t tn, time_t cur_time ) -{ - dap_client_remote_t *dcr, *tmp; - dap_server_thread_t *dsth = &dap_server_threads[ tn ]; - -// log_it( L_INFO,"s_socket_info_all_check_activity() on thread %u", tn ); - - pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - - DL_FOREACH_SAFE( dsth->dap_remote_clients, dcr, tmp ) { - - if ( !dcr->kill_signal && cur_time >= dcr->last_time_active + SOCKET_TIMEOUT_TIME && !dcr->no_close ) { - - log_it( L_INFO, "Socket %u timeout, closing...", dcr->socket ); - - if ( epoll_ctl( dcr->efd, EPOLL_CTL_DEL, dcr->socket, &dcr->pevent ) == -1 ) - log_it( L_ERROR,"Can't remove event socket's handler from the epoll_fd" ); - - DL_DELETE( dsth->dap_remote_clients, dcr ); - dsth->connections_count --; - - dap_client_remote_remove( dcr ); - } - } - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); -} - -/* -========================================================= - read_write_cb( ) - -========================================================= -*/ -static void read_write_cb( dap_client_remote_t *dap_cur, int32_t revents ) -{ -// log_it( L_NOTICE, "[THREAD %u] read_write_cb fd %u revents %u", dap_cur->tn, dap_cur->socket, revents ); -// sleep( 5 ); // ????????? - - if( !dap_cur ) { - - log_it( L_ERROR, "read_write_cb: dap_client_remote NULL" ); - return; - } - - if ( revents & EPOLLIN ) { - -// log_it( L_DEBUG, "[THREAD %u] socket read %d ", dap_cur->tn, dap_cur->socket ); - - int32_t bytes_read = recv( dap_cur->socket, - dap_cur->buf_in + dap_cur->buf_in_size, - sizeof(dap_cur->buf_in) - dap_cur->buf_in_size, - 0 ); - if ( bytes_read > 0 ) { -// log_it( L_DEBUG, "[THREAD %u] read %u socket client said: %s", dap_cur->tn, bytes_read, dap_cur->buf_in + dap_cur->buf_in_size ); - - dap_cur->buf_in_size += (size_t)bytes_read; - dap_cur->upload_stat.buf_size_total += (size_t)bytes_read; - -// log_it( L_DEBUG, "[THREAD %u] read %u socket read callback()", dap_cur->tn, bytes_read ); - _current_run_server->client_read_callback( dap_cur ,NULL ); - } - else if ( bytes_read < 0 ) { - log_it( L_ERROR,"Bytes read Error %s",strerror(errno) ); - if ( strcmp(strerror(errno),"Resource temporarily unavailable") != 0 ) - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - } - else { // bytes_read == 0 - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it( L_DEBUG, "0 bytes read" ); - } - } - - if( ( (revents & EPOLLOUT) || (dap_cur->flags & DAP_SOCK_READY_TO_WRITE) ) && !(dap_cur->flags & DAP_SOCK_SIGNAL_CLOSE) ) { - -// log_it(L_DEBUG, "[THREAD %u] socket write %d ", dap_cur->tn, dap_cur->socket ); - _current_run_server->client_write_callback( dap_cur, NULL ); // Call callback to process write event - - if( dap_cur->buf_out_size == 0 ) { - //log_it(L_DEBUG, "dap_cur->buf_out_size = 0, set ev_read watcher " ); - - dap_cur->pevent.events = EPOLLIN | EPOLLERR; - if( epoll_ctl(dap_cur->efd, EPOLL_CTL_MOD, dap_cur->socket, &dap_cur->pevent) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed 003" ); - } - } - else { -// log_it(L_DEBUG, "[THREAD %u] send dap_cur->buf_out_size = %u , %s", dap_cur->tn, dap_cur->buf_out_size, dap_cur->buf_out ); - - size_t total_sent = dap_cur->buf_out_offset; - - while ( total_sent < dap_cur->buf_out_size ) { - //log_it(DEBUG, "Output: %u from %u bytes are sent ", total_sent, dap_cur->buf_out_size); - ssize_t bytes_sent = send( dap_cur->socket, - dap_cur->buf_out + total_sent, - dap_cur->buf_out_size - total_sent, - MSG_DONTWAIT | MSG_NOSIGNAL ); - if( bytes_sent < 0 ) { - if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { - dap_cur->pevent.events = EPOLLOUT | EPOLLERR; - if( epoll_ctl(dap_cur->efd, EPOLL_CTL_MOD, dap_cur->socket, &dap_cur->pevent) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed..." ); - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - break; - } - } else { - log_it(L_ERROR,"[THREAD %u] Error occured in send() function %s", dap_cur->tn, strerror(errno) ); - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - break; - } - } - - total_sent += (size_t)bytes_sent; - dap_cur->download_stat.buf_size_total += (size_t)bytes_sent; - } - -// log_it( L_ERROR, "check !" ); - - if( total_sent == dap_cur->buf_out_size ) { - dap_cur->buf_out_offset = dap_cur->buf_out_size = 0; - } - else { - dap_cur->buf_out_offset = total_sent; - } - } // else - } // write - - -// log_it(L_ERROR,"OPA !") ; -// Sleep(200); - -// if ( (dap_cur->flags & DAP_SOCK_SIGNAL_CLOSE) && !dap_cur->no_close ) { -// log_it(L_ERROR,"Close signal" ); - -// dap_server_remove_socket( dap_cur ); -// dap_client_remote_remove( dap_cur, _current_run_server ); -// } - -} - - -/* -========================================================= - dap_server_listen( ) - - Create server_t instance and start to listen tcp port with selected address - -========================================================= -*/ -dap_server_t *dap_server_listen( const char *addr, uint16_t port, dap_server_type_t type ) -{ - dap_server_t* sh = dap_server_new( ); - - sh->socket_listener = -111; - - if( type == DAP_SERVER_TCP ) - sh->socket_listener = socket( AF_INET, SOCK_STREAM, 0 ); - else { - dap_server_delete( sh ); - return NULL; - } - - if ( set_nonblock_socket(sh->socket_listener) == -1 ) { - log_it( L_WARNING, "error server socket nonblock" ); - dap_server_delete( sh ); - return NULL; - } - - if ( sh->socket_listener < 0 ) { - log_it ( L_ERROR,"Socket error %s", strerror(errno) ); - dap_server_delete( sh ); - return NULL; - } - - log_it( L_NOTICE," Socket created..." ); - - int32_t reuse = 1; - - if ( reuse ) - if ( setsockopt( sh->socket_listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0 ) - log_it( L_WARNING, "Can't set up REUSEADDR flag to the socket" ); - - sh->listener_addr.sin_family = AF_INET; - sh->listener_addr.sin_port = htons( port ); - inet_pton( AF_INET, addr, &(sh->listener_addr.sin_addr) ); - - if( bind(sh->socket_listener, (struct sockaddr *)&(sh->listener_addr), sizeof(sh->listener_addr)) < 0 ) { - log_it( L_ERROR,"Bind error: %s",strerror(errno) ); - dap_server_delete( sh ); - return NULL; - } - - log_it( L_INFO,"Binded %s:%u", addr, port ); - listen( sh->socket_listener, DAP_MAX_THREAD_EVENTS * _count_threads ); - - return sh; -} - - -/* -========================================================= - thread_loop( ) - - Server listener thread loop -========================================================= -*/ -void *thread_loop( void *arg ) -{ - dap_client_remote_t *dap_cur, *tmp; - dap_server_thread_t *dsth = (dap_server_thread_t *)arg; - uint32_t tn = dsth->thread_num; - EPOLL_HANDLE efd = dsth->epoll_fd; - struct epoll_event *events = dsth->epoll_events; - time_t next_time_timeout_check = time( NULL ) + SOCKETS_TIMEOUT_CHECK_PERIOD; - - log_it(L_NOTICE, "Start loop listener socket thread %u efd %u", tn, efd ); - - #ifndef _WIN32 - cpu_set_t mask; - CPU_ZERO( &mask ); - CPU_SET( tn, &mask ); - - int err; - int l_sock_err = 0, l_sock_err_size = sizeof(l_sock_err); -#ifndef ANDROID - err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask); -#else - err = sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &mask); -#endif - if (err) { - log_it( L_CRITICAL, "Error pthread_setaffinity_np() You really have %d or more core in CPU?", tn ); - abort(); - } - #else - - if ( !SetThreadAffinityMask( GetCurrentThread(), (DWORD_PTR)(1 << tn) ) ) { - log_it( L_CRITICAL, "Error pthread_setaffinity_np() You really have %d or more core in CPU?", tn ); - abort(); - } - - #endif - - do { - - int32_t n = epoll_wait( efd, events, DAP_MAX_THREAD_EVENTS, 1000 ); - -// log_it(L_WARNING,"[THREAD %u] epoll events %u", tn, n ); -// Sleep(300); - - if ( bQuitSignal ) - break; - - if ( n < 0 ) { - if ( errno == EINTR ) - continue; - break; - } - - time_t cur_time = time( NULL ); - - for ( int32_t i = 0; i < n; ++ i ) { - -// log_it(L_ERROR,"[THREAD %u] process epoll event %u", tn, i ); - dap_cur = (dap_client_remote_t *)events[i].data.ptr; - - if ( !dap_cur ) { - log_it( L_ERROR,"dap_client_remote_t NULL" ); - continue; - } - - dap_cur->last_time_active = cur_time; - if( events[i].events & EPOLLERR ) { - getsockopt(dap_cur->socket, SOL_SOCKET, SO_ERROR, (void *)&l_sock_err, (socklen_t *)&l_sock_err_size); - log_it( L_ERROR,"Socket %u error: %s, remove it" , dap_cur->socket, strerror(l_sock_err)); - dap_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; - } - set_nonblock_socket(dap_cur->socket); - if ( !(dap_cur->flags & DAP_SOCK_SIGNAL_CLOSE) || dap_cur->no_close ) - read_write_cb( dap_cur, events[i].events ); - - if ( (dap_cur->flags & DAP_SOCK_SIGNAL_CLOSE) && !dap_cur->no_close ) { - - pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - - if ( dap_cur->kill_signal ) { - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - continue; - } - -// pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); -// dap_server_kill_socket( dap_cur ); -// continue; - - log_it( L_INFO, "Got signal to close %u socket, closing...[ %u ]", dap_cur->socket, tn ); - - dap_server_remove_socket( dap_cur ); - dap_client_remote_remove( dap_cur ); - - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - } - - } // for - - if ( cur_time >= next_time_timeout_check ) { - - s_socket_all_check_activity( tn, cur_time ); - next_time_timeout_check = cur_time + SOCKETS_TIMEOUT_CHECK_PERIOD; - } - - pthread_mutex_lock( &dsth->mutex_dlist_add_remove ); - if ( !dsth->to_kill_count ) { - - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - continue; - } - - dap_cur = dsth->dap_clients_to_kill; - - do { - - if ( dap_cur->no_close ) { - dap_cur = dap_cur->knext; - continue; - } - - log_it( L_INFO, "Kill %u socket ...............[ thread %u ]", dap_cur->socket, tn ); - - tmp = dap_cur->knext; - DL_LIST_REMOVE_NODE( dsth->dap_clients_to_kill, dap_cur, kprev, knext, dsth->to_kill_count ); - - dap_server_remove_socket( dap_cur ); - dap_client_remote_remove( dap_cur ); - dap_cur = tmp; - - } while ( dap_cur ); - - log_it( L_INFO, "[ Thread %u ] coneections: %u, to kill: %u", tn, dsth->connections_count, dsth->to_kill_count ); - pthread_mutex_unlock( &dsth->mutex_dlist_add_remove ); - - } while( !bQuitSignal ); - - return NULL; -} - -/* -========================================================= - dap_server_loop( ) - - Main server loop - - @param a_server Server instance - @return Zero if ok others if not -========================================================= -*/ -int32_t dap_server_loop( dap_server_t *d_server ) -{ - int errCode = 0; - - if(d_server == NULL){ - log_it(L_ERROR, "Server is NULL"); - return -1; - } - - _current_run_server = d_server; - - EPOLL_HANDLE efd = epoll_create1( 0 ); - if ( (intptr_t)efd == -1 ) { - return -10; - } - - struct epoll_event pev; - struct epoll_event events[ 16 ]; - - memset(&pev, 0, sizeof(pev)); - pev.events = EPOLLIN | EPOLLERR; - pev.data.fd = d_server->socket_listener; - - if( epoll_ctl( efd, EPOLL_CTL_ADD, d_server->socket_listener, &pev) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed 004" ); - return -20; - } - - while( !bQuitSignal && errCode == 0 ) { - int32_t n = epoll_wait( efd, &events[0], 16, 1000 ); - - if ( bQuitSignal ) - break; - - if ( n < 0 ) { - if ( errno == EINTR ) - continue; - log_it( L_ERROR, "Server wakeup on error: %i", errno ); - errCode = -30; - } - - for( int32_t i = 0; i < n && errCode == 0; ++i ) { - - if ( events[i].events & EPOLLIN ) { - int client_fd = accept( events[i].data.fd, 0, 0 ); - - if ( client_fd < 0 ) { - log_it( L_ERROR, "accept_cb: error accept socket"); - continue; - } - - set_nonblock_socket( client_fd ); - dap_server_add_socket( client_fd, -1 ); - } - else if( events[i].events & EPOLLERR ) { - log_it( L_ERROR, "Server socket error event" ); - errCode = -40; - } - - } // for - } // while - - if (efd != -1) { - #ifndef _WIN32 - close( efd ); - #else - epoll_close( efd ); - #endif - } - - return errCode; -} +/* + * 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 <arpa/inet.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <sys/epoll.h> + +#include <netdb.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> + +#include <stdio.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <errno.h> +#include <signal.h> +#include <sys/timerfd.h> +#include <utlist.h> +#if ! defined(_GNU_SOURCE) +#define _GNU_SOURCE +#endif +#if ! defined (__USE_GNU) +#define __USE_GNU +#endif +#include <sched.h> +#include "dap_common.h" +#include "dap_config.h" +#include "dap_server.h" +#include "dap_worker.h" +#include "dap_events.h" + +#define LOG_TAG "dap_server" + +static dap_events_socket_t * s_es_server_create(dap_events_t * a_events, int a_sock, + dap_events_socket_callbacks_t * a_callbacks, dap_server_t * a_server); + +static void s_es_server_accept(dap_events_socket_t *a_es, int a_remote_socket, struct sockaddr* a_remote_addr); +static void s_es_server_error(dap_events_socket_t *a_es, int a_arg); +static void s_es_server_new(dap_events_socket_t *a_es, void * a_arg); +static void s_server_delete(dap_server_t * a_server); +/** + * @brief dap_server_init + * @return + */ +int dap_server_init() +{ + log_it(L_NOTICE,"Server module init"); + return 0; +} + +/** + * @brief dap_server_deinit + */ +void dap_server_deinit() +{ +} + +/** + * @brief dap_server_delete + * @param a_server + */ +void s_server_delete(dap_server_t * a_server) +{ + if(a_server->delete_callback) + a_server->delete_callback(a_server,NULL); + if( a_server->address ) + DAP_DELETE(a_server->address ); + if( a_server->_inheritor ) + DAP_DELETE( a_server->_inheritor ); + DAP_DELETE(a_server); +} + +/** + * @brief dap_server_new + * @param a_events + * @param a_addr + * @param a_port + * @param a_type + * @return + */ +dap_server_t* dap_server_new(dap_events_t *a_events, const char * a_addr, uint16_t a_port, dap_server_type_t a_type) +{ + assert(a_events); + dap_server_t *l_server = DAP_NEW_Z(dap_server_t); + + l_server->socket_listener=-1; // To diff it from 0 fd + l_server->address = a_addr? strdup( a_addr) : strdup("0.0.0.0"); // If NULL we listen everything + l_server->port = a_port; + l_server->type = a_type; + + if(l_server->type == DAP_SERVER_TCP) + l_server->socket_listener = socket(AF_INET, SOCK_STREAM, 0); + + if (l_server->socket_listener < 0) { + int l_errno = errno; + log_it (L_ERROR,"Socket error %s (%d)",strerror(l_errno), l_errno); + DAP_DELETE(l_server); + return NULL; + } + + log_it(L_NOTICE,"Listen socket %d created...", l_server->socket_listener); + int reuse=1; + + if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) + log_it(L_WARNING, "Can't set up REUSEADDR flag to the socket"); +#ifdef SO_REUSEPORT + if (setsockopt(l_server->socket_listener, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) + log_it(L_WARNING, "Can't set up REUSEPORT flag to the socket"); +#endif + +//create socket + l_server->listener_addr.sin_family = AF_INET; + l_server->listener_addr.sin_port = htons(l_server->port); + inet_pton(AF_INET, l_server->address, &(l_server->listener_addr.sin_addr)); + + if(bind (l_server->socket_listener, (struct sockaddr *) &(l_server->listener_addr), sizeof(l_server->listener_addr)) < 0){ + log_it(L_ERROR,"Bind error: %s",strerror(errno)); + close(l_server->socket_listener); + DAP_DELETE(l_server); + return NULL; + }else{ + log_it(L_INFO,"Binded %s:%u",l_server->address,l_server->port); + listen(l_server->socket_listener, SOMAXCONN); + } + + fcntl( l_server->socket_listener, F_SETFL, O_NONBLOCK); + pthread_mutex_init(&l_server->started_mutex,NULL); + pthread_cond_init(&l_server->started_cond,NULL); + + + + dap_events_socket_callbacks_t l_callbacks; + memset(&l_callbacks,0,sizeof (l_callbacks)); + l_callbacks.new_callback = s_es_server_new; + l_callbacks.accept_callback = s_es_server_accept; + l_callbacks.error_callback = s_es_server_error; + + for(size_t l_worker_id = 0; l_worker_id < dap_events_worker_get_count() ; l_worker_id++){ + dap_worker_t *l_w = dap_events_worker_get(l_worker_id); + assert(l_w); + dap_events_socket_t * l_es = dap_events_socket_wrap2( l_server, a_events, l_server->socket_listener, &l_callbacks); + + if ( l_es){ + l_es->type = DESCRIPTOR_TYPE_SOCKET_LISTENING; +#ifdef DAP_EVENTS_CAPS_EPOLL + // Prepare for multi thread listening + l_es->ev_base_flags = EPOLLET| EPOLLIN | EPOLLEXCLUSIVE; +#endif + l_es->_inheritor = l_server; + pthread_mutex_lock(&l_server->started_mutex); + dap_worker_add_events_socket( l_es, l_w ); + pthread_cond_wait(&l_server->started_cond, &l_server->started_mutex); + pthread_mutex_unlock(&l_server->started_mutex); + } else{ + log_it(L_WARNING, "Can't wrap event socket for %s:%u server", a_addr, a_port); + return NULL; + } + } + return l_server; +} + +/** + * @brief s_es_server_new + * @param a_es + * @param a_arg + */ +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); + 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); + pthread_cond_broadcast( &l_server->started_cond); +} + +/** + * @brief s_es_server_error + * @param a_es + * @param a_arg + */ +static void s_es_server_error(dap_events_socket_t *a_es, int a_arg) +{ + (void) a_arg; + (void) a_es; + char l_buf[128]; + strerror_r(errno, l_buf, sizeof (l_buf)); + log_it(L_WARNING, "Listening socket error: %s, ", l_buf); +} + +/** + * @brief s_es_server_accept + * @param a_events + * @param a_remote_socket + * @param a_remote_addr + */ +static void s_es_server_accept(dap_events_socket_t *a_es, int a_remote_socket, struct sockaddr *a_remote_addr) +{ + socklen_t a_remote_addr_size = sizeof(*a_remote_addr); + a_es->buf_in_size = 0; // It should be 1 so we reset it to 0 + //log_it(L_DEBUG, "Server socket %d is active",i); + dap_server_t * l_server = (dap_server_t*) a_es->_inheritor; + assert(l_server); + + 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 %d from %d)", 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->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 + , sizeof(l_es_new->hostaddr),l_es_new->service,sizeof(l_es_new->service), + NI_NUMERICHOST | NI_NUMERICSERV); + + log_it(L_INFO,"Connection accepted from %s (%s)", l_es_new->hostaddr, l_es_new->service ); + dap_worker_add_events_socket_auto(l_es_new); +} + + +/** + * @brief s_esocket_new + * @param a_events + * @param a_sock + * @param a_callbacks + * @param a_server + * @return + */ +static dap_events_socket_t * s_es_server_create(dap_events_t * a_events, int a_sock, + dap_events_socket_callbacks_t * a_callbacks, dap_server_t * a_server) +{ + dap_events_socket_t * ret = NULL; + if (a_sock > 0) { + // set it nonblock + //fcntl(a_sock, F_SETFL, O_NONBLOCK); + + ret = dap_events_socket_wrap_no_add(a_events, a_sock, a_callbacks); + ret->is_dont_reset_write_flag = true; + ret->type = DESCRIPTOR_TYPE_SOCKET; + ret->server = a_server; + + } else { + log_it(L_CRITICAL,"Accept error: %s",strerror(errno)); + } + return ret; +} diff --git a/dap-sdk/net/core/dap_timerfd.c b/dap-sdk/net/core/dap_timerfd.c index 89bf5f116b86707e539d67918356742a984d88c4..f2cc746622a5bf2c312f710b4327de38d48b586c 100644 --- a/dap-sdk/net/core/dap_timerfd.c +++ b/dap-sdk/net/core/dap_timerfd.c @@ -1,27 +1,26 @@ /* * Authors: * Alexander Lysikov <alexander.lysikov@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain + * DeM Labs Ltd. https://demlabs.net * Copyright (c) 2020 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) 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 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 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. + 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 based project. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef WIN32 + 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/>. +*/ +#ifdef DAP_OS_UNIX #include <stdint.h> #include <stdbool.h> #include <errno.h> @@ -33,38 +32,14 @@ #include <inttypes.h> #include "dap_common.h" +#include "dap_events.h" +#include "dap_worker.h" #include "dap_events_socket.h" #include "dap_timerfd.h" #define LOG_TAG "dap_timerfd" +static void s_es_callback_timer(struct dap_events_socket *a_event_sock); -void callback_timerfd_read(struct dap_events_socket *a_event_sock, void * arg) -{ - uint64_t l_ptiu64; - size_t l_read_ret; - do { - l_read_ret = dap_events_socket_read(a_event_sock, &l_ptiu64, sizeof(l_ptiu64)); - - if(l_read_ret > 0) { - dap_timerfd_t *l_timerfd = a_event_sock->_inheritor; - //printf("\nread() returned %d, %d\n", l_ptiu64, l_read_ret); - struct itimerspec l_ts; - // first expiration in 0 seconds after times start - l_ts.it_interval.tv_sec = 0; - l_ts.it_interval.tv_nsec = 0; - // timeout for timer - l_ts.it_value.tv_sec = l_timerfd->timeout_ms / 1000; - l_ts.it_value.tv_nsec = (l_timerfd->timeout_ms % 1000) * 1000000; - if(timerfd_settime(l_timerfd->tfd, 0, &l_ts, NULL) < 0) { - log_it(L_WARNING, "callback_timerfd_read() failed: timerfd_settime() errno=%d\n", errno); - } - // run user's callback - if(l_timerfd->callback) - l_timerfd->callback(l_timerfd->callback_arg); - } - } while(l_read_ret > 0); - dap_events_socket_set_readable(a_event_sock, true); -} /** * @brief dap_events_socket_init Init clients module @@ -82,7 +57,21 @@ int dap_timerfd_init() * @param a_callback * @return new allocated dap_timerfd_t structure or NULL if error */ -dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t *a_callback, void *a_callback_arg) +dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg) +{ + return dap_timerfd_start_on_worker(dap_events_worker_get_auto(), a_timeout_ms, a_callback, a_callback_arg ); +} + +/** + * @brief dap_timerfd_start_on_worker + * @param a_worker + * @param a_timeout_ms + * @param a_callback + * @param a_callback_arg + * @return + */ +dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg) + { struct itimerspec l_ts; int l_tfd = timerfd_create(CLOCK_MONOTONIC, 0); @@ -106,15 +95,12 @@ dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t * dap_timerfd_t *l_timerfd = DAP_NEW(dap_timerfd_t); // create events_socket for timer file descriptor - static dap_events_socket_callbacks_t l_s_callbacks = { - .read_callback = callback_timerfd_read, - .write_callback = NULL, - .error_callback = NULL, - .delete_callback = NULL - }; - dap_events_socket_t * l_events_socket = dap_events_socket_wrap_no_add(NULL, l_tfd, &l_s_callbacks); - l_events_socket->type = DESCRIPTOR_TYPE_FILE; - dap_events_socket_create_after(l_events_socket); + dap_events_socket_callbacks_t l_s_callbacks; + memset(&l_s_callbacks,0,sizeof (l_s_callbacks)); + l_s_callbacks.timer_callback = s_es_callback_timer; + + dap_events_socket_t * l_events_socket = dap_events_socket_wrap_no_add(a_worker->events, l_tfd, &l_s_callbacks); + l_events_socket->type = DESCRIPTOR_TYPE_TIMER; // pass l_timerfd to events_socket l_events_socket->_inheritor = l_timerfd; @@ -124,29 +110,45 @@ dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t * l_timerfd->events_socket = l_events_socket; l_timerfd->callback = a_callback; l_timerfd->callback_arg = a_callback_arg; + dap_worker_add_events_socket(l_events_socket, a_worker); + return l_timerfd; } +/** + * @brief s_es_callback_timer + * @param a_event_sock + */ +static void s_es_callback_timer(struct dap_events_socket *a_event_sock) +{ + uint64_t l_ptiu64; + dap_timerfd_t *l_timerfd = a_event_sock->_inheritor; + //printf("\nread() returned %d, %d\n", l_ptiu64, l_read_ret); + struct itimerspec l_ts; + // first expiration in 0 seconds after times start + l_ts.it_interval.tv_sec = 0; + l_ts.it_interval.tv_nsec = 0; + // timeout for timer + l_ts.it_value.tv_sec = l_timerfd->timeout_ms / 1000; + l_ts.it_value.tv_nsec = (l_timerfd->timeout_ms % 1000) * 1000000; + if(timerfd_settime(l_timerfd->tfd, 0, &l_ts, NULL) < 0) { + log_it(L_WARNING, "callback_timerfd_read() failed: timerfd_settime() errno=%d\n", errno); + } + // run user's callback + if(l_timerfd->callback) + l_timerfd->callback(l_timerfd->callback_arg); + dap_events_socket_set_readable_unsafe(a_event_sock, true); +} + /** * @brief dap_timerfd_stop * @param a_tfd * @param a_callback - * @return 0 or <0 if error */ -int dap_timerfd_delete(dap_timerfd_t *l_timerfd) +void dap_timerfd_delete(dap_timerfd_t *l_timerfd) { - if(!l_timerfd || l_timerfd->tfd < 1 || !l_timerfd->events_socket) { - return -1; - } - - if(close(l_timerfd->tfd) == -1) { - log_it(L_WARNING, "dap_timerfd_stop() failed to close timerfd: errno=%d\n", errno); - return -2; - } - - dap_events_socket_kill_socket(l_timerfd->events_socket); - l_timerfd->events_socket = NULL; - DAP_DELETE(l_timerfd); - return 0; + dap_events_socket_remove_and_delete_mt(l_timerfd->events_socket->worker, l_timerfd->events_socket); } +#else +#error "No dap_timerfd realization for your platform" #endif diff --git a/dap-sdk/net/core/dap_traffic_track.c b/dap-sdk/net/core/dap_traffic_track.c deleted file mode 100644 index 44c7506a6c426d84dcdfd0ce7aec280e8f766b46..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/dap_traffic_track.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Authors: - * Anatoliy Kurotich <anatoliy.kurotich@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> -#include <time.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> - -#ifndef _WIN32 -#include <pthread.h> -#include <ev.h> -#else -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include <pthread.h> -#endif - -#include "dap_traffic_track.h" -#include "dap_common.h" -#include "dap_cpu_monitor.h" - -#define LOG_TAG "dap_traffic_track" - -#define BITS_IN_BYTE 8 -#define ALLOC_STEP 100 - -static dap_traffic_callback_t _callback = NULL; -static dap_server_t *_dap_server; - -#ifndef _WIN32 -static ev_timer _timeout_watcher; -static struct ev_loop *loop; -#else -static HANDLE _timeout_watcher; -#endif -static size_t timertimeout = 1; - -static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t _cond = PTHREAD_COND_INITIALIZER; -static pthread_t worker_thread; -static bool _stop_worker_signal = false; - - -/** - * @brief calculate_mbits_speed - * @param count_bytes - * @details timeout we gots from _timeout_watcher.repeat - * @return mbit/second speed - */ -static double _calculate_mbits_speed( size_t count_bytes ) -{ - size_t bits_per_second = (count_bytes / timertimeout) * BITS_IN_BYTE; - // log_it(L_DEBUG, "TIMEOUT: %d, bits_per_second: %d mbits: %f", - // (size_t)_timeout_watcher.repeat, bits_per_second, bits_per_second / 1000000.0); - return (double)bits_per_second / 1000000.0; // convert to mbits -} - -void *_worker_run( void *a ) -{ - (void)a; - - pthread_mutex_lock( &_mutex ); - - while( true ) { - pthread_cond_wait( &_cond, &_mutex ); - if ( _stop_worker_signal ) { - log_it(L_INFO, "Dap traffic track worker stopped"); - _stop_worker_signal = false; - break; - } - _callback( _dap_server ); - } - - pthread_mutex_unlock( &_mutex ); - return NULL; -} - -void _worker_start( ) -{ - pthread_mutex_init( &_mutex, NULL ); - pthread_cond_init( &_cond, NULL ); - pthread_create( &worker_thread, NULL, _worker_run, NULL ); -} - -void _worker_stop() -{ - pthread_mutex_lock( &_mutex ); - _stop_worker_signal = true; - pthread_cond_signal( &_cond ); - pthread_mutex_unlock( &_mutex ); - - // wait for exit worker_thread - pthread_join( worker_thread, NULL ); - - pthread_mutex_destroy( &_mutex ); - pthread_cond_destroy( &_cond ); - _callback = NULL; -} - -#ifndef _WIN32 -static void _timeout_cb( ) -#else -VOID CALLBACK _timeout_cb( void *lpParameter, BOOL TimerOrWaitFired ) -#endif -{ -#if 0 - pthread_mutex_lock( &_dap_server->mutex_on_hash ); - - size_t count_users = HASH_COUNT(_dap_server->clients ); - - if ( count_users ) { -// size_t idx = 0; - dap_client_remote_t *dap_cur, *tmp; - HASH_ITER( hh, _dap_server->clients, dap_cur, tmp ) { - - dap_cur->upload_stat.speed_mbs = _calculate_mbits_speed( dap_cur->upload_stat.buf_size_total - - dap_cur->upload_stat.buf_size_total_old ); - - dap_cur->upload_stat.buf_size_total_old = dap_cur->upload_stat.buf_size_total; - - dap_cur->download_stat.speed_mbs = _calculate_mbits_speed( dap_cur->download_stat.buf_size_total - - dap_cur->download_stat.buf_size_total_old ); - - dap_cur->download_stat.buf_size_total_old = dap_cur->download_stat.buf_size_total; - -// idx ++; - } - } - - /* TODO find some better solution and place for this line */ - _dap_server->cpu_stats = dap_cpu_get_stats( ); - - pthread_mutex_unlock( &_dap_server->mutex_on_hash ); -#endif - - if ( _callback != NULL ) { - pthread_mutex_lock( &_mutex ); - pthread_cond_signal( &_cond ); - pthread_mutex_unlock( &_mutex ); - } -} - -void dap_traffic_track_init( dap_server_t * server, - time_t timeout ) -{ - dap_cpu_monitor_init( ); - - _dap_server = server; -#ifndef _WIN32 - _timeout_watcher.repeat = timeout; - - loop = EV_DEFAULT; - - ev_init( &_timeout_watcher, _timeout_cb ); - ev_timer_again( loop, &_timeout_watcher ); -#else - - timertimeout = timeout; - - CreateTimerQueueTimer( &_timeout_watcher, NULL, (WAITORTIMERCALLBACK)_timeout_cb, NULL, timertimeout, timertimeout, 0 ); - -#endif - - log_it(L_NOTICE, "Initialized traffic track module"); -} - -void dap_traffic_track_deinit() -{ - if ( _callback != NULL ) - _worker_stop(); - -#ifndef _WIN32 - ev_timer_stop( loop, &_timeout_watcher ); - ev_loop_destroy( loop ); -#else - DeleteTimerQueueTimer( NULL, _timeout_watcher, NULL ); -#endif - - log_it( L_NOTICE, "Deinitialized traffic track module" ); - dap_cpu_monitor_deinit( ); -} - -void dap_traffic_callback_stop() { - - if ( _callback == NULL ) { - log_it( L_WARNING, "worker not running" ); - return; - } - _worker_stop(); -} - -void dap_traffic_callback_set(dap_traffic_callback_t cb) -{ - if( _callback == NULL ) { - _callback = cb; - _worker_start(); - return; - } - - log_it( L_WARNING, "Callback already setted" ); -} diff --git a/dap-sdk/net/core/dap_worker.c b/dap-sdk/net/core/dap_worker.c new file mode 100644 index 0000000000000000000000000000000000000000..ea14d3a1feb2c0e2df2dcf48797a764972f2d5b4 --- /dev/null +++ b/dap-sdk/net/core/dap_worker.c @@ -0,0 +1,579 @@ +/* + * 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> +#if ! defined (_GNU_SOURCE) +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#endif +#include <fcntl.h> + +#include "dap_common.h" +#include "dap_math_ops.h" +#include "dap_worker.h" +#include "dap_events.h" + +#define LOG_TAG "dap_worker" + + +static time_t s_connection_timeout = 20000; + + +static void s_socket_all_check_activity( void * a_arg); +static void s_queue_new_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); + +/** + * @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_events_socket_t *l_cur; + dap_worker_t *l_worker = (dap_worker_t *) arg; + time_t l_next_time_timeout_check = time( NULL) + s_connection_timeout / 2; + uint32_t l_tn = l_worker->id; + + dap_cpu_assign_thread_on(l_worker->id); + struct sched_param l_shed_params; + l_shed_params.sched_priority = 0; + pthread_setschedparam(pthread_self(),SCHED_FIFO ,&l_shed_params); + + l_worker->queue_es_new = dap_events_socket_create_type_queue_ptr_unsafe( l_worker, s_queue_new_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 ); + l_worker->queue_callback= dap_events_socket_create_type_queue_ptr_unsafe( l_worker, s_queue_callback_callback); + l_worker->timer_check_activity = dap_timerfd_start_on_worker( l_worker,s_connection_timeout / 2,s_socket_all_check_activity,l_worker); + +#ifdef DAP_EVENTS_CAPS_EPOLL + struct epoll_event l_epoll_events[ DAP_MAX_EPOLL_EVENTS]= {{0}}; + log_it(L_INFO, "Worker #%d started with epoll fd %d and assigned to dedicated CPU unit", l_worker->id, l_worker->epoll_fd); +#else +#error "Unimplemented socket array for this platform" +#endif + + pthread_cond_broadcast(&l_worker->started_cond); + bool s_loop_is_active = true; + while(s_loop_is_active) { +#ifdef DAP_EVENTS_CAPS_EPOLL + int l_selected_sockets = epoll_wait(l_worker->epoll_fd, l_epoll_events, DAP_MAX_EPOLL_EVENTS, -1); +#else +#error "Unimplemented poll wait analog for this platform" +#endif + if(l_selected_sockets == -1) { + if( errno == EINTR) + continue; + int l_errno = errno; + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_ERROR, "Worker thread %d got errno:\"%s\" (%d)", l_worker->id, l_errbuf, l_errno); + break; + } + + time_t l_cur_time = time( NULL); + for(int32_t n = 0; n < l_selected_sockets; n++) { + + l_cur = (dap_events_socket_t *) l_epoll_events[n].data.ptr; + if(!l_cur) { + log_it(L_ERROR, "dap_events_socket NULL"); + continue; + } + l_cur->last_time_active = l_cur_time; + + //log_it(L_DEBUG, "Worker=%d fd=%d socket=%d event=0x%x(%d)", l_worker->id, + // l_worker->epoll_fd,l_cur->socket, l_epoll_events[n].events,l_epoll_events[n].events); + int l_sock_err = 0, l_sock_err_size = sizeof(l_sock_err); + //connection already closed (EPOLLHUP - shutdown has been made in both directions) + if(l_epoll_events[n].events & EPOLLHUP) { // && events[n].events & EPOLLERR) { + switch (l_cur->type ){ + case DESCRIPTOR_TYPE_SOCKET_LISTENING: + case DESCRIPTOR_TYPE_SOCKET: + getsockopt(l_cur->socket, SOL_SOCKET, SO_ERROR, (void *)&l_sock_err, (socklen_t *)&l_sock_err_size); + //if(!(events[n].events & EPOLLIN)) + //cur->no_close = false; + if (l_sock_err) { + l_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + log_it(L_INFO, "Socket shutdown (EPOLLHUP): %s", strerror(l_sock_err)); + } + break; + default: log_it(L_WARNING, "Unimplemented EPOLLHUP for socket type %d", l_cur->type); + } + } + + if(l_epoll_events[n].events & EPOLLERR) { + switch (l_cur->type ){ + case DESCRIPTOR_TYPE_SOCKET_LISTENING: + case DESCRIPTOR_TYPE_SOCKET: + getsockopt(l_cur->socket, SOL_SOCKET, SO_ERROR, (void *)&l_sock_err, (socklen_t *)&l_sock_err_size); + log_it(L_ERROR, "Socket error: %s", strerror(l_sock_err)); + default: ; + } + l_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + l_cur->callbacks.error_callback(l_cur, 0); // Call callback to process error event + } + + if (l_epoll_events[n].events & EPOLLRDHUP) { + log_it(L_INFO, "Client socket disconnected"); + dap_events_socket_set_readable_unsafe(l_cur, false); + l_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + } + + if(l_epoll_events[n].events & EPOLLIN) { + + //log_it(L_DEBUG, "Comes connection with type %d", l_cur->type); + if(l_cur->buf_in_size == sizeof(l_cur->buf_in)) { + log_it(L_WARNING, "Buffer is full when there is smth to read. Its dropped!"); + l_cur->buf_in_size = 0; + } + + int32_t l_bytes_read = 0; + int l_errno=0; + bool l_must_read_smth = false; + switch (l_cur->type) { + case DESCRIPTOR_TYPE_PIPE: + case DESCRIPTOR_TYPE_FILE: + l_must_read_smth = true; + l_bytes_read = read(l_cur->socket, (char *) (l_cur->buf_in + l_cur->buf_in_size), + sizeof(l_cur->buf_in) - l_cur->buf_in_size); + l_errno = errno; + break; + case DESCRIPTOR_TYPE_SOCKET: + l_must_read_smth = true; + l_bytes_read = recv(l_cur->fd, (char *) (l_cur->buf_in + l_cur->buf_in_size), + sizeof(l_cur->buf_in) - l_cur->buf_in_size, 0); + l_errno = errno; + break; + case DESCRIPTOR_TYPE_SOCKET_LISTENING: + // Accept connection + if ( l_cur->callbacks.accept_callback){ + struct sockaddr l_remote_addr; + socklen_t l_remote_addr_size= sizeof (l_remote_addr); + int l_remote_socket= accept(l_cur->socket ,&l_remote_addr,&l_remote_addr_size); + int l_errno = errno; + if ( l_remote_socket == -1 ){ + if( l_errno == EAGAIN || l_errno == EWOULDBLOCK){// Everything is good, we'll receive ACCEPT on next poll + continue; + }else{ + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_WARNING,"accept() on socket %d error:\"%s\"(%d)",l_cur->socket, l_errbuf,l_errno); + } + } + + l_cur->callbacks.accept_callback(l_cur,l_remote_socket,&l_remote_addr); + }else + log_it(L_ERROR,"No accept_callback on listening socket"); + break; + case DESCRIPTOR_TYPE_TIMER:{ + uint64_t val; + /* if we not reading data from socket, he triggered again */ + read( l_cur->fd, &val, 8); + if (l_cur->callbacks.timer_callback) + l_cur->callbacks.timer_callback(l_cur); + else + log_it(L_ERROR, "Socket %d with timer callback fired, but callback is NULL ", l_cur->socket); + + } break; + case DESCRIPTOR_TYPE_QUEUE: + dap_events_socket_queue_proc_input_unsafe(l_cur); + break; + case DESCRIPTOR_TYPE_EVENT: + dap_events_socket_event_proc_input_unsafe(l_cur); + break; + } + + if (l_must_read_smth){ // Socket/Descriptor read + if(l_bytes_read > 0) { + l_cur->buf_in_size += l_bytes_read; + //log_it(L_DEBUG, "Received %d bytes", l_bytes_read); + 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, + // continue to poll another esockets + continue; + } + }else{ + log_it(L_WARNING, "We have incomming %u data but no read callback on socket %d, removing from read set", l_cur->socket); + dap_events_socket_set_readable_unsafe(l_cur,false); + } + } + else if(l_bytes_read < 0) { + if (l_errno != EAGAIN && l_errno != EWOULDBLOCK){ // Socket is blocked + log_it(L_ERROR, "Some error occured in recv() function: %s", strerror(errno)); + dap_events_socket_set_readable_unsafe(l_cur, false); + l_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + } + } + else if (!(l_epoll_events[n].events & EPOLLRDHUP) || !(l_epoll_events[n].events & EPOLLERR)) { + log_it(L_WARNING, "EPOLLIN triggered but nothing to read"); + dap_events_socket_set_readable_unsafe(l_cur,false); + } + } + } + + // Socket is ready to write + if(((l_epoll_events[n].events & EPOLLOUT) || (l_cur->flags & DAP_SOCK_READY_TO_WRITE)) + && !(l_cur->flags & DAP_SOCK_SIGNAL_CLOSE)) { + + //log_it(L_DEBUG, "Main loop output: %u bytes to send", l_cur->buf_out_size); + if(l_cur->callbacks.write_callback) + l_cur->callbacks.write_callback(l_cur, NULL); // Call callback to process write event + + if (l_cur->worker == NULL ){ // esocket was unassigned in callback, we don't need any ops with it now, + // continue to poll another esockets + continue; + } + if(l_cur->flags & DAP_SOCK_READY_TO_WRITE) { + + static const uint32_t buf_out_zero_count_max = 2; + //l_cur->buf_out[l_cur->buf_out_size] = 0; + + if(!l_cur->buf_out_size) { + + //log_it(L_WARNING, "Output: nothing to send. Why we are in write socket set?"); + l_cur->buf_out_zero_count++; + + if(l_cur->buf_out_zero_count > buf_out_zero_count_max) { // How many time buf_out on write event could be empty + //log_it(L_WARNING, "Output: nothing to send %u times, remove socket from the write set", + // buf_out_zero_count_max); + dap_events_socket_set_writable_unsafe(l_cur, false); + } + } + else + l_cur->buf_out_zero_count = 0; + } + //for(total_sent = 0; total_sent < cur->buf_out_size;) { // If after callback there is smth to send - we do it + ssize_t l_bytes_sent =0; + int l_errno; + switch (l_cur->type){ + case DESCRIPTOR_TYPE_SOCKET: + l_bytes_sent = send(l_cur->socket, l_cur->buf_out, + l_cur->buf_out_size, MSG_DONTWAIT | MSG_NOSIGNAL); + l_errno = errno; + break; + case DESCRIPTOR_TYPE_PIPE: + case DESCRIPTOR_TYPE_FILE: + l_bytes_sent = write(l_cur->socket, (char *) (l_cur->buf_out + l_bytes_sent), + l_cur->buf_out_size ); + l_errno = errno; + break; + default: + log_it(L_WARNING, "Socket %d is not SOCKET, PIPE or FILE but has WRITE state on. Switching it off"); + dap_events_socket_set_writable_unsafe(l_cur,false); + } + + if(l_bytes_sent < 0) { + if (l_errno != EAGAIN && l_errno != EWOULDBLOCK ){ // If we have non-blocking socket + log_it(L_ERROR, "Some error occured in send(): %s", strerror(errno)); + l_cur->flags |= DAP_SOCK_SIGNAL_CLOSE; + } + }else{ + + //log_it(L_DEBUG, "Output: %u from %u bytes are sent ", l_bytes_sent,l_cur->buf_out_size); + if (l_bytes_sent) { + if ( l_bytes_sent <= l_cur->buf_out_size ){ + l_cur->buf_out_size -= l_bytes_sent; + if (l_cur->buf_out_size ) { + memmove(l_cur->buf_out, &l_cur->buf_out[l_bytes_sent], l_cur->buf_out_size); + } + }else{ + log_it(L_ERROR, "Wrong bytes sent, %zd more then was in buffer %zd",l_bytes_sent, l_cur->buf_out_size); + l_cur->buf_out_size = 0; + } + } + } + } + if (l_cur->buf_out_size) { + dap_events_socket_set_writable_unsafe(l_cur,true); + } + if((l_cur->flags & DAP_SOCK_SIGNAL_CLOSE) && !l_cur->no_close && l_cur->buf_out_size == 0) { + // protect against double deletion + l_cur->kill_signal = true; + //dap_events_socket_remove_and_delete(cur, true); + log_it(L_INFO, "Got signal to close %s, sock %u [thread %u]", l_cur->hostaddr, l_cur->socket, l_tn); + } else if (l_cur->buf_out_size ){ + log_it(L_INFO, "Got signal to close %s, sock %u [thread %u] but buffer is not empty(%zd)", l_cur->hostaddr, l_cur->socket, l_tn, + l_cur->buf_out_size); + } + + if(l_cur->kill_signal && l_cur->buf_out_size == 0) { + log_it(L_INFO, "Kill %u socket (processed).... [ thread %u ]", l_cur->socket, l_tn); + dap_events_socket_remove_and_delete_unsafe( l_cur, false); + }else if (l_cur->buf_out_size ){ + log_it(L_INFO, "Kill %u socket (processed).... [ thread %u ] but buffer is not empty(%zd)", l_cur->socket, l_tn, + l_cur->buf_out_size); + } + + } + + } // while + + return NULL; +} + +/** + * @brief s_new_es_callback + * @param a_es + * @param a_arg + */ +static void s_queue_new_es_callback( dap_events_socket_t * a_es, void * a_arg) +{ + dap_events_socket_t * l_es_new =(dap_events_socket_t *) a_arg; + dap_worker_t * w = a_es->worker; + //log_it(L_DEBUG, "Received event socket %p to add on worker", l_es_new); + if(dap_events_socket_check_unsafe( w, a_es)){ + log_it(L_ERROR, "Already assigned %d (%p), you're doing smth wrong", a_es->socket, a_es); + return; + } + + if ( l_es_new->type == DESCRIPTOR_TYPE_SOCKET || l_es_new->type == DESCRIPTOR_TYPE_SOCKET_LISTENING ){ + int l_cpu = w->id; + setsockopt(l_es_new->socket , SOL_SOCKET, SO_INCOMING_CPU, &l_cpu, sizeof(l_cpu)); + } + bool l_socket_present = (l_es_new->worker && l_es_new->is_initalized) ? true : false; + l_es_new->worker = w; + // 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; + } + + if (l_es_new->socket>0){ + int l_ret = -1; +#ifdef DAP_EVENTS_CAPS_EPOLL + // Init events for EPOLL + l_es_new->ev.events = l_es_new->ev_base_flags ; + if(l_es_new->flags & DAP_SOCK_READY_TO_READ ) + l_es_new->ev.events |= EPOLLIN; + if(l_es_new->flags & DAP_SOCK_READY_TO_WRITE ) + l_es_new->ev.events |= EPOLLOUT; + l_es_new->ev.data.ptr = l_es_new; + if (l_socket_present) { + // Update only flags, socket already present in worker + return; + } + l_ret = epoll_ctl(w->epoll_fd, EPOLL_CTL_ADD, l_es_new->socket, &l_es_new->ev); +#else +#error "Unimplemented new esocket on worker callback for current platform" +#endif + 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 global list + // Add in worker + l_es_new->me = l_es_new; + HASH_ADD(hh_worker, w->esockets, me, sizeof(void *), l_es_new ); + w->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, w); + + } + }else{ + log_it(L_ERROR, "Incorrect socket %d after new callback. Dropping this handler out", l_es_new->socket); + dap_events_socket_remove_and_delete_unsafe( l_es_new, false ); + } +} + +/** + * @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) +{ + dap_events_socket_t * l_esocket = (dap_events_socket_t*) a_arg; + if (dap_events_socket_check_unsafe(a_es->worker,l_esocket)){ + ((dap_events_socket_t*)a_arg)->kill_signal = true; // Send signal to socket to kill + }else + log_it(L_INFO, "While we were sending the delete() message, esocket %p has been disconnected", l_esocket); +} + +/** + * @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) +{ + dap_worker_msg_reassign_t * l_msg = (dap_worker_msg_reassign_t*) a_arg; + dap_events_socket_t * l_es_reassign = l_msg->esocket; + if (dap_events_socket_check_unsafe(a_es->worker,l_es_reassign)){ + 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); + + }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->worker, l_msg->arg); + DAP_DELETE(l_msg); +} + +/** + * @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) +{ + dap_worker_msg_io_t * l_msg = a_arg; + + // Check if it was removed from the list + dap_events_socket_t *l_msg_es = NULL; + HASH_FIND(hh_worker, a_es->worker->esockets, &l_msg->esocket , sizeof (void*), l_msg_es ); + if ( l_msg_es == NULL){ + log_it(L_INFO, "We got i/o message for client thats now not in list. Lost %u data", l_msg->data_size); + DAP_DELETE(l_msg); + return; + } + + 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); +} + +/** + * @brief s_socket_all_check_activity + * @param a_arg + */ +static void 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, *tmp; + char l_curtimebuf[64]; + time_t l_curtime= time(NULL); + 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->esockets, l_es, tmp ) { + if ( l_es->type == DESCRIPTOR_TYPE_SOCKET ){ + if ( !l_es->kill_signal && l_curtime >= (time_t)l_es->last_time_active + s_connection_timeout && !l_es->no_close ) { + log_it( L_INFO, "Socket %u timeout, closing...", l_es->socket ); + if (l_es->callbacks.error_callback) { + l_es->callbacks.error_callback(l_es, ETIMEDOUT); + } + dap_events_socket_remove_and_delete_mt( l_worker, l_es); + } + } + } +} + +/** + * @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) +{ + 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]; + 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_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]; + 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( ); + + a_es->events = l_worker->events; + dap_worker_add_events_socket( a_es, l_worker); + return l_worker; +} + + + diff --git a/dap-sdk/net/core/include/dap_client_remote.h b/dap-sdk/net/core/include/dap_client_remote.h deleted file mode 100644 index 00a70653d7f63c2d836c17f9586b6b6f6a61eab6..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/include/dap_client_remote.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. -*/ -#pragma once - -#include <stdint.h> -#include <stddef.h> -#include <stdbool.h> -#include "uthash.h" - -#ifndef WIN32 -#include <sys/epoll.h> -#include <sys/timerfd.h> -#endif - -#ifndef EPOLL_HANDLE - #ifndef WIN32 - #define EPOLL_HANDLE int - #else - #define EPOLL_HANDLE HANDLE - #include "wepoll.h" - #endif -#endif - -typedef char str_ip[16]; - -typedef struct dap_server dap_server_t; -typedef struct dap_server_thread_s dap_server_thread_t; - -struct dap_client_remote; - -typedef void (*dap_server_client_callback_t) (struct dap_client_remote *,void * arg); // Callback for specific client operations - -#define DAP_CLIENT_REMOTE_BUF 500000 -#define CLIENT_ID_SIZE 12 - -typedef char dap_server_client_id[CLIENT_ID_SIZE]; - -typedef struct traffic_stats { - - size_t buf_size_total; - size_t buf_size_total_old; // for calculate speed - double speed_mbs; // MegaBits per second -} traffic_stats_t; - -typedef struct dap_client_remote { - - int socket; - dap_server_client_id id; - - uint32_t flags; - bool no_close; - bool kill_signal; - - uint16_t port; - str_ip s_ip; - - uint32_t buf_out_zero_count; - char buf_in[DAP_CLIENT_REMOTE_BUF]; // Internal buffer for input data - - size_t buf_in_size; // size of data that is in the input buffer - - traffic_stats_t upload_stat; - traffic_stats_t download_stat; - - char buf_out[DAP_CLIENT_REMOTE_BUF]; // Internal buffer for output data - size_t buf_out_offset; - - char hostaddr[1024]; // Address - char service[128]; - - size_t buf_out_size; // size of data that is in the output buffer - struct epoll_event pevent; - - EPOLL_HANDLE efd; // Epoll fd - int tn; // working thread index - - time_t time_connection; - time_t last_time_active; - - struct dap_server *server; - dap_server_thread_t *thread; - - UT_hash_handle hh; - struct dap_client_remote *next, *prev; - struct dap_client_remote *knext, *kprev; - - void *_internal; - void *_inheritor; // Internal data to specific client type, usualy states for state machine - -} dap_client_remote_t; // Node of bidirectional list of clients - -int dap_client_remote_init( void ); // Init clients module -void dap_client_remote_deinit( void ); // Deinit clients module - -dap_client_remote_t *dap_client_remote_create( dap_server_t *sh, int s, dap_server_thread_t *dsth ); -dap_client_remote_t *dap_client_remote_find( int sock, dap_server_thread_t *t ); - -bool dap_client_remote_is_ready_to_read( dap_client_remote_t * sc ); -bool dap_client_remote_is_ready_to_write( dap_client_remote_t * sc ); -void dap_client_remote_ready_to_read( dap_client_remote_t * sc,bool is_ready ); -void dap_client_remote_ready_to_write( dap_client_remote_t * sc,bool is_ready ); - -size_t dap_client_remote_write( dap_client_remote_t *sc, const void * data, size_t data_size ); -size_t dap_client_remote_write_f( dap_client_remote_t *a_client, const char * a_format,... ); -size_t dap_client_remote_read( dap_client_remote_t *sc, void * data, size_t data_size ); - -//void dap_client_remote_remove( dap_client_remote_t *sc, struct dap_server * sh ); // Removes the client from the list -void dap_client_remote_remove( dap_client_remote_t *sc ); - -void dap_client_remote_shrink_buf_in( dap_client_remote_t * cl, size_t shrink_size ); - diff --git a/dap-sdk/net/core/include/dap_events.h b/dap-sdk/net/core/include/dap_events.h index e7b7777b1087b98c104d33bc0c91860f0d8b4d4d..c8e5471fb9e525c88370d01b1fa8c2661269f680 100644 --- a/dap-sdk/net/core/include/dap_events.h +++ b/dap-sdk/net/core/include/dap_events.h @@ -3,7 +3,7 @@ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * DeM Labs Inc. https://demlabs.net * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2019 + * Copyright (c) 2017-2020 * All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project @@ -22,23 +22,13 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once - -#ifndef WIN32 -#include <netinet/in.h> - -#include <stdint.h> #include <pthread.h> -#include <stdatomic.h> -#define EPOLL_HANDLE int -#else -#define EPOLL_HANDLE HANDLE -#endif - #include "uthash.h" #include "dap_events_socket.h" #include "dap_server.h" - +#include "dap_worker.h" struct dap_events; +#define DAP_MAX_EPOLL_EVENTS 8192 typedef void (*dap_events_callback_t) (struct dap_events *, void *arg); // Callback for specific server's operations @@ -46,47 +36,29 @@ typedef struct dap_thread { pthread_t tid; } dap_thread_t; -struct dap_worker; - typedef struct dap_events { - - dap_events_socket_t *sockets; // Hashmap of event sockets - dap_events_socket_t *dlsockets; // Dlist of event sockets - dap_events_socket_t *to_kill_sockets; // Dlist of event sockets - - pthread_rwlock_t sockets_rwlock; - void *_inheritor; // Pointer to the internal data, HTTP for example - dap_thread_t proc_thread; - pthread_rwlock_t servers_rwlock; - + dap_events_socket_t *sockets; // Hashmap of event sockets + pthread_rwlock_t sockets_rwlock; + void *_inheritor; // Pointer to the internal data, HTTP for example + dap_thread_t proc_thread; } dap_events_t; -typedef struct dap_worker -{ - atomic_uint event_sockets_count; - //uint32_t event_to_kill_count; - - EPOLL_HANDLE epoll_fd; - uint32_t number_thread; - pthread_mutex_t locker_on_count; - dap_events_t *events; - -} dap_worker_t; - -int32_t dap_events_init( uint32_t a_threads_count, size_t conn_t ); // Init server module +int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout ); // Init server module void dap_events_deinit( ); // Deinit server module -void dap_events_thread_wake_up( dap_thread_t *th ); dap_events_t* dap_events_new( ); -void dap_events_delete( dap_events_t * sh ); - -int32_t dap_events_start( dap_events_t *sh ); -void dap_events_stop(); -int32_t dap_events_wait( dap_events_t *sh ); +dap_events_t* dap_events_get_default( ); +void dap_events_delete( dap_events_t * a_events ); -uint32_t dap_worker_get_index_min( ); -dap_worker_t *dap_worker_get_min( ); +int32_t dap_events_start( dap_events_t *a_events ); +void dap_events_stop_all(); +int32_t dap_events_wait( dap_events_t *a_events ); -void dap_worker_add_events_socket( dap_events_socket_t * a_events_socket ); -void dap_worker_print_all( ); +void dap_events_worker_print_all( ); +uint32_t dap_events_worker_get_index_min( ); +uint32_t dap_events_worker_get_count(); +dap_worker_t *dap_events_worker_get_auto( ); +dap_worker_t * dap_events_worker_get(uint8_t a_index); +uint32_t dap_get_cpu_count(); +void dap_cpu_assign_thread_on(uint32_t a_cpu_id); diff --git a/dap-sdk/net/core/include/dap_events_socket.h b/dap-sdk/net/core/include/dap_events_socket.h index 99ebe57b2bc355c41ecf4545b16a6547867bae23..81bf6a0098557b55c6d8db40b8fda629ea7aadb4 100644 --- a/dap-sdk/net/core/include/dap_events_socket.h +++ b/dap-sdk/net/core/include/dap_events_socket.h @@ -1,173 +1,243 @@ /* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2019 + * DeM Labs Ltd. https://demlabs.net + * Copyright (c) 2017 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + 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 is distributed in the hope that it will be useful, + 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 based project. If not, see <http://www.gnu.org/licenses/>. + along with any DAP SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once - #include <stdint.h> #include <stddef.h> #include <stdbool.h> #include <stdatomic.h> +#include <pthread.h> #include "uthash.h" -#ifndef _WIN32 + +#include "dap_common.h" + +// Caps for different platforms +#if defined(DAP_OS_LINUX) + #define DAP_EVENTS_CAPS_EPOLL + #define DAP_EVENTS_CAPS_PIPE_POSIX + #define DAP_EVENTS_CAPS_QUEUE_PIPE2 + //#define DAP_EVENTS_CAPS_QUEUE_POSIX + #define DAP_EVENTS_CAPS_EVENT_EVENTFD + #include <netinet/in.h> + #include <sys/eventfd.h> + #include <mqueue.h> +#elif defined (DAP_OS_UNIX) + #define DAP_EVENTS_CAPS_KQUEUE + #define DAP_EVENTS_CAPS_PIPE_POSIX + #define DAP_EVENTS_CAPS_EVENT_KEVENT + #define DAP_EVENTS_CAPS_QUEUE_SOCKETPAIR + #include <netinet/in.h> +#elif defined (DAP_OS_WINDOWS) + #define DAP_EVENTS_CAPS_WEPOLL + #define DAP_EVENTS_CAPS_EPOLL + #define DAP_EVENTS_CAPS_QUEUE_WEVENT + #define DAP_EVENTS_CAPS_EVENT_WEVENT + #define DAP_EVENTS_CAPS_PIPE_POSIX +#endif + +#if defined(DAP_EVENTS_CAPS_EPOLL) #include <sys/epoll.h> -#else +#define EPOLL_HANDLE int +#elif defined (DAP_EVENTS_CAPS_WEPOLL) #include "wepoll.h" +#define EPOLL_HANDLE HANDLE #endif -#include <pthread.h> -struct dap_events; -struct dap_events_socket; -struct dap_worker; + +#define BIT( x ) ( 1 << x ) +#define DAP_SOCK_READY_TO_READ BIT( 0 ) +#define DAP_SOCK_READY_TO_WRITE BIT( 1 ) +#define DAP_SOCK_SIGNAL_CLOSE BIT( 2 ) +#define DAP_SOCK_ACTIVE BIT( 3 ) +#define DAP_SOCK_REASSIGN_ONCE BIT( 4 ) // This usable for FlowControl to prevent multiple reassigment + +// If set - queue limited to sizeof(void*) size of data transmitted +#define DAP_SOCK_QUEUE_PTR BIT( 8 ) + +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_server dap_server_t; -typedef void (*dap_events_socket_callback_t) (struct dap_events_socket *,void * arg); // Callback for specific client operations +typedef void (*dap_events_socket_callback_t) (dap_events_socket_t *,void * ); // Callback for specific client operations +typedef void (*dap_events_socket_callback_error_t) (dap_events_socket_t *, int ); // Callback for specific client operations +typedef void (*dap_events_socket_callback_queue_t) (dap_events_socket_t *,const void * , size_t); // Callback for specific client operations +typedef void (*dap_events_socket_callback_event_t) (dap_events_socket_t *, uint64_t); // Callback for specific client operations +typedef void (*dap_events_socket_callback_pipe_t) (dap_events_socket_t *,const void * , size_t); // Callback for specific client operations +typedef void (*dap_events_socket_callback_queue_ptr_t) (dap_events_socket_t *, void *); // Callback for specific client operations +typedef void (*dap_events_socket_callback_timer_t) (dap_events_socket_t * ); // Callback for specific client operations +typedef void (*dap_events_socket_callback_accept_t) (dap_events_socket_t * , int, struct sockaddr* ); // Callback for accept of new connection +typedef void (*dap_events_socket_worker_callback_t) (dap_events_socket_t *,dap_worker_t * ); // Callback for specific client operations typedef struct dap_events_socket_callbacks { - + union{ + dap_events_socket_callback_accept_t accept_callback; // Accept callback for listening socket + dap_events_socket_callback_timer_t timer_callback; // Timer callback for listening socket + dap_events_socket_callback_event_t event_callback; // Event callback for listening socket + dap_events_socket_callback_queue_t queue_callback; // Queue callback for listening socket + dap_events_socket_callback_queue_ptr_t queue_ptr_callback; // queue_ptr callback for listening socket + }; dap_events_socket_callback_t new_callback; // Create new client callback dap_events_socket_callback_t delete_callback; // Delete client callback dap_events_socket_callback_t read_callback; // Read function dap_events_socket_callback_t write_callback; // Write function - dap_events_socket_callback_t error_callback; // Error processing function + dap_events_socket_callback_error_t error_callback; // Error processing function + + dap_events_socket_worker_callback_t worker_assign_callback; // After successful worker assign + dap_events_socket_worker_callback_t worker_unassign_callback; // After successful worker unassign } dap_events_socket_callbacks_t; #define DAP_EVENTS_SOCKET_BUF 100000 -#if 0 +typedef enum { + DESCRIPTOR_TYPE_SOCKET = 0, + DESCRIPTOR_TYPE_SOCKET_LISTENING, + DESCRIPTOR_TYPE_QUEUE, + DESCRIPTOR_TYPE_PIPE, + DESCRIPTOR_TYPE_TIMER, + DESCRIPTOR_TYPE_EVENT, + DESCRIPTOR_TYPE_FILE +} dap_events_desc_type_t; + typedef struct dap_events_socket { + union{ + int socket; + int fd; +#if defined(DAP_EVENTS_CAPS_QUEUE_POSIX) + mqd_t mqd; +#endif + }; +#ifdef DAP_EVENTS_CAPS_PIPE_POSIX + int fd2; +#endif + dap_events_desc_type_t type; + // Related sockets (be careful - possible problems, delete them before ) + dap_events_socket_t ** workers_es; // If not NULL - on every worker must be present + size_t workers_es_size; // events socket with same socket + + // Flags. TODO - rework in bool fields + uint32_t flags; + bool no_close; + atomic_bool kill_signal; + atomic_bool is_initalized; + bool was_reassigned; // Was reassigment at least once - int socket; - bool signal_close; + uint32_t buf_out_zero_count; - bool _ready_to_write; - bool _ready_to_read; + // Flags + bool is_pingable; + bool is_read_direct; // If set - don't call read() in worker, let operate with handler to callback + bool is_dont_reset_write_flag; // If set - don't reset write flag ever data is over - uint32_t buf_out_zero_count; + // Input section union{ uint8_t buf_in[DAP_EVENTS_SOCKET_BUF+1]; // Internal buffer for input data char buf_in_str[DAP_EVENTS_SOCKET_BUF+1]; }; size_t buf_in_size; // size of data that is in the input buffer + // Output section + uint8_t buf_out[DAP_EVENTS_SOCKET_BUF+1]; // Internal buffer for output data + size_t buf_out_size; // size of data that is in the output buffer + dap_events_socket_t * pipe_out; // Pipe socket with data for output + // Stored string representation char hostaddr[1024]; // Address char service[128]; + struct sockaddr remote_addr; - size_t buf_out_size; // size of data that is in the output buffer + // Links to related objects + dap_events_t *events; + dap_worker_t *worker; + dap_server_t *server; // If this socket assigned with server - struct dap_events *events; + // Platform specific things +#ifdef DAP_EVENTS_CAPS_EPOLL + uint32_t ev_base_flags; + struct epoll_event ev; +#endif - struct dap_worker *dap_worker; - dap_events_socket_callbacks_t *callbacks; + dap_events_socket_callbacks_t callbacks; time_t time_connection; + time_t last_time_active; time_t last_ping_request; - bool is_pingable; - - UT_hash_handle hh; - - void * _inheritor; // Inheritor data to specific client type, usualy states for state machine -} dap_events_socket_t; // Node of bidirectional list of clients -#endif - -typedef enum { - DESCRIPTOR_TYPE_SOCKET = 0, - DESCRIPTOR_TYPE_FILE -} dap_events_desc_type_t; - -typedef struct dap_events_socket { - int32_t socket; - dap_events_desc_type_t type; + void *_inheritor; // Inheritor data to specific client type, usualy states for state machine + struct dap_events_socket * me; // pointer on itself - uint32_t flags; -// bool signal_close; - bool no_close; - atomic_bool kill_signal; -// bool _ready_to_write; -// bool _ready_to_read; - - uint32_t buf_out_zero_count; - union{ - uint8_t buf_in[DAP_EVENTS_SOCKET_BUF+1]; // Internal buffer for input data - char buf_in_str[DAP_EVENTS_SOCKET_BUF+1]; - }; - size_t buf_in_size; // size of data that is in the input buffer - - uint8_t buf_out[DAP_EVENTS_SOCKET_BUF+1]; // Internal buffer for output data - - char hostaddr[1024]; // Address - char service[128]; - - size_t buf_out_size; // size of data that is in the output buffer - - struct dap_events *events; - struct dap_worker *dap_worker; - struct epoll_event ev; - - dap_events_socket_callbacks_t *callbacks; - - time_t time_connection; - time_t last_time_active; - time_t last_ping_request; - bool is_pingable; - - UT_hash_handle hh; - struct dap_events_socket *next, *prev; - struct dap_events_socket *knext, *kprev; - - void *_inheritor; // Inheritor data to specific client type, usualy states for state machine - - pthread_mutex_t write_hold; + UT_hash_handle hh; + UT_hash_handle hh_worker; // Handle for local CPU storage on worker } dap_events_socket_t; // Node of bidirectional list of clients int dap_events_socket_init(); // Init clients module void dap_events_socket_deinit(); // Deinit clients module -void dap_events_socket_create_after(dap_events_socket_t * a_es); +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); -dap_events_socket_t * dap_events_socket_wrap_no_add(struct dap_events * a_events, - int s, dap_events_socket_callbacks_t * a_callbacks); // Create new client and add it to the list +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 * dap_events_socket_create_type_event_mt(dap_worker_t * a_w, dap_events_socket_callback_event_t a_callback); +void dap_events_socket_event_proc_input_unsafe(dap_events_socket_t *a_esocket); +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 * dap_events_socket_create_type_pipe_mt(dap_worker_t * a_w, dap_events_socket_callback_t a_callback, uint32_t a_flags); +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); -dap_events_socket_t * dap_events_socket_find(int sock, struct dap_events * sh); // Find client by socket +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 ); +dap_events_socket_t * dap_events_socket_wrap2( dap_server_t *a_server, struct dap_events *a_events, + int a_sock, dap_events_socket_callbacks_t *a_callbacks ); -bool dap_events_socket_is_ready_to_read(dap_events_socket_t * sc); -bool dap_events_socket_is_ready_to_write(dap_events_socket_t * sc); -void dap_events_socket_set_readable(dap_events_socket_t * sc,bool is_ready); -void dap_events_socket_set_writable(dap_events_socket_t * sc,bool is_ready); +void dap_events_socket_assign_on_worker_unsafe(dap_events_socket_t * a_es, struct dap_worker * a_worker); +void dap_events_socket_assign_on_worker_mt(dap_events_socket_t * a_es, struct dap_worker * a_worker); -size_t dap_events_socket_write(dap_events_socket_t *sc, const void * data, size_t data_size); -size_t dap_events_socket_write_f(dap_events_socket_t *sc, const char * format,...); -size_t dap_events_socket_read(dap_events_socket_t *sc, void * data, size_t data_size); +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); -void dap_events_socket_remove( dap_events_socket_t *a_es); -void dap_events_socket_delete(dap_events_socket_t *sc,bool preserve_inheritor); // Removes the client from the list -void dap_events_socket_remove_and_delete(dap_events_socket_t* a_es, bool preserve_inheritor ); -int dap_events_socket_kill_socket( dap_events_socket_t *a_es ); +dap_events_socket_t * dap_events_socket_find_unsafe(int sock, struct dap_events * sh); // Find client by socket +size_t dap_events_socket_pop_from_buf_in(dap_events_socket_t *sc, void * data, size_t data_size); +// Non-MT functions +bool dap_events_socket_check_unsafe(dap_worker_t * a_worker,dap_events_socket_t * a_es); +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); +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,...); + +// MT variants less +void dap_events_socket_set_readable_mt(dap_worker_t * a_w, dap_events_socket_t * a_es,bool a_is_ready); +void dap_events_socket_set_writable_mt(dap_worker_t * a_w, dap_events_socket_t * a_es,bool a_is_ready); +size_t dap_events_socket_write_mt(dap_worker_t * a_w, dap_events_socket_t *sc, const void * data, size_t data_size); +size_t dap_events_socket_write_f_mt(dap_worker_t * a_w, dap_events_socket_t *sc, const char * format,...); +void dap_events_socket_remove_and_delete_mt( dap_worker_t * a_w, dap_events_socket_t* a_es); +void dap_events_socket_remove_and_delete_unsafe( dap_events_socket_t *a_es, bool preserve_inheritor ); + +void dap_events_socket_remove_from_worker_unsafe( dap_events_socket_t *a_es, dap_worker_t * a_worker); void dap_events_socket_shrink_buf_in(dap_events_socket_t * cl, size_t shrink_size); + diff --git a/dap-sdk/net/core/include/dap_proc_queue.h b/dap-sdk/net/core/include/dap_proc_queue.h new file mode 100644 index 0000000000000000000000000000000000000000..e38c2d82c3c99bd37da2f338105f1ace57c52d23 --- /dev/null +++ b/dap-sdk/net/core/include/dap_proc_queue.h @@ -0,0 +1,48 @@ +/* + * 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/>. +*/ +#pragma once +#include "dap_events_socket.h" + +typedef struct dap_proc_thread dap_proc_thread_t; + +typedef bool (*dap_proc_queue_callback_t)(dap_proc_thread_t*,void* ); // Callback for processor. Returns true if we want to continue running + +typedef struct dap_proc_queue_item{ + dap_proc_queue_callback_t callback; + void *callback_arg; + struct dap_proc_queue_item * next; +} dap_proc_queue_item_t; + +typedef struct dap_proc_queue{ + dap_proc_thread_t * proc_thread; + dap_events_socket_t *esocket; + dap_proc_queue_item_t * items; +} dap_proc_queue_t; + +dap_proc_queue_t * dap_proc_queue_create(dap_proc_thread_t * a_thread); + +void dap_proc_queue_delete(dap_proc_queue_t * a_queue); +void dap_proc_queue_add_callback(dap_proc_queue_t * a_queue,dap_proc_queue_callback_t a_callback, void * a_callback_arg); + +void dap_proc_queue_add_callback_auto(dap_proc_queue_callback_t a_callback, void * a_callback_arg); + diff --git a/dap-sdk/net/core/include/dap_proc_thread.h b/dap-sdk/net/core/include/dap_proc_thread.h new file mode 100644 index 0000000000000000000000000000000000000000..0682f285b22a6d568846986cdf3e32c628cf5b1b --- /dev/null +++ b/dap-sdk/net/core/include/dap_proc_thread.h @@ -0,0 +1,52 @@ +/* + * 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/>. +*/ + +#pragma once + +#include <pthread.h> +#include <stdatomic.h> +#include "dap_common.h" +#include "dap_proc_queue.h" + +typedef struct dap_proc_thread{ + uint32_t cpu_id; + pthread_t thread_id; + dap_proc_queue_t * proc_queue; + dap_events_socket_t * proc_event; // Should be armed if we have to deal with it + atomic_uint proc_queue_size; + + pthread_cond_t started_cond; + pthread_mutex_t started_mutex; + + bool signal_kill; + +#ifdef DAP_EVENTS_CAPS_EPOLL + EPOLL_HANDLE epoll_ctl; +#else +#error "No poll for proc thread for your platform" +#endif +} dap_proc_thread_t; + +int dap_proc_thread_init(uint32_t a_threads_count); +dap_proc_thread_t * dap_proc_thread_get(uint32_t a_thread_number); +dap_proc_thread_t * dap_proc_thread_get_auto(); diff --git a/dap-sdk/net/core/include/dap_server.h b/dap-sdk/net/core/include/dap_server.h index 77f0004e0d1ee306a409e37969f55df2a37c6397..44bf62135e5756e0d1c05fb1f62937e4d0b1ccc8 100644 --- a/dap-sdk/net/core/include/dap_server.h +++ b/dap-sdk/net/core/include/dap_server.h @@ -1,36 +1,47 @@ /* - Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc - All rights reserved. + * 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 (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + 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 is distributed in the hope that it will be useful, + 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 Lesser General Public License for more details. + GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. + 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 -#ifndef _WIN32 +#include "dap_common.h" +#if defined( DAP_OS_LINUX) + #include <netinet/in.h> #include <stdint.h> #include <sys/epoll.h> #include <sys/timerfd.h> #define EPOLL_HANDLE int -#else + +#elif defined(DAP_OS_WINDOWS) + #define EPOLL_HANDLE HANDLE #define MSG_DONTWAIT 0 #define MSG_NOSIGNAL 0 #include "winsock.h" #include "wepoll.h" +#else +#error "No poll headers for your platform" #endif #include <pthread.h> @@ -38,34 +49,11 @@ #include "utlist.h" #include "dap_cpu_monitor.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" typedef enum dap_server_type {DAP_SERVER_TCP} dap_server_type_t; -#define BIT( x ) ( 1 << x ) -#define DAP_SOCK_READY_TO_READ BIT( 0 ) -#define DAP_SOCK_READY_TO_WRITE BIT( 1 ) -#define DAP_SOCK_SIGNAL_CLOSE BIT( 2 ) -#define DAP_SOCK_ACTIVE BIT( 3 ) - -typedef struct dap_server_thread_s { - - EPOLL_HANDLE epoll_fd; - - uint32_t thread_num; - uint32_t connections_count; - uint32_t to_kill_count; - - struct epoll_event *epoll_events; - dap_client_remote_t *dap_remote_clients; - dap_client_remote_t *hclients; // Hashmap of clients - dap_client_remote_t *dap_clients_to_kill; - - pthread_mutex_t mutex_dlist_add_remove; - pthread_mutex_t mutex_on_hash; - -} dap_server_thread_t; struct dap_server; @@ -78,7 +66,7 @@ typedef struct dap_server { char *address; // Listen address int32_t socket_listener; // Socket for listener - EPOLL_HANDLE epoll_fd; // Epoll fd + dap_events_socket_t * es_listener; struct sockaddr_in listener_addr; // Kernel structure for listener's binded address @@ -86,64 +74,15 @@ typedef struct dap_server { dap_cpu_stats_t cpu_stats; - dap_server_callback_t server_delete_callback; + dap_server_callback_t delete_callback; - dap_server_client_callback_t client_new_callback; // Create new client callback - dap_server_client_callback_t client_delete_callback; // Delete client callback - dap_server_client_callback_t client_read_callback; // Read function - dap_server_client_callback_t client_write_callback; // Write function - dap_server_client_callback_t client_error_callback; // Error processing function + dap_events_socket_callbacks_t client_callbacks; // Callbacks for the new clients + pthread_cond_t started_cond; // Condition for initialized socket + pthread_mutex_t started_mutex; // Mutex for shared operation between mirrored sockets } dap_server_t; -int32_t dap_server_init( uint32_t count_threads ); // Init server module -void dap_server_deinit( void ); // Deinit server module - -dap_server_t *dap_server_listen( const char *addr, uint16_t port, dap_server_type_t type ); - -int32_t dap_server_loop( dap_server_t *d_server ); -void dap_server_loop_stop( void ); - -#define DL_LIST_REMOVE_NODE( head, obj, _prev_, _next_, total ) \ - \ - if ( obj->_next_ ) { \ - \ - if ( obj->_prev_ ) \ - obj->_next_->_prev_ = obj->_prev_; \ - else { \ - \ - obj->_next_->_prev_ = NULL; \ - head = obj->_next_; \ - } \ - } \ - \ - if ( obj->_prev_ ) { \ - \ - if ( obj->_next_ ) \ - obj->_prev_->_next_ = obj->_next_; \ - else { \ - \ - obj->_prev_->_next_ = NULL; \ - } \ - } \ - -- total; - -#define DL_LIST_ADD_NODE_HEAD( head, obj, _prev_, _next_, total )\ - \ - if ( !total ) { \ - \ - obj->_prev_ = NULL; \ - obj->_next_ = NULL; \ - \ - head = obj; \ - } \ - else { \ - \ - head->_prev_ = obj; \ - \ - obj->_prev_ = NULL; \ - obj->_next_ = head; \ - \ - head = obj; \ - } \ - ++ total; +int dap_server_init( ); // Init server module +void dap_server_deinit( void ); // Deinit server module + +dap_server_t* dap_server_new(dap_events_t *a_events, const char * a_addr, uint16_t a_port, dap_server_type_t a_type); diff --git a/dap-sdk/net/core/include/dap_timerfd.h b/dap-sdk/net/core/include/dap_timerfd.h index a658606e8395a69668ae11d1fa430c35e5e011dd..716e721871db6501e60daced826294e6ff4bc2b8 100644 --- a/dap-sdk/net/core/include/dap_timerfd.h +++ b/dap-sdk/net/core/include/dap_timerfd.h @@ -1,27 +1,26 @@ /* * Authors: * Alexander Lysikov <alexander.lysikov@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain + * DeM Labs Ltd. https://demlabs.net * Copyright (c) 2020 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) 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 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 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 based project. If not, see <http://www.gnu.org/licenses/>. - */ + 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 <stdint.h> #include <stdbool.h> #include <errno.h> @@ -35,7 +34,7 @@ #include "dap_common.h" #include "dap_events_socket.h" -typedef void (*dap_timerfd_callback_t)(void * arg); // Callback for timer +typedef void (*dap_timerfd_callback_t)(void* ); // Callback for timer typedef struct dap_timerfd { uint64_t timeout_ms; @@ -46,6 +45,7 @@ typedef struct dap_timerfd { } dap_timerfd_t; int dap_timerfd_init(); -dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t *a_callback, void *callback_arg); -int dap_timerfd_delete(dap_timerfd_t *l_timerfd); +dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *callback_arg); +dap_timerfd_t* dap_timerfd_start_on_worker(dap_worker_t * a_worker, uint64_t a_timeout_ms, dap_timerfd_callback_t a_callback, void *a_callback_arg); +void dap_timerfd_delete(dap_timerfd_t *l_timerfd); diff --git a/dap-sdk/net/core/include/dap_traffic_track.h b/dap-sdk/net/core/include/dap_traffic_track.h deleted file mode 100644 index 1cfae9d22689621d0c99a746f96d07a9321543a3..0000000000000000000000000000000000000000 --- a/dap-sdk/net/core/include/dap_traffic_track.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Authors: - * Anatoliy Jurotich <anatoliy.kurotich@demlabs.net> - * DeM Labs Inc. https://demlabs.net - * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2017-2018 - * All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) 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 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 based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#pragma once - -#include "dap_client_remote.h" -#include "dap_server.h" - -typedef void (*dap_traffic_callback_t) (dap_server_t *); - -/** - * @brief dap_traffic_track_init - * @param clients - * @param timeout callback - */ -void dap_traffic_track_init( dap_server_t *server, time_t timeout ); - -/** - * @brief dap_traffic_track_deinit - */ -void dap_traffic_track_deinit( void ); - -/** - * @brief dap_traffic_add_callback - */ -void dap_traffic_callback_set( dap_traffic_callback_t ); - -void dap_traffic_callback_stop( void ); - diff --git a/dap-sdk/net/core/include/dap_worker.h b/dap-sdk/net/core/include/dap_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..eb02022f633a4162e63536a2349091a553857e28 --- /dev/null +++ b/dap-sdk/net/core/include/dap_worker.h @@ -0,0 +1,86 @@ +/* + * 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/>. +*/ +#pragma once +#include <stdint.h> +#include <stdatomic.h> +#include <pthread.h> +#include "dap_events_socket.h" +#include "dap_timerfd.h" + +#include "dap_proc_queue.h" +typedef struct dap_worker +{ + uint32_t id; + dap_events_t* events; + dap_proc_queue_t* proc_queue; + atomic_uint event_sockets_count; + dap_events_socket_t *esockets; // Hashmap of event sockets + + // worker control queues + dap_events_socket_t * queue_es_new; // Events socket for new socket + dap_events_socket_t * queue_es_delete; // Events socke + dap_events_socket_t * queue_es_reassign; // Reassign between workers + dap_events_socket_t * queue_es_io; // Events socket for new socket + + dap_events_socket_t * queue_callback; // Queue for pure callback on worker + + dap_timerfd_t * timer_check_activity; +#ifdef DAP_EVENTS_CAPS_EPOLL + EPOLL_HANDLE epoll_fd; +#endif + pthread_cond_t started_cond; + pthread_mutex_t started_mutex; + void * _inheritor; +} dap_worker_t; + +// Message for reassigment +typedef struct dap_worker_msg_reassign{ + dap_events_socket_t * esocket; + dap_worker_t * worker_new; +} dap_worker_msg_reassign_t; + +// Message for input/output queue +typedef struct dap_worker_msg_io{ + dap_events_socket_t * esocket; + size_t data_size; + void *data; + uint32_t flags_set; + uint32_t flags_unset; +} dap_worker_msg_io_t; + +// Message for callback execution +typedef void (*dap_worker_callback_t)(dap_worker_t *,void *); +typedef struct dap_worker_msg_callback{ + dap_worker_callback_t callback; // Callback for specific client operations + void * arg; +} dap_worker_msg_callback_t; + +int dap_worker_init( size_t a_conn_timeout ); +void dap_worker_deinit(); + +void dap_worker_add_events_socket(dap_events_socket_t * a_events_socket, dap_worker_t * a_worker); +dap_worker_t *dap_worker_add_events_socket_auto( dap_events_socket_t * a_events_socket ); +void dap_worker_exec_callback_on(dap_worker_t * a_worker, dap_worker_callback_t a_callback, void * a_arg); + +// Thread function +void *dap_worker_thread(void *arg); diff --git a/dap-sdk/net/server-udp/dap_udp_client.c b/dap-sdk/net/server-udp/dap_udp_client.c index ab13f7de654ba89a6184c4c38eb71a4e7a3c9d28..fd4e86e809fa192a12a492537eeeb2f7cd7e51d8 100644 --- a/dap-sdk/net/server-udp/dap_udp_client.c +++ b/dap-sdk/net/server-udp/dap_udp_client.c @@ -70,7 +70,7 @@ extern bool sb_payload_ready; * @param port Client port * @return Pointer to the new list's node */ -dap_client_remote_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE efd, unsigned long host, unsigned short port ) +dap_events_socket_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE efd, unsigned long host, unsigned short port ) { dap_udp_server_t *udp_server = DAP_UDP_SERVER( dap_srv ); log_it( L_DEBUG, "Client structure create with host = %x, port = %d", host, port ); @@ -78,14 +78,10 @@ dap_client_remote_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE dap_udp_client_t *inh = DAP_NEW_Z( dap_udp_client_t ); inh->host_key = get_key( host, port ); - dap_client_remote_t *ret = DAP_NEW_Z( dap_client_remote_t ); - inh->client = ret; - - ret->pevent.events = EPOLLIN | EPOLLERR; - ret->pevent.data.fd = dap_srv->socket_listener; + dap_events_socket_t *ret = dap_events_socket_wrap_no_add( dap_srv->es_listener->events, dap_srv->socket_listener, &dap_srv->client_callbacks); + inh->esocket = ret; ret->server = dap_srv; - ret->efd = efd; ret->flags = DAP_SOCK_READY_TO_READ; @@ -101,8 +97,8 @@ dap_client_remote_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE HASH_ADD_INT( udp_server->hclients, host_key, inh ); pthread_mutex_unlock( &udp_server->mutex_on_list ); - if( dap_srv->client_new_callback ) - dap_srv->client_new_callback( ret, NULL ); // Init internal structure + if( dap_srv->client_callbacks.new_callback ) + dap_srv->client_callbacks.new_callback( ret, NULL ); // Init internal structure return ret; } @@ -113,7 +109,7 @@ dap_client_remote_t *dap_udp_client_create( dap_server_t *dap_srv, EPOLL_HANDLE * @param host Variable for host address * @param host Variable for port */ -void dap_udp_client_get_address( dap_client_remote_t *client, unsigned int* host, unsigned short* port ) +void dap_udp_client_get_address( dap_events_socket_t *client, unsigned int* host, unsigned short* port ) { dap_udp_client_t* udp_client = DAP_UDP_CLIENT( client ); *host = udp_client->host_key >> 32; @@ -127,7 +123,7 @@ void dap_udp_client_get_address( dap_client_remote_t *client, unsigned int* host * @param port Source port * @return Pointer to client or NULL if not found */ -dap_client_remote_t *dap_udp_client_find( dap_server_t *dap_srv, unsigned long host, unsigned short port ) +dap_events_socket_t *dap_udp_client_find( dap_server_t *dap_srv, unsigned long host, unsigned short port ) { dap_udp_client_t *inh = NULL; dap_udp_server_t *udp_server = DAP_UDP_SERVER( dap_srv ); @@ -141,78 +137,14 @@ dap_client_remote_t *dap_udp_client_find( dap_server_t *dap_srv, unsigned long h if( inh == NULL ) return NULL; else - return inh->client; -} - -/** - * @brief udp_client_ready_to_read Set ready_to_read flag - * @param dap_rclient Client structure - * @param is_ready Flag value - */ -void dap_udp_client_ready_to_read( dap_client_remote_t *sc, bool is_ready ) -{ - if( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_READ) ) - return; - - if ( is_ready ) - sc->flags |= DAP_SOCK_READY_TO_READ; - else - sc->flags ^= DAP_SOCK_READY_TO_READ; - - int events = EPOLLERR; - - if( sc->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; - - if( sc->flags & DAP_SOCK_READY_TO_WRITE ) - events |= EPOLLOUT; - - sc->pevent.events = events; - - if( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->server->socket_listener, &sc->pevent) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed 002" ); - } -} - -/** - * @brief udp_client_ready_to_write Set ready_to_write flag - * @param dap_rclient Client structure - * @param is_ready Flag value - */ -void dap_udp_client_ready_to_write( dap_client_remote_t *sc, bool is_ready ) -{ - if ( is_ready == (bool)(sc->flags & DAP_SOCK_READY_TO_WRITE) ) - return; - - if ( is_ready ) - sc->flags |= DAP_SOCK_READY_TO_WRITE; - else - sc->flags ^= DAP_SOCK_READY_TO_WRITE; - int events = EPOLLERR; - - if( sc->flags & DAP_SOCK_READY_TO_READ ) - events |= EPOLLIN; - - if( sc->flags & DAP_SOCK_READY_TO_WRITE ) - { - dap_udp_server_t *udp_server = DAP_UDP_SERVER(sc->server); - pthread_mutex_lock(&udp_server->mutex_on_list); - sb_payload_ready = true; - pthread_mutex_unlock(&udp_server->mutex_on_list ); - } - - sc->pevent.events = events; - - if ( epoll_ctl(sc->efd, EPOLL_CTL_MOD, sc->pevent.data.fd, &sc->pevent) != 0 ) { - log_it( L_ERROR, "epoll_ctl failed 003" ); - } + return inh->esocket; } /** * @brief add_waiting_client Add Client to write queue * @param client Client instance */ -void add_waiting_client( dap_client_remote_t *dap_rclient ) +void add_waiting_client( dap_events_socket_t *dap_rclient ) { dap_udp_client_t* udp_cl, *tmp; @@ -231,20 +163,20 @@ void add_waiting_client( dap_client_remote_t *dap_rclient ) pthread_mutex_unlock( &udp_server->mutex_on_list ); } -size_t dap_udp_client_write( dap_client_remote_t *dap_rclient, const void *data, size_t data_size ) +size_t dap_udp_client_write_unsafe( dap_events_socket_t *dap_rclient, const void *data, size_t data_size ) { - size_t size = dap_client_remote_write( dap_rclient, data, data_size ); + size_t size = dap_events_socket_write_unsafe( dap_rclient, data, data_size ); add_waiting_client( dap_rclient ); return size; } -size_t dap_udp_client_write_f( dap_client_remote_t *dap_rclient, const char * a_format, ... ) +size_t dap_udp_client_write_f( dap_events_socket_t *dap_rclient, const char * a_format, ... ) { size_t size = 0; va_list va; va_start( va, a_format ); - size = dap_client_remote_write_f( dap_rclient, a_format, va ); + size = dap_events_socket_write_f_unsafe( dap_rclient, a_format, va ); va_end( va ); add_waiting_client( dap_rclient ); diff --git a/dap-sdk/net/server-udp/dap_udp_server.c b/dap-sdk/net/server-udp/dap_udp_server.c index 12c1c82120c35e0cb5981dc38c1eca371a45f555..26a0fc39bb2bd9378a6b91011415cfe163468a62 100644 --- a/dap-sdk/net/server-udp/dap_udp_server.c +++ b/dap-sdk/net/server-udp/dap_udp_server.c @@ -67,7 +67,7 @@ EPOLL_HANDLE efd_read = (EPOLL_HANDLE)-1; //static void write_cb( EPOLL_HANDLE efd, int revents ); -int check_close( dap_client_remote_t *client ); +int check_close( dap_events_socket_t *client ); /** */ @@ -113,8 +113,8 @@ void dap_udp_server_delete( dap_server_t *sh ) // HASH_ITER( hh, udps->hclients, client, tmp ) // dap_client_remote_remove( client ); - if ( sh->server_delete_callback ) - sh->server_delete_callback( sh, NULL ); + if ( sh->delete_callback ) + sh->delete_callback( sh, NULL ); if ( sh->_inheritor ) free( sh->_inheritor ); @@ -179,17 +179,10 @@ static void write_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh ) //log_it(L_INFO,"write_cb"); //pthread_mutex_lock(&udp_client->mutex_on_client); - dap_client_remote_t *client = udp_client->client; + dap_events_socket_t *client = udp_client->esocket; if( client != NULL && !check_close(client) && (client->flags & DAP_SOCK_READY_TO_WRITE) ) { - - if ( sh->client_write_callback ) - sh->client_write_callback( client, NULL ); - if ( client->buf_out_size > 0 ) { - - - struct sockaddr_in addr; addr.sin_family = AF_INET; dap_udp_client_get_address( client, (unsigned int *)&addr.sin_addr.s_addr, &addr.sin_port ); @@ -211,6 +204,8 @@ static void write_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh ) sb_payload_ready = false; } LL_DELETE( udp->waiting_clients, udp_client ); + if ( sh->client_callbacks.write_callback ) + sh->client_callbacks.write_callback( client, NULL ); } else if( client == NULL ) { LL_DELETE( udp->waiting_clients, udp_client ); @@ -226,25 +221,26 @@ static void write_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh ) * @param client Client structure * @return 1 if client deleted, 0 if client is no need to delete */ -int check_close( dap_client_remote_t *client ) +int check_close( dap_events_socket_t *client ) { - dap_udp_client_t *client_check, *tmp; + dap_udp_client_t *client_check, *tmp; - if( !(client->flags & DAP_SOCK_SIGNAL_CLOSE) ) return 0; + if( !(client->flags & DAP_SOCK_SIGNAL_CLOSE) ) + return 0; - dap_udp_client_t *udp_client = DAP_UDP_CLIENT( client ); - dap_server_t *sh = client->server; - dap_udp_server_t *udp_server = DAP_UDP_SERVER( sh ); + dap_udp_client_t *udp_client = DAP_UDP_CLIENT( client ); + dap_server_t *sh = client->server; + dap_udp_server_t *udp_server = DAP_UDP_SERVER( sh ); - LL_FOREACH_SAFE( udp_server->waiting_clients, client_check, tmp ) { + LL_FOREACH_SAFE( udp_server->waiting_clients, client_check, tmp ) { if ( client_check->host_key == udp_client->host_key ) - LL_DELETE( udp_server->waiting_clients, client_check ); - } + LL_DELETE( udp_server->waiting_clients, client_check ); + } - dap_client_remote_remove( client ); + dap_events_socket_remove_and_delete_mt(client->worker, client ); - return 1; + return 1; } /** @@ -263,7 +259,7 @@ static void read_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh ) int32_t bytes = (int32_t) recvfrom( sh->socket_listener, buf, BUFSIZE, 0,(struct sockaddr *) &clientaddr, &clientlen ); - dap_client_remote_t *client = dap_udp_client_find( sh, clientaddr.sin_addr.s_addr, clientaddr.sin_port ); + dap_events_socket_t *client = dap_udp_client_find( sh, clientaddr.sin_addr.s_addr, clientaddr.sin_port ); if( client != NULL && check_close(client) != 0 ) return; @@ -304,8 +300,8 @@ static void read_cb( EPOLL_HANDLE efd, int revents, dap_server_t *sh ) memcpy( client->buf_in + client->buf_in_size,buf + bytes_processed, bytes_to_transfer ); client->buf_in_size += bytes_to_transfer; - if ( sh->client_read_callback ) - sh->client_read_callback( client, NULL ); + if ( sh->client_callbacks.read_callback ) + sh->client_callbacks.read_callback( client, NULL ); bytes_processed += bytes_to_transfer; bytes_recieved -= bytes_to_transfer; diff --git a/dap-sdk/net/server-udp/include/dap_udp_client.h b/dap-sdk/net/server-udp/include/dap_udp_client.h index 7fc66f14585e359c482b97c201a7fb6bb5beb1ad..f1b3844f5123cae65beb051171dc62c9211e7a1a 100644 --- a/dap-sdk/net/server-udp/include/dap_udp_client.h +++ b/dap-sdk/net/server-udp/include/dap_udp_client.h @@ -27,10 +27,10 @@ #include <sys/queue.h> #endif +#include "dap_events_socket.h" +#include "dap_server.h" #include "uthash.h" -#include "dap_client_remote.h" - typedef struct dap_udp_server dap_udp_server_t; struct dap_udp_client; @@ -38,7 +38,7 @@ struct dap_udp_client; typedef struct dap_udp_client { - dap_client_remote_t *client; + dap_events_socket_t *esocket; uint64_t host_key; //key contains host address in first 4 bytes and port in last 4 bytes UT_hash_handle hh; @@ -52,15 +52,15 @@ typedef struct dap_udp_client { #define DAP_UDP_CLIENT(a) ((dap_udp_client_t *) (a)->_inheritor) -dap_client_remote_t *dap_udp_client_create( dap_server_t *sh, EPOLL_HANDLE efd, unsigned long host, unsigned short port ); // Create new client and add it to the list -dap_client_remote_t *dap_udp_client_find( dap_server_t *sh, unsigned long host, unsigned short port ); // Find client by host and port +dap_events_socket_t *dap_udp_client_create( dap_server_t *sh, EPOLL_HANDLE efd, unsigned long host, unsigned short port ); // Create new client and add it to the list +dap_events_socket_t *dap_udp_client_find( dap_server_t *sh, unsigned long host, unsigned short port ); // Find client by host and port -void dap_udp_client_ready_to_read( dap_client_remote_t *sc, bool is_ready ); -void dap_udp_client_ready_to_write( dap_client_remote_t *sc, bool is_ready ); +void dap_udp_client_ready_to_read( dap_events_socket_t *sc, bool is_ready ); +void dap_udp_client_ready_to_write( dap_events_socket_t *sc, bool is_ready ); -size_t dap_udp_client_write( dap_client_remote_t *sc, const void * data, size_t data_size ); -size_t dap_udp_client_write_f( dap_client_remote_t *a_client, const char * a_format, ... ); +size_t dap_udp_client_write_unsafe( dap_events_socket_t *sc, const void * data, size_t data_size ); +size_t dap_udp_client_write_f( dap_events_socket_t *a_client, const char * a_format, ... ); -void add_waiting_client( dap_client_remote_t *client ); // Add client to writing queue +void add_waiting_client( dap_events_socket_t *client ); // Add client to writing queue -void dap_udp_client_get_address( dap_client_remote_t *client, unsigned int *host, unsigned short *port ); +void dap_udp_client_get_address( dap_events_socket_t *client, unsigned int *host, unsigned short *port ); diff --git a/dap-sdk/net/server-udp/include/dap_udp_server.h b/dap-sdk/net/server-udp/include/dap_udp_server.h index 2ed9465c012118bf5f4edd3761ae1b92f58fa39a..f1725b4d141d6c6704d00d9f3eab397913a48593 100644 --- a/dap-sdk/net/server-udp/include/dap_udp_server.h +++ b/dap-sdk/net/server-udp/include/dap_udp_server.h @@ -36,7 +36,6 @@ #include "dap_udp_client.h" #include "dap_server.h" -#include "dap_client_remote.h" struct dap_udp_server; diff --git a/dap-sdk/net/server/enc_server/dap_enc_http.c b/dap-sdk/net/server/enc_server/dap_enc_http.c index c04ddf05f18018e72f717db26160bf6e7580b79a..eabc22b6f6c1fa57f3781f051c181a719824cc5f 100644 --- a/dap-sdk/net/server/enc_server/dap_enc_http.c +++ b/dap-sdk/net/server/enc_server/dap_enc_http.c @@ -98,7 +98,7 @@ void enc_http_proc(struct dap_http_simple *cl_st, void * arg) log_it(L_DEBUG,"Proc enc http request"); http_status_code_t * return_code = (http_status_code_t*)arg; - if(strcmp(cl_st->http->url_path,"gd4y5yh78w42aaagh") == 0 ) { + if(strcmp(cl_st->http_client->url_path,"gd4y5yh78w42aaagh") == 0 ) { uint8_t alice_msg[cl_st->request_size]; size_t decode_len = dap_enc_base64_decode(cl_st->request, cl_st->request_size, alice_msg, DAP_ENC_DATA_TYPE_B64); @@ -148,7 +148,7 @@ void enc_http_proc(struct dap_http_simple *cl_st, void * arg) *return_code = Http_Status_OK; } else{ - log_it(L_ERROR,"Wrong path '%s' in the request to enc_http module",cl_st->http->url_path); + log_it(L_ERROR,"Wrong path '%s' in the request to enc_http module",cl_st->http_client->url_path); *return_code = Http_Status_NotFound; } } @@ -171,16 +171,16 @@ void enc_http_add_proc(struct dap_http * sh, const char * url) enc_http_delegate_t *enc_http_request_decode(struct dap_http_simple *a_http_simple) { - dap_enc_key_t * l_key= dap_enc_ks_find_http(a_http_simple->http); + dap_enc_key_t * l_key= dap_enc_ks_find_http(a_http_simple->http_client); if(l_key){ enc_http_delegate_t * dg = DAP_NEW_Z(enc_http_delegate_t); dg->key=l_key; - dg->http=a_http_simple->http; + dg->http=a_http_simple->http_client; // dg->isOk=true; - strncpy(dg->action,a_http_simple->http->action,sizeof(dg->action)-1); - if(a_http_simple->http->in_cookie[0]) - dg->cookie=strdup(a_http_simple->http->in_cookie); + strncpy(dg->action,a_http_simple->http_client->action,sizeof(dg->action)-1); + if(a_http_simple->http_client->in_cookie[0]) + dg->cookie=strdup(a_http_simple->http_client->in_cookie); if(a_http_simple->request_size){ size_t l_dg_request_size_max = a_http_simple->request_size; @@ -199,20 +199,20 @@ enc_http_delegate_t *enc_http_request_decode(struct dap_http_simple *a_http_simp else l_enc_type = DAP_ENC_DATA_TYPE_B64; - size_t l_url_path_size_max = strlen(a_http_simple->http->url_path); + size_t l_url_path_size_max = strlen(a_http_simple->http_client->url_path); if(l_url_path_size_max){ dg->url_path= DAP_NEW_SIZE(char,l_url_path_size_max+1); - dg->url_path_size=dap_enc_decode(l_key, a_http_simple->http->url_path,l_url_path_size_max,dg->url_path, l_url_path_size_max, l_enc_type); + dg->url_path_size=dap_enc_decode(l_key, a_http_simple->http_client->url_path,l_url_path_size_max,dg->url_path, l_url_path_size_max, l_enc_type); dg->url_path[dg->url_path_size] = 0; log_it(L_DEBUG,"URL path after decode '%s'",dg->url_path ); // log_it(L_DEBUG,"URL path before decode: '%s' after decode '%s'",cl_st->http->url_path,dg->url_path ); } - size_t l_in_query_size=strlen(a_http_simple->http->in_query_string); + size_t l_in_query_size=strlen(a_http_simple->http_client->in_query_string); if(l_in_query_size){ dg->in_query= DAP_NEW_SIZE(char, l_in_query_size+1); - dg->in_query_size=dap_enc_decode(l_key, a_http_simple->http->in_query_string,l_in_query_size,dg->in_query,l_in_query_size, l_enc_type); + dg->in_query_size=dap_enc_decode(l_key, a_http_simple->http_client->in_query_string,l_in_query_size,dg->in_query,l_in_query_size, l_enc_type); dg->in_query[dg->in_query_size] = 0; log_it(L_DEBUG,"Query string after decode '%s'",dg->in_query); } @@ -233,7 +233,7 @@ enc_http_delegate_t *enc_http_request_decode(struct dap_http_simple *a_http_simp */ void enc_http_reply_encode(struct dap_http_simple *a_http_simple,enc_http_delegate_t * a_http_delegate) { - dap_enc_key_t * key = dap_enc_ks_find_http(a_http_simple->http); + dap_enc_key_t * key = dap_enc_ks_find_http(a_http_simple->http_client); if( key == NULL ) { log_it(L_ERROR, "Can't find http key."); return; diff --git a/dap-sdk/net/server/http_server/dap_http.c b/dap-sdk/net/server/http_server/dap_http.c index 51fe57a57e4b8fbc14e776666dd1ffe1012d2d10..d28c653537df9cd4a78b4d8b1d61fe121fa7eaa6 100644 --- a/dap-sdk/net/server/http_server/dap_http.c +++ b/dap-sdk/net/server/http_server/dap_http.c @@ -47,7 +47,7 @@ #include "dap_common.h" #include "dap_server.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http.h" #include "dap_http_header.h" #include "dap_http_client.h" @@ -99,11 +99,11 @@ int dap_http_new( dap_server_t *sh, const char * server_name ) shttp->server = sh; strncpy( shttp->server_name, server_name, sizeof(shttp->server_name)-1 ); - sh->client_new_callback = dap_http_client_new; - sh->client_delete_callback = dap_http_client_delete; - sh->client_read_callback = dap_http_client_read; - sh->client_write_callback = dap_http_client_write; - sh->client_error_callback = dap_http_client_error; + sh->client_callbacks.new_callback = dap_http_client_new; + sh->client_callbacks.delete_callback = dap_http_client_delete; + sh->client_callbacks.read_callback = dap_http_client_read; + sh->client_callbacks.write_callback = dap_http_client_write; + sh->client_callbacks.error_callback = dap_http_client_error; return 0; } @@ -144,7 +144,7 @@ void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal ,dap_http_client_callback_t headers_write_callback ,dap_http_client_callback_t data_read_callback ,dap_http_client_callback_t data_write_callback - ,dap_http_client_callback_t error_callback + ,dap_http_client_callback_error_t error_callback ) { diff --git a/dap-sdk/net/server/http_server/dap_http_folder.c b/dap-sdk/net/server/http_server/dap_http_folder.c index e3a34342983862540e54aca62b83964213ed4933..857f39775268a9c2affa017e80cd2bfa22e5c52e 100644 --- a/dap-sdk/net/server/http_server/dap_http_folder.c +++ b/dap-sdk/net/server/http_server/dap_http_folder.c @@ -1,310 +1,314 @@ -/* - Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc - All rights reserved. - - This file is part of DAP (Deus Applications Prototypes) the open source project - - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - DAP 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 Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <stdio.h> -#include <unistd.h> -#include <dirent.h> -#include <errno.h> - -#ifndef _WIN32 -#include <sys/types.h> -#include <sys/stat.h> -#else -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#endif - -#include <pthread.h> -#include <magic.h> - -#include "dap_common.h" -#include "dap_client_remote.h" -#include "dap_http.h" -#include "dap_http_client.h" -#include "dap_http_folder.h" -#include "http_status_code.h" - -typedef struct dap_http_url_proc_folder { - char local_path[4096]; - magic_t mime_detector; -} dap_http_url_proc_folder_t; - -#define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior ) - -typedef struct dap_http_file{ - FILE * fd; - size_t position; - char local_path[4096+2048+1]; - dap_http_client_t *client; -} dap_http_file_t; - -#define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor ) - -void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg ); - -#define LOG_TAG "dap_http_folder" - -int dap_http_folder_init( ) -{ - return 0; -} - -void dap_http_folder_deinit( ) -{ - -} - - -/** - * @brief dap_http_folder_add Add folder for reading to the HTTP server - * @param sh Server instance - * @param url_path Beginning part of the URL - * @param local_path Local path that will be read for - */ -int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path ) -{ - if ( !local_path ) { - log_it( L_ERROR, "Directory Path parameter is empty!" ); - return -11; - } - - log_it( L_DEBUG, "Checking url path %s", local_path ); - -#ifndef _WIN32 - DIR *dirptr = opendir( local_path ); - if ( dirptr == NULL ) { - log_it( L_ERROR, "Directory Not Found!" ); - return -11; - } - else { - closedir( dirptr ); - } -#else // WIN32 - - DWORD attr = GetFileAttributesA( local_path ); - if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) { - log_it( L_ERROR, "Directory Not Found!" ); - return -11; - } - -#endif - - log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path ); - - dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) ); - strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path)-1 ); - - up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME ); - - if ( up_folder->mime_detector == NULL) { - log_it( L_CRITICAL,"Can't init MIME detection library" ); - free( up_folder ); - return -1; - } - -#ifndef _WIN32 - if( 0 != magic_load( up_folder->mime_detector, NULL) ) { -#else - if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) { -#endif - - log_it( L_CRITICAL, "Can't load MIME magic detection database" ); - magic_close( up_folder->mime_detector ); - free( up_folder ); - return -2; - } - - dap_http_add_proc( sh, - url_path, - up_folder, - NULL, - NULL, - dap_http_folder_headers_read, - dap_http_folder_headers_write, - dap_http_folder_data_read, - dap_http_folder_data_write, - NULL ); - return 0; -} - -/** - * @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data - * @param cl_ht HTTP client instance - * @param arg Not used - */ -void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) -{ - (void) arg; - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_write(cl_ht->client,true); - dap_client_remote_ready_to_read(cl_ht->client, cl_ht->keep_alive); -} - -#ifdef _WIN32 -time_t FileTimeToUnixTime( FILETIME ft ) -{ - ULARGE_INTEGER ull; - - ull.LowPart = ft.dwLowDateTime; - ull.HighPart = ft.dwHighDateTime; - - return ull.QuadPart / 10000000ULL - 11644473600ULL; -} -#endif - -/** - * @brief dap_http_folder_headers Prepare response HTTP headers for file folder request - * @param cl_ht HTTP client instane - * @param arg Not used - */ -void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg) -{ - (void) arg; - // Get specific data for folder URL processor - dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor; - - // Init specific file response data for HTTP client instance - cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t); - - dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht); - cl_ht_file->client=cl_ht; - - // Produce local path for file to open - dap_snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path ); - log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path); - -#ifndef _WIN32 - - struct stat file_stat; - - if ( stat(cl_ht_file->local_path, &file_stat) != 0 ) - goto err; - - cl_ht->out_last_modified = file_stat.st_mtime; - cl_ht->out_content_length = file_stat.st_size; - -#else - - FILETIME CreationTime; - FILETIME LastAccessTime; - FILETIME LastWriteTime; - - HANDLE fileh = CreateFileA( cl_ht_file->local_path, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_ARCHIVE, - NULL - ); - - if ( fileh == INVALID_HANDLE_VALUE ) - goto err; - - GetFileTime( fileh, - &CreationTime, - &LastAccessTime, - &LastWriteTime ); - - cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime ); - cl_ht->out_content_length = GetFileSize( fileh, NULL ); - - CloseHandle( fileh ); - -#endif - - cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" ); - - if ( cl_ht_file->fd == NULL ) { - log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno)); - cl_ht->reply_status_code = Http_Status_NotFound; - strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); - } - else { - cl_ht->reply_status_code = Http_Status_OK; - strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase)-1 ); - - const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path ); - if( mime_type ) { - strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)-1); - log_it( L_DEBUG, "MIME type detected: '%s'", mime_type ); - } - else { - cl_ht->reply_status_code=Http_Status_NotFound; - cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); - } - } - - return; - -err: - - log_it( L_WARNING, "Can't get file info: %s", strerror(errno) ); - cl_ht->reply_status_code = 404; - strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); - - return; -} - -/** - * @brief dap_http_folder_read HTTP client callback for reading function for the folder processing - * @param cl_ht HTTP client instance - * @param arg Pointer to int with return bytes number - */ -void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg) -{ - int * bytes_return = (int*) arg; // Return number of read bytes - //Do nothing - *bytes_return=cl_ht->client->buf_in_size; -} - -/** - * @brief dap_http_folder_write HTTP client callback for writting function for the folder processing - * @param cl_ht HTTP client instance - * @param arg - */ -void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg) -{ - (void) arg; - dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht); - cl_ht->client->buf_out_size=fread(cl_ht->client->buf_out,1,sizeof(cl_ht->client->buf_out),cl_ht_file->fd); - cl_ht_file->position+=cl_ht->client->buf_out_size; - - if(feof(cl_ht_file->fd)!=0){ - log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path); - //strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out)); - fclose(cl_ht_file->fd); - dap_client_remote_ready_to_write(cl_ht->client,false); - - if ( !cl_ht->keep_alive ) - cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; - } -} - +/* + * 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 <stdio.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> + +#ifndef _WIN32 +#include <sys/types.h> +#include <sys/stat.h> +#else +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <ws2tcpip.h> +#include <io.h> +#endif + +#include <pthread.h> +#include <magic.h> + +#include "dap_common.h" +#include "dap_events_socket.h" +#include "dap_http.h" +#include "dap_http_client.h" +#include "dap_http_folder.h" +#include "http_status_code.h" + +typedef struct dap_http_url_proc_folder { + char local_path[4096]; + magic_t mime_detector; +} dap_http_url_proc_folder_t; + +#define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior ) + +typedef struct dap_http_file{ + FILE * fd; + size_t position; + char local_path[4096+2048+1]; + dap_http_client_t *client; +} dap_http_file_t; + +#define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor ) + +void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg ); + +#define LOG_TAG "dap_http_folder" + +int dap_http_folder_init( ) +{ + return 0; +} + +void dap_http_folder_deinit( ) +{ + +} + + +/** + * @brief dap_http_folder_add Add folder for reading to the HTTP server + * @param sh Server instance + * @param url_path Beginning part of the URL + * @param local_path Local path that will be read for + */ +int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path ) +{ + if ( !local_path ) { + log_it( L_ERROR, "Directory Path parameter is empty!" ); + return -11; + } + + log_it( L_DEBUG, "Checking url path %s", local_path ); + +#ifndef _WIN32 + DIR *dirptr = opendir( local_path ); + if ( dirptr == NULL ) { + log_it( L_ERROR, "Directory Not Found!" ); + return -11; + } + else { + closedir( dirptr ); + } +#else // WIN32 + + DWORD attr = GetFileAttributesA( local_path ); + if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) { + log_it( L_ERROR, "Directory Not Found!" ); + return -11; + } + +#endif + + log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path ); + + dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) ); + strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path)-1 ); + + up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME ); + + if ( up_folder->mime_detector == NULL) { + log_it( L_CRITICAL,"Can't init MIME detection library" ); + free( up_folder ); + return -1; + } + +#ifndef _WIN32 + if( 0 != magic_load( up_folder->mime_detector, NULL) ) { +#else + if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) { +#endif + + log_it( L_CRITICAL, "Can't load MIME magic detection database" ); + magic_close( up_folder->mime_detector ); + free( up_folder ); + return -2; + } + + dap_http_add_proc( sh, + url_path, + up_folder, + NULL, + NULL, + dap_http_folder_headers_read, + dap_http_folder_headers_write, + dap_http_folder_data_read, + dap_http_folder_data_write, + NULL ); + return 0; +} + +/** + * @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data + * @param cl_ht HTTP client instance + * @param arg Not used + */ +void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) +{ + (void) arg; + cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; + cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE; + + dap_events_socket_set_writable_unsafe(cl_ht->esocket,true); + dap_events_socket_set_readable_unsafe(cl_ht->esocket, cl_ht->keep_alive); +} + +#ifdef _WIN32 +time_t FileTimeToUnixTime( FILETIME ft ) +{ + ULARGE_INTEGER ull; + + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + + return ull.QuadPart / 10000000ULL - 11644473600ULL; +} +#endif + +/** + * @brief dap_http_folder_headers Prepare response HTTP headers for file folder request + * @param cl_ht HTTP client instane + * @param arg Not used + */ +void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg) +{ + (void) arg; + // Get specific data for folder URL processor + dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor; + + // Init specific file response data for HTTP client instance + cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t); + + dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht); + cl_ht_file->client=cl_ht; + + // Produce local path for file to open + dap_snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path ); + log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path); + +#ifndef _WIN32 + + struct stat file_stat; + + if ( stat(cl_ht_file->local_path, &file_stat) != 0 ) + goto err; + + cl_ht->out_last_modified = file_stat.st_mtime; + cl_ht->out_content_length = file_stat.st_size; + +#else + + FILETIME CreationTime; + FILETIME LastAccessTime; + FILETIME LastWriteTime; + + HANDLE fileh = CreateFileA( cl_ht_file->local_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE, + NULL + ); + + if ( fileh == INVALID_HANDLE_VALUE ) + goto err; + + GetFileTime( fileh, + &CreationTime, + &LastAccessTime, + &LastWriteTime ); + + cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime ); + cl_ht->out_content_length = GetFileSize( fileh, NULL ); + + CloseHandle( fileh ); + +#endif + + cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" ); + + if ( cl_ht_file->fd == NULL ) { + log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno)); + cl_ht->reply_status_code = Http_Status_NotFound; + strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); + } + else { + cl_ht->reply_status_code = Http_Status_OK; + strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase)-1 ); + + const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path ); + if( mime_type ) { + strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)-1); + log_it( L_DEBUG, "MIME type detected: '%s'", mime_type ); + } + else { + cl_ht->reply_status_code=Http_Status_NotFound; + cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); + } + } + + return; + +err: + + log_it( L_WARNING, "Can't get file info: %s", strerror(errno) ); + cl_ht->reply_status_code = 404; + strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase)-1 ); + + return; +} + +/** + * @brief dap_http_folder_read HTTP client callback for reading function for the folder processing + * @param cl_ht HTTP client instance + * @param arg Pointer to int with return bytes number + */ +void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg) +{ + int * bytes_return = (int*) arg; // Return number of read bytes + //Do nothing + *bytes_return=cl_ht->esocket->buf_in_size; +} + +/** + * @brief dap_http_folder_write HTTP client callback for writting function for the folder processing + * @param cl_ht HTTP client instance + * @param arg + */ +void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg) +{ + (void) arg; + dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht); + cl_ht->esocket->buf_out_size=fread(cl_ht->esocket->buf_out,1,sizeof(cl_ht->esocket->buf_out),cl_ht_file->fd); + cl_ht_file->position+=cl_ht->esocket->buf_out_size; + dap_events_socket_set_writable_unsafe(cl_ht->esocket, true); + + if(feof(cl_ht_file->fd)!=0){ + log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path); + //strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out)); + fclose(cl_ht_file->fd); + dap_events_socket_set_writable_unsafe(cl_ht->esocket,false); + + if ( !cl_ht->keep_alive ) + cl_ht->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + + cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; + } +} + 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 b8beddd0981899b1c3e943d9ac55d9ef681a22a5..9428a6f00d77ed74601667fa6a974debb43086f8 100644 --- a/dap-sdk/net/server/http_server/dap_http_simple.c +++ b/dap-sdk/net/server/http_server/dap_http_simple.c @@ -45,6 +45,9 @@ See more details here <http://www.gnu.org/licenses/>. #include "dap_common.h" #include "dap_config.h" +#include "dap_worker.h" +#include "dap_events.h" +#include "dap_proc_thread.h" #include "dap_http.h" #include "dap_http_client.h" #include "dap_http_simple.h" @@ -59,16 +62,10 @@ See more details here <http://www.gnu.org/licenses/>. #define LOG_TAG "dap_http_simple" -static void s_headers_read( dap_http_client_t *cl_ht, void *arg ); -static void s_data_write( dap_http_client_t *a_http_client, void *a_arg ); -static void s_data_read( dap_http_client_t * cl_ht, void *arg ); -void *dap_http_simple_proc( dap_http_simple_t * cl_sh ); - -static void *loop_http_simple_proc( void *arg ); - -static void async_control_proc( void ); -static void queue_http_request_put( dap_http_simple_t *cl_sh ); - +static void s_http_client_headers_read( dap_http_client_t *cl_ht, void *arg ); +static void s_http_client_data_read( dap_http_client_t * cl_ht, void *arg ); +static void s_http_client_data_write( dap_http_client_t * a_http_client, void *a_arg ); +static bool s_proc_queue_callback(dap_proc_thread_t * a_thread, void *a_arg ); typedef struct dap_http_simple_url_proc { @@ -99,91 +96,16 @@ static bool is_unknown_user_agents_pass = false; #define DAP_HTTP_SIMPLE_URL_PROC(a) ((dap_http_simple_url_proc_t*) (a)->_inheritor) -///static struct ev_loop* http_simple_loop; -///static ev_async async_watcher_http_simple; - -static pthread_mutex_t mutex_on_queue_http_response = PTHREAD_MUTEX_INITIALIZER; -static pthread_t http_simple_loop_thread; -static bool bSimpleLoopThreadQuitSignal = false; - -static dap_http_simple_t **s_requests = NULL; -static dap_http_simple_t **s_requestsproc = NULL; - -static uint32_t s_requests_count = 0; -static uint32_t s_requestsproc_count = 0; - static void _free_user_agents_list( void ); int dap_http_simple_module_init( ) { - s_requests = DAP_NEW_Z_SIZE(dap_http_simple_t*, sizeof(dap_http_simple_t *) * DAP_HTTP_SIMPLE_REQUEST_MAX * 2 ); - if ( !s_requests ) { - - log_it( L_ERROR, "Out of memory" ); - return -1; - } - - s_requestsproc = s_requests + DAP_HTTP_SIMPLE_REQUEST_MAX; - s_requests_count = 0; - - bSimpleLoopThreadQuitSignal = false; - pthread_create( &http_simple_loop_thread, NULL, loop_http_simple_proc, NULL ); - - return 0; + return 0; } void dap_http_simple_module_deinit( void ) { - bSimpleLoopThreadQuitSignal = true; - - pthread_mutex_destroy( &mutex_on_queue_http_response ); - pthread_join( http_simple_loop_thread, NULL ); - - _free_user_agents_list( ); - - if ( s_requests ) { - free( s_requests ); - s_requests = NULL; - } -} - -//#define SIMPLE_LOOP_SLEEP 25 // ms -#define SIMPLE_LOOP_SLEEP 50 // ms - -static struct timespec simple_loop_sleep = { 0, SIMPLE_LOOP_SLEEP * 1000 * 1000 }; - -static void *loop_http_simple_proc( void *arg ) -{ - log_it( L_NOTICE, "Start loop http simple thread" ); - - do { - - pthread_mutex_lock( &mutex_on_queue_http_response ); - if ( s_requests_count ) { - - s_requestsproc_count = s_requests_count; - s_requests_count = 0; - memcpy( s_requestsproc, s_requests, sizeof(void *) * s_requestsproc_count ); - pthread_mutex_unlock( &mutex_on_queue_http_response ); - - for ( uint32_t i = 0; i < s_requestsproc_count; ++ i ) { - dap_http_simple_proc( s_requestsproc[i] ); - s_requestsproc[i]->http->client->no_close = false; -// free( s_requestsproc[i] ); // ??? - } - } - else { - pthread_mutex_unlock( &mutex_on_queue_http_response ); - #ifndef _WIN32 - nanosleep( &simple_loop_sleep, NULL ); - #else - Sleep( SIMPLE_LOOP_SLEEP ); - #endif - } - - } while( !bSimpleLoopThreadQuitSignal ); - - return NULL; + _free_user_agents_list( ); } /** @@ -204,8 +126,8 @@ void dap_http_simple_proc_add( dap_http_t *a_http, const char *a_url_path, size_ l_url_proc, // Internal structure NULL, // Contrustor NULL, // Destructor - s_headers_read, NULL, // Headers read, write - s_data_read, s_data_write, // Data read, write + s_http_client_headers_read, NULL, // Headers read, write + s_http_client_data_read, s_http_client_data_write, // Data read, write NULL); // errror } @@ -253,6 +175,7 @@ END: return result; } + bool dap_http_simple_set_supported_user_agents( const char *user_agents, ... ) { va_list argptr; @@ -305,14 +228,10 @@ inline static bool _is_supported_user_agents_list_setted() inline static void _set_only_write_http_client_state(dap_http_client_t* http_client) { // log_it(L_DEBUG,"_set_only_write_http_client_state"); -// Sleep(300); - - dap_client_remote_ready_to_read(http_client->client,false); -// http_client->state_write=DAP_HTTP_CLIENT_STATE_NONE; http_client->state_write=DAP_HTTP_CLIENT_STATE_START; - dap_client_remote_ready_to_write(http_client->client,true); -// http_client->state_write=DAP_HTTP_CLIENT_STATE_START; + dap_events_socket_set_writable_unsafe(http_client->esocket,true); + dap_events_socket_set_readable_unsafe(http_client->esocket, false); } static void _copy_reply_and_mime_to_response( dap_http_simple_t *cl_sh ) @@ -326,12 +245,12 @@ static void _copy_reply_and_mime_to_response( dap_http_simple_t *cl_sh ) return; } - cl_sh->http->out_content_length = cl_sh->reply_size; - strcpy( cl_sh->http->out_content_type, cl_sh->reply_mime ); + cl_sh->http_client->out_content_length = cl_sh->reply_size; + strcpy( cl_sh->http_client->out_content_type, cl_sh->reply_mime ); return; } -inline static void _write_response_bad_request( dap_http_simple_t * cl_sh, +inline static void _write_response_bad_request( dap_http_simple_t * a_http_simple, const char* error_msg ) { // log_it(L_DEBUG,"_write_response_bad_request"); @@ -341,75 +260,84 @@ inline static void _write_response_bad_request( dap_http_simple_t * cl_sh, json_object_object_add( jobj, "error", json_object_new_string(error_msg) ); log_it( L_DEBUG, "error message %s", json_object_to_json_string(jobj) ); - cl_sh->http->reply_status_code = Http_Status_BadRequest; + a_http_simple->http_client->reply_status_code = Http_Status_BadRequest; const char* json_str = json_object_to_json_string( jobj ); - dap_http_simple_reply(cl_sh, (void*) json_str, + dap_http_simple_reply(a_http_simple, (void*) json_str, (size_t) strlen(json_str) ); - strcpy( cl_sh->reply_mime, "application/json" ); + strcpy( a_http_simple->reply_mime, "application/json" ); - _copy_reply_and_mime_to_response( cl_sh ); + _copy_reply_and_mime_to_response( a_http_simple ); json_object_put( jobj ); // free obj - _set_only_write_http_client_state( cl_sh->http ); } /** * @brief dap_http_simple_proc Execute procession callback and switch to write state * @param cl_sh HTTP simple client instance */ -void* dap_http_simple_proc( dap_http_simple_t *cl_sh ) +bool s_proc_queue_callback(dap_proc_thread_t * a_thread, void * a_arg ) { -// log_it(L_DEBUG, "dap http simple proc"); + (void) a_thread; + dap_http_simple_t *l_http_simple = (dap_http_simple_t*) a_arg; + log_it(L_DEBUG, "dap http simple proc"); // Sleep(300); http_status_code_t return_code = (http_status_code_t)0; if(_is_supported_user_agents_list_setted() == true) { - dap_http_header_t *header = dap_http_header_find(cl_sh->http->in_headers, "User-Agent"); + dap_http_header_t *header = dap_http_header_find(l_http_simple->http_client->in_headers, "User-Agent"); if(header == NULL && is_unknown_user_agents_pass == false) { - const char* error_msg = "Not found User-Agent HTTP header"; - _write_response_bad_request(cl_sh, error_msg); - return NULL; + const char error_msg[] = "Not found User-Agent HTTP header"; + _write_response_bad_request(l_http_simple, error_msg); + _set_only_write_http_client_state( l_http_simple->http_client); + dap_events_socket_assign_on_worker_mt(l_http_simple->esocket, l_http_simple->worker); + return true; } if(_is_user_agent_supported(header->value) == false) { log_it(L_DEBUG, "Not supported user agent in request: %s", header->value); const char* error_msg = "User-Agent version not supported. Update your software"; - _write_response_bad_request(cl_sh, error_msg); - return NULL; + _write_response_bad_request(l_http_simple, error_msg); + _set_only_write_http_client_state( l_http_simple->http_client); + dap_events_socket_assign_on_worker_mt(l_http_simple->esocket, l_http_simple->worker); + return true; } } - DAP_HTTP_SIMPLE_URL_PROC(cl_sh->http->proc)->proc_callback(cl_sh,&return_code); + DAP_HTTP_SIMPLE_URL_PROC(l_http_simple->http_client->proc)->proc_callback(l_http_simple,&return_code); if(return_code) { log_it(L_DEBUG, "Request was processed well return_code=%d", return_code); - cl_sh->http->reply_status_code = (uint16_t)return_code; - _copy_reply_and_mime_to_response(cl_sh); + l_http_simple->http_client->reply_status_code = (uint16_t)return_code; + _copy_reply_and_mime_to_response(l_http_simple); } else { log_it(L_ERROR, "Request was processed with ERROR"); - cl_sh->http->reply_status_code = Http_Status_InternalServerError; + l_http_simple->http_client->reply_status_code = Http_Status_InternalServerError; } - _set_only_write_http_client_state(cl_sh->http); - return NULL; + _set_only_write_http_client_state( l_http_simple->http_client); + dap_events_socket_assign_on_worker_mt(l_http_simple->esocket, l_http_simple->worker); + + return true; } -static void s_headers_read( dap_http_client_t *a_http_client, void *a_arg ) +static void s_http_client_headers_read( dap_http_client_t *a_http_client, void *a_arg ) { (void) a_arg; a_http_client->_inheritor = DAP_NEW_Z( dap_http_simple_t ); - + dap_http_simple_t * l_http_simple = DAP_HTTP_SIMPLE(a_http_client); // log_it(L_DEBUG,"dap_http_simple_headers_read"); // Sleep(300); - DAP_HTTP_SIMPLE(a_http_client)->http = a_http_client; - DAP_HTTP_SIMPLE(a_http_client)->reply_size_max = DAP_HTTP_SIMPLE_URL_PROC( a_http_client->proc )->reply_size_max; - DAP_HTTP_SIMPLE(a_http_client)->reply_byte = DAP_NEW_Z_SIZE(uint8_t, DAP_HTTP_SIMPLE(a_http_client)->reply_size_max ); + 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->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 ); if( a_http_client->in_content_length ) { // dbg if( a_http_client->in_content_length < 3){ @@ -425,21 +353,51 @@ static void s_headers_read( dap_http_client_t *a_http_client, void *a_arg ) log_it(L_ERROR, "Not defined content-length %u in request", a_http_client->in_content_length); } else { log_it( L_DEBUG, "No data section, execution proc callback" ); - queue_http_request_put( DAP_HTTP_SIMPLE(a_http_client) ); + dap_events_socket_remove_from_worker_unsafe(a_http_client->esocket,a_http_client->esocket->worker); + dap_proc_queue_add_callback( l_http_simple->worker->proc_queue, s_proc_queue_callback, l_http_simple); + } } -void s_data_read( dap_http_client_t *a_http_client, void * a_arg ) +static void s_http_client_data_write( dap_http_client_t * a_http_client, void *a_arg ) +{ + (void) a_arg; + dap_http_simple_t *l_http_simple = DAP_HTTP_SIMPLE( a_http_client ); + + // log_it(L_DEBUG,"dap_http_simple_data_write"); + // Sleep(300); + + if ( !l_http_simple->reply ) { + a_http_client->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + log_it( L_WARNING, "No reply to write, close connection" ); + return; + } + + l_http_simple->reply_sent += dap_events_socket_write_unsafe( a_http_client->esocket, + l_http_simple->reply_byte + l_http_simple->reply_sent, + a_http_client->out_content_length - l_http_simple->reply_sent ); + dap_events_socket_set_writable_unsafe(a_http_client->esocket, true); + + if ( l_http_simple->reply_sent >= a_http_client->out_content_length ) { + log_it(L_INFO, "All the reply (%u) is sent out", a_http_client->out_content_length ); + //cl_ht->client->signal_close=cl_ht->keep_alive; + a_http_client->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + //dap_client_ready_to_write(cl_ht->client,false); + DAP_DELETE(l_http_simple->reply ); + } +} + +void s_http_client_data_read( dap_http_client_t *a_http_client, void * a_arg ) { int *ret = (int *)a_arg; - // log_it(L_DEBUG,"dap_http_simple_data_read"); + //log_it(L_DEBUG,"dap_http_simple_data_read"); // Sleep(300); dap_http_simple_t *l_http_simple = DAP_HTTP_SIMPLE(a_http_client); - size_t bytes_to_read = (a_http_client->client->buf_in_size + l_http_simple->request_size) < a_http_client->in_content_length ? - a_http_client->client->buf_in_size : ( a_http_client->in_content_length - l_http_simple->request_size ); + size_t bytes_to_read = (a_http_client->esocket->buf_in_size + l_http_simple->request_size) < a_http_client->in_content_length ? + a_http_client->esocket->buf_in_size : ( a_http_client->in_content_length - l_http_simple->request_size ); if( bytes_to_read ) { // Oops! The client sent more data than write in the CONTENT_LENGTH header @@ -450,68 +408,33 @@ void s_data_read( dap_http_client_t *a_http_client, void * a_arg ) l_http_simple->request = DAP_REALLOC(l_http_simple->request, l_http_simple->request_size_max); } if(l_http_simple->request){// request_byte=request - memcpy( l_http_simple->request_byte + l_http_simple->request_size, a_http_client->client->buf_in, bytes_to_read ); + memcpy( l_http_simple->request_byte + l_http_simple->request_size, a_http_client->esocket->buf_in, bytes_to_read ); l_http_simple->request_size += bytes_to_read; } } - + *ret = (int) a_http_client->esocket->buf_in_size; if( l_http_simple->request_size >= a_http_client->in_content_length ) { // bool isOK=true; - log_it( L_DEBUG,"Data collected" ); - queue_http_request_put( l_http_simple ); + 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_proc_queue_add_callback( l_http_simple->worker->proc_queue , s_proc_queue_callback, l_http_simple); } - - *ret = (int) a_http_client->client->buf_in_size; } -/** - * @brief dap_http_simple_data_write - * @param a_http_client - * @param a_arg - */ -static void s_data_write( dap_http_client_t *a_http_client, void *a_arg ) -{ - (void) a_arg; - dap_http_simple_t *cl_st = DAP_HTTP_SIMPLE( a_http_client ); - -// log_it(L_DEBUG,"dap_http_simple_data_write"); -// Sleep(300); - - if ( !cl_st->reply ) { - - a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it( L_WARNING, "No reply to write, close connection" ); - - return; - } - - cl_st->reply_sent += dap_client_remote_write( a_http_client->client, - cl_st->reply_byte + cl_st->reply_sent, - a_http_client->out_content_length - cl_st->reply_sent ); - - if ( cl_st->reply_sent >= a_http_client->out_content_length ) { - log_it(L_INFO, "All the reply (%u) is sent out", a_http_client->out_content_length ); - //cl_ht->client->signal_close=cl_ht->keep_alive; - a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - //dap_client_ready_to_write(cl_ht->client,false); - } - - free( cl_st->reply ); -} - /** * @brief dap_http_simple_reply Add data to the reply buffer * @param shs HTTP simple client instance * @param data * @param data_size */ -size_t dap_http_simple_reply( dap_http_simple_t *a_http_simple, void *a_data, size_t a_data_size ) +size_t dap_http_simple_reply(dap_http_simple_t *a_http_simple, void *a_data, size_t a_data_size ) { size_t l_data_copy_size = (a_data_size > (a_http_simple->reply_size_max - a_http_simple->reply_size) ) ? (a_http_simple->reply_size_max - a_http_simple->reply_size) : a_data_size; - memcpy( a_http_simple->reply_byte + a_http_simple->reply_size, a_data, l_data_copy_size ); + memcpy(a_http_simple->reply_byte+a_http_simple->reply_size, a_data,l_data_copy_size ); + a_http_simple->reply_size += l_data_copy_size; return l_data_copy_size; @@ -522,7 +445,7 @@ size_t dap_http_simple_reply( dap_http_simple_t *a_http_simple, void *a_data, si * @param shs * @param data */ -size_t dap_http_simple_reply_f( dap_http_simple_t * shs, const char * data, ... ) +size_t dap_http_simple_reply_f(dap_http_simple_t * shs, const char * data, ... ) { char buf[4096]; va_list va; @@ -538,26 +461,6 @@ size_t dap_http_simple_reply_f( dap_http_simple_t * shs, const char * data, ... return 0; } -inline void queue_http_request_put( dap_http_simple_t *cl_sh ) -{ -// dap_http_simple_proc( cl_sh ); - - pthread_mutex_lock( &mutex_on_queue_http_response ); - - if ( s_requests_count >= DAP_HTTP_SIMPLE_REQUEST_MAX ) { - - log_it( L_NOTICE, "Requests Buffer is FULL( %u ) ignore request" ); - pthread_mutex_unlock( &mutex_on_queue_http_response ); - return; - } - - log_it( L_WARNING, "queue_http_request_put >>> %u", s_requests_count ); - - s_requests[ s_requests_count ++ ] = cl_sh; - cl_sh->http->client->no_close = true; - - pthread_mutex_unlock( &mutex_on_queue_http_response ); -} /* Key Expired deprecated code */ diff --git a/dap-sdk/net/server/http_server/http_client/dap_http_client.c b/dap-sdk/net/server/http_server/http_client/dap_http_client.c index 81cdd8cdfec2f2f98f544a7a50858864cb902ec2..59f30cf660aefe3d5977ac80c5397f792e3355b6 100644 --- a/dap-sdk/net/server/http_server/http_client/dap_http_client.c +++ b/dap-sdk/net/server/http_server/http_client/dap_http_client.c @@ -36,7 +36,7 @@ #include <pthread.h> #include "dap_common.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http.h" #include "http_status_code.h" @@ -44,11 +44,7 @@ #include "dap_http_header.h" #include "dap_http_client.h" -#define LOG_TAG "http_client" - -//#define BUF_SIZE 2048 - -void dap_http_client_out_header_generate( dap_http_client_t *cl_ht ); +#define LOG_TAG "dap_http_client" /** * @brief dap_http_client_init Init HTTP client module @@ -73,21 +69,20 @@ void dap_http_client_deinit( ) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_new( dap_client_remote_t *cl, void *arg ) +void dap_http_client_new( dap_events_socket_t *cl, void *arg ) { - (void) arg; + (void) arg; - log_it( L_NOTICE, "dap_http_client_new" ); - cl->_inheritor = DAP_NEW_Z( dap_http_client_t ); + cl->_inheritor = DAP_NEW_Z( dap_http_client_t ); - dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); - cl_ht->client = cl; - cl_ht->http = DAP_HTTP( cl->server ); - cl_ht->state_read = DAP_HTTP_CLIENT_STATE_START; - cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + cl_ht->esocket = cl; + cl_ht->http = DAP_HTTP( cl->server ); + cl_ht->state_read = DAP_HTTP_CLIENT_STATE_START; + cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; - return; + return; } /** @@ -95,25 +90,27 @@ void dap_http_client_new( dap_client_remote_t *cl, void *arg ) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_delete( dap_client_remote_t * cl, void *arg ) +void dap_http_client_delete( dap_events_socket_t * cl, void *arg ) { - dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); - - while( cl_ht->in_headers ) - dap_http_header_remove( &cl_ht->in_headers, cl_ht->in_headers ); + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + if (cl_ht == NULL){ // Client is in proc callback in another thread so we don't delete it + return; + } + while( cl_ht->in_headers ) + dap_http_header_remove( &cl_ht->in_headers, cl_ht->in_headers ); - while( cl_ht->out_headers ) - dap_http_header_remove( &cl_ht->out_headers, cl_ht->out_headers ); + while( cl_ht->out_headers ) + dap_http_header_remove( &cl_ht->out_headers, cl_ht->out_headers ); - if( cl_ht->proc ) { - if( cl_ht->proc->delete_callback ) { - cl_ht->proc->delete_callback( cl_ht, NULL ); + if( cl_ht->proc ) { + if( cl_ht->proc->delete_callback ) { + cl_ht->proc->delete_callback( cl_ht, NULL ); + } } - } - if( cl_ht->_inheritor ) { - free( cl_ht->_inheritor ); - } + if( cl_ht->_inheritor ) { + free( cl_ht->_inheritor ); + } (void) arg; } @@ -203,7 +200,7 @@ int32_t z_rootdirname( char *path, uint32_t len ) ++ptr; } - int32_t len2 = (uint32_t)(ptr - path); + uint32_t len2 = (uint32_t)(ptr - path); if ( len2 == len ) return 0; @@ -212,6 +209,13 @@ int32_t z_rootdirname( char *path, uint32_t len ) return len2; } +/** + * @brief dap_http_request_line_parse + * @param cl_ht + * @param buf + * @param buf_length + * @return + */ bool dap_http_request_line_parse( dap_http_client_t *cl_ht, char *buf, size_t buf_length ) { size_t pos; @@ -293,13 +297,18 @@ bool dap_http_request_line_parse( dap_http_client_t *cl_ht, char *buf, size_t bu return cl_ht->url_path[0] && cl_ht->action[0]; } -static inline void ReportErrorAndRestart( dap_client_remote_t *cl, dap_http_client_t *cl_ht ) +/** + * @brief s_report_error_and_restart + * @param cl + * @param cl_ht + */ +static inline void s_report_error_and_restart( dap_events_socket_t *cl, dap_http_client_t *cl_ht ) { cl->buf_in_size = 0; cl_ht->state_read = DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_read( cl_ht->client, false ); - dap_client_remote_ready_to_write( cl_ht->client, true ); + dap_events_socket_set_readable_unsafe( cl_ht->esocket, false ); + dap_events_socket_set_writable_unsafe( cl_ht->esocket, true ); cl_ht->reply_status_code = 505; strcpy( cl_ht->reply_reason_phrase, "Error" ); @@ -313,214 +322,155 @@ static inline void ReportErrorAndRestart( dap_client_remote_t *cl, dap_http_clie * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_read( dap_client_remote_t *cl, void *arg ) +void dap_http_client_read( dap_events_socket_t *a_esocket, void *arg ) { - char buf_line[4096] = {'\0'}; - dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT( a_esocket ); // log_it( L_DEBUG, "dap_http_client_read..." ); - //log_it( L_DEBUG, "HTTP client in state read %d taked bytes in input %lu", cl_ht->state_read, cl->buf_in_size ); - - do { - switch( cl_ht->state_read ) { - - case DAP_HTTP_CLIENT_STATE_START: { // Beginning of the session. We try to detect - - char *peol; - uint32_t eol; - - if (!(peol = (char*)memchr(cl->buf_in, 10, cl->buf_in_size))) { /// search LF - peol = (char*)memchr(cl->buf_in, 13, cl->buf_in_size); - } - - if (peol) { - eol = peol - cl->buf_in; - if (eol <= 0) { - eol = cl->buf_in_size - 2; - } - } else { - log_it( L_WARNING, "Single-line, possibly trash, input detected"); - eol = cl->buf_in_size - 2; - } - - if ( eol + 3 >= sizeof(buf_line) ) { - log_it( L_WARNING,"Too big line in request, more than %llu symbols - thats very strange", sizeof(buf_line) - 3 ); - ReportErrorAndRestart( cl, cl_ht ); - break; - } - - memcpy( buf_line, cl->buf_in, eol + 1 ); // copy with LF - - dap_client_remote_shrink_buf_in( cl, eol + 1 ); - buf_line[ eol + 2 ] = 0; // null terminate - - // parse http_request_line - if ( !dap_http_request_line_parse(cl_ht, buf_line, eol + 1) ) { - - log_it( L_WARNING, "Input: Wrong request line '%s'", buf_line ); - ReportErrorAndRestart( cl, cl_ht ); - break; - } - -// uint32_t action_len; -// uint32_t url_path_len; - - char *query_string; - - if( (query_string = strchr(cl_ht->url_path, '?')) != NULL ) { - - size_t len_after = strlen( query_string + 1 ); - - if ( len_after ) { - if( len_after > (sizeof(cl_ht->in_query_string) - 1) ) - len_after = sizeof(cl_ht->in_query_string) - 1; - - if ( strstr(query_string, "HTTP/1.1") ) - strncpy( cl_ht->in_query_string, query_string + 1, len_after - 11 ); - else - strncpy( cl_ht->in_query_string,query_string + 1, len_after ); - - if ( cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] == ' ' ) - cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] = 0; - - query_string[0] = 0; - } - } - - log_it( L_WARNING, "Input: %s request for %s document (query string '%s')", cl_ht->action, cl_ht->url_path, cl_ht->in_query_string ? cl_ht->in_query_string : "" ); - - dap_http_url_proc_t *url_proc; - int32_t tpos = z_dirname( cl_ht->url_path, 0 ); - log_it( L_WARNING, "cl_ht->url_path(dir) = %s", cl_ht->url_path ); - - HASH_FIND_STR( cl_ht->http->url_proc, cl_ht->url_path, url_proc ); // Find URL processor - - cl_ht->proc = url_proc; - - if ( tpos ) - cl_ht->url_path[ tpos ] = '/'; - - char *ptr = z_basename( cl_ht->url_path, 0 ); - log_it( L_WARNING, "basename = %s", ptr ); - -// log_it( L_WARNING, "cl_ht->client->socket = %u efd %u", cl_ht->client->socket, cl_ht->client->efd ); - - memmove( cl_ht->url_path, ptr, strlen(ptr) + 1 ); - - log_it( L_WARNING, "cl_ht->url_path = %s", cl_ht->url_path ); - - if ( url_proc ) { - cl_ht->state_read = DAP_HTTP_CLIENT_STATE_HEADERS; - } - else { - log_it( L_WARNING, "Input: unprocessed URL request %s is rejected", cl_ht->url_path ); - ReportErrorAndRestart( cl, cl_ht ); - break; - } - - } - break; - - case DAP_HTTP_CLIENT_STATE_HEADERS: { // Parse input headers - -// log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS" ); - char *peol; - uint32_t eol; - - if ( !(peol = (char *)memchr(cl->buf_in, 10, cl->buf_in_size)) ) { /// search LF - log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS: no LF" ); - ReportErrorAndRestart( cl, cl_ht ); - break; - } - - eol = peol - cl->buf_in; - -// int eol = detect_end_of_line( cl->buf_in, cl->buf_in_size ); - -// if ( eol < 0 ) { -// log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS: no LF" ); -// return; -// } - - int parse_ret; - memcpy( buf_line, cl->buf_in, eol + 1 ); - buf_line[eol-1] = 0; - - parse_ret = dap_http_header_parse( cl_ht, buf_line ); - -// log_it( L_WARNING, "cl_ht->client->socket = %u efd %u", cl_ht->client->socket, cl_ht->client->efd ); - - // log_it(L_WARNINGNG, "++ ALL HEADERS TO PARSE [%s]", buf_line); - if( parse_ret < 0 ) - log_it( L_WARNING, "Input: not a valid header '%s'", buf_line ); - - else if ( parse_ret == 1 ) { - - log_it( L_INFO, "Input: HTTP headers are over" ); - - if ( cl_ht->proc->access_callback ) { - -// log_it( L_WARNING, "access_callback" ); - - bool isOk = true; - cl_ht->proc->access_callback( cl_ht, &isOk ); - if ( !isOk ) { - log_it( L_NOTICE, "Access restricted" ); - ReportErrorAndRestart( cl, cl_ht ); - } - } - - if ( cl_ht->proc->headers_read_callback ) { - log_it( L_WARNING, "headers_read_callback" ); - cl_ht->proc->headers_read_callback( cl_ht, NULL ); - } - - // If no headers callback we go to the DATA processing - if( cl_ht->in_content_length ) { - log_it( L_WARNING, "headers -> DAP_HTTP_CLIENT_STATE_DATA" ); - cl_ht->state_read = DAP_HTTP_CLIENT_STATE_DATA; - } - else { - //log_it - //cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - //cl_ht->client->ready_to_read=t; - //cl_ht->client->signal_close=!cl_ht->keep_alive; - } - } // parse_ret == 1 - - dap_client_remote_shrink_buf_in( cl, eol + 1 ); - } - break; - - case DAP_HTTP_CLIENT_STATE_DATA: - { - // log_it(L_WARNINGNG, "DBG_#002 [%s] [%s]", cl_ht->in_query_string, cl_ht->url_path); - - size_t read_bytes = 0; - if ( cl_ht->proc->data_read_callback ) { -// log_it( L_WARNING, "cl_ht->proc->data_read_callback()" ); - - //while(cl_ht->client->buf_in_size){ - cl_ht->proc->data_read_callback( cl_ht, &read_bytes ); - dap_client_remote_shrink_buf_in( cl, read_bytes ); - //} - } - else { - log_it( L_WARNING, "data_read callback is NULL in DAP_HTTP_CLIENT_STATE_DATA" ); - cl->buf_in_size = 0; - } - } - break; - - case DAP_HTTP_CLIENT_STATE_NONE: { - cl->buf_in_size = 0; - } - break; - - } // switch - - } while ( cl->buf_in_size > 0 ); - + do{ + //log_it( L_DEBUG, "HTTP client in state read %d taked bytes in input %lu", l_http_client->state_read, a_esocket->buf_in_size ); + switch( l_http_client->state_read ) { + case DAP_HTTP_CLIENT_STATE_START: { // Beginning of the session. We try to detect + char l_buf_line[4096]; + char *peol; + uint32_t eol; + + if (!(peol = (char*)memchr(a_esocket->buf_in, 10, a_esocket->buf_in_size))) { /// search LF + peol = (char*)memchr(a_esocket->buf_in, 13, a_esocket->buf_in_size); + } + + if (peol) { + eol = peol - a_esocket->buf_in_str; + if (eol <= 0) { + eol = a_esocket->buf_in_size - 2; + } + } else { + log_it( L_WARNING, "Single-line, possibly trash, input detected"); + eol = a_esocket->buf_in_size - 2; + } + + if ( eol + 3 >= sizeof(l_buf_line) ) { + log_it( L_WARNING,"Too big line in request, more than %llu symbols - thats very strange", sizeof(l_buf_line) - 3 ); + s_report_error_and_restart( a_esocket, l_http_client ); + break; + } + + memcpy( l_buf_line, a_esocket->buf_in, eol + 1 ); // copy with LF + + dap_events_socket_shrink_buf_in( a_esocket, eol + 1 ); + l_buf_line[ eol + 2 ] = 0; // null terminate + + // parse http_request_line + if ( !dap_http_request_line_parse(l_http_client, l_buf_line, eol + 1) ) { + log_it( L_WARNING, "Input: Wrong request line '%s'", l_buf_line ); + s_report_error_and_restart( a_esocket, l_http_client ); + break; + } + + char *l_query_string; + if( (l_query_string = strchr(l_http_client->url_path, '?')) != NULL ) { + size_t len_after = strlen( l_query_string + 1 ); + + if ( len_after ) { + if( len_after > (sizeof(l_http_client->in_query_string) - 1) ){ + len_after = sizeof(l_http_client->in_query_string) - 1; + } + + if ( strstr(l_query_string, "HTTP/1.1") ){ + strncpy( l_http_client->in_query_string, l_query_string + 1, len_after - 11 ); + }else{ + strncpy( l_http_client->in_query_string,l_query_string + 1, len_after ); + } + + if ( l_http_client->in_query_string[strlen(l_http_client->in_query_string) - 1] == ' ' ){ + l_http_client->in_query_string[strlen(l_http_client->in_query_string) - 1] = 0; + } + l_query_string[0] = 0; + } + } + + log_it( L_INFO, "Input: %s request for %s document (query string '%s')", l_http_client->action, l_http_client->url_path, l_http_client->in_query_string[0] ? l_http_client->in_query_string : "" ); + + dap_http_url_proc_t *url_proc; + int32_t tpos = z_dirname( l_http_client->url_path, 0 ); + HASH_FIND_STR( l_http_client->http->url_proc, l_http_client->url_path, url_proc ); // Find URL processor + l_http_client->proc = url_proc; + + if ( tpos ){ + l_http_client->url_path[ tpos ] = '/'; + } + char *ptr = z_basename( l_http_client->url_path, 0 ); + memmove( l_http_client->url_path, ptr, strlen(ptr) + 1 ); + + if ( url_proc ) { + l_http_client->state_read = DAP_HTTP_CLIENT_STATE_HEADERS; + } else { + log_it( L_WARNING, "Input: unprocessed URL request %s is rejected", l_http_client->url_path ); + s_report_error_and_restart( a_esocket, l_http_client ); + break; + } + } break; + + case DAP_HTTP_CLIENT_STATE_HEADERS: { // Parse input headers + char l_buf_line[4096]; + char *l_str_eol; + uint32_t l_eol_pos; + + if ( !(l_str_eol = (char *)memchr(a_esocket->buf_in, 10, a_esocket->buf_in_size)) ) { /// search LF + log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS: no LF" ); + s_report_error_and_restart( a_esocket, l_http_client ); + break; + } + + l_eol_pos = l_str_eol - a_esocket->buf_in_str; + + int parse_ret; + memcpy( l_buf_line, a_esocket->buf_in, l_eol_pos + 1 ); + l_buf_line[l_eol_pos-1] = 0; + + parse_ret = dap_http_header_parse( l_http_client, l_buf_line ); + + if( parse_ret < 0 ){ + log_it( L_WARNING, "Input: not a valid header '%s'", l_buf_line ); + }else if ( parse_ret == 1 ) { + log_it( L_INFO, "Input: HTTP headers are over" ); + if ( l_http_client->proc->access_callback ) { + bool isOk = true; + l_http_client->proc->access_callback( l_http_client, &isOk ); + if ( !isOk ) { + log_it( L_NOTICE, "Access restricted" ); + s_report_error_and_restart( a_esocket, l_http_client ); + } + } + + if ( l_http_client->proc->headers_read_callback ) { + l_http_client->proc->headers_read_callback( l_http_client, NULL ); + } + + // If no headers callback we go to the DATA processing + if( l_http_client->in_content_length ) { + //log_it( L_DEBUG, "headers -> DAP_HTTP_CLIENT_STATE_DATA" ); + l_http_client->state_read = DAP_HTTP_CLIENT_STATE_DATA; + } + } + dap_events_socket_shrink_buf_in( a_esocket, l_eol_pos + 1 ); + } break; + case DAP_HTTP_CLIENT_STATE_DATA:{ + size_t read_bytes = 0; + //log_it(L_DEBUG, "dap_http_client_read: DAP_HTTP_CLIENT_STATE_DATA"); + if ( l_http_client->proc->data_read_callback ) { + l_http_client->proc->data_read_callback( l_http_client, &read_bytes ); + dap_events_socket_shrink_buf_in( a_esocket, read_bytes ); + } else { + log_it( L_WARNING, "data_read callback is NULL in DAP_HTTP_CLIENT_STATE_DATA" ); + a_esocket->buf_in_size = 0; + } + } break; + case DAP_HTTP_CLIENT_STATE_NONE: { + a_esocket->buf_in_size = 0; + } break; + } // switch + } while (a_esocket->buf_in_size); // log_it( L_DEBUG, "dap_http_client_read...exit" ); // Sleep(100); } @@ -530,65 +480,64 @@ void dap_http_client_read( dap_client_remote_t *cl, void *arg ) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_write( dap_client_remote_t * cl, void *arg ) +void dap_http_client_write( dap_events_socket_t * cl, void *arg ) { -// log_it( L_DEBUG, "dap_http_client_write..." ); - - (void) arg; - dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); - - // log_it(L_WARNING,"HTTP client write callback in state %d",cl_ht->state_write); - - switch( cl_ht->state_write ) { - case DAP_HTTP_CLIENT_STATE_NONE: - return; - case DAP_HTTP_CLIENT_STATE_START: - { - if ( cl_ht->proc ) - if ( cl_ht->proc->headers_write_callback ) - cl_ht->proc->headers_write_callback( cl_ht, NULL ); - - log_it( L_DEBUG,"Output: HTTP response with %u status code", cl_ht->reply_status_code ); - - dap_client_remote_write_f( cl,"HTTP/1.1 %u %s\r\n",cl_ht->reply_status_code, cl_ht->reply_reason_phrase[0] ? - cl_ht->reply_reason_phrase : http_status_reason_phrase(cl_ht->reply_status_code) ); - - dap_http_client_out_header_generate( cl_ht ); - cl_ht->state_write = DAP_HTTP_CLIENT_STATE_HEADERS; - } - break; - - case DAP_HTTP_CLIENT_STATE_HEADERS: - { - dap_http_header_t *hdr = cl_ht->out_headers; - if ( hdr == NULL ) { - log_it(L_DEBUG, "Output: headers are over (reply status code %u)",cl_ht->reply_status_code); - dap_client_remote_write_f( cl,"\r\n" ); - if ( cl_ht->out_content_length || cl_ht->out_content_ready ) { - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_DATA; - } - else { - log_it( L_DEBUG, "Nothing to output" ); - cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_write( cl, false ); - cl->flags |= DAP_SOCK_SIGNAL_CLOSE; + // log_it( L_DEBUG, "dap_http_client_write..." ); + + (void) arg; + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT( cl ); + //log_it(L_WARNING,"HTTP client write callback in state %d",l_http_client->state_write); + + switch( l_http_client->state_write ) { + case DAP_HTTP_CLIENT_STATE_NONE: + return; + case DAP_HTTP_CLIENT_STATE_START:{ + if ( l_http_client->proc ) + if ( l_http_client->proc->headers_write_callback ) + l_http_client->proc->headers_write_callback( l_http_client, NULL ); + + log_it( L_INFO," HTTP response with %u status code", l_http_client->reply_status_code ); + dap_events_socket_write_f_unsafe(cl, "HTTP/1.1 %u %s\r\n",l_http_client->reply_status_code, l_http_client->reply_reason_phrase[0] ? + l_http_client->reply_reason_phrase : http_status_reason_phrase(l_http_client->reply_status_code) ); + dap_events_socket_set_writable_unsafe(cl, true); + dap_http_client_out_header_generate( l_http_client ); + l_http_client->state_write = DAP_HTTP_CLIENT_STATE_HEADERS; + } break; + + case DAP_HTTP_CLIENT_STATE_HEADERS: { + dap_http_header_t *hdr = l_http_client->out_headers; + if ( hdr == NULL ) { + log_it(L_DEBUG, "Output: headers are over (reply status code %u content_lentgh %u)", + l_http_client->reply_status_code, l_http_client->out_content_length); + dap_events_socket_write_f_unsafe(cl, "\r\n"); + dap_events_socket_set_writable_unsafe(cl, true); + if ( l_http_client->out_content_length || l_http_client->out_content_ready ) { + l_http_client->state_write=DAP_HTTP_CLIENT_STATE_DATA; + } else { + log_it( L_DEBUG, "Nothing to output" ); + l_http_client->state_write = DAP_HTTP_CLIENT_STATE_NONE; + dap_events_socket_set_writable_unsafe( cl, false ); + cl->flags |= DAP_SOCK_SIGNAL_CLOSE; + } + dap_events_socket_set_readable_unsafe( cl, true ); + } else { + //log_it(L_WARNING,"Output: header %s: %s",hdr->name,hdr->value); + dap_events_socket_write_f_unsafe(cl, "%s: %s\r\n", hdr->name, hdr->value); + dap_events_socket_set_writable_unsafe(cl, true); + dap_http_header_remove( &l_http_client->out_headers, hdr ); + } + } break; + case DAP_HTTP_CLIENT_STATE_DATA: + { + if ( l_http_client->proc ){ + if ( l_http_client->proc->data_write_callback ){ + l_http_client->proc->data_write_callback( l_http_client, NULL ); + } + }else{ + log_it(L_WARNING, "No http proc, nothing to write"); + } } - dap_client_remote_ready_to_read( cl, true ); - } - else { - //log_it(L_WARNING,"Output: header %s: %s",hdr->name,hdr->value); - dap_client_remote_write_f( cl, "%s: %s\r\n", hdr->name,hdr->value ); - dap_http_header_remove( &cl_ht->out_headers, hdr ); - } - } - break; - case DAP_HTTP_CLIENT_STATE_DATA: - { - if ( cl_ht->proc ) - if ( cl_ht->proc->data_write_callback ) - cl_ht->proc->data_write_callback( cl_ht, NULL ); - } - break; + break; } } @@ -634,7 +583,7 @@ void dap_http_client_out_header_generate(dap_http_client_t *cl_ht) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_error( struct dap_client_remote *cl, void *arg ) +void dap_http_client_error( dap_events_socket_t *cl, int arg ) { (void) arg; diff --git a/dap-sdk/net/server/http_server/http_client/dap_http_header.c b/dap-sdk/net/server/http_server/http_client/dap_http_header.c index 68b964040fdd2a223754772ef25229ed35e461f0..e2458cadeff4b56331854ff6b474db6f4a0a7d03 100644 --- a/dap-sdk/net/server/http_server/http_client/dap_http_header.c +++ b/dap-sdk/net/server/http_server/http_client/dap_http_header.c @@ -34,7 +34,7 @@ #include <pthread.h> #include "dap_common.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http_client.h" #include "dap_http_header.h" diff --git a/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h b/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h index f90569be39404776caee3d90c15bc566a834d1ca..864233216d48cfb1fda03baacfcb1c1b2f909bb7 100644 --- a/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h +++ b/dap-sdk/net/server/http_server/http_client/include/dap_http_client.h @@ -17,15 +17,11 @@ You should have received a copy of the GNU Lesser General Public License along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef _DAP_HTTP_CLIENT_H_ -#define _DAP_HTTP_CLIENT_H_ - +#pragma once #include <stdint.h> #include <time.h> #include <stdbool.h> -#include "dap_client_remote.h" +#include "dap_events_socket.h" struct dap_http_client; struct dap_http; @@ -39,6 +35,7 @@ typedef enum dap_http_client_state{ } dap_http_client_state_t; typedef void (*dap_http_client_callback_t) (struct dap_http_client *,void * arg); // Callback for specific client operations +typedef void (*dap_http_client_callback_error_t) (struct dap_http_client *,int); // Callback for specific client operations typedef struct dap_http_client { @@ -66,7 +63,7 @@ typedef struct dap_http_client time_t out_last_modified; bool out_connection_close; - dap_client_remote_t *client; + dap_events_socket_t *esocket; struct dap_http * http; uint16_t reply_status_code; @@ -87,16 +84,15 @@ extern "C" { int dap_http_client_init( ); void dap_http_client_deinit( ); +void dap_http_client_new( dap_events_socket_t * cl,void *arg ); // Creates HTTP client's internal structure +void dap_http_client_delete( dap_events_socket_t * cl,void *arg ); // Free memory for HTTP client's internal structure -void dap_http_client_new( dap_client_remote_t * cl,void *arg ); // Creates HTTP client's internal structure -void dap_http_client_delete( dap_client_remote_t * cl,void *arg ); // Free memory for HTTP client's internal structure - -void dap_http_client_read( dap_client_remote_t * cl,void *arg ); // Process read event -void dap_http_client_write( dap_client_remote_t * cl,void *arg ); // Process write event -void dap_http_client_error( dap_client_remote_t * cl,void *arg ); // Process error event +void dap_http_client_read( dap_events_socket_t * cl,void *arg ); // Process read event +void dap_http_client_write( dap_events_socket_t * cl,void *arg ); // Process write event +void dap_http_client_error( dap_events_socket_t * cl,int arg ); // Process error event +void dap_http_client_out_header_generate( dap_http_client_t *cl_ht ); #ifdef __cplusplus } #endif -#endif diff --git a/dap-sdk/net/server/http_server/include/dap_http.h b/dap-sdk/net/server/http_server/include/dap_http.h index 646811940151ee8b8d46f158e90fa6b48165d153..0d1fcfb84f5ff0d6ddc30451e8f225c2537cc974 100644 --- a/dap-sdk/net/server/http_server/include/dap_http.h +++ b/dap-sdk/net/server/http_server/include/dap_http.h @@ -23,7 +23,7 @@ See more details here <http://www.gnu.org/licenses/>. #pragma once #include "dap_server.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http_header.h" #include "dap_http_client.h" #include "uthash.h" @@ -45,7 +45,7 @@ typedef struct dap_http_url_proc{ dap_http_client_callback_t data_read_callback; dap_http_client_callback_t data_write_callback; - dap_http_client_callback_t error_callback; + dap_http_client_callback_error_t error_callback; dap_http_client_callback_t access_callback; @@ -75,5 +75,5 @@ void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal ,dap_http_client_callback_t headers_write_callback ,dap_http_client_callback_t data_read_callback ,dap_http_client_callback_t data_write_callback - ,dap_http_client_callback_t error_callback ); // Add custom procesor for the HTTP server + ,dap_http_client_callback_error_t error_callback ); // Add custom procesor for the HTTP server diff --git a/dap-sdk/net/server/http_server/include/dap_http_folder.h b/dap-sdk/net/server/http_server/include/dap_http_folder.h index 3dec0498a19076fff6cf71e8b4eed3f10ce7c3bc..530afb1e2e43ca00154ccf8611946a048c318acc 100644 --- a/dap-sdk/net/server/http_server/include/dap_http_folder.h +++ b/dap-sdk/net/server/http_server/include/dap_http_folder.h @@ -1,31 +1,30 @@ /* - Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc - All rights reserved. + * 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 (Deus Applications Prototypes) the open source project + This file is part of DAP SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by + 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 is distributed in the hope that it will be useful, + 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 Lesser General Public License for more details. + GNU General Public License for more details. - You should have received a copy of the GNU Lesser General Public License - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. + 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/>. */ - -#ifndef _DAP_HTTP_FOLDER_H_ -#define _DAP_HTTP_FOLDER_H_ - +#pragma once struct dap_http; -extern int dap_http_folder_init(); -extern void dap_http_folder_deinit(); +int dap_http_folder_init(void); +void dap_http_folder_deinit(void); -extern int dap_http_folder_add(struct dap_http *sh, const char * url_path, const char * local_path); // Add folder for reading to the HTTP server +int dap_http_folder_add(struct dap_http *sh, const char * url_path, const char * local_path); // Add folder for reading to the HTTP server -#endif diff --git a/dap-sdk/net/server/http_server/include/dap_http_simple.h b/dap-sdk/net/server/http_server/include/dap_http_simple.h index 0dda2401f49d982c7528307fce9d706dc802f822..bd2ccc1a517751da27a8fa59ba8f3efcff42825f 100644 --- a/dap-sdk/net/server/http_server/include/dap_http_simple.h +++ b/dap-sdk/net/server/http_server/include/dap_http_simple.h @@ -35,28 +35,29 @@ struct dap_http_simple; typedef void ( *dap_http_simple_callback_t )( struct dap_http_simple *, void * ); typedef struct dap_http_simple { - - dap_http_client_t *http; - - union { - void *request; - char *request_str; - uint8_t * request_byte; - }; - - union { - void *reply; - uint8_t *reply_byte; - char *reply_str; - }; - - size_t request_size; - size_t request_size_max; - size_t reply_size; - size_t reply_size_max; - size_t reply_sent; - - char reply_mime[256]; + dap_events_socket_t * esocket; + dap_worker_t * worker; + dap_http_client_t * http_client; + union { + void *request; + char *request_str; + uint8_t * request_byte; + }; + + union { + void *reply; + uint8_t *reply_byte; + char *reply_str; + }; + size_t content_length; + + size_t request_size; + size_t request_size_max; + size_t reply_size; + size_t reply_size_max; + size_t reply_sent; + + char reply_mime[256]; // dap_http_simple_callback_t reply_proc_post_callback; } dap_http_simple_t; diff --git a/dap-sdk/net/stream/ch/dap_stream_ch.c b/dap-sdk/net/stream/ch/dap_stream_ch.c index 2d589d439fe0fe1b0bc3dda5d079b1dab7fd70c1..b28f693ab8148ae67d6eaaf399d612a694a8fcf6 100644 --- a/dap-sdk/net/stream/ch/dap_stream_ch.c +++ b/dap-sdk/net/stream/ch/dap_stream_ch.c @@ -36,12 +36,13 @@ #include <pthread.h> #include "dap_common.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http_client.h" #include "dap_stream.h" #include "dap_stream_ch.h" #include "dap_stream_ch_proc.h" #include "dap_stream_ch_pkt.h" +#include "dap_stream_worker.h" #define LOG_TAG "dap_stream_ch" @@ -88,53 +89,50 @@ dap_stream_ch_t* dap_stream_ch_new(dap_stream_t* a_stream, uint8_t id) { stream_ch_proc_t * proc=stream_ch_proc_find(id); if(proc){ - dap_stream_ch_t* ret = DAP_NEW_Z(dap_stream_ch_t); - ret->stream = a_stream; - ret->proc = proc; - ret->ready_to_read = true; + dap_stream_ch_t* l_ch_new = DAP_NEW_Z(dap_stream_ch_t); + l_ch_new->me = l_ch_new; + l_ch_new->stream = a_stream; + l_ch_new->proc = proc; + l_ch_new->ready_to_read = true; - pthread_mutex_init(&(ret->mutex),NULL); - if(ret->proc->new_callback) - ret->proc->new_callback(ret,NULL); + // Init on stream worker + dap_stream_worker_t * l_stream_worker = a_stream->stream_worker; + l_ch_new->stream_worker = l_stream_worker; + HASH_ADD(hh_worker,l_stream_worker->channels, me,sizeof (void*),l_ch_new); - pthread_rwlock_wrlock(&a_stream->rwlock); - a_stream->channel[ret->stream->channel_count] = ret; + pthread_mutex_init(&(l_ch_new->mutex),NULL); + + // Proc new callback + if(l_ch_new->proc->new_callback) + l_ch_new->proc->new_callback(l_ch_new,NULL); + + a_stream->channel[l_ch_new->stream->channel_count] = l_ch_new; a_stream->channel_count++; - pthread_rwlock_unlock(&a_stream->rwlock); struct dap_stream_ch_table_t *l_new_ch = DAP_NEW_Z(struct dap_stream_ch_table_t); - l_new_ch->ch = ret; + l_new_ch->ch = l_ch_new; pthread_mutex_lock(&s_ch_table_lock); HASH_ADD_PTR(s_ch_table, ch, l_new_ch); pthread_mutex_unlock(&s_ch_table_lock); - return ret; + + return l_ch_new; }else{ log_it(L_WARNING, "Unknown stream processor with id %uc",id); return NULL; } } -struct dap_stream_ch_table_t *dap_stream_ch_valid(dap_stream_ch_t *a_ch) -{ - struct dap_stream_ch_table_t *l_ret; - if(!a_ch) - return false; - pthread_mutex_lock(&s_ch_table_lock); - HASH_FIND_PTR(s_ch_table, &a_ch, l_ret); - if (l_ret) { - pthread_mutex_lock(&a_ch->mutex); - } - pthread_mutex_unlock(&s_ch_table_lock); - return l_ret; -} - /** * @brief stream_ch_delete Delete channel instance * @param ch Channel delete */ void dap_stream_ch_delete(dap_stream_ch_t *a_ch) { + dap_stream_worker_t * l_stream_worker = a_ch->stream_worker; + HASH_DELETE(hh_worker,l_stream_worker->channels, a_ch); + + pthread_mutex_lock(&s_ch_table_lock); struct dap_stream_ch_table_t *l_ret;; HASH_FIND_PTR(s_ch_table, &a_ch, l_ret); @@ -170,24 +168,13 @@ void dap_stream_ch_delete(dap_stream_ch_t *a_ch) * @param a_ch * @param a_is_ready */ -void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * a_ch,bool a_is_ready) +void dap_stream_ch_set_ready_to_read_unsafe(dap_stream_ch_t * a_ch,bool a_is_ready) { - if (!dap_stream_ch_valid(a_ch)) { - return; - } if( a_ch->ready_to_read != a_is_ready){ //log_it(L_DEBUG,"Change channel '%c' to %s", (char) ch->proc->id, is_ready?"true":"false"); a_ch->ready_to_read=a_is_ready; - if(a_ch->stream->conn_udp) - dap_udp_client_ready_to_read(a_ch->stream->conn,a_is_ready); - // for stream server - else if(a_ch->stream->conn) - dap_client_remote_ready_to_read( a_ch->stream->conn,a_is_ready); - // for stream client - else if(a_ch->stream->events_socket) - dap_events_socket_set_readable( a_ch->stream->events_socket, a_is_ready); + dap_events_socket_set_readable_unsafe(a_ch->stream->esocket, a_is_ready); } - pthread_mutex_unlock(&a_ch->mutex); } /** @@ -195,56 +182,14 @@ void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * a_ch,bool a_is_ready) * @param ch * @param is_ready */ -void dap_stream_ch_set_ready_to_write(dap_stream_ch_t * ch,bool is_ready) +void dap_stream_ch_set_ready_to_write_unsafe(dap_stream_ch_t * ch,bool is_ready) { - if (!dap_stream_ch_valid(ch)) { - return; - } if(ch->ready_to_write!=is_ready){ //log_it(L_DEBUG,"Change channel '%c' to %s", (char) ch->proc->id, is_ready?"true":"false"); ch->ready_to_write=is_ready; if(is_ready && ch->stream->conn_http) ch->stream->conn_http->state_write=DAP_HTTP_CLIENT_STATE_DATA; - if(ch->stream->conn_udp) - dap_udp_client_ready_to_write(ch->stream->conn,is_ready); - // for stream server - else if(ch->stream->conn) - dap_client_remote_ready_to_write(ch->stream->conn,is_ready); - // for stream client - else if(ch->stream->events_socket) - dap_events_socket_set_writable(ch->stream->events_socket, is_ready); + dap_events_socket_set_writable_unsafe(ch->stream->esocket, is_ready); } - pthread_mutex_unlock(&ch->mutex); } -/** - * @brief dap_stream_ch_get_ready_to_read - * @param a_ch - * @return - */ -bool dap_stream_ch_get_ready_to_read(dap_stream_ch_t * a_ch) -{ - if (!dap_stream_ch_valid(a_ch)) { - return false; - } - bool l_ret; - l_ret = a_ch->ready_to_read; - pthread_mutex_unlock(&a_ch->mutex); - return l_ret; -} - -/** - * @brief dap_stream_ch_get_ready_to_write - * @param a_ch - * @return - */ -bool dap_stream_ch_get_ready_to_write(dap_stream_ch_t * a_ch) -{ - if (!dap_stream_ch_valid(a_ch)) { - return false; - } - bool l_ret; - l_ret = a_ch->ready_to_write; - pthread_mutex_unlock(&a_ch->mutex); - return l_ret; -} diff --git a/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c b/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c index db22f60fae5d208182e50fefebc60077ada7869d..ab462092341907aff6aa4fda8094bcdbc5c6bdb0 100644 --- a/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c +++ b/dap-sdk/net/stream/ch/dap_stream_ch_pkt.c @@ -41,12 +41,13 @@ #include "dap_enc.h" #include "dap_enc_key.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_stream.h" #include "dap_stream_ch.h" #include "dap_stream_ch_pkt.h" #include "dap_stream_ch_proc.h" #include "dap_stream_pkt.h" +#include "dap_stream_worker.h" #define LOG_TAG "dap_stream_ch_pkt" @@ -65,6 +66,92 @@ void dap_stream_ch_pkt_deinit() } +/** + * @brief dap_stream_ch_pkt_write_f_mt + * @param a_ch + * @param a_type + * @param a_str + * @return + */ +size_t dap_stream_ch_pkt_write_f_mt(dap_stream_worker_t * a_worker , dap_stream_ch_t *a_ch, uint8_t a_type, const char * a_format,...) +{ + va_list ap; + va_start(ap,a_format); + int l_data_size = dap_vsnprintf(NULL,0,a_format,ap); + if (l_data_size <0 ){ + log_it(L_ERROR,"Can't write out formatted data '%s' with values",a_format); + return 0; + } + l_data_size++; // To calc trailing zero + dap_stream_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_stream_worker_msg_io_t); + l_msg->ch = a_ch; + l_msg->ch_pkt_type = a_type; + l_msg->data = DAP_NEW_SIZE(void,l_data_size); + l_msg->flags_set = DAP_SOCK_READY_TO_WRITE; + l_data_size = dap_vsnprintf(l_msg->data,0,a_format,ap); + if (l_data_size <0 ){ + log_it(L_ERROR,"Can't write out formatted data '%s' with values",a_format); + DAP_DELETE(l_msg); + return 0; + } + l_data_size++; + l_msg->data_size = l_data_size; + int l_ret= dap_events_socket_queue_ptr_send(a_worker->queue_ch_io , l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + return 0; + } + return l_data_size; + +} + +/** + * @brief dap_stream_ch_pkt_write_mt + * @param a_ch + * @param a_type + * @param a_data + * @param a_data_size + * @return + */ +size_t dap_stream_ch_pkt_write_mt(dap_stream_worker_t * a_worker , dap_stream_ch_t *a_ch, uint8_t a_type, const void * a_data, size_t a_data_size) +{ + dap_stream_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_stream_worker_msg_io_t); + l_msg->ch = a_ch; + l_msg->ch_pkt_type = a_type; + l_msg->data = DAP_NEW_SIZE(void,a_data_size); + l_msg->flags_set = DAP_SOCK_READY_TO_WRITE; + l_msg->data_size = a_data_size; + memcpy( l_msg->data, a_data, a_data_size); + int l_ret= dap_events_socket_queue_ptr_send(a_worker->queue_ch_io , l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + return 0; + } + return a_data_size; +} + +/** + * @brief dap_stream_ch_check_unsafe + * @param a_worker + * @param a_ch + * @return + */ +bool dap_stream_ch_check_unsafe(dap_stream_worker_t * a_worker,dap_stream_ch_t * a_ch) +{ + if (a_ch){ + if ( a_worker->channels){ + dap_stream_ch_t * l_ch = NULL; + HASH_FIND(hh_worker,a_worker->channels ,&a_ch, sizeof(a_ch), l_ch ); + return l_ch == a_ch; + }else + return false; + }else + return false; +} + + /** * @brief stream_ch_pkt_write @@ -73,16 +160,12 @@ void dap_stream_ch_pkt_deinit() * @param data_size * @return */ -size_t dap_stream_ch_pkt_write(struct dap_stream_ch * a_ch, uint8_t a_type, const void * a_data, size_t a_data_size) +size_t dap_stream_ch_pkt_write_unsafe(dap_stream_ch_t * a_ch, uint8_t a_type, const void * a_data, size_t a_data_size) { - if (! a_data_size){ - log_it(L_WARNING,"Zero data size to write out in channel"); - return 0; - } - if (!dap_stream_ch_valid(a_ch)) { + if (!a_data_size || !a_ch || !a_data) { + log_it(L_WARNING, "NULL ptr or zero data size to write out in channel"); return 0; } - //log_it(L_DEBUG,"Output: Has %u bytes of %c type for %c channel id",data_size, (char)type, (char) ch->proc->id ); dap_stream_ch_pkt_hdr_t l_hdr; @@ -93,29 +176,34 @@ size_t dap_stream_ch_pkt_write(struct dap_stream_ch * a_ch, uint8_t a_type, con l_hdr.type=a_type; l_hdr.enc_type = a_ch->proc->enc_type; - pthread_rwlock_wrlock(&a_ch->stream->rwlock); l_hdr.seq_id=a_ch->stream->seq_id; a_ch->stream->seq_id++; - pthread_rwlock_unlock(&a_ch->stream->rwlock); if ( dap_stream_get_dump_packet_headers() ){ log_it(L_INFO,"Outgoing channel packet: id='%c' size=%u type=0x%02Xu seq_id=0x%016X enc_type=0x%02hhX", (char) l_hdr.id, l_hdr.size, l_hdr.type, l_hdr.seq_id , l_hdr.enc_type ); } + uint8_t * l_buf_selected = a_ch->buf; + uint8_t * l_buf_allocated = NULL; + size_t l_buf_size_required = a_data_size + sizeof(l_hdr); - if(a_data_size+sizeof(l_hdr)> sizeof(a_ch->buf) ){ - log_it(L_ERROR,"Too big data size %lu, bigger than encryption buffer size %lu", a_data_size, sizeof(a_ch->buf)); - a_data_size=sizeof(a_ch->buf)-sizeof(l_hdr); + if(l_buf_size_required > sizeof(a_ch->buf) ){ + log_it(L_WARNING,"packet size is way too big: %lu bytes", a_data_size); + l_buf_allocated = DAP_NEW_Z_SIZE(uint8_t, l_buf_size_required); + l_buf_selected = l_buf_allocated; } - memcpy(a_ch->buf,&l_hdr,sizeof(l_hdr) ); + + memcpy(l_buf_selected,&l_hdr,sizeof(l_hdr) ); if( a_data_size ) - memcpy(a_ch->buf+sizeof(l_hdr),a_data,a_data_size ); + memcpy(l_buf_selected+sizeof(l_hdr),a_data,a_data_size ); - size_t l_ret=dap_stream_pkt_write(a_ch->stream,a_ch->buf,a_data_size+sizeof(l_hdr)); + size_t l_ret=dap_stream_pkt_write_unsafe(a_ch->stream,l_buf_selected,a_data_size+sizeof(l_hdr)); a_ch->stat.bytes_write+=a_data_size; a_ch->ready_to_write=true; - pthread_mutex_unlock( &a_ch->mutex); + + if(l_buf_allocated) + DAP_DELETE(l_buf_allocated); return l_ret; } @@ -126,14 +214,13 @@ size_t dap_stream_ch_pkt_write(struct dap_stream_ch * a_ch, uint8_t a_type, con * @param str * @return */ -size_t dap_stream_ch_pkt_write_f(struct dap_stream_ch * a_ch, uint8_t a_type, const char * a_str,...) +size_t dap_stream_ch_pkt_write_f_unsafe(struct dap_stream_ch * a_ch, uint8_t a_type, const char * a_str,...) { char l_buf[4096]; va_list ap; va_start(ap,a_str); dap_vsnprintf(l_buf,sizeof(l_buf),a_str,ap); va_end(ap); - size_t ret=dap_stream_ch_pkt_write(a_ch,a_type,l_buf,strlen(l_buf)); + size_t ret=dap_stream_ch_pkt_write_unsafe(a_ch,a_type,l_buf,strlen(l_buf)); return ret; } - diff --git a/dap-sdk/net/stream/ch/include/dap_stream_ch.h b/dap-sdk/net/stream/ch/include/dap_stream_ch.h index ff3368e064f2d65e0a8163696c78a687f7bf2eb9..a4da8d255f3d8d2f6b266eef94f699fdaae96ef6 100644 --- a/dap-sdk/net/stream/ch/include/dap_stream_ch.h +++ b/dap-sdk/net/stream/ch/include/dap_stream_ch.h @@ -23,8 +23,9 @@ #include <stdbool.h> #include <pthread.h> #include <stdint.h> - +#include "uthash.h" typedef struct dap_stream dap_stream_t; +typedef struct dap_stream_worker dap_stream_worker_t; typedef struct dap_stream_pkt dap_stream_pkt_t; typedef struct dap_stream_ch_proc dap_stream_ch_proc_t; typedef struct dap_stream_ch dap_stream_ch_t; @@ -39,6 +40,7 @@ typedef struct dap_stream_ch{ bool ready_to_write; bool ready_to_read; dap_stream_t * stream; + dap_stream_worker_t * stream_worker; struct{ uint64_t bytes_write; uint64_t bytes_read; @@ -48,21 +50,17 @@ typedef struct dap_stream_ch{ dap_stream_ch_proc_t * proc; void * internal; + struct dap_stream_ch *me; + UT_hash_handle hh_worker; } dap_stream_ch_t; int dap_stream_ch_init(); void dap_stream_ch_deinit(); dap_stream_ch_t* dap_stream_ch_new( dap_stream_t * dap_stream,uint8_t id); - -void dap_stream_ch_set_ready_to_read(dap_stream_ch_t * ch,bool is_ready); -void dap_stream_ch_set_ready_to_write(dap_stream_ch_t * ch,bool is_ready); - -bool dap_stream_ch_get_ready_to_read(dap_stream_ch_t *a_ch); -bool dap_stream_ch_get_ready_to_write(dap_stream_ch_t *a_ch); - +void dap_stream_ch_set_ready_to_read_unsafe(dap_stream_ch_t * ch,bool is_ready); +void dap_stream_ch_set_ready_to_write_unsafe(dap_stream_ch_t * ch,bool is_ready); void dap_stream_ch_delete(dap_stream_ch_t *a_ch); -struct dap_stream_ch_table_t *dap_stream_ch_valid(dap_stream_ch_t *a_ch); #endif diff --git a/dap-sdk/net/stream/ch/include/dap_stream_ch_pkt.h b/dap-sdk/net/stream/ch/include/dap_stream_ch_pkt.h index 24049870056463045363967e8066fa5209162ffc..47dfac6ebf540ba7bb56f772575480683ab6d252 100644 --- a/dap-sdk/net/stream/ch/include/dap_stream_ch_pkt.h +++ b/dap-sdk/net/stream/ch/include/dap_stream_ch_pkt.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc + Copyright (c) 2020 (c) DeM Labs Ltd http://demlabs.net All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project @@ -26,7 +26,13 @@ #include <stdint.h> #include <stddef.h> -struct dap_stream_ch; + +#include "dap_enc_key.h" + +typedef struct dap_stream_ch dap_stream_ch_t; +typedef struct dap_stream_session dap_stream_session_t; +typedef struct dap_events_socket dap_events_socket_t; +typedef struct dap_stream_worker dap_stream_worker_t; typedef struct dap_stream_ch_pkt_hdr{ uint8_t id; // Channel id uint8_t enc_type; // Zero if not encrypted @@ -45,6 +51,10 @@ typedef struct dap_stream_ch_pkt{ int dap_stream_ch_pkt_init(); void dap_stream_ch_pkt_deinit(); -size_t dap_stream_ch_pkt_write_f(struct dap_stream_ch * a_ch, uint8_t a_type, const char * a_str,...); -size_t dap_stream_ch_pkt_write(struct dap_stream_ch * a_ch, uint8_t a_type, const void * a_data, size_t a_data_size); +size_t dap_stream_ch_pkt_write_f_unsafe(struct dap_stream_ch * a_ch, uint8_t a_type, const char * a_str,...); +size_t dap_stream_ch_pkt_write_unsafe(struct dap_stream_ch * a_ch, uint8_t a_type, const void * a_data, size_t a_data_size); + +bool dap_stream_ch_check_unsafe(dap_stream_worker_t * a_worker,dap_stream_ch_t * a_ch); +size_t dap_stream_ch_pkt_write_f_mt(dap_stream_worker_t * a_worker , dap_stream_ch_t *a_ch, uint8_t a_type, const char * a_str,...); +size_t dap_stream_ch_pkt_write_mt(dap_stream_worker_t * a_worker , dap_stream_ch_t *a_ch, uint8_t a_type, const void * a_data, size_t a_data_size); diff --git a/dap-sdk/net/stream/ch/include/dap_stream_ch_proc.h b/dap-sdk/net/stream/ch/include/dap_stream_ch_proc.h index 1847aa42bfd323b28cf39bf550a1c448958856dd..f3ea2c410c3e1c3b78329ba964816d05e03ab05f 100644 --- a/dap-sdk/net/stream/ch/include/dap_stream_ch_proc.h +++ b/dap-sdk/net/stream/ch/include/dap_stream_ch_proc.h @@ -37,14 +37,14 @@ typedef struct dap_stream_ch_proc{ void * internal; } stream_ch_proc_t; -extern int stream_ch_proc_init(); -extern void stream_ch_proc_deinit(); +int stream_ch_proc_init(); +void stream_ch_proc_deinit(); -extern void dap_stream_ch_proc_add(uint8_t id, +void dap_stream_ch_proc_add(uint8_t id, dap_stream_ch_callback_t new_callback, dap_stream_ch_callback_t delete_callback, dap_stream_ch_callback_t packet_in_callback, dap_stream_ch_callback_t packet_out_callback ); -extern stream_ch_proc_t* stream_ch_proc_find(uint8_t id); +stream_ch_proc_t* stream_ch_proc_find(uint8_t id); #endif diff --git a/dap-sdk/net/stream/session/dap_stream_session.c b/dap-sdk/net/stream/session/dap_stream_session.c index d2faca7c9e40c7560d7902e39ac508d05572b94d..1dcfa0c62168210cf60170b677c5b31e0dbfe74b 100644 --- a/dap-sdk/net/stream/session/dap_stream_session.c +++ b/dap-sdk/net/stream/session/dap_stream_session.c @@ -38,7 +38,7 @@ #define LOG_TAG "dap_stream_session" dap_stream_session_t * sessions=NULL; - +pthread_mutex_t sessions_mutex = PTHREAD_MUTEX_INITIALIZER; int stream_session_close2(dap_stream_session_t * s); static void * session_check(void * data); @@ -52,27 +52,16 @@ void dap_stream_session_deinit() { dap_stream_session_t *current, *tmp; log_it(L_INFO,"Destroy all the sessions"); - + pthread_mutex_lock(&sessions_mutex); HASH_ITER(hh, sessions, current, tmp) { HASH_DEL(sessions,current); - stream_session_close2(current); - } -} - -void dap_stream_session_list() -{ - dap_stream_session_t *current, *tmp; - - log_it(L_INFO,"=== sessions list ======"); - - HASH_ITER( hh, sessions, current, tmp ) { - log_it(L_INFO,"ID %u session %X", current->id, current); - -// HASH_DEL(sessions,current); -// stream_session_close2(current); + if (current->callback_delete) + current->callback_delete(current, NULL); + if (current->_inheritor ) + DAP_DELETE(current->_inheritor); + DAP_DELETE(current); } - - log_it(L_INFO,"=== sessions list ======"); + pthread_mutex_unlock(&sessions_mutex); } @@ -99,8 +88,9 @@ dap_stream_session_t * dap_stream_session_pure_new() ret->create_empty=true; ret->enc_type = 0x01; // Default encryption type log_it(L_DEBUG,"Timestamp %u",(unsigned int) ret->time_created); + pthread_mutex_lock(&sessions_mutex); HASH_ADD_INT(sessions,id,ret); - + pthread_mutex_unlock(&sessions_mutex); return ret; } @@ -114,29 +104,64 @@ dap_stream_session_t * dap_stream_session_new(unsigned int media_id, bool open_p return ret; } -dap_stream_session_t *dap_stream_session_id( unsigned int id ) +/** + * @brief dap_stream_session_id_mt + * @param id + * @return + */ +dap_stream_session_t *dap_stream_session_id_mt( unsigned int id ) { dap_stream_session_t *ret; + dap_stream_session_lock(); HASH_FIND_INT( sessions, &id, ret ); + dap_stream_session_unlock(); + return ret; +} +/** + * @brief dap_stream_session_id_unsafe + * @param id + * @return + */ +dap_stream_session_t *dap_stream_session_id_unsafe( unsigned int id ) +{ + dap_stream_session_t *ret; + HASH_FIND_INT( sessions, &id, ret ); return ret; } +/** + * @brief dap_stream_session_lock + */ +void dap_stream_session_lock() +{ + pthread_mutex_lock(&sessions_mutex); +} + +/** + * @brief dap_stream_session_unlock + */ +void dap_stream_session_unlock() +{ + pthread_mutex_unlock(&sessions_mutex); +} -int dap_stream_session_close(unsigned int id) + +int dap_stream_session_close_mt(unsigned int id) { log_it(L_INFO,"Close session id %u", id); // dap_stream_session_list(); - - dap_stream_session_t *l_s = dap_stream_session_id( id ); - + dap_stream_session_lock(); + dap_stream_session_t *l_s = dap_stream_session_id_unsafe( id ); if(!l_s) { log_it(L_WARNING, "Session id %u not found", id); return -1; } - return stream_session_close2(l_s); + int ret = stream_session_close2(l_s); + dap_stream_session_unlock(); + return ret; } int stream_session_close2(dap_stream_session_t * a_session) diff --git a/dap-sdk/net/stream/session/include/dap_stream_session.h b/dap-sdk/net/stream/session/include/dap_stream_session.h index 2f8d9e624d23a5eebb694515b06796f31aac87f7..921c9ff700227301a39eef1d946e699925796eb7 100644 --- a/dap-sdk/net/stream/session/include/dap_stream_session.h +++ b/dap-sdk/net/stream/session/include/dap_stream_session.h @@ -72,7 +72,11 @@ void dap_stream_session_deinit(); dap_stream_session_t * dap_stream_session_pure_new(); dap_stream_session_t * dap_stream_session_new(unsigned int media_id, bool open_preview); -dap_stream_session_t * dap_stream_session_id(unsigned int id); +dap_stream_session_t * dap_stream_session_id_mt(unsigned int id); +dap_stream_session_t *dap_stream_session_id_unsafe( unsigned int id ); +void dap_stream_session_lock(); +void dap_stream_session_unlock(); + int dap_stream_session_open(dap_stream_session_t * a_session); /*Lock for opening for single client , return 0 if ok*/ -int dap_stream_session_close(unsigned int id); +int dap_stream_session_close_mt(unsigned int id); diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c index ee3b1fd7d5abeee6d461ae2c2d310fd1735fe5fe..35b1dc91dc4cc1c10d8a467f1eef7a603cb5719a 100644 --- a/dap-sdk/net/stream/stream/dap_stream.c +++ b/dap-sdk/net/stream/stream/dap_stream.c @@ -26,6 +26,8 @@ #include <stdint.h> #include <unistd.h> +#include <mqueue.h> + #ifdef _WIN32 #include <winsock2.h> #include <windows.h> @@ -45,33 +47,32 @@ #include "dap_stream_session.h" #include "dap_events_socket.h" -#include "dap_client_remote.h" #include "dap_http.h" #include "dap_http_client.h" #include "dap_http_header.h" #include "dap_udp_server.h" +#include "dap_stream_worker.h" - -#define LOG_TAG "stream" +#define LOG_TAG "dap_stream" #define HEADER_WITH_SIZE_FIELD 12 //This count of bytes enough for allocate memory for stream packet -void stream_proc_pkt_in(dap_stream_t * sid); +static void s_stream_proc_pkt_in(dap_stream_t * a_stream); // Callbacks for HTTP client -void stream_headers_read(dap_http_client_t * sh, void * arg); // Prepare stream when all headers are read +static void s_http_client_headers_read(dap_http_client_t * a_http_client, void * a_arg); // Prepare stream when all headers are read -void s_headers_write(dap_http_client_t * sh, void * arg); // Output headers -void s_data_write(dap_http_client_t * sh, void * arg); // Write the data -void stream_data_read(dap_http_client_t * sh, void * arg); // Read the data +static void s_http_client_headers_write(dap_http_client_t * a_http_client, void * a_arg); // Output headers +static void s_http_client_data_write(dap_http_client_t * a_http_client, void * a_arg); // Write the data +static void s_http_client_data_read(dap_http_client_t * a_http_client, void * a_arg); // Read the data -void s_data_read(dap_client_remote_t* sh, void * arg); -void stream_dap_data_write(dap_client_remote_t* sh, void * arg); -void stream_dap_delete(dap_client_remote_t* sh, void * arg); -void stream_dap_new(dap_client_remote_t* sh,void * arg); +static void s_esocket_data_read(dap_events_socket_t* a_esocket, void * a_arg); +static void s_esocket_write(dap_events_socket_t* a_esocket, void * a_arg); +static void s_esocket_callback_delete(dap_events_socket_t* a_esocket, void * a_arg); +static void s_udp_esocket_new(dap_events_socket_t* a_esocket,void * a_arg); // Internal functions -dap_stream_t * stream_new(dap_http_client_t * a_sh); // Create new stream -void stream_delete(dap_http_client_t * sh, void * arg); +static dap_stream_t * s_stream_new(dap_http_client_t * a_http_client); // Create new stream +static void s_http_client_delete(dap_http_client_t * a_esocket, void * a_arg); //struct ev_loop *keepalive_loop; pthread_t keepalive_thread; @@ -79,8 +80,7 @@ pthread_t keepalive_thread; static dap_stream_t *s_stream_keepalive_list = NULL; static pthread_mutex_t s_mutex_keepalive_list; -static void start_keepalive( dap_stream_t *sid ); -static void keepalive_cb( void ); +static void s_keepalive_cb( void ); static bool s_keep_alive_loop_quit_signal = false; static bool s_dump_packet_headers = false; @@ -88,28 +88,7 @@ static bool s_dump_packet_headers = false; bool dap_stream_get_dump_packet_headers(){ return s_dump_packet_headers; } static struct timespec keepalive_loop_sleep = { 0, STREAM_KEEPALIVE_TIMEOUT * 1000 * 1000 }; - -// Start keepalive stream -static void *stream_loop( void *arg ) -{ - UNUSED(arg); -// keepalive_loop = ev_loop_new(0); -// ev_loop(keepalive_loop, 0); - do { - - #ifndef _WIN32 - //nanosleep( &keepalive_loop_sleep, NULL ); - sleep( STREAM_KEEPALIVE_TIMEOUT ); - #else - Sleep( STREAM_KEEPALIVE_TIMEOUT * 1000 ); - #endif - - keepalive_cb( ); - - } while ( !s_keep_alive_loop_quit_signal ); - - return NULL; -} +static bool s_detect_loose_packet(dap_stream_t * a_stream); /** * @brief stream_init Init stream module @@ -121,10 +100,13 @@ int dap_stream_init( bool a_dump_packet_headers) log_it(L_CRITICAL, "Can't init channel types submodule"); return -1; } - s_dump_packet_headers = a_dump_packet_headers; + if( dap_stream_worker_init() != 0 ){ + log_it(L_CRITICAL, "Can't init stream worker extention submodule"); + return -2; + } + s_dump_packet_headers = a_dump_packet_headers; s_keep_alive_loop_quit_signal = false; - pthread_mutex_init( &s_mutex_keepalive_list, NULL ); //pthread_create( &keepalive_thread, NULL, stream_loop, NULL ); @@ -151,114 +133,63 @@ void dap_stream_deinit() * @param sh HTTP server instance * @param url URL */ -void dap_stream_add_proc_http(struct dap_http * sh, const char * url) +void dap_stream_add_proc_http(struct dap_http * a_http, const char * a_url) { - dap_http_add_proc(sh,url,NULL,NULL,stream_delete,stream_headers_read,s_headers_write,stream_data_read,s_data_write,NULL); + dap_http_add_proc(a_http,a_url + ,NULL, // _internal + NULL, // New + s_http_client_delete, // Delete + s_http_client_headers_read, // Headers read + s_http_client_headers_write, // Headerts write + s_http_client_data_read, // Data read + s_http_client_data_write, // Data write + NULL); // Error callback } /** * @brief stream_add_proc_udp Add processor callback for streaming - * @param sh UDP server instance + * @param a_udp_server UDP server instance */ -void dap_stream_add_proc_udp(dap_udp_server_t * sh) +void dap_stream_add_proc_udp(dap_udp_server_t * a_udp_server) { - dap_server_t* server = sh->dap_server; - server->client_read_callback = s_data_read; - server->client_write_callback = stream_dap_data_write; - server->client_delete_callback = stream_dap_delete; - server->client_new_callback = stream_dap_new; + dap_server_t* l_server = a_udp_server->dap_server; + l_server->client_callbacks.read_callback = s_esocket_data_read; + l_server->client_callbacks.write_callback = s_esocket_write; + l_server->client_callbacks.delete_callback = s_esocket_callback_delete; + l_server->client_callbacks.new_callback = s_udp_esocket_new; } /** * @brief stream_states_update - * @param sid stream instance + * @param a_stream stream instance */ -void stream_states_update(struct dap_stream *sid) +void stream_states_update(struct dap_stream *a_stream) { - if(sid->conn_http) - sid->conn_http->state_write=DAP_HTTP_CLIENT_STATE_START; + if(a_stream->conn_http) + a_stream->conn_http->state_write=DAP_HTTP_CLIENT_STATE_START; size_t i; bool ready_to_write=false; - for(i=0;i<sid->channel_count; i++) - ready_to_write|=sid->channel[i]->ready_to_write; - if(sid->conn_udp) - dap_udp_client_ready_to_write(sid->conn_udp->client,ready_to_write); - else - dap_client_remote_ready_to_write(sid->conn,ready_to_write); - if(sid->conn_http) - sid->conn_http->out_content_ready=true; + for(i=0;i<a_stream->channel_count; i++) + ready_to_write|=a_stream->channel[i]->ready_to_write; + dap_events_socket_set_writable_unsafe(a_stream->esocket,ready_to_write); + if(a_stream->conn_http) + a_stream->conn_http->out_content_ready=true; } -/** - * @brief stream_header_read Read headers callback for HTTP - * @param cl_ht HTTP client structure - * @param arg Not used - */ -void stream_headers_read(dap_http_client_t * cl_ht, void * arg) -{ - (void) arg; - // char * raw=0; - // int raw_size; - unsigned int id=0; - -// log_it(L_DEBUG,"Prepare data stream"); - if(cl_ht->in_query_string[0]){ - log_it(L_INFO,"Query string [%s]",cl_ht->in_query_string); -// if(sscanf(cl_ht->in_query_string,"fj913htmdgaq-d9hf=%u",&id)==1){ - if(sscanf(cl_ht->in_query_string,"session_id=%u",&id) == 1 || - sscanf(cl_ht->in_query_string,"fj913htmdgaq-d9hf=%u",&id) == 1) { - dap_stream_session_t * ss=NULL; - ss=dap_stream_session_id(id); - if(ss==NULL){ - log_it(L_ERROR,"No session id %u was found",id); - cl_ht->reply_status_code=404; - strcpy(cl_ht->reply_reason_phrase,"Not found"); - }else{ - log_it(L_INFO,"Session id %u was found with channels = %s",id,ss->active_channels); - if(dap_stream_session_open(ss)==0){ // Create new stream - dap_stream_t * sid = stream_new(cl_ht); - sid->session=ss; - dap_http_header_t *header = dap_http_header_find(cl_ht->in_headers, "Service-Key"); - if (header) - ss->service_key = strdup(header->value); - size_t count_channels = strlen(ss->active_channels); - for(size_t i = 0; i < count_channels; i++) { - dap_stream_ch_new(sid, ss->active_channels[i]); - //sid->channel[i]->ready_to_write = true; - } - - cl_ht->reply_status_code=200; - strcpy(cl_ht->reply_reason_phrase,"OK"); - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_DATA; - dap_client_remote_ready_to_read(cl_ht->client,true); - - stream_states_update(sid); - }else{ - log_it(L_ERROR,"Can't open session id %u",id); - cl_ht->reply_status_code=404; - strcpy(cl_ht->reply_reason_phrase,"Not found"); - } - } - } - }else{ - log_it(L_ERROR,"No query string"); - } -} /** * @brief stream_new_udp Create new stream instance for UDP client * @param sh DAP client structure */ -dap_stream_t * stream_new_udp(dap_client_remote_t * sh) +dap_stream_t * stream_new_udp(dap_events_socket_t * a_esocket) { dap_stream_t * ret=(dap_stream_t*) calloc(1,sizeof(dap_stream_t)); - ret->conn = sh; - ret->conn_udp=sh->_inheritor; + ret->esocket = a_esocket; ret->buf_defrag_size = 0; - sh->_internal=ret; + a_esocket->_inheritor = ret; log_it(L_NOTICE,"New stream instance udp"); return ret; @@ -269,11 +200,11 @@ dap_stream_t * stream_new_udp(dap_client_remote_t * sh) * @param id session id * @param cl DAP client structure */ -void check_session( unsigned int a_id, dap_client_remote_t *a_client_remote ) +void check_session( unsigned int a_id, dap_events_socket_t *a_esocket ) { dap_stream_session_t *l_session = NULL; - l_session = dap_stream_session_id( a_id ); + l_session = dap_stream_session_id_mt( a_id ); if ( l_session == NULL ) { log_it(L_ERROR,"No session id %u was found",a_id); @@ -289,11 +220,11 @@ void check_session( unsigned int a_id, dap_client_remote_t *a_client_remote ) } dap_stream_t *l_stream; - - if ( DAP_STREAM(a_client_remote) == NULL ) - l_stream = stream_new_udp( a_client_remote ); + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_esocket); + if ( DAP_STREAM(l_http_client) == NULL ) + l_stream = stream_new_udp( a_esocket ); else - l_stream = DAP_STREAM( a_client_remote ); + l_stream = DAP_STREAM( l_http_client ); l_stream->session = l_session; @@ -302,42 +233,43 @@ void check_session( unsigned int a_id, dap_client_remote_t *a_client_remote ) log_it( L_INFO, "Opened stream session technical and data channels" ); - size_t count_channels = strlen(l_session->active_channels); + //size_t count_channels = strlen(l_session->active_channels); for (size_t i =0; i<sizeof (l_session->active_channels); i++ ) if ( l_session->active_channels[i]) dap_stream_ch_new( l_stream, l_session->active_channels[i] ); stream_states_update( l_stream ); - if ( DAP_STREAM(a_client_remote)->conn_udp ) - dap_udp_client_ready_to_read( a_client_remote, true ); - else - dap_client_remote_ready_to_read( a_client_remote, true ); + dap_events_socket_set_readable_unsafe( a_esocket, true ); - start_keepalive( l_stream ); } /** * @brief stream_new Create new stream instance for HTTP client * @return New stream_t instance */ -dap_stream_t * stream_new(dap_http_client_t * a_sh) +dap_stream_t * s_stream_new(dap_http_client_t * a_http_client) { - dap_stream_t * ret=(dap_stream_t*) calloc(1,sizeof(dap_stream_t)); + dap_stream_t * ret= DAP_NEW_Z(dap_stream_t); - pthread_rwlock_init( &ret->rwlock, NULL); - ret->conn = a_sh->client; - ret->conn_http=a_sh; + ret->esocket = a_http_client->esocket; + ret->stream_worker = (dap_stream_worker_t*) a_http_client->esocket->worker->_inheritor; + ret->conn_http=a_http_client; ret->buf_defrag_size = 0; ret->seq_id = 0; ret->client_last_seq_id_packet = (size_t)-1; - ret->conn->_internal=ret; + a_http_client->_inheritor=ret; log_it(L_NOTICE,"New stream instance"); return ret; } + +/** + * @brief dap_stream_delete + * @param a_stream + */ void dap_stream_delete(dap_stream_t *a_stream) { if(a_stream == NULL) { @@ -348,21 +280,16 @@ void dap_stream_delete(dap_stream_t *a_stream) if(s_stream_keepalive_list){ DL_DELETE(s_stream_keepalive_list, a_stream); } - a_stream->conn_udp = NULL; - a_stream->conn = NULL; - a_stream->events_socket = NULL; pthread_mutex_unlock(&s_mutex_keepalive_list); while (a_stream->channel_count) { dap_stream_ch_delete(a_stream->channel[a_stream->channel_count - 1]); } - pthread_rwlock_wrlock(&a_stream->rwlock); if(a_stream->session) - dap_stream_session_close(a_stream->session->id); + dap_stream_session_close_mt(a_stream->session->id); // TODO make stream close after timeout, not momentaly a_stream->session = NULL; - pthread_rwlock_unlock(&a_stream->rwlock); - pthread_rwlock_destroy(&a_stream->rwlock); + a_stream->esocket = NULL; DAP_DELETE(a_stream); log_it(L_NOTICE,"Stream connection is over"); } @@ -372,12 +299,14 @@ void dap_stream_delete(dap_stream_t *a_stream) * @param sh DAP client instance * @param arg Not used */ -void stream_dap_delete(dap_client_remote_t* sh, void * arg) +static void s_esocket_callback_delete(dap_events_socket_t* a_esocket, void * a_arg) { - UNUSED(arg); - if (!sh) + UNUSED(a_arg); + if (!a_esocket) return; - dap_stream_t *l_stream = DAP_STREAM(sh); + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_esocket); + dap_stream_t *l_stream = DAP_STREAM(l_http_client); + l_http_client->_inheritor = NULL; // To prevent double free dap_stream_delete(l_stream); } @@ -387,41 +316,16 @@ void stream_dap_delete(dap_client_remote_t* sh, void * arg) * @param a_es * @return */ -dap_stream_t* dap_stream_new_es(dap_events_socket_t * a_es) +dap_stream_t* dap_stream_new_es_client(dap_events_socket_t * a_esocket) { dap_stream_t * ret= DAP_NEW_Z(dap_stream_t); - pthread_rwlock_init( &ret->rwlock, NULL); - ret->events_socket = a_es; + ret->esocket = a_esocket; ret->buf_defrag_size=0; ret->is_client_to_uplink = true; - - log_it(L_NOTICE,"New stream with events socket instance for %s",a_es->hostaddr); + log_it(L_NOTICE,"New stream with events socket instance for %s",a_esocket->hostaddr); return ret; } -/** - * @brief s_headers_write Prepare headers for output. Creates stream structure - * @param sh HTTP client instance - * @param arg Not used - */ -void s_headers_write(dap_http_client_t * sh, void *arg) -{ - (void) arg; - - if(sh->reply_status_code==200){ - dap_stream_t *sid=DAP_STREAM(sh->client); - - dap_http_out_header_add(sh,"Content-Type","application/octet-stream"); - dap_http_out_header_add(sh,"Connnection","keep-alive"); - dap_http_out_header_add(sh,"Cache-Control","no-cache"); - - if(sid->stream_size>0) - dap_http_out_header_add_f(sh,"Content-Length","%u", (unsigned int) sid->stream_size ); - - sh->state_read=DAP_HTTP_CLIENT_STATE_DATA; - dap_client_remote_ready_to_read(sh->client,true); - } -} /** Function for keepalive loop @@ -442,75 +346,195 @@ static void keepalive_cb (EV_P_ ev_timer *w, int revents) } **/ -static void keepalive_cb( void ) -{ - dap_stream_t *l_stream, *tmp; - return; - pthread_mutex_lock( &s_mutex_keepalive_list ); - DL_FOREACH_SAFE( s_stream_keepalive_list, l_stream, tmp ) { - if ( l_stream->keepalive_passed < STREAM_KEEPALIVE_PASSES ) { - dap_stream_send_keepalive( l_stream ); - l_stream->keepalive_passed += 1; - } - else { - log_it( L_INFO, "Client disconnected" ); - DL_DELETE( s_stream_keepalive_list, l_stream ); - stream_dap_delete( l_stream->conn, NULL ); - } - } - pthread_mutex_unlock( &s_mutex_keepalive_list ); -} +/** + * @brief stream_header_read Read headers callback for HTTP + * @param a_http_client HTTP client structure + * @param a_arg Not used + */ +void s_http_client_headers_read(dap_http_client_t * a_http_client, void * a_arg) +{ + (void) a_arg; + // char * raw=0; + // int raw_size; + unsigned int id=0; + //log_it(L_DEBUG,"Prepare data stream"); + if(a_http_client->in_query_string[0]){ + log_it(L_INFO,"Query string [%s]",a_http_client->in_query_string); +// if(sscanf(cl_ht->in_query_string,"fj913htmdgaq-d9hf=%u",&id)==1){ + if(sscanf(a_http_client->in_query_string,"session_id=%u",&id) == 1 || + sscanf(a_http_client->in_query_string,"fj913htmdgaq-d9hf=%u",&id) == 1) { + dap_stream_session_t * ss=NULL; + ss=dap_stream_session_id_mt(id); + if(ss==NULL){ + log_it(L_ERROR,"No session id %u was found",id); + a_http_client->reply_status_code=404; + strcpy(a_http_client->reply_reason_phrase,"Not found"); + }else{ + log_it(L_INFO,"Session id %u was found with channels = %s",id,ss->active_channels); + if(dap_stream_session_open(ss)==0){ // Create new stream + dap_stream_t * sid = s_stream_new(a_http_client); + sid->session=ss; + dap_http_header_t *header = dap_http_header_find(a_http_client->in_headers, "Service-Key"); + if (header) + ss->service_key = strdup(header->value); + size_t count_channels = strlen(ss->active_channels); + for(size_t i = 0; i < count_channels; i++) { + dap_stream_ch_t * l_ch = dap_stream_ch_new(sid, ss->active_channels[i]); + l_ch->ready_to_read = true; + //sid->channel[i]->ready_to_write = true; + } + a_http_client->reply_status_code=200; + strcpy(a_http_client->reply_reason_phrase,"OK"); + stream_states_update(sid); + a_http_client->state_read=DAP_HTTP_CLIENT_STATE_DATA; + a_http_client->state_write=DAP_HTTP_CLIENT_STATE_START; + dap_events_socket_set_readable_unsafe(a_http_client->esocket,true); + dap_events_socket_set_writable_unsafe(a_http_client->esocket,true); // Dirty hack, because previous function shouldn't + // // set write flag off but it does! + }else{ + log_it(L_ERROR,"Can't open session id %u",id); + a_http_client->reply_status_code=404; + strcpy(a_http_client->reply_reason_phrase,"Not found"); + } + } + } + }else{ + log_it(L_ERROR,"No query string"); + } +} /** - * @brief start_keepalive Start keepalive signals exchange for stream - * @param sid Stream instance + * @brief s_http_client_headers_write Prepare headers for output. Creates stream structure + * @param sh HTTP client instance + * @param arg Not used */ -void start_keepalive( dap_stream_t *sid ) { - return; -// keepalive_loop = EV_DEFAULT; -// sid->keepalive_watcher.data = sid; -// ev_timer_init (&sid->keepalive_watcher, keepalive_cb, STREAM_KEEPALIVE_TIMEOUT, STREAM_KEEPALIVE_TIMEOUT); -// ev_timer_start (keepalive_loop, &sid->keepalive_watcher); - pthread_mutex_lock( &s_mutex_keepalive_list ); - DL_APPEND( s_stream_keepalive_list, sid ); - pthread_mutex_unlock( &s_mutex_keepalive_list ); +static void s_http_client_headers_write(dap_http_client_t * a_http_client, void *a_arg) +{ + (void) a_arg; + //log_it(L_DEBUG,"s_http_client_headers_write()"); + if(a_http_client->reply_status_code==200){ + dap_stream_t *sid=DAP_STREAM(a_http_client); + + dap_http_out_header_add(a_http_client,"Content-Type","application/octet-stream"); + dap_http_out_header_add(a_http_client,"Connnection","keep-alive"); + dap_http_out_header_add(a_http_client,"Cache-Control","no-cache"); + + if(sid->stream_size>0) + dap_http_out_header_add_f(a_http_client,"Content-Length","%u", (unsigned int) sid->stream_size ); + + a_http_client->state_read=DAP_HTTP_CLIENT_STATE_DATA; + dap_events_socket_set_readable_unsafe(a_http_client->esocket,true); + } } /** * @brief stream_data_write HTTP data write callback - * @param sh HTTP client instance - * @param arg Not used + * @param a_http_client HTTP client instance + * @param a_arg Not used */ -void s_data_write(dap_http_client_t * sh, void * arg) +static void s_http_client_data_write(dap_http_client_t * a_http_client, void * a_arg) { - (void) arg; + (void) a_arg; - if(sh->reply_status_code==200){ - stream_dap_data_write(sh->client,arg); + if( a_http_client->reply_status_code == 200 ){ + s_esocket_write(a_http_client->esocket, a_arg); }else{ - log_it(L_WARNING, "Wrong request, reply status code is %u",sh->reply_status_code); + log_it(L_WARNING, "Wrong request, reply status code is %u",a_http_client->reply_status_code); } } /** * @brief s_data_read - * @param sh - * @param arg + * @param a_client + * @param a_arg */ -void s_data_read(dap_client_remote_t* a_client, void * arg) +static void s_esocket_data_read(dap_events_socket_t* a_client, void * a_arg) { - dap_stream_t * l_stream =DAP_STREAM(a_client); - int * ret = (int *) arg; + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_client); + dap_stream_t * l_stream =DAP_STREAM(l_http_client); + int * l_ret = (int *) a_arg; if (s_dump_packet_headers ) { log_it(L_DEBUG,"dap_stream_data_read: ready_to_write=%s, client->buf_in_size=%u" , (a_client->flags & DAP_SOCK_READY_TO_WRITE)?"true":"false", a_client->buf_in_size ); } - *ret = dap_stream_data_proc_read( l_stream); + *l_ret = dap_stream_data_proc_read( l_stream); +} + + + +/** + * @brief stream_dap_data_write Write callback for UDP client + * @param sh DAP client instance + * @param arg Not used + */ +static void s_esocket_write(dap_events_socket_t* a_esocket , void * a_arg){ + (void) a_arg; + size_t i; + bool l_ready_to_write=false; + dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_esocket); + //log_it(L_DEBUG,"Process channels data output (%u channels)", DAP_STREAM(l_http_client)->channel_count ); + for(i=0;i<DAP_STREAM(l_http_client)->channel_count; i++){ + dap_stream_ch_t * ch = DAP_STREAM(l_http_client)->channel[i]; + if(ch->ready_to_write){ + if(ch->proc->packet_out_callback) + ch->proc->packet_out_callback(ch,NULL); + l_ready_to_write|=ch->ready_to_write; + } + } + if (s_dump_packet_headers ) { + log_it(L_DEBUG,"dap_stream_data_write: ready_to_write=%s client->buf_out_size=%u" , + l_ready_to_write?"true":"false", a_esocket->buf_out_size ); + } + dap_events_socket_set_writable_unsafe(a_esocket, l_ready_to_write); + //log_it(L_DEBUG,"stream_dap_data_write ok"); +} + +/** + * @brief stream_dap_new New connection callback for UDP client + * @param sh DAP client instance + * @param arg Not used + */ +static void s_udp_esocket_new(dap_events_socket_t* a_esocket, void * a_arg){ + stream_new_udp(a_esocket); +} + + +/** + * @brief stream_data_read HTTP data read callback. Read packet and passes that to the channel's callback + * @param sh HTTP client instance + * @param arg Processed number of bytes + */ +static void s_http_client_data_read(dap_http_client_t * sh, void * arg) +{ + s_esocket_data_read(sh->esocket,arg); +} + + + +/** + * @brief stream_delete Delete stream and free its resources + * @param sid Stream id + */ +static void s_http_client_delete(dap_http_client_t * sh, void * arg) +{ + s_esocket_callback_delete(sh->esocket,arg); +} + +/** + * @brief dap_stream_set_ready_to_write + * @param a_stream + * @param a_is_ready + */ +void dap_stream_set_ready_to_write(dap_stream_t * a_stream,bool a_is_ready) +{ + if(a_is_ready && a_stream->conn_http) + a_stream->conn_http->state_write=DAP_HTTP_CLIENT_STATE_DATA; + dap_events_socket_set_writable_unsafe(a_stream->esocket,a_is_ready); } /** @@ -523,8 +547,8 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream) bool found_sig=false; dap_stream_pkt_t * pkt=NULL; - char *buf_in = (a_stream->conn) ? (char*)a_stream->conn->buf_in : (char*)a_stream->events_socket->buf_in; - size_t buf_in_size = (a_stream->conn) ? a_stream->conn->buf_in_size : a_stream->events_socket->buf_in_size; + char *buf_in = (a_stream->esocket) ? (char*)a_stream->esocket->buf_in : (char*)a_stream->esocket->buf_in; + size_t buf_in_size = (a_stream->esocket) ? a_stream->esocket->buf_in_size : a_stream->esocket->buf_in_size; uint8_t *proc_data = (uint8_t *)buf_in;//a_stream->conn->buf_in; bool proc_data_defrag=false; // We are or not in defrag buffer size_t read_bytes_to=0; @@ -573,7 +597,7 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream) a_stream->pkt_buf_in = NULL; } else{ - stream_proc_pkt_in(a_stream); + s_stream_proc_pkt_in(a_stream); } } proc_data = (uint8_t *)(buf_in + buf_in_size - bytes_left_to_read);//proc_data=(a_stream->conn->buf_in + a_stream->conn->buf_in_size - bytes_left_to_read); @@ -613,7 +637,7 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream) bytes_left_to_read -= pkt_offset ; found_sig=true; - dap_stream_pkt_t *temp_pkt = dap_stream_pkt_detect( (uint8_t*)pkt + 1 ,pkt->hdr.size+sizeof(stream_pkt_hdr_t) ); + //dap_stream_pkt_t *temp_pkt = dap_stream_pkt_detect( (uint8_t*)pkt + 1 ,pkt->hdr.size+sizeof(stream_pkt_hdr_t) ); if(bytes_left_to_read <(pkt->hdr.size+sizeof(stream_pkt_hdr_t) )){ // Is all the packet in da buf? read_bytes_to=bytes_left_to_read; @@ -644,7 +668,7 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream) if(a_stream->pkt_buf_in_data_size==(pkt->hdr.size + sizeof(stream_pkt_hdr_t))){ // log_it(INFO,"All the packet is present in da buffer (hdr.size=%u read_bytes_to=%u buf_in_size=%u)" // ,sid->pkt_buf_in->hdr.size,read_bytes_to,sid->conn->buf_in_size); - stream_proc_pkt_in(a_stream); + s_stream_proc_pkt_in(a_stream); }else if(a_stream->pkt_buf_in_data_size>pkt->hdr.size + sizeof(stream_pkt_hdr_t)){ //log_it(L_WARNING,"Input: packet buffer has %u bytes more than we need, they're lost",a_stream->pkt_buf_in_data_size-pkt->hdr.size); }else{ @@ -675,126 +699,49 @@ size_t dap_stream_data_proc_read (dap_stream_t *a_stream) return buf_in_size;//a_stream->conn->buf_in_size; } - -/** - * @brief stream_dap_data_write Write callback for UDP client - * @param sh DAP client instance - * @param arg Not used - */ -void stream_dap_data_write(dap_client_remote_t* a_client , void * arg){ - size_t i; - (void) arg; - bool ready_to_write=false; - //log_it(L_DEBUG,"Process channels data output (%u channels)", DAP_STREAM(a_client )->channel_count ); - - for(i=0;i<DAP_STREAM(a_client )->channel_count; i++){ - dap_stream_ch_t * ch = DAP_STREAM(a_client )->channel[i]; - if(ch->ready_to_write){ - if(ch->proc->packet_out_callback) - ch->proc->packet_out_callback(ch,NULL); - ready_to_write|=ch->ready_to_write; - } - } - if (s_dump_packet_headers ) { - log_it(L_DEBUG,"dap_stream_data_write: ready_to_write=%s client->buf_out_size=%u" , - ready_to_write?"true":"false", a_client->buf_out_size ); - } - - /* if(STREAM(sh)->conn_udp) - dap_udp_client_ready_to_write(STREAM(sh)->conn,ready_to_write); - else - dap_client_ready_to_write(sh,ready_to_write);*/ - //log_it(L_ERROR,"No stream_data_write_callback is defined"); - - //log_it(L_DEBUG,"stream_dap_data_write ok"); -} - -/** - * @brief stream_dap_new New connection callback for UDP client - * @param sh DAP client instance - * @param arg Not used - */ -void stream_dap_new(dap_client_remote_t* sh, void * arg){ -// dap_stream_t *sid = stream_new_udp(sh); - stream_new_udp(sh); -} - - -static bool _detect_loose_packet(dap_stream_t * a_stream) -{ - dap_stream_ch_pkt_t * ch_pkt = (dap_stream_ch_pkt_t *) a_stream->pkt_cache; - - pthread_rwlock_wrlock (&a_stream->rwlock); - - int count_loosed_packets = ch_pkt->hdr.seq_id - (a_stream->client_last_seq_id_packet + 1); - if(count_loosed_packets > 0) - { - log_it(L_WARNING, "Detected loosed %d packets. " - "Last read seq_id packet: %d Current: %d", count_loosed_packets, - a_stream->client_last_seq_id_packet, ch_pkt->hdr.seq_id); - } else if(count_loosed_packets < 0) { - if(a_stream->client_last_seq_id_packet != 0 && ch_pkt->hdr.seq_id != 0) { - log_it(L_WARNING, "Something wrong. count_loosed packets %d can't less than zero. " - "Last read seq_id packet: %d Current: %d", count_loosed_packets, - a_stream->client_last_seq_id_packet, ch_pkt->hdr.seq_id); - } // else client don't support seqid functionality - } -// log_it(L_DEBUG, "Packet seq id: %d", ch_pkt->hdr.seq_id); -// log_it(L_DEBUG, "Last seq id: %d", sid->last_seq_id_packet); - a_stream->client_last_seq_id_packet = ch_pkt->hdr.seq_id; - pthread_rwlock_unlock (&a_stream->rwlock); - - return false; -} - - /** * @brief stream_proc_pkt_in * @param sid */ -void stream_proc_pkt_in(dap_stream_t * a_stream) +static void s_stream_proc_pkt_in(dap_stream_t * a_stream) { - pthread_rwlock_wrlock( &a_stream->rwlock ); dap_stream_pkt_t * l_pkt = a_stream->pkt_buf_in; size_t l_pkt_size = a_stream->pkt_buf_in_data_size; a_stream->pkt_buf_in=NULL; a_stream->pkt_buf_in_data_size=0; a_stream->keepalive_passed = 0; - pthread_rwlock_unlock (&a_stream->rwlock); if(l_pkt->hdr.type == STREAM_PKT_TYPE_DATA_PACKET) { dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_stream->pkt_cache; - if(dap_stream_pkt_read(a_stream,l_pkt, l_ch_pkt, sizeof(a_stream->pkt_cache))==0){ + if(dap_stream_pkt_read_unsafe(a_stream,l_pkt, l_ch_pkt, sizeof(a_stream->pkt_cache))==0){ log_it(L_WARNING, "Input: can't decode packet size=%d",l_pkt_size); DAP_DELETE(l_pkt); return; } - _detect_loose_packet(a_stream); + s_detect_loose_packet(a_stream); // Find channel - dap_stream_ch_t * ch = NULL; - pthread_rwlock_wrlock (&a_stream->rwlock); + dap_stream_ch_t * l_ch = NULL; for(size_t i=0;i<a_stream->channel_count;i++){ if(a_stream->channel[i]->proc){ if(a_stream->channel[i]->proc->id == l_ch_pkt->hdr.id ){ - ch=a_stream->channel[i]; + l_ch=a_stream->channel[i]; } } } - pthread_rwlock_unlock (&a_stream->rwlock); - if(ch){ - ch->stat.bytes_read+=l_ch_pkt->hdr.size; - if(ch->proc) - if(ch->proc->packet_in_callback){ + if(l_ch){ + l_ch->stat.bytes_read+=l_ch_pkt->hdr.size; + if(l_ch->proc) + if(l_ch->proc->packet_in_callback){ if ( s_dump_packet_headers ){ log_it(L_INFO,"Income channel packet: id='%c' size=%u type=0x%02Xu seq_id=0x%016X enc_type=0x%02X",(char) l_ch_pkt->hdr.id, l_ch_pkt->hdr.size, l_ch_pkt->hdr.type, l_ch_pkt->hdr.seq_id , l_ch_pkt->hdr.enc_type); } - ch->proc->packet_in_callback(ch,l_ch_pkt); + l_ch->proc->packet_in_callback(l_ch,l_ch_pkt); } } else if(l_ch_pkt->hdr.id == TECHICAL_CHANNEL_ID && l_ch_pkt->hdr.type == STREAM_CH_PKT_TYPE_KEEPALIVE){ @@ -806,54 +753,62 @@ void stream_proc_pkt_in(dap_stream_t * a_stream) stream_srv_pkt_t * srv_pkt = DAP_NEW(stream_srv_pkt_t); memcpy(srv_pkt, l_pkt->data,sizeof(stream_srv_pkt_t)); uint32_t session_id = srv_pkt->session_id; - check_session(session_id,a_stream->conn); + check_session(session_id,a_stream->esocket); DAP_DELETE(srv_pkt); } else { log_it(L_WARNING, "Unknown header type"); } - -// ev_timer_again (keepalive_loop, &a_stream->keepalive_watcher); - start_keepalive( a_stream ); DAP_DELETE(l_pkt); } /** - * @brief stream_data_read HTTP data read callback. Read packet and passes that to the channel's callback - * @param sh HTTP client instance - * @param arg Processed number of bytes + * @brief _detect_loose_packet + * @param a_stream + * @return */ -void stream_data_read(dap_http_client_t * sh, void * arg) +static bool s_detect_loose_packet(dap_stream_t * a_stream) { - s_data_read(sh->client,arg); -} - + dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_stream->pkt_cache; + int l_count_loosed_packets = l_ch_pkt->hdr.seq_id - (a_stream->client_last_seq_id_packet + 1); + if(l_count_loosed_packets > 0) + { + log_it(L_WARNING, "Detected loosed %d packets. " + "Last read seq_id packet: %d Current: %d", l_count_loosed_packets, + a_stream->client_last_seq_id_packet, l_ch_pkt->hdr.seq_id); + } else if(l_count_loosed_packets < 0) { + if(a_stream->client_last_seq_id_packet != 0 && l_ch_pkt->hdr.seq_id != 0) { + log_it(L_WARNING, "Something wrong. count_loosed packets %d can't less than zero. " + "Last read seq_id packet: %d Current: %d", l_count_loosed_packets, + a_stream->client_last_seq_id_packet, l_ch_pkt->hdr.seq_id); + } // else client don't support seqid functionality + } +// log_it(L_DEBUG, "Packet seq id: %d", ch_pkt->hdr.seq_id); +// log_it(L_DEBUG, "Last seq id: %d", sid->last_seq_id_packet); + a_stream->client_last_seq_id_packet = l_ch_pkt->hdr.seq_id; -/** - * @brief stream_delete Delete stream and free its resources - * @param sid Stream id - */ -void stream_delete(dap_http_client_t * sh, void * arg) -{ - stream_dap_delete(sh->client,arg); + return false; } -/** - * @brief dap_stream_set_ready_to_write - * @param a_stream - * @param a_is_ready - */ -void dap_stream_set_ready_to_write(dap_stream_t * a_stream,bool a_is_ready) + +static void s_keepalive_cb( void ) { - if(a_is_ready && a_stream->conn_http) - a_stream->conn_http->state_write=DAP_HTTP_CLIENT_STATE_DATA; - if(a_stream->conn_udp) - dap_udp_client_ready_to_write(a_stream->conn,a_is_ready); - // for stream server - else if(a_stream->conn) - dap_client_remote_ready_to_write(a_stream->conn,a_is_ready); - // for stream client - else if(a_stream->events_socket) - dap_events_socket_set_writable(a_stream->events_socket, a_is_ready); + dap_stream_t *l_stream, *tmp; + return; + pthread_mutex_lock( &s_mutex_keepalive_list ); + DL_FOREACH_SAFE( s_stream_keepalive_list, l_stream, tmp ) { + if ( l_stream->keepalive_passed < STREAM_KEEPALIVE_PASSES ) { + dap_stream_send_keepalive( l_stream ); + l_stream->keepalive_passed += 1; + } + else { + log_it( L_INFO, "Client disconnected" ); + DL_DELETE( s_stream_keepalive_list, l_stream ); + s_esocket_callback_delete( l_stream->esocket, NULL ); + } + } + + pthread_mutex_unlock( &s_mutex_keepalive_list ); } + diff --git a/dap-sdk/net/stream/stream/dap_stream_ctl.c b/dap-sdk/net/stream/stream/dap_stream_ctl.c index 21bd39eb99423262c6199bc573df54b2b48036e8..ef5d72345ae8dbb122417fbf8f92a739da045fd1 100644 --- a/dap-sdk/net/stream/stream/dap_stream_ctl.c +++ b/dap-sdk/net/stream/stream/dap_stream_ctl.c @@ -44,7 +44,7 @@ #include "dap_http.h" #include "dap_http_client.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http_simple.h" #include "dap_stream_session.h" @@ -146,7 +146,7 @@ void s_proc(struct dap_http_simple *a_http_simple, void * a_arg) dap_random_string_fill(key_str, KEX_KEY_STR_SIZE); ss->key = dap_enc_key_new_generate( s_socket_forward_key.type, key_str, KEX_KEY_STR_SIZE, NULL, 0, s_socket_forward_key.size); - dap_http_header_t *l_hdr_key_id = dap_http_header_find(a_http_simple->http->in_headers, "KeyID"); + dap_http_header_t *l_hdr_key_id = dap_http_header_find(a_http_simple->http_client->in_headers, "KeyID"); if (l_hdr_key_id) { dap_enc_ks_key_t *l_ks_key = dap_enc_ks_find(l_hdr_key_id->value); if (!l_ks_key) { diff --git a/dap-sdk/net/stream/stream/dap_stream_pkt.c b/dap-sdk/net/stream/stream/dap_stream_pkt.c index d50740bb9889ce7bfa5c92cba1e93fc1c4eafbfe..9642362c3cb2f06c839b935572e88e7b291c446d 100644 --- a/dap-sdk/net/stream/stream/dap_stream_pkt.c +++ b/dap-sdk/net/stream/stream/dap_stream_pkt.c @@ -25,6 +25,7 @@ #include <stdlib.h> #include <stddef.h> #include <stdint.h> +#include <unistd.h> #ifdef WIN32 #include <winsock2.h> @@ -39,7 +40,8 @@ //#include "config.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" +#include "dap_worker.h" #include "dap_http_client.h" #include "dap_enc.h" @@ -105,7 +107,7 @@ static size_t s_encode_dummy(const void * a_buf, size_t a_buf_size, void * a_buf * @param pkt * @param buf_out */ -size_t dap_stream_pkt_read( dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, void * a_buf_out, size_t a_buf_out_size) +size_t dap_stream_pkt_read_unsafe( dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, void * a_buf_out, size_t a_buf_out_size) { size_t ds = a_stream->session->key->dec_na(a_stream->session->key,a_pkt->data,a_pkt->hdr.size,a_buf_out, a_buf_out_size); // log_it(L_DEBUG,"Stream decoded %lu bytes ( last bytes 0x%02x 0x%02x 0x%02x 0x%02x ) ", ds, @@ -119,6 +121,7 @@ size_t dap_stream_pkt_read( dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, v } +#define DAP_STREAM_CH_PKT_ENCRYPTION_OVERHEAD 200 //in fact is's about 2*16+15 for OAES /** * @brief stream_ch_pkt_write @@ -128,42 +131,61 @@ size_t dap_stream_pkt_read( dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, v * @return */ -size_t dap_stream_pkt_write(dap_stream_t * a_stream, const void * a_data, size_t a_data_size) +size_t dap_stream_pkt_write_unsafe(dap_stream_t * a_stream, const void * a_data, size_t a_data_size) { size_t ret=0; stream_pkt_hdr_t pkt_hdr; - if(a_data_size > STREAM_BUF_SIZE_MAX ){ - log_it(L_ERROR,"Too big data size %lu, bigger than encryption buffer size %lu",a_data_size,sizeof(a_stream->buf)); - a_data_size=sizeof(a_stream->buf); + uint8_t * l_buf_allocated = NULL; + uint8_t * l_buf_selected = a_stream->buf; + size_t l_buf_size_required = a_data_size + DAP_STREAM_CH_PKT_ENCRYPTION_OVERHEAD; + + if(l_buf_size_required > sizeof(a_stream->buf) ){ + l_buf_allocated = DAP_NEW_SIZE(uint8_t, l_buf_size_required); + l_buf_selected = l_buf_allocated; } memset(&pkt_hdr,0,sizeof(pkt_hdr)); memcpy(pkt_hdr.sig,c_dap_stream_sig,sizeof(pkt_hdr.sig)); - pkt_hdr.size =(uint32_t) a_stream->session->key->enc_na(a_stream->session->key, a_data,a_data_size,a_stream->buf, STREAM_BUF_SIZE_MAX); -// printf("*[dap_stream_pkt_write] size=%d key=0x%x _inheritor_size=%d\n", pkt_hdr.size, sid->session->key, -// sid->session->key->_inheritor_size); + pkt_hdr.size =(uint32_t) dap_enc_code( a_stream->session->key, a_data,a_data_size,l_buf_selected, l_buf_size_required, DAP_ENC_DATA_TYPE_RAW); - if(a_stream->conn_udp){ - ret+=dap_udp_client_write(a_stream->conn,&pkt_hdr,sizeof(pkt_hdr)); - ret+=dap_udp_client_write(a_stream->conn,a_stream->buf,pkt_hdr.size); - dap_client_remote_ready_to_write(a_stream->conn, true); - } - else if(a_stream->conn){ - ret+=dap_client_remote_write(a_stream->conn,&pkt_hdr,sizeof(pkt_hdr)); - ret+=dap_client_remote_write(a_stream->conn,a_stream->buf,pkt_hdr.size); - dap_client_remote_ready_to_write(a_stream->conn, true); - } - else if(a_stream->events_socket) { - ret += dap_events_socket_write(a_stream->events_socket, &pkt_hdr, sizeof(pkt_hdr)); - ret += dap_events_socket_write(a_stream->events_socket, a_stream->buf, pkt_hdr.size); - dap_events_socket_set_writable(a_stream->events_socket, true); - } + ret+=dap_events_socket_write_unsafe(a_stream->esocket,&pkt_hdr,sizeof(pkt_hdr)); + ret+=dap_events_socket_write_unsafe(a_stream->esocket,l_buf_selected,pkt_hdr.size); + dap_events_socket_set_writable_unsafe(a_stream->esocket, true); + if(l_buf_allocated) + DAP_DELETE(l_buf_allocated); return ret; } +/** + * @brief dap_stream_pkt_write_mt + * @param a_stream_session + * @param a_es + * @param a_data + * @param a_data_size + * @return + */ +size_t dap_stream_pkt_write_mt(dap_worker_t * a_w,dap_events_socket_t *a_es, dap_enc_key_t *a_key, const void * a_data, size_t a_data_size) +{ + dap_worker_msg_io_t * l_msg = DAP_NEW_Z(dap_worker_msg_io_t); + stream_pkt_hdr_t *l_pkt_hdr; + l_msg->data_size = 16-a_data_size%16+a_data_size+sizeof(*l_pkt_hdr); + l_msg->data = DAP_NEW_SIZE(void,l_msg->data_size); + l_pkt_hdr=(stream_pkt_hdr_t*) l_msg->data; + memset(l_pkt_hdr,0,sizeof(*l_pkt_hdr)); + memcpy(l_pkt_hdr->sig,c_dap_stream_sig,sizeof(l_pkt_hdr->sig)); + l_msg->data_size=sizeof (*l_pkt_hdr) +dap_enc_code(a_key, a_data,a_data_size, ((byte_t*)l_msg->data)+sizeof (*l_pkt_hdr),l_msg->data_size-sizeof (*l_pkt_hdr),DAP_ENC_DATA_TYPE_RAW); + + int l_ret= dap_events_socket_queue_ptr_send(a_w->queue_es_io, l_msg ); + if (l_ret!=0){ + log_it(L_ERROR, "Wasn't send pointer to queue: code %d", l_ret); + DAP_DELETE(l_msg); + return 0; + } + return a_data_size; +} /** @@ -176,7 +198,5 @@ void dap_stream_send_keepalive(dap_stream_t * a_stream) l_pkt.id = TECHICAL_CHANNEL_ID; l_pkt.type=STREAM_CH_PKT_TYPE_KEEPALIVE; - if( dap_stream_pkt_write( a_stream, &l_pkt, sizeof(l_pkt) ) ) - dap_stream_set_ready_to_write( a_stream, true ); + dap_stream_pkt_write_unsafe( a_stream, &l_pkt, sizeof(l_pkt) ); } - diff --git a/dap-sdk/net/stream/stream/dap_stream_worker.c b/dap-sdk/net/stream/stream/dap_stream_worker.c new file mode 100644 index 0000000000000000000000000000000000000000..fe374507f386098af0efc7fad49e6f5973ad5c6b --- /dev/null +++ b/dap-sdk/net/stream/stream/dap_stream_worker.c @@ -0,0 +1,88 @@ +/* + * 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 "dap_common.h" +#include "dap_events.h" +#include "dap_events_socket.h" +#include "dap_stream_worker.h" +#include "dap_stream_ch_pkt.h" + +#define LOG_TAG "dap_stream_worker" + +static void s_ch_io_callback(dap_events_socket_t * a_es, void * a_msg); + +/** + * @brief dap_stream_worker_init + * @return + */ +int dap_stream_worker_init() +{ + uint32_t l_worker_count = dap_events_worker_get_count(); + for (uint32_t i = 0; i < l_worker_count; i++){ + dap_worker_t * l_worker = dap_events_worker_get(i); + if (!l_worker) { + log_it(L_CRITICAL,"Can't init stream worker, woreker thread don't exist"); + return -2; + } + if (l_worker->_inheritor){ + log_it(L_CRITICAL,"Can't init stream worker, core worker has already inheritor"); + return -1; + } + dap_stream_worker_t *l_stream_worker = DAP_NEW_Z(dap_stream_worker_t); + l_worker->_inheritor = l_stream_worker; + l_stream_worker->worker = l_worker; + l_stream_worker->queue_ch_io = dap_events_socket_create_type_queue_ptr_mt( l_worker, s_ch_io_callback); + } + return 0; +} + +/** + * @brief s_ch_io_callback + * @param a_es + * @param a_msg + */ +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_msg_io_t * l_msg = (dap_stream_worker_msg_io_t*) a_msg; + + // Check if it was removed from the list + dap_stream_ch_t *l_msg_ch = NULL; + HASH_FIND(hh_worker, l_stream_worker->channels , &l_msg->ch , sizeof (void*), l_msg_ch ); + if ( l_msg_ch == NULL){ + log_it(L_DEBUG, "We got i/o message for client thats now not in list. Lost %u data", l_msg->data_size); + DAP_DELETE(l_msg); + return; + } + + if (l_msg->flags_set & DAP_SOCK_READY_TO_READ) + dap_stream_ch_set_ready_to_read_unsafe(l_msg_ch, true); + if (l_msg->flags_unset & DAP_SOCK_READY_TO_READ) + dap_stream_ch_set_ready_to_read_unsafe(l_msg_ch, false); + if (l_msg->flags_set & DAP_SOCK_READY_TO_WRITE) + dap_stream_ch_set_ready_to_write_unsafe(l_msg_ch, true); + if (l_msg->flags_unset & DAP_SOCK_READY_TO_WRITE) + dap_stream_ch_set_ready_to_write_unsafe(l_msg_ch, false); + if (l_msg->data_size && l_msg->data) + dap_stream_ch_pkt_write_unsafe(l_msg_ch, l_msg->ch_pkt_type, l_msg->data,l_msg->data_size); + DAP_DELETE(l_msg); +} diff --git a/dap-sdk/net/stream/stream/include/dap_stream.h b/dap-sdk/net/stream/stream/include/dap_stream.h index 2e3aa9c2853cebbf29d7573f369ed3530b0d9d31..888be346b5ae1b3b43b0d3aea5bc9004bfc999e1 100644 --- a/dap-sdk/net/stream/stream/include/dap_stream.h +++ b/dap-sdk/net/stream/stream/include/dap_stream.h @@ -52,15 +52,11 @@ typedef void (*dap_stream_callback)( dap_stream_t *,void*); typedef struct dap_stream { int id; - pthread_rwlock_t rwlock; dap_stream_session_t * session; - struct dap_client_remote * conn; // Connection - + dap_events_socket_t * esocket; // Connection + dap_stream_worker_t * stream_worker; struct dap_http_client * conn_http; // HTTP-specific - struct dap_udp_client * conn_udp; // UDP-client - dap_events_socket_t * events_socket; - char * service_key; bool is_live; @@ -93,7 +89,7 @@ typedef struct dap_stream { } dap_stream_t; -#define DAP_STREAM(a) ((dap_stream_t *) (a)->_internal ) +#define DAP_STREAM(a) ((dap_stream_t *) (a)->_inheritor ) int dap_stream_init(bool a_dump_packet_headers); @@ -105,7 +101,7 @@ void dap_stream_add_proc_http(dap_http_t * sh, const char * url); void dap_stream_add_proc_udp(dap_udp_server_t * sh); -dap_stream_t* dap_stream_new_es(dap_events_socket_t * a_es); +dap_stream_t* dap_stream_new_es_client(dap_events_socket_t * a_es); size_t dap_stream_data_proc_read(dap_stream_t * a_stream); size_t dap_stream_data_proc_write(dap_stream_t * a_stream); void dap_stream_delete(dap_stream_t * a_stream); diff --git a/dap-sdk/net/stream/stream/include/dap_stream_ctl.h b/dap-sdk/net/stream/stream/include/dap_stream_ctl.h index 94a5d62ee2dcc1b644db7c8e657c44a46fade8df..56fe6e995554b46dbe186ffb0906712194979452 100644 --- a/dap-sdk/net/stream/stream/include/dap_stream_ctl.h +++ b/dap-sdk/net/stream/stream/include/dap_stream_ctl.h @@ -19,10 +19,12 @@ */ #pragma once -typedef struct dap_http dap_http_t; +#include "dap_enc.h" +typedef struct dap_http dap_http_t; #define KEX_KEY_STR_SIZE 128 + int dap_stream_ctl_init(dap_enc_key_type_t socket_forward_key_type, size_t socket_forward_key_size); void dap_stream_ctl_deinit(); diff --git a/dap-sdk/net/stream/stream/include/dap_stream_pkt.h b/dap-sdk/net/stream/stream/include/dap_stream_pkt.h index ce6fd70636e35133c9f6076896a911fd913e4472..34beb4e381cb71bbda533701ebfa49c2b6deab16 100644 --- a/dap-sdk/net/stream/stream/include/dap_stream_pkt.h +++ b/dap-sdk/net/stream/stream/include/dap_stream_pkt.h @@ -21,10 +21,11 @@ #pragma once #include <stdint.h> #include <stddef.h> - -#define STREAM_PKT_SIZE_MAX 500000 -struct dap_stream; +#include "dap_enc_key.h" +#include "dap_events_socket.h" +#define STREAM_PKT_SIZE_MAX 100000 typedef struct dap_stream dap_stream_t; +typedef struct dap_stream_session dap_stream_session_t; #define STREAM_PKT_TYPE_DATA_PACKET 0x00 #define STREAM_PKT_TYPE_SERVICE_PACKET 0xff //#define STREAM_PKT_TYPE_KEEPALIVE 0x11 @@ -53,9 +54,10 @@ extern const uint8_t c_dap_stream_sig[8]; dap_stream_pkt_t * dap_stream_pkt_detect(void * a_data, size_t data_size); -size_t dap_stream_pkt_read(dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, void * a_buf_out, size_t a_buf_out_size); +size_t dap_stream_pkt_read_unsafe(dap_stream_t * a_stream, dap_stream_pkt_t * a_pkt, void * a_buf_out, size_t a_buf_out_size); -size_t dap_stream_pkt_write(dap_stream_t * a_stream, const void * data, size_t a_data_size); +size_t dap_stream_pkt_write_unsafe(dap_stream_t * a_stream, const void * data, size_t a_data_size); +size_t dap_stream_pkt_write_mt (dap_worker_t * a_w, dap_events_socket_t *a_es, dap_enc_key_t *a_key, const void * data, size_t a_data_size); void dap_stream_send_keepalive( dap_stream_t * a_stream); diff --git a/dap-sdk/net/stream/stream/include/dap_stream_worker.h b/dap-sdk/net/stream/stream/include/dap_stream_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..3058cdf8d68e39e48e88e5cd0f6d72a7de3caf93 --- /dev/null +++ b/dap-sdk/net/stream/stream/include/dap_stream_worker.h @@ -0,0 +1,44 @@ +/* + * 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/>. +*/ +#pragma once +#include "dap_worker.h" +#include "dap_stream_ch.h" + +typedef struct dap_stream_worker { + dap_worker_t * worker; + dap_events_socket_t *queue_ch_io; // IO queue for channels + dap_stream_ch_t * channels; // Client channels assigned on worker. Unsafe list, operate only in worker's context +} dap_stream_worker_t; + +#define DAP_STREAM_WORKER(a) ((dap_stream_worker_t*) (a->_inheritor) ) + +typedef struct dap_stream_worker_msg_io { + dap_stream_ch_t * ch; // Channel that has operations with + uint32_t flags_set; // set flags + uint32_t flags_unset; // unset flags + uint8_t ch_pkt_type; + void * data; + size_t data_size; +} dap_stream_worker_msg_io_t; + +int dap_stream_worker_init(); diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index dd0910e8f6d156746a39d7f02766a4ed672533ac..b7d05539b15f8fd2de45a09918ff039f52b82cfa 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -24,7 +24,7 @@ #include <dap_chain_ledger.h> #include <sys/types.h> #include <dirent.h> - +#include <stdc-predef.h> #include <unistd.h> #include "dap_common.h" @@ -255,9 +255,9 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha // Recognize chains id if ( (l_chain_id_str = dap_config_get_item_str(l_cfg,"chain","id")) != NULL ){ - if ( sscanf(l_chain_id_str,"0x%016llX",& l_chain_id_u ) !=1 ){ - if ( sscanf(l_chain_id_str,"0x%016llx",&l_chain_id_u) !=1 ) { - if ( sscanf(l_chain_id_str,"%llu",&l_chain_id_u ) !=1 ){ + if ( sscanf(l_chain_id_str,"0x%"DAP_UINT64_FORMAT_X,& l_chain_id_u ) !=1 ){ + if ( sscanf(l_chain_id_str,"0x%"DAP_UINT64_FORMAT_x,&l_chain_id_u) !=1 ) { + if ( sscanf(l_chain_id_str,"%"DAP_UINT64_FORMAT_u,&l_chain_id_u ) !=1 ){ log_it (L_ERROR,"Can't recognize '%s' string as chain net id, hex or dec",l_chain_id_str); dap_config_close(l_cfg); return NULL; @@ -269,7 +269,7 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha if (l_chain_id_str ) { - log_it (L_NOTICE, "Chain id 0x%016lX ( \"%s\" )",l_chain_id.uint64 , l_chain_id_str) ; + log_it (L_NOTICE, "Chain id 0x%016"DAP_UINT64_FORMAT_x" ( \"%s\" )",l_chain_id.uint64 , l_chain_id_str) ; }else { log_it (L_ERROR,"Wasn't recognized '%s' string as chain net id, hex or dec",l_chain_id_str); dap_config_close(l_cfg); diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 4d7f76f0aa01c735677f9d345b2e5ccd78bfb01a..cb84cba7ab0887ef6f28847e2e6d44d04e95df0d 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -134,7 +134,7 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path) if ( l_element_size > 0 ){ dap_chain_atom_ptr_t * l_element = DAP_NEW_Z_SIZE (dap_chain_atom_ptr_t, l_element_size ); if ( fread( l_element,1,l_element_size,l_cell->file_storage ) == l_element_size ) { - a_chain->callback_atom_add (a_chain, l_element ); + a_chain->callback_atom_add (a_chain, l_element, l_element_size); } } else { log_it (L_ERROR, "Zero element size, file is corrupted"); @@ -270,13 +270,12 @@ int dap_chain_cell_file_update( dap_chain_cell_t * a_cell) if ( a_cell->file_storage ){ dap_chain_t * l_chain = a_cell->chain; dap_chain_atom_iter_t *l_atom_iter = l_chain->callback_atom_iter_create (l_chain); - dap_chain_atom_ptr_t *l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter); - size_t l_atom_size = l_chain->callback_atom_get_size(l_atom); + size_t l_atom_size = 0; + dap_chain_atom_ptr_t *l_atom = l_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); while ( l_atom && l_atom_size){ if ( dap_chain_cell_file_append (a_cell,l_atom, l_atom_size) <0 ) break; - l_atom = l_chain->callback_atom_iter_get_next( l_atom_iter ); - l_atom_size = l_chain->callback_atom_get_size(l_atom); + l_atom = l_chain->callback_atom_iter_get_next( l_atom_iter, &l_atom_size ); } }else { log_it (L_ERROR,"Can't write cell 0x%016X file \"%s\"",a_cell->id.uint64, a_cell->file_storage_path); diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 0888d5eaa2a8de225cb84c9666365042581c0872..86f4782d85f2e2720f72e56a7c5a305f2c0ee0b5 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -45,15 +45,16 @@ typedef void * dap_chain_atom_ptr_t; typedef struct dap_chain_atom_iter{ dap_chain_t * chain; dap_chain_atom_ptr_t cur; + size_t cur_size; void * cur_item; void * _inheritor; } dap_chain_atom_iter_t; typedef enum dap_chain_atom_verify_res{ - ATOM_ACCEPT, - ATOM_PASS, - ATOM_REJECT, - ATOM_MOVE_TO_THRESHOLD + ATOM_ACCEPT=0, + ATOM_PASS=1, + ATOM_REJECT=2, + ATOM_MOVE_TO_THRESHOLD=3 } dap_chain_atom_verify_res_t; typedef dap_chain_t* (*dap_chain_callback_new_t)(void); @@ -62,22 +63,20 @@ typedef void (*dap_chain_callback_t)(dap_chain_t *); typedef int (*dap_chain_callback_new_cfg_t)(dap_chain_t*, dap_config_t *); typedef void (*dap_chain_callback_ptr_t)(dap_chain_t *, void * ); -typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_t)(dap_chain_t *, dap_chain_atom_ptr_t ); -typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_verify_t)(dap_chain_t *, dap_chain_atom_ptr_t ); -typedef int (*dap_chain_callback_atom_size_t)(dap_chain_t *, dap_chain_atom_ptr_t ,size_t); +typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_t)(dap_chain_t *, dap_chain_atom_ptr_t, size_t ); +typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_verify_t)(dap_chain_t *, dap_chain_atom_ptr_t , size_t); typedef size_t (*dap_chain_callback_atom_get_hdr_size_t)(void); -typedef size_t (*dap_chain_callback_atom_hdr_get_size_t)(dap_chain_atom_ptr_t ); typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_t)(dap_chain_t * ); -typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_from_t)(dap_chain_t * ,dap_chain_atom_ptr_t); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_first_t)(dap_chain_atom_iter_t * ); -typedef dap_chain_datum_t* (*dap_chain_callback_atom_get_datum)(dap_chain_atom_ptr_t ); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t * ,dap_chain_hash_fast_t *); +typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_from_t)(dap_chain_t * ,dap_chain_atom_ptr_t, size_t); +typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_first_t)(dap_chain_atom_iter_t * , size_t*); +typedef dap_chain_datum_t* (*dap_chain_callback_atom_get_datum)(dap_chain_atom_ptr_t, size_t ); +typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t * ,dap_chain_hash_fast_t *,size_t*); typedef dap_chain_datum_tx_t* (*dap_chain_callback_tx_find_by_hash_t)(dap_chain_t * ,dap_chain_hash_fast_t *); -typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t * ); +typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t* ,size_t**); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ); +typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ,size_t*); typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t * ); typedef size_t (*dap_chain_datum_callback_datum_pool_proc_add_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); @@ -126,7 +125,6 @@ typedef struct dap_chain{ dap_chain_datum_callback_datum_pool_proc_add_with_group_t callback_datums_pool_proc_with_group; dap_chain_callback_atom_get_hdr_size_t callback_atom_get_hdr_static_size; // Get atom header's size - dap_chain_callback_atom_hdr_get_size_t callback_atom_get_size; // Get atom's size from header dap_chain_callback_atom_iter_create_t callback_atom_iter_create; dap_chain_callback_atom_iter_create_from_t callback_atom_iter_create_from; diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c index ddd9ad790d4ae25e45da02c3385ab112e9d4dc33..cd4c5958021f28578725720bfb35ff21e2bba44f 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c @@ -141,7 +141,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) a_ch->stream->session->_inheritor : NULL; if ( ! l_srv_session ){ log_it( L_ERROR, "Not defined service session, switching off packet input process"); - dap_stream_ch_set_ready_to_read(a_ch, false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch, false); return; } dap_stream_ch_chain_net_srv_pkt_error_t l_err; @@ -152,14 +152,15 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) // for send test data case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST:{ int l_err_code = 0; - dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_request_t*) l_ch_pkt->data; + dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t*) l_ch_pkt->data; size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); if(l_ch_pkt->hdr.size != l_request_size) { log_it(L_WARNING, "Wrong request size, less or more than required"); break; } - - gettimeofday(&l_request->recv_time2, NULL); + struct timeval l_recvtime2; + gettimeofday(&l_recvtime2, NULL); + memcpy(&l_request->recv_time2,&l_recvtime2,sizeof (l_recvtime2)); //printf("\n%lu.%06lu \n", (unsigned long) l_request->recv_time2.tv_sec, (unsigned long) l_request->recv_time2.tv_usec); dap_chain_hash_fast_t l_data_hash; dap_hash_fast(l_request->data, l_request->data_size, &l_data_hash); @@ -175,12 +176,17 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) randombytes(l_request_out->data, l_request_out->data_size); l_request_out->err_code = l_err_code; dap_hash_fast(l_request_out->data, l_request_out->data_size, &l_request_out->data_hash); - memcpy(l_request_out->ip_send, a_ch->stream->conn->s_ip, sizeof(l_request_out->ip_send)); - gettimeofday(&l_request_out->send_time2, NULL); + strncpy(l_request_out->ip_send,a_ch->stream->esocket->hostaddr , sizeof(l_request_out->ip_send)-1); + + // Thats to prevent unaligned pointer + struct timeval l_tval; + gettimeofday(&l_tval, NULL); + l_request_out->send_time2.tv_sec = l_tval.tv_sec; + l_request_out->send_time2.tv_usec = l_tval.tv_usec; // send response - if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE, l_request_out, l_request_out->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t))) { - dap_stream_ch_set_ready_to_write(a_ch, true); + if(dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE, l_request_out, l_request_out->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t))) { + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } DAP_DELETE(l_request_out); @@ -188,7 +194,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) break; // for receive test data. case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: { - dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_request_t *) l_ch_pkt->data; + dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t *) l_ch_pkt->data; size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); if(l_ch_pkt->hdr.size != l_request_size) { log_it(L_WARNING, "Wrong request size, less or more than required"); @@ -200,7 +206,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if(!dap_hash_fast_compare(&l_data_hash, &(l_request->data_hash))) { l_request->err_code += 4; } - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); } break; @@ -226,13 +232,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND; if ( l_err.code ){ - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv && l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; } - dap_ledger_t * l_ledger = dap_chain_ledger_by_net_name( l_net->pub.name); + dap_ledger_t * l_ledger =l_net->pub.ledger; dap_chain_datum_tx_t * l_tx = NULL; dap_chain_tx_out_cond_t * l_tx_out_cond = NULL; if (l_srv->pricelist ){ // Is present pricelist, not free service @@ -240,7 +246,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if ( !l_ledger ){ // No ledger log_it( L_WARNING, "No Ledger"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; @@ -252,7 +258,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) /// TODO Add tx cond treshold and ability to provide service before the transaction comes from CDB /// l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; @@ -265,7 +271,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) log_it( L_WARNING, "No conditioned output"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; @@ -276,7 +282,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016lX", l_tx_out_cond->subtype.srv_pay.srv_uid ); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; @@ -287,7 +293,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if ( !l_usage ){ // Usage can't add log_it( L_WARNING, "Usage can't add"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_USAGE_CANT_ADD; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,0,NULL,&l_err,sizeof (l_err) ); break; @@ -296,9 +302,11 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_err.usage_id = l_usage->id; // Create one client - l_usage->clients = DAP_NEW_Z( dap_chain_net_srv_client_t); - l_usage->clients->ch = a_ch; - l_usage->clients->ts_created = time(NULL); + l_usage->client = DAP_NEW_Z( dap_chain_net_srv_client_t); + l_usage->client->stream_worker = a_ch->stream_worker; + l_usage->client->ch = a_ch; + l_usage->client->session_id = a_ch->stream->session->id; + l_usage->client->ts_created = time(NULL); l_usage->tx_cond = l_tx; memcpy(&l_usage->tx_cond_hash, &l_request->hdr.tx_cond,sizeof (l_usage->tx_cond_hash)); l_usage->ts_created = time(NULL); @@ -326,18 +334,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_ticker, l_net->pub.name ); dap_chain_net_srv_usage_delete(l_srv_session, l_usage); l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) - l_srv->callback_response_error(l_srv,l_usage->id,l_usage->clients,&l_err,sizeof (l_err) ); + l_srv->callback_response_error(l_srv,l_usage->id,l_usage->client,&l_err,sizeof (l_err) ); break; } } int ret; - if ( (ret= l_srv->callback_requested(l_srv,l_usage->id, l_usage->clients, l_request, l_ch_pkt->hdr.size ) )!= 0 ){ + if ( (ret= l_srv->callback_requested(l_srv,l_usage->id, l_usage->client, l_request, l_ch_pkt->hdr.size ) )!= 0 ){ log_it( L_WARNING, "Request canceled by service callback, return code %d", ret); dap_chain_net_srv_usage_delete(l_srv_session, l_usage); l_err.code = (uint32_t) ret ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error(l_srv,l_usage->id, NULL,&l_err,sizeof (l_err) ); break; @@ -348,12 +356,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_usage->price = l_price; // TODO extend callback to pass ext and ext size from service callbacks l_receipt = dap_chain_net_srv_issue_receipt( l_usage->service, l_usage, l_usage->price,NULL,0 ); - dap_stream_ch_pkt_write( l_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , + dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , l_receipt, l_receipt->size); }else{ l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_srv->callback_response_error) l_srv->callback_response_error( l_srv, l_usage->id, NULL, &l_err, sizeof( l_err ) ); } @@ -368,13 +376,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64; l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64; - if (dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, + if (dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size)) { - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } if ( l_usage->service->callback_receipt_first_success ) - l_usage->service->callback_receipt_first_success ( l_usage->service, l_usage->id, l_usage->clients, NULL, 0 ); + l_usage->service->callback_receipt_first_success ( l_usage->service, l_usage->id, l_usage->client, NULL, 0 ); DAP_DELETE(l_success); } @@ -402,9 +410,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if(l_srv && l_srv->callback_client_sign_request) { // Sign receipt l_srv->callback_client_sign_request(l_srv, 0, NULL, &l_receipt_new, l_receipt_size); - if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE, + if(dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE, l_receipt_new, l_receipt_new->size)) { - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } } DAP_DELETE(l_receipt_new); @@ -436,9 +444,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if ( !l_is_found || ! l_usage ){ log_it(L_WARNING, "Can't find receipt in usages thats equal to response receipt"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_usage && l_usage->service && l_usage->service->callback_response_error) - l_usage->service->callback_response_error(l_usage->service,l_usage->id, l_usage->clients,&l_err,sizeof (l_err) ); + l_usage->service->callback_response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err) ); break; } l_err.usage_id = l_usage->id; @@ -448,9 +456,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if (! l_usage->tx_cond ){ log_it(L_WARNING, "No tx out in usage"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_usage->service->callback_response_error) - l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->clients, + l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->client, &l_err, sizeof (l_err) ); break; } @@ -460,18 +468,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if ( ! l_tx_out_cond ){ // No conditioned output l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_usage->service->callback_response_error) - l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->clients,&l_err,sizeof (l_err) ); + l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->client,&l_err,sizeof (l_err) ); break; } // get a second signature - from the client (first sign in server, second sign in client) dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( l_receipt, l_receipt_size, 1); if ( ! l_receipt_sign ){ l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_usage->service->callback_response_error) - l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->clients, + l_usage->service->callback_response_error( l_usage->service, l_usage->id, l_usage->client, &l_err, sizeof (l_err) ); break; } @@ -483,9 +491,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if( memcmp ( l_pkey_hash.raw, l_tx_out_cond->subtype.srv_pay.pkey_hash.raw , sizeof(l_pkey_hash) ) != 0 ){ l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_WRONG_PKEY_HASH ; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); if (l_usage->service->callback_response_error) - l_usage->service->callback_response_error(l_usage->service,l_usage->id, l_usage->clients,&l_err,sizeof (l_err) ); + l_usage->service->callback_response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err) ); break; } @@ -548,12 +556,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) memcpy(l_success->custom_data, l_tx_in_hash, sizeof(dap_chain_hash_fast_t)); DAP_DELETE(l_tx_in_hash); } - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS , + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS , l_success, l_success_size); DAP_DELETE(l_success); if ( l_is_first_sign && l_usage->service->callback_receipt_first_success){ - if( l_usage->service->callback_receipt_first_success(l_usage->service,l_usage->id, l_usage->clients, + if( l_usage->service->callback_receipt_first_success(l_usage->service,l_usage->id, l_usage->client, l_receipt, l_receipt_size ) !=0 ){ log_it(L_NOTICE, "No success by service callback, inactivating service usage"); l_usage->is_active = false; @@ -561,11 +569,11 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) // issue receipt next l_usage->receipt_next = dap_chain_net_srv_issue_receipt( l_usage->service, l_usage, l_usage->price ,NULL,0); l_usage->receipt_next_size = l_usage->receipt_next->size; - dap_stream_ch_pkt_write( l_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , + dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , l_usage->receipt_next, l_usage->receipt_next->size); }else if ( l_usage->service->callback_receipt_next_success){ - if (l_usage->service->callback_receipt_next_success(l_usage->service,l_usage->id, l_usage->clients, + if (l_usage->service->callback_receipt_next_success(l_usage->service,l_usage->id, l_usage->client, l_receipt, l_receipt_size ) != 0 ){ log_it(L_NOTICE, "No success by service callback, inactivating service usage"); l_usage->is_active = false; @@ -585,10 +593,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get(l_success->hdr.srv_uid); if ( l_srv && l_srv->callback_client_success){ // Create client for client) - dap_chain_net_srv_client_t *l_clients = DAP_NEW_Z( dap_chain_net_srv_client_t); - l_clients->ch = a_ch; - l_clients->ts_created = time(NULL); - l_srv->callback_client_success(l_srv, l_success->hdr.usage_id, l_clients, l_success, l_success_size ); + dap_chain_net_srv_client_t *l_client = DAP_NEW_Z( dap_chain_net_srv_client_t); + l_client->ch = a_ch; + l_client->stream_worker = a_ch->stream_worker; + l_client->ts_created = time(NULL); + l_client->session_id = a_ch->stream->session->id; + l_srv->callback_client_success(l_srv, l_success->hdr.usage_id, l_client, l_success, l_success_size ); //l_success->hdr.net_id, l_success->hdr.srv_uid, l_success->hdr.usage_id } } break; @@ -601,25 +611,25 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) dap_stream_ch_chain_net_srv_pkt_data_t * l_pkt =(dap_stream_ch_chain_net_srv_pkt_data_t *) l_ch_pkt->data; size_t l_pkt_size = l_ch_pkt->hdr.size - sizeof (dap_stream_ch_chain_net_srv_pkt_data_t); dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get( l_pkt->hdr.srv_uid); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find( l_srv_session, l_pkt->hdr.usage_id ); + dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe( l_srv_session, l_pkt->hdr.usage_id ); // If service not found if ( l_srv == NULL){ l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND ; l_err.srv_uid = l_pkt->hdr.srv_uid; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); break; } // Check if callback is not present if ( l_srv->callback_stream_ch_read == NULL ){ l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_CH_NOT_FOUND ; l_err.srv_uid = l_pkt->hdr.srv_uid; - dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); break; } // Call callback if present - l_srv->callback_stream_ch_read( l_srv,l_usage->id, l_usage->clients, l_pkt->data, l_pkt_size ); + l_srv->callback_stream_ch_read( l_srv,l_usage->id, l_usage->client, l_pkt->data, l_pkt_size ); } break; @@ -650,7 +660,7 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch , void* a_arg) { (void) a_arg; - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); // Callback should note that after write action it should restore write flag if it has more data to send on next iteration dap_chain_net_srv_call_write_all( a_ch); } diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h index f6b83f171919a1d99abfff45a5cfa156cb3a5380..ced85e9ac1bb8bba8a12a71edd3208982f33d8f0 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h @@ -44,4 +44,4 @@ typedef struct dap_stream_ch_chain_net_srv { void dap_stream_ch_chain_net_srv_set_srv_uid(dap_stream_ch_t* a_ch, dap_chain_net_srv_uid_t a_srv_uid); uint8_t dap_stream_ch_chain_net_srv_get_id(); - +int dap_stream_ch_chain_net_srv_init(void); diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv_pkt.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv_pkt.c index 1ec2de169a8d7df4db04f2d42d706c8f97debce7..a6f028efe7734c86f29fc4b16783f71c50c1e32a 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv_pkt.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv_pkt.c @@ -50,7 +50,7 @@ size_t dap_stream_ch_chain_net_srv_pkt_data_write(dap_stream_ch_t *a_ch, l_pkt_data->hdr.srv_uid = a_srv_uid; l_pkt_data->hdr.usage_id = a_usage_id; memcpy( l_pkt_data->data, a_data, a_data_size); - size_t l_ret = dap_stream_ch_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA , l_pkt_data, l_pkt_data_size); + size_t l_ret = dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA , l_pkt_data, l_pkt_data_size); DAP_DELETE(l_pkt_data); return l_ret; } diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index 74dcd903c674c4f4e93b15f8ca5c9da53562adbc..3bc1d829ddea5eb4a4a7e0883de688ec00334cc3 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -186,7 +186,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) dap_chain_net_session_data_t *l_session_data = session_data_find(a_ch->stream->session->id); if (l_session_data == NULL) { log_it(L_ERROR, "Can't find chain net session for stream session %d", a_ch->stream->session->id); - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); } if(l_ch_chain_net) { @@ -210,7 +210,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) if (l_error) { dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str, strlen(l_err_str) + 1); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } //size_t l_ch_chain_net_pkt_data_size = (size_t) l_ch_pkt->hdr.size - sizeof (l_ch_chain_net_pkt->hdr); if (!l_error && l_ch_chain_net_pkt) { @@ -219,7 +219,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_DBG: { dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PING, l_ch_chain_net_pkt->hdr.net_id, NULL, 0); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } break; // received ping request - > send pong request @@ -227,13 +227,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PING"); dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG, l_ch_chain_net_pkt->hdr.net_id,NULL, 0); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } break; // receive pong request -> send nothing case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG: { //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PONG"); - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); } break; case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR: { @@ -246,7 +246,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_WARNING,"Wrong data secion size %u",l_ch_chain_net_pkt_data_size, sizeof (dap_chain_node_addr_t)); } - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); }break; case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_LEASE: { log_it(L_INFO, "Get CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_LEASE"); @@ -258,7 +258,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) char l_err_str[]="ERROR_NET_INVALID_ID"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str,sizeof (l_err_str)); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); log_it(L_ERROR, "Invalid net id in packet"); } else { if (dap_db_set_cur_node_addr_exp( l_addr->uint64, l_net->pub.name )) @@ -271,7 +271,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_WARNING,"Wrong data secion size %u",l_ch_chain_net_pkt_data_size, sizeof (dap_chain_node_addr_t)); } - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); }break; // get current node address case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST: { @@ -283,7 +283,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) // send cur node addr dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR, l_ch_chain_net_pkt->hdr.net_id, &l_addr, l_send_data_len); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } break; case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_LEASE_REQUEST: { log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST"); @@ -293,12 +293,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) char l_err_str[]="ERROR_NET_INVALID_ID"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_net->pub.id, l_err_str,sizeof (l_err_str)); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } else { dap_chain_node_addr_t *l_addr_new = dap_chain_node_gen_addr(l_net, &l_net->pub.cell_id ); dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_LEASE , l_ch_chain_net_pkt->hdr.net_id, l_addr_new, sizeof (*l_addr_new)); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); memcpy( &l_session_data->addr_remote,l_addr_new,sizeof (*l_addr_new) ); DAP_DELETE(l_addr_new); } @@ -323,5 +323,5 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) */ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) { - dap_stream_ch_set_ready_to_write(a_ch, false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); } diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c b/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c index d5626fc7e9f219c3d1a67881569dbb2dc72d8e52..717fc1d7153b20ccf04bec758baea230d5c78fa3 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c @@ -41,7 +41,7 @@ size_t dap_stream_ch_chain_net_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type,d l_net_pkt->hdr.version = 1; l_net_pkt->hdr.net_id.uint64 = a_net_id.uint64; memcpy( l_net_pkt->data, a_data, a_data_size); - size_t l_ret = dap_stream_ch_pkt_write(a_ch, a_type , l_net_pkt, l_net_pkt_size); + size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type , l_net_pkt, l_net_pkt_size); DAP_DELETE(l_net_pkt); return l_ret; } diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 140bf61c3c3c2d6ec73f4998d7eccefa2fedbc6a..607a183509803aa709b230b7353c527da02fae72 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -46,6 +46,10 @@ #include "dap_hash.h" #include "utlist.h" +#include "dap_worker.h" +#include "dap_events.h" +#include "dap_proc_thread.h" + #include "dap_chain.h" #include "dap_chain_datum.h" #include "dap_chain_cs.h" @@ -55,6 +59,7 @@ #include "dap_chain_global_db_remote.h" #include "dap_stream.h" +#include "dap_stream_worker.h" #include "dap_stream_ch_pkt.h" #include "dap_stream_ch.h" #include "dap_stream_ch_proc.h" @@ -118,6 +123,258 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg) pthread_mutex_destroy(&DAP_STREAM_CH_CHAIN(a_ch)->mutex); } + +bool s_sync_chains_callback(dap_proc_thread_t *a_thread, void *a_arg) +{ + UNUSED(a_thread); + dap_stream_ch_t *l_ch = (dap_stream_ch_t *)a_arg; + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + + dap_chain_t * l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); + + dap_chain_atom_ptr_t * l_lasts = NULL; + size_t *l_lasts_sizes = NULL; + size_t l_lasts_count = 0; + dap_chain_atom_iter_t* l_iter = l_chain->callback_atom_iter_create(l_chain); + l_ch_chain->request_atom_iter = l_iter; + l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_count, &l_lasts_sizes); + log_it(L_INFO, "Found %d last atoms for synchronization", l_lasts_count); + if (l_lasts && l_lasts_sizes) { + for(long int i = 0; i < l_lasts_count; i++) { + dap_chain_atom_item_t * l_item = NULL; + dap_chain_hash_fast_t l_atom_hash; + dap_hash_fast(l_lasts[i], l_lasts_sizes[i], &l_atom_hash); + pthread_mutex_lock(&l_ch_chain->mutex); + HASH_FIND(hh, l_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), + l_item); + if(l_item == NULL) { // Not found, add new lasts + l_item = DAP_NEW_Z(dap_chain_atom_item_t); + l_item->atom = l_lasts[i]; + l_item->atom_size = l_lasts_sizes[i]; + memcpy(&l_item->atom_hash, &l_atom_hash, sizeof(l_atom_hash)); + HASH_ADD(hh, l_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash), + l_item); + } + pthread_mutex_unlock(&l_ch_chain->mutex); + } + // first packet + l_ch_chain->state = CHAIN_STATE_SYNC_CHAINS; + dap_chain_node_addr_t l_node_addr = { 0 }; + dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); + l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); + } + else { + // last packet + dap_stream_ch_chain_sync_request_t l_request; + memset(&l_request,0,sizeof (l_request)); + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); + l_ch_chain->state = CHAIN_STATE_IDLE; + } + DAP_DELETE(l_lasts); + DAP_DELETE(l_iter); + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); + dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); + return true; +} + +bool s_sync_gdb_callback(dap_proc_thread_t *a_thread, void *a_arg) +{ + UNUSED(a_thread); + dap_stream_ch_t *l_ch = (dap_stream_ch_t *)a_arg; + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + + // Get log diff + l_ch_chain->request_last_ts = dap_db_log_get_last_id(); + //log_it(L_DEBUG, "Requested transactions %llu:%llu", l_request->id_start, (uint64_t ) l_ch_chain->request_last_ts); + uint64_t l_start_item = l_ch_chain->request.id_start; + // If the current global_db has been truncated, but the remote node has not known this + if(l_ch_chain->request.id_start > l_ch_chain->request_last_ts) { + l_start_item = 0; + } + dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); + dap_list_t *l_add_groups = dap_chain_net_get_add_gdb_group(l_net, l_ch_chain->request.node_addr); + dap_db_log_list_t *l_db_log = dap_db_log_list_start(l_start_item + 1, l_add_groups); + dap_chain_node_addr_t l_node_addr = { 0 }; + l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); + if(l_db_log) { + //log_it(L_DEBUG, "Start getting items %u:%u", l_request->id_start + 1,l_db_log->items_number);//dap_list_length(l_list)); + // Add it to outgoing list + l_ch_chain->request_global_db_trs = l_db_log; + l_ch_chain->db_iter = NULL; + l_ch_chain->state = CHAIN_STATE_SYNC_GLOBAL_DB; + } else { + dap_stream_ch_chain_sync_request_t l_request = {}; + //log_it(L_DEBUG, "No items to sync from %u", l_request->id_start + 1); + l_request.node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; + l_request.id_start = dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); + l_ch_chain->state = CHAIN_STATE_IDLE; + if(l_ch_chain->callback_notify_packet_out) + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + NULL, 0, l_ch_chain->callback_notify_arg); + } + //log_it(L_INFO, "Prepared %u items for sync", l_db_log->items_number - l_request->id_start); + // go to send data from list [in s_stream_ch_packet_out()] + // no data to send -> send one empty message DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB_SYNCED + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); + dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); + return true; +} + +bool s_chain_pkt_callback(dap_proc_thread_t *a_thread, void *a_arg) +{ + UNUSED(a_thread); + dap_stream_ch_t *l_ch = (dap_stream_ch_t *)a_arg; + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_t * l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); + if (!l_chain) { + log_it(L_WARNING, "No chain found for DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN"); + return true; + } + + dap_chain_hash_fast_t l_atom_hash = {}; + dap_chain_atom_ptr_t l_atom_copy = l_ch_chain->pkt_data; + uint64_t l_atom_copy_size = l_ch_chain->pkt_data_size; + l_ch_chain->pkt_data = NULL; + l_ch_chain->pkt_data_size = 0; + if( l_atom_copy && l_atom_copy_size){ + dap_hash_fast(l_atom_copy, l_atom_copy_size, &l_atom_hash); + dap_chain_atom_iter_t *l_atom_iter = l_chain->callback_atom_iter_create(l_chain); + size_t l_atom_size =0; + if ( l_chain->callback_atom_find_by_hash(l_atom_iter, &l_atom_hash, &l_atom_size) == NULL ) { + dap_chain_atom_verify_res_t l_atom_add_res = l_chain->callback_atom_add(l_chain, l_atom_copy, l_atom_copy_size); + if(l_atom_add_res == ATOM_ACCEPT && dap_chain_has_file_store(l_chain)) { + // append to file + dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(l_chain, l_ch_chain->request_cell_id); + // add one atom only + int l_res = dap_chain_cell_file_append(l_cell, l_atom_copy, l_atom_copy_size); + // rewrite all file + //l_res = dap_chain_cell_file_update(l_cell); + if(!l_cell || l_res < 0) { + log_it(L_ERROR, "Can't save event 0x%x to the file '%s'", l_atom_hash, + l_cell ? l_cell->file_storage_path : "[null]"); + } + // delete cell and close file + dap_chain_cell_delete(l_cell); + } + if(l_atom_add_res == ATOM_PASS) + DAP_DELETE(l_atom_copy); + } else { + DAP_DELETE(l_atom_copy); + } + l_chain->callback_atom_iter_delete(l_atom_iter); + }else + log_it(L_WARNING, "In proc thread got stream ch packet with pkt_size: %zd and pkt_data: %p", l_atom_copy_size, l_atom_copy); + dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); + return true; +} + +bool s_gdb_pkt_callback(dap_proc_thread_t *a_thread, void *a_arg) +{ + UNUSED(a_thread); + dap_stream_ch_t *l_ch = (dap_stream_ch_t *)a_arg; + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_t * l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); + + size_t l_data_obj_count = 0; + // deserialize data & Parse data from dap_db_log_pack() + dap_store_obj_t *l_store_obj = dap_db_log_unpack(l_ch_chain->pkt_data,l_ch_chain->pkt_data_size, &l_data_obj_count); + //log_it(L_INFO, "In: l_data_obj_count = %d", l_data_obj_count ); + + for(size_t i = 0; i < l_data_obj_count; i++) { + // timestamp for exist obj + time_t l_timestamp_cur = 0; + // obj to add + dap_store_obj_t* l_obj = l_store_obj + i; + // read item from base; + size_t l_count_read = 0; + dap_store_obj_t *l_read_obj = dap_chain_global_db_driver_read(l_obj->group, + l_obj->key, &l_count_read); + // get timestamp for the exist entry + if(l_read_obj) + l_timestamp_cur = l_read_obj->timestamp; + // get timestamp for the deleted entry + else + { + l_timestamp_cur = global_db_gr_del_get_timestamp(l_obj->group, l_obj->key); + } + + //check whether to apply the received data into the database + bool l_apply = true; + if(l_obj->timestamp < l_timestamp_cur) + l_apply = false; + else if(l_obj->type == 'd') { + // already deleted + if(!l_read_obj) + l_apply = false; + } + else if(l_obj->type == 'a') { + bool l_is_the_same_present = false; + if(l_read_obj && + l_read_obj->value_len == l_obj->value_len && + !memcmp(l_read_obj->value, l_obj->value, l_obj->value_len)) + l_is_the_same_present = true; + // this data already present in global_db and not obsolete (out of date) + if(l_read_obj && (l_is_the_same_present || l_read_obj->timestamp >= l_store_obj->timestamp)) + l_apply = false; + } + if(l_read_obj) + dap_store_obj_free(l_read_obj, l_count_read); + + if(!l_apply) { + // If request was from defined node_addr we update its state + if(l_ch_chain->request.node_addr.uint64) { + dap_db_log_set_last_id_remote(l_ch_chain->request.node_addr.uint64, l_obj->id); + } + continue; + } + + char l_ts_str[50]; + dap_time_to_str_rfc822(l_ts_str, sizeof(l_ts_str), l_store_obj[i].timestamp); + /*log_it(L_DEBUG, "Unpacked log history: type='%c' (0x%02hhX) group=\"%s\" key=\"%s\"" + " timestamp=\"%s\" value_len=%u ", + (char ) l_store_obj[i].type, l_store_obj[i].type, l_store_obj[i].group, + l_store_obj[i].key, l_ts_str, l_store_obj[i].value_len);*/ + // apply received transaction + dap_chain_t *l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); + if(l_chain) { + if(l_chain->callback_datums_pool_proc_with_group){ + void * restrict l_store_obj_value = l_store_obj->value; + l_chain->callback_datums_pool_proc_with_group(l_chain, + (dap_chain_datum_t** restrict) l_store_obj_value, 1, + l_store_obj[i].group); + } + } + // save data to global_db + if(!dap_chain_global_db_obj_save(l_obj, 1)) { + dap_stream_ch_chain_pkt_write_error(l_ch, l_ch_chain->request_net_id, + l_ch_chain->request_chain_id, l_ch_chain->request_cell_id, + "ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED"); + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); + } else { + // If request was from defined node_addr we update its state + if(l_ch_chain->request.node_addr.uint64) { + dap_db_log_set_last_id_remote(l_ch_chain->request.node_addr.uint64, l_obj->id); + } + //log_it(L_DEBUG, "Added new GLOBAL_DB history pack"); + } + } + if(l_store_obj) + dap_store_obj_free(l_store_obj, l_data_obj_count); + dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); + return true; +} + /** * @brief s_stream_ch_packet_in * @param a_ch @@ -125,145 +382,75 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg) */ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) { - //static char *s_net_name = NULL; dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); - if(l_ch_chain) { - dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; - dap_stream_ch_chain_pkt_t * l_chain_pkt = (dap_stream_ch_chain_pkt_t *) l_ch_pkt->data; - uint8_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_chain_pkt->hdr.net_id); - bool l_error = false; - char l_err_str[64]; - if (l_acl_idx == (uint8_t)-1) { - log_it(L_ERROR, "Invalid net id in packet"); - strcpy(l_err_str, "ERROR_NET_INVALID_ID"); - l_error = true; - } - if (!l_error && a_ch->stream->session->acl && !a_ch->stream->session->acl[l_acl_idx]) { - log_it(L_WARNING, "Unauthorized request attempt to network %s", - dap_chain_net_by_id(l_chain_pkt->hdr.net_id)->pub.name); - strcpy(l_err_str, "ERROR_NET_NOT_AUTHORIZED"); - l_error = true; - } - if (l_error) { + if (!l_ch_chain) { + return; + } + dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; + dap_stream_ch_chain_pkt_t * l_chain_pkt = (dap_stream_ch_chain_pkt_t *) l_ch_pkt->data; + if (!l_chain_pkt) { + return; + } + size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size - sizeof(l_chain_pkt->hdr); + uint8_t l_acl_idx = dap_chain_net_acl_idx_by_id(l_chain_pkt->hdr.net_id); + if (l_acl_idx == (uint8_t)-1) { + log_it(L_ERROR, "Invalid net id in packet"); + if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR) { + if(l_ch_chain->callback_notify_packet_in) { + l_ch_chain->callback_notify_packet_in(l_ch_chain, l_ch_pkt->hdr.type, l_chain_pkt, + l_chain_pkt_data_size, l_ch_chain->callback_notify_arg); + } + } else { dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, l_err_str); - dap_stream_ch_set_ready_to_write(a_ch, true); + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_NET_INVALID_ID"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } - size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size - sizeof(l_chain_pkt->hdr); - if (!l_error && l_chain_pkt) { - switch (l_ch_pkt->hdr.type) { - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL: { - log_it(L_INFO, "In: SYNCED_ALL pkt"); - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB: { - log_it(L_INFO, "In: SYNCED_GLOBAL_DB pkt"); - /*if(s_net_name) { - DAP_DELETE(s_net_name); - s_net_name = NULL; //"kelvin-testnet" - }*/ - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB_GROUP: { - log_it(L_INFO, "In: SYNCED_GLOBAL_DB_GROUP pkt"); - /*if(s_net_name) { - DAP_DELETE(s_net_name); - s_net_name = NULL; //"kelvin-testnet" - }*/ - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB_GROUP: { - log_it(L_INFO, "In: SYNCED_GLOBAL_DB_GROUP pkt"); - } - break; - - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS: { - log_it(L_INFO, "In: SYNCED_CHAINS pkt"); - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS: { - //log_it(L_INFO, "In: SYNC_CHAINS pkt"); - dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); - if(l_chain) { - if(l_ch_chain->state != CHAIN_STATE_IDLE) { - log_it(L_INFO, "Can't process SYNC_CHAINS request because not in idle state"); - dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_STATE_NOT_IN_IDLE"); - } else { - // fill ids - if(l_chain_pkt_data_size == sizeof(dap_stream_ch_chain_sync_request_t)) { - dap_stream_ch_chain_sync_request_t * l_request = - (dap_stream_ch_chain_sync_request_t *) l_chain_pkt->data; - memcpy(&l_ch_chain->request, l_request, l_chain_pkt_data_size); - memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, - sizeof(dap_chain_cell_id_t)); - memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); - memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); - } - - dap_chain_atom_ptr_t * l_lasts = NULL; - size_t l_lasts_size = 0; - dap_chain_atom_iter_t* l_iter = l_chain->callback_atom_iter_create(l_chain); - l_ch_chain->request_atom_iter = l_iter; - l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_size); - if(l_lasts) { - for(size_t i = 0; i < l_lasts_size; i++) { - dap_chain_atom_item_t * l_item = NULL; - dap_chain_hash_fast_t l_atom_hash; - dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]), - &l_atom_hash); - pthread_mutex_lock(&l_ch_chain->mutex); - HASH_FIND(hh, l_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), - l_item); - if(l_item == NULL) { // Not found, add new lasts - l_item = DAP_NEW_Z(dap_chain_atom_item_t); - l_item->atom = l_lasts[i]; - memcpy(&l_item->atom_hash, &l_atom_hash, sizeof(l_atom_hash)); - HASH_ADD(hh, l_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash), - l_item); - } - pthread_mutex_unlock(&l_ch_chain->mutex); - //else - // DAP_DELETE(l_lasts[i]); - } - // first packet - l_ch_chain->state = CHAIN_STATE_SYNC_CHAINS; - dap_chain_node_addr_t l_node_addr = { 0 }; - dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); - l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); - } - else { - // last packet - dap_stream_ch_chain_sync_request_t l_request = { { 0 } }; - l_request.id_start = 0;//dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); - l_ch_chain->state = CHAIN_STATE_IDLE; - } + return; + } + if (a_ch->stream->session->acl && !a_ch->stream->session->acl[l_acl_idx]) { + log_it(L_WARNING, "Unauthorized request attempt to network %s", + dap_chain_net_by_id(l_chain_pkt->hdr.net_id)->pub.name); + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_NET_NOT_AUTHORIZED"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); + return; + } + switch (l_ch_pkt->hdr.type) { + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL: { + log_it(L_INFO, "In: SYNCED_ALL pkt"); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB: { + log_it(L_INFO, "In: SYNCED_GLOBAL_DB pkt"); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB_GROUP: { + log_it(L_INFO, "In: SYNCED_GLOBAL_DB_GROUP pkt"); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB_GROUP: { + log_it(L_INFO, "In: SYNCED_GLOBAL_DB_GROUP pkt"); + } + break; - DAP_DELETE(l_lasts); - DAP_DELETE(l_iter); - } - dap_stream_ch_set_ready_to_write(a_ch, true); - } - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB: { - log_it(L_INFO, "In: SYNC_GLOBAL_DB pkt"); - if(l_ch_chain->state != CHAIN_STATE_IDLE) { - log_it(L_INFO, "Can't process SYNC_GLOBAL_DB request because not in idle state"); - dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_STATE_NOT_IN_IDLE"); - dap_stream_ch_set_ready_to_write(a_ch, true); - break; - } - // receive the latest global_db revision of the remote node -> go to send mode + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS: { + log_it(L_INFO, "In: SYNCED_CHAINS pkt"); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS: { + log_it(L_INFO, "In: SYNC_CHAINS pkt"); + dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); + if(l_chain) { + if(l_ch_chain->state != CHAIN_STATE_IDLE) { + log_it(L_INFO, "Can't process SYNC_CHAINS request because not in idle state"); + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_STATE_NOT_IN_IDLE"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); + } else { + // fill ids if(l_chain_pkt_data_size == sizeof(dap_stream_ch_chain_sync_request_t)) { dap_stream_ch_chain_sync_request_t * l_request = (dap_stream_ch_chain_sync_request_t *) l_chain_pkt->data; @@ -271,264 +458,138 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, sizeof(dap_chain_cell_id_t)); memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); - - // Get log diff - l_ch_chain->request_last_ts = dap_db_log_get_last_id(); - //log_it(L_DEBUG, "Requested transactions %llu:%llu", l_request->id_start, - // (uint64_t ) l_ch_chain->request_last_ts); - //dap_list_t *l_list = dap_db_log_get_list(l_request->id_start + 1); - uint64_t l_start_item = l_request->id_start; - // If the current global_db has been truncated, but the remote node has not known this - if(l_request->id_start > l_ch_chain->request_last_ts) { - l_start_item = 0; - } - dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); - dap_list_t *l_add_groups = dap_chain_net_get_add_gdb_group(l_net, l_request->node_addr); - dap_db_log_list_t *l_db_log = dap_db_log_list_start(l_start_item + 1, l_add_groups); - if(l_db_log) { - //log_it(L_DEBUG, "Start getting items %u:%u", l_request->id_start + 1,l_db_log->items_number);//dap_list_length(l_list)); - // Add it to outgoing list - l_ch_chain->request_global_db_trs = l_db_log;//l_list; - //dap_list_t *l_last = dap_list_last(l_list); - //if(l_last) - // l_last->next = l_ch_chain->request_global_db_trs; - //l_ch_chain->request_global_db_trs = l_list; - l_ch_chain->state = CHAIN_STATE_SYNC_GLOBAL_DB; - - dap_chain_node_addr_t l_node_addr = { 0 }; - dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); - l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); - - } else { - dap_chain_node_addr_t l_node_addr = { 0 }; - dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); - l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); - - dap_stream_ch_chain_sync_request_t l_request = {}; - //log_it(L_DEBUG, "No items to sync from %u", l_request->id_start + 1); - l_request.node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - l_request.id_start = dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); -// dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB ,&l_request, -// sizeof (l_request)); - l_ch_chain->state = CHAIN_STATE_IDLE; - if(l_ch_chain->callback_notify_packet_out) - l_ch_chain->callback_notify_packet_out(l_ch_chain, - DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - NULL, 0, l_ch_chain->callback_notify_arg); - } - //log_it(L_INFO, "Prepared %u items for sync", l_db_log->items_number - l_request->id_start);//dap_list_length(l_ch_chain->request_global_db_trs)); - // go to send data from list [in s_stream_ch_packet_out()] - // no data to send -> send one empty message DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB_SYNCED - dap_stream_ch_set_ready_to_write(a_ch, true); - } - else { - log_it(L_ERROR, "Get DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB session_id=%u bad request", - a_ch->stream->session->id); - dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_SYNC_GLOBAL_DB_REQUEST_BAD"); - dap_stream_ch_set_ready_to_write(a_ch, true); - } - } - break; - // first packet of data with source node address - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN: { - log_it(L_INFO, "In: FIRST_CHAIN data_size=%d", l_chain_pkt_data_size); - if(l_chain_pkt_data_size == sizeof(dap_chain_node_addr_t)) - memcpy(&l_ch_chain->request.node_addr, l_chain_pkt->data, l_chain_pkt_data_size); - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN: { - //log_it(L_INFO, "In: CHAIN pkt"); - dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); - if(l_chain) { - // Expect atom element in - if(l_chain_pkt_data_size > 0) { - dap_chain_hash_fast_t l_atom_hash = {}; - dap_hash_fast(l_chain_pkt->data, l_chain_pkt_data_size, &l_atom_hash); - dap_chain_atom_iter_t *l_atom_iter = l_chain->callback_atom_iter_create(l_chain); - if (!l_chain->callback_atom_find_by_hash(l_atom_iter, &l_atom_hash)) { - dap_chain_atom_ptr_t l_atom_copy = DAP_CALLOC(1, l_chain_pkt_data_size); - memcpy(l_atom_copy, l_chain_pkt->data, l_chain_pkt_data_size); - dap_chain_atom_verify_res_t l_atom_add_res = l_chain->callback_atom_add(l_chain, l_atom_copy); - if(l_atom_add_res == ATOM_ACCEPT && dap_chain_has_file_store(l_chain)) { - // append to file - dap_chain_cell_id_t l_cell_id; - l_cell_id.uint64 = l_chain_pkt->hdr.cell_id.uint64; - dap_chain_cell_t *l_cell = dap_chain_cell_create_fill(l_chain, l_cell_id); - // add one atom only - int l_res = dap_chain_cell_file_append(l_cell, l_chain_pkt->data, l_chain_pkt_data_size); - // rewrite all file - //l_res = dap_chain_cell_file_update(l_cell); - if(!l_cell || l_res < 0) { - log_it(L_ERROR, "Can't save event 0x%x to the file '%s'", l_chain_pkt->data, - l_cell ? l_cell->file_storage_path : "[null]"); - } - // delete cell and close file - dap_chain_cell_delete(l_cell); - } - if(l_atom_add_res == ATOM_PASS) - DAP_DELETE(l_atom_copy); - } - l_chain->callback_atom_iter_delete(l_atom_iter); - } else { - log_it(L_WARNING, "Empty chain packet"); - dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_CHAIN_PACKET_EMPTY"); - dap_stream_ch_set_ready_to_write(a_ch, true); - } - } } - break; - // first packet of data with source node address - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB: { - log_it(L_INFO, "In: FIRST_GLOBAL_DB data_size=%d", l_chain_pkt_data_size); - if(l_chain_pkt_data_size == sizeof(dap_chain_node_addr_t)) - memcpy(&l_ch_chain->request.node_addr, l_chain_pkt->data, l_chain_pkt_data_size); - //memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, sizeof(dap_chain_cell_id_t)); - //memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); - //memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); + dap_events_socket_remove_from_worker_unsafe(a_ch->stream->esocket, a_ch->stream_worker->worker); + dap_proc_queue_add_callback(a_ch->stream_worker->worker->proc_queue, s_sync_chains_callback, a_ch); } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB: { - //log_it(L_INFO, "In: GLOBAL_DB data_size=%d", l_chain_pkt_data_size); - // get transaction and save it to global_db - if(l_chain_pkt_data_size > 0) { - //session_data_t *l_data = session_data_find(a_ch->stream->session->id); - size_t l_data_obj_count = 0; - // deserialize data - dap_store_obj_t *l_store_obj = dap_db_log_unpack((uint8_t*) l_chain_pkt->data, - l_chain_pkt_data_size, &l_data_obj_count); // Parse data from dap_db_log_pack() -// log_it(L_INFO, "In: l_data_obj_count = %d", l_data_obj_count ); - - for(size_t i = 0; i < l_data_obj_count; i++) { - // timestamp for exist obj - time_t l_timestamp_cur = 0; - // obj to add - dap_store_obj_t* l_obj = l_store_obj + i; - // read item from base; - size_t l_count_read = 0; - dap_store_obj_t *l_read_obj = dap_chain_global_db_driver_read(l_obj->group, - l_obj->key, &l_count_read); - // get timestamp for the exist entry - if(l_read_obj) - l_timestamp_cur = l_read_obj->timestamp; - // get timestamp for the deleted entry - else - { - l_timestamp_cur = global_db_gr_del_get_timestamp(l_obj->group, l_obj->key); - } - - //check whether to apply the received data into the database - bool l_apply = true; - if(l_obj->timestamp < l_timestamp_cur) - l_apply = false; - else if(l_obj->type == 'd') { - // already deleted - if(!l_read_obj) - l_apply = false; - } - else if(l_obj->type == 'a') { - bool l_is_the_same_present = false; - if(l_read_obj && - l_read_obj->value_len == l_obj->value_len && - !memcmp(l_read_obj->value, l_obj->value, l_obj->value_len)) - l_is_the_same_present = true; - // this data already present in global_db and not obsolete (out of date) - if(l_read_obj && (l_is_the_same_present || l_read_obj->timestamp >= l_store_obj->timestamp)) - l_apply = false; - } - if(l_read_obj) - dap_store_obj_free(l_read_obj, l_count_read); - - if(!l_apply) { - // If request was from defined node_addr we update its state - if(l_ch_chain->request.node_addr.uint64) { - dap_db_log_set_last_id_remote(l_ch_chain->request.node_addr.uint64, l_obj->id); - } - continue; - } - - char l_ts_str[50]; - dap_time_to_str_rfc822(l_ts_str, sizeof(l_ts_str), l_store_obj[i].timestamp); - /*log_it(L_DEBUG, "Unpacked log history: type='%c' (0x%02hhX) group=\"%s\" key=\"%s\"" - " timestamp=\"%s\" value_len=%u ", - (char ) l_store_obj[i].type, l_store_obj[i].type, l_store_obj[i].group, - l_store_obj[i].key, l_ts_str, l_store_obj[i].value_len);*/ - // apply received transaction - dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); - if(l_chain) { - if(l_chain->callback_datums_pool_proc_with_group) - l_chain->callback_datums_pool_proc_with_group(l_chain, - (dap_chain_datum_t**) &(l_store_obj->value), 1, - l_store_obj[i].group); - } - // save data to global_db - if(!dap_chain_global_db_obj_save(l_obj, 1)) { - dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED"); - dap_stream_ch_set_ready_to_write(a_ch, true); - } else { - // If request was from defined node_addr we update its state - if(l_ch_chain->request.node_addr.uint64) { - dap_db_log_set_last_id_remote(l_ch_chain->request.node_addr.uint64, - l_obj->id); - } - //log_it(L_DEBUG, "Added new GLOBAL_DB history pack"); - } - } - if(l_store_obj) - dap_store_obj_free(l_store_obj, l_data_obj_count); - - } else { - log_it(L_WARNING, "Packet with GLOBAL_DB atom has zero body size"); - } - } - break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS: { - dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - memcpy(&l_sync_gdb, l_chain_pkt->data, l_chain_pkt_data_size); - dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); - l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr(l_net) ? - dap_chain_net_get_cur_addr(l_net)->uint64 : - dap_db_get_cur_node_addr(l_net->pub.name); - // Get last timestamp in log - l_sync_gdb.id_start = (uint64_t) dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); - // no limit - l_sync_gdb.id_end = (uint64_t)0; - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); - } - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS_RVRS: { - dap_stream_ch_chain_sync_request_t l_sync_chains = {}; - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, &l_sync_chains, sizeof(l_sync_chains)); - } - default: { + } + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB: { + log_it(L_INFO, "In: SYNC_GLOBAL_DB pkt"); + if(l_ch_chain->state != CHAIN_STATE_IDLE) { + log_it(L_INFO, "Can't process SYNC_GLOBAL_DB request because not in idle state"); + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_STATE_NOT_IN_IDLE"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); + break; + } + // receive the latest global_db revision of the remote node -> go to send mode + if(l_chain_pkt_data_size == sizeof(dap_stream_ch_chain_sync_request_t)) { + dap_stream_ch_chain_sync_request_t * l_request = + (dap_stream_ch_chain_sync_request_t *) l_chain_pkt->data; + memcpy(&l_ch_chain->request, l_request, l_chain_pkt_data_size); + memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, sizeof(dap_chain_cell_id_t)); + memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); + memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); + dap_events_socket_remove_from_worker_unsafe(a_ch->stream->esocket, a_ch->stream_worker->worker); + dap_proc_queue_add_callback(a_ch->stream_worker->worker->proc_queue, s_sync_gdb_callback, a_ch); + } + else { + log_it(L_ERROR, "Get DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB session_id=%u bad request", + a_ch->stream->session->id); + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_SYNC_GLOBAL_DB_REQUEST_BAD"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); + } + } + break; + // first packet of data with source node address + case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN: { + log_it(L_INFO, "In: FIRST_CHAIN data_size=%d", l_chain_pkt_data_size); + if(l_chain_pkt_data_size == sizeof(dap_chain_node_addr_t)) + memcpy(&l_ch_chain->request.node_addr, l_chain_pkt->data, l_chain_pkt_data_size); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN: { + log_it(L_INFO, "In: CHAIN pkt data_size=%d", l_chain_pkt_data_size); + dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); + if(l_chain) { + // Expect atom element in + if(l_chain_pkt_data_size > 0) { + memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); + memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); + memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, sizeof(dap_chain_cell_id_t)); + l_ch_chain->pkt_data = DAP_CALLOC(1, l_chain_pkt_data_size); + memcpy(l_ch_chain->pkt_data, l_chain_pkt->data, l_chain_pkt_data_size); + l_ch_chain->pkt_data_size = l_chain_pkt_data_size; + dap_events_socket_remove_from_worker_unsafe(a_ch->stream->esocket, a_ch->stream_worker->worker); + dap_proc_queue_add_callback(a_ch->stream_worker->worker->proc_queue, s_chain_pkt_callback, a_ch); + } else { + log_it(L_WARNING, "Empty chain packet"); dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, - l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, - "ERROR_UNKNOWN_CHAIN_PKT_TYPE"); - } + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_CHAIN_PACKET_EMPTY"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); } - if(l_ch_chain->callback_notify_packet_in) - l_ch_chain->callback_notify_packet_in(l_ch_chain, l_ch_pkt->hdr.type, l_chain_pkt, - l_chain_pkt_data_size, //l_ch_pkt->hdr.size, - l_ch_chain->callback_notify_arg); } } + break; + // first packet of data with source node address + case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB: { + log_it(L_INFO, "In: FIRST_GLOBAL_DB data_size=%d", l_chain_pkt_data_size); + if(l_chain_pkt_data_size == sizeof(dap_chain_node_addr_t)) + memcpy(&l_ch_chain->request.node_addr, l_chain_pkt->data, l_chain_pkt_data_size); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB: { + log_it(L_INFO, "In: GLOBAL_DB data_size=%d", l_chain_pkt_data_size); + // get transaction and save it to global_db + if(l_chain_pkt_data_size > 0) { + memcpy(&l_ch_chain->request_net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t)); + memcpy(&l_ch_chain->request_chain_id, &l_chain_pkt->hdr.chain_id, sizeof(dap_chain_id_t)); + memcpy(&l_ch_chain->request_cell_id, &l_chain_pkt->hdr.cell_id, sizeof(dap_chain_cell_id_t)); + l_ch_chain->pkt_data = DAP_CALLOC(1, l_chain_pkt_data_size); + memcpy(l_ch_chain->pkt_data, l_chain_pkt->data, l_chain_pkt_data_size); + l_ch_chain->pkt_data_size = l_chain_pkt_data_size; + dap_events_socket_remove_from_worker_unsafe(a_ch->stream->esocket, a_ch->stream_worker->worker); + dap_proc_queue_add_callback(a_ch->stream_worker->worker->proc_queue, s_gdb_pkt_callback, a_ch); + } else { + log_it(L_WARNING, "Packet with GLOBAL_DB atom has zero body size"); + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_GLOBAL_DB_PACKET_EMPTY"); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); + } + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS: { + dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; + memcpy(&l_sync_gdb, l_chain_pkt->data, l_chain_pkt_data_size); + dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); + l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr(l_net) ? + dap_chain_net_get_cur_addr(l_net)->uint64 : + dap_db_get_cur_node_addr(l_net->pub.name); + // Get last timestamp in log + l_sync_gdb.id_start = (uint64_t) dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); + // no limit + l_sync_gdb.id_end = (uint64_t)0; + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS_RVRS: { + dap_stream_ch_chain_sync_request_t l_sync_chains = {}; + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, &l_sync_chains, sizeof(l_sync_chains)); + } + break; + case DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR: + break; + default: { + dap_stream_ch_chain_pkt_write_error(a_ch, l_chain_pkt->hdr.net_id, + l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, + "ERROR_UNKNOWN_CHAIN_PKT_TYPE"); + } + } + if(l_ch_chain->callback_notify_packet_in) + l_ch_chain->callback_notify_packet_in(l_ch_chain, l_ch_pkt->hdr.type, l_chain_pkt, + l_chain_pkt_data_size, l_ch_chain->callback_notify_arg); } + /** * @brief dap_stream_ch_chain_go_idle * @param a_ch_chain @@ -553,160 +614,106 @@ void dap_stream_ch_chain_go_idle ( dap_stream_ch_chain_t * a_ch_chain) HASH_ITER( hh, a_ch_chain->request_atoms_processed, l_atom_item, l_atom_item_tmp ) HASH_DEL(a_ch_chain->request_atoms_processed, l_atom_item); pthread_mutex_unlock(&a_ch_chain->mutex); - dap_stream_ch_set_ready_to_write(a_ch_chain->ch, false); - } -/** - * @brief s_stream_ch_packet_out - * @param ch - * @param arg - */ -void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) +bool s_process_gdb_iter(dap_stream_ch_t *a_ch) { - (void) a_arg; - dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_db_log_list_t *l_db_list = l_ch_chain->request_global_db_trs; + dap_store_obj_pkt_t *l_pkt = (dap_store_obj_pkt_t *)l_ch_chain->db_iter->data; + uint32_t l_pkt_size = sizeof(dap_store_obj_pkt_t) + l_pkt->data_size; + log_it(L_INFO, "Send one global_db record packet len=%d (rest=%d/%d items)", l_pkt_size, + dap_db_log_list_get_count_rest(l_db_list), dap_db_log_list_get_count(l_db_list)); + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, l_pkt, l_pkt_size); + dap_list_t *l_iter = dap_list_next(l_ch_chain->db_iter); + if (l_iter) { + l_ch_chain->db_iter = l_iter; + } else { + l_ch_chain->stats_request_gdb_processed++; + l_ch_chain->db_iter = dap_list_first(l_ch_chain->db_iter); + dap_list_free_full(l_ch_chain->db_iter, free); + l_ch_chain->db_iter = NULL; + } + return true; +} + +bool s_out_pkt_callback(dap_proc_thread_t *a_thread, void *a_arg) +{ + UNUSED(a_thread); + dap_stream_ch_t *l_ch = (dap_stream_ch_t *)a_arg; + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); //log_it( L_DEBUG,"s_stream_ch_packet_out state=%d", l_ch_chain ? l_ch_chain->state : -1); // log_it( L_DEBUG,"l_ch_chain %X", l_ch_chain ); - + bool l_packet_out = false; switch (l_ch_chain->state) { + case CHAIN_STATE_IDLE: { dap_stream_ch_chain_go_idle(l_ch_chain); } break; - case CHAIN_STATE_SYNC_ALL: - case CHAIN_STATE_SYNC_GLOBAL_DB: { - - // Get log diff - //size_t l_data_size_out = 0; - - dap_db_log_list_t *l_db_list = l_ch_chain->request_global_db_trs; //dap_list_last( l_ch_chain->request_global_db_trs ); - dap_global_db_obj_t *l_obj = dap_db_log_list_get(l_db_list); - - if (1) { - //dap_list_t *l_list = l_ch_chain->request_global_db_trs; //dap_list_last( l_ch_chain->request_global_db_trs ); - bool l_is_stop = true; //l_list ? false : true; - while(l_obj) { - - size_t l_items_total = dap_db_log_list_get_count(l_db_list); - size_t l_items_rest = dap_db_log_list_get_count_rest(l_db_list); - + if (l_ch_chain->db_iter) { + l_packet_out = s_process_gdb_iter(l_ch); + } else { + dap_global_db_obj_t *l_obj; + do { // Get log diff size_t l_item_size_out = 0; - uint8_t *l_item = dap_db_log_pack(l_obj, &l_item_size_out); - // Item not found, maybe it has deleted? Then go to the next item - if(!l_item || !l_item_size_out) { - //log_it(L_WARNING, "Log pack returned NULL??? data=0x%x (nothing to send) (rest=%d records)", l_obj, - // l_items_rest); - l_item_size_out = 0; - //dap_stream_ch_set_ready_to_write(a_ch, false); - - // go to next item - l_obj = dap_db_log_list_get(l_db_list); - //if(l_obj) - // continue; - // stop global_db sync - //else - // break; - } - else { - //log_it(L_INFO, "Send one global_db record data=0x%x len=%d (rest=%d/%d items)", l_item, l_item_size_out, - // l_items_rest, l_items_total); - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, l_item, l_item_size_out); - l_ch_chain->stats_request_gdb_processed++; - //dap_stream_ch_set_ready_to_write(a_ch, true); - //sleep(1); - - DAP_DELETE(l_item); - // sent the record, another will be sent - l_is_stop = false; + l_obj = dap_db_log_list_get(l_ch_chain->request_global_db_trs); + l_ch_chain->db_iter = dap_db_log_pack(l_obj, &l_item_size_out); + if (l_ch_chain->db_iter && l_item_size_out) { break; } - // remove current item from list and go to next item - /*dap_chain_global_db_obj_delete((dap_global_db_obj_t *) l_list->data); - l_ch_chain->request_global_db_trs = dap_list_delete_link(l_ch_chain->request_global_db_trs, l_list); - // nothing was sent - if(!l_item_size_out) { - l_list = l_ch_chain->request_global_db_trs; - // go to next item - if(l_list) - continue; - // stop global_db sync - else - break; - }*/ - } - - if(l_is_stop){ + // Item not found, maybe it has deleted? Then go to the next item + } while (l_obj); + if (l_ch_chain->db_iter) { + l_packet_out = s_process_gdb_iter(l_ch); + } else { //log_it(L_DEBUG, "l_obj == 0, STOP"); - // If we don't need to send chains after -// if(l_ch_chain->state != CHAIN_STATE_SYNC_ALL){ -// dap_stream_ch_chain_go_idle(l_ch_chain); -// }else if(l_ch_chain->state == CHAIN_STATE_SYNC_GLOBAL_DB) - { - // free log list - l_ch_chain->request_global_db_trs = NULL; - dap_db_log_list_delete(l_db_list); - - // last message - - dap_stream_ch_chain_sync_request_t l_request = {}; - dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); - l_request.node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - l_request.id_start = dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); - l_request.id_end = 0; - - log_it( L_DEBUG,"Syncronized database: last id %llu, items syncronyzed %llu ", l_request.id_start, - l_ch_chain->stats_request_gdb_processed ); - - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); - - if(l_ch_chain->callback_notify_packet_out) - l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - NULL, 0, l_ch_chain->callback_notify_arg); - - if(l_ch_chain->state != CHAIN_STATE_SYNC_ALL) - dap_stream_ch_chain_go_idle(l_ch_chain); - } + // free log list + dap_db_log_list_delete(l_ch_chain->request_global_db_trs); + l_ch_chain->request_global_db_trs = NULL; + // last message + dap_stream_ch_chain_sync_request_t l_request = {}; + dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_net_id); + l_request.node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; + l_request.id_start = dap_db_log_get_last_id_remote(l_ch_chain->request.node_addr.uint64); + l_request.id_end = 0; + + log_it( L_DEBUG,"Syncronized database: last id %llu, items syncronyzed %llu ", l_request.id_start, + l_ch_chain->stats_request_gdb_processed ); + + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); + l_packet_out = true; + + if(l_ch_chain->callback_notify_packet_out) + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + NULL, 0, l_ch_chain->callback_notify_arg); + dap_stream_ch_chain_go_idle(l_ch_chain); } } + } break; - } - if(l_ch_chain->state != CHAIN_STATE_SYNC_ALL) - break; - - // Synchronize chains + // Synchronize chains case CHAIN_STATE_SYNC_CHAINS: { //log_it(L_DEBUG, "CHAIN_STATE_SYNC_CHAINS"); dap_chain_t * l_chain = dap_chain_find_by_id(l_ch_chain->request_net_id, l_ch_chain->request_chain_id); - /* - // alternative way to get l_chain - if(!l_ch_chain->request_atom_iter) { - log_it(L_ERROR, "CHAIN_STATE_SYNC_CHAINS not ready to send chains"); - l_ch_chain->state = CHAIN_STATE_IDLE; - break; - } - //dap_chain_atom_iter_t* l_iter = l_chain->callback_atom_iter_create(l_chain); - dap_chain_t * l_chain = l_ch_chain->request_atom_iter->chain; - */ - dap_chain_atom_item_t * l_atom_item = NULL, *l_atom_item_tmp = NULL;//, *l_chains_lasts_new = NULL; if(l_ch_chain->request_atoms_lasts == NULL) { // All chains synced - dap_stream_ch_chain_sync_request_t l_request = { { 0 } }; + dap_stream_ch_chain_sync_request_t l_request; + memset(&l_request,0,sizeof (l_request)); uint8_t l_send_pkt_type = l_ch_chain->state == CHAIN_STATE_SYNC_CHAINS ? DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS : DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL; // last message - dap_stream_ch_chain_pkt_write(a_ch, - l_send_pkt_type, - l_ch_chain->request_net_id, l_ch_chain->request_chain_id, - l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); + dap_stream_ch_chain_pkt_write_unsafe(l_ch, l_send_pkt_type, + l_ch_chain->request_net_id, l_ch_chain->request_chain_id, + l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); + l_packet_out = true; log_it( L_DEBUG,"Synced: %llu atoms processed", l_ch_chain->stats_request_atoms_processed); dap_stream_ch_chain_go_idle(l_ch_chain); @@ -729,53 +736,70 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) l_atom_item_proc); // Then flush it out to the remote - size_t l_atom_size = l_chain->callback_atom_get_size(l_atom_item->atom); - dap_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN, l_ch_chain->request_net_id, - l_ch_chain->request_chain_id, l_ch_chain->request_cell_id, - l_atom_item->atom, l_atom_size); + size_t l_atom_size = l_atom_item->atom_size; + log_it(L_INFO, "Send one chain packet len=%d", l_atom_size); + dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN, l_ch_chain->request_net_id, + l_ch_chain->request_chain_id, l_ch_chain->request_cell_id, + l_atom_item->atom, l_atom_size); + l_packet_out = true; l_ch_chain->stats_request_atoms_processed++; // Then parse links and populate new lasts - size_t l_lasts_size = 0; + size_t l_links_count = 0; dap_chain_atom_ptr_t * l_links = NULL; - - dap_chain_atom_iter_t* l_iter = l_chain->callback_atom_iter_create_from(l_chain, l_atom_item->atom); - l_links = l_chain->callback_atom_iter_get_links(l_iter, &l_lasts_size); - //DAP_DELETE(l_atom_item->atom); + size_t *l_links_sizes = NULL; + dap_chain_atom_iter_t* l_iter = l_chain->callback_atom_iter_create_from(l_chain, l_atom_item->atom, l_atom_item->atom_size); + l_links = l_chain->callback_atom_iter_get_links(l_iter, &l_links_count, &l_links_sizes); DAP_DELETE(l_iter); - //l_links = l_chain->callback_atom_iter_get_links(l_atom_item->atom, &l_lasts_size); - - for(size_t i = 0; i < l_lasts_size; i++) { // Find links - dap_chain_atom_item_t * l_link_item = NULL; - dap_chain_hash_fast_t l_link_hash; - dap_hash_fast(l_links[i], l_chain->callback_atom_get_size(l_links[i]), - &l_link_hash); - // Check link in processed atims - HASH_FIND(hh, l_ch_chain->request_atoms_processed, &l_link_hash, sizeof(l_link_hash), l_link_item); - if(l_link_item == NULL) { // Not found, add new lasts - l_link_item = DAP_NEW_Z(dap_chain_atom_item_t); - l_link_item->atom = l_links[i];// do not use memory cause it will be deleted - memcpy(&l_link_item->atom_hash, &l_link_hash, sizeof(l_link_hash)); - //HASH_ADD(hh, l_chains_lasts_new, atom_hash, sizeof(l_link_hash), l_link_item); - HASH_ADD(hh, l_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_link_hash), l_link_item); + if (l_links && l_links_sizes) { + for(size_t i = 0; i < l_links_count; i++) { // Find links + dap_chain_atom_item_t * l_link_item = NULL; + dap_chain_hash_fast_t l_link_hash; + dap_hash_fast(l_links[i], l_links_sizes[i], &l_link_hash); + // Check link in processed atims + HASH_FIND(hh, l_ch_chain->request_atoms_processed, &l_link_hash, sizeof(l_link_hash), l_link_item); + if(l_link_item == NULL) { // Not found, add new lasts + l_link_item = DAP_NEW_Z(dap_chain_atom_item_t); + l_link_item->atom = l_links[i];// do not use memory cause it will be deleted + l_link_item->atom_size = l_links_sizes[i]; + memcpy(&l_link_item->atom_hash, &l_link_hash, sizeof(l_link_hash)); + HASH_ADD(hh, l_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_link_hash), l_link_item); + } } - //else - // DAP_DELETE(l_links[i]); + DAP_DELETE(l_links); } - DAP_DELETE(l_links); HASH_DEL(l_ch_chain->request_atoms_lasts, l_atom_item); break; - } - else{ + } else { HASH_DEL(l_ch_chain->request_atoms_lasts, l_atom_item); } } pthread_mutex_unlock(&l_ch_chain->mutex); } - //assert(l_ch_chain->request_atoms_lasts == NULL); - //l_ch_chain->request_atoms_lasts = l_chains_lasts_new; - } - break; - + } break; + default: break; + } + if (l_packet_out) { + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); } + dap_events_socket_assign_on_worker_mt(l_ch->stream->esocket, l_ch->stream_worker->worker); + return true; +} +/** + * @brief s_stream_ch_packet_out + * @param ch + * @param arg + */ +void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) +{ + (void) a_arg; + if (a_ch->stream->esocket->buf_out_size > DAP_EVENTS_SOCKET_BUF / 2) { + return; + } + dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); + dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + if (l_ch_chain && l_ch_chain->state != CHAIN_STATE_IDLE) { + dap_events_socket_remove_from_worker_unsafe(a_ch->stream->esocket, a_ch->stream_worker->worker); + dap_proc_queue_add_callback(a_ch->stream_worker->worker->proc_queue, s_out_pkt_callback, a_ch); + } } diff --git a/modules/channel/chain/dap_stream_ch_chain_pkt.c b/modules/channel/chain/dap_stream_ch_chain_pkt.c index bbb00965cc5b7b69af2f318d515b47b117d37fc5..19cc566016f4a6da7dced3ae83de9970c270cd00 100644 --- a/modules/channel/chain/dap_stream_ch_chain_pkt.c +++ b/modules/channel/chain/dap_stream_ch_chain_pkt.c @@ -48,9 +48,9 @@ dap_stream_ch_chain_state_t dap_stream_ch_chain_pkt_type_to_dap_stream_ch_chain_ * @param data_size * @return */ -size_t dap_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type,dap_chain_net_id_t a_net_id, - dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, - const void * a_data, size_t a_data_size) +size_t dap_stream_ch_chain_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type,dap_chain_net_id_t a_net_id, + dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, + const void * a_data, size_t a_data_size) { dap_stream_ch_chain_pkt_t * l_chain_pkt; size_t l_chain_pkt_size = sizeof (l_chain_pkt->hdr) + a_data_size; @@ -63,7 +63,27 @@ size_t dap_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type,dap_c if (a_data_size && a_data) memcpy( l_chain_pkt->data, a_data, a_data_size); - size_t l_ret = dap_stream_ch_pkt_write(a_ch, a_type , l_chain_pkt, l_chain_pkt_size); + size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type , l_chain_pkt, l_chain_pkt_size); + DAP_DELETE(l_chain_pkt); + return l_ret; +} + +size_t dap_stream_ch_chain_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_t *a_ch, uint8_t a_type,dap_chain_net_id_t a_net_id, + dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, + const void * a_data, size_t a_data_size) +{ + dap_stream_ch_chain_pkt_t * l_chain_pkt; + size_t l_chain_pkt_size = sizeof (l_chain_pkt->hdr) + a_data_size; + l_chain_pkt = DAP_NEW_Z_SIZE(dap_stream_ch_chain_pkt_t, l_chain_pkt_size ); + l_chain_pkt->hdr.version = 1; + l_chain_pkt->hdr.net_id.uint64 = a_net_id.uint64; + l_chain_pkt->hdr.cell_id.uint64 = a_cell_id.uint64; + l_chain_pkt->hdr.chain_id.uint64 = a_chain_id.uint64; + + if (a_data_size && a_data) + memcpy( l_chain_pkt->data, a_data, a_data_size); + + size_t l_ret = dap_stream_ch_pkt_write_mt(a_worker, a_ch, a_type , l_chain_pkt, l_chain_pkt_size); DAP_DELETE(l_chain_pkt); return l_ret; } diff --git a/modules/channel/chain/include/dap_stream_ch_chain.h b/modules/channel/chain/include/dap_stream_ch_chain.h index 0e5e6793752fb76e882827b48c986ca4c75ed039..9e576b7656c964ae5dbe01f999b38f7dcb6fedb5 100644 --- a/modules/channel/chain/include/dap_stream_ch_chain.h +++ b/modules/channel/chain/include/dap_stream_ch_chain.h @@ -41,6 +41,7 @@ typedef void (*dap_stream_ch_chain_callback_packet_t)(dap_stream_ch_chain_t*, ui typedef struct dap_chain_atom_item{ dap_chain_hash_fast_t atom_hash; dap_chain_atom_ptr_t atom; + size_t atom_size; UT_hash_handle hh; } dap_chain_atom_item_t; @@ -48,12 +49,15 @@ typedef struct dap_stream_ch_chain { pthread_mutex_t mutex; dap_stream_ch_t * ch; - dap_db_log_list_t *request_global_db_trs; // list of transactions + dap_db_log_list_t *request_global_db_trs; // list of global db records + dap_list_t *db_iter; dap_stream_ch_chain_state_t state; dap_chain_atom_iter_t * request_atom_iter; dap_chain_atom_item_t * request_atoms_lasts; dap_chain_atom_item_t * request_atoms_processed; + uint8_t *pkt_data; + uint64_t pkt_data_size; uint64_t stats_request_atoms_processed; uint64_t stats_request_gdb_processed; dap_stream_ch_chain_sync_request_t request; diff --git a/modules/channel/chain/include/dap_stream_ch_chain_pkt.h b/modules/channel/chain/include/dap_stream_ch_chain_pkt.h index 47903691f86ad4677b5cb46bf7eeb8c9fc68ed0f..a56e07c49053032fc1e2e054ca3a673e4aadf1ae 100644 --- a/modules/channel/chain/include/dap_stream_ch_chain_pkt.h +++ b/modules/channel/chain/include/dap_stream_ch_chain_pkt.h @@ -57,7 +57,7 @@ typedef enum dap_stream_ch_chain_state{ CHAIN_STATE_IDLE=0, CHAIN_STATE_SYNC_CHAINS, CHAIN_STATE_SYNC_GLOBAL_DB, - CHAIN_STATE_SYNC_ALL, + CHAIN_STATE_SYNC_ALL } dap_stream_ch_chain_state_t; typedef struct dap_stream_ch_chain_sync_request{ @@ -97,12 +97,16 @@ static const char* c_dap_stream_ch_chain_pkt_type_str[]={ dap_stream_ch_chain_state_t dap_stream_ch_chain_pkt_type_to_dap_stream_ch_chain_state(char a_state); -size_t dap_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type,dap_chain_net_id_t a_net_id, - dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, - const void * a_data, size_t a_data_size); +size_t dap_stream_ch_chain_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, dap_chain_net_id_t a_net_id, + dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, + const void * a_data, size_t a_data_size); + +size_t dap_stream_ch_chain_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_t *a_ch, uint8_t a_type, dap_chain_net_id_t a_net_id, + dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, + const void * a_data, size_t a_data_size); inline static size_t dap_stream_ch_chain_pkt_write_error(dap_stream_ch_t *a_ch, dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, const char * a_err_string ) { - return dap_stream_ch_chain_pkt_write( a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR, a_net_id, a_chain_id, a_cell_id, a_err_string,strlen (a_err_string)+1 ); + return dap_stream_ch_chain_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR, a_net_id, a_chain_id, a_cell_id, a_err_string,strlen (a_err_string)+1 ); } diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c index ac632bf6be2fc51c38ce3ee651cd95e6abffeba6..60b04baf49f1a973f1ae0739752db6c60366b58b 100644 --- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c +++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c @@ -66,9 +66,9 @@ typedef struct dap_chain_cs_dag_poa_pvt static void s_callback_delete(dap_chain_cs_dag_t * a_dag); static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_cfg); -static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event); +static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event, size_t a_dag_event_size); static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum, - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count); + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t* a_event_size); // CLI commands static int s_cli_dag_poa(int argc, char ** argv, void *arg_func, char **str_reply); @@ -109,6 +109,7 @@ void dap_chain_cs_dag_poa_deinit(void) */ static int s_cli_dag_poa(int argc, char ** argv, void *arg_func, char **a_str_reply) { + (void) arg_func; int ret = -666; int arg_index = 1; dap_chain_net_t * l_chain_net = NULL; @@ -165,9 +166,9 @@ static int s_cli_dag_poa(int argc, char ** argv, void *arg_func, char **a_str_re l_event_hash_str); ret = -30; }else { - dap_chain_cs_dag_event_t *l_event_new = dap_chain_cs_dag_event_copy_with_sign_add(l_event,l_poa_pvt->events_sign_cert->enc_key ); + dap_chain_cs_dag_event_t *l_event_new = dap_chain_cs_dag_event_copy_with_sign_add(l_event, l_event_size,l_poa_pvt->events_sign_cert->enc_key ); dap_chain_hash_fast_t l_event_new_hash; - dap_chain_cs_dag_event_calc_hash(l_event_new,&l_event_new_hash); + dap_chain_cs_dag_event_calc_hash(l_event_new, l_event_size,&l_event_new_hash); //size_t l_event_new_size = dap_chain_cs_dag_event_calc_size(l_event_new); char * l_event_new_hash_hex_str = dap_chain_hash_fast_to_str_new(&l_event_new_hash); char * l_event_new_hash_base58_str = dap_enc_base58_encode_hash_to_str(&l_event_new_hash); @@ -319,7 +320,7 @@ static void s_callback_delete(dap_chain_cs_dag_t * a_dag) * @return */ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum, - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count) + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t* a_event_size) { dap_return_val_if_fail(a_dag && a_dag->chain && DAP_CHAIN_CS_DAG_POA(a_dag), NULL); dap_chain_net_t * l_net = dap_chain_net_by_name( a_dag->chain->net_name ); @@ -330,7 +331,7 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a } if ( s_seed_mode || (a_hashes && a_hashes_count) ){ dap_chain_cs_dag_event_t * l_event = dap_chain_cs_dag_event_new( a_dag->chain->id, l_net->pub.cell_id, a_datum, - PVT(l_poa)->events_sign_cert->enc_key, a_hashes, a_hashes_count); + PVT(l_poa)->events_sign_cert->enc_key, a_hashes, a_hashes_count,a_event_size); return l_event; }else return NULL; @@ -344,17 +345,30 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a * @param a_dag_event * @return */ -static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event) +static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event, size_t a_dag_event_size) { dap_chain_cs_dag_poa_pvt_t * l_poa_pvt = PVT ( DAP_CHAIN_CS_DAG_POA( a_dag ) ); + size_t l_offset_from_beginning = dap_chain_cs_dag_event_calc_size_excl_signs(a_dag_event,a_dag_event_size); + if( l_offset_from_beginning >= a_dag_event_size){ + log_it(L_WARNING,"Incorrect size with event %p: caled size excl signs %zd is bigger or equal then event size %zd", + a_dag_event, l_offset_from_beginning, a_dag_event_size); + return -7; // Incorrest size + } if ( a_dag_event->header.signs_count >= l_poa_pvt->auth_certs_count_verify ){ size_t l_verified = 0; for ( uint16_t i = 0; i < a_dag_event->header.signs_count; i++ ) { - dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event, 0); + if (l_offset_from_beginning == a_dag_event_size) + break; + dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event,a_dag_event_size , 0); if ( l_sign == NULL){ log_it(L_WARNING, "Event is NOT signed with anything"); return -4; } + l_offset_from_beginning += dap_sign_get_size( l_sign); + if (l_offset_from_beginning > a_dag_event_size){ + log_it(L_WARNING,"Incorrect size with event %p", a_dag_event); + return -7; + } for (uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++) { if (dap_cert_compare_with_sign ( l_poa_pvt->auth_certs[j], l_sign) == 0) l_verified++; @@ -367,10 +381,11 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ } dap_chain_addr_t l_addr = {}; dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_dag->chain->net_id); - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event); + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event, a_dag_event_size); if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; if (!dap_chain_net_srv_stake_validator(&l_addr, l_tx)) { + log_it(L_WARNING,"Not passed stake validator event %p", a_dag_event); return -6; } } @@ -378,7 +393,9 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ } return l_verified >= l_poa_pvt->auth_certs_count_verify ? 0 : -1; - }else - return -2; // Wrong signatures number + }else{ + log_it(L_WARNING,"Wrong signatures number with event %p", a_dag_event); + return -2; // Wrong signatures number + } } diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c index fc3337dcef13d408ac1a63ed4e7f89dc3a0e9c21..597ea51c63afaf5db0f92c5567c1fc847866389c 100644 --- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c +++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c @@ -49,9 +49,9 @@ typedef struct dap_chain_cs_dag_pos_pvt static void s_callback_delete(dap_chain_cs_dag_t * a_dag); static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); static int s_callback_created(dap_chain_t * a_chain, dap_config_t *a_chain_cfg); -static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event); +static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event, size_t a_dag_event_size); static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum, - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count); + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t *a_dag_event_size); /** * @brief dap_chain_cs_dag_pos_init @@ -186,7 +186,8 @@ static void s_callback_delete(dap_chain_cs_dag_t * a_dag) * @return */ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a_dag, dap_chain_datum_t * a_datum, - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count) + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, + size_t *a_dag_event_size) { dap_return_val_if_fail(a_dag && a_dag->chain && DAP_CHAIN_CS_DAG_POS(a_dag) && a_datum, NULL); dap_chain_net_t * l_net = dap_chain_net_by_name( a_dag->chain->net_name ); @@ -198,7 +199,7 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a } if(a_datum || (a_hashes && a_hashes_count)) { dap_chain_cs_dag_event_t * l_event = dap_chain_cs_dag_event_new(a_dag->chain->id, l_net->pub.cell_id, a_datum, - PVT(l_pos)->events_sign_wallet->enc_key, a_hashes, a_hashes_count); + PVT(l_pos)->events_sign_wallet->enc_key, a_hashes, a_hashes_count, a_dag_event_size); return l_event; } else return NULL; @@ -210,21 +211,27 @@ static dap_chain_cs_dag_event_t * s_callback_event_create(dap_chain_cs_dag_t * a * @param a_dag_event * @return */ -static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event) +static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_dag_event, size_t a_dag_event_size) { dap_chain_cs_dag_pos_t * l_pos =DAP_CHAIN_CS_DAG_POS( a_dag ) ; dap_chain_cs_dag_pos_pvt_t * l_pos_pvt = PVT ( DAP_CHAIN_CS_DAG_POS( a_dag ) ); - if(a_dag->chain->ledger == NULL) + if(a_dag->chain->ledger == NULL){ + log_it(L_CRITICAL,"Ledger is NULL can't check PoS on this chain %s", a_dag->chain->name); return -3; + } + if (sizeof (a_dag_event->header)>= a_dag_event_size){ + log_it(L_WARNING,"Incorrect size with event %p on chain %s", a_dag_event, a_dag->chain->name); + return -7; + } if ( a_dag_event->header.signs_count >= l_pos_pvt->confirmations_minimum ){ uint16_t l_verified_num = 0; dap_chain_addr_t l_addr = { 0 }; for ( size_t l_sig_pos=0; l_sig_pos < a_dag_event->header.signs_count; l_sig_pos++ ){ - dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event, 0); + dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event, 0,a_dag_event_size); if ( l_sign == NULL){ log_it(L_WARNING, "Event is NOT signed with anything"); return -4; @@ -238,10 +245,11 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, a_dag->chain->net_id); if (l_sig_pos == 0) { - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event); + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event,a_dag_event_size); if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; if (!dap_chain_net_srv_stake_validator(&l_addr, l_tx)) { + log_it(L_WARNING,"Not passed stake validator with event %p on chain %s", a_dag_event, a_dag->chain->name); return -6; } } @@ -287,6 +295,8 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_ log_it(L_WARNING, "Wrong event: only %su/%su signs are valid", l_verified_num, l_pos_pvt->confirmations_minimum ); return -2; } - }else - return -2; // Wrong signatures number + }else{ + log_it(L_WARNING,"Wrong signature number with event %p on chain %s", a_dag_event, a_dag->chain->name); + return -2; // Wrong signatures number + } } diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index 5086bc7adea914a2e9a423db8feeea8bec9a4572..f68ce988c17733f7bc2ef0354ae48308afc0ba96 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -68,30 +68,29 @@ typedef struct dap_chain_gdb_private static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net); // Atomic element organization callbacks -static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Accept new event in gdb -static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t); // Verify new event in gdb -static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t); // Get gdb event size +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Accept new event in gdb +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Verify new event in gdb static size_t s_chain_callback_atom_get_static_hdr_size(void); // Get gdb event header size static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain); static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain, - dap_chain_atom_ptr_t a); + dap_chain_atom_ptr_t a, size_t a_atom_size); // Delete iterator static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter); // Get the fisrt event from gdb static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, - dap_chain_hash_fast_t * a_atom_hash); + dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_tx_hash(dap_chain_atom_iter_t * a_atom_iter , - dap_chain_hash_fast_t * a_atom_hash); + dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); // Get event(s) from gdb -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter); // Get the fisrt event from gdb -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter); // Get the next event from gdb +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t * a_atom_size); // Get the fisrt event from gdb +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter, size_t * a_atom_size); // Get the next event from gdb static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_links(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_links_size_ptr); // Get list of linked events + size_t * a_links_size_ptr, size_t ** a_lasts_sizes_ptr); // Get list of linked events static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_lasts(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_lasts_size_ptr); // Get list of linked events + size_t * a_lasts_size_ptr, size_t ** a_lasts_sizes_ptr); // Get list of linked events static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size); @@ -185,7 +184,6 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add; // Accept new element in chain a_chain->callback_atom_verify = s_chain_callback_atom_verify; // Verify new element in chain - a_chain->callback_atom_get_size = s_chain_callback_atom_hdr_get_size; // Get dag event size a_chain->callback_atom_get_hdr_static_size = s_chain_callback_atom_get_static_hdr_size; // Get dag event hdr size a_chain->callback_atom_iter_create = s_chain_callback_atom_iter_create; @@ -263,7 +261,6 @@ const char* dap_chain_gdb_get_group(dap_chain_t * a_chain) static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net) { dap_chain_gdb_private_t *l_gdb_priv = PVT(a_gdb); - dap_list_t *l_datum_list = NULL, *l_list_tmp = NULL; // protect from reloading if(dap_chain_ledger_count( a_net->pub.ledger ) > 0) return 0; @@ -275,19 +272,10 @@ static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_ dap_global_db_obj_t *data = dap_chain_global_db_gr_load(l_gdb_priv->group_datums , &l_data_size); // make list of datums for(size_t i = 0; i < l_data_size; i++) { - l_datum_list = dap_list_append(l_datum_list, data[i].value); - } - // sort list by time - //l_datum_list = dap_list_sort(l_datum_list, (dap_callback_compare_t) compare_datum_items); - l_list_tmp = l_datum_list; - // add datum_tx from list to ledger - while(l_list_tmp) { - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_list_tmp->data; - s_chain_callback_atom_add(a_gdb->chain,l_datum); - l_list_tmp = dap_list_next(l_list_tmp); + s_chain_callback_atom_add(a_gdb->chain,data[i].value, data[i].value_len); + } dap_chain_global_db_objs_delete(data, l_data_size); - dap_list_free(l_datum_list); return 0; } @@ -302,7 +290,7 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain { for(size_t i = 0; i < a_datums_count; i++) { dap_chain_datum_t * l_datum = a_datums[i]; - s_chain_callback_atom_add(a_chain, l_datum ); + s_chain_callback_atom_add(a_chain, l_datum,dap_chain_datum_size(l_datum) ); } return a_datums_count; } @@ -321,11 +309,16 @@ static size_t s_chain_callback_datums_pool_proc_with_group(dap_chain_t * a_chain * @param a_datums * @param a_datums_size */ -static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_chain); dap_chain_gdb_private_t *l_gdb_priv = PVT(l_gdb); dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom; + if ( a_atom_size < l_datum->header.data_size+ sizeof (l_datum->header) ){ + log_it(L_INFO,"Corrupted atom rejected: wrong size %zd not equel or less atom size %zd",l_datum->header.data_size+ sizeof (l_datum->header), + a_atom_size); + return ATOM_REJECT; + } switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL:{ dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; @@ -369,22 +362,14 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha * @param a_atom * @return */ -static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { (void) a_chain; (void) a_atom; + (void) a_atom_size; return ATOM_ACCEPT; } -/** - * @brief s_chain_callback_atom_get_size Get size of atomic element - * @param a_atom - * @return - */ -static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t a_atom) -{ - return ((dap_chain_datum_t *) a_atom)->header.data_size +sizeof (((dap_chain_datum_t *) a_atom)->header); -} /** * @brief s_chain_callback_atom_get_static_hdr_size @@ -416,7 +401,7 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_ * @return */ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain, - dap_chain_atom_ptr_t a_atom) + dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { dap_chain_atom_iter_t * l_iter = DAP_NEW_Z(dap_chain_atom_iter_t); l_iter->chain = a_chain; @@ -441,7 +426,7 @@ static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_ite * @return */ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, - dap_chain_hash_fast_t * a_atom_hash) + dap_chain_hash_fast_t * a_atom_hash, size_t *a_atom_size) { char * l_key = dap_chain_hash_fast_to_str_new(a_atom_hash); size_t l_ret_size; @@ -449,6 +434,7 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_at dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_atom_iter->chain ); l_ret = dap_chain_global_db_gr_get(l_key,&l_ret_size, PVT ( l_gdb )->group_datums ); + *a_atom_size = l_ret_size; return l_ret; } @@ -457,7 +443,7 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_at * @param a_atom_iter * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size) { dap_chain_datum_t * l_datum = NULL; a_atom_iter->cur_item = PVT ( DAP_CHAIN_GDB(a_atom_iter->chain) )->hash_items; @@ -468,7 +454,9 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_ if (a_atom_iter->cur) // This iterator should clean up data for it because its allocate it DAP_DELETE( a_atom_iter->cur); a_atom_iter->cur = l_datum; - } + *a_atom_size = l_datum_size; + }else + *a_atom_size = 0; return l_datum; } @@ -477,7 +465,7 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_ * @param a_atom_iter * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size) { dap_chain_datum_t * l_datum = NULL; a_atom_iter->cur_item = a_atom_iter->cur_item? @@ -490,7 +478,9 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_i if (a_atom_iter->cur) // This iterator should clean up data for it because its allocate it DAP_DELETE( a_atom_iter->cur); a_atom_iter->cur = l_datum; - } + *a_atom_size = l_datum_size; + }else + *a_atom_size = 0; return l_datum; } @@ -501,10 +491,11 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next(dap_chain_atom_i * @return */ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_links_size_ptr) + size_t * a_links_size_ptr, size_t **a_links_sizes_ptr) { (void) a_atom_iter; (void) a_links_size_ptr; + (void) a_links_sizes_ptr; return NULL; } @@ -515,10 +506,11 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links(dap_chain_atom * @return */ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_lasts_size_ptr) + size_t * a_lasts_size_ptr, size_t **a_links_sizes_ptr) { (void) a_atom_iter; (void) a_lasts_size_ptr; + (void) a_links_sizes_ptr; return NULL; } diff --git a/modules/global-db/dap_chain_global_db_driver.c b/modules/global-db/dap_chain_global_db_driver.c index b1e80583100dff38df943ec1daddc158b286f400..fd07a1bda401d4a7667c7b4377629862718659c5 100644 --- a/modules/global-db/dap_chain_global_db_driver.c +++ b/modules/global-db/dap_chain_global_db_driver.c @@ -196,53 +196,64 @@ static size_t dap_db_get_size_pdap_store_obj_t(pdap_store_obj_t store_obj) * @param a_size_out[out] size of output structure * @return NULL in case of an error */ -dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, +dap_list_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count) { - if(!a_store_obj || a_store_obj_count < 1) + if (!a_store_obj || a_store_obj_count < 1) return NULL; - size_t l_data_size_out = sizeof(uint32_t); // size of output data + // calculate output structure size - for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q) + dap_list_t *l_ret = NULL; + dap_store_obj_pkt_t *l_pkt; + uint32_t l_obj_count = 0, l_data_size_out = 0; + for (size_t l_q = 0; l_q < a_store_obj_count; ++l_q) { l_data_size_out += dap_db_get_size_pdap_store_obj_t(&a_store_obj[l_q]); - - dap_store_obj_pkt_t *l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out); - l_pkt->data_size = l_data_size_out; - l_pkt->timestamp = a_timestamp; - uint64_t l_offset = 0; - uint32_t l_count = (uint32_t) a_store_obj_count; - memcpy(l_pkt->data + l_offset, &l_count, sizeof(uint32_t)); - l_offset += sizeof(uint32_t); - for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q) { - dap_store_obj_t obj = a_store_obj[l_q]; - //uint16_t section_size = (uint16_t) dap_strlen(obj.section); - uint16_t group_size = (uint16_t) dap_strlen(obj.group); - uint16_t key_size = (uint16_t) dap_strlen(obj.key); - memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int)); - l_offset += sizeof(int); - //memcpy(l_pkt->data + l_offset, §ion_size, sizeof(uint16_t)); - //l_offset += sizeof(uint16_t); - //memcpy(l_pkt->data + l_offset, obj.section, section_size); - //l_offset += section_size; - memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t)); - l_offset += sizeof(uint16_t); - memcpy(l_pkt->data + l_offset, obj.group, group_size); - l_offset += group_size; - memcpy(l_pkt->data + l_offset, &obj.id, sizeof(uint64_t)); - l_offset += sizeof(uint64_t); - memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t)); - l_offset += sizeof(time_t); - memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t)); - l_offset += sizeof(uint16_t); - memcpy(l_pkt->data + l_offset, obj.key, key_size); - l_offset += key_size; - memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t)); - l_offset += sizeof(size_t); - memcpy(l_pkt->data + l_offset, obj.value, obj.value_len); - l_offset += obj.value_len; + if (l_data_size_out > DAP_CHAIN_PKT_EXPECT_SIZE || (l_q == a_store_obj_count - 1 && l_data_size_out)) { + l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out); + l_pkt->data_size = l_data_size_out; + l_pkt->timestamp = a_timestamp; + l_pkt->obj_count = l_q + 1 - l_obj_count; + l_ret = dap_list_append(l_ret, l_pkt); + l_data_size_out = 0; + l_obj_count = l_q + 1; + } } - assert(l_data_size_out == l_offset); - return l_pkt; + l_obj_count = 0; + for (dap_list_t *l_iter = l_ret; l_iter; l_iter = dap_list_next(l_iter)) { + l_pkt = (dap_store_obj_pkt_t *)l_iter->data; + uint64_t l_offset = 0; + for(size_t l_q = 0; l_q < l_pkt->obj_count; ++l_q) { + dap_store_obj_t obj = a_store_obj[l_obj_count + l_q]; + //uint16_t section_size = (uint16_t) dap_strlen(obj.section); + uint16_t group_size = (uint16_t) dap_strlen(obj.group); + uint16_t key_size = (uint16_t) dap_strlen(obj.key); + memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int)); + l_offset += sizeof(int); + //memcpy(l_pkt->data + l_offset, §ion_size, sizeof(uint16_t)); + //l_offset += sizeof(uint16_t); + //memcpy(l_pkt->data + l_offset, obj.section, section_size); + //l_offset += section_size; + memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, obj.group, group_size); + l_offset += group_size; + memcpy(l_pkt->data + l_offset, &obj.id, sizeof(uint64_t)); + l_offset += sizeof(uint64_t); + memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t)); + l_offset += sizeof(time_t); + memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, obj.key, key_size); + l_offset += key_size; + memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t)); + l_offset += sizeof(size_t); + memcpy(l_pkt->data + l_offset, obj.value, obj.value_len); + l_offset += obj.value_len; + } + l_obj_count += l_pkt->obj_count; + assert(l_pkt->data_size == l_offset); + } + return l_ret; } /** * deserialization @@ -255,9 +266,7 @@ dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *pkt, siz if(!pkt || pkt->data_size < 1) return NULL; uint64_t offset = 0; - uint32_t count; - memcpy(&count, pkt->data, sizeof(uint32_t)); - offset += sizeof(uint32_t); + uint32_t count = pkt->obj_count; dap_store_obj_t *store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, count * sizeof(struct dap_store_obj)); for(size_t q = 0; q < count; ++q) { dap_store_obj_t *obj = store_obj + q; diff --git a/modules/global-db/dap_chain_global_db_hist.c b/modules/global-db/dap_chain_global_db_hist.c index c2683b156035b3ac7eab75ef6fed3f7d9cf45301..4ac96d14723d9dba34e479c32cba8cfc776cce10 100644 --- a/modules/global-db/dap_chain_global_db_hist.c +++ b/modules/global-db/dap_chain_global_db_hist.c @@ -77,7 +77,7 @@ static char* dap_db_new_history_timestamp() * * return dap_store_obj_pkt_t* */ -uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) +dap_list_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) { if(!a_obj) return NULL; @@ -122,15 +122,18 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) i++; } // serialize data - dap_store_obj_pkt_t *l_data_out = dap_store_packet_multiple(l_store_obj, l_timestamp, l_count); + dap_list_t *l_data_out = dap_store_packet_multiple(l_store_obj, l_timestamp, l_count); dap_store_obj_free(l_store_obj, l_count); dap_strfreev(l_keys); if(l_data_out && a_data_size_out) { - *a_data_size_out = sizeof(dap_store_obj_pkt_t) + l_data_out->data_size; + *a_data_size_out = 0; + for (dap_list_t *l_iter = l_data_out; l_iter; l_iter = dap_list_next(l_iter)) { + *a_data_size_out += sizeof(dap_store_obj_pkt_t) + ((dap_store_obj_pkt_t *)l_data_out)->data_size; + } } - return (uint8_t*) l_data_out; + return l_data_out; } @@ -1326,7 +1329,6 @@ dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_gr dap_db_log_list_t *l_dap_db_log_list = DAP_NEW_Z(dap_db_log_list_t); size_t l_add_groups_num = 0;// number of group - //size_t l_add_groups_items_num = 0;// number items in all groups dap_list_t *l_add_groups_mask = a_add_groups_mask; // calc l_add_groups_num while(l_add_groups_mask) { @@ -1337,7 +1339,6 @@ dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_gr l_add_groups_mask = dap_list_next(l_add_groups_mask); } - //size_t l_add_groups_num = dap_list_length(a_add_groups_mask); size_t l_data_size_out_main = dap_chain_global_db_driver_count(GROUP_LOCAL_HISTORY, first_id); size_t *l_data_size_out_add_items = DAP_NEW_Z_SIZE(size_t, sizeof(size_t) * l_add_groups_num); uint64_t *l_group_last_id = DAP_NEW_Z_SIZE(uint64_t, sizeof(uint64_t) * l_add_groups_num); @@ -1366,9 +1367,6 @@ dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_gr } if(!(l_data_size_out_main + l_data_size_out_add_items_count)) return NULL; - // debug -// if(l_data_size_out>11) -// l_data_size_out = 11; l_dap_db_log_list->item_start = first_id; l_dap_db_log_list->item_last = first_id + l_data_size_out_main; l_dap_db_log_list->items_number_main = l_data_size_out_main; @@ -1381,31 +1379,9 @@ dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_gr l_dap_db_log_list->group_names = l_group_names; l_dap_db_log_list->group_cur = -1; l_dap_db_log_list->add_groups = a_add_groups_mask; - // there are too few items, read items right now - if(0) {//l_data_size_out <= 10) { - dap_list_t *l_list = NULL; - // read first items - size_t l_objs_count = 0; - dap_store_obj_t *l_objs = dap_chain_global_db_cond_load(GROUP_LOCAL_HISTORY, first_id, &l_objs_count); - for(size_t i = 0; i < l_objs_count; i++) { - dap_store_obj_t *l_obj_cur = l_objs + i; - dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t); - l_item->id = l_obj_cur->id; - l_item->key = dap_strdup(l_obj_cur->key); - l_item->value = (uint8_t*) dap_strdup((char*) l_obj_cur->value); - l_list = dap_list_append(l_list, l_item); - } - l_dap_db_log_list->list_write = l_list; - l_dap_db_log_list->list_read = l_list; - //log_it(L_DEBUG, "loaded items n=%d", l_data_size_out); - dap_store_obj_free(l_objs, l_objs_count); - } - // start thread for items loading - else { - l_dap_db_log_list->is_process = true; - pthread_mutex_init(&l_dap_db_log_list->list_mutex, NULL); - pthread_create(&l_dap_db_log_list->thread, NULL, s_list_thread_proc, l_dap_db_log_list); - } + l_dap_db_log_list->is_process = true; + pthread_mutex_init(&l_dap_db_log_list->list_mutex, NULL); + pthread_create(&l_dap_db_log_list->thread, NULL, s_list_thread_proc, l_dap_db_log_list); return l_dap_db_log_list; } diff --git a/modules/global-db/include/dap_chain_global_db.h b/modules/global-db/include/dap_chain_global_db.h index 4ac3c5a9a341967527090abafd49e33c3499e618..76ae0627161424824ce8d44a65eb493be464bcf3 100644 --- a/modules/global-db/include/dap_chain_global_db.h +++ b/modules/global-db/include/dap_chain_global_db.h @@ -119,7 +119,7 @@ char* dap_chain_global_db_hash(const uint8_t *data, size_t data_size); char* dap_chain_global_db_hash_fast(const uint8_t *data, size_t data_size); // Get data according the history log -uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out); +dap_list_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out); // Get data according the history log //char* dap_db_history_tx(dap_chain_hash_fast_t * a_tx_hash, const char *a_group_mempool); diff --git a/modules/global-db/include/dap_chain_global_db_driver.h b/modules/global-db/include/dap_chain_global_db_driver.h index c8d7ef9c5297971699256e5cfe12ed8e68f53e9d..4bccdc9e0905fa1ee4423aca3459065b331c29de 100644 --- a/modules/global-db/include/dap_chain_global_db_driver.h +++ b/modules/global-db/include/dap_chain_global_db_driver.h @@ -29,6 +29,8 @@ #include "dap_common.h" #include "dap_list.h" +#define DAP_CHAIN_PKT_EXPECT_SIZE 7168 + typedef struct dap_store_obj { uint64_t id; time_t timestamp; @@ -42,8 +44,9 @@ typedef struct dap_store_obj { }DAP_ALIGN_PACKED dap_store_obj_t, *pdap_store_obj_t; typedef struct dap_store_obj_pkt { - time_t timestamp; - size_t data_size; + uint64_t timestamp; + uint64_t data_size; + uint32_t obj_count; uint8_t data[]; }__attribute__((packed)) dap_store_obj_pkt_t; @@ -90,7 +93,7 @@ bool dap_chain_global_db_driver_is(const char *a_group, const char *a_key); size_t dap_chain_global_db_driver_count(const char *a_group, uint64_t id); dap_list_t* dap_chain_global_db_driver_get_groups_by_mask(const char *a_group_mask); -dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, +dap_list_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count); dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *a_pkt, size_t *a_store_obj_count); diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index 9b4c4ebe29990324b568e1323b28a9d8ef8a9eac..c5150e1cfd84094cb2abaee51480592e0c446545 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -887,15 +887,15 @@ void chain_mempool_proc(struct dap_http_simple *cl_st, void * arg) { http_status_code_t * return_code = (http_status_code_t*) arg; // save key while it alive, i.e. still exist - dap_enc_key_t *key = dap_enc_ks_find_http(cl_st->http); + dap_enc_key_t *key = dap_enc_ks_find_http(cl_st->http_client); //dap_enc_key_serealize_t *key_ser = dap_enc_key_serealize(key_tmp); //dap_enc_key_t *key = dap_enc_key_deserealize(key_ser, sizeof(dap_enc_key_serealize_t)); // read header dap_http_header_t *hdr_session_close_id = - (cl_st->http) ? dap_http_header_find(cl_st->http->in_headers, "SessionCloseAfterRequest") : NULL; + (cl_st->http_client) ? dap_http_header_find(cl_st->http_client->in_headers, "SessionCloseAfterRequest") : NULL; dap_http_header_t *hdr_key_id = - (hdr_session_close_id && cl_st->http) ? dap_http_header_find(cl_st->http->in_headers, "KeyID") : NULL; + (hdr_session_close_id && cl_st->http_client) ? dap_http_header_find(cl_st->http_client->in_headers, "KeyID") : NULL; enc_http_delegate_t *dg = enc_http_request_decode(cl_st); if(dg) { diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 2f54a6c98138bf589bd0dc8a0c8840c419867e0c..fb3731e98df40e5610f20bdd12398dc30b09f9d5 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -23,11 +23,12 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ - #include <stdlib.h> -#define _XOPEN_SOURCE /* See feature_test_macros(7) */ +#include <stdint.h> +#include <stddef.h> #include <stdio.h> -#include <time.h> + + #include <stdlib.h> #include <stddef.h> #include <stdint.h> @@ -88,7 +89,9 @@ #include <dirent.h> #define _XOPEN_SOURCE /* See feature_test_macros(7) */ +#ifndef __USE_XOPEN #define __USE_XOPEN +#endif #define _GNU_SOURCE #include <time.h> @@ -265,17 +268,23 @@ void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const c l_obj->type = (uint8_t)a_op_code; DAP_DELETE(l_obj->group); l_obj->group = dap_strdup(a_group); - dap_store_obj_pkt_t *l_data_out = dap_store_packet_multiple(l_obj, l_obj->timestamp, 1); + dap_list_t *l_list_out = dap_store_packet_multiple(l_obj, l_obj->timestamp, 1); + // Expect only one element in list + dap_store_obj_pkt_t *l_data_out = (dap_store_obj_pkt_t *)l_list_out->data; dap_store_obj_free(l_obj, 1); dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, "gdb"); dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t) {}; for (dap_list_t *l_tmp = PVT(l_net)->links; l_tmp; l_tmp = dap_list_next(l_tmp)) { dap_chain_node_client_t *l_node_client = (dap_chain_node_client_t *)l_tmp->data; dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id()); - dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, l_net->pub.id, - l_chain_id, l_net->pub.cell_id, l_data_out, sizeof(dap_store_obj_pkt_t) + l_data_out->data_size); + if (!l_ch_chain) { + continue; + } + dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, l_net->pub.id, + l_chain_id, l_net->pub.cell_id, l_data_out, + sizeof(dap_store_obj_pkt_t) + l_data_out->data_size); } - DAP_DELETE(l_data_out); + dap_list_free_full(l_list_out, free); } } @@ -295,6 +304,7 @@ static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, c if (!a_arg) { return; } + dap_chain_node_mempool_autoproc_notify(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); dap_chain_net_sync_gdb_broadcast(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); if (s_srv_callback_notify) { s_srv_callback_notify(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); @@ -321,7 +331,7 @@ static void s_chain_callback_notify(void * a_arg, dap_chain_t *a_chain, dap_chai log_it(L_DEBUG,"Can't get stream_ch for id='%c' ", l_ch_id); continue; } - dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN, l_net->pub.id, + dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN, l_net->pub.id, a_chain->id, a_id, a_atom, a_atom_size); } } @@ -385,10 +395,10 @@ static int s_net_states_proc(dap_chain_net_t * l_net) case NODE_ROLE_ARCHIVE: case NODE_ROLE_CELL_MASTER: { // Add other root nodes as synchronization links - while (dap_list_length(l_pvt_net->links_info) < s_max_links_count) { - int i = rand() % l_pvt_net->seed_aliases_count; + for (int i = 0; i < MIN(s_max_links_count, l_pvt_net->seed_aliases_count); i++) { dap_chain_node_addr_t *l_link_addr = dap_chain_node_alias_find(l_net, l_pvt_net->seed_aliases[i]); - dap_chain_node_info_read(l_net, l_link_addr); + dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(l_net, l_link_addr); + l_pvt_net->links_info = dap_list_append(l_pvt_net->links_info, l_link_node_info); } } break; case NODE_ROLE_FULL: @@ -467,6 +477,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net) l_pvt_net->links = dap_list_remove(l_pvt_net->links, l_node_client); continue; } + dap_stream_worker_t *l_worker = dap_client_get_stream_worker(l_node_client->client); dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; // Get last timestamp in log l_sync_gdb.id_start = (uint64_t) dap_db_log_get_last_id_remote(l_node_client->remote_node_addr.uint64); @@ -480,17 +491,16 @@ static int s_net_states_proc(dap_chain_net_t * l_net) // find dap_chain_id_t dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, "gdb"); dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t ) {}; - - size_t l_res = dap_stream_ch_chain_pkt_write(dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id()), - DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, l_net->pub.id, l_chain_id, - l_net->pub.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); + l_node_client->state = NODE_CLIENT_STATE_CONNECTED; + size_t l_res = dap_stream_ch_chain_pkt_write_mt(l_worker, l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, l_net->pub.id, + l_chain_id, l_net->pub.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); if (l_res == 0) { log_it(L_WARNING, "Can't send GDB sync request"); continue; } // wait for finishing of request - int timeout_ms = 300000; // 5 min = 300 sec = 300 000 ms + int timeout_ms = 30000; // 5 min = 300 sec = 300 000 ms // TODO add progress info to console l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); switch (l_res) { @@ -503,21 +513,19 @@ static int s_net_states_proc(dap_chain_net_t * l_net) default: log_it(L_INFO, "Node sync error %d",l_res); } - if (!dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id())) { - l_res = dap_stream_ch_chain_pkt_write(dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id()), - DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS, l_net->pub.id, l_chain_id, - l_net->pub.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); - l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); - switch (l_res) { - case -1: - log_it(L_WARNING,"Timeout with link sync"); - break; - case 0: - log_it(L_INFO, "Node sync completed"); - break; - default: - log_it(L_INFO, "Node sync error %d",l_res); - } + l_node_client->state = NODE_CLIENT_STATE_CONNECTED; + l_res = dap_stream_ch_chain_pkt_write_mt(l_worker, l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS, l_net->pub.id, + l_chain_id, l_net->pub.cell_id, &l_sync_gdb, sizeof(l_sync_gdb)); + l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); + switch (l_res) { + case -1: + log_it(L_WARNING, "Timeout with reverse link sync"); + break; + case 0: + log_it(L_INFO, "Node reverse sync completed"); + break; + default: + log_it(L_INFO, "Node reverse sync error %d",l_res); } l_tmp = dap_list_next(l_tmp); } @@ -543,52 +551,50 @@ static int s_net_states_proc(dap_chain_net_t * l_net) l_pvt_net->links = dap_list_remove(l_pvt_net->links, l_node_client); continue; } + dap_stream_worker_t *l_worker = dap_client_get_stream_worker(l_node_client->client); dap_chain_t * l_chain = NULL; int l_res = 0; DL_FOREACH (l_net->pub.chains, l_chain) { l_node_client->state = NODE_CLIENT_STATE_CONNECTED; dap_stream_ch_chain_sync_request_t l_request ; memset(&l_request, 0, sizeof (l_request)); - dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, l_net->pub.id, - l_chain->id, l_net->pub.cell_id, &l_request, sizeof(l_request)); + dap_stream_ch_chain_pkt_write_mt(l_worker, l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, l_net->pub.id, + l_chain->id, l_net->pub.cell_id, &l_request, sizeof(l_request)); // wait for finishing of request - int timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms - // TODO add progress info to console - if (dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id())) { - l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); - switch (l_res) { - case -1: - log_it(L_WARNING,"Timeout with sync of chain '%s' ", l_chain->name); - break; - case 0: - l_need_flush = true; - log_it(L_INFO, "Sync of chain '%s' completed ", l_chain->name); - break; - default: - log_it(L_ERROR, "Sync of chain '%s' error %d", l_chain->name,l_res); - } + int timeout_ms = 20000; // 2 min = 120 sec = 120 000 ms + // TODO add progress info to console + l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); + switch (l_res) { + case -1: + log_it(L_WARNING,"Timeout with sync of chain '%s' ", l_chain->name); + break; + case 0: + l_need_flush = true; + log_it(L_INFO, "Sync of chain '%s' completed ", l_chain->name); + break; + default: + log_it(L_ERROR, "Sync of chain '%s' error %d", l_chain->name,l_res); } - if (dap_client_get_stream_ch(l_node_client->client, dap_stream_ch_chain_get_id())) { - dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS_RVRS, l_net->pub.id, - l_chain->id, l_net->pub.cell_id, &l_request, sizeof(l_request)); - l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); - switch (l_res) { - case -1: - log_it(L_WARNING,"Timeout with reverse sync of chain '%s' ", l_chain->name); - break; - case 0: - l_need_flush = true; - log_it(L_INFO, "Reverse sync of chain '%s' completed ", l_chain->name); - // set time of last sync - { - struct timespec l_to; - clock_gettime(CLOCK_MONOTONIC, &l_to); - l_pvt_net->last_sync = l_to.tv_sec; - } - break; - default: - log_it(L_ERROR, "Reverse sync of chain '%s' error %d", l_chain->name,l_res); + l_node_client->state = NODE_CLIENT_STATE_CONNECTED; + dap_stream_ch_chain_pkt_write_mt(l_worker, l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS_RVRS, l_net->pub.id, + l_chain->id, l_net->pub.cell_id, &l_request, sizeof(l_request)); + l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); + switch (l_res) { + case -1: + log_it(L_WARNING,"Timeout with reverse sync of chain '%s' ", l_chain->name); + break; + case 0: + l_need_flush = true; + log_it(L_INFO, "Reverse sync of chain '%s' completed ", l_chain->name); + // set time of last sync + { + struct timespec l_to; + clock_gettime(CLOCK_MONOTONIC, &l_to); + l_pvt_net->last_sync = l_to.tv_sec; } + break; + default: + log_it(L_ERROR, "Reverse sync of chain '%s' error %d", l_chain->name,l_res); } } l_tmp = dap_list_next(l_tmp); @@ -761,8 +767,7 @@ static dap_chain_net_t *s_net_new(const char * a_id, const char * a_name , PVT(ret)->state_proc_cond = CreateEventA( NULL, FALSE, FALSE, NULL ); #endif - // if ( sscanf(a_id,"0x%016lx", &ret->pub.id.uint64 ) == 1 ){ - if ( sscanf(a_id,"0x%016llx", &ret->pub.id.uint64 ) == 1 ){ + if ( sscanf(a_id,"0x%016lx", &ret->pub.id.uint64 ) == 1 ){ if (strcmp (a_node_role, "root_master")==0){ PVT(ret)->node_role.enums = NODE_ROLE_ROOT_MASTER; log_it (L_NOTICE, "Node role \"root master\" selected"); @@ -895,7 +900,7 @@ void dap_chain_net_load_all() } void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){ - const char* l_node_address_text_block = NULL; + char* l_node_address_text_block = NULL; dap_chain_node_addr_t l_cur_node_addr = { 0 }; l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr(a_net) ? dap_chain_net_get_cur_addr(a_net)->uint64 : dap_db_get_cur_node_addr(a_net->pub.name); if(!l_cur_node_addr.uint64) @@ -903,7 +908,7 @@ void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){ else l_node_address_text_block = dap_strdup_printf(", cur node address " NODE_ADDR_FP_STR,NODE_ADDR_FP_ARGS_S(l_cur_node_addr)); - const char* l_sync_current_link_text_block = NULL; + char* l_sync_current_link_text_block = NULL; if(PVT(a_net)->state == NET_STATE_LINKS_PREPARE || PVT(a_net)->state == NET_STATE_LINKS_CONNECTING || PVT(a_net)->state == NET_STATE_SYNC_GDB || @@ -1534,7 +1539,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) else{ l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t); bool parse_succesfully = false; - if ( sscanf(l_node_addr_str, "0x%016llx",&l_node_addr->uint64 ) == 1 ){ + if ( sscanf(l_node_addr_str, "0x%016" DAP_UINT64_FORMAT_x ,&l_node_addr->uint64 ) == 1 ){ log_it(L_DEBUG, "Parse node address with format 0x016llx"); parse_succesfully = true; } @@ -1688,7 +1693,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) char ** l_proc_chains = dap_config_get_array_str(l_cfg,"role-master" , "proc_chains", &l_proc_chains_count ); for ( size_t i = 0; i< l_proc_chains_count ; i++){ dap_chain_id_t l_chain_id = {{0}}; - if(dap_sscanf( l_proc_chains[i], "0x%16lX", &l_chain_id.uint64) ==1 || dap_scanf("0x%16lx", &l_chain_id.uint64) == 1){ + if(dap_sscanf( l_proc_chains[i], "0x%16"DAP_UINT64_FORMAT_X, &l_chain_id.uint64) ==1 || dap_scanf("0x%16"DAP_UINT64_FORMAT_x, &l_chain_id.uint64) == 1){ dap_chain_t * l_chain = dap_chain_find_by_id(l_net->pub.id, l_chain_id ); if ( l_chain ){ l_chain->is_datum_pool_proc = true; diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 749937380ec332edeabf35a7b4b59ca6087787c6..22484d478b6ae9870866abafc8c1b1719b48faba 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -239,53 +239,38 @@ dap_chain_node_info_t* dap_chain_node_info_read( dap_chain_net_t * a_net,dap_cha return node_info; }*/ -int dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t a_role) +bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t a_role, dap_chain_datum_t *a_datum) { - char *l_gdb_group_mempool = NULL; - if (!a_chain) { - return -1; + bool l_need_process = false; + for (uint16_t j = 0; j < a_chain->autoproc_datum_types_count; j++) { + if (a_datum->header.type_id == a_chain->autoproc_datum_types[j]) { + l_need_process = true; + break; + } } - l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(a_chain); - size_t l_objs_size = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool, &l_objs_size); - if (l_objs_size) { - for (size_t i = 0; i < l_objs_size; i++) { - dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; - bool l_need_process = false; - for (uint16_t j = 0; j < a_chain->autoproc_datum_types_count; j++) { - if (l_datum->header.type_id == a_chain->autoproc_datum_types[j]) { - l_need_process = true; - break; - } + if (!l_need_process) + return false; + if (a_datum->header.type_id == DAP_CHAIN_DATUM_TX) { + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)a_datum->data; + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_IN, NULL); + // Is not it a base transaction? + if (l_tx_in && !dap_hash_fast_is_blank(&l_tx_in->header.tx_prev_hash)) { + if (a_role.enums == NODE_ROLE_ROOT) { + return false; } - if (!l_need_process) - continue; - if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) { - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data; - dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_IN, NULL); - // Is not it a base transaction? - if (l_tx_in && !dap_hash_fast_is_blank(&l_tx_in->header.tx_prev_hash)) { - if (a_role.enums == NODE_ROLE_ROOT) { - continue; - } - } - } - if (a_chain->callback_datums_pool_proc(a_chain, &l_datum, 1) != 1) { - continue; - } // Delete processed objects - dap_chain_global_db_gr_del(dap_strdup(l_objs[i].key), l_gdb_group_mempool); } - dap_chain_global_db_objs_delete(l_objs, l_objs_size); } - DAP_DELETE(l_gdb_group_mempool); - return 0; + if (a_chain->callback_datums_pool_proc(a_chain, &a_datum, 1) != 1) { + return false; + } + return true; } -void dap_chain_node_mempool_periodic(void *a_param) +static bool s_mempool_auto = false; + +bool dap_chain_node_mempool_autoproc_init() { - UNUSED(a_param); uint16_t l_net_count; - bool l_mempool_auto; bool l_mempool_auto_default = false; dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count); for (uint16_t i = 0; i < l_net_count; i++) { @@ -299,44 +284,67 @@ void dap_chain_node_mempool_periodic(void *a_param) l_mempool_auto_default = true; break; default: - l_mempool_auto_default = false; + break; } - - l_mempool_auto = dap_config_get_item_bool_default(g_config, "mempool", "auto_proc", l_mempool_auto_default); - if (l_mempool_auto) { + s_mempool_auto = dap_config_get_item_bool_default(g_config, "mempool", "auto_proc", l_mempool_auto_default); + if (s_mempool_auto) { dap_chain_t *l_chain; DL_FOREACH(l_net_list[i]->pub.chains, l_chain) { - dap_chain_node_mempool_process(l_chain, l_role); + if (!l_chain) { + continue; + } + char *l_gdb_group_mempool = NULL; + l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain); + size_t l_objs_size = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group_mempool, &l_objs_size); + if (l_objs_size) { + for (size_t i = 0; i < l_objs_size; i++) { + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; + if (dap_chain_node_mempool_process(l_chain, l_role, l_datum)) { + // Delete processed objects + dap_chain_global_db_gr_del(dap_strdup(l_objs[i].key), l_gdb_group_mempool); + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + DAP_DELETE(l_gdb_group_mempool); } } } DAP_DELETE(l_net_list); + return s_mempool_auto; } -static void *s_mempool_timer = NULL; - /** - * @brief dap_chain_node_mempool_init - * @return + * @brief dap_chain_node_mempool_deinit */ -int dap_chain_node_mempool_init() +void dap_chain_node_mempool_autoproc_deinit() { - s_mempool_timer = dap_interval_timer_create(DAP_CHAIN_NODE_MEMPOOL_INTERVAL, dap_chain_node_mempool_periodic, 0); - if (s_mempool_timer) { - return 0; - } else { - return -1; - } + s_mempool_auto = false; } -/** - * @brief dap_chain_node_mempool_deinit - */ -void dap_chain_node_mempool_deinit() +void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, + const char *a_key, const void *a_value, const size_t a_value_len) { - if (s_mempool_timer) { - dap_interval_timer_delete(s_mempool_timer); - s_mempool_timer = NULL; + UNUSED(a_prefix); + UNUSED(a_value_len); + if (!a_arg || !a_value || !s_mempool_auto || a_op_code != 'a') { + return; + } + dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg; + dap_chain_t *l_chain; + DL_FOREACH(l_net->pub.chains, l_chain) { + if (!l_chain) { + continue; + } + char *l_gdb_group_str = dap_chain_net_get_gdb_group_mempool(l_chain); + if (!strcmp(a_group, l_gdb_group_str)) { + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_value; + dap_chain_node_role_t l_role = dap_chain_net_get_role(l_net); + if (dap_chain_node_mempool_process(l_chain, l_role, l_datum)) { + dap_chain_global_db_gr_del(dap_strdup(a_key), l_gdb_group_str); + } + } + DAP_DELETE(l_gdb_group_str); } } - diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 15eb060d90b8c5b8ade107eeafef3099889df408..6c3f58918094a1439dc9d335ea7d3d682f56caec 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -1098,7 +1098,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) DAP_DELETE(l_remote_node_info); return -1;*/ } - /* if(0 == dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST, + /* if(0 == dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR_REQUEST, l_net->pub.id, l_chain_id_null, l_chain_cell_id_null, &l_sync_request, sizeof(l_sync_request))) { dap_chain_node_cli_set_reply_text(a_str_reply, "Error: Cant send sync chains request"); @@ -1130,7 +1130,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) //l_s_ch_chain->request_cell_id.uint64 = l_chain_cell_id_null.uint64; //memcpy(&l_s_ch_chain->request, &l_sync_request, sizeof(l_sync_request)); - if(0 == dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, + if(0 == dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, l_net->pub.id, l_chain_id_null, l_chain_cell_id_null, &l_sync_request, sizeof(l_sync_request))) { dap_chain_node_cli_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); @@ -1139,7 +1139,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) DAP_DELETE(l_remote_node_info); return -1; } - dap_stream_ch_set_ready_to_write(l_ch_chain, true); + dap_stream_ch_set_ready_to_write_unsafe(l_ch_chain, true); // wait for finishing of request int timeout_ms = 420000; // 7 min = 420 sec = 420 000 ms // TODO add progress info to console @@ -1165,7 +1165,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) l_node_client->state = NODE_CLIENT_STATE_CONNECTED; // send request dap_stream_ch_chain_sync_request_t l_sync_request = { { 0 } }; - if(0 == dap_stream_ch_chain_pkt_write(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, + if(0 == dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, l_net->pub.id, l_chain->id, l_remote_node_info->hdr.cell_id, &l_sync_request, sizeof(l_sync_request))) { dap_chain_node_cli_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); @@ -1176,7 +1176,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) return -3; } log_it(L_NOTICE, "Requested syncronization for chain \"%s\"", l_chain->name); - dap_stream_ch_set_ready_to_write(l_ch_chain, true); + dap_stream_ch_set_ready_to_write_unsafe(l_ch_chain, true); // wait for finishing of request timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms @@ -2001,7 +2001,7 @@ int com_token_decl_sign(int argc, char ** argv, void *arg_func, char ** a_str_re } } -void s_com_mempool_list_print_for_chain(const dap_chain_net_t * a_net, const dap_chain_t * a_chain, dap_string_t * a_str_tmp, const char *a_hash_out_type){ +void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a_chain, dap_string_t * a_str_tmp, const char *a_hash_out_type){ char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(a_chain); if(!l_gdb_group_mempool){ dap_string_append_printf(a_str_tmp, "%s.%s: chain not found\n", a_net->pub.name, a_chain->name); diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index c34c4e7e817e7b5ea945fdadd717d4e4b9c8a01a..7838fc19203efa50aca9f8872f2f8f8d41a798e5 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -94,15 +94,14 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, dap_tx_data_t *l_tx_data_hash = NULL; // load transactions dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain); - dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter); - size_t l_atom_size = a_chain->callback_atom_get_size(l_atom); + size_t l_atom_size = 0; + dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); while(l_atom && l_atom_size) { dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_atom; if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { // go to next transaction - l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); - l_atom_size = a_chain->callback_atom_get_size(l_atom); + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); continue; } dap_tx_data_t *l_tx_data = NULL; @@ -181,8 +180,7 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, // search tx with a_tx_hash if(!dap_hash_fast_compare(a_tx_hash, &l_tx_hash)) { // go to next transaction - l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); - l_atom_size = a_chain->callback_atom_get_size(l_atom); + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); continue; } // found a_tx_hash now @@ -200,7 +198,7 @@ char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, dap_chain_t * a_chain, l_list_tmp = l_list_out_items; while(l_list_tmp) { const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; - dap_tx_data_t *l_tx_data_prev = NULL; + //dap_tx_data_t *l_tx_data_prev = NULL; const char *l_token_str = NULL; if(l_tx_data) @@ -311,18 +309,18 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons dap_tx_data_t *l_tx_data_hash = NULL; // load transactions dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain); - dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter); + size_t l_atom_size=0; + dap_chain_atom_ptr_t *l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); if (!l_atom) { return NULL; } - size_t l_atom_size = a_chain->callback_atom_get_size(l_atom); while(l_atom && l_atom_size) { - dap_chain_datum_t *l_datum = a_chain->callback_atom_get_datum ? a_chain->callback_atom_get_datum(l_atom) : (dap_chain_datum_t*)l_atom; + dap_chain_datum_t *l_datum = a_chain->callback_atom_get_datum ? a_chain->callback_atom_get_datum(l_atom, l_atom_size) : + (dap_chain_datum_t*)l_atom; if(!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX) { // go to next transaction - l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); - l_atom_size = a_chain->callback_atom_get_size(l_atom); + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); continue; } // transaction @@ -656,8 +654,7 @@ char* dap_db_history_addr(dap_chain_addr_t * a_addr, dap_chain_t * a_chain, cons DAP_DELETE(l_time_str); // go to next transaction - l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter); - l_atom_size = l_atom ? a_chain->callback_atom_get_size(l_atom) : 0; + l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); } // delete hashes diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 598041a8475773de9ddbb42254ca7bfdd6619c5a..ce8848a5b700b483664c4b38b216606b78721546 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -50,6 +50,7 @@ #include "dap_chain_global_db_remote.h" #include "dap_chain_global_db_hist.h" #include "dap_chain_net_srv_common.h" +#include "dap_stream_worker.h" #include "dap_stream_ch_pkt.h" #include "dap_stream_ch_chain.h" #include "dap_stream_ch_chain_pkt.h" @@ -126,6 +127,7 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg) SetEvent( l_node_client->wait_cond ); #endif pthread_mutex_unlock(&l_node_client->wait_mutex); + return; } if(l_node_client && l_node_client->keep_connection && @@ -273,127 +275,19 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha l_request = (dap_stream_ch_chain_sync_request_t*) a_pkt->data; if(l_request) { - uint64_t l_id_last_here = 1; - // for sync chain not used time - //if(a_pkt_type != DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS) - // l_id_last_here =(uint64_t) dap_db_log_get_last_id(); - if(1) {//if(l_request->id_start < l_id_last_here) { - log_it(L_INFO, "Remote is synced but we have updates for it"); - bool l_is_sync = true; - // Get log diff - if(a_pkt_type == DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB) { - a_ch_chain->request_last_ts = dap_db_log_get_last_id(); - uint64_t l_start_item = l_request->id_start; - dap_db_log_list_t *l_db_log = NULL; - // If the current global_db has been truncated, but the remote node has not known this - uint64_t l_last_id = dap_db_log_get_last_id(); - if(l_request->id_start > a_ch_chain->request_last_ts){ - dap_chain_net_t *l_net = dap_chain_net_by_id(a_pkt->hdr.net_id); - dap_list_t *l_add_groups = dap_chain_net_get_add_gdb_group(l_net, a_ch_chain->request.node_addr); - l_db_log = dap_db_log_list_start(l_start_item + 1, l_add_groups); - if(!l_db_log) - l_start_item = 0; - } - //dap_list_t *l_list = dap_db_log_get_list(l_request->id_start + 1); - if(!l_db_log){ - dap_chain_net_t *l_net = dap_chain_net_by_id(a_pkt->hdr.net_id); - dap_list_t *l_add_groups = dap_chain_net_get_add_gdb_group(l_net, a_ch_chain->request.node_addr); - l_db_log = dap_db_log_list_start(l_start_item + 1, l_add_groups); - } - if(l_db_log) { - // Add it to outgoing list - //l_list->prev = a_ch_chain->request_global_db_trs; - a_ch_chain->request_global_db_trs = l_db_log;//l_list; - } - else - l_is_sync = false; - } - if(l_is_sync) { - a_ch_chain->request_net_id.uint64 = a_pkt->hdr.net_id.uint64; - a_ch_chain->request_cell_id.uint64 = a_pkt->hdr.cell_id.uint64; - a_ch_chain->request_chain_id.uint64 = a_pkt->hdr.chain_id.uint64; - a_ch_chain->state = dap_stream_ch_chain_pkt_type_to_dap_stream_ch_chain_state(a_pkt_type);//CHAIN_STATE_SYNC_CHAINS;//GLOBAL_DB; - - // type of first packet - uint8_t l_type = - (a_pkt_type != DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS) ? - DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB : - DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN; - if(l_type == DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN) - { - dap_chain_t * l_chain = dap_chain_find_by_id(a_pkt->hdr.net_id, a_pkt->hdr.chain_id); - if (l_chain ){ - dap_chain_atom_iter_t* l_iter = l_chain ? l_chain->callback_atom_iter_create(l_chain) : NULL; - if ( l_iter ){ - //a_ch_chain->request_atom_iter = l_iter; - - dap_chain_atom_ptr_t * l_lasts = NULL; - size_t l_lasts_size = 0; - l_lasts = l_chain->callback_atom_iter_get_lasts(l_iter, &l_lasts_size); - if ( l_lasts){ - for(size_t i = 0; i < l_lasts_size; i++) { - dap_chain_atom_item_t * l_item = NULL; - dap_chain_hash_fast_t l_atom_hash; - dap_hash_fast(l_lasts[i], l_chain->callback_atom_get_size(l_lasts[i]), &l_atom_hash); - pthread_mutex_lock(&a_ch_chain->mutex); - HASH_FIND(hh, a_ch_chain->request_atoms_lasts, &l_atom_hash, sizeof(l_atom_hash), l_item); - if(l_item == NULL) { // Not found, add new lasts - l_item = DAP_NEW_Z(dap_chain_atom_item_t); - l_item->atom = l_lasts[i]; - memcpy(&l_item->atom_hash, &l_atom_hash, sizeof(l_atom_hash)); - HASH_ADD(hh, a_ch_chain->request_atoms_lasts, atom_hash, sizeof(l_atom_hash), l_item); - } - //else - // DAP_DELETE(l_lasts[i]); - pthread_mutex_unlock(&a_ch_chain->mutex); - } - DAP_DELETE(l_lasts); - } - DAP_DELETE(l_iter); - }else{ - log_it(L_ERROR, "Can't create iterator for chain_id 0x%016X", a_pkt->hdr.chain_id ); - } - }else { - log_it(L_WARNING, "Can't find chain_id 0x%016X", a_pkt->hdr.chain_id ); - } - } - dap_chain_node_addr_t l_node_addr = { 0 }; - dap_chain_net_t *l_net = dap_chain_net_by_id(a_ch_chain->request_net_id); - l_node_addr.uint64 = l_net ? dap_db_get_cur_node_addr(l_net->pub.name) : 0; - dap_stream_ch_chain_pkt_write(a_ch_chain->ch, l_type, - a_ch_chain->request_net_id, a_ch_chain->request_chain_id, - a_ch_chain->request_cell_id, &l_node_addr, sizeof(dap_chain_node_addr_t)); - - log_it(L_INFO, "Sync for remote tr type=%d", a_pkt_type);//_count=%d", dap_list_length(l_list)); - dap_stream_ch_set_ready_to_write(a_ch_chain->ch, true); - } - else { - log_it(L_INFO, "Remote node has lastes timestamp for us type=%d", a_pkt_type); - pthread_mutex_lock(&l_node_client->wait_mutex); - l_node_client->state = NODE_CLIENT_STATE_SYNCED; -#ifndef _WIN32 - pthread_cond_signal(&l_node_client->wait_cond); -#else - SetEvent( l_node_client->wait_cond ); -#endif - pthread_mutex_unlock(&l_node_client->wait_mutex); - } - } - } else { - log_it(L_INFO, "Sync notify without request to sync back, stay in SYNCED state"); - pthread_mutex_lock(&l_node_client->wait_mutex); - l_node_client->state = NODE_CLIENT_STATE_SYNCED; + // Process it if need + } + log_it(L_INFO, "Sync notify without request to sync back, stay in SYNCED state"); + pthread_mutex_lock(&l_node_client->wait_mutex); + l_node_client->state = NODE_CLIENT_STATE_SYNCED; #ifndef _WIN32 - pthread_cond_signal(&l_node_client->wait_cond); + pthread_cond_signal(&l_node_client->wait_cond); #else - SetEvent( l_node_client->wait_cond ); + SetEvent( l_node_client->wait_cond ); #endif - pthread_mutex_unlock(&l_node_client->wait_mutex); - } - - } - default: { + pthread_mutex_unlock(&l_node_client->wait_mutex); } + default: break; } } @@ -492,7 +386,7 @@ static void s_ch_chain_callback_notify_packet_R(dap_stream_ch_chain_net_srv_t* a switch (a_pkt_type) { // get new generated current node address case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: { - dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_request_t *) a_pkt->data; + dap_stream_ch_chain_net_srv_pkt_test_t *l_request = (dap_stream_ch_chain_net_srv_pkt_test_t *) a_pkt->data; size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); if(a_pkt->hdr.size != l_request_size) { log_it(L_WARNING, "Wrong request size, less or more than required"); @@ -622,13 +516,11 @@ int dap_chain_node_client_send_ch_pkt(dap_chain_node_client_t *a_client, uint8_t if(!a_client || a_client->state < NODE_CLIENT_STATE_CONNECTED) return -1; -// dap_stream_t *l_stream = dap_client_get_stream(a_client->client); + dap_stream_worker_t *l_stream_worker = dap_client_get_stream_worker(a_client->client); dap_stream_ch_t * l_ch = dap_client_get_stream_ch(a_client->client, a_ch_id); if(l_ch) { // dap_stream_ch_chain_net_t * l_ch_chain = DAP_STREAM_CH_CHAIN_NET(l_ch); - - dap_stream_ch_pkt_write(l_ch, a_type, a_pkt_data, a_pkt_data_size); - dap_stream_ch_set_ready_to_write(l_ch, true); + dap_stream_ch_pkt_write_mt(l_stream_worker , l_ch , a_type, a_pkt_data, a_pkt_data_size); return 0; } else return -1; diff --git a/modules/net/dap_chain_node_ping.c b/modules/net/dap_chain_node_ping.c index 72c9c0978737881e89c6ee29244a295fcca4b17c..67ab55b30619a724a521050cb7a782deaebb7e17 100644 --- a/modules/net/dap_chain_node_ping.c +++ b/modules/net/dap_chain_node_ping.c @@ -24,7 +24,8 @@ //#include <sys/socket.h> #include <time.h> #include <errno.h> -#define _GNU_SOURCE /* See feature_test_macros(7) */ +#define _GNU_SOURCE +#define __USE_GNU /* See feature_test_macros(7) */ #include <pthread.h> #include "dap_common.h" diff --git a/modules/net/dap_dns_server.c b/modules/net/dap_dns_server.c index 1f000b8a45d37d92528cba78e1f2f4ca0f9e62f3..8c6907d31e1d1cfe2dfce67005a5db4309669fc7 100644 --- a/modules/net/dap_dns_server.c +++ b/modules/net/dap_dns_server.c @@ -26,7 +26,7 @@ #include "dap_dns_server.h" #include "dap_udp_server.h" #include "dap_udp_client.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_common.h" #include "dap_chain_net.h" #include "dap_chain_node.h" @@ -191,7 +191,7 @@ dap_dns_zone_callback_t dap_dns_zone_find(char *hostname) { * @param arg Unused * @return none */ -void dap_dns_client_read(dap_client_remote_t *client, void * arg) { +void dap_dns_client_read(dap_events_socket_t *client, void * arg) { UNUSED(arg); if (client->buf_in_size < DNS_HEADER_SIZE) { // Bad request return; @@ -200,7 +200,7 @@ void dap_dns_client_read(dap_client_remote_t *client, void * arg) { dap_dns_buf_t *dns_reply = DAP_NEW(dap_dns_buf_t); dns_message->data = DAP_NEW_SIZE(char, client->buf_in_size + 1); dns_message->data[client->buf_in_size] = 0; - dap_client_remote_read(client, dns_message->data, client->buf_in_size); + dap_events_socket_pop_from_buf_in(client, dns_message->data, client->buf_in_size); dns_message->ptr = 0; // Parse incoming DNS message @@ -332,8 +332,8 @@ void dap_dns_client_read(dap_client_remote_t *client, void * arg) { dns_reply->data[2] = msg_flags.val >> 8; dns_reply->data[3] = msg_flags.val; // Send DNS reply - dap_udp_client_write(client, dns_reply->data, dns_reply->ptr); - dap_udp_client_ready_to_write(client, true); + dap_events_socket_write_unsafe( client, dns_reply->data, dns_reply->ptr); + dap_events_socket_set_writable_unsafe( client, true); dap_string_free(dns_hostname, true); cleanup: DAP_DELETE(dns_reply->data); @@ -351,10 +351,10 @@ void dap_dns_server_start() { log_it(L_ERROR, "Can't start DNS server"); return; } - s_dns_server->instance->client_read_callback = dap_dns_client_read; - s_dns_server->instance->client_write_callback = NULL; - s_dns_server->instance->client_new_callback = NULL; - s_dns_server->instance->client_delete_callback = NULL; + s_dns_server->instance->client_callbacks.read_callback = dap_dns_client_read; + s_dns_server->instance->client_callbacks.write_callback = NULL; + s_dns_server->instance->client_callbacks.new_callback = NULL; + s_dns_server->instance->client_callbacks.delete_callback = NULL; dap_dns_zone_register(&s_root_alias[0], dap_dns_resolve_hostname); // root resolver pthread_create(&s_dns_server->udp_thread, NULL, (void *)dap_udp_server_loop, s_dns_server->instance); } diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index 78931e2864782a8b0b015598f505bda2635dc3b0..0277aefb71f3b59b11f3e64c2ad20cb77556bdd0 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -141,6 +141,8 @@ inline static char* dap_chain_node_addr_to_hash_str(dap_chain_node_addr_t *addre return a_key; } -int dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t a_role); -int dap_chain_node_mempool_init(); -void dap_chain_node_mempool_deinit(); +bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t a_role, dap_chain_datum_t *a_datum); +bool dap_chain_node_mempool_autoproc_init(); +void dap_chain_node_mempool_autoproc_deinit(); +void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, + const char *a_key, const void *a_value, const size_t a_value_len); diff --git a/modules/net/srv/dap_chain_net_srv_client.c b/modules/net/srv/dap_chain_net_srv_client.c index c9f43454f35b06cfe2e9e6b5e58bb4337d21ae66..595a2802107b989c6d0c02a0a9c5a4d27b07934e 100644 --- a/modules/net/srv/dap_chain_net_srv_client.c +++ b/modules/net/srv/dap_chain_net_srv_client.c @@ -42,7 +42,7 @@ int dap_chain_net_srv_client_init(dap_chain_net_srv_uid_t a_uid, dap_chain_net_srv_callback_data_t a_callback_response_error, dap_chain_net_srv_callback_data_t a_callback_receipt_next_success, dap_chain_net_srv_callback_data_t a_callback_client_success, - dap_chain_net_srv_callback_data_t a_callback_client_sign_request, + dap_chain_net_srv_callback_sign_request_t a_callback_client_sign_request, void *a_inhertor) { dap_chain_net_srv_t *l_srv_custom = dap_chain_net_srv_get(a_uid); diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 948ec9a6d09a74172d4f099fd38fac44fb9d430a..8aba700a30215b038b580b8d0ee49744bd6684e3 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -514,10 +514,9 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len) { - (void) a_op_code; UNUSED(a_prefix); UNUSED(a_value_len); - if (!a_arg || !a_value || !dap_config_get_item_bool_default(g_config, "srv", "order_signed_only", false)) { + if (!a_arg || !a_value || a_op_code != 'a' || !dap_config_get_item_bool_default(g_config, "srv", "order_signed_only", false)) { return; } dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg; diff --git a/modules/net/srv/dap_chain_net_srv_stream_session.c b/modules/net/srv/dap_chain_net_srv_stream_session.c index f5f1517b0e884fc9ccb8dd4f6cc3e5c927a08d7b..d5a20c27358fd4bc42af90c283ecc85aa18d4c37 100644 --- a/modules/net/srv/dap_chain_net_srv_stream_session.c +++ b/modules/net/srv/dap_chain_net_srv_stream_session.c @@ -86,8 +86,8 @@ void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_ { if ( a_usage->receipt ) DAP_DELETE( a_usage->receipt ); - if ( a_usage->clients ){ - for (dap_chain_net_srv_client_t * l_srv_client = a_usage->clients, * tmp = NULL; l_srv_client; ){ + if ( a_usage->client ){ + for (dap_chain_net_srv_client_t * l_srv_client = a_usage->client, * tmp = NULL; l_srv_client; ){ tmp = l_srv_client; l_srv_client = l_srv_client->next; DAP_DELETE( tmp); @@ -107,12 +107,10 @@ void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_ * @param a_usage_id * @return */ -dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find (dap_chain_net_srv_stream_session_t * a_srv_session, +dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find_unsafe (dap_chain_net_srv_stream_session_t * a_srv_session, uint32_t a_usage_id) { dap_chain_net_srv_usage_t * l_ret = NULL; - pthread_mutex_lock(&a_srv_session->parent->mutex); HASH_FIND_INT(a_srv_session->usages, &a_usage_id, l_ret); - pthread_mutex_unlock(&a_srv_session->parent->mutex); return l_ret; } diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h index 4673bff67e3f8f40ad79a4e242221446feb59792..c7de7e8f0c988d173597e837c08dffc02c2ad979 100755 --- a/modules/net/srv/include/dap_chain_net_srv.h +++ b/modules/net/srv/include/dap_chain_net_srv.h @@ -33,6 +33,7 @@ typedef struct dap_chain_net_srv dap_chain_net_srv_t; typedef void (*dap_chain_net_srv_callback_t)(dap_chain_net_srv_t *, dap_chain_net_srv_client_t *); typedef int (*dap_chain_net_srv_callback_data_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_t *, const void *, size_t ); +typedef int (*dap_chain_net_srv_callback_sign_request_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_t *, dap_chain_datum_tx_receipt_t **, size_t ); typedef void (*dap_chain_net_srv_callback_ch_t)(dap_chain_net_srv_t *, dap_stream_ch_t *); typedef struct dap_chain_net_srv @@ -63,7 +64,7 @@ typedef struct dap_chain_net_srv // Client have to start service dap_chain_net_srv_callback_data_t callback_client_success; // Client have to sign receipt - dap_chain_net_srv_callback_data_t callback_client_sign_request; + dap_chain_net_srv_callback_sign_request_t callback_client_sign_request; // Pointer to inheritor object void * _inhertor; @@ -108,5 +109,5 @@ int dap_chain_net_srv_client_init(dap_chain_net_srv_uid_t a_uid, dap_chain_net_srv_callback_data_t a_callback_response_error, dap_chain_net_srv_callback_data_t a_callback_receipt_next_success, dap_chain_net_srv_callback_data_t a_callback_client_success, - dap_chain_net_srv_callback_data_t a_callback_client_sign_request, + dap_chain_net_srv_callback_sign_request_t a_callback_client_sign_request, void *a_inhertor); diff --git a/modules/net/srv/include/dap_chain_net_srv_client.h b/modules/net/srv/include/dap_chain_net_srv_client.h index d25801c9cfd3d9c06da8269fc9efc1c347074693..724fbccf13e700285620574f3c73da2902fe8e3d 100644 --- a/modules/net/srv/include/dap_chain_net_srv_client.h +++ b/modules/net/srv/include/dap_chain_net_srv_client.h @@ -27,14 +27,19 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include <time.h> +#include "dap_enc_key.h" +#include "dap_stream_session.h" +#include "dap_stream_worker.h" #include "dap_chain_net_srv_common.h" #include "dap_chain_net_remote.h" typedef struct dap_chain_net_srv_client { + dap_stream_ch_t * ch; // Use ONLY in own context, not thread-safe time_t ts_created; - dap_stream_ch_t *ch; // For direct connections + dap_stream_worker_t * stream_worker; + int session_id; dap_chain_net_remote_t *net_remote; // For remotes uint64_t bytes_received; uint64_t bytes_sent; diff --git a/modules/net/srv/include/dap_chain_net_srv_common.h b/modules/net/srv/include/dap_chain_net_srv_common.h index d45ace6791a839ce7019b8b642c7de519b4fc737..d4141c574611305fc4eab2795fd847ef890c03f1 100755 --- a/modules/net/srv/include/dap_chain_net_srv_common.h +++ b/modules/net/srv/include/dap_chain_net_srv_common.h @@ -73,7 +73,7 @@ typedef struct dap_chain_net_srv_abstract char decription[128]; }DAP_ALIGN_PACKED dap_chain_net_srv_abstract_t; -typedef void (*dap_chain_callback_trafic_t)(dap_client_remote_t *, dap_stream_ch_t *); +typedef void (*dap_chain_callback_trafic_t)(dap_events_socket_t *, dap_stream_ch_t *); typedef struct dap_chain_net_srv_price { diff --git a/modules/net/srv/include/dap_chain_net_srv_stream_session.h b/modules/net/srv/include/dap_chain_net_srv_stream_session.h index 29c506e8ebf04197184a34d2e42f0b2edf74be42..a47a16c9bc76a751b3c50319430cc69926b5dded 100644 --- a/modules/net/srv/include/dap_chain_net_srv_stream_session.h +++ b/modules/net/srv/include/dap_chain_net_srv_stream_session.h @@ -50,7 +50,7 @@ typedef struct dap_chain_net_srv_usage{ dap_chain_net_srv_price_t * price; // Price for issue next receipt size_t receipt_size; size_t receipt_next_size; - dap_chain_net_srv_client_t * clients; + dap_chain_net_srv_client_t * client; dap_chain_datum_tx_t * tx_cond; dap_chain_hash_fast_t tx_cond_hash; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; @@ -61,15 +61,30 @@ typedef struct dap_chain_net_srv_usage{ typedef void (*dap_response_success_callback_t) (dap_stream_ch_chain_net_srv_pkt_success_t*, void*); +typedef struct dap_net_stats{ + uintmax_t bytes_sent; + uintmax_t bytes_recv; + uintmax_t bytes_sent_lost; + uintmax_t bytes_recv_lost; + + uintmax_t packets_sent; + uintmax_t packets_recv; + uintmax_t packets_sent_lost; + intmax_t packets_recv_lost; +} dap_net_stats_t; + typedef struct dap_chain_net_srv_stream_session { dap_stream_session_t * parent; dap_chain_net_srv_usage_t * usages; dap_chain_net_srv_usage_t * usage_active; - uint128_t limits_bytes; // Bytes left + uintmax_t limits_bytes; // Bytes left time_t limits_ts; // Timestamp until its activte dap_chain_net_srv_price_unit_uid_t limits_units_type; + // Some common stats + volatile dap_net_stats_t stats; + time_t ts_activated; dap_sign_t* user_sign; // User's signature for auth if reconnect @@ -85,5 +100,5 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream dap_chain_net_t * a_net, dap_chain_net_srv_t * a_srv); void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session, dap_chain_net_srv_usage_t* a_usage); -dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find (dap_chain_net_srv_stream_session_t * a_srv_session, +dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find_unsafe (dap_chain_net_srv_stream_session_t * a_srv_session, uint32_t a_usage_id); diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c index 77f964178c05dce2c2c742a98c8022ee838aab86..58405ee7720603a91d3c5f580eb47eed537d7ed8 100644 --- a/modules/service/stake/dap_chain_net_srv_stake.c +++ b/modules/service/stake/dap_chain_net_srv_stake.c @@ -24,6 +24,7 @@ #include <math.h> #include "dap_string.h" +#include "dap_enc_base58.h" #include "dap_chain_common.h" #include "dap_chain_node_cli.h" #include "dap_chain_mempool.h" diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index d6e5d5b305ceb7172d3babb326dab09ee94e36aa..aaf563d863221a664b0a72364784bf60975043ec 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -53,7 +53,7 @@ #include "dap_strfuncs.h" #include "dap_config.h" -#include "dap_client_remote.h" +#include "dap_events_socket.h" #include "dap_http_client.h" #include "dap_stream.h" @@ -74,58 +74,73 @@ #define LOG_TAG "dap_chain_net_srv_vpn" -#define DAP_TUN_IN_WORKER - #define SF_MAX_EVENTS 256 -typedef struct usage_client { - pthread_rwlock_t rwlock; - dap_chain_net_srv_ch_vpn_t * ch_vpn; - dap_chain_net_srv_client_t *net_srv_client; - dap_chain_datum_tx_receipt_t * receipt; - size_t receipt_size; - uint32_t usage_id; - dap_chain_net_srv_t * srv; - UT_hash_handle hh; -} usage_client_t; - - typedef struct vpn_local_network { struct in_addr ipv4_lease_last; struct in_addr ipv4_network_mask; - struct in_addr ipv4_host; struct in_addr ipv4_network_addr; + struct in_addr ipv4_gw; int tun_ctl_fd; int tun_fd; struct ifreq ifr; + bool auto_cpu_reassignment; -#ifdef DAP_TUN_IN_WORKER - dap_events_socket_t * tun_events_socket; -#endif ch_vpn_pkt_t * pkt_out[400]; size_t pkt_out_size; size_t pkt_out_rindex; size_t pkt_out_windex; pthread_mutex_t pkt_out_mutex; - + pthread_rwlock_t rwlock; } vpn_local_network_t; +// Message for QUEUE_PTR operations +struct tun_socket_msg{ + enum{ + TUN_SOCKET_MSG_IP_ASSIGNED, + TUN_SOCKET_MSG_IP_UNASSIGNED, + TUN_SOCKET_MSG_CH_VPN_SEND, + TUN_SOCKET_MSG_ESOCKET_REASSIGNED, + TUN_SOCKET_MSG_NONE + } type; + dap_chain_net_srv_ch_vpn_t * ch_vpn; + dap_events_socket_t * esocket; + bool is_reassigned_once; + union{ + struct{ // Esocket reassigment + uint32_t worker_id; + struct in_addr addr; + } esocket_reassigment; + struct{ // IP assign/unassign + uint32_t worker_id; + struct in_addr addr; + uint32_t usage_id; + } ip_assigment; + struct{ // IP assign/unassign + uint32_t worker_id; + struct in_addr addr; + } ip_unassigment; + struct{ // CH VPN send operation + ch_vpn_pkt_t * pkt; + } ch_vpn_send; + }; +}; + + +ch_sf_tun_socket_t ** s_tun_sockets = NULL; +dap_events_socket_t ** s_tun_sockets_queue_msg = NULL; +uint32_t s_tun_sockets_count = 0; +bool s_debug_more = false; + static usage_client_t * s_clients; static dap_chain_net_srv_ch_vpn_t * s_ch_vpn_addrs ; static pthread_rwlock_t s_clients_rwlock = PTHREAD_RWLOCK_INITIALIZER; -static ch_vpn_socket_proxy_t * sf_socks = NULL; -static ch_vpn_socket_proxy_t * sf_socks_client = NULL; static pthread_mutex_t s_sf_socks_mutex; static pthread_cond_t s_sf_socks_cond; -static int sf_socks_epoll_fd; -static pthread_t srv_sf_socks_pid; -static pthread_t srv_sf_socks_raw_pid; static vpn_local_network_t *s_raw_server; static pthread_rwlock_t s_raw_server_rwlock = PTHREAD_RWLOCK_INITIALIZER; -static const char *s_addr; - // Service callbacks static int s_callback_requested(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_t * a_srv_client , const void * a_custom_data, size_t a_custom_data_size ); @@ -138,16 +153,9 @@ static int s_callback_receipt_next_success(dap_chain_net_srv_t * a_srv, uint32_t const void * a_receipt_next, size_t a_receipt_next_size); -// Tunnel threads -static void *srv_ch_sf_thread(void * a_arg); -static void *srv_ch_sf_thread_raw(void *arg); -static void s_tun_create(void); -static void s_tun_destroy(void); - - // Stream callbacks -static void s_new(dap_stream_ch_t* ch, void* arg); -static void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg); +static void s_ch_vpn_new(dap_stream_ch_t* ch, void* arg); +static void s_ch_vpn_delete(dap_stream_ch_t* ch, void* arg); static void s_ch_packet_in(dap_stream_ch_t* ch, void* a_arg); static void s_ch_packet_out(dap_stream_ch_t* ch, void* arg); @@ -160,55 +168,329 @@ static void s_update_limits(dap_stream_ch_t * a_ch , dap_chain_net_srv_stream_session_t * a_srv_session, dap_chain_net_srv_usage_t * a_usage, size_t a_bytes); -#ifdef DAP_TUN_IN_WORKER +static void m_es_tun_new(dap_events_socket_t * a_es, void * arg); static void m_es_tun_delete(dap_events_socket_t * a_es, void * arg); static void m_es_tun_read(dap_events_socket_t * a_es, void * arg); -static void m_es_tun_error(dap_events_socket_t * a_es, void * arg); +static void m_es_tun_error(dap_events_socket_t * a_es,int arg); + +static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void * a_msg ); +static void s_tun_send_msg_ip_assigned(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); +static void s_tun_send_msg_ip_assigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); +static void s_tun_send_msg_ip_unassigned(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); +static void s_tun_send_msg_ip_unassigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); + +static int s_tun_deattach_queue(int fd); +static int s_tun_attach_queue(int fd); + -bool is_dap_tun_in_worker(void) +static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * a_ch_vpn_info, const void * a_data, size_t a_data_size); +static size_t s_stream_session_esocket_send(dap_chain_net_srv_stream_session_t * l_srv_session, dap_events_socket_t * l_es, const void * a_data, size_t a_data_size ); +static bool s_tun_client_send_data_unsafe(dap_chain_net_srv_ch_vpn_t * l_ch_vpn, ch_vpn_pkt_t * l_pkt_out); + + +static bool s_tun_client_send_data_unsafe(dap_chain_net_srv_ch_vpn_t * l_ch_vpn, ch_vpn_pkt_t * l_pkt_out) { -#ifdef DAP_TUN_IN_WORKER + dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (l_ch_vpn->ch->stream->session ); + dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_ch_vpn->usage_id); + + size_t l_data_to_send = (l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); + size_t l_data_sent = dap_stream_ch_pkt_write_unsafe(l_ch_vpn->ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, l_pkt_out, l_data_to_send); + s_update_limits(l_ch_vpn->ch,l_srv_session,l_usage, l_data_sent ); + if ( l_data_sent < l_data_to_send){ + log_it(L_WARNING, "Wasn't sent all the data in tunnel (%zd was sent from %zd): probably buffer overflow", l_data_sent, l_data_to_send); + l_srv_session->stats.bytes_recv_lost += l_data_to_send - l_data_sent; + l_srv_session->stats.packets_recv_lost++; + return false; + }else{ + l_srv_session->stats.bytes_recv += l_data_sent; + l_srv_session->stats.packets_recv++; + return true; + } +} + +static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_info, const void * a_data, size_t a_data_size) +{ + assert(a_data_size > sizeof (struct iphdr)); + ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, sizeof(l_pkt_out->header) + a_data_size); + l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; + l_pkt_out->header.sock_id = s_raw_server->tun_fd; + l_pkt_out->header.usage_id = l_ch_vpn_info->usage_id; + l_pkt_out->header.op_data.data_size = a_data_size; + memcpy(l_pkt_out->data, a_data, a_data_size); + + struct in_addr l_in_daddr; + l_in_daddr.s_addr = ((struct iphdr* ) l_pkt_out->data)->daddr; + + if(l_ch_vpn_info->is_on_this_worker){ + if( dap_events_socket_check_unsafe(l_ch_vpn_info->worker, l_ch_vpn_info->esocket ) ){ + if(s_debug_more){ + char l_str_daddr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET,&l_in_daddr,l_str_daddr,sizeof (l_in_daddr)); + log_it(L_DEBUG, "Sent packet size %zd for desitnation in own context", a_data_size); + } + + s_tun_client_send_data_unsafe(l_ch_vpn_info->ch_vpn,l_pkt_out); + DAP_DELETE(l_pkt_out); + }else{ + log_it(L_WARNING, "Was no esocket %p on worker #%u, lost %zd data",l_ch_vpn_info->esocket, l_ch_vpn_info->worker->id,a_data_size ); + DAP_DELETE(l_pkt_out); + return false; + } + + }else{ + struct tun_socket_msg * l_msg= DAP_NEW_Z(struct tun_socket_msg); + l_msg->type = TUN_SOCKET_MSG_CH_VPN_SEND; + l_msg->ch_vpn = l_ch_vpn_info->ch_vpn; + l_msg->esocket = l_ch_vpn_info->esocket; + l_msg->ch_vpn_send.pkt = l_pkt_out; + if (dap_events_socket_queue_ptr_send(l_ch_vpn_info->queue_msg, l_msg) != 0 ){ + log_it(L_WARNING, "Lost %zd data send in tunnel send operation in alien context: queue is overfilled?",a_data_size ); + DAP_DELETE(l_msg); + DAP_DELETE(l_pkt_out); + return false; + } + if(s_debug_more){ + char l_str_daddr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET,&l_in_daddr,l_str_daddr,sizeof (l_in_daddr)); + log_it(L_INFO, "Sent packet for desitnation %zd between contexts",a_data_size); + } + + } return true; -#else - return false; -#endif } -//TODO: create .new_callback for event sockets -int s_tun_event_stream_create() +/** + * @brief s_tun_recv_msg_callback + * @param a_esocket_queue + * @param a_msg + */ +static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void * a_msg ) +{ + struct tun_socket_msg * l_msg = (struct tun_socket_msg*) a_msg; + switch (l_msg->type) { + case TUN_SOCKET_MSG_ESOCKET_REASSIGNED:{ + assert(l_msg->esocket_reassigment.worker_id < s_tun_sockets_count); + ch_sf_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + assert(l_tun_sock); + + dap_chain_net_srv_ch_vpn_info_t * l_info = NULL; + HASH_FIND(hh,l_tun_sock->clients,&l_msg->esocket_reassigment.addr , sizeof (l_msg->esocket_reassigment.addr), l_info); + if (l_info){ // Updating info + l_info->worker = dap_events_worker_get(l_msg->esocket_reassigment.worker_id); + l_info->queue_msg = s_tun_sockets_queue_msg[l_msg->esocket_reassigment.worker_id]; + l_info->is_reassigned_once = true; + l_info->is_on_this_worker =(a_esocket_queue->worker->id == l_msg->esocket_reassigment.worker_id); + }else{ + if(dap_log_level_get() <= L_INFO){ + char l_addrbuf[17]; + inet_ntop(AF_INET,&l_msg->esocket_reassigment.addr, l_addrbuf, sizeof (l_addrbuf)); + log_it(L_INFO,"Reassigment message for address %s on worker %u comes but no such address was found on tun socket %u", + l_addrbuf, l_msg->esocket_reassigment.worker_id, + a_esocket_queue->worker->id); + } + } + } break; + case TUN_SOCKET_MSG_IP_ASSIGNED:{ + assert(l_msg->ip_assigment.worker_id < s_tun_sockets_count); + ch_sf_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + assert(l_tun_sock); + + dap_chain_net_srv_ch_vpn_info_t * l_new_info = NULL; + HASH_FIND(hh,l_tun_sock->clients,&l_msg->ip_assigment.addr, sizeof (l_msg->ip_assigment.addr), l_new_info); + if( l_new_info){ + char l_addrbuf[17]; + inet_ntop(AF_INET,&l_msg->ip_assigment.addr, l_addrbuf, sizeof (l_addrbuf)); + log_it(L_WARNING, "Already assigned address %s on tun sock #%u", l_addrbuf, l_tun_sock->worker_id); + }else{ + l_new_info = DAP_NEW_Z(dap_chain_net_srv_ch_vpn_info_t); + l_new_info->ch_vpn = l_msg->ch_vpn; + l_new_info->addr_ipv4 = l_msg->ip_assigment.addr; + l_new_info->queue_msg = s_tun_sockets_queue_msg[l_msg->ip_assigment.worker_id]; + l_new_info->usage_id = l_msg->ip_assigment.usage_id; + l_new_info->is_reassigned_once = l_msg->is_reassigned_once; + l_new_info->is_on_this_worker = (l_msg->ip_assigment.worker_id == a_esocket_queue->worker->id); + l_new_info->esocket = l_msg->esocket; + l_new_info->worker = dap_events_worker_get(l_msg->ip_assigment.worker_id); + HASH_ADD(hh,l_tun_sock->clients, addr_ipv4, sizeof (l_new_info->addr_ipv4), l_new_info); + } + + }break; + case TUN_SOCKET_MSG_IP_UNASSIGNED:{ + assert(l_msg->ip_unassigment.worker_id < s_tun_sockets_count); + ch_sf_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + assert(l_tun_sock); + + dap_chain_net_srv_ch_vpn_info_t * l_new_info = NULL; + HASH_FIND(hh,l_tun_sock->clients,&l_msg->ip_unassigment.addr, sizeof (l_msg->ip_unassigment.addr), l_new_info); + if( l_new_info){ + HASH_DELETE(hh, l_tun_sock->clients, l_new_info); + DAP_DELETE(l_new_info); + if( dap_log_level_get() <= L_INFO){ + char l_addrbuf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET,&l_msg->ip_unassigment.addr, l_addrbuf, sizeof (l_addrbuf)); + log_it(L_INFO, "Unassigned %s address from tun sock #%u", l_addrbuf, l_tun_sock->worker_id); + } + }else{ + char l_addrbuf[INET_ADDRSTRLEN]; + inet_ntop(AF_INET,&l_msg->ip_unassigment.addr, l_addrbuf, sizeof (l_addrbuf)); + log_it(L_WARNING, "Can't fund address %s on tun sock #%u to unassign it", l_addrbuf, l_tun_sock->worker_id); + } + + }break; + case TUN_SOCKET_MSG_CH_VPN_SEND:{ + if(dap_events_socket_check_unsafe(a_esocket_queue->worker, l_msg->esocket ) ) + s_tun_client_send_data_unsafe(l_msg->ch_vpn,l_msg->ch_vpn_send.pkt); + DAP_DELETE(l_msg->ch_vpn_send.pkt); + }break; + default:log_it(L_ERROR,"Wrong tun socket message type %d", l_msg->type); + } + DAP_DELETE(l_msg); +} + +/** + * @brief s_tun_send_msg_ip_assigned + * @param a_worker_id + * @param a_ch_vpn + * @param a_addr + */ +static void s_tun_send_msg_ip_assigned(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr ) { - static dap_events_socket_callbacks_t l_s_callbacks = { - .read_callback = m_es_tun_read,// for server - .write_callback = NULL,// for client - .error_callback = m_es_tun_error, - .delete_callback = m_es_tun_delete - }; - - s_raw_server->tun_events_socket = dap_events_socket_wrap_no_add(NULL, - s_raw_server->tun_fd, &l_s_callbacks); - s_raw_server->tun_events_socket->type = DESCRIPTOR_TYPE_FILE; - dap_events_socket_create_after(s_raw_server->tun_events_socket); - s_raw_server->tun_events_socket->_inheritor = s_raw_server; - - return 0; + struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg); + l_msg->type = TUN_SOCKET_MSG_IP_ASSIGNED; + l_msg->ch_vpn = a_ch_vpn; + l_msg->esocket = a_ch_vpn->ch->stream->esocket; + l_msg->is_reassigned_once = a_ch_vpn->ch->stream->esocket->was_reassigned; + l_msg->ip_assigment.addr = a_addr; + l_msg->ip_assigment.worker_id = a_ch_vpn->ch->stream_worker->worker->id; + l_msg->ip_assigment.usage_id = a_ch_vpn->usage_id; + + if (dap_events_socket_queue_ptr_send(s_tun_sockets_queue_msg[a_worker_id], l_msg) != 0){ + log_it(L_WARNING, "Cant send new ip assign message to the tun msg queue #%u", a_worker_id); + } +} + +/** + * @brief s_tun_send_msg_ip_assigned_all + * @param a_ch_vpn + * @param a_addr + */ +static void s_tun_send_msg_ip_assigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr) +{ + for( uint32_t i=0; i< s_tun_sockets_count; i++) + s_tun_send_msg_ip_assigned(i, a_ch_vpn , a_addr ); +} + +/** + * @brief s_tun_send_msg_ip_unassigned + * @param a_worker_id + * @param a_ch_vpn + * @param a_addr + */ +static void s_tun_send_msg_ip_unassigned(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr) +{ + struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg); + l_msg->type = TUN_SOCKET_MSG_IP_UNASSIGNED; + l_msg->ch_vpn = a_ch_vpn; + l_msg->ip_unassigment.addr = a_addr; + l_msg->ip_unassigment.worker_id = a_ch_vpn->ch->stream_worker->worker->id; + l_msg->esocket = a_ch_vpn->ch->stream->esocket; + l_msg->is_reassigned_once = a_ch_vpn->ch->stream->esocket->was_reassigned; + + if ( dap_events_socket_queue_ptr_send(s_tun_sockets_queue_msg[a_worker_id], l_msg) != 0 ) { + log_it(L_WARNING, "Cant send new ip unassign message to the tun msg queue #%u", a_worker_id); + } } -#endif + +/** + * @brief s_tun_send_msg_ip_unassigned_all + * @param a_ch_vpn + * @param a_addr + */ +static void s_tun_send_msg_ip_unassigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr) +{ + for( uint32_t i=0; i< s_tun_sockets_count; i++) + s_tun_send_msg_ip_unassigned(i, a_ch_vpn, a_addr); +} + +/** + * @brief s_tun_send_msg_esocket_reasigned_mt + * @param a_worker_id + * @param a_ch_vpn + * @param a_esocket + * @param a_addr + * @param a_esocket_worker_id + */ +static void s_tun_send_msg_esocket_reasigned_mt(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, dap_events_socket_t * a_esocket, + struct in_addr a_addr, uint32_t a_esocket_worker_id) +{ + struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg); + l_msg->type = TUN_SOCKET_MSG_ESOCKET_REASSIGNED ; + l_msg->ch_vpn = a_ch_vpn; + l_msg->ip_unassigment.addr = a_addr; + l_msg->ip_unassigment.worker_id = a_esocket_worker_id; + l_msg->esocket = a_esocket; + l_msg->is_reassigned_once = true; + + if (dap_events_socket_queue_ptr_send(s_tun_sockets_queue_msg[a_worker_id], l_msg) != 0){ + log_it(L_WARNING, "Cant send esocket reassigment message to the tun msg queue #%u", a_worker_id); + } +} + +static void s_tun_send_msg_esocket_reasigned_all_mt(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, dap_events_socket_t * a_esocket, + struct in_addr a_addr, uint32_t a_worker_id) +{ + for( uint32_t i=0; i< s_tun_sockets_count; i++) + s_tun_send_msg_esocket_reasigned_mt(i, a_ch_vpn, a_esocket, a_addr, a_worker_id); +} + + +/** + * @brief s_tun_event_stream_create + * @param a_worker + * @param a_tun_fd + * @return + */ +dap_events_socket_t * s_tun_event_stream_create(dap_worker_t * a_worker, int a_tun_fd) +{ + assert(a_worker); + dap_events_socket_callbacks_t l_s_callbacks; + memset(&l_s_callbacks,0,sizeof (l_s_callbacks)); + l_s_callbacks.new_callback = m_es_tun_new; + l_s_callbacks.read_callback = m_es_tun_read; + l_s_callbacks.error_callback = m_es_tun_error; + l_s_callbacks.delete_callback = m_es_tun_delete; + + s_tun_deattach_queue(a_tun_fd); + + dap_events_socket_t * l_es = dap_events_socket_wrap_no_add(a_worker->events , + a_tun_fd, &l_s_callbacks); + l_es->type = DESCRIPTOR_TYPE_FILE; + dap_events_socket_assign_on_worker_mt(l_es, a_worker); + + return l_es; +} + static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_t * a_srv_client, const void * a_success, size_t a_success_size) { - if(!a_srv || !a_srv_client || !a_srv_client->ch || !a_success || a_success_size < sizeof(dap_stream_ch_chain_net_srv_pkt_success_t)) + if(!a_srv || !a_srv_client || !a_srv_client->stream_worker || !a_success || a_success_size < sizeof(dap_stream_ch_chain_net_srv_pkt_success_t)) return -1; dap_stream_ch_chain_net_srv_pkt_success_t * l_success = (dap_stream_ch_chain_net_srv_pkt_success_t*) a_success; + dap_stream_session_lock(); + dap_stream_session_t *l_stream_session = dap_stream_session_id_unsafe(a_srv_client->session_id); dap_chain_net_srv_stream_session_t * l_srv_session = - (dap_chain_net_srv_stream_session_t *) a_srv_client->ch->stream->session->_inheritor; + (dap_chain_net_srv_stream_session_t *) l_stream_session->_inheritor; + dap_chain_net_srv_vpn_t* l_srv_vpn = (dap_chain_net_srv_vpn_t*) a_srv->_inhertor; //a_srv_client->ch-> dap_chain_net_t * l_net = dap_chain_net_by_id(l_success->hdr.net_id); dap_chain_net_srv_usage_t *l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, a_srv); - if(!l_usage) + if(!l_usage){ + dap_stream_session_unlock(); return -2; + } dap_chain_net_srv_ch_vpn_t * l_srv_ch_vpn = (dap_chain_net_srv_ch_vpn_t*) a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID] ? @@ -223,29 +505,6 @@ static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usa dap_stream_ch_t *l_ch = dap_chain_net_vpn_client_get_stream_ch(); - int remote_sock_id = 0;//l_vpn_pkt->header.sock_id; - ch_vpn_socket_proxy_t * sf_sock = NULL; - sf_sock = DAP_NEW_Z(ch_vpn_socket_proxy_t); - sf_sock->id = remote_sock_id; - sf_sock->sock = l_ch->stream->events_socket->socket; - sf_sock->ch = l_ch; - pthread_mutex_init(&sf_sock->mutex, NULL); - dap_chain_net_srv_ch_vpn_t *f = CH_VPN(a_srv_client->ch); - //pthread_mutex_lock(&s_sf_socks_mutex); - pthread_mutex_lock(&l_srv_ch_vpn->mutex); - HASH_ADD_INT(l_srv_ch_vpn->socks, id, sf_sock); - pthread_mutex_unlock(&l_srv_ch_vpn->mutex); - //HASH_ADD_INT(CH_VPN(a_srv_client->ch)->socks, id, sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, sf_sock->sock); - - //!!!//l_usage->receipt = ; - - /* - dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION( a_ch->stream->session ); - dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); - if ( ! l_usage->is_active - */ if(l_ch) { // Is present in hash table such destination address size_t l_ipv4_str_len = 0; //dap_strlen(a_ipv4_str); @@ -256,29 +515,24 @@ static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usa //pkt_out->header.op_connect.addr_size = l_ipv4_str_len; //remoteAddrBA.length(); //pkt_out->header.op_connect.port = a_port; //memcpy(pkt_out->data, a_ipv4_str, l_ipv4_str_len); - sf_sock->pkt_out[sf_sock->pkt_out_size] = pkt_out; - sf_sock->pkt_out_size++; - dap_stream_ch_pkt_write(l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(l_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); //DAP_DELETE(pkt_out); } - - - // usage is present, we've accepted packets - dap_stream_ch_set_ready_to_read( l_srv_ch_vpn->ch , true ); + dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true ); return 0; } static int callback_client_sign_request(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_t * a_srv_client, - const void **a_receipt, size_t a_receipt_size) + dap_chain_datum_tx_receipt_t **a_receipt, size_t a_receipt_size) { - dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t*)*a_receipt; + dap_chain_datum_tx_receipt_t *l_receipt = *a_receipt; char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - char *l_wallet_name = dap_chain_global_db_gr_get(dap_strdup("wallet_name"), NULL, l_gdb_group); + char *l_wallet_name = (char*) dap_chain_global_db_gr_get(dap_strdup("wallet_name"), NULL, l_gdb_group); dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_name, dap_chain_wallet_get_path(g_config)); if(l_wallet) { @@ -296,7 +550,7 @@ static int callback_client_sign_request(dap_chain_net_srv_t * a_srv, uint32_t a_ /* * Client VPN init (after dap_chain_net_srv_vpn_init!) */ -int dap_chain_net_srv_client_vpn_init(dap_config_t * g_config) { +int dap_chain_net_srv_client_vpn_init(dap_config_t * l_config) { dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get(l_uid); dap_chain_net_srv_vpn_t* l_srv_vpn = l_srv ? (dap_chain_net_srv_vpn_t*) l_srv->_inhertor : NULL; @@ -305,10 +559,12 @@ int dap_chain_net_srv_client_vpn_init(dap_config_t * g_config) { l_srv_vpn = DAP_NEW_Z(dap_chain_net_srv_vpn_t); if(l_srv) l_srv->_inhertor = l_srv_vpn; - dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_new, srv_ch_vpn_delete, s_ch_packet_in, s_ch_packet_out); + dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, s_ch_packet_out); pthread_mutex_init(&s_sf_socks_mutex, NULL); pthread_cond_init(&s_sf_socks_cond, NULL); } + + if(!dap_chain_net_srv_client_init(l_uid, s_callback_requested, s_callback_response_success, s_callback_response_error, s_callback_receipt_next_success, @@ -325,130 +581,195 @@ int dap_chain_net_srv_client_vpn_init(dap_config_t * g_config) { return 0; } -/** - * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel - * @param vpn_addr Zero if only client mode. Address if the node shares its local VPN - * @param vpn_mask Zero if only client mode. Mask if the node shares its local VPN - * @return 0 if everything is okay, lesser then zero if errors - */ -int dap_chain_net_srv_vpn_init(dap_config_t * g_config) { + + +int s_vpn_tun_create(dap_config_t * g_config) +{ const char *c_addr = dap_config_get_item_str(g_config, "srv_vpn", "network_address"); const char *c_mask = dap_config_get_item_str(g_config, "srv_vpn", "network_mask"); - if(c_addr && c_mask) { - s_srv_vpn_addr = strdup(c_addr); - s_srv_vpn_mask = strdup(c_mask); + if(!c_addr || !c_mask){ + log_it(L_ERROR, "%s: error while reading network parameters from config (network_address and network_mask)", __PRETTY_FUNCTION__); + DAP_DELETE((void*)c_addr); + DAP_DELETE((void*)c_mask); + return -1; + } - s_raw_server = DAP_NEW_Z(vpn_local_network_t); - pthread_mutex_init(&s_raw_server->pkt_out_mutex, NULL); - pthread_mutex_init(&s_sf_socks_mutex, NULL); - pthread_cond_init(&s_sf_socks_cond, NULL); + inet_aton(c_addr, &s_raw_server->ipv4_network_addr ); + inet_aton(c_mask, &s_raw_server->ipv4_network_mask ); + s_raw_server->ipv4_gw.s_addr= (s_raw_server->ipv4_network_addr.s_addr | 0x01000000); // grow up some shit here! + s_raw_server->ipv4_lease_last.s_addr = s_raw_server->ipv4_gw.s_addr; + + s_raw_server->auto_cpu_reassignment = dap_config_get_item_bool_default(g_config, "srv_vpn", "auto_cpu_reassignment", false); + log_it(L_NOTICE,"auto cpu reassignment is set to '%s'", s_raw_server->auto_cpu_reassignment); + + memset(&s_raw_server->ifr, 0, sizeof(s_raw_server->ifr)); + s_raw_server->ifr.ifr_flags = IFF_TUN | IFF_MULTI_QUEUE| IFF_NO_PI; + + uint32_t l_cpu_count = dap_get_cpu_count(); // maybe replace with getting s_threads_count directly + log_it(L_NOTICE,"%s: trying to initialize multiqueue for %u workers", __PRETTY_FUNCTION__, l_cpu_count); + s_tun_sockets_count = l_cpu_count; + s_tun_sockets = DAP_NEW_Z_SIZE(ch_sf_tun_socket_t*,s_tun_sockets_count*sizeof(ch_sf_tun_socket_t*)); + s_tun_sockets_queue_msg = DAP_NEW_Z_SIZE(dap_events_socket_t*,s_tun_sockets_count*sizeof(dap_events_socket_t*)); + int err = -1; + for( uint8_t i =0; i< l_cpu_count; i++){ + dap_worker_t * l_worker = dap_events_worker_get(i); + assert( l_worker ); + int l_tun_fd; + if( (l_tun_fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0 ) { + log_it(L_ERROR,"Opening /dev/net/tun error: '%s'", strerror(errno)); + err = -100; + break; + } + log_it(L_DEBUG,"Opening /dev/net/tun:%u", i); + if( (err = ioctl(l_tun_fd, TUNSETIFF, (void *)& s_raw_server->ifr)) < 0 ) { + log_it(L_CRITICAL, "ioctl(TUNSETIFF) error: '%s' ",strerror(errno)); + close(l_tun_fd); + break; + } + s_tun_deattach_queue(l_tun_fd); + s_tun_event_stream_create(l_worker, l_tun_fd); + } -#ifdef DAP_TUN_IN_WORKER - s_tun_create(); + if (! err ){ + char buf[256]; + log_it(L_NOTICE,"Bringed up %s virtual network interface (%s/%s)", s_raw_server->ifr.ifr_name,inet_ntoa(s_raw_server->ipv4_gw),c_mask); + snprintf(buf,sizeof(buf),"ip link set %s up",s_raw_server->ifr.ifr_name); + system(buf); + snprintf(buf,sizeof(buf),"ip addr add %s/%s dev %s ",inet_ntoa(s_raw_server->ipv4_gw),c_mask, s_raw_server->ifr.ifr_name ); + system(buf); + } - if(s_raw_server->tun_fd == -1){ - log_it(L_CRITICAL,"Error creating file descriptor for /dev/net/tun device"); - return -2; - } + return err; +} - s_tun_event_stream_create(); -#else - pthread_create(&srv_sf_socks_raw_pid, NULL, srv_ch_sf_thread_raw, NULL); -#endif +/** +* @brief ch_sf_tun_init +* @return +*/ +int s_vpn_tun_init() +{ + s_raw_server=DAP_NEW_Z(vpn_local_network_t); + pthread_rwlock_init(&s_raw_server->rwlock, NULL); + pthread_mutex_init(&s_raw_server->pkt_out_mutex,NULL); + pthread_mutex_init(&s_sf_socks_mutex, NULL); + pthread_cond_init(&s_sf_socks_cond, NULL); - pthread_create(&srv_sf_socks_pid, NULL, srv_ch_sf_thread, NULL); - dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_new, srv_ch_vpn_delete, s_ch_packet_in, - s_ch_packet_out); - dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; - dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add( l_uid, s_callback_requested, - s_callback_response_success, s_callback_response_error, - s_callback_receipt_next_success); - dap_chain_net_srv_vpn_t* l_srv_vpn = DAP_NEW_Z( dap_chain_net_srv_vpn_t); - l_srv->_inhertor = l_srv_vpn; - l_srv_vpn->parent = l_srv; - - uint16_t l_pricelist_count = 0; - - /* ! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data - * ! it also must NOT be freed within this module ! - */ - char **l_pricelist = dap_config_get_array_str(g_config, "srv_vpn", "pricelist", &l_pricelist_count); // must not be freed! - for (uint16_t i = 0; i < l_pricelist_count; i++) { - dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t); - short l_iter = 0; - char *l_ctx; - for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) { - //log_it(L_DEBUG, "Tokenizer: %s", l_price_token); - switch (l_iter) { - case 0: - l_price->net_name = l_price_token; - if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) { - log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token); - DAP_DELETE(l_price); - break; - } - continue; - case 1: - l_price->value_coins = atof(l_price_token); - if (!(l_price->value_datoshi = (uint64_t)dap_chain_coins_to_balance((long double)l_price->value_coins))) { - log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token); - l_iter = 0; - DAP_DELETE(l_price); - break; - } - continue; - case 2: - dap_stpcpy(l_price->token, l_price_token); - continue; - case 3: - l_price->units = strtoul(l_price_token, NULL, 10); - if (!l_price->units) { - log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token); - l_iter = 0; - DAP_DELETE(l_price); - break; - } - continue; - case 4: - if (!strcmp(l_price_token, "SEC")) - l_price->units_uid.enm = SERV_UNIT_SEC; - else if (!strcmp(l_price_token, "DAY")) - l_price->units_uid.enm = SERV_UNIT_DAY; - else if (!strcmp(l_price_token, "MB")) - l_price->units_uid.enm = SERV_UNIT_MB; - else { - log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token); - l_iter = 0; - DAP_DELETE(l_price); - break; - } - continue; - case 5: - if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) { - log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token); - l_iter = 0; - DAP_DELETE(l_price); - break; - } - continue; - case 6: - log_it(L_INFO, "Price item correct, added to service"); - DL_APPEND(l_srv->pricelist, l_price); + return 0; +} + +int s_vpn_service_create(dap_config_t * g_config){ + dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; + dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add( l_uid, s_callback_requested, + s_callback_response_success, s_callback_response_error, + s_callback_receipt_next_success); + + dap_chain_net_srv_vpn_t* l_srv_vpn = DAP_NEW_Z( dap_chain_net_srv_vpn_t); + l_srv->_inhertor = l_srv_vpn; + l_srv_vpn->parent = l_srv; + + uint16_t l_pricelist_count = 0; + + // Read if we need to dump all pkt operations + s_debug_more= dap_config_get_item_bool_default(g_config,"srv_vpn", "debug_more",false); + + + //! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data + //! it also must NOT be freed within this module ! + char **l_pricelist = dap_config_get_array_str(g_config, "srv_vpn", "pricelist", &l_pricelist_count); // must not be freed! + for (uint16_t i = 0; i < l_pricelist_count; i++) { + dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t); + short l_iter = 0; + char *l_ctx; + for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) { + //log_it(L_DEBUG, "Tokenizer: %s", l_price_token); + switch (l_iter) { + case 0: + l_price->net_name = l_price_token; + if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) { + log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token); + DAP_DELETE(l_price); + break; + } + continue; + case 1: + l_price->value_coins = atof(l_price_token); + if (!(l_price->value_datoshi = (uint64_t)dap_chain_coins_to_balance((long double)l_price->value_coins))) { + log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token); + l_iter = 0; + DAP_DELETE(l_price); + break; + } + continue; + case 2: + dap_stpcpy(l_price->token, l_price_token); + continue; + case 3: + l_price->units = strtoul(l_price_token, NULL, 10); + if (!l_price->units) { + log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token); + l_iter = 0; + DAP_DELETE(l_price); break; - default: + } + continue; + case 4: + if (!strcmp(l_price_token, "SEC")) + l_price->units_uid.enm = SERV_UNIT_SEC; + else if (!strcmp(l_price_token, "DAY")) + l_price->units_uid.enm = SERV_UNIT_DAY; + else if (!strcmp(l_price_token, "MB")) + l_price->units_uid.enm = SERV_UNIT_MB; + else { + log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token); + l_iter = 0; + DAP_DELETE(l_price); break; } - log_it(L_DEBUG, "Done with price item %d", i); - break; // double break exits tokenizer loop and steps to next price item + continue; + case 5: + if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) { + log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token); + l_iter = 0; + DAP_DELETE(l_price); + break; + } + continue; + case 6: + log_it(L_INFO, "Price item correct, added to service"); + DL_APPEND(l_srv->pricelist, l_price); + break; + default: + break; } + log_it(L_DEBUG, "Done with price item %d", i); + break; // double break exits tokenizer loop and steps to next price item } + } + return 0; - return 0; - //int retVal = dap_chain_net_srv_vpn_cmd_init(); - //return retVal; +} + + +/** + * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel + * @param g_config + * @return 0 if everything is okay, lesser then zero if errors + */ +int dap_chain_net_srv_vpn_init(dap_config_t * g_config) { + s_vpn_tun_init(); + + log_it(L_DEBUG,"Initializing TUN driver..."); + if(s_vpn_tun_create(g_config) != 0){ + log_it(L_CRITICAL, "Error initializing TUN device driver!"); + return -1; } - return -1; + log_it(L_INFO,"TUN driver configured successfuly"); + s_vpn_service_create(g_config); + dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, + s_ch_packet_out); + + return 0; } /** @@ -492,7 +813,7 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u // dap_stream_ch_chain_net_srv_pkt_request_t * l_request = (dap_stream_ch_chain_net_srv_pkt_request_t *) a_request; // dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_srv_client->ch->stream->session->_inheritor; dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_srv_client->ch->stream->session->_inheritor; - dap_chain_net_srv_usage_t * l_usage_active= dap_chain_net_srv_usage_find(l_srv_session,a_usage_id); + dap_chain_net_srv_usage_t * l_usage_active= dap_chain_net_srv_usage_find_unsafe(l_srv_session,a_usage_id); dap_chain_net_srv_ch_vpn_t * l_srv_ch_vpn =(dap_chain_net_srv_ch_vpn_t*) a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID] ? a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID]->internal : NULL; @@ -505,21 +826,19 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u l_usage_client = DAP_NEW_Z(usage_client_t); l_usage_client->usage_id = a_usage_id; - l_usage_client->net_srv_client = a_srv_client; l_usage_client->receipt = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size); - pthread_rwlock_init(&l_usage_client->rwlock,NULL); memcpy(l_usage_client->receipt, l_receipt, l_receipt_size); + pthread_rwlock_wrlock(&s_clients_rwlock); HASH_ADD(hh, s_clients,usage_id,sizeof(a_usage_id),l_usage_client); - l_srv_session->usage_active = l_usage_active; l_srv_session->usage_active->is_active = true; log_it(L_NOTICE,"Enable VPN service"); if ( l_srv_ch_vpn ){ // If channel is already opened - dap_stream_ch_set_ready_to_read( l_srv_ch_vpn->ch , true ); + dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true ); l_srv_ch_vpn->usage_id = a_usage_id; // So complicated to update usage client to be sure that nothing breaks it @@ -551,7 +870,7 @@ static int s_callback_receipt_next_success(dap_chain_net_srv_t * a_srv, uint32_t log_it(L_INFO, "Next receipt successfuly accepted"); // usage is present, we've accepted packets - dap_stream_ch_set_ready_to_read( l_srv_ch_vpn->ch , true ); + dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true ); return 0; } @@ -571,72 +890,6 @@ static int s_callback_response_error(dap_chain_net_srv_t * a_srv, uint32_t a_usa } -/** - * @brief s_tun_create - */ -static void s_tun_create(void) -{ - pthread_rwlock_wrlock(& s_raw_server_rwlock); - inet_aton(s_srv_vpn_addr, &s_raw_server->ipv4_network_addr); - inet_aton(s_srv_vpn_mask, &s_raw_server->ipv4_network_mask); - s_raw_server->ipv4_host.s_addr = (s_raw_server->ipv4_network_addr.s_addr | 0x01000000); // grow up some shit here! - s_raw_server->ipv4_lease_last.s_addr = s_raw_server->ipv4_host.s_addr; - - if((s_raw_server->tun_ctl_fd = open("/dev/net/tun", O_RDWR)) < 0) { - log_it(L_ERROR, "Opening /dev/net/tun error: '%s'", strerror(errno)); - } else { - int err; - memset(&s_raw_server->ifr, 0, sizeof(s_raw_server->ifr)); - s_raw_server->ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - if((err = ioctl(s_raw_server->tun_ctl_fd, TUNSETIFF, (void *) &s_raw_server->ifr)) < 0) { - log_it(L_CRITICAL, "ioctl(TUNSETIFF) error: '%s' ", strerror(errno)); - close(s_raw_server->tun_ctl_fd); - s_raw_server->tun_ctl_fd = -1; - s_raw_server->tun_fd = -1; - } else { - char buf[256]; - log_it(L_NOTICE, "Bringed up %s virtual network interface (%s/%s)", s_raw_server->ifr.ifr_name, - inet_ntoa(s_raw_server->ipv4_host), s_srv_vpn_mask); - s_raw_server->tun_fd = s_raw_server->tun_ctl_fd; // Looks yes, its so - snprintf(buf, sizeof(buf), "ip link set %s up", s_raw_server->ifr.ifr_name); - int res = system(buf); - snprintf(buf, sizeof(buf), "ip addr add %s/%s dev %s ", inet_ntoa(s_raw_server->ipv4_host), - s_srv_vpn_mask, - s_raw_server->ifr.ifr_name); - res = system(buf); - res = 0; - } - } - pthread_rwlock_unlock(& s_raw_server_rwlock); - -} - -/** - * @brief s_tun_destroy - */ -static void s_tun_destroy(void) -{ - pthread_rwlock_wrlock(& s_raw_server_rwlock); -#ifdef DAP_TUN_IN_WORKER - dap_events_socket_kill_socket(s_raw_server->tun_events_socket); -#endif - close(s_raw_server->tun_fd); - s_raw_server->tun_fd = -1; - pthread_rwlock_unlock(& s_raw_server_rwlock); -} - - -/** - * @brief ch_sf_socket_delete - * @param sf - */ -static void ch_sf_socket_delete(ch_vpn_socket_proxy_t * a_vpn_socket_proxy) -{ - close(a_vpn_socket_proxy->sock); - pthread_mutex_destroy(& (a_vpn_socket_proxy->mutex) ); - if (a_vpn_socket_proxy) - DAP_DELETE(a_vpn_socket_proxy); -} /** @@ -644,22 +897,22 @@ static void ch_sf_socket_delete(ch_vpn_socket_proxy_t * a_vpn_socket_proxy) * @param ch * @param arg */ -void s_new(dap_stream_ch_t* a_stream_ch, void* a_arg) +void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg) { (void) a_arg; - - a_stream_ch->internal = DAP_NEW_Z(dap_chain_net_srv_ch_vpn_t); - dap_chain_net_srv_ch_vpn_t * l_srv_vpn = CH_VPN(a_stream_ch); - - if(a_stream_ch->stream->session->_inheritor == NULL && a_stream_ch->stream->session != NULL) - dap_chain_net_srv_stream_session_create(a_stream_ch->stream->session); + a_ch->stream->esocket->flags |= DAP_SOCK_REASSIGN_ONCE; // We will try to reassign on another worker + // to use FlowControl if its present in system + // If not - we prevent jumping between workers with this trick + a_ch->internal = DAP_NEW_Z(dap_chain_net_srv_ch_vpn_t); + dap_chain_net_srv_ch_vpn_t * l_srv_vpn = CH_VPN(a_ch); + + if(a_ch->stream->session->_inheritor == NULL && a_ch->stream->session != NULL) + dap_chain_net_srv_stream_session_create(a_ch->stream->session); dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; l_srv_vpn->net_srv = dap_chain_net_srv_get(l_uid); - l_srv_vpn->ch = a_stream_ch; + l_srv_vpn->ch = a_ch; - dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_stream_ch->stream->session->_inheritor; - pthread_mutex_init(&l_srv_vpn->mutex, NULL); - l_srv_vpn->raw_l3_sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); + dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_ch->stream->session->_inheritor; l_srv_vpn->usage_id = l_srv_session->usage_active? l_srv_session->usage_active->id : 0; @@ -669,9 +922,7 @@ void s_new(dap_stream_ch_t* a_stream_ch, void* a_arg) pthread_rwlock_rdlock(&s_clients_rwlock); HASH_FIND(hh,s_clients, &l_srv_vpn->usage_id,sizeof(l_srv_vpn->usage_id),l_usage_client ); if (l_usage_client){ - pthread_rwlock_wrlock(&l_usage_client->rwlock); l_usage_client->ch_vpn = l_srv_vpn; - pthread_rwlock_unlock(&l_usage_client->rwlock); } pthread_rwlock_unlock(&s_clients_rwlock); } @@ -683,17 +934,19 @@ void s_new(dap_stream_ch_t* a_stream_ch, void* a_arg) * @param ch * @param arg */ -void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) +void s_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) { - //log_it(L_DEBUG, "ch_sf_delete() for %s", ch->stream->conn->s_ip); <<- causes segfault dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(ch); dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_inhertor; - pthread_mutex_lock(&(l_ch_vpn->mutex)); + + // So complicated to update usage client to be sure that nothing breaks it usage_client_t * l_usage_client = NULL; bool l_is_unleased = false; if ( l_ch_vpn->addr_ipv4.s_addr ){ // if leased address + s_tun_send_msg_ip_unassigned_all(l_ch_vpn, l_ch_vpn->addr_ipv4); // Signal all the workers that we're switching off + pthread_rwlock_wrlock(& s_raw_server_rwlock); if ( s_raw_server->ipv4_lease_last.s_addr == l_ch_vpn->addr_ipv4.s_addr ){ s_raw_server->ipv4_lease_last.s_addr = ntohl( ntohl(s_raw_server->ipv4_lease_last.s_addr)-1 ); @@ -717,64 +970,14 @@ void srv_ch_vpn_delete(dap_stream_ch_t* ch, void* arg) HASH_FIND(hh,s_clients, &l_ch_vpn->usage_id,sizeof(l_ch_vpn->usage_id),l_usage_client ); if (l_usage_client){ - pthread_rwlock_wrlock(&l_usage_client->rwlock); l_usage_client->ch_vpn = NULL; // NULL the channel, nobody uses that indicates - pthread_rwlock_unlock(&l_usage_client->rwlock); } pthread_rwlock_unlock(&s_clients_rwlock); - ch_vpn_socket_proxy_t * cur, *tmp; - // in_addr_t raw_client_addr = CH_SF(ch)->tun_client_addr.s_addr; - HASH_ITER(hh, l_ch_vpn->socks , cur, tmp) - { - log_it(L_DEBUG, "delete socket: %i", cur->sock); - if(l_ch_vpn->socks){ - HASH_DEL(l_ch_vpn->socks, cur); - } - if(cur) - free(cur); - } - - if(l_ch_vpn->raw_l3_sock) - close(l_ch_vpn->raw_l3_sock); l_ch_vpn->ch = NULL; l_ch_vpn->net_srv = NULL; l_ch_vpn->is_allowed =false; - pthread_mutex_unlock(&(l_ch_vpn->mutex)); - pthread_mutex_destroy(& l_ch_vpn->mutex); -} - -static void s_ch_proxy_delete(ch_vpn_socket_proxy_t * a_sock_proxy) -{ - if( !a_sock_proxy) - return; - - if(a_sock_proxy->sock > 0) - close(a_sock_proxy->sock); - // wait while mutex will be released if it be locked - pthread_mutex_lock(&a_sock_proxy->mutex); - pthread_mutex_unlock(&a_sock_proxy->mutex); - - pthread_mutex_destroy(&(a_sock_proxy->mutex)); - DAP_DELETE(a_sock_proxy); -} - -static ch_vpn_pkt_t* srv_ch_sf_raw_read() -{ - ch_vpn_pkt_t*ret = NULL; - pthread_mutex_lock(&s_raw_server->pkt_out_mutex); - if(s_raw_server->pkt_out_rindex == (sizeof(s_raw_server->pkt_out) / sizeof(s_raw_server->pkt_out[0]))) { - s_raw_server->pkt_out_rindex = 0; // ring the buffer! - } - if((s_raw_server->pkt_out_rindex != s_raw_server->pkt_out_windex) || (s_raw_server->pkt_out_size == 0)) { - ret = s_raw_server->pkt_out[s_raw_server->pkt_out_rindex]; - s_raw_server->pkt_out_rindex++; - s_raw_server->pkt_out_size--; - } //else - // log_it(L_WARNING, "Packet drop on raw_read() operation, ring buffer is full"); - pthread_mutex_unlock(&s_raw_server->pkt_out_mutex); - return ret; } /** @@ -811,18 +1014,18 @@ static void s_update_limits(dap_stream_ch_t * a_ch , } break; default: { log_it(L_WARNING, "VPN doesnt accept serv unit type 0x%08X for limits_ts", a_usage->receipt->receipt_info.units_type.uint32 ); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - dap_stream_ch_pkt_write( a_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } //l_ch_vpn->limits_ts = time(NULL) + l_usage->receipt->receipt }else { log_it( L_NOTICE, "No activate receipt in usage, switch off write callback for channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - dap_stream_ch_pkt_write( a_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } }else if ( a_srv_session->limits_bytes ){ @@ -852,18 +1055,18 @@ static void s_update_limits(dap_stream_ch_t * a_ch , } break; default: { log_it(L_WARNING, "VPN doesnt accept serv unit type 0x%08X for limits_bytes", a_usage->receipt->receipt_info.units_type.uint32 ); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - dap_stream_ch_pkt_write( a_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } }else { log_it( L_NOTICE, "No activate receipt in usage, switch off write callback for channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - dap_stream_ch_pkt_write( a_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } @@ -875,7 +1078,7 @@ static void s_update_limits(dap_stream_ch_t * a_ch , if ( a_usage->receipt){ dap_chain_datum_tx_receipt_t * l_receipt =dap_chain_net_srv_issue_receipt(a_usage->service, a_usage,a_usage->price,NULL,0 ); a_usage->receipt_next = l_receipt; - dap_stream_ch_pkt_write( a_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , + dap_stream_ch_pkt_write_unsafe( a_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST , l_receipt, l_receipt->size); } } @@ -889,12 +1092,164 @@ static void send_pong_pkt(dap_stream_ch_t* a_ch) ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); pkt_out->header.op_code = VPN_PACKET_OP_CODE_PONG; - dap_stream_ch_pkt_write(a_ch, 'd', pkt_out, + dap_stream_ch_pkt_write_unsafe(a_ch, 'd', pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); free(pkt_out); } +void s_ch_packet_in_vpn_address_request(dap_stream_ch_t* a_ch, dap_chain_net_srv_usage_t * a_usage){ + dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch); + dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) a_usage->service->_inhertor; + dap_chain_net_srv_stream_session_t * l_srv_session= DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); + + if ( l_ch_vpn->addr_ipv4.s_addr ){ + log_it(L_WARNING,"We already have ip address leased to us"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; + pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_ALREADY_ASSIGNED_ADDR; + pkt_out->header.sock_id = s_raw_server->tun_fd; + pkt_out->header.usage_id = a_usage->id; + + size_t l_data_to_write = pkt_out->header.op_data.data_size + sizeof(pkt_out->header); + size_t l_data_wrote = dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + l_data_to_write); + if (l_data_wrote < l_data_to_write){ + log_it(L_WARNING, "Buffer overfilled: can't send packet with VPN_PROBLEM_CODE_ALREADY_ASSIGNED_ADDR: sent only %zd from %zd", + l_data_wrote,l_data_to_write ); + l_srv_session->stats.bytes_sent_lost += l_data_to_write - l_data_wrote; + l_srv_session->stats.packets_sent_lost++; + }else{ + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_data_wrote; + } + return; + } + dap_chain_net_srv_vpn_item_ipv4_t * l_item_ipv4 = l_srv_vpn->ipv4_unleased; + if ( l_item_ipv4){ + log_it(L_WARNING,"We have unleased ip address"); + l_ch_vpn->addr_ipv4.s_addr = l_item_ipv4->addr.s_addr; + + pthread_rwlock_wrlock( &s_clients_rwlock ); + HASH_ADD(hh, s_ch_vpn_addrs, addr_ipv4, sizeof (l_ch_vpn->addr_ipv4), l_ch_vpn); + pthread_rwlock_unlock( &s_clients_rwlock ); + + ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, + sizeof(l_pkt_out->header) + sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_network_addr)); + l_pkt_out->header.sock_id = s_raw_server->tun_fd; + l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; + l_pkt_out->header.op_data.data_size = sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_gw); + l_pkt_out->header.usage_id = a_usage->id; + + memcpy(l_pkt_out->data, &l_ch_vpn->addr_ipv4, sizeof(l_ch_vpn->addr_ipv4)); + memcpy(l_pkt_out->data + sizeof(l_ch_vpn->addr_ipv4), &s_raw_server->ipv4_gw , + sizeof(s_raw_server->ipv4_gw)); + + size_t l_data_to_write = l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header); + size_t l_data_wrote = dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA , l_pkt_out, + l_data_to_write); + if (l_data_wrote < l_data_to_write){ + log_it(L_WARNING, "Buffer overfilled: can't send packet with VPN_PACKET_OP_CODE_VPN_ADDR_REPLY: sent only %zd from %zd", + l_data_wrote,l_data_to_write ); + dap_chain_net_srv_stream_session_t * l_srv_session= DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); + assert(l_srv_session); + l_srv_session->stats.bytes_sent_lost += l_data_to_write - l_data_wrote; + l_srv_session->stats.packets_sent_lost++; + }else{ + log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(l_ch_vpn->addr_ipv4)); + log_it(L_INFO, "\tnet gateway %s", inet_ntoa(s_raw_server->ipv4_network_addr)); + log_it(L_INFO, "\tnet mask %s", inet_ntoa(s_raw_server->ipv4_network_mask)); + log_it(L_INFO, "\tgw %s", inet_ntoa(s_raw_server->ipv4_gw)); + log_it(L_INFO, "\tlast_addr %s", inet_ntoa(s_raw_server->ipv4_lease_last)); + l_srv_vpn->ipv4_unleased = l_item_ipv4->next; + DAP_DELETE(l_item_ipv4); + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_data_wrote; + s_tun_send_msg_ip_assigned_all(l_ch_vpn, l_ch_vpn->addr_ipv4); + } + }else{ + struct in_addr n_addr = { 0 }, n_addr_max; + n_addr.s_addr = ntohl(s_raw_server->ipv4_lease_last.s_addr); + n_addr.s_addr++; + n_addr_max.s_addr = (ntohl(s_raw_server->ipv4_gw.s_addr) + | ~ntohl(s_raw_server->ipv4_network_mask.s_addr)); + + // Just for log output we revert it back and forward + n_addr.s_addr = htonl(n_addr.s_addr); + n_addr_max.s_addr = htonl(n_addr_max.s_addr); + log_it(L_DEBUG, "Check if is address is lesser than"); + log_it(L_DEBUG," new_address = %s", inet_ntoa(n_addr)); + log_it(L_DEBUG," new_address_max = %s", inet_ntoa(n_addr_max)); + n_addr.s_addr = ntohl(n_addr.s_addr); + n_addr_max.s_addr = ntohl(n_addr_max.s_addr); + if(n_addr.s_addr <= n_addr_max.s_addr ) { + n_addr.s_addr = htonl(n_addr.s_addr); + n_addr_max.s_addr = htonl(n_addr_max.s_addr); + + s_raw_server->ipv4_lease_last.s_addr =n_addr.s_addr; + a_ch->stream->session->tun_client_addr.s_addr = n_addr.s_addr; + l_ch_vpn->addr_ipv4.s_addr = n_addr.s_addr; + + log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(n_addr)); + log_it(L_INFO, "\tgateway %s", inet_ntoa(s_raw_server->ipv4_gw )); + log_it(L_INFO, "\tnet mask %s", inet_ntoa(s_raw_server->ipv4_network_mask)); + log_it(L_INFO, "\tnet addr %s", inet_ntoa(s_raw_server->ipv4_network_addr )); + log_it(L_INFO, "\tlast_addr %s", inet_ntoa(s_raw_server->ipv4_lease_last)); + pthread_rwlock_wrlock( &s_clients_rwlock ); + HASH_ADD(hh, s_ch_vpn_addrs, addr_ipv4, sizeof (l_ch_vpn->addr_ipv4), l_ch_vpn); + pthread_rwlock_unlock( &s_clients_rwlock ); + + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, + sizeof(pkt_out->header) + sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_gw)); + pkt_out->header.sock_id = s_raw_server->tun_fd; + pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; + pkt_out->header.op_data.data_size = sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_gw); + pkt_out->header.usage_id = a_usage->id; + + memcpy(pkt_out->data, &l_ch_vpn->addr_ipv4, sizeof(l_ch_vpn->addr_ipv4)); + memcpy(pkt_out->data + sizeof(l_ch_vpn->addr_ipv4), &s_raw_server->ipv4_gw, + sizeof(s_raw_server->ipv4_gw)); + + size_t l_data_to_write = pkt_out->header.op_data.data_size + sizeof(pkt_out->header); + size_t l_data_wrote = dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + l_data_to_write); + if (l_data_wrote < l_data_to_write){ + log_it(L_WARNING, "Buffer overfilled: can't send packet with VPN_PACKET_OP_CODE_VPN_ADDR_REPLY: sent only %zd from %zd", + l_data_wrote,l_data_to_write ); + dap_chain_net_srv_stream_session_t * l_srv_session= DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); + assert(l_srv_session); + l_srv_session->stats.bytes_sent_lost += l_data_to_write - l_data_wrote; + l_srv_session->stats.packets_sent_lost++; + }else{ + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_data_wrote; + s_tun_send_msg_ip_assigned_all(l_ch_vpn, l_ch_vpn->addr_ipv4); + } + } else { // All the network is filled with clients, can't lease a new address + log_it(L_WARNING, "All the network is filled with clients, can't lease a new address"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.sock_id = s_raw_server->tun_fd; + pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; + pkt_out->header.usage_id = a_usage->id; + pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_NO_FREE_ADDR; + size_t l_data_to_write = pkt_out->header.op_data.data_size + sizeof(pkt_out->header); + size_t l_data_wrote = dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + if (l_data_wrote < l_data_to_write){ + log_it(L_WARNING, "Buffer overfilled: can't send packet with VPN_PACKET_OP_CODE_PROBLEM: sent only %zd from %zd", + l_data_wrote,l_data_to_write ); + dap_chain_net_srv_stream_session_t * l_srv_session= DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); + assert(l_srv_session); + l_srv_session->stats.bytes_sent_lost += l_data_to_write - l_data_wrote; + l_srv_session->stats.packets_sent_lost++; + }else{ + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_data_wrote; + } + } + } +} + /** * @brief stream_sf_packet_in * @param ch @@ -905,380 +1260,137 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) dap_stream_ch_pkt_t * l_pkt = (dap_stream_ch_pkt_t *) a_arg; dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (a_ch->stream->session ); dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); + dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_ch_vpn->usage_id); if ( ! l_usage){ log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothin on this channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); return; } if ( ! l_usage->is_active ){ log_it(L_INFO, "Usage inactivation: switch off packet input channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); return; } // TODO move address leasing to this structure - dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_inhertor; + //dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_usage->service->_inhertor; - //if ( pkt->hdr.type == DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT ) - // dap_chain_net_vpn_client_pkt_in( a_ch, l_pkt); - if(l_pkt->hdr.type != DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT) { - static bool client_connected = false; - ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data; - size_t l_vpn_pkt_size = l_pkt->hdr.size - sizeof (l_vpn_pkt->header); + ch_vpn_pkt_t * l_vpn_pkt = (ch_vpn_pkt_t *) l_pkt->data; + size_t l_vpn_pkt_size = l_pkt->hdr.size - sizeof (l_vpn_pkt->header); - int remote_sock_id = l_vpn_pkt->header.sock_id; + if (s_debug_more) + log_it(L_INFO, "Got srv_vpn packet with op_code=0x%02x", l_vpn_pkt->header.op_code); - //log_it(L_DEBUG, "Got SF packet with id %d op_code 0x%02x", remote_sock_id, sf_pkt->header.op_code); - if(l_vpn_pkt->header.op_code >= 0xb0) { // Raw packets - switch (l_vpn_pkt->header.op_code) { + if(l_vpn_pkt->header.op_code >= 0xb0) { // Raw packets + switch (l_vpn_pkt->header.op_code) { case VPN_PACKET_OP_CODE_PING: - a_ch->stream->events_socket->last_ping_request = time(NULL); + a_ch->stream->esocket->last_ping_request = time(NULL); + l_srv_session->stats.bytes_recv += l_vpn_pkt_size; + l_srv_session->stats.packets_recv++; send_pong_pkt(a_ch); - break; + break; case VPN_PACKET_OP_CODE_PONG: - a_ch->stream->events_socket->last_ping_request = time(NULL); - break; + a_ch->stream->esocket->last_ping_request = time(NULL); + l_srv_session->stats.bytes_recv += l_vpn_pkt_size; + l_srv_session->stats.packets_recv++; + break; // for client case VPN_PACKET_OP_CODE_VPN_ADDR_REPLY: { // Assigned address for peer if(ch_sf_tun_addr_leased(CH_VPN(a_ch), l_vpn_pkt, l_vpn_pkt_size) < 0) { log_it(L_ERROR, "Can't create tun"); - } - } - break; + }else + s_tun_send_msg_ip_assigned_all(CH_VPN(a_ch), CH_VPN(a_ch)->addr_ipv4); + l_srv_session->stats.bytes_recv += l_vpn_pkt_size; + l_srv_session->stats.packets_recv++; + } break; // for server case VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST: { // Client request after L3 connection the new IP address log_it(L_INFO, "Received address request "); - if ( l_ch_vpn->addr_ipv4.s_addr ){ - log_it(L_WARNING,"We already have ip address leased to us"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_ALREADY_ASSIGNED_ADDR; - pkt_out->header.sock_id = s_raw_server->tun_fd; - pkt_out->header.usage_id = l_usage->id; - dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - break; - } - dap_chain_net_srv_vpn_item_ipv4_t * l_item_ipv4 = l_srv_vpn->ipv4_unleased; - if ( l_item_ipv4){ - log_it(L_WARNING,"We have unleased ip address"); - l_ch_vpn->addr_ipv4.s_addr = l_item_ipv4->addr.s_addr; - - pthread_rwlock_wrlock( &s_clients_rwlock ); - HASH_ADD(hh, s_ch_vpn_addrs, addr_ipv4, sizeof (l_ch_vpn->addr_ipv4), l_ch_vpn); - pthread_rwlock_unlock( &s_clients_rwlock ); - - ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, - sizeof(l_pkt_out->header) + sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_host)); - l_pkt_out->header.sock_id = s_raw_server->tun_fd; - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; - l_pkt_out->header.op_data.data_size = sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_host); - l_pkt_out->header.usage_id = l_usage->id; - - memcpy(l_pkt_out->data, &l_ch_vpn->addr_ipv4, sizeof(l_ch_vpn->addr_ipv4)); - memcpy(l_pkt_out->data + sizeof(l_ch_vpn->addr_ipv4), &s_raw_server->ipv4_host, - sizeof(s_raw_server->ipv4_host)); - dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA , l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(l_ch_vpn->addr_ipv4)); - log_it(L_INFO, "\tgateway %s", inet_ntoa(s_raw_server->ipv4_host)); - log_it(L_INFO, "\tmask %s", inet_ntoa(s_raw_server->ipv4_network_mask)); - log_it(L_INFO, "\taddr %s", inet_ntoa(s_raw_server->ipv4_network_addr)); - log_it(L_INFO, "\tlast_addr %s", inet_ntoa(s_raw_server->ipv4_lease_last)); - //dap_stream_ch_set_ready_to_write(a_ch, true); - l_srv_vpn->ipv4_unleased = l_item_ipv4->next; - DAP_DELETE(l_item_ipv4); - }else{ - struct in_addr n_addr = { 0 }, n_addr_max; - n_addr.s_addr = ntohl(s_raw_server->ipv4_lease_last.s_addr); - n_addr.s_addr++; - n_addr_max.s_addr = (ntohl(s_raw_server->ipv4_network_addr.s_addr) - | ~ntohl(s_raw_server->ipv4_network_mask.s_addr)); - - // Just for log output we revert it back and forward - n_addr.s_addr = htonl(n_addr.s_addr); - n_addr_max.s_addr = htonl(n_addr_max.s_addr); - log_it(L_DEBUG, "Check if is address is lesser than"); - log_it(L_DEBUG," new_address = %s", inet_ntoa(n_addr)); - log_it(L_DEBUG," new_address_max = %s", inet_ntoa(n_addr_max)); - n_addr.s_addr = ntohl(n_addr.s_addr); - n_addr_max.s_addr = ntohl(n_addr_max.s_addr); - if(n_addr.s_addr <= n_addr_max.s_addr ) { - n_addr.s_addr = htonl(n_addr.s_addr); - n_addr_max.s_addr = htonl(n_addr_max.s_addr); - - s_raw_server->ipv4_lease_last.s_addr =n_addr.s_addr; - a_ch->stream->session->tun_client_addr.s_addr = n_addr.s_addr; - l_ch_vpn->addr_ipv4.s_addr = n_addr.s_addr; - - log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(n_addr)); - log_it(L_INFO, "\tgateway %s", inet_ntoa(s_raw_server->ipv4_host)); - log_it(L_INFO, "\tmask %s", inet_ntoa(s_raw_server->ipv4_network_mask)); - log_it(L_INFO, "\taddr %s", inet_ntoa(s_raw_server->ipv4_network_addr)); - log_it(L_INFO, "\tlast_addr %s", inet_ntoa(s_raw_server->ipv4_lease_last)); - pthread_rwlock_wrlock( &s_clients_rwlock ); - HASH_ADD(hh, s_ch_vpn_addrs, addr_ipv4, sizeof (l_ch_vpn->addr_ipv4), l_ch_vpn); - pthread_rwlock_unlock( &s_clients_rwlock ); - - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, - sizeof(pkt_out->header) + sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_host)); - pkt_out->header.sock_id = s_raw_server->tun_fd; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; - pkt_out->header.op_data.data_size = sizeof(l_ch_vpn->addr_ipv4) + sizeof(s_raw_server->ipv4_host); - pkt_out->header.usage_id = l_usage->id; - - memcpy(pkt_out->data, &l_ch_vpn->addr_ipv4, sizeof(l_ch_vpn->addr_ipv4)); - memcpy(pkt_out->data + sizeof(l_ch_vpn->addr_ipv4), &s_raw_server->ipv4_host, - sizeof(s_raw_server->ipv4_host)); - - if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header))) { - dap_stream_ch_set_ready_to_write(a_ch, true); - } - - //ch_sf_raw_write(n_addr.s_addr,STREAM_SF_PACKET_OP_CODE_RAW_L3_ADDR_REPLY,&n_addr,sizeof(n_addr)); - } else { // All the network is filled with clients, can't lease a new address - log_it(L_WARNING, "All the network is filled with clients, can't lease a new address"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.sock_id = s_raw_server->tun_fd; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.usage_id = l_usage->id; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_NO_FREE_ADDR; - dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - } - } - } - break; + s_ch_packet_in_vpn_address_request(a_ch, l_usage); + l_srv_session->stats.bytes_recv += l_vpn_pkt_size; + l_srv_session->stats.packets_recv++; + } break; // for client only case VPN_PACKET_OP_CODE_VPN_RECV:{ - a_ch->stream->events_socket->last_ping_request = time(NULL); // not ping, but better ;-) - ch_sf_tun_send(CH_VPN(a_ch), l_vpn_pkt->data, l_vpn_pkt->header.op_data.data_size); - } - break; + a_ch->stream->esocket->last_ping_request = time(NULL); // not ping, but better ;-) + // Find tun socket for current worker + ch_sf_tun_socket_t * l_tun = s_tun_sockets[a_ch->stream_worker->worker->id]; + assert(l_tun); + s_stream_session_esocket_send(l_srv_session, l_tun->es, l_vpn_pkt->data, l_vpn_pkt->header.op_data.data_size); + } break; // for servier only case VPN_PACKET_OP_CODE_VPN_SEND: { - struct in_addr in_saddr, in_daddr; - in_saddr.s_addr = ((struct iphdr*) l_vpn_pkt->data)->saddr; - in_daddr.s_addr = ((struct iphdr*) l_vpn_pkt->data)->daddr; - - char str_daddr[43], str_saddr[43]; - strncpy(str_saddr, inet_ntoa(in_saddr), sizeof(str_saddr)-1); - strncpy(str_daddr, inet_ntoa(in_daddr), sizeof(str_daddr)-1); - - // The packet can't be written, errno == EINVAL !!! - //log_it(L_DEBUG, "VPN packet, source: %s; dest: %s", inet_ntoa(in_saddr), inet_ntoa(in_daddr)); - int ret; - //if( ch_sf_raw_write(STREAM_SF_PACKET_OP_CODE_RAW_SEND, sf_pkt->data, sf_pkt->op_data.data_size)<0){ - /*struct sockaddr_in sin = { 0 }; - sin.sin_family = AF_INET; - sin.sin_port = 0; - sin.sin_addr.s_addr = in_daddr.s_addr;*/ - - - //if((ret=sendto(CH_SF(ch)->raw_l3_sock , sf_pkt->data,sf_pkt->header.op_data.data_size,0,(struct sockaddr *) &sin, sizeof (sin)))<0){ - if((ret = write(s_raw_server->tun_fd, l_vpn_pkt->data, l_vpn_pkt->header.op_data.data_size)) < 0) { - log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno)); - //log_it(L_ERROR,"raw socket ring buffer overflowed"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST; - pkt_out->header.sock_id = s_raw_server->tun_fd; - dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - } else { - s_update_limits (a_ch, l_srv_session, l_usage,(size_t) ret ); - //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", - // str_saddr, str_daddr, sf_pkt->header.op_data.data_size, ret); - //log_it(L_DEBUG, "Raw IP sent %u bytes ", ret); - } - //} - } - break; + ch_sf_tun_socket_t * l_tun = s_tun_sockets[a_ch->stream_worker->worker->id]; + assert(l_tun); + // Unsafely send it + size_t l_ret = s_stream_session_esocket_send(l_srv_session, l_tun->es, l_vpn_pkt->data, l_vpn_pkt->header.op_data.data_size); + if( l_ret) + s_update_limits (a_ch, l_srv_session, l_usage,l_ret ); + } break; default: log_it(L_WARNING, "Can't process SF type 0x%02x", l_vpn_pkt->header.op_code); - } - } else { // All except CONNECT - ch_vpn_socket_proxy_t * sf_sock = NULL; - if(l_vpn_pkt->header.op_code != VPN_PACKET_OP_CODE_CONNECT) { - - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - // log_it(L_DEBUG,"Looking in hash table with %d",remote_sock_id); - HASH_FIND_INT((CH_VPN(a_ch)->socks), &remote_sock_id, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - if(sf_sock != NULL) { - pthread_mutex_lock(&sf_sock->mutex); // Unlock it in your case as soon as possible to reduce lock time - sf_sock->time_lastused = time(NULL); - switch (l_vpn_pkt->header.op_code) { - case VPN_PACKET_OP_CODE_SEND: { - if(client_connected == false) - { - log_it(L_WARNING, "Drop Packet! User not connected!"); // Client need send - pthread_mutex_unlock(&s_sf_socks_mutex); - break; - } - int ret; - if((ret = send(sf_sock->sock, l_vpn_pkt->data, l_vpn_pkt->header.op_data.data_size, 0)) < 0) { - log_it(L_INFO, "Disconnected from the remote host"); - pthread_mutex_unlock(&sf_sock->mutex); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(CH_VPN(a_ch)->socks, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&s_sf_socks_mutex); - HASH_DELETE(hh2, sf_socks, sf_sock); - HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - - struct epoll_event ev = {0, {0}}; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Removed sock_id %d from the the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=0",sf_pkt->sock_id, sf_pkt->op_code); - } - pthread_mutex_unlock(&s_sf_socks_mutex); - - s_ch_proxy_delete(sf_sock); - } else { - sf_sock->bytes_sent += ret; - pthread_mutex_unlock(&sf_sock->mutex); - } - //log_it(L_INFO, "Send action from %d sock_id (sf_packet size %lu, ch packet size %lu, have sent %d)" - // , sf_sock->id, sf_pkt->header.op_data.data_size, l_pkt->hdr.size, ret); - } - break; - case VPN_PACKET_OP_CODE_DISCONNECT: { - log_it(L_INFO, "Disconnect action from %d sock_id", sf_sock->id); - - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(CH_VPN(a_ch)->socks, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&s_sf_socks_mutex); - HASH_DELETE(hh2, sf_socks, sf_sock); - HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - struct epoll_event ev = {0, {0}};; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Removed sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=0",sf_pkt->sock_id, sf_pkt->op_code); - } - pthread_mutex_unlock(&s_sf_socks_mutex); - - pthread_mutex_unlock(&sf_sock->mutex); - s_ch_proxy_delete(sf_sock); - } - break; - default: { - log_it(L_WARNING, "Unprocessed op code 0x%02x", l_vpn_pkt->header.op_code); - pthread_mutex_unlock(&sf_sock->mutex); - } - } - } //else - // log_it(L_WARNING, "Packet input: packet with sock_id %d thats not present in current stream channel", - // remote_sock_id); - } else { - HASH_FIND_INT(CH_VPN(a_ch)->socks, &remote_sock_id, sf_sock); - if(sf_sock) { - log_it(L_WARNING, "Socket id %d is already used, take another number for socket id", remote_sock_id); - } else { // Connect action - struct sockaddr_in remote_addr; - char addr_str[1024]; - size_t addr_str_size = - (l_vpn_pkt->header.op_connect.addr_size > (sizeof(addr_str) - 1)) ? - (sizeof(addr_str) - 1) : - l_vpn_pkt->header.op_connect.addr_size; - memset(&remote_addr, 0, sizeof(remote_addr)); - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(l_vpn_pkt->header.op_connect.port); - - memcpy(addr_str, l_vpn_pkt->data, addr_str_size); - addr_str[addr_str_size] = 0; - - log_it(L_DEBUG, "Connect action to %s:%u (addr_size %lu)", addr_str, l_vpn_pkt->header.op_connect.port, - l_vpn_pkt->header.op_connect.addr_size); - if(inet_pton(AF_INET, addr_str, &(remote_addr.sin_addr)) < 0) { - log_it(L_ERROR, "Wrong remote address '%s:%u'", addr_str, l_vpn_pkt->header.op_connect.port); - } else { - int s; - if((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0) { - log_it(L_DEBUG, "Socket is created (%d)", s); - if(connect(s, (struct sockaddr *) &remote_addr, sizeof(remote_addr)) >= 0) { - fcntl(s, F_SETFL, O_NONBLOCK); - log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", addr_str, - l_vpn_pkt->header.op_connect.port, remote_sock_id); - ch_vpn_socket_proxy_t * sf_sock = NULL; - sf_sock = DAP_NEW_Z(ch_vpn_socket_proxy_t); - sf_sock->id = remote_sock_id; - sf_sock->sock = s; - sf_sock->ch = a_ch; - pthread_mutex_init(&sf_sock->mutex, NULL); - - pthread_mutex_lock(&s_sf_socks_mutex); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_ADD_INT(CH_VPN(a_ch)->socks, id, sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh2, sf_socks, id, sizeof(sf_sock->id), sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh_sock, sf_socks_client, sock, sizeof(int), sf_sock); - //log_it(L_DEBUG,"Added %d sock_id with sock %d to the socks hash table",sf->id,sf->sock); - pthread_mutex_unlock(&s_sf_socks_mutex); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - struct epoll_event ev = {0, {0}}; - ev.data.fd = s; - ev.events = EPOLLIN | EPOLLERR; - - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_ADD, s, &ev) == -1) { - log_it(L_ERROR, "Can't add sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Added sock_id %d with sock %d to the epoll fd", remote_sock_id, s); - log_it(L_NOTICE, "Send Connected packet to User"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.sock_id = remote_sock_id; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_CONNECTED; - dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - free(pkt_out); - client_connected = true; - } - dap_stream_ch_set_ready_to_write(a_ch, true); - } else { - log_it(L_INFO, "Can't connect to the remote server %s", addr_str); - dap_stream_ch_pkt_write_f(a_ch, 'i', "sock_id=%d op_code=%c result=-1", - l_vpn_pkt->header.sock_id, l_vpn_pkt->header.op_code); - dap_stream_ch_set_ready_to_write(a_ch, true); - } - } else { - log_it(L_ERROR, "Can't create the socket"); - } - } - } - } } } } +/** + * @brief s_stream_session_esocket_send + * @param l_srv_session + * @param l_es + * @param a_data + * @param a_data_size + */ +static size_t s_stream_session_esocket_send(dap_chain_net_srv_stream_session_t * l_srv_session, dap_events_socket_t * l_es, const void * a_data, size_t a_data_size ) +{ + // Lets first try to send it directly with write() call + ssize_t l_direct_wrote; + size_t l_ret = 0; + if (l_es->type == DESCRIPTOR_TYPE_FILE ) + l_direct_wrote = write(l_es->fd, a_data, a_data_size); + else + l_direct_wrote = send(l_es->fd, a_data, a_data_size, MSG_DONTWAIT | MSG_NOSIGNAL); + int l_errno = errno; + + size_t l_data_left_to_send=0; + if (l_direct_wrote > 0){ + l_ret += l_direct_wrote; + if((size_t) l_direct_wrote < a_data_size){ // If we sent not all - lets put tail in buffer + l_data_left_to_send = a_data_size-l_direct_wrote; + }else{ + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_direct_wrote; + } + }else{ + l_data_left_to_send = a_data_size; + l_direct_wrote=0; + if(l_errno != EAGAIN && l_errno != EWOULDBLOCK){ + char l_errbuf[128]; + strerror_r(l_errno, l_errbuf, sizeof (l_errbuf)); + log_it(L_WARNING,"Error with data sent: \"%s\" code %d",l_errbuf, l_errno); + } + } + + if(l_data_left_to_send){ + //if ( dap_events_socket_write_unsafe( l_es, a_data +l_direct_wrote,l_data_left_to_send + // ) < l_data_left_to_send ){ + //log_it(L_WARNING,"Loosing data, probably buffers are overfilling, lost %zd bytes", l_data_left_to_send); + log_it(L_WARNING,"Loosing data, lost %zd bytes", l_data_left_to_send); + l_srv_session->stats.bytes_sent_lost += l_data_left_to_send; + l_srv_session->stats.packets_sent_lost++; + /*}else{ + l_ret += l_data_left_to_send; + l_srv_session->stats.packets_sent++; + l_srv_session->stats.bytes_sent+= l_direct_wrote; + }*/ + } + return l_ret; +} + /** * @brief stream_sf_packet_out Packet Out Ch callback * @param ch @@ -1287,407 +1399,132 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) static void s_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) { (void) a_arg; - ch_vpn_socket_proxy_t * cur, *tmp; dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION( a_ch->stream->session ); dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(a_ch); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); + dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_ch_vpn->usage_id); if ( ! l_usage){ log_it(L_NOTICE, "No active usage in list, possible disconnected. Send nothin on this channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); return; } if ( ! l_usage->is_active ){ log_it(L_INFO, "Usage inactivation: switch off packet output channel"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - if (l_usage->clients) - dap_stream_ch_pkt_write( l_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + if (l_usage->client) + dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); return; } if ( (! l_usage->is_free) && (! l_usage->receipt) ){ log_it(L_WARNING, "No active receipt, switching off"); - dap_stream_ch_set_ready_to_write(a_ch,false); - dap_stream_ch_set_ready_to_read(a_ch,false); - if (l_usage->clients) - dap_stream_ch_pkt_write( l_usage->clients->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); + if (l_usage->client) + dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); return; } + // Check for empty buffer out here to prevent warnings in worker + if ( ! a_ch->stream->esocket->buf_out_size ) + dap_events_socket_set_writable_unsafe(a_ch->stream->esocket,false); - bool l_is_smth_out = false; -// log_it(L_DEBUG,"Socket forwarding packet out callback: %u sockets in hashtable", HASH_COUNT(CH_SF(ch)->socks) ); - HASH_ITER(hh, l_ch_vpn->socks , cur, tmp) - { - bool l_signal_to_break = false; - pthread_mutex_lock(&(cur->mutex)); - size_t i; - //log_it(L_DEBUG, "Socket with id %d has %u packets in output buffer", cur->id, cur->pkt_out_size); - if(cur->pkt_out_size) { - for(i = 0; i < cur->pkt_out_size; i++) { - ch_vpn_pkt_t * pout = cur->pkt_out[i]; - if(pout) { - size_t l_wrote_size; - if((l_wrote_size = dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pout, - pout->header.op_data.data_size + sizeof(pout->header)))>0 ) { - l_is_smth_out = true; - DAP_DELETE(pout); - cur->pkt_out[i] = NULL; - } else { - log_it(L_WARNING, "Buffer is overflowed, breaking cycle to let the upper level cycle drop data to the output socket"); - l_is_smth_out = true; - l_signal_to_break = true; - break; - } - s_update_limits (a_ch, l_srv_session, l_usage,l_wrote_size ); - } - } - } - - if(l_signal_to_break) { - pthread_mutex_unlock(&(cur->mutex)); - break; - } - cur->pkt_out_size = 0; - if(cur->signal_to_delete) { - log_it(L_NOTICE, "Socket id %d got signal to be deleted", cur->id); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(l_ch_vpn->socks, cur); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&(s_sf_socks_mutex)); - HASH_DELETE(hh2, sf_socks, cur); - HASH_DELETE(hh_sock, sf_socks_client, cur); - pthread_mutex_unlock(&(s_sf_socks_mutex)); - - pthread_mutex_unlock(&(cur->mutex)); - s_ch_proxy_delete(cur); - } else - pthread_mutex_unlock(&(cur->mutex)); - } - if(l_is_smth_out) { - if(a_ch->stream->conn_http) - a_ch->stream->conn_http->state_write = DAP_HTTP_CLIENT_STATE_DATA; - } - - dap_stream_ch_set_ready_to_write(a_ch, l_is_smth_out); } -/** - * @brief stream_sf_disconnect - * @param sf - */ -void srv_stream_sf_disconnect(ch_vpn_socket_proxy_t * sf_sock) +void m_es_tun_delete(dap_events_socket_t * a_es, void * arg) { - struct epoll_event ev = {0, {0}}; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN | EPOLLERR; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) == -1) { - log_it(L_ERROR, "Can't del sock_id %d from the epoll fd", sf_sock->id); - //stream_ch_pkt_write_f(sf->ch,'i',"sock_id=%d op_code=%uc result=-1",sf->id, STREAM_SF_PACKET_OP_CODE_RECV); - } else { - log_it(L_ERROR, "Removed sock_id %d from the epoll fd", sf_sock->id); - //stream_ch_pkt_write_f(sf->ch,'i',"sock_id=%d op_code=%uc result=0",sf->id, STREAM_SF_PACKET_OP_CODE_RECV); - } - - // Compise signal to disconnect to another side, with special opcode STREAM_SF_PACKET_OP_CODE_DISCONNECT - ch_vpn_pkt_t * pkt_out; - pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + 1); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_DISCONNECT; - pkt_out->header.sock_id = sf_sock->id; - sf_sock->pkt_out[sf_sock->pkt_out_size] = pkt_out; - sf_sock->pkt_out_size++; - sf_sock->signal_to_delete = true; + s_tun_sockets[a_es->worker->id] = NULL; + dap_events_socket_remove_and_delete_unsafe(s_tun_sockets_queue_msg[a_es->worker->id],false); + log_it(L_NOTICE,"Destroyed TUN event socket"); } -/** +void m_es_tun_read(dap_events_socket_t * a_es, void * arg) +{ + ch_sf_tun_socket_t * l_tun_socket = CH_SF_TUN_SOCKET(a_es); + assert(l_tun_socket); + size_t l_buf_in_size = a_es->buf_in_size; + //log_it(L_DEBUG,"m_es_tun_read() received ip pacet %u size", l_buf_in_size); - Socket forward - **/ + if(l_buf_in_size) { + struct iphdr *iph = (struct iphdr*) a_es->buf_in; + struct in_addr l_in_daddr; + l_in_daddr.s_addr = iph->daddr; -void * srv_ch_sf_thread(void * a_arg) -{ - UNUSED(a_arg); - struct epoll_event ev = {0, {0}}, events[SF_MAX_EVENTS] = { {0, {0}} }; - //pthread_mutex_lock(&sf_socks_mutex); - sf_socks_epoll_fd = epoll_create(SF_MAX_EVENTS); - sigset_t sf_sigmask; - sigemptyset(&sf_sigmask); - sigaddset(&sf_sigmask, SIGUSR2); - - while(1) { - int nfds = epoll_pwait(sf_socks_epoll_fd, events, SF_MAX_EVENTS, 10000, &sf_sigmask); - if(nfds < 0) { - //log_it(L_CRITICAL,"Can't run epoll_wait: %s",strerror(errno)); - continue; + // + dap_chain_net_srv_ch_vpn_info_t * l_vpn_info = NULL; + // Try to find in worker's clients, without locks + if ( l_tun_socket->clients){ + HASH_FIND_INT( l_tun_socket->clients,&l_in_daddr.s_addr,l_vpn_info ); } - if(nfds > 0) - log_it(L_DEBUG, "Epolled %d fd", nfds); - else - continue; - int n; - for(n = 0; n < nfds; ++n) { - int s = events[n].data.fd; - - ch_vpn_socket_proxy_t * l_socket_proxy = NULL; - pthread_mutex_lock(&s_sf_socks_mutex); - HASH_FIND(hh_sock, sf_socks_client, &s, sizeof(s), l_socket_proxy); - pthread_mutex_unlock(&s_sf_socks_mutex); - if( l_socket_proxy ) { - dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (l_socket_proxy->ch->stream->session ); - dap_chain_net_srv_ch_vpn_t *l_ch_vpn = CH_VPN(l_socket_proxy->ch); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); - - if(events[n].events & EPOLLERR) { - log_it(L_NOTICE, "Socket id %d has EPOLLERR flag on", s); - pthread_mutex_lock(&(l_socket_proxy->mutex)); - srv_stream_sf_disconnect(l_socket_proxy); - pthread_mutex_unlock(&(l_socket_proxy->mutex)); - } else if(events[n].events & EPOLLIN) { - char buf[1000000]; - ssize_t ret; - pthread_mutex_lock(&(l_socket_proxy->mutex)); - if(l_socket_proxy->pkt_out_size < ((sizeof(l_socket_proxy->pkt_out) / sizeof(l_socket_proxy->pkt_out[0])) - 1)) { - ret = recv(l_socket_proxy->sock, buf, sizeof(buf), 0); - //log_it(L_DEBUG,"recv() returned %d",ret); - if(ret > 0) { - size_t buf_size = ret; - s_update_limits(l_socket_proxy->ch,l_srv_session,l_usage,buf_size); - if ( dap_stream_ch_get_ready_to_read(l_socket_proxy->ch) ){ - ch_vpn_pkt_t * pout; - pout = l_socket_proxy->pkt_out[l_socket_proxy->pkt_out_size] = (ch_vpn_pkt_t *) calloc(1, - buf_size + sizeof(pout->header)); - pout->header.op_code = VPN_PACKET_OP_CODE_RECV; - pout->header.sock_id = l_socket_proxy->id; - pout->header.usage_id = l_usage->id; - pout->header.op_data.data_size = buf_size; - memcpy(pout->data, buf, buf_size); - l_socket_proxy->pkt_out_size++; - pthread_mutex_unlock(&(l_socket_proxy->mutex)); - dap_stream_ch_set_ready_to_write(l_socket_proxy->ch, true); - }else{ - pthread_mutex_unlock(&(l_socket_proxy->mutex)); - } - - } else { - log_it(L_NOTICE, - "Socket id %d returned error on recv() function - may be host has disconnected", s); - pthread_mutex_unlock(&(l_socket_proxy->mutex)); - dap_stream_ch_set_ready_to_write(l_socket_proxy->ch, true); - srv_stream_sf_disconnect(l_socket_proxy); - } - } else { - log_it(L_WARNING, "Can't receive data, full of stack"); - pthread_mutex_unlock(&(l_socket_proxy->mutex)); - } - } else { - log_it(L_WARNING, "Unprocessed flags 0x%08X", events[n].events); - } - } else { - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, s, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d to the epoll fd", s); - } else { - log_it(L_NOTICE, "Socket id %d is removed from the list", s); - } + // We found in local table, sending data (if possible) + if (l_vpn_info){ + if ( !l_vpn_info->is_on_this_worker && !l_vpn_info->is_reassigned_once ){ + log_it(L_NOTICE, "Reassigning from worker %u to %u", l_vpn_info->worker->id, a_es->worker->id); + l_vpn_info->is_reassigned_once = true; + s_tun_send_msg_esocket_reasigned_all_mt(l_vpn_info->ch_vpn, l_vpn_info->esocket, l_vpn_info->addr_ipv4,a_es->worker->id); + dap_events_socket_reassign_between_workers_mt( l_vpn_info->worker,l_vpn_info->esocket,a_es->worker); } + s_tun_client_send_data(l_vpn_info, a_es->buf_in, l_buf_in_size); + }else if(s_debug_more){ + char l_str_daddr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET,&l_in_daddr,l_str_daddr,sizeof (l_in_daddr)); + log_it(L_WARNING, "Can't find route for desitnation %s",l_str_daddr); } - //pthread_mutex_unlock(&sf_socks_mutex); } - return NULL; + a_es->buf_in_size=0; // NULL it out because read it all } -static volatile bool s_srv_ch_sf_thread_raw_is_exit = false; -/* Signal handler. */ -static void s_sig_handle (int sig) +void m_es_tun_error(dap_events_socket_t * a_es, int arg) { - UNUSED(sig); - s_srv_ch_sf_thread_raw_is_exit = true; + if (! a_es->_inheritor) + return; + log_it(L_ERROR,"%s: error in socket %u (socket type %d)", __PRETTY_FUNCTION__, a_es->socket, a_es->type); } -/** - * - * - **/ -void* srv_ch_sf_thread_raw(void *arg) +void m_es_tun_new(dap_events_socket_t * a_es, void * arg) { - UNUSED(arg); - s_tun_create(); - - if(s_raw_server->tun_fd <= 0) { - log_it(L_CRITICAL, "Tun/tap file descriptor is not initialized"); - return NULL; + (void) arg; + ch_sf_tun_socket_t * l_tun_socket = DAP_NEW_Z(ch_sf_tun_socket_t); + if ( l_tun_socket ){ + l_tun_socket->worker = a_es->worker; + l_tun_socket->worker_id = l_tun_socket->worker->id; + l_tun_socket->es = a_es; + s_tun_sockets_queue_msg[a_es->worker->id] = dap_events_socket_create_type_queue_ptr_unsafe(a_es->worker, s_tun_recv_msg_callback ); + s_tun_sockets[a_es->worker->id] = l_tun_socket; + + a_es->_inheritor = l_tun_socket; + s_tun_attach_queue( a_es->fd ); + log_it(L_NOTICE,"New TUN event socket initialized for worker %u" , l_tun_socket->worker_id); + + }else{ + log_it(L_ERROR, "Can't allocate memory for tun socket"); } - /* if (fcntl(raw_server->tun_fd, F_SETFL, O_NONBLOCK) < 0){ ; - log_it(L_CRITICAL,"Can't switch tun/tap socket into the non-block mode"); - return NULL; - } - if (fcntl(raw_server->tun_fd, F_SETFD, FD_CLOEXEC) < 0){; - log_it(L_CRITICAL,"Can't switch tun/tap socket to not be passed across execs"); - return NULL; - } - */ - uint8_t *l_tmp_buf; - ssize_t tmp_buf_size; - static int tun_MTU = 100000; /// TODO Replace with detection of MTU size - - l_tmp_buf = (uint8_t *) alloca(tun_MTU); - if ( !l_tmp_buf){ // Can't allocate on stack - log_it(L_ERROR,"Can't allocate read buffer on stack, trying to get one from heap"); - l_tmp_buf = DAP_NEW_SIZE(uint8_t, tun_MTU); - } - tmp_buf_size = 0; - log_it(L_INFO, "Tun/tap thread starts with MTU = %d", tun_MTU); - - fd_set fds_read, fds_read_active; - sigset_t l_sig_mask_proc; - sigset_t l_sig_mask_orig; - sigemptyset (&l_sig_mask_proc); - sigaddset (&l_sig_mask_proc, SIGTERM); - - - FD_ZERO(&fds_read); - FD_SET(s_raw_server->tun_fd, &fds_read); - FD_SET(get_select_breaker(), &fds_read); - /// Main cycle - do { - fds_read_active = fds_read; - int ret = select(FD_SETSIZE, &fds_read_active, NULL, NULL, NULL); - // - if(ret > 0) { - if(FD_ISSET(get_select_breaker(), &fds_read_active)) { // Smth to send - ch_vpn_pkt_t* pkt = srv_ch_sf_raw_read(); - if(pkt) { - int write_ret = write(s_raw_server->tun_fd, pkt->data, pkt->header.op_data.data_size); - if(write_ret > 0) { - //log_it(L_DEBUG, "Wrote out %d bytes to the tun/tap interface", write_ret); - } else { - log_it(L_ERROR, "Tun/tap write %u bytes returned '%s' error, code (%d)", - pkt->header.op_data.data_size, strerror(errno), write_ret); - } - } - } - - if(FD_ISSET(s_raw_server->tun_fd, &fds_read_active)) { - int l_read_ret = read(s_raw_server->tun_fd, l_tmp_buf, tun_MTU); - if(l_read_ret < 0) { - log_it(L_CRITICAL, "Tun/tap read returned '%s' error, code (%d)", strerror(errno), l_read_ret); - break; - } else { - struct iphdr *iph = (struct iphdr*) l_tmp_buf; - struct in_addr in_daddr, in_saddr; - in_daddr.s_addr = iph->daddr; - in_saddr.s_addr = iph->saddr; - char str_daddr[42], str_saddr[42]; - dap_snprintf(str_saddr, sizeof(str_saddr), "%s",inet_ntoa(in_saddr) ); - dap_snprintf(str_daddr, sizeof(str_daddr), "%s",inet_ntoa(in_daddr) ); - - //log_it(L_DEBUG, "Read IP packet from tun/tap interface daddr=%s saddr=%s total_size = %d " - // , str_daddr, str_saddr, read_ret); - dap_chain_net_srv_ch_vpn_t * l_ch_vpn = NULL; - pthread_rwlock_rdlock(&s_clients_rwlock); - HASH_FIND(hh,s_ch_vpn_addrs, &in_daddr, sizeof (in_daddr), l_ch_vpn); -// HASH_ADD_INT(CH_SF(ch)->socks, id, sf_sock ); -// HASH_DEL(CH_SF(ch)->socks,sf_sock); - - /// - if(l_ch_vpn) { // Is present in hash table such destination address - - if (dap_stream_ch_get_ready_to_read(l_ch_vpn->ch ) ){ - dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (l_ch_vpn->ch->stream->session ); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); - ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, sizeof(l_pkt_out->header) + l_read_ret); - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; - l_pkt_out->header.sock_id = s_raw_server->tun_fd; - l_pkt_out->header.usage_id = l_ch_vpn->usage_id; - l_pkt_out->header.op_data.data_size = l_read_ret; - memcpy(l_pkt_out->data, l_tmp_buf, l_read_ret); - dap_stream_ch_pkt_write(l_ch_vpn->ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - s_update_limits(l_ch_vpn->ch,l_srv_session,l_usage, l_read_ret); - } - } - pthread_rwlock_unlock(&s_clients_rwlock);\ - } - }/*else { - log_it(L_CRITICAL,"select() has no tun handler in the returned set"); - break; - - }*/ - } else { - //log_it(L_WARNING, "Select returned %d: %s", ret, strerror(errno)); - //break; - } - } while(! s_srv_ch_sf_thread_raw_is_exit ); - log_it(L_NOTICE, "Raw sockets listen thread is stopped"); - s_tun_destroy(); - return NULL; -} - -#ifdef DAP_TUN_IN_WORKER -void m_es_tun_delete(dap_events_socket_t * a_es, void * arg) -{ - log_it(L_WARNING, __PRETTY_FUNCTION__); - log_it(L_NOTICE, "Raw sockets listen thread is stopped"); - dap_events_socket_kill_socket(s_raw_server->tun_events_socket); - s_tun_destroy(); } -void m_es_tun_write(dap_events_socket_t * a_es, void * arg) -{ - -} - -void m_es_tun_read(dap_events_socket_t * a_es, void * arg) +/** + * @brief s_tun_attach_queue + * @param fd + * @return + */ +static int s_tun_attach_queue(int fd) { - const static int tun_MTU = 100000; /// TODO Replace with detection of MTU size - uint8_t l_tmp_buf[tun_MTU]; - - size_t l_read_ret; - - - l_read_ret = dap_events_socket_read(s_raw_server->tun_events_socket, l_tmp_buf, sizeof(l_tmp_buf)); - - if(l_read_ret > 0) { - struct iphdr *iph = (struct iphdr*) l_tmp_buf; - struct in_addr in_daddr, in_saddr; - in_daddr.s_addr = iph->daddr; - in_saddr.s_addr = iph->saddr; - char str_daddr[42], str_saddr[42]; - dap_snprintf(str_saddr, sizeof(str_saddr), "%s",inet_ntoa(in_saddr) ); - dap_snprintf(str_daddr, sizeof(str_daddr), "%s",inet_ntoa(in_daddr) ); - - dap_chain_net_srv_ch_vpn_t * l_ch_vpn = NULL; - pthread_rwlock_rdlock(&s_clients_rwlock); - HASH_FIND(hh,s_ch_vpn_addrs, &in_daddr, sizeof (in_daddr), l_ch_vpn); - - if(l_ch_vpn) { // Is present in hash table such destination address - - if (dap_stream_ch_get_ready_to_read(l_ch_vpn->ch ) ){ - dap_chain_net_srv_stream_session_t * l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION (l_ch_vpn->ch->stream->session ); - dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find(l_srv_session, l_ch_vpn->usage_id); - ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, sizeof(l_pkt_out->header) + l_read_ret); - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; - l_pkt_out->header.sock_id = s_raw_server->tun_fd; - l_pkt_out->header.usage_id = l_ch_vpn->usage_id; - l_pkt_out->header.op_data.data_size = l_read_ret; - memcpy(l_pkt_out->data, l_tmp_buf, l_read_ret); - dap_stream_ch_pkt_write(l_ch_vpn->ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - s_update_limits(l_ch_vpn->ch,l_srv_session,l_usage, l_read_ret); - } - } - pthread_rwlock_unlock(&s_clients_rwlock); - } - - - dap_events_socket_set_readable(a_es, true); + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_ATTACH_QUEUE; + return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } -void m_es_tun_error(dap_events_socket_t * a_es, void * arg) +/** + * @brief s_tun_deattach_queue + * @param fd + * @return + */ +static int s_tun_deattach_queue(int fd) { - log_it(L_WARNING, __PRETTY_FUNCTION__); + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_DETACH_QUEUE; + return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } -#endif - diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c index ce9f46417292427b0b42e8359cd9dbe1e8dddc0f..d676903d06a3d87c6d0dbd4f3930ba43bb5feee3 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c @@ -230,6 +230,5 @@ int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_repl int dap_chain_net_srv_vpn_cmd_init() { - - + return 0; } diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index 41f1d101f801ac05c73c4ff2b55ea76a9b398fe9..35684d2e56e6c2fd1bc18079a7fb36d0a470e75f 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -81,14 +81,19 @@ static EPOLL_HANDLE sf_socks_epoll_fd; -static ch_vpn_socket_proxy_t *sf_socks = NULL; -static ch_vpn_socket_proxy_t *sf_socks_client = NULL; static pthread_mutex_t sf_socks_mutex; static dap_chain_node_info_t *s_node_info = NULL; static dap_chain_node_client_t *s_vpn_client = NULL; +dap_stream_worker_t* dap_chain_net_vpn_client_get_stream_worker(void) +{ + if(!s_vpn_client) + return NULL; + return dap_client_get_stream_worker( s_vpn_client->client ); +} + dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void) { if(!s_vpn_client) @@ -477,8 +482,8 @@ int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_st l_request->time_connect_ms = l_dtime_connect_ms; gettimeofday(&l_request->send_time1, NULL); size_t l_request_size = l_request->data_size + sizeof(dap_stream_ch_chain_net_srv_pkt_test_t); - dap_stream_ch_pkt_write(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST, l_request, l_request_size); - dap_stream_ch_set_ready_to_write(l_ch, true); + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST, l_request, l_request_size); + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); DAP_DELETE(l_request); } } @@ -568,8 +573,8 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st //dap_chain_hash_fast_t l_request //.hdr.tx_cond = a_txCond.value(); // strncpy(l_request->hdr.token, a_token.toLatin1().constData(),sizeof (l_request->hdr.token)-1); - dap_stream_ch_pkt_write(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST, &l_request, sizeof(l_request)); - dap_stream_ch_set_ready_to_write(l_ch, true); + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST, &l_request, sizeof(l_request)); + dap_stream_ch_set_ready_to_write_unsafe(l_ch, true); } } @@ -606,14 +611,6 @@ dap_chain_net_vpn_client_status_t dap_chain_net_vpn_client_status(void) return VPN_CLIENT_STATUS_STOPPED; } -static void vpn_socket_delete(ch_vpn_socket_proxy_t * sf) -{ - close(sf->sock); - pthread_mutex_destroy(&(sf->mutex)); - if(sf) - free(sf); -} - /** * @brief dap_chain_net_vpn_client_pkt_in * @param a_ch @@ -664,200 +661,12 @@ void dap_chain_net_vpn_client_pkt_in(dap_stream_ch_t* a_ch, dap_stream_ch_pkt_t* a_ch->stream->events_socket->last_ping_request = time(NULL); break; */ - default: - log_it(L_WARNING, "Can't process SF type 0x%02x", l_sf_pkt->header.op_code); - } - } else { // All except CONNECT - ch_vpn_socket_proxy_t * sf_sock = NULL; - if((l_sf_pkt->header.op_code != VPN_PACKET_OP_CODE_CONNECT) // tcp - && (l_sf_pkt->header.op_code != VPN_PACKET_OP_CODE_CONNECTED)) { //udp - - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - log_it(L_DEBUG, "Looking in hash table with %d", remote_sock_id); - HASH_FIND_INT((CH_VPN(a_ch)->socks), &remote_sock_id, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - if(sf_sock != NULL) { - pthread_mutex_lock(&sf_sock->mutex); // Unlock it in your case as soon as possible to reduce lock time - sf_sock->time_lastused = time(NULL); - switch (l_sf_pkt->header.op_code) { - case VPN_PACKET_OP_CODE_SEND: { - int ret; - if((ret = send(sf_sock->sock, l_sf_pkt->data, l_sf_pkt->header.op_data.data_size, 0)) < 0) { - log_it(L_INFO, "Disconnected from the remote host"); - pthread_mutex_unlock(&sf_sock->mutex); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(CH_VPN(a_ch)->socks, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&sf_socks_mutex); - HASH_DELETE(hh2, sf_socks, sf_sock); - HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - - struct epoll_event ev = {0, {0}}; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Removed sock_id %d from the the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=0",sf_pkt->sock_id, sf_pkt->op_code); - } - pthread_mutex_unlock(&sf_socks_mutex); - - vpn_socket_delete(sf_sock); - } else { - sf_sock->bytes_sent += ret; - pthread_mutex_unlock(&sf_sock->mutex); - } - log_it(L_INFO, "Send action from %d sock_id (sf_packet size %lu, ch packet size %lu, have sent %d)" - , sf_sock->id, l_sf_pkt->header.op_data.data_size, a_pkt->hdr.size, ret); - } - break; - case VPN_PACKET_OP_CODE_DISCONNECT: { - log_it(L_INFO, "Disconnect action from %d sock_id", sf_sock->id); - - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(CH_VPN(a_ch)->socks, sf_sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&sf_socks_mutex); - - HASH_DELETE(hh2, sf_socks, sf_sock); - HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - - struct epoll_event ev = {0, {0}}; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Removed sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=0",sf_pkt->sock_id, sf_pkt->op_code); - } - pthread_mutex_unlock(&sf_socks_mutex); - - pthread_mutex_unlock(&sf_sock->mutex); - vpn_socket_delete(sf_sock); - } - break; - default: { - log_it(L_WARNING, "Unprocessed op code 0x%02x", l_sf_pkt->header.op_code); - pthread_mutex_unlock(&sf_sock->mutex); - } - } - } else - log_it(L_WARNING, "Packet input: packet with sock_id %d thats not present in current stream channel", - remote_sock_id); - } else { - HASH_FIND_INT(CH_VPN(a_ch)->socks, &remote_sock_id, sf_sock); - if(sf_sock) { - log_it(L_WARNING, "Socket id %d is already used, take another number for socket id", remote_sock_id); - } else { // Connect action - struct sockaddr_in remote_addr; - char addr_str[1024]; - size_t addr_str_size = - (l_sf_pkt->header.op_connect.addr_size > (sizeof(addr_str) - 1)) ? - (sizeof(addr_str) - 1) : - l_sf_pkt->header.op_connect.addr_size; - memset(&remote_addr, 0, sizeof(remote_addr)); - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(l_sf_pkt->header.op_connect.port); - - memcpy(addr_str, l_sf_pkt->data, addr_str_size); - addr_str[addr_str_size] = 0; - - log_it(L_DEBUG, "Connect action to %s:%u (addr_size %lu)", addr_str, l_sf_pkt->header.op_connect.port, - l_sf_pkt->header.op_connect.addr_size); - if(inet_pton(AF_INET, addr_str, &(remote_addr.sin_addr)) < 0) { - log_it(L_ERROR, "Wrong remote address '%s:%u'", addr_str, l_sf_pkt->header.op_connect.port); - - ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z(ch_vpn_pkt_t); - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - - dap_stream_ch_pkt_write(a_ch, 'd', l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - - free(l_pkt_out); - - } else { - int s; - if((s = socket(AF_INET, - (l_sf_pkt->header.op_code == VPN_PACKET_OP_CODE_CONNECT) ? - SOCK_STREAM : - SOCK_DGRAM, 0)) >= 0) { - log_it(L_DEBUG, "Socket is created (%d)", s); - if(connect(s, (struct sockaddr *) &remote_addr, sizeof(remote_addr)) >= 0) { - fcntl(s, F_SETFL, O_NONBLOCK); - log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", addr_str, - l_sf_pkt->header.op_connect.port, remote_sock_id); - ch_vpn_socket_proxy_t * sf_sock = NULL; - sf_sock = DAP_NEW_Z(ch_vpn_socket_proxy_t); - sf_sock->id = remote_sock_id; - sf_sock->sock = s; - sf_sock->ch = a_ch; - pthread_mutex_init(&sf_sock->mutex, NULL); - - pthread_mutex_lock(&sf_socks_mutex); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_ADD_INT(CH_VPN(a_ch)->socks, id, sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh2, sf_socks, id, sizeof(sf_sock->id), sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh_sock, sf_socks_client, sock, sizeof(int), sf_sock); - // log_it(L_DEBUG,"Added %d sock_id with sock %d to the socks hash table",sf->id,sf->sock); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - pthread_mutex_unlock(&sf_socks_mutex); - - struct epoll_event ev = { 0, {0} }; - ev.data.fd = s; - ev.events = EPOLLIN | EPOLLERR; - - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_ADD, s, &ev) == -1) { - log_it(L_ERROR, "Can't add sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Added sock_id %d with sock %d to the epoll fd", remote_sock_id, s); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=0",sf_pkt->sock_id, sf_pkt->op_code); - } - dap_stream_ch_set_ready_to_write(a_ch, true); - } else { - ch_vpn_pkt_t *l_pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(l_pkt_out->header)); - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - - dap_stream_ch_pkt_write(a_ch, 'd', l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - - free(l_pkt_out); - - log_it(L_INFO, "Can't connect to the remote server %s", addr_str); - dap_stream_ch_pkt_write_f(a_ch, 'i', "sock_id=%d op_code=%c result=-1", - l_sf_pkt->header.sock_id, l_sf_pkt->header.op_code); - dap_stream_ch_set_ready_to_write(a_ch, true); - - } - } else { - log_it(L_ERROR, "Can't create the socket"); - ch_vpn_pkt_t *l_pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(l_pkt_out->header)); - l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - - dap_stream_ch_pkt_write(a_ch, 'd', l_pkt_out, - l_pkt_out->header.op_data.data_size + sizeof(l_pkt_out->header)); - dap_stream_ch_set_ready_to_write(a_ch, true); - - free(l_pkt_out); - - } - } - } + default: + log_it(L_WARNING, "Can't process SF type 0x%02x", l_sf_pkt->header.op_code); } + } + } /** @@ -866,57 +675,6 @@ void dap_chain_net_vpn_client_pkt_in(dap_stream_ch_t* a_ch, dap_stream_ch_pkt_t* */ void dap_chain_net_vpn_client_pkt_out(dap_stream_ch_t* a_ch) { - ch_vpn_socket_proxy_t * l_cur = NULL, *l_tmp; - bool l_is_smth_out = false; -// log_it(L_DEBUG,"Socket forwarding packet out callback: %u sockets in hashtable", HASH_COUNT(CH_VPN(ch)->socks) ); - HASH_ITER(hh, CH_VPN(a_ch)->socks , l_cur, l_tmp) - { - bool l_signal_to_break = false; - pthread_mutex_lock(&(l_cur->mutex)); - int i; -// log_it(L_DEBUG,"Socket with id %d has %u packets in output buffer", cur->id, cur->pkt_out_size ); - if(l_cur->pkt_out_size) { - for(i = 0; i < l_cur->pkt_out_size; i++) { - ch_vpn_pkt_t * pout = l_cur->pkt_out[i]; - if(pout) { - if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pout, - pout->header.op_data.data_size + sizeof(pout->header))) { - l_is_smth_out = true; - if(pout) - free(pout); - l_cur->pkt_out[i] = NULL; - } else { - log_it(L_WARNING, - "Buffer is overflowed, breaking cycle to let the upper level cycle drop data to the output socket"); - l_is_smth_out = true; - l_signal_to_break = true; - break; - } - } - } - } - - if(l_signal_to_break) { - pthread_mutex_unlock(&(l_cur->mutex)); - break; - } - l_cur->pkt_out_size = 0; - if(l_cur->signal_to_delete) { - log_it(L_NOTICE, "Socket id %d got signal to be deleted", l_cur->id); - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - HASH_DEL(CH_VPN(a_ch)->socks, l_cur); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - pthread_mutex_lock(&(sf_socks_mutex)); - HASH_DELETE(hh2, sf_socks, l_cur); - HASH_DELETE(hh_sock, sf_socks_client, l_cur); - pthread_mutex_unlock(&(sf_socks_mutex)); - - pthread_mutex_unlock(&(l_cur->mutex)); - vpn_socket_delete(l_cur); - } else - pthread_mutex_unlock(&(l_cur->mutex)); - } /* ch->writable = isSmthOut; if(isSmthOut) { if(ch->stream->conn_http) @@ -944,5 +702,4 @@ int dap_chain_net_vpn_client_init(dap_config_t * g_config) void dap_chain_net_vpn_client_deinit() { - pthread_mutex_destroy(&sf_socks_mutex); } diff --git a/modules/service/vpn/dap_chain_net_vpn_client_tun.c b/modules/service/vpn/dap_chain_net_vpn_client_tun.c index cde51a32662596848ce826e6fe2974f3d045177e..ca890bcfc029c4cf4b47e4cc8844dac5dec5096f 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client_tun.c +++ b/modules/service/vpn/dap_chain_net_vpn_client_tun.c @@ -46,6 +46,7 @@ #include "dap_strfuncs.h" #include "dap_stream.h" #include "dap_stream_ch_pkt.h" +#include "dap_client.h" #include <arpa/inet.h> #include <fcntl.h> @@ -71,7 +72,6 @@ static char *s_cur_ipv4_server = NULL; static const char *s_conn_name = "nodeVPNClient"; static char *s_last_used_connection_name = NULL, *s_last_used_connection_device = NULL; -static pthread_t s_thread_read_tun_id; static pthread_mutex_t s_clients_mutex; static dap_events_socket_t * s_tun_events_socket = NULL; @@ -230,137 +230,6 @@ static bool is_local_address(const char *a_address) } -/** - * Thread for read from /dev/net/tun - */ -static void* thread_read_tun(void *arg) -{ - //srv_ch_sf_tun_create(); - - if(s_fd_tun <= 0) { - log_it(L_CRITICAL, "Tun/tap file descriptor is not initialized"); - return NULL; - } - /* if (fcntl(raw_server->tun_fd, F_SETFL, O_NONBLOCK) < 0){ ; - log_it(L_CRITICAL,"Can't switch tun/tap socket into the non-block mode"); - return NULL; - } - if (fcntl(raw_server->tun_fd, F_SETFD, FD_CLOEXEC) < 0){; - log_it(L_CRITICAL,"Can't switch tun/tap socket to not be passed across execs"); - return NULL; - } - */ - uint8_t *tmp_buf; -// ssize_t tmp_buf_size; - static int tun_MTU = 100000; /// TODO Replace with detection of MTU size - - tmp_buf = (uint8_t *) calloc(1, tun_MTU); -// tmp_buf_size = 0; - log_it(L_INFO, "Tun/tap thread starts with MTU = %d", tun_MTU); - - fd_set fds_read, fds_read_active; - - FD_ZERO(&fds_read); - FD_SET(s_fd_tun, &fds_read); - FD_SET(get_select_breaker(), &fds_read); - /// Main cycle - do { - fds_read_active = fds_read; - int ret = select(FD_SETSIZE, &fds_read_active, NULL, NULL, NULL); - // - if(ret > 0) { - if(FD_ISSET(get_select_breaker(), &fds_read_active)) { // Smth to send - ch_vpn_pkt_t* pkt = NULL; //TODO srv_ch_sf_raw_read(); - if(pkt) { - int write_ret = write(s_fd_tun, pkt->data, pkt->header.op_data.data_size); - if(write_ret > 0) { - log_it(L_DEBUG, "Wrote out %d bytes to the tun/tap interface", write_ret); - } else { - log_it(L_ERROR, "Tun/tap write %u bytes returned '%s' error, code (%d)", - pkt->header.op_data.data_size, strerror(errno), write_ret); - } - } - } - // there is data in tun for sent to vpn server - if(FD_ISSET(s_fd_tun, &fds_read_active)) { - int read_ret = read(s_fd_tun, tmp_buf, tun_MTU); - if(read_ret < 0) { - log_it(L_CRITICAL, "Tun/tap read returned '%s' error, code (%d)", strerror(errno), read_ret); - break; - } else { - struct iphdr *iph = (struct iphdr*) tmp_buf; - struct in_addr in_daddr, in_saddr; - // destination address - in_daddr.s_addr = iph->daddr; - // source address - in_saddr.s_addr = iph->saddr; - char str_daddr[42], str_saddr[42]; - strncpy(str_saddr, inet_ntoa(in_saddr), sizeof(str_saddr)); - strncpy(str_daddr, inet_ntoa(in_daddr), sizeof(str_daddr)); - - if(iph->tot_len > (uint16_t) read_ret) { - log_it(L_INFO, "Tun/Tap interface returned only the fragment (tot_len =%u read_ret=%d) ", - iph->tot_len, read_ret); - } - if(iph->tot_len < (uint16_t) read_ret) { - log_it(L_WARNING, "Tun/Tap interface returned more then one packet (tot_len =%u read_ret=%d) ", - iph->tot_len, read_ret); - } - - log_it(L_DEBUG, "Read IP packet from tun/tap interface daddr=%s saddr=%s total_size = %d " - , str_daddr, str_saddr, read_ret); - - //dap_client_t *l_client = l_vpn_client ? l_vpn_client->client : NULL; - //DAP_CLIENT_PVT(l_client); - //dap_stream_ch_vpn_remote_single_t * raw_client = l_client->; - -// HASH_FIND_INT(raw_server->clients, &in_daddr.s_addr, raw_client); - // HASH_ADD_INT(CH_SF(ch)->socks, id, sf_sock ); - // HASH_DEL(CH_SF(ch)->socks,sf_sock); -// if(l_stream) { // Is present in hash table such destination address - dap_stream_ch_t *l_stream = dap_chain_net_vpn_client_get_stream_ch(); - if(l_stream) { - // form packet to vpn-server - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + read_ret); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_SEND; //VPN_PACKET_OP_CODE_VPN_RECV - pkt_out->header.sock_id = s_fd_tun; - pkt_out->header.op_data.data_size = read_ret; - memcpy(pkt_out->data, tmp_buf, read_ret); - - pthread_mutex_lock(&s_clients_mutex); - // sent packet to vpn server - dap_stream_ch_pkt_write(l_stream, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(l_stream, true); - pthread_mutex_unlock(&s_clients_mutex); - - DAP_DELETE(pkt_out); - } - else { - log_it(L_DEBUG, "No remote client for income IP packet with addr %s", inet_ntoa(in_daddr)); - } - - } - }/*else { - log_it(L_CRITICAL,"select() has no tun handler in the returned set"); - break; - - }*/ - } else { - log_it(L_CRITICAL, "Select returned %d", ret); - break; - } - } while(1); - log_it(L_NOTICE, "Raw sockets listen thread is stopped"); - // close tun - if(s_fd_tun > 0) { - int l_fd_tun = s_fd_tun; - s_fd_tun = 0; - close(l_fd_tun); - } - - return NULL; -} int dap_chain_net_vpn_client_tun_init(const char *a_ipv4_server_str) { @@ -393,7 +262,7 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg) log_it(L_WARNING, __PRETTY_FUNCTION__); do{ - l_read_ret = dap_events_socket_read(a_es, l_tmp_buf, sizeof(l_tmp_buf)); + l_read_ret = dap_events_socket_pop_from_buf_in(a_es, l_tmp_buf, sizeof(l_tmp_buf)); if(l_read_ret > 0) { struct iphdr *iph = (struct iphdr*) l_tmp_buf; @@ -404,8 +273,8 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg) dap_snprintf(str_saddr, sizeof(str_saddr), "%s",inet_ntoa(in_saddr) ); dap_snprintf(str_daddr, sizeof(str_daddr), "%s",inet_ntoa(in_daddr) ); - dap_stream_ch_t *l_stream = dap_chain_net_vpn_client_get_stream_ch(); - if(l_stream) { + dap_stream_ch_t *l_ch = dap_chain_net_vpn_client_get_stream_ch(); + if(l_ch) { // form packet to vpn-server ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + l_read_ret); pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_SEND; //VPN_PACKET_OP_CODE_VPN_RECV @@ -415,9 +284,8 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg) pthread_mutex_lock(&s_clients_mutex); // sent packet to vpn server - dap_stream_ch_pkt_write(l_stream, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + dap_stream_ch_pkt_write_mt(l_ch->stream_worker,l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(l_stream, true); pthread_mutex_unlock(&s_clients_mutex); DAP_DELETE(pkt_out); @@ -428,12 +296,12 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg) } }while(l_read_ret > 0); - dap_events_socket_set_readable(a_es, true); + dap_events_socket_set_readable_unsafe(a_es, true); } -static void m_client_tun_error(dap_events_socket_t * a_es, void * arg) +static void m_client_tun_error(dap_events_socket_t * a_es, int a_arg) { - log_it(L_DEBUG, __PRETTY_FUNCTION__); + log_it(L_WARNING, " TUN client problems: code %d", a_arg); } int dap_chain_net_vpn_client_tun_create(const char *a_ipv4_addr_str, const char *a_ipv4_gw_str) @@ -543,26 +411,19 @@ int dap_chain_net_vpn_client_tun_create(const char *a_ipv4_addr_str, const char pthread_mutex_init(&s_clients_mutex, NULL); - if(is_dap_tun_in_worker()) { + static dap_events_socket_callbacks_t l_s_callbacks = { + .read_callback = m_client_tun_read,// for server + .write_callback = m_client_tun_write,// for client + .error_callback = m_client_tun_error, + .delete_callback = m_client_tun_delete + }; - static dap_events_socket_callbacks_t l_s_callbacks = { - .read_callback = m_client_tun_read,// for server - .write_callback = m_client_tun_write,// for client - .error_callback = m_client_tun_error, - .delete_callback = m_client_tun_delete - }; - - s_tun_events_socket = dap_events_socket_wrap_no_add(NULL, s_fd_tun, &l_s_callbacks); - s_tun_events_socket->type = DESCRIPTOR_TYPE_FILE; - dap_events_socket_create_after(s_tun_events_socket); - s_tun_events_socket->_inheritor = NULL; - - return 0; - } - else { - pthread_create(&s_thread_read_tun_id, NULL, thread_read_tun, NULL); - } + s_tun_events_socket = dap_events_socket_wrap_no_add(dap_events_get_default(), s_fd_tun, &l_s_callbacks); + s_tun_events_socket->type = DESCRIPTOR_TYPE_FILE; + dap_worker_add_events_socket_auto(s_tun_events_socket); + s_tun_events_socket->_inheritor = NULL; + //return 0; //m_tunDeviceName = dev; //m_tunSocket = fd; @@ -571,10 +432,9 @@ int dap_chain_net_vpn_client_tun_create(const char *a_ipv4_addr_str, const char int dap_chain_net_vpn_client_tun_delete(void) { - if(is_dap_tun_in_worker()) - { + if(s_tun_events_socket) { pthread_mutex_lock(&s_clients_mutex); - dap_events_socket_kill_socket(s_tun_events_socket); + dap_events_socket_remove_and_delete_mt(s_tun_events_socket->worker, s_tun_events_socket); s_tun_events_socket = NULL; pthread_mutex_unlock(&s_clients_mutex); } @@ -663,69 +523,57 @@ static void ch_sf_pkt_send(dap_stream_ch_t * a_ch, void * a_data, size_t a_data_ } l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, l_pkt_out_size); l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; - l_pkt_out->header.sock_id = a_ch->stream->events_socket->socket; + l_pkt_out->header.sock_id = a_ch->stream->esocket->socket; l_pkt_out->header.op_data.data_size = a_data_size; memcpy(l_pkt_out->data, a_data, a_data_size); - dap_stream_ch_pkt_write(a_ch, 'd', l_pkt_out, l_pkt_out_size); - dap_stream_ch_set_ready_to_write(a_ch, true); + dap_stream_ch_pkt_write_unsafe(a_ch, 'd', l_pkt_out, l_pkt_out_size); } -void ch_sf_tun_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, size_t pkt_data_size) { - bool passPacket = true; - /*switch(ch_sf_snort_pkt(pkt_data,pkt_data_size)){ - case SNORT_ALERT: passPacket=false; break; - default: passPacket=true; - }*/ -// log_it(L_DEBUG,"==== ch_sf_tun_send()"); - if(passPacket) { -// log_it(L_DEBUG,"==== ch_sf_tun_send() ++"); - struct in_addr in_saddr, in_daddr, in_daddr_net; - in_saddr.s_addr = ((struct iphdr*) pkt_data)->saddr; - in_daddr.s_addr = ((struct iphdr*) pkt_data)->daddr; - in_daddr_net.s_addr = ch_sf->ch->stream->session->tun_client_addr.s_addr; //in_daddr_net.s_addr = in_daddr.s_addr & m_tun_server->int_network_mask.s_addr; - char * in_daddr_str = strdup(inet_ntoa(in_daddr)); - char * in_saddr_str = strdup(inet_ntoa(in_saddr)); - - dap_stream_ch_t * l_route_ch = NULL; //ch_sf_peer_ch_find(ch_sf->ch->stream->session, pkt_data, pkt_data_size); - - if(l_route_ch) { -// log_it(L_DEBUG, "Route packet %s=>%s to %d socket", in_saddr_str,in_daddr_str,l_route_ch->stream->events_socket->socket); - ch_sf_pkt_send(l_route_ch, pkt_data, pkt_data_size); -// }else /*if(m_tun_server->int_network.s_addr != in_daddr_net.s_addr )*/{ // No ways to route so write it out to the OS network stack -// }else if(ch_sf_peer_ch_find(NULL, pkt_data,pkt_data_size)){ // No ways to route so write it out to the OS network stack - } else { // if(!ch_sf_peer_ch_check(pkt_data,pkt_data_size)){ // No ways to route so write it out to the OS network stack - int ret; -// log_it(L_DEBUG, "Route packet %s=>%s size %u to the OS network stack",in_saddr_str, -// in_daddr_str,pkt_data_size); - //if( ch_sf_raw_write(STREAM_SF_PACKET_OP_CODE_RAW_SEND, sf_pkt->data, sf_pkt->op_data.data_size)<0){ - struct sockaddr_in sin = { 0 }; - sin.sin_family = AF_INET; - sin.sin_port = 0; - sin.sin_addr.s_addr = in_daddr.s_addr; - if((ret = sendto(ch_sf->raw_l3_sock, pkt_data, pkt_data_size, 0, (struct sockaddr *) &sin, sizeof(sin))) - < 0) { - // if((ret = write(raw_server->tun_fd, sf_pkt->data, sf_pkt->header.op_data.data_size))<0){ - log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno)); - //log_it(ERROR,"raw socket ring buffer overflowed"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST; - pkt_out->header.sock_id = s_fd_tun; - dap_stream_ch_pkt_write(ch_sf->ch, 'd', pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(ch_sf->ch, true); - } else { - //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", - // str_saddr,str_daddr, sf_pkt->header.op_data.data_size,ret); -// log_it(L_DEBUG,"Raw IP sent %u bytes ",ret); - } - }/*else log_it(L_ERROR,"I don't know what to do with packet");*/ - - if(in_daddr_str) - free(in_daddr_str); - if(in_saddr_str) - free(in_saddr_str); +/** + * @brief ch_sf_tun_send + * @param ch_sf + * @param pkt_data + * @param pkt_data_size + */ +void ch_sf_tun_client_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, size_t pkt_data_size) { + log_it(L_CRITICAL, "Unimplemented tun_client_send"); + + struct in_addr in_saddr, in_daddr, in_daddr_net; + in_saddr.s_addr = ((struct iphdr*) pkt_data)->saddr; + in_daddr.s_addr = ((struct iphdr*) pkt_data)->daddr; + in_daddr_net.s_addr = ch_sf->ch->stream->session->tun_client_addr.s_addr; //in_daddr_net.s_addr = in_daddr.s_addr & m_tun_server->int_network_mask.s_addr; + char * in_daddr_str = strdup(inet_ntoa(in_daddr)); + char * in_saddr_str = strdup(inet_ntoa(in_saddr)); + + int ret; + // log_it(L_DEBUG, "Route packet %s=>%s size %u to the OS network stack",in_saddr_str, + // in_daddr_str,pkt_data_size); + //if( ch_sf_raw_write(STREAM_SF_PACKET_OP_CODE_RAW_SEND, sf_pkt->data, sf_pkt->op_data.data_size)<0){ + struct sockaddr_in sin = { 0 }; + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = in_daddr.s_addr; + if((ret = /*sendto(ch_sf->raw_l3_sock, pkt_data, pkt_data_size, 0, (struct sockaddr *) &sin, sizeof(sin))*/-1 ) + < 0) { + // if((ret = write(raw_server->tun_fd, sf_pkt->data, sf_pkt->header.op_data.data_size))<0){ + log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno)); + //log_it(ERROR,"raw socket ring buffer overflowed"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; + pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST; + pkt_out->header.sock_id = s_fd_tun; + dap_stream_ch_pkt_write_unsafe(ch_sf->ch, 'd', pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + } else { + //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", + // str_saddr,str_daddr, sf_pkt->header.op_data.data_size,ret); + // log_it(L_DEBUG,"Raw IP sent %u bytes ",ret); } + + if(in_daddr_str) + free(in_daddr_str); + if(in_saddr_str) + free(in_saddr_str); } /** @@ -758,79 +606,13 @@ int ch_sf_tun_addr_leased(dap_chain_net_srv_ch_vpn_t * a_sf, ch_vpn_pkt_t * a_pk char l_addr_buf[INET_ADDRSTRLEN]; char l_gw_buf[INET_ADDRSTRLEN]; - //char l_netmask_buf[INET_ADDRSTRLEN]; - //char l_netaddr_buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &l_addr, l_addr_buf, sizeof(l_addr_buf)); inet_ntop(AF_INET, &l_gw, l_gw_buf, sizeof(l_gw_buf)); - //inet_ntop(AF_INET, &l_netmask, l_netmask_buf, sizeof(l_netmask_buf)); - //inet_ntop(AF_INET, &l_netaddr, l_netaddr_buf, sizeof(l_netaddr_buf)); + log_it(L_INFO,"Leased address %s with gateway %s", l_addr, l_gw_buf); // start new tun connection with vpn address and vpn gateway int l_res = dap_chain_net_vpn_client_tun_create(l_addr_buf, l_gw_buf); return l_res; - //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", - -// n_client->addr = l_addr.s_addr; -// if(a_sf->ch->stream->session) { -// a_sf->ch->stream->session->tun_client_addr.s_addr = l_addr.s_addr; -// a_sf->ch->stream->session->tun_client_gw.s_addr = l_gw.s_addr; -// a_sf->ch->stream->session->tun_client_mask.s_addr = l_netmask.s_addr; -// } -// HASH_ADD_INT(m_tun_server->clients, addr, n_client); -// char l_addr_buf[INET_ADDRSTRLEN]; -// char l_netmask_buf[INET_ADDRSTRLEN]; -// char l_netaddr_buf[INET_ADDRSTRLEN]; -// char l_gw_buf[INET_ADDRSTRLEN]; -// char* err; -// pthread_mutex_unlock(&m_tun_server->clients_mutex); -// inet_ntop(AF_INET, &l_addr, l_addr_buf, sizeof(l_addr_buf)); -// inet_ntop(AF_INET, &l_gw, l_gw_buf, sizeof(l_gw_buf)); -// inet_ntop(AF_INET, &l_netmask, l_netmask_buf, sizeof(l_netmask_buf)); -// inet_ntop(AF_INET, &l_netaddr, l_netaddr_buf, sizeof(l_netaddr_buf)); -// log_it(L_NOTICE, "Registred tunnel %s=>%s to %s/%s via remote socket %d", l_addr_buf, l_gw_buf, l_netaddr_buf, -// l_netmask_buf, -// a_sf->ch->stream->events_socket->socket); -// if(a_sf->ch->stream->is_client_to_uplink) { -// log_it(L_NOTICE, "Assign address %s to the network device %s", l_addr_buf, m_tun_server->ifr.ifr_name); -// if(exec_with_ret_f(&err, "ip address add %s/%s dev %s", l_addr_buf, l_netmask_buf, m_tun_server->ifr.ifr_name)) -// { -// log_it(L_ERROR, -// "Can't assign ip address, leased from remote server. Routing to the remote network will not work"); -// log_it(L_ERROR, "exec returns: '%s'", err); -// } -// ch_sf_tun_peer_add(a_sf, l_addr.s_addr, l_gw.s_addr, l_netmask.s_addr & l_gw.s_addr, l_netmask.s_addr); -// -// size_t i; -// log_it(L_DEBUG, "Found %u networks in reply", l_route_net_count); -// for(i = 0; i < l_route_net_count; i++) { -// in_addr_t l_r_netaddr; -// in_addr_t l_r_netmask; -// -// memcpy(&l_r_netaddr, a_pkt->data + (3 + i * 2) * sizeof(in_addr_t), sizeof(in_addr_t)); -// memcpy(&l_r_netmask, a_pkt->data + (4 + i * 2) * sizeof(in_addr_t), sizeof(in_addr_t)); -// -// if(!l_r_netaddr && !l_r_netmask) { -// log_it(L_DEBUG, "Ignores default route from upstream"); -// continue; -// } -// -//// ch_sf_tun_peer_add(a_sf, 0,0,l_r_netaddr,l_r_netmask); -// ch_sf_tun_peer_add(a_sf, l_r_netaddr, l_r_netmask, l_r_netaddr, l_r_netmask); -// inet_ntop(AF_INET, &l_r_netmask, l_netmask_buf, sizeof(l_netmask_buf)); -// inet_ntop(AF_INET, &l_r_netaddr, l_netaddr_buf, sizeof(l_netaddr_buf)); -// -//// if(!l_r_netaddr && !l_r_netmask){ -//// log_it(L_DEBUG,"Ignores default route from upstream"); -//// log_it(L_DEBUG," %s/%s ",l_netaddr_buf, l_netmask_buf); -//// continue; -//// } -// -// char *l_cmd = dap_strdup_printf("route add -net %s netmask %s dev %s metric 2", -// l_netaddr_buf, l_netmask_buf, m_tun_server->ifr.ifr_ifrn.ifrn_name); -// exe_bash_cmd(l_cmd); -// } -// -// } } diff --git a/modules/service/vpn/include/dap_chain_net_srv_vpn.h b/modules/service/vpn/include/dap_chain_net_srv_vpn.h index b7896676fff8a42a18709dc31cf44262feeb9214..a073dbad18162e85af65f5412ef320c5bad25e10 100644 --- a/modules/service/vpn/include/dap_chain_net_srv_vpn.h +++ b/modules/service/vpn/include/dap_chain_net_srv_vpn.h @@ -26,10 +26,13 @@ #pragma once #ifdef DAP_OS_UNIX #include <netinet/in.h> +#include <linux/if.h> +#include <linux/if_tun.h> #endif #include "dap_config.h" #include "dap_chain_net_srv.h" +#include "dap_events.h" #define DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT 0x01 @@ -87,36 +90,35 @@ typedef struct ch_vpn_pkt { } raw; // Raw access to OP bytes }; } DAP_ALIGN_PACKED header; - uint8_t data[]; // Binary data nested by packet + byte_t data[]; // Binary data nested by packet }DAP_ALIGN_PACKED ch_vpn_pkt_t; -/** - * @struct ch_vpn_socket_proxy - * @brief Internal data storage for single socket proxy functions. Usualy helpfull for\ - * port forwarding or for protecting single application's connection - * - **/ -typedef struct ch_vpn_socket_proxy { - int id; - int sock; - struct in_addr client_addr; // Used in raw L3 connections - pthread_mutex_t mutex; - dap_stream_ch_t * ch; +typedef struct ch_sf_tun_socket ch_sf_tun_socket_t; +typedef struct dap_chain_net_srv_ch_vpn dap_chain_net_srv_ch_vpn_t; - bool signal_to_delete; - ch_vpn_pkt_t * pkt_out[100]; - size_t pkt_out_size; - uint64_t bytes_sent; - uint64_t bytes_recieved; +// Copy is present on each tun socket +typedef struct usage_client { + dap_chain_net_srv_ch_vpn_t * ch_vpn; + dap_chain_datum_tx_receipt_t * receipt; + size_t receipt_size; + uint32_t usage_id; + dap_chain_net_srv_t * srv; + ch_sf_tun_socket_t * tun_socket; + UT_hash_handle hh; +} usage_client_t; - time_t time_created; - time_t time_lastused; +typedef struct dap_chain_net_srv_ch_vpn_info dap_chain_net_srv_ch_vpn_info_t; - UT_hash_handle hh; - UT_hash_handle hh2; - UT_hash_handle hh_sock; -} ch_vpn_socket_proxy_t; +typedef struct ch_sf_tun_socket { + uint8_t worker_id; + dap_worker_t * worker; + dap_events_socket_t * es; + dap_chain_net_srv_ch_vpn_info_t * clients; // Remote clients identified by destination address + //UT_hash_handle hh; +}ch_sf_tun_socket_t; + +#define CH_SF_TUN_SOCKET(a) ((ch_sf_tun_socket_t*) a->_inheritor ) /** @@ -130,16 +132,27 @@ typedef struct dap_chain_net_srv_ch_vpn uint32_t usage_id; dap_chain_net_srv_t* net_srv; //dap_chain_net_srv_uid_t srv_uid; // Unique ID for service. - pthread_mutex_t mutex; - ch_vpn_socket_proxy_t * socks; - int raw_l3_sock; bool is_allowed; + ch_sf_tun_socket_t * tun_socket; struct in_addr addr_ipv4; dap_stream_ch_t * ch; UT_hash_handle hh; } dap_chain_net_srv_ch_vpn_t; +typedef struct dap_chain_net_srv_ch_vpn_info +{ + struct in_addr addr_ipv4; + bool is_on_this_worker; + bool is_reassigned_once;//Copy of esocket was_reassigned field. Used + // to prevent jumping on systems without FlowControl + uint32_t usage_id; + dap_chain_net_srv_ch_vpn_t * ch_vpn; + dap_events_socket_t * queue_msg; // Message queue + dap_worker_t * worker; + dap_events_socket_t * esocket; + UT_hash_handle hh; +}dap_chain_net_srv_ch_vpn_info_t; typedef struct dap_chain_net_srv_vpn_item_ipv4{ struct in_addr addr; @@ -155,8 +168,6 @@ typedef struct dap_chain_net_srv_vpn #define CH_VPN(a) ((dap_chain_net_srv_ch_vpn_t *) ((a)->internal) ) -bool is_dap_tun_in_worker(void); - int dap_chain_net_srv_client_vpn_init(dap_config_t * g_config); int dap_chain_net_srv_vpn_init(dap_config_t * g_config); diff --git a/modules/service/vpn/include/dap_chain_net_vpn_client.h b/modules/service/vpn/include/dap_chain_net_vpn_client.h index c97f694c0adbdc5e1243d759b2ba1c63dc8d5246..5faf509bb8146bdcd271230957b67a9182755cf3 100644 --- a/modules/service/vpn/include/dap_chain_net_vpn_client.h +++ b/modules/service/vpn/include/dap_chain_net_vpn_client.h @@ -38,6 +38,7 @@ typedef enum dap_chain_net_vpn_client_status_enum{ dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void); +dap_stream_worker_t* dap_chain_net_vpn_client_get_stream_worker(void); int dap_chain_net_vpn_client_update(dap_chain_net_t *a_net, const char *a_wallet_name, const char *a_str_token, uint64_t a_value_datoshi); int dap_chain_net_vpn_client_get_wallet_info(dap_chain_net_t *a_net, char **a_wallet_name, char **a_str_token, uint64_t *a_value_datoshi); diff --git a/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h b/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h index 8322907d10761622ec5260d1fca036b589d9be92..054b7642ad81f23f99e7787d692349cc0c1d459f 100644 --- a/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h +++ b/modules/service/vpn/include/dap_chain_net_vpn_client_tun.h @@ -31,4 +31,4 @@ int dap_chain_net_vpn_client_tun_delete(void); int dap_chain_net_vpn_client_tun_status(void); int ch_sf_tun_addr_leased(dap_chain_net_srv_ch_vpn_t * a_sf, ch_vpn_pkt_t * a_pkt, size_t a_pkt_data_size); -void ch_sf_tun_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, size_t pkt_data_size); +void ch_sf_tun_client_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, size_t pkt_data_size); diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index a2250e0abd53ce2b8ac181c44d596ace2e723d9c..c0de3cc2d7d37f9955134fec723f3fe6d9adebf8 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -56,6 +56,7 @@ typedef struct dap_chain_cs_dag_event_item { dap_chain_hash_fast_t hash; time_t ts_added; dap_chain_cs_dag_event_t *event; + size_t event_size; UT_hash_handle hh; } dap_chain_cs_dag_event_item_t; @@ -78,29 +79,28 @@ typedef struct dap_chain_cs_dag_pvt { #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) // Atomic element organization callbacks -static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Accept new event in dag -static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t ); // Verify new event in dag -static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t ); // Get dag event size +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); // Accept new event in dag +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); // Verify new event in dag static size_t s_chain_callback_atom_get_static_hdr_size(void); // Get dag event header size static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain ); -static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain , - dap_chain_atom_ptr_t a); +static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * , + dap_chain_atom_ptr_t , size_t); static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , - dap_chain_hash_fast_t * a_atom_hash); + dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); static dap_chain_datum_tx_t* s_chain_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain , dap_chain_hash_fast_t * a_atom_hash); -static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event); +static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size); // Get event(s) from dag -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter ); // Get the fisrt event from dag -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter ); // Get the next event from dag -static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , - size_t * a_links_size_ptr ); // Get list of linked events -static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter , - size_t * a_lasts_size_ptr ); // Get list of linked events +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ); // Get the fisrt event from dag +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ); // Get the next event from dag +static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, + size_t ** a_links_size_ptr ); // Get list of linked events +static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, + size_t ** a_lasts_size_ptr ); // Get list of linked events // Delete iterator static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ); // Get the fisrt event from dag @@ -172,7 +172,6 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add ; // Accept new element in chain a_chain->callback_atom_verify = s_chain_callback_atom_verify ; // Verify new element in chain - a_chain->callback_atom_get_size = s_chain_callback_atom_hdr_get_size; // Get dag event size a_chain->callback_atom_get_hdr_static_size = s_chain_callback_atom_get_static_hdr_size; // Get dag event hdr size a_chain->callback_atom_iter_create = s_chain_callback_atom_iter_create; @@ -248,16 +247,16 @@ void dap_chain_cs_dag_delete(dap_chain_t * a_chain) static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a_ledger, dap_chain_cs_dag_event_item_t * a_event_item){ - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) dap_chain_cs_dag_event_get_datum(a_event_item->event); + dap_chain_datum_t *l_datum = (dap_chain_datum_t*) dap_chain_cs_dag_event_get_datum(a_event_item->event, a_event_item->event_size); switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL: { dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - dap_chain_ledger_token_add(a_ledger, l_token, l_datum->header.data_size); + return dap_chain_ledger_token_add(a_ledger, l_token, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TOKEN_EMISSION: { dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data; - dap_chain_ledger_token_emission_add(a_ledger, l_token_emission, l_datum->header.data_size); + return dap_chain_ledger_token_emission_add(a_ledger, l_token_emission, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TX: { @@ -265,6 +264,7 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger dap_chain_cs_dag_event_item_t * l_tx_event= DAP_NEW_Z(dap_chain_cs_dag_event_item_t); l_tx_event->ts_added = a_event_item->ts_added; l_tx_event->event = a_event_item->event; + l_tx_event->event_size = a_event_item->event_size; memcpy(&l_tx_event->hash, &a_event_item->hash, sizeof (l_tx_event->hash) ); HASH_ADD(hh,PVT(a_dag)->tx_events,hash,sizeof (l_tx_event->hash),l_tx_event); @@ -282,15 +282,21 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger } static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a_ledger, dap_chain_cs_dag_event_item_t * a_event_item ){ - int res = a_dag->callback_cs_verify(a_dag,a_event_item->event); + int res = a_dag->callback_cs_verify(a_dag,a_event_item->event, a_event_item->event_size); if(res == 0){ + char l_buf_hash[128]; + dap_chain_hash_fast_to_str(&a_event_item->hash,l_buf_hash,sizeof(l_buf_hash)-1); + log_it(L_DEBUG,"Dag event %s checked, add it to ledger", l_buf_hash); res = s_dap_chain_add_atom_to_ledger(a_dag, a_ledger, a_event_item); - + //All correct, no matter for result HASH_ADD(hh, PVT(a_dag)->events,hash,sizeof (a_event_item->hash), a_event_item); s_dag_events_lasts_process_new_last_event(a_dag, a_event_item); + } else { + char l_buf_hash[128]; + dap_chain_hash_fast_to_str(&a_event_item->hash,l_buf_hash,sizeof(l_buf_hash)-1); + log_it(L_WARNING,"Dag event %s check failed: code %d", l_buf_hash, res ); } - return res; } @@ -312,9 +318,10 @@ static bool s_dap_chain_check_if_event_is_present(dap_chain_cs_dag_event_item_t * @brief s_chain_callback_atom_add Accept new event in dag * @param a_chain DAG object * @param a_atom + * @param a_atom_size * @return 0 if verified and added well, otherwise if not */ -static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { dap_chain_atom_verify_res_t ret = ATOM_ACCEPT; dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain); @@ -323,11 +330,12 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha dap_chain_cs_dag_event_item_t * l_event_item = DAP_NEW_Z(dap_chain_cs_dag_event_item_t); pthread_rwlock_t * l_events_rwlock = &PVT(l_dag)->events_rwlock ; l_event_item->event = l_event; + l_event_item->event_size = a_atom_size; l_event_item->ts_added = time(NULL); - dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_item->hash ); + dap_hash_fast(l_event, a_atom_size,&l_event_item->hash ); dap_chain_hash_fast_t l_event_hash; - dap_chain_cs_dag_event_calc_hash(l_event,&l_event_hash); + dap_chain_cs_dag_event_calc_hash(l_event, a_atom_size,&l_event_hash); char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash); log_it(L_DEBUG, "Processing event: %s...", l_event_hash_str); @@ -344,8 +352,10 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha } // verify hashes and consensus - if(ret == ATOM_ACCEPT) - ret = s_chain_callback_atom_verify (a_chain, a_atom); + if(ret == ATOM_ACCEPT){ + ret = s_chain_callback_atom_verify (a_chain, a_atom, a_atom_size); + log_it(L_DEBUG, "Verified atom %p: code %d", a_atom, ret); + } if( ret == ATOM_MOVE_TO_THRESHOLD){ HASH_ADD(hh, PVT(l_dag)->events_treshold,hash,sizeof (l_event_item->hash), l_event_item); @@ -427,7 +437,7 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain int l_index = rand() % (int) l_events_round_new_size; dap_chain_hash_fast_t l_hash; dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) l_events_round_new[l_index].value; - size_t l_event_size = dap_chain_cs_dag_event_calc_size(l_event); + size_t l_event_size = l_events_round_new[l_index].value_len; dap_hash_fast(l_event, l_event_size,&l_hash); bool l_is_already_in_event = false; @@ -468,12 +478,13 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain if (l_hashes_linked || s_seed_mode ) { dap_chain_cs_dag_event_t * l_event = NULL; + size_t l_event_size = 0; if(l_dag->callback_cs_event_create) - l_event = l_dag->callback_cs_event_create(l_dag,l_datum,l_hashes,l_hashes_linked); - if ( l_event){ // Event is created + l_event = l_dag->callback_cs_event_create(l_dag,l_datum,l_hashes,l_hashes_linked,&l_event_size); + if ( l_event&&l_event_size){ // Event is created if (l_dag->is_add_directy) { - if (s_chain_callback_atom_add(a_chain, l_event) == ATOM_ACCEPT) { + if (s_chain_callback_atom_add(a_chain, l_event, l_event_size) == ATOM_ACCEPT) { // add events to file if (!l_cell) { l_cell = dap_chain_cell_create(); @@ -486,7 +497,7 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain l_cell->id.uint64 = l_net ? l_net->pub.cell_id.uint64 : 0; l_cell->file_storage_path = dap_strdup_printf("%0llx.dchaincell", l_cell->id.uint64); } - if (dap_chain_cell_file_append(l_cell, l_event, a_chain->callback_atom_get_size(l_event)) < 0) { + if (dap_chain_cell_file_append(l_cell, l_event, l_event_size ) < 0) { log_it(L_ERROR, "Can't add new event to the file '%s'", l_cell->file_storage_path); continue; } @@ -500,10 +511,10 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain // add to new round into global_db else { dap_chain_hash_fast_t l_event_hash; - dap_chain_cs_dag_event_calc_hash(l_event, &l_event_hash); + dap_chain_cs_dag_event_calc_hash(l_event,l_event_size, &l_event_hash); char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_hash); if(dap_chain_global_db_gr_set(dap_strdup(l_event_hash_str), (uint8_t *) l_event, - dap_chain_cs_dag_event_calc_size(l_event), + l_event_size, l_dag->gdb_group_events_round_new)) { log_it(L_INFO, "Event %s placed in the new forming round", l_event_hash_str); DAP_DELETE(l_event_hash_str); @@ -570,12 +581,16 @@ dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * @param a_atom * @return */ -static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom) +static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom,size_t a_atom_size) { dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain); dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom; dap_chain_atom_verify_res_t res = ATOM_ACCEPT; + if(sizeof (l_event->header) >= a_atom_size){ + log_it(L_WARNING,"Size of atom is %zd that is equel or less then header %zd",a_atom_size,sizeof (l_event->header)); + return ATOM_REJECT; + } // genesis or seed mode if (l_event->header.hash_count == 0){ if(s_seed_mode && !PVT(l_dag)->events) @@ -583,7 +598,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_ if (l_dag->is_static_genesis_event ){ dap_chain_hash_fast_t l_event_hash; - dap_chain_cs_dag_event_calc_hash(l_event,&l_event_hash); + dap_chain_cs_dag_event_calc_hash(l_event,a_atom_size, &l_event_hash); if ( memcmp( &l_event_hash, &l_dag->static_genesis_event_hash, sizeof(l_event_hash) ) != 0 ){ char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_hash); char * l_genesis_event_hash_str = dap_chain_hash_fast_to_str_new(&l_dag->static_genesis_event_hash); @@ -618,7 +633,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_ //consensus if(res == ATOM_ACCEPT) - if(l_dag->callback_cs_verify ( l_dag, l_event )) + if(l_dag->callback_cs_verify ( l_dag, l_event,a_atom_size )) res = ATOM_REJECT; return res; @@ -661,7 +676,8 @@ void s_dag_events_lasts_process_new_last_event(dap_chain_cs_dag_t * a_dag, dap_c dap_chain_cs_dag_event_item_t * l_event_last= DAP_NEW_Z(dap_chain_cs_dag_event_item_t); l_event_last->ts_added = a_event_item->ts_added; l_event_last->event = a_event_item->event; - dap_hash_fast(l_event_last->event, dap_chain_cs_dag_event_calc_size(l_event_last->event),&l_event_last->hash ); + l_event_last->event_size = a_event_item->event_size; + dap_hash_fast(l_event_last->event, a_event_item->event_size,&l_event_last->hash ); HASH_ADD(hh,PVT(a_dag)->events_lasts_unlinked,hash, sizeof(l_event_last->hash),l_event_last); } @@ -678,7 +694,7 @@ int dap_chain_cs_dag_event_verify_hashes_with_treshold(dap_chain_cs_dag_t * a_da bool l_is_events_all_hashes = true; bool l_is_events_main_hashes = true; - if(a_event->header.hash_count == 0){ + if (a_event->header.hash_count == 0) { //looks like an alternative genesis event return DAP_THRESHOLD_CONFLICTING; } @@ -749,17 +765,6 @@ bool dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag, dap_ledger_t * a return res; } - -/** - * @brief s_chain_callback_atom_get_size Get size of atomic element - * @param a_atom - * @return - */ -static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t a_atom) -{ - return dap_chain_cs_dag_event_calc_size( (dap_chain_cs_dag_event_t * ) a_atom); -} - /** * @brief s_chain_callback_atom_get_static_hdr_size * @param a_chain @@ -777,7 +782,7 @@ static size_t s_chain_callback_atom_get_static_hdr_size() * @return */ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain , - dap_chain_atom_ptr_t a_atom) + dap_chain_atom_ptr_t a_atom, size_t a_atom_size) { dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); l_atom_iter->chain = a_chain; @@ -785,7 +790,7 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t if ( a_atom ){ dap_chain_hash_fast_t l_atom_hash; - dap_hash_fast(a_atom, a_chain->callback_atom_get_size(a_atom), &l_atom_hash ); + dap_hash_fast(a_atom, a_atom_size, &l_atom_hash ); dap_chain_cs_dag_event_item_t * l_atom_item; HASH_FIND(hh, PVT(DAP_CHAIN_CS_DAG(a_chain))->events, &l_atom_hash, sizeof(l_atom_hash),l_atom_item ); @@ -812,10 +817,10 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_ * @param a_atom_iter * @return */ -static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event) +static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size) { if(a_event) - return dap_chain_cs_dag_event_get_datum((dap_chain_cs_dag_event_t*) a_event); + return dap_chain_cs_dag_event_get_datum((dap_chain_cs_dag_event_t*) a_event, a_atom_size); return NULL; } @@ -824,16 +829,19 @@ static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a * @param a_atom_iter * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter ) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t * a_ret_size ) { dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain); dap_chain_cs_dag_pvt_t *l_dag_pvt = l_dag ? PVT(l_dag) : NULL; a_atom_iter->cur_item = l_dag_pvt->events; a_atom_iter->cur = (dap_chain_cs_dag_event_t*) (l_dag_pvt->events ? l_dag_pvt->events->event : NULL); + a_atom_iter->cur_size =l_dag_pvt->events->event_size; // a_atom_iter->cur = a_atom_iter->cur ? // (dap_chain_cs_dag_event_t*) PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events->event : NULL; // a_atom_iter->cur_item = PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events; + if (a_ret_size) + *a_ret_size = a_atom_iter->cur_size; return a_atom_iter->cur; } @@ -843,27 +851,28 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_ * @param a_lasts_size_ptr * @return */ -static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter , - size_t * a_lasts_size_ptr ) +static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t * a_lasts_size, + size_t ** a_lasts_size_array ) { dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain ); - - *a_lasts_size_ptr = HASH_COUNT( PVT(l_dag)->events_lasts_unlinked ); - if ( *a_lasts_size_ptr > 0 ) { - dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE( dap_chain_atom_ptr_t, - sizeof (dap_chain_atom_ptr_t*) * (*a_lasts_size_ptr) ); - + dap_chain_atom_ptr_t * l_ret = NULL; + pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); + size_t l_lasts_size = HASH_COUNT( PVT(l_dag)->events_lasts_unlinked ); + if ( l_lasts_size > 0 ) { + if( a_lasts_size) + *a_lasts_size = l_lasts_size; + l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t, sizeof(dap_chain_atom_ptr_t *) * l_lasts_size); dap_chain_cs_dag_event_item_t * l_event_item = NULL, *l_event_item_tmp = NULL; size_t i = 0; - pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); + *a_lasts_size_array = DAP_NEW_Z_SIZE(size_t, sizeof(size_t) * l_lasts_size); HASH_ITER(hh,PVT(l_dag)->events_lasts_unlinked, l_event_item,l_event_item_tmp){ l_ret[i] = l_event_item->event; + (*a_lasts_size_array)[i] = l_event_item->event_size; i++; - } - pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); - return l_ret; + } } - return NULL; + pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); + return l_ret; } /** @@ -872,8 +881,8 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_ato * @param a_links_size_ptr * @return */ -static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , - size_t * a_links_size_ptr ) +static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter ,size_t* a_links_size, + size_t ** a_links_size_array ) { if ( a_atom_iter->cur && a_atom_iter->chain){ dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain ); @@ -886,7 +895,9 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato if ( l_event->header.hash_count > 0){ dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t, sizeof (dap_chain_atom_ptr_t*) * l_event->header.hash_count ); - *a_links_size_ptr = l_event->header.hash_count; + if( a_links_size) + *a_links_size = l_event->header.hash_count; + *a_links_size_array = DAP_NEW_Z_SIZE(size_t, l_event->header.hash_count*sizeof (size_t)); for (uint16_t i = 0; i < l_event->header.hash_count; i++){ dap_chain_cs_dag_event_item_t * l_link_item = NULL; dap_chain_hash_fast_t * l_link_hash = (dap_chain_hash_fast_t *) @@ -895,16 +906,17 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato HASH_FIND(hh, PVT(l_dag)->events,l_link_hash,sizeof(*l_link_hash),l_link_item); if ( l_link_item ){ l_ret[i] = l_link_item->event; + (*a_links_size_array)[i] = l_link_item->event_size; }else { char * l_link_hash_str = dap_chain_hash_fast_to_str_new(l_link_hash); char * l_event_hash_str = l_event_item ? dap_chain_hash_fast_to_str_new(&l_event_item->hash) : NULL; log_it(L_ERROR,"Can't find %s->%s links", l_event_hash_str ? l_event_hash_str : "[null]", l_link_hash_str); DAP_DELETE(l_event_hash_str); DAP_DELETE(l_link_hash_str); - (*a_links_size_ptr)--; + (*a_links_size_array)--; } } - if(!(*a_links_size_ptr)){ + if(!(*a_links_size_array)){ DAP_DELETE(l_ret); l_ret = NULL; } @@ -921,7 +933,7 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato * @return */ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , - dap_chain_hash_fast_t * a_atom_hash) + dap_chain_hash_fast_t * a_atom_hash,size_t *a_atom_size) { dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain ); dap_chain_cs_dag_event_item_t * l_event_item = NULL; @@ -929,6 +941,9 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_at if ( l_event_item ){ a_atom_iter->cur_item = l_event_item; a_atom_iter->cur = l_event_item->event; + a_atom_iter->cur_size= l_event_item->event_size; + if(a_atom_size) + *a_atom_size = l_event_item->event_size; return l_event_item->event; }else return NULL; @@ -942,7 +957,7 @@ static dap_chain_datum_tx_t* s_chain_callback_atom_iter_find_by_tx_hash(dap_chai dap_chain_cs_dag_event_item_t * l_event_item = NULL; HASH_FIND(hh, PVT(l_dag)->tx_events,a_atom_hash,sizeof(*a_atom_hash),l_event_item); if ( l_event_item ){ - dap_chain_datum_t * l_datum = dap_chain_cs_dag_event_get_datum(l_event_item->event) ; + dap_chain_datum_t * l_datum = dap_chain_cs_dag_event_get_datum(l_event_item->event, l_event_item->event_size) ; return l_datum ? l_datum->header.data_size ? (dap_chain_datum_tx_t*) l_datum->data : NULL :NULL; }else return NULL; @@ -953,7 +968,7 @@ static dap_chain_datum_tx_t* s_chain_callback_atom_iter_find_by_tx_hash(dap_chai * @param a_atom_iter * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter ) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t * a_atom_size ) { if (a_atom_iter->cur ){ dap_chain_cs_dag_event_item_t * l_event_item = (dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item; @@ -962,6 +977,10 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_ // if l_event_item=NULL then items are over a_atom_iter->cur = l_event_item ? l_event_item->event : NULL; } + a_atom_iter->cur_size = a_atom_iter->cur?a_atom_iter->cur_size: 0; + if(a_atom_size) + *a_atom_size = a_atom_iter->cur_size; + return a_atom_iter->cur; } @@ -984,6 +1003,7 @@ static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_ite */ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) { + (void) arg_func; enum { SUBCMD_EVENT_CREATE, SUBCMD_EVENT_CANCEL, @@ -992,13 +1012,13 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) SUBCMD_UNDEFINED } l_event_subcmd={0}; - const char* l_event_subcmd_str[]={ + /*const char* l_event_subcmd_str[]={ [SUBCMD_EVENT_CREATE]="create", [SUBCMD_EVENT_CANCEL]="cancel", [SUBCMD_EVENT_LIST]="list", [SUBCMD_EVENT_DUMP]="dump", [SUBCMD_UNDEFINED]="UNDEFINED" - }; + };*/ int arg_index = 1; @@ -1082,7 +1102,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t*) l_objs[i].value; size_t l_event_size = l_objs[i].value_len; int l_ret_event_verify; - if ( ( l_ret_event_verify = l_dag->callback_cs_verify (l_dag,l_event) ) !=0 ){// if consensus accept the event + if ( ( l_ret_event_verify = l_dag->callback_cs_verify (l_dag,l_event,l_event_size) ) !=0 ){// if consensus accept the event dap_string_append_printf( l_str_ret_tmp, "Error! Event %s is not passing consensus verification, ret code %d\n", l_objs[i].key, l_ret_event_verify ); @@ -1092,9 +1112,9 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) dap_string_append_printf( l_str_ret_tmp, "Event %s verification passed\n", l_objs[i].key); // If not verify only mode we add if ( ! l_verify_only ){ - dap_chain_atom_ptr_t l_new_atom = (dap_chain_atom_ptr_t)dap_chain_cs_dag_event_copy(l_event); // produce deep copy of event; + dap_chain_atom_ptr_t l_new_atom = (dap_chain_atom_ptr_t)dap_chain_cs_dag_event_copy(l_event, l_event_size); // produce deep copy of event; memcpy(l_new_atom, l_event, l_event_size); - if(s_chain_callback_atom_add(l_chain, l_new_atom) < 0) { // Add new atom in chain + if(s_chain_callback_atom_add(l_chain, l_new_atom,l_event_size) < 0) { // Add new atom in chain DAP_DELETE(l_new_atom); dap_string_append_printf(l_str_ret_tmp, "Event %s not added in chain\n", l_objs[i].key); } @@ -1297,7 +1317,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) }else if ( strcmp(l_from_events_str,"events_lasts") == 0){ dap_chain_cs_dag_event_item_t * l_event_item = NULL; - pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); + pthread_rwlock_rdlock(&PVT(l_dag)->events_rwlock); HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_event_hash,sizeof(l_event_hash),l_event_item); pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); if ( l_event_item ) @@ -1310,7 +1330,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) } }else if ( strcmp(l_from_events_str,"events") == 0){ dap_chain_cs_dag_event_item_t * l_event_item = NULL; - pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); + pthread_rwlock_rdlock(&PVT(l_dag)->events_rwlock); HASH_FIND(hh,PVT(l_dag)->events,&l_event_hash,sizeof(l_event_hash),l_event_item); pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); if ( l_event_item ) diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c index edf2b6621705cece4659efc2ddae1e91063a979d..a9d1d755b57b6591a1c395fe59d05aeebc0c3e34 100644 --- a/modules/type/dag/dap_chain_cs_dag_event.c +++ b/modules/type/dag/dap_chain_cs_dag_event.c @@ -45,8 +45,9 @@ */ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_datum_t * a_datum ,dap_enc_key_t * a_key , - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count) + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t * a_event_size) { + assert(a_event_size); size_t l_hashes_size = sizeof(*a_hashes)*a_hashes_count; size_t l_datum_size = dap_chain_datum_size(a_datum); dap_chain_cs_dag_event_t * l_event_new = NULL; @@ -58,11 +59,15 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, l_event_new->header.cell_id.uint64 = a_cell_id.uint64; l_event_new->header.chain_id.uint64 = a_chain_id.uint64; l_event_new->header.hash_count = a_hashes_count; + *a_event_size = sizeof (l_event_new->header); - if ( l_hashes_size ) + if ( l_hashes_size ){ memcpy(l_event_new->hashes_n_datum_n_signs, a_hashes, l_hashes_size ); + *a_event_size += l_hashes_size; + } memcpy(l_event_new->hashes_n_datum_n_signs+l_hashes_size, a_datum,l_datum_size ); + *a_event_size += l_datum_size; if ( a_key ){ dap_sign_t * l_sign = dap_sign_create(a_key,l_event_new, @@ -72,6 +77,7 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, size_t l_sign_size = dap_sign_get_size(l_sign); l_event_new = (dap_chain_cs_dag_event_t* )DAP_REALLOC(l_event_new,l_event_size+l_sign_size ); memcpy(l_event_new->hashes_n_datum_n_signs + l_hashes_size + l_datum_size, l_sign, l_sign_size); + *a_event_size += l_sign_size; l_event_size += l_sign_size; l_event_new->header.signs_count++; DAP_DELETE(l_sign); @@ -91,13 +97,12 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, * @param a_event_src * @return */ -dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src) +dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src,size_t a_event_size) { if(!a_event_src) return NULL; - size_t l_event_size = dap_chain_cs_dag_event_calc_size(a_event_src); - dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size); - memcpy(l_event_new, a_event_src, l_event_size); + dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, a_event_size); + memcpy(l_event_new, a_event_src, a_event_size); return l_event_new; } @@ -107,16 +112,15 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t * @param l_key * @return */ -dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event, +dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event, size_t a_event_size, dap_enc_key_t * l_key) { - size_t l_event_size = dap_chain_cs_dag_event_calc_size( a_event ); - size_t l_event_signing_size = dap_chain_cs_dag_event_calc_size_excl_signs( a_event ); + size_t l_event_signing_size = dap_chain_cs_dag_event_calc_size_excl_signs( a_event ,a_event_size); dap_sign_t * l_sign = dap_sign_create(l_key,a_event,l_event_signing_size,0); size_t l_sign_size = dap_sign_get_size(l_sign); - dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size+l_sign_size); - memcpy(l_event_new, a_event,l_event_size); - memcpy(l_event_new+l_event_size,l_sign,l_sign_size); + dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, a_event_size+l_sign_size); + memcpy(l_event_new, a_event,a_event_size); + memcpy(l_event_new+a_event_size,l_sign,l_sign_size); l_event_new->header.signs_count++; return l_event_new; } @@ -127,16 +131,23 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_ * @param a_sign_number * @return */ -dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, uint16_t a_sign_number) +dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, size_t a_event_size, uint16_t a_sign_number) { + size_t l_offset_passed = sizeof (a_event->header); if (a_event->header.signs_count > a_sign_number ){ - size_t l_offset_to_sign = dap_chain_cs_dag_event_calc_size_excl_signs(a_event); + size_t l_offset_to_sign = dap_chain_cs_dag_event_calc_size_excl_signs(a_event,a_event_size); + l_offset_passed += l_offset_to_sign; + if ( l_offset_passed >= a_event_size) + return NULL; uint8_t * l_signs = ((uint8_t*) a_event)+l_offset_to_sign; uint16_t l_signs_offset = 0; uint16_t l_signs_passed; for ( l_signs_passed=0; l_signs_passed < a_sign_number; l_signs_passed++){ dap_sign_t * l_sign = (dap_sign_t *) (l_signs+l_signs_offset); l_signs_offset+=l_sign->header.sign_pkey_size+l_sign->header.sign_size+sizeof(l_sign->header); + l_offset_passed += l_offset_to_sign; + if ( l_offset_passed >= a_event_size) + return NULL; } return (dap_sign_t*) l_signs + l_signs_offset; }else diff --git a/modules/type/dag/include/dap_chain_cs_dag.h b/modules/type/dag/include/dap_chain_cs_dag.h index 74a974b5a6d1a568c0cb1915da15f52cc3798144..6befe38ae351a1f4d04298ef2a8b8f588ca3a3de 100644 --- a/modules/type/dag/include/dap_chain_cs_dag.h +++ b/modules/type/dag/include/dap_chain_cs_dag.h @@ -28,14 +28,14 @@ typedef struct dap_chain_cs_dag dap_chain_cs_dag_t; typedef void (*dap_chain_cs_dag_callback_t)(dap_chain_cs_dag_t *); -typedef int (*dap_chain_cs_dag_callback_event_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_t *); +typedef int (*dap_chain_cs_dag_callback_event_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_t *,size_t); typedef dap_chain_cs_dag_event_t * (*dap_chain_cs_dag_callback_event_create_t)(dap_chain_cs_dag_t *, dap_chain_datum_t *, dap_chain_hash_fast_t *, - size_t); + size_t, size_t*); typedef struct dap_chain_cs_dag { diff --git a/modules/type/dag/include/dap_chain_cs_dag_event.h b/modules/type/dag/include/dap_chain_cs_dag_event.h index 39b898d9b1e9123e8ed62b068287a85a0c31d3e6..5f3661be72d0cf47ea6bb17fc73fb116c2b47ee3 100644 --- a/modules/type/dag/include/dap_chain_cs_dag_event.h +++ b/modules/type/dag/include/dap_chain_cs_dag_event.h @@ -49,7 +49,7 @@ typedef struct dap_chain_cs_dag_event { dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_datum_t * a_datum, dap_enc_key_t * a_key, - dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count); + dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count, size_t * a_event_size); /** @@ -57,23 +57,25 @@ dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, * @param a_event * @return */ -static inline dap_chain_datum_t* dap_chain_cs_dag_event_get_datum(dap_chain_cs_dag_event_t * a_event) +static inline dap_chain_datum_t* dap_chain_cs_dag_event_get_datum(dap_chain_cs_dag_event_t * a_event,size_t a_event_size) { - return (dap_chain_datum_t* ) (a_event->hashes_n_datum_n_signs - +a_event->header.hash_count*sizeof(dap_chain_hash_fast_t)); + return a_event->header.hash_count*sizeof(dap_chain_hash_fast_t)<=a_event_size?(dap_chain_datum_t* ) (a_event->hashes_n_datum_n_signs + +a_event->header.hash_count*sizeof(dap_chain_hash_fast_t)): NULL; } -dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src); +dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src, size_t a_event_size); // Important: returns new deep copy of event -dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event, dap_enc_key_t * l_key); -dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, uint16_t a_sign_number); +dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event,size_t a_event_size, dap_enc_key_t * l_key); +dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, size_t a_event_size, uint16_t a_sign_number); /** * @brief dap_chain_cs_dag_event_calc_size * @param a_event * @return */ + +/** static inline size_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t * a_event) { if(!a_event) @@ -93,14 +95,16 @@ static inline size_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t * return sizeof( a_event->header ) + l_hashes_size +l_signs_offset +l_datum_size; } - +**/ /** * @brief dap_chain_cs_dag_event_calc_size_excl_signs * @param a_event * @return */ -static inline size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t * a_event) +static inline ssize_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t * a_event,size_t a_event_size) { + if (a_event_size< sizeof (a_event->header)) + return -1; size_t l_hashes_size = a_event->header.hash_count*sizeof(dap_chain_hash_fast_t); dap_chain_datum_t * l_datum = (dap_chain_datum_t*) (a_event->hashes_n_datum_n_signs + l_hashes_size); size_t l_datum_size = dap_chain_datum_size(l_datum); @@ -113,7 +117,7 @@ static inline size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_da * @param a_event * @param a_event_hash */ -static inline void dap_chain_cs_dag_event_calc_hash(dap_chain_cs_dag_event_t * a_event,dap_chain_hash_fast_t * a_event_hash) +static inline void dap_chain_cs_dag_event_calc_hash(dap_chain_cs_dag_event_t * a_event,size_t a_event_size, dap_chain_hash_fast_t * a_event_hash) { - dap_hash_fast(a_event, dap_chain_cs_dag_event_calc_size (a_event) , a_event_hash); + dap_hash_fast(a_event, a_event_size , a_event_hash); }