From 4c7a9b425de74df920babbf47898c7ab69fb15b4 Mon Sep 17 00:00:00 2001 From: anta999 <antarctic@linuxpc> Date: Fri, 14 Jun 2019 15:58:09 +0400 Subject: [PATCH] change0 --- http_server/dap_http.c | 356 +++++----- http_server/dap_http.h | 156 ++--- http_server/dap_http_folder.c | 628 ++++++++--------- http_server/dap_http_folder.h | 62 +- http_server/dap_http_simple.c | 1184 ++++++++++++++++----------------- http_server/dap_http_simple.h | 160 ++--- 6 files changed, 1257 insertions(+), 1289 deletions(-) diff --git a/http_server/dap_http.c b/http_server/dap_http.c index eb66d5e..57b4a3e 100755 --- a/http_server/dap_http.c +++ b/http_server/dap_http.c @@ -1,178 +1,178 @@ -/* - 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 <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> - -#ifndef _WIN32 -#include <netinet/in.h> - -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> -#include <netdb.h> -#else -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include <time.h> -#include "wrappers.h" -#include <wepoll.h> -#include <pthread.h> -#endif - -#include "dap_common.h" - -#include "dap_server.h" -#include "dap_client_remote.h" - -#include "dap_http.h" -#include "dap_http_header.h" -#include "dap_http_client.h" - -#define LOG_TAG "dap_http" - - -/** - * @brief dap_http_init // Init HTTP module - * @return Zero if ok others if not - */ -int dap_http_init( ) -{ - if ( dap_http_header_init() != 0 ) { // Init submodule for headers manipulations - log_it(L_CRITICAL,"Can't init HTTP headers processing submodule"); - return -1; - } - - if ( dap_http_client_init() !=0 ) { // Init submodule for HTTP client event processing - log_it(L_CRITICAL,"Can't init HTTP client submodule"); - return -2; - } - - log_it( L_NOTICE, "Initialized HTTP server module" ); - return 0; -} - -/** - * @brief dap_http_deinit Deinit HTTP module - */ -void dap_http_deinit() -{ - dap_http_header_deinit( ); - dap_http_client_deinit( ); -} - - -/** - * @brief dap_server_http_init Init HTTP server - * @param sh Server instance - * @return 0 if ok lesser number if error - */ -int dap_http_new( dap_server_t *sh, const char * server_name ) -{ - sh->_inheritor = calloc( 1, sizeof(dap_http_t) ); - - dap_http_t *shttp = DAP_HTTP( sh ); - - shttp->server = sh; - strncpy( shttp->server_name, server_name, sizeof(shttp->server_name)-1 ); - - sh->client_new_callback = dap_http_client_new; - sh->client_delete_callback = dap_http_client_delete; - sh->client_read_callback = dap_http_client_read; - sh->client_write_callback = dap_http_client_write; - sh->client_error_callback = dap_http_client_error; - - return 0; -} - -/** - * @brief dap_http_delete Clear dap_http structure in the internal data field of dap_server_t instance - * @param sh Server's instance - * @param arg Non-used argument - */ -void dap_http_delete( dap_server_t *sh, void * arg ) -{ - (void) arg; - (void) sh; - dap_http_t *shttp = DAP_HTTP( sh ); - dap_http_url_proc_t *up, *tmp; - - HASH_ITER( hh, shttp->url_proc ,up, tmp ) { - HASH_DEL(shttp->url_proc, up); - if( up->_inheritor ) - free( up->_inheritor ); - free( up ); - } -} - - -/** - * @brief dap_http_add_proc Add custom procesor for the HTTP server - * @param sh Server's instance - * @param url_path Part of URL to be processed - * @param read_callback Callback for read in DATA state - * @param write_callback Callback for write in DATA state - * @param error_callback Callback for error processing - */ -void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal - ,dap_http_client_callback_t new_callback - ,dap_http_client_callback_t delete_callback - ,dap_http_client_callback_t headers_read_callback - ,dap_http_client_callback_t headers_write_callback - ,dap_http_client_callback_t data_read_callback - ,dap_http_client_callback_t data_write_callback - ,dap_http_client_callback_t error_callback - - ) -{ - dap_http_url_proc_t *up = (dap_http_url_proc_t *) calloc( 1, sizeof(dap_http_url_proc_t) ); - - strncpy( up->url, url_path, sizeof(up->url) ); - - up->new_callback = new_callback; - up->delete_callback = delete_callback; - - up->data_read_callback = data_read_callback; - up->data_write_callback = data_write_callback; - up->headers_read_callback = headers_read_callback; - up->headers_write_callback = headers_write_callback; - up->error_callback = error_callback; - - up->_inheritor = internal; - - HASH_ADD_STR( sh->url_proc, url, up ); - - log_it( L_DEBUG, "Added URL processor for '%s' path", up->url ); -} - - +/* + 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 <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#ifndef _WIN32 +#include <netinet/in.h> + +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <netdb.h> +#else +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <ws2tcpip.h> +#include <io.h> +#include <time.h> +#include "wrappers.h" +#include <wepoll.h> +#include <pthread.h> +#endif + +#include "dap_common.h" + +#include "dap_server.h" +#include "dap_client_remote.h" + +#include "dap_http.h" +#include "dap_http_header.h" +#include "dap_http_client.h" + +#define LOG_TAG "dap_http" + + +/** + * @brief dap_http_init // Init HTTP module + * @return Zero if ok others if not + */ +int dap_http_init( ) +{ + if ( dap_http_header_init() != 0 ) { // Init submodule for headers manipulations + log_it(L_CRITICAL,"Can't init HTTP headers processing submodule"); + return -1; + } + + if ( dap_http_client_init() !=0 ) { // Init submodule for HTTP client event processing + log_it(L_CRITICAL,"Can't init HTTP client submodule"); + return -2; + } + + log_it( L_NOTICE, "Initialized HTTP server module" ); + return 0; +} + +/** + * @brief dap_http_deinit Deinit HTTP module + */ +void dap_http_deinit() +{ + dap_http_header_deinit( ); + dap_http_client_deinit( ); +} + + +/** + * @brief dap_server_http_init Init HTTP server + * @param sh Server instance + * @return 0 if ok lesser number if error + */ +int dap_http_new( dap_server_t *sh, const char * server_name ) +{ + sh->_inheritor = calloc( 1, sizeof(dap_http_t) ); + + dap_http_t *shttp = DAP_HTTP( sh ); + + shttp->server = sh; + strncpy( shttp->server_name, server_name, sizeof(shttp->server_name)-1 ); + + sh->client_new_callback = dap_http_client_new; + sh->client_delete_callback = dap_http_client_delete; + sh->client_read_callback = dap_http_client_read; + sh->client_write_callback = dap_http_client_write; + sh->client_error_callback = dap_http_client_error; + + return 0; +} + +/** + * @brief dap_http_delete Clear dap_http structure in the internal data field of dap_server_t instance + * @param sh Server's instance + * @param arg Non-used argument + */ +void dap_http_delete( dap_server_t *sh, void * arg ) +{ + (void) arg; + (void) sh; + dap_http_t *shttp = DAP_HTTP( sh ); + dap_http_url_proc_t *up, *tmp; + + HASH_ITER( hh, shttp->url_proc ,up, tmp ) { + HASH_DEL(shttp->url_proc, up); + if( up->_inheritor ) + free( up->_inheritor ); + free( up ); + } +} + + +/** + * @brief dap_http_add_proc Add custom procesor for the HTTP server + * @param sh Server's instance + * @param url_path Part of URL to be processed + * @param read_callback Callback for read in DATA state + * @param write_callback Callback for write in DATA state + * @param error_callback Callback for error processing + */ +void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal + ,dap_http_client_callback_t new_callback + ,dap_http_client_callback_t delete_callback + ,dap_http_client_callback_t headers_read_callback + ,dap_http_client_callback_t headers_write_callback + ,dap_http_client_callback_t data_read_callback + ,dap_http_client_callback_t data_write_callback + ,dap_http_client_callback_t error_callback + + ) +{ + dap_http_url_proc_t *up = (dap_http_url_proc_t *) calloc( 1, sizeof(dap_http_url_proc_t) ); + + strncpy( up->url, url_path, sizeof(up->url) ); + + up->new_callback = new_callback; + up->delete_callback = delete_callback; + + up->data_read_callback = data_read_callback; + up->data_write_callback = data_write_callback; + up->headers_read_callback = headers_read_callback; + up->headers_write_callback = headers_write_callback; + up->error_callback = error_callback; + + up->_inheritor = internal; + + HASH_ADD_STR( sh->url_proc, url, up ); + + log_it( L_DEBUG, "Added URL processor for '%s' path", up->url ); +} + + diff --git a/http_server/dap_http.h b/http_server/dap_http.h index 13d3a70..9ed36a1 100755 --- a/http_server/dap_http.h +++ b/http_server/dap_http.h @@ -1,78 +1,78 @@ -/* - 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 _SERVER_HTTP_H_ -#define _SERVER_HTTP_H_ -#include "dap_server.h" -#include "dap_client_remote.h" -#include "http_client/dap_http_header.h" -#include "http_client/dap_http_client.h" -#include "uthash.h" - -struct dap_http; -struct dap_http_url_processor; -//Structure for internal data of dap_server_t structure for holding special HTTP data - -// Structure for holding URL processors -typedef struct dap_http_url_proc{ - char url[512]; // First part of URL that will be processed - struct dap_http * http; // Pointer to HTTP server instance - - dap_http_client_callback_t new_callback; // Init internal structure - dap_http_client_callback_t delete_callback; // Delete internal structure - - dap_http_client_callback_t headers_read_callback; - dap_http_client_callback_t headers_write_callback; - - dap_http_client_callback_t data_read_callback; - dap_http_client_callback_t data_write_callback; - dap_http_client_callback_t error_callback; - - dap_http_client_callback_t access_callback; - - void *_inheritor; // Internal data specific to the current URL processor - UT_hash_handle hh; // makes this structure hashable with UTHASH library -} dap_http_url_proc_t; - -// Internal server structure for HTTP server -typedef struct dap_http { - dap_server_t *server; - char server_name[256]; - dap_http_url_proc_t * url_proc; -} dap_http_t; - -#define DAP_HTTP(a) ((dap_http_t *) (a)->_inheritor) - -extern int dap_http_init( ); // Init module -extern void dap_http_deinit( ); // Deinit module - -extern int dap_http_new( dap_server_t *sh, const char *server_name ); // Create dap_http structure in the internal data field of dap_server_t instance -extern void dap_http_delete( dap_server_t *sh, void *arg ); // Clear dap_http structure in the internal data field of dap_server_t instance - -extern void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal - ,dap_http_client_callback_t new_callback - ,dap_http_client_callback_t delete_callback - ,dap_http_client_callback_t headers_read_callback - ,dap_http_client_callback_t headers_write_callback - ,dap_http_client_callback_t data_read_callback - ,dap_http_client_callback_t data_write_callback - ,dap_http_client_callback_t error_callback ); // Add custom procesor for the HTTP server - -#endif +/* + 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 _SERVER_HTTP_H_ +#define _SERVER_HTTP_H_ +#include "dap_server.h" +#include "dap_client_remote.h" +#include "http_client/dap_http_header.h" +#include "http_client/dap_http_client.h" +#include "uthash.h" + +struct dap_http; +struct dap_http_url_processor; +//Structure for internal data of dap_server_t structure for holding special HTTP data + +// Structure for holding URL processors +typedef struct dap_http_url_proc{ + char url[512]; // First part of URL that will be processed + struct dap_http * http; // Pointer to HTTP server instance + + dap_http_client_callback_t new_callback; // Init internal structure + dap_http_client_callback_t delete_callback; // Delete internal structure + + dap_http_client_callback_t headers_read_callback; + dap_http_client_callback_t headers_write_callback; + + dap_http_client_callback_t data_read_callback; + dap_http_client_callback_t data_write_callback; + dap_http_client_callback_t error_callback; + + dap_http_client_callback_t access_callback; + + void *_inheritor; // Internal data specific to the current URL processor + UT_hash_handle hh; // makes this structure hashable with UTHASH library +} dap_http_url_proc_t; + +// Internal server structure for HTTP server +typedef struct dap_http { + dap_server_t *server; + char server_name[256]; + dap_http_url_proc_t * url_proc; +} dap_http_t; + +#define DAP_HTTP(a) ((dap_http_t *) (a)->_inheritor) + +extern int dap_http_init( ); // Init module +extern void dap_http_deinit( ); // Deinit module + +extern int dap_http_new( dap_server_t *sh, const char *server_name ); // Create dap_http structure in the internal data field of dap_server_t instance +extern void dap_http_delete( dap_server_t *sh, void *arg ); // Clear dap_http structure in the internal data field of dap_server_t instance + +extern void dap_http_add_proc(dap_http_t *sh, const char *url_path, void *internal + ,dap_http_client_callback_t new_callback + ,dap_http_client_callback_t delete_callback + ,dap_http_client_callback_t headers_read_callback + ,dap_http_client_callback_t headers_write_callback + ,dap_http_client_callback_t data_read_callback + ,dap_http_client_callback_t data_write_callback + ,dap_http_client_callback_t error_callback ); // Add custom procesor for the HTTP server + +#endif diff --git a/http_server/dap_http_folder.c b/http_server/dap_http_folder.c index 8639a25..090ece3 100755 --- a/http_server/dap_http_folder.c +++ b/http_server/dap_http_folder.c @@ -1,314 +1,314 @@ -/* - 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 <stdio.h> - -#ifndef _WIN32 -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> -#include <errno.h> -#else -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include "wrappers.h" -#include <wepoll.h> -#include <pthread.h> -#endif - -#include <magic.h> - -#include "dap_common.h" -#include "dap_client_remote.h" -#include "dap_http.h" -#include "dap_http_client.h" -#include "dap_http_folder.h" -#include "http_status_code.h" - -typedef struct dap_http_url_proc_folder { - char local_path[4096]; - magic_t mime_detector; -} dap_http_url_proc_folder_t; - -#define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior ) - -typedef struct dap_http_file{ - FILE * fd; - size_t position; - char local_path[4096]; - dap_http_client_t *client; -} dap_http_file_t; - -#define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor ) - -void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg ); -void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg ); - -#define LOG_TAG "dap_http_folder" - -int dap_http_folder_init( ) -{ - return 0; -} - -void dap_http_folder_deinit( ) -{ - -} - - -/** - * @brief dap_http_folder_add Add folder for reading to the HTTP server - * @param sh Server instance - * @param url_path Beginning part of the URL - * @param local_path Local path that will be read for - */ -int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path ) -{ - if ( !local_path ) { - log_it( L_ERROR, "Directory Path parameter is empty!" ); - return -11; - } - - log_it( L_DEBUG, "Checking url path %s", local_path ); - -#ifndef _WIN32 - DIR *dirptr = opendir( local_path ); - if ( dirptr == NULL ) { - log_it( L_ERROR, "Directory Not Found!" ); - return -11; - } - else { - closedir( dirptr ); - } -#else // WIN32 - - DWORD attr = GetFileAttributesA( local_path ); - if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) { - log_it( L_ERROR, "Directory Not Found!" ); - return -11; - } - -#endif - - log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path ); - - dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) ); - strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path) ); - - up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME ); - - if ( up_folder->mime_detector == NULL) { - log_it( L_CRITICAL,"Can't init MIME detection library" ); - free( up_folder ); - return -1; - } - -#ifndef _WIN32 - if( 0 != magic_load( up_folder->mime_detector, NULL) ) { -#else - if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) { -#endif - - log_it( L_CRITICAL, "Can't load MIME magic detection database" ); - magic_close( up_folder->mime_detector ); - free( up_folder ); - return -2; - } - - dap_http_add_proc( sh, - url_path, - up_folder, - NULL, - NULL, - dap_http_folder_headers_read, - dap_http_folder_headers_write, - dap_http_folder_data_read, - dap_http_folder_data_write, - NULL ); - return 0; -} - -/** - * @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data - * @param cl_ht HTTP client instance - * @param arg Not used - */ -void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) -{ - (void) arg; - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_write(cl_ht->client,true); - dap_client_remote_ready_to_read(cl_ht->client, cl_ht->keep_alive); -} - -#ifdef _WIN32 -time_t FileTimeToUnixTime( FILETIME ft ) -{ - ULARGE_INTEGER ull; - - ull.LowPart = ft.dwLowDateTime; - ull.HighPart = ft.dwHighDateTime; - - return ull.QuadPart / 10000000ULL - 11644473600ULL; -} -#endif - -/** - * @brief dap_http_folder_headers Prepare response HTTP headers for file folder request - * @param cl_ht HTTP client instane - * @param arg Not used - */ -void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg) -{ - (void) arg; - // Get specific data for folder URL processor - dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor; - - // Init specific file response data for HTTP client instance - cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t); - - dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht); - cl_ht_file->client=cl_ht; - - // Produce local path for file to open - snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path ); - log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path); - -#ifndef _WIN32 - - struct stat file_stat; - - if ( stat(cl_ht_file->local_path, &file_stat) != 0 ) - goto err; - - cl_ht->out_last_modified = file_stat.st_mtime; - cl_ht->out_content_length = file_stat.st_size; - -#else - - FILETIME CreationTime; - FILETIME LastAccessTime; - FILETIME LastWriteTime; - - HANDLE fileh = CreateFileA( cl_ht_file->local_path, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_ARCHIVE, - NULL - ); - - if ( fileh == INVALID_HANDLE_VALUE ) - goto err; - - GetFileTime( fileh, - &CreationTime, - &LastAccessTime, - &LastWriteTime ); - - cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime ); - cl_ht->out_content_length = GetFileSize( fileh, NULL ); - - CloseHandle( fileh ); - -#endif - - cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" ); - - if ( cl_ht_file->fd == NULL ) { - log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno)); - cl_ht->reply_status_code = Http_Status_NotFound; - strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase) ); - } - else { - cl_ht->reply_status_code = Http_Status_OK; - strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase) ); - - const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path ); - if( mime_type ) { - strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)); - log_it( L_DEBUG, "MIME type detected: '%s'", mime_type ); - } - else { - cl_ht->reply_status_code=Http_Status_NotFound; - cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); - } - } - - return; - -err: - - log_it( L_WARNING, "Can't get file info: %s", strerror(errno) ); - cl_ht->reply_status_code = 404; - strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase) ); - - return; -} - -/** - * @brief dap_http_folder_read HTTP client callback for reading function for the folder processing - * @param cl_ht HTTP client instance - * @param arg Pointer to int with return bytes number - */ -void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg) -{ - int * bytes_return = (int*) arg; // Return number of read bytes - //Do nothing - *bytes_return=cl_ht->client->buf_in_size; -} - -/** - * @brief dap_http_folder_write HTTP client callback for writting function for the folder processing - * @param cl_ht HTTP client instance - * @param arg - */ -void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg) -{ - (void) arg; - dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht); - cl_ht->client->buf_out_size=fread(cl_ht->client->buf_out,1,sizeof(cl_ht->client->buf_out),cl_ht_file->fd); - cl_ht_file->position+=cl_ht->client->buf_out_size; - - if(feof(cl_ht_file->fd)!=0){ - log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path); - //strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out)); - fclose(cl_ht_file->fd); - dap_client_remote_ready_to_write(cl_ht->client,false); - - if ( !cl_ht->keep_alive ) - cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; - } -} - +/* + 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 <stdio.h> + +#ifndef _WIN32 +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> +#else +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <ws2tcpip.h> +#include <io.h> +#include "wrappers.h" +#include <wepoll.h> +#include <pthread.h> +#endif + +#include <magic.h> + +#include "dap_common.h" +#include "dap_client_remote.h" +#include "dap_http.h" +#include "dap_http_client.h" +#include "dap_http_folder.h" +#include "http_status_code.h" + +typedef struct dap_http_url_proc_folder { + char local_path[4096]; + magic_t mime_detector; +} dap_http_url_proc_folder_t; + +#define URL_PROC_FOLDER(a) ((dap_http_url_proc_folder_t*) (a)->_inhertior ) + +typedef struct dap_http_file{ + FILE * fd; + size_t position; + char local_path[4096]; + dap_http_client_t *client; +} dap_http_file_t; + +#define DAP_HTTP_FILE(a) ((dap_http_file_t*) (a)->_inheritor ) + +void dap_http_folder_headers_read( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_data_read( dap_http_client_t *cl_ht, void *arg ); +void dap_http_folder_data_write( dap_http_client_t *cl_ht, void *arg ); + +#define LOG_TAG "dap_http_folder" + +int dap_http_folder_init( ) +{ + return 0; +} + +void dap_http_folder_deinit( ) +{ + +} + + +/** + * @brief dap_http_folder_add Add folder for reading to the HTTP server + * @param sh Server instance + * @param url_path Beginning part of the URL + * @param local_path Local path that will be read for + */ +int dap_http_folder_add( dap_http_t *sh, const char *url_path, const char *local_path ) +{ + if ( !local_path ) { + log_it( L_ERROR, "Directory Path parameter is empty!" ); + return -11; + } + + log_it( L_DEBUG, "Checking url path %s", local_path ); + +#ifndef _WIN32 + DIR *dirptr = opendir( local_path ); + if ( dirptr == NULL ) { + log_it( L_ERROR, "Directory Not Found!" ); + return -11; + } + else { + closedir( dirptr ); + } +#else // WIN32 + + DWORD attr = GetFileAttributesA( local_path ); + if ( attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY) ) { + log_it( L_ERROR, "Directory Not Found!" ); + return -11; + } + +#endif + + log_it( L_NOTICE, "File service for %s => %s ", url_path, local_path ); + + dap_http_url_proc_folder_t *up_folder = (dap_http_url_proc_folder_t *)calloc( 1, sizeof(dap_http_url_proc_folder_t) ); + strncpy( up_folder->local_path, local_path, sizeof(up_folder->local_path) ); + + up_folder->mime_detector = magic_open( MAGIC_SYMLINK | MAGIC_MIME | MAGIC_PRESERVE_ATIME ); + + if ( up_folder->mime_detector == NULL) { + log_it( L_CRITICAL,"Can't init MIME detection library" ); + free( up_folder ); + return -1; + } + +#ifndef _WIN32 + if( 0 != magic_load( up_folder->mime_detector, NULL) ) { +#else + if( 0 != magic_load( up_folder->mime_detector, "data.mag" ) ) { +#endif + + log_it( L_CRITICAL, "Can't load MIME magic detection database" ); + magic_close( up_folder->mime_detector ); + free( up_folder ); + return -2; + } + + dap_http_add_proc( sh, + url_path, + up_folder, + NULL, + NULL, + dap_http_folder_headers_read, + dap_http_folder_headers_write, + dap_http_folder_data_read, + dap_http_folder_data_write, + NULL ); + return 0; +} + +/** + * @brief dap_http_folder_headers_read Signal thats HTTP client is now going to output the data + * @param cl_ht HTTP client instance + * @param arg Not used + */ +void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) +{ + (void) arg; + cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; + cl_ht->state_read=cl_ht->keep_alive?DAP_HTTP_CLIENT_STATE_START:DAP_HTTP_CLIENT_STATE_NONE; + dap_client_remote_ready_to_write(cl_ht->client,true); + dap_client_remote_ready_to_read(cl_ht->client, cl_ht->keep_alive); +} + +#ifdef _WIN32 +time_t FileTimeToUnixTime( FILETIME ft ) +{ + ULARGE_INTEGER ull; + + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + + return ull.QuadPart / 10000000ULL - 11644473600ULL; +} +#endif + +/** + * @brief dap_http_folder_headers Prepare response HTTP headers for file folder request + * @param cl_ht HTTP client instane + * @param arg Not used + */ +void dap_http_folder_headers_write( dap_http_client_t *cl_ht, void * arg) +{ + (void) arg; + // Get specific data for folder URL processor + dap_http_url_proc_folder_t * up_folder=(dap_http_url_proc_folder_t*) cl_ht->proc->_inheritor; + + // Init specific file response data for HTTP client instance + cl_ht->_inheritor=DAP_NEW_Z(dap_http_file_t); + + dap_http_file_t* cl_ht_file=DAP_HTTP_FILE(cl_ht); + cl_ht_file->client=cl_ht; + + // Produce local path for file to open + snprintf(cl_ht_file->local_path,sizeof(cl_ht_file->local_path),"%s/%s", up_folder->local_path, cl_ht->url_path ); + log_it(L_DEBUG, "Check %s file", cl_ht_file->local_path); + +#ifndef _WIN32 + + struct stat file_stat; + + if ( stat(cl_ht_file->local_path, &file_stat) != 0 ) + goto err; + + cl_ht->out_last_modified = file_stat.st_mtime; + cl_ht->out_content_length = file_stat.st_size; + +#else + + FILETIME CreationTime; + FILETIME LastAccessTime; + FILETIME LastWriteTime; + + HANDLE fileh = CreateFileA( cl_ht_file->local_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_ARCHIVE, + NULL + ); + + if ( fileh == INVALID_HANDLE_VALUE ) + goto err; + + GetFileTime( fileh, + &CreationTime, + &LastAccessTime, + &LastWriteTime ); + + cl_ht->out_last_modified = FileTimeToUnixTime( LastWriteTime ); + cl_ht->out_content_length = GetFileSize( fileh, NULL ); + + CloseHandle( fileh ); + +#endif + + cl_ht_file->fd = fopen( cl_ht_file->local_path, "rb" ); + + if ( cl_ht_file->fd == NULL ) { + log_it(L_ERROR, "Can't open %s: %s",cl_ht_file->local_path,strerror(errno)); + cl_ht->reply_status_code = Http_Status_NotFound; + strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase) ); + } + else { + cl_ht->reply_status_code = Http_Status_OK; + strncpy( cl_ht->reply_reason_phrase,"OK",sizeof(cl_ht->reply_reason_phrase) ); + + const char *mime_type = magic_file( up_folder->mime_detector, cl_ht_file->local_path ); + if( mime_type ) { + strncpy(cl_ht->out_content_type,mime_type,sizeof(cl_ht->out_content_type)); + log_it( L_DEBUG, "MIME type detected: '%s'", mime_type ); + } + else { + cl_ht->reply_status_code=Http_Status_NotFound; + cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; + log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); + } + } + + return; + +err: + + log_it( L_WARNING, "Can't get file info: %s", strerror(errno) ); + cl_ht->reply_status_code = 404; + strncpy( cl_ht->reply_reason_phrase, "Not Found", sizeof(cl_ht->reply_reason_phrase) ); + + return; +} + +/** + * @brief dap_http_folder_read HTTP client callback for reading function for the folder processing + * @param cl_ht HTTP client instance + * @param arg Pointer to int with return bytes number + */ +void dap_http_folder_data_read(dap_http_client_t * cl_ht, void * arg) +{ + int * bytes_return = (int*) arg; // Return number of read bytes + //Do nothing + *bytes_return=cl_ht->client->buf_in_size; +} + +/** + * @brief dap_http_folder_write HTTP client callback for writting function for the folder processing + * @param cl_ht HTTP client instance + * @param arg + */ +void dap_http_folder_data_write(dap_http_client_t * cl_ht, void * arg) +{ + (void) arg; + dap_http_file_t * cl_ht_file= DAP_HTTP_FILE(cl_ht); + cl_ht->client->buf_out_size=fread(cl_ht->client->buf_out,1,sizeof(cl_ht->client->buf_out),cl_ht_file->fd); + cl_ht_file->position+=cl_ht->client->buf_out_size; + + if(feof(cl_ht_file->fd)!=0){ + log_it(L_INFO, "All the file %s is sent out",cl_ht_file->local_path); + //strncat(cl_ht->client->buf_out+cl_ht->client->buf_out_size,"\r\n",sizeof(cl_ht->client->buf_out)); + fclose(cl_ht_file->fd); + dap_client_remote_ready_to_write(cl_ht->client,false); + + if ( !cl_ht->keep_alive ) + cl_ht->client->flags |= DAP_SOCK_SIGNAL_CLOSE; + + cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; + } +} + diff --git a/http_server/dap_http_folder.h b/http_server/dap_http_folder.h index 3dec049..05d0eed 100755 --- a/http_server/dap_http_folder.h +++ b/http_server/dap_http_folder.h @@ -1,31 +1,31 @@ -/* - 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_HTTP_FOLDER_H_ -#define _DAP_HTTP_FOLDER_H_ - -struct dap_http; - -extern int dap_http_folder_init(); -extern void dap_http_folder_deinit(); - -extern int dap_http_folder_add(struct dap_http *sh, const char * url_path, const char * local_path); // Add folder for reading to the HTTP server - -#endif +/* + 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_HTTP_FOLDER_H_ +#define _DAP_HTTP_FOLDER_H_ + +struct dap_http; + +extern int dap_http_folder_init(); +extern void dap_http_folder_deinit(); + +extern int dap_http_folder_add(struct dap_http *sh, const char * url_path, const char * local_path); // Add folder for reading to the HTTP server + +#endif diff --git a/http_server/dap_http_simple.c b/http_server/dap_http_simple.c index 0a3413c..0c9c159 100755 --- a/http_server/dap_http_simple.c +++ b/http_server/dap_http_simple.c @@ -1,608 +1,576 @@ -/* - * Authors: - * Dmitriy A. Gearasimov <kahovski@gmail.com> - * Anatolii Kurotych <akurotych@gmail.com> - * DeM Labs Inc. https://demlabs.net - * DeM Labs Open source community https://github.com/kelvinblockchain - * 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 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 <stdio.h> -#include <stdarg.h> -#include <stdbool.h> -#include <string.h> -#include <stdint.h> -#include <time.h> - -#ifndef _WIN32 -//#include <ev.h> -#include <sys/queue.h> -#include <utlist.h> -#else -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0600 -#include <winsock2.h> -#include <windows.h> -#include <mswsock.h> -#include <ws2tcpip.h> -#include <io.h> -#include "wrappers.h" -#include <wepoll.h> -#include <pthread.h> -#endif - -#include <json-c/json.h> - -#include "dap_common.h" -#include "dap_config.h" -#include "dap_http.h" -#include "dap_http_client.h" -#include "dap_http_simple.h" -#include "dap_enc_key.h" -#include "dap_http_user_agent.h" - -#include "../enc_server/dap_enc_ks.h" -#include "../enc_server/dap_enc_http.h" - -#include "http_status_code.h" - -#define LOG_TAG "dap_http_simple" - -void dap_http_simple_headers_read( dap_http_client_t *cl_ht, void *arg ); -void dap_http_simple_data_write( dap_http_client_t *a_http_client, void *a_arg ); -void dap_http_simple_data_read( dap_http_client_t * cl_ht, void *arg ); -void *dap_http_simple_proc( dap_http_simple_t * cl_sh ); - -static void *loop_http_simple_proc( void *arg ); - -static void async_control_proc( void ); -static void queue_http_request_put( dap_http_simple_t *cl_sh ); - - -typedef struct dap_http_simple_url_proc { - - dap_http_simple_callback_t proc_callback; - size_t reply_size_max; - -} dap_http_simple_url_proc_t; - -//typedef struct tailq_entry { - -// dap_http_simple_t *cl_sh; -// TAILQ_ENTRY(tailq_entry) entries; - -//} tailq_entry_t; - -//TAILQ_HEAD(, tailq_entry) tailq_head; - -///DAP_HTTP_SIMPLE_REQUEST_MAX - -typedef struct user_agents_item { - dap_http_user_agent_ptr_t user_agent; - /* This is instead of "struct foo *next" */ - struct user_agents_item *next; -} user_agents_item_t; - -static user_agents_item_t *user_agents_list = NULL; -static bool is_unknown_user_agents_pass = false; - -#define DAP_HTTP_SIMPLE_URL_PROC(a) ((dap_http_simple_url_proc_t*) (a)->_inheritor) - -///static struct ev_loop* http_simple_loop; -///static ev_async async_watcher_http_simple; - -static pthread_mutex_t mutex_on_queue_http_response = PTHREAD_MUTEX_INITIALIZER; -static pthread_t http_simple_loop_thread; -static bool bSimpleLoopThreadQuitSignal = false; - -static dap_http_simple_t **s_requests = NULL; -static uint32_t s_requests_count = 0; - -// uint64_t s_TTL_session_key=3600; - -static void _free_user_agents_list( void ); - -int dap_http_simple_module_init( ) -{ - s_requests = DAP_NEW_Z_SIZE( dap_http_simple_t *, sizeof(dap_http_simple_t *) * DAP_HTTP_SIMPLE_REQUEST_MAX ); - if ( !s_requests ) { - - log_it( L_ERROR, "Out of memory" ); - return -1; - } - - s_requests_count = 0; - -// http_simple_loop = ev_loop_new(0); - -// TAILQ_INIT( &tailq_head ); - -// ev_async_init( &async_watcher_http_simple, async_control_proc ); -// ev_async_start( http_simple_loop, &async_watcher_http_simple ); - - bSimpleLoopThreadQuitSignal = false; - pthread_create( &http_simple_loop_thread, NULL, loop_http_simple_proc, NULL ); - - return 0; -} - -void dap_http_simple_module_deinit( void ) -{ -// ev_async_stop( http_simple_loop, &async_watcher_http_simple ); - - bSimpleLoopThreadQuitSignal = true; - - pthread_mutex_destroy( &mutex_on_queue_http_response ); - pthread_join( http_simple_loop_thread, NULL ); - -// ev_loop_destroy( http_simple_loop ); - _free_user_agents_list( ); - - if ( s_requests ) { - free( s_requests ); - s_requests = NULL; - } -} - -//static void async_control_proc( EV_P_ ev_async *w, int revents ) - -static void async_control_proc( void ) -{ - pthread_mutex_lock( &mutex_on_queue_http_response ); - - for ( uint32_t i = 0; i < s_requests_count; ++ i ) { - - dap_http_simple_proc( s_requests[i] ); - free( s_requests[i] ); - } - - s_requests_count = 0; - -// tailq_entry_t *item; - -// while ( item = TAILQ_FIRST(&tailq_head) ) { -// dap_http_simple_proc( item->cl_sh ); -// TAILQ_REMOVE( &tailq_head, item, entries ); -// free(item); -// } - - pthread_mutex_unlock( &mutex_on_queue_http_response ); -} - -#define SIMPLE_LOOP_SLEEP 250 // ms -static struct timespec simple_loop_sleep = { 0, SIMPLE_LOOP_SLEEP * 1000 * 1000 }; - -static void *loop_http_simple_proc( void *arg ) -{ - log_it( L_NOTICE, "Start loop http simple thread" ); - - return NULL; - do { - - #ifndef _WIN32 - nanosleep( &simple_loop_sleep, NULL ); - #else - Sleep( SIMPLE_LOOP_SLEEP ); - #endif - -/// async_control_proc( ); - - } while( !bSimpleLoopThreadQuitSignal ); - -// for ( i = 0; i < ui32TotalRequests; ++ i ) { - -// dap_http_simple_proc( pRequestsBuffer[i] ); -// free( pRequestsBuffer[i] ); -// } - - -// ev_loop( http_simple_loop, 0 ); - return NULL; -} - -/** - * @brief dap_http_simple_proc_add Add simple HTTP processor - * @param sh HTTP server instance - * @param url_path URL path - * @param cb Callback for data processing - */ -void dap_http_simple_proc_add( dap_http_t *sh, const char *url_path, size_t reply_size_max, dap_http_simple_callback_t cb ) -{ - dap_http_simple_url_proc_t *shs_up = DAP_NEW_Z( dap_http_simple_url_proc_t ); - - shs_up->proc_callback = cb; - shs_up->reply_size_max = reply_size_max; - - dap_http_add_proc( sh, url_path, - shs_up, // Internal structure - NULL, // Contrustor - NULL, // Destructor - dap_http_simple_headers_read, NULL, // Headers read, write - dap_http_simple_data_read, dap_http_simple_data_write, // Data read, write - NULL); // errror -} - -static void _free_user_agents_list() -{ - user_agents_item_t *elt, *tmp; - LL_FOREACH_SAFE( user_agents_list, elt, tmp ) { - LL_DELETE( user_agents_list, elt ); - dap_http_user_agent_delete( elt->user_agent ); - free( elt ); - } -} - -static bool _is_user_agent_supported( const char *user_agent ) -{ - bool result = is_unknown_user_agents_pass; - - dap_http_user_agent_ptr_t find_agent = dap_http_user_agent_new_from_str( user_agent ); - - if ( find_agent == NULL ) { - return result; - } - - const char* find_agent_name = dap_http_user_agent_get_name( find_agent ); - - user_agents_item_t *elt; - LL_FOREACH( user_agents_list, elt ) { - - const char* user_agent_name = dap_http_user_agent_get_name( elt->user_agent ); - - if ( strcmp(find_agent_name, user_agent_name) == 0) { - if(dap_http_user_agent_versions_compare(find_agent, elt->user_agent) >= 0) { - result = true; - goto END; - } - else { - result = false; - goto END; - } - } - } - -END: - dap_http_user_agent_delete( find_agent ); - return result; -} - -bool dap_http_simple_set_supported_user_agents( const char *user_agents, ... ) -{ - va_list argptr; - va_start( argptr, user_agents ); - - const char* str = user_agents; - -// log_it(L_DEBUG,"dap_http_simple_set_supported_user_agents"); -// Sleep(300); - - while ( str != NULL ) - { - dap_http_user_agent_ptr_t user_agent = dap_http_user_agent_new_from_str( str ); - - if ( user_agent == NULL ) { - log_it(L_ERROR, "Can't parse user agent string"); - _free_user_agents_list(); - return NULL; - } - - user_agents_item_t *item = calloc( 1, sizeof (user_agents_item_t) ); - - item->user_agent = user_agent; - LL_APPEND( user_agents_list, item ); - - str = va_arg( argptr, const char * ); - } - - va_end( argptr ); - - return true; -} - -// if this function was called. We checking version only supported user-agents -// other will pass automatically ( and request with without user-agents field too ) -void dap_http_simple_set_pass_unknown_user_agents(bool pass) -{ - is_unknown_user_agents_pass = pass; -} - -inline static bool _is_supported_user_agents_list_setted() -{ - user_agents_item_t * tmp; - int cnt = 0; - LL_COUNT(user_agents_list, tmp, cnt); - - return cnt; -} - -inline static void _set_only_write_http_client_state(dap_http_client_t* http_client) -{ -// log_it(L_DEBUG,"_set_only_write_http_client_state"); -// Sleep(300); - - dap_client_remote_ready_to_read(http_client->client,false); - http_client->state_write=DAP_HTTP_CLIENT_STATE_NONE; - - dap_client_remote_ready_to_write(http_client->client,true); - http_client->state_write=DAP_HTTP_CLIENT_STATE_START; -} - -static void _copy_reply_and_mime_to_response( dap_http_simple_t *cl_sh ) -{ -// log_it(L_DEBUG,"_copy_reply_and_mime_to_response"); -// Sleep(300); - - if( !cl_sh->reply_size ) { - - log_it( L_WARNING, " cl_sh->reply_size equal 0" ); - return; - } - - cl_sh->http->out_content_length = cl_sh->reply_size; - strcpy( cl_sh->http->out_content_type, cl_sh->reply_mime ); - return; -} - -inline static void _write_response_bad_request( dap_http_simple_t * cl_sh, - const char* error_msg ) -{ -// log_it(L_DEBUG,"_write_response_bad_request"); -// Sleep(300); - - struct json_object *jobj = json_object_new_object( ); - json_object_object_add( jobj, "error", json_object_new_string(error_msg) ); - - log_it( L_DEBUG, "error message %s", json_object_to_json_string(jobj) ); - cl_sh->http->reply_status_code = Http_Status_BadRequest; - - const char* json_str = json_object_to_json_string( jobj ); - dap_http_simple_reply(cl_sh, (void*) json_str, - (size_t) strlen(json_str) ); - - strcpy( cl_sh->reply_mime, "application/json" ); - - _copy_reply_and_mime_to_response( cl_sh ); - - json_object_put( jobj ); // free obj - _set_only_write_http_client_state( cl_sh->http ); -} - -/** - * @brief dap_http_simple_proc Execute procession callback and switch to write state - * @param cl_sh HTTP simple client instance - */ -void* dap_http_simple_proc( dap_http_simple_t *cl_sh ) -{ -// log_it(L_DEBUG, "dap http simple proc"); -// Sleep(300); - - http_status_code_t return_code = (http_status_code_t)0; - - if(_is_supported_user_agents_list_setted() == true) { - dap_http_header_t *header = dap_http_header_find(cl_sh->http->in_headers, "User-Agent"); - if(header == NULL && is_unknown_user_agents_pass == false) { - const char* error_msg = "Not found User-Agent HTTP header"; - _write_response_bad_request(cl_sh, error_msg); - return NULL; - } - - if(_is_user_agent_supported(header->value) == false) { - log_it(L_DEBUG, "Not supported user agent in request: %s", header->value); - const char* error_msg = "User-Agent version not supported. Update your software"; - _write_response_bad_request(cl_sh, error_msg); - return NULL; - } - } - - DAP_HTTP_SIMPLE_URL_PROC(cl_sh->http->proc)->proc_callback(cl_sh,&return_code); - - if(return_code) { - log_it(L_DEBUG, "Request was processed well"); - cl_sh->http->reply_status_code = (uint16_t)return_code; - _copy_reply_and_mime_to_response(cl_sh); - } else { - log_it(L_ERROR, "Request was processed with ERROR"); - cl_sh->http->reply_status_code = Http_Status_InternalServerError; - } - - _set_only_write_http_client_state(cl_sh->http); - return NULL; -} - -/** - * @brief dap_http_simple_headers_read Prepare reply on request - * @param cl_ht - * @param arg - */ -void dap_http_simple_headers_read( dap_http_client_t *cl_ht, void *arg ) -{ - cl_ht->_inheritor = DAP_NEW_Z( dap_http_simple_t ); - -// log_it(L_DEBUG,"dap_http_simple_headers_read"); -// Sleep(300); - - DAP_HTTP_SIMPLE(cl_ht)->http = cl_ht; - DAP_HTTP_SIMPLE(cl_ht)->reply_size_max = DAP_HTTP_SIMPLE_URL_PROC( cl_ht->proc )->reply_size_max; - DAP_HTTP_SIMPLE(cl_ht)->reply = calloc( 1, DAP_HTTP_SIMPLE(cl_ht)->reply_size_max ); - - if( cl_ht->in_content_length ) { - if( cl_ht->in_content_length < DAP_HTTP_SIMPLE_REQUEST_MAX ) - DAP_HTTP_SIMPLE(cl_ht)->request = calloc( 1, cl_ht->in_content_length + 1 ); - else - log_it( L_ERROR, "Too big content-length %u in request", cl_ht->in_content_length ); - } - else { - log_it( L_DEBUG, "No data section, execution proc callback" ); - queue_http_request_put( DAP_HTTP_SIMPLE(cl_ht) ); - } -} - -void dap_http_simple_data_read( dap_http_client_t *cl_ht, void * arg ) -{ - int *ret = (int *)arg; - -// log_it(L_DEBUG,"dap_http_simple_data_read"); -// Sleep(300); - - dap_http_simple_t *shs = DAP_HTTP_SIMPLE(cl_ht); - - size_t bytes_to_read = (cl_ht->client->buf_in_size + shs->request_size) < cl_ht->in_content_length ? - cl_ht->client->buf_in_size : ( cl_ht->in_content_length - shs->request_size ); - if( bytes_to_read ) { - memcpy( shs->request + shs->request_size, cl_ht->client->buf_in, bytes_to_read ); - shs->request_size += bytes_to_read; - } - - if( shs->request_size >= cl_ht->in_content_length ) { - - // bool isOK=true; - log_it( L_DEBUG,"Data collected" ); - queue_http_request_put( shs ); - } - - *ret = cl_ht->client->buf_in_size; -} - - -/** - * @brief dap_http_simple_data_write - * @param a_http_client - * @param a_arg - */ -void dap_http_simple_data_write( dap_http_client_t *a_http_client, void *a_arg ) -{ - (void) a_arg; - dap_http_simple_t *cl_st = DAP_HTTP_SIMPLE( a_http_client ); - -// log_it(L_DEBUG,"dap_http_simple_data_write"); -// Sleep(300); - - if ( !cl_st->reply ) { - - a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - log_it( L_WARNING, "No reply to write, close connection" ); - - return; - } - - cl_st->reply_sent += dap_client_remote_write( a_http_client->client, - cl_st->reply + cl_st->reply_sent, - a_http_client->out_content_length - cl_st->reply_sent ); - - if ( cl_st->reply_sent >= a_http_client->out_content_length ) { - log_it(L_INFO, "All the reply (%u) is sent out", a_http_client->out_content_length ); - //cl_ht->client->signal_close=cl_ht->keep_alive; - a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; - //dap_client_ready_to_write(cl_ht->client,false); - } - - free( cl_st->reply ); -} - -/** - * @brief dap_http_simple_reply Add data to the reply buffer - * @param shs HTTP simple client instance - * @param data - * @param data_size - */ -size_t dap_http_simple_reply( dap_http_simple_t *shs, void *data, size_t data_size ) -{ - size_t wb = (data_size > (shs->reply_size_max - shs->reply_size) ) ? (shs->reply_size_max - shs->reply_size) : data_size; - - memcpy( shs->reply + shs->reply_size, data, wb ); - shs->reply_size += wb; - - return wb; -} - -/** - * @brief dap_http_simple_reply_f - * @param shs - * @param data - */ -size_t dap_http_simple_reply_f( dap_http_simple_t * shs, const char * data, ... ) -{ - char buf[4096]; - va_list va; - int vret; - - va_start(va,data); - vret = vsnprintf( buf, sizeof(buf) - 1, data, va ); - va_end(va); - - if ( vret > 0 ) - return dap_http_simple_reply( shs, buf, vret ); - else - return 0; -} - -inline void queue_http_request_put( dap_http_simple_t *cl_sh ) -{ - dap_http_simple_proc( cl_sh ); - - return; - - pthread_mutex_lock( &mutex_on_queue_http_response ); - -// tailq_entry_t *item = malloc (sizeof(tailq_entry_t)); -// item->cl_sh = cl_sh; -// TAILQ_INSERT_TAIL(&tailq_head, item, entries); - - if ( s_requests_count >= DAP_HTTP_SIMPLE_REQUEST_MAX ) { - - log_it( L_NOTICE, "Requests Buffer is FULL( %u ) ignore request" ); - pthread_mutex_unlock( &mutex_on_queue_http_response ); - return; - } - - log_it( L_WARNING, "queue_http_request_put >>> %u", s_requests_count ); - - s_requests[ s_requests_count ++ ] = cl_sh; - - pthread_mutex_unlock( &mutex_on_queue_http_response ); - -// ev_async_send( http_simple_loop, &async_watcher_http_simple ); -} - -/* Key Expired deprecated code */ - -// bool key_is_expiried = false; - -// dap_enc_key_t * key = dap_enc_ks_find_http(cl_sh->http); -// if(key){ -// if( key->last_used_timestamp && ( (time(NULL) - key->last_used_timestamp ) -// > s_TTL_session_key ) ) { - -// enc_http_delegate_t * dg = enc_http_request_decode(cl_sh); - -// if( dg == NULL ) { -// log_it(L_ERROR, "dg is NULL"); -// return NULL; -// } - -// log_it(L_WARNING, "Key has been expiried"); -// strcpy(cl_sh->reply_mime,"text/plain"); -// enc_http_reply_f(dg,"Key has been expiried"); -// enc_http_reply_encode(cl_sh,dg); -// enc_http_delegate_delete(dg); -// key_is_expiried = true; -// } else{ -// key->last_used_timestamp = time(NULL); -// } -// } +/* + * Authors: + * Dmitriy A. Gearasimov <kahovski@gmail.com> + * Anatolii Kurotych <akurotych@gmail.com> + * DeM Labs Inc. https://demlabs.net + * DeM Labs Open source community https://github.com/kelvinblockchain + * 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 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 <stdio.h> +#include <stdarg.h> +#include <stdbool.h> +#include <string.h> +#include <stdint.h> +#include <time.h> + +#ifndef _WIN32 +//#include <ev.h> +#include <sys/queue.h> +#include <utlist.h> +#else +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#include <winsock2.h> +#include <windows.h> +#include <mswsock.h> +#include <ws2tcpip.h> +#include <io.h> +#include "wrappers.h" +#include <wepoll.h> +#include <pthread.h> +#endif + +#include <json-c/json.h> + +#include "dap_common.h" +#include "dap_config.h" +#include "dap_http.h" +#include "dap_http_client.h" +#include "dap_http_simple.h" +#include "dap_enc_key.h" +#include "dap_http_user_agent.h" + +#include "../enc_server/dap_enc_ks.h" +#include "../enc_server/dap_enc_http.h" + +#include "http_status_code.h" + +#define LOG_TAG "dap_http_simple" + +void dap_http_simple_headers_read( dap_http_client_t *cl_ht, void *arg ); +void dap_http_simple_data_write( dap_http_client_t *a_http_client, void *a_arg ); +void dap_http_simple_data_read( dap_http_client_t * cl_ht, void *arg ); +void *dap_http_simple_proc( dap_http_simple_t * cl_sh ); + +static void *loop_http_simple_proc( void *arg ); + +static void async_control_proc( void ); +static void queue_http_request_put( dap_http_simple_t *cl_sh ); + + +typedef struct dap_http_simple_url_proc { + + dap_http_simple_callback_t proc_callback; + size_t reply_size_max; + +} dap_http_simple_url_proc_t; + +//typedef struct tailq_entry { + +// dap_http_simple_t *cl_sh; +// TAILQ_ENTRY(tailq_entry) entries; + +//} tailq_entry_t; + +//TAILQ_HEAD(, tailq_entry) tailq_head; + +///DAP_HTTP_SIMPLE_REQUEST_MAX + +typedef struct user_agents_item { + dap_http_user_agent_ptr_t user_agent; + /* This is instead of "struct foo *next" */ + struct user_agents_item *next; +} user_agents_item_t; + +static user_agents_item_t *user_agents_list = NULL; +static bool is_unknown_user_agents_pass = false; + +#define DAP_HTTP_SIMPLE_URL_PROC(a) ((dap_http_simple_url_proc_t*) (a)->_inheritor) + +///static struct ev_loop* http_simple_loop; +///static ev_async async_watcher_http_simple; + +static pthread_mutex_t mutex_on_queue_http_response = PTHREAD_MUTEX_INITIALIZER; +static pthread_t http_simple_loop_thread; +static bool bSimpleLoopThreadQuitSignal = false; + +static dap_http_simple_t **s_requests = NULL; +static dap_http_simple_t **s_requestsproc = NULL; + +static uint32_t s_requests_count = 0; +static uint32_t s_requestsproc_count = 0; + +static void _free_user_agents_list( void ); + +int dap_http_simple_module_init( ) +{ + s_requests = (dap_http_simple_t *)malloc( sizeof(dap_http_simple_t *) * DAP_HTTP_SIMPLE_REQUEST_MAX * 2 ); + if ( !s_requests ) { + + log_it( L_ERROR, "Out of memory" ); + return -1; + } + + s_requestsproc = s_requests + DAP_HTTP_SIMPLE_REQUEST_MAX; + s_requests_count = 0; + + bSimpleLoopThreadQuitSignal = false; + pthread_create( &http_simple_loop_thread, NULL, loop_http_simple_proc, NULL ); + + return 0; +} + +void dap_http_simple_module_deinit( void ) +{ + bSimpleLoopThreadQuitSignal = true; + + pthread_mutex_destroy( &mutex_on_queue_http_response ); + pthread_join( http_simple_loop_thread, NULL ); + + _free_user_agents_list( ); + + if ( s_requests ) { + free( s_requests ); + s_requests = NULL; + } +} + +//#define SIMPLE_LOOP_SLEEP 25 // ms +#define SIMPLE_LOOP_SLEEP 50 // ms + +static struct timespec simple_loop_sleep = { 0, SIMPLE_LOOP_SLEEP * 1000 * 1000 }; + +static void *loop_http_simple_proc( void *arg ) +{ + log_it( L_NOTICE, "Start loop http simple thread" ); + + do { + + pthread_mutex_lock( &mutex_on_queue_http_response ); + if ( s_requests_count ) { + + s_requestsproc_count = s_requests_count; + s_requests_count = 0; + memcpy( s_requestsproc, s_requests, sizeof(void *) * s_requestsproc_count ); + pthread_mutex_unlock( &mutex_on_queue_http_response ); + + for ( uint32_t i = 0; i < s_requestsproc_count; ++ i ) { + dap_http_simple_proc( s_requestsproc[i] ); +// s_requestsproc[i]->http->client->no_close = false; +// free( s_requestsproc[i] ); // ??? + } + } + else { + pthread_mutex_unlock( &mutex_on_queue_http_response ); + #ifndef _WIN32 + nanosleep( &simple_loop_sleep, NULL ); + #else + Sleep( SIMPLE_LOOP_SLEEP ); + #endif + } + + } while( !bSimpleLoopThreadQuitSignal ); + + return NULL; +} + +/** + * @brief dap_http_simple_proc_add Add simple HTTP processor + * @param sh HTTP server instance + * @param url_path URL path + * @param cb Callback for data processing + */ +void dap_http_simple_proc_add( dap_http_t *sh, const char *url_path, size_t reply_size_max, dap_http_simple_callback_t cb ) +{ + dap_http_simple_url_proc_t *shs_up = DAP_NEW_Z( dap_http_simple_url_proc_t ); + + shs_up->proc_callback = cb; + shs_up->reply_size_max = reply_size_max; + + dap_http_add_proc( sh, url_path, + shs_up, // Internal structure + NULL, // Contrustor + NULL, // Destructor + dap_http_simple_headers_read, NULL, // Headers read, write + dap_http_simple_data_read, dap_http_simple_data_write, // Data read, write + NULL); // errror +} + +static void _free_user_agents_list() +{ + user_agents_item_t *elt, *tmp; + LL_FOREACH_SAFE( user_agents_list, elt, tmp ) { + LL_DELETE( user_agents_list, elt ); + dap_http_user_agent_delete( elt->user_agent ); + free( elt ); + } +} + +static bool _is_user_agent_supported( const char *user_agent ) +{ + bool result = is_unknown_user_agents_pass; + + dap_http_user_agent_ptr_t find_agent = dap_http_user_agent_new_from_str( user_agent ); + + if ( find_agent == NULL ) { + return result; + } + + const char* find_agent_name = dap_http_user_agent_get_name( find_agent ); + + user_agents_item_t *elt; + LL_FOREACH( user_agents_list, elt ) { + + const char* user_agent_name = dap_http_user_agent_get_name( elt->user_agent ); + + if ( strcmp(find_agent_name, user_agent_name) == 0) { + if(dap_http_user_agent_versions_compare(find_agent, elt->user_agent) >= 0) { + result = true; + goto END; + } + else { + result = false; + goto END; + } + } + } + +END: + dap_http_user_agent_delete( find_agent ); + return result; +} + +bool dap_http_simple_set_supported_user_agents( const char *user_agents, ... ) +{ + va_list argptr; + va_start( argptr, user_agents ); + + const char* str = user_agents; + +// log_it(L_DEBUG,"dap_http_simple_set_supported_user_agents"); +// Sleep(300); + + while ( str != NULL ) + { + dap_http_user_agent_ptr_t user_agent = dap_http_user_agent_new_from_str( str ); + + if ( user_agent == NULL ) { + log_it(L_ERROR, "Can't parse user agent string"); + _free_user_agents_list(); + return NULL; + } + + user_agents_item_t *item = calloc( 1, sizeof (user_agents_item_t) ); + + item->user_agent = user_agent; + LL_APPEND( user_agents_list, item ); + + str = va_arg( argptr, const char * ); + } + + va_end( argptr ); + + return true; +} + +// if this function was called. We checking version only supported user-agents +// other will pass automatically ( and request with without user-agents field too ) +void dap_http_simple_set_pass_unknown_user_agents(bool pass) +{ + is_unknown_user_agents_pass = pass; +} + +inline static bool _is_supported_user_agents_list_setted() +{ + user_agents_item_t * tmp; + int cnt = 0; + LL_COUNT(user_agents_list, tmp, cnt); + + return cnt; +} + +inline static void _set_only_write_http_client_state(dap_http_client_t* http_client) +{ +// log_it(L_DEBUG,"_set_only_write_http_client_state"); +// Sleep(300); + + dap_client_remote_ready_to_read(http_client->client,false); + http_client->state_write=DAP_HTTP_CLIENT_STATE_NONE; + + dap_client_remote_ready_to_write(http_client->client,true); + http_client->state_write=DAP_HTTP_CLIENT_STATE_START; +} + +static void _copy_reply_and_mime_to_response( dap_http_simple_t *cl_sh ) +{ +// log_it(L_DEBUG,"_copy_reply_and_mime_to_response"); +// Sleep(300); + + if( !cl_sh->reply_size ) { + + log_it( L_WARNING, " cl_sh->reply_size equal 0" ); + return; + } + + cl_sh->http->out_content_length = cl_sh->reply_size; + strcpy( cl_sh->http->out_content_type, cl_sh->reply_mime ); + return; +} + +inline static void _write_response_bad_request( dap_http_simple_t * cl_sh, + const char* error_msg ) +{ +// log_it(L_DEBUG,"_write_response_bad_request"); +// Sleep(300); + + struct json_object *jobj = json_object_new_object( ); + json_object_object_add( jobj, "error", json_object_new_string(error_msg) ); + + log_it( L_DEBUG, "error message %s", json_object_to_json_string(jobj) ); + cl_sh->http->reply_status_code = Http_Status_BadRequest; + + const char* json_str = json_object_to_json_string( jobj ); + dap_http_simple_reply(cl_sh, (void*) json_str, + (size_t) strlen(json_str) ); + + strcpy( cl_sh->reply_mime, "application/json" ); + + _copy_reply_and_mime_to_response( cl_sh ); + + json_object_put( jobj ); // free obj + _set_only_write_http_client_state( cl_sh->http ); +} + +/** + * @brief dap_http_simple_proc Execute procession callback and switch to write state + * @param cl_sh HTTP simple client instance + */ +void* dap_http_simple_proc( dap_http_simple_t *cl_sh ) +{ +// log_it(L_DEBUG, "dap http simple proc"); +// Sleep(300); + + http_status_code_t return_code = (http_status_code_t)0; + + if(_is_supported_user_agents_list_setted() == true) { + dap_http_header_t *header = dap_http_header_find(cl_sh->http->in_headers, "User-Agent"); + if(header == NULL && is_unknown_user_agents_pass == false) { + const char* error_msg = "Not found User-Agent HTTP header"; + _write_response_bad_request(cl_sh, error_msg); + return NULL; + } + + if(_is_user_agent_supported(header->value) == false) { + log_it(L_DEBUG, "Not supported user agent in request: %s", header->value); + const char* error_msg = "User-Agent version not supported. Update your software"; + _write_response_bad_request(cl_sh, error_msg); + return NULL; + } + } + + DAP_HTTP_SIMPLE_URL_PROC(cl_sh->http->proc)->proc_callback(cl_sh,&return_code); + + if(return_code) { + log_it(L_DEBUG, "Request was processed well"); + cl_sh->http->reply_status_code = (uint16_t)return_code; + _copy_reply_and_mime_to_response(cl_sh); + } else { + log_it(L_ERROR, "Request was processed with ERROR"); + cl_sh->http->reply_status_code = Http_Status_InternalServerError; + } + + _set_only_write_http_client_state(cl_sh->http); + return NULL; +} + +/** + * @brief dap_http_simple_headers_read Prepare reply on request + * @param cl_ht + * @param arg + */ +void dap_http_simple_headers_read( dap_http_client_t *cl_ht, void *arg ) +{ + cl_ht->_inheritor = DAP_NEW_Z( dap_http_simple_t ); + +// log_it(L_DEBUG,"dap_http_simple_headers_read"); +// Sleep(300); + + DAP_HTTP_SIMPLE(cl_ht)->http = cl_ht; + DAP_HTTP_SIMPLE(cl_ht)->reply_size_max = DAP_HTTP_SIMPLE_URL_PROC( cl_ht->proc )->reply_size_max; + DAP_HTTP_SIMPLE(cl_ht)->reply = calloc( 1, DAP_HTTP_SIMPLE(cl_ht)->reply_size_max ); + + if( cl_ht->in_content_length ) { + if( cl_ht->in_content_length < DAP_HTTP_SIMPLE_REQUEST_MAX ) + DAP_HTTP_SIMPLE(cl_ht)->request = calloc( 1, cl_ht->in_content_length + 1 ); + else + log_it( L_ERROR, "Too big content-length %u in request", cl_ht->in_content_length ); + } + else { + log_it( L_DEBUG, "No data section, execution proc callback" ); + queue_http_request_put( DAP_HTTP_SIMPLE(cl_ht) ); + } +} + +void dap_http_simple_data_read( dap_http_client_t *cl_ht, void * arg ) +{ + int *ret = (int *)arg; + +// log_it(L_DEBUG,"dap_http_simple_data_read"); +// Sleep(300); + + dap_http_simple_t *shs = DAP_HTTP_SIMPLE(cl_ht); + + size_t bytes_to_read = (cl_ht->client->buf_in_size + shs->request_size) < cl_ht->in_content_length ? + cl_ht->client->buf_in_size : ( cl_ht->in_content_length - shs->request_size ); + if( bytes_to_read ) { + memcpy( shs->request + shs->request_size, cl_ht->client->buf_in, bytes_to_read ); + shs->request_size += bytes_to_read; + } + + if( shs->request_size >= cl_ht->in_content_length ) { + + // bool isOK=true; + log_it( L_DEBUG,"Data collected" ); + queue_http_request_put( shs ); + } + + *ret = cl_ht->client->buf_in_size; +} + + +/** + * @brief dap_http_simple_data_write + * @param a_http_client + * @param a_arg + */ +void dap_http_simple_data_write( dap_http_client_t *a_http_client, void *a_arg ) +{ + (void) a_arg; + dap_http_simple_t *cl_st = DAP_HTTP_SIMPLE( a_http_client ); + +// log_it(L_DEBUG,"dap_http_simple_data_write"); +// Sleep(300); + + if ( !cl_st->reply ) { + + a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; + log_it( L_WARNING, "No reply to write, close connection" ); + + return; + } + + cl_st->reply_sent += dap_client_remote_write( a_http_client->client, + cl_st->reply + cl_st->reply_sent, + a_http_client->out_content_length - cl_st->reply_sent ); + + if ( cl_st->reply_sent >= a_http_client->out_content_length ) { + log_it(L_INFO, "All the reply (%u) is sent out", a_http_client->out_content_length ); + //cl_ht->client->signal_close=cl_ht->keep_alive; + a_http_client->client->flags |= DAP_SOCK_SIGNAL_CLOSE; + //dap_client_ready_to_write(cl_ht->client,false); + } + + free( cl_st->reply ); +} + +/** + * @brief dap_http_simple_reply Add data to the reply buffer + * @param shs HTTP simple client instance + * @param data + * @param data_size + */ +size_t dap_http_simple_reply( dap_http_simple_t *shs, void *data, size_t data_size ) +{ + size_t wb = (data_size > (shs->reply_size_max - shs->reply_size) ) ? (shs->reply_size_max - shs->reply_size) : data_size; + + memcpy( shs->reply + shs->reply_size, data, wb ); + shs->reply_size += wb; + + return wb; +} + +/** + * @brief dap_http_simple_reply_f + * @param shs + * @param data + */ +size_t dap_http_simple_reply_f( dap_http_simple_t * shs, const char * data, ... ) +{ + char buf[4096]; + va_list va; + int vret; + + va_start(va,data); + vret = vsnprintf( buf, sizeof(buf) - 1, data, va ); + va_end(va); + + if ( vret > 0 ) + return dap_http_simple_reply( shs, buf, vret ); + else + return 0; +} + +inline void queue_http_request_put( dap_http_simple_t *cl_sh ) +{ +// dap_http_simple_proc( cl_sh ); + + pthread_mutex_lock( &mutex_on_queue_http_response ); + + if ( s_requests_count >= DAP_HTTP_SIMPLE_REQUEST_MAX ) { + + log_it( L_NOTICE, "Requests Buffer is FULL( %u ) ignore request" ); + pthread_mutex_unlock( &mutex_on_queue_http_response ); + return; + } + + log_it( L_WARNING, "queue_http_request_put >>> %u", s_requests_count ); + + s_requests[ s_requests_count ++ ] = cl_sh; +// cl_sh->http->client->no_close = true; + + pthread_mutex_unlock( &mutex_on_queue_http_response ); +} + +/* Key Expired deprecated code */ + +// bool key_is_expiried = false; + +// dap_enc_key_t * key = dap_enc_ks_find_http(cl_sh->http); +// if(key){ +// if( key->last_used_timestamp && ( (time(NULL) - key->last_used_timestamp ) +// > s_TTL_session_key ) ) { + +// enc_http_delegate_t * dg = enc_http_request_decode(cl_sh); + +// if( dg == NULL ) { +// log_it(L_ERROR, "dg is NULL"); +// return NULL; +// } + +// log_it(L_WARNING, "Key has been expiried"); +// strcpy(cl_sh->reply_mime,"text/plain"); +// enc_http_reply_f(dg,"Key has been expiried"); +// enc_http_reply_encode(cl_sh,dg); +// enc_http_delegate_delete(dg); +// key_is_expiried = true; +// } else{ +// key->last_used_timestamp = time(NULL); +// } +// } diff --git a/http_server/dap_http_simple.h b/http_server/dap_http_simple.h index b7f2ac6..a71fb8c 100755 --- a/http_server/dap_http_simple.h +++ b/http_server/dap_http_simple.h @@ -1,80 +1,80 @@ -/* - 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_HTTP_SIMPLE_H_ -#define _DAP_HTTP_SIMPLE_H_ - -#include <stddef.h> -#include "dap_http.h" - -//#define DAP_HTTP_SIMPLE_REQUEST_MAX 100000 - -#define DAP_HTTP_SIMPLE_REQUEST_MAX 65536 - -struct dap_http_simple; -typedef void ( *dap_http_simple_callback_t )( struct dap_http_simple *, void * ); - -typedef struct dap_http_simple { - - dap_http_client_t *http; - - union { - void *request; - char *request_str; - }; - - union { - void *reply; - char *reply_str; - }; - - size_t request_size; - size_t reply_size; - size_t reply_size_max; - size_t reply_sent; - - char reply_mime[256]; - - // dap_http_simple_callback_t reply_proc_post_callback; -} dap_http_simple_t; - -#define DAP_HTTP_SIMPLE(a) ((dap_http_simple_t*) (a)->_inheritor ) - -void dap_http_simple_proc_add( dap_http_t *sh, const char *url_path, size_t reply_size_max, dap_http_simple_callback_t cb ); // Add simple processor -int dap_http_simple_module_init( void ); -void dap_http_simple_module_deinit(void); - -// input string must match NameClient/MiminalVersion -// For example DapClient/2.2 -// If this function was not called. All user agents will supported by default -// ATTENTION: Last parameter must be NULL -// example call: dap_http_simple_set_supported_user_agents("DapVpnClient/2.2", "Mozila/5.0", NULL); -// returns false if operation not successful -bool dap_http_simple_set_supported_user_agents( const char *str_agents, ... ); - -// if this function was called. We checking version only supported user-agents -// other will pass automatically ( and request with without user-agents field too ) -// Affects the behavior of the internal function _is_user_agent_supported -void dap_http_simple_set_pass_unknown_user_agents( bool pass ); - -size_t dap_http_simple_reply( dap_http_simple_t *shs, void *data, size_t data_size ); -size_t dap_http_simple_reply_f( dap_http_simple_t *shs, const char *data, ... ); - -#endif +/* + 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_HTTP_SIMPLE_H_ +#define _DAP_HTTP_SIMPLE_H_ + +#include <stddef.h> +#include "dap_http.h" + +//#define DAP_HTTP_SIMPLE_REQUEST_MAX 100000 + +#define DAP_HTTP_SIMPLE_REQUEST_MAX 65536 + +struct dap_http_simple; +typedef void ( *dap_http_simple_callback_t )( struct dap_http_simple *, void * ); + +typedef struct dap_http_simple { + + dap_http_client_t *http; + + union { + void *request; + char *request_str; + }; + + union { + void *reply; + char *reply_str; + }; + + size_t request_size; + size_t reply_size; + size_t reply_size_max; + size_t reply_sent; + + char reply_mime[256]; + + // dap_http_simple_callback_t reply_proc_post_callback; +} dap_http_simple_t; + +#define DAP_HTTP_SIMPLE(a) ((dap_http_simple_t*) (a)->_inheritor ) + +void dap_http_simple_proc_add( dap_http_t *sh, const char *url_path, size_t reply_size_max, dap_http_simple_callback_t cb ); // Add simple processor +int dap_http_simple_module_init( void ); +void dap_http_simple_module_deinit(void); + +// input string must match NameClient/MiminalVersion +// For example DapClient/2.2 +// If this function was not called. All user agents will supported by default +// ATTENTION: Last parameter must be NULL +// example call: dap_http_simple_set_supported_user_agents("DapVpnClient/2.2", "Mozila/5.0", NULL); +// returns false if operation not successful +bool dap_http_simple_set_supported_user_agents( const char *str_agents, ... ); + +// if this function was called. We checking version only supported user-agents +// other will pass automatically ( and request with without user-agents field too ) +// Affects the behavior of the internal function _is_user_agent_supported +void dap_http_simple_set_pass_unknown_user_agents( bool pass ); + +size_t dap_http_simple_reply( dap_http_simple_t *shs, void *data, size_t data_size ); +size_t dap_http_simple_reply_f( dap_http_simple_t *shs, const char *data, ... ); + +#endif -- GitLab