diff --git a/http_server.c b/http_server.c index 57517c4..02c969b 100644 --- a/http_server.c +++ b/http_server.c @@ -669,9 +669,9 @@ void *decode_post_request(void *data) char *method = (char *)dvalue(rq->request, "METHOD"); task = antd_create_task(NULL, (void *)rq, NULL); task->priority++; + task->type = HEAVY; if (!method || strcmp(method, "POST") != 0) return task; - if (ctype == NULL || clen == -1) { LOG("Bad request\n"); @@ -803,11 +803,11 @@ void *decode_multi_part_request(void *data, const char *ctype) if (line) { task->handle = decode_multi_part_request_data; - task->type = HEAVY; free(line); } } free(orgcpy); + task->type = HEAVY; return task; } void *decode_multi_part_request_data(void *data) @@ -1089,6 +1089,7 @@ void *execute_plugin(void *data, const char *pname) if (meta && meta->raw_body == 1) { task->handle = fn; + task->type = HEAVY; } else { @@ -1096,7 +1097,6 @@ void *execute_plugin(void *data, const char *pname) task = antd_create_task(decode_post_request, (void *)rq, fn); task->priority++; } - task->type = HEAVY; return task; } diff --git a/httpd.c b/httpd.c index 7e53812..c5e8ae3 100644 --- a/httpd.c +++ b/httpd.c @@ -131,13 +131,22 @@ int main(int argc, char* argv[]) // default to 4 workers antd_scheduler_init(&scheduler, config()->n_workers); set_nonblock(server_sock); + int stat = 0; + struct timespec ts_sleep; while (scheduler.status) { - antd_task_schedule(&scheduler); + stat = antd_task_schedule(&scheduler); client_sock = accept(server_sock,(struct sockaddr *)&client_name,&client_name_len); if (client_sock == -1) { - //perror("Cannot accept client request\n"); + if(!stat) + { + // sleep for 500usec if + // there is nothing todo + ts_sleep.tv_sec = 0; + ts_sleep.tv_nsec = 500000; + nanosleep(&ts_sleep, NULL); + } continue; } antd_client_t* client = (antd_client_t*)malloc(sizeof(antd_client_t)); diff --git a/libs/handle.c b/libs/handle.c index ae01c8f..937a276 100644 --- a/libs/handle.c +++ b/libs/handle.c @@ -71,18 +71,96 @@ int response(void* client, const char* data) int antd_send(void *src, const void* data, int len) { if(!src || !data) return -1; - int ret; + int written; antd_client_t * source = (antd_client_t *) src; #ifdef USE_OPENSSL if(usessl()) { //LOG("SSL WRITE\n"); - ret = SSL_write((SSL*) source->ssl, data, len); + //ret = SSL_write((SSL*) source->ssl, data, len); + int count; + char* ptr = (char* )data; + int writelen = len > BUFFLEN?BUFFLEN:len; + written = 0; + fd_set fds; + struct timeval timeout; + while (writelen > 0) + { + count = SSL_write (source->ssl, ptr+written, writelen); + if (count > 0) + { + written += count; + writelen = (len - written) > BUFFLEN?BUFFLEN:(len-written); + } + else + { + //printf(" received equal to or less than 0\n") + int err = SSL_get_error(source->ssl, count); + 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; + } + } } else { #endif - ret = send(source->sock, data, len, 0); + written = send(source->sock, data, len, 0); #ifdef USE_OPENSSL } #endif @@ -90,7 +168,7 @@ int antd_send(void *src, const void* data, int len) { antd_close(src); }*/ - return ret; + return written; } int antd_recv(void *src, void* data, int len) { diff --git a/libs/scheduler.c b/libs/scheduler.c index 7d59ee8..a8c6e91 100644 --- a/libs/scheduler.c +++ b/libs/scheduler.c @@ -118,6 +118,15 @@ static void work(antd_scheduler_t* scheduler) pthread_mutex_unlock(&scheduler->worker_lock); // execute the task //LOG("task executed by worker %d\n", worker->pid); + // no task to execute, just sleep for 500usec + if(!it) + { + struct timespec ts_sleep; + ts_sleep.tv_sec = 0; + ts_sleep.tv_nsec = 500000; + nanosleep(&ts_sleep, NULL); + continue; + } antd_execute_task(scheduler, it); } } @@ -256,7 +265,7 @@ int antd_scheduler_busy(antd_scheduler_t* scheduler) return scheduler->pending_task != 0; } -void antd_task_schedule(antd_scheduler_t* scheduler) +int antd_task_schedule(antd_scheduler_t* scheduler) { // fetch next task from the task_queue antd_task_item_t it = NULL; @@ -271,7 +280,7 @@ void antd_task_schedule(antd_scheduler_t* scheduler) pthread_mutex_unlock(&scheduler->scheduler_lock); if(!it) { - return; + return 0; } // has the task now // check the type of tas @@ -289,4 +298,5 @@ void antd_task_schedule(antd_scheduler_t* scheduler) pthread_mutex_unlock(&scheduler->worker_lock); free(it); } + return 1; } \ No newline at end of file diff --git a/libs/scheduler.h b/libs/scheduler.h index 4c9747d..349c1f2 100644 --- a/libs/scheduler.h +++ b/libs/scheduler.h @@ -92,5 +92,5 @@ int antd_scheduler_busy(antd_scheduler_t*); /* schedule a task */ -void antd_task_schedule(antd_scheduler_t*); +int antd_task_schedule(antd_scheduler_t*); #endif \ No newline at end of file diff --git a/relay.c b/relay.c index 0fe8327..1176f16 100644 --- a/relay.c +++ b/relay.c @@ -24,11 +24,11 @@ void* antd_redirect(void* user_data) void** data = (void**)user_data; void* client = data[0]; char* host = (char*)data[1]; - __t(client,"%s", "HTTP/1.1 301 Moved Permanently"); + set_status(client, 301,"Moved Permanently"); __t(client, "Location: https://%s", host); __t(client, "%s", "Content-Type: text/html"); - __t(client, ""); - __t(client, "This page has moved to https://%s", host); + response(client, ""); + __t(client, "This page has been moved to https://%s", host); free(host); free(user_data); return antd_create_task(NULL,client, NULL); @@ -60,7 +60,7 @@ void* antd_get_host(void * client) if(line) { host = strdup(line); - break; + //break; } } if(!host) host = strdup("lxsang.me"); @@ -92,18 +92,28 @@ int main(int argc, char* argv[]) // 0 worker antd_scheduler_init(&scheduler, 0); // set server socket to non blocking - fcntl(server_sock, F_SETFL, O_NONBLOCK); /* Change the socket into non-blocking state */ + set_nonblock(server_sock); LOG("relayd running on port %d\n", port); - + struct timespec ts_sleep; while (scheduler.status) { // execute task - antd_task_schedule(&scheduler); + int stat = antd_task_schedule(&scheduler); client_sock = accept(server_sock,(struct sockaddr *)&client_name,&client_name_len); if (client_sock == -1) { + // sleep for 500usec if + // there is nothing todo + if(!stat) + { + ts_sleep.tv_sec = 0; + ts_sleep.tv_nsec = 5000000; + nanosleep(&ts_sleep, NULL); + } + continue; } + set_nonblock(client_sock); antd_client_t* client = (antd_client_t*)malloc(sizeof(antd_client_t)); // set timeout to socket