--- parser3/src/main/pa_http.C 2020/12/16 15:04:47 1.111 +++ parser3/src/main/pa_http.C 2021/01/21 16:46:53 1.118 @@ -14,7 +14,7 @@ #include "pa_vfile.h" #include "pa_random.h" -volatile const char * IDENT_PA_HTTP_C="$Id: pa_http.C,v 1.111 2020/12/16 15:04:47 moko Exp $" IDENT_PA_HTTP_H; +volatile const char * IDENT_PA_HTTP_C="$Id: pa_http.C,v 1.118 2021/01/21 16:46:53 moko Exp $" IDENT_PA_HTTP_H; #ifdef _MSC_VER #include @@ -264,7 +264,10 @@ static sigjmp_buf timeout_env; static void timeout_handler(int /*sig*/){ siglongjmp(timeout_env, 1); } -#define ALARM(value) alarm(value) + +#define PA_NO_THREADS (HTTPD_Server::mode != HTTPD_Server::MULTITHREADED) + +#define ALARM(value) if(PA_NO_THREADS) alarm(value) #else #define ALARM(value) #endif @@ -276,8 +279,8 @@ static int http_request(HTTP_response& r volatile int sock=-1; // to prevent makeing it register variable, because it will be clobbered by longjmp [thanks gcc warning] #ifdef PA_USE_ALARM - signal(SIGALRM, timeout_handler); - if(sigsetjmp(timeout_env, 1)) { + if(PA_NO_THREADS) signal(SIGALRM, timeout_handler); + if(PA_NO_THREADS && sigsetjmp(timeout_env, 1)) { // duplicating closesocket to make code more simple for old compilers if(sock>=0) closesocket(sock); @@ -1036,15 +1039,10 @@ enum HTTPD_request_state { ssize_t HTTPD_request::pa_recv(int sockfd, char *buffer, size_t len){ LOG(pa_log("httpd [%d] recv %d appending to %d ...", sockfd, len, length)); - if(HTTPD_Server::mode == HTTPD_Server::MULTITHREADED){ - ssize_t result=recv(sockfd, buffer, len, 0); - LOG(pa_log("httpd [%d] recv got %d bytes", sockfd, result)); - return result; - } #ifdef PA_USE_ALARM - signal(SIGALRM, timeout_handler); - if(sigsetjmp(timeout_env, 1)) { + if(PA_NO_THREADS) signal(SIGALRM, timeout_handler); + if(PA_NO_THREADS && sigsetjmp(timeout_env, 1)) { LOG(pa_log("httpd [%d] recv got %d sec timeout", sockfd, pa_httpd_timeout)); if(length) // timeout on "void" connection is normal throw Exception("httpd.timeout", 0, "timeout occurred while receiving request"); @@ -1056,10 +1054,25 @@ ssize_t HTTPD_request::pa_recv(int sockf ssize_t result=recv(sockfd, buffer, len, 0); ALARM(0); LOG(pa_log("httpd [%d] recv got %d bytes", sockfd, result)); + LOG(pa_log("httpd [%d] %s", sockfd, buffer)); return result; } } +static bool valid_http_method(const char * method){ + return method && ( + !strcmp(method, "GET") || + !strcmp(method, "HEAD") || + !strcmp(method, "POST") || + !strcmp(method, "PUT") || + !strcmp(method, "DELETE") || + !strcmp(method, "CONNECT") || + !strcmp(method, "OPTIONS") || + !strcmp(method, "TRACE") || + !strcmp(method, "PATCH") + ); +} + bool HTTPD_request::read_header(int sock) { enum HTTPD_request_state state = HTTPD_METHOD; @@ -1076,14 +1089,7 @@ bool HTTPD_request::read_header(int sock char *method_line = pa_strdup(buf, method_size); method = extract_method(method_line); - if(!method || - strcmp(method, "GET") && - strcmp(method, "HEAD") && - strcmp(method, "POST") && - strcmp(method, "PUT") && - strcmp(method, "DELETE") && - strcmp(method, "PATCH") - ) + if(!valid_http_method(method)) throw Exception("httpd.method", new String(method ? method : method_line), "invalid request method"); state = HTTPD_HEADERS; } @@ -1168,7 +1174,8 @@ size_t HTTPD_Connection::read_post(char } size_t HTTPD_Connection::send_body(const void *buf, size_t size) { - LOG(pa_log("httpd [%d] response %d", sock, size)); + LOG(pa_log("httpd [%d] response %d bytes", sock, size)); + LOG(pa_log("httpd [%d] %s", sock, buf)); if(send(sock, (const char*)buf, size, 0) != (ssize_t)size) { int no=pa_socks_errno(); throw Exception("httpd.write", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no); @@ -1222,25 +1229,29 @@ bool HTTPD_Connection::accept(int server } HTTPD_Server::HTTPD_MODE HTTPD_Server::mode = HTTPD_Server::SEQUENTIAL; +const char *HTTPD_Server::port=NULL; void HTTPD_Server::set_mode(const String &value){ if(value == "sequental") mode = SEQUENTIAL; +#ifdef HAVE_TLS else if (value == "threaded") mode = MULTITHREADED; +#endif #ifdef _MSC_VER - else throw Exception("httpd.mode", &value, "$main:HTTPD.mode must be 'sequental' or 'threaded'"); + else throw Exception("httpd.mode", &value, "$MAIN:HTTPD.mode must be 'sequental' or 'threaded'"); #else else if (value == "parallel") mode = PARALLEL; - else throw Exception("httpd.mode", &value, "$main:HTTPD.mode must be 'sequental', 'parallel' or 'threaded'"); + else throw Exception("httpd.mode", &value, "$MAIN:HTTPD.mode must be 'sequental', 'parallel' or 'threaded'"); #endif } int HTTPD_Server::bind(const char *host_port){ struct sockaddr_in me; - const char *port = strchr(host_port, ':'); + port = strchr(host_port, ':'); const char *host = NULL; - if(port && port > host_port){ - host = pa_strdup(host_port, port - host_port); + if(port){ + if(port > host_port) + host = pa_strdup(host_port, port - host_port); port += 1; } else { port = host_port;