diff --git a/CMakeLists.txt b/CMakeLists.txt index 39bbfb4f62aee622d46e5f617bbd433c931c6b95..ea07339f7e29b13c647a12566f106a2e66988dae 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,8 @@ set(DAP_CHAIN_NET_SRCS dap_chain_node_ctl.c dap_chain_node_cli.c dap_chain_node_cli_cmd.c + dap_chain_node_cli_connect.c + dap_chain_node_remote.c ) set(DAP_CHAIN_NET_HEADERS @@ -15,6 +17,8 @@ set(DAP_CHAIN_NET_HEADERS dap_chain_node_ctl.h dap_chain_node_cli.h dap_chain_node_cli_cmd.h + dap_chain_node_cli_connect.h + dap_chain_node_remote.h ) set(IPUTILS_INCLUDE_DIRS @@ -29,7 +33,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED glib-2.0) -target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_global_db -lresolv ${GLIB_LDFLAGS}) +target_link_libraries(dap_chain_net dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_mempool dap_chain_global_db -lresolv ${GLIB_LDFLAGS}) target_include_directories(dap_chain_net INTERFACE . PUBLIC ${GLIB_INCLUDE_DIRS} ${IPUTILS_INCLUDE_DIRS}) set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) diff --git a/dap_chain_node.c b/dap_chain_node.c index efea2e6730ca133fdb66d0c82851136f9e0f6e9d..d2c09b125a4dd44c23483a308682b2ce2e304473 100644 --- a/dap_chain_node.c +++ b/dap_chain_node.c @@ -155,12 +155,12 @@ uint8_t* dap_chain_node_info_serialize(dap_chain_node_info_t *node_info, size_t */ dap_chain_node_info_t* dap_chain_node_info_deserialize(uint8_t *node_info_str, size_t size) { - if(!node_info_str) + if(!node_info_str || size<=0) return NULL; dap_chain_node_info_t *node_info = DAP_NEW_Z_SIZE(dap_chain_node_info_t, (size / 2 + 1)); if(hex2bin((char*) node_info, (const unsigned char *) node_info_str, size) == -1 || (size / 2) != dap_chain_node_info_get_size(node_info)) { - log_it(L_ERROR, "node_info_deserialize - bad node_info size (%ld!=%ld)", + log_it(L_ERROR, "node_info_deserialize - incorrect node_info size (%ld!=%ld)", size / 2, dap_chain_node_info_get_size(node_info)); DAP_DELETE(node_info); return NULL; diff --git a/dap_chain_node_cli.c b/dap_chain_node_cli.c index 9744539cb86cb9b1f32d983a4d0f36f365e07da5..9e29499c40c368e13f14a0c8f6d27fb919e6451c 100644 --- a/dap_chain_node_cli.c +++ b/dap_chain_node_cli.c @@ -49,6 +49,7 @@ typedef int SOCKET; #include "iputils/iputils.h" #include "dap_common.h" #include "dap_chain_node_cli_cmd.h" +#include "dap_chain_node_cli_connect.h" #include "dap_chain_node_cli.h" //#include "dap_chain_node_cli.h" @@ -97,13 +98,13 @@ static int s_poll(int socket, int timeout) struct pollfd fds; int res; fds.fd = socket; -// POLLIN - received data -// POLLNVAL - closed the socket on our side -// POLLHUP - closed the socket on another side (does not work! Received POLLIN and the next reading returns 0 bytes) + // POLLIN - received data + // POLLNVAL - closed the socket on our side + // POLLHUP - closed the socket on another side (does not work! Received POLLIN and the next reading returns 0 bytes) fds.events = POLLIN; // | | POLLNVAL | POLLHUP | POLLERR | POLLPRI res = poll(&fds, 1, timeout); -// since POLLIN=(POLLRDNORM | POLLRDBAND), then maybe revents=POLLRDNORM + // since POLLIN=(POLLRDNORM | POLLRDBAND), then maybe revents=POLLRDNORM if(res == 1 && !(fds.revents & POLLIN)) //if(res==1 && fds.revents!=POLLIN) return -1; return res; @@ -117,25 +118,25 @@ static bool is_valid_socket(SOCKET sock) struct pollfd fds; fds.fd = sock; fds.events = POLLIN; -// return: -1 err, 0 timeout, 1 waited + // return: -1 err, 0 timeout, 1 waited int count_desc = poll(&fds, 1, 0); -// error + // error if(count_desc == -1) return false; -// event with an error code + // event with an error code if(count_desc > 0) { -// feature of disconnection under Windows -// under Windows, with socket closed fds.revents=POLLHUP, in Unix fds.events = POLLIN + // feature of disconnection under Windows + // under Windows, with socket closed fds.revents=POLLHUP, in Unix fds.events = POLLIN if(fds.revents & (POLLERR | POLLHUP | POLLNVAL)) return false; -// feature of disconnection under Unix (QNX) -// under Windows, with socket closed res = 0, in Unix res = -1 + // feature of disconnection under Unix (QNX) + // under Windows, with socket closed res = 0, in Unix res = -1 char buf[2]; int res = recv(sock, buf, 1, MSG_PEEK); // MSG_PEEK The data is treated as unread and the next recv() function shall still return this data. if(res < 0) return false; -// data in the buffer must be(count_desc>0), but read 0 bytes(res=0) + // data in the buffer must be(count_desc>0), but read 0 bytes(res=0) if(!res && (fds.revents & POLLIN)) return false; } @@ -162,7 +163,7 @@ int s_recv(SOCKET sock, unsigned char *buf, int bufsize, int timeout) if(res < 1) { return -1; } -// res = read(sock, (char*) buf, bufsize); + // res = read(sock, (char*) buf, bufsize); res = recv(sock, (char*) buf, bufsize, 0); //MSG_WAITALL if(res <= 0) { //EINTR=4 ENOENT=2 EINVAL=22 ECONNRESET=254 printf("[s_recv] recv()=%d errno=%d\n", res, errno); @@ -183,29 +184,29 @@ char* s_get_next_str(SOCKET nSocket, int *dwLen, const char *stop_str, bool del_ bool bSuccess = false; int nRecv = 0; // count of bytes received int stop_str_len = (stop_str) ? strlen(stop_str) : 0; -// if there is nothing to look for + // if there is nothing to look for if(!stop_str_len) return NULL; int lpszBuffer_len = 256; char *lpszBuffer = calloc(1, lpszBuffer_len); -// received string will not be larger than MAX_REPLY_LEN + // received string will not be larger than MAX_REPLY_LEN while(1) //nRecv < MAX_REPLY_LEN) { -// read one byte + // read one byte int ret = s_recv(nSocket, (unsigned char *) (lpszBuffer + nRecv), 1, timeout); -//int ret = recv(nSocket,lpszBuffer+nRecv,1, 0); + //int ret = recv(nSocket,lpszBuffer+nRecv,1, 0); if(ret <= 0) { break; } nRecv += ret; -//printf("**debug** socket=%d read %d bytes '%0s'",nSocket, ret, (lpszBuffer + nRecv)); + //printf("**debug** socket=%d read %d bytes '%0s'",nSocket, ret, (lpszBuffer + nRecv)); while((nRecv + 1) >= lpszBuffer_len) { lpszBuffer_len *= 2; lpszBuffer = (char*) realloc(lpszBuffer, lpszBuffer_len); } -// search for the required string + // search for the required string if(nRecv >= stop_str_len) { // found the required string if(!strncasecmp(lpszBuffer + nRecv - stop_str_len, stop_str, stop_str_len)) { @@ -214,9 +215,9 @@ char* s_get_next_str(SOCKET nSocket, int *dwLen, const char *stop_str, bool del_ } } }; -// end reading + // end reading if(bSuccess) { -// delete the searched string + // delete the searched string if(del_stop_str) { lpszBuffer[nRecv - stop_str_len] = '\0'; if(dwLen) @@ -230,7 +231,7 @@ char* s_get_next_str(SOCKET nSocket, int *dwLen, const char *stop_str, bool del_ lpszBuffer = realloc(lpszBuffer, *dwLen + 1); return lpszBuffer; } -// in case of an error or missing string + // in case of an error or missing string if(dwLen) *dwLen = 0; free(lpszBuffer); @@ -252,26 +253,23 @@ static void* thread_one_client_func(void *args) GList *cmd_param_list = NULL; while(1) { -// wait data from client + // wait data from client int is_data = s_poll(newsockfd, timeout); -//printf("is data=%d sockfd=%d \n", is_data, newsockfd); -// timeout + // timeout if(!is_data) continue; -// error (may be socket closed) + // error (may be socket closed) if(is_data < 0) break; int is_valid = is_valid_socket(newsockfd); if(!is_valid) { - //printf("isvalid=%d sockfd=%d \n", is_valid, newsockfd); break; } -// receiving http header + // receiving http header char *str_header = s_get_next_str(newsockfd, &str_len, "\r\n", true, timeout); -//printf("str_header='%s' sock=%d\n", str_header, newsockfd); -// bad format + // bad format if(!str_header) break; if(str_header && strlen(str_header) == 0) { @@ -279,7 +277,7 @@ static void* thread_one_client_func(void *args) if(marker == 1) continue; } -// filling parameters of command + // filling parameters of command if(marker == 1) { cmd_param_list = g_list_append(cmd_param_list, str_header); //printf("g_list_append argc=%d command=%s ", argc, str_header); @@ -332,7 +330,7 @@ static void* thread_one_client_func(void *args) break; } } -// close connection + // close connection int cs = closesocket(newsockfd); log_it(L_INFO, "close connection=%d sockfd=%d", cs, newsockfd); return NULL; @@ -346,23 +344,23 @@ static void* thread_main_func(void *args) SOCKET sockfd = (SOCKET) (intptr_t) args; SOCKET newsockfd; log_it(L_INFO, "Server start socket=%s", UNIX_SOCKET_FILE); -// wait of clients + // wait of clients while(1) { pthread_t threadId; struct sockaddr_in peer; socklen_t size = sizeof(peer); -// received a new connection request + // received a new connection request if((newsockfd = accept(sockfd, (struct sockaddr*) &peer, &size)) == (SOCKET) -1) { log_it(L_ERROR, "new connection break newsockfd=%d", newsockfd); break; } -// create child thread for a client connection + // create child thread for a client connection pthread_create(&threadId, NULL, thread_one_client_func, (void*) (intptr_t) newsockfd); -// in order to thread not remain in state "dead" after completion + // in order to thread not remain in state "dead" after completion pthread_detach(threadId); }; -// close connection + // close connection int cs = closesocket(sockfd); log_it(L_INFO, "Exit server thread=%d socket=%d", cs, sockfd); return NULL; @@ -377,8 +375,11 @@ static void* thread_main_func(void *args) int dap_chain_node_cli_init(dap_config_t * g_config) { struct sockaddr_un server = { AF_UNIX, UNIX_SOCKET_FILE }; -//server.sun_family = AF_UNIX; -//strcpy(server.sun_path, SOCKET_FILE); + //server.sun_family = AF_UNIX; + //strcpy(server.sun_path, SOCKET_FILE); + + // init client for handshake + chain_node_client_init(); SOCKET sockfd; @@ -387,7 +388,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config) server_sockfd = 0; } -// create socket + // create socket if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == INVALID_SOCKET) return -1; int gdsg = sizeof(struct sockaddr_un); @@ -395,9 +396,9 @@ int dap_chain_node_cli_init(dap_config_t * g_config) { unlink(UNIX_SOCKET_FILE); } -// connecting the address with a socket + // connecting the address with a socket if(bind(sockfd, (const struct sockaddr*) &server, sizeof(struct sockaddr_un)) == SOCKET_ERROR) { -// errno = EACCES 13 Permission denied + // errno = EACCES 13 Permission denied if(errno == EACCES) // EACCES=13 log_it(L_ERROR, "Server can't start(err=%d). Can't create file=%s [Permission denied]", errno, UNIX_SOCKET_FILE); @@ -406,16 +407,16 @@ int dap_chain_node_cli_init(dap_config_t * g_config) closesocket(sockfd); return -1; } -// turn on reception of connections + // turn on reception of connections if(listen(sockfd, 5) == SOCKET_ERROR) return -1; -// create thread for waiting of clients + // create thread for waiting of clients pthread_t threadId; if(pthread_create(&threadId, NULL, thread_main_func, (void*) (intptr_t) sockfd) != 0) { closesocket(sockfd); return -1; } -// in order to thread not remain in state "dead" after completion + // in order to thread not remain in state "dead" after completion pthread_detach(threadId); server_sockfd = sockfd; return 0; @@ -429,4 +430,7 @@ void dap_chain_node_cli_delete(void) { if(server_sockfd >= 0) closesocket(server_sockfd); + + // deinit client for handshake + chain_node_client_deinit(); } diff --git a/dap_chain_node_cli_cmd.c b/dap_chain_node_cli_cmd.c index 59eac88b6146f145b14dcd73ec08a57567dc8f67..f17c9383dc548ffe85f1d936adcf68c3b3051d9c 100644 --- a/dap_chain_node_cli_cmd.c +++ b/dap_chain_node_cli_cmd.c @@ -33,6 +33,8 @@ //#include "dap_common.h" #include "dap_chain_node.h" #include "dap_chain_global_db.h" +#include "dap_chain_node_cli_connect.h" +#include "dap_chain_node_remote.h" #include "dap_chain_node_cli_cmd.h" // Max and min macros @@ -201,6 +203,11 @@ static char* com_global_db_get_key_for_addr(dap_chain_node_addr_t *address) static void set_reply_text(char **str_reply, const char *str, ...) { if(str_reply) { + if(*str_reply) { + assert(!*str_reply); + g_free(*str_reply); + *str_reply = NULL; + } va_list args; va_start(args, str); *str_reply = g_strdup_vprintf(str, args); //*str_reply = g_strdup(str); @@ -208,6 +215,54 @@ static void set_reply_text(char **str_reply, const char *str, ...) } } +/** + * 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' * @@ -239,8 +294,7 @@ static int com_global_db_add(dap_chain_node_info_t *node_info, const char *alias // 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)) { - if(str_reply) - *str_reply = g_strdup("shard does not match addr"); + set_reply_text(str_reply, "shard does not match addr"); return -1; }*/ if(alias_str) { @@ -254,16 +308,11 @@ static int com_global_db_add(dap_chain_node_info_t *node_info, const char *alias } // write to base - char *a_key = dap_chain_global_db_hash((const uint8_t*) &(node_info->hdr.address), - sizeof(dap_chain_node_addr_t)); - 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); + bool res = dap_chain_node_info_save(node_info, str_reply); if(res) set_reply_text(str_reply, "node added"); else - set_reply_text(str_reply, "node not added"); - DAP_DELETE(a_key); - DAP_DELETE(a_value); + return -1; if(res) return 0; return -1; @@ -303,7 +352,7 @@ static int com_global_db_del(dap_chain_node_info_t *node_info, const char *alias del_alias(alias); list = g_list_next(list); } - g_list_free_full(list_aliases, free); + g_list_free_full(list_aliases, (GDestroyNotify) free); } // set text response set_reply_text(str_reply, "node deleted"); @@ -351,30 +400,9 @@ static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, set_reply_text(str_reply, "alias not found"); return -1; } - char *a_key = com_global_db_get_key_for_addr(address); - if(!a_key) - { - set_reply_text(str_reply, "addr to link can't be defined"); - DAP_DELETE(address); - return -1; - } - bool res_successful = false; - // read node - char *str = dap_chain_global_db_gr_get(a_key, GROUP_NODE); - if(!str) { - set_reply_text(str_reply, "node is not found in base"); - DAP_DELETE(address); - DAP_DELETE(a_key); - return -1; - } - dap_chain_node_info_t *node_info_read = dap_chain_node_info_deserialize(str, strlen(str)); - if(!node_info_read) { - set_reply_text(str_reply, "node have bad format in base"); - DAP_DELETE(str); - DAP_DELETE(a_key); - DAP_DELETE(address); + 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")) @@ -391,6 +419,7 @@ static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, break; } } + bool res_successful = false; // is successful whether add/del // add link if(cmd_int == 1) { if(index_link == -1) { @@ -412,9 +441,7 @@ static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, } // save edited node_info if(res_successful) { - - char *a_value = dap_chain_node_info_serialize(node_info_read, NULL); - bool res = dap_chain_global_db_gr_set(a_key, a_value, GROUP_NODE); + bool res = dap_chain_node_info_save(node_info_read, str_reply); if(res) { res_successful = true; if(cmd_int == 1) @@ -425,7 +452,6 @@ static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, else { res_successful = false; } - DAP_DELETE(a_value); } else { if(cmd_int == 1) { @@ -442,8 +468,6 @@ static int com_global_db_link(dap_chain_node_info_t *node_info, const char *cmd, } } - DAP_DELETE(str); - DAP_DELETE(a_key); DAP_DELETE(address); DAP_DELETE(node_info_read); if(res_successful) @@ -464,86 +488,63 @@ static int com_global_db_dump(dap_chain_node_info_t *node_info, const char *alia set_reply_text(str_reply, "addr not found"); return -1; } -// find addr by alias or addr_str + // 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; } - a_key = com_global_db_get_key_for_addr(address); - if(a_key) - { - dap_chain_node_info_t *node_info_read = NULL; - // read node - char *str = dap_chain_global_db_gr_get(a_key, GROUP_NODE); - if(str) { - node_info_read = dap_chain_node_info_deserialize(str, strlen(str)); - if(!node_info_read) { - set_reply_text(str_reply, "node have bad format in base"); - } - else { - ; - //get_host(struct in_addr addr, char *host, size_t hostlen) - int hostlen = 128; - char host4[hostlen]; - char host6[hostlen]; - //const struct sockaddr *sa - //sockaddr_in - struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = node_info_read->hdr.ext_addr_v4 }; - const char* res4 = 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* res6 = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa6)->sin6_addr), host6, hostlen); - //int res = getnameinfo(&sa4, sizeof sa4, host4, hostlen, 0, 0, 0); - - // get aliases in form of string - GString *aliases_string = g_string_new(NULL); - GList *list_aliases = get_aliases_by_name(address); - if(list_aliases) - { - GList *list = list_aliases; - while(list) - { - const char *alias = (const char *) list->data; - g_string_append_printf(aliases_string, "\nalias %s", alias); - list = g_list_next(list); - } - g_list_free_full(list_aliases, (GDestroyNotify) free); - } - else - g_string_append(aliases_string, "\nno aliases"); - - // get links in form of string - GString *links_string = g_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]; - g_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, - host4, host6, - node_info_read->hdr.links_number, links_string->str); - g_string_free(aliases_string, TRUE); - g_string_free(links_string, TRUE); - } - } - else - set_reply_text(str_reply, "node is not found in base"); - DAP_DELETE(str); - DAP_DELETE(a_key); + // read node + dap_chain_node_info_t *node_info_read = dap_chain_node_info_read(address, str_reply); + if(!node_info_read) { DAP_DELETE(address); - 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 + GString *aliases_string = g_string_new(NULL); + GList *list_aliases = get_aliases_by_name(address); + if(list_aliases) + { + GList *list = list_aliases; + while(list) { - DAP_DELETE(node_info_read); - return 0; + const char *alias = (const char *) list->data; + g_string_append_printf(aliases_string, "\nalias %s", alias); + list = g_list_next(list); } - return -1; + g_list_free_full(list_aliases, (GDestroyNotify) free); } - set_reply_text(str_reply, "addr to dump can't be defined"); + else + g_string_append(aliases_string, "\nno aliases"); + + // get links in form of string + GString *links_string = g_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]; + g_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); + g_string_free(aliases_string, TRUE); + g_string_free(links_string, TRUE); + DAP_DELETE(address); + DAP_DELETE(node_info_read); + return -1; } @@ -559,15 +560,14 @@ int com_global_db(int argc, const char ** argv, char **str_reply) }; printf("com_global_db\n"); int arg_index = 1; -// find 'node' as first parameter only + // find 'node' as first parameter only arg_index = find_option_val(argv, arg_index, min(argc, arg_index + 1), "node", NULL); if(!arg_index || argc < 4) { - if(str_reply) - *str_reply = g_strdup("parameters are not valid"); + set_reply_text(str_reply, "parameters are not valid"); return -1; } int arg_index_n = ++arg_index; -// find command (add, delete, etc) as second parameter only + // find command (add, delete, etc) as second parameter only int cmd_num = CMD_NONE; if((arg_index_n = find_option_val(argv, arg_index, min(argc, arg_index + 1), "add", NULL)) != 0) { cmd_num = CMD_ADD; @@ -582,16 +582,15 @@ int com_global_db(int argc, const char ** argv, char **str_reply) cmd_num = CMD_DUMP; } if(cmd_num == CMD_NONE) { - if(str_reply) - *str_reply = g_strdup_printf("command %s not recognized", argv[1]); + set_reply_text(str_reply, "command %s not recognized", argv[1]); return -1; } -//arg_index = arg_index_n; // no need, they are already equal must be + //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 addr, alias + // find addr, alias 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); @@ -599,7 +598,7 @@ int com_global_db(int argc, const char ** argv, char **str_reply) find_option_val(argv, arg_index, argc, "-ipv6", &ipv6_str); find_option_val(argv, arg_index, argc, "-link", &link_str); -// struct to write to the global db + // struct to write to the global db dap_chain_node_info_t node_info; dap_chain_node_addr_t link; memset(&node_info, 0, sizeof(dap_chain_node_info_t)); @@ -616,14 +615,13 @@ int com_global_db(int argc, const char ** argv, char **str_reply) switch (cmd_num) { -// add new node to global_db + // add new node to global_db case CMD_ADD: if(!arg_index || argc < 8) { - if(str_reply) - *str_reply = g_strdup("parameters are not valid"); + set_reply_text(str_reply, "invalid parameters"); return -1; } -// handler of command 'global_db node add' + // handler of command 'global_db node add' return com_global_db_add(&node_info, alias_str, shard_str, ipv4_str, ipv6_str, str_reply); break; @@ -649,15 +647,9 @@ int com_global_db(int argc, const char ** argv, char **str_reply) return com_global_db_dump(&node_info, alias_str, str_reply); break; default: - if(str_reply) - *str_reply = g_strdup_printf("command %s not recognized", argv[1]); + set_reply_text(str_reply, "command %s not recognized", argv[1]); return -1; } - -//inet_ntop(AF_INET, &(dap_addr.uint64), str, INET_ADDRSTRLEN); -//uint64 -// timestamp = time(NULL); - return -1; } @@ -681,11 +673,11 @@ int com_node(int argc, const char ** argv, char **str_reply) } arg_index++; if(cmd_num == CMD_NONE) { - if(str_reply) - *str_reply = g_strdup_printf("command %s not recognized", argv[1]); + 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 addr, alias find_option_val(argv, arg_index, argc, "-addr", &addr_str); @@ -703,19 +695,16 @@ int com_node(int argc, const char ** argv, char **str_reply) if(!add_alias(alias_str, &address)) log_it(L_WARNING, "can't save alias %s", alias_str); else { - if(str_reply) - *str_reply = g_strdup("alias mapped successfully"); + set_reply_text(str_reply, "alias mapped successfully"); } } else { - if(str_reply) - *str_reply = g_strdup("alias can't be mapped because -addr is not found"); + set_reply_text(str_reply, "alias can't be mapped because -addr is not found"); return -1; } } else { - if(str_reply) - *str_reply = g_strdup("alias can't be mapped because -alias is not found"); + set_reply_text(str_reply, "alias can't be mapped because -alias is not found"); return -1; } @@ -740,10 +729,33 @@ int com_node(int argc, const char ** argv, char **str_reply) return -1; } - // TODO start handshake + dap_chain_node_info_t *node_info = dap_chain_node_info_read(&address, str_reply); + if(!node_info) { + return -1; + } + int timeout_ms = 100000; //100 sec. + // start handshake + chain_node_client_t *client = 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 + chain_node_client_close(client); + DAP_DELETE(node_info); + return -1; + } + DAP_DELETE(node_info); - if(str_reply) - *str_reply = g_strdup("handshake in progress..."); + //Add new established connection in the list + chain_node_client_list_add(client); + + set_reply_text(str_reply, "connection established"); break; } return 0; @@ -763,56 +775,55 @@ int com_traceroute(int argc, const char** argv, char **str_reply) iputils_set_verbose(); int res = (addr) ? traceroute_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL; if(res >= 0) { - if(str_reply) - *str_reply = g_strdup_printf("traceroute %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000); + 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: - *str_reply = g_strdup_printf("traceroute %s error: %s", (addr) ? addr : "", + set_reply_text(str_reply, "traceroute %s error: %s", (addr) ? addr : "", (addr) ? "Name or service not known" : "Host not defined"); break; case 2: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "Unknown traceroute module"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "Unknown traceroute module"); break; case 3: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "first hop out of range"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "first hop out of range"); break; case 4: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "max hops cannot be more than 255"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "max hops cannot be more than 255"); break; case 5: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "no more than 10 probes per hop"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "no more than 10 probes per hop"); break; case 6: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "bad wait specifications"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad wait specifications"); break; case 7: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "too big packetlen "); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "too big packetlen "); break; case 8: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, + set_reply_text(str_reply, "traceroute %s error: %s", addr, "IP version mismatch in addresses specified"); break; case 9: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "bad sendtime"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "bad sendtime"); break; case 10: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "init_ip_options"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "init_ip_options"); break; case 11: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "calloc"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "calloc"); break; case 12: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "parse cmdline"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "parse cmdline"); break; case 13: - *str_reply = g_strdup_printf("traceroute %s error: %s", addr, "trace method's init failed"); + set_reply_text(str_reply, "traceroute %s error: %s", addr, "trace method's init failed"); break; default: - *str_reply = g_strdup_printf("traceroute %s error(%d) %s", addr, res, "trace not found"); + set_reply_text(str_reply, "traceroute %s error(%d) %s", addr, res, "trace not found"); } } } @@ -834,48 +845,48 @@ int com_tracepath(int argc, const char** argv, char **str_reply) int res = (addr) ? tracepath_util(addr, &hops, &time_usec) : -EADDRNOTAVAIL; if(res >= 0) { if(str_reply) - *str_reply = g_strdup_printf("tracepath %s hops=%d time=%.1lf ms", addr, hops, time_usec * 1. / 1000); + 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: - *str_reply = g_strdup_printf("tracepath %s error: %s", (addr) ? addr : "", + set_reply_text(str_reply, "tracepath %s error: %s", (addr) ? addr : "", (addr) ? "Name or service not known" : "Host not defined"); break; case ESOCKTNOSUPPORT: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't create socket"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't create socket"); break; case 2: - *str_reply = g_strdup_printf("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_MTU_DISCOVER"); break; case 3: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_RECVERR"); break; case 4: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_HOPLIMIT"); break; case 5: - *str_reply = g_strdup_printf("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_MTU_DISCOVER"); break; case 6: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVERR"); break; case 7: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_RECVTTL"); break; case 8: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "malloc"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "malloc"); break; case 9: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IPV6_UNICAST_HOPS"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IPV6_UNICAST_HOPS"); break; case 10: - *str_reply = g_strdup_printf("tracepath %s error: %s", addr, "Can't setsockopt IP_TTL"); + set_reply_text(str_reply, "tracepath %s error: %s", addr, "Can't setsockopt IP_TTL"); break; default: - *str_reply = g_strdup_printf("tracepath %s error(%d) %s", addr, res, "trace not found"); + set_reply_text(str_reply, "tracepath %s error(%d) %s", addr, res, "trace not found"); } } } @@ -904,24 +915,24 @@ int com_ping(int argc, const char** argv, char **str_reply) int res = (addr) ? ping_util(addr, n) : -EADDRNOTAVAIL; if(res >= 0) { if(str_reply) - *str_reply = g_strdup_printf("ping %s time=%.1lf ms", addr, res * 1. / 1000); + set_reply_text(str_reply, "ping %s time=%.1lf ms", addr, res * 1. / 1000); } else { if(str_reply) { switch (-res) { case EDESTADDRREQ: - *str_reply = g_strdup_printf("ping %s error: %s", addr, "Destination address required"); + set_reply_text(str_reply, "ping %s error: %s", addr, "Destination address required"); break; case EADDRNOTAVAIL: - *str_reply = g_strdup_printf("ping %s error: %s", (addr) ? addr : "", + set_reply_text(str_reply, "ping %s error: %s", (addr) ? addr : "", (addr) ? "Host not found" : "Host not defined"); break; case EPFNOSUPPORT: - *str_reply = g_strdup_printf("ping %s error: %s", addr, "Unknown protocol family"); + set_reply_text(str_reply, "ping %s error: %s", addr, "Unknown protocol family"); break; default: - *str_reply = g_strdup_printf("ping %s error(%d)", addr, -res); + set_reply_text(str_reply, "ping %s error(%d)", addr, -res); } } } @@ -942,10 +953,10 @@ int com_help(int argc, const char ** argv, char **str_reply) return 1; } if(str_reply) - *str_reply = g_strdup_printf("command \"%s\" not recognized", argv[1]); + set_reply_text(str_reply, "command \"%s\" not recognized", argv[1]); } if(str_reply) - *str_reply = g_strdup("command not defined, enter \"help <cmd name>\""); + set_reply_text(str_reply, "command not defined, enter \"help <cmd name>\""); return -1; } diff --git a/dap_chain_node_cli_connect.c b/dap_chain_node_cli_connect.c new file mode 100644 index 0000000000000000000000000000000000000000..b3bf58164381c40a2844b81b91a429db3180bc8b --- /dev/null +++ b/dap_chain_node_cli_connect.c @@ -0,0 +1,198 @@ +/* + * 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <glib.h> +#include <time.h> + +#include "dap_common.h" +#include "dap_client.h" +#include "dap_client_pvt.h" +#include "dap_config.h" +#include "dap_events.h" +#include "dap_http_client_simple.h" +#include "dap_chain_node_cli_connect.h" + +#define LOG_TAG "chain_node_cli_connect" + +#define DAP_APP_NAME NODE_NETNAME"-node" +#define SYSTEM_PREFIX "/opt/"DAP_APP_NAME +#define SYSTEM_CONFIGS_DIR SYSTEM_PREFIX"/etc" + +static int listen_port_tcp = 8079; + +int chain_node_client_init(void) +{ + int res = dap_client_init(); + res = dap_http_client_simple_init(); + dap_config_t *g_config; + // read listen_port_tcp from settings + dap_config_init(SYSTEM_CONFIGS_DIR); + if((g_config = dap_config_open(DAP_APP_NAME)) == NULL) { + return -1; + } + else { + const char *port_str = dap_config_get_item_str(g_config, "server", "listen_port_tcp"); + listen_port_tcp = (port_str) ? atoi(port_str) : 8079; + } + if(g_config) + dap_config_close(g_config); + return res; +} + +void chain_node_client_deinit() +{ + dap_http_client_simple_deinit(); + dap_client_deinit(); +} + +// callback for dap_client_new() in chain_node_client_connect() +static void stage_status_callback(dap_client_t *a_client, void *a_arg) +{ + //printf("* stage_status_callback client=%x data=%x\n", a_client, a_arg); +} +// callback for dap_client_new() in chain_node_client_connect() +static void stage_status_error_callback(dap_client_t *a_client, void *a_arg) +{ + //printf("* tage_status_error_callback client=%x data=%x\n", a_client, a_arg); +} + +// callback for the end of handshake in dap_client_go_stage() / chain_node_client_connect() +static void a_stage_end_callback(dap_client_t *a_client, void *a_arg) +{ + chain_node_client_t *client = a_client->_inheritor; + assert(client); + if(client) { + pthread_mutex_lock(&client->wait_mutex); + client->state = NODE_CLIENT_STATE_CONNECT; + pthread_cond_signal(&client->wait_cond); + pthread_mutex_unlock(&client->wait_mutex); + } +} + +/** + * Create connection to server + * + * return a connection handle, or NULL, if an error + */ +chain_node_client_t* chain_node_client_connect(dap_chain_node_info_t *node_info) +{ + if(!node_info) + return NULL; + chain_node_client_t *client = DAP_NEW_Z(chain_node_client_t); + client->state = NODE_CLIENT_STATE_INIT; + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&client->wait_cond, &attr); + pthread_mutex_init(&client->wait_mutex, NULL); + client->a_events = dap_events_new(); + client->a_client = dap_client_new(client->a_events, stage_status_callback, stage_status_error_callback); + client->a_client->_inheritor = client; + dap_client_pvt_t *l_client_internal = DAP_CLIENT_PVT(client->a_client); + + int hostlen = 128; + char host[hostlen]; + if(node_info->hdr.ext_addr_v4.s_addr) + { + struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = node_info->hdr.ext_addr_v4 }; + inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host, hostlen); + } + else + { + struct sockaddr_in6 sa6 = { .sin6_family = AF_INET6, .sin6_addr = node_info->hdr.ext_addr_v6 }; + inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) &sa6)->sin6_addr), host, hostlen); + } + // address not defined + if(!strcmp(host, "::")) { + chain_node_client_close(client); + return NULL; + } + l_client_internal->uplink_addr = strdup(host); + l_client_internal->uplink_port = listen_port_tcp; // reads from settings, default 8079 + l_client_internal->uplink_protocol_version = DAP_PROTOCOL_VERSION; + dap_client_stage_t a_stage_target = STAGE_ENC_INIT; + + client->state = NODE_CLIENT_STATE_CONNECT; + // Handshake + dap_client_go_stage(client->a_client, a_stage_target, a_stage_end_callback); + return client; +} + +/** + * Close connection to server, delete chain_node_client_t *client + */ +void chain_node_client_close(chain_node_client_t *client) +{ + if(client) { + // clean client + dap_client_pvt_t *l_client_internal = DAP_CLIENT_PVT(client->a_client); + DAP_DELETE(l_client_internal->uplink_addr); + dap_client_delete(client->a_client); + dap_events_delete(client->a_events); + pthread_cond_destroy(&client->wait_cond); + pthread_mutex_destroy(&client->wait_mutex); + DAP_DELETE(client); + } +} + +/** + * wait for the complete of request + * + * timeout_ms timeout in milliseconds + * waited_state state which we will wait, sample NODE_CLIENT_STATE_CONNECT or NODE_CLIENT_STATE_SENDED + * return -1 false, 0 timeout, 1 end of connection or sending data + */ +int chain_node_client_wait(chain_node_client_t *client, int waited_state, int timeout_ms) +{ + int ret = -1; + if(!client) + return -1; + pthread_mutex_lock(&client->wait_mutex); + // have waited + if(client->state == waited_state) { + pthread_mutex_unlock(&client->wait_mutex); + return 1; + } + // prepare for signal waiting + struct timespec to; + clock_gettime(CLOCK_MONOTONIC, &to); + int64_t nsec_new = to.tv_nsec + timeout_ms * 1000000ll; + // if the new number of nanoseconds is more than a second + if(nsec_new > (long) 1e9) { + to.tv_sec += nsec_new / (long) 1e9; + to.tv_nsec = nsec_new % (long) 1e9; + } + else + to.tv_nsec = (long) nsec_new; + // signal waiting + int wait = pthread_cond_timedwait(&client->wait_cond, &client->wait_mutex, &to); + if(wait == 0) //0 + ret = 1; + else if(wait == ETIMEDOUT) // 110 260 + ret = 0; + pthread_mutex_unlock(&client->wait_mutex); + return ret; +} diff --git a/dap_chain_node_cli_connect.h b/dap_chain_node_cli_connect.h new file mode 100644 index 0000000000000000000000000000000000000000..c2f91c1ecf31182e587d4d2180cf8dab26ea011f --- /dev/null +++ b/dap_chain_node_cli_connect.h @@ -0,0 +1,75 @@ +/* + * 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/>. + */ + +#pragma once + +#include <pthread.h> +#include <stdbool.h> + +#include "dap_client.h" +#include "dap_chain_node.h" + +// connection states +enum { + NODE_CLIENT_STATE_ERROR = -1, + NODE_CLIENT_STATE_INIT, + NODE_CLIENT_STATE_CONNECT, + NODE_CLIENT_STATE_CONNECTED, + NODE_CLIENT_STATE_SEND, + NODE_CLIENT_STATE_SENDED, + NODE_CLIENT_STATE_END +}; + +// state for a client connection +typedef struct chain_node_client { + int state; + dap_client_t *a_client; + dap_events_t *a_events; + pthread_cond_t wait_cond; + pthread_mutex_t wait_mutex; +} chain_node_client_t; + + +int chain_node_client_init(void); + +void chain_node_client_deinit(); + +/** + * Create connection to server + * + * return a connection handle, or NULL, if an error + */ +chain_node_client_t* chain_node_client_connect(dap_chain_node_info_t *node_info); + +/** + * Close connection to server, delete chain_node_client_t *client + */ +void chain_node_client_close(chain_node_client_t *client); + +/** + * wait for the complete of request + * + * timeout_ms timeout in milliseconds + * waited_state state which we will wait, sample NODE_CLIENT_STATE_CONNECT or NODE_CLIENT_STATE_SENDED + * return -1 false, 0 timeout, 1 end of connection or sending data + */ +int chain_node_client_wait(chain_node_client_t *client, int waited_state, int timeout_ms); + diff --git a/dap_chain_node_remote.c b/dap_chain_node_remote.c new file mode 100644 index 0000000000000000000000000000000000000000..914a847221d0a14ae9b7cc78e7fcaea4bf2ffca9 --- /dev/null +++ b/dap_chain_node_remote.c @@ -0,0 +1,90 @@ +/* + * 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 <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <glib.h> +#include <pthread.h> + +#include "dap_chain_node_remote.h" + + +// List of connections +static GList *connect_list = NULL; + +// for separate access to connect_list +static pthread_mutex_t connect_list_mutex = PTHREAD_MUTEX_INITIALIZER; + +/** + * Add new established connection in the list + */ +bool chain_node_client_list_add(chain_node_client_t *client) +{ + if(!client) + return false; + pthread_mutex_lock(&connect_list_mutex); + connect_list = g_list_append(connect_list, client); + pthread_mutex_unlock(&connect_list_mutex); + return true; +} + +/** + * Delete established connection from the list + */ +bool chain_node_client_list_del(chain_node_client_t *client) +{ + pthread_mutex_lock(&connect_list_mutex); + GList *list = g_list_find(connect_list, client); + // found + if(list) + connect_list = g_list_remove(connect_list, client); + pthread_mutex_unlock(&connect_list_mutex); + if(list) + return true; + return false; +} + +/** + * Get one established connection + * + * n - the position of the established connection, counting from 0 + * + * return client, or NULL if the position is off the end of the list + */ +chain_node_client_t* chain_node_client_list_get_item(int n) +{ + pthread_mutex_lock(&connect_list_mutex); + chain_node_client_t *client = g_list_nth_data(connect_list, (guint) n); + pthread_mutex_unlock(&connect_list_mutex); + return client; +} +/** + * Get the number of established connections + */ +int chain_node_client_list_count(void) +{ + pthread_mutex_lock(&connect_list_mutex); + int len = g_list_length(connect_list); + pthread_mutex_unlock(&connect_list_mutex); + return len; +} + diff --git a/dap_chain_node_remote.h b/dap_chain_node_remote.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7f4c5ef5452c2d5f5a1fdcfb046c67e03391a2 --- /dev/null +++ b/dap_chain_node_remote.h @@ -0,0 +1,50 @@ +/* + * 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/>. + */ + +#pragma once + +#include <stdbool.h> + +#include "dap_chain_node_cli_connect.h" + +/** + * Add new established connection in the list + */ +bool chain_node_client_list_add(chain_node_client_t *client); + +/** + * Delete established connection from the list + */ +bool chain_node_client_list_del(chain_node_client_t *client); + +/** + * Get one established connection + * + * n - the position of the established connection, counting from 0 + * + * return client, or NULL if the position is off the end of the list + */ +chain_node_client_t* chain_node_client_list_get_item(int n); + +/** + * Get the number of established connections + */ +int chain_node_client_list_count(void);