From 07f6ff9e309dda3156aa60af908e34a56790b1b0 Mon Sep 17 00:00:00 2001 From: "daniil.frolov" <daniil.frolov@demlabs.net> Date: Tue, 25 Feb 2025 18:54:39 +0300 Subject: [PATCH] .. --- .../dap_stream_ch_chain_net_srv.c | 533 ++++++++++++++---- modules/net/srv/include/dap_chain_net_srv.h | 1 - .../dap_chain_net_srv_stream_session.h | 50 +- modules/service/vpn/dap_chain_net_srv_vpn.c | 2 + 4 files changed, 465 insertions(+), 121 deletions(-) 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 6363737ad1..48b05b675b 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 @@ -54,6 +54,7 @@ typedef enum { PAY_SERVICE_STATUS_SUCCESS = 0, PAY_SERVICE_STATUS_NOT_ENOUGH, PAY_SERVICE_STATUS_TX_ERROR, + PAY_SERVICE_STATUS_TX_CANT_FIND, PAY_SERVICE_STATUS_MEMALLOC_ERROR, } pay_service_status; @@ -105,6 +106,262 @@ 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); + +/** Service states handlers **/ +static void s_go_to_service_with_remain(dap_chain_net_srv_usage_t *a_usage); +static void s_go_to_service_in_grace(dap_chain_net_srv_usage_t *a_usage); +static void s_go_to_service_normal(dap_chain_net_srv_usage_t *a_usage); +static void s_go_to_service_error(dap_chain_net_srv_usage_t *a_usage); +/*****************************/ + +/** Service substates handlers **/ +static void s_service_substate_go_to_normal_mode(dap_chain_net_srv_usage_t *a_usage); +static void s_service_substate_request_first_receipt(dap_chain_net_srv_usage_t *a_usage); +static void s_service_substate_request_next_receipt(dap_chain_net_srv_usage_t *a_usage); +static void s_service_substate_pay_service(dap_chain_net_srv_usage_t *a_usage); +/********************************/ + + + + + + +static void s_go_to_service_with_remain(dap_chain_net_srv_usage_t *a_usage) +{ + if (!a_usage) + return; + + a_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_REMAIN_LIMITS; + a_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_IDLE; + + // Start with remain limit + // 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_usage->client->ch->stream->session->_inheritor; + switch(l_tx_out_cond->subtype.srv_pay.unit.enm){ + case SERV_UNIT_SEC: + l_srv_session->limits_ts = l_remain_service->limits_ts; + break; + case SERV_UNIT_B: + l_srv_session->limits_bytes = l_remain_service->limits_bytes; + break; + } + char *l_user_key = dap_chain_hash_fast_to_str_new(&a_grace->usage->client_pkey_hash); + log_it(L_INFO, "User %s has %ld %s remain service. Start service without paying.", l_user_key, + 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)); + DAP_DELETE(l_user_key); + 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, + l_success_size); + if(!l_success) { + log_it(L_ERROR, "Memory allocation error in %s, line %d", __PRETTY_FUNCTION__, __LINE__); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR; + 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 (a_grace->usage->service && a_grace->usage->service->callbacks.response_error) + a_grace->usage->service->callbacks.response_error(a_grace->usage->service, 0, NULL, &l_err, sizeof(l_err)); + + // TODO go to state error + } else { + l_success->hdr.usage_id = a_grace->usage->id; + l_success->hdr.net_id.uint64 = a_grace->usage->net->pub.id.uint64; + l_success->hdr.srv_uid.uint64 = a_grace->usage->service->uid.uint64; + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size); + + // Restore last receipt from DB + + // create and fill first receipt + // + // a_grace->usage->receipt = dap_chain_datum_tx_receipt_create( + // a_grace->usage->service->uid, l_price->units_uid, l_price->units, l_price->value_datoshi, NULL, 0); + // if (a_grace->usage->service->callbacks.response_success) + // a_grace->usage->service->callbacks.response_success(a_grace->usage->service, a_grace->usage->id, + // a_grace->usage->client, a_grace->usage->receipt, + // sizeof(dap_chain_datum_tx_receipt_t) + a_grace->usage->receipt->size + a_grace->usage->receipt->exts_size); + // DAP_DELETE(l_success); + } + + + // TODO go to substate normal + + DAP_DELETE(a_grace->request); + DAP_DELETE(a_grace); + DAP_DELETE(l_remain_service); + return false; + +} + +static void s_go_to_service_in_grace(dap_chain_net_srv_usage_t *a_usage) +{ + if (!a_usage) + return; + + a_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_GRACE; + a_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_IDLE; + + dap_stream_ch_t *l_ch = a_usage->client->ch; + dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get( a_usage->service->uid); + dap_stream_ch_chain_net_srv_pkt_error_t l_err; + dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); + if (!l_grace) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + 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)); + if (l_srv && l_srv->callbacks.response_error) + l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); + + // TODO: go to substate error + + + return; + } + l_grace->ch_uuid = l_ch->uuid; + l_grace->stream_worker = l_ch->stream_worker; + l_grace->usage = a_usage; + // TODO go to wait_tx_for_pay + // TODO call start service callback + +} + +static void s_go_to_service_normal(dap_chain_net_srv_usage_t *a_usage) +{ + if (!a_usage) + return; + + if (a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_IDLE || + a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_GRACE){ + + a_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_NORMAL; + a_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_IDLE; + + dap_stream_ch_t *l_ch = a_usage->client->ch; + dap_chain_net_srv_t *l_srv = dap_chain_net_srv_get( a_usage->service->uid); + dap_stream_ch_chain_net_srv_pkt_error_t l_err; + dap_chain_net_t *l_net = a_usage->net; + dap_chain_datum_tx_t *l_tx = a_usage->tx_cond; + dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL ); + + + 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 ; + //TODO go to error state + return false; + } + + // Check cond output if it equesl or not to request + if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, a_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 ; + //TODO go to error state + return false; + } + + const char *l_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_usage->net->pub.ledger, &a_usage->tx_cond_hash); + if (!l_ticker) { + char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }; + dap_hash_fast_to_str(&a_usage->tx_cond_hash, l_hash_str, sizeof(l_hash_str)); + 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_TICKER_ERROR; + //TODO go to error state + return false; + } + dap_stpcpy(a_usage->token_ticker, l_ticker); + + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_usage->static_order_hash); + log_it(L_MSG, "Using price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + + dap_chain_net_srv_price_t *l_price = a_usage->price; + if (l_price){ + if (l_price->net->pub.id.uint64 != a_usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", a_usage->net->pub.name); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + //TODO go to error state + return false; + } + + 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; + //TODO go to error state + 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_UNIT_TYPE_ERROR; + //TODO go to error state + 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_RECEIPT_UNITS_ERROR; + //TODO go to error state + 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_RECEIPT_UNITS_ERROR; + //TODO go to error state + 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_PRICE_ERROR; + //TODO go to error state + return false; + } + int ret; + if ((ret = a_usage->service->callbacks.requested(a_usage->service, a_usage->id, a_usage->client, NULL, 0)) != 0) { + log_it( L_WARNING, "Request canceled by service callback, return code %d", ret); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_REQUEST_INTERNAL_ERROR; + //TODO go to error state + return false; + } + + // TODO go to waiting first receipt substate + a_usage->receipt = dap_chain_net_srv_issue_receipt(a_usage->service, a_usage->price, NULL, 0); + dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST, + a_usage->receipt, a_usage->receipt->size); + a_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN; + + //start timeout timer + a_usage->receipt_timeout_timer_start_callback(a_usage); + } else if (a_usage->service_state == DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_REMAIN_LIMITS){ + a_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_NORMAL; + a_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_NORMAL; + } else { + + } + +} + +static void s_go_to_service_error(dap_chain_net_srv_usage_t *a_usage) +{ + +} + + + + + + + + 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){ @@ -462,6 +719,8 @@ static bool 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; l_usage->receipt_timeout_timer_start_callback = s_start_receipt_timeout_timer; + l_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_IDLE; + l_usage->service_substate = DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_IDLE; dap_chain_net_srv_price_t * l_price = NULL; bool l_specific_order_free = false; @@ -473,8 +732,8 @@ static bool 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)); - // DAP_DEL_Z(l_usage->client); - // DAP_DEL_Z(l_usage); + DAP_DEL_Z(l_usage->client); + DAP_DEL_Z(l_usage); return false; } @@ -501,41 +760,120 @@ static bool s_service_start(dap_stream_ch_t *a_ch , dap_stream_ch_chain_net_srv_ 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) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR; - 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; + + // check remain limits + dap_stream_ch_chain_net_srv_remain_service_store_t* l_remain_service = NULL; + l_remain_service = l_usage->service->callbacks.get_remain_service(l_usage->service, l_usage->id, l_usage->client); + if (l_remain_service && ((l_remain_service->limits_ts && l_usage->price->units_uid.enm == SERV_UNIT_SEC) || + (l_remain_service->limits_bytes && l_usage->price->units_uid.enm == SERV_UNIT_B))){ + // TODO go to start with remain limits + + } else { + // Check tx + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_usage->tx_cond_hash); + + if (!l_tx){ + // Start grace + + } else { + // Start normal mode + l_usage->tx_cond = l_tx; + s_go_to_service_normal(l_usage) + } } - l_grace->request = DAP_DUP_SIZE(a_request, a_request_size); - if (!l_grace->request) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR; - 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); - DAP_DEL_Z(l_grace); - return false; + + + + + + + + l_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_usage->tx_cond_hash); + if ( ! l_tx ){ // No tx cond transaction, start grace-period + log_it( L_WARNING, "No tx cond transaction"); + 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 + + dap_stream_ch_chain_net_srv_remain_service_store_t* l_remain_service = NULL; + l_remain_service = l_usage->service->callbacks.get_remain_service(l_usage->service, l_usage->id, l_usage->client); + if (l_remain_service && ((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))){ + + // Start with remain limit + // 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_usage->client->ch->stream->session->_inheritor; + switch(l_tx_out_cond->subtype.srv_pay.unit.enm){ + case SERV_UNIT_SEC: + l_srv_session->limits_ts = l_remain_service->limits_ts; + break; + case SERV_UNIT_B: + l_srv_session->limits_bytes = l_remain_service->limits_bytes; + break; + } + char *l_user_key = dap_chain_hash_fast_to_str_new(&a_grace->usage->client_pkey_hash); + log_it(L_INFO, "User %s has %ld %s remain service. Start service without paying.", l_user_key, + 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)); + DAP_DELETE(l_user_key); + 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, + l_success_size); + if(!l_success) { + log_it(L_ERROR, "Memory allocation error in %s, line %d", __PRETTY_FUNCTION__, __LINE__); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR; + 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 (a_grace->usage->service && a_grace->usage->service->callbacks.response_error) + a_grace->usage->service->callbacks.response_error(a_grace->usage->service, 0, NULL, &l_err, sizeof(l_err)); + } else { + l_success->hdr.usage_id = a_grace->usage->id; + l_success->hdr.net_id.uint64 = a_grace->usage->net->pub.id.uint64; + l_success->hdr.srv_uid.uint64 = a_grace->usage->service->uid.uint64; + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size); + + // Restore last receipt from DB + + // create and fill first receipt + // + // a_grace->usage->receipt = dap_chain_datum_tx_receipt_create( + // a_grace->usage->service->uid, l_price->units_uid, l_price->units, l_price->value_datoshi, NULL, 0); + // if (a_grace->usage->service->callbacks.response_success) + // a_grace->usage->service->callbacks.response_success(a_grace->usage->service, a_grace->usage->id, + // a_grace->usage->client, a_grace->usage->receipt, + // sizeof(dap_chain_datum_tx_receipt_t) + a_grace->usage->receipt->size + a_grace->usage->receipt->exts_size); + // DAP_DELETE(l_success); + } + + + + + DAP_DELETE(a_grace->request); + DAP_DELETE(a_grace); + DAP_DELETE(l_remain_service); + return false; + } else { + + } } - 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; + + + + + + + + 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; + l_usage->service_state = DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_FREE; 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, l_success_size); @@ -1174,6 +1512,8 @@ static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace_item) int l_ret = s_pay_cervice(l_grace->usage, l_receipt); switch (l_ret){ + case PAY_SERVICE_STATUS_SUCCESS: + break; case PAY_SERVICE_STATUS_NOT_ENOUGH: if (l_waiting_new_tx_in_ledger){ log_it(L_ERROR, "New tx cond have not enough funds. Waiting for end of service."); @@ -1210,19 +1550,17 @@ static bool s_grace_period_finish(dap_chain_net_srv_grace_usage_t *a_grace_item) RET_WITH_DEL_A_GRACE(0); } break; - case PAY_SERVICE_STATUS_SUCCESS: - break; - case PAY_SERVICE_STATUS_MEMALLOC_ERROR: + case PAY_SERVICE_STATUS_MEMALLOC_ERROR:{ log_it(L_CRITICAL, "%s", c_error_memory_alloc); RET_WITH_DEL_A_GRACE(DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_ALLOC_MEMORY_ERROR); - break; + break;} case PAY_SERVICE_STATUS_TX_ERROR: default: { memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash)); - if (a_usage->receipt_next){ - DAP_DEL_Z(a_usage->receipt_next); - } else if (a_usage->receipt){ - DAP_DEL_Z(a_usage->receipt); + if (l_grace->usage->receipt_next){ + DAP_DEL_Z(l_grace->usage->receipt_next); + } else if (l_grace->usage->receipt){ + DAP_DEL_Z(l_grace->usage->receipt); } l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_CREATION_ERROR; dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); @@ -1338,8 +1676,18 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { // Check receipt sign and make tx if success dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active; + if (! l_usage ){ + log_it(L_WARNING, "No usage in srv."); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND; + 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 && l_usage->service && 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) ); + break; + } - if (!l_usage->is_waiting_first_receipt_sign && !l_usage->is_waiting_next_receipt_sign){ + if (l_usage->service_substate != DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN && + l_usage->service_substate != DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_NEXT_RECEIPT_SIGN){ + // wrong responce break; } @@ -1358,9 +1706,9 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) { log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size, sizeof(dap_chain_receipt_info_t)); - if ( l_usage->receipt_next && !l_usage->is_waiting_first_receipt_sign && l_usage->is_waiting_next_receipt_sign){ // If we have receipt next + if ( l_usage->service_substate == DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_NEXT_RECEIPT_SIGN){ // If we have receipt next DAP_DEL_Z(l_usage->receipt_next); - }else if (l_usage->receipt ){ // If we sign first receipt + }else if (l_usage->service_substate == DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN){ // If we sign first receipt DAP_DEL_Z(l_usage->receipt); } return false; @@ -1370,11 +1718,11 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) size_t l_receipt_size = l_ch_pkt->hdr.data_size; bool l_is_found = false; - if ( l_usage->receipt_next && !l_usage->is_waiting_first_receipt_sign && l_usage->is_waiting_next_receipt_sign){ // If we have receipt next + if (l_usage->service_substate == DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_NEXT_RECEIPT_SIGN){ // If we have receipt next if ( memcmp(&l_usage->receipt_next->receipt_info, &l_receipt->receipt_info,sizeof (l_receipt->receipt_info) )==0 ){ l_is_found = true; } - }else if (l_usage->receipt){ // If we sign first receipt + }else if (l_usage->service_substate == DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN){ // If we sign first receipt if ( memcmp(&l_usage->receipt->receipt_info, &l_receipt->receipt_info,sizeof (l_receipt->receipt_info) )==0 ){ l_is_found = true; } @@ -1392,7 +1740,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) l_err.srv_uid.uint64 = l_usage->service->uid.uint64; dap_chain_tx_out_cond_t *l_tx_out_cond = NULL; - if (! l_usage->tx_cond ){ + if ( ! l_usage->tx_cond ){ log_it(L_WARNING, "No tx cond in usage"); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ; dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) ); @@ -1464,29 +1812,16 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) size_t l_success_size; if (!l_usage->is_grace) { // Form input transaction - char *l_hash_str = dap_hash_fast_to_str_new(&l_usage->tx_cond_hash); - char *l_user_key = dap_chain_hash_fast_to_str_new(&l_usage->client_pkey_hash); - log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt for user %s", l_hash_str, l_user_key); - DAP_DEL_Z(l_hash_str); - DAP_DEL_Z(l_user_key); - int ret_status = 0; - char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(l_usage->net, &l_usage->tx_cond_hash, l_usage->price->wallet_addr, - l_usage->price->receipt_sign_cert->enc_key, - l_receipt, "hex", &ret_status); - if (!ret_status) { - dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_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{ - dap_chain_net_srv_grace_t *l_grace = NULL; - switch(ret_status){ - case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_FIND_FINAL_TX_HASH: + int l_ret = s_pay_cervice(l_usage, l_receipt); + switch (l_ret){ + case PAY_SERVICE_STATUS_SUCCESS: + break; + case PAY_SERVICE_STATUS_TX_CANT_FIND: // TX not found in ledger and we not in grace, start grace log_it(L_ERROR, "Can't find tx cond. Start grace!"); - l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); + dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); if (!l_grace) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - DAP_DELETE(l_tx_in_hash_str); break; } UNUSED(l_grace); @@ -1494,8 +1829,6 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) l_grace->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->request) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - DAP_DEL_Z(l_grace) - DAP_DELETE(l_tx_in_hash_str); break; } l_grace->request->hdr.net_id = l_usage->net->pub.id; @@ -1508,15 +1841,13 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) l_grace->stream_worker = a_ch->stream_worker; l_grace->usage = l_usage; s_grace_period_start(l_grace); - DAP_DELETE(l_tx_in_hash_str); - break; - case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH: + break; + case PAY_SERVICE_STATUS_NOT_ENOUGH: log_it(L_ERROR, "Tx cond have not enough funds"); l_usage->is_waiting_new_tx_cond = 1; - l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); + dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); if (!l_grace) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - DAP_DELETE(l_tx_in_hash_str); return true; } // Parse the request @@ -1524,7 +1855,6 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) if (!l_grace->request) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); DAP_DEL_Z(l_grace) - DAP_DELETE(l_tx_in_hash_str); return true; } l_grace->request->hdr.net_id = l_usage->net->pub.id; @@ -1541,16 +1871,14 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) 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: - case DAP_CHAIN_MEMPOOl_RET_STATUS_WRONG_ADDR: - case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_NATIVE_TOKEN: - case DAP_CHAIN_MEMPOOl_RET_STATUS_NO_COND_OUT: - case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_ADD_TX_OUT: - case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_ADD_SIGN: - default: + } + break; + case PAY_SERVICE_STATUS_MEMALLOC_ERROR:{ + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + return true; + break;} + case PAY_SERVICE_STATUS_TX_ERROR: + default: { log_it(L_ERROR, "Can't create input tx cond transaction!"); memset(&l_usage->tx_cond_hash, 0, sizeof(l_usage->tx_cond_hash)); DAP_DEL_Z(l_usage->receipt_next); @@ -1558,12 +1886,11 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) 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; } - if (!l_usage->is_grace) - break; } + if (!l_usage->is_grace) + break; l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t) + DAP_CHAIN_HASH_FAST_STR_SIZE; } else { l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t); @@ -1763,24 +2090,28 @@ static int s_pay_cervice(dap_chain_net_srv_usage_t *a_usage, dap_chain_datum_tx_ int ret_status = 0; char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(a_usage->net, &a_usage->tx_cond_hash, a_usage->price->wallet_addr, a_usage->price->receipt_sign_cert->enc_key, a_receipt, "hex", &ret_status); - - // PAY_SERVICE_STATUS_NOT_ENOUGH, - // PAY_SERVICE_STATUS_TX_ERROR, - // PAY_SERVICE_STATUS_MEMALLOC_ERROR, - - if (!ret_status) { - dap_chain_hash_fast_from_str(l_tx_in_hash_str, &a_usage->tx_cond_hash); - log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str); - DAP_DEL_Z(l_tx_in_hash_str); - return PAY_SERVICE_STATUS_SUCCESS; - } else { - if(ret_status == DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH){ - log_it(L_ERROR, "Tx cond have not enough funds"); + switch (ret_status){ + case DAP_CHAIN_MEMPOOl_RET_STATUS_SUCCESS: + dap_chain_hash_fast_from_str(l_tx_in_hash_str, &a_usage->tx_cond_hash); + log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str); + DAP_DEL_Z(l_tx_in_hash_str); + return PAY_SERVICE_STATUS_SUCCESS; + case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_FIND_FINAL_TX_HASH: + case DAP_CHAIN_MEMPOOl_RET_STATUS_NO_COND_OUT:{ + if (dap_ledger_tx_find_by_hash(a_usage->net->pub.ledger, &a_usage->tx_cond_hash)) + return PAY_SERVICE_STATUS_NOT_ENOUGH; + else + return PAY_SERVICE_STATUS_TX_CANT_FIND; + }break; + case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH:{ return PAY_SERVICE_STATUS_NOT_ENOUGH; - } else { - log_it(L_ERROR, "Can't create input tx cond transaction!"); - DAP_DEL_Z(l_tx_in_hash_str); + }break; + case DAP_CHAIN_MEMPOOL_RET_STATUS_BAD_ARGUMENTS: + case DAP_CHAIN_MEMPOOl_RET_STATUS_WRONG_ADDR: + case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_NATIVE_TOKEN: + case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_ADD_TX_OUT: + case DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_ADD_SIGN: + default: return PAY_SERVICE_STATUS_TX_ERROR; - } } } \ No newline at end of file diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h index c8b252b9af..cae6917348 100755 --- a/modules/net/srv/include/dap_chain_net_srv.h +++ b/modules/net/srv/include/dap_chain_net_srv.h @@ -96,7 +96,6 @@ typedef struct dap_chain_net_srv_grace { dap_stream_ch_uuid_t ch_uuid; dap_chain_net_srv_usage_t *usage; dap_timerfd_t *timer; - dap_stream_ch_chain_net_srv_pkt_request_t *request; size_t request_size; } dap_chain_net_srv_grace_t; 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 424ca17934..3bdbc6eb51 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 @@ -39,6 +39,26 @@ typedef struct dap_chain_net_srv dap_chain_net_srv_t; typedef struct dap_chain_net_srv_client_remote dap_chain_net_srv_client_remote_t; typedef struct dap_chain_net_srv_price dap_chain_net_srv_price_t; +typedef enum dap_chain_net_srv_usage_service_state{ + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_REMAIN_LIMITS = 0, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_GRACE, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_NORMAL, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_ERROR, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_FREE, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_STATE_IDLE +} dap_chain_net_srv_usage_service_state_t; + +typedef enum dap_chain_net_srv_usage_service_substate{ + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_FIRST_RECEIPT_SIGN=0, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_NEXT_RECEIPT_SIGN, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_TX_FOR_PAYING, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_WAITING_NEW_TX_FROM_CLIENT, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_NORMAL, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_ERROR, + DAP_CHAIN_NET_SRV_USAGE_SERVICE_SUBSTATE_IDLE +} dap_chain_net_srv_usage_service_substate_t; + + typedef struct dap_chain_net_srv_usage{ uint32_t id; // Usage id pthread_rwlock_t rwlock; @@ -60,28 +80,20 @@ typedef struct dap_chain_net_srv_usage{ int receipt_sign_req_cnt; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - uint16_t is_active : 1; - uint16_t is_free : 1; - uint16_t is_grace : 1; - uint16_t is_waiting_new_tx_cond : 1; - uint16_t is_waiting_new_tx_cond_in_ledger : 1; - uint16_t is_waiting_first_receipt_sign : 1; - uint16_t is_waiting_next_receipt_sign : 1; - uint16_t is_limits_changed : 1; - uint16_t reserved : 8; - + dap_chain_net_srv_usage_service_state_t service_state; + dap_chain_net_srv_usage_service_substate_t service_substate; } dap_chain_net_srv_usage_t; typedef struct dap_net_stats{ - uintmax_t bytes_sent; - uintmax_t bytes_recv; - uintmax_t bytes_sent_lost; - uintmax_t bytes_recv_lost; - - uintmax_t packets_sent; - uintmax_t packets_recv; - uintmax_t packets_sent_lost; - intmax_t packets_recv_lost; + uintmax_t bytes_sent; + uintmax_t bytes_recv; + uintmax_t bytes_sent_lost; + uintmax_t bytes_recv_lost; + + uintmax_t packets_sent; + uintmax_t packets_recv; + uintmax_t packets_sent_lost; + intmax_t packets_recv_lost; } dap_net_stats_t; typedef struct dap_chain_net_srv_stream_session { diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index b1ea1c1f70..126b1aaef8 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -971,6 +971,8 @@ static int s_callback_requested(dap_chain_net_srv_t * a_srv, uint32_t a_usage_id return 0; // aways allow to use it for now } + + /** * Called if responses success with all signature checks */ -- GitLab