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