Newer
Older
/*
* Authors:
* Dmitriy A. Gearasimov <naeper@demlabs.net>
* DeM Labs Inc. https://demlabs.net
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "iputils/iputils.h"
//#include "dap_common.h"
#include "dap_chain_common.h"
#include "dap_strfuncs.h"
#include "dap_list.h"
#include "dap_string.h"
#include "dap_chain_node.h"
#include "dap_chain_global_db.h"
#include "dap_chain_node_cli_cmd.h"
#include "dap_chain_datum_tx_ctrl.h"
#include "dap_chain_datum_tx_items.h"
#include "dap_chain_datum_tx_cache.h"
#include "dap_chain_global_db.h"
#include "dap_stream_ch_chain_net.h"
/**
* find option value
*
* return index of string in argv, or 0 if not found
*/
static int find_option_val(const char** argv, int arg_start, int arg_end, const char *opt_name, const char **opt_value)
{
int arg_index = arg_start;
int arg_character, on_or_off, next_arg, i;
char *arg_string;
while(arg_index < arg_end)
{
arg_string = (char *) argv[arg_index];
// find opt_name
if(arg_string && opt_name && !strcmp(arg_string, opt_name)) {
// find opt_value
if(opt_value) {
arg_string = (char *) argv[++arg_index];
if(arg_string) {
*opt_value = arg_string;
return arg_index;
}
}
else
// need only opt_name
return arg_index;
}
arg_index++;
}
return 0;
}
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* Convert string to digit
*/
static void digit_from_string(const char *num_str, uint8_t *raw, size_t raw_len)
{
if(!num_str)
return;
uint64_t val;
if(!strncasecmp(num_str, "0x", 2)) {
val = strtoull(num_str + 2, NULL, 16);
}
else {
val = strtoull(num_str, NULL, 10);
}
// for LITTLE_ENDIAN (Intel), do nothing, otherwise swap bytes
val = le64toh(val);
memset(raw, 0, raw_len);
memcpy(raw, &val, min(raw_len, sizeof(uint64_t)));
}
/**
* Add alias in base
*/
static bool add_alias(const char *alias, dap_chain_node_addr_t *addr)
{
const char *a_key = alias;
char a_value[2 * sizeof(dap_chain_node_addr_t) + 1];
if(bin2hex(a_value, (const unsigned char *) addr, sizeof(dap_chain_node_addr_t)) == -1)
return false;
a_value[2 * sizeof(dap_chain_node_addr_t)] = '\0';
bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_ALIAS);
return res;
}
/**
* Delete alias from base
*/
{
const char *a_key = alias;
bool res = dap_chain_global_db_gr_del(a_key, GROUP_ALIAS);
return res;
}
/**
* Find in base addr by alias
*
* return addr, NULL if not found
*/
dap_chain_node_addr_t* get_name_by_alias(const char *alias)
{
dap_chain_node_addr_t *addr = NULL;
if(!alias)
return NULL;
const char *a_key = alias;
char *addr_str = dap_chain_global_db_gr_get(a_key, GROUP_ALIAS);
if(addr_str && strlen(addr_str) == sizeof(dap_chain_node_addr_t) * 2) {
addr = DAP_NEW_Z(dap_chain_node_addr_t);
if(hex2bin((char*) addr, (const unsigned char *) addr_str, sizeof(dap_chain_node_addr_t) * 2) == -1) {
DAP_DELETE(addr);
addr = NULL;
}
}
DAP_DELETE(addr_str);
return addr;
}
* return list of addr, NULL if not found
static dap_list_t* get_aliases_by_name(dap_chain_node_addr_t *addr)
dap_list_t *list_aliases = NULL;
size_t data_size = 0;
// read all aliases
dap_global_db_obj_t **objs = dap_chain_global_db_gr_load(GROUP_ALIAS, &data_size);
return NULL;
for(int i = 0; i < data_size; i++) {
dap_chain_node_addr_t addr_i;
dap_global_db_obj_t *obj = objs[i];
if(!obj)
break;
char *addr_str = obj->value;
if(addr_str && strlen(addr_str) == sizeof(dap_chain_node_addr_t) * 2) {
//addr_i = DAP_NEW_Z(dap_chain_node_addr_t);
if(hex2bin((char*) &addr_i, (const unsigned char *) addr_str, sizeof(dap_chain_node_addr_t) * 2) == -1) {
continue;
}
if(addr->uint64 == addr_i.uint64) {
list_aliases = dap_list_prepend(list_aliases, strdup(obj->key));
dap_chain_global_db_objs_delete(objs);
return list_aliases;
}
static dap_chain_node_addr_t* com_global_db_get_addr(dap_chain_node_info_t *node_info,
dap_chain_node_addr_t *addr, const char *alias_str)
{
dap_chain_node_addr_t *address = NULL;
address = get_name_by_alias(alias_str);
}
}
return address;
}
static char* com_global_db_get_key_for_addr(dap_chain_node_addr_t *address)
{
char *a_key = dap_chain_global_db_hash((const uint8_t*) address, sizeof(dap_chain_node_addr_t));
return a_key;
}
/**
* Write text to reply string
*/
static void set_reply_text(char **str_reply, const char *str, ...)
{
if(str_reply) {
if(*str_reply) {
assert(!*str_reply);
va_list args;
va_start(args, str);
*str_reply = dap_strdup_vprintf(str, args); //*str_reply = dap_strdup(str);
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/**
* Read node from base
*/
static dap_chain_node_info_t* dap_chain_node_info_read(dap_chain_node_addr_t *address, char **str_reply)
{
char *a_key = com_global_db_get_key_for_addr(address);
if(!a_key)
{
set_reply_text(str_reply, "can't calculate hash of addr");
return NULL;
}
// read node
char *str = dap_chain_global_db_gr_get(a_key, GROUP_NODE);
if(!str) {
set_reply_text(str_reply, "node not found in base");
DAP_DELETE(a_key);
return NULL;
}
dap_chain_node_info_t *node_info = dap_chain_node_info_deserialize(str, (str) ? strlen(str) : 0);
if(!node_info) {
set_reply_text(str_reply, "node has invalid format in base");
}
DAP_DELETE(str);
DAP_DELETE(a_key);
return node_info;
}
/**
* Save node from base
*/
static bool dap_chain_node_info_save(dap_chain_node_info_t *node_info, char **str_reply)
{
if(!node_info || !node_info->hdr.address.uint64) {
set_reply_text(str_reply, "node addr not found");
return false;
}
char *a_key = com_global_db_get_key_for_addr(&node_info->hdr.address);
if(!a_key)
{
set_reply_text(str_reply, "can't calculate hash for addr");
return NULL;
}
char *a_value = dap_chain_node_info_serialize(node_info, NULL);
bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_NODE);
DAP_DELETE(a_key);
DAP_DELETE(a_value);
return res;
}
/**
* Handler of command 'global_db node add'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_add(dap_chain_node_info_t *node_info, const char *alias_str,
const char *shard_str, const char *ipv4_str, const char *ipv6_str, char **str_reply)
{
if(!node_info->hdr.address.uint64) {
set_reply_text(str_reply, "not found -addr parameter");
set_reply_text(str_reply, "not found -shard parameter");
return -1;
}
if(!ipv4_str && !ipv6_str) {
set_reply_text(str_reply, "not found -ipv4 or -ipv6 parameter");
return -1;
}
else {
if(ipv4_str)
inet_pton(AF_INET, ipv4_str, &(node_info->hdr.ext_addr_v4));
if(ipv6_str)
inet_pton(AF_INET6, ipv6_str, &(node_info->hdr.ext_addr_v6));
}
// check match addr to shard or no
/*dap_chain_node_addr_t *addr = dap_chain_node_gen_addr(&node_info->hdr.shard_id);
if(!dap_chain_node_check_addr(&node_info->hdr.address, &node_info->hdr.shard_id)) {
set_reply_text(str_reply, "shard does not match addr");
if(alias_str) {
// add alias
if(!add_alias(alias_str, &node_info->hdr.address)) {
log_it(L_WARNING, "can't save alias %s", alias_str);
set_reply_text(str_reply, "alias '%s' can't be mapped to addr=0x%lld",
alias_str, node_info->hdr.address.uint64);
return -1;
}
}
bool res = dap_chain_node_info_save(node_info, str_reply);
if(res)
set_reply_text(str_reply, "node added");
else
if(res)
return 0;
return -1;
}
/**
* Handler of command 'global_db node add'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_del(dap_chain_node_info_t *node_info, const char *alias_str, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
return -1;
// find addr by alias or addr_str
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
if(!address) {
set_reply_text(str_reply, "alias not found");
return -1;
char *a_key = com_global_db_get_key_for_addr(address);
if(a_key)
{
// delete node
bool res = dap_chain_global_db_gr_del(a_key, GROUP_NODE);
if(res) {
// delete all aliases for node address
{
dap_list_t *list_aliases = get_aliases_by_name(address);
dap_list_t *list = list_aliases;
while(list)
{
const char *alias = (const char *) list->data;
dap_list_free_full(list_aliases, (DapDestroyNotify) free);
// set text response
set_reply_text(str_reply, "node deleted");
else
set_reply_text(str_reply, "node not deleted");
set_reply_text(str_reply, "addr to delete can't be defined");
DAP_DELETE(address);
return -1;
}
/**
* Handler of command 'global_db node link'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, const char *alias_str,
dap_chain_node_addr_t *link, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
return -1;
}
if(!link->uint64) {
set_reply_text(str_reply, "link not found");
return -1;
}
// TODO check the presence of link in the node base
if(0) {
set_reply_text(str_reply, "node 0x%llx not found in base", link->uint64);
return -1;
// find addr by alias or addr_str
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
if(!address) {
set_reply_text(str_reply, "alias not found");
return -1;
}
dap_chain_node_info_t *node_info_read = dap_chain_node_info_read(address, str_reply);
if(!node_info_read)
return -1;
int cmd_int = 0;
if(!strcmp(cmd, "add"))
cmd_int = 1;
else if(!strcmp(cmd, "del"))
cmd_int = 2;
// find link in node_info_read
int index_link = -1;
for(int i = 0; i < node_info_read->hdr.links_number; i++) {
if(node_info_read->links[i].uint64 == link->uint64) {
// link already present
index_link = i;
break;
bool res_successful = false; // is successful whether add/del
// add link
if(cmd_int == 1) {
if(index_link == -1) {
memcpy(&(node_info_read->links[node_info_read->hdr.links_number]), link, sizeof(dap_chain_node_addr_t));
node_info_read->hdr.links_number++;
res_successful = true;
}
}
// delete link
else if(cmd_int == 2) {
// move link list to one item prev
if(index_link >= 0) {
for(int j = index_link; j < node_info_read->hdr.links_number - 1; j++) {
memcpy(&(node_info_read->links[j]), &(node_info_read->links[j + 1]), sizeof(dap_chain_node_addr_t));
}
node_info_read->hdr.links_number--;
res_successful = true;
}
}
// save edited node_info
if(res_successful) {
bool res = dap_chain_node_info_save(node_info_read, str_reply);
if(res) {
res_successful = true;
if(cmd_int == 1)
set_reply_text(str_reply, "link added");
if(cmd_int == 2)
set_reply_text(str_reply, "link deleted");
else {
res_successful = false;
}
else {
if(cmd_int == 1) {
if(index_link >= 0)
set_reply_text(str_reply, "link not added because it is already present");
else
set_reply_text(str_reply, "link not added");
}
if(cmd_int == 2) {
if(index_link == -1)
set_reply_text(str_reply, "link not deleted because not found");
else
set_reply_text(str_reply, "link not deleted");
}
}
DAP_DELETE(node_info_read);
if(res_successful)
return 0;
return -1;
}
/**
* Handler of command 'global_db node dump'
*
* str_reply[out] for reply
* return 0 Ok, -1 error
*/
static int com_global_db_dump(dap_chain_node_info_t *node_info, const char *alias_str, char **str_reply)
if(!node_info->hdr.address.uint64 && !alias_str) {
set_reply_text(str_reply, "addr not found");
dap_chain_node_addr_t *address = com_global_db_get_addr(node_info, &node_info->hdr.address, alias_str);
set_reply_text(str_reply, "alias not found");
// read node
dap_chain_node_info_t *node_info_read = dap_chain_node_info_read(address, str_reply);
if(!node_info_read) {
return -1;
}
int hostlen = 128;
char host4[hostlen];
char host6[hostlen];
struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = node_info_read->hdr.ext_addr_v4 };
const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, hostlen);
struct sockaddr_in6 sa6 = { .sin6_family = AF_INET6, .sin6_addr = node_info_read->hdr.ext_addr_v6 };
const char* str_ip6 = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa6)->sin6_addr), host6, hostlen);
// get aliases in form of string
dap_string_t *aliases_string = dap_string_new(NULL);
dap_list_t *list_aliases = get_aliases_by_name(address);
dap_list_t *list = list_aliases;
const char *alias = (const char *) list->data;
dap_string_append_printf(aliases_string, "\nalias %s", alias);
list = dap_list_next(list);
dap_list_free_full(list_aliases, (DapDestroyNotify) free);
dap_string_append(aliases_string, "\nno aliases");
dap_string_t *links_string = dap_string_new(NULL);
for(int i = 0; i < node_info_read->hdr.links_number; i++) {
dap_chain_node_addr_t link_addr = node_info_read->links[i];
dap_string_append_printf(links_string, "\nlink%02d address : 0x%llx", i, link_addr.uint64);
}
// set full reply with node param
set_reply_text(str_reply, "node address 0x%llx\nshard 0x%llx%s\nipv4 %s\nipv6 %s\nnumber of links %d%s",
node_info_read->hdr.address, node_info_read->hdr.shard_id, aliases_string->str,
str_ip4, str_ip6,
node_info_read->hdr.links_number, links_string->str);
dap_string_free(aliases_string, true);
dap_string_free(links_string, true);
/**
* global_db command
*
* return 0 OK, -1 Err
*/
int com_global_db(int argc, const char ** argv, char **str_reply)
{
enum {
CMD_NONE, CMD_ADD, CMD_DEL, CMD_LINK, CMD_DUMP
};
printf("com_global_db\n");
int arg_index = 1;
arg_index = find_option_val(argv, arg_index, min(argc, arg_index + 1), "node", NULL);
set_reply_text(str_reply, "parameters are not valid");
// find command (add, delete, etc) as second parameter only
if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "add", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "del", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "link", NULL)) != 0) {
else if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "dump", NULL)) != 0) {
cmd_num = CMD_DUMP;
}
if(cmd_num == CMD_NONE) {
set_reply_text(str_reply, "command %s not recognized", argv[1]);
//arg_index = arg_index_n; // no need, they are already equal must be
assert(arg_index == arg_index_n);
arg_index++;
const char *addr_str = NULL, *alias_str = NULL, *shard_str = NULL, *link_str = NULL;
const char *ipv4_str = NULL, *ipv6_str = NULL;
find_option_val(argv, arg_index, argc, "-addr", &addr_str);
find_option_val(argv, arg_index, argc, "-alias", &alias_str);
find_option_val(argv, arg_index, argc, "-shard", &shard_str);
find_option_val(argv, arg_index, argc, "-ipv4", &ipv4_str);
find_option_val(argv, arg_index, argc, "-ipv6", &ipv6_str);
find_option_val(argv, arg_index, argc, "-link", &link_str);
memset(&node_info, 0, sizeof(dap_chain_node_info_t));
memset(&link, 0, sizeof(dap_chain_node_addr_t));
if(addr_str) {
digit_from_string(addr_str, node_info.hdr.address.raw, sizeof(node_info.hdr.address.raw));
}
if(shard_str) {
digit_from_string(shard_str, node_info.hdr.shard_id.raw, sizeof(node_info.hdr.shard_id.raw)); //DAP_CHAIN_SHARD_ID_SIZE);
}
if(link_str) {
digit_from_string(link_str, link.raw, sizeof(link.raw));
}
case CMD_ADD:
if(!arg_index || argc < 8) {
set_reply_text(str_reply, "invalid parameters");
// handler of command 'global_db node add'
return com_global_db_add(&node_info, alias_str, shard_str, ipv4_str, ipv6_str, str_reply);
return com_global_db_del(&node_info, alias_str, str_reply);
if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "add", NULL))
// handler of command 'global_db node link add -addr <node address> -link <node address>'
return com_global_db_link(&node_info, "add", alias_str, &link, str_reply);
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "del", NULL))
// handler of command 'global_db node link del -addr <node address> -link <node address>'
return com_global_db_link(&node_info, "del", alias_str, &link, str_reply);
else {
set_reply_text(str_reply, "command not recognize, supported format:\n"
"global_db node link <add|del] [-addr <node address> | -alias <node alias>] -link <node address>");
break;
case CMD_DUMP:
// handler of command 'global_db node dump'
return com_global_db_dump(&node_info, alias_str, str_reply);
set_reply_text(str_reply, "command %s not recognized", argv[1]);
}
return -1;
}
/**
* Node command
*/
int com_node(int argc, const char ** argv, char **str_reply)
{
CMD_NONE, CMD_ALIAS, CMD_HANDSHAKE, CMD_CONNECT
};
int arg_index = 1;
int cmd_num = CMD_NONE;
const char *cmd_str = NULL;
// find add parameter ('alias' or 'handshake')
if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "handshake", NULL)) {
cmd_num = CMD_HANDSHAKE;
}
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "connect", NULL)) {
cmd_num = CMD_CONNECT;
}
else if(find_option_val(argv, arg_index, min(argc, arg_index + 1), "alias", NULL)) {
cmd_num = CMD_ALIAS;
}
arg_index++;
if(cmd_num == CMD_NONE) {
set_reply_text(str_reply, "command %s not recognized", argv[1]);
return -1;
}
dap_chain_node_addr_t address;
memset(&address, 0, sizeof(dap_chain_node_addr_t));
const char *addr_str = NULL, *alias_str = NULL;
find_option_val(argv, arg_index, argc, "-addr", &addr_str);
find_option_val(argv, arg_index, argc, "-alias", &alias_str);
digit_from_string(addr_str, address.raw, sizeof(address.raw));
switch (cmd_num)
{
// add alias
case CMD_ALIAS:
if(alias_str) {
if(addr_str) {
// add alias
if(!add_alias(alias_str, &address))
log_it(L_WARNING, "can't save alias %s", alias_str);
else {
set_reply_text(str_reply, "alias mapped successfully");
set_reply_text(str_reply, "alias can't be mapped because -addr is not found");
set_reply_text(str_reply, "alias can't be mapped because -alias is not found");
// make connect
case CMD_CONNECT: {
// get address from alias if addr not defined
if(alias_str && !address.uint64) {
dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
if(address_tmp) {
memcpy(&address, address_tmp, sizeof(address_tmp));
DAP_DELETE(address_tmp);
}
else {
set_reply_text(str_reply, "no address found by alias");
return -1;
}
}
if(!address.uint64) {
set_reply_text(str_reply, "addr not found");
return -1;
}
// debug
if(0)
{
#include "dap_chain_global_db.h"
size_t l_data_size_out = 0;
dap_global_db_obj_t a_objs[2];
a_objs[0].key = "k1";
a_objs[1].key = "k2";
a_objs[0].value = "v1";
a_objs[1].value = "v2";
dap_chain_global_db_save(a_objs, 2); //dap_chain_global_db_save
char *l_diff = dap_db_log_get_diff(NULL);
DAP_DELETE(l_diff);
dap_global_db_obj_t **db1 = dap_chain_global_db_gr_load(GROUP_DATUM, &l_data_size_out);
printf("GROUP_DATUM size = %d\n", l_data_size_out);
dap_global_db_obj_t **db2 = dap_chain_global_db_gr_load(GROUP_ALIAS, &l_data_size_out);
printf("GROUP_ALIAS size = %d\n", l_data_size_out);
dap_global_db_obj_t **db3 = dap_chain_global_db_gr_load(GROUP_NODE, &l_data_size_out);
printf("GROUP_NODE size = %d\n", l_data_size_out);
set_reply_text(str_reply, "debug ok");
return 0;
}
dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
if(!node_info) {
set_reply_text(str_reply, "node by addr not found");
return -1;
}
// start connect
dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
if(!client) {
set_reply_text(str_reply, "can't connect");
DAP_DELETE(node_info);
return -1;
}
// wait connected
int timeout_ms = 150000; //15 sec = 15000 ms
int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
if(res != 1) {
set_reply_text(str_reply, "no response from node");
// clean client struct
dap_chain_node_client_close(client);
DAP_DELETE(node_info);
return -1;
}
// send request
size_t l_data_size_out = 0;
// Get last timestamp in log
char *l_str = dap_db_log_get_last_timestamp();
// Get log diff
//char *l_str = dap_db_log_get_diff(&l_data_size_out);
//dap_global_db_obj_t **l_hist_objs = dap_chain_global_db_load(l_data_size_out);
//size_t *a_data_size_out(l_hist_objs);
uint8_t l_ch_id = dap_stream_ch_chain_net_get_id(); // Channel id for global_db sync
res = dap_chain_node_client_send_chain_net_request(client, l_ch_id,
STREAM_CH_CHAIN_NET_PKT_TYPE_GLOBAL_DB_REQUEST_SYNC, l_str, (l_str) ? strlen(l_str) : 0); //, NULL);
if(res != 1) {
set_reply_text(str_reply, "no response from node(send request)");
// clean client struct
dap_chain_node_client_close(client);
DAP_DELETE(node_info);
return -1;
}
// wait for finishing of request
timeout_ms = 120000; // 2 min = 120 sec = 120 000 ms
// TODO add progress info to console
res = chain_node_client_wait(client, NODE_CLIENT_STATE_END, timeout_ms);
DAP_DELETE(node_info);
dap_client_disconnect(client->client);
dap_chain_node_client_close(client);
set_reply_text(str_reply, "getting pong");
}
break;
// get address from alias if addr not defined
if(alias_str && !address.uint64) {
dap_chain_node_addr_t *address_tmp = get_name_by_alias(alias_str);
if(address_tmp) {
memcpy(&address, address_tmp, sizeof(address_tmp));
DAP_DELETE(address_tmp);
}
else {
set_reply_text(str_reply, "no address found by alias");
return -1;
}
}
if(!address.uint64) {
set_reply_text(str_reply, "addr not found");
return -1;
}
dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply);
if(!node_info) {
set_reply_text(str_reply, "node by addr not found");
int timeout_ms = 10000; //10 sec = 10000 ms
dap_chain_node_client_t *client = dap_chain_node_client_connect(node_info);
if(!client) {
set_reply_text(str_reply, "can't connect");
DAP_DELETE(node_info);
return -1;
}
// wait handshake
int res = chain_node_client_wait(client, NODE_CLIENT_STATE_CONNECTED, timeout_ms);
if(res != 1) {
set_reply_text(str_reply, "no response from node");
// clean client struct
DAP_DELETE(node_info);
return -1;
}
DAP_DELETE(node_info);
//Add new established connection in the list
int ret = chain_node_client_list_add(&address, client);
switch (ret)
{
case -1:
dap_chain_node_client_close(client);
set_reply_text(str_reply, "connection established, but not saved");
return -1;
case -2:
dap_chain_node_client_close(client);
set_reply_text(str_reply, "connection already present");
return -1;
}
set_reply_text(str_reply, "connection established");
return 0;
}
/**
* Traceroute command
*
* return 0 OK, -1 Err
*/
int com_traceroute(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? traceroute_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
set_reply_text(str_reply, "traceroute %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
set_reply_text(str_reply, "traceroute %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case 2:
set_reply_text(str_reply, "traceroute %s error: %s", addr, "Unknown traceroute module");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "first hop out of range");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "max hops cannot be more than 255");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "no more than 10 probes per hop");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad wait specifications");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "too big packetlen ");
set_reply_text(str_reply, "traceroute %s error: %s", addr,
"IP version mismatch in addresses specified");
break;
case 9:
set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad sendtime");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "init_ip_options");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "calloc");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "parse cmdline");
set_reply_text(str_reply, "traceroute %s error: %s", addr, "trace method's init failed");
set_reply_text(str_reply, "traceroute %s error(%d) %s", addr, res, "trace not found");
}
}
}
return res;
}
/**
* Tracepath command
*
* return 0 OK, -1 Err
*/
int com_tracepath(int argc, const char** argv, char **str_reply)
{
const char *addr = NULL;
int hops = 0, time_usec = 0;
if(argc > 1)
addr = argv[1];
iputils_set_verbose();
int res = (addr) ? tracepath_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL;
if(res >= 0) {
if(str_reply)
set_reply_text(str_reply, "tracepath %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000);
}
else {
if(str_reply) {
switch (-res)
{
case EADDRNOTAVAIL:
set_reply_text(str_reply, "tracepath %s error: %s", (addr) ? addr : "",
(addr) ? "Name or service not known" : "Host not defined");
break;
case ESOCKTNOSUPPORT:
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't create socket");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_MTU_DISCOVER");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_MTU_DISCOVER");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL");
set_reply_text(str_reply, "tracepath %s error: %s", addr, "malloc");