Diff for /parser3/src/main/pa_http.C between versions 1.111 and 1.119

version 1.111, 2020/12/16 15:04:47 version 1.119, 2021/11/08 11:44:20
Line 264  static sigjmp_buf timeout_env; Line 264  static sigjmp_buf timeout_env;
 static void timeout_handler(int /*sig*/){  static void timeout_handler(int /*sig*/){
         siglongjmp(timeout_env, 1);          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  #else
 #define ALARM(value)  #define ALARM(value)
 #endif  #endif
Line 276  static int http_request(HTTP_response& r Line 279  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]          volatile int sock=-1; // to prevent makeing it register variable, because it will be clobbered by longjmp [thanks gcc warning]
                                   
 #ifdef PA_USE_ALARM  #ifdef PA_USE_ALARM
         signal(SIGALRM, timeout_handler);          if(PA_NO_THREADS) signal(SIGALRM, timeout_handler);
         if(sigsetjmp(timeout_env, 1)) {          if(PA_NO_THREADS && sigsetjmp(timeout_env, 1)) {
                 // duplicating closesocket to make code more simple for old compilers                  // duplicating closesocket to make code more simple for old compilers
                 if(sock>=0)                  if(sock>=0)
                         closesocket(sock);                          closesocket(sock);
Line 739  File_read_http_result pa_internal_file_r Line 742  File_read_http_result pa_internal_file_r
                         throw Exception(PARSER_RUNTIME, &connect_string, "does not start with http://"); //never                          throw Exception(PARSER_RUNTIME, &connect_string, "does not start with http://"); //never
                 current+=7;                  current+=7;
   
                 strncpy(host, current, sizeof(host)-1);  host[sizeof(host)-1]=0;                  pa_strncpy(host, current, sizeof(host));
                 char* host_uri=lsplit(host, '/');                  char* host_uri=lsplit(host, '/');
                 uri=host_uri?current+(host_uri-1-host):"/";                  uri=host_uri?current+(host_uri-1-host):"/";
                 char* port_cstr=lsplit(host, ':');                  char* port_cstr=lsplit(host, ':');
Line 1036  enum HTTPD_request_state { Line 1039  enum HTTPD_request_state {
   
 ssize_t HTTPD_request::pa_recv(int sockfd, char *buffer, size_t len){  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));          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  #ifdef PA_USE_ALARM
         signal(SIGALRM, timeout_handler);          if(PA_NO_THREADS) signal(SIGALRM, timeout_handler);
         if(sigsetjmp(timeout_env, 1)) {          if(PA_NO_THREADS && sigsetjmp(timeout_env, 1)) {
                 LOG(pa_log("httpd [%d] recv got %d sec timeout", sockfd, pa_httpd_timeout));                  LOG(pa_log("httpd [%d] recv got %d sec timeout", sockfd, pa_httpd_timeout));
                 if(length) // timeout on "void" connection is normal                  if(length) // timeout on "void" connection is normal
                         throw Exception("httpd.timeout", 0, "timeout occurred while receiving request");                          throw Exception("httpd.timeout", 0, "timeout occurred while receiving request");
Line 1056  ssize_t HTTPD_request::pa_recv(int sockf Line 1054  ssize_t HTTPD_request::pa_recv(int sockf
                 ssize_t result=recv(sockfd, buffer, len, 0);                  ssize_t result=recv(sockfd, buffer, len, 0);
                 ALARM(0);                  ALARM(0);
                 LOG(pa_log("httpd [%d] recv got %d bytes", sockfd, result));                  LOG(pa_log("httpd [%d] recv got %d bytes", sockfd, result));
                   LOG(pa_log("httpd [%d] %s", sockfd, buffer));
                 return result;                  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) {  bool HTTPD_request::read_header(int sock) {
         enum HTTPD_request_state state = HTTPD_METHOD;          enum HTTPD_request_state state = HTTPD_METHOD;
   
Line 1076  bool HTTPD_request::read_header(int sock Line 1089  bool HTTPD_request::read_header(int sock
                                 char *method_line = pa_strdup(buf, method_size);                                  char *method_line = pa_strdup(buf, method_size);
                                 method = extract_method(method_line);                                  method = extract_method(method_line);
   
                                 if(!method ||                                  if(!valid_http_method(method))
                                         strcmp(method, "GET") &&  
                                         strcmp(method, "HEAD") &&  
                                         strcmp(method, "POST") &&  
                                         strcmp(method, "PUT") &&  
                                         strcmp(method, "DELETE") &&  
                                         strcmp(method, "PATCH")  
                                 )  
                                         throw Exception("httpd.method", new String(method ? method : method_line), "invalid request method");                                          throw Exception("httpd.method", new String(method ? method : method_line), "invalid request method");
                                 state = HTTPD_HEADERS;                                  state = HTTPD_HEADERS;
                         }                          }
Line 1168  size_t HTTPD_Connection::read_post(char Line 1174  size_t HTTPD_Connection::read_post(char
 }  }
   
 size_t HTTPD_Connection::send_body(const void *buf, size_t size) {  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) {          if(send(sock, (const char*)buf, size, 0) != (ssize_t)size) {
                 int no=pa_socks_errno();                  int no=pa_socks_errno();
                 throw Exception("httpd.write", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no);                  throw Exception("httpd.write", 0, "error sending response: %s (%d)", pa_socks_strerr(no), no);
Line 1222  bool HTTPD_Connection::accept(int server Line 1229  bool HTTPD_Connection::accept(int server
 }  }
   
 HTTPD_Server::HTTPD_MODE HTTPD_Server::mode = HTTPD_Server::SEQUENTIAL;  HTTPD_Server::HTTPD_MODE HTTPD_Server::mode = HTTPD_Server::SEQUENTIAL;
   const char *HTTPD_Server::port=NULL;
   
 void HTTPD_Server::set_mode(const String &value){  void HTTPD_Server::set_mode(const String &value){
                 if(value == "sequental") mode = SEQUENTIAL;                  if(value == "sequental") mode = SEQUENTIAL;
   #ifdef HAVE_TLS
                 else if (value == "threaded") mode = MULTITHREADED;                  else if (value == "threaded") mode = MULTITHREADED;
   #endif
 #ifdef _MSC_VER  #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
                 else if (value == "parallel") mode = PARALLEL;                  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  #endif
 }  }
   
 int HTTPD_Server::bind(const char *host_port){  int HTTPD_Server::bind(const char *host_port){
         struct sockaddr_in me;          struct sockaddr_in me;
   
         const char *port = strchr(host_port, ':');          port = strchr(host_port, ':');
         const char *host = NULL;          const char *host = NULL;
         if(port && port > host_port){          if(port){
                 host = pa_strdup(host_port, port - host_port);                  if(port > host_port)
                           host = pa_strdup(host_port, port - host_port);
                 port += 1;                  port += 1;
         } else {          } else {
                 port = host_port;                  port = host_port;

Removed from v.1.111  
changed lines
  Added in v.1.119


E-mail: