|  | @@ -16339,10 +16339,6 @@ close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  void
 |  |  void
 | 
											
												
													
														|  |  mg_close_connection(struct mg_connection *conn)
 |  |  mg_close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -#if defined(USE_WEBSOCKET)
 |  | 
 | 
											
												
													
														|  | -	struct mg_context *client_ctx = NULL;
 |  | 
 | 
											
												
													
														|  | -#endif /* defined(USE_WEBSOCKET) */
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |  	if ((conn == NULL) || (conn->phys_ctx == NULL)) {
 |  |  	if ((conn == NULL) || (conn->phys_ctx == NULL)) {
 | 
											
												
													
														|  |  		return;
 |  |  		return;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -16359,11 +16355,8 @@ mg_close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		unsigned int i;
 |  |  		unsigned int i;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -		/* ws/wss client */
 |  | 
 | 
											
												
													
														|  | -		client_ctx = conn->phys_ctx;
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |  		/* client context: loops must end */
 |  |  		/* client context: loops must end */
 | 
											
												
													
														|  | -		client_ctx->stop_flag = 1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		conn->phys_ctx->stop_flag = 1;
 | 
											
												
													
														|  |  		conn->must_close = 1;
 |  |  		conn->must_close = 1;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		/* We need to get the client thread out of the select/recv call
 |  |  		/* We need to get the client thread out of the select/recv call
 | 
											
										
											
												
													
														|  | @@ -16372,10 +16365,8 @@ mg_close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  		 * timeouts, we will just wait a few seconds in mg_join_thread. */
 |  |  		 * timeouts, we will just wait a few seconds in mg_join_thread. */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		/* join worker thread */
 |  |  		/* join worker thread */
 | 
											
												
													
														|  | -		for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
 |  | 
 | 
											
												
													
														|  | -			if (client_ctx->worker_threadids[i] != 0) {
 |  | 
 | 
											
												
													
														|  | -				mg_join_thread(client_ctx->worker_threadids[i]);
 |  | 
 | 
											
												
													
														|  | -			}
 |  | 
 | 
											
												
													
														|  | 
 |  | +		for (i = 0; i < conn->phys_ctx->cfg_worker_threads; i++) {
 | 
											
												
													
														|  | 
 |  | +			mg_join_thread(conn->phys_ctx->worker_threadids[i]);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  #endif /* defined(USE_WEBSOCKET) */
 |  |  #endif /* defined(USE_WEBSOCKET) */
 | 
											
										
											
												
													
														|  | @@ -16391,10 +16382,8 @@ mg_close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #if defined(USE_WEBSOCKET)
 |  |  #if defined(USE_WEBSOCKET)
 | 
											
												
													
														|  | -	if (client_ctx != NULL) {
 |  | 
 | 
											
												
													
														|  | -		/* free context */
 |  | 
 | 
											
												
													
														|  | -		mg_free(client_ctx->worker_threadids);
 |  | 
 | 
											
												
													
														|  | -		mg_free(client_ctx);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) {
 | 
											
												
													
														|  | 
 |  | +		mg_free(conn->phys_ctx->worker_threadids);
 | 
											
												
													
														|  |  		(void)pthread_mutex_destroy(&conn->mutex);
 |  |  		(void)pthread_mutex_destroy(&conn->mutex);
 | 
											
												
													
														|  |  		mg_free(conn);
 |  |  		mg_free(conn);
 | 
											
												
													
														|  |  	} else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) {
 |  |  	} else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) {
 | 
											
										
											
												
													
														|  | @@ -17302,7 +17291,6 @@ mg_connect_websocket_client(const char *host,
 | 
											
												
													
														|  |  	struct mg_connection *conn = NULL;
 |  |  	struct mg_connection *conn = NULL;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #if defined(USE_WEBSOCKET)
 |  |  #if defined(USE_WEBSOCKET)
 | 
											
												
													
														|  | -	struct mg_context *newctx = NULL;
 |  | 
 | 
											
												
													
														|  |  	struct websocket_client_thread_data *thread_data;
 |  |  	struct websocket_client_thread_data *thread_data;
 | 
											
												
													
														|  |  	static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
 |  |  	static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
 | 
											
												
													
														|  |  	static const char *handshake_req;
 |  |  	static const char *handshake_req;
 | 
											
										
											
												
													
														|  | @@ -17375,37 +17363,15 @@ mg_connect_websocket_client(const char *host,
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
 |  |  		DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
 | 
											
												
													
														|  | -		mg_free(conn);
 |  | 
 | 
											
												
													
														|  | -		return NULL;
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	/* For client connections, mg_context is fake. Since we need to set a
 |  | 
 | 
											
												
													
														|  | -	 * callback function, we need to create a copy and modify it. */
 |  | 
 | 
											
												
													
														|  | -	newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
 |  | 
 | 
											
												
													
														|  | -	if (!newctx) {
 |  | 
 | 
											
												
													
														|  | -		DEBUG_TRACE("%s\r\n", "Out of memory");
 |  | 
 | 
											
												
													
														|  | -		mg_free(conn);
 |  | 
 | 
											
												
													
														|  | 
 |  | +		mg_close_connection(conn);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	memcpy(newctx, conn->phys_ctx, sizeof(struct mg_context));
 |  | 
 | 
											
												
													
														|  | -	newctx->user_data = user_data;
 |  | 
 | 
											
												
													
														|  | -	newctx->context_type = CONTEXT_WS_CLIENT; /* ws/wss client context */
 |  | 
 | 
											
												
													
														|  | -	newctx->cfg_worker_threads = 1; /* one worker thread will be created */
 |  | 
 | 
											
												
													
														|  | -	newctx->worker_threadids =
 |  | 
 | 
											
												
													
														|  | -	    (pthread_t *)mg_calloc_ctx(newctx->cfg_worker_threads,
 |  | 
 | 
											
												
													
														|  | -	                               sizeof(pthread_t),
 |  | 
 | 
											
												
													
														|  | -	                               newctx);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	conn->phys_ctx = newctx;
 |  | 
 | 
											
												
													
														|  | -	conn->dom_ctx = &(newctx->dd);
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  | -	thread_data = (struct websocket_client_thread_data *)
 |  | 
 | 
											
												
													
														|  | -	    mg_calloc_ctx(sizeof(struct websocket_client_thread_data), 1, newctx);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	thread_data = (struct websocket_client_thread_data *)mg_calloc_ctx(
 | 
											
												
													
														|  | 
 |  | +	    1, sizeof(struct websocket_client_thread_data), conn->phys_ctx);
 | 
											
												
													
														|  |  	if (!thread_data) {
 |  |  	if (!thread_data) {
 | 
											
												
													
														|  |  		DEBUG_TRACE("%s\r\n", "Out of memory");
 |  |  		DEBUG_TRACE("%s\r\n", "Out of memory");
 | 
											
												
													
														|  | -		mg_free(newctx);
 |  | 
 | 
											
												
													
														|  | -		mg_free(conn);
 |  | 
 | 
											
												
													
														|  | 
 |  | +		mg_close_connection(conn);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -17414,17 +17380,30 @@ mg_connect_websocket_client(const char *host,
 | 
											
												
													
														|  |  	thread_data->close_handler = close_func;
 |  |  	thread_data->close_handler = close_func;
 | 
											
												
													
														|  |  	thread_data->callback_data = user_data;
 |  |  	thread_data->callback_data = user_data;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +	conn->phys_ctx->worker_threadids =
 | 
											
												
													
														|  | 
 |  | +	    (pthread_t *)mg_calloc_ctx(1, sizeof(pthread_t), conn->phys_ctx);
 | 
											
												
													
														|  | 
 |  | +	if (!conn->phys_ctx->worker_threadids) {
 | 
											
												
													
														|  | 
 |  | +		DEBUG_TRACE("%s\r\n", "Out of memory");
 | 
											
												
													
														|  | 
 |  | +		mg_free(thread_data);
 | 
											
												
													
														|  | 
 |  | +		mg_close_connection(conn);
 | 
											
												
													
														|  | 
 |  | +		return NULL;
 | 
											
												
													
														|  | 
 |  | +	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	/* Now upgrade to ws/wss client context */
 | 
											
												
													
														|  | 
 |  | +	conn->phys_ctx->user_data = user_data;
 | 
											
												
													
														|  | 
 |  | +	conn->phys_ctx->context_type = CONTEXT_WS_CLIENT;
 | 
											
												
													
														|  | 
 |  | +	conn->phys_ctx->cfg_worker_threads = 1; /* one worker thread */
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	/* Start a thread to read the websocket client connection
 |  |  	/* Start a thread to read the websocket client connection
 | 
											
												
													
														|  |  	 * This thread will automatically stop when mg_disconnect is
 |  |  	 * This thread will automatically stop when mg_disconnect is
 | 
											
												
													
														|  |  	 * called on the client connection */
 |  |  	 * called on the client connection */
 | 
											
												
													
														|  |  	if (mg_start_thread_with_id(websocket_client_thread,
 |  |  	if (mg_start_thread_with_id(websocket_client_thread,
 | 
											
												
													
														|  | -	                            (void *)thread_data,
 |  | 
 | 
											
												
													
														|  | -	                            newctx->worker_threadids)
 |  | 
 | 
											
												
													
														|  | 
 |  | +	                            thread_data,
 | 
											
												
													
														|  | 
 |  | +	                            conn->phys_ctx->worker_threadids)
 | 
											
												
													
														|  |  	    != 0) {
 |  |  	    != 0) {
 | 
											
												
													
														|  | -		mg_free((void *)thread_data);
 |  | 
 | 
											
												
													
														|  | -		mg_free((void *)newctx->worker_threadids);
 |  | 
 | 
											
												
													
														|  | -		mg_free((void *)newctx);
 |  | 
 | 
											
												
													
														|  | -		mg_free((void *)conn);
 |  | 
 | 
											
												
													
														|  | 
 |  | +		conn->phys_ctx->cfg_worker_threads = 0;
 | 
											
												
													
														|  | 
 |  | +		mg_free(thread_data);
 | 
											
												
													
														|  | 
 |  | +		mg_close_connection(conn);
 | 
											
												
													
														|  |  		conn = NULL;
 |  |  		conn = NULL;
 | 
											
												
													
														|  |  		DEBUG_TRACE("%s",
 |  |  		DEBUG_TRACE("%s",
 | 
											
												
													
														|  |  		            "Websocket client connect thread could not be started\r\n");
 |  |  		            "Websocket client connect thread could not be started\r\n");
 |