Skip to content
Snippets Groups Projects
dap_chain_node_cli.c 44.1 KiB
Newer Older
Roman Khlopkov's avatar
Roman Khlopkov committed
 * Dmitriy A. Gerasimov <gerasimov.dmitriy@demlabs.net>
 * Alexander Lysikov <alexander.lysikov@demlabs.net>
 * DeM Labs Inc.   https://demlabs.net
 * Cellframe  https://cellframe.net
 * Copyright  (c) 2019-2021
 * All rights reserved.
 This file is part of Cellframe SDK
 Cellframe SDK 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.

 Cellframe SDK 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 Cellframe SDK based project.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
#include <assert.h>
//#include <glib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
//#include <unistd.h> // for close
#include <fcntl.h>
//#include <sys/poll.h>
//#include <sys/select.h>
#include <netinet/in.h>
#include <sys/un.h>
Roman Khlopkov's avatar
Roman Khlopkov committed
#include <sys/stat.h>
//#define closesocket close
//typedef int SOCKET;
//#define SOCKET_ERROR    -1  // for win32 =  (-1)
//#define INVALID_SOCKET  -1  // for win32 =  (SOCKET)(~0)
// for Windows
#else
#include <winsock2.h>
ANTA's avatar
ANTA committed
#include <windows.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <io.h>
ANTA's avatar
ANTA committed
#include <pthread.h>

#include "iputils/iputils.h"
#include "dap_config.h"
#include "dap_strfuncs.h"
#include "dap_file_utils.h"
#include "dap_list.h"
#include "dap_chain_node_cli_cmd.h"
Dmitriy A. Gerasimov's avatar
Dmitriy A. Gerasimov committed
#include "dap_chain_node_client.h"
#include "dap_chain_node_cli_cmd_tx.h"
#include "dap_chain_node_cli.h"

//#include "dap_chain_node_cli.h"

#define LOG_TAG "chain_node_cli"

ANTA's avatar
ANTA committed
#define MAX_CONSOLE_CLIENTS 16

static SOCKET server_sockfd = -1; // network or local unix
uint32_t l_listen_port = 0;
bool s_debug_cli = false;
ANTA's avatar
ANTA committed

#ifdef _WIN32
  #define poll WSAPoll
#endif
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
static dap_chain_node_cmd_item_t * s_commands = NULL;
/**
 * Wait for data
 * timeout -  timeout in ms
 * [Specifying a negative value in timeout means an infinite timeout.]
 * [Specifying a timeout of zero causes poll() to return immediately, even if no file descriptors are ready.]
 * return zero if the time limit expired
 * return: >0 if data is present to read
 * return: -1 if error
 */
ANTA's avatar
ANTA committed
static int s_poll( int socket, int timeout )
    // 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
    if(res == 1 && !(fds.revents & POLLIN)) //if(res==1 && fds.revents!=POLLIN)
        return -1;
    return res;
}

/**
 * Check socket for validity
 */
static bool is_valid_socket(SOCKET sock)
{
    struct pollfd fds;
    fds.fd = sock;
    fds.events = POLLIN;
    // return: -1 err, 0 timeout, 1 waited
    int count_desc = poll(&fds, 1, 0);
    // event with an error code
        // 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
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
        long 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.
        // data in the buffer must be(count_desc>0), but read 0 bytes(res=0)
        if(!res && (fds.revents & POLLIN))
            return false;
    }
    return true;
}

/**
 * Read from socket
 *
 * timeout in milliseconds
 * return the number of read bytes (-1 err or -2 timeout)
 */
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
long s_recv(SOCKET sock, unsigned char *buf, size_t bufsize, int timeout)
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
    long res;
    fds.fd = sock;
    fds.events = POLLIN; // | POLLNVAL | POLLHUP | POLLERR | POLLPRI;// | POLLRDNORM;//POLLOUT |
    res = poll(&fds, 1, timeout);
    if(res == 1 && !(fds.revents & POLLIN))
        return -1;
    if(!res) // timeout
        return -2;
    if(res < 1) {
        return -1;
    }
    //    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
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
        printf("[s_recv] recv()=%ld errno=%d\n", res, errno);
    }
    return res;
}

/**
 * Reading from the socket till arrival the specified string
 *
 * stop_str - string to which reading will continue
 * del_stop_str - удалять ли строку для поиска в конце
 * timeout - in ms
 * return: string (if waited for final characters) or NULL, if the string requires deletion
 */
ANTA's avatar
ANTA committed
char* s_get_next_str( SOCKET nSocket, int *dwLen, const char *stop_str, bool del_stop_str, int timeout )
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
    long nRecv = 0; // count of bytes received
    size_t stop_str_len = (stop_str) ? strlen(stop_str) : 0;
    // if there is nothing to look for
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
    size_t lpszBuffer_len = 256;
    char *lpszBuffer = DAP_NEW_Z_SIZE(char, lpszBuffer_len);
    // received string will not be larger than MAX_REPLY_LEN
ANTA's avatar
ANTA committed

        // read one byte
dmitriy.gerasimov's avatar
dmitriy.gerasimov committed
        long ret = s_recv(nSocket, (unsigned char *) (lpszBuffer + nRecv), 1, timeout);
        //int ret = recv(nSocket,lpszBuffer+nRecv,1, 0);
Loading
Loading full blame...