diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eb778919de0ac8c8c54163b5158d5c88b193bf8..ba6e5613ad032803ba5742f2528213a57b8db1b5 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.6-22") +set(CELLFRAME_SDK_NATIVE_VERSION "2.6-23") add_definitions ("-DCELLFRAME_SDK_VERSION=\"${CELLFRAME_SDK_NATIVE_VERSION}\"") set(DAPSDK_MODULES "") diff --git a/dap-sdk/net/client/dap_client.c b/dap-sdk/net/client/dap_client.c index c9e6dd5c8b1bdb60b8b263aec8036c3cab7b3e0b..cbed679e9611900c8de9b446b0089e861316e3d6 100644 --- a/dap-sdk/net/client/dap_client.c +++ b/dap-sdk/net/client/dap_client.c @@ -30,7 +30,8 @@ // FSM realization: thats callback executes after the every stage is done // and have to select the next one stage -void m_stage_fsm_operator_unsafe(dap_client_t *, void *); +static void s_stage_fsm_operator_unsafe(dap_client_t *, void *); +static void s_stage_done_delete(dap_client_t * a_client, void * a_arg); /** * @brief dap_client_init @@ -94,7 +95,7 @@ MEM_ALLOC_ERR: log_it(L_ERROR, "dap_client_new can not allocate memory"); if (l_client) if(l_client->_internal) - free(l_client->_internal); + DAP_DELETE(l_client->_internal); if (l_client) DAP_DELETE (l_client); @@ -107,7 +108,7 @@ MEM_ALLOC_ERR: * @param a_addr * @param a_port */ -void dap_client_set_uplink(dap_client_t * a_client,const char* a_addr, uint16_t a_port) +void dap_client_set_uplink_unsafe(dap_client_t * a_client,const char* a_addr, uint16_t a_port) { if(a_addr == NULL){ log_it(L_ERROR,"Address is NULL for dap_client_set_uplink"); @@ -126,14 +127,14 @@ void dap_client_set_uplink(dap_client_t * a_client,const char* a_addr, uint16_t * @param a_client * @return */ -const char* dap_client_get_uplink_addr(dap_client_t * a_client) +const char* dap_client_get_uplink_addr_unsafe(dap_client_t * a_client) { if(a_client == NULL){ log_it(L_ERROR,"Client is NULL for dap_client_get_uplink"); return NULL; } - - return DAP_CLIENT_PVT(a_client)->uplink_addr; + const char * l_ret = DAP_CLIENT_PVT(a_client)->uplink_addr; + return l_ret; } /** @@ -141,7 +142,7 @@ const char* dap_client_get_uplink_addr(dap_client_t * a_client) * @param a_client * @param a_active_channels */ -void dap_client_set_active_channels (dap_client_t * a_client, const char * a_active_channels) +void dap_client_set_active_channels_unsafe (dap_client_t * a_client, const char * a_active_channels) { if(a_client == NULL){ log_it(L_ERROR,"Client is NULL for dap_client_set_active_channels"); @@ -158,7 +159,7 @@ void dap_client_set_active_channels (dap_client_t * a_client, const char * a_act * @param a_client * @return */ -uint16_t dap_client_get_uplink_port(dap_client_t * a_client) +uint16_t dap_client_get_uplink_port_unsafe(dap_client_t * a_client) { if(a_client == NULL){ log_it(L_ERROR,"Client is NULL for dap_client_get_uplink_port"); @@ -168,7 +169,7 @@ uint16_t dap_client_get_uplink_port(dap_client_t * a_client) return DAP_CLIENT_PVT(a_client)->uplink_port; } -void dap_client_set_auth_cert(dap_client_t * a_client, dap_cert_t *a_cert) +void dap_client_set_auth_cert_unsafe(dap_client_t * a_client, dap_cert_t *a_cert) { if(a_client == NULL){ log_it(L_ERROR,"Client is NULL for dap_client_set_auth_cert"); @@ -178,74 +179,45 @@ void dap_client_set_auth_cert(dap_client_t * a_client, dap_cert_t *a_cert) DAP_CLIENT_PVT(a_client)->auth_cert = a_cert; } - -/** - * @brief s_client_reset_unsafe - * @param a_worker - * @param a_arg - */ -static void s_client_reset_unsafe(dap_worker_t * a_worker, void * a_arg) -{ - (void) a_arg; - assert(a_arg); - dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT( ((dap_client_t*)a_arg)); - assert(l_client_internal); - if(l_client_internal->session_key){ - dap_enc_key_delete(l_client_internal->session_key); - l_client_internal->session_key = NULL; - - } - if(l_client_internal->session_key_id){ - DAP_DELETE(l_client_internal->session_key_id); - l_client_internal->session_key_id = NULL; - } - if ( l_client_internal->stream_key ){ - dap_enc_key_delete(l_client_internal->stream_key ); - l_client_internal->stream_key = NULL; - } - l_client_internal->stream_es = NULL; - - l_client_internal->stage = STAGE_BEGIN; - l_client_internal->stage_status = STAGE_STATUS_DONE ; - l_client_internal->stage_target = STAGE_BEGIN ; - -} - /** - * @brief dap_client_reset + * @brief s_client_delete * @param a_client */ -void dap_client_reset(dap_client_t * a_client) +void dap_client_delete_unsafe(dap_client_t * a_client) { - dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client); - assert(l_client_internal); - dap_worker_exec_callback_on(l_client_internal->worker, s_client_reset_unsafe, a_client); + if ( DAP_CLIENT_PVT(a_client)->refs_count ==0 ){ + DAP_CLIENT_PVT(a_client)->delete_callback(a_client, NULL); + dap_client_pvt_delete( DAP_CLIENT_PVT(a_client) ); + pthread_mutex_destroy(&a_client->mutex); + DAP_DELETE(a_client); + } else + DAP_CLIENT_PVT(a_client)->is_to_delete = true; } - /** - * @brief dap_client_delete + * @brief s_stage_begin_before_delete * @param a_client + * @param a_arg */ -void dap_client_delete(dap_client_t * a_client) +static void s_stage_done_delete(dap_client_t * a_client, void * a_arg) { - if(!a_client) - return; - pthread_mutex_lock(&a_client->mutex); - - dap_client_pvt_delete_n_wait(DAP_CLIENT_PVT(a_client)); - a_client->_internal = NULL; - pthread_mutex_unlock(&a_client->mutex); + (void) a_arg; pthread_mutex_destroy(&a_client->mutex); - DAP_DELETE(a_client); } + struct go_stage_arg{ + bool flag_delete_after;// Delete after stage achievement dap_client_pvt_t *client_pvt; dap_client_stage_t stage_target; dap_client_callback_t stage_end_callback; }; +/** + * @brief s_go_stage_on_client_worker_unsafe + * @param a_worker + * @param a_arg + */ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_arg) { (void) a_worker; @@ -253,8 +225,22 @@ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_ dap_client_stage_t l_stage_target = ((struct go_stage_arg*) a_arg)->stage_target; dap_client_callback_t l_stage_end_callback= ((struct go_stage_arg*) a_arg)->stage_end_callback; dap_client_pvt_t * l_client_pvt = ((struct go_stage_arg*) a_arg)->client_pvt; + dap_client_t * l_client = ((struct go_stage_arg*) a_arg)->client_pvt->client; + bool l_flag_delete_after = ((struct go_stage_arg *) a_arg)->flag_delete_after ;// Delete after stage achievement DAP_DELETE(a_arg); + l_client_pvt->is_to_delete = l_flag_delete_after; + if ( l_client==NULL){ + log_it(L_WARNING,"Client is NULL, why? Refs %u", l_client_pvt->refs_count); + if ( l_client_pvt->refs_count ==0 ){ + dap_client_pvt_delete( l_client_pvt ); + } else + l_client_pvt->is_to_delete = true; + return; + } + + + dap_client_stage_t l_cur_stage = l_client_pvt->stage; dap_client_stage_status_t l_cur_stage_status= l_client_pvt->stage_status; if (l_stage_target == l_cur_stage){ @@ -276,6 +262,8 @@ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_ log_it(L_WARNING, "Unprocessed stage status %s for go to stage %s scheme ", dap_client_stage_str(l_stage_target), dap_client_stage_status_str( l_cur_stage_status)); } + l_client_pvt->refs_count--; + dap_client_delete_unsafe(l_client_pvt->client); return; } log_it(L_DEBUG, "Start transitions chain for client %p from %s to %s", l_client_pvt->client, dap_client_stage_str(l_cur_stage ) , dap_client_stage_str(l_stage_target)); @@ -301,10 +289,14 @@ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_ default: { dap_client_pvt_stage_transaction_begin(l_client_pvt, l_cur_stage + 1, - m_stage_fsm_operator_unsafe); + s_stage_fsm_operator_unsafe); } } } + l_client_pvt->refs_count--; + if ( l_client_pvt->is_to_delete ) + dap_client_delete_unsafe(l_client_pvt->client); + } /** * @brief dap_client_go_stage @@ -333,19 +325,40 @@ void dap_client_go_stage(dap_client_t * a_client, dap_client_stage_t a_stage_tar dap_worker_exec_callback_on(l_client_pvt->worker, s_go_stage_on_client_worker_unsafe, l_stage_arg); } +/** + * @brief dap_client_go_delete + * @param a_client + */ +void dap_client_delete_mt(dap_client_t * a_client) +{ + assert(a_client); + dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client); + assert(l_client_pvt); + + struct go_stage_arg *l_stage_arg = DAP_NEW(struct go_stage_arg); + l_stage_arg->stage_end_callback = s_stage_done_delete ; + l_stage_arg->stage_target = STAGE_BEGIN ; + l_stage_arg->client_pvt = l_client_pvt; + l_stage_arg->flag_delete_after = true; + dap_worker_exec_callback_on(l_client_pvt->worker, s_go_stage_on_client_worker_unsafe, l_stage_arg); +} + /** - * @brief m_stage_fsm_operator_unsafe + * @brief s_stage_fsm_operator_unsafe * @param a_client * @param a_arg */ -void m_stage_fsm_operator_unsafe(dap_client_t * a_client, void * a_arg) +static void s_stage_fsm_operator_unsafe(dap_client_t * a_client, void * a_arg) { UNUSED(a_arg); + assert(a_client); dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client); - if(!l_client_internal){ - log_it(L_ERROR, "FSM Op: l_client_internal is NULL!"); - return; + assert(l_client_internal); + + if ( l_client_internal->is_to_delete ){ // If we're switched once to delete and smbd else switched to another state - we restore target + l_client_internal->stage_target = STAGE_BEGIN; + l_client_internal->stage_target_done_callback = s_stage_done_delete; } if (l_client_internal->stage_target == l_client_internal->stage){ @@ -362,7 +375,7 @@ void m_stage_fsm_operator_unsafe(dap_client_t * a_client, void * a_arg) ,dap_client_stage_str(l_client_internal->stage), dap_client_stage_str(l_stage_next) ,dap_client_stage_str(l_client_internal->stage_target)); dap_client_pvt_stage_transaction_begin(l_client_internal, - l_stage_next, m_stage_fsm_operator_unsafe + l_stage_next, s_stage_fsm_operator_unsafe ); } diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c index cb482095566d4952f9b0b1bc3e32ff065d6d0ef6..13cf12303432141fc20b5b0a2b6f09e3c8288a7d 100644 --- a/dap-sdk/net/client/dap_client_pvt.c +++ b/dap-sdk/net/client/dap_client_pvt.c @@ -132,95 +132,43 @@ void dap_client_pvt_new(dap_client_pvt_t * a_client_internal) a_client_internal->stage_status = STAGE_STATUS_DONE; a_client_internal->uplink_protocol_version = DAP_PROTOCOL_VERSION; a_client_internal->events = dap_events_get_default(); - pthread_mutex_init( &a_client_internal->disconnected_mutex, NULL); - pthread_cond_init( &a_client_internal->disconnected_cond, NULL); // add to list dap_client_pvt_hh_add(a_client_internal); } -/** - * @brief s_client_pvt_disconnected - * @param a_client - * @param a_arg - */ -static void s_client_pvt_disconnected(dap_client_t * a_client, void * a_arg ) -{ - (void) a_arg; - // To be sure thats cond waiter is waiting and unlocked mutex - pthread_mutex_lock(&DAP_CLIENT_PVT(a_client)->disconnected_mutex); - pthread_mutex_unlock(&DAP_CLIENT_PVT(a_client)->disconnected_mutex); - DAP_CLIENT_PVT(a_client)->stage_status = STAGE_STATUS_ABORTING; - pthread_cond_broadcast(&DAP_CLIENT_PVT(a_client)->disconnected_cond); -} - -/** - * @brief dap_client_disconnect - * @param a_client - * @return - */ -int dap_client_pvt_disconnect_all_n_wait(dap_client_pvt_t *a_client_pvt) -{ - if(!a_client_pvt) - return -1; - time_t l_ts_begin=time(NULL); - log_it(L_DEBUG,"Disconnect_n_wait called"); - - pthread_mutex_lock(&a_client_pvt->disconnected_mutex); - dap_client_go_stage(a_client_pvt->client, STAGE_BEGIN, s_client_pvt_disconnected ); - - pthread_cond_wait(&a_client_pvt->disconnected_cond, &a_client_pvt->disconnected_mutex); - pthread_mutex_unlock(&a_client_pvt->disconnected_mutex); - - - time_t l_ts_end=time(NULL); - // Dont read or write client stage here. If you're here - it must be STAGE_BEGIN. Ever it would be problems - we must reset all - // the states to the STAGE_BEGIN - log_it(L_INFO,"Disconnected: achieved STAGE_BEGIN at time %d", - l_ts_end-l_ts_begin); - return 0; -} /** * @brief dap_client_pvt_delete * @param a_client_pvt */ -void dap_client_pvt_delete_n_wait(dap_client_pvt_t * a_client_pvt) +void dap_client_pvt_delete(dap_client_pvt_t * a_client_pvt) { - if(!a_client_pvt) - return; + assert(a_client_pvt); + if(a_client_pvt->delete_callback) + a_client_pvt->delete_callback(a_client_pvt->client, NULL); // delete from list if(dap_client_pvt_hh_del(a_client_pvt)<0){ log_it(L_DEBUG, "dap_client_pvt 0x%x already deleted", a_client_pvt); return; } - - dap_client_pvt_disconnect_all_n_wait(a_client_pvt); - log_it(L_INFO, "dap_client_pvt_delete 0x%x", a_client_pvt); if(a_client_pvt->session_key_id) DAP_DELETE(a_client_pvt->session_key_id); - a_client_pvt->session_key_id = NULL; if(a_client_pvt->active_channels) DAP_DELETE(a_client_pvt->active_channels); - a_client_pvt->active_channels = NULL; if(a_client_pvt->session_key) dap_enc_key_delete(a_client_pvt->session_key); - a_client_pvt->session_key = NULL; if(a_client_pvt->session_key_open) dap_enc_key_delete(a_client_pvt->session_key_open); - a_client_pvt->session_key_open = NULL; if(a_client_pvt->stream_key) dap_enc_key_delete(a_client_pvt->stream_key); - a_client_pvt->stream_key = NULL; - pthread_mutex_destroy( &a_client_pvt->disconnected_mutex); - pthread_cond_destroy( &a_client_pvt->disconnected_cond); DAP_DELETE(a_client_pvt); } @@ -601,6 +549,7 @@ int dap_client_pvt_request(dap_client_pvt_t * a_client_internal, const char * a_ a_client_internal->request_response_callback = a_response_proc; a_client_internal->request_error_callback = a_response_error; a_client_internal->is_encrypted = false; + a_client_internal->refs_count++;; void *l_ret = dap_client_http_request(a_client_internal->worker, a_client_internal->uplink_addr,a_client_internal->uplink_port, a_request ? "POST" : "GET", "text/text", a_path, a_request, @@ -722,6 +671,7 @@ void dap_client_pvt_request_enc(dap_client_pvt_t * a_client_internal, const char l_custom_new[1] = dap_strdup("SessionCloseAfterRequest: true"); l_custom_count++; } + a_client_internal->refs_count++; dap_client_http_request_custom(a_client_internal->worker, a_client_internal->uplink_addr, a_client_internal->uplink_port, a_request ? "POST" : "GET", "text/text", l_path, l_request_enc, l_request_enc_size, NULL, s_request_response, s_request_error, a_client_internal, l_custom_new, l_custom_count); @@ -772,8 +722,23 @@ static void s_request_error(int a_err_code, void * a_obj) static void s_request_response(void * a_response, size_t a_response_size, void * a_obj) { dap_client_pvt_t * a_client_internal = (dap_client_pvt_t *) a_obj; - if(!a_client_internal || !a_client_internal->client) + if(!a_client_internal || !a_client_internal->client){ + if( !a_client_internal ) + log_it(L_ERROR,"Client internal is NULL for s_request_response"); + else + log_it(L_ERROR,"Client is NULL for s_request_response"); + return; + } + a_client_internal->refs_count--; + + if (a_client_internal->is_to_delete){ + if(a_client_internal->refs_count==0) // Was requested to delete until we was working with request + dap_client_delete_unsafe(a_client_internal->client); // Init delete + return; + } + + //int l_ref = dap_client_pvt_get_ref(a_client_internal); if(a_client_internal->is_encrypted) { size_t l_response_dec_size_max = a_response_size ? a_response_size * 2 + 16 : 0; @@ -785,12 +750,18 @@ static void s_request_response(void * a_response, size_t a_response_size, void * l_response_dec, l_response_dec_size_max, DAP_ENC_DATA_TYPE_RAW); - a_client_internal->request_response_callback(a_client_internal->client, l_response_dec, l_response_dec_size); + if ( a_client_internal->request_response_callback ) + a_client_internal->request_response_callback(a_client_internal->client, l_response_dec, l_response_dec_size); + else + log_it(L_ERROR, "NULL request_response_callback for encrypted client %p", a_client_internal->client ); if(l_response_dec) DAP_DELETE(l_response_dec); } else { - a_client_internal->request_response_callback(a_client_internal->client, a_response, a_response_size); + if ( a_client_internal->request_response_callback ) + a_client_internal->request_response_callback(a_client_internal->client, a_response, a_response_size); + else + log_it(L_ERROR, "NULL request_response_callback for unencrypted client %p", a_client_internal->client ); } //int l_ref2 = dap_client_pvt_get_ref(a_client_internal); diff --git a/dap-sdk/net/client/include/dap_client.h b/dap-sdk/net/client/include/dap_client.h index 4bbd72dbb13ba68ff9227249ba4f47afe4cabe2f..a19f9439d5dc082d280ebdb09f89b0ab4e011680 100644 --- a/dap-sdk/net/client/include/dap_client.h +++ b/dap-sdk/net/client/include/dap_client.h @@ -99,19 +99,16 @@ void dap_client_deinit(); dap_client_t * dap_client_new(dap_events_t * a_events, dap_client_callback_t a_stage_status_callback , dap_client_callback_t a_stage_status_error_callback ); -void dap_client_set_uplink(dap_client_t * a_client,const char* a_addr, uint16_t a_port); -const char* dap_client_get_uplink_addr(dap_client_t * a_client); -uint16_t dap_client_get_uplink_port(dap_client_t * a_client); - - -void dap_client_delete(dap_client_t * a_client); +void dap_client_set_uplink_unsafe(dap_client_t * a_client,const char* a_addr, uint16_t a_port); +const char* dap_client_get_uplink_addr_unsafe(dap_client_t * a_client); +uint16_t dap_client_get_uplink_port_unsafe(dap_client_t * a_client); dap_enc_key_t * dap_client_get_key_stream(dap_client_t * a_client); void dap_client_go_stage(dap_client_t * a_client, dap_client_stage_t a_stage_end, dap_client_callback_t a_stage_end_callback); - -void dap_client_reset(dap_client_t * a_client); +void dap_client_delete_mt(dap_client_t * a_client); +void dap_client_delete_unsafe(dap_client_t * a_client); void dap_client_request_enc_unsafe(dap_client_t * a_client, const char * a_path,const char * a_suburl,const char* a_query, void * a_request, size_t a_request_size, dap_client_callback_data_size_t a_response_proc, dap_client_callback_int_t a_response_error); @@ -134,8 +131,8 @@ dap_stream_t * dap_client_get_stream(dap_client_t * a_client); dap_stream_worker_t * dap_client_get_stream_worker(dap_client_t * a_client); dap_stream_ch_t * dap_client_get_stream_ch_unsafe(dap_client_t * a_client, uint8_t a_ch_id); const char * dap_client_get_stream_id(dap_client_t * a_client); -void dap_client_set_active_channels (dap_client_t * a_client, const char * a_active_channels); -void dap_client_set_auth_cert(dap_client_t * a_client, dap_cert_t *a_cert); +void dap_client_set_active_channels_unsafe (dap_client_t * a_client, const char * a_active_channels); +void dap_client_set_auth_cert_unsafe(dap_client_t * a_client, dap_cert_t *a_cert); dap_client_stage_t dap_client_get_stage(dap_client_t * a_client); dap_client_stage_status_t dap_client_get_stage_status(dap_client_t * a_client); diff --git a/dap-sdk/net/client/include/dap_client_pvt.h b/dap-sdk/net/client/include/dap_client_pvt.h index a4cbac71eb4b66d329c03ac9af37e3abe4159048..05c023a69b3865601eb5ac26e31e74027ca57d4a 100644 --- a/dap-sdk/net/client/include/dap_client_pvt.h +++ b/dap-sdk/net/client/include/dap_client_pvt.h @@ -75,18 +75,18 @@ typedef struct dap_client_internal dap_client_callback_t stage_status_callback; dap_client_callback_t stage_status_done_callback; dap_client_callback_t stage_status_error_callback; + dap_client_callback_t delete_callback; int stage_errors; + atomic_uint refs_count; + atomic_bool is_to_delete; bool is_encrypted; bool is_encrypted_headers; bool is_close_session;// the last request in session, in the header will be added "SessionCloseAfterRequest: true" dap_client_callback_data_size_t request_response_callback; dap_client_callback_int_t request_error_callback; - // Conds - pthread_cond_t disconnected_cond; - pthread_mutex_t disconnected_mutex; } dap_client_pvt_t; #define DAP_CLIENT_PVT(a) (a ? (dap_client_pvt_t*) a->_internal : NULL) @@ -106,7 +106,7 @@ void dap_client_pvt_request_enc(dap_client_pvt_t * a_client_internal, const char dap_client_callback_int_t a_error_proc); void dap_client_pvt_new(dap_client_pvt_t * a_client_internal); -void dap_client_pvt_delete_n_wait(dap_client_pvt_t * a_client_pvt); +void dap_client_pvt_delete(dap_client_pvt_t * a_client_pvt); //int dap_client_pvt_ref(dap_client_pvt_t * a_client_internal); //int dap_client_pvt_unref(dap_client_pvt_t * a_client_internal); diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 0000663b4a7ceb10b15e281fc3dca6a584e9d27b..e0e99708f4028712c9019782e31fe862d4b576c3 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -429,7 +429,7 @@ dap_chain_node_client_t* dap_chain_client_connect(dap_chain_node_info_t *a_node_ s_stage_status_error_callback); l_node_client->client->_inheritor = l_node_client; l_node_client->remote_node_addr.uint64 = a_node_info->hdr.address.uint64; - dap_client_set_active_channels(l_node_client->client, a_active_channels); + dap_client_set_active_channels_unsafe(l_node_client->client, a_active_channels); //dap_client_set_auth_cert(l_node_client->client, dap_cert_find_by_name("auth")); // TODO provide the certificate choice @@ -450,7 +450,7 @@ dap_chain_node_client_t* dap_chain_client_connect(dap_chain_node_info_t *a_node_ dap_chain_node_client_close(l_node_client); return NULL; } - dap_client_set_uplink(l_node_client->client, strdup(host), a_node_info->hdr.ext_port); + dap_client_set_uplink_unsafe(l_node_client->client, strdup(host), a_node_info->hdr.ext_port); // dap_client_stage_t a_stage_target = STAGE_ENC_INIT; // dap_client_stage_t l_stage_target = STAGE_STREAM_STREAMING; @@ -488,7 +488,7 @@ void dap_chain_node_client_close(dap_chain_node_client_t *a_client) { if (a_client && a_client->client) { // block tryes to close twice // clean client - dap_client_delete(a_client->client); + dap_client_delete_mt(a_client->client); #ifndef _WIN32 pthread_cond_destroy(&a_client->wait_cond); #else