Forráskód Böngészése

Add strdup allocations to memory statistics of context

mg_strdup: Replace most calls by new function mg_strdup_ctx
conn->host: set host when reading requests
bel2125 7 éve
szülő
commit
5081212c62
2 módosított fájl, 87 hozzáadás és 42 törlés
  1. 78 41
      src/civetweb.c
  2. 9 1
      src/mod_lua.inl

+ 78 - 41
src/civetweb.c

@@ -141,12 +141,14 @@ static void DEBUG_TRACE_FUNC(const char *func,
                              ...) PRINTF_ARGS(3, 4);
                              ...) PRINTF_ARGS(3, 4);
 
 
 #define DEBUG_TRACE(fmt, ...)                                                  \
 #define DEBUG_TRACE(fmt, ...)                                                  \
-    DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
+	DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
+
+#define NEED_DEBUG_TRACE_FUNC
 
 
 #else
 #else
 #define DEBUG_TRACE(fmt, ...)                                                  \
 #define DEBUG_TRACE(fmt, ...)                                                  \
-    do {                                                                       \
-    } while (0)
+	do {                                                                       \
+	} while (0)
 #endif /* DEBUG */
 #endif /* DEBUG */
 #endif /* DEBUG_TRACE */
 #endif /* DEBUG_TRACE */
 
 
@@ -154,16 +156,16 @@ static void DEBUG_TRACE_FUNC(const char *func,
 #if !defined(DEBUG_ASSERT)
 #if !defined(DEBUG_ASSERT)
 #if defined(DEBUG)
 #if defined(DEBUG)
 #define DEBUG_ASSERT(cond)                                                     \
 #define DEBUG_ASSERT(cond)                                                     \
-    do {                                                                       \
-        if (!(cond)) {                                                         \
-            DEBUG_TRACE("ASSERTION FAILED: %s", #cond);                        \
-            exit(2); /* Exit with error */                                     \
-        }                                                                      \
-    } while (0)
+	do {                                                                       \
+		if (!(cond)) {                                                         \
+			DEBUG_TRACE("ASSERTION FAILED: %s", #cond);                        \
+			exit(2); /* Exit with error */                                     \
+		}                                                                      \
+	} while (0)
 #else
 #else
 #define DEBUG_ASSERT(cond)                                                     \
 #define DEBUG_ASSERT(cond)                                                     \
-    do {                                                                       \
-    } while (0)
+	do {                                                                       \
+	} while (0)
 #endif /* DEBUG */
 #endif /* DEBUG */
 #endif
 #endif
 
 
@@ -1505,8 +1507,7 @@ mg_get_current_time_ns(void)
 #endif
 #endif
 
 
 
 
-#if !defined(DEBUG_TRACE)
-#if defined(DEBUG)
+#if defined(NEED_DEBUG_TRACE_FUNC)
 static void
 static void
 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
 DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
 {
 {
@@ -1542,8 +1543,7 @@ DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
 	funlockfile(stdout);
 	funlockfile(stdout);
 	nslast = nsnow;
 	nslast = nsnow;
 }
 }
-#endif /* DEBUG */
-#endif /* DEBUG_TRACE */
+#endif /* NEED_DEBUG_TRACE_FUNC */
 
 
 
 
 #define MD5_STATIC static
 #define MD5_STATIC static
@@ -2487,6 +2487,7 @@ struct mg_connection {
 	                 * mg_get_connection_info_impl */
 	                 * mg_get_connection_info_impl */
 #endif
 #endif
 
 
+	const char *host;         /* Host (HTTP/1.1 header or SNI) */
 	SSL *ssl;                 /* SSL descriptor */
 	SSL *ssl;                 /* SSL descriptor */
 	SSL_CTX *client_ssl_ctx;  /* SSL context for client connections */
 	SSL_CTX *client_ssl_ctx;  /* SSL context for client connections */
 	struct socket client;     /* Connected client */
 	struct socket client;     /* Connected client */
@@ -3092,11 +3093,11 @@ mg_strcasecmp(const char *s1, const char *s2)
 
 
 
 
 static char *
 static char *
-mg_strndup(const char *ptr, size_t len)
+mg_strndup_ctx(const char *ptr, size_t len, struct mg_context *ctx)
 {
 {
 	char *p;
 	char *p;
 
 
-	if ((p = (char *)mg_malloc(len + 1)) != NULL) {
+	if ((p = (char *)mg_malloc_ctx(len + 1, ctx)) != NULL) {
 		mg_strlcpy(p, ptr, len + 1);
 		mg_strlcpy(p, ptr, len + 1);
 	}
 	}
 
 
@@ -3105,9 +3106,15 @@ mg_strndup(const char *ptr, size_t len)
 
 
 
 
 static char *
 static char *
+mg_strdup_ctx(const char *str, struct mg_context *ctx)
+{
+	return mg_strndup_ctx(str, strlen(str), ctx);
+}
+
+static char *
 mg_strdup(const char *str)
 mg_strdup(const char *str)
 {
 {
-	return mg_strndup(str, strlen(str));
+	return mg_strndup_ctx(str, strlen(str), NULL);
 }
 }
 
 
 
 
@@ -7048,7 +7055,8 @@ interpret_uri(struct mg_connection *conn, /* in/out: request (must be valid) */
 						            filename);
 						            filename);
 
 
 						/* this index file is a script */
 						/* this index file is a script */
-						tmp_str2 = mg_strdup(filename + sep_pos + 1);
+						tmp_str2 = mg_strdup_ctx(filename + sep_pos + 1,
+						                         conn->phys_ctx);
 						mg_snprintf(conn,
 						mg_snprintf(conn,
 						            &truncated,
 						            &truncated,
 						            filename,
 						            filename,
@@ -7675,7 +7683,8 @@ parse_auth_header(struct mg_connection *conn,
 
 
 	/* CGI needs it as REMOTE_USER */
 	/* CGI needs it as REMOTE_USER */
 	if (ah->user != NULL) {
 	if (ah->user != NULL) {
-		conn->request_info.remote_user = mg_strdup(ah->user);
+		conn->request_info.remote_user =
+		    mg_strdup_ctx(ah->user, conn->phys_ctx);
 	} else {
 	} else {
 		return 0;
 		return 0;
 	}
 	}
@@ -8268,7 +8277,7 @@ connect_socket(struct mg_context *ctx /* may be NULL */,
 		/* While getaddrinfo on Windows will work with [::1],
 		/* While getaddrinfo on Windows will work with [::1],
 		 * getaddrinfo on Linux only works with ::1 (without []). */
 		 * getaddrinfo on Linux only works with ::1 (without []). */
 		size_t l = strlen(host + 1);
 		size_t l = strlen(host + 1);
-		char *h = (l > 1) ? mg_strdup(host + 1) : NULL;
+		char *h = (l > 1) ? mg_strdup_ctx(host + 1, ctx) : NULL;
 		if (h) {
 		if (h) {
 			h[l - 1] = 0;
 			h[l - 1] = 0;
 			if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
 			if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
@@ -12141,14 +12150,18 @@ get_first_ssl_listener_index(const struct mg_context *ctx)
 }
 }
 
 
 
 
-static void
-redirect_to_https_port(struct mg_connection *conn, int ssl_index)
+/* Return host (without port) */
+/* Use mg_free to free the result */
+static const char *
+alloc_get_host(struct mg_connection *conn)
 {
 {
 	char host[1025];
 	char host[1025];
 	const char *host_header;
 	const char *host_header;
 	size_t hostlen;
 	size_t hostlen;
 
 
-	host_header = mg_get_header(conn, "Host");
+	host_header = get_header(conn->request_info.http_headers,
+	                         conn->request_info.num_headers,
+	                         "Host");
 	hostlen = sizeof(host);
 	hostlen = sizeof(host);
 	if (host_header != NULL) {
 	if (host_header != NULL) {
 		char *pos;
 		char *pos;
@@ -12159,19 +12172,26 @@ redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 		if (pos != NULL) {
 		if (pos != NULL) {
 			*pos = '\0';
 			*pos = '\0';
 		}
 		}
+		DEBUG_TRACE("Host: %s", host);
 	} else {
 	} else {
-		/* Cannot get host from the Host: header.
-		 * Fallback to our IP address. */
-		if (conn) {
-			sockaddr_to_string(host, hostlen, &conn->client.lsa);
-		}
+		sockaddr_to_string(host, hostlen, &conn->client.lsa);
+		DEBUG_TRACE("IP: %s", host);
 	}
 	}
 
 
+	return mg_strdup_ctx(host, conn->phys_ctx);
+}
+
+
+static void
+redirect_to_https_port(struct mg_connection *conn, int ssl_index)
+{
+	conn->must_close = 1;
+
 	/* Send host, port, uri and (if it exists) ?query_string */
 	/* Send host, port, uri and (if it exists) ?query_string */
-	if (conn) {
+	if (conn->host) {
 		mg_printf(conn,
 		mg_printf(conn,
 		          "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
 		          "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
-		          host,
+		          conn->host,
 #if defined(USE_IPV6)
 #if defined(USE_IPV6)
 		          (conn->phys_ctx->listening_sockets[ssl_index].lsa.sa.sa_family
 		          (conn->phys_ctx->listening_sockets[ssl_index].lsa.sa.sa_family
 		           == AF_INET6)
 		           == AF_INET6)
@@ -12318,7 +12338,7 @@ mg_set_handler_type(struct mg_context *phys_ctx,
 		       "Cannot create new request handler struct, OOM");
 		       "Cannot create new request handler struct, OOM");
 		return;
 		return;
 	}
 	}
-	tmp_rh->uri = mg_strdup(uri);
+	tmp_rh->uri = mg_strdup_ctx(uri, phys_ctx);
 	if (!tmp_rh->uri) {
 	if (!tmp_rh->uri) {
 		mg_unlock_context(phys_ctx);
 		mg_unlock_context(phys_ctx);
 		mg_free(tmp_rh);
 		mg_free(tmp_rh);
@@ -14105,10 +14125,14 @@ ssl_get_client_cert_info(struct mg_connection *conn)
 		    mg_malloc_ctx(sizeof(struct mg_client_cert), conn->phys_ctx);
 		    mg_malloc_ctx(sizeof(struct mg_client_cert), conn->phys_ctx);
 		if (conn->request_info.client_cert) {
 		if (conn->request_info.client_cert) {
 			conn->request_info.client_cert->peer_cert = (void *)cert;
 			conn->request_info.client_cert->peer_cert = (void *)cert;
-			conn->request_info.client_cert->subject = mg_strdup(str_subject);
-			conn->request_info.client_cert->issuer = mg_strdup(str_issuer);
-			conn->request_info.client_cert->serial = mg_strdup(str_serial);
-			conn->request_info.client_cert->finger = mg_strdup(str_finger);
+			conn->request_info.client_cert->subject =
+			    mg_strdup_ctx(str_subject, conn->phys_ctx);
+			conn->request_info.client_cert->issuer =
+			    mg_strdup_ctx(str_issuer, conn->phys_ctx);
+			conn->request_info.client_cert->serial =
+			    mg_strdup_ctx(str_serial, conn->phys_ctx);
+			conn->request_info.client_cert->finger =
+			    mg_strdup_ctx(str_finger, conn->phys_ctx);
 		} else {
 		} else {
 			mg_cry(conn,
 			mg_cry(conn,
 			       "Out of memory: Cannot allocate memory for client "
 			       "Out of memory: Cannot allocate memory for client "
@@ -15122,6 +15146,11 @@ close_connection(struct mg_connection *conn)
 		conn->client.sock = INVALID_SOCKET;
 		conn->client.sock = INVALID_SOCKET;
 	}
 	}
 
 
+	if (conn->host) {
+		mg_free((void *)conn->host);
+		conn->host = NULL;
+	}
+
 	mg_unlock_connection(conn);
 	mg_unlock_connection(conn);
 
 
 #if defined(USE_SERVER_STATS)
 #if defined(USE_SERVER_STATS)
@@ -15729,6 +15758,11 @@ get_request(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
 	}
 	}
 
 
 	/* Message is a valid request */
 	/* Message is a valid request */
+
+	/* Is there a "host" ? */
+	conn->host = alloc_get_host(conn);
+
+	/* Do we know the content length? */
 	if ((cl = get_header(conn->request_info.http_headers,
 	if ((cl = get_header(conn->request_info.http_headers,
 	                     conn->request_info.num_headers,
 	                     conn->request_info.num_headers,
 	                     "Content-Length")) != NULL) {
 	                     "Content-Length")) != NULL) {
@@ -15789,6 +15823,8 @@ get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
 	}
 	}
 
 
 	/* Message is a valid response */
 	/* Message is a valid response */
+
+	/* Do we know the content length? */
 	if ((cl = get_header(conn->response_info.http_headers,
 	if ((cl = get_header(conn->response_info.http_headers,
 	                     conn->response_info.num_headers,
 	                     conn->response_info.num_headers,
 	                     "Content-Length")) != NULL) {
 	                     "Content-Length")) != NULL) {
@@ -16528,7 +16564,8 @@ worker_thread_run(struct worker_thread_args *thread_args)
 	conn->buf_size = (int)ctx->max_request_size;
 	conn->buf_size = (int)ctx->max_request_size;
 
 
 	conn->phys_ctx = ctx;
 	conn->phys_ctx = ctx;
-	conn->dom_ctx = &(ctx->dd); /* Use default domain, until more is knwon */
+	conn->dom_ctx = &(ctx->dd); /* Use default domain and default host */
+	conn->host = NULL;          /* until we have more information. */
 
 
 	conn->thread_index = thread_args->index;
 	conn->thread_index = thread_args->index;
 	conn->request_info.user_data = ctx->user_data;
 	conn->request_info.user_data = ctx->user_data;
@@ -17177,7 +17214,7 @@ mg_start(const struct mg_callbacks *callbacks,
 			mg_cry(fc(ctx), "warning: %s: duplicate option", name);
 			mg_cry(fc(ctx), "warning: %s: duplicate option", name);
 			mg_free(ctx->dd.config[idx]);
 			mg_free(ctx->dd.config[idx]);
 		}
 		}
-		ctx->dd.config[idx] = mg_strdup(value);
+		ctx->dd.config[idx] = mg_strdup_ctx(value, ctx);
 		DEBUG_TRACE("[%s] -> [%s]", name, value);
 		DEBUG_TRACE("[%s] -> [%s]", name, value);
 	}
 	}
 
 
@@ -17185,7 +17222,7 @@ mg_start(const struct mg_callbacks *callbacks,
 	for (i = 0; config_options[i].name != NULL; i++) {
 	for (i = 0; config_options[i].name != NULL; i++) {
 		default_value = config_options[i].default_value;
 		default_value = config_options[i].default_value;
 		if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
 		if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
-			ctx->dd.config[i] = mg_strdup(default_value);
+			ctx->dd.config[i] = mg_strdup_ctx(default_value, ctx);
 		}
 		}
 	}
 	}
 
 
@@ -17445,7 +17482,7 @@ mg_start_domain(struct mg_context *ctx, const char **options)
 			mg_cry(fc(ctx), "warning: %s: duplicate option", name);
 			mg_cry(fc(ctx), "warning: %s: duplicate option", name);
 			mg_free(new_dom->config[idx]);
 			mg_free(new_dom->config[idx]);
 		}
 		}
-		new_dom->config[idx] = mg_strdup(value);
+		new_dom->config[idx] = mg_strdup_ctx(value, ctx);
 		DEBUG_TRACE("[%s] -> [%s]", name, value);
 		DEBUG_TRACE("[%s] -> [%s]", name, value);
 	}
 	}
 
 
@@ -17460,7 +17497,7 @@ mg_start_domain(struct mg_context *ctx, const char **options)
 	for (i = 0; config_options[i].name != NULL; i++) {
 	for (i = 0; config_options[i].name != NULL; i++) {
 		default_value = ctx->dd.config[i];
 		default_value = ctx->dd.config[i];
 		if ((new_dom->config[i] == NULL) && (default_value != NULL)) {
 		if ((new_dom->config[i] == NULL) && (default_value != NULL)) {
-			new_dom->config[i] = mg_strdup(default_value);
+			new_dom->config[i] = mg_strdup_ctx(default_value, ctx);
 		}
 		}
 	}
 	}
 
 

+ 9 - 1
src/mod_lua.inl

@@ -2090,13 +2090,21 @@ lua_websocket_new(const char *script, struct mg_connection *conn)
 		    (struct mg_shared_lua_websocket_list *)mg_calloc_ctx(
 		    (struct mg_shared_lua_websocket_list *)mg_calloc_ctx(
 		        sizeof(struct mg_shared_lua_websocket_list), 1, conn->phys_ctx);
 		        sizeof(struct mg_shared_lua_websocket_list), 1, conn->phys_ctx);
 		if (*shared_websock_list == NULL) {
 		if (*shared_websock_list == NULL) {
+			conn->must_close = 1;
 			mg_unlock_context(conn->phys_ctx);
 			mg_unlock_context(conn->phys_ctx);
 			mg_cry(conn, "Cannot create shared websocket struct, OOM");
 			mg_cry(conn, "Cannot create shared websocket struct, OOM");
 			return NULL;
 			return NULL;
 		}
 		}
 		/* init ws list element */
 		/* init ws list element */
 		ws = &(*shared_websock_list)->ws;
 		ws = &(*shared_websock_list)->ws;
-		ws->script = mg_strdup(script); /* TODO (low): handle OOM */
+		ws->script =
+		    mg_strdup_ctx(script, conn->phys_ctx); /* TODO (low): handle OOM */
+		if (!ws->script) {
+			conn->must_close = 1;
+			mg_unlock_context(conn->phys_ctx);
+			mg_cry(conn, "Cannot create shared websocket script, OOM");
+			return NULL;
+		}
 		pthread_mutex_init(&(ws->ws_mutex), &pthread_mutex_attr);
 		pthread_mutex_init(&(ws->ws_mutex), &pthread_mutex_attr);
 		(void)pthread_mutex_lock(&(ws->ws_mutex));
 		(void)pthread_mutex_lock(&(ws->ws_mutex));
 		ws->state = lua_newstate(lua_allocator, (void *)(conn->phys_ctx));
 		ws->state = lua_newstate(lua_allocator, (void *)(conn->phys_ctx));