|
@@ -1638,11 +1638,14 @@ static void send_http_error(struct mg_connection *conn, int status, const char *
|
|
}
|
|
}
|
|
DEBUG_TRACE("[%s]", buf);
|
|
DEBUG_TRACE("[%s]", buf);
|
|
|
|
|
|
- mg_printf(conn, "HTTP/1.1 %d %s\r\n"
|
|
|
|
- "Content-Length: %d\r\n"
|
|
|
|
|
|
+ mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
|
|
|
|
+ if (len>0) {
|
|
|
|
+ mg_printf(conn, "Content-Type: text/plain\r\n");
|
|
|
|
+ }
|
|
|
|
+ mg_printf(conn, "Content-Length: %d\r\n"
|
|
"Date: %s\r\n"
|
|
"Date: %s\r\n"
|
|
"Connection: %s\r\n\r\n",
|
|
"Connection: %s\r\n\r\n",
|
|
- status, status_text, len, date,
|
|
|
|
|
|
+ len, date,
|
|
suggest_connection_header(conn));
|
|
suggest_connection_header(conn));
|
|
conn->num_bytes_sent += mg_printf(conn, "%s", buf);
|
|
conn->num_bytes_sent += mg_printf(conn, "%s", buf);
|
|
}
|
|
}
|
|
@@ -1818,13 +1821,19 @@ static void change_slashes_to_backslashes(char *path)
|
|
int i;
|
|
int i;
|
|
|
|
|
|
for (i = 0; path[i] != '\0'; i++) {
|
|
for (i = 0; path[i] != '\0'; i++) {
|
|
- if (path[i] == '/')
|
|
|
|
|
|
+
|
|
|
|
+ if (path[i] == '/') {
|
|
path[i] = '\\';
|
|
path[i] = '\\';
|
|
- /* i > 0 check is to preserve UNC paths, like \\server\file.txt */
|
|
|
|
- if (path[i] == '\\' && i > 0)
|
|
|
|
- while (path[i + 1] == '\\' || path[i + 1] == '/')
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* remove double backslash (check i > 0 to preserve UNC paths, like \\server\file.txt) */
|
|
|
|
+ if ((path[i] == '\\') && (i > 0)) {
|
|
|
|
+
|
|
|
|
+ while (path[i + 1] == '\\' || path[i + 1] == '/') {
|
|
(void) memmove(path + i + 1,
|
|
(void) memmove(path + i + 1,
|
|
path + i + 2, strlen(path + i + 1));
|
|
path + i + 2, strlen(path + i + 1));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7499,15 +7508,32 @@ static void produce_socket(struct mg_context *ctx, const struct socket *sp)
|
|
|
|
|
|
static int set_sock_timeout(SOCKET sock, int milliseconds)
|
|
static int set_sock_timeout(SOCKET sock, int milliseconds)
|
|
{
|
|
{
|
|
|
|
+ int r1, r2;
|
|
#ifdef _WIN32
|
|
#ifdef _WIN32
|
|
DWORD t = milliseconds;
|
|
DWORD t = milliseconds;
|
|
#else
|
|
#else
|
|
|
|
+ unsigned int uto = (unsigned int)milliseconds;
|
|
struct timeval t;
|
|
struct timeval t;
|
|
t.tv_sec = milliseconds / 1000;
|
|
t.tv_sec = milliseconds / 1000;
|
|
t.tv_usec = (milliseconds * 1000) % 1000000;
|
|
t.tv_usec = (milliseconds * 1000) % 1000000;
|
|
|
|
+
|
|
|
|
+ /* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
|
|
|
|
+ max. time waiting for the acknowledged of TCP data before the connection
|
|
|
|
+ will be forcefully closed and ETIMEDOUT is returned to the application.
|
|
|
|
+ If this option is not set, the default timeout of 20-30 minutes is used.
|
|
|
|
+ */
|
|
|
|
+ /* #define TCP_USER_TIMEOUT (18) */
|
|
|
|
+
|
|
|
|
+#if defined(TCP_USER_TIMEOUT)
|
|
|
|
+ setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
|
|
#endif
|
|
#endif
|
|
- return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE) &t, sizeof(t)) ||
|
|
|
|
- setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE) &t, sizeof(t));
|
|
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ r1 = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE) &t, sizeof(t));
|
|
|
|
+ r2 = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE) &t, sizeof(t));
|
|
|
|
+
|
|
|
|
+ return r1 || r2;
|
|
}
|
|
}
|
|
|
|
|
|
static void accept_new_connection(const struct socket *listener,
|
|
static void accept_new_connection(const struct socket *listener,
|