From 34d938f7ce3e6fc1cb35edb5dfd8dc5f133899e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Al=D0=B5x=D0=B0nder=20Lysik=D0=BEv?= <alexander.lysikov@demlabs.net> Date: Mon, 20 Jul 2020 19:25:34 +0500 Subject: [PATCH] added timerfd and command check --- dap-sdk/net/core/dap_timerfd.c | 159 ++++++++++++++++++ dap-sdk/net/core/include/dap_timerfd.h | 51 ++++++ .../dap_stream_ch_chain_net_srv.c | 20 +++ .../srv/include/dap_chain_net_srv_common.h | 3 + .../service/vpn/dap_chain_net_srv_vpn_cmd.c | 38 ++++- .../service/vpn/dap_chain_net_vpn_client.c | 83 +++++++++ .../vpn/include/dap_chain_net_vpn_client.h | 2 + 7 files changed, 355 insertions(+), 1 deletion(-) create mode 100644 dap-sdk/net/core/dap_timerfd.c create mode 100644 dap-sdk/net/core/include/dap_timerfd.h diff --git a/dap-sdk/net/core/dap_timerfd.c b/dap-sdk/net/core/dap_timerfd.c new file mode 100644 index 0000000000..4fecd22ee2 --- /dev/null +++ b/dap-sdk/net/core/dap_timerfd.c @@ -0,0 +1,159 @@ +/* + * Authors: + * Alexander Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2020 + * 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 <stdint.h> +#include <stdbool.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/timerfd.h> +#include <inttypes.h> + +#include "dap_common.h" +#include "dap_events_socket.h" +#include "dap_timerfd.h" + +#define LOG_TAG "dap_timerfd" + +void callback_timerfd_read(struct dap_events_socket *a_event_sock, void * arg) +{ + uint64_t l_ptiu64; + size_t l_read_ret; + do { + l_read_ret = dap_events_socket_read(a_event_sock, &l_ptiu64, sizeof(l_ptiu64)); + + if(l_read_ret > 0) { + dap_timerfd_t *l_timerfd = a_event_sock->_inheritor; + //printf("\nread() returned %d, %d\n", l_ptiu64, l_read_ret); + struct itimerspec l_ts; + // first expiration in 0 seconds after times start + l_ts.it_interval.tv_sec = 0; + l_ts.it_interval.tv_nsec = 0; + // timeout for timer + l_ts.it_value.tv_sec = l_timerfd->timeout_ms / 1000; + l_ts.it_value.tv_nsec = (l_timerfd->timeout_ms % 1000) * 1000000; + if(timerfd_settime(l_timerfd->tfd, 0, &l_ts, NULL) < 0) { + log_it(L_WARNING, "callback_timerfd_read() failed: timerfd_settime() errno=%d\n", errno); + } + // run user's callback + if(l_timerfd->callback) + l_timerfd->callback(l_timerfd->callback_arg); + } + } while(l_read_ret > 0); + dap_events_socket_set_readable(a_event_sock, true); +} + +void tmpd(void * arg) +{ + printf("2 arg=0x%x\n", arg); +} + +/** + * @brief dap_events_socket_init Init clients module + * @return Zero if ok others if no + */ +int dap_timerfd_init() +{ + log_it(L_NOTICE, "Initialized timerfd"); + + dap_timerfd_t *l_sd = dap_timerfd_start(1000, &tmpd, (void*)45); + return 0; +} + +/** + * @brief dap_timerfd_start + * @param a_timeout_ms + * @param a_callback + * @return new allocated dap_timerfd_t structure or NULL if error + */ +dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t *a_callback, void *a_callback_arg) +{ + struct itimerspec l_ts; + int l_tfd = timerfd_create(CLOCK_MONOTONIC, 0); + if(l_tfd == -1) { + log_it(L_WARNING, "dap_timerfd_start() failed: timerfd_create() errno=%d\n", errno); + return NULL; + } + // first expiration in 0 seconds after times start + l_ts.it_interval.tv_sec = 0; + l_ts.it_interval.tv_nsec = 0; + // timeout for timer + l_ts.it_value.tv_sec = a_timeout_ms / 1000; + l_ts.it_value.tv_nsec = (a_timeout_ms % 1000) * 1000000; + if(timerfd_settime(l_tfd, 0, &l_ts, NULL) < 0) { + log_it(L_WARNING, "dap_timerfd_start() failed: timerfd_settime() errno=%d\n", errno); + close(l_tfd); + return NULL; + } + + // create dap_timerfd_t structure + dap_timerfd_t *l_timerfd = DAP_NEW(dap_timerfd_t); + + // create events_socket for timer file descriptor + static dap_events_socket_callbacks_t l_s_callbacks = { + .read_callback = callback_timerfd_read, + .write_callback = NULL, + .error_callback = NULL, + .delete_callback = NULL + }; + dap_events_socket_t * l_events_socket = dap_events_socket_wrap_no_add(NULL, l_tfd, &l_s_callbacks); + l_events_socket->type = DESCRIPTOR_TYPE_FILE; + dap_events_socket_create_after(l_events_socket); + // pass l_timerfd to events_socket + l_events_socket->_inheritor = l_timerfd; + + // fill out dap_timerfd_t structure + l_timerfd->timeout_ms = a_timeout_ms; + l_timerfd->tfd = l_tfd; + l_timerfd->events_socket = l_events_socket; + l_timerfd->callback = a_callback; + l_timerfd->callback_arg = a_callback_arg; + return l_timerfd; +} + +/** + * @brief dap_timerfd_stop + * @param a_tfd + * @param a_callback + * @return 0 or <0 if error + */ +int dap_timerfd_delete(dap_timerfd_t *l_timerfd) +{ + if(!l_timerfd || l_timerfd->tfd < 1 || !l_timerfd->events_socket) { + return -1; + } + + if(close(l_timerfd->tfd) == -1) { + log_it(L_WARNING, "dap_timerfd_stop() failed to close timerfd: errno=%d\n", errno); + return -2; + } + + dap_events_socket_kill_socket(l_timerfd->events_socket); + l_timerfd->events_socket = NULL; + DAP_DELETE(l_timerfd); + return 0; +} + diff --git a/dap-sdk/net/core/include/dap_timerfd.h b/dap-sdk/net/core/include/dap_timerfd.h new file mode 100644 index 0000000000..a658606e83 --- /dev/null +++ b/dap-sdk/net/core/include/dap_timerfd.h @@ -0,0 +1,51 @@ +/* + * Authors: + * Alexander Lysikov <alexander.lysikov@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * Kelvin Project https://github.com/kelvinblockchain + * Copyright (c) 2020 + * 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 <stdint.h> +#include <stdbool.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/timerfd.h> +#include <inttypes.h> + +#include "dap_common.h" +#include "dap_events_socket.h" + +typedef void (*dap_timerfd_callback_t)(void * arg); // Callback for timer + +typedef struct dap_timerfd { + uint64_t timeout_ms; + int tfd; //timer file descriptor + dap_events_socket_t *events_socket; + dap_timerfd_callback_t callback; + void *callback_arg; +} dap_timerfd_t; + +int dap_timerfd_init(); +dap_timerfd_t* dap_timerfd_start(uint64_t a_timeout_ms, dap_timerfd_callback_t *a_callback, void *callback_arg); +int dap_timerfd_delete(dap_timerfd_t *l_timerfd); + 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 694be366df..91e4a18d77 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 @@ -146,6 +146,26 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) if(l_ch_pkt ) { switch (l_ch_pkt->hdr.type) { + // for send test data + /*todo l_receipt_new + * case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST:{ + // send response + if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE, + l_receipt_new, l_receipt_new->size)) { + dap_stream_ch_set_ready_to_write(a_ch, true); + } + } + break; + // for receive test data. + case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE: { + // send response + if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE, + l_receipt_new, l_receipt_new->size)) { + dap_stream_ch_set_ready_to_write(a_ch, true); + } + } + break;*/ + // only for server case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST:{ if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){ diff --git a/modules/net/srv/include/dap_chain_net_srv_common.h b/modules/net/srv/include/dap_chain_net_srv_common.h index 673e65959d..aedeed9adb 100755 --- a/modules/net/srv/include/dap_chain_net_srv_common.h +++ b/modules/net/srv/include/dap_chain_net_srv_common.h @@ -98,6 +98,9 @@ typedef struct dap_chain_net_srv_price #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA 0x30 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS 0xf0 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR 0xff +// for connection testing +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST 0x40 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_RESPONSE 0x41 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_UNDEFINED 0x00000000 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND 0x00000100 diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c index 01a18e9f0d..be11d11264 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c @@ -12,7 +12,7 @@ int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_repl { #ifndef _WIN32 enum { - CMD_NONE, CMD_INIT, CMD_START, CMD_STOP, CMD_STATUS + CMD_NONE, CMD_INIT, CMD_START, CMD_STOP, CMD_STATUS, CMD_CHECK }; int l_arg_index = 1; // find net @@ -33,6 +33,9 @@ int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_repl else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "status", NULL)) { cmd_num = CMD_STATUS; } + else if(dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "check", NULL)) { + cmd_num = CMD_CHECK; + } if(cmd_num == CMD_NONE) { if(!a_argv[1]) dap_chain_node_cli_set_reply_text(a_str_reply, "invalid parameters"); @@ -43,6 +46,39 @@ int com_vpn_client(int a_argc, char ** a_argv, void *arg_func, char **a_str_repl switch (cmd_num) { + case CMD_CHECK: { + const char * l_str_addr = NULL; // for example, "192.168.100.93" + const char * l_str_port = NULL; // for example, "8079" + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_str_addr); + if(!l_str_addr) { + dap_chain_node_cli_set_reply_text(a_str_reply, + "VPN server address not defined, use -addr <vpn server ipv4 address> parameter"); + break; + } + dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-port", &l_str_port); + int l_srv_port = (l_str_port) ? (int) strtoll(l_str_port, 0, 10) : 0; + if(!l_srv_port) { + dap_chain_node_cli_set_reply_text(a_str_reply, + "VPN server port not defined, use -port <vpn server port> parameter"); + break; + } + int l_rate_out = 0; + int l_res = dap_chain_net_vpn_client_check(l_net, l_str_addr, NULL, l_srv_port, l_rate_out); + switch (l_res) { + case 0: + dap_chain_node_cli_set_reply_text(a_str_reply, "tested VPN server successfully"); + break; + case -2: + case -3: + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't connect to VPN server"); + break; + default: + dap_chain_node_cli_set_reply_text(a_str_reply, "Can't recognize error code=%d", l_res); + break; + } + return l_res; + } + break; case CMD_INIT: { const char * l_str_token = NULL; // token name const char * l_str_value_datoshi = NULL; diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index 9109e9320c..28ba0a0d2a 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -303,6 +303,89 @@ int dap_chain_net_vpn_client_get_wallet_info(dap_chain_net_t *a_net, char **a_wa return 0; } +/** + * Check VPN server + * + * return: 0 Ok, <0 Error + */ +int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_str, const char *a_ipv6_str, int a_port, int a_rate_out) +{ + int l_ret = 0; + if(!a_ipv4_str) // && !a_ipv6_str) + return -1; + if(!s_node_info) + s_node_info = DAP_NEW_Z(dap_chain_node_info_t); + s_node_info->hdr.ext_port = a_port; + + dap_client_stage_t l_stage_target = STAGE_STREAM_STREAMING; //DAP_CLIENT_STAGE_STREAM_CTL;//STAGE_STREAM_STREAMING; + const char l_active_channels[] = { dap_stream_ch_chain_net_srv_get_id(), 0 }; //only R, without S + if(a_ipv4_str) + inet_pton(AF_INET, a_ipv4_str, &(s_node_info->hdr.ext_addr_v4)); + if(a_ipv6_str) + inet_pton(AF_INET6, a_ipv6_str, &(s_node_info->hdr.ext_addr_v6)); + + s_vpn_client = dap_chain_client_connect(s_node_info, l_stage_target, l_active_channels); + if(!s_vpn_client) { + log_it(L_ERROR, "Can't connect to VPN server=%s:%d", a_ipv4_str, a_port); + // clean client struct + dap_chain_node_client_close(s_vpn_client); + DAP_DELETE(s_node_info); + s_node_info = NULL; + return -2; + } + // wait connected + int timeout_ms = 5000; //5 sec = 5000 ms + int l_res = dap_chain_node_client_wait(s_vpn_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms); + if(l_res) { + log_it(L_ERROR, "No response from VPN server=%s:%d", a_ipv4_str, a_port); + // clean client struct + dap_chain_node_client_close(s_vpn_client); + DAP_DELETE(s_node_info); + s_node_info = NULL; + return -3; + } + + l_ret = dap_chain_net_vpn_client_tun_init(a_ipv4_str); + + // send first packet to server + { + uint8_t l_ch_id = dap_stream_ch_chain_net_srv_get_id(); // Channel id for chain net request = 'R' + dap_stream_ch_t *l_ch = dap_client_get_stream_ch(s_vpn_client->client, l_ch_id); + if(l_ch) { + dap_stream_ch_chain_net_srv_pkt_request_t l_request; + memset(&l_request, 0, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t)); + l_request.hdr.net_id.uint64 = a_net->pub.id.uint64; + l_request.hdr.srv_uid.uint64 = DAP_CHAIN_NET_SRV_VPN_ID; + dap_chain_hash_fast_t *l_tx_cond = dap_chain_net_vpn_client_tx_cond_hash(a_net, NULL, NULL, 0); + if(l_tx_cond) { + memcpy(&l_request.hdr.tx_cond, l_tx_cond, sizeof(dap_chain_hash_fast_t)); + DAP_DELETE(l_tx_cond); + } + // set srv id + dap_stream_ch_chain_net_srv_set_srv_uid(l_ch, l_request.hdr.srv_uid); + //dap_chain_hash_fast_t l_request + //.hdr.tx_cond = a_txCond.value(); +// strncpy(l_request->hdr.token, a_token.toLatin1().constData(),sizeof (l_request->hdr.token)-1); + dap_stream_ch_pkt_write(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST, &l_request, sizeof(l_request)); + dap_stream_ch_set_ready_to_write(l_ch, true); + } + } + // wait testing + int timeout__ms = 10000000; //10 sec = 10000 ms + l_res = dap_chain_node_client_wait(s_vpn_client, NODE_CLIENT_STATE_CONNECTED, timeout_ms); + if(l_res) { + log_it(L_ERROR, "No response from VPN server=%s:%d", a_ipv4_str, a_port); + // clean client struct + dap_chain_node_client_close(s_vpn_client); + DAP_DELETE(s_node_info); + s_node_info = NULL; + return -3; + } + + return l_ret; +} + + /** * Start VPN client * diff --git a/modules/service/vpn/include/dap_chain_net_vpn_client.h b/modules/service/vpn/include/dap_chain_net_vpn_client.h index 4f613e02c8..c53e26422d 100644 --- a/modules/service/vpn/include/dap_chain_net_vpn_client.h +++ b/modules/service/vpn/include/dap_chain_net_vpn_client.h @@ -42,6 +42,8 @@ dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void); int dap_chain_net_vpn_client_update(dap_chain_net_t *a_net, const char *a_wallet_name, const char *a_str_token, uint64_t a_value_datoshi); int dap_chain_net_vpn_client_get_wallet_info(dap_chain_net_t *a_net, char **a_wallet_name, char **a_str_token, uint64_t *a_value_datoshi); +int dap_chain_net_vpn_client_check(dap_chain_net_t *a_net, const char *a_ipv4_str, const char *a_ipv6_str, int a_port, int a_rate_out); + int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_str, const char *a_ipv6_str, int a_port); int dap_chain_net_vpn_client_stop(void); dap_chain_net_vpn_client_status_t dap_chain_net_vpn_client_status(void); -- GitLab