/* * Authors: * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> * DeM Labs Inc. https://demlabs.net * Kelvin Project https://github.com/kelvinblockchain * Copyright (c) 2017-2019 * All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. DAP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> #include <stdio.h> #include <time.h> #include <stdlib.h> #include <stddef.h> #include <stdint.h> #ifdef WIN32 #include <winsock2.h> #include <windows.h> #include <mswsock.h> #include <ws2tcpip.h> #include <io.h> #endif #include <errno.h> #include <string.h> #include <pthread.h> #include "dap_common.h" #include "dap_strfuncs.h" #include "dap_cert.h" #include "uthash.h" #include "dap_http_client.h" #include "dap_global_db.h" #include "dap_stream.h" #include "dap_stream_ch_pkt.h" #include "dap_stream_ch_proc.h" #include "dap_stream_ch_chain_net_pkt.h" #include "dap_stream_ch_chain_net.h" #include "dap_chain_net_srv_stake_pos_delegate.h" #define LOG_TAG "dap_stream_ch_chain_net" 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); static void s_stream_ch_packet_in(dap_stream_ch_t* ch, void* arg); /** * @brief dap_stream_ch_chain_net_init * @return always 0 */ int dap_stream_ch_chain_net_init() { log_it(L_NOTICE, "Chain network channel initialized"); dap_stream_ch_proc_add(DAP_STREAM_CH_NET_ID, s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in, NULL); return 0; } /** * @brief dap_chain_ch_deinit */ void dap_stream_ch_chain_net_deinit() { } /** * @brief s_stream_ch_new * @param a_ch * @param arg */ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg) { (void) a_arg; a_ch->internal = DAP_NEW_Z(dap_stream_ch_chain_net_t); dap_stream_ch_chain_net_t * l_ch_chain_net = DAP_STREAM_CH_CHAIN_NET(a_ch); l_ch_chain_net->ch = a_ch; } /** * @brief s_stream_ch_delete * @param ch * @param arg */ void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg) { (void) a_arg; DAP_DEL_Z(a_ch->internal); } /** * @brief s_stream_ch_packet_in * @param ch * @param arg */ void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg) { dap_stream_ch_chain_net_t * l_ch_chain_net = DAP_STREAM_CH_CHAIN_NET(a_ch); if(l_ch_chain_net) { dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *)a_arg; if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_TEST) { char *l_data_hash_str; dap_get_data_hash_str_static(l_ch_pkt->data, l_ch_pkt->hdr.data_size, l_data_hash_str); log_it(L_ATT, "Receive test data packet with hash %s", l_data_hash_str); return; } if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_pkt_t)) { log_it(L_WARNING, "Too small stream channel N packet size %u (header size %zu)", l_ch_pkt->hdr.data_size, sizeof(dap_stream_ch_chain_net_pkt_t)); return; } dap_stream_ch_chain_net_pkt_t *l_ch_chain_net_pkt = (dap_stream_ch_chain_net_pkt_t *)l_ch_pkt->data; if (l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t) > l_ch_pkt->hdr.data_size) { log_it(L_WARNING, "Too small stream channel N packet size %u (expected at least %zu)", l_ch_pkt->hdr.data_size, l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t)); return; } if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR) { char *l_err_str = (char *)l_ch_chain_net_pkt->data; log_it(L_WARNING, "Stream channel N for network communication got error on other side: %s", l_err_str); return; } dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id); if (!l_net) { log_it(L_ERROR, "Invalid net id in packet"); char l_err_str[] = "ERROR_NET_INVALID_ID"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str, sizeof(l_err_str)); return; } uint16_t l_acl_idx = dap_chain_net_get_acl_idx(l_net); uint8_t l_acl = a_ch->stream->session->acl ? a_ch->stream->session->acl[l_acl_idx] : 1; if (!l_acl) { log_it(L_WARNING, "Unauthorized request attempt to network %s", dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id)->pub.name); char l_err_str[] = "ERROR_NET_NOT_AUTHORIZED"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str, sizeof(l_err_str)); return; } /*if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, "ERROR_NET_IS_OFFLINE"); a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; return; }*/ switch (l_ch_pkt->hdr.type) { case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ANNOUNCE: assert(!dap_stream_node_addr_is_blank(&a_ch->stream->node)); dap_accounting_downlink_in_net(l_net->pub.id.uint64, &a_ch->stream->node); break; // received ping request - > send pong request case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PING: //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PING"); dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG, l_ch_chain_net_pkt->hdr.net_id,NULL, 0); dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); break; // receive pong request -> send nothing case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG: //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PONG"); dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); break; case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_VALIDATOR_READY_REQUEST:{ log_it(L_INFO, "Get CH_CHAIN_NET_PKT_TYPE_NODE_VALIDATOR_READY_REQUEST"); dap_chain_net_t * l_net = dap_chain_net_by_id( l_ch_chain_net_pkt->hdr.net_id ); if ( l_net == NULL){ char l_err_str[]="ERROR_NET_INVALID_ID"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str,sizeof (l_err_str)); 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_enc_key_t * enc_key_pvt = NULL; dap_chain_t *l_chain = NULL; DL_FOREACH(l_net->pub.chains, l_chain) if(l_chain->callback_get_signing_certificate != NULL){ enc_key_pvt = l_chain->callback_get_signing_certificate(l_chain); if(enc_key_pvt) break; } dap_sign_t *l_sign = NULL; size_t sign_s = 0; size_t l_orders_num = 0; dap_chain_ch_validator_test_t *send = NULL; dap_chain_net_srv_price_unit_uid_t l_price_unit = { { 0 } }; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID }; uint256_t l_price_min = {}; uint256_t l_price_max = {}; uint8_t flags = 0; dap_chain_node_addr_t l_cur_node_addr = { .uint64 = dap_chain_net_get_cur_addr_int(l_net) }; if(enc_key_pvt) { flags = flags | F_CERT;//faund sert l_sign = dap_sign_create(enc_key_pvt, (uint8_t*)l_ch_chain_net_pkt->data, l_ch_chain_net_pkt->hdr.data_size, 0); if(l_sign) { sign_s = dap_sign_get_size(l_sign); flags = flags | D_SIGN;//data signed } else flags = flags & ~D_SIGN;//data doesn't sign } else flags = flags & ~F_CERT;//Specified certificate not found send = DAP_NEW_Z_SIZE(dap_chain_ch_validator_test_t, sizeof(dap_chain_ch_validator_test_t) + sign_s); #ifdef DAP_VERSION strncpy((char *)send->header.version, (char *)DAP_VERSION, sizeof(send->header.version)); #endif send->header.sign_size = sign_s; //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 (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)) auto_update = true; else auto_update = false; flags = auto_online ? flags | A_ONLN : flags & ~A_ONLN; flags = auto_update ? flags | A_UPDT : flags & ~A_UPDT; send->header.flags = flags; //add sign if(sign_s) memcpy(send->sign,l_sign,sign_s); dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_VALIDATOR_READY , l_ch_chain_net_pkt->hdr.net_id, send, sizeof(dap_chain_ch_validator_test_t) + sign_s); dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); if(l_sign) DAP_DELETE(l_sign); DAP_DELETE(send); } } break; case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_NODE_VALIDATOR_READY:{ log_it(L_INFO, "Get CH_CHAIN_NET_PKT_TYPE_NODE_VALIDATOR_READY"); dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); } break; default: log_it(L_ERROR, "Unknown paket type %hhu", l_ch_pkt->hdr.type); break; } if(l_ch_chain_net->notify_callback) l_ch_chain_net->notify_callback(l_ch_chain_net,l_ch_pkt->hdr.type, l_ch_chain_net_pkt, l_ch_chain_net_pkt->hdr.data_size, l_ch_chain_net->notify_callback_arg); } }