From c6e9a626726a7004fef5adac217cd053418760a0 Mon Sep 17 00:00:00 2001 From: Dmitriy Gerasimov <dm@cifercom.com> Date: Wed, 27 Dec 2017 14:44:42 +0700 Subject: [PATCH] [+] Declarations for dap_client [+] Moved dap_client_remote from libdap-server (ex-dap_client) --- CMakeLists.txt | 12 ++ client/CMakeLists.txt | 10 ++ client/dap_client.c | 167 +++++++++++++++++++++++++ client/dap_client.h | 69 ++++++++++ client/dap_client_remote.c | 249 +++++++++++++++++++++++++++++++++++++ client/dap_client_remote.h | 86 +++++++++++++ core/CMakeLists.txt | 2 +- 7 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt create mode 100644 client/CMakeLists.txt create mode 100644 client/dap_client.c create mode 100644 client/dap_client.h create mode 100644 client/dap_client_remote.c create mode 100644 client/dap_client_remote.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..b1bce72dd7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +project(libdap C) +cmake_minimum_required(VERSION 2.8) + +add_subdirectory(core) +add_subdirectory(crypt) +add_subdirectory(client) +add_subdirectory(http) + +include_directories("${INCLUDE_DIRECTORIES} ${dapcrypt_INCLUDE_DIRS}") +include_directories("${INCLUDE_DIRECTORIES} ${dapcore_INCLUDE_DIRS}") +include_directories("${INCLUDE_DIRECTORIES} ${daphttp_INCLUDE_DIRS}") +include_directories("${INCLUDE_DIRECTORIES} ${dapclient_INCLUDE_DIRS}") diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt new file mode 100644 index 0000000000..ed60b07fa1 --- /dev/null +++ b/client/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8) +project (dapclient) + +set(CLIENT_SRCS dap_client_remote.c dap_client.c) + +add_library(${PROJECT_NAME} STATIC ${CORE_SRCS}) + +set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) + +set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR} CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE) diff --git a/client/dap_client.c b/client/dap_client.c new file mode 100644 index 0000000000..62dc62e0aa --- /dev/null +++ b/client/dap_client.c @@ -0,0 +1,167 @@ +#include "common.h" + +#include "sap_client.h" +#include "sap_client_internal.h" + +#define LOG_TAG "sap_client" + +/** + * @brief sap_client_init + * @return + */ +int sap_client_init() +{ + log_it(L_INFO, "Init SAP client module"); + return 0; +} + +/** + * @brief sap_client_deinit + */ +void sap_client_deinit() +{ + log_it(L_INFO, "Deinit SAP client module"); +} + +/** + * @brief sap_client_new + * @param a_stage_status_callback + * @return + */ +sap_client_t * sap_client_new(sap_client_callback_t a_stage_status_callback) +{ + +} + +/** + * @brief sap_client_delete + * @param a_client + */ +void sap_client_delete(sap_client_t * a_client) +{ + +} + +/** + * @brief sap_client_go_stage + * @param a_client + * @param a_stage_end + */ +void sap_client_go_stage(sap_client_t * a_client, sap_client_stage_t a_stage_end, sap_client_callback_t a_stage_end_callback) +{ + +} + +/** + * @brief sap_client_session_request + * @param a_client + * @param a_path + * @param a_request + * @param a_request_size + * @param a_response_proc + */ +void sap_client_session_request(sap_client_t * a_client, const char * a_path, void * a_request, size_t a_request_size, + sap_client_callback_t a_response_proc) +{ + +} + +/** + * @brief sap_client_set_uplink + * @param a_client + * @param a_addr + * @param a_port + */ +void sap_client_set_uplink(sap_client_t * a_client,const char* a_addr, uint16_t a_port) +{ + +} + +/** + * @brief sap_client_set_credentials + * @param a_client + * @param a_user + * @param a_password + */ +void sap_client_set_credentials(sap_client_t * a_client,const char* a_user, const char * a_password) +{ + +} + + +/** + * @brief sap_client_error_str + * @param a_client_error + * @return + */ +const char * sap_client_error_str(sap_client_error_t a_client_error) +{ + switch(a_client_error){ + case SAP_CLIENT_ERROR_ENC_NO_KEY: return "ENC_NO_KEY"; + case SAP_CLIENT_ERROR_ENC_WRONG_KEY: return "ENC_WRONG_KEY"; + case SAP_CLIENT_ERROR_AUTH_WRONG_COOKIE: return "AUTH_WRONG_COOKIE"; + case SAP_CLIENT_ERROR_AUTH_WRONG_CREDENTIALS: return "AUTH_WRONG_CREDENTIALS"; + case SAP_CLIENT_ERROR_NETWORK_CONNECTION_TIMEOUT: return "NETWORK_CONNECTION_TIMEOUT"; + case SAP_CLIENT_ERROR_NETWORK_CONNECTION_REFUSE: return "NETWORK_CONNECTION_REFUSE"; + case SAP_CLIENT_ERROR_NETWORK_DISCONNECTED: return "NETWORK_DISCONNECTED"; + case SAP_CLIENT_ERROR_STREAM_RESPONSE_WRONG: return "STREAM_RESPONSE_WRONG"; + case SAP_CLIENT_ERROR_STREAM_RESPONSE_TIMEOUT: return "STREAM_RESPONSE_TIMEOUT"; + case SAP_CLIENT_ERROR_STREAM_FREEZED: return "STREAM_FREEZED"; + case SAP_CLIENT_ERROR_LICENSE: return "LICENSE_ERROR"; + default : return "UNDEFINED"; + } +} + +/** + * @brief sap_client_get_stage + * @param a_client + * @return + */ +sap_client_stage_t sap_client_get_stage(sap_client_t * a_client) +{ + return SAP_CLIENT_INTERNAL(a_client)->stage; +} + +/** + * @brief sap_client_get_stage_status_str + * @param a_client + * @return + */ +const char * sap_client_get_stage_status_str(sap_client_t *a_client) +{ + switch(SAP_CLIENT_INTERNAL(a_client)->stage_status){ + case SAP_CLIENT_STAGE_STATUS_NONE: return "NONE"; + case SAP_CLIENT_STAGE_STATUS_IN_PROGRESS: return "IN_PROGRESS"; + case SAP_CLIENT_STAGE_STATUS_ERROR: return "ERROR"; + case SAP_CLIENT_STAGE_STATUS_DONE: return "DONE"; + default: return "UNDEFINED"; + } +} + +/** + * @brief sap_client_get_stage_str + * @param a_client + * @return + */ +const char * sap_client_get_stage_str(sap_client_t * a_client) +{ + switch(SAP_CLIENT_INTERNAL(a_client)->stage){ + case SAP_CLIENT_STAGE_BEGIN: return "BEGIN"; + case SAP_CLIENT_STAGE_ENC: return "ENC"; + case SAP_CLIENT_STAGE_AUTH: return "AUTH"; + case SAP_CLIENT_STAGE_STREAM_CTL: return "STREAM_CTL"; + case SAP_CLIENT_STAGE_STREAM: return "STREAM"; + case SAP_CLIENT_STAGE_NETCONF: return "NETCONF"; + case SAP_CLIENT_STAGE_TUNNEL: return "TUNNEL"; + default: return "UNDEFINED"; + } +} +/** + * @brief sap_client_get_stage_status + * @param a_client + * @return + */ +sap_client_stage_status_t sap_client_get_stage_status(sap_client_t * a_client) +{ + return SAP_CLIENT_INTERNAL(a_client)->stage_status; +} diff --git a/client/dap_client.h b/client/dap_client.h new file mode 100644 index 0000000000..a09cbadeee --- /dev/null +++ b/client/dap_client.h @@ -0,0 +1,69 @@ +#ifndef _SAP_CLIENT_H_ +#define _SAP_CLIENT_H_ +#include <stdint.h> + + +/** + * @brief The dap_client_stage enum. Top level of client's state machine + **/ +typedef enum dap_client_stage { + DAP_CLIENT_STAGE_BEGIN=0, + DAP_CLIENT_STAGE_ENC=1, + DAP_CLIENT_STAGE_AUTH=2, +} dap_client_stage_t; + +typedef enum dap_client_stage_status { + DAP_CLIENT_STAGE_STATUS_NONE=0, + // Enc init stage + DAP_CLIENT_STAGE_STATUS_IN_PROGRESS, + DAP_CLIENT_STAGE_STATUS_ERROR, + DAP_CLIENT_STAGE_STATUS_DONE, +} dap_client_stage_status_t; + +typedef enum dap_client_error { + DAP_CLIENT_ERROR_UNDEFINED = 0, + DAP_CLIENT_ERROR_ENC_NO_KEY, + DAP_CLIENT_ERROR_ENC_WRONG_KEY, + DAP_CLIENT_ERROR_NETWORK_CONNECTION_TIMEOUT, + DAP_CLIENT_ERROR_NETWORK_CONNECTION_REFUSE, + DAP_CLIENT_ERROR_NETWORK_DISCONNECTED, +} dap_client_error_t; + + +/** + * @brief The dap_client struct + */ +typedef struct sap_client{ + void * _internal; + void * _inheritor; +} dap_client_t; + +typedef void (*dap_client_callback_t) (dap_client_t *, void*); + +#ifdef __cplusplus +extern "C" { +#endif + +int dap_client_init(); +void dap_client_deinit(); + +dap_client_t * dap_client_new(dap_client_callback_t a_stage_status_callback); +void dap_client_delete(dap_client_t * a_client); + +void dap_client_set_uplink(dap_client_t * a_client,const char* a_addr, uint16_t a_port); +void dap_client_go_stage(dap_client_t * a_client, dap_client_stage_t a_stage_end, dap_client_callback_t a_stage_end_callback); + +void dap_client_enc_request(dap_client_t * a_client, const char * a_path, void * a_request, size_t a_request_size, + dap_client_callback_t a_response_proc); + +const char * dap_client_get_stage_str(dap_client_t * a_client); +const char * dap_client_get_stage_status_str(dap_client_t * a_client); +const char * dap_client_error_str(dap_client_error_t a_client_error); +dap_client_stage_t dap_client_get_stage(dap_client_t * a_client); +dap_client_stage_status_t dap_client_get_stage_status(dap_client_t * a_client); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/client/dap_client_remote.c b/client/dap_client_remote.c new file mode 100644 index 0000000000..d2f9d4aefa --- /dev/null +++ b/client/dap_client_remote.c @@ -0,0 +1,249 @@ +/* + Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <sys/epoll.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include "common.h" +#include "dap_server.h" +#include "dap_client.h" +#include <ev.h> +#define LOG_TAG "client" + + +/** + * @brief dap_client_init Init clients module + * @return Zero if ok others if no + */ +int dap_client_init() +{ + log_it(NOTICE,"Initialized socket client module"); + return 0; +} + +/** + * @brief dap_client_deinit Deinit clients module + */ +void dap_client_deinit() +{ + +} + +/** + * @brief safe_client_create Create new client and add it to the list + * @param sh Server instance + * @param s Client's socket + * @return Pointer to the new list's node + */ +dap_client_t * dap_client_create(dap_server_t * sh, int s, ev_io* w_client) +{ + pthread_mutex_lock(&sh->mutex_on_hash); + log_it(DEBUG,"Client structure create"); + + dap_client_t * ret=(dap_client_t *) calloc(1,sizeof(dap_client_t)); + ret->socket=s; + ret->server=sh; + ret->watcher_client = w_client; + ret->_ready_to_read=true; + + HASH_ADD_INT( sh->clients, socket, ret); + + if(sh->client_new_callback) + sh->client_new_callback(ret,NULL); // Init internal structure + + pthread_mutex_unlock(&sh->mutex_on_hash); + return ret; +} + +/** + * @brief dap_client_find + * @param sock + * @param sh + * @return + */ +dap_client_t * dap_client_find(int sock, struct dap_server * sh) +{ + pthread_mutex_lock(&sh->mutex_on_hash); + dap_client_t * ret=NULL; + HASH_FIND_INT(sh->clients,&sock,ret); + pthread_mutex_unlock(&sh->mutex_on_hash); + return ret; +} + +/** + * @brief dap_client_ready_to_read + * @param sc + * @param isReady + */ +void dap_client_ready_to_read(dap_client_t * sc,bool is_ready) +{ + if(is_ready != sc->_ready_to_read) { + + uint32_t events = 0; + sc->_ready_to_read=is_ready; + + if(sc->_ready_to_read) + events |= EV_READ; + + if(sc->_ready_to_write) + events |= EV_WRITE; + + ev_io_set(sc->watcher_client, sc->socket, events ); + } +} + +/** + * @brief dap_client_ready_to_write + * @param sc + * @param isReady + */ +void dap_client_ready_to_write(dap_client_t * sc,bool is_ready) +{ + if(is_ready != sc->_ready_to_write) { + + uint32_t events = 0; + sc->_ready_to_write=is_ready; + + if(sc->_ready_to_read) + events |= EV_READ; + + if(sc->_ready_to_write) + events |= EV_WRITE; + + ev_io_set(sc->watcher_client, sc->socket, events ); + } + +} + + +/** + * @brief safe_client_remove Removes the client from the list + * @param sc Client instance + */ +void dap_client_remove(dap_client_t *sc, struct dap_server * sh) +{ + pthread_mutex_lock(&sh->mutex_on_hash); + + log_it(DEBUG, "Client structure remove"); + HASH_DEL(sc->server->clients,sc); + + if(sc->server->client_delete_callback) + sc->server->client_delete_callback(sc,NULL); // Init internal structure + if(sc->internal) + free(sc->internal); + + if(sc->socket) + close(sc->socket); + free(sc); + pthread_mutex_unlock(&sh->mutex_on_hash); +} + +/** + * @brief dap_client_write Write data to the client + * @param sc Client instance + * @param data Pointer to data + * @param data_size Size of data to write + * @return Number of bytes that were placed into the buffer + */ +size_t dap_client_write(dap_client_t *sc, const void * data, size_t data_size) +{ + data_size = ((sc->buf_out_size+data_size)<(sizeof(sc->buf_out)))?data_size:(sizeof(sc->buf_out)-sc->buf_out_size ); + memcpy(sc->buf_out+sc->buf_out_size,data,data_size); + sc->buf_out_size+=data_size; + return data_size; +} + +/** + * @brief dap_client_write_f Write formatted text to the client + * @param sc Client instance + * @param format Format + * @return Number of bytes that were placed into the buffer + */ +size_t dap_client_write_f(dap_client_t *sc, const char * format,...) +{ + size_t max_data_size = sizeof(sc->buf_out)-sc->buf_out_size; + va_list ap; + va_start(ap,format); + int ret=vsnprintf(sc->buf_out+sc->buf_out_size,max_data_size,format,ap); + va_end(ap); + if(ret>0){ + sc->buf_out_size+=ret; + return ret; + }else{ + log_it(ERROR,"Can't write out formatted data '%s'",format); + return 0; + } +} + +/** + * @brief dap_client_read Read data from input buffer + * @param sc Client instasnce + * @param data Pointer to memory where to store the data + * @param data_size Size of data to read + * @return Actual bytes number that were read + */ +size_t dap_client_read(dap_client_t *sc, void * data, size_t data_size) +{ + + printf("Size of package: %d\n", (int)data_size); + // дамп пакета + hexdump(data, data_size); + + if (data_size < sc->buf_in_size) { + memcpy(data, sc->buf_in, data_size); + memmove(data, sc->buf_in + data_size, sc->buf_in_size - data_size); + } else { + if (data_size > sc->buf_in_size) { + data_size = sc->buf_in_size; + } + memcpy(data, sc->buf_in, data_size); + } + sc->buf_in_size -= data_size; + return data_size; +} + + +/** + * @brief shrink_client_buf_in Shrink input buffer (shift it left) + * @param cl Client instance + * @param shrink_size Size on wich we shrink the buffer with shifting it left + */ +void dap_client_shrink_buf_in(dap_client_t * cl, size_t shrink_size) +{ + if((shrink_size==0)||(cl->buf_in_size==0) ){ + //log_it(WARNING, "DBG_#003"); + return; + }else if(cl->buf_in_size>shrink_size){ + size_t buf_size=cl->buf_in_size-shrink_size; + void * buf = malloc(buf_size); + memcpy(buf,cl->buf_in+ shrink_size,buf_size ); + memcpy(cl->buf_in,buf,buf_size); + cl->buf_in_size=buf_size; + //log_it(WARNING, "DBG_#004"); + free(buf); + }else { + //log_it(WARNING, "DBG_#005"); + cl->buf_in_size=0; + } + +} diff --git a/client/dap_client_remote.h b/client/dap_client_remote.h new file mode 100644 index 0000000000..1868b4ddb2 --- /dev/null +++ b/client/dap_client_remote.h @@ -0,0 +1,86 @@ +/* + Copyright (c) 2017-2018 (c) Project "DeM Labs Inc" https://github.com/demlabsinc + 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 Lesser 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _DAP_CLIENT_H +#define _DAP_CLIENT_H + +#include <stdint.h> +#include <stddef.h> +#include <stdbool.h> +#include "uthash.h" +#include <ev.h> + + +struct dap_server; +struct dap_client; + +typedef void (*dap_client_callback_t) (struct dap_client *,void * arg); // Callback for specific client operations + +#define DAP_CLIENT_BUF 100000 + +typedef struct dap_client{ + int socket; + bool signal_close; + + bool _ready_to_write; + bool _ready_to_read; + + uint32_t buf_out_zero_count; + char buf_in[DAP_CLIENT_BUF+1]; // Internal buffer for input data + size_t buf_in_size; // size of data that is in the input buffer + + char buf_out[DAP_CLIENT_BUF+1]; // Internal buffer for output data + + char hostaddr[1024]; // Address + char service[128]; + + size_t buf_out_size; // size of data that is in the output buffer + + ev_io* watcher_client; + + struct dap_server * server; + + UT_hash_handle hh; + + void * internal; // Internal data to specific client type, usualy states for state machine +} dap_client_t; // Node of bidirectional list of clients + + + +extern int dap_client_init(); // Init clients module +extern void dap_client_deinit(); // Deinit clients module + +extern dap_client_t * dap_client_create(struct dap_server * sh, int s, ev_io* w_client); // Create new client and add it to the list +extern dap_client_t * dap_client_find(int sock, struct dap_server * sh); // Find client by socket + +extern bool dap_client_is_ready_to_read(dap_client_t * sc); +extern bool dap_client_is_ready_to_write(dap_client_t * sc); +extern void dap_client_ready_to_read(dap_client_t * sc,bool is_ready); +extern void dap_client_ready_to_write(dap_client_t * sc,bool is_ready); + +extern size_t dap_client_write(dap_client_t *sc, const void * data, size_t data_size); +extern size_t dap_client_write_f(dap_client_t *sc, const char * format,...); +extern size_t dap_client_read(dap_client_t *sc, void * data, size_t data_size); + +extern void dap_client_remove(dap_client_t *sc, struct dap_server * sh); // Removes the client from the list + +extern void dap_client_shrink_buf_in(dap_client_t * cl, size_t shrink_size); + +#endif diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 3678a54122..b4ce806776 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project (dapcore) -set(CORE_SRCS common.c config.c dap_client.c dap_server.c) +set(CORE_SRCS common.c dap_client_remote.c) add_library(${PROJECT_NAME} STATIC ${CORE_SRCS}) -- GitLab