Skip to content
Snippets Groups Projects
main_node_cli_net.c 6.41 KiB
Newer Older
/*
 * Authors:
 * Dmitriy A. Gearasimov <kahovski@gmail.com>
 * DeM Labs Inc.   https://demlabs.net
 * DeM Labs Open source community https://github.com/demlabsinc
 * Copyright  (c) 2017-2019
 * All rights reserved.

 This file is part of DAP (Deus Applications Prototypes) the open source project

 DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 DAP is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <dap_client.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include "dap_chain_node_cli.h" // for UNIX_SOCKET_FILE
#include "main_node_cli_net.h"

/**
 * Add to one array another one
 *
 * memory - destination array of data
 * add_mem - source array of data
 * memory_len - memory array size
 * add_size - add_mem array size
 */
static int add_mem_data(uint8_t **memory, size_t *memory_len, char *add_mem, size_t add_size)
{
    *memory = (char*) realloc(*memory, *memory_len + add_size + 1);
    //out of memory!
    if(*memory == NULL) {
        //printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }
    if(add_mem) {
        memcpy((*memory + *memory_len), add_mem, add_size);
        // increase the received bytes number
        *memory_len += add_size;
        // zero out the last byte
        *(*memory + *memory_len) = 0;
    }
    return add_size;
}

//callback functions to receive header
static size_t WriteHttpMemoryHeadCallback(void *contents, size_t size, size_t nmemb, cmd_state *cmd)
{
    if(!cmd)
        return 0;
    printf("[header] %s len=%d\n", contents, size * nmemb);
    // добавить к заголовку принятые данные
    //return add_mem_data(&page->raw_header, &page->header_len,(char*)contents, size * nmemb);
    return size;
}

// callback function to receive data
static size_t WriteHttpMemoryCallback(void *contents, size_t size, size_t nmemb, cmd_state *cmd)
{
    if(!cmd)
        return 0;
    printf("[data] %s len=%d\n", contents, size * nmemb);
    // add received data to body
    return add_mem_data(&cmd->ret_str, &cmd->ret_str_len, (char*) contents, size * nmemb);
}

/**
 * Connect to node unix socket server
 *
 * return struct connect_param if connect established, else NULL
 */
connect_param* node_cli_connect(void)
{
    curl_global_init(CURL_GLOBAL_DEFAULT);
    connect_param *param = DAP_NEW_Z(connect_param);
    CURL *curl_handle = curl_easy_init();
    int ret = curl_easy_setopt(curl_handle, CURLOPT_UNIX_SOCKET_PATH, UNIX_SOCKET_FILE); // unix socket mode
    curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 20L); // complete within 20 seconds
    ret = curl_easy_setopt(curl_handle, CURLOPT_CONNECT_ONLY, 1L); // connection only
    ret = curl_easy_setopt(curl_handle, CURLOPT_URL, "http:/localhost/connect");
    // execute request
    ret = curl_easy_perform(curl_handle);
    if(!ret)
    {
        param->curl = curl_handle;
        curl_easy_setopt(curl_handle, CURLOPT_CONNECT_ONLY, 0L); // disable mode - connection only
    }
    else
    {
        curl_easy_cleanup(curl_handle);
        DAP_DELETE(param);
        param = NULL;
    }
    return param;
}

/**
 * Send request to kelvin-node
 *
 * return 0 if OK, else error code
 */
int node_cli_post_command(connect_param *conn, cmd_state *cmd)
{
    if(!conn || !conn->curl || !cmd || !cmd->cmd_name)
            {
        assert(0);
        return -1;
    }
    CURLcode ret;
    CURL *curl = conn->curl;

    ret = curl_easy_setopt(curl, CURLOPT_HEADER, 0L); // don't get header in the body
    //ret = curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip, deflate"); // allow receive of compressed data
    //callback functions to receive data
    ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteHttpMemoryCallback); // callback for the data read
    //callback functions to receive header
    ret = curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, WriteHttpMemoryHeadCallback); // callback for the header read
    // passing a parameter to the callback function
    ret = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void * )cmd);
    ret = curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void * )cmd);
    ret = curl_easy_setopt(curl, CURLOPT_USERAGENT, "kelvin-console 1.0");

//    ret = curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);// GET запрос
    //  ret = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);// удалённый сервер не будет проверять наш сертификат. В противном случае необходимо этот самый сертификат послать.
    //ret = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
    ret = curl_easy_setopt(curl, CURLOPT_POST, 1); // POST request - optional if CURLOPT_POSTFIELDS will be

    add_mem_data((uint8_t**) &post_data, &post_data_len, cmd->cmd_name, strlen(cmd->cmd_name));
    if(cmd->cmd_param) {
        for(int i = 0; i < cmd->cmd_param_count; i++) {
            if(cmd->cmd_param[i]) {
                add_mem_data((uint8_t**) &post_data, &post_data_len, "\r\n", 2);
                add_mem_data((uint8_t**) &post_data, &post_data_len, cmd->cmd_param[i], strlen(cmd->cmd_param[i]));
            }
        }
        add_mem_data((uint8_t**) &post_data, &post_data_len, "\r\n\r\n", 4);
        if(post_data)
            ret = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); // data for POST request
        if(post_data_len >= 0)
            ret = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long )post_data_len); // if need a lot to send: CURLOPT_POSTFIELDSIZE_LARGE
        // sending request and receiving the http page (filling cmd)
        ret = curl_easy_perform(curl); // curl_easy_send
        free(post_data);
        return ret;
}

int node_cli_desconnect(connect_param *param)
{
    if(param) {
        if(param->curl)
            curl_easy_cleanup(param->curl);
        DAP_DELETE(param);
    }

    curl_global_cleanup();
}