From 1a87a8e3ca23ffd3871d06b5a414f7dddb707c72 Mon Sep 17 00:00:00 2001
From: Dmitriy Gerasimov <naeper@demlabs.net>
Date: Fri, 25 Jun 2021 15:35:33 +0700
Subject: [PATCH] [+] Added check for existance of dap_chain_node_client_t
 inside timer

---
 modules/net/dap_chain_node_client.c         | 55 +++++++++++++++++++--
 modules/net/include/dap_chain_node_client.h |  3 +-
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index f4fb4e7dae..4f37eea5c8 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -29,7 +29,6 @@
 #include <errno.h>
 #include <assert.h>
 #include <string.h>
-#include <json-c/json.h>
 
 #ifdef WIN32
 #include <winsock2.h>
@@ -44,6 +43,9 @@
 #include <arpa/inet.h>
 #endif
 
+#include <json-c/json.h>
+#include "uthash.h"
+
 #include "dap_common.h"
 #include "dap_client.h"
 #include "dap_config.h"
@@ -73,6 +75,13 @@
 
 #define LOG_TAG "dap_chain_node_client"
 
+typedef struct dap_chain_node_client_handle {
+    uint128_t uuid;
+    dap_chain_node_client_t * client;
+    UT_hash_handle hh;
+} dap_chain_node_client_handle_t;
+
+static dap_chain_node_client_handle_t * s_clients = NULL;
 
 //static int listen_port_tcp = 8079;
 
@@ -106,6 +115,11 @@ int dap_chain_node_client_init(void)
  */
 void dap_chain_node_client_deinit()
 {
+    dap_chain_node_client_handle_t *l_client = NULL, *l_tmp = NULL;
+    HASH_ITER(hh, s_clients,l_client, l_tmp){
+        HASH_DEL(s_clients,l_client);
+        DAP_DELETE(l_client);
+    }
     //dap_http_client_simple_deinit();
     dap_client_deinit();
 }
@@ -148,7 +162,12 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg)
 #endif
         pthread_mutex_unlock(&l_node_client->wait_mutex);
         l_node_client->own_esh.esocket = 0;
-        dap_timerfd_start_on_worker(dap_events_worker_get_auto(),s_timer_update_states*1000,s_timer_update_states_callback, l_node_client);
+
+        dap_chain_node_client_handle_t * l_client_handle = DAP_NEW_Z(dap_chain_node_client_handle_t);
+        l_client_handle->uuid = l_node_client->uuid;
+        l_client_handle->client = l_node_client;
+
+        dap_timerfd_start_on_worker(dap_events_worker_get_auto(),s_timer_update_states*1000,s_timer_update_states_callback, l_client_handle);
         return;
     }
 
@@ -186,7 +205,16 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg)
  */
 static bool s_timer_update_states_callback(void * a_arg )
 {
-    dap_chain_node_client_t *l_me = (dap_chain_node_client_t *) a_arg;
+    dap_chain_node_client_handle_t * l_client_handle = (dap_chain_node_client_handle_t *) a_arg, *l_client_found = NULL;
+    assert(l_client_handle);
+    HASH_FIND(hh,s_clients,&l_client_handle->uuid,sizeof(l_client_handle->uuid),l_client_found);
+    if(! l_client_found){
+        log_it(L_DEBUG,"Chain node client %p was deleted before timer fired, nothing to do", l_client_handle->client);
+        DAP_DELETE(l_client_handle);
+        return false;
+    }
+
+    dap_chain_node_client_t *l_me = l_client_handle->client;
     dap_worker_t * l_worker = dap_events_get_current_worker(dap_events_get_default());
     assert(l_worker);
     assert(l_me);
@@ -220,17 +248,20 @@ static bool s_timer_update_states_callback(void * a_arg )
                                                                         l_chain_id.uint64, l_net->pub.cell_id.uint64,
                                                               &l_sync_gdb, sizeof(l_sync_gdb));
                     }
+                    DAP_DELETE(l_client_handle);
                     return true;
                 }
             }
         }
     }
+
     // if we not returned yet
     l_me->state = NODE_CLIENT_STATE_DISCONNECTED;
     if (l_me->keep_connection) {
         log_it(L_INFO, "Reconnecting node client with peer "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_me->remote_node_addr));
         dap_chain_node_client_connect_internal(l_me, "CN"); // isn't always CN here?
     }
+    DAP_DELETE(l_client_handle);
     return false;
 }
 
@@ -267,7 +298,12 @@ static void s_stage_connected_callback(dap_client_t *a_client, void *a_arg)
         if (l_stream) {
             l_node_client->own_esh.esocket = l_stream->esocket;
             l_node_client->own_esh.uuid = l_stream->esocket->uuid;
-            dap_timerfd_start_on_worker(l_stream->esocket->worker,s_timer_update_states*1000,s_timer_update_states_callback, l_node_client);
+
+            dap_chain_node_client_handle_t * l_client_handle = DAP_NEW_Z(dap_chain_node_client_handle_t);
+            l_client_handle->uuid = l_node_client->uuid;
+            l_client_handle->client = l_node_client;
+
+            dap_timerfd_start_on_worker(l_stream->esocket->worker,s_timer_update_states*1000,s_timer_update_states_callback, l_client_handle);
         }
 #ifndef _WIN32
         pthread_cond_broadcast(&l_node_client->wait_cond);
@@ -580,6 +616,7 @@ dap_chain_node_client_t* dap_chain_node_client_create_n_connect(dap_chain_net_t
         return NULL;
     }
     dap_chain_node_client_t *l_node_client = DAP_NEW_Z(dap_chain_node_client_t);
+
     l_node_client->state = NODE_CLIENT_STATE_DISCONNECTED;
     l_node_client->callbacks_arg = a_callback_arg;
     if(a_callbacks)
@@ -679,6 +716,16 @@ 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);
     }
 }
diff --git a/modules/net/include/dap_chain_node_client.h b/modules/net/include/dap_chain_node_client.h
index 1ea41b6517..d54907d255 100644
--- a/modules/net/include/dap_chain_node_client.h
+++ b/modules/net/include/dap_chain_node_client.h
@@ -66,7 +66,7 @@ typedef struct dap_chain_node_client_callbacks{
 // state for a client connection
 typedef struct dap_chain_node_client {
     dap_chain_node_client_state_t state;
-
+    uint128_t uuid;
     bool sync_gdb;
     bool sync_chains;
 
@@ -118,6 +118,7 @@ typedef struct dap_chain_node_client {
     dap_chain_node_client_callbacks_t callbacks;
     void * callbacks_arg;
 } dap_chain_node_client_t;
+
 #define DAP_CHAIN_NODE_CLIENT(a) (a ? (dap_chain_node_client_t *) (a)->_inheritor : NULL)
 
 int dap_chain_node_client_init(void);
-- 
GitLab