From 04fec05b701fbfbd8b84a789073029d4ea5b8ef4 Mon Sep 17 00:00:00 2001 From: lxsang Date: Sun, 7 Oct 2018 01:03:05 +0200 Subject: [PATCH] fix open ssl bug --- http_server.c | 69 ++++++++++++++++++++++++++++++++++++++---------- http_server.h | 1 - httpd.c | 8 +++--- libs/handle.c | 35 +++++++++++++++++++++++- libs/handle.h | 7 ++++- libs/scheduler.c | 1 + 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/http_server.c b/http_server.c index 60db928..c7ffb3b 100644 --- a/http_server.c +++ b/http_server.c @@ -125,12 +125,7 @@ void load_config(const char* file) } init_file_system(); } -void set_nonblock(int socket) { - int flags; - flags = fcntl(socket,F_GETFL,0); - //assert(flags != -1); - fcntl(socket, F_SETFL, flags | O_NONBLOCK); -} + void* accept_request(void* data) { @@ -144,28 +139,68 @@ void* accept_request(void* data) task = antd_create_task(NULL,(void*)rq,NULL); task->priority++; server_config.connection++; - fd_set read_flags; + fd_set read_flags, write_flags; // first verify if the socket is ready antd_client_t* client = (antd_client_t*) rq->client; FD_ZERO(&read_flags); FD_SET(rq->client->sock, &read_flags); + FD_ZERO(&write_flags); + FD_SET(rq->client->sock, &write_flags); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 500; // select - int sel = select(client->sock+1, &read_flags, NULL, (fd_set*)0, &timeout); + int sel = select(client->sock+1, &read_flags, &write_flags, (fd_set*)0, &timeout); if(sel == -1) { unknow(rq->client); return task; } - if(sel == 0 || !FD_ISSET(client->sock, &read_flags) ) + if(sel == 0 || (!FD_ISSET(client->sock, &read_flags) && !FD_ISSET(client->sock, &write_flags))) { // retry it later server_config.connection--; task->handle = accept_request; return task; } + // perform the ssl handshake if enabled +#ifdef USE_OPENSSL + int ret,stat; + if(server_config.usessl == 1 && client->status == 0) + { + if (SSL_accept((SSL*)client->ssl) == -1) { + stat = SSL_get_error((SSL*)client->ssl, ret); + switch(stat) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_NONE: + //LOG("RECALL %d\n", stat); + task->handle = accept_request; + task->priority = HIGH_PRIORITY; + server_config.connection--; + return task; + default: + LOG("ERRRRRRRRROR accept %d %d %d\n", stat, ret, ERR_get_error()); + ERR_print_errors_fp(stderr); + return task; + } + } + client->status = 1; + server_config.connection--; + task->handle = accept_request; + return task; + } + else + { + if(!FD_ISSET(client->sock, &read_flags)) + { + task->handle = accept_request; + server_config.connection--; + return task; + } + } +#endif count = read_buf(rq->client, buf, sizeof(buf)); //LOG("count is %d\n", count); line = buf; @@ -831,6 +866,8 @@ void* decode_multi_part_request_data(void* data) { int totalsize=0,len=0; //read until the next boundary + // TODO: this is not efficient for big file + // need a solution while((len = read_buf(rq->client,buf,sizeof(buf))) > 0 && strstr(buf,boundary) <= 0) { fwrite(buf, len, 1, fp); @@ -927,12 +964,16 @@ void decode_url_request(const char* query, dictionary dic) char* post_data_decode(void* client,int len) { char *query = (char*) malloc((len+1)*sizeof(char)); - for (int i = 0; i < len; i++) { - antd_recv(client, (query+i), 1); - } + char* ptr = query; + int readlen = len > BUFFLEN?BUFFLEN:len; + int read = 0; + while(readlen > 0) + { + read += antd_recv(client, query+read, readlen); + LOG("READ %d/%d\n", read, len); + readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read); + } query[len]='\0'; - //query = url_decode(query); - //LOG("JSON Query %s\n", query); return query; } diff --git a/http_server.h b/http_server.h index 6a965c7..ed54a86 100644 --- a/http_server.h +++ b/http_server.h @@ -8,7 +8,6 @@ #include #include #include -#include #include "libs/handle.h" #include "libs/scheduler.h" #include "plugin_manager.h" diff --git a/httpd.c b/httpd.c index 89ba04f..54200ca 100644 --- a/httpd.c +++ b/httpd.c @@ -167,17 +167,19 @@ int main(int argc, char* argv[]) //LOG("Unclosed connection: %d\n", server_config->connection); #ifdef USE_OPENSSL client->ssl = NULL; + client->status = 0; if(config()->usessl == 1) { client->ssl = (void*)SSL_new(ctx); if(!client->ssl) continue; - SSL_set_fd((SSL*)client->ssl, client_sock); + SSL_set_fd((SSL*)client->ssl, client->sock); - if (SSL_accept((SSL*)client->ssl) <= 0) { + /*if (SSL_accept((SSL*)client->ssl) <= 0) { + LOG("EROOR accept\n"); ERR_print_errors_fp(stderr); antd_close(client); continue; - } + }*/ } #endif // create callback for the server diff --git a/libs/handle.c b/libs/handle.c index eea6f16..893d994 100644 --- a/libs/handle.c +++ b/libs/handle.c @@ -100,8 +100,28 @@ int antd_recv(void *src, void* data, int len) #ifdef USE_OPENSSL if(usessl()) { - //LOG("SSL READ\n"); + // TODO: blocking is not good, need a workaround + set_nonblock(source->sock); ret = SSL_read((SSL*) source->ssl, data, len); + set_nonblock(source->sock); + /* + int stat, r, st; + do{ + ret = SSL_read((SSL*) source->ssl, data, len); + stat = SSL_get_error((SSL*)source->ssl, r); + } while(ret == -1 && + ( + stat == SSL_ERROR_WANT_READ || + stat == SSL_ERROR_WANT_WRITE || + stat == SSL_ERROR_NONE || + (stat == SSL_ERROR_SYSCALL && r== 0 && !ERR_get_error()) + )); + if(ret == -1) + { + LOG("Problem reading %d %d %d\n", ret, stat, r); + } + //set_nonblock(source->sock); + */ } else { @@ -116,6 +136,19 @@ int antd_recv(void *src, void* data, int len) }*/ return ret; } +void set_nonblock(int socket) { + int flags; + flags = fcntl(socket,F_GETFL,0); + //assert(flags != -1); + fcntl(socket, F_SETFL, flags | O_NONBLOCK); +} +void set_block() +{ + int flags; + flags = fcntl(socket,F_GETFL,0); + //assert(flags != -1); + fcntl(socket, F_SETFL, flags & (~O_NONBLOCK)); +} int antd_close(void* src) { if(!src) return -1; diff --git a/libs/handle.h b/libs/handle.h index 61da196..9aa1738 100644 --- a/libs/handle.h +++ b/libs/handle.h @@ -11,6 +11,7 @@ #ifdef USE_DB #include "dbhelper.h" #endif +#include #include "dictionary.h" #include "list.h" #include "ini.h" @@ -33,6 +34,9 @@ typedef struct{ int sock; void* ssl; char* ip; +#ifdef USE_OPENSSL + int status; +#endif } antd_client_t; typedef struct { @@ -60,7 +64,8 @@ typedef struct { char* sslkey; #endif }config_t; - +void set_nonblock(int socket); +void set_block(int socket); int response(void*, const char*); void ctype(void*,const char*); void redirect(void*,const char*); diff --git a/libs/scheduler.c b/libs/scheduler.c index 0800231..7d59ee8 100644 --- a/libs/scheduler.c +++ b/libs/scheduler.c @@ -195,6 +195,7 @@ void antd_add_task(antd_scheduler_t* scheduler, antd_task_t* task) { // check if task is exist int prio = task->priority>N_PRIORITY-1?N_PRIORITY-1:task->priority; + //LOG("Prio is %d\n", prio); pthread_mutex_lock(&scheduler->scheduler_lock); enqueue(&scheduler->task_queue[prio], task); pthread_mutex_unlock(&scheduler->scheduler_lock);