Selaa lähdekoodia

Various fixes from bel2125, http://code.google.com/r/bel2125-mongoose/source/detail?r=9fe067d34a3f3a7311f86627b8e1ecb7719a663d

Sergey Lyubka 13 vuotta sitten
vanhempi
commit
6dc1b347a0
1 muutettua tiedostoa jossa 28 lisäystä ja 10 poistoa
  1. 28 10
      mongoose.c

+ 28 - 10
mongoose.c

@@ -124,8 +124,8 @@ typedef long off_t;
 #define fdopen(x, y) _fdopen((x), (y))
 #define write(x, y, z) _write((x), (y), (unsigned) z)
 #define read(x, y, z) _read((x), (y), (unsigned) z)
-#define flockfile(x) (void) 0
-#define funlockfile(x) (void) 0
+#define flockfile(x) EnterCriticalSection(&global_log_file_lock)
+#define funlockfile(x) LeaveCriticalSection(&global_log_file_lock)
 
 #if !defined(fileno)
 #define fileno(x) _fileno(x)
@@ -222,6 +222,7 @@ typedef int SOCKET;
 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
 
 #ifdef _WIN32
+static CRITICAL_SECTION global_log_file_lock;
 static pthread_t pthread_self(void) {
   return GetCurrentThreadId();
 }
@@ -467,6 +468,7 @@ struct mg_connection {
   int64_t consumed_content;   // How many bytes of content is already read
   char *buf;                  // Buffer for received data
   char *path_info;            // PATH_INFO part of the URL
+  int must_close;             // 1 if connection must be closed
   int buf_size;               // Buffer size
   int request_len;            // Size of the request + headers in a buffer
   int data_len;               // Total size of data in a buffer
@@ -818,7 +820,9 @@ static int match_prefix(const char *pattern, int pattern_len, const char *str) {
 static int should_keep_alive(const struct mg_connection *conn) {
   const char *http_version = conn->request_info.http_version;
   const char *header = mg_get_header(conn, "Connection");
-  return (!mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") &&
+  return (!conn->must_close &&
+          !conn->request_info.status_code != 401 &&
+          !mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") &&
           (header == NULL && http_version && !strcmp(http_version, "1.1"))) ||
           (header != NULL && !mg_strcasecmp(header, "keep-alive"));
 }
@@ -951,6 +955,7 @@ static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len) {
   } else {
     // Convert to Unicode and back. If doubly-converted string does not
     // match the original, something is fishy, reject.
+    memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
     MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
     WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
                         NULL, NULL);
@@ -1348,11 +1353,11 @@ static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf,
     if (ssl != NULL) {
       n = SSL_write(ssl, buf + sent, k);
     } else if (fp != NULL) {
-      n = fwrite(buf + sent, 1, (size_t)k, fp);
+      n = fwrite(buf + sent, 1, (size_t) k, fp);
       if (ferror(fp))
         n = -1;
     } else {
-      n = send(sock, buf + sent, (size_t)k, 0);
+      n = send(sock, buf + sent, (size_t) k, 0);
     }
 
     if (n < 0)
@@ -2920,7 +2925,7 @@ static void prepare_cgi_environment(struct mg_connection *conn,
 
 static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
   int headers_len, data_len, i, fd_stdin[2], fd_stdout[2];
-  const char *status;
+  const char *status, *status_text;
   char buf[BUFSIZ], *pbuf, dir[PATH_MAX], *p;
   struct mg_request_info ri;
   struct cgi_env_block blk;
@@ -2991,14 +2996,24 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) {
   parse_http_headers(&pbuf, &ri);
 
   // Make up and send the status line
+  status_text = "OK";
   if ((status = get_header(&ri, "Status")) != NULL) {
     conn->request_info.status_code = atoi(status);
+    status_text = status;
+    while (isdigit(* (unsigned char *) status_text) || *status_text == ' ') {
+      status_text++;
+    }
   } else if (get_header(&ri, "Location") != NULL) {
     conn->request_info.status_code = 302;
   } else {
     conn->request_info.status_code = 200;
   }
-  (void) mg_printf(conn, "HTTP/1.1 %d OK\r\n", conn->request_info.status_code);
+  if (get_header(&ri, "Connection") != NULL &&
+      !mg_strcasecmp(get_header(&ri, "Connection"), "keep-alive")) {
+    conn->must_close = 1;
+  }
+  (void) mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->request_info.status_code,
+                   status_text);
 
   // Send headers
   for (i = 0; i < ri.num_headers; i++) {
@@ -3240,6 +3255,7 @@ static void handle_ssi_file_request(struct mg_connection *conn,
     send_http_error(conn, 500, http_500_error, "fopen(%s): %s", path,
                     strerror(ERRNO));
   } else {
+    conn->must_close = 1;
     set_close_on_exec(fileno(fp));
     mg_printf(conn, "HTTP/1.1 200 OK\r\n"
               "Content-Type: text/html\r\nConnection: %s\r\n\r\n",
@@ -3774,9 +3790,6 @@ static void reset_per_request_attributes(struct mg_connection *conn) {
   struct mg_request_info *ri = &conn->request_info;
 
   // Reset request info attributes. DO NOT TOUCH is_ssl, remote_ip, remote_port
-  if (ri->remote_user != NULL) {
-    free((void *) ri->remote_user);
-  }
   ri->remote_user = ri->request_method = ri->uri = ri->http_version =
     conn->path_info = NULL;
   ri->num_headers = 0;
@@ -3785,6 +3798,7 @@ static void reset_per_request_attributes(struct mg_connection *conn) {
   conn->num_bytes_sent = conn->consumed_content = 0;
   conn->content_len = -1;
   conn->request_len = conn->data_len = 0;
+  conn->must_close = 0;
 }
 
 static void close_socket_gracefully(SOCKET sock) {
@@ -3896,6 +3910,9 @@ static void process_new_connection(struct mg_connection *conn) {
       log_access(conn);
       discard_current_request_from_buffer(conn);
     }
+    if (ri->remote_user != NULL) {
+      free((void *) ri->remote_user);
+    }
   } while (conn->ctx->stop_flag == 0 &&
            keep_alive_enabled &&
            should_keep_alive(conn));
@@ -4142,6 +4159,7 @@ struct mg_context *mg_start(mg_callback_t user_callback, void *user_data,
 #if defined(_WIN32) && !defined(__SYMBIAN32__)
   WSADATA data;
   WSAStartup(MAKEWORD(2,2), &data);
+  InitializeCriticalSection(&global_log_file_lock);
 #endif // _WIN32
 
   // Allocate context and initialize reasonable general case defaults.