From 489cad3a79e4ca0227b06afb47274e8c5b956c53 Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Tue, 24 Aug 2021 17:28:17 +0300
Subject: [PATCH] bugs-4850-

---
 dap-sdk/net/client/dap_client.c         | 42 +++++++++++++------------
 dap-sdk/net/client/dap_client_pvt.c     | 17 +++++++---
 dap-sdk/net/client/include/dap_client.h |  1 +
 modules/net/dap_chain_node_client.c     | 28 ++++++++---------
 4 files changed, 48 insertions(+), 40 deletions(-)

diff --git a/dap-sdk/net/client/dap_client.c b/dap-sdk/net/client/dap_client.c
index 138c188502..4aecd9b0d1 100644
--- a/dap-sdk/net/client/dap_client.c
+++ b/dap-sdk/net/client/dap_client.c
@@ -86,13 +86,15 @@ dap_client_t * dap_client_new(dap_events_t * a_events, dap_client_callback_t a_s
         goto MEM_ALLOC_ERR;
 
     // CONSTRUCT dap_client object
-    DAP_CLIENT_PVT(l_client)->client = l_client;
-    DAP_CLIENT_PVT(l_client)->events = a_events;
-    DAP_CLIENT_PVT(l_client)->stage_status_callback = a_stage_status_callback;
-    DAP_CLIENT_PVT(l_client)->stage_status_error_callback = a_stage_status_error_callback;
-    DAP_CLIENT_PVT(l_client)->worker = dap_events_worker_get_auto();
+    dap_client_pvt_t *l_client_pvt = DAP_CLIENT_PVT(l_client);
+    l_client_pvt->client = l_client;
+    l_client_pvt->events = a_events;
+    l_client_pvt->stage_status_callback = a_stage_status_callback;
+    l_client_pvt->stage_status_error_callback = a_stage_status_error_callback;
+    l_client_pvt->worker = dap_events_worker_get_auto();
 
-    dap_client_pvt_new(DAP_CLIENT_PVT(l_client) );
+    dap_client_pvt_new(l_client_pvt);
+    l_client->pvt_uuid = l_client_pvt->uuid;
 
     return l_client;
 
@@ -235,8 +237,8 @@ static void s_go_stage_on_client_worker_unsafe(dap_worker_t * a_worker,void * a_
     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 || l_client->_internal != l_client_pvt) {
+        log_it(L_WARNING,"Client is NULL or corrupted, why? Refs %u", l_client_pvt->refs_count);
         if ( l_client_pvt->refs_count ==0 ){
             dap_client_pvt_delete( l_client_pvt );
         } else
@@ -317,7 +319,7 @@ void dap_client_go_stage(dap_client_t * a_client, dap_client_stage_t a_stage_tar
         log_it(L_ERROR, "dap_client_go_stage, a_stage_end_callback == NULL");
         return;
     }
-    dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client);
+    dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(a_client->pvt_uuid);
 
     assert(l_client_pvt);
 
@@ -335,7 +337,7 @@ void dap_client_go_stage(dap_client_t * a_client, dap_client_stage_t a_stage_tar
 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);
+    dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(a_client->pvt_uuid);
     assert(l_client_pvt);
 
     struct go_stage_arg *l_stage_arg = DAP_NEW(struct go_stage_arg); if (! l_stage_arg) return;
@@ -356,7 +358,7 @@ 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);
+    dap_client_pvt_t * l_client_internal = dap_client_pvt_find(a_client->pvt_uuid);
     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
@@ -398,14 +400,14 @@ static void s_stage_fsm_operator_unsafe(dap_client_t * a_client, void * a_arg)
 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 )
 {
-    dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client);
+    dap_client_pvt_t * l_client_internal = dap_client_pvt_find(a_client->pvt_uuid);
     dap_client_pvt_request_enc(l_client_internal, a_path, a_suburl, a_query,a_request,a_request_size, a_response_proc,a_response_error);
 }
 
 void dap_client_request_unsafe(dap_client_t * a_client, const char * a_full_path, 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 )
 {
-    dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client);
+    dap_client_pvt_t * l_client_internal = dap_client_pvt_find(a_client->pvt_uuid);
     dap_client_pvt_request(l_client_internal, a_full_path, a_request, a_request_size, a_response_proc, a_response_error);
 }
 
@@ -439,7 +441,7 @@ const char * dap_client_error_str(dap_client_error_t a_client_error)
  */
 const char * dap_client_get_error_str(dap_client_t * a_client)
 {
-    if(a_client == NULL || DAP_CLIENT_PVT(a_client) == NULL){
+    if(a_client == NULL || dap_client_pvt_find(a_client->pvt_uuid) == NULL){
         log_it(L_ERROR,"Client is NULL for dap_client_get_error_str");
         return NULL;
     }
@@ -527,7 +529,7 @@ const char * dap_client_stage_str(dap_client_stage_t a_stage)
  */
 dap_client_stage_status_t dap_client_get_stage_status(dap_client_t * a_client)
 {
-    return (a_client && DAP_CLIENT_PVT(a_client)) ? DAP_CLIENT_PVT(a_client)->stage_status : STAGE_STATUS_NONE;
+    return (a_client && dap_client_pvt_find(a_client->pvt_uuid)) ? DAP_CLIENT_PVT(a_client)->stage_status : STAGE_STATUS_NONE;
 }
 
 /**
@@ -536,7 +538,7 @@ dap_client_stage_status_t dap_client_get_stage_status(dap_client_t * a_client)
  * @return
  */
 dap_enc_key_t * dap_client_get_key_stream(dap_client_t * a_client){
-    return (a_client && DAP_CLIENT_PVT(a_client)) ? DAP_CLIENT_PVT(a_client)->stream_key : NULL;
+    return (a_client && dap_client_pvt_find(a_client->pvt_uuid)) ? DAP_CLIENT_PVT(a_client)->stream_key : NULL;
 }
 
 
@@ -552,7 +554,7 @@ dap_stream_t * dap_client_get_stream(dap_client_t * a_client)
         return NULL;
     }
 
-    dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client);
+    dap_client_pvt_t * l_client_internal = dap_client_pvt_find(a_client->pvt_uuid);
     return (l_client_internal) ? l_client_internal->stream : NULL;
 }
 
@@ -567,7 +569,7 @@ dap_stream_worker_t * dap_client_get_stream_worker(dap_client_t * a_client)
         log_it(L_ERROR,"Client is NULL for dap_client_get_stream_worker");
         return NULL;
     }
-    dap_client_pvt_t * l_client_internal = DAP_CLIENT_PVT(a_client);
+    dap_client_pvt_t * l_client_internal = dap_client_pvt_find(a_client->pvt_uuid);
     return (l_client_internal) ? l_client_internal->stream_worker : NULL;
 
 }
@@ -575,7 +577,7 @@ 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)
 {
     dap_stream_ch_t * l_ch = NULL;
-    dap_client_pvt_t * l_client_internal = a_client ? DAP_CLIENT_PVT(a_client) : NULL;
+    dap_client_pvt_t * l_client_internal = a_client ? dap_client_pvt_find(a_client->pvt_uuid) : NULL;
     if(l_client_internal && l_client_internal->stream && l_client_internal->stream_es)
         for(size_t i = 0; i < l_client_internal->stream->channel_count; i++) {
             if(l_client_internal->stream->channel[i]->proc->id == a_ch_id) {
@@ -593,7 +595,7 @@ dap_stream_ch_t * dap_client_get_stream_ch_unsafe(dap_client_t * a_client, uint8
  */
 const char * dap_client_get_stream_id(dap_client_t * a_client)
 {
-    if(!(a_client || !DAP_CLIENT_PVT(a_client)))
+    if(!(a_client || !dap_client_pvt_find(a_client->pvt_uuid)))
         return NULL;
     return DAP_CLIENT_PVT(a_client)->stream_id;
 }
diff --git a/dap-sdk/net/client/dap_client_pvt.c b/dap-sdk/net/client/dap_client_pvt.c
index 537221e0b2..b2c15f14b1 100644
--- a/dap-sdk/net/client/dap_client_pvt.c
+++ b/dap-sdk/net/client/dap_client_pvt.c
@@ -167,14 +167,17 @@ void dap_client_pvt_new(dap_client_pvt_t * a_client_pvt)
 void dap_client_pvt_delete(dap_client_pvt_t * a_client_pvt)
 {
     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_unsafe(a_client_pvt)<0){
         if(s_debug_more)
             log_it(L_DEBUG, "dap_client_pvt 0x%x already deleted", a_client_pvt);
         return;
     }
+    if(a_client_pvt->delete_callback)
+        a_client_pvt->delete_callback(a_client_pvt->client, NULL);
+    if (a_client_pvt->stream_es) {
+        dap_events_socket_remove_and_delete_unsafe(a_client_pvt->stream_es, true);
+    }
     if(s_debug_more)
         log_it(L_INFO, "dap_client_pvt_delete 0x%x", a_client_pvt);
 
@@ -319,6 +322,8 @@ static bool s_enc_init_delay_before_request_timer_callback(void * a_arg)
  */
 static bool s_stage_status_after(dap_client_pvt_t * a_client_pvt)
 {
+    if (!dap_client_pvt_find(a_client_pvt->uuid))
+        return false;
     dap_worker_t * l_worker= a_client_pvt->worker;
     assert(l_worker);
     assert(l_worker->_inheritor);
@@ -870,8 +875,9 @@ static void s_request_error(int a_err_code, void * a_obj)
 
     if(l_client_pvt && l_client_pvt->request_error_callback && l_client_pvt->client)
     {
+        l_client_pvt = dap_client_pvt_find(l_client_pvt->uuid);
         if(l_client_pvt && l_client_pvt->request_error_callback
-                && l_client_pvt->client && l_client_pvt->client->_internal && l_client_pvt->client->_internal == l_client_pvt)
+                && l_client_pvt->client && l_client_pvt->client->_internal)
             l_client_pvt->request_error_callback(l_client_pvt->client, a_err_code);
     }
 }
@@ -921,8 +927,9 @@ static void s_request_response(void * a_response, size_t a_response_size, void *
  */
 static void s_enc_init_response(dap_client_t * a_client, void * a_response, size_t a_response_size)
 {
-    dap_client_pvt_t * l_client_pvt = DAP_CLIENT_PVT(a_client);
-    assert(l_client_pvt);
+    dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(a_client->pvt_uuid);
+    if (!l_client_pvt)
+        return;
 
     if (!l_client_pvt->session_key_open){
         log_it(L_ERROR, "m_enc_init_response: session is NULL!");
diff --git a/dap-sdk/net/client/include/dap_client.h b/dap-sdk/net/client/include/dap_client.h
index d311f50ded..1c6920b1b6 100644
--- a/dap-sdk/net/client/include/dap_client.h
+++ b/dap-sdk/net/client/include/dap_client.h
@@ -77,6 +77,7 @@ typedef struct dap_client{
     pthread_mutex_t mutex;
     void * _internal;
     void * _inheritor;
+    uint64_t pvt_uuid;
 } dap_client_t;
 
 typedef void (*dap_client_callback_t) (dap_client_t *, void*);
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index 9c8ffa7d18..4677ee5561 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -687,16 +687,21 @@ void dap_chain_node_client_reset(dap_chain_node_client_t *a_client)
  */
 void dap_chain_node_client_close(dap_chain_node_client_t *a_client)
 {
-    if (a_client && a_client->client) { // block tryes to close twice
+    dap_chain_node_client_handle_t * l_client_found = NULL;
+    HASH_FIND(hh,s_clients,&a_client->uuid,sizeof(a_client->uuid),l_client_found);
+    if (l_client_found) {
+        HASH_DEL(s_clients,l_client_found);
+        DAP_DELETE(l_client_found);
         char l_node_addr_str[INET_ADDRSTRLEN] = {};
         inet_ntop(AF_INET, &a_client->info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
         log_it(L_INFO, "Closing node client to uplink %s:%d", l_node_addr_str, a_client->info->hdr.ext_port);
         // clean client
-        DAP_CLIENT_PVT(a_client->client)->stage_status_error_callback = NULL;
-        a_client->client->_inheritor = NULL;
-        if (a_client->stream_worker)
-            dap_events_socket_remove_and_delete_mt(a_client->stream_worker->worker, a_client->esocket_uuid);
-        dap_client_delete_mt(a_client->client);
+        dap_client_pvt_t *l_client_pvt = dap_client_pvt_find(a_client->client->pvt_uuid);
+        if (l_client_pvt) {
+            l_client_pvt->stage_status_error_callback = NULL;
+            dap_client_delete_mt(a_client->client);
+            a_client->client->_inheritor = NULL;
+        }
 #ifndef _WIN32
         pthread_cond_destroy(&a_client->wait_cond);
 #else
@@ -704,16 +709,9 @@ void dap_chain_node_client_close(dap_chain_node_client_t *a_client)
 #endif
         pthread_mutex_destroy(&a_client->wait_mutex);
         a_client->client = NULL;
-        dap_chain_node_client_handle_t * l_client_found = NULL;
-        HASH_FIND(hh,s_clients,&a_client->uuid,sizeof(a_client->uuid),l_client_found);
-        if (l_client_found){
-            HASH_DEL(s_clients,l_client_found);
-            DAP_DELETE(l_client_found);
-        }else{
-            log_it(L_WARNING, "Chain node client was removed from hash table before for some reasons");
-        }
-
         DAP_DELETE(a_client);
+    } else {
+        log_it(L_WARNING, "Chain node client was removed from hash table before for some reasons");
     }
 }
 
-- 
GitLab