forked from cory/tildefriends
		
	Stop leaking the TLS context.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4802 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										22
									
								
								src/http.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/http.c
									
									
									
									
									
								
							@@ -77,6 +77,8 @@ typedef struct _tf_http_listener_t
 | 
				
			|||||||
	tf_http_t* http;
 | 
						tf_http_t* http;
 | 
				
			||||||
	tf_tls_context_t* tls;
 | 
						tf_tls_context_t* tls;
 | 
				
			||||||
	uv_tcp_t tcp;
 | 
						uv_tcp_t tcp;
 | 
				
			||||||
 | 
						tf_http_cleanup_t* cleanup;
 | 
				
			||||||
 | 
						void* user_data;
 | 
				
			||||||
} tf_http_listener_t;
 | 
					} tf_http_listener_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _tf_http_t
 | 
					typedef struct _tf_http_t
 | 
				
			||||||
@@ -606,10 +608,17 @@ static void _http_on_connection(uv_stream_t* stream, int status)
 | 
				
			|||||||
	http->connections[http->connections_count++] = connection;
 | 
						http->connections[http->connections_count++] = connection;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
					int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
 | 
						tf_http_listener_t* listener = tf_malloc(sizeof(tf_http_listener_t));
 | 
				
			||||||
	*listener = (tf_http_listener_t) { .http = http, .tls = tls, .tcp = { .data = listener } };
 | 
						*listener = (tf_http_listener_t)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.http = http,
 | 
				
			||||||
 | 
							.tls = tls,
 | 
				
			||||||
 | 
							.tcp = { .data = listener },
 | 
				
			||||||
 | 
							.cleanup = cleanup,
 | 
				
			||||||
 | 
							.user_data = user_data,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	int r = uv_tcp_init(http->loop, &listener->tcp);
 | 
						int r = uv_tcp_init(http->loop, &listener->tcp);
 | 
				
			||||||
	if (r)
 | 
						if (r)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -651,7 +660,7 @@ int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (r == 0)
 | 
						if (r == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		http->listeners = tf_realloc(http->listeners, sizeof(tf_http_listener_t*) * (http->listeners_count + 1));
 | 
							http->listeners = tf_resize_vec(http->listeners, sizeof(tf_http_listener_t*) * (http->listeners_count + 1));
 | 
				
			||||||
		http->listeners[http->listeners_count++] = listener;
 | 
							http->listeners[http->listeners_count++] = listener;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return assigned_port;
 | 
						return assigned_port;
 | 
				
			||||||
@@ -680,7 +689,12 @@ void tf_http_destroy(tf_http_t* http)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	for (int i = 0; i < http->listeners_count; i++)
 | 
						for (int i = 0; i < http->listeners_count; i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uv_close((uv_handle_t*)&http->listeners[i]->tcp, _http_free_listener_on_close);
 | 
							tf_http_listener_t* listener = http->listeners[i];
 | 
				
			||||||
 | 
							if (listener->cleanup)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								listener->cleanup(listener->user_data);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							uv_close((uv_handle_t*)&listener->tcp, _http_free_listener_on_close);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	tf_free(http->listeners);
 | 
						tf_free(http->listeners);
 | 
				
			||||||
	http->listeners = NULL;
 | 
						http->listeners = NULL;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ typedef void (tf_http_cleanup_t)(void* user_data);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
tf_http_t* tf_http_create(uv_loop_t* loop);
 | 
					tf_http_t* tf_http_create(uv_loop_t* loop);
 | 
				
			||||||
void tf_http_set_trace(tf_http_t* http, tf_trace_t* trace);
 | 
					void tf_http_set_trace(tf_http_t* http, tf_trace_t* trace);
 | 
				
			||||||
int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls);
 | 
					int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data);
 | 
				
			||||||
void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, tf_http_cleanup_t* cleanup, void* user_data);
 | 
					void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, tf_http_cleanup_t* cleanup, void* user_data);
 | 
				
			||||||
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
 | 
					void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
 | 
				
			||||||
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
 | 
					size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -347,20 +347,34 @@ static JSValue _httpd_endpoint_all(JSContext* context, JSValueConst this_val, in
 | 
				
			|||||||
	const char* pattern = JS_ToCString(context, argv[0]);
 | 
						const char* pattern = JS_ToCString(context, argv[0]);
 | 
				
			||||||
	http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
 | 
						http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
 | 
				
			||||||
	*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
 | 
						*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
 | 
				
			||||||
	/* TODO: This leaks the callback. */
 | 
					 | 
				
			||||||
	tf_http_add_handler(http, pattern, _httpd_callback, _httpd_cleanup_callback, data);
 | 
						tf_http_add_handler(http, pattern, _httpd_callback, _httpd_cleanup_callback, data);
 | 
				
			||||||
	JS_FreeCString(context, pattern);
 | 
						JS_FreeCString(context, pattern);
 | 
				
			||||||
	return JS_UNDEFINED;
 | 
						return JS_UNDEFINED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct _httpd_listener_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						JSContext* context;
 | 
				
			||||||
 | 
						JSValue tls;
 | 
				
			||||||
 | 
					} httpd_listener_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void _httpd_listener_cleanup(void* user_data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						httpd_listener_t* listener = user_data;
 | 
				
			||||||
 | 
						JS_FreeValue(listener->context, listener->tls);
 | 
				
			||||||
 | 
						tf_free(listener);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static JSValue _httpd_endpoint_start(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
					static JSValue _httpd_endpoint_start(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id);
 | 
						tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id);
 | 
				
			||||||
	int port = 0;
 | 
						int port = 0;
 | 
				
			||||||
	JS_ToInt32(context, &port, argv[0]);
 | 
						JS_ToInt32(context, &port, argv[0]);
 | 
				
			||||||
	/* TODO: This leaks the TLS context. */
 | 
					
 | 
				
			||||||
	tf_tls_context_t* tls = tf_tls_context_get(JS_DupValue(context, argv[1]));
 | 
						httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
 | 
				
			||||||
	int assigned_port = tf_http_listen(http, port, tls);
 | 
						*listener = (httpd_listener_t) { .context = context, .tls = JS_DupValue(context, argv[1]) };
 | 
				
			||||||
 | 
						tf_tls_context_t* tls = tf_tls_context_get(listener->tls);
 | 
				
			||||||
 | 
						int assigned_port = tf_http_listen(http, port, tls, _httpd_listener_cleanup, listener);
 | 
				
			||||||
	return JS_NewInt32(context, assigned_port);
 | 
						return JS_NewInt32(context, assigned_port);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -739,7 +739,7 @@ static void _test_http(const tf_test_options_t* options)
 | 
				
			|||||||
	tf_http_t* http = tf_http_create(&loop);
 | 
						tf_http_t* http = tf_http_create(&loop);
 | 
				
			||||||
	tf_http_add_handler(http, "/hello", _test_http_handler, NULL, NULL);
 | 
						tf_http_add_handler(http, "/hello", _test_http_handler, NULL, NULL);
 | 
				
			||||||
	tf_http_add_handler(http, "/post", _test_http_handler_post, NULL, NULL);
 | 
						tf_http_add_handler(http, "/post", _test_http_handler_post, NULL, NULL);
 | 
				
			||||||
	tf_http_listen(http, 23456, NULL);
 | 
						tf_http_listen(http, 23456, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_http_t test = { .loop = &loop };
 | 
						test_http_t test = { .loop = &loop };
 | 
				
			||||||
	uv_async_init(&loop, &test.async, _test_http_async);
 | 
						uv_async_init(&loop, &test.async, _test_http_async);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user