diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c86cc5c60f69e1260a24211e5b71dc75cafe8ec..1e04fb59a169d62f8d758bd2be989f18d1a2c06c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ if(WIN32) add_definitions ("-D_POSIX_") add_definitions ("-D_POSIX_THREAD_SAFE_FUNCTIONS") add_definitions ("-DNODE_NETNAME=\"cellframe\"") + add_compile_definitions(_GNU_SOURCE) include_directories(../libdap/src/win32/) include_directories(../3rdparty/wepoll/include/) include_directories(../3rdparty/uthash/src/) diff --git a/dap_chain_net.c b/dap_chain_net.c index ad42a7190b4e3b4ae4523ca8a80b36b2d05f370a..bcfb68cf33afcab1df8d055eef4f6b795430c2fc 100755 --- a/dap_chain_net.c +++ b/dap_chain_net.c @@ -720,6 +720,11 @@ static void s_net_proc_kill( dap_chain_net_t * a_net ) return; } +dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net) +{ + return PVT(a_net)->node_role; +} + /** * @brief dap_chain_net_new * @param a_id @@ -824,6 +829,8 @@ int dap_chain_net_init() dap_chain_global_db_add_history_group_prefix("global"); dap_chain_global_db_add_history_callback_notify("global", s_gbd_history_callback_notify, NULL ); + + dap_chain_net_load_all(); return 0; } @@ -1606,8 +1613,44 @@ dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net) return PVT(l_net)->node_info? &PVT(l_net)->node_info->hdr.cell_id: 0; } + /** - * Get remote node list + * Get nodes list (list of dap_chain_node_addr_t struct) + */ +dap_list_t* dap_chain_net_get_link_node_list(dap_chain_net_t * l_net, bool a_is_only_cur_cell) +{ + dap_list_t *l_node_list = NULL; + // get cur node address + dap_chain_node_addr_t l_cur_node_addr = { 0 }; + l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + + dap_chain_node_info_t *l_cur_node_info = dap_chain_node_info_read(l_net, &l_cur_node_addr); + // add links to nodes list only from the same cell + if(l_cur_node_info) { + for(unsigned int i = 0; i < l_cur_node_info->hdr.links_number; i++) { + bool l_is_add = true; + dap_chain_node_addr_t *l_remote_address = l_cur_node_info->links + i; + if(a_is_only_cur_cell) { + // get remote node list + dap_chain_node_info_t *l_remote_node_info = dap_chain_node_info_read(l_net, l_remote_address); + if(!l_remote_node_info || l_remote_node_info->hdr.cell_id.uint64 != l_cur_node_info->hdr.cell_id.uint64) + l_is_add = false; + DAP_DELETE(l_remote_node_info); + } + if(l_is_add) { + dap_chain_node_addr_t *l_address = DAP_NEW(dap_chain_node_addr_t); + l_address->uint64 = l_cur_node_info->links[i].uint64; + l_node_list = dap_list_append(l_node_list, l_address); + } + } + + } + DAP_DELETE(l_cur_node_info); + return l_node_list; +} + +/** + * Get remote nodes list (list of dap_chain_node_addr_t struct) */ dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net) { @@ -1679,9 +1722,55 @@ dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net) * @brief dap_chain_net_proc_datapool * @param a_net */ -void dap_chain_net_proc_datapool (dap_chain_net_t * a_net) +void dap_chain_net_proc_mempool (dap_chain_net_t * a_net) { + dap_string_t * l_str_tmp = dap_string_new(NULL); + for(dap_chain_type_t i = CHAIN_TYPE_FIRST + 1; i < CHAIN_TYPE_LAST; i++) { + dap_chain_t * l_chain = dap_chain_net_get_chain_by_chain_type(a_net, i); + char * 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) { + log_it(L_INFO, "%s.%s: Found %u records :", a_net->pub.name, l_chain->name, + l_objs_size); + size_t l_datums_size = l_objs_size; + dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*, + sizeof(dap_chain_datum_t*) * l_datums_size); + size_t l_objs_size_tmp = (l_objs_size > 15) ? min(l_objs_size, 10) : 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; + l_datums[i] = l_datum; + if(i < l_objs_size_tmp) { + char buf[50]; + time_t l_ts_create = (time_t) l_datum->header.ts_create; + log_it(L_INFO, "\t\t0x%s: type_id=%s ts_create=%s data_size=%u", + l_objs[i].key, c_datum_type_str[l_datum->header.type_id], + ctime_r(&l_ts_create, buf), l_datum->header.data_size); + } + } + size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums, l_datums_size); + // Delete processed objects + size_t l_objs_processed_tmp = (l_objs_processed > 15) ? min(l_objs_processed, 10) : l_objs_processed; + for(size_t i = 0; i < l_objs_processed; i++) { + dap_chain_global_db_gr_del(l_objs[i].key, l_gdb_group_mempool); + if(i < l_objs_processed_tmp) { + dap_string_append_printf(l_str_tmp, "New event created, removed datum 0x%s from mempool \n", + l_objs[i].key); + } + } + if(l_objs_processed < l_datums_size) + log_it(L_WARNING, "%s.%s: %d records not processed", a_net->pub.name, l_chain->name, + l_datums_size - l_objs_processed); + dap_chain_global_db_objs_delete(l_objs, l_objs_size); + } + else { + log_it(L_INFO, "%s.%s: No records in mempool", a_net->pub.name, l_chain ? l_chain->name : "[no chain]"); + } + DAP_DELETE(l_gdb_group_mempool); + + } } /** diff --git a/dap_chain_net.h b/dap_chain_net.h index 1a7171f19d41c71bace4a85634f932bd06fd0f91..5cc4f2c16f2df38bad4f89efbfc342b4496693bb 100644 --- a/dap_chain_net.h +++ b/dap_chain_net.h @@ -36,6 +36,7 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include "win32/ip.h" #include "win32/iphdr.h" +#define s6_addr32 s6_addr #define herror perror #endif @@ -93,7 +94,7 @@ inline static int dap_chain_net_sync_gdb(dap_chain_net_t * a_net) { return dap_c inline static int dap_chain_net_sync_all(dap_chain_net_t * a_net) { return dap_chain_net_state_go_to(a_net,NET_STATE_SYNC_GDB); }//NET_STATE_ONLINE void dap_chain_net_delete( dap_chain_net_t * a_net); -void dap_chain_net_proc_datapool (dap_chain_net_t * a_net); +void dap_chain_net_proc_mempool (dap_chain_net_t * a_net); dap_chain_net_t * dap_chain_net_by_name( const char * a_name); dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id); @@ -106,6 +107,7 @@ dap_chain_node_addr_t * dap_chain_net_get_cur_addr( dap_chain_net_t * l_net); uint64_t dap_chain_net_get_cur_addr_int(dap_chain_net_t * l_net); dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t * l_net); +dap_list_t* dap_chain_net_get_link_node_list(dap_chain_net_t * l_net, bool a_is_only_cur_cell); dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net); void dap_chain_net_links_connect(dap_chain_net_t * a_net); @@ -126,6 +128,8 @@ typedef enum dap_chain_net_tx_search_type { dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap_chain_hash_fast_t * a_tx_hash, dap_chain_net_tx_search_type_t a_search_type); +dap_chain_node_role_t dap_chain_net_get_role(dap_chain_net_t * a_net); + /** * @brief dap_chain_net_get_gdb_group_mempool * @param l_chain diff --git a/dap_chain_node.h b/dap_chain_node.h index 1c7bff5ce37baf32e88b577b280888d8f2719994..95ca8c1bdd2cc5773f3d9d77aec27e68034d1081 100644 --- a/dap_chain_node.h +++ b/dap_chain_node.h @@ -36,8 +36,6 @@ #include "win32/ip.h" #include "win32/iphdr.h" -#define __in6_u _S6_un -#define __u6_addr32 _S6_u8 #endif diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c index 2e859dea541072365f7d00a36f768ea87c87272a..41d5018ee9683b350ef9d46803a8dd5f3f2b5a0e 100644 --- a/dap_chain_node_cli_cmd.c +++ b/dap_chain_node_cli_cmd.c @@ -43,13 +43,13 @@ #include <ws2tcpip.h> #include <io.h> #include <wepoll.h> -#include <signal.h> -#include <pthread.h> #else #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> +#include <signal.h> #endif +#include <pthread.h> #include "iputils/iputils.h" @@ -72,9 +72,11 @@ #include "dap_chain_node_cli_cmd_tx.h" #include "dap_chain_node_ping.h" #include "dap_chain_net_srv.h" +#include "dap_chain_net_srv_vpn.h" #include "dap_chain_net_vpn_client.h" #include "dap_chain_cell.h" +#include "dap_chain_common.h" #include "dap_chain_datum.h" #include "dap_chain_datum_token.h" #include "dap_chain_datum_tx_items.h" @@ -913,109 +915,98 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) return -1; } } + // for auto mode + int l_is_auto = 0; + // list of dap_chain_node_addr_t struct + unsigned int l_nodes_count = 0; + dap_list_t *l_node_list = NULL; + dap_chain_node_addr_t *l_remote_node_addr = NULL; if(!l_node_addr.uint64) { // check whether auto mode - int l_is_auto = dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "auto", NULL); + l_is_auto = dap_chain_node_cli_find_option_val(a_argv, arg_index, a_argc, "auto", NULL); if(!l_is_auto) { dap_chain_node_cli_set_reply_text(a_str_reply, "addr not found"); return -1; } // if auto mode, then looking for the node address - // list of dap_chain_node_addr_t struct - dap_list_t *l_node_list = dap_chain_net_get_node_list(l_net); - // add cur node links to list - dap_chain_node_info_t *l_cur_node_info = NULL; - { - // get cur node address - dap_chain_node_addr_t l_cur_node_addr = { 0 }; - l_cur_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - // get cur node info - l_cur_node_info = node_info_read_and_reply(l_net, &l_cur_node_addr, NULL); - // add links to nodes list only from the same cell - if(l_cur_node_info) { - for(unsigned int i = 0; i < l_cur_node_info->hdr.links_number; i++) { - //if(l_node_info && l_node_info->hdr.cell_id == l_cur_node_info->hdr.cell_id){ - l_node_list = dap_list_append(l_node_list, l_cur_node_info->links + i); - //} - } - - } - } - - // select the nearest node from the list - unsigned int l_nodes_count = dap_list_length(l_node_list); - unsigned int l_thread_id = 0; - pthread_t *l_threads = DAP_NEW_Z_SIZE(pthread_t, sizeof(pthread_t) * l_nodes_count); - uint64_t *l_nodes_addr = DAP_NEW_Z_SIZE(uint64_t, sizeof(uint64_t) * l_nodes_count); - dap_list_t *l_node_list0 = l_node_list; - // send ping to all nodes - while(l_node_list) { - dap_chain_node_addr_t *l_node_addr = l_node_list->data; - dap_chain_node_info_t *l_node_info = node_info_read_and_reply(l_net, l_node_addr, NULL); - - // start sending ping - start_node_ping(&l_threads[l_thread_id], l_node_info->hdr.ext_addr_v4, l_node_info->hdr.ext_port, 1); - - l_nodes_addr[l_thread_id] = l_node_info->hdr.address.uint64; - l_thread_id++; - DAP_DELETE(l_node_info); - l_node_list = dap_list_next(l_node_list); - } - // wait for reply from nodes - int best_node_pos = -1; - int best_node_reply = INT32_MAX; - // timeout for all threads - int l_timeout_full_ms = 3000;// wait max 3 second - for(l_thread_id = 0; l_thread_id < l_nodes_count; l_thread_id++) { - if(l_timeout_full_ms<100) - l_timeout_full_ms = 100;// make small timeout anyway, may be - struct timespec l_time_start; - clock_gettime(CLOCK_MONOTONIC, &l_time_start); - int res = wait_node_ping(l_threads[l_thread_id], l_timeout_full_ms); - if(res > 0 && res < best_node_reply) { - best_node_pos = l_thread_id; - best_node_reply = res; - } - struct timespec l_time_stop; - clock_gettime(CLOCK_MONOTONIC, &l_time_stop); - l_timeout_full_ms -= timespec_diff(&l_time_start, &l_time_stop, NULL); - //printf(" thread %x ping=%d\n", l_threads[l_thread_id], res); - } - if(best_node_pos > 0) { - l_node_addr.uint64 = l_nodes_addr[best_node_pos]; + // get cur node links + bool a_is_only_cur_cell = false; + dap_list_t *l_node_link_list = dap_chain_net_get_link_node_list(l_net, a_is_only_cur_cell); + // get all nodes list if no links + if(!l_node_link_list) + l_node_list = dap_chain_net_get_node_list(l_net); + else + l_node_list = dap_list_concat(l_node_link_list, l_node_list); + + // select random node from the list + l_nodes_count = dap_list_length(l_node_list); + if(l_nodes_count > 0) { + unsigned int l_node_pos = rand() % l_nodes_count; + dap_list_t *l_tmp = dap_list_nth(l_node_list, l_node_pos); + l_remote_node_addr = l_tmp->data; + l_node_addr.uint64 = l_remote_node_addr->uint64; } - DAP_DELETE(l_nodes_addr); - DAP_DELETE(l_threads); - dap_list_free_full(l_node_list0, free); - DAP_DELETE(l_cur_node_info); - if(!l_node_addr.uint64) { dap_chain_node_cli_set_reply_text(a_str_reply, "no node is available"); return -1; } } - - dap_chain_node_info_t *l_remote_node_info = node_info_read_and_reply(l_net, &l_node_addr, a_str_reply); - if(!l_remote_node_info) { - return -1; + dap_chain_node_info_t *l_remote_node_info; + dap_chain_node_client_t *l_node_client; + int res; + do { + l_remote_node_info = node_info_read_and_reply(l_net, &l_node_addr, a_str_reply); + if(!l_remote_node_info) { + return -1; + } + // start connect + l_node_client = dap_chain_node_client_connect(l_remote_node_info); + if(!l_node_client) { + dap_chain_node_cli_set_reply_text(a_str_reply, "can't connect"); + DAP_DELETE(l_remote_node_info); + return -1; + } + // wait connected + int timeout_ms = 5000; //5 sec = 5000 ms + res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms); + // select new node addr + if(l_is_auto && res){ + if(l_remote_node_addr && l_nodes_count>1){ + l_nodes_count--; + l_node_list = dap_list_remove(l_node_list, l_remote_node_addr); + DAP_DELETE(l_remote_node_addr); + unsigned int l_node_pos = rand() % l_nodes_count; + dap_list_t *l_tmp = dap_list_nth(l_node_list, l_node_pos); + l_remote_node_addr = l_tmp->data; + l_node_addr.uint64 = l_remote_node_addr->uint64; + + // clean client struct + dap_chain_node_client_close(l_node_client); + DAP_DELETE(l_remote_node_info); + //return -1; + continue; + } + } + break; } - // start connect - dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect(l_remote_node_info); - if(!l_node_client) { - dap_chain_node_cli_set_reply_text(a_str_reply, "can't connect"); - DAP_DELETE(l_remote_node_info); - return -1; + while(1); + // for auto mode only + if(l_is_auto) { + //start background thread for testing connect to the nodes + dap_chain_node_ping_background_start(l_net, l_node_list); + dap_list_free_full(l_node_list, free); } - // wait connected - int timeout_ms = 5000; //5 sec = 5000 ms - int res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms); + + + if(res) { - dap_chain_node_cli_set_reply_text(a_str_reply, "no response from node: code %d", res); + dap_chain_node_cli_set_reply_text(a_str_reply, "no response from remote node(s)"); + log_it(L_WARNING, "No response from remote node(s): err code %d", res); // clean client struct - dap_chain_node_client_close(l_node_client); - DAP_DELETE(l_remote_node_info); + //dap_chain_node_client_close(l_node_client); + //DAP_DELETE(l_remote_node_info); return -1; } @@ -1118,7 +1109,7 @@ int com_node(int a_argc, char ** a_argv, char **a_str_reply) } dap_stream_ch_set_ready_to_write(l_ch_chain, true); // wait for finishing of request - timeout_ms = 1200000; // 20 min = 1200 sec = 1 200 000 ms + int timeout_ms = 1200000; // 20 min = 1200 sec = 1 200 000 ms // TODO add progress info to console res = dap_chain_node_client_wait(l_node_client, NODE_CLIENT_STATE_SYNCED, timeout_ms); if(res < 0) { @@ -2085,12 +2076,23 @@ int com_mempool_proc(int argc, char ** argv, char ** a_str_reply) if(l_objs_size > 15) { dap_string_append_printf(l_str_tmp, "...\n"); } - size_t l_objs_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums, l_datums_size); + + size_t l_objs_processed = 0; + bool l_procecced[l_objs_size]; + for(size_t i = 0; i < l_objs_size; i++) { + int l_is_processed = l_chain->callback_datums_pool_proc(l_chain, l_datums + i, 1); //l_datums_size + l_objs_processed += l_is_processed; + l_procecced[i] = l_is_processed; + } // Delete processed objects size_t l_objs_processed_tmp = (l_objs_processed > 15) ? min(l_objs_processed, 10) : l_objs_processed; - for(size_t i = 0; i < l_objs_processed; i++) { - dap_chain_global_db_gr_del(l_objs[i].key, l_gdb_group_mempool); - if(i < l_objs_processed_tmp) { + size_t l_objs_processed_cur = 0; + for(size_t i = 0; i < l_datums_size; i++) { + if(l_procecced[i]!=1) + continue; + dap_chain_global_db_gr_del(l_objs[i].key, l_gdb_group_mempool_tmp); + l_objs_processed_cur++; + if(l_objs_processed_cur < l_objs_processed_tmp) { dap_string_append_printf(l_str_tmp, "New event created, removed datum 0x%s from mempool \n", l_objs[i].key); } @@ -2562,24 +2564,122 @@ int com_token_emit(int argc, char ** argv, char ** str_reply) int com_tx_cond_create(int argc, char ** argv, char **str_reply) { (void) argc; - // test - /* - const char * l_token_ticker = NULL; + int arg_index = 1; const char *c_wallets_path = dap_chain_wallet_get_path(g_config); - const char *c_wallet_name_from = "w_tesla"; // where to take coins for service - const char *c_wallet_name_cond = "w_picnic"; // who will be use service, usually the same address (addr_from) - uint64_t l_value = 50; + const char * l_token_ticker = NULL; + const char * l_wallet_from_str = NULL; + const char * l_wallet_to_str = NULL; //l_addr_to_str + const char * l_value_datoshi_str = NULL; + const char * l_net_name = NULL; + const char * l_unit_str = NULL; + const char * l_service_str = NULL; + uint64_t l_value_datoshi = 0; + + // Token ticker + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-token", &l_token_ticker); + // Wallet name - from + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-wallet_f", &l_wallet_from_str); + // Wallet address - to + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-wallet_t", &l_wallet_to_str); + // value datoshi + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-value", &l_value_datoshi_str); + // net + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_name); + // unit + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-unit", &l_unit_str); + // service + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-service", &l_service_str); + + if(!l_token_ticker) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-token'"); + return -1; + } + if(!l_wallet_from_str) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-wallet_f'"); + return -2; + } + if(!l_wallet_to_str) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-wallet_t'"); + return -3; + } + if(!l_value_datoshi_str) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-value'"); + return -4; + } - dap_chain_wallet_t *l_wallet_from = dap_chain_wallet_open(c_wallet_name_from, c_wallets_path); - dap_enc_key_t *l_key = dap_chain_wallet_get_key(l_wallet_from, 0); - dap_chain_wallet_t *l_wallet_cond = dap_chain_wallet_open(c_wallet_name_cond, c_wallets_path); + if(!l_net_name) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-net'"); + return -5; + } + if(!l_unit_str) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-unit={mb|kb|b|sec|day}'"); + return -6; + } + if(!l_service_str) { + dap_chain_node_cli_set_reply_text(str_reply, "tx_cond_create requires parameter '-service={vpn}'"); + return -7; + } + dap_chain_net_srv_uid_t l_srv_uid = { 0 }; + if(!dap_strcmp(l_service_str, "vpn")) + l_srv_uid.uint64 = DAP_CHAIN_NET_SRV_VPN_ID; + //dap_chain_addr_t *addr_to = dap_chain_addr_from_str(l_addr_to_str); + if(!l_srv_uid.uint64) { + dap_chain_node_cli_set_reply_text(str_reply, "can't recognize service='%s' unit must look like {vpn}", + l_service_str); + return -8; + } + + dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = SERV_UNIT_UNDEFINED }; + if(!dap_strcmp(l_unit_str, "mb")) + l_price_unit.enm = SERV_UNIT_MB; + else if(!dap_strcmp(l_unit_str, "sec")) + l_price_unit.enm = SERV_UNIT_SEC; + else if(!dap_strcmp(l_unit_str, "day")) + l_price_unit.enm = SERV_UNIT_DAY; + else if(!dap_strcmp(l_unit_str, "kb")) + l_price_unit.enm = SERV_UNIT_KB; + else if(!dap_strcmp(l_unit_str, "b")) + l_price_unit.enm = SERV_UNIT_B; + + if(l_price_unit.enm == SERV_UNIT_UNDEFINED) { + dap_chain_node_cli_set_reply_text(str_reply, "can't recognize unit='%s' unit must look like {mb|kb|b|sec|day}", + l_unit_str); + return -9; + } + + l_value_datoshi = strtoll(l_value_datoshi_str, NULL, 10); + if(!l_value_datoshi) { + dap_chain_node_cli_set_reply_text(str_reply, "can't recognize value='%s' as a number", l_value_datoshi_str); + return -10; + } + + dap_chain_net_t * l_net = l_net_name ? dap_chain_net_by_name(l_net_name) : NULL; + if(!l_net) { + dap_chain_node_cli_set_reply_text(str_reply, "can't find net '%s'", l_net_name); + return -11; + } + dap_chain_wallet_t *l_wallet_from = dap_chain_wallet_open(l_wallet_from_str, c_wallets_path); + if(!l_wallet_from) { + dap_chain_node_cli_set_reply_text(str_reply, "can't open wallet '%s'", l_wallet_from); + return -12; + } + dap_chain_wallet_t *l_wallet_cond = dap_chain_wallet_open(l_wallet_to_str, c_wallets_path); + if(!l_wallet_to_str) { + dap_chain_wallet_close(l_wallet_from); + dap_chain_node_cli_set_reply_text(str_reply, "can't open wallet '%s'", l_wallet_to_str); + return -13; + } + dap_enc_key_t *l_key_from = dap_chain_wallet_get_key(l_wallet_from, 0); dap_enc_key_t *l_key_cond = dap_chain_wallet_get_key(l_wallet_cond, 0); + + // where to take coins for service - const dap_chain_addr_t *addr_from = dap_chain_wallet_get_addr(l_wallet_from); + const dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(l_wallet_from, l_net->pub.id); // who will be use service, usually the same address (addr_from) - const dap_chain_addr_t *addr_cond = dap_chain_wallet_get_addr(l_wallet_cond); + //const dap_chain_addr_t *l_addr_cond = dap_chain_wallet_get_addr(l_wallet_cond, l_net->pub.id); + - dap_chain_net_srv_abstract_t l_cond; +/* //dap_chain_net_srv_abstract_t l_cond; // dap_chain_net_srv_abstract_set(&l_cond, SERV_CLASS_PERMANENT, SERV_ID_VPN, l_value, SERV_UNIT_MB, // "test vpn service"); // dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name((const char *) c_net_name); @@ -2587,14 +2687,33 @@ int com_tx_cond_create(int argc, char ** argv, char **str_reply) int res = dap_chain_mempool_tx_create_cond(NULL, l_key, l_key_cond, addr_from, addr_cond, NULL, l_token_ticker, l_value, 0, (const void*) &l_cond, sizeof(dap_chain_net_srv_abstract_t)); +*/ + + dap_chain_hash_fast_t *l_tx_cond_hash = dap_chain_mempool_tx_create_cond(l_net, l_key_from, l_key_cond, l_addr_from, l_token_ticker, + l_value_datoshi, 0, l_price_unit, l_srv_uid, 0, NULL, 0); dap_chain_wallet_close(l_wallet_from); dap_chain_wallet_close(l_wallet_cond); - dap_chain_node_cli_set_reply_text(str_reply, "cond create=%s\n", + + char *l_hash_str = l_tx_cond_hash ? dap_chain_hash_fast_to_str_new(l_tx_cond_hash) : NULL; + + /*dap_chain_node_cli_set_reply_text(str_reply, "cond create=%s\n", (res == 0) ? "Ok" : (res == -2) ? "False, not enough funds for service fee" : "False"); - return res; - */ - return -1; + return res;*/ + + int l_ret; + // example: cond create succefully hash=0x4AA303EB7C10430C0AAC42F399D265BC7DD09E3983E088E02B8CED38DA22EDA9 + if(l_hash_str){ + dap_chain_node_cli_set_reply_text(str_reply, "cond create succefully hash=%s\n", l_hash_str); + l_ret = 0; + } + else{ + dap_chain_node_cli_set_reply_text(str_reply, "cond can't create\n"); + l_ret = -1; + } + + DAP_DELETE(l_hash_str); + return l_ret; } /** diff --git a/dap_chain_node_client.c b/dap_chain_node_client.c index bce0989d71e738eb7d3953a1b5d1953ee0a3a0e3..3ddaddcba9b8139172f25d9647fc13f1392d76fd 100644 --- a/dap_chain_node_client.c +++ b/dap_chain_node_client.c @@ -127,6 +127,8 @@ static void s_stage_status_callback(dap_client_t *a_client, void *a_arg) static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg) { dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client); + if(!l_node_client) + return; // check for last attempt bool l_is_last_attempt = a_arg ? true : false; if(l_is_last_attempt){ @@ -471,6 +473,8 @@ dap_chain_node_client_t* dap_chain_client_connect(dap_chain_node_info_t *a_node_ // dap_client_stage_t l_stage_target = STAGE_STREAM_STREAMING; l_node_client->state = NODE_CLIENT_STATE_CONNECT; + // ref pvt client + //dap_client_pvt_ref(DAP_CLIENT_PVT(l_node_client->client)); // Handshake & connect dap_client_go_stage(l_node_client->client, a_stage_target, s_stage_connected_callback); return l_node_client; diff --git a/dap_chain_node_client.h b/dap_chain_node_client.h index 21678c23bf4ffb5d4b7a08f1dd004e5adda35dfc..4a5eb2e307768a133a46050a280d871b4bff22e2 100644 --- a/dap_chain_node_client.h +++ b/dap_chain_node_client.h @@ -75,7 +75,7 @@ typedef struct dap_chain_node_client { bool keep_connection; } dap_chain_node_client_t; -#define DAP_CHAIN_NODE_CLIENT(a) ( (dap_chain_node_client_t *) (a)->_inheritor ) +#define DAP_CHAIN_NODE_CLIENT(a) (a ? (dap_chain_node_client_t *) (a)->_inheritor : NULL) int dap_chain_node_client_init(void); diff --git a/dap_chain_node_ping.c b/dap_chain_node_ping.c index bf3527d9ca07225715724c02c64cacabc6038d7a..39a3ad083d986dcf6c357d059c854e652f6dabeb 100644 --- a/dap_chain_node_ping.c +++ b/dap_chain_node_ping.c @@ -24,10 +24,14 @@ //#include <sys/socket.h> #include <time.h> #include <errno.h> +#include <pthread.h> #include "dap_common.h" #include "dap_client.h" #include "dap_strfuncs.h" +#include "dap_list.h" +#include "dap_chain_common.h" +#include "dap_chain_node.h" #include "dap_chain_node_ping.h" /* @@ -54,9 +58,10 @@ #else #include <signal.h> #endif - #include <pthread.h> +#include "iputils/iputils.h" + #include "dap_common.h" //#include "dap_client.h" #include "dap_strfuncs.h" @@ -71,7 +76,7 @@ static void* node_ping_proc(void *a_arg) int l_port = 0; int l_count; if(!a_arg) - return NULL; + return NULL ; memcpy(&l_count, a_arg, sizeof(int)); memcpy(&l_port, (a_arg + sizeof(int)), sizeof(int)); memcpy(&l_addr, (a_arg + 2 * sizeof(int)), sizeof(struct in_addr)); @@ -81,7 +86,7 @@ static void* node_ping_proc(void *a_arg) struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = l_addr }; const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, INET_ADDRSTRLEN); if(!str_ip4) - return NULL; + return NULL ; //printf(" %s %d ping start\n", str_ip4, l_count); /* // send ping @@ -115,7 +120,7 @@ static void* node_ping_proc(void *a_arg) uint8_t l_buf[l_buf_size]; const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, - INET_ADDRSTRLEN); + INET_ADDRSTRLEN); char *l_str_to_send = dap_strdup_printf("GET /%s/ping_sub_url HTTP/1.1\r\nHost: %s\r\n\r\n", DAP_UPLINK_PATH_ENC_INIT, str_ip4); // send data to bad suburl @@ -131,8 +136,8 @@ static void* node_ping_proc(void *a_arg) } DAP_DELETE(l_str_to_send); } - else{ - ;//log_it(L_INFO, "Can't connect to node for ping"); + else { + ; //log_it(L_INFO, "Can't connect to node for ping"); } closesocket(l_socket); } @@ -160,11 +165,10 @@ int wait_node_ping(pthread_t l_thread, int timeout_ms) timeout_ms *= 1000; l_wait_time.tv_sec += timeout_ms / DAP_USEC_PER_SEC; l_wait_time.tv_nsec += 1000 * (timeout_ms % DAP_USEC_PER_SEC); - -#ifdef __ANDROID__ - int res = pthread_join(l_thread, (void **) &l_ping_time); -#else +#if !defined(_WIN32) && !defined(__ANDROID__) int res = pthread_timedjoin_np(l_thread, (void **) &l_ping_time, &l_wait_time); +#else + int res = pthread_join(l_thread, (void **) &l_ping_time); #endif if(res == ETIMEDOUT) { pthread_kill(l_thread, 3); // SIGQUIT SIGABRT @@ -173,3 +177,142 @@ int wait_node_ping(pthread_t l_thread, int timeout_ms) return l_ping_time; return -1; } + +static dap_chain_node_addr_t *s_node_addr_tr = NULL, *s_node_addr_ping = NULL; + +static void* node_ping_background_proc(void *a_arg) +{ + dap_chain_net_t *l_net; + dap_list_t *l_node_list; + memcpy(&l_net, a_arg, sizeof(dap_chain_net_t*)); + memcpy(&l_node_list, a_arg + sizeof(dap_chain_net_t*), sizeof(dap_list_t*)); + DAP_DELETE(a_arg); + dap_chain_node_addr_t l_node_addr = { 0 }; + + + // select the nearest node from the list + unsigned int l_nodes_count = dap_list_length(l_node_list); + unsigned int l_thread_id = 0; + pthread_t *l_threads = DAP_NEW_Z_SIZE(pthread_t, sizeof(pthread_t) * l_nodes_count); + uint64_t *l_nodes_addr = DAP_NEW_Z_SIZE(uint64_t, sizeof(uint64_t) * l_nodes_count); + dap_list_t *l_node_list0 = l_node_list; + + dap_chain_node_addr_t *s_node_addr_tr = NULL, *l_node_addr_ping = NULL; + int l_min_hops = INT32_MAX; + int l_min_ping = INT32_MAX; + // send ping to all nodes + while(l_node_list) { + dap_chain_node_addr_t *l_node_addr = l_node_list->data; + dap_chain_node_info_t *l_node_info = dap_chain_node_info_read(l_net, l_node_addr); + + + char *host4 = DAP_NEW_SIZE(char, INET_ADDRSTRLEN); + struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = l_node_info->hdr.ext_addr_v4 }; + const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, INET_ADDRSTRLEN); + if(!str_ip4) + continue; + int hops = 0, time_usec = 0; + int res = traceroute_util(str_ip4, &hops, &time_usec); + DAP_DELETE(host4); + if(l_min_hops>hops) + s_node_addr_tr = l_node_list->data; + + // start sending ping + start_node_ping(&l_threads[l_thread_id], l_node_info->hdr.ext_addr_v4, l_node_info->hdr.ext_port, 1); + + l_nodes_addr[l_thread_id] = l_node_info->hdr.address.uint64; + l_thread_id++; + DAP_DELETE(l_node_info); + l_node_list = dap_list_next(l_node_list); + } + // wait for reply from nodes + int best_node_pos = -1; + int best_node_reply = INT32_MAX; + // timeout for all threads + int l_timeout_full_ms = 3000; // wait max 3 second + for(l_thread_id = 0; l_thread_id < l_nodes_count; l_thread_id++) { + if(l_timeout_full_ms < 100) + l_timeout_full_ms = 100; // make small timeout anyway, may be + struct timespec l_time_start; + clock_gettime(CLOCK_MONOTONIC, &l_time_start); + int res = wait_node_ping(l_threads[l_thread_id], l_timeout_full_ms); + if(res > 0 && res < best_node_reply) { + best_node_pos = l_thread_id; + s_node_addr_ping = l_node_list->data; + best_node_reply = res; + } + struct timespec l_time_stop; + clock_gettime(CLOCK_MONOTONIC, &l_time_stop); + l_timeout_full_ms -= timespec_diff(&l_time_start, &l_time_stop, NULL); + //printf(" thread %x ping=%d\n", l_threads[l_thread_id], res); + } + if(best_node_pos > 0) { + l_node_addr.uint64 = l_nodes_addr[best_node_pos]; + } + + // allocate memory for best node addresses + dap_chain_node_addr_t *s_node_addr_tmp; + s_node_addr_tmp = DAP_NEW(dap_chain_node_addr_t); + memcmp(s_node_addr_tmp, s_node_addr_tr, sizeof(dap_chain_node_addr_t)); + s_node_addr_tr = s_node_addr_tmp; + s_node_addr_tmp = DAP_NEW(dap_chain_node_addr_t); + memcmp(s_node_addr_tmp, s_node_addr_ping, sizeof(dap_chain_node_addr_t)); + s_node_addr_ping = s_node_addr_tmp; + + // delete memory + DAP_DELETE(l_nodes_addr); + DAP_DELETE(l_threads); + dap_list_free_full(l_node_list0, free); + return 0; +} + +static pthread_t s_thread = 0; + +// start background thread for testing connect to the nodes +int dap_chain_node_ping_background_start(dap_chain_net_t *a_net, dap_list_t *a_node_list) +{ + if(!a_node_list) + return -1; + // already started + if(s_thread) + return 0; + // copy list + dap_list_t *l_node_list = NULL; + dap_list_t *l_node_list_tmp = a_node_list; + while(l_node_list_tmp) { + dap_chain_node_addr_t *l_addr = DAP_NEW(dap_chain_node_addr_t); + memcpy(l_addr, l_node_list_tmp->data, sizeof(dap_chain_node_addr_t)); + l_node_list = dap_list_append(l_node_list, l_addr); + l_node_list_tmp = dap_list_next(l_node_list_tmp); + } + // start searching for better nodes + uint8_t *l_arg = DAP_NEW_SIZE(uint8_t, sizeof(dap_chain_net_t*) + sizeof(dap_chain_net_t*)); + memcpy(l_arg, &a_net, sizeof(dap_chain_net_t*)); + memcpy(l_arg + sizeof(dap_chain_net_t*), &l_node_list, sizeof(dap_list_t*)); + pthread_create(&s_thread, NULL, node_ping_background_proc, l_arg); + return 0; +} + +const dap_chain_node_addr_t* dap_chain_node_ping_get_node_tr(void) +{ + return s_node_addr_tr; +} + +const dap_chain_node_addr_t* dap_chain_node_ping_get_node_ping(void) +{ + return s_node_addr_ping; +} + +int dap_chain_node_ping_background_stop(void) +{ + int l_ret = wait_node_ping(s_thread, 500); + s_thread = 0; + return l_ret; +} + +int dap_chain_node_ping_background_status(void) +{ + if(s_thread) + return 1; + return 0; +} diff --git a/dap_chain_node_ping.h b/dap_chain_node_ping.h index 8289031c8fab5b8ebfef3aa799ec38f48dc8b659..a44f4fc25966047b079e9f6d15daee117daa6150 100644 --- a/dap_chain_node_ping.h +++ b/dap_chain_node_ping.h @@ -20,7 +20,11 @@ */ #pragma once +#ifndef _WIN32 #include <netinet/in.h> +#else +#include <windows.h> +#endif #include <pthread.h> // start sending ping @@ -28,3 +32,9 @@ int start_node_ping(pthread_t *a_thread, struct in_addr a_addr, int a_port, int // wait for ending ping within timeout_ms milliseconds int wait_node_ping(pthread_t l_thread, int timeout_ms); + + +// background thread for testing connect to the nodes +int dap_chain_node_ping_background_start(dap_chain_net_t *a_net, dap_list_t *a_node_list); +int dap_chain_node_ping_background_stop(void); +int dap_chain_node_ping_background_status(void); diff --git a/iputils/iputils.h b/iputils/iputils.h index d7948fb516426365b93229a56c8d153127f5b035..0330b548f1a23b5b677a4218683a933a169669e5 100644 --- a/iputils/iputils.h +++ b/iputils/iputils.h @@ -7,7 +7,18 @@ #include <stdint.h> #include <stdlib.h> +#ifndef _WIN32 #include <netinet/ip.h> +#else +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <ws2tcpip.h> +#include <io.h> +#include "win32/iphdr.h" +#include "win32/ip.h" +#define uid_t uint32_t +#endif #include <setjmp.h> #include <sys/time.h>