From 187da8a59d96472d86bc0ad77b097dd75f2207b4 Mon Sep 17 00:00:00 2001
From: Constantin Papizh <p_const@bk.ru>
Date: Wed, 18 Dec 2019 01:51:12 +0300
Subject: [PATCH] Reinterpreted vpn service concerned things

---
 dap_chain_net_srv_vpn.c     | 129 +++++++++++++++---------------------
 dap_chain_net_srv_vpn_cdb.c | 127 ++++++++++++++++++-----------------
 2 files changed, 117 insertions(+), 139 deletions(-)

diff --git a/dap_chain_net_srv_vpn.c b/dap_chain_net_srv_vpn.c
index 993ceee..66e9cdc 100755
--- a/dap_chain_net_srv_vpn.c
+++ b/dap_chain_net_srv_vpn.c
@@ -147,7 +147,6 @@ static void s_ch_packet_out(dap_stream_ch_t* ch, void* arg);
 
 static char *s_srv_vpn_addr = NULL, *s_srv_vpn_mask = NULL;
 
-
 static void s_update_limits(dap_stream_ch_t * a_ch ,
                            dap_chain_net_srv_stream_session_t * a_srv_session,
                            dap_chain_net_srv_usage_t * a_usage, size_t a_bytes);
@@ -184,101 +183,81 @@ int dap_chain_net_srv_vpn_init(dap_config_t * g_config)
         l_srv_vpn->parent = l_srv;
 
         uint16_t l_pricelist_count = 0;
-        char ** l_pricelist = dap_config_get_array_str(g_config,"srv_vpn","pricelist", &l_pricelist_count );
-        for ( uint16_t i = 0; i < l_pricelist_count; i++ ){
-            char * l_price_str = l_pricelist[i];
-            size_t l_price_length = strlen(l_price_str);
-            size_t l_iter = 0;
-            char * l_pos_old = l_price_str;
-            dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
-            for (char * l_pos = index(l_price_str,':');  ;  l_pos = index(l_pos+1,':') ){
-                if( l_iter == 0)
-                    break;
-
-                size_t l_parse_token_size =  l_pos?(size_t) (l_pos - l_pos_old)-1: l_price_length- (size_t)(l_pos_old - l_pricelist[i]) ;
-                char * l_parse_token = strndup(l_pos_old, l_parse_token_size);
-                if( l_parse_token_size ==0 ){
-                    log_it(L_ERROR, "Wrong price element size nil");
-                    DAP_DELETE(l_parse_token);
-                    break;
-                }
-                if ( l_iter == 0){
-                    l_price->net_name = strdup(l_parse_token);
+        l_srv->pricelist = NULL;
 
-                    l_price->net = dap_chain_net_by_name( l_price->net_name);
-                    if( ! l_price->net ){
-                        log_it(L_ERROR, "Error parse pricelist: can't find network \"%s\"", l_price->net_name);
-                        DAP_DELETE( l_price->net);
+        /* ! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data
+         * ! it also must NOT be freed within this module !
+         */
+        char **l_pricelist = dap_config_get_array_str(g_config, "srv_vpn", "pricelist", &l_pricelist_count); // must not be freed!
+        for (uint16_t i = 0; i < l_pricelist_count; i++) {
+            dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
+            short l_iter = 0;
+            char *l_ctx;
+            for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) {
+                //log_it(L_DEBUG, "Tokenizer: %s", l_price_token);
+                switch (l_iter) {
+                case 0:
+                    l_price->net_name = l_price_token;
+                    if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) {
+                        log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token);
                         DAP_DELETE(l_price);
-                        DAP_DELETE(l_parse_token);
                         break;
                     }
-                }else if (l_iter == 1){
-                    l_price->value_coins = atof( l_parse_token);
-                    l_price->value_datoshi =(uint64_t) dap_chain_coins_to_balance((long double)l_price->value_coins);
-                    if ( ! l_price->value_datoshi ){
-                        log_it(L_ERROR, "Error parse pricelist: text on 2nd position \"%s\" is not floating number", l_parse_token);
-                        DAP_DELETE( l_price->net);
+                    continue;
+                case 1:
+                    l_price->value_coins = atof(l_price_token);
+                    if (!(l_price->value_datoshi = (uint64_t)dap_chain_coins_to_balance((long double)l_price->value_coins))) {
+                        log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token);
+                        l_iter = 0;
                         DAP_DELETE(l_price);
-                        DAP_DELETE(l_parse_token);
                         break;
                     }
-                }else if (l_iter == 2){
-                    strncpy( l_price->token, l_parse_token, sizeof (l_price->token)-1);
-
-                }else if (l_iter == 3){
-                    l_price->units = strtoul( l_parse_token,NULL,10);
-                    if ( !l_price->units ){
-                        log_it(L_ERROR, "Error parse pricelist: text on 4th position \"%s\" is not unsigned integer", l_parse_token);
-                        DAP_DELETE( l_price->net);
+                    continue;
+                case 2:
+                    dap_stpcpy(l_price->token, l_price_token);
+                    continue;
+                case 3:
+                    l_price->units = strtoul(l_price_token, NULL, 10);
+                    if (!l_price->units) {
+                        log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token);
+                        l_iter = 0;
                         DAP_DELETE(l_price);
-                        DAP_DELETE(l_parse_token);
                         break;
                     }
-                }else if (l_iter == 4){
-                    if ( strcmp(l_parse_token,"SEC") == 0 ){
+                    continue;
+                case 4:
+                    if (!strcmp(l_price_token,      "SEC"))
                         l_price->units_uid.enm = SERV_UNIT_SEC;
-                    }else if ( strcmp(l_parse_token,"DAY") == 0 ){
+                    else if (!strcmp(l_price_token, "DAY"))
                         l_price->units_uid.enm = SERV_UNIT_DAY;
-                    }else if ( strcmp(l_parse_token,"MB") == 0 ){
+                    else if (!strcmp(l_price_token, "MB"))
                         l_price->units_uid.enm = SERV_UNIT_MB;
-                    }else {
-                        log_it(L_ERROR, "Error parse pricelist: wrong unit type \"%s\"", l_parse_token);
-                        DAP_DELETE( l_price->net);
+                    else {
+                        log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token);
+                        l_iter = 0;
                         DAP_DELETE(l_price);
-                        DAP_DELETE(l_parse_token);
                         break;
                     }
-                }else if (l_iter == 5){
-                    l_price->wallet = dap_chain_wallet_open( l_parse_token, dap_config_get_item_str_default(g_config,"resources","wallets_path",NULL) );
-                    if (! l_price->wallet ){
-                        log_it(L_ERROR, "Error parse pricelist: can't open wallet \"%s\"", l_parse_token);
-                        DAP_DELETE( l_price->net);
+                    continue;
+                case 5:
+                    if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) {
+                        log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token);
+                        l_iter = 0;
                         DAP_DELETE(l_price);
-                        DAP_DELETE(l_parse_token);
                         break;
                     }
-                }else{
-                    DAP_DELETE(l_parse_token);
+                    continue;
+                case 6:
+                    log_it(L_INFO, "Price item correct, added to service");
+                    DL_APPEND(l_srv->pricelist, l_price);
                     break;
-                }
-                l_iter++;
-                l_pos_old = l_pos;
-                if (! l_pos ){
-                    DAP_DELETE(l_parse_token);
+                default:
                     break;
                 }
+                log_it(L_DEBUG, "Done with price item %d", i);
+                break; // double break exits tokenizer loop and steps to next price item
             }
-            if( l_iter == 6){
-                log_it(L_NOTICE, "All price parsed well, added to service %s", l_price_str);
-                if (l_srv->pricelist)
-                    l_srv->pricelist->prev = l_price;
-                l_price->next =  l_srv->pricelist;
-                l_srv->pricelist = l_price;
-            }
-
         }
-
         return 0;
     }
     return -1;
@@ -291,10 +270,10 @@ void dap_chain_net_srv_vpn_deinit(void)
 {
     pthread_mutex_destroy(&s_sf_socks_mutex);
     pthread_cond_destroy(&s_sf_socks_cond);
-    free((char*) s_srv_vpn_addr);
-    free((char*) s_srv_vpn_mask);
+    DAP_DELETE(s_srv_vpn_addr);
+    DAP_DELETE(s_srv_vpn_mask);
     if(s_raw_server)
-        free(s_raw_server);
+        DAP_DELETE(s_raw_server);
 }
 
 /**
diff --git a/dap_chain_net_srv_vpn_cdb.c b/dap_chain_net_srv_vpn_cdb.c
index 3179ed3..9485bde 100644
--- a/dap_chain_net_srv_vpn_cdb.c
+++ b/dap_chain_net_srv_vpn_cdb.c
@@ -71,7 +71,7 @@ typedef struct tx_cond_template{
     long double value_coins;
     uint128_t value_datoshi;
 
-    char * token_ticker;
+    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
     char * net_name;
     dap_chain_net_t * net;
     dap_ledger_t * ledger;
@@ -129,11 +129,13 @@ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http)
                                                             "cdb_auth",
                                                             "tx_cond_create",
                                                             false)) {
-            log_it (L_DEBUG, "2791: tx_cond_create is true");
             // Parse tx cond templates
             size_t l_tx_cond_tpls_count = 0;
+
+            /* ! IMPORTANT ! This fetch is single-action and cannot be further reused, since it modifies the stored config data
+             * ! it also must NOT be freed within this module !
+             */
             char **l_tx_cond_tpls = dap_config_get_array_str(g_config, "cdb_auth", "tx_cond_templates", &l_tx_cond_tpls_count);
-            log_it (L_DEBUG, "2791: tx_cond_templates: %d", l_tx_cond_tpls_count);
             if (l_tx_cond_tpls_count == 0) {
                 log_it( L_ERROR, "No condition tpl, can't setup auth callback");
                 return -5;
@@ -141,74 +143,71 @@ int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http)
             db_auth_set_callbacks(s_auth_callback);
 
             for (size_t i = 0 ; i < l_tx_cond_tpls_count; i++) {
-                char *l_wallet_name     = NULL;
-                long double l_value     = 0.0L;
-                char *l_token_ticker    = NULL;
-                char *l_net_name        = NULL;
-                int l_step              = 0;
-                time_t l_min_time       = 0;
-                log_it (L_DEBUG, "2791: tx_cond: %s", l_tx_cond_tpls[i]);
+                tx_cond_template_t *l_tx_cond_template = DAP_NEW_Z(tx_cond_template_t);
 
                 // Parse template entries
+                short l_step = 0;
                 char *ctx;
-                for (char *l_tpl_token = strtok_r(l_tx_cond_tpls[i], ":", &ctx); l_tpl_token && l_step <= 4; l_tpl_token = strtok_r(NULL, ":", &ctx), ++l_step) {
-                    log_it (L_DEBUG, "2791: tx_cond_token: %s", l_tpl_token);
+                for (char *l_tpl_token = strtok_r(l_tx_cond_tpls[i], ":", &ctx); l_tpl_token || l_step == 5; l_tpl_token = strtok_r(NULL, ":", &ctx), ++l_step) {
                     switch (l_step) {
-                        case 0: l_wallet_name = l_tpl_token;                break;
-                        case 1: l_value = strtold( l_tpl_token, NULL);      break;
-                        case 2: l_min_time =(time_t) atoll(l_tpl_token);    break;
-                        case 3: l_token_ticker = l_tpl_token;               break;
-                        case 4: l_net_name = l_tpl_token;                   break;
-                        default: log_it(L_WARNING, "Too many ':' (%d) characters in condition template", l_step); break;
-                    }
-                }
-
-                // If all what we need is present
-                if (l_step <= 4) {
-                    log_it(L_ERROR, "Not enough elements in condition template: 5 needed, %d present", l_step);
-                    //assert(l_wallet_name && l_value > 0.0L && l_token_ticker && l_net_name && l_min_time);
-                    if (!l_wallet_name || l_value <= 0.0L || !l_token_ticker || !l_net_name || !l_min_time) {
-                        log_it(L_ERROR, "Condition template inconsistent");
+                    case 0:
+                        if(!(l_tx_cond_template->wallet = dap_chain_wallet_open(l_tpl_token, c_wallets_path))) {
+                            log_it(L_ERROR, "Can't open wallet \"%s\"", l_tpl_token);
+                            DAP_DELETE(l_tx_cond_template);
+                            break;
+                        }
+                        l_tx_cond_template->wallet_name = l_tpl_token;
+                        continue;
+                    case 1:
+                        if (!(l_tx_cond_template->value_coins = strtold(l_tpl_token, NULL))) {
+                            log_it(L_ERROR, "Error parsing tpl: text on 2nd position \"%s\" is not a number", l_tpl_token);
+                            DAP_DELETE(l_tx_cond_template->wallet);
+                            DAP_DELETE(l_tx_cond_template);
+                            l_step = 0;
+                            break;
+                        }
+                        l_tx_cond_template->value_datoshi = dap_chain_coins_to_balance(l_tx_cond_template->value_coins);
+                        continue;
+                    case 2:
+                        if (!(l_tx_cond_template->min_time = (time_t)atoll(l_tpl_token))) {
+                            log_it(L_ERROR, "Error parsing tpl: text on 3d position \"%s\" is not a number", l_tpl_token);
+                            DAP_DELETE(l_tx_cond_template->wallet);
+                            DAP_DELETE(l_tx_cond_template);
+                            l_step = 0;
+                            break;
+                        }
+                        continue;
+                    case 3:
+                        dap_stpcpy(l_tx_cond_template->token_ticker, l_tpl_token);
+                        continue;
+                    case 4:
+                        if (!(l_tx_cond_template->net = dap_chain_net_by_name(l_tpl_token))
+                                || !(l_tx_cond_template->ledger = dap_chain_ledger_by_net_name(l_tpl_token)))
+                        {
+                            log_it(L_ERROR, "Can't open network \"%s\" or ledger in it", l_tpl_token);
+                            DAP_DELETE(l_tx_cond_template->wallet);
+                            DAP_DELETE(l_tx_cond_template);
+                            l_step = 0;
+                            break;
+                        }
+                        l_tx_cond_template->net_name = l_tpl_token;
+                        continue;
+                    case 5:
+                        log_it(L_INFO, "Condition template correct, added to list");
+                        DL_APPEND(s_tx_cond_templates, l_tx_cond_template);
+                        break;
+                    default:
+                        break;
                     }
-                    continue;
+                    log_it(L_DEBUG, "Done with tpl item %d", i);
+                    break; // double break exits tokenizer loop and steps to next tpl item
                 }
-
-                // we create condition template
-                tx_cond_template_t *l_tx_cond_template = DAP_NEW_Z(tx_cond_template_t);
-
-                if(!(l_tx_cond_template->wallet = dap_chain_wallet_open(l_wallet_name, c_wallets_path))) {
-                    log_it(L_ERROR, "Can't open wallet \"%s\" for condition transaction template \"%s\"", l_wallet_name, l_tx_cond_tpls[i]);
-                    DAP_DELETE(l_tx_cond_template);
-                    continue;
-                }
-
-                if (!(l_tx_cond_template->net = dap_chain_net_by_name(l_net_name))) {
-                    log_it(L_ERROR, "Can't open network \"%s\" for condition transaction template \"%s\"", l_net_name, l_tx_cond_tpls[i]);
-                    DAP_DELETE(l_tx_cond_template->wallet);
-                    DAP_DELETE(l_tx_cond_template);
-                    continue;
-                }
-
-                if (!(l_tx_cond_template->ledger = dap_chain_ledger_by_net_name(l_net_name))) {
-                    log_it(L_ERROR, "Can't open ledger in network \"%s\" for condition transaction template \"%s\"", l_net_name, l_tx_cond_tpls[i]);
-                    DAP_DELETE(l_tx_cond_template->wallet);
-                    DAP_DELETE(l_tx_cond_template);
-                    continue;
-                }
-
-                l_tx_cond_template->wallet_name     = l_wallet_name;
-                l_tx_cond_template->net_name        = l_net_name;
-                l_tx_cond_template->min_time        = l_min_time;
-                l_tx_cond_template->value_coins     = l_value;
-                l_tx_cond_template->value_datoshi   = dap_chain_coins_to_balance (l_value);
-                l_tx_cond_template->token_ticker    = l_token_ticker;
-                DL_APPEND(s_tx_cond_templates, l_tx_cond_template);
             }
+            if (!s_tx_cond_templates) ret = -1;
+        } else {
+            log_it(L_INFO, "No conditional transactions, provide VPN service for free");
         }
     }
-
-    if (!s_tx_cond_templates)
-        ret = -1;
     return ret;
 }
 
@@ -246,8 +245,8 @@ static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg)
         l_client_key = dap_enc_key_deserealize(l_pkey_raw, l_pkey_raw_size);
     }
 
-    tx_cond_template_t *l_tpl, *l_tmp;
-    DL_FOREACH_SAFE(s_tx_cond_templates, l_tpl, l_tmp) {
+    tx_cond_template_t *l_tpl;
+    DL_FOREACH(s_tx_cond_templates, l_tpl) {
         size_t l_gdb_group_size = 0;
 
         // Try to load from gdb
-- 
GitLab