diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c
deleted file mode 100644
index 396971e1c3613580c893eae6b7a8d35fa59172b5..0000000000000000000000000000000000000000
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * CellFrame       https://cellframe.net
- * Sources         https://gitlab.demlabs.net/cellframe
- * Copyright  (c) 2017-2019
- * All rights reserved.
-
- This file is part of CellFrame SDK the open source project
-
-    CellFrame SDK is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    CellFrame SDK is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "utlist.h"
-#include "dap_common.h"
-#include "dap_config.h"
-#include "dap_enc_http.h"
-#include "dap_enc_base64.h"
-#include "dap_http.h"
-
-#include "dap_chain.h"
-#include "dap_chain_net.h"
-#include "dap_chain_ledger.h"
-#include "dap_chain_wallet.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_in_cond.h"
-#include "dap_chain_datum_tx_out_cond.h"
-#include "dap_chain_datum_tx_out.h"
-#include "dap_chain_datum_tx_pkey.h"
-#include "dap_chain_datum_tx_receipt.h"
-#include "dap_chain_datum_tx_sig.h"
-#include "dap_chain_global_db.h"
-
-#include "dap_chain_node_cli.h"
-
-#include "dap_chain_mempool.h"
-#include "dap_pkey.h"
-
-#include "dap_chain_net_srv_vpn.h"
-#include "dap_chain_net_srv_vpn_cdb.h"
-#include "dap_chain_net_srv_vpn_cdb_auth.h"
-#include "dap_chain_net_srv_vpn_cdb_server_list.h"
-
-
-#define LOG_TAG "dap_chain_net_srv_vpn_cdb"
-
-#define DB_URL "/db"
-#define NODELIST_URL "/nodelist"
-
-typedef struct tx_cond_template{
-    char * wallet_name;
-    dap_chain_wallet_t * wallet;
-
-    long double value_coins;
-    uint128_t value_datoshi;
-
-    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
-    char * net_name;
-    dap_chain_net_t * net;
-    dap_ledger_t * ledger;
-    time_t min_time; // Minimum time between transactions
-    struct tx_cond_template *prev, *next;
-} tx_cond_template_t;
-
-static tx_cond_template_t *s_tx_cond_templates = NULL;
-const char *c_wallets_path = NULL;
-
-static int s_cli_vpn_cdb(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply);
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_init
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http)
-{
-    int ret=0;
-    c_wallets_path = dap_chain_wallet_get_path(g_config);
-    if (dap_config_get_item_bool_default( g_config,
-                                                                "cdb",
-                                                                "servers_list_enabled",
-                                                                false)) {
-
-        if (dap_chain_net_srv_vpn_cdb_server_list_init() != 0) {
-            log_it(L_CRITICAL,"Can't init vpn servers list");
-            return -10;
-        }
-    }
-
-    dap_chain_node_cli_cmd_item_create ("vpn_cdb", s_cli_vpn_cdb, NULL, "VPN Central DataBase (CDB) commands",
-        "vpn_cdb user create --login <Login> --password <Password> [--first_name <First Name] [--last_name <Last Name>] [--email <Email>]"
-        "[--acive_days <Setup active day thats left for user >]\n"
-            "\tCreate user with login, password and some more optional fields\n\n"
-        "vpn_cdb user update --login <Login> [--password <Password>] [--first_name <First Name] [--last_name <Last Name>] [--email <Email>]"
-                             "[--active_days <Setup active days that left for user >]\n"
-            "\tUpdate existent user\n"
-        "vpn_cdb user delete --login <Login>\n"
-            "\tDelete user by login\n"
-        "vpn_cdb user show --login <Login>\n"
-            "\tShow user fields by login\n"
-        "vpn_cdb user check --login <Login> --password <Password>\n"
-            "\tCompare <Password> with stored in GDB for <Login>\n"
-        "vpn_cdb user list\n"
-            "\tShow all users\n"
-        "vpn_cdb serial generate -n <number of serial keys>] [-acive_days <active days that left for serial>]\n"
-            "\tGenerate new serial keys\n"
-        "vpn_cdb serial list [-n <How many show serial keys>] [-shift <How many skip serial keys>] [-activated_only|-inactive_only] [-nototal|-total_only]\n"
-            "\tShow serial keys\n"
-        "vpn_cdb serial update -serial <serial keys> -acive_days <active days that left for serial>\n"
-            "\tEdit serial key\n"
-        "vpn_cdb serial info -serial <serial keys>\n"
-            "\tInformation about serial key\n"
-        "vpn_cdb serial delete -serial <serial keys>\n"
-            "\tDelete serial key\n"
-        "vpn_cdb serial deactivate -serial <serial keys>\n"
-            "\tDeactivate serial key\n"
-                                        );
-
-    // Load all chain networks
-    if (dap_config_get_item_bool_default( g_config,
-                                                        "cdb",
-                                                        "servers_list_enabled",
-                                                        false)) {
-        dap_chain_net_srv_vpn_cdb_server_list_add_proc ( a_http, NODELIST_URL);
-    }
-    if (dap_config_get_item_bool_default( g_config,"cdb_auth","enabled",false) ){
-
-        ret = dap_chain_net_srv_vpn_cdb_auth_init(  dap_config_get_item_str_default(g_config,"cdb_auth","domain","cdb"),
-                                              dap_config_get_item_str_default(g_config,"cdb_auth","mode","passwd"),
-                                              dap_config_get_item_bool_default(g_config,"cdb_auth","registration_open",false));
-        if(ret<0)
-            return ret;
-        dap_chain_net_srv_vpn_cdb_auth_add_proc( a_http , DB_URL );
-
-        // Produce transaction for authorized users
-        if (dap_config_get_item_bool_default( g_config,
-                                                            "cdb_auth",
-                                                            "tx_cond_create",
-                                                            false)) {
-            // Parse tx cond templates
-            uint16_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);
-            if (l_tx_cond_tpls_count == 0) {
-                log_it( L_ERROR, "No condition tpl, can't setup auth callback");
-                return -5;
-            }
-
-            for (size_t i = 0 ; i < l_tx_cond_tpls_count; 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 == 5; l_tpl_token = strtok_r(NULL, ":", &ctx), ++l_step) {
-                    switch (l_step) {
-                    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;
-                    }
-                    log_it(L_DEBUG, "Done with tpl item %d", i);
-                    break; // double break exits tokenizer loop and steps to next tpl item
-                }
-            }
-            if (!s_tx_cond_templates) ret = -1;
-        } else {
-            log_it(L_INFO, "No conditional transactions, provide VPN service for free");
-        }
-    }
-    return ret;
-}
-
-static int s_cli_vpn_cdb(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply)
-{
-    const char *l_user_str = NULL;
-    const char *l_serial_add_param_str = NULL;
-    int l_arg_index = 1;
-    int l_ret = -1;
-
-    int l_user_pos = dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "user", &l_user_str);
-    int l_serial_pos = dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "serial", &l_serial_add_param_str);
-
-
-    // Selected 'user' subcommand
-    if ( l_user_str ){
-        l_ret = 0;
-        return dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user(l_user_str,l_arg_index,  a_argc,  a_argv,a_str_reply);
-    }
-    // Selected 'serial' subcoummand
-    else if(l_serial_add_param_str) {
-        l_ret = 0;
-        return dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(l_serial_add_param_str, l_arg_index, a_argc, a_argv, a_str_reply);
-    }
-    else {
-        if(l_user_pos || l_user_pos)
-            dap_chain_node_cli_set_reply_text(a_str_reply, "require additional subcommand, see 'help vpn_cdb'");
-        else
-            dap_chain_node_cli_set_reply_text(a_str_reply, "unknown subcommand, use 'user' or 'serial'", l_user_str);
-    }
-    return l_ret;
-}
-
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_deinit
- */
-void dap_chain_net_srv_vpn_cdb_deinit()
-{
-
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_after
- * @param a_delegate
- * @param a_login
- * @param a_pkey_b64
- */
-void dap_chain_net_srv_vpn_cdb_auth_after(enc_http_delegate_t* a_delegate, const char * a_login, const char * a_pkey_b64 )
-{
-#ifndef __ANDROID__
-
-    dap_enc_key_t *l_client_key = NULL;
-    byte_t *l_pkey_raw = NULL;
-    size_t l_pkey_raw_size = 0;
-    log_it( L_DEBUG, "Authorized, now need to create conditioned transaction if not present key_len=%d", dap_strlen( a_pkey_b64));
-    {
-        size_t l_pkey_b64_length = dap_strlen( a_pkey_b64);
-        l_pkey_raw = DAP_NEW_Z_SIZE(byte_t,l_pkey_b64_length);
-        memset(l_pkey_raw, 0, l_pkey_b64_length);
-        l_pkey_raw_size = dap_enc_base64_decode(a_pkey_b64, l_pkey_b64_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-        char *l_pkey_gdb_group =  dap_strdup_printf( "cdb.%s.pkey", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX);
-        log_it(L_DEBUG, "Pkey group '%s'", l_pkey_gdb_group);
-        dap_chain_global_db_gr_set( dap_strdup(a_login), l_pkey_raw, l_pkey_raw_size, l_pkey_gdb_group);
-
-        l_client_key = dap_enc_key_new(DAP_ENC_KEY_TYPE_SIG_TESLA);
-        int l_res = dap_enc_key_deserealize_pub_key(l_client_key, l_pkey_raw, l_pkey_raw_size);
-        // bad pkey
-        if(l_res){
-            log_it(L_WARNING, "dap_enc_key_deserealize_priv_key='%d'", l_res);
-            DAP_DELETE(l_pkey_raw);
-            l_pkey_raw_size = 0;
-            l_pkey_raw = NULL;
-        }
-        DAP_DELETE(l_pkey_gdb_group);
-    }
-
-    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
-        //char *l_tx_cond_gdb_group =  dap_strdup_printf( "%s.%s.tx_cond", l_tpl->net->pub.name, DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX);
-        char *l_tx_cond_gdb_group =  dap_strdup_printf( "cdb.%s.tx_cond", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX);
-        log_it(L_DEBUG, "Checkout group %s", l_tx_cond_gdb_group);
-        // get key for tx_cond
-        char *l_user_key;
-        {
-            dap_chain_hash_fast_t l_hash = { 0 };
-            char *l_key_hash_str = NULL;
-            if(dap_hash_fast(a_pkey_b64, dap_strlen(a_pkey_b64), &l_hash))
-                l_key_hash_str = dap_chain_hash_fast_to_str_new(&l_hash);
-            l_user_key = dap_strdup_printf("%s/%s", a_login, l_key_hash_str);
-            DAP_DELETE(l_key_hash_str);
-        }
-        log_it(L_DEBUG, "\ndbg l_user_key=%s\n", l_user_key);
-        dap_chain_hash_fast_t *l_tx_cond_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get(l_user_key, &l_gdb_group_size, l_tx_cond_gdb_group);
-
-        // Check for entry size
-        if (l_gdb_group_size && l_gdb_group_size != sizeof(dap_chain_hash_fast_t)) {
-            log_it(L_ERROR, "Wrong size of tx condition on database (%zd but expected %zd), may be old entry",
-                   l_gdb_group_size, sizeof(dap_chain_hash_fast_t));
-        }
-
-        time_t l_tx_cond_ts = 0;
-        // If loaded lets check is it spent or not
-        if ( l_tx_cond_hash ){
-            log_it(L_DEBUG, "2791: Search for unspent tx, net %s", l_tpl->net_name);
-            dap_chain_datum_tx_t *l_tx = dap_chain_net_get_tx_by_hash(l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET_UNSPENT);
-            if ( !l_tx ){ // If not found - all outs are used. Create new one
-                // pass all chains
-                l_tx = dap_chain_net_get_tx_by_hash(l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET);
-                DAP_DELETE(l_tx_cond_hash);
-                l_tx_cond_hash = NULL;
-                if ( l_tx ){
-                    l_tx_cond_ts =(time_t) l_tx->header.ts_created;
-                    log_it(L_DEBUG, "2791: got some tx, created %d", l_tx->header.ts_created);
-                }
-            }
-        }
-
-        // Try to create condition
-        if (! l_tx_cond_hash ) {
-            dap_chain_wallet_t *l_wallet_from = l_tpl->wallet;
-            log_it(L_DEBUG, "Create tx from wallet %s", l_wallet_from->name);
-            dap_enc_key_t *l_key_from = dap_chain_wallet_get_key(l_wallet_from, 0);
-
-
-            //dap_chain_cell_id_t *xccell = dap_chain_net_get_cur_cell(l_tpl->net);
-            //uint64_t uint64 =dap_chain_net_get_cur_cell(l_tpl->net)->uint64;
-
-
-            // where to take coins for service
-            dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(l_wallet_from, l_tpl->net->pub.id);
-            dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = SERV_UNIT_SEC };
-            dap_chain_net_srv_uid_t l_srv_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID };
-            l_tx_cond_hash = dap_chain_proc_tx_create_cond(l_tpl->net, l_key_from, l_client_key, l_addr_from, l_tpl->token_ticker,
-                                                       (uint64_t) l_tpl->value_datoshi, 0, l_price_unit, l_srv_uid, 0, l_pkey_raw, l_pkey_raw_size);
-            char *l_addr_from_str = dap_chain_addr_to_str( l_addr_from );
-            DAP_DELETE( l_addr_from);
-            if (!l_tx_cond_hash) {
-                log_it(L_ERROR, "Can't create condition for user");
-            } else {
-                // save transaction for login
-                dap_chain_global_db_gr_set(l_user_key, l_tx_cond_hash, sizeof(dap_chain_hash_fast_t), l_tx_cond_gdb_group);
-                log_it(L_NOTICE, "User \"%s\": created conditioned transaction from %s(%s) on "
-                                , a_login, l_tpl->wallet_name, l_addr_from_str);
-            }
-            DAP_DELETE( l_addr_from_str );
-        }
-        DAP_DELETE(l_user_key);
-        // dbg
-        //dap_ledger_t * l_ledger = dap_chain_ledger_by_net_name( l_tpl->net->pub.name);
-        //dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_hash( l_ledger, l_tx_cond_hash);
-
-        // If we loaded or created hash
-        if( l_tx_cond_hash ){
-            char * l_tx_cond_hash_str = dap_chain_hash_fast_to_str_new(l_tx_cond_hash);
-            enc_http_reply_f(a_delegate,"\t<tx_cond_tpl>\n");
-            //enc_http_reply_f(a_delegate,"\t\t<net>%s</net>\n",l_tpl->net_name);
-            enc_http_reply_f(a_delegate,"\t\t<net>0x%x</net>\n",l_tpl->net->pub.id.uint64);
-            enc_http_reply_f(a_delegate,"\t\t<token>%s</token>\n",l_tpl->token_ticker);
-            enc_http_reply_f(a_delegate,"\t\t<tx_cond>%s</tx_cond>\n",l_tx_cond_hash_str);
-            enc_http_reply_f(a_delegate,"\t</tx_cond_tpl>\n");
-            DAP_DELETE(l_tx_cond_hash);
-            DAP_DELETE(l_tx_cond_hash_str);
-        }
-
-        DAP_DELETE(l_tx_cond_gdb_group);
-    }
-    if (l_client_key)
-        dap_enc_key_delete(l_client_key);
-#endif
-}
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c
deleted file mode 100644
index 22b2e01e38e2be6f84d9635070fc99ecd4a054f0..0000000000000000000000000000000000000000
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c
+++ /dev/null
@@ -1,1529 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * CellFrame       https://cellframe.net
- * Sources         https://gitlab.demlabs.net/cellframe
- * Copyright  (c) 2017-2020
- * All rights reserved.
-
- This file is part of CellFrame SDK the open source project
-
-    CellFrame SDK is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    CellFrame SDK is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/wait.h>
-#include <rand/dap_rand.h>
-
-#include <time.h>
-
-#include "dap_common.h"
-#include "dap_string.h"
-#include "dap_strfuncs.h"
-#include "dap_file_utils.h"
-#include "dap_client_remote.h"
-
-#include "dap_http.h"
-#include "dap_http_client.h"
-#include "dap_http_simple.h"
-
-#include "dap_enc.h"
-#include "dap_enc_key.h"
-#include "dap_enc_ks.h"
-#include "dap_enc_http.h"
-#include "dap_enc_base64.h"
-#include "dap_server.h"
-
-#include "dap_chain_node_cli.h"
-#include "dap_chain_global_db.h"
-
-#include "http_status_code.h"
-
-#include "dap_chain_net_srv_vpn_cdb.h"
-#include "dap_chain_net_srv_vpn_cdb_auth.h"
-
-#define LOG_TAG "dap_chain_net_srv_vpn_cdb_auth"
-
-#define OP_CODE_LOGIN_INCORRECT_PSWD "0xf2"
-#define OP_CODE_LOGIN_INCORRECT_SIGN "0xf2"
-#define OP_CODE_NOT_FOUND_LOGIN_IN_DB "0xf3"
-#define OP_CODE_SUBSCRIBE_EXPIRIED "0xf4"
-#define OP_CODE_INCORRECT_SYMOLS "0xf6"
-#define OP_CODE_LOGIN_INACTIVE  "0xf7"
-#define OP_CODE_SERIAL_ACTIVED  "0xf8"
-
-
-dap_enc_http_callback_t s_callback_success = NULL;
-
-static char * s_domain = NULL;
-static char * s_group_users = NULL;
-static char * s_group_serials = NULL;
-static char * s_group_serials_activated = NULL;
-
-static char * s_group_password = NULL;
-static char * s_group_first_name = NULL;
-static char * s_group_last_name = NULL;
-static char * s_group_email = NULL;
-static char * s_group_ts_updated = NULL;
-static char * s_group_ts_last_login = NULL;
-static char * s_group_cookies = NULL;
-static char * s_group_cookie = NULL;
-static char * s_group_ts_active_till = NULL;
-
-static char * s_salt_str = "Ijg24GAS56h3hg7hj245b";
-
-static bool s_is_registration_open = false;
-static bool s_mode_passwd = true;
-
-// hook paths
-static char *s_hook_user_create = NULL;
-static char *s_hook_user_login = NULL;
-static char *s_hook_user_update = NULL;
-static char *s_hook_user_delete = NULL;
-
-static char *s_hook_serial_generate = NULL;
-static char *s_hook_serial_login = NULL;
-static char *s_hook_serial_activate = NULL;
-static char *s_hook_serial_update = NULL;
-static char *s_hook_serial_delete = NULL;
-static char *s_hook_serial_deactivate = NULL;
-
-static int s_input_validation(const char * str);
-static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg);
-static void s_http_enc_proc_key(enc_http_delegate_t *a_delegate, void * a_arg);
-static void s_http_proc(dap_http_simple_t *a_http_simple, void * arg );
-
-static char *register_hook(const char *a_cfg_name)
-{
-    char *l_hook_path_ret = NULL;
-    const char *l_hook_path = dap_config_get_item_str(g_config, "cdb_auth", a_cfg_name);
-    if(dap_file_test(l_hook_path))
-        l_hook_path_ret = dap_strdup(l_hook_path);
-    else if(l_hook_path) {
-        log_it(L_WARNING, "file for %s = %s not found", a_cfg_name, l_hook_path);
-    }
-    return l_hook_path_ret;
-}
-
-static int run_hook(char *a_hook_path, char *a_format, ...)
-{
-    if(!a_hook_path)
-        return -1;
-    char *l_params = NULL;
-    va_list l_args;
-    va_start(l_args, a_format);
-    l_params = dap_strdup_vprintf(a_format, l_args);
-    va_end(l_args);
-    char *l_cmd = dap_strdup_printf("%s %s", a_hook_path, l_params);
-    int l_ret = system(l_cmd);
-    DAP_DELETE(l_params);
-    DAP_DELETE(l_cmd);
-    return l_ret;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_init
- * @param a_domain
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_init (const char * a_domain, const char * a_mode, bool a_is_registration_open)
-{
-    s_is_registration_open = a_is_registration_open;
-
-    s_domain = dap_strdup(a_domain);
-
-    // Prefix for gdb groups
-    s_group_users = dap_strdup_printf("cdb.%s.users",s_domain);
-    s_group_serials = dap_strdup_printf("cdb.%s.serials",s_domain);
-    s_group_serials_activated = dap_strdup_printf("cdb.%s.serials_activated",s_domain);
-
-    // Cookie -> login
-    s_group_cookies = dap_strdup_printf("cdb.%s.cookies",s_domain);
-
-    // mode: passwd or serial
-    if(!dap_strcmp(a_mode, "serial"))
-        s_mode_passwd = false;
-    else if(!dap_strcmp(a_mode, "passwd"))
-        s_mode_passwd = true;
-    else{
-        log_it( L_ERROR, "Unknown cdb mode=%s", a_mode);
-        return -1;
-    }
-
-    // Login -> Password, First Name, Last Name, Email, Cookie,Timestamp Last Update, Timestamp Last Login
-    s_group_password = dap_strdup_printf("%s.password",s_group_users);
-    s_group_first_name = dap_strdup_printf("%s.first_name",s_group_users);
-    s_group_last_name = dap_strdup_printf("%s.last_name",s_group_users);
-    s_group_email = dap_strdup_printf("%s.email",s_group_users);
-    s_group_cookie  = dap_strdup_printf("%s.cookie",s_group_users);
-    s_group_ts_updated = dap_strdup_printf("%s.ts_updated",s_group_users);
-    s_group_ts_last_login = dap_strdup_printf("%s.ts_last_login",s_group_users);
-    s_group_ts_active_till = dap_strdup_printf("%s.ts_active_till",s_group_users);
-
-    // load hook paths
-    s_hook_user_create = register_hook("hook_user_create");
-    s_hook_user_login = register_hook("hook_user_login");
-    s_hook_user_update = register_hook("hook_user_update");
-    s_hook_user_delete = register_hook("hook_user_delete");
-
-    s_hook_serial_generate = register_hook("hook_serial_generate");
-    s_hook_serial_login = register_hook("hook_serial_login");
-    s_hook_serial_activate = register_hook("hook_serial_activate");
-    s_hook_serial_update = register_hook("hook_serial_update");
-    s_hook_serial_delete = register_hook("hook_serial_delete");
-    s_hook_serial_deactivate = register_hook("hook_serial_deactivate");
-    return 0;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_deinit
- */
-void dap_chain_net_srv_vpn_cdb_auth_deinit()
-{
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_set_callback
- * @param a_callback_success
- */
-void dap_chain_net_srv_vpn_cdb_auth_set_callback(dap_enc_http_callback_t a_callback_success)
-{
-    s_callback_success = a_callback_success;
-}
-
-/*
- * Convert XXXXXXXXXXXXXXXX -> XXXX-XXXX-XXXX-XXXX
- */
-static char* make_fullserial(const char * a_serial)
-{
-    if(dap_strlen(a_serial)!=16)
-        return dap_strdup(a_serial);
-    return dap_strdup_printf("%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c",
-            a_serial[0], a_serial[1], a_serial[2], a_serial[3],
-            a_serial[4], a_serial[5], a_serial[6], a_serial[7],
-            a_serial[8], a_serial[9], a_serial[10], a_serial[11],
-            a_serial[12], a_serial[13], a_serial[14], a_serial[15]
-            );
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_check_password
- * @param a_login
- * @param a_password
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_check_login(const char * a_login, const char * a_password)
-{
-    int l_ret;
-
-    size_t l_tmp_size=0;
-    dap_chain_hash_fast_t *l_gdb_password_hash;
-    if ( (l_gdb_password_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get (
-             a_login,&l_tmp_size  ,s_group_password ) ) ==NULL ){
-        // No user in database
-        return -1;
-    }
-
-    char * l_hash_str = dap_strdup_printf("%s%s",a_password, s_salt_str );
-    dap_chain_hash_fast_t l_password_hash = {0};
-    dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), &l_password_hash );
-    DAP_DELETE(l_hash_str);
-
-    l_ret = (memcmp(&l_password_hash, l_gdb_password_hash,sizeof (l_password_hash) ) == 0)? 0: -2;
-    DAP_DELETE(l_gdb_password_hash);
-
-    // if password check passed lets see is it active or not
-    if ( l_ret == 0){
-        time_t *l_ts_active_till= (time_t*) dap_chain_global_db_gr_get( a_login, &l_tmp_size, s_group_ts_active_till );
-        if ( l_ts_active_till ){
-            if ( *l_ts_active_till < time(NULL) )
-                l_ret = -4;
-        }else
-            l_ret = -3;
-    }
-    return l_ret;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_activate_serial
- * @param a_login
- * @param a_password
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_activate_serial(const char * a_serial_raw, const char * a_serial, const char * a_sign, const char * a_pkey)
-{
-    int l_ret = -1;
-    if(!a_sign || !a_pkey)
-        return -2;//OP_CODE_LOGIN_INCORRECT_SIGN
-    dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(a_serial, NULL);
-    // not found
-    if(!l_serial_key)
-        return -1;//OP_CODE_NOT_FOUND_LOGIN_IN_DB
-    // already activated
-    if(l_serial_key->header.activated) {
-        l_ret = 0;// OK
-    }
-    else {
-        // check sign
-        int l_res = 0;
-        byte_t *l_pkey_raw = NULL;
-        size_t l_pkey_raw_size = 0;
-        dap_enc_key_type_t l_key_type;
-        {
-            // verify sign
-            byte_t *l_sign_raw = NULL;
-            size_t l_sign_length = dap_strlen(a_sign);
-            l_sign_raw = DAP_NEW_Z_SIZE(byte_t, l_sign_length * 2);
-            size_t l_sign_raw_size = dap_enc_base64_decode(a_sign, l_sign_length, l_sign_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-            dap_sign_t *l_sign = (dap_sign_t*) l_sign_raw; //dap_sign_pack(l_client_key, l_sign_raw, l_sign_raw_size, l_pkey_raw, l_pkey_length);
-            //get key type for pkey
-            dap_sign_type_t l_chain_sign_type;
-            l_chain_sign_type.raw = l_sign_raw_size > 0 ? l_sign->header.type.raw : SIG_TYPE_NULL;
-            l_key_type =  dap_sign_type_to_key_type(l_chain_sign_type);
-            size_t l_serial_len = dap_strlen(a_serial_raw);
-            l_res = dap_sign_verify(l_sign, a_serial_raw, l_serial_len);
-            if(!l_res){
-                DAP_DELETE(l_sign_raw);
-                return -2;//OP_CODE_LOGIN_INCORRECT_SIGN
-            }
-
-            // deserialize pkey
-            dap_enc_key_t *l_client_key = NULL;
-            size_t l_pkey_length = dap_strlen(a_pkey);
-            l_pkey_raw = DAP_NEW_Z_SIZE(byte_t, l_pkey_length);
-            memset(l_pkey_raw, 0, l_pkey_length);
-            l_pkey_raw_size = dap_enc_base64_decode(a_pkey, l_pkey_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE);
-            l_client_key = dap_enc_key_new(l_key_type); //DAP_ENC_KEY_TYPE_SIG_TESLA
-            l_res = dap_enc_key_deserealize_pub_key(l_client_key, l_pkey_raw, l_pkey_raw_size);
-            // pkey from sign
-            size_t l_pkey_sign_size = 0;
-            uint8_t *l_pkey_sign = dap_sign_get_pkey(l_sign, &l_pkey_sign_size);
-            // activate serial key
-            if(l_pkey_sign_size == l_pkey_raw_size && !memcmp(l_pkey_sign, l_pkey_raw, l_pkey_sign_size)) {
-                // added pkey to serial
-                l_serial_key->header.ext_size = l_pkey_raw_size;
-                l_serial_key = DAP_REALLOC(l_serial_key, dap_serial_key_len(l_serial_key));
-                l_serial_key->header.activated = time(NULL);
-                if(l_serial_key->header.license_length)
-                    l_serial_key->header.expired = l_serial_key->header.activated + l_serial_key->header.license_length;
-                l_serial_key->header.pkey_type = l_key_type;
-                memcpy(l_serial_key->ext, l_pkey_raw, l_pkey_raw_size);
-                // save updated serial
-                if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key,
-                        dap_serial_key_len(l_serial_key),
-                        s_group_serials_activated)) {
-                    dap_chain_global_db_gr_del(l_serial_key->header.serial, s_group_serials);
-                    // save gdb
-                    dap_chain_global_db_flush();
-                    l_ret = 0; // OK
-                }
-            }
-            // bad pkey
-            else
-                l_ret = -2;//OP_CODE_LOGIN_INCORRECT_SIGN
-            DAP_DELETE(l_sign_raw);
-        }
-        DAP_DELETE(l_pkey_raw);
-    }
-    DAP_DELETE(l_serial_key);
-    return l_ret;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_check_password
- * @param a_login
- * @param a_password
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_check_serial(const char * a_serial, const char * a_pkey_b64)
-{
-    int l_ret = 0;
-    dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(a_serial, NULL);
-    // not found
-    if(!l_serial_key)
-        return -1;
-    // inactive serial key
-    if(!l_serial_key->header.activated) {
-        l_ret = -3;
-    }
-    // check time expired, if expired=0, then the time never expires
-    else if(l_serial_key->header.expired) {
-        if((l_serial_key->header.expired) < time(NULL))
-            l_ret = -4;
-    }
-    if(!l_ret) {
-        // check pkey
-        dap_enc_key_t *l_client_key = NULL;
-        size_t l_pkey_length = dap_strlen(a_pkey_b64);
-        byte_t *l_pkey_raw = DAP_NEW_Z_SIZE(byte_t, l_pkey_length);
-        memset(l_pkey_raw, 0, l_pkey_length);
-        size_t l_pkey_raw_size = dap_enc_base64_decode(a_pkey_b64, l_pkey_length, l_pkey_raw,
-                DAP_ENC_DATA_TYPE_B64_URLSAFE);
-        // pkey from sign
-        size_t l_pkey_sign_size = l_serial_key->header.ext_size;
-        uint8_t *l_pkey_sign = l_serial_key->ext;
-        // compare pkeys
-        if(l_pkey_sign_size != l_pkey_raw_size || memcmp(l_pkey_sign, l_pkey_raw, l_pkey_sign_size)) {
-            l_ret = -2;
-        }
-        DAP_DELETE(l_pkey_raw);
-    }
-    DAP_DELETE(l_serial_key);
-    return l_ret;
-}
-
-/**
- * @brief s_input_validation
- * @param str
- * @return
- */
-static int s_input_validation(const char * str)
-{
-        // The compiler will stack "multiple" "strings" "end" "to" "end"
-        // into "multiplestringsendtoend", so we don't need one giant line.
-        static const char *nospecial="0123456789"
-                "abcdefghijklmnopqrstuvwxyz"
-                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                ".=@?_!#$%-";// /+
-        while(*str) // Loop until (*url) == 0.  (*url) is about equivalent to url[0].
-        {
-                // Can we find the character at *url in the string 'nospecial'?
-                // If not, it's a special character and we should return 0.
-                if(strchr(nospecial, *str) == NULL){
-                    return(0);
-                }
-                str++; // Jump to the next character.  Adding one to a pointer moves it ahead one element.
-        }
-
-        return(1); // Return 1 for success.
-}
-
-/**
- * Generate serial number like xxx-xxx-xxx
- * without symbols 0,1,L,I,O
- * a_group_sepa may be NULL
- */
-static char* generate_serial(int a_group_count, int a_group_len, const char *a_group_sepa)
-{
-    size_t l_group_sepa_len = a_group_sepa ? strlen(a_group_sepa) : 0;
-    char *l_serial = DAP_NEW_Z_SIZE(char, a_group_count * (a_group_len + l_group_sepa_len));
-    int l_serial_pos = 0;
-    for(int l_group_count = 0; l_group_count < a_group_count; l_group_count++) {
-        for(int l_group_len = 0; l_group_len < a_group_len; l_group_len++) {
-            uint32_t l_max_len = 'Z' - 'A' + 5; //['Z' - 'A' - 3]alpha + [10 - 2]digit
-            uint32_t l_value = random_uint32_t(l_max_len);
-            char l_sym;
-            if(l_value < 8)
-                l_sym = '2' + l_value;
-            // replace unused characters I,O,L
-            else if(l_value == 'I' - 'A' + 8)
-                l_sym = 'X';
-            else if(l_value == 'L' - 'A' + 8)
-                l_sym = 'Y';
-            else if(l_value == 'O' - 'A' + 8)
-                l_sym = 'Z';
-            else
-                l_sym = 'A' + l_value - 8;
-            l_serial[l_serial_pos] = l_sym;
-            l_serial_pos++;
-        }
-        // copy separator to serial
-        if(l_group_sepa_len && l_group_count < a_group_count - 1) {
-            dap_stpcpy(l_serial + l_serial_pos, a_group_sepa);
-            l_serial_pos += l_group_sepa_len;
-        }
-    }
-    return l_serial;
-}
-
-
-size_t dap_serial_key_len(dap_serial_key_t *a_serial_key)
-{
-    if(!a_serial_key)
-        return 0;
-    return sizeof(dap_serial_key_t) + a_serial_key->header.ext_size;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_get_serial_param
- * @param a_serial_str
- * @param a_group_out
- * @return
- */
-dap_serial_key_t* dap_chain_net_srv_vpn_cdb_auth_get_serial_param(const char *a_serial_str, const char **a_group_out)
-{
-    const char *l_group_out = s_group_serials_activated;
-    if(!a_serial_str)
-        return NULL;
-    size_t l_serial_data_len = 0;
-    dap_serial_key_t *l_serial_key = (dap_serial_key_t*)dap_chain_global_db_gr_get(a_serial_str, &l_serial_data_len, s_group_serials_activated);
-    if(!l_serial_key){
-        l_serial_key = (dap_serial_key_t*)dap_chain_global_db_gr_get(a_serial_str, &l_serial_data_len, s_group_serials);
-        l_group_out = s_group_serials;
-    }
-    if(l_serial_data_len>=sizeof(dap_serial_key_t)){
-        if(a_group_out)
-            *a_group_out = l_group_out;
-        return l_serial_key;
-    }
-    DAP_DELETE(l_serial_key);
-    return NULL;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial
- * @param a_serial_str
- * @param a_arg_index
- * @param a_argc
- * @param a_argv
- * @param a_str_reply
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_serial(const char *a_serial_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply)
-{
-    int l_ret = 0;
-    // Command 'serial list'
-    if(!dap_strcmp(a_serial_str, "list")) {
-        const char * l_serial_count_str = NULL;
-        const char * l_serial_shift_str = NULL;
-        int l_serial_nototal = dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-nototal", NULL);
-        int l_serial_total_only = dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-total_only", NULL);
-        int l_serial_show_activated_only = dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-activated_only", NULL);
-        int l_serial_show_inactive_only = dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-inactive_only", NULL);
-        bool l_serial_show_all =  !l_serial_show_activated_only && !l_serial_show_inactive_only ? true : false;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-n", &l_serial_count_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-shift", &l_serial_shift_str);
-
-        if(l_serial_nototal && l_serial_total_only){
-            dap_chain_node_cli_set_reply_text(a_str_reply, "use only one option '-nototal' or '-total_only'");
-            return -1;
-        }
-        if(l_serial_show_activated_only && l_serial_show_inactive_only){
-            dap_chain_node_cli_set_reply_text(a_str_reply, "use only one option '-activated_only' or '-inactive_only'");
-            return -1;
-        }
-        long long l_serial_count_tmp = l_serial_count_str ? strtoll(l_serial_count_str, NULL, 10) : 0;
-        long long l_serial_shift_tmp = l_serial_shift_str ? strtoll(l_serial_shift_str, NULL, 10) : 0;
-        //size_t l_serial_shift = l_serial_shift_str ? strtoll(l_serial_shift_str, NULL, 10)+1 : 1;
-        //size_t l_total = dap_chain_global_db_driver_count(s_group_serials, l_serial_shift);
-        //l_serial_count = l_serial_count ? min(l_serial_count, l_total - l_serial_shift) : l_total;
-        size_t l_serial_count_noactivated = 0;
-        size_t l_serial_count_activated = 0;
-        // read inactive serials
-        dap_store_obj_t *l_obj = l_serial_show_inactive_only || l_serial_show_all ? dap_chain_global_db_driver_cond_read(s_group_serials, 0, &l_serial_count_noactivated) : NULL;
-        // read activated serials
-        dap_store_obj_t *l_obj_activated = l_serial_show_activated_only || l_serial_show_all ? dap_chain_global_db_driver_cond_read(s_group_serials_activated, 0, &l_serial_count_activated) : NULL;
-        size_t l_total = l_serial_count_noactivated + l_serial_count_activated;
-        size_t l_serial_count = l_serial_count_tmp > 0 ? l_serial_count_tmp : (!l_serial_count_tmp ? l_total : 0);
-        size_t l_serial_shift = l_serial_shift_tmp > 0 ? l_serial_shift_tmp : 0;
-        if(l_serial_count > 0) {
-            dap_string_t *l_keys = dap_string_new("");
-            if(!l_serial_total_only) {
-                l_keys =  l_serial_count > 1 ? dap_string_append(l_keys, "serial keys:\n") : dap_string_append(l_keys, "serial key: ");
-            }
-            size_t l_total_actual = 0;
-            for(size_t i = 0; i < l_serial_count_noactivated; i++) {
-                if((l_obj + i)->value_len < sizeof(dap_serial_key_t))
-                    continue;
-                if(l_serial_count > 0 && l_total_actual >= l_serial_count)
-                    break;
-                dap_serial_key_t *l_serial = (dap_serial_key_t*) (l_obj + i)->value;
-                if(l_serial_shift > 0)
-                    l_serial_shift--;
-                else {
-                    if(!l_serial_total_only) {
-                        dap_string_append(l_keys, l_serial->header.serial);
-                        dap_string_append(l_keys, " inactive");
-                        //if(i < l_serial_count - 1)
-                        dap_string_append(l_keys, "\n");
-                    }
-                    l_total_actual++;
-                }
-            }
-            for(size_t i = 0; i < l_serial_count_activated; i++) {
-                if((l_obj_activated + i)->value_len < sizeof(dap_serial_key_t))
-                    continue;
-                dap_serial_key_t *l_serial = (dap_serial_key_t*) (l_obj_activated + i)->value;
-                if(l_serial_count > 0 && l_total_actual >= l_serial_count)
-                    break;
-                if(l_serial_shift > 0)
-                    l_serial_shift--;
-                else {
-                    if(!l_serial_total_only) {
-                        dap_string_append(l_keys, l_serial->header.serial);
-                        dap_string_append(l_keys, " activated");
-                        //if(i < l_serial_count - 1)
-                        dap_string_append(l_keys, "\n");
-                    }
-                    l_total_actual++;
-                }
-            }
-            if(!l_serial_nototal){
-                char *l_total_str = l_total_actual == 1 ? dap_strdup_printf("total 1 key") : dap_strdup_printf("total %u keys", l_total_actual);
-                dap_string_append(l_keys, l_total_str);
-                DAP_DELETE(l_total_str);
-            }
-            dap_chain_node_cli_set_reply_text(a_str_reply, "%s", l_keys->str);
-            dap_string_free(l_keys, true);
-            dap_store_obj_free(l_obj, l_serial_count_noactivated);
-            dap_store_obj_free(l_obj_activated, l_serial_count_activated);
-        }
-        else
-            dap_chain_node_cli_set_reply_text(a_str_reply, "keys not found");
-        return 0;
-    }
-    else
-    // Command 'serial generate'
-    if(!dap_strcmp(a_serial_str, "generate")) {
-        const char * l_serial_count_str = NULL;
-        const char * l_active_days_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-n", &l_serial_count_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-active_days", &l_active_days_str);
-        uint32_t l_serial_count = l_serial_count_str ? strtoll(l_serial_count_str, NULL, 10) : 1;
-        size_t l_active_days = l_active_days_str ? strtoll(l_active_days_str, NULL, 10) : 0;
-        if(l_serial_count < 1)
-            l_serial_count = 1;
-        dap_string_t *l_keys = l_serial_count > 1 ? dap_string_new("serial keys:\n") : dap_string_new("serial key: ");
-        for(uint32_t i = 0; i < l_serial_count; i++) {
-            dap_serial_key_t l_serial;
-            memset(&l_serial, 0, sizeof(dap_serial_key_t));
-            while(1) {
-                char *l_serial_str = generate_serial(4, 4, "-");
-                uint8_t *l_serial_str_prev = dap_chain_global_db_gr_get(l_serial_str, NULL, s_group_serials);
-                if(l_serial_str_prev)
-                    DAP_DELETE(l_serial_str_prev);
-                else{
-                    strncpy(l_serial.header.serial, l_serial_str, sizeof(l_serial.header.serial));
-                    if(l_active_days)
-                        l_serial.header.license_length = l_active_days * 86400;// days to sec
-                    break;
-                }
-            };
-            l_serial.header.ext_size = 0;
-
-            if(dap_chain_global_db_gr_set(dap_strdup(l_serial.header.serial), &l_serial, sizeof(l_serial), s_group_serials)) {
-                dap_string_append(l_keys, l_serial.header.serial);
-                if(i < l_serial_count - 1)
-                    dap_string_append(l_keys, "\n");
-            }
-            run_hook(s_hook_serial_generate, "serial=%s active_days=%lld", l_serial.header.serial, l_active_days);
-        }
-        dap_chain_node_cli_set_reply_text(a_str_reply, "generated new %s", l_keys->str);
-        dap_string_free(l_keys, true);
-        // save gdb
-        dap_chain_global_db_flush();
-        return 0;
-    }
-    else
-    // Command 'serial update'
-    if(!dap_strcmp(a_serial_str, "update")) {
-        const char * l_serial_number_str = NULL;
-        const char * l_active_days_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-serial", &l_serial_number_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-active_days", &l_active_days_str);
-        size_t l_active_days = l_active_days_str ? strtoll(l_active_days_str, NULL, 10) : 0;
-        if(!l_serial_number_str) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "option '-serial XXXX-XXXX-XXXX-XXXX' is not defined");
-        }
-        else if(!l_active_days_str) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "option '-active_days <active days that left for serial after activation>' is not defined");
-        }
-        else {
-            const char *l_group;
-            dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(l_serial_number_str, &l_group);
-            if(l_serial_key){
-                // if serial inactive, then header.activated=0
-                if(l_serial_key->header.activated){
-                    if(l_active_days > 0)
-                        l_serial_key->header.expired = l_serial_key->header.activated + l_active_days * 86400; // 24*3600 = days to sec;
-                }
-                else
-                    l_serial_key->header.license_length = l_active_days * 86400; // 24*3600 = days to sec;
-                // save updated serial
-                if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, dap_serial_key_len(l_serial_key), l_group)) {
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' successfully updated", l_serial_key->header.serial);
-                    // save gdb
-                    dap_chain_global_db_flush();
-                    run_hook(s_hook_serial_update, "serial=%s status=%s active_days=%lld", l_serial_key->header.serial, l_serial_key->header.activated ? "activated" : "inactive", l_active_days);
-                    DAP_DELETE(l_serial_key);
-                    return 0;
-                }
-                else{
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' can't updated", l_serial_key->header.serial);
-                }
-                DAP_DELETE(l_serial_key);
-            }
-            else{
-                dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not found", l_serial_number_str);
-            }
-            return 0;
-        }
-    }
-    else
-    // Command 'serial info'
-    if(!dap_strcmp(a_serial_str, "info")) {
-        int l_ret = 0;
-        const char * l_serial_number_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-serial", &l_serial_number_str);
-        if(!l_serial_number_str) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "option '-serial XXXX-XXXX-XXXX-XXXX' is not defined");
-            l_ret = -1;
-        }
-        else {
-            const char *l_group;
-            dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(l_serial_number_str, &l_group);
-            if(l_serial_key) {
-                char l_out_str[121];
-                char *l_str_message;
-                // form full string with serial info
-                if(l_serial_key->header.activated) {
-                    if(dap_time_to_str_rfc822(l_out_str, 120, l_serial_key->header.activated) > 0) {// instead of strftime
-                        // form expired time string
-                        char *l_expired_txt = NULL;
-                        if(l_serial_key->header.expired) {
-                            time_t l_expired_sec = l_serial_key->header.expired - time(NULL);
-                            if(l_expired_sec <= 0)
-                                l_expired_txt = dap_strdup("0 days");
-                            else
-                                l_expired_txt = dap_strdup_printf("%lld days", l_expired_sec/(24*3600));
-                        }
-                        else
-                            l_expired_txt = dap_strdup("no time limit");
-                        l_str_message = dap_strdup_printf("serial %s actitated %s\nexpired: %s", l_serial_key->header.serial, l_out_str, l_expired_txt);
-                        DAP_DELETE(l_expired_txt);
-                    }
-                    else {
-                        l_str_message = dap_strdup_printf("serial %s actitated ???", l_serial_key->header.serial);
-                        l_ret = -3;
-                    }
-                }
-                // not activated serial
-                else {
-                    // form expired time string
-                    char *l_expired_txt = NULL;
-                    if(l_serial_key->header.license_length) {
-                        l_expired_txt = dap_strdup_printf("%lld days", l_serial_key->header.license_length/(24*3600));
-                    }
-                    else
-                        l_expired_txt = dap_strdup("no time limit");
-                    l_str_message = dap_strdup_printf("serial %s not activated\nlicense length: %s", l_serial_key->header.serial, l_expired_txt);
-                    DAP_DELETE(l_expired_txt);
-                }
-                dap_chain_node_cli_set_reply_text(a_str_reply, l_str_message);
-
-                DAP_DELETE(l_str_message);
-            }
-            else {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not found", l_serial_number_str);
-                l_ret = -2;
-            }
-
-            DAP_DELETE(l_serial_key);
-        }
-        return l_ret;
-
-    }
-    else
-    // Command 'serial delete'
-    if(!dap_strcmp(a_serial_str, "delete")) {
-        int l_ret = 0;
-        const char * l_serial_number_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-serial", &l_serial_number_str);
-        if(!l_serial_number_str) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "option '-serial XXXX-XXXX-XXXX-XXXX' is not defined");
-            l_ret = -1;
-        }
-        else {
-            const char *l_group;
-            dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(l_serial_number_str, &l_group);
-            if(l_serial_key) {
-                if(dap_chain_global_db_gr_del(l_serial_key->header.serial, l_group)){
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' deleted", l_serial_key->header.serial);
-                    run_hook(s_hook_serial_delete, "serial=%s", l_serial_key->header.serial);
-                    // save gdb
-                    dap_chain_global_db_flush();
-                }
-                else {
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not deleted", l_serial_key->header.serial);
-                    l_ret = -4;
-                }
-            }
-            else {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not found", l_serial_number_str);
-                l_ret = -2;
-            }
-
-            DAP_DELETE(l_serial_key);
-        }
-        return l_ret;
-    }
-    else
-    // Command 'serial deactivate'
-    if(!dap_strcmp(a_serial_str, "deactivate")) {
-        int l_ret = 0;
-        const char * l_serial_number_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "-serial", &l_serial_number_str);
-        if(!l_serial_number_str) {
-            dap_chain_node_cli_set_reply_text(a_str_reply, "option '-serial XXXX-XXXX-XXXX-XXXX' is not defined");
-            l_ret = -1;
-        }
-        else {
-            const char *l_group;
-            dap_serial_key_t *l_serial_key = dap_chain_net_srv_vpn_cdb_auth_get_serial_param(l_serial_number_str, &l_group);
-            if(l_serial_key) {
-                if(!l_serial_key->header.activated){
-                    dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' already deactivated", l_serial_number_str);
-                }
-                else{
-                    if(l_serial_key->header.expired)
-                        l_serial_key->header.expired = l_serial_key->header.expired - l_serial_key->header.activated;
-                    l_serial_key->header.activated = 0;
-
-                    // pkey in l_serial_key->ext remains
-                    // save updated serial
-                    if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, dap_serial_key_len(l_serial_key), s_group_serials)) {
-                        dap_chain_global_db_gr_del(l_serial_key->header.serial, s_group_serials_activated);
-                        dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' deactivated successfully", l_serial_number_str);
-                        run_hook(s_hook_serial_deactivate, "serial=%s", l_serial_key->header.serial);
-                        l_ret = 0; // OK
-                        // save gdb
-                        dap_chain_global_db_flush();
-                    }
-                    else{
-                        l_ret = -5;
-                        dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not deactivated", l_serial_number_str);
-                    }
-                }
-            }
-            else {
-                dap_chain_node_cli_set_reply_text(a_str_reply, "serial '%s' not found", l_serial_number_str);
-                l_ret = -2;
-            }
-
-            DAP_DELETE(l_serial_key);
-        }
-        return l_ret;
-    }
-    else {
-        dap_chain_node_cli_set_reply_text(a_str_reply, "unknown subcommand %s, use 'generate', 'list', 'update', 'info', 'delete' or 'deactivate'", a_serial_str);
-    }
-    return -1;
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user
- * @param a_user_str
- * @param a_arg_index
- * @param a_argc
- * @param a_argv
- * @param a_str_reply
- * @return
- */
-int dap_chain_net_srv_vpn_cdb_auth_cli_cmd_user(const char *a_user_str, int a_arg_index, int a_argc, char ** a_argv, char **a_str_reply)
-{
-    int l_ret = 0;
-    dap_string_t * l_ret_str = dap_string_new("");
-    // Command 'user create'
-    bool l_is_user_create = (dap_strcmp(a_user_str, "create") == 0 );
-    bool l_is_user_update = (dap_strcmp(a_user_str, "update") == 0 );
-    if ( l_is_user_create  || l_is_user_update ){
-        const char * l_login_str = NULL;
-        const char * l_password_str = NULL;
-        const char * l_first_name_str = NULL;
-        const char * l_last_name_str = NULL;
-        const char * l_email_str = NULL;
-        const char * l_active_days_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--password", &l_password_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--first_name", &l_first_name_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--last_name", &l_last_name_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--email", &l_email_str);
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--active_days", &l_active_days_str);
-
-        if ( ( l_is_user_create && l_login_str && l_password_str ) ||
-             ( l_is_user_update && l_login_str && ( l_password_str || l_first_name_str || l_last_name_str || l_email_str ) ) ){
-
-            if (l_password_str){
-                char * l_hash_str = dap_strdup_printf("%s%s",l_password_str, s_salt_str );
-                dap_chain_hash_fast_t *l_password_hash = DAP_NEW_Z(dap_chain_hash_fast_t);
-                dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), l_password_hash );
-                DAP_DELETE(l_hash_str);
-                dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_password_hash,sizeof(*l_password_hash),s_group_password );
-            }
-
-            if ( l_first_name_str )
-                dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_first_name_str),strlen(l_first_name_str)+1,s_group_first_name );
-
-            if ( l_last_name_str )
-                dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_last_name_str),strlen(l_last_name_str)+1,s_group_last_name );
-
-            if ( l_email_str )
-                dap_chain_global_db_gr_set(dap_strdup(l_login_str), dap_strdup(l_email_str),strlen(l_email_str)+1,s_group_email );
-
-            // Update timestamp
-            dap_chain_time_t *l_time = DAP_NEW_Z(dap_chain_time_t);
-            *l_time = dap_chain_time_now();
-            dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_time,sizeof (*l_time),s_group_ts_updated );
-            l_time = NULL; // to prevent usage uleased memory that could be free in any moment
-
-            uint64_t l_active_days = 0;
-            if ( l_active_days_str ){
-                l_active_days = strtoull(l_active_days_str,NULL,10);
-                if ( l_active_days ){
-                    l_time = DAP_NEW_Z(dap_chain_time_t);
-                    *l_time = dap_chain_time_now() + (dap_chain_time_t) l_active_days*86400ull;
-                    dap_chain_global_db_gr_set(dap_strdup(l_login_str), l_time,sizeof (*l_time) ,s_group_ts_active_till );
-                }else
-                    dap_string_append_printf(l_ret_str,"WARNING: Wrong --active_time format\n");
-            }
-
-            if (l_is_user_create){
-                run_hook(s_hook_user_create, "login=%s pass=%s active_days=%lld first_name=%s last_name=%s email=%s", l_login_str, l_password_str, l_active_days,
-                        l_first_name_str ? l_first_name_str : "-",
-                        l_last_name_str ? l_last_name_str : "-",
-                        l_email_str ? l_email_str : "-");
-                dap_string_append_printf(l_ret_str,"OK: Created user '%s'\n",l_login_str );
-                l_ret = 0;
-            }else if (l_is_user_update){
-                run_hook(s_hook_user_update, "login=%s pass=%s active_days=%lld first_name=%s last_name=%s email=%s", l_login_str, l_password_str, l_active_days,
-                                        l_first_name_str ? l_first_name_str : "-",
-                                        l_last_name_str ? l_last_name_str : "-",
-                                        l_email_str ? l_email_str : "-");
-                dap_string_append_printf(l_ret_str,"OK: Updated user '%s'\n",l_login_str );
-                l_ret = 0;
-            }else{
-                dap_string_append_printf(l_ret_str,"OK: Unknown action success\n");
-                l_ret = 0;
-            }
-        }else{
-            if (l_is_user_create){
-                dap_string_append_printf(l_ret_str,"ERROR: Need at least --login and --password options\n" );
-                l_ret = -2;
-            }else if (l_is_user_update){
-                dap_string_append_printf(l_ret_str,"ERROR: Need at least --login and one of next options: --password, --first_name, --last_name or --email\n" );
-                l_ret = -3;
-            }else{
-                dap_string_append_printf(l_ret_str,"ERROR: Unknown error in options\n");
-                l_ret = -4;
-            }
-        }
-
-    }else if ( dap_strcmp(a_user_str, "delete") == 0 ){
-        const char * l_login_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str);
-        if ( l_login_str ) {
-            if ( dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_password ) ){
-                dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_last_name );
-                dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_first_name );
-                dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_email );
-                dap_chain_global_db_gr_del( dap_strdup( l_login_str),s_group_cookie );
-
-                // Find if present cookie and delete it
-                size_t l_cookie_size = 0;
-                char * l_cookie = (char*) dap_chain_global_db_gr_get(l_login_str,&l_cookie_size, s_group_cookie );
-                if ( l_cookie ){
-                    dap_chain_global_db_gr_del( l_cookie,s_group_cookies );
-                    log_it(L_WARNING,"Deleted user but its cookie is active in table. Deleted that but better also to close session");
-                    // TODO close session when cookie deleted
-                }
-
-                dap_string_append_printf(l_ret_str,"OK: Deleted user '%s'\n",l_login_str );
-                run_hook(s_hook_user_delete, "login=%s", l_login_str);
-                l_ret = 0;
-            }else{
-                l_ret = -6;
-                dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str );
-            }
-        }else{
-            l_ret = -5;
-            dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" );
-        }
-    }else if ( dap_strcmp(a_user_str, "check") == 0 ){
-        const char * l_login_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str);
-        const char * l_password_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--password", &l_password_str);
-        if ( l_login_str && l_password_str) {
-            int l_check = dap_chain_net_srv_vpn_cdb_auth_check_login (l_login_str, l_password_str);
-            if ( l_check == 0){
-                dap_string_append_printf(l_ret_str,"OK: Passed password check for '%s'\n",l_login_str );
-                l_ret = 0;
-            }else if (l_check == -1){
-                l_ret = -7;
-                dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str );
-            }else if (l_check == -2){
-                l_ret = -8;
-                dap_string_append_printf(l_ret_str,"ERROR: Wrong password for login '%s'\n", l_login_str );
-            }else if (l_check == -3){
-                l_ret = -10;
-                dap_string_append_printf(l_ret_str,"ERROR: Login '%s' is not activated\n", l_login_str );
-            }else if (l_check == -4){
-                l_ret = -11;
-                dap_string_append_printf(l_ret_str,"ERROR: Login '%s' activation is overdue\n", l_login_str );
-            }else {
-                l_ret = -9;
-                dap_string_append_printf(l_ret_str,"ERROR: Unknown error in password check for login '%s'\n", l_login_str );
-            }
-        }else{
-            l_ret = -5;
-            dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" );
-        }
-    }else if ( dap_strcmp(a_user_str, "show") == 0 ){
-        const char * l_login_str = NULL;
-        dap_chain_node_cli_find_option_val(a_argv, a_arg_index, a_argc, "--login", &l_login_str);
-        if ( l_login_str ) {
-            size_t l_password_hash_size=0;
-            dap_chain_hash_fast_t *l_password_hash;
-            if ( (l_password_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get (
-                     l_login_str,&l_password_hash_size  ,s_group_password ) ) !=NULL ){
-                dap_string_append_printf(l_ret_str,"OK: Find user '%s'\n",l_login_str );
-
-                size_t l_first_name_size=0;
-                char * l_first_name =(char *) dap_chain_global_db_gr_get (  l_login_str,&l_first_name_size  ,s_group_first_name ) ;
-                if ( l_first_name ){
-                    dap_string_append_printf(l_ret_str,"\tFirst_name: %s\n", l_first_name);
-                    DAP_DELETE( l_first_name );
-                }
-
-                size_t l_last_name_size=0;
-                char * l_last_name =(char *) dap_chain_global_db_gr_get (  l_login_str,&l_last_name_size  ,s_group_last_name ) ;
-                if (l_last_name){
-                    dap_string_append_printf(l_ret_str,"\tLast_name: %s\n", l_last_name);
-                    DAP_DELETE( l_last_name );
-                }
-
-                size_t l_email_size=0;
-                char * l_email =(char *) dap_chain_global_db_gr_get (  l_login_str,&l_email_size  ,s_group_email ) ;
-                if (l_email){
-                    dap_string_append_printf(l_ret_str,"\tEmail: %s\n", l_email);
-                    DAP_DELETE( l_email );
-                }
-
-                size_t l_ts_active_till_size = 0;
-                time_t *l_ts_active_till = (time_t*) dap_chain_global_db_gr_get(l_login_str, &l_ts_active_till_size, s_group_ts_active_till);
-                if(l_ts_active_till_size) {
-                    double l_dt_days = difftime(*l_ts_active_till, time(NULL)) / 86400;
-
-                    if(l_dt_days < 1) {
-                        if(l_dt_days < 0)
-                            l_dt_days = 0;
-                        dap_string_append_printf(l_ret_str, "\tActive hours: %.2lf\n", l_dt_days * 24);
-                    }
-                    else
-                        dap_string_append_printf(l_ret_str, "\tActive days: %.2lf\n", l_dt_days);
-                    DAP_DELETE(l_ts_active_till);
-                }
-
-                l_ret = 0;
-            }else{
-                l_ret = -6;
-                dap_string_append_printf(l_ret_str,"ERROR: Can't find login '%s' in database\n", l_login_str );
-            }
-        }else{
-            l_ret = -5;
-            dap_string_append_printf(l_ret_str,"ERROR: Need --login option\n" );
-        }
-    }else if ( dap_strcmp(a_user_str, "list") == 0 ){
-        size_t l_users_size = 0;
-        dap_global_db_obj_t* l_users = dap_chain_global_db_gr_load(s_group_password,&l_users_size);
-        if (l_users_size){
-            dap_string_append_printf(l_ret_str,"OK: %zd users in DB\n",l_users_size);
-            for ( size_t i = 0; i < l_users_size; i++ ){
-                dap_string_append_printf(l_ret_str,"\t%s\n",l_users[i].key);
-            }
-            dap_chain_global_db_objs_delete(l_users, l_users_size);
-        }else{
-            dap_string_append_printf(l_ret_str,"OK: 0 users in DB\n");
-        }
-    }else {
-        dap_string_append_printf(l_ret_str,"ERROR: Unknown command 'user %s'\n", a_user_str );
-        l_ret = -1;
-    }
-    dap_chain_node_cli_set_reply_text( a_str_reply, l_ret_str->str );
-    dap_string_free( l_ret_str, false );
-    return l_ret;
-}
-
-
-void dap_chain_net_srv_vpn_cdb_auth_add_proc(dap_http_t * a_http, const char * a_url)
-{
-    dap_http_simple_proc_add(a_http,a_url,24000, s_http_proc);
-}
-
-/**
- * @brief s_http_proc Process auth request
- * @param sh HTTP simple client instance
- * @param arg Return if ok
- */
-static void s_http_proc(dap_http_simple_t *a_http_simple, void * arg )
-{
-    http_status_code_t * return_code = (http_status_code_t*)arg;
-    enc_http_delegate_t * l_delegate;
-    strcpy(a_http_simple->reply_mime,"application/octet-stream");
-
-    l_delegate = enc_http_request_decode(a_http_simple);
-    if(l_delegate){
-        if(strcmp(l_delegate->url_path, "auth") == 0) {
-            s_http_enc_proc(l_delegate, arg);
-        }
-        else if(strcmp(l_delegate->url_path, "auth_key") == 0) {
-            s_http_enc_proc_key(l_delegate, arg);
-        }
-        else {
-
-            if(l_delegate->url_path)
-                log_it(L_ERROR,"Wrong auth request %s",l_delegate->url_path);
-            else
-                log_it(L_ERROR,"Wrong auth request: nothing after / ");
-
-            *return_code = Http_Status_BadRequest;
-        }
-
-        enc_http_reply_encode(a_http_simple,l_delegate);
-        enc_http_delegate_delete(l_delegate);
-    }else{
-        *return_code = Http_Status_Unauthorized;
-        log_it(L_WARNING,"No KeyID in the request");
-    }
-}
-
-/**
- * @brief s_http_enc_proc Auth http interface
- * @param a_delegate HTTP Simple client instance
- * @param a_arg Pointer to bool with okay status (true if everything is ok, by default)
- */
-static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg)
-{
-    http_status_code_t * l_return_code = (http_status_code_t*)a_arg;
-
-    if((a_delegate->request)&&(strcmp(a_delegate->action,"POST")==0)){
-        if(a_delegate->in_query==NULL){
-            log_it(L_WARNING,"Empty auth action");
-            *l_return_code = Http_Status_BadRequest;
-            return;
-        }else{
-            if(strcmp(a_delegate->in_query,"logout")==0 ){
-                if(dap_chain_global_db_gr_del(dap_strdup( a_delegate->cookie), s_group_cookies)){
-                    enc_http_reply_f(a_delegate,
-                                     "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
-                                     "<return>Successfuly logouted</return>\n"
-                                     );
-                    *l_return_code = Http_Status_OK;
-                }else{
-                    log_it(L_NOTICE,"Logout action: cookie %s is already logouted (by timeout?)", a_delegate->cookie);
-                    enc_http_reply_f(a_delegate,
-                                     "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
-                                     "<err_str>No session in table</err_str>\n"
-                                     );
-                    *l_return_code = Http_Status_OK;
-                }
-
-            }else if(strcmp(a_delegate->in_query,"login")==0 || strcmp(a_delegate->in_query,"serial")==0 ){
-                char l_login[128]={0};
-                char l_password[256]={0};
-                char l_pkey[6001]={0};//char l_pkey[4096]={0};
-
-                char l_domain[64], l_domain2[64];
-
-                //log_it(L_DEBUG, "request_size=%d request_str='%s'\n",a_delegate->request_size, a_delegate->request_str);
-
-                // password mode
-                if(s_mode_passwd) {
-                    if(sscanf(a_delegate->request_str, "%127s %255s %63s %6000s %63s", l_login, l_password, l_domain,
-                            l_pkey, l_domain2) >= 4 ||
-                            sscanf(a_delegate->request_str, "%127s %255s %6000s ", l_login, l_password, l_pkey) >= 3) {
-                        log_it(L_INFO, "Trying to login with username '%s'", l_login);
-
-                        if(s_input_validation(l_login) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in username");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            return;
-                        }
-                        if(s_input_validation(l_password) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in password");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            return;
-                        }
-                        if(s_input_validation(l_pkey) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in base64 pkey string");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            return;
-                        }
-
-                        int l_login_result = dap_chain_net_srv_vpn_cdb_auth_check_login(l_login, l_password);
-                        switch (l_login_result) {
-                        case 0: {
-                            run_hook(s_hook_user_login, "login=%s pass=%s result=true", l_login, l_password);
-                            size_t l_tmp_size;
-                            char * l_first_name = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size,
-                                    s_group_first_name);
-                            char * l_last_name = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size,
-                                    s_group_last_name);
-                            char * l_email = (char*) dap_chain_global_db_gr_get(l_login, &l_tmp_size, s_group_email);
-                            dap_chain_time_t * l_ts_last_logined = (dap_chain_time_t*) dap_chain_global_db_gr_get(
-                                    l_login, &l_tmp_size, s_group_ts_last_login);
-                            dap_chain_time_t *l_ts_active_till = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_login,
-                                    &l_tmp_size, s_group_ts_active_till);
-
-                            enc_http_reply_f(a_delegate,
-                                    "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
-                                            "<auth_info>\n"
-                                    );
-                            enc_http_reply_f(a_delegate, "\t<login>%s</login>\n", l_login);
-                            if(l_first_name)
-                                enc_http_reply_f(a_delegate, "\t<first_name>%s</first_name>\n", l_first_name);
-                            if(l_last_name)
-                                enc_http_reply_f(a_delegate, "\t<last_name>%s</last_name>\n", l_last_name);
-                            if(l_email)
-                                enc_http_reply_f(a_delegate, "\t<email>%s</email>\n", l_email);
-                            if(l_ts_last_logined)
-                                enc_http_reply_f(a_delegate, "\t<ts_prev_login>%llu</ts_prev_login>\n", (long long unsigned) *l_ts_last_logined);
-                            if(l_ts_active_till)
-                                enc_http_reply_f(a_delegate, "\t<ts_active_till>%llu</ts_acyive_till>\n", (long long unsigned) *l_ts_active_till);
-
-                            if(a_delegate->cookie)
-                                enc_http_reply_f(a_delegate, "\t<cookie>%s</cookie>\n", a_delegate->cookie);
-                            dap_chain_net_srv_vpn_cdb_auth_after(a_delegate, l_login, l_pkey); // Here if smbd want to add smth to the output
-                            enc_http_reply_f(a_delegate, "</auth_info>");
-                            log_it(L_INFO, "Login: Successfuly logined user %s", l_login);
-                            *l_return_code = Http_Status_OK;
-                            //log_it(L_DEBUG, "response_size='%d'",a_delegate->response_size);
-                            DAP_DELETE(l_first_name);
-                            DAP_DELETE(l_last_name);
-                            DAP_DELETE(l_email);
-                            DAP_DELETE(l_ts_last_logined);
-                            DAP_DELETE(l_ts_active_till);
-
-                            // Update last logined
-                            l_ts_last_logined = DAP_NEW_Z(dap_chain_time_t);
-                            *l_ts_last_logined = dap_chain_time_now();
-                            dap_chain_global_db_gr_set(dap_strdup(l_login), l_ts_last_logined, sizeof(time_t), s_group_ts_last_login);
-                            DAP_DELETE(l_ts_last_logined);
-                        }
-                            break;
-                        case -1:
-                            run_hook(s_hook_user_login, "login=%s pass=%s result=false error=user_no_found", l_login, l_password);
-                            enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -2:
-                            run_hook(s_hook_user_login, "login=%s pass=%s result=false error=passwd_not_correct", l_login, l_password);
-                            enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -3:
-                            enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -4:
-                            run_hook(s_hook_user_login, "login=%s pass=%s result=false error=expired", l_login, l_password);
-                            enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED);
-                            *l_return_code = Http_Status_PaymentRequired;
-                            break;
-                        default:
-                            log_it(L_WARNING, "Login: Unknown authorize error for login '%s'", l_login);
-                            *l_return_code = Http_Status_BadRequest;
-                            break;
-                        }
-                    } else {
-                        log_it(L_DEBUG, "Login: wrong auth's request body ");
-                        *l_return_code = Http_Status_BadRequest;
-                    }
-                }
-                // serial mode
-                else
-                {
-                    char l_serial_tmp[64]={0};
-                    if(sscanf(a_delegate->request_str, "%63s %63s %6000s", l_serial_tmp, l_domain, l_pkey) >= 3) {
-                        char *l_serial = make_fullserial(l_serial_tmp);
-                        log_it(L_INFO, "Trying to login with serial '%s'", l_serial);
-                        if(s_input_validation(l_serial) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in serial");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        if(s_input_validation(l_domain) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in l_domain");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        if(s_input_validation(l_pkey) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in base64 pkey string");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        int l_login_result = dap_chain_net_srv_vpn_cdb_auth_check_serial(l_serial, l_pkey);
-                        log_it(L_INFO, "Check serial '%s' with code %d (Ok=0)", l_serial, l_login_result);
-                        switch (l_login_result) {
-                        case 0: {
-                            run_hook(s_hook_serial_login, "serial=%s result=true", l_serial);
-                            size_t l_tmp_size;
-                            enc_http_reply_f(a_delegate,
-                                    "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
-                                            "<auth_info>\n"
-                                    );
-                            enc_http_reply_f(a_delegate, "\t<serial>%s</serial>\n", l_serial);
-
-                            dap_chain_time_t * l_ts_last_logined = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_serial, &l_tmp_size, s_group_ts_last_login);
-                            dap_chain_time_t *l_ts_active_till = (dap_chain_time_t*) dap_chain_global_db_gr_get(l_serial, &l_tmp_size, s_group_ts_active_till);
-                            if(l_ts_last_logined)
-                                enc_http_reply_f(a_delegate, "\t<ts_prev_login>%llu</ts_prev_login>\n", (long long unsigned) *l_ts_last_logined);
-                            if(l_ts_active_till)
-                                enc_http_reply_f(a_delegate, "\t<ts_active_till>%llu</ts_acyive_till>\n", (long long unsigned) *l_ts_active_till);
-                            if(a_delegate->cookie)
-                                enc_http_reply_f(a_delegate, "\t<cookie>%s</cookie>\n", a_delegate->cookie);
-                            dap_chain_net_srv_vpn_cdb_auth_after(a_delegate, l_serial, l_pkey); // Here if smbd want to add smth to the output
-                            enc_http_reply_f(a_delegate, "</auth_info>");
-                            log_it(L_INFO, "Login: Successfuly logined user %s", l_login);
-                            *l_return_code = Http_Status_OK;
-                            //log_it(L_DEBUG, "response_size='%d'",a_delegate->response_size);
-
-                            DAP_DELETE(l_ts_last_logined);
-                            DAP_DELETE(l_ts_active_till);
-
-                            // Update last logined
-                            l_ts_last_logined = DAP_NEW_Z(dap_chain_time_t);
-                            *l_ts_last_logined = dap_chain_time_now();
-                            dap_chain_global_db_gr_set(dap_strdup(l_serial), l_ts_last_logined, sizeof(time_t),s_group_ts_last_login);
-                            DAP_DELETE(l_ts_last_logined);
-                        }
-                            break;
-                        case -1:
-                            run_hook(s_hook_serial_login, "serial=%s result=false error=serial_no_found", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -2:
-                            run_hook(s_hook_serial_login, "serial=%s result=false error=other_device", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_SIGN);// incorrect pkey
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -3:
-                            enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -4:
-                            run_hook(s_hook_serial_login, "serial=%s result=false error=expired", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED);
-                            *l_return_code = Http_Status_PaymentRequired;
-                            break;
-                        default:
-                            log_it(L_WARNING, "Login: Unknown authorize error for login '%s'", l_login);
-                            *l_return_code = Http_Status_BadRequest;
-                            break;
-                        }
-                        DAP_DELETE(l_serial);
-                    }
-                }
-            }else if (s_is_registration_open && strcmp(a_delegate->in_query,"register")==0){
-                char l_login[128];
-                char l_password[256];
-                char l_first_name[128];
-                char l_last_name[128];
-                char l_email[256];
-
-                log_it(L_INFO, "Request str = %s", a_delegate->request_str);
-                if(sscanf(a_delegate->request_str,"%127s %255s %127s %127s %255s"
-                          ,l_login,l_password,l_email,l_first_name,l_last_name)>=3){
-                    if(s_input_validation(l_login)==0){
-                        log_it(L_WARNING,"Registration: Wrong symbols in the username '%s'",l_login);
-                        *l_return_code = Http_Status_BadRequest;
-                        return;
-                    }
-                    if(s_input_validation(l_password)==0){
-                        log_it(L_WARNING,"Registration: Wrong symbols in the password");
-                        *l_return_code = Http_Status_BadRequest;
-                        return;
-                    }
-                    if(s_input_validation(l_first_name)==0){
-                        log_it(L_WARNING,"Registration: Wrong symbols in the first name '%s'",l_first_name);
-                        *l_return_code = Http_Status_BadRequest;
-                        return;
-                    }
-                    if(s_input_validation(l_last_name)==0){
-                        log_it(L_WARNING,"Registration: Wrong symbols in the last name '%s'",l_last_name);
-                        *l_return_code = Http_Status_BadRequest;
-                        return;
-                    }
-                    if(s_input_validation(l_email)==0){
-                        log_it(L_WARNING,"Registration: Wrong symbols in the email '%s'",l_email);
-                        *l_return_code = Http_Status_BadRequest;
-                        return;
-                    }
-                    if ( l_login[0] && l_password[0] && l_email[0] ){
-
-                        // Hash password with salt
-                        char * l_hash_str = dap_strdup_printf("%s%s",l_password, s_salt_str );
-                        dap_chain_hash_fast_t *l_password_hash = DAP_NEW_Z(dap_chain_hash_fast_t);
-                        dap_hash_fast(l_hash_str,dap_strlen(l_hash_str), l_password_hash );
-                        DAP_DELETE(l_hash_str);
-                        dap_chain_global_db_gr_set(dap_strdup(l_login), l_password_hash,sizeof(*l_password_hash),s_group_password );
-
-                        // Write email in db
-                        dap_chain_global_db_gr_set(dap_strdup(l_login), dap_strdup(l_email),strlen(l_email)+1,s_group_email );
-
-                        enc_http_reply_f(a_delegate,
-                                         "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
-                                         "<auth_info>\n"
-                                         );
-
-                        enc_http_reply_f(a_delegate,"\t<login>%s</login>\n",l_login);
-                        // Write first and last names in db if present
-                        if ( l_first_name[0] ){
-                            dap_chain_global_db_gr_set( dap_strdup(l_login), dap_strdup(l_first_name),strlen(l_first_name)+1,
-                                                        s_group_first_name );
-                            enc_http_reply_f(a_delegate,"\t<first_name>%s</first_name>\n",l_first_name);
-                        }
-
-                        if ( l_last_name[0] ){
-                            dap_chain_global_db_gr_set( dap_strdup(l_login), dap_strdup( l_last_name ), strlen( l_last_name)+1,
-                                                        s_group_last_name );
-                            enc_http_reply_f(a_delegate,"\t<last_name>%s</last_name>\n",l_last_name);
-                        }
-
-                        // If cookie present - report it
-                        if ( a_delegate->cookie )
-                            enc_http_reply_f(a_delegate,"\t<cookie>%s</cookie>\n",a_delegate->cookie );
-                        enc_http_reply_f(a_delegate,"</auth_info>");
-
-                        log_it(L_NOTICE,"Registration: new user %s \"%s %s\"<%s> is registred",l_login,l_first_name,l_last_name,l_email);
-                    }
-                }else{
-                    log_it(L_ERROR, "Registration: Wrong auth's request body ");
-                    *l_return_code = Http_Status_BadRequest;
-                }
-            }else{
-                log_it(L_ERROR, "Unknown auth command was selected (query_string='%s')",a_delegate->in_query);
-                *l_return_code = Http_Status_BadRequest;
-            }
-        }
-    }else{
-        log_it(L_ERROR, "Wrong auth request action '%s'",a_delegate->action);
-        *l_return_code = Http_Status_BadRequest;
-    }
-}
-
-/**
- * @brief s_http_enc_proc Auth http interface
- * @param a_delegate HTTP Simple client instance
- * @param a_arg Pointer to bool with okay status (true if everything is ok, by default)
- */
-static void s_http_enc_proc_key(enc_http_delegate_t *a_delegate, void * a_arg)
-{
-    http_status_code_t * l_return_code = (http_status_code_t*) a_arg;
-
-    if((a_delegate->request) && (strcmp(a_delegate->action, "POST") == 0)) {
-        if(a_delegate->in_query == NULL) {
-            log_it(L_WARNING, "Empty auth action");
-            *l_return_code = Http_Status_BadRequest;
-            return;
-        } else {
-            if(strcmp(a_delegate->in_query, "serial") == 0) {
-                char l_serial_raw[64] = { 0 };
-                char l_serial_sign[12000] = { 0 };
-                char l_pkey[6001] = { 0 };
-
-                // only for serial mode
-                if(!s_mode_passwd)
-                {
-                    char l_domain[64];
-                    if(sscanf(a_delegate->request_str, "%63s %12000s %63s %6000s", l_serial_raw, l_serial_sign, l_domain, l_pkey) >= 4) {
-                        char *l_serial = make_fullserial(l_serial_raw);
-                        /*size_t a1 = dap_strlen(l_serial);
-                        size_t a2 = dap_strlen(l_serial_sign);
-                        size_t a3 = dap_strlen(l_pkey);*/
-                        log_it(L_INFO, "Trying to activate with serial '%s'", l_serial);
-                        if(s_input_validation(l_serial) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in serial");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        if(s_input_validation(l_pkey) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in base64 pkey string");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        if(s_input_validation(l_serial_sign) == 0) {
-                            log_it(L_WARNING, "Wrong symbols in base64 serial sign");
-                            enc_http_reply_f(a_delegate, OP_CODE_INCORRECT_SYMOLS);
-                            *l_return_code = Http_Status_BadRequest;
-                            DAP_DELETE(l_serial);
-                            return;
-                        }
-                        int l_activate_result = dap_chain_net_srv_vpn_cdb_auth_activate_serial(l_serial_raw, l_serial, l_serial_sign, l_pkey);
-                        log_it(L_INFO, "Serial '%s' activated with code %d (Ok=0)", l_serial, l_activate_result);
-                        switch (l_activate_result) {
-                        case 0:
-                            run_hook(s_hook_serial_activate, "serial=%s result=true", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_SERIAL_ACTIVED);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -1:
-                            run_hook(s_hook_serial_activate, "serial=%s result=false error=serial_no_found", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                        case -2:
-                            run_hook(s_hook_serial_activate, "serial=%s result=false error=sign_incorrect", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_SIGN);
-                            *l_return_code = Http_Status_OK;
-                            break;
-                            /*case -3:
-                             enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE);
-                             *l_return_code = Http_Status_OK;
-                             break;*/
-                        case -4:
-                            run_hook(s_hook_serial_activate, "serial=%s result=false error=expired", l_serial);
-                            enc_http_reply_f(a_delegate, OP_CODE_SUBSCRIBE_EXPIRIED);
-                            *l_return_code = Http_Status_PaymentRequired;
-                            break;
-                        default:
-                            log_it(L_WARNING, "Login: Unknown authorize error for activate serial '%s'", l_serial);
-                            *l_return_code = Http_Status_BadRequest;
-                            break;
-                        }
-                        DAP_DELETE(l_serial);
-                    }
-                    else {
-                        log_it(L_ERROR, "Registration: Wrong auth_key's request body ");
-                        *l_return_code = Http_Status_BadRequest;
-                    }
-                }
-            } else {
-                log_it(L_ERROR, "Unknown auth command was selected (query_string='%s')", a_delegate->in_query);
-                *l_return_code = Http_Status_BadRequest;
-            }
-        }
-    } else {
-        log_it(L_ERROR, "Wrong auth request action '%s'", a_delegate->action);
-        *l_return_code = Http_Status_BadRequest;
-    }
-}
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c
deleted file mode 100644
index b03956319f890a8f994e5de51b97f28eb3508e52..0000000000000000000000000000000000000000
--- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_server_list.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Authors:
- * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
- * Alexander Lysikov <alexander.lysikov@demlabs.net>
- * DeM Labs Inc.   https://demlabs.net
- * CellFrame       https://cellframe.net
- * Sources         https://gitlab.demlabs.net/cellframe
- * Copyright  (c) 2017-2019
- * All rights reserved.
-
- This file is part of DAP (Deus Applications Prototypes) the open source project
-
-    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    DAP is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include "dap_common.h"
-#include "dap_config.h"
-
-#include "dap_chain.h"
-#include "dap_chain_net.h"
-#include "dap_chain_net_srv.h"
-#include "dap_chain_net_srv_vpn.h"
-#include "dap_chain_net_srv_order.h"
-#include "dap_chain_net_srv_geoip.h"
-
-#include "dap_http.h"
-#include "dap_http_simple.h"
-#include "http_status_code.h"
-
-#include "dap_chain_net_srv_vpn_cdb_server_list.h"
-
-#define LOG_TAG "dap_chain_net_srv_vpn_cdb_server_list"
-
-
-static size_t s_cdb_net_count = 0;
-static dap_chain_net_t ** s_cdb_net = NULL;
-static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg);
-
-int dap_chain_net_srv_vpn_cdb_server_list_init()
-{
-    char **l_cdb_networks;
-    uint16_t l_cdb_networks_count = 0;
-    log_it(L_NOTICE,"Initialized Server List Module");
-    l_cdb_networks = dap_config_get_array_str( g_config, "cdb", "servers_list_networks", &l_cdb_networks_count );
-
-    if ( l_cdb_networks_count ){
-        s_cdb_net = DAP_NEW_Z_SIZE(dap_chain_net_t*, sizeof (dap_chain_net_t*)* l_cdb_networks_count );
-        s_cdb_net_count = l_cdb_networks_count;
-        for ( size_t i = 0; i < l_cdb_networks_count ; i++) {
-            s_cdb_net[i] = dap_chain_net_by_name( l_cdb_networks[i] );
-            if ( s_cdb_net[i] )
-                log_it( L_INFO, "Added \"%s\" network for server list fetchs", l_cdb_networks[i]);
-            else
-                log_it( L_WARNING, "Can't find \"%s\" network to add to server list fetchs", l_cdb_networks[i]);
-        }
-    } else
-        log_it( L_WARNING, "No chain networks listed in config");
-
-    return 0;
-}
-
-void dap_chain_net_srv_vpn_cdb_server_list_deinit(void)
-{
-}
-
-
-/**
- * @brief order_info_print
- * @param a_server_location for server name, NULL not used
- * @param a_node_number for server name, <0 not use
- */
-static int order_info_print(dap_string_t *a_reply_str, dap_chain_net_t * a_net, dap_chain_net_srv_order_t * a_order, const char *a_server_name, int a_node_number)
-{
-    dap_chain_node_info_t * l_node_info = dap_chain_node_info_read(a_net, &a_order->node_addr);
-    if(l_node_info) {
-        char l_node_ext_ipv4_str[INET_ADDRSTRLEN] = { 0 };
-        char l_node_ext_ipv6_str[INET6_ADDRSTRLEN] = { 0 };
-        if(l_node_info->hdr.ext_addr_v4.s_addr)
-            inet_ntop(AF_INET, &l_node_info->hdr.ext_addr_v4, l_node_ext_ipv4_str, sizeof(l_node_ext_ipv4_str));
-        if(*((uint128_t *) l_node_info->hdr.ext_addr_v6.s6_addr))
-            inet_ntop(AF_INET6, &l_node_info->hdr.ext_addr_v6, l_node_ext_ipv6_str, sizeof(l_node_ext_ipv6_str));
-
-        uint8_t l_continent_num = 0;
-        char *l_region = NULL;
-        dap_chain_net_srv_order_get_continent_region(a_order, &l_continent_num, &l_region);
-        const char *l_continent_str = dap_chain_net_srv_order_continent_to_str(l_continent_num);
-        // ext_out in hex view
-        char *l_ext_out = a_order->ext_size ? DAP_NEW_Z_SIZE(char, a_order->ext_size * 2 + 1) : NULL;
-        dap_bin2hex(l_ext_out, a_order->ext, a_order->ext_size);
-
-        dap_string_append_printf(a_reply_str, "    {\n");
-        dap_string_append_printf(a_reply_str, "        \"Location\":\"%s\",\n", l_region ? l_region : "None"); //NETHERLANDS
-                //l_continent_str ? l_continent_str : "None", l_region ? l_region : "None");
-
-
-        dap_string_append_printf(a_reply_str, "        \"ChainNet\":\"%s\",\n", a_net->pub.name);
-        //dap_string_append_printf(a_reply_str, "        \"Name\":\"%s.Cell-%lu.%zd\",\n", a_net->pub.name, l_node_info->hdr.cell_id.uint64, 0);
-        if(a_server_name)
-            dap_string_append_printf(a_reply_str, "        \"Name\":\"%s\",\n", a_server_name);
-        else
-            dap_string_append_printf(a_reply_str, "        \"Name\":\"%s.%s.%zd\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : "", a_node_number + 1);
-            //dap_string_append_printf(a_reply_str, "        \"Name\":\"%s.%s.Cell-%lu.%zd\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : "", l_node_info->hdr.cell_id.uint64, a_node_number + 1);
-        if(l_node_ext_ipv4_str[0])
-            dap_string_append_printf(a_reply_str, "        \"Address\":\"%s\",\n", l_node_ext_ipv4_str);
-        if(l_node_ext_ipv6_str[0])
-            dap_string_append_printf(a_reply_str, "        \"Address6\":\"%s\",\n", l_node_ext_ipv6_str);
-        dap_string_append_printf(a_reply_str, "        \"Port\":%hu,\n", l_node_info->hdr.ext_port ? l_node_info->hdr.ext_port : 80);
-
-        //dap_string_append_printf(a_reply_str, "        \"Ext\":\"%s-%s\",\n", l_continent_str ? l_continent_str : "", l_region ? l_region : "");
-        if(l_ext_out)
-            dap_string_append_printf(a_reply_str, "        \"Ext\":\"0x%s\",\n", l_ext_out);
-        else
-            dap_string_append_printf(a_reply_str, "        \"Ext\":\"0x0\",\n");
-        dap_string_append_printf(a_reply_str, "        \"Price\":%lu,\n", a_order->price);
-        dap_string_append_printf(a_reply_str, "        \"PriceUnits\":%u,\n", a_order->price_unit.uint32);
-        dap_string_append_printf(a_reply_str, "        \"PriceToken\":\"%s\"\n", a_order->price_ticker);
-        dap_string_append_printf(a_reply_str, "    }");
-        DAP_DELETE(l_region);
-        DAP_DELETE(l_ext_out);
-
-
-    } else{
-        log_it(L_WARNING, "Order in \"%s\" network issued by node without ext_ipv4 field", a_net->pub.name);
-        return -1;
-    }
-    return 0;
-}
-
-
-static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg)
-{
-    http_status_code_t * l_ret_code = (http_status_code_t*)a_arg;
-    dap_string_t *l_reply_str = dap_string_new("[\n");
-
-
-    char *l_client_ip = a_http_simple->http->client->s_ip;//"64.225.61.216"
-    geoip_info_t *l_geoip_info = chain_net_geoip_get_ip_info(l_client_ip);
-
-    log_it(L_DEBUG, "Have %zd chain networks for cdb lists", s_cdb_net_count );
-
-    for ( size_t i = 0; i < s_cdb_net_count ; i++ ) {
-        dap_chain_net_t * l_net = s_cdb_net[i];
-        if ( l_net ) {
-            dap_chain_net_srv_order_t * l_orders = NULL;
-            size_t l_orders_num = 0;
-            dap_chain_net_srv_price_unit_uid_t l_unit_uid = {{0}};
-            dap_chain_net_srv_uid_t l_srv_uid = { .uint64 =DAP_CHAIN_NET_SRV_VPN_ID };
-            dap_chain_net_srv_order_find_all_by( l_net, SERV_DIR_SELL,  l_srv_uid, l_unit_uid ,
-                                                 NULL,0,0, &l_orders, &l_orders_num );
-            log_it(L_DEBUG, "Found %zd orders in \"%s\" network", l_orders_num, l_net->pub.name );
-
-
-            // find the shift for each node
-            dap_chain_net_srv_order_t *l_orders_pos[l_orders_num];
-            size_t l_orders_size = 0;
-            for(size_t j = 0; j < l_orders_num; j++) {
-                l_orders_pos[j] = (dap_chain_net_srv_order_t*) ((char*) l_orders + l_orders_size);
-                l_orders_size += dap_chain_net_srv_order_get_size(l_orders_pos[j]);
-            }
-
-
-            // list of node numbers
-            size_t l_continents_count = dap_chain_net_srv_order_continents_count(); //int *l_node_numbering = DAP_NEW_Z_SIZE(int, l_orders_num * sizeof(int));
-            // list of the number of nodes in each continent
-            int l_continents_numbers[l_continents_count]; //int *l_continents_numbers = DAP_NEW_Z_SIZE(int, l_continents_count * sizeof(int));
-            int l_node_numbering[l_continents_count][l_orders_num];
-            // init arrays
-            for(size_t m1 = 0; m1 < l_continents_count; m1++) {
-                l_continents_numbers[m1] = 0;
-                for(size_t m2 = 0; m2 < l_orders_num; m2++)
-                    l_node_numbering[m1][m2] = -1;
-            }
-
-            // node numbering
-            size_t l_orders_used_num = 0;
-            {
-                // filling l_continents_numbers and l_node_numbering
-                for(size_t j = 0; j < l_orders_num; j++) {
-                    dap_chain_net_srv_order_t *l_order = l_orders_pos[j];
-                    uint8_t l_continent_num;
-                    if(!dap_chain_net_srv_order_get_continent_region(l_order, &l_continent_num, NULL))
-                        continue;
-                    l_node_numbering[l_continent_num][j] = l_continents_numbers[l_continent_num]++;
-                    l_orders_used_num++;
-                }
-                // shuffle nodes for each continent
-                for(size_t m1 = 0; m1 < l_continents_count; m1++) {
-                    int l_cont_num = l_continents_numbers[m1];
-                    if(l_cont_num <= 1)
-                        continue;
-                    // number of shuffles
-                    int l_shuffle_num = rand() % (l_cont_num + 1);
-                    for(size_t l_sh = 0; l_sh <= l_shuffle_num; l_sh++) {
-                        size_t l_pos1 = 0;
-                        size_t l_pos2 = 0;
-                        while(l_pos1 == l_pos2) {
-                            l_pos1 = rand() % l_cont_num;
-                            l_pos2 = rand() % l_cont_num;
-                        }
-                        for(size_t m2 = 0; m2 < l_orders_num; m2++) {
-                            if(l_node_numbering[m1][m2] == l_pos1)
-                                l_node_numbering[m1][m2] = l_pos2;
-                            else if(l_node_numbering[m1][m2] == l_pos2)
-                                l_node_numbering[m1][m2] = l_pos1;
-                        }
-                    }
-                }
-            }
-
-            int8_t l_client_continent = l_geoip_info ? dap_chain_net_srv_order_continent_to_num(l_geoip_info->continent) : 0;
-            // random node on client's continent
-            if(l_client_continent > 0 && l_continents_numbers[l_client_continent] > 1) {
-                int l_count = 0;
-                while(l_orders_num > 0) {
-                    size_t k = rand() % l_continents_numbers[l_client_continent];
-                    size_t l_node_pos = -1;
-                    for(size_t j2 = 0; j2 <= l_orders_num; j2++) {
-                        if(k == l_node_numbering[l_client_continent][j2]) {
-                            l_node_pos = j2;
-                            break;
-                        }
-                    }
-                    if(l_node_pos == -1) {
-                        // random node for the whole world
-                        l_node_pos = rand() % l_orders_num;
-                    }
-                    dap_chain_net_srv_order_t *l_order = l_orders_pos[l_node_pos];
-                    const char *country_code = dap_chain_net_srv_order_get_country_code(l_order);
-                    if(country_code) {
-                        // only for other countries
-                        if(dap_strcmp(l_geoip_info->country_code, country_code)) {
-                            if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)) {
-                                dap_string_append_printf(l_reply_str, ",\n");
-                                break;
-                            }
-                        }
-                    }
-                    if(l_count > 20)
-                        break;
-                    l_count++;
-                }
-
-            }
-            // random node for the whole world
-			else {
-				int l_count = 0;
-				while(l_orders_num > 0) {
-					// first random node
-					size_t k = rand() % l_orders_num;
-					dap_chain_net_srv_order_t *l_order = l_orders_pos[k];
-					if(!order_info_print(l_reply_str, l_net, l_order, "Auto", -1)){
-						dap_string_append_printf(l_reply_str, ",\n");
-						break;
-					}
-					if (l_count>20)
-						break;
-					l_count++;
-				}
-            }
-            // random nodes for continents
-            int l_count = 0;
-            for(size_t l_c = 0; l_c < l_continents_count; l_c++) {
-                while(l_continents_numbers[l_c] > 0) {
-                    // random node for continent
-                    size_t k = rand() % l_continents_numbers[l_c];
-                    size_t l_node_pos = -1;
-                    for(size_t j2 = 0; j2 <= l_orders_num; j2++) {
-                        if(k == l_node_numbering[l_c][j2]) {
-                            l_node_pos = j2;
-                            break;
-                        }
-                    }
-                    if(l_node_pos == -1)
-                        break;
-                    dap_chain_net_srv_order_t *l_order = l_orders_pos[l_node_pos];
-                    char *l_server_name = dap_strdup_printf("%s", dap_chain_net_srv_order_continent_to_str(l_c));
-                    if(!order_info_print(l_reply_str, l_net, l_order, l_server_name, -1)) {
-                        dap_string_append_printf(l_reply_str, ",\n");
-                        DAP_DELETE(l_server_name);
-                        break;
-                    }
-                    else
-                        DAP_DELETE(l_server_name);
-                    if(l_count > 20)
-                        break;
-                    l_count++;
-                }
-            }
-
-            for(size_t l_c = 0; l_c < l_continents_count; l_c++) {
-                // print all nodes for continent
-                for(size_t l_n = 0; l_n < l_continents_numbers[l_c]; l_n++) {
-                    // since the nodes are shuffled, look for the desired node index
-                    for(size_t l_o = 0; l_o < l_orders_num; l_o++) {
-                        if(l_node_numbering[l_c][l_o] != l_n)
-                            continue;
-                        dap_chain_net_srv_order_t *l_order = l_orders_pos[l_o];
-                        if(!order_info_print(l_reply_str, l_net, l_order, NULL, l_n)) {
-                            dap_string_append_printf(l_reply_str, ",\n");
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
-    DAP_DELETE(l_geoip_info);
-    //delete trailing comma if exists
-    if(l_reply_str->str[l_reply_str->len - 2] == ','){
-        dap_string_truncate(l_reply_str, l_reply_str->len - 2);
-        dap_string_append_printf(l_reply_str, "\n");
-    }
-
-    dap_string_append_printf( l_reply_str, "]\n\n");
-    dap_http_simple_reply( a_http_simple, l_reply_str->str, l_reply_str->len );
-    dap_string_free(l_reply_str, true);
-    //log_it(L_DEBUG,"Reply in buffer: %s", a_http_simple->reply_str );
-    *l_ret_code = Http_Status_OK;
-
-}
-
-/**
- * @brief dap_chain_net_srv_vpn_cdb_server_list_add_proc
- * @param sh
- * @param url
- */
-void dap_chain_net_srv_vpn_cdb_server_list_add_proc(dap_http_t *a_http, const char *a_url)
-{
-    dap_http_simple_proc_add(a_http,a_url,100000,s_http_simple_proc);
-}