|
@@ -1778,11 +1778,11 @@ mg_current_thread_id(void)
|
|
|
#if defined(__clang__)
|
|
|
#pragma clang diagnostic push
|
|
|
#pragma clang diagnostic ignored "-Wunreachable-code"
|
|
|
-/* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
|
|
|
- * or not, so one of the two conditions will be unreachable by construction.
|
|
|
- * Unfortunately the C standard does not define a way to check this at
|
|
|
- * compile time, since the #if preprocessor conditions can not use the sizeof
|
|
|
- * operator as an argument. */
|
|
|
+ /* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
|
|
|
+ * or not, so one of the two conditions will be unreachable by construction.
|
|
|
+ * Unfortunately the C standard does not define a way to check this at
|
|
|
+ * compile time, since the #if preprocessor conditions can not use the
|
|
|
+ * sizeof operator as an argument. */
|
|
|
#endif
|
|
|
|
|
|
if (sizeof(pthread_t) > sizeof(unsigned long)) {
|
|
@@ -1883,8 +1883,12 @@ typedef int socklen_t;
|
|
|
|
|
|
|
|
|
#if defined(NO_SSL)
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+#include "mod_mbedtls.inl"
|
|
|
+#else
|
|
|
typedef struct SSL SSL; /* dummy for SSL argument to push/pull */
|
|
|
typedef struct SSL_CTX SSL_CTX;
|
|
|
+#endif
|
|
|
#else
|
|
|
#if defined(NO_SSL_DL)
|
|
|
#include <openssl/bn.h>
|
|
@@ -2965,13 +2969,13 @@ struct mg_context {
|
|
|
pthread_t *worker_threadids; /* The worker thread IDs */
|
|
|
unsigned long starter_thread_idx; /* thread index which called mg_start */
|
|
|
|
|
|
-/* Connection to thread dispatching */
|
|
|
+ /* Connection to thread dispatching */
|
|
|
#if defined(ALTERNATIVE_QUEUE)
|
|
|
struct socket *client_socks;
|
|
|
void **client_wait_events;
|
|
|
#else
|
|
|
struct socket *squeue; /* Socket queue (sq) : accepted sockets waiting for a
|
|
|
- worker thread */
|
|
|
+ worker thread */
|
|
|
volatile int sq_head; /* Head of the socket queue */
|
|
|
volatile int sq_tail; /* Tail of the socket queue */
|
|
|
pthread_cond_t sq_full; /* Signaled when socket is produced */
|
|
@@ -2999,7 +3003,7 @@ struct mg_context {
|
|
|
struct ttimers *timers;
|
|
|
#endif
|
|
|
|
|
|
-/* Lua specific: Background operations and shared websockets */
|
|
|
+ /* Lua specific: Background operations and shared websockets */
|
|
|
#if defined(USE_LUA)
|
|
|
void *lua_background_state;
|
|
|
#endif
|
|
@@ -3067,7 +3071,7 @@ struct mg_connection {
|
|
|
int connection_type; /* see CONNECTION_TYPE_* above */
|
|
|
int protocol_type; /* see PROTOCOL_TYPE_*: 0=http/1.x, 1=ws, 2=http/2 */
|
|
|
int request_state; /* 0: nothing sent, 1: header partially sent, 2: header
|
|
|
- fully sent */
|
|
|
+ fully sent */
|
|
|
#if defined(USE_HTTP2)
|
|
|
struct mg_http2_connection http2;
|
|
|
#endif
|
|
@@ -3382,11 +3386,11 @@ mg_set_thread_name(const char *name)
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
}
|
|
|
#elif defined(__MINGW32__)
|
|
|
-/* No option known to set thread name for MinGW known */
|
|
|
+ /* No option known to set thread name for MinGW known */
|
|
|
#endif
|
|
|
#elif defined(_GNU_SOURCE) && defined(__GLIBC__) \
|
|
|
&& ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
|
|
|
-/* pthread_setname_np first appeared in glibc in version 2.12 */
|
|
|
+ /* pthread_setname_np first appeared in glibc in version 2.12 */
|
|
|
#if defined(__MACH__)
|
|
|
/* OS X only current thread name can be changed */
|
|
|
(void)pthread_setname_np(threadName);
|
|
@@ -3699,8 +3703,8 @@ mg_vsnprintf(const struct mg_connection *conn,
|
|
|
#if defined(__clang__)
|
|
|
#pragma clang diagnostic push
|
|
|
#pragma clang diagnostic ignored "-Wformat-nonliteral"
|
|
|
-/* Using fmt as a non-literal is intended here, since it is mostly called
|
|
|
- * indirectly by mg_snprintf */
|
|
|
+ /* Using fmt as a non-literal is intended here, since it is mostly called
|
|
|
+ * indirectly by mg_snprintf */
|
|
|
#endif
|
|
|
|
|
|
n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
|
|
@@ -3927,15 +3931,15 @@ sockaddr_to_string(char *buf, size_t len, const union usa *usa)
|
|
|
#if defined(USE_X_DOM_SOCKET)
|
|
|
else if (usa->sa.sa_family == AF_UNIX) {
|
|
|
/* TODO: Define a remote address for unix domain sockets.
|
|
|
- * This code will always return "localhost", identical to http+tcp:
|
|
|
+ * This code will always return "localhost", identical to http+tcp:
|
|
|
getnameinfo(&usa->sa,
|
|
|
- sizeof(usa->sun),
|
|
|
- buf,
|
|
|
- (unsigned)len,
|
|
|
- NULL,
|
|
|
- 0,
|
|
|
- NI_NUMERICHOST);
|
|
|
- */
|
|
|
+ sizeof(usa->sun),
|
|
|
+ buf,
|
|
|
+ (unsigned)len,
|
|
|
+ NULL,
|
|
|
+ 0,
|
|
|
+ NI_NUMERICHOST);
|
|
|
+ */
|
|
|
strncpy(buf, UNIX_DOMAIN_SOCKET_SERVER_NAME, len);
|
|
|
buf[len] = 0;
|
|
|
}
|
|
@@ -4182,11 +4186,11 @@ get_proto_name(const struct mg_connection *conn)
|
|
|
#if defined(__clang__)
|
|
|
#pragma clang diagnostic push
|
|
|
#pragma clang diagnostic ignored "-Wunreachable-code"
|
|
|
-/* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
|
|
|
- * not supported. Clang raises an "unreachable code" warning for parts of ?:
|
|
|
- * unreachable, but splitting into four different #ifdef clauses here is more
|
|
|
- * complicated.
|
|
|
- */
|
|
|
+ /* Depending on USE_WEBSOCKET and NO_SSL, some oft the protocols might be
|
|
|
+ * not supported. Clang raises an "unreachable code" warning for parts of ?:
|
|
|
+ * unreachable, but splitting into four different #ifdef clauses here is
|
|
|
+ * more complicated.
|
|
|
+ */
|
|
|
#endif
|
|
|
|
|
|
const struct mg_request_info *ri = &conn->request_info;
|
|
@@ -4377,7 +4381,7 @@ skip_quoted(char **buf,
|
|
|
} else {
|
|
|
|
|
|
#if defined(GCC_DIAGNOSTIC)
|
|
|
-/* Disable spurious conversion warning for GCC */
|
|
|
+ /* Disable spurious conversion warning for GCC */
|
|
|
#pragma GCC diagnostic push
|
|
|
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
|
|
#endif /* defined(GCC_DIAGNOSTIC) */
|
|
@@ -4783,7 +4787,7 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
*/
|
|
|
|
|
|
switch (response_code) {
|
|
|
- /* RFC2616 Section 10.1 - Informational 1xx */
|
|
|
+ /* RFC2616 Section 10.1 - Informational 1xx */
|
|
|
case 100:
|
|
|
return "Continue"; /* RFC2616 Section 10.1.1 */
|
|
|
case 101:
|
|
@@ -4791,7 +4795,7 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
case 102:
|
|
|
return "Processing"; /* RFC2518 Section 10.1 */
|
|
|
|
|
|
- /* RFC2616 Section 10.2 - Successful 2xx */
|
|
|
+ /* RFC2616 Section 10.2 - Successful 2xx */
|
|
|
case 200:
|
|
|
return "OK"; /* RFC2616 Section 10.2.1 */
|
|
|
case 201:
|
|
@@ -4815,7 +4819,7 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
case 226:
|
|
|
return "IM used"; /* RFC3229 Section 10.4.1 */
|
|
|
|
|
|
- /* RFC2616 Section 10.3 - Redirection 3xx */
|
|
|
+ /* RFC2616 Section 10.3 - Redirection 3xx */
|
|
|
case 300:
|
|
|
return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
|
|
|
case 301:
|
|
@@ -4833,7 +4837,7 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
case 308:
|
|
|
return "Permanent Redirect"; /* RFC7238 Section 3 */
|
|
|
|
|
|
- /* RFC2616 Section 10.4 - Client Error 4xx */
|
|
|
+ /* RFC2616 Section 10.4 - Client Error 4xx */
|
|
|
case 400:
|
|
|
return "Bad Request"; /* RFC2616 Section 10.4.1 */
|
|
|
case 401:
|
|
@@ -4898,7 +4902,7 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
|
|
|
* Section 3 */
|
|
|
|
|
|
- /* RFC2616 Section 10.5 - Server Error 5xx */
|
|
|
+ /* RFC2616 Section 10.5 - Server Error 5xx */
|
|
|
case 500:
|
|
|
return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
|
|
|
case 501:
|
|
@@ -4924,9 +4928,9 @@ mg_get_response_code_text(const struct mg_connection *conn, int response_code)
|
|
|
case 511:
|
|
|
return "Network Authentication Required"; /* RFC 6585, Section 6 */
|
|
|
|
|
|
- /* Other status codes, not shown in the IANA HTTP status code
|
|
|
- * assignment.
|
|
|
- * E.g., "de facto" standards due to common use, ... */
|
|
|
+ /* Other status codes, not shown in the IANA HTTP status code
|
|
|
+ * assignment.
|
|
|
+ * E.g., "de facto" standards due to common use, ... */
|
|
|
case 418:
|
|
|
return "I am a teapot"; /* RFC2324 Section 2.3.2 */
|
|
|
case 419:
|
|
@@ -6608,7 +6612,7 @@ push_inner(struct mg_context *ctx,
|
|
|
return -2;
|
|
|
}
|
|
|
|
|
|
-#if defined(NO_SSL)
|
|
|
+#if defined(NO_SSL) && !defined(USE_MBEDTLS)
|
|
|
if (ssl) {
|
|
|
return -2;
|
|
|
}
|
|
@@ -6640,6 +6644,25 @@ push_inner(struct mg_context *ctx,
|
|
|
}
|
|
|
} else
|
|
|
#endif
|
|
|
+
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ if (ssl != NULL) {
|
|
|
+ n = mbed_ssl_write(ssl, (const unsigned char *)buf, len);
|
|
|
+ if (n <= 0) {
|
|
|
+ if ((n == MBEDTLS_ERR_SSL_WANT_READ)
|
|
|
+ || (n == MBEDTLS_ERR_SSL_WANT_WRITE)
|
|
|
+ || n == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
|
|
|
+ n = 0;
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "SSL write failed, error %d\n", n);
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ err = 0;
|
|
|
+ }
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+
|
|
|
if (fp != NULL) {
|
|
|
n = (int)fwrite(buf, 1, (size_t)len, fp);
|
|
|
if (ferror(fp)) {
|
|
@@ -6722,7 +6745,7 @@ push_inner(struct mg_context *ctx,
|
|
|
}
|
|
|
|
|
|
(void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
|
|
|
- used */
|
|
|
+ used */
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
@@ -6867,6 +6890,62 @@ pull_inner(FILE *fp,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ } else if (conn->ssl != NULL) {
|
|
|
+ struct pollfd pfd[1];
|
|
|
+ int to_read;
|
|
|
+ int pollres;
|
|
|
+
|
|
|
+ to_read = mbedtls_ssl_get_bytes_avail(conn->ssl);
|
|
|
+
|
|
|
+ if (to_read > 0) {
|
|
|
+ /* We already know there is no more data buffered in conn->buf
|
|
|
+ * but there is more available in the SSL layer. So don't poll
|
|
|
+ * conn->client.sock yet. */
|
|
|
+
|
|
|
+ pollres = 1;
|
|
|
+ if (to_read > len)
|
|
|
+ to_read = len;
|
|
|
+ } else {
|
|
|
+ pfd[0].fd = conn->client.sock;
|
|
|
+ pfd[0].events = POLLIN;
|
|
|
+
|
|
|
+ to_read = len;
|
|
|
+
|
|
|
+ pollres = mg_poll(pfd,
|
|
|
+ 1,
|
|
|
+ (int)(timeout * 1000.0),
|
|
|
+ &(conn->phys_ctx->stop_flag));
|
|
|
+
|
|
|
+ if (conn->phys_ctx->stop_flag) {
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pollres > 0) {
|
|
|
+ nread = mbed_ssl_read(conn->ssl, (unsigned char *)buf, to_read);
|
|
|
+ if (nread <= 0) {
|
|
|
+ if ((nread == MBEDTLS_ERR_SSL_WANT_READ)
|
|
|
+ || (nread == MBEDTLS_ERR_SSL_WANT_WRITE)
|
|
|
+ || nread == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
|
|
|
+ nread = 0;
|
|
|
+ } else {
|
|
|
+ fprintf(stderr, "SSL read failed, error %d\n", nread);
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ err = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else if (pollres < 0) {
|
|
|
+ /* Error */
|
|
|
+ return -2;
|
|
|
+ } else {
|
|
|
+ /* pollres = 0 means timeout */
|
|
|
+ nread = 0;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
} else {
|
|
|
struct mg_pollfd pfd[1];
|
|
|
int pollres;
|
|
@@ -6906,7 +6985,7 @@ pull_inner(FILE *fp,
|
|
|
}
|
|
|
|
|
|
if (nread < 0) {
|
|
|
-/* socket error - check errno */
|
|
|
+ /* socket error - check errno */
|
|
|
#if defined(_WIN32)
|
|
|
if (err == WSAEWOULDBLOCK) {
|
|
|
/* TODO (low): check if this is still required */
|
|
@@ -7976,8 +8055,8 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
|
|
|
/* Step 2: Check if the request attempts to modify the file system */
|
|
|
*is_put_or_delete_request = is_put_or_delete_method(conn);
|
|
|
|
|
|
-/* Step 3: Check if it is a websocket request, and modify the document
|
|
|
- * root if required */
|
|
|
+ /* Step 3: Check if it is a websocket request, and modify the document
|
|
|
+ * root if required */
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
*is_websocket_request = (conn->protocol_type == PROTOCOL_TYPE_WEBSOCKET);
|
|
|
#if !defined(NO_FILES)
|
|
@@ -8185,7 +8264,7 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
|
|
|
size_t script_name_len = strlen(tmp_str);
|
|
|
|
|
|
/* subres_name read before this memory locatio will be
|
|
|
- overwritten */
|
|
|
+ overwritten */
|
|
|
char *subres_name = filename + sep_pos;
|
|
|
size_t subres_name_len = strlen(subres_name);
|
|
|
|
|
@@ -10188,7 +10267,7 @@ send_file_data(struct mg_connection *conn,
|
|
|
offset = (offset < 0) ? 0 : ((offset > size) ? size : offset);
|
|
|
|
|
|
if (len > 0 && filep->access.fp != NULL) {
|
|
|
-/* file stored on disk */
|
|
|
+ /* file stored on disk */
|
|
|
#if defined(__linux__)
|
|
|
/* sendfile is only available for Linux */
|
|
|
if ((conn->ssl == 0) && (conn->throttle == 0)
|
|
@@ -10467,8 +10546,8 @@ handle_static_file_request(struct mg_connection *conn,
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-/* Do not compress small files. Small files do not benefit from file
|
|
|
- * compression, but there is still some overhead. */
|
|
|
+ /* Do not compress small files. Small files do not benefit from file
|
|
|
+ * compression, but there is still some overhead. */
|
|
|
#if defined(USE_ZLIB)
|
|
|
if (filep->stat.size < MG_FILE_COMPRESSION_SIZE_LIMIT) {
|
|
|
/* File is below the size limit. */
|
|
@@ -11382,7 +11461,7 @@ struct cgi_environment {
|
|
|
char *buf; /* Environment buffer */
|
|
|
size_t buflen; /* Space available in buf */
|
|
|
size_t bufused; /* Space taken in buf */
|
|
|
- /* Index block */
|
|
|
+ /* Index block */
|
|
|
char **var; /* char **envp */
|
|
|
size_t varlen; /* Number of variables available in var */
|
|
|
size_t varused; /* Number of variables stored in var */
|
|
@@ -12937,7 +13016,7 @@ read_websocket(struct mg_connection *conn,
|
|
|
DEBUG_ASSERT(body_len >= header_len);
|
|
|
if (data_len + (uint64_t)header_len > (uint64_t)body_len) {
|
|
|
mop = buf[0]; /* current mask and opcode */
|
|
|
- /* Overflow case */
|
|
|
+ /* Overflow case */
|
|
|
len = body_len - header_len;
|
|
|
memcpy(data, buf + header_len, len);
|
|
|
error = 0;
|
|
@@ -13039,8 +13118,8 @@ read_websocket(struct mg_connection *conn,
|
|
|
size_t inflate_buf_size_old = 0;
|
|
|
size_t inflate_buf_size =
|
|
|
data_len
|
|
|
- * 10; // Initial guess of the inflated message
|
|
|
- // size. We double the memory when needed.
|
|
|
+ * 4; // Initial guess of the inflated message
|
|
|
+ // size. We double the memory when needed.
|
|
|
Bytef *inflated;
|
|
|
Bytef *new_mem;
|
|
|
conn->websocket_inflate_state.avail_in =
|
|
@@ -13064,7 +13143,7 @@ read_websocket(struct mg_connection *conn,
|
|
|
mg_cry_internal(
|
|
|
conn,
|
|
|
"Out of memory: Cannot allocate "
|
|
|
- "inflate buffer of %zu bytes",
|
|
|
+ "inflate buffer of %i bytes",
|
|
|
inflate_buf_size);
|
|
|
exit_by_callback = 1;
|
|
|
break;
|
|
@@ -13213,7 +13292,7 @@ mg_websocket_write_exec(struct mg_connection *conn,
|
|
|
int retval;
|
|
|
|
|
|
#if defined(GCC_DIAGNOSTIC)
|
|
|
-/* Disable spurious conversion warning for GCC */
|
|
|
+ /* Disable spurious conversion warning for GCC */
|
|
|
#pragma GCC diagnostic push
|
|
|
#pragma GCC diagnostic ignored "-Wconversion"
|
|
|
#endif
|
|
@@ -13252,7 +13331,7 @@ mg_websocket_write_exec(struct mg_connection *conn,
|
|
|
if (deflated == NULL) {
|
|
|
mg_cry_internal(
|
|
|
conn,
|
|
|
- "Out of memory: Cannot allocate deflate buffer of %zu bytes",
|
|
|
+ "Out of memory: Cannot allocate deflate buffer of %i bytes",
|
|
|
deflated_size);
|
|
|
mg_unlock_connection(conn);
|
|
|
return -1;
|
|
@@ -14295,7 +14374,7 @@ get_request_handler(struct mg_connection *conn,
|
|
|
&& (strcmp(tmp_rh->uri, uri) == 0);
|
|
|
} else if (step == 1) {
|
|
|
/* next try for a partial match, we will accept
|
|
|
- uri/something */
|
|
|
+ uri/something */
|
|
|
matched =
|
|
|
(tmp_rh->uri_len < urilen)
|
|
|
&& (uri[tmp_rh->uri_len] == '/')
|
|
@@ -14382,6 +14461,21 @@ experimental_websocket_client_close_wrapper(const struct mg_connection *conn,
|
|
|
#endif
|
|
|
|
|
|
|
|
|
+/* Decrement recount of handler. conn must not be NULL, handler_info may be NULL
|
|
|
+ */
|
|
|
+static void
|
|
|
+release_handler_ref(struct mg_connection *conn,
|
|
|
+ struct mg_handler_info *handler_info)
|
|
|
+{
|
|
|
+ if (handler_info != NULL) {
|
|
|
+ /* Use context lock for ref counter */
|
|
|
+ mg_lock_context(conn->phys_ctx);
|
|
|
+ handler_info->refcount--;
|
|
|
+ mg_unlock_context(conn->phys_ctx);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* This is the heart of the Civetweb's logic.
|
|
|
* This function is called when the request is read, parsed and validated,
|
|
|
* and Civetweb must decide what action to take: serve a file, or
|
|
@@ -14476,7 +14570,7 @@ handle_request(struct mg_connection *conn)
|
|
|
i = conn->phys_ctx->callbacks.begin_request(conn);
|
|
|
if (i > 0) {
|
|
|
/* callback already processed the request. Store the
|
|
|
- return value as a status code for the access log. */
|
|
|
+ return value as a status code for the access log. */
|
|
|
conn->status_code = i;
|
|
|
if (!conn->must_close) {
|
|
|
discard_unread_request_data(conn);
|
|
@@ -14626,18 +14720,25 @@ handle_request(struct mg_connection *conn)
|
|
|
&auth_callback_data,
|
|
|
NULL)) {
|
|
|
if (!auth_handler(conn, auth_callback_data)) {
|
|
|
+
|
|
|
+ /* Callback handler will not be used anymore. Release it */
|
|
|
+ release_handler_ref(conn, handler_info);
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
} else if (is_put_or_delete_request && !is_script_resource
|
|
|
&& !is_callback_resource) {
|
|
|
HTTP1_only;
|
|
|
-/* 6.2. this request is a PUT/DELETE to a real file */
|
|
|
-/* 6.2.1. thus, the server must have real files */
|
|
|
+ /* 6.2. this request is a PUT/DELETE to a real file */
|
|
|
+ /* 6.2.1. thus, the server must have real files */
|
|
|
#if defined(NO_FILES)
|
|
|
if (1) {
|
|
|
#else
|
|
|
if (conn->dom_ctx->config[DOCUMENT_ROOT] == NULL) {
|
|
|
#endif
|
|
|
+ /* This code path will not be called for request handlers */
|
|
|
+ DEBUG_ASSERT(handler_info == NULL);
|
|
|
+
|
|
|
/* This server does not have any real files, thus the
|
|
|
* PUT/DELETE methods are not valid. */
|
|
|
mg_send_http_error(conn,
|
|
@@ -14663,6 +14764,10 @@ handle_request(struct mg_connection *conn)
|
|
|
* correspond to a file. Check authorization. */
|
|
|
if (!check_authorization(conn, path)) {
|
|
|
send_authorization_request(conn, NULL);
|
|
|
+
|
|
|
+ /* Callback handler will not be used anymore. Release it */
|
|
|
+ release_handler_ref(conn, handler_info);
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -14676,9 +14781,7 @@ handle_request(struct mg_connection *conn)
|
|
|
i = callback_handler(conn, callback_data);
|
|
|
|
|
|
/* Callback handler will not be used anymore. Release it */
|
|
|
- mg_lock_context(conn->phys_ctx);
|
|
|
- handler_info->refcount--;
|
|
|
- mg_unlock_context(conn->phys_ctx);
|
|
|
+ release_handler_ref(conn, handler_info);
|
|
|
|
|
|
if (i > 0) {
|
|
|
/* Do nothing, callback has served the request. Store
|
|
@@ -14744,7 +14847,7 @@ handle_request(struct mg_connection *conn)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-/* 8. handle websocket requests */
|
|
|
+ /* 8. handle websocket requests */
|
|
|
#if defined(USE_WEBSOCKET)
|
|
|
if (is_websocket_request) {
|
|
|
HTTP1_only;
|
|
@@ -15379,7 +15482,7 @@ set_ports_option(struct mg_context *phys_ctx)
|
|
|
#endif
|
|
|
|
|
|
if (ip_version > 4) {
|
|
|
-/* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */
|
|
|
+ /* Could be 6 for IPv6 onlyor 10 (4+6) for IPv4+IPv6 */
|
|
|
#if defined(USE_IPV6)
|
|
|
if (ip_version > 6) {
|
|
|
if (so.lsa.sa.sa_family == AF_INET6
|
|
@@ -15518,7 +15621,7 @@ set_ports_option(struct mg_context *phys_ctx)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
-/* Update lsa port in case of random free ports */
|
|
|
+ /* Update lsa port in case of random free ports */
|
|
|
#if defined(USE_IPV6)
|
|
|
if (so.lsa.sa.sa_family == AF_INET6) {
|
|
|
so.lsa.sin6.sin6_port = usa.sin6.sin6_port;
|
|
@@ -17054,6 +17157,37 @@ uninitialize_ssl(void)
|
|
|
}
|
|
|
#endif /* !NO_SSL */
|
|
|
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+/* Check if SSL is required.
|
|
|
+ * If so, set up ctx->ssl_ctx pointer. */
|
|
|
+static int
|
|
|
+mg_sslctx_init(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
|
|
|
+{
|
|
|
+ if (!phys_ctx) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!dom_ctx) {
|
|
|
+ dom_ctx = &(phys_ctx->dd);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!is_ssl_port_used(dom_ctx->config[LISTENING_PORTS])) {
|
|
|
+ /* No SSL port is set. No need to setup SSL. */
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ dom_ctx->ssl_ctx = mg_calloc(1, sizeof(*dom_ctx->ssl_ctx));
|
|
|
+ if (dom_ctx->ssl_ctx == NULL) {
|
|
|
+ fprintf(stderr, "ssl_ctx malloc failed\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return mbed_sslctx_init(dom_ctx->ssl_ctx, dom_ctx->config[SSL_CERTIFICATE])
|
|
|
+ == 0
|
|
|
+ ? 1
|
|
|
+ : 0;
|
|
|
+}
|
|
|
+#endif /* USE_MBEDTLS */
|
|
|
|
|
|
#if !defined(NO_FILESYSTEMS)
|
|
|
static int
|
|
@@ -17316,6 +17450,13 @@ close_connection(struct mg_connection *conn)
|
|
|
conn->conn_state = 7; /* closing */
|
|
|
#endif
|
|
|
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ if (conn->ssl != NULL) {
|
|
|
+ mbed_ssl_close(conn->ssl);
|
|
|
+ conn->ssl = NULL;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
#if !defined(NO_SSL)
|
|
|
if (conn->ssl != NULL) {
|
|
|
/* Run SSL_shutdown twice to ensure completely close SSL connection
|
|
@@ -18320,7 +18461,7 @@ websocket_client_thread(void *data)
|
|
|
}
|
|
|
|
|
|
/* The websocket_client context has only this thread. If it runs out,
|
|
|
- set the stop_flag to 2 (= "stopped"). */
|
|
|
+ set the stop_flag to 2 (= "stopped"). */
|
|
|
STOP_FLAG_ASSIGN(&cdata->conn->phys_ctx->stop_flag, 2);
|
|
|
|
|
|
if (cdata->conn->phys_ctx->callbacks.exit_thread) {
|
|
@@ -18722,7 +18863,6 @@ process_new_connection(struct mg_connection *conn)
|
|
|
/* Loop over multiple requests sent using the same connection
|
|
|
* (while "keep alive"). */
|
|
|
do {
|
|
|
-
|
|
|
DEBUG_TRACE("calling get_request (%i times for this connection)",
|
|
|
conn->handled_requests + 1);
|
|
|
|
|
@@ -18816,7 +18956,7 @@ process_new_connection(struct mg_connection *conn)
|
|
|
if (ebuf[0] == '\0') {
|
|
|
if (conn->request_info.local_uri) {
|
|
|
|
|
|
-/* handle request to local server */
|
|
|
+ /* handle request to local server */
|
|
|
#if defined(USE_SERVER_STATS)
|
|
|
conn->conn_state = 4; /* processing */
|
|
|
#endif
|
|
@@ -18881,6 +19021,7 @@ process_new_connection(struct mg_connection *conn)
|
|
|
? (int)(conn->request_len + conn->content_len)
|
|
|
: conn->data_len;
|
|
|
conn->data_len -= discard_len;
|
|
|
+
|
|
|
if (conn->data_len > 0) {
|
|
|
DEBUG_TRACE("discard_len = %d", discard_len);
|
|
|
memmove(conn->buf,
|
|
@@ -18898,9 +19039,7 @@ process_new_connection(struct mg_connection *conn)
|
|
|
(long int)conn->buf_size);
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
conn->handled_requests++;
|
|
|
-
|
|
|
} while (keep_alive);
|
|
|
|
|
|
DEBUG_TRACE("Done processing connection from %s (%f sec)",
|
|
@@ -19158,12 +19297,33 @@ worker_thread_run(struct mg_connection *conn)
|
|
|
sizeof(conn->request_info.remote_addr),
|
|
|
&conn->client.rsa);
|
|
|
|
|
|
- DEBUG_TRACE("Start processing connection from %s",
|
|
|
+ DEBUG_TRACE("Incomming %sconnection from %s",
|
|
|
+ (conn->client.is_ssl ? "SSL " : ""),
|
|
|
conn->request_info.remote_addr);
|
|
|
|
|
|
conn->request_info.is_ssl = conn->client.is_ssl;
|
|
|
|
|
|
if (conn->client.is_ssl) {
|
|
|
+
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ /* HTTPS connection */
|
|
|
+ if (mbed_ssl_accept(&(conn->ssl),
|
|
|
+ conn->dom_ctx->ssl_ctx,
|
|
|
+ &(conn->client.sock),
|
|
|
+ conn->phys_ctx)
|
|
|
+ == 0) {
|
|
|
+ /* conn->dom_ctx is set in get_request */
|
|
|
+ /* process HTTPS connection */
|
|
|
+ init_connection(conn);
|
|
|
+ conn->connection_type = CONNECTION_TYPE_REQUEST;
|
|
|
+ conn->protocol_type = PROTOCOL_TYPE_HTTP1;
|
|
|
+ process_new_connection(conn);
|
|
|
+ } else {
|
|
|
+ /* make sure the connection is cleaned up on SSL failure */
|
|
|
+ close_connection(conn);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
#if !defined(NO_SSL)
|
|
|
/* HTTPS connection */
|
|
|
if (sslize(conn, SSL_accept, NULL)) {
|
|
@@ -19389,7 +19549,7 @@ master_thread_run(struct mg_context *ctx)
|
|
|
|
|
|
mg_set_thread_name("master");
|
|
|
|
|
|
-/* Increase priority of the master thread */
|
|
|
+ /* Increase priority of the master thread */
|
|
|
#if defined(_WIN32)
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
|
|
|
#elif defined(USE_MASTER_THREAD_PRIORITY)
|
|
@@ -19404,7 +19564,7 @@ master_thread_run(struct mg_context *ctx)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-/* Initialize thread local storage */
|
|
|
+ /* Initialize thread local storage */
|
|
|
#if defined(_WIN32)
|
|
|
tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
#endif
|
|
@@ -19592,6 +19752,14 @@ free_context(struct mg_context *ctx)
|
|
|
mg_free(tmp_rh);
|
|
|
}
|
|
|
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ if (ctx->dd.ssl_ctx != NULL) {
|
|
|
+ mbed_sslctx_uninit(ctx->dd.ssl_ctx);
|
|
|
+ mg_free(ctx->dd.ssl_ctx);
|
|
|
+ ctx->dd.ssl_ctx = NULL;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
#if !defined(NO_SSL)
|
|
|
/* Deallocate SSL context */
|
|
|
if (ctx->dd.ssl_ctx != NULL) {
|
|
@@ -19682,7 +19850,7 @@ get_system_name(char **sysName)
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
|
#pragma warning(push)
|
|
|
-/* GetVersion was declared deprecated */
|
|
|
+ /* GetVersion was declared deprecated */
|
|
|
#pragma warning(disable : 4996)
|
|
|
#endif
|
|
|
dwVersion = GetVersion();
|
|
@@ -19989,7 +20157,7 @@ static
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-/* Document root */
|
|
|
+ /* Document root */
|
|
|
#if defined(NO_FILES)
|
|
|
if (ctx->dd.config[DOCUMENT_ROOT] != NULL) {
|
|
|
mg_cry_ctx_internal(ctx, "%s", "Document root must not be set");
|
|
@@ -20109,6 +20277,26 @@ static
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+#if defined(USE_MBEDTLS)
|
|
|
+ if (!mg_sslctx_init(ctx, NULL)) {
|
|
|
+ const char *err_msg = "Error initializing SSL context";
|
|
|
+ /* Fatal error - abort start. */
|
|
|
+ mg_cry_ctx_internal(ctx, "%s", err_msg);
|
|
|
+
|
|
|
+ if ((error != NULL) && (error->text_buffer_size > 0)) {
|
|
|
+ mg_snprintf(NULL,
|
|
|
+ NULL, /* No truncation check for error buffers */
|
|
|
+ error->text,
|
|
|
+ error->text_buffer_size,
|
|
|
+ "%s",
|
|
|
+ err_msg);
|
|
|
+ }
|
|
|
+ free_context(ctx);
|
|
|
+ pthread_setspecific(sTlsKey, NULL);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
#if !defined(NO_SSL)
|
|
|
if (!init_ssl_ctx(ctx, NULL)) {
|
|
|
const char *err_msg = "Error initializing SSL context";
|
|
@@ -20608,13 +20796,13 @@ unsigned
|
|
|
mg_check_feature(unsigned feature)
|
|
|
{
|
|
|
static const unsigned feature_set = 0
|
|
|
-/* Set bits for available features according to API documentation.
|
|
|
- * This bit mask is created at compile time, according to the active
|
|
|
- * preprocessor defines. It is a single const value at runtime. */
|
|
|
+ /* Set bits for available features according to API documentation.
|
|
|
+ * This bit mask is created at compile time, according to the active
|
|
|
+ * preprocessor defines. It is a single const value at runtime. */
|
|
|
#if !defined(NO_FILES)
|
|
|
| MG_FEATURES_FILES
|
|
|
#endif
|
|
|
-#if !defined(NO_SSL)
|
|
|
+#if !defined(NO_SSL) || defined(USE_MBEDTLS)
|
|
|
| MG_FEATURES_SSL
|
|
|
#endif
|
|
|
#if !defined(NO_CGI)
|
|
@@ -20648,8 +20836,8 @@ mg_check_feature(unsigned feature)
|
|
|
| MG_FEATURES_X_DOMAIN_SOCKET
|
|
|
#endif
|
|
|
|
|
|
-/* Set some extra bits not defined in the API documentation.
|
|
|
- * These bits may change without further notice. */
|
|
|
+ /* Set some extra bits not defined in the API documentation.
|
|
|
+ * These bits may change without further notice. */
|
|
|
#if defined(MG_LEGACY_INTERFACE)
|
|
|
| 0x80000000u
|
|
|
#endif
|
|
@@ -20740,7 +20928,7 @@ mg_get_system_info(char *buffer, int buflen)
|
|
|
|
|
|
#if defined(_MSC_VER)
|
|
|
#pragma warning(push)
|
|
|
-/* GetVersion was declared deprecated */
|
|
|
+ /* GetVersion was declared deprecated */
|
|
|
#pragma warning(disable : 4996)
|
|
|
#endif
|
|
|
dwVersion = GetVersion();
|
|
@@ -21048,7 +21236,7 @@ mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
|
|
|
context_info_length += mg_str_append(&buffer, end, "{");
|
|
|
|
|
|
if (ms) { /* <-- should be always true */
|
|
|
- /* Memory information */
|
|
|
+ /* Memory information */
|
|
|
int blockCount = (int)ms->blockCount;
|
|
|
int64_t totalMemUsed = ms->totalMemUsed;
|
|
|
int64_t maxMemUsed = ms->maxMemUsed;
|