From 5ca961c39935b717d79eac1d42895250ef2c040d Mon Sep 17 00:00:00 2001
From: "cellframe.docs" <artur.khudiaev@demlabs.net>
Date: Thu, 2 Jun 2022 08:52:59 +0000
Subject: [PATCH] bugfix-network-chain-list

Former-commit-id: e062c2d036d60cc3d1a4ffb10b6a34713e02b412
---
 dap-sdk/core/include/dap_strfuncs.h  |  1 +
 dap-sdk/core/src/dap_strfuncs.c      | 35 ++++++++++++++++++++++++++++
 modules/net/dap_chain_net.c          | 27 +++++++++++++++++++--
 modules/net/dap_chain_node_cli_cmd.c | 20 ++++++++++++++++
 modules/net/include/dap_chain_net.h  |  1 +
 5 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h
index c638d9260d..a14b12dc5c 100755
--- a/dap-sdk/core/include/dap_strfuncs.h
+++ b/dap-sdk/core/include/dap_strfuncs.h
@@ -46,6 +46,7 @@ char *strptime( char *buff, const char *fmt, struct tm *tm );
 
 bool dap_isstralnum(const char *c);
 size_t dap_strlen(const char *a_str);
+char* dap_strcat2(const char* s1, const char* s2);
 // compare a_str1 and a_str2
 int dap_strcmp(const char *a_str1, const char *a_str2);
 // compare a_n characters of a_str1 and a_str2
diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c
index f960159e16..a0e88234b2 100755
--- a/dap-sdk/core/src/dap_strfuncs.c
+++ b/dap-sdk/core/src/dap_strfuncs.c
@@ -33,6 +33,41 @@ bool dap_isstralnum(const char *c)
     return true;
 }
 
+/**
+ * @brief strcat two strings with new char array in result
+ * 
+ * @param s1 preallocated buffer with char string
+ * @param s2 char string
+ * @return char* 
+ */
+char* dap_strcat2(const char* s1, const char* s2)
+{
+  size_t size1 = 0;
+  size_t size2 = 0;
+  if (!s1)
+    size1 = 0;
+  else
+    size1 = strlen(s1);
+  if (!s2)
+    size2 = 0;
+  else
+    size2 = strlen(s2);
+    
+  char* result = malloc(size1 + size2 + 1);
+
+  if(result == NULL) 
+  {
+    exit(EXIT_FAILURE);
+  }
+
+  memcpy(result, s1, size1);
+  memcpy(result+size1, s2, size2);
+  free((void*)s1);
+  result[size1 + size2] = '\0';
+  return result;
+}
+
+
 
 /**
  * @brief s_strdigit
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 5de75f6190..cc1a2a0c75 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -302,12 +302,12 @@ int dap_chain_net_init()
             "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n"
         "net -net <chain net name> get status\n"
             "\tLook at current status\n"
-        "net -net <chain net name> stats tx [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n"
+        "net -net <chain net name> stats tx|tps [-from <From time>] [-to <To time>] [-prev_sec <Seconds>] \n"
             "\tTransactions statistics. Time format is <Year>-<Month>-<Day>_<Hours>:<Minutes>:<Seconds> or just <Seconds> \n"
         "net -net <chain net name> [-mode {update | all}] sync {all | gdb | chains}\n"
             "\tSyncronyze gdb, chains or everything\n"
             "\tMode \"update\" is by default when only new chains and gdb are updated. Mode \"all\" updates everything from zero\n"
-        "net -net <chain net name> link {list | add | del | info | establish}\n"
+        "net -net <chain net name> link {list | add | del | info | disconnect_all}\n"
             "\tList, add, del, dump or establish links\n"
         "net -net <chain net name> ca add {-cert <cert name> | -hash <cert hash>}\n"
             "\tAdd certificate to list of authority cetificates in GDB group\n"
@@ -1638,6 +1638,29 @@ void dap_chain_net_load_all()
     DAP_DELETE (l_net_dir_str);
 }
 
+dap_string_t* dap_cli_list_net()
+{
+    dap_chain_net_item_t * l_net_item, *l_net_item_tmp;
+    dap_string_t *l_string_ret = dap_string_new("");
+    dap_chain_net_t * l_net = NULL;
+    int l_net_i = 0;
+    dap_string_append(l_string_ret,"Available networks and chains:\n");
+    pthread_rwlock_rdlock(&g_net_items_rwlock);
+    HASH_ITER(hh, s_net_items, l_net_item, l_net_item_tmp){
+        l_net = l_net_item->chain_net;
+        dap_string_append_printf(l_string_ret, "\t%s:\n", l_net_item->name);
+        l_net_i++;
+
+        dap_chain_t * l_chain = l_net->pub.chains;
+        while (l_chain) {
+            dap_string_append_printf(l_string_ret, "\t\t%s\n", l_chain->name );
+            l_chain = l_chain->next;
+        }
+    }
+    pthread_rwlock_unlock(&g_net_items_rwlock);
+    return l_string_ret;
+}
+
 void s_set_reply_text_node_status(char **a_str_reply, dap_chain_net_t * a_net){
     char* l_node_address_text_block = NULL;
     dap_chain_node_addr_t l_cur_node_addr = { 0 };
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 702014929c..9ca432efac 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -1988,6 +1988,13 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch
 
     if((*a_net = dap_chain_net_by_name(l_net_str)) == NULL) { // Can't find such network
         dap_chain_node_cli_set_reply_text(a_str_reply, "%s can't find network \"%s\"", argv[0], l_net_str);
+        char l_str_to_reply_chain[500] = {0};
+        char *l_str_to_reply = NULL;
+        dap_sprintf(l_str_to_reply_chain, "%s can't find network \"%s\"\n", argv[0], l_net_str);
+        l_str_to_reply = dap_strcat2(l_str_to_reply,l_str_to_reply_chain);
+        dap_string_t* l_net_str = dap_cli_list_net();
+        l_str_to_reply = dap_strcat2(l_str_to_reply,l_net_str->str);
+        dap_chain_node_cli_set_reply_text(a_str_reply, l_str_to_reply);
         return -102;
     }
 
@@ -2000,7 +2007,20 @@ int dap_chain_node_cli_cmd_values_parse_net_chain(int *a_arg_index, int argc, ch
             if((*a_chain = dap_chain_net_get_chain_by_name(*a_net, l_chain_str)) == NULL) { // Can't find such chain
                 dap_chain_node_cli_set_reply_text(a_str_reply,
                         "%s requires parameter '-chain' to be valid chain name in chain net %s. Current chain %s is not valid",
+                char l_str_to_reply_chain[500] = {0};
+                char *l_str_to_reply = NULL;
+                dap_sprintf(l_str_to_reply_chain, "%s requires parameter '-chain' to be valid chain name in chain net %s. Current chain %s is not valid\n",
                         argv[0], l_net_str, l_chain_str);
+                l_str_to_reply = dap_strcat2(l_str_to_reply,l_str_to_reply_chain);
+                dap_chain_t * l_chain;
+                dap_chain_net_t * l_chain_net = *a_net;
+                l_str_to_reply = dap_strcat2(l_str_to_reply,"\nAvailable chains:\n");
+                DL_FOREACH(l_chain_net->pub.chains, l_chain){
+                        l_str_to_reply = dap_strcat2(l_str_to_reply,"\t");
+                        l_str_to_reply = dap_strcat2(l_str_to_reply,l_chain->name);
+                        l_str_to_reply = dap_strcat2(l_str_to_reply,"\n");
+                }
+                dap_chain_node_cli_set_reply_text(a_str_reply, l_str_to_reply);
                 return -103;
             }
         }
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 4e8d1438de..8e300c0fe4 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -124,6 +124,7 @@ dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id);
 uint16_t dap_chain_net_acl_idx_by_id(dap_chain_net_id_t a_id);
 dap_chain_net_id_t dap_chain_net_id_by_name( const char * a_name);
 dap_ledger_t * dap_chain_ledger_by_net_name( const char * a_net_name);
+dap_string_t* dap_cli_list_net();
 
 dap_chain_t * dap_chain_net_get_chain_by_name( dap_chain_net_t * l_net, const char * a_name);
 
-- 
GitLab