From 7f8ec89e3ba33cf96772872445664a0aa89e4c40 Mon Sep 17 00:00:00 2001 From: "daniil.frolov" <daniil.frolov@demlabs.net> Date: Thu, 21 Mar 2024 19:21:28 +0000 Subject: [PATCH] hotfix_10684_port_to_rc --- .../dap_stream_ch_chain_net_srv.c | 851 +++++++++--------- .../dap_stream_ch_chain_net_srv.h | 60 -- .../include/dap_stream_ch_chain_net_srv.h | 69 +- .../chain-net/dap_stream_ch_chain_net.c | 24 +- modules/common/dap_chain_datum.c | 1 - modules/common/include/dap_chain_common.h | 24 +- modules/net/dap_chain_ledger.c | 6 +- modules/net/dap_chain_net.c | 4 +- modules/net/dap_chain_net_voting.c | 42 +- modules/net/dap_chain_node_cli_cmd.c | 2 +- modules/net/include/dap_chain_ledger.h | 1 - modules/net/include/dap_chain_net_voting.h | 4 +- .../net/include/dap_chain_node_cli_cmd_tx.h | 2 +- modules/net/srv/dap_chain_net_srv.c | 767 +++++++--------- modules/net/srv/dap_chain_net_srv_order.c | 12 +- .../srv/dap_chain_net_srv_stream_session.c | 2 +- modules/net/srv/include/dap_chain_net_srv.h | 44 +- .../net/srv/include/dap_chain_net_srv_order.h | 3 +- .../dap_chain_net_srv_stream_session.h | 3 +- .../service/datum/dap_chain_net_srv_datum.c | 13 +- modules/service/vpn/dap_chain_net_srv_vpn.c | 164 ++-- .../service/vpn/dap_chain_net_vpn_client.c | 9 +- .../xchange/dap_chain_net_srv_xchange.c | 46 - 23 files changed, 982 insertions(+), 1171 deletions(-) delete mode 100644 modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c index b1d9e9998f..f27ac58f68 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c @@ -30,7 +30,6 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include "dap_hash.h" #include "rand/dap_rand.h" -#include "dap_chain_net_srv.h" #include "dap_chain_net_srv_stream_session.h" #include "dap_stream.h" @@ -43,12 +42,38 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #define LOG_TAG "dap_stream_ch_chain_net_srv" #define SRV_PAY_GDB_GROUP "local.srv_pay" - -typedef struct usages_in_grace{ - dap_hash_fast_t tx_cond_hash; - dap_chain_net_srv_grace_t *grace; - UT_hash_handle hh; -} usages_in_grace_t; +#define SRV_STATISTIC_GDB_GROUP "local.srv_statistic" +#define SRV_RECEIPTS_GDB_GROUP "local.receipts" + +// client statistic key struct +typedef struct client_statistic_key{ + char key[18 + DAP_CHAIN_HASH_FAST_STR_SIZE]; +} client_statistic_key_t; + +// client statistic value struct +typedef struct client_statistic_value{ + struct { + uint64_t using_time; + uint256_t datoshi_value; + uint64_t bytes_received; + uint64_t bytes_sent; + uint64_t units; + } payed; + struct { + uint64_t using_time; + uint64_t bytes_received; + uint64_t bytes_sent; + uint64_t units; + } free; + struct { + uint64_t using_time; + uint256_t datoshi_value; + uint64_t bytes_received; + uint64_t bytes_sent; + uint64_t units; + uint64_t using_count; + } grace; +} client_statistic_value_t; static void s_stream_ch_new(dap_stream_ch_t* ch , void* arg); static void s_stream_ch_delete(dap_stream_ch_t* ch , void* arg); @@ -57,9 +82,11 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t* ch , void* arg); static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item); -static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size); -static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace); -static bool s_grace_period_finish(usages_in_grace_t *a_grace); +static bool s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size); +static bool s_grace_period_start(dap_chain_net_srv_grace_t *a_grace); +static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace); +static void s_set_usage_data_to_gdb(const dap_chain_net_srv_usage_t *a_usage); +static uint256_t s_calc_datoshi(const dap_chain_net_srv_usage_t *a_usage, uint256_t *a_prev); static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ch_chain_net_srv_pkt_error_t a_err){ @@ -69,8 +96,8 @@ static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ (dap_chain_net_srv_stream_session_t *)l_ch->stream->session->_inheritor : NULL; if (!l_srv_session){ - DAP_DELETE(a_grace->request); - DAP_DELETE(a_grace); + DAP_DEL_Z(a_grace->request); + DAP_DEL_Z(a_grace); return; } @@ -79,8 +106,8 @@ static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ log_it( L_WARNING, "Next receipt is rejected. Waiting until current limits is over."); DAP_DEL_Z(a_grace->usage->receipt_next); memset(&a_grace->usage->tx_cond_hash, 0, sizeof(a_grace->usage->tx_cond_hash)); - DAP_DELETE(a_grace->request); - DAP_DELETE(a_grace); + DAP_DEL_Z(a_grace->request); + DAP_DEL_Z(a_grace); return; } @@ -103,8 +130,8 @@ static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t); if (!l_item) { log_it(L_CRITICAL, "Memory allocation error"); - DAP_DELETE(a_grace->request); - DAP_DELETE(a_grace); + DAP_DEL_Z(a_grace->request); + DAP_DEL_Z(a_grace); return; } log_it(L_DEBUG, "Add client to banlist"); @@ -119,22 +146,20 @@ static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ } else if (l_srv_session->usage_active) dap_chain_net_srv_usage_delete(l_srv_session); - DAP_DELETE(a_grace->request); - DAP_DELETE(a_grace); + DAP_DEL_Z(a_grace->request); + DAP_DEL_Z(a_grace); } -// TODO: move this to net_srv -static usages_in_grace_t * s_grace_table = NULL; -static pthread_mutex_t s_ht_grace_table_mutex; /** * @brief dap_stream_ch_chain_net_init + * @param a_srv - inited service * @return */ -int dap_stream_ch_chain_net_srv_init(void) +int dap_stream_ch_chain_net_srv_init(dap_chain_net_srv_t *a_srv) { log_it(L_NOTICE,"Chain network services channel initialized"); dap_stream_ch_proc_add(DAP_STREAM_CH_NET_SRV_ID, s_stream_ch_new,s_stream_ch_delete,s_stream_ch_packet_in,s_stream_ch_packet_out); - pthread_mutex_init(&s_ht_grace_table_mutex, NULL); + pthread_mutex_init(&a_srv->grace_mutex, NULL); return 0; } @@ -175,17 +200,21 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch , void* arg) * @param ch * @param arg */ -void s_stream_ch_delete(dap_stream_ch_t* a_ch , void* a_arg) +void s_stream_ch_delete(dap_stream_ch_t* a_ch , UNUSED_ARG void *a_arg) { - (void) a_ch; - (void) a_arg; +// sanity check + dap_return_if_pass(!a_ch); +// func work log_it(L_DEBUG, "Stream ch chain net srv delete"); dap_chain_net_srv_stream_session_t * l_srv_session = a_ch && a_ch->stream && a_ch->stream->session ? (dap_chain_net_srv_stream_session_t *) a_ch->stream->session->_inheritor : NULL; dap_chain_net_srv_t * l_srv = l_srv_session && l_srv_session->usage_active ? dap_chain_net_srv_get(l_srv_session->usage_active->service->uid) : NULL; - if (l_srv) + if (l_srv) { + dap_chain_net_srv_usage_t *l_usage = dap_chain_net_srv_usage_find_unsafe(l_srv_session, l_srv_session->usage_active->id); + s_set_usage_data_to_gdb(l_usage); l_srv->callbacks.save_remain_service(l_srv, l_srv_session->usage_active->id, l_srv_session->usage_active->client); + } dap_chain_net_srv_call_closed_all(a_ch); if (a_ch->stream->session && a_ch->stream->session->_inheritor) @@ -195,6 +224,9 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch , void* a_arg) static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item) { +// sanity check + dap_return_val_if_pass(!a_item, false); +// func work log_it(L_DEBUG, "Unban client"); pthread_mutex_lock(a_item->ht_mutex); HASH_DEL(*(a_item->ht_head), a_item); @@ -203,33 +235,84 @@ static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item) return false; } -void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) +/** + * @brief create string with usage service statistic + * @return string with staticstic + */ +char *dap_stream_ch_chain_net_srv_create_statistic_report() +{ + size_t l_store_obj_count = 0; + dap_string_t *l_ret = dap_string_new("Service report:\n"); + dap_store_obj_t *l_store_obj = dap_global_db_get_all_raw_sync(SRV_STATISTIC_GDB_GROUP, &l_store_obj_count); + for (size_t i = 0; i < l_store_obj_count; ++i) { + if(l_store_obj[i].value_len != sizeof(client_statistic_value_t)) { + log_it(L_ERROR, "Error size check statistic in %zu raw of %zu, expected value len %zu received %zu", i + 1, l_store_obj_count, sizeof(client_statistic_value_t), l_store_obj[i].value_len); + DAP_DEL_Z(l_store_obj[i].group); + DAP_DEL_Z(l_store_obj[i].key); + DAP_DEL_Z(l_store_obj[i].value); + continue; + } + client_statistic_value_t *l_value = (client_statistic_value_t *)l_store_obj[i].value; + char *l_payed_datoshi = dap_chain_balance_print(l_value->payed.datoshi_value); + char *l_grace_datoshi = dap_chain_balance_print(l_value->grace.datoshi_value); + dap_string_append_printf( + l_ret, "SRV UID: %.18s\nClient pkey hash: %s\n " \ + "\tpayed:\n\t\tusing time:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes sent:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes received:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tunits used:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tdatoshi value:\t\t%s\n" \ + "\tgrace:\n\t\tusing time:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes sent:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes received:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tunits used:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tdatoshi value:\t\t%s\n" \ + "\tfree:\n\t\tusing time:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes sent:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tbytes received:\t\t%"DAP_UINT64_FORMAT_U"\n\t\tunits used:\t\t%"DAP_UINT64_FORMAT_U"\n", + l_store_obj[i].key, l_store_obj[i].key + 18, + l_value->payed.using_time, l_value->payed.bytes_sent, l_value->payed.bytes_received, l_value->payed.units, l_payed_datoshi, + l_value->grace.using_time, l_value->grace.bytes_sent, l_value->grace.bytes_received, l_value->grace.units, l_grace_datoshi, + l_value->free.using_time, l_value->free.bytes_sent, l_value->free.bytes_received, l_value->free.units + ); + DAP_DEL_Z(l_store_obj[i].group); + DAP_DEL_Z(l_store_obj[i].key); + DAP_DEL_Z(l_store_obj[i].value); + DAP_DEL_Z(l_payed_datoshi); + DAP_DEL_Z(l_grace_datoshi); + } + DAP_DEL_Z(l_store_obj); + return dap_string_free(l_ret, false); +} + +void dap_stream_ch_chain_net_srv_tx_cond_added_cb(UNUSED_ARG void *a_arg, UNUSED_ARG dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) { - UNUSED(a_ledger); - UNUSED(a_arg); - // TODO: 1. Get net_srv by srv_uid from tx_cond - // 2. Get usages in grace HT from service - usages_in_grace_t *l_item = NULL; - dap_hash_fast_t tx_cond_hash = {}; - dap_hash_fast((void*)a_tx, dap_chain_datum_tx_get_size(a_tx), &tx_cond_hash); - pthread_mutex_lock(&s_ht_grace_table_mutex); - HASH_FIND(hh, s_grace_table, &tx_cond_hash, sizeof(dap_hash_fast_t), l_item); - pthread_mutex_unlock(&s_ht_grace_table_mutex); +// sanity check + dap_return_if_pass(!a_tx); +// func work + dap_chain_net_srv_grace_usage_t *l_item = NULL; + dap_hash_fast_t l_tx_cond_hash = {0}; + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL); + if (!l_out_cond) { + log_it(L_ERROR, "Can't find dap_chain_tx_out_cond_t in dap_chain_datum_tx_t"); + return; + } + dap_chain_net_srv_t *l_net_srv = dap_chain_net_srv_get(l_out_cond->header.srv_uid); + if (!l_net_srv) { + log_it(L_ERROR, "Can't find dap_chain_net_srv_t uid 0x%016"DAP_UINT64_FORMAT_X"", l_out_cond->header.srv_uid.uint64); + return; + } + dap_hash_fast((void*)a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_cond_hash); + pthread_mutex_lock(&l_net_srv->grace_mutex); + HASH_FIND(hh, l_net_srv->grace_hash_tab, &l_tx_cond_hash, sizeof(dap_hash_fast_t), l_item); + pthread_mutex_unlock(&l_net_srv->grace_mutex); if (l_item){ log_it(L_INFO, "Found tx in ledger by notify. Finish grace."); // Stop timer - dap_timerfd_delete_mt(l_item->grace->stream_worker->worker, l_item->grace->timer_es_uuid); + dap_timerfd_delete_mt(l_item->grace->timer->worker, l_item->grace->timer->esocket_uuid); // finish grace + if(!l_item->grace->usage->service) + HASH_DEL(l_net_srv->grace_hash_tab, l_item); s_grace_period_finish(l_item); } } -static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size) +static bool s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size) { assert(a_ch); dap_stream_ch_chain_net_srv_pkt_error_t l_err; memset(&l_err, 0, sizeof(l_err)); - dap_chain_net_srv_t * l_srv = NULL; + dap_chain_net_srv_t *l_srv = NULL; dap_chain_net_srv_stream_session_t *l_srv_session = a_ch->stream && a_ch->stream->session ? (dap_chain_net_srv_stream_session_t *)a_ch->stream->session->_inheritor : NULL; @@ -239,15 +322,25 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_err.net_id.uint64 = a_request->hdr.net_id.uint64; l_err.srv_uid.uint64 = a_request->hdr.srv_uid.uint64; + if (dap_hash_fast_is_blank(&a_request->hdr.order_hash)){ + log_it( L_ERROR, "No order hash in request."); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND; + if(a_ch) + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); + if (l_srv && l_srv->callbacks.response_error) + l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); + return false; + } + if ( ! l_net ) { // Network not found - log_it( L_WARNING, "Can't find net with id 0x%016"DAP_UINT64_FORMAT_x"", a_request->hdr.srv_uid.uint64); + log_it( L_ERROR, "Can't find net with id 0x%016"DAP_UINT64_FORMAT_x"", a_request->hdr.srv_uid.uint64); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND; if(a_ch) dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); - return; + return false; } bool l_check_role = dap_chain_net_get_role(l_net).enums > NODE_ROLE_MASTER; // check role @@ -264,7 +357,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); - return; + return false; } dap_chain_net_srv_usage_t *l_usage = NULL; @@ -276,7 +369,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); - return; + return false; } l_err.usage_id = l_usage->id; @@ -290,7 +383,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); dap_chain_net_srv_usage_delete(l_srv_session); - return; + return false; } l_usage->client->stream_worker = a_ch->stream_worker; l_usage->client->ch = a_ch; @@ -302,8 +395,28 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_usage->service = l_srv; l_usage->client_pkey_hash = a_request->hdr.client_pkey_hash; + dap_chain_net_srv_price_t * l_price = NULL; + bool l_specific_order_free = false; + l_price = dap_chain_net_srv_get_price_from_order(l_srv, "srv_vpn", &a_request->hdr.order_hash); + if (!l_price){ + log_it(L_ERROR, "Can't get price from order!"); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND; + if(a_ch) + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); + if (l_srv && l_srv->callbacks.response_error) + l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); + DAP_DEL_Z(l_usage->client); + DAP_DEL_Z(l_usage); + return false; + } - if (l_srv->pricelist || !dap_hash_fast_is_blank(&a_request->hdr.order_hash)){ + if (IS_ZERO_256(l_price->value_datoshi)){ + l_specific_order_free = true; + } + + l_usage->price = l_price; + + if (!l_specific_order_free){ // not free service log_it( L_INFO, "Valid pricelist is founded. Start service in pay mode."); @@ -315,11 +428,10 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); dap_chain_net_srv_usage_delete(l_srv_session); - return; + return false; } - if (!dap_hash_fast_is_blank(&a_request->hdr.order_hash)) - l_usage->static_order_hash = a_request->hdr.order_hash; + l_usage->static_order_hash = a_request->hdr.order_hash; dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); if (!l_grace) { @@ -331,7 +443,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); DAP_DEL_Z(l_usage->client); DAP_DEL_Z(l_usage); - return; + return false; } l_grace->request = DAP_DUP_SIZE(a_request, a_request_size); if (!l_grace->request) { @@ -344,14 +456,15 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ DAP_DEL_Z(l_usage->client); DAP_DEL_Z(l_usage); DAP_DEL_Z(l_grace); - return; + return false; } l_grace->request_size = a_request_size; l_grace->ch_uuid = a_ch->uuid; l_grace->stream_worker = a_ch->stream_worker; l_grace->usage = l_usage; - s_grace_period_start(l_grace); - } else if (l_srv->allow_free_srv){ + if (!s_grace_period_start(l_grace)) + return false; + } else if (l_specific_order_free && l_srv->allow_free_srv){ // Start service for free log_it( L_INFO, "Can't find a valid pricelist. Service provide for free"); l_usage->is_free = true; @@ -367,7 +480,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); DAP_DEL_Z(l_usage->client); DAP_DEL_Z(l_usage); - return; + return false; } l_success->hdr.usage_id = l_usage->id; l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64; @@ -377,23 +490,25 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_usage->service->callbacks.response_success(l_usage->service, l_usage->id, l_usage->client, NULL, 0); DAP_DELETE(l_success); }else { - log_it( L_INFO, "No pricelists. Free service sharing is not allowed. Service stop."); + log_it( L_INFO, "Free service sharing is not allowed. Service stop. If you want to share service for free switch on this function in configuration file."); dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err)); if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); } - return; + return true; } -static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) +static bool s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) { - assert(a_grace); +// sanity check + dap_return_val_if_pass(!a_grace, false); +// func work dap_stream_ch_chain_net_srv_pkt_error_t l_err = { }; dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid); if (!l_ch){ s_grace_error(a_grace, l_err); - return; + return false; } dap_chain_net_t * l_net = a_grace->usage->net; @@ -409,7 +524,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) log_it( L_WARNING, "No Ledger"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ; s_grace_error(a_grace, l_err); - return; + return false; } l_tx = a_grace->usage->is_waiting_new_tx_cond ? NULL : dap_ledger_tx_find_by_hash(l_ledger, &a_grace->usage->tx_cond_hash); @@ -423,84 +538,45 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) log_it(L_INFO, "Client pkey is banned!"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH ; s_grace_error(a_grace, l_err);; - return; + return false; } } a_grace->usage->is_grace = true; if (a_grace->usage->receipt){ // If it is repeated grace - if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){ - log_it(L_MSG, "Get price from list."); - DL_FOREACH(a_grace->usage->service->pricelist, l_price) { - switch (l_price->units_uid.enm) { - case SERV_UNIT_MB: - case SERV_UNIT_SEC: - case SERV_UNIT_DAY: - case SERV_UNIT_KB: - case SERV_UNIT_B: - log_it(L_MSG, "Proper unit type %s found among available prices", - dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm)); - break; - default: - continue; - } - break; // proper price found, thus we exit from the loop - } - - if (!l_price) { - log_it(L_ERROR, "Price with proper unit type not found, check available orders and/or pricelists"); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE; - s_grace_error(a_grace, l_err); - return; - } - a_grace->usage->price = l_price; - } else { - log_it(L_MSG, "Get price from order %s.", - dap_chain_hash_fast_to_str_static(&a_grace->usage->static_order_hash)); - if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){ - switch (l_price->units_uid.enm) { - case SERV_UNIT_MB: - case SERV_UNIT_SEC: - case SERV_UNIT_DAY: - case SERV_UNIT_KB: - case SERV_UNIT_B: - log_it(L_MSG, "Proper unit type %s found among available prices", - dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm)); - a_grace->usage->price = l_price; - default: - DAP_DEL_Z(l_price); - } - } - } + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash); + log_it(L_MSG, "Using price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + l_price = a_grace->usage->price; if (!l_price) { log_it(L_ERROR, "Price with proper unit type not found, check available orders and/or pricelists"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE; s_grace_error(a_grace, l_err); - return; + return false; } - usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t)); + dap_chain_net_srv_grace_usage_t *l_item = DAP_NEW_Z(dap_chain_net_srv_grace_usage_t); if (!l_item) { log_it(L_CRITICAL, "Memory allocation error"); s_grace_error(a_grace, l_err); - return; + return false; } l_item->grace = a_grace; l_item->tx_cond_hash = a_grace->usage->tx_cond_hash; - pthread_mutex_lock(&s_ht_grace_table_mutex); - HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_item); - pthread_mutex_unlock(&s_ht_grace_table_mutex); - a_grace->timer_es_uuid = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000, - (dap_timerfd_callback_t)s_grace_period_finish, l_item)->esocket_uuid; - log_it(L_INFO, "Start grace timer %s.", a_grace->timer_es_uuid ? "successfuly." : "failed." ); + pthread_mutex_lock(&a_grace->usage->service->grace_mutex); + HASH_ADD(hh, a_grace->usage->service->grace_hash_tab, tx_cond_hash, sizeof(dap_hash_fast_t), l_item); + pthread_mutex_unlock(&a_grace->usage->service->grace_mutex); + a_grace->timer = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000, + (dap_timerfd_callback_t)s_grace_period_finish, l_item); + log_it(L_INFO, "Start grace timer %s.", a_grace->timer ? "successfuly." : "failed." ); } else { // Else if first grace at service start - usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t)); + dap_chain_net_srv_grace_usage_t *l_item = DAP_NEW_Z(dap_chain_net_srv_grace_usage_t); if (!l_item) { log_it(L_CRITICAL, "Memory allocation error"); s_grace_error(a_grace, l_err); - return; + return false; } l_item->grace = a_grace; l_item->tx_cond_hash = a_grace->usage->tx_cond_hash; @@ -510,7 +586,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t, l_success_size); if(!l_success) { - log_it(L_ERROR, "Memory allocation error in %s, line %d", __PRETTY_FUNCTION__, __LINE__); + log_it(L_CRITICAL, "Memory allocation error"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR; if(l_ch) dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); @@ -531,12 +607,12 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) a_grace->usage->service->callbacks.response_success(a_grace->usage->service, a_grace->usage->id, a_grace->usage->client, NULL, 0); DAP_DELETE(l_success); - pthread_mutex_lock(&s_ht_grace_table_mutex); - HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_item); - pthread_mutex_unlock(&s_ht_grace_table_mutex); - a_grace->timer_es_uuid = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000, - (dap_timerfd_callback_t)s_grace_period_finish, l_item)->esocket_uuid; - log_it(L_INFO, "Start grace timer %s.", a_grace->timer_es_uuid ? "successfuly." : "failed." ); + pthread_mutex_lock(&a_grace->usage->service->grace_mutex); + HASH_ADD(hh, a_grace->usage->service->grace_hash_tab, tx_cond_hash, sizeof(dap_hash_fast_t), l_item); + pthread_mutex_unlock(&a_grace->usage->service->grace_mutex); + a_grace->timer = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000, + (dap_timerfd_callback_t)s_grace_period_finish, l_item); + log_it(L_INFO, "Start grace timer %s.", a_grace->timer ? "successfuly." : "failed." ); } } @@ -545,7 +621,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; s_grace_error(a_grace, l_err); - return; + return false; } a_grace->usage->tx_cond = l_tx; @@ -556,7 +632,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) log_it( L_WARNING, "No conditioned output"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ; s_grace_error(a_grace, l_err); - return; + return false; } // Check cond output if it equesl or not to request @@ -565,7 +641,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) l_tx_out_cond->header.srv_uid.uint64 ); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID ; s_grace_error(a_grace, l_err); - return; + return false; } const char *l_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &a_grace->usage->tx_cond_hash); @@ -575,109 +651,69 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) log_it( L_ERROR, "Token ticker not found for tx cond hash %s", l_hash_str); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND; s_grace_error(a_grace, l_err); - return; + return false; } dap_stpcpy(a_grace->usage->token_ticker, l_ticker); - - if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){ - dap_chain_net_srv_price_t *l_price_tmp; - DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) { - if (!l_price_tmp){ - continue; - } - - if (l_price_tmp->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name); - continue; - } - - if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - continue; - } - - if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - continue; - } - - uint256_t l_unit_price = {}; - if (l_price_tmp->units != 0){ - DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - continue; - } - - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - l_price = l_price_tmp; - break; - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); - } + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash); + log_it(L_MSG, "Using price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + if ((l_price = a_grace->usage->price)){ + if (l_price->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(a_grace, l_err); + return false; } - } else { - log_it(L_MSG, "Get price from order %s.", - dap_chain_hash_fast_to_str_static(&a_grace->usage->static_order_hash)); - if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){ - if (l_price->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(a_grace, l_err); - return; - } - if (dap_strcmp(l_price->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(a_grace, l_err); - return; - } + if (dap_strcmp(l_price->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(a_grace, l_err); + return false; + } - if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(a_grace, l_err); - return; - } + if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(a_grace, l_err); + return false; + } - uint256_t l_unit_price = {}; - if (l_price->units != 0){ - DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(a_grace, l_err); - return; - } + uint256_t l_unit_price = {}; + if (l_price->units != 0){ + DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(a_grace, l_err); + return false; + } - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(a_grace, l_err); - return; - } + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(a_grace, l_err); + return false; } } + if ( !l_price ) { log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s", l_ticker, l_net->pub.name ); l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; s_grace_error(a_grace, l_err); - return; + return false; } - a_grace->usage->price = l_price; int ret; if ((ret = a_grace->usage->service->callbacks.requested(a_grace->usage->service, a_grace->usage->id, a_grace->usage->client, a_grace->request, a_grace->request_size)) != 0) { log_it( L_WARNING, "Request canceled by service callback, return code %d", ret); l_err.code = (uint32_t) ret ; s_grace_error(a_grace, l_err); - return; + return false; } // memcpy(&a_grace->usage->client_pkey_hash, &l_tx_out_cond->subtype.srv_pay.pkey_hash, sizeof(dap_chain_hash_fast_t)); @@ -686,36 +722,20 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) dap_stream_ch_chain_net_srv_remain_service_store_t* l_remain_service = NULL; l_remain_service = a_grace->usage->service->callbacks.get_remain_service(a_grace->usage->service, a_grace->usage->id, a_grace->usage->client); if (l_remain_service && !a_grace->usage->is_active && - (l_remain_service->limits_ts || l_remain_service->limits_bytes) && - l_remain_service->remain_units_type.enm == l_tx_out_cond->subtype.srv_pay.unit.enm){ + ((l_remain_service->limits_ts && l_tx_out_cond->subtype.srv_pay.unit.enm == SERV_UNIT_SEC) || + (l_remain_service->limits_bytes && l_tx_out_cond->subtype.srv_pay.unit.enm == SERV_UNIT_B))){ // Accept connection, set limits and start service dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_grace->usage->client->ch->stream->session->_inheritor; - char *l_unit_type_str = NULL; - switch(l_remain_service->remain_units_type.enm){ + switch(l_tx_out_cond->subtype.srv_pay.unit.enm){ case SERV_UNIT_SEC: - l_unit_type_str = dap_strdup_printf( "SEC"); - l_srv_session->limits_ts = l_remain_service->limits_ts; - break; - case SERV_UNIT_DAY: - l_unit_type_str = dap_strdup_printf( "DAY"); l_srv_session->limits_ts = l_remain_service->limits_ts; break; - case SERV_UNIT_MB: - l_unit_type_str = dap_strdup_printf( "MB"); - l_srv_session->limits_bytes = l_remain_service->limits_bytes; - break; - case SERV_UNIT_KB: - l_unit_type_str = dap_strdup_printf( "KB"); - l_srv_session->limits_bytes = l_remain_service->limits_bytes; - break; case SERV_UNIT_B: - l_unit_type_str = dap_strdup_printf( "B"); l_srv_session->limits_bytes = l_remain_service->limits_bytes; break; } - log_it(L_INFO, "User has %ld %s remain service. Start service without paying.", l_remain_service->limits_ts ? l_remain_service->limits_ts : l_remain_service->limits_bytes, l_unit_type_str); - DAP_DELETE(l_unit_type_str); + log_it(L_INFO, "User has %ld %s remain service. Start service without paying.", l_remain_service->limits_ts ? l_remain_service->limits_ts : l_remain_service->limits_bytes, dap_chain_srv_unit_enum_to_str(l_tx_out_cond->subtype.srv_pay.unit.enm)); size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t ); dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t, @@ -746,7 +766,7 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) DAP_DELETE(a_grace->request); DAP_DELETE(a_grace); DAP_DELETE(l_remain_service); - return; + return false; } } @@ -762,32 +782,126 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) DAP_DELETE(a_grace); } + + return true; +} + +/** + * @brief calculating used datoshi price by pricelist + * @param a_usage - usage data + * @param a_prev - prev value, calced add to prev + */ +uint256_t s_calc_datoshi(const dap_chain_net_srv_usage_t *a_usage, uint256_t *a_prev) +{ + uint256_t l_ret = {0}, l_prev = {0}, l_datosi_used = {0}; + uint64_t l_used = 0; + if (a_prev) + l_prev = *a_prev; + dap_return_val_if_pass(!a_usage, l_prev); + switch(a_usage->price->units_uid.enm){ + case SERV_UNIT_SEC: + l_used = dap_time_now() - a_usage->ts_created; + break; + case SERV_UNIT_B: + l_used = a_usage->client->bytes_received + a_usage->client->bytes_sent; + break; + } + MULT_256_256(a_usage->price->value_datoshi, GET_256_FROM_64(l_used), &l_ret); + DIV_256(l_ret, GET_256_FROM_64(a_usage->price->units), &l_datosi_used); + SUM_256_256(l_prev, l_datosi_used, &l_ret); + return l_ret; +} + +/** + * @brief set usage data to local GDB group + * @param a_usage - usage data + */ +void s_set_usage_data_to_gdb(const dap_chain_net_srv_usage_t *a_usage) +{ +// sanity check + dap_return_if_pass(!a_usage); +// func work + client_statistic_key_t l_bin_key = {0}; + client_statistic_value_t l_bin_value_new = {0}; + size_t l_value_size = 0; + // forming key + dap_sprintf(l_bin_key.key, "0x%016"DAP_UINT64_FORMAT_X"", a_usage->service->uid.uint64); + dap_chain_hash_fast_to_str_do(&a_usage->client_pkey_hash, l_bin_key.key + 18); + // check writed value + client_statistic_value_t *l_bin_value = (client_statistic_value_t *)dap_global_db_get_sync(SRV_STATISTIC_GDB_GROUP, l_bin_key.key, &l_value_size, NULL, NULL); + if (l_bin_value && l_value_size != sizeof(client_statistic_value_t)) { + log_it(L_ERROR, "Wrong srv client_statistic size in GDB. Expecting %zu, getted %zu", sizeof(client_statistic_value_t), l_value_size); + //dap_global_db_set(SRV_STATISTIC_GDB_GROUP, l_bin_key.key, &l_bin_value_new, sizeof(client_statistic_value_t), false, NULL, NULL); value size update + DAP_DEL_Z(l_bin_value); + return; + } + if (l_bin_value) { + l_bin_value_new = *l_bin_value; + } + // forming new data + if (a_usage->is_grace) { + l_bin_value_new.grace.using_count += 1; + l_bin_value_new.grace.using_time += dap_time_now() - a_usage->ts_created; + l_bin_value_new.grace.bytes_received += a_usage->client->bytes_received; + l_bin_value_new.grace.bytes_sent += a_usage->client->bytes_sent; + l_bin_value_new.grace.datoshi_value = s_calc_datoshi(a_usage, l_bin_value ? &l_bin_value->grace.datoshi_value : NULL); + } else if (a_usage->is_free) { + l_bin_value_new.free.using_time += dap_time_now() - a_usage->ts_created; + l_bin_value_new.free.bytes_received += a_usage->client->bytes_received; + l_bin_value_new.free.bytes_sent += a_usage->client->bytes_sent; + } else if (a_usage->is_active) { + l_bin_value_new.payed.using_time += dap_time_now() - a_usage->ts_created; + l_bin_value_new.payed.bytes_received += a_usage->client->bytes_received; + l_bin_value_new.payed.bytes_sent += a_usage->client->bytes_sent; + l_bin_value_new.payed.datoshi_value = s_calc_datoshi(a_usage, l_bin_value ? &l_bin_value->payed.datoshi_value : NULL); + } + dap_global_db_set(SRV_STATISTIC_GDB_GROUP, l_bin_key.key, &l_bin_value_new, sizeof(client_statistic_value_t), false, NULL, NULL); + + DAP_DEL_Z(l_bin_value); } -static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) +static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace_item) { - assert(a_grace_item); + dap_return_val_if_pass(!a_grace_item || !a_grace_item->grace, false); dap_stream_ch_chain_net_srv_pkt_error_t l_err = { }; dap_chain_net_srv_grace_t *l_grace = a_grace_item->grace; + dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get(l_grace->request->hdr.srv_uid); + +#define RET_WITH_DEL_A_GRACE(error) do \ + {\ + s_set_usage_data_to_gdb(l_grace->usage); \ + if (error) { \ + l_err.code = error ; \ + s_grace_error(l_grace, l_err); \ + } \ + DAP_DELETE(a_grace_item); \ + return false; \ + } \ + while(0); - dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_grace->stream_worker, l_grace->ch_uuid); + pthread_mutex_lock(&l_srv->grace_mutex); + HASH_DEL(l_srv->grace_hash_tab, a_grace_item); + pthread_mutex_unlock(&l_srv->grace_mutex); -#define RET_WITH_DEL_A_GRACE do \ - { HASH_DEL(s_grace_table, a_grace_item); DAP_DELETE(a_grace_item); return false; } \ - while(0); + dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_grace->stream_worker, l_grace->ch_uuid); - if (!l_ch){ + if (!l_ch || l_srv != l_grace->usage->service) { + l_err.code = !l_ch ? DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND : + DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_CH_NOT_FOUND; s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + DAP_DELETE(a_grace_item); + return false; } if (l_grace->usage->is_waiting_new_tx_cond){ log_it(L_INFO, "No new tx cond!"); - s_grace_error(l_grace, l_err); l_grace->usage->is_waiting_new_tx_cond = false; - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_NEW_COND); } + bool l_waiting_new_tx_in_ledger = l_grace->usage->is_waiting_new_tx_cond_in_ledger; + l_grace->usage->is_waiting_new_tx_cond_in_ledger = false; + dap_chain_net_t * l_net = l_grace->usage->net; l_err.net_id.uint64 = l_net->pub.id.uint64; @@ -799,23 +913,17 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) if ( !l_ledger ){ // No ledger log_it( L_WARNING, "No Ledger"); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER); } log_it(L_INFO, "Grace period is over! Check tx in ledger."); l_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_grace->usage->tx_cond_hash); if ( ! l_tx ){ // No tx cond transaction, start grace-period log_it( L_WARNING, "No tx cond transaction"); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND); } else { // Start service in normal pay mode if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE); } log_it(L_INFO, "Tx is found in ledger."); @@ -825,18 +933,14 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) if ( ! l_tx_out_cond ) { // No conditioned output log_it( L_WARNING, "No conditioned output"); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT); } // Check cond output if it equesl or not to request if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, l_grace->usage->service->uid)) { log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X, l_tx_out_cond->header.srv_uid.uint64 ); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID ; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID); } dap_chain_net_srv_price_t * l_price = NULL; @@ -844,106 +948,53 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) l_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_grace->usage->tx_cond_hash); dap_stpcpy(l_grace->usage->token_ticker, l_ticker); - if (dap_hash_fast_is_blank(&l_grace->usage->static_order_hash)){ - dap_chain_net_srv_price_t *l_price_tmp; - DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) { - if (!l_price_tmp){ - continue; - } - - if (l_price_tmp->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name); - continue; - } - - if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - continue; - } - - if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - continue; - } - - uint256_t l_unit_price = {}; - if (l_price_tmp->units != 0){ - DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - continue; - } - - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - l_price = l_price_tmp; - break; - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); - } + + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_grace->usage->static_order_hash); + log_it(L_MSG, "Using price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + if ((l_price = l_grace->usage->price)){ + if (l_price->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); } - } else { - log_it(L_MSG, "Get price from order %s.", - dap_chain_hash_fast_to_str_static(&l_grace->usage->static_order_hash)); - if ((l_price = dap_chain_net_srv_get_price_from_order(l_grace->usage->service, "srv_vpn", &l_grace->usage->static_order_hash))){ - if (l_price->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; - } - if (dap_strcmp(l_price->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; - } + if (dap_strcmp(l_price->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); + } - if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; - } + if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm) { + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); + } - uint256_t l_unit_price = {}; - if (l_price->units != 0){ - DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; - } + uint256_t l_unit_price = {}; + if (l_price->units != 0){ + DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); + } - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; - } + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); } } + if ( !l_price ) { log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s", l_ticker, l_net->pub.name ); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN); } - l_grace->usage->price = l_price; - int ret; if ((ret = l_grace->usage->service->callbacks.requested(l_grace->usage->service, l_grace->usage->id, l_grace->usage->client, l_grace->request, l_grace->request_size)) != 0) { log_it( L_WARNING, "Request canceled by service callback, return code %d", ret); - l_err.code = (uint32_t) ret ; - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE((uint32_t) ret); } if (!l_grace->usage->receipt){ @@ -951,36 +1002,19 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) dap_stream_ch_chain_net_srv_remain_service_store_t* l_remain_service = NULL; l_remain_service = l_grace->usage->service->callbacks.get_remain_service(l_grace->usage->service, l_grace->usage->id, l_grace->usage->client); if (l_remain_service && !l_grace->usage->is_active && - (l_remain_service->limits_ts || l_remain_service->limits_bytes) && - l_remain_service->remain_units_type.enm == l_tx_out_cond->subtype.srv_pay.unit.enm){ + ((l_remain_service->limits_ts && l_tx_out_cond->subtype.srv_pay.unit.enm == SERV_UNIT_SEC) || + (l_remain_service->limits_bytes && l_tx_out_cond->subtype.srv_pay.unit.enm == SERV_UNIT_B))){ // Accept connection, set limits and start service dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) l_grace->usage->client->ch->stream->session->_inheritor; - char *l_unit_type_str = NULL; - switch(l_remain_service->remain_units_type.enm){ + switch(l_tx_out_cond->subtype.srv_pay.unit.enm){ case SERV_UNIT_SEC: - l_unit_type_str = dap_strdup_printf( "SEC"); - l_srv_session->limits_ts = l_remain_service->limits_ts; - break; - case SERV_UNIT_DAY: - l_unit_type_str = dap_strdup_printf( "DAY"); l_srv_session->limits_ts = l_remain_service->limits_ts; break; - case SERV_UNIT_MB: - l_unit_type_str = dap_strdup_printf( "MB"); - l_srv_session->limits_bytes = l_remain_service->limits_bytes; - break; - case SERV_UNIT_KB: - l_unit_type_str = dap_strdup_printf( "KB"); - l_srv_session->limits_bytes = l_remain_service->limits_bytes; - break; case SERV_UNIT_B: - l_unit_type_str = dap_strdup_printf( "B"); l_srv_session->limits_bytes = l_remain_service->limits_bytes; break; } - - log_it(L_INFO, "User has %ld %s remain service. Start service without paying.", l_remain_service->limits_ts ? l_remain_service->limits_ts : l_remain_service->limits_bytes, l_unit_type_str); - DAP_DELETE(l_unit_type_str); + log_it(L_INFO, "User has %ld %s remain service. Start service without paying.", l_remain_service->limits_ts ? l_remain_service->limits_ts : l_remain_service->limits_bytes, dap_chain_srv_unit_enum_to_str(l_tx_out_cond->subtype.srv_pay.unit.enm)); size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t ); dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t, @@ -1008,12 +1042,9 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) sizeof(dap_chain_datum_tx_receipt_t) + l_grace->usage->receipt->size + l_grace->usage->receipt->exts_size); DAP_DELETE(l_success); } - DAP_DELETE(l_grace->request); DAP_DELETE(l_grace); DAP_DELETE(l_remain_service); - HASH_DEL(s_grace_table, a_grace_item); - DAP_DELETE(a_grace_item); - return false; + RET_WITH_DEL_A_GRACE(0); } } @@ -1027,14 +1058,19 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) } else { log_it(L_INFO, "Send first receipt to sign"); l_grace->usage->receipt = dap_chain_net_srv_issue_receipt(l_grace->usage->service, l_grace->usage->price, NULL, 0); - dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST, + if (l_grace->usage->receipt ) + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST, l_grace->usage->receipt, l_grace->usage->receipt->size); - RET_WITH_DEL_A_GRACE; + else{ + log_it(L_WARNING, "Can't sign the receipt."); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNDEFINED); + } + + RET_WITH_DEL_A_GRACE(0); } if (!l_receipt) { log_it(L_ERROR, "Receipt is not present, finish grace"); - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_IS_NOT_PRESENT); } size_t l_receipt_size = l_receipt->size; @@ -1042,11 +1078,10 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( l_receipt, l_receipt_size, 1); if ( ! l_receipt_sign ){ log_it(L_WARNING, "Tx already in chain, but receipt is not signed by client. Finish grace and wait receipt sign responce."); - s_grace_error(l_grace, l_err); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN); } dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str); - dap_global_db_set("local.receipts", l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL); + dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL); // Form input transaction char *l_hash_str = dap_hash_fast_to_str_new(&l_grace->usage->tx_cond_hash); log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt", l_hash_str); @@ -1055,31 +1090,28 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(l_grace->usage->net, &l_grace->usage->tx_cond_hash, l_grace->usage->price->wallet_addr, l_grace->usage->price->receipt_sign_cert->enc_key, l_receipt, "hex", &ret_status); -// DAP_DEL_Z(l_wallet_addr); if (!ret_status) { dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_grace->usage->tx_cond_hash); log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str); DAP_DELETE(l_tx_in_hash_str); - - }else{ + } else { if(ret_status == DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH){ -// memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash)); -// DAP_DEL_Z(l_grace->usage->receipt_next); log_it(L_ERROR, "Tx cond have not enough funds"); + if (l_waiting_new_tx_in_ledger){ + log_it(L_ERROR, "New tx cond have not enough funds. Waiting for end of service."); + RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NEW_TX_COND_NOT_ENOUGH); + } + dap_chain_net_srv_grace_t* l_grace_new = DAP_NEW_Z(dap_chain_net_srv_grace_t); if (!l_grace_new) { log_it(L_CRITICAL, "Memory allocation error"); - DAP_DELETE(a_grace_item->grace->request); - DAP_DEL_Z(a_grace_item->grace); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(0); } // Parse the request l_grace_new->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t)); if (!l_grace_new->request) { log_it(L_CRITICAL, "Memory allocation error"); - DAP_DELETE(a_grace_item->grace->request); - DAP_DEL_Z(a_grace_item->grace); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(0); } l_grace_new->request->hdr.net_id = a_grace_item->grace->usage->net->pub.id; dap_stpcpy(l_grace_new->request->hdr.token, a_grace_item->grace->usage->token_ticker); @@ -1090,17 +1122,16 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) l_grace_new->stream_worker = a_grace_item->grace->usage->client->ch->stream_worker; l_grace_new->usage = a_grace_item->grace->usage; l_grace_new->usage->is_waiting_new_tx_cond = true; - s_grace_period_start(l_grace_new); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH; - dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); - if (l_grace->usage->service->callbacks.response_error) + if (s_grace_period_start(l_grace_new)){ + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH; + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); + if (l_grace->usage->service->callbacks.response_error) l_grace->usage->service->callbacks.response_error(l_grace->usage->service,l_grace->usage->id, l_grace->usage->client,&l_err,sizeof (l_err)); + } DAP_DELETE(l_tx_in_hash_str); - DAP_DELETE(a_grace_item->grace->request); - DAP_DEL_Z(a_grace_item->grace); - RET_WITH_DEL_A_GRACE; - }else{ + RET_WITH_DEL_A_GRACE(0); + } else { log_it(L_ERROR, "Can't create input tx cond transaction!"); memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash)); if (l_grace->usage->receipt_next){ @@ -1117,9 +1148,7 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) } } l_grace->usage->is_grace = false; - DAP_DELETE(a_grace_item->grace->request); - DAP_DEL_Z(a_grace_item->grace); - RET_WITH_DEL_A_GRACE; + RET_WITH_DEL_A_GRACE(0); #undef RET_WITH_DEL_A_GRACE } @@ -1324,7 +1353,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) // Store receipt if any problems with transactions char *l_receipt_hash_str; dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str); - dap_global_db_set("local.receipts", l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL); + dap_global_db_set(SRV_RECEIPTS_GDB_GROUP, l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL); size_t l_success_size; if (!l_usage->is_grace) { // Form input transaction @@ -1340,7 +1369,6 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str); DAP_DELETE(l_tx_in_hash_str); }else{ - // TODO add ret status handling/ if tx not found start grace again dap_chain_net_srv_grace_t *l_grace = NULL; switch(ret_status){ case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_FIND_FINAL_TX_HASH: @@ -1399,11 +1427,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) l_grace->ch_uuid = a_ch->uuid; l_grace->stream_worker = a_ch->stream_worker; l_grace->usage = l_usage; - s_grace_period_start(l_grace); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH; - dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); - if (l_usage->service->callbacks.response_error) - l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err)); + if (s_grace_period_start(l_grace)){ + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH; + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); + if (l_usage->service->callbacks.response_error) + l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err)); + } DAP_DELETE(l_tx_in_hash_str); break; case DAP_CHAIN_MEMPOOL_RET_STATUS_BAD_ARGUMENTS: @@ -1523,16 +1552,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) } l_usage->is_waiting_new_tx_cond = false; + l_usage->is_waiting_new_tx_cond_in_ledger = true; dap_stream_ch_chain_net_srv_pkt_error_t l_err = { }; - usages_in_grace_t *l_curr_grace_item = NULL; - pthread_mutex_lock(&s_ht_grace_table_mutex); - HASH_FIND(hh, s_grace_table, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item); - pthread_mutex_unlock(&s_ht_grace_table_mutex); + dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get(l_responce->hdr.srv_uid); + dap_chain_net_srv_grace_usage_t *l_curr_grace_item = NULL; + pthread_mutex_lock(&l_srv->grace_mutex); + HASH_FIND(hh, l_srv->grace_hash_tab, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item); + pthread_mutex_unlock(&l_srv->grace_mutex); if (dap_hash_fast_is_blank(&l_responce->hdr.tx_cond)){ //if new tx cond creation failed tx_cond in responce will be blank if (l_curr_grace_item){ - HASH_DEL(s_grace_table, l_curr_grace_item); - dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid); + HASH_DEL(l_srv->grace_hash_tab, l_curr_grace_item); + dap_timerfd_delete_mt(l_curr_grace_item->grace->timer->worker, l_curr_grace_item->grace->timer->esocket_uuid); s_grace_error(l_curr_grace_item->grace, l_err); DAP_DEL_Z(l_curr_grace_item); } @@ -1545,7 +1576,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if (l_curr_grace_item){ log_it(L_INFO, "Found tx in ledger by net tx responce handler. Finish waiting new tx grace period."); // Stop timer - dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid); + dap_timerfd_delete_mt(l_curr_grace_item->grace->timer->worker, l_curr_grace_item->grace->timer->esocket_uuid); // finish grace l_usage->tx_cond_hash = l_responce->hdr.tx_cond; l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond; @@ -1555,11 +1586,11 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if (l_curr_grace_item){ l_curr_grace_item->grace->usage->tx_cond_hash = l_responce->hdr.tx_cond; l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond; - pthread_mutex_lock(&s_ht_grace_table_mutex); - HASH_DEL(s_grace_table, l_curr_grace_item); + pthread_mutex_lock(&l_srv->grace_mutex); + HASH_DEL(l_srv->grace_hash_tab, l_curr_grace_item); l_curr_grace_item->tx_cond_hash = l_responce->hdr.tx_cond; - HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item); - pthread_mutex_unlock(&s_ht_grace_table_mutex); + HASH_ADD(hh, l_srv->grace_hash_tab, tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item); + pthread_mutex_unlock(&l_srv->grace_mutex); } } @@ -1590,8 +1621,6 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) */ static bool s_stream_ch_packet_out(dap_stream_ch_t* a_ch , void* a_arg) { - (void) a_arg; - dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); // Callback should note that after write action it should restore write flag if it has more data to send on next iteration dap_chain_net_srv_call_write_all( a_ch); diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h deleted file mode 100644 index 18d3f1a112..0000000000 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Authors: - * Alexander Lysikov <alexander.lysikov@demlabs.net> - * Cellframe https://cellframe.net - * DeM Labs Inc. https://demlabs.net - * Copyright (c) 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/>. - */ - -#pragma once - -#include <pthread.h> -#include "dap_stream_worker.h" -#include "dap_stream_ch_pkt.h" -#include "dap_chain_common.h" - -#include "dap_chain.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.h" -#include "dap_chain_datum_tx_out_cond.h" -#include "dap_chain_datum_tx_receipt.h" -#include "dap_chain_mempool.h" -#include "dap_common.h" - -typedef struct dap_stream_ch_chain_net_srv dap_stream_ch_chain_net_srv_t; - -typedef void (*dap_stream_ch_chain_net_srv_callback_packet_t)(dap_stream_ch_chain_net_srv_t *, uint8_t, - dap_stream_ch_pkt_t *, void *); - -typedef struct dap_stream_ch_chain_net_srv { - dap_chain_net_srv_uid_t srv_uid; - dap_stream_ch_t *ch; - dap_stream_ch_uuid_t ch_uuid; - dap_stream_ch_chain_net_srv_callback_packet_t notify_callback; - void *notify_callback_arg; -} dap_stream_ch_chain_net_srv_t; - -#define DAP_STREAM_CH_CHAIN_NET_SRV(a) ((dap_stream_ch_chain_net_srv_t *) ((a)->internal) ) -#define DAP_STREAM_CH_NET_SRV_ID 'R' - -int dap_stream_ch_chain_net_srv_init(void); - -void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); diff --git a/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv.h index 637939a8ff..7f1970fb4f 100644 --- a/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv.h +++ b/modules/channel/chain-net-srv/include/dap_stream_ch_chain_net_srv.h @@ -1,33 +1,62 @@ /* * Authors: - * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * Alexander Lysikov <alexander.lysikov@demlabs.net> + * Cellframe https://cellframe.net * DeM Labs Inc. https://demlabs.net - * CellFrame https://cellframe.net - * Sources https://gitlab.demlabs.net/cellframe - * Copyright (c) 2017-2019 + * Copyright (c) 2020 * All rights reserved. - This file is part of DAP (Demlabs Application Protocol) the open source project + This file is part of CellFrame SDK the open source project - DAP (Demlabs Application Protocol) 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 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. + 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 DAP based project. If not, see <http://www.gnu.org/licenses/>. -*/ + 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/>. + */ #pragma once +#include <pthread.h> +#include "dap_stream_worker.h" +#include "dap_stream_ch_pkt.h" #include "dap_chain_common.h" -int dap_stream_ch_chain_net_srv_init(void); -void dap_stream_ch_chain_net_srv_deinit(void); - -void dap_stream_ch_chain_net_srv_set_srv_uid(dap_stream_ch_t* a_ch, dap_chain_net_srv_uid_t a_srv_uid); +#include "dap_chain.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.h" +#include "dap_chain_datum_tx_out_cond.h" +#include "dap_chain_datum_tx_receipt.h" +#include "dap_chain_mempool.h" +#include "dap_common.h" +#include "dap_chain_net_srv.h" + +typedef struct dap_stream_ch_chain_net_srv dap_stream_ch_chain_net_srv_t; + +typedef void (*dap_stream_ch_chain_net_srv_callback_packet_t)(dap_stream_ch_chain_net_srv_t *, uint8_t, + dap_stream_ch_pkt_t *, void *); + +typedef struct dap_stream_ch_chain_net_srv { + dap_chain_net_srv_uid_t srv_uid; + dap_stream_ch_t *ch; + dap_stream_ch_uuid_t ch_uuid; + dap_stream_ch_chain_net_srv_callback_packet_t notify_callback; + void *notify_callback_arg; +} dap_stream_ch_chain_net_srv_t; + +#define DAP_STREAM_CH_CHAIN_NET_SRV(a) ((dap_stream_ch_chain_net_srv_t *) ((a)->internal) ) +#define DAP_STREAM_CH_NET_SRV_ID 'R' + +int dap_stream_ch_chain_net_srv_init(dap_chain_net_srv_t *a_srv); + +void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); +char *dap_stream_ch_chain_net_srv_create_statistic_report(); diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index b2c9a96cd9..831f04a10e 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -190,7 +190,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg) dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); log_it(L_ERROR, "Invalid net id in packet"); } else { - dap_chain_net_srv_order_t * l_orders = NULL; + dap_list_t * l_orders = NULL; dap_enc_key_t * enc_key_pvt = NULL; dap_chain_t *l_chain = NULL; DL_FOREACH(l_net->pub.chains, l_chain) @@ -236,20 +236,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg) //strncpy(send->header.data,(uint8_t*)l_ch_chain_net_pkt->data,10); flags = (l_net->pub.mempool_autoproc) ? flags | A_PROC : flags & ~A_PROC; - dap_chain_net_srv_order_find_all_by(l_net,SERV_DIR_UNDEFINED,l_uid, - l_price_unit,NULL,l_price_min,l_price_max,&l_orders,&l_orders_num); - size_t l_orders_size = 0; - for (size_t i = 0; i< l_orders_num; i++){ - dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) (((byte_t*) l_orders) + l_orders_size); - l_orders_size += dap_chain_net_srv_order_get_size(l_order); - if(l_order->node_addr.uint64 == l_cur_node_addr.uint64) - { - flags = flags | F_ORDR; - break; + if (dap_chain_net_srv_order_find_all_by(l_net,SERV_DIR_UNDEFINED,l_uid, + l_price_unit,NULL,l_price_min,l_price_max,&l_orders,&l_orders_num)==0){ + for (dap_list_t *l_temp = l_orders;l_temp; l_temp = l_orders->next){ + dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) l_temp->data; + if(l_order->node_addr.uint64 == l_cur_node_addr.uint64) + { + flags = flags | F_ORDR; + break; + } } + dap_list_free_full(l_orders, NULL); } - if (l_orders_num) - DAP_DELETE(l_orders); bool auto_online = dap_config_get_item_bool_default( g_config, "general", "auto_online", false ); bool auto_update = false; if((system("systemctl status cellframe-updater.service") == 768) && (system("systemctl status cellframe-updater.timer") == 0)) diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index b5e90e48a0..1dbb358441 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -839,7 +839,6 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c { log_it(L_ERROR, "Illformed DATUM type %d, TSD section is out-of-buffer (%" DAP_UINT64_FORMAT_U " vs %zu)", l_emission->hdr.type, l_emission->data.type_auth.tsd_total_size, l_emission_size); - dap_string_append_printf(a_str_out, " Skip incorrect or illformed DATUM"); break; } diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index d07547d443..fe9cebf3cc 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -126,10 +126,7 @@ extern const dap_chain_addr_t c_dap_chain_addr_blank; enum dap_chain_srv_unit_enum { SERV_UNIT_UNDEFINED = 0 , - SERV_UNIT_MB = 0x00000001, // megabytes SERV_UNIT_SEC = 0x00000002, // seconds - SERV_UNIT_DAY = 0x00000003, // days - SERV_UNIT_KB = 0x00000010, // kilobytes SERV_UNIT_B = 0x00000011, // bytes SERV_UNIT_PCS = 0x00000022 // pieces }; @@ -138,28 +135,19 @@ typedef uint32_t dap_chain_srv_unit_enum_t; DAP_STATIC_INLINE const char *dap_chain_srv_unit_enum_to_str(dap_chain_srv_unit_enum_t a_unit_enum) { switch (a_unit_enum) { - case SERV_UNIT_UNDEFINED: return "SERV_UNIT_UNDEFINED"; - case SERV_UNIT_MB: return "SERV_UNIT_MB"; - case SERV_UNIT_SEC: return "SERV_UNIT_SEC"; - case SERV_UNIT_DAY: return "SERV_UNIT_DAY"; - case SERV_UNIT_KB: return "SERV_UNIT_KB"; - case SERV_UNIT_B: return "SERV_UNIT_B"; - case SERV_UNIT_PCS: return "SERV_UNIT_PCS"; + case SERV_UNIT_UNDEFINED: return "UNDEFINED"; + case SERV_UNIT_SEC: return "SEC"; + case SERV_UNIT_B: return "B"; + case SERV_UNIT_PCS: return "PCS"; default: return "UNDEFINED"; } } -DAP_STATIC_INLINE dap_chain_srv_unit_enum_t dap_chain_srv_str_to_unit_enum(char* a_price_unit_str) { +DAP_STATIC_INLINE dap_chain_srv_unit_enum_t dap_chain_srv_str_to_unit_enum(const char* a_price_unit_str) { if (!a_price_unit_str) return SERV_UNIT_UNDEFINED; - if (!dap_strcmp(a_price_unit_str, "MB")){ - return SERV_UNIT_MB; - } else if (!dap_strcmp(a_price_unit_str, "SEC")){ + if (!dap_strcmp(a_price_unit_str, "SEC")){ return SERV_UNIT_SEC; - } else if (!dap_strcmp(a_price_unit_str, "DAY")){ - return SERV_UNIT_DAY; - } else if (!dap_strcmp(a_price_unit_str, "KB")){ - return SERV_UNIT_KB; } else if (!dap_strcmp(a_price_unit_str, "B")){ return SERV_UNIT_B; } else if (!dap_strcmp(a_price_unit_str, "PCS")){ diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 3a6bc21aea..67264de681 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -5936,12 +5936,10 @@ const char *dap_ledger_tx_get_main_ticker(dap_ledger_t *a_ledger, dap_chain_datu { const char *l_main_ticker = NULL; dap_chain_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); - int l_rc = dap_ledger_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, (char **)&l_main_ticker); - + int l_rc = dap_ledger_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, (char **)&l_main_ticker); + if (l_rc == DAP_LEDGER_TX_ALREADY_CACHED) - { l_main_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_hash); - } if (a_ledger_rc) *a_ledger_rc = l_rc; diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index c8b0298dc2..05e8dc7b92 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -1755,8 +1755,8 @@ static int s_cli_net(int argc, char **argv, void **reply) "Can't save public key hash %s in database", l_hash_hex_str); DAP_DELETE(l_hash_hex_str); return DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE; - } - DAP_DELETE(l_hash_hex_str); + } else + DAP_DELETE(l_hash_hex_str); } else{ json_object_put(l_jobj_return); dap_json_rpc_error_add(DAP_CHAIN_NET_JSON_RPC_CAN_NOT_SAVE_PUBLIC_KEY_IN_DATABASE, "%s", diff --git a/modules/net/dap_chain_net_voting.c b/modules/net/dap_chain_net_voting.c index 590e07e9a2..ad54206ed9 100644 --- a/modules/net/dap_chain_net_voting.c +++ b/modules/net/dap_chain_net_voting.c @@ -296,6 +296,7 @@ bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_t *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.delegate_key_required_offset)){ if (!dap_chain_net_srv_stake_check_pkey_hash(&pkey_hash)){ log_it(L_ERROR, "The voting required a delegated key."); + dap_list_free(l_signs_list); return false; } } @@ -336,6 +337,7 @@ bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_t } l_temp = l_temp->next; } + dap_list_free(l_signs_list); } uint256_t l_weight = {}; @@ -422,6 +424,7 @@ bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_t dap_chain_net_vote_t *l_vote_item = DAP_NEW_Z(dap_chain_net_vote_t); if (!l_vote_item){ log_it(L_CRITICAL, "Memory allocate_error!"); + dap_list_free(l_signs_list); return false; } l_vote_item->vote_hash = l_hash; @@ -438,15 +441,18 @@ bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_t l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); log_it(L_ERROR, "Vote is changed."); + dap_list_free(l_signs_list); return true; } else { log_it(L_ERROR, "The voting don't allow change your vote."); + dap_list_free(l_signs_list); DAP_DELETE(l_vote_item); return false; } } l_temp = l_temp->next; } + dap_list_free(l_signs_list); log_it(L_INFO, "Vote is accepted."); l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); } @@ -591,16 +597,12 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) return -103; } - dap_time_t *l_time_expire = NULL; - if(l_voting_expire_str){ - dap_time_t l_expired_time = dap_time_from_str_rfc822(l_voting_expire_str); - l_time_expire = &l_expired_time; - } - uint64_t *l_max_count = NULL; - if (l_max_votes_count_str) { - uint64_t ll_max_count = atoll(l_max_votes_count_str); - l_max_count = &ll_max_count; - } + dap_time_t l_time_expire = 0; + if (l_voting_expire_str) + l_time_expire = dap_time_from_str_rfc822(l_voting_expire_str); + uint64_t l_max_count = 0; + if (l_max_votes_count_str) + l_max_count = strtoul(l_max_votes_count_str, NULL, 10); bool l_is_delegated_key = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-delegated_key_required", NULL) ? true : false; bool l_is_vote_changing_allowed = dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-vote_changing_allowed", NULL) ? true : false; @@ -613,6 +615,8 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) char *l_hash_ret = NULL; int res = dap_chain_net_vote_create(l_question_str, l_options_list, l_time_expire, l_max_count, l_value_fee, l_is_delegated_key, l_is_vote_changing_allowed, l_wallet_fee, l_net, l_hash_out_type, &l_hash_ret); + dap_list_free(l_options_list); + dap_chain_wallet_close(l_wallet_fee); switch (res) { case DAP_CHAIN_NET_VOTE_CREATE_OK: { @@ -743,12 +747,14 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) return -112; } - uint64_t l_option_idx_count = atoll(l_option_idx_str); + uint64_t l_option_idx_count = strtoul(l_option_idx_str, NULL, 10); char *l_hash_tx; int res = dap_chain_net_vote_voting(l_cert, l_value_fee, l_wallet_fee, l_voting_hash, l_option_idx_count, l_net, l_hash_out_type, &l_hash_tx); + dap_chain_wallet_close(l_wallet_fee); + switch (res) { case DAP_CHAIN_NET_VOTE_VOTING_OK: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Datum %s successfully added to mempool", l_hash_tx); @@ -1124,8 +1130,8 @@ static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_has return 1; } -int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t *a_expire_vote, - uint64_t *a_max_vote, uint256_t a_fee, bool a_delegated_key_required, +int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t a_expire_vote, + uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required, bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet, dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output) { @@ -1196,9 +1202,9 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap } // add voting expire time if needed - if(a_expire_vote){ - dap_time_t l_expired_vote = *a_expire_vote; - if (*a_expire_vote < dap_time_now()){ + if(a_expire_vote != 0){ + dap_time_t l_expired_vote = a_expire_vote; + if (l_expired_vote < dap_time_now()){ dap_chain_datum_tx_delete(l_tx); return DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME; } @@ -1213,8 +1219,8 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap } // Add vote max count if needed - if(a_max_vote){ - dap_chain_tx_tsd_t* l_max_votes_item = dap_chain_datum_voting_max_votes_count_tsd_create(*a_max_vote); + if (a_max_vote != 0) { + dap_chain_tx_tsd_t* l_max_votes_item = dap_chain_datum_voting_max_votes_count_tsd_create(a_max_vote); if(!l_max_votes_item){ dap_chain_datum_tx_delete(l_tx); return DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_EXPIRE_TIME; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 1363047b38..785eb810a5 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -5022,7 +5022,7 @@ int com_tx_cond_create(int a_argc, char ** a_argv, void **a_str_reply) dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = dap_chain_srv_str_to_unit_enum((char*)l_unit_str)}; if(l_price_unit.enm == SERV_UNIT_UNDEFINED) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize unit '%s'. Unit must look like {mb | kb | b | sec | day}", + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize unit '%s'. Unit must look like { B | SEC }", l_unit_str); return -9; } diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index 0a6ca76a68..0b1b58d21a 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -275,7 +275,6 @@ int dap_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx const char *dap_ledger_tx_get_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc); - /** * Delete all transactions from the cache */ diff --git a/modules/net/include/dap_chain_net_voting.h b/modules/net/include/dap_chain_net_voting.h index e03e6dda51..c045605f30 100644 --- a/modules/net/include/dap_chain_net_voting.h +++ b/modules/net/include/dap_chain_net_voting.h @@ -79,8 +79,8 @@ enum DAP_CHAIN_NET_VOTE_CREATE_ERROR { DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_SIGNED_TX, DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_POOL_DATUM_IN_MEMPOOL }; -int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t *a_expire_vote, - uint64_t *a_max_vote, uint256_t a_fee, bool a_delegated_key_required, +int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t a_expire_vote, + uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required, bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet, dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output); diff --git a/modules/net/include/dap_chain_node_cli_cmd_tx.h b/modules/net/include/dap_chain_node_cli_cmd_tx.h index 1dc043c876..54d784bd94 100644 --- a/modules/net/include/dap_chain_node_cli_cmd_tx.h +++ b/modules/net/include/dap_chain_node_cli_cmd_tx.h @@ -50,10 +50,10 @@ json_object * dap_db_tx_history_to_json(dap_chain_hash_fast_t* a_tx_hash, int l_ret_code, bool *accepted_tx, bool out_brief); + json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, const char *l_hash_out_type, json_object *json_obj_summary, size_t a_limit, size_t a_offset, bool out_brief); - /** * ledger command * diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c index 5661288884..6ef4cde5fd 100644 --- a/modules/net/srv/dap_chain_net_srv.c +++ b/modules/net/srv/dap_chain_net_srv.c @@ -40,7 +40,6 @@ #include "utlist.h" #include "dap_chain_net.h" -#include "dap_chain_net_tx.h" #include "dap_hash.h" #include "dap_common.h" #include "dap_enc_base58.h" @@ -53,6 +52,7 @@ #include "dap_chain_net_tx.h" #include "dap_chain_net_srv_order.h" #include "dap_chain_net_srv_stream_session.h" +#include "dap_chain_net_tx.h" #include "dap_stream_ch_chain_net_srv.h" #include "dap_chain_cs_blocks.h" #ifdef DAP_MODULES_DYNAMIC @@ -74,10 +74,7 @@ typedef struct service_list { static service_list_t *s_srv_list = NULL; // for separate access to s_srv_list static pthread_mutex_t s_srv_list_mutex = PTHREAD_MUTEX_INITIALIZER; - - - -static int s_cli_net_srv(int argc, char **argv, void **a_str_reply); +static int s_cli_net_srv(int argc, char **argv, void **reply); static void s_load(const char * a_path); static void s_load_all(); @@ -95,20 +92,22 @@ int dap_chain_net_srv_init() { dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, s_pay_verificator_callback, NULL); dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE, s_fee_verificator_callback, NULL); - dap_stream_ch_chain_net_srv_init(); dap_cli_server_cmd_add ("net_srv", s_cli_net_srv, "Network services managment", - "net_srv -net <net_name> order find [-direction {sell | buy}] [-srv_uid <Service UID>] [-price_unit <price unit>]\n" - " [-price_token <Token ticker>] [-price_min <Price minimum>] [-price_max <Price maximum>]\n" + "net_srv -net <net_name> order find [-direction {sell | buy}] [-srv_uid <service_UID>] [-price_unit <price_unit>]" + " [-price_token <token_ticker>] [-price_min <price_minimum>] [-price_max <price_maximum>]\n" "\tOrders list, all or by UID and/or class\n" - "net_srv -net <net_name> order delete -hash <Order hash>\n" + "net_srv -net <net_name> order delete -hash <ip_addr>\n" "\tOrder delete\n" - "net_srv -net <net_name> order dump -hash <Order hash>\n" + "net_srv -net <net_name> order dump -hash <ip_addr>\n" "\tOrder dump info\n" "net_srv -net <net_name> order create -direction {sell | buy} -srv_uid <Service UID> -price <Price>\n" " -price_unit <Price Unit> -price_token <token_ticker> -units <units> [-node_addr <Node Address>] [-tx_cond <TX Cond Hash>]\n" " [-expires <Unix time when expires>] [-cert <cert name to sign order>]\n" " [{-ext <Extension with params> | -region <Region name> -continent <Continent name>}]\n" + "net_srv get_limits -net <net_name> -srv_uid <Service_UID> -provider_pkey_hash <Service_provider_public_key_hash> -client_pkey_hash <Client_public_key_hash>\n" + "net_srv report\n" + "\tGet report about srv usage" #ifdef DAP_MODULES_DYNAMIC "\tOrder create\n" "net_srv -net <net_name> order static [save | delete]\n" @@ -202,6 +201,15 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply) return -1; } + + int l_report = dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "report", NULL); + if (l_report) { + const char *l_report_str = dap_stream_ch_chain_net_srv_create_statistic_report(); + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_report_str); + DAP_DEL_Z(l_report_str); + return 0; + } + int l_ret = dap_chain_node_cli_cmd_values_parse_net_chain( &arg_index, argc, argv, a_str_reply, NULL, &l_net ); if ( l_net ) { //char * l_orders_group = dap_chain_net_srv_order_get_gdb_group( l_net ); @@ -209,6 +217,8 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply) dap_string_t *l_string_ret = dap_string_new(""); const char *l_order_str = NULL; int l_order_arg_pos = dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "order", &l_order_str); + const char *l_get_limits_str = NULL; + int l_get_limits_arg_pos = dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "get_limits", &l_get_limits_str); // Order direction const char *l_direction_str = NULL; @@ -254,38 +264,39 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply) const char *l_units_str = NULL; dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-units", &l_units_str); - char *l_order_hash_hex_str = NULL; - char *l_order_hash_base58_str = NULL; - // datum hash may be in hex or base58 format - if (l_order_hash_str) { - if(!dap_strncmp(l_order_hash_str, "0x", 2) || !dap_strncmp(l_order_hash_str, "0X", 2)) { - l_order_hash_hex_str = dap_strdup(l_order_hash_str); - l_order_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_order_hash_str); - } else { - l_order_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_order_hash_str); - l_order_hash_base58_str = dap_strdup(l_order_hash_str); + if (l_order_str){ + char *l_order_hash_hex_str = NULL; + char *l_order_hash_base58_str = NULL; + // datum hash may be in hex or base58 format + if (l_order_hash_str) { + if(!dap_strncmp(l_order_hash_str, "0x", 2) || !dap_strncmp(l_order_hash_str, "0X", 2)) { + l_order_hash_hex_str = dap_strdup(l_order_hash_str); + l_order_hash_base58_str = dap_enc_base58_from_hex_str_to_str(l_order_hash_str); + } else { + l_order_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_order_hash_str); + l_order_hash_base58_str = dap_strdup(l_order_hash_str); + } } - } - if(l_continent_str && l_continent_num <= 0) { - dap_string_t *l_string_err = dap_string_new("Unrecognized \"-continent\" option="); - dap_string_append_printf(l_string_err, "\"%s\". Variants: ", l_continent_str); - int i = 0; - while(1) { - const char *l_continent = dap_chain_net_srv_order_continent_to_str(i); - if(!l_continent) - break; - if(!i) - dap_string_append_printf(l_string_err, "\"%s\"", l_continent); - else - dap_string_append_printf(l_string_err, ", \"%s\"", l_continent); - i++; + if(l_continent_str && l_continent_num <= 0) { + dap_string_t *l_string_err = dap_string_new("Unrecognized \"-continent\" option="); + dap_string_append_printf(l_string_err, "\"%s\". Variants: ", l_continent_str); + int i = 0; + while(1) { + const char *l_continent = dap_chain_net_srv_order_continent_to_str(i); + if(!l_continent) + break; + if(!i) + dap_string_append_printf(l_string_err, "\"%s\"", l_continent); + else + dap_string_append_printf(l_string_err, ", \"%s\"", l_continent); + i++; + } + dap_string_append_printf(l_string_ret, "%s\n", l_string_err->str); + dap_string_free(l_string_err, true); + l_ret = -1; } - dap_string_append_printf(l_string_ret, "%s\n", l_string_err->str); - dap_string_free(l_string_err, true); - l_ret = -1; - } - // Update order - else if(!dap_strcmp(l_order_str, "update")) { + // Update order + else if(!dap_strcmp(l_order_str, "update")) { if(!l_order_hash_str) { l_ret = -1; @@ -384,181 +395,176 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply) if ( l_price_max_str ) l_price_max = dap_chain_balance_scan(l_price_max_str); - if (l_price_unit_str){ - if (!dap_strcmp(l_price_unit_str, "MB")){ - l_price_unit.uint32 = SERV_UNIT_MB; - } else if (!dap_strcmp(l_price_unit_str, "SEC")){ - l_price_unit.uint32 = SERV_UNIT_SEC; - } else if (!dap_strcmp(l_price_unit_str, "DAY")){ - l_price_unit.uint32 = SERV_UNIT_DAY; - } else if (!dap_strcmp(l_price_unit_str, "KB")){ - l_price_unit.uint32 = SERV_UNIT_KB; - } else if (!dap_strcmp(l_price_unit_str, "B")){ - l_price_unit.uint32 = SERV_UNIT_B; - } else if (!dap_strcmp(l_price_unit_str, "PCS")){ - l_price_unit.uint32 = SERV_UNIT_PCS; - } - } + l_price_unit.uint32 = dap_chain_srv_str_to_unit_enum(l_price_unit_str); - dap_chain_net_srv_order_t * l_orders; + dap_list_t * l_orders; size_t l_orders_num = 0; if( dap_chain_net_srv_order_find_all_by( l_net, l_direction,l_srv_uid,l_price_unit,l_price_token_str,l_price_min, l_price_max,&l_orders,&l_orders_num) == 0 ){ dap_string_append_printf(l_string_ret, "Found %zu orders:\n", l_orders_num); - size_t l_orders_size = 0; - for (size_t i = 0; i< l_orders_num; i++){ - dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) (((byte_t*) l_orders) + l_orders_size); + for (dap_list_t *l_temp = l_orders;l_temp; l_temp = l_orders->next){ + dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) l_temp->data; dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type, l_net->pub.native_ticker); - l_orders_size += dap_chain_net_srv_order_get_size(l_order); dap_string_append(l_string_ret,"\n"); } l_ret = 0; - if (l_orders_num) - DAP_DELETE(l_orders); - }else{ + dap_list_free_full(l_orders, NULL); + }else{ l_ret = -5 ; dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n"); } - } else if(!dap_strcmp( l_order_str, "dump" )) { - // Select with specified service uid - if ( l_order_hash_str ){ - dap_chain_net_srv_order_t * l_order = dap_chain_net_srv_order_find_by_hash_str( l_net, l_order_hash_hex_str ); - if (l_order) { - dap_chain_net_srv_order_dump_to_string(l_order,l_string_ret, l_hash_out_type, l_net->pub.native_ticker); - l_ret = 0; - }else{ - l_ret = -7 ; - if(!dap_strcmp(l_hash_out_type,"hex")) - dap_string_append_printf(l_string_ret,"Can't find order with hash %s\n", l_order_hash_hex_str ); - else - dap_string_append_printf(l_string_ret,"Can't find order with hash %s\n", l_order_hash_base58_str ); - } - } else { - - dap_chain_net_srv_order_t * l_orders = NULL; - size_t l_orders_num = 0; - dap_chain_net_srv_uid_t l_srv_uid={{0}}; - uint256_t l_price_min = {}; - uint256_t l_price_max = {}; - dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}}; - dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED; - - if( !dap_chain_net_srv_order_find_all_by( l_net,l_direction,l_srv_uid,l_price_unit, NULL, l_price_min, l_price_max,&l_orders,&l_orders_num) ){ - dap_string_append_printf(l_string_ret,"Found %zd orders:\n",l_orders_num); - size_t l_orders_size = 0; - for(size_t i = 0; i < l_orders_num; i++) { - dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) (((byte_t*) l_orders) + l_orders_size); - dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type, l_net->pub.native_ticker); - l_orders_size += dap_chain_net_srv_order_get_size(l_order); - dap_string_append(l_string_ret, "\n"); - } - l_ret = 0; - }else{ - l_ret = -5 ; - dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n"); - } - DAP_DELETE(l_orders); - } - } else if(!dap_strcmp( l_order_str, "delete" )) { - if (l_order_hash_str) { - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_hex_str); - if (l_order) { - if (!dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_hex_str)) { + } else if(!dap_strcmp( l_order_str, "dump" )) { + // Select with specified service uid + if ( l_order_hash_str ){ + dap_chain_net_srv_order_t * l_order = dap_chain_net_srv_order_find_by_hash_str( l_net, l_order_hash_hex_str ); + if (l_order) { + dap_chain_net_srv_order_dump_to_string(l_order,l_string_ret, l_hash_out_type, l_net->pub.native_ticker); l_ret = 0; - dap_string_append_printf(l_string_ret, "Deleted order %s\n", l_order_hash_str); - } else { - l_ret = -9; - dap_string_append_printf(l_string_ret, "Can't delete order with hash %s\n", l_order_hash_str); + }else{ + l_ret = -7 ; + if(!dap_strcmp(l_hash_out_type,"hex")) + dap_string_append_printf(l_string_ret,"Can't find order with hash %s\n", l_order_hash_hex_str ); + else + dap_string_append_printf(l_string_ret,"Can't find order with hash %s\n", l_order_hash_base58_str ); } } else { - l_ret = -8; - dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_str); - } - DAP_DELETE(l_order); - } else { - l_ret = -9; - dap_string_append(l_string_ret,"Comman 'oreder delete' requires -hash param\n"); - } - } else if(!dap_strcmp( l_order_str, "create" )) { - if (dap_chain_net_get_role(l_net).enums > NODE_ROLE_MASTER) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Node role should be not lower than master\n"); - return -4; - } - const char *l_order_cert_name = NULL; - dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-cert", &l_order_cert_name); - if ( l_srv_uid_str && l_price_str && l_price_token_str && l_price_unit_str && l_units_str) { - dap_chain_net_srv_uid_t l_srv_uid={{0}}; - dap_chain_node_addr_t l_node_addr={0}; - dap_chain_hash_fast_t l_tx_cond_hash={{0}}; - dap_time_t l_expires = 0; // TS when the service expires - uint256_t l_price = {0}; - char l_price_token[DAP_CHAIN_TICKER_SIZE_MAX]={0}; - dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}}; - dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED; - if ( l_direction_str ){ - if (!strcmp(l_direction_str, "sell")) { - l_direction = SERV_DIR_SELL; - log_it(L_DEBUG, "Created order to sell"); - } else if (!strcmp(l_direction_str, "buy")) { - l_direction = SERV_DIR_BUY; - log_it(L_DEBUG, "Created order to buy"); - } else { - log_it(L_WARNING, "Undefined order direction"); - dap_string_free(l_string_ret, true); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong direction of the token was " - "specified, possible directions: buy, sell."); - return -18; + dap_list_t * l_orders = NULL; + size_t l_orders_num = 0; + dap_chain_net_srv_uid_t l_srv_uid={{0}}; + uint256_t l_price_min = {}; + uint256_t l_price_max = {}; + dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}}; + dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED; + + if( !dap_chain_net_srv_order_find_all_by( l_net,l_direction,l_srv_uid,l_price_unit, NULL, l_price_min, l_price_max,&l_orders,&l_orders_num) ){ + dap_string_append_printf(l_string_ret,"Found %zd orders:\n",l_orders_num); + for(dap_list_t *l_temp = l_orders;l_temp; l_temp = l_orders->next) { + dap_chain_net_srv_order_t *l_order =(dap_chain_net_srv_order_t *) l_temp->data; + dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type, l_net->pub.native_ticker); + dap_string_append(l_string_ret, "\n"); + } + l_ret = 0; + }else{ + l_ret = -5 ; + dap_string_append(l_string_ret,"Can't get orders: some internal error or wrong params\n"); } + dap_list_free_full(l_orders, NULL); } - - if (l_expires_str) - l_expires = (dap_time_t ) atoll( l_expires_str); - if (l_srv_uid_str && dap_id_uint64_parse(l_srv_uid_str ,&l_srv_uid.uint64)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize '%s' string as 64-bit id, hex or dec.", l_srv_uid_str); - dap_string_free(l_string_ret, true); - return -21; - } - if (l_node_addr_str) { - if (dap_chain_node_addr_str_check(l_node_addr_str)) { - dap_chain_node_addr_from_str( &l_node_addr, l_node_addr_str ); - } else { - log_it(L_ERROR, "Can't parse \"%s\" as node addr", l_node_addr_str); - dap_cli_server_cmd_set_reply_text(a_str_reply, "The order has not been created. " - "Failed to convert string representation of '%s' " - "to node address.", l_node_addr_str); - dap_string_free(l_string_ret, true); - return -17; + } else if (!dap_strcmp(l_order_str, "delete")) { + if (l_order_hash_str) { + l_ret = dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_hex_str); + if (!l_ret) + dap_string_append_printf(l_string_ret, "Deleted order %s\n", l_order_hash_str); + else { + l_ret = -8; + dap_string_append_printf(l_string_ret, "Can't find order with hash %s\n", l_order_hash_str); } } else { - l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + l_ret = -9 ; + dap_string_append(l_string_ret,"need -hash param to obtain what the order we need to dump\n"); } - if (l_tx_cond_hash_str) - dap_chain_hash_fast_from_str (l_tx_cond_hash_str, &l_tx_cond_hash); - l_price = dap_chain_balance_scan(l_price_str); - - if (s_str_to_price_unit(l_price_unit_str, &l_price_unit)){ - log_it(L_ERROR, "Undefined price unit"); - dap_string_free(l_string_ret, true); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong unit type sepcified, possible values: B, KB, MB, SEC, DAY, PCS"); - return -18; + } else if(!dap_strcmp( l_order_str, "create" )) { + if (dap_chain_net_get_role(l_net).enums > NODE_ROLE_MASTER) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Node role should be not lower than master\n"); + return -4; } + const char *l_order_cert_name = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-cert", &l_order_cert_name); + if ( l_srv_uid_str && l_price_str && l_price_token_str && l_price_unit_str && l_units_str) { + dap_chain_net_srv_uid_t l_srv_uid={{0}}; + dap_chain_node_addr_t l_node_addr={0}; + dap_chain_hash_fast_t l_tx_cond_hash={{0}}; + dap_time_t l_expires = 0; // TS when the service expires + uint256_t l_price = {0}; + char l_price_token[DAP_CHAIN_TICKER_SIZE_MAX]={0}; + dap_chain_net_srv_price_unit_uid_t l_price_unit={{0}}; + dap_chain_net_srv_order_direction_t l_direction = SERV_DIR_UNDEFINED; + if ( l_direction_str ){ + if (!strcmp(l_direction_str, "sell")) { + l_direction = SERV_DIR_SELL; + log_it(L_DEBUG, "Created order to sell"); + } else if (!strcmp(l_direction_str, "buy")) { + l_direction = SERV_DIR_BUY; + log_it(L_DEBUG, "Created order to buy"); + } else { + log_it(L_WARNING, "Undefined order direction"); + dap_string_free(l_string_ret, true); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong direction of the token was " + "specified, possible directions: buy, sell."); + return -18; + } + } - uint64_t l_units = atoi(l_units_str); - strncpy(l_price_token, l_price_token_str, DAP_CHAIN_TICKER_SIZE_MAX - 1); - size_t l_ext_len = l_ext? strlen(l_ext) + 1 : 0; - // get cert to order sign - dap_cert_t *l_cert = NULL; - dap_enc_key_t *l_key = NULL; - if(l_order_cert_name) { - l_cert = dap_cert_find_by_name(l_order_cert_name); - if(l_cert) { - l_key = l_cert->enc_key; - } else { - log_it(L_ERROR, "Can't load cert '%s' for sign order", l_order_cert_name); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't load cert '%s' for sign " - "order", l_order_cert_name); + if (l_expires_str) + l_expires = (dap_time_t ) atoll( l_expires_str); + if (l_srv_uid_str && dap_id_uint64_parse(l_srv_uid_str ,&l_srv_uid.uint64)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize '%s' string as 64-bit id, hex or dec.", l_srv_uid_str); dap_string_free(l_string_ret, true); - return -19; + return -21; + }else if (!l_srv_uid_str){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Parameter -srv_uid is required."); + dap_string_free(l_string_ret, true); + return -22; } + if (l_node_addr_str){ + if (dap_chain_node_addr_str_check(l_node_addr_str)) { + dap_chain_node_addr_from_str( &l_node_addr, l_node_addr_str ); + } else { + log_it(L_ERROR, "Can't parse \"%s\" as node addr", l_node_addr_str); + dap_cli_server_cmd_set_reply_text(a_str_reply, "The order has not been created. " + "Failed to convert string representation of '%s' " + "to node address.", l_node_addr_str); + dap_string_free(l_string_ret, true); + return -17; + } + } else { + l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + } + if (l_tx_cond_hash_str) + dap_chain_hash_fast_from_str (l_tx_cond_hash_str, &l_tx_cond_hash); + l_price = dap_chain_balance_scan(l_price_str); + + uint64_t l_units = atoi(l_units_str); + + if (!dap_strcmp(l_price_unit_str, "B")){ + l_price_unit.enm = SERV_UNIT_B; + } else if (!dap_strcmp(l_price_unit_str, "KB")){ + l_price_unit.enm = SERV_UNIT_B; + l_units *= 1024; + } else if (!dap_strcmp(l_price_unit_str, "MB")){ + l_price_unit.enm = SERV_UNIT_B; + l_units *= 1024*1024; + } else if (!dap_strcmp(l_price_unit_str, "DAY")){ + l_price_unit.enm = SERV_UNIT_SEC; + l_units *= 3600*24; + } else if (!dap_strcmp(l_price_unit_str, "SEC")){ + l_price_unit.enm = SERV_UNIT_SEC; + } else if (!dap_strcmp(l_price_unit_str, "PCS")){ + l_price_unit.enm = SERV_UNIT_PCS; + } else { + log_it(L_ERROR, "Undefined price unit"); + dap_string_free(l_string_ret, true); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Wrong unit type sepcified, possible values: B, KB, MB, SEC, DAY, PCS"); + return -18; + } + + + + strncpy(l_price_token, l_price_token_str, DAP_CHAIN_TICKER_SIZE_MAX - 1); + size_t l_ext_len = l_ext? strlen(l_ext) + 1 : 0; + // get cert to order sign + dap_cert_t *l_cert = NULL; + dap_enc_key_t *l_key = NULL; + if(l_order_cert_name) { + l_cert = dap_cert_find_by_name(l_order_cert_name); + if(l_cert) { + l_key = l_cert->enc_key; + } else { + log_it(L_ERROR, "Can't load cert '%s' for sign order", l_order_cert_name); + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't load cert '%s' for sign " + "order", l_order_cert_name); + dap_string_free(l_string_ret, true); + return -19; + } } else { dap_cli_server_cmd_set_reply_text(a_str_reply, "The certificate name was not " "specified. Since version 5.2 it is not possible to " @@ -582,73 +588,74 @@ static int s_cli_net_srv( int argc, char **argv, void **a_str_reply) dap_string_append_printf( l_string_ret, "Missed some required params\n"); l_ret=-5; } - } -#ifdef DAP_MODULES_DYNAMIC - else if(!dap_strcmp( l_order_str, "recheck" )) { - int (*dap_chain_net_srv_vpn_cdb_server_list_check_orders)(dap_chain_net_t *a_net); - dap_chain_net_srv_vpn_cdb_server_list_check_orders = dap_modules_dynamic_get_cdb_func("dap_chain_net_srv_vpn_cdb_server_list_check_orders"); - int l_init_res = dap_chain_net_srv_vpn_cdb_server_list_check_orders ? dap_chain_net_srv_vpn_cdb_server_list_check_orders(l_net) : -5; - if (l_init_res >= 0) { - dap_string_append_printf(l_string_ret, "Orders recheck started\n"); - l_ret = 0; - } else { - dap_string_append_printf(l_string_ret, "Orders recheck not started, code %d\n", l_init_res); - l_ret = -10; + } + else if (l_order_str) { + dap_string_append_printf(l_string_ret, "Unrecognized subcommand '%s'", l_order_str); + l_ret = -14; + } + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_string_ret->str); + dap_string_free(l_string_ret, true); + } else if (l_get_limits_str){ + const char *l_provider_pkey_hash_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-provider_pkey_hash", &l_provider_pkey_hash_str); + + const char *l_client_pkey_hash_str = NULL; + dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-client_pkey_hash", &l_client_pkey_hash_str); + + if (!l_provider_pkey_hash_str){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'get_limits' require the parameter provider_pkey_hash"); + dap_string_free(l_string_ret, true); + return -15; } - } else if(!dap_strcmp( l_order_str, "static" )) { - // find the subcommand directly after the 'order' command - int l_subcmd_save = dap_cli_server_cmd_find_option_val(argv, l_order_arg_pos + 1, l_order_arg_pos + 2, "save", NULL); - int l_subcmd_del = dap_cli_server_cmd_find_option_val(argv, l_order_arg_pos + 1, l_order_arg_pos + 2, "delete", NULL) | - dap_cli_server_cmd_find_option_val(argv, l_order_arg_pos + 1, l_order_arg_pos + 2, "del", NULL); - - int (*dap_chain_net_srv_vpn_cdb_server_list_static_create)(dap_chain_net_t *a_net) = NULL; - int (*dap_chain_net_srv_vpn_cdb_server_list_static_delete)(dap_chain_net_t *a_net) = NULL; - // find func from dinamic library - if(l_subcmd_save || l_subcmd_del) { - dap_chain_net_srv_vpn_cdb_server_list_static_create = dap_modules_dynamic_get_cdb_func("dap_chain_net_srv_vpn_cdb_server_list_static_create"); - dap_chain_net_srv_vpn_cdb_server_list_static_delete = dap_modules_dynamic_get_cdb_func("dap_chain_net_srv_vpn_cdb_server_list_static_delete"); + if (!l_client_pkey_hash_str){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'get_limits' require the parameter client_pkey_hash"); + dap_string_free(l_string_ret, true); + return -16; } - if(l_subcmd_save) { - int l_init_res = dap_chain_net_srv_vpn_cdb_server_list_static_create ? dap_chain_net_srv_vpn_cdb_server_list_static_create(l_net) : -5; - if(l_init_res >= 0){ - dap_string_append_printf(l_string_ret, "Static node list saved, %d orders in list\n", l_init_res); - l_ret = 0; - } - else{ - dap_string_append_printf(l_string_ret, "Static node list not saved, error code %d\n", l_init_res); - l_ret = -11; - } - } else if(l_subcmd_del) { - int l_init_res = dap_chain_net_srv_vpn_cdb_server_list_static_delete ? dap_chain_net_srv_vpn_cdb_server_list_static_delete(l_net) : -5; - if(!l_init_res){ - dap_string_append_printf(l_string_ret, "Static node list deleted\n"); - l_ret = 0; - } - else if(l_init_res > 0){ - dap_string_append_printf(l_string_ret, "Static node list already deleted\n"); - l_ret = -12; - } - else - dap_string_append_printf(l_string_ret, "Static node list not deleted, error code %d\n", l_init_res); - } else { - dap_string_append(l_string_ret, "not found subcommand 'save' or 'delete'\n"); - l_ret = -13; + dap_chain_net_srv_uid_t l_srv_uid={{0}}; + if (l_srv_uid_str && dap_id_uint64_parse(l_srv_uid_str ,&l_srv_uid.uint64)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't recognize '%s' string as 64-bit id, hex or dec.", l_srv_uid_str); + dap_string_free(l_string_ret, true); + return -21; + } else if (!l_srv_uid_str){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Parameter -srv_uid is required."); + dap_string_free(l_string_ret, true); + return -22; } - } -#endif - else if (l_order_str) { - dap_string_append_printf(l_string_ret, "Unrecognized subcommand '%s'", l_order_str); - l_ret = -14; + + dap_stream_ch_chain_net_srv_remain_service_store_t *l_remain_service = NULL; + size_t l_remain_service_size = 0; + char *l_remain_limits_gdb_group = dap_strdup_printf( "%s.0x%016"DAP_UINT64_FORMAT_x".remain_limits.%s", + l_net->pub.gdb_groups_prefix, l_srv_uid.uint64, + l_provider_pkey_hash_str); + + l_remain_service = (dap_stream_ch_chain_net_srv_remain_service_store_t*) dap_global_db_get_sync(l_remain_limits_gdb_group, l_client_pkey_hash_str, &l_remain_service_size, NULL, NULL); + DAP_DELETE(l_remain_limits_gdb_group); + + if(!l_remain_service || !l_remain_service_size){ + dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't get remain service data"); + dap_string_free(l_string_ret, true); + return -21; + } + + dap_cli_server_cmd_set_reply_text(a_str_reply, "Provider %s. Client %s remain service values:\n" + "SEC: %"DAP_UINT64_FORMAT_U"\n" + "BYTES: %"DAP_UINT64_FORMAT_U"\n", l_provider_pkey_hash_str, l_client_pkey_hash_str, + (uint64_t)l_remain_service->limits_ts, (uint64_t)l_remain_service->limits_bytes); + + dap_string_free(l_string_ret, true); + DAP_DELETE(l_remain_service); } else { - dap_string_append_printf(l_string_ret, "Command 'net_srv' requires subcommand 'order'"); - l_ret = -3; + dap_cli_server_cmd_set_reply_text(a_str_reply, "Unrecognized bcommand."); + dap_string_free(l_string_ret, true); + return -17; } - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s", l_string_ret->str); - dap_string_free(l_string_ret, true); + } + return l_ret; } @@ -836,12 +843,21 @@ dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net const char *l_wallet_addr = dap_config_get_item_str_default(g_config, a_config_section, "wallet_addr", NULL); const char *l_cert_name = dap_config_get_item_str_default(g_config, a_config_section, "receipt_sign_cert", NULL); const char *l_net_name = dap_config_get_item_str_default(g_config, a_config_section, "net", NULL); - if (!l_wallet_addr || !l_cert_name || !l_net_name){ + if (!l_wallet_addr){ + log_it(L_CRITICAL, "Wallet addr is not defined. Check node configuration file."); + return NULL; + } + if (!l_cert_name){ + log_it(L_CRITICAL, "Receipt sign certificate is not defined. Check node configuration file."); + return NULL; + } + if (!l_net_name){ + log_it(L_CRITICAL, "Net for is not defined. Check node configuration file."); return NULL; } - dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_name); if (!l_net) { + log_it(L_CRITICAL, "Can't find net %s. Check node configuration file.", l_net_name); return NULL; } @@ -875,7 +891,7 @@ dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net l_price->net = l_net; l_price->net_name = dap_strdup(l_net->pub.name); uint256_t l_max_price = GET_256_FROM_64(l_max_price_cfg); // Change this value when max price wil be calculated - if (IS_ZERO_256(l_order->price) || l_order->units == 0 ){ + if ((IS_ZERO_256(l_order->price) || l_order->units == 0 ) && !a_srv->allow_free_srv){ log_it(L_ERROR, "Invalid order: units count or price unspecified"); DAP_DELETE(l_price); DAP_DEL_Z(l_order); @@ -918,9 +934,20 @@ dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net dap_hash_fast_t order_pkey_hash = {}; dap_hash_fast_t price_pkey_hash = {}; dap_sign_get_pkey_hash((dap_sign_t*)(l_order->ext_n_sign + l_order->ext_size), &order_pkey_hash); - dap_hash_fast(l_price->receipt_sign_cert->enc_key->pub_key_data, - l_price->receipt_sign_cert->enc_key->pub_key_data_size, &price_pkey_hash); - if (dap_hash_fast_compare(&order_pkey_hash, &price_pkey_hash)) + size_t l_key_size = 0; + uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(l_price->receipt_sign_cert->enc_key, &l_key_size); + if (!l_pub_key || !l_key_size) + { + log_it(L_ERROR, "Can't get pkey from cert %s.", l_cert_name); + DAP_DEL_Z(l_order); + DAP_DELETE(l_price); + return NULL; + } + + dap_hash_fast(l_pub_key, l_key_size, &price_pkey_hash); + DAP_DELETE(l_pub_key); + + if (!dap_hash_fast_compare(&order_pkey_hash, &price_pkey_hash)) { log_it(L_ERROR, "pkey in order not equal to pkey in config."); DAP_DEL_Z(l_order); @@ -930,197 +957,14 @@ dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net DAP_DELETE(l_order); return l_price; - } +int dap_chain_net_srv_price_apply_from_my_order(dap_chain_net_srv_t *a_srv, const char *a_config_section) +{ -int dap_chain_net_srv_price_apply_from_my_order(dap_chain_net_srv_t *a_srv, const char *a_config_section){ - -// const char *l_wallet_path = dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL); -// const char *l_wallet_name = dap_config_get_item_str_default(g_config, a_config_section, "wallet", NULL); - - const char *l_wallet_addr = dap_config_get_item_str_default(g_config, a_config_section, "wallet_addr", NULL); - const char *l_cert_name = dap_config_get_item_str_default(g_config, a_config_section, "receipt_sign_cert", NULL); - const char *l_net_name = dap_config_get_item_str_default(g_config, a_config_section, "net", NULL); - if (!l_wallet_addr || !l_cert_name || !l_net_name){ - return -2; - } - -// dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_name, l_wallet_path); -// if (!l_wallet) { -// return -3; -// } - dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_name); - if (!l_net) { - return -4; - } - a_srv->grace_period = dap_config_get_item_uint32_default(g_config, a_config_section, "grace_period", 60); - a_srv->allow_free_srv = dap_config_get_item_bool_default(g_config, a_config_section, "allow_free_srv", false); - int l_err_code = 0; - size_t l_orders_count = 0; - uint64_t l_max_price_cfg = dap_config_get_item_uint64_default(g_config, a_config_section, "max_price", 0xFFFFFFFFFFFFFFF); - char *l_gdb_order_group = dap_chain_net_srv_order_get_gdb_group(l_net); - dap_global_db_obj_t *l_orders = dap_global_db_get_all_sync(l_gdb_order_group, &l_orders_count); - log_it(L_INFO, "Found %"DAP_UINT64_FORMAT_U" orders.", l_orders_count); - for (size_t i=0; i < l_orders_count; i++){ - l_err_code = -4; - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_read(l_orders[i].value, l_orders[i].value_len); - if(!l_order){ - log_it(L_ERROR, "Invalid order: NULL. Skip order."); - continue; - } - if (l_order->node_addr.uint64 == g_node_addr.uint64 && - l_order->srv_uid.uint64 == a_srv->uid.uint64) { - l_err_code = 0; - dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t); - if (!l_price) { - log_it(L_CRITICAL, "Memory allocation error"); - DAP_DEL_Z(l_order); - dap_global_db_objs_delete(l_orders, l_orders_count); - return -1; - } - l_price->net = l_net; - l_price->net_name = dap_strdup(l_net->pub.name); - uint256_t l_max_price = GET_256_FROM_64(l_max_price_cfg); // Change this value when max price wil be calculated - if (IS_ZERO_256(l_order->price) || l_order->units == 0 ){ - log_it(L_ERROR, "Invalid order: units count or price unspecified"); - DAP_DELETE(l_price); - continue; - } - l_price->value_datoshi = l_order->price; - dap_stpcpy(l_price->token, l_order->price_ticker); - l_price->units = l_order->units; - l_price->units_uid = l_order->price_unit; - if (!IS_ZERO_256(l_max_price)){ - uint256_t l_price_unit = uint256_0; - DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_order->units), &l_price_unit); - if (compare256(l_price_unit, l_max_price)>0){ - char *l_price_unit_str = dap_chain_balance_print(l_price_unit), *l_max_price_str = dap_chain_balance_print(l_max_price); - log_it(L_ERROR, "Unit price exeeds max permitted value: %s > %s", l_price_unit_str, l_max_price_str); - DAP_DELETE(l_price_unit_str); - DAP_DELETE(l_max_price_str); - DAP_DELETE(l_price); - continue; - } - } -// l_price->wallet = l_wallet; - l_price->wallet_addr = dap_chain_addr_from_str(l_wallet_addr); - if(!l_price->wallet_addr){ - log_it(L_ERROR, "Can't get wallet addr from wallet_addr in config file."); - DAP_DEL_Z(l_order); - DAP_DELETE(l_price); - dap_global_db_objs_delete(l_orders, l_orders_count); - return -100; - } - - l_price->receipt_sign_cert = dap_cert_find_by_name(l_cert_name); - if(!l_price->receipt_sign_cert){ - log_it(L_ERROR, "Can't find cert %s.", l_cert_name); - DAP_DEL_Z(l_order); - DAP_DELETE(l_price); - dap_global_db_objs_delete(l_orders, l_orders_count); - return -101; - } - - dap_hash_fast_t order_pkey_hash = { }, price_pkey_hash = { }; - dap_sign_get_pkey_hash((dap_sign_t*)(l_order->ext_n_sign + l_order->ext_size), &order_pkey_hash); - dap_hash_fast(l_price->receipt_sign_cert->enc_key->pub_key_data, - l_price->receipt_sign_cert->enc_key->pub_key_data_size, &price_pkey_hash); - if (dap_hash_fast_compare(&order_pkey_hash, &price_pkey_hash)) - { - log_it(L_ERROR, "pkey in order not equal to pkey in config."); - DAP_DEL_Z(l_order); - DAP_DELETE(l_price); - dap_global_db_objs_delete(l_orders, l_orders_count); - continue; - } - // TODO: find most advantageous order for us - DL_APPEND(a_srv->pricelist, l_price); - break; - } - DAP_DELETE(l_order); - } - dap_global_db_objs_delete(l_orders, l_orders_count); - return l_err_code; -} -int dap_chain_net_srv_parse_pricelist(dap_chain_net_srv_t *a_srv, const char *a_config_section) -{ - int ret = 0; - if (!a_config_section) - return ret; - a_srv->grace_period = dap_config_get_item_uint32_default(g_config, a_config_section, "grace_period", 60); - uint16_t l_pricelist_count = 0; - char **l_pricelist = dap_config_get_array_str(g_config, a_config_section, "pricelist", &l_pricelist_count); - for (uint16_t i = 0; i < l_pricelist_count; i++) { - dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t); - if (!l_price) { - log_it(L_CRITICAL, "Memory allocation error"); - return ret; - } - short l_iter = 0; - char *l_price_str = dap_strdup(l_pricelist[i]), *l_ctx; - for (char *l_price_token = strtok_r(l_price_str, ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) { - //log_it(L_DEBUG, "Tokenizer: %s", l_price_token); - switch (l_iter) { - case 0: - l_price->net_name = l_price_token; - if (!(l_price->net = dap_chain_net_by_name(l_price->net_name))) { - log_it(L_ERROR, "Error parsing pricelist: can't find network \"%s\"", l_price_token); - break; - } - continue; - case 1: - l_price->value_datoshi = dap_chain_coins_to_balance(l_price_token); - if (IS_ZERO_256(l_price->value_datoshi)) { - log_it(L_ERROR, "Error parsing pricelist: text on 2nd position \"%s\" is not floating number", l_price_token); - l_iter = 0; - break; - } - continue; - case 2: - dap_stpcpy(l_price->token, l_price_token); - continue; - case 3: - l_price->units = strtoul(l_price_token, NULL, 10); - if (!l_price->units) { - log_it(L_ERROR, "Error parsing pricelist: text on 4th position \"%s\" is not unsigned integer", l_price_token); - l_iter = 0; - break; - } - continue; - case 4: - if (s_str_to_price_unit(l_price_token, &(l_price->units_uid))) { - log_it(L_ERROR, "Error parsing pricelist: wrong unit type \"%s\"", l_price_token); - l_iter = 0; - break; - } - continue; - case 5: -// if (!(l_price->wallet = dap_chain_wallet_open(l_price_token, dap_config_get_item_str_default(g_config, "resources", "wallets_path", NULL)))) { -// log_it(L_ERROR, "Error parsing pricelist: can't open wallet \"%s\"", l_price_token); -// l_iter = 0; -// break; -// } - continue; - case 6: - log_it(L_INFO, "Price item correct, added to service"); - ret++; - break; - default: - break; - } - log_it(L_DEBUG, "Done with price item %d", i); - if (l_iter == 6) - DL_APPEND(a_srv->pricelist, l_price); - break; // double break exits tokenizer loop and steps to next price item - } - if (l_iter != 6) - DAP_DELETE(l_price); - DAP_DELETE(l_price_str); - } - return ret; + return 0; } /** @@ -1139,6 +983,13 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid, service_list_t *l_sdata = NULL; dap_chain_net_srv_t * l_srv = NULL; dap_chain_net_srv_uid_t l_uid = {.uint64 = a_uid.uint64 }; // Copy to let then compiler to pass args via registers not stack + const char* l_net_name_str = dap_config_get_item_str_default(g_config, a_config_section, "net", ""); + dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_name_str); + if(!l_net && a_uid.uint64 == 1){ + log_it(L_ERROR, "Can't find net [%s]. Check configuration file.", l_net_name_str); + return NULL; + } + pthread_mutex_lock(&s_srv_list_mutex); HASH_FIND(hh, s_srv_list, &l_uid, sizeof(l_uid), l_sdata); if(!l_sdata) { @@ -1162,11 +1013,14 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid, l_sdata->uid = l_uid; strncpy(l_sdata->name, a_config_section, sizeof(l_sdata->name) - 1); l_sdata->srv = l_srv; - dap_chain_net_srv_price_apply_from_my_order(l_srv, a_config_section); -// dap_chain_net_srv_parse_pricelist(l_srv, a_config_section); + if (a_uid.uint64 == 1){ + l_srv->grace_period = dap_config_get_item_uint32_default(g_config, a_config_section, "grace_period", DAP_CHAIN_NET_SRV_GRACE_PERIOD_DEFAULT); + l_srv->allow_free_srv = dap_config_get_item_bool_default(g_config, a_config_section, "allow_free_srv", false); + } HASH_ADD(hh, s_srv_list, uid, sizeof(l_srv->uid), l_sdata); - if (l_srv->pricelist) - dap_ledger_tx_add_notify(l_srv->pricelist->net->pub.ledger, dap_stream_ch_chain_net_srv_tx_cond_added_cb, NULL); + dap_stream_ch_chain_net_srv_init(l_srv); + if (l_net) + dap_ledger_tx_add_notify(l_net->pub.ledger, dap_stream_ch_chain_net_srv_tx_cond_added_cb, NULL); }else{ log_it(L_ERROR, "Already present service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64); } @@ -1178,14 +1032,26 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid, * @brief dap_chain_net_srv_del * @param a_srv */ -void dap_chain_net_srv_del(dap_chain_net_srv_t * a_srv) +void dap_chain_net_srv_del(dap_chain_net_srv_t *a_srv) { +// sanity check + dap_return_if_pass(!a_srv); +// func work service_list_t *l_sdata; - if(!a_srv) - return; + // delete srv from hash table pthread_mutex_lock(&s_srv_list_mutex); HASH_FIND(hh, s_srv_list, a_srv, sizeof(dap_chain_net_srv_uid_t), l_sdata); if(l_sdata) { + // grace table clean + dap_chain_net_srv_grace_usage_t *l_gdata, *l_gdata_tmp; + pthread_mutex_lock(&a_srv->grace_mutex); + HASH_ITER(hh, a_srv->grace_hash_tab, l_gdata, l_gdata_tmp) + { + HASH_DEL(a_srv->grace_hash_tab, l_gdata); + DAP_DELETE(l_gdata); + } + pthread_mutex_unlock(&a_srv->grace_mutex); + HASH_DEL(s_srv_list, l_sdata); pthread_mutex_destroy(&a_srv->banlist_mutex); DAP_DELETE(a_srv); @@ -1250,6 +1116,7 @@ void dap_chain_net_srv_del_all(void) pthread_mutex_lock(&s_srv_list_mutex); HASH_ITER(hh, s_srv_list , l_sdata, l_sdata_tmp) { + // Clang bug at this, l_sdata should change at every loop cycle HASH_DEL(s_srv_list, l_sdata); pthread_mutex_destroy(&l_sdata->srv->banlist_mutex); DAP_DELETE(l_sdata->srv); @@ -1263,7 +1130,7 @@ void dap_chain_net_srv_del_all(void) * @param a_uid * @return */ -dap_chain_net_srv_t * dap_chain_net_srv_get(dap_chain_net_srv_uid_t a_uid) +dap_chain_net_srv_t *dap_chain_net_srv_get(dap_chain_net_srv_uid_t a_uid) { service_list_t *l_sdata = NULL; pthread_mutex_lock(&s_srv_list_mutex); diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 9a27a68489..1141d2584c 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -44,6 +44,7 @@ OC : Oceania geonameId=6255151 SA : South America geonameId=6255150 AN : Antarctica geonameId=6255152 */ + char *s_server_continents[]={ "None", "Africa", @@ -449,13 +450,15 @@ int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,const dap_chain_ const dap_chain_net_srv_uid_t a_srv_uid, const dap_chain_net_srv_price_unit_uid_t a_price_unit,const char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX], const uint256_t a_price_min, const uint256_t a_price_max, - dap_chain_net_srv_order_t ** a_output_orders, size_t * a_output_orders_count) + dap_list_t** a_output_orders, size_t * a_output_orders_count) { if (!a_net || !a_output_orders || !a_output_orders_count) return -1; size_t l_orders_size = 0, l_output_orders_count = 0; *a_output_orders = NULL; + dap_list_t* l_out_list = NULL; + for (int i = 0; i < 2; i++) { char *l_gdb_group_str = i ? dap_chain_net_srv_order_get_gdb_group(a_net) : dap_chain_net_srv_order_get_common_group(a_net); @@ -464,7 +467,6 @@ int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,const dap_chain_ log_it( L_DEBUG, "Loaded %zu orders", l_orders_count); dap_chain_net_srv_order_t *l_order = NULL; for (size_t i = 0; i < l_orders_count; i++) { - DAP_DEL_Z(l_order); l_order = dap_chain_net_srv_order_read(l_orders[i].value, l_orders[i].value_len); if (!l_order) { dap_global_db_del_sync(l_gdb_group_str, l_orders[i].key); @@ -496,16 +498,16 @@ int dap_chain_net_srv_order_find_all_by(dap_chain_net_t * a_net,const dap_chain_ if (a_price_ticker && strcmp( l_order->price_ticker, a_price_ticker)) continue; size_t l_order_mem_size = dap_chain_net_srv_order_get_size(l_order); - *a_output_orders = DAP_REALLOC(*a_output_orders, l_orders_size + l_order_mem_size); - memcpy((byte_t *)*a_output_orders + l_orders_size, l_order, l_order_mem_size); + dap_chain_net_srv_order_t *l_output_order = DAP_DUP_SIZE(l_order, l_order_mem_size); DAP_DEL_Z(l_order); - l_orders_size += l_order_mem_size; + l_out_list = dap_list_append(l_out_list, l_output_order); l_output_orders_count++; } dap_global_db_objs_delete(l_orders, l_orders_count); DAP_DELETE(l_gdb_group_str); } *a_output_orders_count = l_output_orders_count; + *a_output_orders = l_out_list; return 0; } diff --git a/modules/net/srv/dap_chain_net_srv_stream_session.c b/modules/net/srv/dap_chain_net_srv_stream_session.c index 63ff8c9de4..ddf96cb51d 100644 --- a/modules/net/srv/dap_chain_net_srv_stream_session.c +++ b/modules/net/srv/dap_chain_net_srv_stream_session.c @@ -133,7 +133,7 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find_unsafe (dap_chain_net_sr uint32_t a_usage_id) { dap_chain_net_srv_usage_t * l_ret = NULL; - if (a_srv_session->usage_active->id == a_usage_id) + if (a_srv_session && a_srv_session->usage_active && a_srv_session->usage_active->id == a_usage_id) l_ret = a_srv_session->usage_active; return l_ret; } diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h index 8669a791d9..938efa969a 100755 --- a/modules/net/srv/include/dap_chain_net_srv.h +++ b/modules/net/srv/include/dap_chain_net_srv.h @@ -33,6 +33,8 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include "dap_stream_ch.h" #include "dap_time.h" +#define DAP_CHAIN_NET_SRV_GRACE_PERIOD_DEFAULT 60 + //Service direction enum dap_chain_net_srv_order_direction{ SERV_DIR_BUY = 1, @@ -41,6 +43,10 @@ enum dap_chain_net_srv_order_direction{ }; typedef byte_t dap_chain_net_srv_order_direction_t; +typedef struct { + intmax_t limits_bytes; // Bytes provided for using the service left + time_t limits_ts; //Time provided for using the service +} dap_stream_ch_chain_net_srv_remain_service_store_t; typedef struct dap_chain_net_srv_abstract { @@ -111,16 +117,20 @@ typedef struct dap_chain_net_srv_price #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH 0x00000402 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN 0x00000403 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID 0x00000404 -#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE 0x00000405 -#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_BIG_SIZE 0x00000406 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_NEW_COND 0x00000405 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE 0x00000406 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_BIG_SIZE 0x00000407 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NEW_TX_COND_NOT_ENOUGH 0x00000408 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND 0x00000500 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_NO_SIGN 0x00000501 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_WRONG_PKEY_HASH 0x00000502 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH 0x00000503 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_IS_NOT_PRESENT 0x00000504 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND 0x00000600 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_HASH 0x00000BAD #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR 0x00BADA55 + #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNKNOWN 0xffffffff // TYPE_REQUEST typedef struct dap_stream_ch_chain_net_srv_pkt_request_hdr{ @@ -192,7 +202,7 @@ typedef struct dap_chain_net_srv_grace { dap_stream_worker_t *stream_worker; dap_stream_ch_uuid_t ch_uuid; dap_chain_net_srv_usage_t *usage; - dap_events_socket_uuid_t timer_es_uuid; + dap_timerfd_t *timer; dap_stream_ch_chain_net_srv_pkt_request_t *request; size_t request_size; } dap_chain_net_srv_grace_t; @@ -209,12 +219,6 @@ typedef struct dap_chain_net_srv_client_remote struct dap_chain_net_srv_client_remote *next; } dap_chain_net_srv_client_remote_t; -typedef struct { - intmax_t limits_bytes; // Bytes provided for using the service left - time_t limits_ts; //Time provided for using the service - dap_chain_net_srv_price_unit_uid_t remain_units_type; -} dap_stream_ch_chain_net_srv_remain_service_store_t; - typedef int (*dap_chain_net_srv_callback_data_t)(dap_chain_net_srv_t *, uint32_t, dap_chain_net_srv_client_remote_t *, const void *, size_t); typedef void* (*dap_chain_net_srv_callback_custom_data_t)(dap_chain_net_srv_t *, dap_chain_net_srv_usage_t *, const void *, size_t, size_t *); typedef void (*dap_chain_net_srv_callback_ch_t)(dap_chain_net_srv_t *, dap_stream_ch_t *); @@ -256,11 +260,17 @@ typedef struct dap_chain_net_srv_callbacks { dap_chain_net_srv_callback_ch_t stream_ch_write; } dap_chain_net_srv_callbacks_t; +typedef struct dap_chain_net_srv_grace_usage { + dap_hash_fast_t tx_cond_hash; + dap_chain_net_srv_grace_t *grace; + UT_hash_handle hh; +} dap_chain_net_srv_grace_usage_t; + typedef struct dap_chain_net_srv { dap_chain_net_srv_uid_t uid; // Unique ID for service. dap_chain_net_srv_abstract_t srv_common; - dap_chain_net_srv_price_t *pricelist; + // dap_chain_net_srv_price_t *pricelist; bool allow_free_srv; uint32_t grace_period; @@ -269,6 +279,9 @@ typedef struct dap_chain_net_srv dap_chain_net_srv_callbacks_t callbacks; + dap_chain_net_srv_grace_usage_t *grace_hash_tab; + pthread_mutex_t grace_mutex; + // Pointer to inheritor object void *_inheritor; // Pointer to internal server structure @@ -329,10 +342,7 @@ DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chai { switch ( a_uid.enm) { case SERV_UNIT_B: return "BYTE"; - case SERV_UNIT_KB: return "KILOBYTE"; - case SERV_UNIT_MB: return "MEGABYTE"; case SERV_UNIT_SEC: return "SECOND"; - case SERV_UNIT_DAY: return "DAY"; case SERV_UNIT_PCS: return "PIECES"; default: return "UNKNOWN"; } @@ -341,14 +351,8 @@ DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chai DAP_STATIC_INLINE dap_chain_net_srv_price_unit_uid_t dap_chain_net_srv_price_unit_uid_from_str( const char *a_unit_str ) { dap_chain_net_srv_price_unit_uid_t l_price_unit = { .enm = SERV_UNIT_UNDEFINED }; - if(!dap_strcmp(a_unit_str, "mb")) - l_price_unit.enm = SERV_UNIT_MB; - else if(!dap_strcmp(a_unit_str, "sec")) + if(!dap_strcmp(a_unit_str, "sec")) l_price_unit.enm = SERV_UNIT_SEC; - else if(!dap_strcmp(a_unit_str, "day")) - l_price_unit.enm = SERV_UNIT_DAY; - else if(!dap_strcmp(a_unit_str, "kb")) - l_price_unit.enm = SERV_UNIT_KB; else if(!dap_strcmp(a_unit_str, "b") || !dap_strcmp(a_unit_str, "bytes")) l_price_unit.enm = SERV_UNIT_B; else if(!dap_strcmp(a_unit_str, "pcs") || !dap_strcmp(a_unit_str, "pieces")) diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h index 8ebb4ed5d0..29906fce08 100644 --- a/modules/net/srv/include/dap_chain_net_srv_order.h +++ b/modules/net/srv/include/dap_chain_net_srv_order.h @@ -28,7 +28,6 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #include "dap_string.h" #include "dap_chain_common.h" #include "dap_chain_net_srv.h" - typedef struct dap_chain_net_srv_order_old { uint16_t version; @@ -104,7 +103,7 @@ int dap_chain_net_srv_order_find_all_by( const dap_chain_net_srv_price_unit_uid_t a_price_unit, const char a_price_ticker[DAP_CHAIN_TICKER_SIZE_MAX], const uint256_t a_price_min, const uint256_t a_price_max, - dap_chain_net_srv_order_t** a_output_orders, + dap_list_t** a_output_orders, size_t* a_output_orders_count); int dap_chain_net_srv_order_delete_by_hash_str_sync( dap_chain_net_t * a_net,const char * a_hash_str ); diff --git a/modules/net/srv/include/dap_chain_net_srv_stream_session.h b/modules/net/srv/include/dap_chain_net_srv_stream_session.h index dcd2088c88..3ec4c2c797 100644 --- a/modules/net/srv/include/dap_chain_net_srv_stream_session.h +++ b/modules/net/srv/include/dap_chain_net_srv_stream_session.h @@ -52,12 +52,13 @@ typedef struct dap_chain_net_srv_usage{ dap_chain_hash_fast_t tx_cond_hash; dap_chain_hash_fast_t client_pkey_hash; dap_chain_hash_fast_t static_order_hash; - dap_events_socket_uuid_t timer_es_uuid; + dap_timerfd_t *save_limits_timer; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; bool is_active; bool is_free; bool is_grace; bool is_waiting_new_tx_cond; + bool is_waiting_new_tx_cond_in_ledger; bool is_waiting_first_receipt_sign; bool is_limits_changed; // UT_hash_handle hh; // diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c index 0f3f5ae93a..202795189e 100644 --- a/modules/service/datum/dap_chain_net_srv_datum.c +++ b/modules/service/datum/dap_chain_net_srv_datum.c @@ -51,14 +51,6 @@ int dap_chain_net_srv_datum_init() return -1; } s_srv_datum->uid.uint64 = DAP_CHAIN_NET_SRV_DATUM_ID; - dap_chain_net_srv_price_apply_from_my_order(s_srv_datum, "srv_datum"); - dap_chain_net_srv_price_t *l_price; - DL_FOREACH(s_srv_datum->pricelist, l_price) { - dap_chain_net_t *l_net = l_price->net; - if (!l_net) - continue; - dap_chain_net_srv_order_add_notify_callback(l_net, s_order_notficator, l_net); - } return 0; } @@ -214,10 +206,7 @@ void s_order_notficator(dap_store_obj_t *a_obj, void *a_arg) if (!dap_chain_net_srv_uid_compare(l_order->srv_uid, s_srv_datum->uid)) return; // order from another service dap_chain_net_srv_price_t *l_price = NULL; - DL_FOREACH(s_srv_datum->pricelist, l_price) { - if (l_price->net == l_net) - break; - } + if (!l_price || l_price->net != l_net) { log_it(L_DEBUG, "Price for net %s is not set", l_net->pub.name); return; // price not set for this network diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index fc801241fe..6c81105973 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -101,7 +101,6 @@ typedef struct iphdr dap_os_iphdr_t; #include "dap_chain_node_cli.h" #include "dap_chain_ledger.h" #include "dap_events.h" -#include "dap_context.h" #define LOG_TAG "dap_chain_net_srv_vpn" @@ -197,6 +196,7 @@ static dap_stream_ch_chain_net_srv_remain_service_store_t* s_callback_get_remain dap_chain_net_srv_client_remote_t * a_srv_client); static int s_callback_save_remain_service(dap_chain_net_srv_t * a_srv, uint32_t usage_id, dap_chain_net_srv_client_remote_t * a_srv_client); static bool s_save_limits(void* arg); +static char* s_ch_vpn_get_my_pkey_str(dap_chain_net_srv_usage_t* a_usage); // Stream callbacks static void s_ch_vpn_new(dap_stream_ch_t* ch, void* arg); static void s_ch_vpn_delete(dap_stream_ch_t* ch, void* arg); @@ -248,6 +248,7 @@ static bool s_tun_client_send_data_unsafe(dap_chain_net_srv_ch_vpn_t * l_ch_vpn, size_t l_data_sent = dap_stream_ch_pkt_write_unsafe(l_ch_vpn->ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, l_pkt_out, l_data_to_send); s_update_limits(l_ch_vpn->ch,l_srv_session,l_usage, l_data_sent); l_srv_session->stats.bytes_recv += l_data_sent; + l_usage->client->bytes_received += l_data_sent; if ( l_data_sent < l_data_to_send){ log_it(L_WARNING, "Wasn't sent all the data in tunnel (%zd was sent from %zd): probably buffer overflow", l_data_sent, l_data_to_send); l_srv_session->stats.bytes_recv_lost += l_data_to_send - l_data_sent; @@ -281,6 +282,7 @@ static bool s_tun_client_send_data_inter(dap_events_socket_t * a_es_input, dap_c return false; }else{ l_srv_session->stats.bytes_recv += l_data_sent; + l_usage->client->bytes_received += l_data_sent; l_srv_session->stats.packets_recv++; return true; } @@ -870,6 +872,10 @@ static int s_vpn_service_create(dap_config_t * g_config) dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_vpn", &l_srv_callbacks); + if (!l_srv){ + log_it(L_CRITICAL, "VPN service initialization failed."); + return -2; + } dap_chain_net_srv_vpn_t* l_srv_vpn = DAP_NEW_Z( dap_chain_net_srv_vpn_t); if(!l_srv_vpn) { @@ -895,19 +901,24 @@ int dap_chain_net_srv_vpn_init(dap_config_t * g_config) { s_vpn_tun_init(); log_it(L_DEBUG,"Initializing TUN driver..."); - if(s_vpn_tun_create(g_config) != 0){ + if(s_vpn_tun_create(g_config)){ log_it(L_CRITICAL, "Error initializing TUN device driver!"); + dap_chain_net_srv_vpn_deinit(); return -1; } log_it(L_INFO,"TUN driver configured successfuly"); - s_vpn_service_create(g_config); + if (s_vpn_service_create(g_config)){ + log_it(L_CRITICAL, "VPN service creating failed"); + dap_chain_net_srv_vpn_deinit(); + return -2; + } dap_stream_ch_proc_add(DAP_STREAM_CH_NET_SRV_ID_VPN, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, s_ch_packet_out); // add console command to display vpn statistics dap_cli_server_cmd_add ("vpn_stat", com_vpn_statistics, "VPN statistics", - "vpn_stat -net <net name> [-full]\n" + "vpn_stat -net <net_name> [-full]\n" ); return 0; } @@ -919,8 +930,8 @@ void dap_chain_net_srv_vpn_deinit(void) { pthread_mutex_destroy(&s_tun_sockets_mutex_started); pthread_cond_destroy(&s_tun_sockets_cond_started); - DAP_DELETE(s_srv_vpn_addr); - DAP_DELETE(s_srv_vpn_mask); + DAP_DEL_Z(s_srv_vpn_addr); + DAP_DEL_Z(s_srv_vpn_mask); if(s_raw_server) DAP_DELETE(s_raw_server); } @@ -950,10 +961,8 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u size_t l_receipt_size = a_request_size; log_it( L_INFO, "s_callback_response_success is called"); -// dap_stream_ch_chain_net_srv_pkt_request_t * l_request = (dap_stream_ch_chain_net_srv_pkt_request_t *) a_request; -// dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_srv_client->ch->stream->session->_inheritor; dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_srv_client->ch->stream->session->_inheritor; - dap_chain_net_srv_usage_t * l_usage_active = l_srv_session->usage_active;// dap_chain_net_srv_usage_find_unsafe(l_srv_session,a_usage_id); + dap_chain_net_srv_usage_t * l_usage_active = l_srv_session->usage_active; dap_chain_net_srv_ch_vpn_t * l_srv_ch_vpn =(dap_chain_net_srv_ch_vpn_t*) a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID] ? a_srv_client->ch->stream->channel[DAP_CHAIN_NET_SRV_VPN_ID]->internal : NULL; if ( !l_usage_active){ @@ -981,47 +990,30 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u l_args->srv = a_srv; l_args->srv_client = a_srv_client; l_args->usage_id = a_usage_id; - l_usage_active->timer_es_uuid = dap_timerfd_start_on_worker(l_usage_active->client->stream_worker->worker, 60 * 1000, - (dap_timerfd_callback_t)s_save_limits, l_args)->esocket_uuid; + l_usage_active->save_limits_timer = dap_timerfd_start_on_worker(l_usage_active->client->stream_worker->worker, 60 * 1000, + (dap_timerfd_callback_t)s_save_limits, l_args); l_srv_session->limits_units_type.uint32 = l_usage_active->receipt->receipt_info.units_type.uint32; switch( l_usage_active->receipt->receipt_info.units_type.enm){ - case SERV_UNIT_DAY:{ - l_srv_session->last_update_ts = time(NULL); - if (!l_usage_active->is_grace && l_srv_session->limits_ts <= 0){ - l_srv_session->limits_ts = (time_t)l_usage_active->receipt->receipt_info.units*24*3600; - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" seconds more for VPN usage", l_usage_active->receipt->receipt_info.units); - } - } break; case SERV_UNIT_SEC:{ l_srv_session->last_update_ts = time(NULL); if (!l_usage_active->is_grace && l_srv_session->limits_ts <= 0){ + log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" seconds more for VPN usage", l_srv_session->limits_ts < 0 ? l_usage_active->receipt->receipt_info.units + l_srv_session->limits_ts : + l_usage_active->receipt->receipt_info.units); l_srv_session->limits_ts += (time_t)l_usage_active->receipt->receipt_info.units; - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" seconds more for VPN usage", l_usage_active->receipt->receipt_info.units); } } break; case SERV_UNIT_B:{ if (!l_usage_active->is_grace && l_srv_session->limits_bytes <= 0){ + log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", l_srv_session->limits_ts < 0 ? l_usage_active->receipt->receipt_info.units + l_srv_session->limits_ts : + l_usage_active->receipt->receipt_info.units); l_srv_session->limits_bytes = (uintmax_t) l_usage_active->receipt->receipt_info.units; - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", l_usage_active->receipt->receipt_info.units); - } - } break; - case SERV_UNIT_KB:{ - if (!l_usage_active->is_grace && l_srv_session->limits_bytes <= 0){ - l_srv_session->limits_bytes = 1000ull * ( (uintmax_t) l_usage_active->receipt->receipt_info.units); - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", l_usage_active->receipt->receipt_info.units); - } - } break; - case SERV_UNIT_MB:{ - if (!l_usage_active->is_grace && l_srv_session->limits_bytes <= 0){ - l_srv_session->limits_bytes = 1000000ull * ( (uintmax_t) l_usage_active->receipt->receipt_info.units); - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", l_usage_active->receipt->receipt_info.units); } } break; default: { log_it(L_WARNING, "VPN doesnt accept serv unit type 0x%08X", l_usage_active->receipt->receipt_info.units_type.uint32 ); + dap_stream_ch_pkt_write_unsafe(l_usage_active->client->ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); dap_stream_ch_set_ready_to_write_unsafe(l_usage_active->client->ch,false); dap_stream_ch_set_ready_to_read_unsafe(l_usage_active->client->ch,false); - dap_stream_ch_pkt_write_unsafe(l_usage_active->client->ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } } else if (!l_usage_active->is_free && !l_usage_active->receipt && l_usage_active->is_grace){ @@ -1091,7 +1083,13 @@ static dap_stream_ch_chain_net_srv_remain_service_store_t* s_callback_get_remain dap_chain_net_t *l_net = l_usage->net; // get remain units from DB - char *l_remain_limits_gdb_group = dap_strdup_printf( "local.srv_pay.%s.vpn_srv.remain_limits", l_net->pub.name); + char *l_server_pkey_hash = s_ch_vpn_get_my_pkey_str(l_usage); + if (!l_server_pkey_hash){ + log_it(L_DEBUG, "Can't get server pkey hash."); + return NULL; + } + char *l_remain_limits_gdb_group = dap_strdup_printf( "%s.0x%016"DAP_UINT64_FORMAT_x".remain_limits.%s", l_net->pub.gdb_groups_prefix, a_srv->uid.uint64, l_server_pkey_hash); + DAP_DEL_Z(l_server_pkey_hash); char *l_user_key = dap_chain_hash_fast_to_str_new(&l_usage->client_pkey_hash); log_it(L_DEBUG, "Checkout user %s in group %s", l_user_key, l_remain_limits_gdb_group); dap_stream_ch_chain_net_srv_remain_service_store_t* l_remain_service = NULL; @@ -1112,6 +1110,33 @@ static bool s_save_limits(void* arg) return true; } +static char* s_ch_vpn_get_my_pkey_str(dap_chain_net_srv_usage_t* a_usage) +{ + dap_chain_net_srv_usage_t* l_usage = a_usage; + if (!l_usage){ + log_it(L_DEBUG, "Can't save remain servis. Usage is NULL."); + return NULL; + } + + dap_chain_net_srv_price_t *l_price = l_usage->price; + + dap_hash_fast_t price_pkey_hash = {}; + size_t l_key_size = 0; + uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(l_price->receipt_sign_cert->enc_key, &l_key_size); + if (!l_pub_key || !l_key_size) + { + log_it(L_ERROR, "Can't get pkey from cert %s.", l_price->receipt_sign_cert->name); + return NULL; + } + + dap_hash_fast(l_pub_key, l_key_size, &price_pkey_hash); + DAP_DELETE(l_pub_key); + char* l_pkey_hash_str = dap_chain_hash_fast_to_str_new(&price_pkey_hash); + + return l_pkey_hash_str; + +} + static int s_callback_save_remain_service(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id, dap_chain_net_srv_client_remote_t * a_srv_client) { @@ -1136,7 +1161,13 @@ static int s_callback_save_remain_service(dap_chain_net_srv_t * a_srv, uint32_t dap_chain_net_t *l_net = l_usage->net; // save remain units from DB - char *l_remain_limits_gdb_group = dap_strdup_printf( "local.srv_pay.%s.vpn_srv.remain_limits", l_net->pub.name); + char *l_server_pkey_hash = s_ch_vpn_get_my_pkey_str(l_usage); + if (!l_server_pkey_hash){ + log_it(L_DEBUG, "Can't get server pkey hash."); + return -101; + } + char *l_remain_limits_gdb_group = dap_strdup_printf( "%s.0x%016"DAP_UINT64_FORMAT_x".remain_limits.%s", l_net->pub.gdb_groups_prefix, a_srv->uid.uint64, l_server_pkey_hash); + DAP_DEL_Z(l_server_pkey_hash); char *l_user_key = dap_chain_hash_fast_to_str_new(&l_usage->client_pkey_hash); log_it(L_DEBUG, "Save user %s remain service into group %s", l_user_key, l_remain_limits_gdb_group); @@ -1146,16 +1177,13 @@ static int s_callback_save_remain_service(dap_chain_net_srv_t * a_srv, uint32_t l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( l_srv_session->usage_active->receipt_next, l_srv_session->usage_active->receipt_next->size, 1); } - l_remain_service.remain_units_type.enm = l_srv_session->limits_units_type.enm; - switch(l_remain_service.remain_units_type.enm){ +// l_remain_service.remain_units_type.enm = l_srv_session->limits_units_type.enm; + switch(l_srv_session->limits_units_type.enm){ case SERV_UNIT_SEC: - case SERV_UNIT_DAY: l_remain_service.limits_ts = l_srv_session->limits_ts >= 0 ? l_srv_session->limits_ts : 0; if(l_receipt_sign) l_remain_service.limits_ts += l_srv_session->usage_active->receipt_next->receipt_info.units; break; - case SERV_UNIT_MB: - case SERV_UNIT_KB: case SERV_UNIT_B: l_remain_service.limits_bytes = l_srv_session->limits_bytes >= 0 ? l_srv_session->limits_bytes : 0; if (l_receipt_sign) @@ -1249,14 +1277,16 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg) dap_chain_net_srv_ch_vpn_t * l_ch_vpn = CH_VPN(a_ch); dap_chain_net_srv_vpn_t * l_srv_vpn =(dap_chain_net_srv_vpn_t *) l_ch_vpn->net_srv->_internal; - // So complicated to update usage client to be sure that nothing breaks it - usage_client_t * l_usage_client = NULL; + dap_chain_net_srv_usage_t *l_usage = NULL; dap_chain_net_srv_stream_session_t *l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); - if (l_srv_session && l_srv_session->usage_active && - l_srv_session->usage_active->client && l_srv_session->usage_active->client->stream_worker) - dap_timerfd_delete_mt(l_srv_session->usage_active->client->stream_worker->worker, l_srv_session->usage_active->timer_es_uuid); + if (l_srv_session) + l_usage = l_srv_session->usage_active; + if (l_usage && l_usage->save_limits_timer){ + dap_timerfd_delete_mt(l_usage->save_limits_timer->worker, l_usage->save_limits_timer->esocket_uuid); + l_usage->save_limits_timer = NULL; + } bool l_is_unleased = false; if ( l_ch_vpn->addr_ipv4.s_addr ){ // if leased address s_tun_send_msg_ip_unassigned_all(a_ch->stream_worker->worker->id,l_ch_vpn, l_ch_vpn->addr_ipv4); // Signal all the workers that we're switching off @@ -1321,14 +1351,10 @@ static void s_update_limits(dap_stream_ch_t * a_ch , return; } - if (a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_DAY || - a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_SEC){ + if (a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_SEC){ time_t l_current_limit_ts = 0; switch( a_usage->receipt->receipt_info.units_type.enm){ - case SERV_UNIT_DAY:{ - l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units*24*3600; - } break; case SERV_UNIT_SEC:{ l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units; } @@ -1358,49 +1384,36 @@ static void s_update_limits(dap_stream_ch_t * a_ch , if ( a_usage->receipt){ // If there is next receipt add the time and request the next receipt a_srv_session->limits_units_type.uint32 = a_usage->receipt->receipt_info.units_type.uint32; switch( a_usage->receipt->receipt_info.units_type.enm){ - case SERV_UNIT_DAY:{ - a_srv_session->limits_ts += (time_t)a_usage->receipt->receipt_info.units*24*3600; - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" days more for VPN usage", a_usage->receipt->receipt_info.units); - } break; case SERV_UNIT_SEC:{ a_srv_session->limits_ts += (time_t)a_usage->receipt->receipt_info.units; log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" seconds more for VPN usage", a_usage->receipt->receipt_info.units); } break; default: { log_it(L_WARNING, "VPN doesnt accept serv unit type 0x%08X for limits_ts", a_usage->receipt->receipt_info.units_type.uint32 ); + dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); - dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } }else if (!a_usage->is_grace){ log_it( L_NOTICE, "No activate receipt in usage, switch off write callback for channel"); dap_stream_ch_chain_net_srv_pkt_error_t l_err = { }; l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND ; + dap_stream_ch_pkt_write_unsafe(a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , &l_err, sizeof(l_err)); dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); - dap_stream_ch_pkt_write_unsafe(a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , &l_err, sizeof(l_err)); } } - }else if ( a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_B || - a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_KB || - a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_MB ){ + }else if ( a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_B){ intmax_t current_limit_bytes = 0; if ( a_usage->receipt){// if we have active receipt and a_srv_session->last_update_ts == 0 then we counts units by traffic switch( a_usage->receipt->receipt_info.units_type.enm){ case SERV_UNIT_B:{ current_limit_bytes = (uintmax_t) a_usage->receipt->receipt_info.units; } break; - case SERV_UNIT_KB:{ - current_limit_bytes = 1000ull * ( (uintmax_t) a_usage->receipt->receipt_info.units); - } break; - case SERV_UNIT_MB:{ - current_limit_bytes = 1000000ull * ( (uintmax_t) a_usage->receipt->receipt_info.units); - } break; } } - a_srv_session->limits_bytes -= (intmax_t) a_bytes; a_usage->is_limits_changed = true; if (a_srv_session->limits_bytes && a_srv_session->limits_bytes < current_limit_bytes/2 && ! a_usage->receipt_next){ @@ -1426,28 +1439,20 @@ static void s_update_limits(dap_stream_ch_t * a_ch , a_srv_session->limits_bytes += (uintmax_t) a_usage->receipt->receipt_info.units; log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", a_usage->receipt->receipt_info.units); } break; - case SERV_UNIT_KB:{ - a_srv_session->limits_bytes += 1000ull * ( (uintmax_t) a_usage->receipt->receipt_info.units); - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", a_usage->receipt->receipt_info.units); - } break; - case SERV_UNIT_MB:{ - a_srv_session->limits_bytes += 1000000ull * ( (uintmax_t) a_usage->receipt->receipt_info.units); - log_it(L_INFO,"%"DAP_UINT64_FORMAT_U" bytes more for VPN usage", a_usage->receipt->receipt_info.units); - } break; default: { log_it(L_WARNING, "VPN doesnt accept serv unit type 0x%08X for limits_bytes", a_usage->receipt->receipt_info.units_type.uint32 ); + dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); - dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); } } }else if (!a_usage->is_grace){ log_it( L_NOTICE, "No activate receipt in usage, switch off write callback for channel"); dap_stream_ch_chain_net_srv_pkt_error_t l_err = { }; l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_CANT_FIND ; - dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); - dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); dap_stream_ch_pkt_write_unsafe( a_ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , &l_err, sizeof(l_err)); + dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); + dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); } } @@ -1710,6 +1715,7 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) "You can't provide service with ID %"DAP_UINT64_FORMAT_X" in net %s. Node role should be not lower than master\n", l_usage->service->uid.uint64, l_usage->net->pub.name ); + l_usage->is_active = false; if (l_usage->client) dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); @@ -1787,6 +1793,7 @@ void s_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) size_t l_ret = dap_events_socket_write_unsafe(l_tun->es, l_vpn_pkt, sizeof(l_vpn_pkt->header) + l_vpn_pkt->header.op_data.data_size) - sizeof(l_vpn_pkt->header); l_srv_session->stats.bytes_sent += l_ret; + l_usage->client->bytes_sent += l_ret; s_update_limits(a_ch, l_srv_session, l_usage, l_ret); if (l_ret == l_vpn_pkt->header.op_data.data_size) { l_srv_session->stats.packets_sent++; @@ -1830,8 +1837,9 @@ static bool s_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) dap_stream_ch_set_ready_to_read_unsafe(a_ch,false); return false; } - if ( (! l_usage->is_free) && (! l_usage->receipt && !l_usage->is_grace) ){ + if ( (!l_usage->is_free) && (! l_usage->receipt && !l_usage->is_grace) ){ log_it(L_WARNING, "No active receipt, switching off"); + l_usage->is_active = false; if (l_usage->client) dap_stream_ch_pkt_write_unsafe( l_usage->client->ch , DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_NOTIFY_STOPPED , NULL, 0 ); dap_stream_ch_set_ready_to_write_unsafe(a_ch,false); diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index fa9395dfd8..6465c2df8e 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -441,7 +441,8 @@ char *dap_chain_net_vpn_client_check_result(dap_chain_net_t *a_net, const char* { - dap_chain_net_srv_order_t * l_orders = NULL; + // dap_chain_net_srv_order_t + dap_list_t* l_orders = NULL; size_t l_orders_num = 0; dap_chain_net_srv_uid_t l_srv_uid = { { 0 } }; uint256_t l_price_min = {}; @@ -452,8 +453,8 @@ char *dap_chain_net_vpn_client_check_result(dap_chain_net_t *a_net, const char* if(dap_chain_net_srv_order_find_all_by(a_net, l_direction, l_srv_uid, l_price_unit, NULL, l_price_min, l_price_max, &l_orders, &l_orders_num) == 0){ size_t l_orders_size = 0; - for(size_t i = 0; i < l_orders_num; i++) { - dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *) (((byte_t*) l_orders) + l_orders_size); + for(dap_list_t *l_temp = l_orders;l_temp; l_temp = l_orders->next) { + dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *) l_temp->data; //dap_chain_net_srv_order_dump_to_string(l_order, l_string_ret, l_hash_out_type); dap_chain_hash_fast_t l_hash={0}; char *l_hash_str; @@ -477,9 +478,9 @@ char *dap_chain_net_vpn_client_check_result(dap_chain_net_t *a_net, const char* } dap_string_append_printf(l_string_ret, "Order %s: State %s\n", l_hash_str, l_state_str); DAP_DELETE(l_hash_str); - l_orders_size += dap_chain_net_srv_order_get_size(l_order); //dap_string_append(l_string_ret, "\n"); } + dap_list_free_full(l_orders, NULL); } // return str from dap_string_t return dap_string_free(l_string_ret, false); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 31e49902ec..dcdafae8ff 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -1220,100 +1220,54 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v } case XCHANGE_CREATE_ERROR_INVALID_ARGUMENT: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Some parameters could not be set during a function call"); - DAP_DELETE(l_hash_ret); return -24; } case XCHANGE_CREATE_ERROR_TOKEN_TICKER_SELL_IS_NOT_FOUND_LEDGER: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_sell_str); - DAP_DELETE(l_hash_ret); return -6; } case XCHANGE_CREATE_ERROR_TOKEN_TICKER_BUY_IS_NOT_FOUND_LEDGER: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_buy_str); - DAP_DELETE(l_hash_ret); return -6; } case XCHANGE_CREATE_ERROR_RATE_IS_ZERO: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate n.n = buy / sell (eg: 1.0, 1.135)"); - DAP_DELETE(l_hash_ret); return -9; } case XCHANGE_CREATE_ERROR_FEE_IS_ZERO: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -value <unsigned integer 256>"); - DAP_DELETE(l_hash_ret); return -21; } case XCHANGE_CREATE_ERROR_VALUE_SELL_IS_ZERO: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -value <unsigned integer 256>"); - DAP_DELETE(l_hash_ret); return -9; } case XCHANGE_CREATE_ERROR_INTEGER_OVERFLOW_WITH_SUM_OF_VALUE_AND_FEE: { log_it(L_ERROR, "Integer overflow with sum of value and fee"); dap_cli_server_cmd_set_reply_text(a_str_reply, "Integer overflow with sum of value and fee"); - DAP_DELETE(l_hash_ret); return -22; } case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_FOR_FEE_IN_SPECIFIED_WALLET: { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash for fee in specified wallet", l_sign_str); - DAP_DELETE(l_hash_ret); return -23; } case XCHANGE_CREATE_ERROR_NOT_ENOUGH_CASH_IN_SPECIFIED_WALLET: { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash in specified wallet", l_sign_str); - DAP_DELETE(l_hash_ret); return -12; } case XCHANGE_CREATE_ERROR_MEMORY_ALLOCATED: { dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory"); - DAP_DELETE(l_hash_ret); return -1; } case XCHANGE_CREATE_ERROR_CAN_NOT_COMPOSE_THE_CONDITIONAL_TRANSACTION: { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - DAP_DELETE(l_hash_ret); return -14; } case XCHANGE_CREATE_ERROR_CAN_NOT_PUT_TRANSACTION_TO_MEMPOOL: { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - DAP_DELETE(l_hash_ret); return -15; } } - - // Create the price - dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t); - if (!l_price) { - log_it(L_CRITICAL, "Memory allocation error"); - dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory"); - dap_chain_wallet_close(l_wallet); - return -1; - } - dap_stpcpy(l_price->token_sell, l_token_sell_str); - l_price->net = l_net; - dap_stpcpy(l_price->token_buy, l_token_buy_str); - l_price->datoshi_sell = l_datoshi_sell; - l_price->rate = l_rate; - l_price->fee = l_fee; - // Create conditional transaction - dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet); - if (!l_tx) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - DAP_DELETE(l_price); - dap_chain_wallet_close(l_wallet); - return -14; - } - dap_hash_fast_t l_tx_hash ={}; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - char* l_ret = NULL; - if(!(l_ret = s_xchange_tx_put(l_tx, l_net))) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str); - DAP_DELETE(l_price); - return -15; - } - // To avoid confusion, the term "order" will apply to the original conditional exchange offer transactions. - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_ret); - DAP_DELETE(l_ret); } break; case CMD_HISTORY:{ -- GitLab