From 0783ba715d28b71d6c2c7fb8ea2df4ad0d5bb894 Mon Sep 17 00:00:00 2001
From: Aleksandr Lysikov <lysikov@inbox.ru>
Date: Mon, 29 Apr 2019 22:46:43 +0500
Subject: [PATCH] added hash table for services

---
 CMakeLists.txt             |   4 +-
 dap_chain_net_srv.c        | 116 ++++++++++++++++++++++++++++++++++---
 dap_chain_net_srv.h        |  44 +++-----------
 dap_chain_net_srv_common.c |  62 ++++++++++++++++++++
 dap_chain_net_srv_common.h |  44 ++++++++++++++
 5 files changed, 224 insertions(+), 46 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d3b84f..4ee838e 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,10 +11,12 @@ set(DAP_CHAIN_NET_SRV_HEADERS
         dap_chain_net_srv_common.h
     )
 
+
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_SRCS} ${DAP_CHAIN_NET_SRV_HEADERS})
 
 
-target_link_libraries(dap_chain_net_srv dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net )
+target_link_libraries(dap_chain_net_srv dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net)
+#target_link_libraries(dap_chain_net_srv dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net dap_server_http_db_auth)
 target_include_directories(dap_chain_net_srv INTERFACE .)
 
 set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
diff --git a/dap_chain_net_srv.c b/dap_chain_net_srv.c
index f1fec03..e5a6389 100755
--- a/dap_chain_net_srv.c
+++ b/dap_chain_net_srv.c
@@ -22,8 +22,11 @@
  along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "utlist.h"
+#include <pthread.h>
 
+#include "uthash.h"
+#include "utlist.h"
+#include "dap_list.h"
 #include "dap_chain_net_srv.h"
 
 #define LOG_TAG "chain_net_srv"
@@ -31,11 +34,22 @@
 size_t m_uid_count;
 dap_chain_net_srv_uid_t * m_uid;
 
+typedef struct service_list {
+    dap_chain_net_srv_uid_t uid;
+    dap_chain_net_srv_t * srv;
+    UT_hash_handle hh;
+} service_list_t;
+
+// list of active services
+static service_list_t *s_srv_list = NULL;
+// for separate access to s_srv_list
+static pthread_mutex_t s_srv_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /**
  * @brief dap_chain_net_srv_init
  * @return
  */
-int dap_chain_net_srv_init()
+int dap_chain_net_srv_init(void)
 {
     m_uid = NULL;
     m_uid_count = 0;
@@ -46,9 +60,11 @@ int dap_chain_net_srv_init()
 /**
  * @brief dap_chain_net_srv_deinit
  */
-void dap_chain_net_srv_deinit()
+void dap_chain_net_srv_deinit(void)
 {
+    // TODO Stop all services
 
+    dap_chain_net_srv_del_all();
 }
 
 /**
@@ -57,7 +73,49 @@ void dap_chain_net_srv_deinit()
  */
 void dap_chain_net_srv_add(dap_chain_net_srv_t * a_srv)
 {
+    service_list_t *l_sdata = NULL;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    HASH_FIND(hh, s_srv_list, &(a_srv->uid), sizeof(a_srv->uid), l_sdata);
+    if(l_sdata == NULL) {
+        l_sdata = DAP_NEW_Z(service_list_t);
+        memcpy(&l_sdata->uid, &a_srv->uid, sizeof(dap_chain_net_srv_uid_t));
+        l_sdata->srv = DAP_NEW(dap_chain_net_srv_t);
+        memcpy(&l_sdata->srv, a_srv, sizeof(dap_chain_net_srv_t));    ;
+        HASH_ADD(hh, s_srv_list, uid, sizeof(a_srv->uid), l_sdata);
+    }
+    pthread_mutex_unlock(&s_srv_list_mutex);
+}
 
+/**
+ * @brief dap_chain_net_srv_del
+ * @param a_srv
+ */
+void dap_chain_net_srv_del(dap_chain_net_srv_t * a_srv)
+{
+    service_list_t *l_sdata;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    HASH_FIND(hh, s_srv_list, a_srv, sizeof(dap_chain_net_srv_uid_t), l_sdata);
+    if(l_sdata) {
+        DAP_DELETE(l_sdata);
+        HASH_DEL(s_srv_list, l_sdata);
+    }
+    pthread_mutex_unlock(&s_srv_list_mutex);
+}
+
+/**
+ * @brief dap_chain_net_srv_del_all
+ * @param a_srv
+ */
+void dap_chain_net_srv_del_all(void)
+{
+    service_list_t *l_sdata, *l_sdata_tmp;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    HASH_ITER(hh, s_srv_list , l_sdata, l_sdata_tmp)
+    {
+        DAP_DELETE(l_sdata);
+        HASH_DEL(s_srv_list, l_sdata);
+    }
+    pthread_mutex_unlock(&s_srv_list_mutex);
 }
 
 /**
@@ -65,25 +123,65 @@ void dap_chain_net_srv_add(dap_chain_net_srv_t * a_srv)
  * @param a_uid
  * @return
  */
-dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t a_uid)
+dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t *a_uid)
 {
-
+    service_list_t *l_sdata = NULL;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    HASH_FIND(hh, s_srv_list, &a_uid, sizeof(dap_chain_net_srv_uid_t), l_sdata);
+    pthread_mutex_unlock(&s_srv_list_mutex);
+    return (l_sdata) ? l_sdata->srv : NULL;
 }
 
 /**
  * @brief dap_chain_net_srv_count
  * @return
  */
-const size_t dap_chain_net_srv_count()
+const size_t dap_chain_net_srv_count(void)
 {
-
+    size_t l_count = 0;
+    service_list_t *l_sdata, *l_sdata_tmp;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    HASH_ITER(hh, s_srv_list , l_sdata, l_sdata_tmp)
+    {
+        l_count++;
+    }
+    pthread_mutex_unlock(&s_srv_list_mutex);
+    return l_count;
 }
 
 /**
  * @brief dap_chain_net_srv_list
  * @return
  */
-const dap_chain_net_srv_uid_t * dap_chain_net_srv_list()
+const dap_chain_net_srv_uid_t * dap_chain_net_srv_list(void)
 {
-
+    static dap_chain_net_srv_uid_t *l_srv_uids = NULL;
+    static size_t l_count_last = 0;
+    size_t l_count_cur = 0;
+    dap_list_t *l_list = NULL;
+    service_list_t *l_sdata, *l_sdata_tmp;
+    pthread_mutex_lock(&s_srv_list_mutex);
+    // count the number of services and save them in list
+    HASH_ITER(hh, s_srv_list , l_sdata, l_sdata_tmp)
+    {
+        l_list = dap_list_append(l_list, l_sdata);
+        l_count_cur++;
+    }
+    // fill the output array
+    if(l_count_cur > 0) {
+        if(l_count_cur != l_count_last) {
+            DAP_DELETE(l_srv_uids);
+            l_srv_uids = DAP_NEW_SIZE(dap_chain_net_srv_uid_t, sizeof(dap_chain_net_srv_uid_t) * l_count_cur);
+        }
+        for(size_t i = 0; i < l_count_cur; i++) {
+            service_list_t *l_sdata = l_list->data;
+            memcpy(l_srv_uids + i, &l_sdata->uid, sizeof(dap_chain_net_srv_uid_t));
+        }
+    }
+    // save new number of services
+    l_count_last = l_count_cur;
+    pthread_mutex_unlock(&s_srv_list_mutex);
+    dap_list_free(l_list);
+    return l_srv_uids;
 }
+
diff --git a/dap_chain_net_srv.h b/dap_chain_net_srv.h
index bd9c5ea..64ff680 100755
--- a/dap_chain_net_srv.h
+++ b/dap_chain_net_srv.h
@@ -26,53 +26,25 @@
 #include "dap_chain_node_ctl.h"
 #include "dap_chain_net_srv_common.h"
 
-//Classes of services
-enum {
-    SERV_CLASS_ONCE = 1, // one-time service
-    SERV_CLASS_PERMANENT = 2
-};
-
-//Types of services
-enum {
-    SERV_ID_VPN = 1,
-};
-
 typedef struct dap_chain_net_srv
 {
     dap_chain_node_ctl_t * node;
     dap_chain_net_srv_uid_t uid; // Unique ID for service.
+    dap_chain_net_srv_abstract_t srv_common;
 
     void * _internal;
     void * _inhertor;
 } dap_chain_net_srv_t;
 
-typedef struct dap_chain_net_srv_abstract
-{
-    uint64_t proposal_id; // id trade proposal. Must be unique to the node.
-
-    uint8_t class; //Class of service
-    uint8_t type_id; //Type of service
-    union {
-        struct {
-            int bandwith;
-            int abuse_resistant;
-            int limit_bytes;
-        } vpn;
-        struct {
-            int value;
-        } other_srv;
-    } proposal_params;
 
-    uint64_t price; //  service price, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
-    uint8_t price_units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
-    char decription[128];
-} DAP_ALIGN_PACKED dap_chain_net_srv_abstract_t;
 
-int dap_chain_net_srv_init();
-void dap_chain_net_srv_deinit();
+int dap_chain_net_srv_init(void);
+void dap_chain_net_srv_deinit(void);
 
 void dap_chain_net_srv_add(dap_chain_net_srv_t * a_srv);
-dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t a_uid);
-const size_t dap_chain_net_srv_count();
-const dap_chain_net_srv_uid_t * dap_chain_net_srv_list();
+void dap_chain_net_srv_del(dap_chain_net_srv_t * a_srv);
+void dap_chain_net_srv_del_all(void);
+dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t *a_uid);
+const size_t dap_chain_net_srv_count(void);
+const dap_chain_net_srv_uid_t * dap_chain_net_srv_list(void);
 
diff --git a/dap_chain_net_srv_common.c b/dap_chain_net_srv_common.c
index e69de29..cd1709e 100755
--- a/dap_chain_net_srv_common.c
+++ b/dap_chain_net_srv_common.c
@@ -0,0 +1,62 @@
+#include <stdint.h>
+#include "rand/dap_rand.h"
+#include "dap_chain_net_srv_common.h"
+#include "dap_chain_datum_tx_items.h"
+#include "dap_chain_utxo.h"
+
+/**
+ * Generate unique id for service
+ */
+bool dap_chain_net_srv_gen_uid(dap_chain_net_srv_uid_t *a_srv)
+{
+    if(!a_srv)
+        return false;
+    randombytes(a_srv, sizeof(dap_chain_net_srv_uid_t));
+    return true;
+}
+
+/**
+ *
+ */
+uint64_t dap_chain_net_srv_client_auth(char *a_addr_base58, uint8_t *a_sign, size_t a_sign_size,
+        const dap_chain_net_srv_abstract_t **a_cond_out)
+{
+    dap_chain_addr_t *l_addr = (a_addr_base58) ? dap_chain_str_to_addr(a_addr_base58) : NULL;
+    dap_chain_tx_out_cond_t *l_tx_out_cond = NULL;
+
+    // Search all value in transactions with l_addr in 'out_cond' item
+    uint64_t l_value = 0;//!!!dap_chain_node_datum_tx_cache_get_out_cond_value(l_addr, &l_tx_out_cond);
+    DAP_DELETE(l_addr);
+    // not found transaction with l_addr in 'out_cond' item
+    if(!l_value)
+        return 0;
+
+    size_t l_pkey_size = 0;
+    size_t l_cond_size = 0;
+    uint8_t *l_cond = dap_chain_datum_tx_out_cond_item_get_pkey(l_tx_out_cond, &l_cond_size);
+    uint8_t *l_pkey = dap_chain_datum_tx_out_cond_item_get_cond(l_tx_out_cond, &l_pkey_size);
+
+    // create l_chain_sign for check a_sign
+    dap_chain_sign_t *l_chain_sign = DAP_NEW_Z_SIZE(dap_chain_sign_t,
+            sizeof(dap_chain_sign_t) + a_sign_size + l_pkey_size);
+    l_chain_sign->header.type = l_addr->sig_type;
+    l_chain_sign->header.sign_size = l_pkey_size;
+    l_chain_sign->header.sign_pkey_size = l_pkey_size;
+    // write serialized public key to dap_chain_sign_t
+    memcpy(l_chain_sign->pkey_n_sign, l_pkey, l_pkey_size);
+    // write serialized signature to dap_chain_sign_t
+    memcpy(l_chain_sign->pkey_n_sign + l_pkey_size, a_sign, a_sign_size);
+
+    // check signature
+    if(dap_chain_sign_verify(l_chain_sign, a_sign, a_sign_size) != 1) {
+        // invalid signature
+        return 0;
+    }
+
+    if(l_cond_size != sizeof(dap_chain_net_srv_abstract_t)) {
+        return 0;
+    }
+    if(a_cond_out)
+        *a_cond_out = (const dap_chain_net_srv_abstract_t*) l_cond;
+    return l_value;
+}
diff --git a/dap_chain_net_srv_common.h b/dap_chain_net_srv_common.h
index 5140363..ee68355 100755
--- a/dap_chain_net_srv_common.h
+++ b/dap_chain_net_srv_common.h
@@ -1,5 +1,6 @@
 #pragma once
 #include <stdint.h>
+#include <stdbool.h>
 #include "dap_common.h"
 #include "dap_math_ops.h"
 
@@ -13,3 +14,46 @@ typedef union{
     dap_uint128_t raw_ui128[1];
 #endif
 }  dap_chain_net_srv_uid_t;
+
+
+//Classes of services
+enum {
+    SERV_CLASS_ONCE = 1, // one-time service
+    SERV_CLASS_PERMANENT = 2
+};
+
+//Types of services
+enum {
+    SERV_ID_VPN = 1,
+};
+
+typedef struct dap_chain_net_srv_abstract
+{
+    uint64_t proposal_id; // id trade proposal. Must be unique to the node.
+
+    uint8_t class; //Class of service
+    uint8_t type_id; //Type of service
+    union {
+        struct {
+            int bandwith;
+            int abuse_resistant;
+            int limit_bytes;
+        } vpn;
+        /*struct {
+            int value;
+        } another_srv;*/
+    } proposal_params;
+
+    //size_t pub_key_data_size;
+    //void * pub_key_data;
+
+    uint64_t price; //  service price, for SERV_CLASS_ONCE ONCE for the whole service, for SERV_CLASS_PERMANENT  for one unit.
+    uint8_t price_units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT
+    char decription[128];
+} DAP_ALIGN_PACKED dap_chain_net_srv_abstract_t;
+
+// generate new dap_chain_net_srv_uid_t
+bool dap_chain_net_srv_gen_uid(dap_chain_net_srv_uid_t *a_srv);
+
+uint64_t dap_chain_net_srv_client_auth(char *a_addr_base58, uint8_t *a_sign, size_t a_sign_size,
+        const dap_chain_net_srv_abstract_t **a_cond_out);
-- 
GitLab