diff --git a/http_server/dap_http.c b/http_server/dap_http.c index e66df7833e5741ecd73bca902d74c6c4d609e066..eb66d5e732d6646b317190d7748f0b639e732624 100755 --- a/http_server/dap_http.c +++ b/http_server/dap_http.c @@ -18,6 +18,12 @@ 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> @@ -25,16 +31,24 @@ #include <sys/types.h> #include <sys/stat.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> - #include <unistd.h> #include <fcntl.h> #include <errno.h> -#include <string.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" @@ -45,7 +59,6 @@ #include "dap_http_header.h" #include "dap_http_client.h" - #define LOG_TAG "dap_http" @@ -53,18 +66,20 @@ * @brief dap_http_init // Init HTTP module * @return Zero if ok others if not */ -int dap_http_init() +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; + 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; } /** @@ -72,33 +87,32 @@ int dap_http_init() */ void dap_http_deinit() { - dap_http_header_deinit(); - dap_http_client_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) +int dap_http_new( dap_server_t *sh, const char * server_name ) { - sh->_inheritor= calloc(1,sizeof(dap_http_t)); + sh->_inheritor = calloc( 1, sizeof(dap_http_t) ); - dap_http_t *shttp = DAP_HTTP(sh); + dap_http_t *shttp = DAP_HTTP( sh ); - shttp->server=sh; - strncpy(shttp->server_name,server_name,sizeof(shttp->server_name)-1); + 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; + 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; + return 0; } /** @@ -106,20 +120,19 @@ int dap_http_new(dap_server_t *sh, const char * server_name) * @param sh Server's instance * @param arg Non-used argument */ -void dap_http_delete(dap_server_t *sh,void * arg) +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); - } - + (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 ); + } } @@ -131,7 +144,7 @@ void dap_http_delete(dap_server_t *sh,void * arg) * @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 +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 @@ -142,18 +155,24 @@ void dap_http_add_proc(dap_http_t * sh, const char * url_path, void * internal ) { - 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); + 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 115c88ce1bbe43887e8b339336469f8bc10eed24..13d3a7071c78b5ca96c6a276f85c50bf0af137ad 100755 --- a/http_server/dap_http.h +++ b/http_server/dap_http.h @@ -47,26 +47,26 @@ typedef struct dap_http_url_proc{ dap_http_client_callback_t access_callback; - void * _inheritor; // Internal data specific to the current URL processor + 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; + 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_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 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 +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 diff --git a/http_server/dap_http_folder.c b/http_server/dap_http_folder.c index f93946ff2a0327e34db6f6a6003b3729ccfbde94..0cc8d2960c62567d82c011d5bb40e562b444d467 100755 --- a/http_server/dap_http_folder.c +++ b/http_server/dap_http_folder.c @@ -18,13 +18,28 @@ 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 <stdio.h> -#include <magic.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" @@ -33,84 +48,109 @@ #include "dap_http_folder.h" #include "http_status_code.h" - -typedef struct dap_http_url_proc_folder{ +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_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); - +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() +int dap_http_folder_init( ) { return 0; } -void dap_http_folder_deinit() +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) +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; - } - DIR * dirptr = opendir(local_path); - if (dirptr == NULL) { - log_it(L_ERROR,"Directory Not Found!"); - return -11; - }else{ - log_it(L_NOTICE, "File service for %s => %s ",url_path,local_path); - closedir(dirptr); - } - - 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; - } - - /* if( 0!= magic_load(up_folder->mime_detector, NULL)){ - 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); + 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; } @@ -128,56 +168,111 @@ void dap_http_folder_headers_read(dap_http_client_t * cl_ht, void * arg) 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 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); - - struct stat file_stat; - if(stat(cl_ht_file->local_path,&file_stat)==0){ - cl_ht->out_last_modified=file_stat.st_mtime; - cl_ht->out_content_length=file_stat.st_size; - cl_ht_file->fd=fopen(cl_ht_file->local_path,"r"); - 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->signal_close=true; - log_it(L_WARNING,"Can't detect MIME type of %s file: %s",cl_ht_file->local_path,magic_error(up_folder->mime_detector)); - } - } - - }else{ - 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)); + (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->signal_close=true; + 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; } /** diff --git a/http_server/dap_http_simple.c b/http_server/dap_http_simple.c index 695f6c412b340cd6b107bf59a5dc7e89d64f84e6..ad656d530ab9db2954464c5cd430bfca92d0c5ea 100755 --- a/http_server/dap_http_simple.c +++ b/http_server/dap_http_simple.c @@ -9,24 +9,45 @@ 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/>. + 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" @@ -35,41 +56,47 @@ #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" -#include <ev.h> -#include <sys/queue.h> -#include <utlist.h> -#include <json-c/json.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); +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 ); -static void* loop_http_simple_proc(void *arg); -static void async_control_proc (EV_P_ ev_async *w, int revents); -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_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; +//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; + 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; @@ -77,58 +104,117 @@ 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 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 **pRequestsBuffer = NULL; +static uint32_t ui32TotalRequests = 0; // uint64_t s_TTL_session_key=3600; -static void _free_user_agents_list(void); +static void _free_user_agents_list( void ); -int dap_http_simple_module_init() +int dap_http_simple_module_init( ) { - http_simple_loop = ev_loop_new(0); + pRequestsBuffer = (dap_http_simple_t *) malloc( sizeof(dap_http_simple_t *) * DAP_HTTP_SIMPLE_REQUEST_MAX ); + if ( !pRequestsBuffer ) { - TAILQ_INIT(&tailq_head); + log_it( L_ERROR, "Out of memory" ); + return -1; + } - ev_async_init(&async_watcher_http_simple, async_control_proc); - ev_async_start(http_simple_loop, &async_watcher_http_simple); - pthread_create(&http_simple_loop_thread, NULL, loop_http_simple_proc, NULL); + ui32TotalRequests = 0; - return 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) +void dap_http_simple_module_deinit( void ) { - ev_async_stop(http_simple_loop, &async_watcher_http_simple); - 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(); +// 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 ( pRequestsBuffer ) { + free( pRequestsBuffer ); + pRequestsBuffer = NULL; + } } -static void async_control_proc (EV_P_ ev_async *w, int revents) +//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); + pthread_mutex_lock( &mutex_on_queue_http_response ); - 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); - } + for ( uint32_t i = 0; i < ui32TotalRequests; ++ i ) { + + dap_http_simple_proc( pRequestsBuffer[i] ); + free( pRequestsBuffer[i] ); + } + + ui32TotalRequests = 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); + pthread_mutex_unlock( &mutex_on_queue_http_response ); } -static void* loop_http_simple_proc(void *arg) +#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"); - ev_loop(http_simple_loop, 0); - return NULL; -} + 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 @@ -136,85 +222,97 @@ static void* loop_http_simple_proc(void *arg) * @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) +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,NULL, // Contrustor, Destructor - dap_http_simple_headers_read,NULL, // Headers read,write + 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); - } + 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) +static bool _is_user_agent_supported( const char *user_agent ) { - bool result = is_unknown_user_agents_pass; + 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; - } - } + 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; + dap_http_user_agent_delete( find_agent ); + return result; } -bool dap_http_simple_set_supported_user_agents(const char *user_agents, ...) +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; - 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); + va_list argptr; + va_start( argptr, user_agents ); + + const char* str = user_agents; - str = va_arg( argptr, const char* ); +// 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; } - va_end(argptr); - return true; + 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 @@ -226,60 +324,73 @@ void dap_http_simple_set_pass_unknown_user_agents(bool 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); + user_agents_item_t * tmp; + int cnt = 0; + LL_COUNT(user_agents_list, tmp, cnt); - return cnt; + return cnt; } inline static void _set_only_write_http_client_state(dap_http_client_t* http_client) { - dap_client_remote_ready_to_read(http_client->client,false); - http_client->state_write=DAP_HTTP_CLIENT_STATE_NONE; +// 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; + 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) +static void _copy_reply_and_mime_to_response( dap_http_simple_t *cl_sh ) { - if(cl_sh->reply_size != 0) { - cl_sh->http->out_content_length = cl_sh->reply_size; - strcpy(cl_sh->http->out_content_type, cl_sh->reply_mime); - return; - } - log_it(L_WARNING, "cl_sh->reply_size equal 0"); +// 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) +inline static void _write_response_bad_request( dap_http_simple_t * cl_sh, + const char* error_msg ) { - struct json_object *jobj = json_object_new_object(); - json_object_object_add(jobj, "error", json_object_new_string(error_msg)); +// log_it(L_DEBUG,"_write_response_bad_request"); +// Sleep(300); - log_it(L_DEBUG, "error message %s", json_object_to_json_string(jobj)); - cl_sh->http->reply_status_code = Http_Status_BadRequest; + struct json_object *jobj = json_object_new_object( ); + json_object_object_add( jobj, "error", json_object_new_string(error_msg) ); - const char* json_str = json_object_to_json_string(jobj); - dap_http_simple_reply(cl_sh, (void*) json_str, - (size_t) strlen(json_str)); + log_it( L_DEBUG, "error message %s", json_object_to_json_string(jobj) ); + cl_sh->http->reply_status_code = Http_Status_BadRequest; - strcpy(cl_sh->reply_mime, "application/json"); + const char* json_str = json_object_to_json_string( jobj ); + dap_http_simple_reply(cl_sh, (void*) json_str, + (size_t) strlen(json_str) ); - _copy_reply_and_mime_to_response(cl_sh); + strcpy( cl_sh->reply_mime, "application/json" ); - json_object_put(jobj); // free obj - _set_only_write_http_client_state(cl_sh->http); + _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) +void* dap_http_simple_proc( dap_http_simple_t *cl_sh ) { - log_it(L_DEBUG, "dap http simple proc"); +// log_it(L_DEBUG, "dap http simple proc"); +// Sleep(300); http_status_code_t return_code = (http_status_code_t)0; @@ -319,48 +430,53 @@ void* dap_http_simple_proc(dap_http_simple_t * cl_sh) * @param cl_ht * @param arg */ -void dap_http_simple_headers_read(dap_http_client_t * cl_ht, void * 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); - - 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); - } + 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_DEBUG,"No data section, execution proc callback"); - queue_http_request_put(DAP_HTTP_SIMPLE(cl_ht)); - } + 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) +void dap_http_simple_data_read( dap_http_client_t *cl_ht, void * arg ) { - int *ret= (int*) arg; - - 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; + 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; } @@ -369,28 +485,34 @@ void dap_http_simple_data_read(dap_http_client_t * cl_ht,void * arg) * @param a_http_client * @param a_arg */ -void dap_http_simple_data_write(dap_http_client_t * a_http_client,void * 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); + (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 ) { - cl_st->reply_sent += dap_client_remote_write(a_http_client->client, + if ( !cl_st->reply ) { + + a_http_client->client->signal_close = true; + 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); + 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->signal_close=true; - //dap_client_ready_to_write(cl_ht->client,false); - } + 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->signal_close = true; + //dap_client_ready_to_write(cl_ht->client,false); + } - free(cl_st->reply); - }else{ - a_http_client->client->signal_close=true; - log_it(L_WARNING,"No reply to write, close connection"); - } + free( cl_st->reply ); } /** @@ -399,12 +521,14 @@ void dap_http_simple_data_write(dap_http_client_t * a_http_client,void * a_arg) * @param data * @param data_size */ -size_t dap_http_simple_reply(dap_http_simple_t * shs, void * data, size_t 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; + 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; } /** @@ -412,29 +536,48 @@ size_t dap_http_simple_reply(dap_http_simple_t * shs, void * data, size_t data_s * @param shs * @param data */ -size_t dap_http_simple_reply_f(dap_http_simple_t * shs, const char * data, ...) +size_t dap_http_simple_reply_f( dap_http_simple_t * shs, const char * data, ... ) { - char buf[4096]; - va_list ap; - int vret; - va_start(ap,data); - vret = vsnprintf(buf, sizeof(buf)-1, data, ap); - va_end(ap); - if(vret > 0) - return dap_http_simple_reply(shs, buf, vret); - else - return 0; + 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) +inline void queue_http_request_put( dap_http_simple_t *cl_sh ) { - 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); - pthread_mutex_unlock(&mutex_on_queue_http_response); + 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 ( ui32TotalRequests >= 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", ui32TotalRequests ); + + pRequestsBuffer[ ui32TotalRequests ++ ] = cl_sh; + + pthread_mutex_unlock( &mutex_on_queue_http_response ); - ev_async_send(http_simple_loop, &async_watcher_http_simple); +// ev_async_send( http_simple_loop, &async_watcher_http_simple ); } /* Key Expired deprecated code */ diff --git a/http_server/dap_http_simple.h b/http_server/dap_http_simple.h index 1082534588985ecf3bac3390a7e64b51f1162086..b7f2ac671baca179f4fe8e1221967d41c4cd8e6e 100755 --- a/http_server/dap_http_simple.h +++ b/http_server/dap_http_simple.h @@ -20,40 +20,45 @@ #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 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; - }; - size_t request_size; - - union{ - void * reply; - char * reply_str; - }; - size_t reply_size_max; - size_t reply_size; - - size_t reply_sent; - char reply_mime[256]; +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_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 @@ -62,15 +67,14 @@ void dap_http_simple_module_deinit(void); // 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, ...); +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); - +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, ...); +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 diff --git a/http_server/http_client/dap_http_client.c b/http_server/http_client/dap_http_client.c index 377b67edf382de4df205289464c88a5119b683a8..430a7418c9fb0d9e41a2a50d056a95d6f5a5eba4 100755 --- a/http_server/http_client/dap_http_client.c +++ b/http_server/http_client/dap_http_client.c @@ -22,7 +22,22 @@ #include <stdio.h> #include <string.h> #include <ctype.h> + +#ifndef _WIN32 #include <libgen.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-win32/pthread.h" + +#endif #include "dap_common.h" #include "dap_client_remote.h" @@ -32,28 +47,28 @@ #include "dap_http_header.h" #include "dap_http_client.h" -#define LOG_TAG "dap_http_client" +#define LOG_TAG "http_client" -#define BUF_SIZE 2048 +//#define BUF_SIZE 2048 -void dap_http_client_out_header_generate(dap_http_client_t *cl_ht); +void dap_http_client_out_header_generate( dap_http_client_t *cl_ht ); /** * @brief dap_http_client_init Init HTTP client module * @return Zero if ok others if not */ -int dap_http_client_init() +int dap_http_client_init( ) { - log_it(L_NOTICE,"Initialized HTTP client module"); - return 0; + log_it(L_NOTICE,"Initialized HTTP client module"); + return 0; } /** * @brief dap_http_client_deinit Deinit HTTP client module */ -void dap_http_client_deinit() +void dap_http_client_deinit( ) { - log_it(L_INFO,"HTTP client module deinit"); + log_it(L_INFO,"HTTP client module deinit"); } /** @@ -61,16 +76,21 @@ void dap_http_client_deinit() * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_new(dap_client_remote_t * cl,void * arg) +void dap_http_client_new( dap_client_remote_t *cl, void *arg ) { - (void) arg; - cl->_inheritor = DAP_NEW_Z(dap_http_client_t); - dap_http_client_t * cl_ht = DAP_HTTP_CLIENT(cl); - cl_ht->client = cl; - cl_ht->http= DAP_HTTP(cl->server); - cl_ht->state_read = DAP_HTTP_CLIENT_STATE_START; - cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; + (void) arg; + + log_it( L_NOTICE, "dap_http_client_new" ); + + cl->_inheritor = DAP_NEW_Z( dap_http_client_t ); + + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + cl_ht->client = cl; + cl_ht->http = DAP_HTTP( cl->server ); + cl_ht->state_read = DAP_HTTP_CLIENT_STATE_START; + cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; + return; } /** @@ -78,22 +98,30 @@ void dap_http_client_new(dap_client_remote_t * cl,void * arg) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_delete(dap_client_remote_t * cl,void * arg) +void dap_http_client_delete( dap_client_remote_t * cl, void *arg ) { - dap_http_client_t * cl_ht = DAP_HTTP_CLIENT(cl); - while(cl_ht->in_headers) - dap_http_header_remove(&cl_ht->in_headers, cl_ht->in_headers); + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + + log_it( L_NOTICE,"dap_http_client_delete" ); + + while( cl_ht->in_headers ) + dap_http_header_remove( &cl_ht->in_headers, cl_ht->in_headers ); + + while( cl_ht->out_headers ) + dap_http_header_remove( &cl_ht->out_headers, cl_ht->out_headers ); + - while(cl_ht->out_headers) - dap_http_header_remove(&cl_ht->out_headers, cl_ht->out_headers); + if( cl_ht->proc ) { + if( cl_ht->proc->delete_callback ) { + log_it( L_NOTICE,"dap_http_client_delete: callback delete" ); + cl_ht->proc->delete_callback( cl_ht, NULL ); + } + } - if(cl_ht->proc) - if(cl_ht->proc->delete_callback) - cl_ht->proc->delete_callback(cl_ht,NULL); + if( cl_ht->_inheritor ) + free( cl_ht->_inheritor ); - if(cl_ht->_inheritor) - free(cl_ht->_inheritor); - (void) arg; + (void) arg; } @@ -103,61 +131,187 @@ void dap_http_client_delete(dap_client_remote_t * cl,void * arg) * @param max_size Maximum size of this buffer minus 1 (for terminating zero) * @return position of the end of line */ -int detect_end_of_line(const char * buf, size_t max_size) + +#if 1 +int detect_end_of_line( const char *buf, size_t max_size ) { - size_t i; - for(i=0;i<max_size; i++){ - if(buf[i]=='\n'){ - return i; - } + size_t i; + + for( i = 0; i < max_size; i++ ) { + if ( buf[i] == '\n' ) { + return i; } - return -1; + } + + return -1; } +#endif -bool dap_http_request_line_parse(dap_http_client_t * cl_ht, char * buf, size_t buf_length) +char *z_basename( char *path, uint32_t len ) { - size_t pos; - size_t pos_kw_begin=0; - enum parse_state{PS_START=0, PS_ACTION=1, PS_URL=2, PS_TYPE=3, PS_VER_MAJOR=4, PS_VER_MINOR=5} p_st=PS_ACTION; - for(pos=0;pos<buf_length; pos++){ - if(buf[pos]=='\n'){ - break; - }else if(( buf[pos]==' ')||( buf[pos]=='\t')){ - switch(p_st){ - case PS_ACTION:{ - size_t c_size= ((pos-pos_kw_begin+1)>sizeof(cl_ht->action) )? - (sizeof(cl_ht->action)-1) : - (pos-pos_kw_begin) ; - memcpy(cl_ht->action, buf+pos_kw_begin,c_size ); - cl_ht->action[c_size]='\0'; - //log_it(L_DEBUGUG, "Input: action '%s' pos=%lu pos_kw_begin=%lu", cl_ht->action,pos,pos_kw_begin); - p_st=PS_URL; - pos_kw_begin=pos+1; - }break; - case PS_URL:{ - size_t c_size= ((pos-pos_kw_begin+1)>sizeof(cl_ht->action) )? - (sizeof(cl_ht->url_path)-1) : - (pos-pos_kw_begin) ; - memcpy(cl_ht->url_path, buf+pos_kw_begin,c_size ); - cl_ht->url_path[c_size]='\0'; - //log_it(L_DEBUGUG, "Input: url '%s' pos=%lu pos_kw_begin=%lu", cl_ht->url_path,pos,pos_kw_begin); - p_st=PS_TYPE; - pos_kw_begin=pos+1; - }break; - default: - break; - } - }else{ - switch(p_st){ - case PS_START:{ - p_st=PS_ACTION; - pos_kw_begin=pos; - };break; - default:break; - } - } + if ( !len ) + len = strlen( path ); + + if ( len < 2 ) + return path; + + char *ptr = path + len - 1; + + while( ptr > path ) { + if ( *ptr == '/' ) { + ++ptr; + break; } - return cl_ht->url_path[0]&&cl_ht->action[0]; + --ptr; + } + + return ptr; +} + +int32_t z_dirname( char *path, uint32_t len ) +{ + if ( !len ) + len = strlen( path ); + + if ( len < 2 ) + return 0; + + char *ptr = path + len - 1; + + while( ptr > path ) { + if ( *ptr == '/' ) { + break; + } + --ptr; + } + + len = (uint32_t)(ptr - path); + if ( len ) + path[ len ] = 0; + + return len; +} + +int32_t z_rootdirname( char *path, uint32_t len ) +{ + if ( !len ) + len = strlen( path ); + + if ( len < 2 ) + return 0; + + char *ptr = path + 1; + + while( ptr < path + len ) { + if ( *ptr == '/' ) { + break; + } + ++ptr; + } + + int32_t len2 = (uint32_t)(ptr - path); + if ( len2 == len ) + return 0; + + path[ len2 ] = 0; + + return len2; +} + +bool dap_http_request_line_parse( dap_http_client_t *cl_ht, char *buf, size_t buf_length ) +{ + size_t pos; + size_t pos_kw_begin = 0; + + enum parse_state { PS_START = 0, PS_ACTION = 1, PS_URL = 2, PS_TYPE = 3, PS_VER_MAJOR = 4, PS_VER_MINOR = 5 } p_st = PS_ACTION; + + log_it( L_NOTICE, "dap_http_request_line_parse" ); + + for( pos = 0; pos < buf_length; pos ++ ) { + + if ( buf[pos] == '\n' ) + break; + + if ( buf[pos] == ' ' || buf[pos] == '\t' ) { + + switch( p_st ) { + case PS_ACTION: + { + size_t c_size = pos - pos_kw_begin; + if ( c_size + 1 > sizeof(cl_ht->action) ) + c_size = sizeof( cl_ht->action ) - 1; + + memcpy( cl_ht->action, buf + pos_kw_begin, c_size ); + cl_ht->action[c_size] = 0; + log_it( L_WARNING, "Input: action '%s' pos=%u pos_kw_begin=%u", cl_ht->action, (uint32_t)pos, (uint32_t)pos_kw_begin ); + + p_st = PS_URL; + pos_kw_begin = pos + 1; + } + break; + + case PS_URL: + { + size_t c_size = pos - pos_kw_begin; + if ( c_size + 1 > sizeof(cl_ht->action) ) + c_size = sizeof( cl_ht->url_path ) - 1; + + memcpy( cl_ht->url_path, buf + pos_kw_begin, c_size ); + cl_ht->url_path[c_size] = 0; + log_it( L_WARNING, "Input: url '%s' pos=%lu pos_kw_begin=%lu", cl_ht->url_path, (uint32_t)pos, (uint32_t)pos_kw_begin ); + p_st = PS_TYPE; + pos_kw_begin = pos + 1; + break; + } + break; + + default: + break; + } + } + } // for + + if ( pos_kw_begin < buf_length && p_st == PS_TYPE ) { + + size_t c_size; + + char *end = memchr( buf + pos_kw_begin, '/', buf_length - pos_kw_begin ); + + if ( end && end < buf + buf_length ) { + + c_size = end - (buf + pos_kw_begin); + //TODO get version here + //end = memchr( buf + pos_kw_begin, '/', buf_length - pos_kw_begin ); + + } + else + c_size = buf_length - pos_kw_begin; + + if ( c_size + 1 > sizeof(cl_ht->in_content_type) ) + c_size = sizeof(cl_ht->in_content_type) - 1; + + memcpy( cl_ht->in_content_type, buf + pos_kw_begin, c_size ); + cl_ht->in_content_type[c_size] = 0; + + log_it( L_WARNING, "Input: type '%s' pos=%lu pos_kw_begin=%lu", cl_ht->in_content_type, (uint32_t)pos, (uint32_t)pos_kw_begin ); + } + + return cl_ht->url_path[0] && cl_ht->action[0]; +} + +static inline void ReportErrorAndRestart( dap_client_remote_t *cl, dap_http_client_t *cl_ht ) +{ + cl->buf_in_size = 0; + cl_ht->state_read = DAP_HTTP_CLIENT_STATE_NONE; + + dap_client_remote_ready_to_read( cl_ht->client, false ); + dap_client_remote_ready_to_write( cl_ht->client, true ); + + cl_ht->reply_status_code = 505; + strcpy( cl_ht->reply_reason_phrase, "Error" ); + cl_ht->state_write = DAP_HTTP_CLIENT_STATE_START; + + return; } /** @@ -165,172 +319,209 @@ bool dap_http_request_line_parse(dap_http_client_t * cl_ht, char * buf, size_t b * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_read(dap_client_remote_t * cl,void * arg) +void dap_http_client_read( dap_client_remote_t *cl, void *arg ) { + char buf_line[4096]; + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); - (void) arg; - dap_http_client_t * cl_ht=DAP_HTTP_CLIENT(cl); - char buf_line[4096]; -// log_it(L_DEBUGUG,"HTTP client in state read %d taked bytes in input %lu",cl_ht->state_read,cl->buf_in_size); -cnt:switch(cl_ht->state_read){ - case DAP_HTTP_CLIENT_STATE_START:{ // Beginning of the session. We try to detect - int eol = detect_end_of_line(cl->buf_in,cl->buf_in_size); - if(eol<0){ - return; - }else if((eol+3)<sizeof(buf_line) ){ - memcpy(buf_line,cl->buf_in,eol+1); - dap_client_remote_shrink_buf_in(cl,eol+1); - buf_line[eol+2]='\0'; - if( dap_http_request_line_parse(cl_ht,buf_line,eol+1) ){ - char * query_string; - - if( query_string = strchr(cl_ht->url_path,'?')) - { - size_t len_after=strlen(query_string+1); - if(len_after){ - if(len_after>(sizeof(cl_ht->in_query_string)-1)) - len_after=sizeof(cl_ht->in_query_string)-1; - - if(strstr(query_string, "HTTP/1.1")) - strncpy(cl_ht->in_query_string,query_string+1,len_after - 11); - else - strncpy(cl_ht->in_query_string,query_string+1,len_after); - - if(cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] == ' ') - cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] = '\0'; - query_string[0]='\0'; - } - } - //log_it(NOTICE, "Input: %s request for %s document (query string '%s')",cl_ht->action,cl_ht->url_path, cl_ht->in_query_string? cl_ht->in_query_string: ""); - char *b_name; - char * url_cpy1, *url_cpy2; - url_cpy1=strdup(cl_ht->url_path); - url_cpy2=strdup(cl_ht->url_path); - - - b_name=basename(url_cpy2); - - strncpy(cl_ht->url_path,b_name,sizeof(cl_ht->url_path)); - char * d_name; - d_name=dirname(url_cpy1); - dap_http_url_proc_t * url_proc; - - HASH_FIND_STR(cl_ht->http->url_proc, d_name , url_proc); // Find URL processor - - cl_ht->proc=url_proc; - if(url_proc) { - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_HEADERS; - } - else{ - log_it(L_WARNING, "Input: unprocessed URL request %s is rejected", d_name); - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_read(cl_ht->client,true); - dap_client_remote_ready_to_write(cl_ht->client,true); - cl_ht->reply_status_code=505; - strcpy(cl_ht->reply_reason_phrase,"Error"); - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - cl->buf_in_size=0; - free(url_cpy1); - free(url_cpy2); - break; - } - - // cl_ht->state_read=DAP_HTTP_CLIENT_STATE_HEADERS; - - //free(d_name); - //free(b_name); - free(url_cpy1); - free(url_cpy2); - }else{ - log_it(L_WARNING, "Input: Wrong request line '%s'",buf_line); - cl->buf_in_size=0; - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_read(cl_ht->client,false); - dap_client_remote_ready_to_write(cl_ht->client,true); - cl_ht->reply_status_code=505; - strcpy(cl_ht->reply_reason_phrase,"Error"); - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - } - }else{ - log_it(L_WARNING,"Too big line in request, more than %llu symbols - thats very strange",sizeof(buf_line)-3); - cl->buf_in_size=0; - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_read(cl_ht->client,false); - dap_client_remote_ready_to_write(cl_ht->client,true); - cl_ht->reply_status_code=505; - strcpy(cl_ht->reply_reason_phrase,"Error"); - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - } - }break; - case DAP_HTTP_CLIENT_STATE_HEADERS:{ // Parse input headers - int eol = detect_end_of_line(cl->buf_in,cl->buf_in_size); - if(eol<0) - return; - else{ - int parse_ret; - memcpy(buf_line,cl->buf_in,eol+1); - buf_line[eol-1]='\0'; - - parse_ret=dap_http_header_parse(cl_ht,buf_line); - // log_it(L_WARNINGNG, "++ ALL HEADERS TO PARSE [%s]", buf_line); - if(parse_ret<0) - log_it(L_WARNING,"Input: not a valid header '%s'",buf_line); - else if(parse_ret==1){ - log_it(L_INFO,"Input: HTTP headers are over"); - if(cl_ht->proc->access_callback){ - bool isOk=true; - cl_ht->proc->access_callback(cl_ht,&isOk); - if(!isOk){ - log_it(L_NOTICE,"Access restricted"); - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_read(cl_ht->client,false); - dap_client_remote_ready_to_write(cl_ht->client,true); - cl_ht->reply_status_code=505; - strcpy(cl_ht->reply_reason_phrase,"Error"); - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_START; - } - } - - if(cl_ht->proc->headers_read_callback) - cl_ht->proc->headers_read_callback(cl_ht,NULL); - - // If no headers callback we go to the DATA processing - if(cl_ht->in_content_length) { - cl_ht->state_read=DAP_HTTP_CLIENT_STATE_DATA; - } else { - //log_it - //cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; - //cl_ht->client->ready_to_read=t; - //cl_ht->client->signal_close=!cl_ht->keep_alive; - } - - } - dap_client_remote_shrink_buf_in(cl,eol+1); - } - }break; - case DAP_HTTP_CLIENT_STATE_DATA:{//Read the data - // log_it(L_WARNINGNG, "DBG_#002 [%s] [%s]", cl_ht->in_query_string, cl_ht->url_path); - - size_t read_bytes = 0; - if(cl_ht->proc->data_read_callback){ - //while(cl_ht->client->buf_in_size){ - cl_ht->proc->data_read_callback(cl_ht,&read_bytes); - dap_client_remote_shrink_buf_in(cl,read_bytes); - //} - }else { - log_it(L_WARNING, "data_read callback is NULL in DAP_HTTP_CLIENT_STATE_DATA"); - cl->buf_in_size=0; - } - } break; - case DAP_HTTP_CLIENT_STATE_NONE:{ - cl->buf_in_size=0; - }break; + log_it( L_DEBUG, "dap_http_client_read..." ); + log_it( L_WARNING, "HTTP client in state read %d taked bytes in input %lu", cl_ht->state_read, cl->buf_in_size ); + + do { + switch( cl_ht->state_read ) { + + case DAP_HTTP_CLIENT_STATE_START: { // Beginning of the session. We try to detect + + char *peol; + uint32_t eol; + + if ( !(peol = (char *)memchr(cl->buf_in, 10, cl->buf_in_size)) ) { /// search LF + break; + } + + if ( !(eol = peol - cl->buf_in) ) { + break; + } + + if ( eol + 3 >= sizeof(buf_line) ) { + log_it( L_WARNING,"Too big line in request, more than %llu symbols - thats very strange", sizeof(buf_line) - 3 ); + ReportErrorAndRestart( cl, cl_ht ); + break; + } + + memcpy( buf_line, cl->buf_in, eol + 1 ); // copy with LF + + dap_client_remote_shrink_buf_in( cl, eol + 1 ); + buf_line[ eol + 2 ] = 0; // null terminate + + // parse http_request_line + if ( !dap_http_request_line_parse(cl_ht, buf_line, eol + 1) ) { + + log_it( L_WARNING, "Input: Wrong request line '%s'", buf_line ); + ReportErrorAndRestart( cl, cl_ht ); + break; + } +// uint32_t action_len; +// uint32_t url_path_len; + + char *query_string; + + if( query_string = strchr(cl_ht->url_path, '?') ) { + + size_t len_after = strlen( query_string + 1 ); + + if ( len_after ) { + if( len_after > (sizeof(cl_ht->in_query_string) - 1) ) + len_after = sizeof(cl_ht->in_query_string) - 1; + + if ( strstr(query_string, "HTTP/1.1") ) + strncpy( cl_ht->in_query_string, query_string + 1, len_after - 11 ); + else + strncpy( cl_ht->in_query_string,query_string + 1, len_after ); + + if ( cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] == ' ' ) + cl_ht->in_query_string[strlen(cl_ht->in_query_string) - 1] = 0; + + query_string[0] = 0; + } + } + + log_it( L_WARNING, "Input: %s request for %s document (query string '%s')", cl_ht->action, cl_ht->url_path, cl_ht->in_query_string ? cl_ht->in_query_string : "" ); + + dap_http_url_proc_t *url_proc; + int32_t tpos = z_dirname( cl_ht->url_path, 0 ); + log_it( L_WARNING, "cl_ht->url_path(dir) = %s", cl_ht->url_path ); + + HASH_FIND_STR( cl_ht->http->url_proc, cl_ht->url_path, url_proc ); // Find URL processor + + cl_ht->proc = url_proc; + + if ( tpos ) + cl_ht->url_path[ tpos ] = '/'; + + char *ptr = z_basename( cl_ht->url_path, 0 ); + log_it( L_WARNING, "basename = %s", ptr ); + +// log_it( L_WARNING, "cl_ht->client->socket = %u efd %u", cl_ht->client->socket, cl_ht->client->efd ); + + memmove( cl_ht->url_path, ptr, strlen(ptr) + 1 ); + + log_it( L_WARNING, "cl_ht->url_path = %s", cl_ht->url_path ); + + if ( url_proc ) { + cl_ht->state_read = DAP_HTTP_CLIENT_STATE_HEADERS; + } + else { + log_it( L_WARNING, "Input: unprocessed URL request %s is rejected", cl_ht->url_path ); + ReportErrorAndRestart( cl, cl_ht ); + break; + } + + } + break; + + case DAP_HTTP_CLIENT_STATE_HEADERS: { // Parse input headers + +// log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS" ); + char *peol; + uint32_t eol; + + if ( !(peol = (char *)memchr(cl->buf_in, 10, cl->buf_in_size)) ) { /// search LF + log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS: no LF" ); + break; + } + + eol = peol - cl->buf_in; + +// int eol = detect_end_of_line( cl->buf_in, cl->buf_in_size ); + +// if ( eol < 0 ) { +// log_it( L_WARNING, "DAP_HTTP_CLIENT_STATE_HEADERS: no LF" ); +// return; +// } + + int parse_ret; + memcpy( buf_line, cl->buf_in, eol + 1 ); + buf_line[eol-1] = 0; + + parse_ret = dap_http_header_parse( cl_ht, buf_line ); + +// log_it( L_WARNING, "cl_ht->client->socket = %u efd %u", cl_ht->client->socket, cl_ht->client->efd ); + + // log_it(L_WARNINGNG, "++ ALL HEADERS TO PARSE [%s]", buf_line); + if( parse_ret < 0 ) + log_it( L_WARNING, "Input: not a valid header '%s'", buf_line ); + + else if ( parse_ret == 1 ) { + + log_it( L_INFO, "Input: HTTP headers are over" ); + + if ( cl_ht->proc->access_callback ) { + + log_it( L_WARNING, "access_callback" ); + + bool isOk = true; + cl_ht->proc->access_callback( cl_ht, &isOk ); + if ( !isOk ) { + log_it( L_NOTICE, "Access restricted" ); + ReportErrorAndRestart( cl, cl_ht ); + } + } + + if ( cl_ht->proc->headers_read_callback ) { + log_it( L_WARNING, "headers_read_callback" ); + cl_ht->proc->headers_read_callback( cl_ht, NULL ); + } + + // If no headers callback we go to the DATA processing + if( cl_ht->in_content_length ) { + log_it( L_WARNING, "headers -> DAP_HTTP_CLIENT_STATE_DATA" ); + cl_ht->state_read = DAP_HTTP_CLIENT_STATE_DATA; + } + else { + //log_it + //cl_ht->state_read=DAP_HTTP_CLIENT_STATE_NONE; + //cl_ht->client->ready_to_read=t; + //cl_ht->client->signal_close=!cl_ht->keep_alive; + } + } // parse_ret == 1 + + dap_client_remote_shrink_buf_in( cl, eol + 1 ); } - if(cl->buf_in_size>0){ - //log_it(L_DEBUGUG,"Continue to process to parse input"); - goto cnt; + break; + + case DAP_HTTP_CLIENT_STATE_DATA: + { + // log_it(L_WARNINGNG, "DBG_#002 [%s] [%s]", cl_ht->in_query_string, cl_ht->url_path); + + size_t read_bytes = 0; + if ( cl_ht->proc->data_read_callback ) { + log_it( L_WARNING, "cl_ht->proc->data_read_callback()" ); + + //while(cl_ht->client->buf_in_size){ + cl_ht->proc->data_read_callback( cl_ht, &read_bytes ); + dap_client_remote_shrink_buf_in( cl, read_bytes ); + //} + } + else { + log_it( L_WARNING, "data_read callback is NULL in DAP_HTTP_CLIENT_STATE_DATA" ); + cl->buf_in_size = 0; + } + } + break; + + case DAP_HTTP_CLIENT_STATE_NONE: { + cl->buf_in_size = 0; } + break; + + } // switch + + } while ( cl->buf_in_size > 0 ); + + log_it( L_DEBUG, "dap_http_client_read...exit" ); +// Sleep(100); } /** @@ -338,52 +529,66 @@ cnt:switch(cl_ht->state_read){ * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_write(dap_client_remote_t * cl,void * arg) +void dap_http_client_write( dap_client_remote_t * cl, void *arg ) { + log_it( L_DEBUG, "dap_http_client_write..." ); + + (void) arg; + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + + // log_it(L_WARNING,"HTTP client write callback in state %d",cl_ht->state_write); - (void) arg; - dap_http_client_t * cl_ht=DAP_HTTP_CLIENT(cl); - // log_it(L_DEBUGUG,"HTTP client write callback in state %d",cl_ht->state_write); - switch(cl_ht->state_write){ - case DAP_HTTP_CLIENT_STATE_NONE: return; - case DAP_HTTP_CLIENT_STATE_START:{ - if(cl_ht->proc) - if(cl_ht->proc->headers_write_callback) - cl_ht->proc->headers_write_callback(cl_ht,NULL); - log_it(L_DEBUG,"Output: HTTP response with %u status code",cl_ht->reply_status_code); - dap_client_remote_write_f(cl,"HTTP/1.1 %u %s\r\n",cl_ht->reply_status_code, cl_ht->reply_reason_phrase[0] ? - cl_ht->reply_reason_phrase : http_status_reason_phrase(cl_ht->reply_status_code)); - dap_http_client_out_header_generate(cl_ht); - - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_HEADERS; - }break; - case DAP_HTTP_CLIENT_STATE_HEADERS:{ - dap_http_header_t * hdr=cl_ht->out_headers; - if(hdr==NULL){ - log_it(L_DEBUG, "Output: headers are over (reply status code %u)",cl_ht->reply_status_code); - dap_client_remote_write_f(cl,"\r\n"); - if(cl_ht->out_content_length || cl_ht->out_content_ready){ - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_DATA; - }else{ - log_it(L_DEBUG,"Nothing to output"); - cl_ht->state_write=DAP_HTTP_CLIENT_STATE_NONE; - dap_client_remote_ready_to_write(cl,false); - - cl->signal_close=true; - } - dap_client_remote_ready_to_read(cl,true); - }else{ - //log_it(L_DEBUGUG,"Output: header %s: %s",hdr->name,hdr->value); - dap_client_remote_write_f(cl,"%s: %s\r\n",hdr->name,hdr->value); - dap_http_header_remove(&cl_ht->out_headers, hdr); - } - }break; - case DAP_HTTP_CLIENT_STATE_DATA:{ - if(cl_ht->proc) - if(cl_ht->proc->data_write_callback) - cl_ht->proc->data_write_callback(cl_ht,NULL); - }break; + switch( cl_ht->state_write ) { + case DAP_HTTP_CLIENT_STATE_NONE: + return; + case DAP_HTTP_CLIENT_STATE_START: + { + if ( cl_ht->proc ) + if ( cl_ht->proc->headers_write_callback ) + cl_ht->proc->headers_write_callback( cl_ht, NULL ); + + log_it( L_DEBUG,"Output: HTTP response with %u status code", cl_ht->reply_status_code ); + + dap_client_remote_write_f( cl,"HTTP/1.1 %u %s\r\n",cl_ht->reply_status_code, cl_ht->reply_reason_phrase[0] ? + cl_ht->reply_reason_phrase : http_status_reason_phrase(cl_ht->reply_status_code) ); + + dap_http_client_out_header_generate( cl_ht ); + cl_ht->state_write = DAP_HTTP_CLIENT_STATE_HEADERS; } + break; + + case DAP_HTTP_CLIENT_STATE_HEADERS: + { + dap_http_header_t *hdr = cl_ht->out_headers; + if ( hdr == NULL ) { + log_it(L_DEBUG, "Output: headers are over (reply status code %u)",cl_ht->reply_status_code); + dap_client_remote_write_f( cl,"\r\n" ); + if ( cl_ht->out_content_length || cl_ht->out_content_ready ) { + cl_ht->state_write=DAP_HTTP_CLIENT_STATE_DATA; + } + else { + log_it( L_DEBUG, "Nothing to output" ); + cl_ht->state_write = DAP_HTTP_CLIENT_STATE_NONE; + dap_client_remote_ready_to_write( cl, false ); + cl->signal_close = true; + } + dap_client_remote_ready_to_read( cl, true ); + } + else { + //log_it(L_WARNING,"Output: header %s: %s",hdr->name,hdr->value); + dap_client_remote_write_f( cl, "%s: %s\r\n", hdr->name,hdr->value ); + dap_http_header_remove( &cl_ht->out_headers, hdr ); + } + } + break; + case DAP_HTTP_CLIENT_STATE_DATA: + { + if ( cl_ht->proc ) + if ( cl_ht->proc->data_write_callback ) + cl_ht->proc->data_write_callback( cl_ht, NULL ); + } + break; + } } /** @@ -392,29 +597,35 @@ void dap_http_client_write(dap_client_remote_t * cl,void * arg) */ void dap_http_client_out_header_generate(dap_http_client_t *cl_ht) { - char buf[1024]; - time_t current_time=time(NULL); - dap_time_to_str_rfc822(buf,sizeof(buf),current_time); - dap_http_header_add(&cl_ht->out_headers,"Date",buf); - if(cl_ht->reply_status_code==200){ - if(cl_ht->out_last_modified){ - dap_time_to_str_rfc822(buf,sizeof(buf),cl_ht->out_last_modified); - dap_http_header_add(&cl_ht->out_headers,"Last-Modified",buf); - } - if(cl_ht->out_content_type[0]){ - dap_http_header_add(&cl_ht->out_headers,"Content-Type",cl_ht->out_content_type); - log_it(L_DEBUG,"output: Content-Type = '%s'",cl_ht->out_content_type); - } - if(cl_ht->out_content_length){ - snprintf(buf,sizeof(buf),"%llu",(unsigned long long)cl_ht->out_content_length); - dap_http_header_add(&cl_ht->out_headers,"Content-Length",buf); - log_it(L_DEBUG,"output: Content-Length = %llu",cl_ht->out_content_length); - } + char buf[1024]; + time_t current_time = time( NULL ); + dap_time_to_str_rfc822( buf, sizeof(buf), current_time ); + + dap_http_header_add( &cl_ht->out_headers,"Date", buf ); + + if ( cl_ht->reply_status_code == 200 ) { + + if ( cl_ht->out_last_modified ) { + dap_time_to_str_rfc822( buf, sizeof(buf), cl_ht->out_last_modified ); + dap_http_header_add( &cl_ht->out_headers, "Last-Modified", buf ); } - if(cl_ht->out_connection_close || (!cl_ht->keep_alive) ) - dap_http_header_add(&cl_ht->out_headers,"Connection","Close"); - dap_http_header_add(&cl_ht->out_headers,"Server-Name", cl_ht->http->server_name); - log_it(L_DEBUG,"Output: Headers generated"); + if ( cl_ht->out_content_type[0] ) { + dap_http_header_add(&cl_ht->out_headers,"Content-Type",cl_ht->out_content_type); + log_it(L_DEBUG,"output: Content-Type = '%s'",cl_ht->out_content_type); + } + if ( cl_ht->out_content_length ) { + snprintf(buf,sizeof(buf),"%llu",(unsigned long long)cl_ht->out_content_length); + dap_http_header_add(&cl_ht->out_headers,"Content-Length",buf); + log_it(L_DEBUG,"output: Content-Length = %llu",cl_ht->out_content_length); + } + } + + if ( cl_ht->out_connection_close || !cl_ht->keep_alive ) + dap_http_header_add( &cl_ht->out_headers, "Connection","Close" ); + + dap_http_header_add( &cl_ht->out_headers, "Server-Name", cl_ht->http->server_name ); + + log_it( L_DEBUG,"Output: Headers generated" ); } /** @@ -422,11 +633,15 @@ void dap_http_client_out_header_generate(dap_http_client_t *cl_ht) * @param cl HTTP Client instance * @param arg Additional argument (usualy not used) */ -void dap_http_client_error(struct dap_client_remote * cl,void * arg) +void dap_http_client_error( struct dap_client_remote *cl, void *arg ) { - (void) arg; - dap_http_client_t * cl_ht=DAP_HTTP_CLIENT(cl); - if(cl_ht->proc) - if(cl_ht->proc->error_callback) - cl_ht->proc->error_callback(cl_ht,arg); + (void) arg; + + log_it( L_NOTICE, "dap_http_client_error" ); + + dap_http_client_t *cl_ht = DAP_HTTP_CLIENT( cl ); + + if ( cl_ht->proc ) + if ( cl_ht->proc->error_callback ) + cl_ht->proc->error_callback( cl_ht, arg ); } diff --git a/http_server/http_client/dap_http_client.h b/http_server/http_client/dap_http_client.h index 9e81cabb8df835f11f71c3fc840e538cddf740ea..f90569be39404776caee3d90c15bc566a834d1ca 100755 --- a/http_server/http_client/dap_http_client.h +++ b/http_server/http_client/dap_http_client.h @@ -46,54 +46,54 @@ typedef struct dap_http_client char url_path[2048]; // URL path of requested document uint32_t http_version_major; // Major version of HTTP protocol uint32_t http_version_minor; // Minor version of HTTP protocol + uint32_t action_len; + uint32_t url_path_len; bool keep_alive; dap_http_client_state_t state_read; dap_http_client_state_t state_write; - struct dap_http_header * in_headers; - uint64_t in_content_length; + struct dap_http_header *in_headers; + size_t in_content_length; char in_content_type[256]; char in_query_string[1024]; char in_cookie[1024]; - struct dap_http_header * out_headers; - uint64_t out_content_length; + struct dap_http_header *out_headers; + size_t out_content_length; bool out_content_ready; char out_content_type[256]; time_t out_last_modified; bool out_connection_close; - dap_client_remote_t * client; + dap_client_remote_t *client; struct dap_http * http; uint16_t reply_status_code; char reply_reason_phrase[256]; - struct dap_http_url_proc * proc; + struct dap_http_url_proc *proc; - void * _inheritor; - void * _internal; + void *_inheritor; + void *_internal; } dap_http_client_t; #define DAP_HTTP_CLIENT(a) ((dap_http_client_t *) (a)->_inheritor ) - #ifdef __cplusplus extern "C" { #endif -int dap_http_client_init(); -void dap_http_client_deinit(); - +int dap_http_client_init( ); +void dap_http_client_deinit( ); -void dap_http_client_new(dap_client_remote_t * cl,void * arg); // Creates HTTP client's internal structure -void dap_http_client_delete(dap_client_remote_t * cl,void * arg); // Free memory for HTTP client's internal structure +void dap_http_client_new( dap_client_remote_t * cl,void *arg ); // Creates HTTP client's internal structure +void dap_http_client_delete( dap_client_remote_t * cl,void *arg ); // Free memory for HTTP client's internal structure -void dap_http_client_read( dap_client_remote_t * cl,void * arg); // Process read event -void dap_http_client_write( dap_client_remote_t * cl,void * arg); // Process write event -void dap_http_client_error( dap_client_remote_t * cl,void * arg); // Process error event +void dap_http_client_read( dap_client_remote_t * cl,void *arg ); // Process read event +void dap_http_client_write( dap_client_remote_t * cl,void *arg ); // Process write event +void dap_http_client_error( dap_client_remote_t * cl,void *arg ); // Process error event #ifdef __cplusplus } diff --git a/http_server/http_client/dap_http_client_simple.c b/http_server/http_client/dap_http_client_simple.c index 1e17ed3acd4b34108c82ed8ee181244ff4ee9d53..b11ae8cd940809c683e90f0e88a142d16d0f96e7 100755 --- a/http_server/http_client/dap_http_client_simple.c +++ b/http_server/http_client/dap_http_client_simple.c @@ -1,12 +1,30 @@ + #define _GNU_SOURCE + #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <stdint.h> #include <string.h> +#include <time.h> + +#ifndef _WIN32 #include <unistd.h> #include <pthread.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-win32/pthread.h" +#endif + #include <curl/curl.h> #include "utlist.h" @@ -16,30 +34,41 @@ #include "dap_http_client.h" #include "dap_http_client_simple.h" -typedef struct dap_http_client_internal{ +typedef struct dap_http_client_internal { + + dap_http_client_simple_callback_data_t response_callback; + dap_http_client_simple_callback_error_t error_callback; + + void *obj; + uint8_t *request; + size_t request_size; + size_t request_sent_size; + + struct curl_slist *request_headers; - dap_http_client_simple_callback_data_t response_callback; - dap_http_client_simple_callback_error_t error_callback; - void * obj; - uint8_t * request; - size_t request_size; - size_t request_sent_size; - struct curl_slist * request_headers; + uint8_t *response; + size_t response_size; + size_t response_size_max; - uint8_t * response; - size_t response_size; - size_t response_size_max; } dap_http_client_internal_t; -CURLM *m_curl_mh; // Multi-thread handle to stack lot of parallel requests -pthread_t curl_pid=0; -pthread_cond_t m_curl_cond = PTHREAD_COND_INITIALIZER; +CURLM *m_curl_mh = NULL; // Multi-thread handle to stack lot of parallel requests + +#ifndef _WIN32 + pthread_t curl_pid = 0; +#else + pthread_t curl_pid = { NULL, 0 }; +#endif + +pthread_cond_t m_curl_cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t m_curl_mutex = PTHREAD_MUTEX_INITIALIZER; -static void *dap_http_client_thread(void * arg); -size_t dap_http_client_curl_request_callback(char * a_ptr, size_t a_size, size_t a_nmemb, void * a_userdata); -size_t dap_http_client_curl_response_callback(char * a_ptr, size_t a_size, size_t a_nmemb, void * a_userdata); -void dap_http_client_internal_delete(dap_http_client_internal_t * a_client); +static void *dap_http_client_thread( void *arg ); + +size_t dap_http_client_curl_request_callback( char *a_ptr, size_t a_size, size_t a_nmemb, void *a_userdata ); +size_t dap_http_client_curl_response_callback(char *a_ptr, size_t a_size, size_t a_nmemb, void *a_userdata ); + +void dap_http_client_internal_delete( dap_http_client_internal_t *a_client ); #define DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX 40960 @@ -49,39 +78,45 @@ void dap_http_client_internal_delete(dap_http_client_internal_t * a_client); * @brief dap_http_client_init * @return */ -int dap_http_client_simple_init() +int dap_http_client_simple_init( ) { - curl_global_init(CURL_GLOBAL_ALL); - m_curl_mh = curl_multi_init(); - pthread_create(&curl_pid,NULL,dap_http_client_thread,NULL ); - return 0; + log_it( L_NOTICE,"dap_http_client_simple_init( )" ); + + curl_global_init( CURL_GLOBAL_ALL ); + m_curl_mh = curl_multi_init( ); + + pthread_create( &curl_pid, NULL, dap_http_client_thread, NULL ); + + return 0; } /** * @brief dap_http_client_deinit */ -void dap_http_client_simple_deinit() +void dap_http_client_simple_deinit( ) { - curl_multi_cleanup( m_curl_mh ); + curl_multi_cleanup( m_curl_mh ); } /** * @brief dap_http_client_internal_delete * @param a_client */ -void dap_http_client_internal_delete(dap_http_client_internal_t * a_client_internal) +void dap_http_client_internal_delete( dap_http_client_internal_t * a_client_internal ) { - if( a_client_internal->request_headers) - curl_slist_free_all( a_client_internal->request_headers ); + log_it( L_NOTICE,"dap_http_client_internal_delete" ); - if ( a_client_internal->request ) - free(a_client_internal->request); + if( a_client_internal->request_headers ) + curl_slist_free_all( a_client_internal->request_headers ); - if ( a_client_internal->response ) - free(a_client_internal->response); + if ( a_client_internal->request ) + free( a_client_internal->request ); - free(a_client_internal); + if ( a_client_internal->response ) + free( a_client_internal->response ); + + free( a_client_internal ); } /** @@ -95,43 +130,48 @@ void dap_http_client_internal_delete(dap_http_client_internal_t * a_client_inter * @param a_error_callback * @param a_obj */ -void dap_http_client_simple_request_custom(const char * a_url, const char * a_method, const char* a_request_content_type, void *a_request, size_t a_request_size, char * a_cookie, dap_http_client_simple_callback_data_t a_response_callback, - dap_http_client_simple_callback_error_t a_error_callback, void *a_obj, char** a_custom, size_t a_custom_count) +void dap_http_client_simple_request_custom( const char *a_url, const char *a_method, const char *a_request_content_type, + void *a_request, size_t a_request_size, char *a_cookie, + dap_http_client_simple_callback_data_t a_response_callback, + dap_http_client_simple_callback_error_t a_error_callback, + void *a_obj, char **a_custom, size_t a_custom_count ) { - log_it(L_DEBUG,"Simple HTTP request with static predefined buffer (%lu bytes) on url '%s'", - DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX, a_url); - CURL *l_curl_h = curl_easy_init(); - - dap_http_client_internal_t * l_client_internal = DAP_NEW_Z(dap_http_client_internal_t); - l_client_internal->error_callback = a_error_callback; - l_client_internal->response_callback = a_response_callback; - l_client_internal->obj = a_obj; - - l_client_internal->response_size_max = DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX; - l_client_internal->response = (uint8_t*) calloc(1,DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX); - - l_client_internal->request = malloc(a_request_size); - memcpy(l_client_internal->request, a_request, a_request_size); - l_client_internal->request_size = a_request_size; - - if( ( a_request ) && ( ( - (strcmp( a_method , "POST" ) == 0) || - (strcmp( a_method , "POST_ENC" ) == 0) - ) ) ){ - char l_buf[1024]; - log_it ( L_DEBUG , "POST request with %u bytes of decoded data" , a_request_size ); - - if( a_request_content_type ) - l_client_internal->request_headers = curl_slist_append(l_client_internal->request_headers, a_request_content_type ); - - if(a_custom) { - for(int i = 0; i < a_custom_count; i++) { - l_client_internal->request_headers = curl_slist_append(l_client_internal->request_headers,(char*) a_custom[i]); - } + log_it( L_DEBUG, "Simple HTTP request with static predefined buffer (%lu bytes) on url '%s'", + DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX, a_url ); + + CURL *l_curl_h = curl_easy_init( ); + + dap_http_client_internal_t *l_client_internal = DAP_NEW_Z( dap_http_client_internal_t ); + + l_client_internal->error_callback = a_error_callback; + l_client_internal->response_callback = a_response_callback; + l_client_internal->obj = a_obj; + + l_client_internal->response_size_max = DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX; + l_client_internal->response = (uint8_t*) calloc( 1 ,DAP_HTTP_CLIENT_RESPONSE_SIZE_MAX ); + + l_client_internal->request = malloc(a_request_size); + memcpy(l_client_internal->request, a_request, a_request_size); + l_client_internal->request_size = a_request_size; + + if( ( a_request ) && ( ( + (strcmp( a_method , "POST" ) == 0) || + (strcmp( a_method , "POST_ENC" ) == 0) + ) ) ){ + char l_buf[1024]; + log_it ( L_DEBUG , "POST request with %u bytes of decoded data" , a_request_size ); + + if( a_request_content_type ) + l_client_internal->request_headers = curl_slist_append(l_client_internal->request_headers, a_request_content_type ); + + if ( a_custom ) { + for( int i = 0; i < a_custom_count; i++ ) { + l_client_internal->request_headers = curl_slist_append( l_client_internal->request_headers, (char*) a_custom[i] ); } + } - if( a_cookie ) - l_client_internal->request_headers = curl_slist_append(l_client_internal->request_headers,(char*) a_cookie ); + if ( a_cookie ) + l_client_internal->request_headers = curl_slist_append( l_client_internal->request_headers,(char*) a_cookie ); snprintf(l_buf,sizeof(l_buf),"Content-Length: %lu", a_request_size ); l_client_internal->request_headers = curl_slist_append(l_client_internal->request_headers, l_buf); @@ -140,23 +180,26 @@ void dap_http_client_simple_request_custom(const char * a_url, const char * a_me curl_easy_setopt( l_curl_h , CURLOPT_POST , 1 ); curl_easy_setopt( l_curl_h , CURLOPT_POSTFIELDSIZE, a_request_size ); - } - if(l_client_internal->request_headers) - curl_easy_setopt(l_curl_h, CURLOPT_HTTPHEADER, l_client_internal->request_headers); + } + + if ( l_client_internal->request_headers ) + curl_easy_setopt( l_curl_h, CURLOPT_HTTPHEADER, l_client_internal->request_headers ); - curl_easy_setopt( l_curl_h , CURLOPT_PRIVATE, l_client_internal ); - curl_easy_setopt( l_curl_h , CURLOPT_URL, a_url); + curl_easy_setopt( l_curl_h , CURLOPT_PRIVATE, l_client_internal ); + curl_easy_setopt( l_curl_h , CURLOPT_URL, a_url); - curl_easy_setopt( l_curl_h , CURLOPT_READDATA , l_client_internal ); - curl_easy_setopt( l_curl_h , CURLOPT_READFUNCTION , dap_http_client_curl_request_callback ); + curl_easy_setopt( l_curl_h , CURLOPT_READDATA , l_client_internal ); + curl_easy_setopt( l_curl_h , CURLOPT_READFUNCTION , dap_http_client_curl_request_callback ); - curl_easy_setopt( l_curl_h , CURLOPT_WRITEDATA , l_client_internal ); - curl_easy_setopt( l_curl_h , CURLOPT_WRITEFUNCTION , dap_http_client_curl_response_callback ); + curl_easy_setopt( l_curl_h , CURLOPT_WRITEDATA , l_client_internal ); + curl_easy_setopt( l_curl_h , CURLOPT_WRITEFUNCTION , dap_http_client_curl_response_callback ); - curl_multi_add_handle( m_curl_mh, l_curl_h ); + curl_multi_add_handle( m_curl_mh, l_curl_h ); //curl_multi_perform(m_curl_mh, &m_curl_cond); - pthread_cond_signal( &m_curl_cond); - send_select_break(); + + pthread_cond_signal( &m_curl_cond); + + send_select_break( ); } /** @@ -175,9 +218,12 @@ void dap_http_client_simple_request(const char * a_url, const char * a_method, c { char *a_custom_new[1]; size_t a_custom_count = 0; + a_custom_new[0] = (char*)a_custom; + if(a_custom) a_custom_count = 1; + dap_http_client_simple_request_custom(a_url, a_method, a_request_content_type, a_request, a_request_size, a_cookie, a_response_callback, a_error_callback, a_obj, a_custom_new, a_custom_count); } @@ -190,10 +236,12 @@ void dap_http_client_simple_request(const char * a_url, const char * a_method, c * @param a_userdata * @return */ -size_t dap_http_client_curl_response_callback(char * a_ptr, size_t a_size, size_t a_nmemb, void * a_userdata) +size_t dap_http_client_curl_response_callback( char *a_ptr, size_t a_size, size_t a_nmemb, void *a_userdata ) { - dap_http_client_internal_t * l_client_internal = (dap_http_client_internal_t *) a_userdata; - log_it(L_DEBUG, "Recieved %lu bytes in HTTP resonse", a_size*a_nmemb); + dap_http_client_internal_t * l_client_internal = (dap_http_client_internal_t *) a_userdata; + + log_it(L_DEBUG, "Recieved %lu bytes in HTTP resonse", a_size*a_nmemb); + if( l_client_internal->response_size < l_client_internal->response_size_max){ size_t l_size = a_size * a_nmemb; if( l_size > ( l_client_internal->response_size_max - l_client_internal->response_size) ) @@ -203,6 +251,7 @@ size_t dap_http_client_curl_response_callback(char * a_ptr, size_t a_size, size_ }else{ log_it(L_WARNING,"Too big reply, %lu bytes a lost",a_size*a_nmemb); } + return a_size*a_nmemb; } @@ -217,7 +266,9 @@ size_t dap_http_client_curl_response_callback(char * a_ptr, size_t a_size, size_ size_t dap_http_client_curl_request_callback(char * a_ptr, size_t a_size, size_t a_nmemb, void * a_userdata) { dap_http_client_internal_t * l_client_internal = (dap_http_client_internal_t *) a_userdata; + size_t l_size = a_size * a_nmemb; + if( ( l_size + l_client_internal->request_sent_size) > l_client_internal->request_size ) l_size = l_client_internal->request_size - l_client_internal->request_sent_size; @@ -225,6 +276,7 @@ size_t dap_http_client_curl_request_callback(char * a_ptr, size_t a_size, size_t memcpy( a_ptr, l_client_internal->request + l_client_internal->request_sent_size, l_size ); l_client_internal->request_sent_size += l_size; } + return l_size; } @@ -235,10 +287,16 @@ size_t dap_http_client_curl_request_callback(char * a_ptr, size_t a_size, size_t static void* dap_http_client_thread(void * arg) { (void) arg; + bool l_still_running = true; + +// return NULL; + + log_it(L_DEBUG, "dap_http_client_thread started"); + do { struct timeval timeout; - int rc; /* select() return code */ + int rc = 0; /* select() return code */ CURLMcode mc; /* curl_multi_fdset() return code */ fd_set fdread; @@ -256,7 +314,8 @@ static void* dap_http_client_thread(void * arg) timeout.tv_sec = 10; timeout.tv_usec = 0; - curl_multi_timeout( m_curl_mh, &curl_timeo); + curl_multi_timeout( m_curl_mh, &curl_timeo ); + if(curl_timeo >= 0) { timeout.tv_sec = curl_timeo / 1000; if(timeout.tv_sec > 1) @@ -267,7 +326,9 @@ static void* dap_http_client_thread(void * arg) /* get file descriptors from the transfers */ mc = curl_multi_fdset(m_curl_mh, &fdread, &fdwrite, &fdexcep, &maxfd); + FD_SET(get_select_breaker(),&fdread); + if(get_select_breaker() > maxfd) maxfd = get_select_breaker(); @@ -281,11 +342,14 @@ static void* dap_http_client_thread(void * arg) no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- to sleep 100ms, which is the minimum suggested value in the curl_multi_fdset() doc. */ + + rc = 0; + if(maxfd == -1) { - //log_it(L_DEBUG, "Waiting for signal"); + log_it(L_DEBUG, "Waiting for signal"); pthread_cond_wait(&m_curl_cond,&m_curl_mutex); } else { - //log_it(L_DEBUG, "Selecting stuff"); + log_it(L_DEBUG, "Selecting stuff"); /* Note that on some platforms 'timeout' may be modified by select(). If you need access to the original value save a copy beforehand. */ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); @@ -303,15 +367,19 @@ static void* dap_http_client_thread(void * arg) struct CURLMsg *m; do { int msgq = 0; + m = curl_multi_info_read(m_curl_mh, &msgq); + if(m && (m->msg == CURLMSG_DONE)) { CURL *e = m->easy_handle; char * l_private = NULL; int l_err_code = 0; curl_easy_getinfo( e, CURLINFO_PRIVATE, &l_private ); if( l_private ){ + bool l_is_ok = false; - dap_http_client_internal_t * l_client_internal = (dap_http_client_internal_t *) l_private; + dap_http_client_internal_t *l_client_internal = (dap_http_client_internal_t *) l_private; + switch ( m->data.result){ case CURLE_OUT_OF_MEMORY: l_err_code = 1 ; log_it(L_CRITICAL, "Out of memory"); break; case CURLE_COULDNT_CONNECT: l_err_code = 2 ; log_it(L_ERROR, "Couldn't connect to the destination server"); break; @@ -325,6 +393,7 @@ static void* dap_http_client_thread(void * arg) }break; default: l_err_code = 12345; } + if( l_is_ok){ l_client_internal->response_callback(l_client_internal->response, l_client_internal->response_size, @@ -334,19 +403,24 @@ static void* dap_http_client_thread(void * arg) l_client_internal->error_callback(l_err_code , l_client_internal->obj ); } + dap_http_client_internal_delete(l_client_internal); - } else { - log_it(L_CRITICAL, "Can't get private information from libcurl handle to perform the reply to DAP connection"); + + } + else { + log_it(L_CRITICAL, "Can't get private information from libcurl handle to perform the reply to SAP connection"); } + curl_multi_remove_handle(m_curl_mh, e); curl_easy_cleanup(e); } + } while(m); } break; } + } while(l_still_running); return NULL; } - diff --git a/http_server/http_client/dap_http_client_simple.h b/http_server/http_client/dap_http_client_simple.h index 1d48d6aa72ec572f73307ba23bff720c7eba1995..a9c6478bbe11212b8ba93a15d8b7714187febd97 100755 --- a/http_server/http_client/dap_http_client_simple.h +++ b/http_server/http_client/dap_http_client_simple.h @@ -1,26 +1,29 @@ #ifndef DAP_HTTP_CLIENT_H #define DAP_HTTP_CLIENT_H + #include <stddef.h> + struct dap_http_client_simple; -typedef void (*dap_http_client_simple_callback_error_t) (int,void *); // Callback for specific http client operations -typedef void (*dap_http_client_simple_callback_data_t) (void *,size_t,void *); // Callback for specific http client operations + +typedef void ( *dap_http_client_simple_callback_error_t ) ( int, void * ); // Callback for specific http client operations +typedef void ( *dap_http_client_simple_callback_data_t ) ( void *,size_t, void * ); // Callback for specific http client operations typedef struct dap_http_client_simple { void * _inheritor; } dap_http_client_simple_t; -int dap_http_client_simple_init(); -void dap_http_client_simple_deinit(); +int dap_http_client_simple_init( ); +void dap_http_client_simple_deinit( ); -void dap_http_client_simple_request_custom(const char * a_url, const char * a_method, - const char* a_request_content_type, void *a_request, size_t a_request_size, char * a_cookie, +void dap_http_client_simple_request_custom( const char * a_url, const char * a_method, + const char* a_request_content_type, void *a_request, size_t a_request_size, char *a_cookie, dap_http_client_simple_callback_data_t a_response_callback, dap_http_client_simple_callback_error_t a_error_callback, - void *a_obj, char** a_custom, size_t a_custom_count); + void *a_obj, char** a_custom, size_t a_custom_count ); -void dap_http_client_simple_request(const char * a_url, const char * a_method, - const char* a_request_content_type , void *a_request, size_t a_request_size, char * a_cookie, +void dap_http_client_simple_request( const char *a_url, const char * a_method, + const char *a_request_content_type , void *a_request, size_t a_request_size, char *a_cookie, dap_http_client_simple_callback_data_t a_response_callback, - dap_http_client_simple_callback_error_t a_error_callback, void *a_obj, void * a_custom); + dap_http_client_simple_callback_error_t a_error_callback, void *a_obj, void *a_custom ); #endif diff --git a/http_server/http_client/dap_http_header.c b/http_server/http_client/dap_http_header.c index 974f4588d249dd39c310a89f41f009b6de37b78b..fe1301027356cda452eec9efd2a9cc7171050cbb 100755 --- a/http_server/http_client/dap_http_header.c +++ b/http_server/http_client/dap_http_header.c @@ -23,6 +23,20 @@ #include <stdarg.h> #include <string.h> #include <stdlib.h> +#ifdef _WIN32 +#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-win32/pthread.h" + +#endif + #include "dap_common.h" #include "dap_client_remote.h" #include "dap_http_client.h" @@ -35,10 +49,10 @@ * @brief dap_http_header_init Init module * @return Zero if ok others if not */ -int dap_http_header_init() +int dap_http_header_init( ) { - log_it(L_NOTICE, "Initialized HTTP headers module"); - return 0; + log_it( L_NOTICE, "Initialized HTTP headers module" ); + return 0; } /** @@ -46,7 +60,7 @@ int dap_http_header_init() */ void dap_http_header_deinit() { - log_it(L_INFO, "HTTP headers module deinit"); + log_it( L_INFO, "HTTP headers module deinit" ); } @@ -58,7 +72,6 @@ void dap_http_header_deinit() */ int dap_http_header_parse(struct dap_http_client * cl_ht, const char * str) { - char name[256], value[1024]; size_t str_len=strlen(str); @@ -68,8 +81,9 @@ int dap_http_header_parse(struct dap_http_client * cl_ht, const char * str) return 1; //log_it(L_DEBUG, "Parse header string '%s'",str); - for(pos=1; pos<str_len;pos++) - if(str[pos]==':'){ + for( pos = 1; pos < str_len; pos ++ ) + + if( str[pos] == ':' ) { size_t name_len; name_len=pos; if(name_len>(sizeof(name)-1) ) @@ -91,15 +105,18 @@ int dap_http_header_parse(struct dap_http_client * cl_ht, const char * str) log_it(L_INFO, "Input: Keep-Alive connection detected"); cl_ht->keep_alive=true; } +// if(strcmp(value,"keep-alive")==0){ +// log_it(L_INFO, "Input: Keep-Alive connection detected"); +// cl_ht->keep_alive=true; +// } }else if(strcmp(name,"Content-Type")==0){ - strncpy(cl_ht->in_content_type,value,sizeof(cl_ht->in_content_type)); + strncpy( cl_ht->in_content_type, value, sizeof(cl_ht->in_content_type) ); }else if(strcmp(name,"Content-Length")==0){ - cl_ht->in_content_length =atoi(value); + cl_ht->in_content_length = atoi( value ); }else if(strcmp(name,"Cookie")==0){ strncpy(cl_ht->in_cookie,value,sizeof(cl_ht->in_cookie)); } - //log_it(L_DEBUG, "Input: Header\t%s '%s'",name,value); dap_http_header_add(&cl_ht->in_headers,name,value); @@ -192,11 +209,13 @@ void print_dap_http_headers(dap_http_header_t * top) * @param name Name of the header * @return NULL if not found or pointer to structure with found item */ -dap_http_header_t * dap_http_header_find(dap_http_header_t * top, const char*name) +dap_http_header_t *dap_http_header_find( dap_http_header_t *top, const char *name ) { - dap_http_header_t * ret; - for(ret=top; ret; ret=ret->next) - if(strcmp(ret->name,name)==0) - return ret; - return ret; + dap_http_header_t *ret; + + for( ret = top; ret; ret = ret->next ) + if( strcmp(ret->name, name) == 0 ) + return ret; + + return ret; } diff --git a/http_server/http_client/dap_http_header.h b/http_server/http_client/dap_http_header.h index 4175f0d70ba99e876bd01ce35a5c220cb4195dc2..55c3e37054f88573378658a02494acac549cba6e 100755 --- a/http_server/http_client/dap_http_header.h +++ b/http_server/http_client/dap_http_header.h @@ -24,10 +24,10 @@ //Structure for holding HTTP header in the bidirectional list typedef struct dap_http_header{ - char * name; - char * value; - struct dap_http_header * next; - struct dap_http_header * prev; + char *name; + char *value; + struct dap_http_header *next; + struct dap_http_header *prev; } dap_http_header_t; struct dap_http_client;