From 82d83ba665435c587eba050291f8ca68c3cb46ad Mon Sep 17 00:00:00 2001 From: lxsang Date: Sun, 7 Oct 2018 13:57:52 +0200 Subject: [PATCH] fix openssl bug on nonblocking mode --- http_server.c | 28 +++++++++------- libs/handle.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/http_server.c b/http_server.c index c7ffb3b..e768dbb 100644 --- a/http_server.c +++ b/http_server.c @@ -138,7 +138,6 @@ void* accept_request(void* data) task = antd_create_task(NULL,(void*)rq,NULL); task->priority++; - server_config.connection++; fd_set read_flags, write_flags; // first verify if the socket is ready antd_client_t* client = (antd_client_t*) rq->client; @@ -159,7 +158,6 @@ void* accept_request(void* data) 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; } @@ -178,7 +176,6 @@ void* accept_request(void* data) //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()); @@ -187,7 +184,6 @@ void* accept_request(void* data) } } client->status = 1; - server_config.connection--; task->handle = accept_request; return task; } @@ -196,11 +192,11 @@ void* accept_request(void* data) if(!FD_ISSET(client->sock, &read_flags)) { task->handle = accept_request; - server_config.connection--; return task; } } #endif + server_config.connection++; count = read_buf(rq->client, buf, sizeof(buf)); //LOG("count is %d\n", count); line = buf; @@ -966,14 +962,24 @@ char* post_data_decode(void* client,int len) char *query = (char*) malloc((len+1)*sizeof(char)); char* ptr = query; int readlen = len > BUFFLEN?BUFFLEN:len; - int read = 0; - while(readlen > 0) + int read = 0, stat = 1; + while(readlen > 0 && stat > 0) { - read += antd_recv(client, query+read, readlen); - LOG("READ %d/%d\n", read, len); - readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read); + stat = antd_recv(client, ptr+read, readlen); + if(stat > 0) + { + read += stat; + readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read); + } + } + + if(read > 0) + query[read]='\0'; + else + { + free(query); + query = NULL; } - query[len]='\0'; return query; } diff --git a/libs/handle.c b/libs/handle.c index 893d994..0a08f6f 100644 --- a/libs/handle.c +++ b/libs/handle.c @@ -95,15 +95,89 @@ int antd_send(void *src, const void* data, int len) int antd_recv(void *src, void* data, int len) { if(!src) return -1; - int ret; + int read; antd_client_t * source = (antd_client_t *) src; #ifdef USE_OPENSSL if(usessl()) { - // 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 received; + char* ptr = (char* )data; + int readlen = len > BUFFLEN?BUFFLEN:len; + read = 0; + fd_set fds; + struct timeval timeout; + while (readlen > 0) + { + received = SSL_read (source->ssl, ptr+read, readlen); + if (received > 0) + { + read += received; + readlen = (len - read) > BUFFLEN?BUFFLEN:(len-read); + } + else + { + //printf(" received equal to or less than 0\n") + int err = SSL_get_error(source->ssl, received); + switch (err) + { + case SSL_ERROR_NONE: + { + // no real error, just try again... + //LOG("SSL_ERROR_NONE \n"); + continue; + } + + case SSL_ERROR_ZERO_RETURN: + { + // peer disconnected... + //printf("SSL_ERROR_ZERO_RETURN \n"); + break; + } + + case SSL_ERROR_WANT_READ: + { + // no data available right now, wait a few seconds in case new data arrives... + //printf("SSL_ERROR_WANT_READ\n"); + + int sock = SSL_get_rfd(source->ssl); + FD_ZERO(&fds); + FD_SET(sock, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 500; + err = select(sock+1, &fds, NULL, NULL, &timeout); + if (err == 0 || (err > 0 && FD_ISSET(sock, &fds))) + continue; // more data to read... + break; + } + + case SSL_ERROR_WANT_WRITE: + { + // socket not writable right now, wait a few seconds and try again... + //printf("SSL_ERROR_WANT_WRITE \n"); + int sock = SSL_get_wfd(source->ssl); + FD_ZERO(&fds); + FD_SET(sock, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 500; + + err = select(sock+1, NULL, &fds, NULL, &timeout); + if (err == 0 || (err > 0 && FD_ISSET(sock, &fds))) + continue; // can write more data now... + break; + } + + default: + { + // other error + break; + } + } + + break; + } + } /* int stat, r, st; do{ @@ -126,7 +200,7 @@ int antd_recv(void *src, void* data, int len) else { #endif - ret = recv(((int) source->sock), data, len, 0); + read = recv(((int) source->sock), data, len, 0); #ifdef USE_OPENSSL } #endif @@ -134,7 +208,7 @@ int antd_recv(void *src, void* data, int len) { antd_close(src); }*/ - return ret; + return read; } void set_nonblock(int socket) { int flags;