diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb71372f3de98d3f9b4d738d19bfa0c5b0acd13..4b0b4cfebdd67ef29b3a37bd9db3356ba8643fb0 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.1-2") +set(CELLFRAME_SDK_NATIVE_VERSION "2.1-4") include(cmake/OS_Detection.cmake) add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") diff --git a/dap-sdk/core/include/dap_file_utils.h b/dap-sdk/core/include/dap_file_utils.h index 92cfe9812c49b4540b6c1d608de58e3470ce7a3e..9bc55055d72e00a02bdfc5d0d30ac3cca3ab4060 100755 --- a/dap-sdk/core/include/dap_file_utils.h +++ b/dap-sdk/core/include/dap_file_utils.h @@ -44,6 +44,9 @@ #else +#ifndef O_BINARY +# define O_BINARY 0 +#endif #define DAP_DIR_SEPARATOR '/' #define DAP_DIR_SEPARATOR_S "/" #define DAP_IS_DIR_SEPARATOR(c) ((c) == DAP_DIR_SEPARATOR) @@ -102,4 +105,10 @@ char* dap_path_get_dirname(const char *a_file_name); */ dap_list_name_directories_t *dap_get_subs(const char *a_path_name); + +/* + * Reads an entire file into allocated memory, with error checking. + */ +bool dap_file_get_contents(const char *filename, char **contents, size_t *length); + #endif // _FILE_UTILS_H_ diff --git a/dap-sdk/core/src/dap_file_utils.c b/dap-sdk/core/src/dap_file_utils.c index 910c64a79ee21dfc1aa2463b6cc3f39921b93894..8a666b8900eaafa1ad63be8eb47083da5f3b3b94 100755 --- a/dap-sdk/core/src/dap_file_utils.c +++ b/dap-sdk/core/src/dap_file_utils.c @@ -25,6 +25,11 @@ #include <stdlib.h> #include <stdint.h> #include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #if (OS_TARGET == OS_MACOS) #include <stdio.h> #else @@ -404,3 +409,203 @@ dap_list_name_directories_t *dap_get_subs(const char *a_path_dir){ #endif return list; } + +static bool get_contents_stdio(const char *filename, FILE *f, char **contents, size_t *length) +{ + char buf[4096]; + size_t bytes; /* always <= sizeof(buf) */ + char *str = NULL; + size_t total_bytes = 0; + size_t total_allocated = 0; + char *tmp; + assert(f != NULL); + while(!feof(f)) { + int save_errno; + + bytes = fread(buf, 1, sizeof(buf), f); + save_errno = errno; + + if(total_bytes > ULONG_MAX - bytes) + goto file_too_large; + + /* Possibility of overflow eliminated above. */ + while(total_bytes + bytes >= total_allocated) { + if(str) { + if(total_allocated > ULONG_MAX / 2) + goto file_too_large; + total_allocated *= 2; + } + else { + total_allocated = MIN(bytes + 1, sizeof(buf)); + } + + tmp = DAP_REALLOC(str, total_allocated); + + if(tmp == NULL) + goto error; + + str = tmp; + } + + if(ferror(f)) + goto error; + + assert(str != NULL); + memcpy(str + total_bytes, buf, bytes); + total_bytes += bytes; + } + + fclose(f); + + if(total_allocated == 0) + { + str = DAP_NEW_SIZE(char, 1); + total_bytes = 0; + } + + str[total_bytes] = '\0'; + + if(length) + *length = total_bytes; + + *contents = str; + + return true; + + file_too_large: + error: + + DAP_DELETE(str); + fclose(f); + return false; +} + +#ifndef _WIN32 + +static bool dap_get_contents_regfile(const char *filename, struct stat *stat_buf, int fd, char **contents, + size_t *length) +{ + char *buf; + size_t bytes_read; + size_t size; + size_t alloc_size; + + size = stat_buf->st_size; + + alloc_size = size + 1; + buf = DAP_NEW_SIZE(char, alloc_size); + + if(buf == NULL) { + goto error; + } + + bytes_read = 0; + while(bytes_read < size) { + size_t rc; + + rc = read(fd, buf + bytes_read, size - bytes_read); + + if(rc < 0) { + if(errno != EINTR) { + DAP_DELETE(buf); + goto error; + } + } + else if(rc == 0) + break; + else + bytes_read += rc; + } + + buf[bytes_read] = '\0'; + + if(length) + *length = bytes_read; + + *contents = buf; + + close(fd); + + return true; + + error: + + close(fd); + + return false; +} + +static bool dap_get_contents_posix(const char *filename, char **contents, size_t *length) +{ + struct stat stat_buf; + int fd; + + /* O_BINARY useful on Cygwin */ + fd = open(filename, O_RDONLY | O_BINARY); + + if(fd < 0) + return false; + + /* I don't think this will ever fail, aside from ENOMEM, but. */ + if(fstat(fd, &stat_buf) < 0) { + close(fd); + return false; + } + + if(stat_buf.st_size > 0 && S_ISREG(stat_buf.st_mode)) { + bool retval = dap_get_contents_regfile(filename, + &stat_buf, + fd, + contents, + length); + return retval; + } + else { + FILE *f; + bool retval; + f = fdopen(fd, "r"); + if(f == NULL) + return false; + retval = get_contents_stdio(filename, f, contents, length); + return retval; + } +} + +#else /* _WIN32 */ + +static bool dap_get_contents_win32(const char *filename, char **contents, size_t *length) +{ + FILE *f; + bool retval; + + f = fopen(filename, "rb"); + + if(f == NULL) + { + return false; + } + retval = get_contents_stdio (filename, f, contents, length); + return retval; +} + +#endif + +/* + * Reads an entire file into allocated memory, with error checking. + */ +bool dap_file_get_contents(const char *filename, char **contents, size_t *length) +{ + dap_return_val_if_fail(filename != NULL, false); + dap_return_val_if_fail(contents != NULL, false); + + *contents = NULL; + if(length) + *length = 0; + +#ifdef _WIN32 + return dap_get_contents_win32 (filename, contents, length); +#else + return dap_get_contents_posix(filename, contents, length); +#endif +} + diff --git a/dap-sdk/net/core/dap_events_socket.c b/dap-sdk/net/core/dap_events_socket.c index d297d1aecdee9ae289438ad437fb0700300a88fc..6060e27a3f02081a19c98a942885ceeace575afb 100644 --- a/dap-sdk/net/core/dap_events_socket.c +++ b/dap-sdk/net/core/dap_events_socket.c @@ -174,7 +174,7 @@ dap_events_socket_t *dap_events_socket_find( int sock, struct dap_events *a_even dap_events_socket_t *ret = NULL; if(!a_events) return NULL; - pthread_rwlock_rdlock( &a_events->sockets_rwlock ); + 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 ); diff --git a/dap-sdk/net/stream/stream/dap_stream.c b/dap-sdk/net/stream/stream/dap_stream.c index d6769440874667f6a4182fd522cdc95a66426d41..adc20540126577325035768c18a2f47330ce9269 100644 --- a/dap-sdk/net/stream/stream/dap_stream.c +++ b/dap-sdk/net/stream/stream/dap_stream.c @@ -776,7 +776,7 @@ void stream_proc_pkt_in(dap_stream_t * a_stream) // Find channel dap_stream_ch_t * ch = NULL; - pthread_rwlock_rdlock (&a_stream->rwlock); + pthread_rwlock_wrlock (&a_stream->rwlock); 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 ){ diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index b8aba895c5b025c991d3b01d6a06d883875e6dfd..08039a78ea10dae69067211070d5acf0bb2640f4 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -189,7 +189,7 @@ dap_chain_t * dap_chain_find_by_id(dap_chain_net_id_t a_chain_net_id,dap_chain_i }; dap_chain_item_t * l_ret_item = NULL; - pthread_rwlock_rdlock(&s_chain_items_rwlock); + pthread_rwlock_wrlock(&s_chain_items_rwlock); HASH_FIND(hh,s_chain_items,&l_chain_item_id,sizeof(dap_chain_item_id_t),l_ret_item); pthread_rwlock_unlock(&s_chain_items_rwlock); if ( l_ret_item ){ diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index 646f888ebce4b32d8cc91c9a8b64fc8f368a48f2..64c463ef26a9bb90905582b74c1c95f293def162 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -315,7 +315,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_ const char * c_token_ticker = a_token_emission->hdr.ticker; dap_chain_ledger_token_item_t * l_token_item = NULL; - pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock); HASH_FIND_STR(l_ledger_priv->tokens, c_token_ticker, l_token_item); pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); @@ -326,7 +326,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_ //dap_chain_hash_fast_t * l_token_emission_hash_ptr = &l_token_emission_hash; dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash); char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_token_emission_hash); - pthread_rwlock_rdlock( l_token_item ? + pthread_rwlock_wrlock( l_token_item ? &l_token_item->token_emissions_rwlock : &l_ledger_priv->treshold_emissions_rwlock ); @@ -364,7 +364,7 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, const char * c_token_ticker = a_token_emission->hdr.ticker; dap_chain_ledger_token_item_t * l_token_item = NULL; - pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock); HASH_FIND_STR(l_ledger_priv->tokens, c_token_ticker, l_token_item); pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); @@ -436,12 +436,12 @@ dap_chain_datum_token_emission_t * dap_chain_ledger_token_emission_find(dap_ledg dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_datum_token_emission_t * l_token_emission = NULL; dap_chain_ledger_token_item_t * l_token_item = NULL; - pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock); HASH_FIND_STR(l_ledger_priv->tokens, a_token_ticker, l_token_item); if(l_token_item) { dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL; - pthread_rwlock_rdlock( &l_token_item->token_emissions_rwlock); + pthread_rwlock_wrlock( &l_token_item->token_emissions_rwlock); HASH_FIND(hh, l_token_item->token_emissions, a_token_emission_hash, sizeof(*a_token_emission_hash), l_token_emission_item); if( l_token_emission_item) @@ -567,7 +567,7 @@ static dap_chain_datum_tx_t* s_find_datum_tx_by_hash(dap_ledger_t *a_ledger, dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_datum_tx_t *l_tx_ret = NULL; dap_chain_ledger_tx_item_t *l_tx_item; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_item); // tx_hash already in the hash? if(l_tx_item) { l_tx_ret = l_tx_item->tx; @@ -613,8 +613,10 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t */ dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - if(!a_tx) + if(!a_tx){ + log_it(L_DEBUG, "NULL transaction, check broken"); return -1; + } dap_list_t *l_list_bound_items = NULL; @@ -822,6 +824,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t dap_list_free_full(l_list_bound_items, free); if (l_list_tx_out) dap_list_free(l_list_tx_out); + log_it(L_ERROR, "Emission for tx_token wasn't found"); return -6; } } @@ -1150,7 +1153,7 @@ _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger) _dap_int128_t l_ret = 0; dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { l_ret++; @@ -1171,7 +1174,7 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro uint64_t l_ret = 0; dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); if ( a_ts_from && a_ts_to) { HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ if ( l_iter_current->ts_created >= a_ts_from && l_iter_current->ts_created <= a_ts_to ) @@ -1286,7 +1289,7 @@ uint64_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_ch */ dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_cur_tx = l_iter_current->tx; @@ -1346,7 +1349,7 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash); bool is_search_enable = is_null_hash; dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { // If a_token is setup we check if its not our token - miss it @@ -1423,7 +1426,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash); bool is_search_enable = is_null_hash; dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; @@ -1469,7 +1472,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash); bool is_search_enable = is_null_hash; dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); HASH_ITER(hh, l_ledger_priv->ledger_items, l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 3e789732cd26aab1bb4d610c91c2898e825fd4e1..be7b4e66c1ca411353de65f628fe9829be625b3c 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -194,6 +194,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) 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 @@ -203,6 +204,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) 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]); } @@ -535,12 +537,13 @@ void dap_stream_ch_chain_go_idle ( dap_stream_ch_chain_t * a_ch_chain) memset(&a_ch_chain->request_last_ts, 0, sizeof(a_ch_chain->request_last_ts)); dap_chain_atom_item_t *l_atom_item = NULL, *l_atom_item_tmp = NULL; - + pthread_mutex_lock(&a_ch_chain->mutex); HASH_ITER( hh,a_ch_chain->request_atoms_lasts, l_atom_item, l_atom_item_tmp) HASH_DEL(a_ch_chain->request_atoms_lasts, l_atom_item); 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); } @@ -702,6 +705,7 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) if(l_ch_chain->callback_notify_packet_out) l_ch_chain->callback_notify_packet_out(l_ch_chain, l_send_pkt_type, NULL, 0, l_ch_chain->callback_notify_arg); }else{ // Process one chain from l_ch_chain->request_atoms_lasts + pthread_mutex_lock(&l_ch_chain->mutex); HASH_ITER(hh,l_ch_chain->request_atoms_lasts, l_atom_item, l_atom_item_tmp) { dap_chain_atom_item_t * l_atom_item_proc = NULL; // Check if its processed already @@ -756,6 +760,7 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) 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; diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c index d0c8a39a530444b29c0714ee2b2cc8f1c05051b9..017e3d238717688379e60c587de666f07dd14b19 100644 --- a/modules/common/dap_chain_datum_token.c +++ b/modules/common/dap_chain_datum_token.c @@ -64,3 +64,74 @@ dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type, return l_tsd; } + +/** + * @brief dap_chain_datum_token_tsd_get + * @param a_token + * @param a_token_size + * @return + */ +dap_chain_datum_token_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t * a_token, size_t a_token_size) +{ + // Check if token type could have tsd section + size_t l_hdr_size; + size_t l_tsd_size; + switch( a_token->type){ + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL: + l_hdr_size = sizeof (a_token->header_private_decl); + if (l_hdr_size> a_token_size){ + log_it(L_WARNING, "Token size smaller then header, corrupted data"); + return NULL; + } + l_tsd_size = a_token->header_private_decl.tsd_total_size; + break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE: + l_hdr_size = sizeof(a_token->header_private_update); + if (l_hdr_size> a_token_size){ + log_it(L_WARNING, "Token size smaller then header, corrupted data"); + return NULL; + } + l_tsd_size = a_token->header_private_update.tsd_total_size; + break; + default: return NULL; + } + + if (l_tsd_size+l_hdr_size > a_token_size){ + log_it(L_WARNING, "TSD size %zd overlaps with header, corrupted data"); + }else if (l_tsd_size +l_hdr_size == a_token_size){ + log_it(L_INFO, "No signatures at all, returning pointer to the top of data"); + return (dap_chain_datum_token_tsd_t*) a_token->data_n_tsd; + } + + // Pass through signatures to find top of TSD section + size_t l_offset = 0; + while( l_offset < (a_token_size - l_hdr_size-l_tsd_size) ){ + dap_sign_t* l_sign = (dap_sign_t*) (a_token->data_n_tsd + l_offset); + if (l_sign->header.sign_size == 0){ + log_it( L_WARNING, "Corrupted signature, 0 size"); + return NULL; + } + l_offset += dap_sign_get_size( l_sign); + } + if ( l_offset + l_hdr_size +l_tsd_size <= a_token_size ) + return (dap_chain_datum_token_tsd_t*) (a_token->data_n_tsd+l_offset); + else{ + log_it(L_WARNING, "Signatures overlaps with TSD section, corrupted data"); + return NULL; + } +} + +/** + * @brief dap_chain_datum_token_flags_dump + * @param a_str_out + * @param a_flags + */ +void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags) +{ + for ( uint16_t i = 0; (2^i) <=DAP_CHAIN_DATUM_TOKEN_FLAG_MAX; i++ ){ + if( a_flags & (2^i) ) + dap_string_append_printf(a_str_out,"%s%s", c_dap_chain_datum_token_flag_str[2^i], + (2^i)==DAP_CHAIN_DATUM_TOKEN_FLAG_MAX?",":"\n" ); + } +} + diff --git a/modules/common/include/dap_chain_datum_token.h b/modules/common/include/dap_chain_datum_token.h index 695c7e02a6dd8ccca54a81e675c8008171bc22fc..f347de9d1a40e2a85816ca6ab105bab9fcefb570 100644 --- a/modules/common/include/dap_chain_datum_token.h +++ b/modules/common/include/dap_chain_datum_token.h @@ -24,8 +24,10 @@ */ #pragma once #include "dap_chain_common.h" +#include "dap_hash.h" #include "dap_sign.h" +#include "dap_string.h" #include "dap_strfuncs.h" // Token declaration @@ -148,24 +150,27 @@ typedef struct dap_chain_datum_token_tsd{ // Set total signs count value to set to be valid #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID 0x0004 +// Remove owner signature by pkey fingerprint +#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE 0x0005 + // Add owner signature's pkey fingerprint #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD 0x0006 -// Remove owner signature by pkey fingerprint -#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE 0x0007 /// ------- Permissions list flags, grouped by update-remove-clear operations -------- +// Blocked datum types list add, remove or clear +#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD 0x0007 +#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE 0x0008 +#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_CLEAR 0x0009 + + // Allowed datum types list add, remove or clear #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD 0x0010 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE 0x0011 #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_CLEAR 0x0012 -// Blocked datum types list add, remove or clear -#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD 0x0013 -#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE 0x0014 -#define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_CLEAR 0x0015 //Allowed tx receiver addres list add, remove or clear #define DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD 0x0014 @@ -230,12 +235,15 @@ extern const char *c_dap_chain_datum_token_emission_type_str[]; /// dap_chain_datum_token_tsd_t * dap_chain_datum_token_tsd_create(uint16_t a_type, const void * a_data, size_t a_data_size); +dap_chain_datum_token_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t * a_token, size_t a_token_size); +void dap_chain_datum_token_flags_dump(dap_string_t * a_str_out, uint16_t a_flags); + #define dap_chain_datum_token_tsd_create_scalar(type,value) dap_chain_datum_token_tsd_create (type, &value, sizeof(value) ) #define dap_chain_datum_token_tsd_get_scalar(a,typeconv) *((typeconv*) a->data) // NULL-terminated string #define dap_chain_datum_token_tsd_create_string(type,str) dap_chain_datum_token_tsd_create (type,str, dap_strlen(str)) -#define dap_chain_datum_token_tsd_get_string(a) ((char*) a->data ) -#define dap_chain_datum_token_tsd_get_string_const(a) ((const char*) a->data ) +#define dap_chain_datum_token_tsd_get_string(a) ( ((char*) a->data )[a->size-1] == '\0'? (char*) a->data : "<CORRUPTED STRING>" ) +#define dap_chain_datum_token_tsd_get_string_const(a) ( ((const char*) a->data )[a->size-1] == '\0'? (const char*) a->data : "<CORRUPTED STRING>" ) #define dap_chain_datum_token_tsd_size(a) (sizeof(*a)+a->size) diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 817a8666efa59c87a67ec6423bfa442d6b46a531..82c303ddcda2ddc1187c66c57cf6bf3db5aea045 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -106,6 +106,7 @@ typedef struct dap_chain_net_pvt{ #else HANDLE state_proc_cond; #endif + pthread_mutex_t state_mutex_cond; dap_chain_node_role_t node_role; uint32_t flags; time_t last_sync; @@ -134,7 +135,6 @@ typedef struct dap_chain_net_pvt{ dap_chain_net_state_t state; dap_chain_net_state_t state_target; - dap_chain_net_state_t state_new; } dap_chain_net_pvt_t; typedef struct dap_chain_net_item{ @@ -209,10 +209,19 @@ inline static const char * s_net_state_to_str(dap_chain_net_state_t l_state) */ int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_new_state) { - if (PVT(a_net)->state_new == a_new_state){ + if (PVT(a_net)->state_target == a_new_state){ log_it(L_WARNING,"Already going to state %s",s_net_state_to_str(a_new_state)); } - PVT(a_net)->state_new = a_new_state; + PVT(a_net)->state_target = a_new_state; + pthread_mutex_lock( &PVT(a_net)->state_mutex_cond); + // set flag for sync + PVT(a_net)->flags |= F_DAP_CHAIN_NET_GO_SYNC; +#ifndef _WIN32 + pthread_cond_signal( &PVT(a_net)->state_proc_cond ); +#else + SetEvent( PVT(a_net)->state_proc_cond ); +#endif + pthread_mutex_unlock( &PVT(a_net)->state_mutex_cond); return 0; } @@ -266,87 +275,84 @@ static void s_chain_callback_notify(void * a_arg, dap_chain_t *a_chain, dap_chai */ static int s_net_states_proc(dap_chain_net_t * l_net) { -#if DAP_DEBUG - dap_chain_net_pvt_t *pvt_debug = PVT(l_net); -#endif + + dap_chain_net_pvt_t *l_pvt_net = PVT(l_net); + int ret=0; - switch ( PVT(l_net)->state ){ + switch ( l_pvt_net->state ){ case NET_STATE_OFFLINE:{ - if (PVT(l_net)->state_new != NET_STATE_UNDEFINED) { - PVT(l_net)->state_target = PVT(l_net)->state_new; - PVT(l_net)->state_new = NET_STATE_UNDEFINED; - } // reset current link - PVT(l_net)->links_count = 0; + l_pvt_net->links_count = 0; // delete all links - dap_chain_node_client_close(PVT(l_net)->links); - PVT(l_net)->links_addrs_count = 0; - if ( PVT(l_net)->links_addrs ) - DAP_DELETE(PVT(l_net)->links_addrs); - PVT(l_net)->links_addrs = NULL; - - if ( PVT(l_net)->state_target != NET_STATE_OFFLINE ){ - PVT(l_net)->state = NET_STATE_LINKS_PREPARE; + dap_chain_node_client_close(l_pvt_net->links); + l_pvt_net->links = NULL; + l_pvt_net->links_addrs_count = 0; + if ( l_pvt_net->links_addrs ) + DAP_DELETE(l_pvt_net->links_addrs); + l_pvt_net->links_addrs = NULL; + + if ( l_pvt_net->state_target != NET_STATE_OFFLINE ){ + l_pvt_net->state = NET_STATE_LINKS_PREPARE; break; } // disable SYNC_GDB - PVT(l_net)->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; - PVT(l_net)->last_sync = 0; + l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->last_sync = 0; } break; case NET_STATE_LINKS_PREPARE:{ log_it(L_NOTICE,"%s.state: NET_STATE_LINKS_PREPARE",l_net->pub.name); - switch (PVT(l_net)->node_role.enums) { + switch (l_pvt_net->node_role.enums) { case NODE_ROLE_ROOT: case NODE_ROLE_ROOT_MASTER: case NODE_ROLE_ARCHIVE: case NODE_ROLE_CELL_MASTER:{ // This roles load predefined links from global_db - if ( PVT(l_net)->node_info ) { - if (PVT(l_net)->links_addrs ) - DAP_DELETE(PVT(l_net)->links_addrs); - PVT(l_net)->links_addrs_count = PVT(l_net)->node_info->hdr.links_number; - PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE( dap_chain_node_addr_t, - PVT(l_net)->links_addrs_count * sizeof(dap_chain_node_addr_t)); - for (size_t i =0 ; i < PVT(l_net)->node_info->hdr.links_number; i++ ){ - PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->node_info->links[i].uint64; + if ( l_pvt_net->node_info ) { + if (l_pvt_net->links_addrs ) + DAP_DELETE(l_pvt_net->links_addrs); + l_pvt_net->links_addrs_count = l_pvt_net->node_info->hdr.links_number; + l_pvt_net->links_addrs = DAP_NEW_Z_SIZE( dap_chain_node_addr_t, + l_pvt_net->links_addrs_count * sizeof(dap_chain_node_addr_t)); + for (size_t i =0 ; i < l_pvt_net->node_info->hdr.links_number; i++ ){ + l_pvt_net->links_addrs[i].uint64 = l_pvt_net->node_info->links[i].uint64; } }else { log_it(L_WARNING,"No nodeinfo in global_db to prepare links for connecting, find nearest 3 links and fill global_db"); } // add other root nodes for connect - //if(!PVT(l_net)->links_addrs_count) + //if(!l_pvt_net->links_addrs_count) { // use no more then 4 root node - int l_use_root_nodes = min(4, PVT(l_net)->seed_aliases_count); - if(!PVT(l_net)->links_addrs_count) { - PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, + int l_use_root_nodes = min(4, l_pvt_net->seed_aliases_count); + if(!l_pvt_net->links_addrs_count) { + l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, l_use_root_nodes * sizeof(dap_chain_node_addr_t)); } else{ - PVT(l_net)->links_addrs = DAP_REALLOC(PVT(l_net)->links_addrs, - (PVT(l_net)->links_addrs_count+l_use_root_nodes) * sizeof(dap_chain_node_addr_t)); - memset(PVT(l_net)->links_addrs + PVT(l_net)->links_addrs_count, 0, + l_pvt_net->links_addrs = DAP_REALLOC(l_pvt_net->links_addrs, + (l_pvt_net->links_addrs_count+l_use_root_nodes) * sizeof(dap_chain_node_addr_t)); + memset(l_pvt_net->links_addrs + l_pvt_net->links_addrs_count, 0, l_use_root_nodes * sizeof(dap_chain_node_addr_t)); } for(uint16_t i = 0; i < l_use_root_nodes; i++) { - dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, PVT(l_net)->seed_aliases[i]); + dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, l_pvt_net->seed_aliases[i]); if(l_node_addr) { - PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 = l_node_addr->uint64; - PVT(l_net)->links_addrs_count++; + l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 = l_node_addr->uint64; + l_pvt_net->links_addrs_count++; } } } // shuffle the order of the nodes - for(size_t i = 0; i < PVT(l_net)->links_addrs_count; i++) { - unsigned int l_new_node_pos = rand() % (PVT(l_net)->links_addrs_count); + for(size_t i = 0; i < l_pvt_net->links_addrs_count; i++) { + unsigned int l_new_node_pos = rand() % (l_pvt_net->links_addrs_count); if(i == l_new_node_pos) continue; - uint64_t l_tmp_uint64 = PVT(l_net)->links_addrs[i].uint64; - PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->links_addrs[l_new_node_pos].uint64; - PVT(l_net)->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64; + uint64_t l_tmp_uint64 = l_pvt_net->links_addrs[i].uint64; + l_pvt_net->links_addrs[i].uint64 = l_pvt_net->links_addrs[l_new_node_pos].uint64; + l_pvt_net->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64; } @@ -357,7 +363,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net) // If we haven't any assigned shard - connect to root-0 if(1) { //if(l_net->pub.cell_id.uint64 == 0) { - //dap_chain_net_pvt_t *pvt_debug = PVT(l_net); + //dap_chain_net_pvt_t *pvt_debug = l_pvt_net; // get current node address dap_chain_node_addr_t l_address; l_address.uint64 = dap_chain_net_get_cur_addr(l_net) ? @@ -368,8 +374,8 @@ static int s_net_states_proc(dap_chain_net_t * l_net) dap_chain_node_info_t *l_cur_node_info = dap_chain_node_info_read(l_net, &l_address); if ( l_cur_node_info ) { - uint16_t l_links_addrs_count = l_cur_node_info->hdr.links_number + PVT(l_net)->seed_aliases_count; - PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, + uint16_t l_links_addrs_count = l_cur_node_info->hdr.links_number + l_pvt_net->seed_aliases_count; + l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, l_links_addrs_count * sizeof(dap_chain_node_addr_t)); // add linked nodes for connect @@ -381,37 +387,37 @@ static int s_net_states_proc(dap_chain_net_t * l_net) // if only nodes from the same cell of cell=0 if(!l_cur_node_info->hdr.cell_id.uint64 || l_cur_node_info->hdr.cell_id.uint64 == l_remore_node_info->hdr.cell_id.uint64) { - PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 = + l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 = l_remore_node_info->hdr.address.uint64; - PVT(l_net)->links_addrs_count++; + l_pvt_net->links_addrs_count++; } DAP_DELETE(l_remore_node_info); } } } // if no links then add root nodes for connect - if(!PVT(l_net)->links_addrs_count){ + if(!l_pvt_net->links_addrs_count){ // use no more then 4 root node - int l_use_root_nodes = min(4, PVT(l_net)->seed_aliases_count); - PVT(l_net)->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, + int l_use_root_nodes = min(4, l_pvt_net->seed_aliases_count); + l_pvt_net->links_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t, l_use_root_nodes * sizeof(dap_chain_node_addr_t)); for(uint16_t i = 0; i < l_use_root_nodes; i++) { - dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, PVT(l_net)->seed_aliases[i]); + dap_chain_node_addr_t * l_node_addr = dap_chain_node_alias_find(l_net, l_pvt_net->seed_aliases[i]); if(l_node_addr) { - PVT(l_net)->links_addrs[PVT(l_net)->links_addrs_count].uint64 = l_node_addr->uint64; - PVT(l_net)->links_addrs_count++; + l_pvt_net->links_addrs[l_pvt_net->links_addrs_count].uint64 = l_node_addr->uint64; + l_pvt_net->links_addrs_count++; } } } // shuffle the order of the nodes - for(size_t i = 0; i < PVT(l_net)->links_addrs_count; i++) { - unsigned int l_new_node_pos = rand() % (PVT(l_net)->links_addrs_count); + for(size_t i = 0; i < l_pvt_net->links_addrs_count; i++) { + unsigned int l_new_node_pos = rand() % (l_pvt_net->links_addrs_count); if(i==l_new_node_pos) continue; - uint64_t l_tmp_uint64 = PVT(l_net)->links_addrs[i].uint64; - PVT(l_net)->links_addrs[i].uint64 = PVT(l_net)->links_addrs[l_new_node_pos].uint64; - PVT(l_net)->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64; + uint64_t l_tmp_uint64 = l_pvt_net->links_addrs[i].uint64; + l_pvt_net->links_addrs[i].uint64 = l_pvt_net->links_addrs[l_new_node_pos].uint64; + l_pvt_net->links_addrs[l_new_node_pos].uint64 = l_tmp_uint64; } DAP_DELETE(l_cur_node_info); }else { @@ -419,40 +425,40 @@ static int s_net_states_proc(dap_chain_net_t * l_net) } } break; } - if ( PVT(l_net)->state_target > NET_STATE_LINKS_PREPARE ){ - if ( PVT(l_net)->links_addrs_count>0 ) { // If links are present - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; - log_it(L_DEBUG,"Prepared %u links, start to establish them", PVT(l_net)->links_addrs_count ); + if ( l_pvt_net->state_target > NET_STATE_LINKS_PREPARE ){ + if ( l_pvt_net->links_addrs_count>0 ) { // If links are present + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; + log_it(L_DEBUG,"Prepared %u links, start to establish them", l_pvt_net->links_addrs_count ); } else { log_it(L_WARNING,"No links for connecting, return back to OFFLINE state"); - PVT(l_net)->state = NET_STATE_OFFLINE; + l_pvt_net->state = NET_STATE_OFFLINE; // remove looping - PVT(l_net)->state_target = NET_STATE_OFFLINE; + l_pvt_net->state_target = NET_STATE_OFFLINE; } }else { log_it(L_WARNING,"Target state is NET_STATE_LINKS_PREPARE? Realy?"); - PVT(l_net)->state = NET_STATE_OFFLINE; + l_pvt_net->state = NET_STATE_OFFLINE; } } break; case NET_STATE_LINKS_CONNECTING:{ - size_t l_links_count = PVT(l_net)->links_count; + size_t l_links_count = l_pvt_net->links_count; if(l_links_count >= s_required_links_count || (l_links_count + 1) >= s_max_links_count) { // TODO what if other failed and we want more? } - if (l_links_count < PVT(l_net)->links_addrs_count) { - PVT(l_net)->links_count++; + if (l_links_count < l_pvt_net->links_addrs_count) { + l_pvt_net->links_count++; } else { log_it(L_NOTICE, "Can't establish enough links, go to offline"); - PVT(l_net)->state = NET_STATE_OFFLINE; - PVT(l_net)->state_target = NET_STATE_OFFLINE; + l_pvt_net->state = NET_STATE_OFFLINE; + l_pvt_net->state_target = NET_STATE_OFFLINE; break; } log_it(L_DEBUG, "%s.state: NET_STATE_LINKS_CONNECTING",l_net->pub.name); log_it(L_DEBUG, "Establishing connection with " NODE_ADDR_FP_STR, - NODE_ADDR_FP_ARGS_S( PVT(l_net)->links_addrs[l_links_count]) ); - dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(l_net, &PVT(l_net)->links_addrs[l_links_count]); + NODE_ADDR_FP_ARGS_S( l_pvt_net->links_addrs[l_links_count]) ); + dap_chain_node_info_t *l_link_node_info = dap_chain_node_info_read(l_net, &l_pvt_net->links_addrs[l_links_count]); if ( l_link_node_info ) { dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect(l_link_node_info); if(!l_node_client) { @@ -465,11 +471,12 @@ static int s_net_states_proc(dap_chain_net_t * l_net) int res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms); if (res == 0 ){ log_it(L_DEBUG, "Connected link %u", l_links_count); - PVT(l_net)->links = l_node_client; - PVT(l_net)->state = NET_STATE_LINKS_ESTABLISHED; + l_pvt_net->links = l_node_client; + l_pvt_net->state = NET_STATE_LINKS_ESTABLISHED; }else { log_it(L_DEBUG, "Cant establish link %u", l_links_count); dap_chain_node_client_close(l_node_client); + l_node_client = NULL; } } } @@ -477,31 +484,31 @@ static int s_net_states_proc(dap_chain_net_t * l_net) case NET_STATE_LINKS_ESTABLISHED:{ log_it(L_DEBUG,"%s.state: NET_STATE_LINKS_ESTABLISHED",l_net->pub.name); - switch (PVT(l_net)->state_target) { + switch (l_pvt_net->state_target) { case NET_STATE_ONLINE:{ // Online - switch ( PVT(l_net)->node_role.enums ){ + switch ( l_pvt_net->node_role.enums ){ case NODE_ROLE_ROOT_MASTER: case NODE_ROLE_ROOT:{ /*dap_chain_node_client_t * l_node_client = NULL, *l_node_client_tmp = NULL; // Send everybody your address when linked - HASH_ITER(hh,PVT(l_net)->links,l_node_client,l_node_client_tmp){ + HASH_ITER(hh,l_pvt_net->links,l_node_client,l_node_client_tmp){ dap_stream_ch_chain_net_pkt_write(dap_client_get_stream_ch( l_node_client->client, dap_stream_ch_chain_net_get_id()), DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_ADDR, l_net->pub.id, dap_chain_net_get_cur_addr(l_net), sizeof (dap_chain_node_addr_t) ); }*/ - PVT(l_net)->state = NET_STATE_SYNC_GDB; + l_pvt_net->state = NET_STATE_SYNC_GDB; }break; case NODE_ROLE_CELL_MASTER: case NODE_ROLE_MASTER:{ - PVT(l_net)->state = NET_STATE_SYNC_GDB;//NET_STATE_ADDR_REQUEST; + l_pvt_net->state = NET_STATE_SYNC_GDB;//NET_STATE_ADDR_REQUEST; } break; default:{ // get addr for current node if it absent if(!dap_chain_net_get_cur_addr_int(l_net)) - PVT(l_net)->state = NET_STATE_ADDR_REQUEST; + l_pvt_net->state = NET_STATE_ADDR_REQUEST; else PVT( l_net)->state = NET_STATE_SYNC_GDB; } @@ -510,33 +517,33 @@ static int s_net_states_proc(dap_chain_net_t * l_net) break; case NET_STATE_SYNC_GDB: // we need only to sync gdb - PVT(l_net)->state = NET_STATE_SYNC_GDB ; - if ( PVT(l_net)->addr_request_attempts >=10 && PVT(l_net)->state == NET_STATE_ADDR_REQUEST){ - PVT(l_net)->addr_request_attempts = 0; - switch( PVT(l_net)->state_target){ + l_pvt_net->state = NET_STATE_SYNC_GDB ; + if ( l_pvt_net->addr_request_attempts >=10 && l_pvt_net->state == NET_STATE_ADDR_REQUEST){ + l_pvt_net->addr_request_attempts = 0; + switch( l_pvt_net->state_target){ case NET_STATE_ONLINE: case NET_STATE_SYNC_GDB: - PVT(l_net)->state = NET_STATE_SYNC_GDB; + l_pvt_net->state = NET_STATE_SYNC_GDB; break; case NET_STATE_SYNC_CHAINS: - PVT(l_net)->state = NET_STATE_SYNC_CHAINS; + l_pvt_net->state = NET_STATE_SYNC_CHAINS; break; default: { - PVT(l_net)->state = NET_STATE_OFFLINE; - PVT(l_net)->state_target = NET_STATE_OFFLINE; + l_pvt_net->state = NET_STATE_OFFLINE; + l_pvt_net->state_target = NET_STATE_OFFLINE; } } } break; case NET_STATE_SYNC_CHAINS: - PVT(l_net)->state = (PVT(l_net)->node_info && PVT(l_net)->node_info->hdr.address.uint64)? + l_pvt_net->state = (l_pvt_net->node_info && l_pvt_net->node_info->hdr.address.uint64)? NET_STATE_SYNC_CHAINS : NET_STATE_ADDR_REQUEST; break; case NET_STATE_ADDR_REQUEST : - PVT(l_net)->state = NET_STATE_ADDR_REQUEST; + l_pvt_net->state = NET_STATE_ADDR_REQUEST; break; default: break; } @@ -544,7 +551,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net) // get addr for remote node case NET_STATE_ADDR_REQUEST: { int l_is_addr_leased = 0; - dap_chain_node_client_t *l_node_client = PVT(l_net)->links; + dap_chain_node_client_t *l_node_client = l_pvt_net->links; uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for chain net request dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch(l_node_client->client, l_ch_id); // set callback for l_ch_id @@ -557,27 +564,28 @@ static int s_net_states_proc(dap_chain_net_t * l_net) if (res == 0) { log_it(L_WARNING,"Can't send NODE_ADDR_REQUEST packet"); dap_chain_node_client_close(l_node_client); - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_node_client = NULL; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; // try with another link } // wait for finishing of request int timeout_ms = 5000; // 5 sec = 5 000 ms // TODO add progress info to console - PVT(l_net)->addr_request_attempts++; + l_pvt_net->addr_request_attempts++; int l_res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_NODE_ADDR_LEASED, timeout_ms); switch (l_res) { case -1: log_it(L_WARNING,"Timeout with addr leasing"); // try again 3 times - if (PVT(l_net)->addr_request_attempts < 3) { + if (l_pvt_net->addr_request_attempts < 3) { break; } - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; // try with another link case 0: log_it(L_INFO, "Node address leased"); l_is_addr_leased++; - PVT(l_net)->addr_request_attempts = 0; + l_pvt_net->addr_request_attempts = 0; break; default: if (l_node_client->last_error[0]) { @@ -585,17 +593,17 @@ static int s_net_states_proc(dap_chain_net_t * l_net) l_node_client->last_error[0] = '\0'; } log_it(L_INFO, "Node address request error %d", l_res); - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; } if (l_is_addr_leased > 0) { - PVT(l_net)->state = NET_STATE_SYNC_GDB; + l_pvt_net->state = NET_STATE_SYNC_GDB; } } break; case NET_STATE_SYNC_GDB:{ // send request - dap_chain_node_client_t *l_node_client = PVT(l_net)->links; + dap_chain_node_client_t *l_node_client = l_pvt_net->links; 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); @@ -622,7 +630,8 @@ static int s_net_states_proc(dap_chain_net_t * l_net) if (l_res == 0) { log_it(L_WARNING, "Can't send GDB sync request"); dap_chain_node_client_close(l_node_client); - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_node_client = NULL; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; //try another link } @@ -643,21 +652,22 @@ static int s_net_states_proc(dap_chain_net_t * l_net) if (l_res) { // try another link break; } - if(PVT(l_net)->state_target >= NET_STATE_SYNC_CHAINS){ - PVT(l_net)->state = NET_STATE_SYNC_CHAINS; + if(l_pvt_net->state_target >= NET_STATE_SYNC_CHAINS){ + l_pvt_net->state = NET_STATE_SYNC_CHAINS; } else { - PVT(l_net)->state = NET_STATE_ONLINE; + l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->state = NET_STATE_ONLINE; } } break; case NET_STATE_SYNC_CHAINS: { - dap_chain_node_client_t *l_node_client = PVT(l_net)->links; + dap_chain_node_client_t *l_node_client = l_pvt_net->links; uint8_t l_ch_id = dap_stream_ch_chain_get_id(); // Channel id for global_db and chains sync dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch(l_node_client->client, l_ch_id); if(!l_ch_chain) { log_it(L_DEBUG,"Can't get stream_ch for id='%c' ", l_ch_id); - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; } dap_chain_t * l_chain = NULL; @@ -695,7 +705,7 @@ static int s_net_states_proc(dap_chain_net_t * l_net) { struct timespec l_to; clock_gettime( CLOCK_MONOTONIC, &l_to); - PVT(l_net)->last_sync = l_to.tv_sec; + l_pvt_net->last_sync = l_to.tv_sec; } break; default: @@ -709,36 +719,35 @@ static int s_net_states_proc(dap_chain_net_t * l_net) //DAP_DELETE( l_atom_iter ); } dap_chain_node_client_close(l_node_client); + l_node_client = NULL; if (l_sync_errors) { - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; } log_it(L_INFO, "Synchronization done"); - PVT(l_net)->state = NET_STATE_ONLINE; - PVT(l_net)->links_count = 0; + l_pvt_net->flags &= ~F_DAP_CHAIN_NET_GO_SYNC; + l_pvt_net->state = NET_STATE_ONLINE; + l_pvt_net->links_count = 0; } break; case NET_STATE_ONLINE: { - if (PVT(l_net)->state_new != NET_STATE_UNDEFINED) { - PVT(l_net)->state_target = PVT(l_net)->state_new; - PVT(l_net)->state_new = NET_STATE_UNDEFINED; - } - switch ( PVT(l_net)->state_target) { + if (l_pvt_net->flags & F_DAP_CHAIN_NET_GO_SYNC) + { + switch ( l_pvt_net->state_target) { // disconnect case NET_STATE_OFFLINE: - PVT(l_net)->state = NET_STATE_OFFLINE; + l_pvt_net->state = NET_STATE_OFFLINE; log_it(L_NOTICE, "Going to disconnet"); break; case NET_STATE_ONLINE: - if((PVT(l_net)->flags & F_DAP_CHAIN_NET_GO_SYNC) == 0) - break; case NET_STATE_SYNC_GDB: case NET_STATE_SYNC_CHAINS: // if flag set then go to SYNC_GDB - PVT(l_net)->state = NET_STATE_LINKS_CONNECTING; + l_pvt_net->state = NET_STATE_LINKS_CONNECTING; break; default: break; + } } } break; @@ -770,18 +779,45 @@ static void *s_net_proc_thread ( void *a_net ) dap_chain_net_t *l_net = (dap_chain_net_t *)a_net; dap_chain_net_pvt_t *p_net = (dap_chain_net_pvt_t *)(void *)l_net->pvt; + const uint64_t l_timeout_ms = 60000;// 60 sec + // set callback to update data //dap_chain_global_db_set_callback_for_update_base(s_net_proc_thread_callback_update_db); while( !(p_net->flags & F_DAP_CHAIN_NET_SHUTDOWN) ) { + // check or start sync s_net_states_proc( l_net ); - // checking whether new sync is needed struct timespec l_to; +#ifndef _WIN32 + int l_ret = 0; + // prepare for signal waiting + clock_gettime( CLOCK_MONOTONIC, &l_to ); + int64_t l_nsec_new = l_to.tv_nsec + l_timeout_ms * 1000000ll; + // if the new number of nanoseconds is more than a second + if(l_nsec_new > (long) 1e9) { + l_to.tv_sec += l_nsec_new / (long) 1e9; + l_to.tv_nsec = l_nsec_new % (long) 1e9; + } + else + l_to.tv_nsec = (long) l_nsec_new; + pthread_mutex_lock( &p_net->state_mutex_cond ); + // wait if flag not set then go to SYNC_GDB + while ((p_net->flags & F_DAP_CHAIN_NET_GO_SYNC) == 0 && l_ret == 0) { + // signal waiting + l_ret = pthread_cond_timedwait( &p_net->state_proc_cond, &p_net->state_mutex_cond, &l_to ); + } + pthread_mutex_unlock(&p_net->state_mutex_cond); +#else // WIN32 + + WaitForSingleObject( p_net->state_proc_cond, (uint32_t)l_timeout_ms ); + +#endif + // checking whether new sync is needed time_t l_sync_timeout = 300; // 300 sec = 5 min clock_gettime(CLOCK_MONOTONIC, &l_to); // start sync every l_sync_timeout sec - if(p_net->last_sync && l_to.tv_sec >= p_net->last_sync + l_sync_timeout) { + if(l_to.tv_sec >= p_net->last_sync + l_sync_timeout) { p_net->flags |= F_DAP_CHAIN_NET_GO_SYNC; } } @@ -1099,12 +1135,12 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) dap_chain_net_state_go_to(l_net, NET_STATE_ONLINE); dap_chain_node_cli_set_reply_text(a_str_reply, "Network \"%s\" go from state %s to %s", l_net->pub.name,c_net_states[PVT(l_net)->state], - c_net_states[PVT(l_net)->state_new]); + c_net_states[PVT(l_net)->state_target]); } else if ( strcmp(l_go_str,"offline") == 0 ) { dap_chain_net_state_go_to(l_net, NET_STATE_OFFLINE); dap_chain_node_cli_set_reply_text(a_str_reply, "Network \"%s\" go from state %s to %s", l_net->pub.name,c_net_states[PVT(l_net)->state], - c_net_states[PVT(l_net)->state_new]); + c_net_states[PVT(l_net)->state_target]); } else if(strcmp(l_go_str, "sync") == 0) { @@ -2096,3 +2132,201 @@ int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t default: return 0; } } + +/** + * @brief dap_chain_net_dump_datum + * @param a_str_out + * @param a_datum + */ +void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_datum) +{ + if( a_datum == NULL){ + dap_string_append_printf(a_str_out,"==Datum is NULL\n"); + return; + } + switch (a_datum->header.type_id){ + case DAP_CHAIN_DATUM_TOKEN_DECL:{ + dap_chain_datum_token_t * l_token = (dap_chain_datum_token_t*) a_datum->data; + size_t l_token_size = a_datum->header.data_size; + dap_string_append_printf(a_str_out,"==Datum Token Declaration\n"); + dap_string_append_printf(a_str_out, "ticker: %s\n", l_token->ticker); + dap_string_append_printf(a_str_out, "size: %zd\n", l_token_size); + switch (l_token->type) { + case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE:{ + dap_string_append_printf(a_str_out, "type: SIMPLE\n"); + dap_string_append_printf(a_str_out, "sign_total: %u\n", l_token->header_private.signs_total ); + dap_string_append_printf(a_str_out, "sign_valid: %u\n", l_token->header_private.signs_valid ); + dap_string_append_printf(a_str_out, "total_supply: %u\n", l_token->header_private.total_supply ); + }break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE:{ + dap_string_append_printf(a_str_out,"type: PRIVATE_UPDATE\n"); + dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_get(l_token, l_token_size); + if (l_tsd == NULL) + dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n"); + else{ + size_t l_offset = 0; + size_t l_offset_max = l_token->header_private_decl.tsd_total_size; + while( l_offset< l_offset_max){ + if ( (l_tsd->size+l_offset) >l_offset_max){ + log_it(L_WARNING, "<CORRUPTED TSD> too big size %zd when left maximum %zd", + l_tsd->size, l_offset_max - l_offset); + return; + } + switch( l_tsd->type){ + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: + dap_string_append_printf(a_str_out,"flags_set: "); + dap_chain_datum_token_flags_dump(a_str_out, + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t)); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: + dap_string_append_printf(a_str_out,"flags_unset: "); + dap_chain_datum_token_flags_dump(a_str_out, + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t)); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: + dap_string_append_printf(a_str_out,"total_supply: %u\n", + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint128_t) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID : + dap_string_append_printf(a_str_out,"total_signs_valid: %u\n", + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_ADD : + if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){ + char *l_hash_str = dap_chain_hash_fast_to_str_new( + (dap_chain_hash_fast_t*) l_tsd->data ); + dap_string_append_printf(a_str_out,"total_signs_add: %s\n", l_hash_str ); + DAP_DELETE( l_hash_str ); + }else + dap_string_append_printf(a_str_out,"total_signs_add: <WRONG SIZE %zd>\n", l_tsd->size); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_REMOVE : + if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){ + char *l_hash_str = dap_chain_hash_fast_to_str_new( + (dap_chain_hash_fast_t*) l_tsd->data ); + dap_string_append_printf(a_str_out,"total_signs_remoev: %s\n", l_hash_str ); + DAP_DELETE( l_hash_str ); + }else + dap_string_append_printf(a_str_out,"total_signs_add: <WRONG SIZE %zd>\n", l_tsd->size); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD : + dap_string_append_printf(a_str_out,"datum_type_allowed_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE : + dap_string_append_printf(a_str_out,"datum_type_allowed_remove: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD : + dap_string_append_printf(a_str_out,"datum_type_blocked_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE: + dap_string_append_printf(a_str_out,"datum_type_blocked_remove: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: + dap_string_append_printf(a_str_out,"tx_sender_allowed_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE: + dap_string_append_printf(a_str_out,"tx_sender_allowed_remove: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: + dap_string_append_printf(a_str_out,"tx_sender_blocked_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE: + dap_string_append_printf(a_str_out,"tx_sender_blocked_remove: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: + dap_string_append_printf(a_str_out,"tx_receiver_allowed_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE: + dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: + dap_string_append_printf(a_str_out, "tx_receiver_blocked_add: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE: + dap_string_append_printf(a_str_out, "tx_receiver_blocked_remove: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + default: dap_string_append_printf(a_str_out, "<0x%04X>: <size %zd>\n", l_tsd->type, l_tsd->size); + } + l_offset += dap_chain_datum_token_tsd_size(l_tsd); + + } + } + }break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_DECL:{ + dap_string_append_printf(a_str_out,"type: PRIVATE_DECL\n"); + dap_string_append_printf(a_str_out,"flags: "); + dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_decl.flags); + dap_chain_datum_token_tsd_t * l_tsd = dap_chain_datum_token_tsd_get(l_token, l_token_size); + if (l_tsd == NULL) + dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n"); + else{ + size_t l_offset = 0; + size_t l_offset_max = l_token->header_private_decl.tsd_total_size; + while( l_offset< l_offset_max){ + if ( (l_tsd->size+l_offset) >l_offset_max){ + log_it(L_WARNING, "<CORRUPTED TSD> too big size %zd when left maximum %zd", + l_tsd->size, l_offset_max - l_offset); + return; + } + switch( l_tsd->type){ + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: + dap_string_append_printf(a_str_out,"total_supply: %u\n", + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint128_t) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID : + dap_string_append_printf(a_str_out,"total_signs_valid: %u\n", + dap_chain_datum_token_tsd_get_scalar(l_tsd, uint16_t) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD : + dap_string_append_printf(a_str_out,"datum_type_allowed: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD : + dap_string_append_printf(a_str_out,"datum_type_blocked: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: + dap_string_append_printf(a_str_out,"tx_sender_allowed: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: + dap_string_append_printf(a_str_out,"tx_sender_blocked: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: + dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: + dap_string_append_printf(a_str_out, "tx_receiver_blocked: %s\n", + dap_chain_datum_token_tsd_get_string_const(l_tsd) ); + break; + default: dap_string_append_printf(a_str_out, "<0x%04X>: <size %zd>\n", l_tsd->type, l_tsd->size); + } + l_offset += dap_chain_datum_token_tsd_size(l_tsd); + + } + } + }break; + case DAP_CHAIN_DATUM_TOKEN_TYPE_PUBLIC:{ + dap_string_append_printf(a_str_out,"type: PUBLIC\n"); + }break; + default: + dap_string_append_printf(a_str_out,"type: UNKNOWN\n"); + } + + }break; + } +} diff --git a/modules/net/dap_chain_net_news.c b/modules/net/dap_chain_net_news.c new file mode 100644 index 0000000000000000000000000000000000000000..9a132c43ce37f003602e2053f3627ab27f289903 --- /dev/null +++ b/modules/net/dap_chain_net_news.c @@ -0,0 +1,126 @@ +/* + * Authors: + * Alexander Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2020 + * 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 <stddef.h> + +#include "dap_common.h" +#include "dap_string.h" +#include "dap_strfuncs.h" +#include "dap_file_utils.h" +#include "dap_config.h" + +#include "http_status_code.h" +#include "dap_http_simple.h" +#include "dap_enc_http.h" +//#include "<dap_chain_global_db_driver.h> +#include "dap_chain_global_db.h" +#include "dap_chain_net_news.h" +#define LOG_TAG "chain_net_news" + +#define NEWS_URL "/news" +#define GROUP_NEWS "cdb.news" +#define DEFAULT_LANG "en" + +/* Set news in the selected language + * a_lang - a language like "en", "ru", "fr" + * a_data_news - news data + * a_data_news_len length of news + */ +int dap_chain_net_news_write(char *a_lang, byte_t *a_data_news, size_t a_data_news_len) +{ + if(!a_data_news || !a_data_news_len) + return -2; + if(!a_lang) + a_lang = DEFAULT_LANG; + size_t l_data_len_out = 0; + if(dap_chain_global_db_gr_set(a_lang, a_data_news, a_data_news_len, GROUP_NEWS)) + return 0; + return -1; +} + +/* Get news in the selected language + * a_lang - a language like "en", "ru", "fr" + */ +byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len) +{ + if(!a_lang) + return NULL; + byte_t *l_ret_data = NULL; + size_t l_data_len_num = 0; + dap_store_obj_t *l_obj = dap_chain_global_db_obj_gr_get(a_lang, &l_data_len_num, GROUP_NEWS); + if(l_obj && l_obj->value_len) { + l_ret_data = DAP_NEW_Z_SIZE(byte_t, l_obj->value_len); + memcpy(l_ret_data, l_obj->value, l_obj->value_len); + if(a_news_len) + *a_news_len = l_obj->value_len; + } + dap_store_obj_free(l_obj, l_data_len_num); + return l_ret_data; +} + +/** + * @brief news_http_proc + * @param a_http_simple + * @param a_arg + */ +static void news_http_proc(struct dap_http_simple *a_http_simple, void * a_arg) +{ + log_it(L_DEBUG, "news_http_proc request"); + http_status_code_t * return_code = (http_status_code_t*) a_arg; + const char *l_lang = DEFAULT_LANG; + if(dap_strcmp(a_http_simple->http->url_path, NEWS_URL)) { + l_lang = a_http_simple->http->url_path; + } + + if(l_lang) + { + size_t l_news_data_len = 0; + // get news in the selected language + char *l_news_data = dap_chain_net_news_read(l_lang, &l_news_data_len); + // get news in the default language + if(!l_news_data && dap_strcmp(a_http_simple->http->in_query_string, "LocalNewsOnly")) + l_news_data = dap_chain_net_news_read(DEFAULT_LANG, &l_news_data_len); + a_http_simple->reply = l_news_data ? l_news_data : dap_strdup("no news"); + a_http_simple->reply_size = l_news_data_len; + *return_code = Http_Status_OK; + } + else { + log_it(L_ERROR, "Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en", NEWS_URL, NEWS_URL); + a_http_simple->reply = dap_strdup_printf("Wrong request. Must be %s/<lang_code>, example http:/<addr>%s/en", + NEWS_URL, NEWS_URL); + a_http_simple->reply_size = strlen(a_http_simple->reply); + *return_code = Http_Status_NotFound; + } +} + +/** + * @brief dap_chain_net_news_add_proc + * @param sh HTTP server instance + */ +void dap_chain_net_news_add_proc(struct dap_http * sh) +{ + const char * url = NEWS_URL; + dap_http_simple_proc_add(sh, url, 14096, news_http_proc); +} + diff --git a/modules/net/dap_chain_net_news.h b/modules/net/dap_chain_net_news.h new file mode 100644 index 0000000000000000000000000000000000000000..0982b05159e95c2af2484f1512deeb21a51c235f --- /dev/null +++ b/modules/net/dap_chain_net_news.h @@ -0,0 +1,39 @@ +/* + * Authors: + * Alexander Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2020 + * 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 "dap_http.h" + +/* Set news in the selected language + * a_lang - a language like "en", "ru", "fr" + * a_data_news - news data + * a_data_news_len length of news + */ +int dap_chain_net_news_write(char *a_lang, byte_t *a_data_news, size_t a_data_news_len); + +/* Get news in the selected language + * a_lang - a language like "en", "ru", "fr" + */ +byte_t* dap_chain_net_news_read(const char *a_lang, size_t *a_news_len); + +void dap_chain_net_news_add_proc(struct dap_http * sh); diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 3b742cf1404bdb19ba646cc8cbecbe078c580c00..abd8b8ccc318935218057caae1ff6a5b00e5a480 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -1011,6 +1011,12 @@ int dap_chain_node_cli_init(dap_config_t * g_config) dap_chain_node_cli_cmd_item_create ("exit", com_exit, NULL, "Stop application and exit", "exit\n" ); +#ifndef _WIN32 + // News + dap_chain_node_cli_cmd_item_create("news", com_news, NULL, "Add News for VPN clients. Language code is a text code like \"en\", \"ru\", \"fr\"", + "news [-text <news text> | -file <filename with news>] -lang <language code> \n"); + +#endif // create thread for waiting of clients pthread_t l_thread_id; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 14c7a183cb08342f4ea1a4d6456b065c3b351b82..2d2a9b7752b34ac494314c42eb112c2124ee3761 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -2014,13 +2014,8 @@ int com_mempool_list(int argc, char ** argv, void *arg_func, char ** a_str_reply dap_string_append_printf(l_str_tmp, "%s: type_id=%s data_size=%u ts_create=%s", // \n included in timestamp l_objs[i].key, c_datum_type_str[l_datum->header.type_id], l_datum->header.data_size, ctime_r(&l_ts_create, buf)); - if ( l_datum->header.type_id == DAP_CHAIN_DATUM_TOKEN_DECL ){ - dap_chain_datum_token_t * l_datum_token = (dap_chain_datum_token_t *) l_datum->data; - dap_string_append_printf(l_str_tmp, - "\tDAP_CHAIN_DATUM_TOKEN_DECL: type=%u ticker=\"%s\" signs_total=%u signs_valid=%u\n", - l_datum_token->type, l_datum_token->ticker, - l_datum_token->header_private.signs_total, l_datum_token->header_private.signs_valid ); - } + + dap_chain_net_dump_datum(l_str_tmp, l_datum); } // Clean up dap_chain_global_db_objs_delete(l_objs, l_objs_size); diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 2b19601490269bec6ebfa8ff457d7d4858909e49..b8d1c88a33f71d79ccfedc03a82205f0450ae625 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -335,10 +335,10 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha 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++) { - pthread_mutex_lock(&l_node_client->wait_mutex); 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); @@ -348,7 +348,7 @@ static void s_ch_chain_callback_notify_packet_in(dap_stream_ch_chain_t* a_ch_cha } //else // DAP_DELETE(l_lasts[i]); - pthread_mutex_unlock(&l_node_client->wait_mutex); + pthread_mutex_unlock(&a_ch_chain->mutex); } DAP_DELETE(l_lasts); } @@ -523,7 +523,8 @@ void dap_chain_node_client_close(dap_chain_node_client_t *a_client) CloseHandle( a_client->wait_cond ); #endif pthread_mutex_destroy(&a_client->wait_mutex); - DAP_DEL_Z(a_client); + a_client->client = NULL; + DAP_DELETE(a_client); } } diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 463a6e777c4d46d4e445f648d362c6077acc9fea..174cfb338759548a74010e1f9f13fd8841777d29 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -44,6 +44,7 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include <stdint.h> #include <string.h> #include "dap_strfuncs.h" +#include "dap_string.h" #include "dap_chain_common.h" #include "dap_chain_node.h" #include "dap_chain.h" @@ -60,8 +61,7 @@ typedef enum dap_chain_net_state{ NET_STATE_ADDR_REQUEST, // Waiting for address assign NET_STATE_SYNC_GDB, NET_STATE_SYNC_CHAINS, - NET_STATE_ONLINE, - NET_STATE_UNDEFINED + NET_STATE_ONLINE } dap_chain_net_state_t; typedef struct dap_chain_net{ @@ -153,3 +153,4 @@ dap_chain_net_t **dap_chain_net_list(size_t *a_size); dap_list_t * dap_chain_net_get_add_gdb_group(dap_chain_net_t * a_net, dap_chain_node_addr_t a_node_addr); int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t * a_datum ); +void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_datum); diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h index 505911d1d5af8a0fee5bc35d09a802266fa7457b..9ceb6f9efdd97101c97c67eff78bcf12ace1bcfe 100644 --- a/modules/net/include/dap_chain_node_cli_cmd.h +++ b/modules/net/include/dap_chain_node_cli_cmd.h @@ -133,6 +133,11 @@ int com_stats(int argc, char ** argv, void *arg_func, char **str_reply); int com_exit(int argc, char ** argv, void *arg_func, char **str_reply); +#ifndef _WIN32 +// Add News for VPN clients +int com_news(int a_argc, char ** a_argv, void *a_arg_func, char **a_str_reply); +#endif + // vpn_client command int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply); diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 873be6125e2d4227abed8fe5fef109549bfd8ed5..eb12e8dda3955cb23ca27f342088a9439df36799 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -291,7 +291,7 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t else PVT(l_dag)->events_treshold = l_events; //HASH_ADD(hh, PVT(l_dag)->events_treshold, hash, sizeof(l_event_item->hash), l_event_item); - + pthread_rwlock_unlock( l_events_rwlock ); if ( l_events == PVT(l_dag)->events){ dap_chain_cs_dag_event_item_t * l_event_last = NULL; // Check the events and update the lasts @@ -300,11 +300,13 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t l_event->hashes_n_datum_n_signs + l_event->header.hash_count*sizeof (*l_link_hash) ); l_link_hash += sizeof (dap_chain_hash_fast_t ) ) { l_event_last = NULL; + pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_link_hash,sizeof(*l_link_hash), l_event_last); if ( l_event_last ){ // If present in unlinked - remove HASH_DEL(PVT(l_dag)->events_lasts_unlinked,l_event_last); - DAP_DELETE(l_event_last); + DAP_DEL_Z(l_event_last); } + pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); } // and then adds itself @@ -312,8 +314,9 @@ static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t l_event_last->ts_added = l_event_item->ts_added; l_event_last->event = l_event; dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_last->hash ); - + pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock); HASH_ADD(hh,PVT(l_dag)->events_lasts_unlinked,hash,sizeof (l_event_last->hash),l_event_last); + pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); } // add datum from event to ledger @@ -391,8 +394,10 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain for (size_t d = 0; d <a_datums_count ; d++){ dap_chain_datum_t * l_datum = a_datums[d]; - if(l_datum == NULL) // Was wrong datum thats not passed checks + if(l_datum == NULL){ // Was wrong datum thats not passed checks + log_it(L_WARNING,"Datum in mempool processing comes NULL"); continue; + } // Verify for correctness dap_chain_net_t * l_net = dap_chain_net_by_id( a_chain->net_id); @@ -444,12 +449,13 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain // Now link with ext events dap_chain_cs_dag_event_item_t *l_event_ext_item = NULL; // is_single_line - only one link inside - if(!l_dag->is_single_line || !l_hashes_linked) - if( PVT(l_dag)->events_lasts_unlinked && l_hashes_linked < l_hashes_size) { // Take then the first one if any events_lasts are present - l_event_ext_item = PVT(l_dag)->events_lasts_unlinked; - memcpy(&l_hashes[l_hashes_linked], &l_event_ext_item->hash, sizeof(l_event_ext_item->hash)); - l_hashes_linked++; - } + if(!l_dag->is_single_line || !l_hashes_linked){ + if( PVT(l_dag)->events_lasts_unlinked && l_hashes_linked < l_hashes_size) { // Take then the first one if any events_lasts are present + l_event_ext_item = PVT(l_dag)->events_lasts_unlinked; + memcpy(&l_hashes[l_hashes_linked], &l_event_ext_item->hash, sizeof(l_event_ext_item->hash)); + l_hashes_linked++; + } + } if (l_hashes_linked || s_seed_mode ) { dap_chain_cs_dag_event_t * l_event = NULL; @@ -540,7 +546,7 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * a_dag, dap_chain_hash_fast_t * a_hash) { dap_chain_cs_dag_event_item_t* l_event_item = NULL; - pthread_rwlock_rdlock( &PVT(a_dag)->events_rwlock ); + pthread_rwlock_wrlock( &PVT(a_dag)->events_rwlock ); HASH_FIND(hh, PVT(a_dag)->events ,a_hash,sizeof(*a_hash), l_event_item); dap_chain_cs_dag_event_t * l_event = l_event_item->event; pthread_rwlock_unlock( &PVT(a_dag)->events_rwlock ); @@ -617,11 +623,13 @@ void s_dag_events_lasts_delete_linked_with_event(dap_chain_cs_dag_t * a_dag, dap for (size_t i = 0; i< a_event->header.hash_count; i++) { dap_chain_hash_fast_t * l_hash = ((dap_chain_hash_fast_t *) a_event->hashes_n_datum_n_signs) + i; dap_chain_cs_dag_event_item_t * l_event_item = NULL; + pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock); HASH_FIND(hh, PVT(a_dag)->events_lasts_unlinked ,l_hash ,sizeof (*l_hash), l_event_item); if ( l_event_item ){ HASH_DEL(PVT(a_dag)->events_lasts_unlinked,l_event_item); - DAP_DELETE(l_event_item); + DAP_DEL_Z(l_event_item); } + pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock); } } @@ -660,7 +668,7 @@ int dap_chain_cs_dag_event_verify_hashes_with_treshold(dap_chain_cs_dag_t * a_da void dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag) { // TODO Process finish treshold. For now - easiest from possible - pthread_rwlock_rdlock(&PVT(a_dag)->events_rwlock); + pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock); dap_chain_cs_dag_event_item_t * l_event_item = NULL, * l_event_item_tmp = NULL; HASH_ITER(hh,PVT(a_dag)->events_treshold,l_event_item, l_event_item_tmp){ dap_chain_cs_dag_event_t * l_event = l_event_item->event; @@ -782,10 +790,12 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_ato 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); HASH_ITER(hh,PVT(l_dag)->events_lasts_unlinked, l_event_item,l_event_item_tmp){ l_ret[i] = l_event_item->event; i++; } + pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock); return l_ret; } return NULL; @@ -1120,10 +1130,22 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) l_event_hash_str); ret = 0; }else { - dap_chain_node_cli_set_reply_text(a_str_reply, - "Can't remove event 0x%s from the new forming round ", - l_event_hash_str); - ret = -1; + dap_chain_cs_dag_event_item_t * l_event_item = NULL; + HASH_FIND(hh,PVT(l_dag)->events,&l_event_hash,sizeof(l_event_hash),l_event_item); + + if ( l_event_item ){ + HASH_DELETE(hh, PVT(l_dag)->events, l_event_item); + log_it(L_WARNING,"Dropped event 0x%s from chains! Hope you know what are you doing!", l_event_hash_str ); + dap_chain_node_cli_set_reply_text(a_str_reply, + "Dropped event 0x%s from chains! Hope you know what are you doing! ", + l_event_hash_str ); + dap_chain_save_all(l_chain); + }else { + dap_chain_node_cli_set_reply_text(a_str_reply, + "Can't remove event 0x%s ", + l_event_hash_str); + ret = -1; + } } DAP_DELETE( l_gdb_group_events ); dap_chain_net_sync_gdb(l_net); @@ -1140,7 +1162,9 @@ 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); 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 ) l_event = l_event_item->event; else { @@ -1151,7 +1175,9 @@ 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); 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 ) l_event = l_event_item->event; else { @@ -1201,7 +1227,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) // Nested datum dap_string_append_printf(l_str_tmp,"\t\t\t\tdatum:\tdatum_size: %u\n",l_datum_size); - dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tversion:=%0x02X\n", l_datum->header.version_id); + dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tversion:=0x%02X\n", l_datum->header.version_id); dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype_id:=%s\n", c_datum_type_str[l_datum->header.type_id]); dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tts_create=%s\n",ctime_r( &l_datum_ts_create,buf )); dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tdata_size=%u\n", l_datum->header.data_size); @@ -1227,6 +1253,7 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply) DAP_DELETE( l_addr_str); dap_enc_key_delete(l_sign_key); } + dap_chain_net_dump_datum(l_str_tmp, l_datum); dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str); dap_string_free(l_str_tmp,false);