|  | @@ -9244,8 +9244,7 @@ connect_socket(
 | 
											
												
													
														|  |      const char *host,
 |  |      const char *host,
 | 
											
												
													
														|  |      int port,    /* 1..65535, or -99 for domain sockets (may be changed) */
 |  |      int port,    /* 1..65535, or -99 for domain sockets (may be changed) */
 | 
											
												
													
														|  |      int use_ssl, /* 0 or 1 */
 |  |      int use_ssl, /* 0 or 1 */
 | 
											
												
													
														|  | -    char *ebuf,
 |  | 
 | 
											
												
													
														|  | -    size_t ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +    const struct mg_error_data *error,
 | 
											
												
													
														|  |      SOCKET *sock /* output: socket, must not be NULL */,
 |  |      SOCKET *sock /* output: socket, must not be NULL */,
 | 
											
												
													
														|  |      union usa *sa /* output: socket address, must not be NULL  */
 |  |      union usa *sa /* output: socket address, must not be NULL  */
 | 
											
												
													
														|  |  )
 |  |  )
 | 
											
										
											
												
													
														|  | @@ -9256,17 +9255,17 @@ connect_socket(
 | 
											
												
													
														|  |  	*sock = INVALID_SOCKET;
 |  |  	*sock = INVALID_SOCKET;
 | 
											
												
													
														|  |  	memset(sa, 0, sizeof(*sa));
 |  |  	memset(sa, 0, sizeof(*sa));
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -	if (ebuf_len > 0) {
 |  | 
 | 
											
												
													
														|  | -		*ebuf = 0;
 |  | 
 | 
											
												
													
														|  | -	}
 |  | 
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |  	if (host == NULL) {
 |  |  	if (host == NULL) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "%s",
 |  |  		            "%s",
 | 
											
												
													
														|  |  		            "NULL host");
 |  |  		            "NULL host");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9277,10 +9276,13 @@ connect_socket(
 | 
											
												
													
														|  |  		if (hostlen >= sizeof(sa->sun.sun_path)) {
 |  |  		if (hostlen >= sizeof(sa->sun.sun_path)) {
 | 
											
												
													
														|  |  			mg_snprintf(NULL,
 |  |  			mg_snprintf(NULL,
 | 
											
												
													
														|  |  			            NULL, /* No truncation check for ebuf */
 |  |  			            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -			            ebuf,
 |  | 
 | 
											
												
													
														|  | -			            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +			            error->text,
 | 
											
												
													
														|  | 
 |  | +			            error->text_buffer_size,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "host length exceeds limit");
 |  |  			            "host length exceeds limit");
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			return 0;
 |  |  			return 0;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  	} else
 |  |  	} else
 | 
											
										
											
												
													
														|  | @@ -9288,10 +9290,13 @@ connect_socket(
 | 
											
												
													
														|  |  	    if ((port <= 0) || !is_valid_port((unsigned)port)) {
 |  |  	    if ((port <= 0) || !is_valid_port((unsigned)port)) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "%s",
 |  |  		            "%s",
 | 
											
												
													
														|  |  		            "invalid port");
 |  |  		            "invalid port");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9300,20 +9305,26 @@ connect_socket(
 | 
											
												
													
														|  |  	if (use_ssl && (TLS_client_method == NULL)) {
 |  |  	if (use_ssl && (TLS_client_method == NULL)) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "%s",
 |  |  		            "%s",
 | 
											
												
													
														|  |  		            "SSL is not initialized");
 |  |  		            "SSL is not initialized");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  #else
 |  |  #else
 | 
											
												
													
														|  |  	if (use_ssl && (SSLv23_client_method == NULL)) {
 |  |  	if (use_ssl && (SSLv23_client_method == NULL)) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "%s",
 |  |  		            "%s",
 | 
											
												
													
														|  |  		            "SSL is not initialized");
 |  |  		            "SSL is not initialized");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0*/
 |  |  #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0*/
 | 
											
										
											
												
													
														|  | @@ -9358,10 +9369,13 @@ connect_socket(
 | 
											
												
													
														|  |  	if (ip_ver == 0) {
 |  |  	if (ip_ver == 0) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "%s",
 |  |  		            "%s",
 | 
											
												
													
														|  |  		            "host not found");
 |  |  		            "host not found");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_HOST_NOT_FOUND;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -9382,20 +9396,26 @@ connect_socket(
 | 
											
												
													
														|  |  	if (*sock == INVALID_SOCKET) {
 |  |  	if (*sock == INVALID_SOCKET) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "socket(): %s",
 |  |  		            "socket(): %s",
 | 
											
												
													
														|  |  		            strerror(ERRNO));
 |  |  		            strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	if (0 != set_non_blocking_mode(*sock)) {
 |  |  	if (0 != set_non_blocking_mode(*sock)) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "Cannot set socket to non-blocking: %s",
 |  |  		            "Cannot set socket to non-blocking: %s",
 | 
											
												
													
														|  |  		            strerror(ERRNO));
 |  |  		            strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		closesocket(*sock);
 |  |  		closesocket(*sock);
 | 
											
												
													
														|  |  		*sock = INVALID_SOCKET;
 |  |  		*sock = INVALID_SOCKET;
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
										
											
												
													
														|  | @@ -9465,11 +9485,14 @@ connect_socket(
 | 
											
												
													
														|  |  			/* Not connected */
 |  |  			/* Not connected */
 | 
											
												
													
														|  |  			mg_snprintf(NULL,
 |  |  			mg_snprintf(NULL,
 | 
											
												
													
														|  |  			            NULL, /* No truncation check for ebuf */
 |  |  			            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -			            ebuf,
 |  | 
 | 
											
												
													
														|  | -			            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +			            error->text,
 | 
											
												
													
														|  | 
 |  | +			            error->text_buffer_size,
 | 
											
												
													
														|  |  			            "connect(%s:%d): timeout",
 |  |  			            "connect(%s:%d): timeout",
 | 
											
												
													
														|  |  			            host,
 |  |  			            host,
 | 
											
												
													
														|  |  			            port);
 |  |  			            port);
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_CONNECT_TIMEOUT;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			closesocket(*sock);
 |  |  			closesocket(*sock);
 | 
											
												
													
														|  |  			*sock = INVALID_SOCKET;
 |  |  			*sock = INVALID_SOCKET;
 | 
											
												
													
														|  |  			return 0;
 |  |  			return 0;
 | 
											
										
											
												
													
														|  | @@ -9490,12 +9513,15 @@ connect_socket(
 | 
											
												
													
														|  |  		/* Not connected */
 |  |  		/* Not connected */
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "connect(%s:%d): error %s",
 |  |  		            "connect(%s:%d): error %s",
 | 
											
												
													
														|  |  		            host,
 |  |  		            host,
 | 
											
												
													
														|  |  		            port,
 |  |  		            port,
 | 
											
												
													
														|  |  		            strerror(sockerr));
 |  |  		            strerror(sockerr));
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_CONNECT_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		closesocket(*sock);
 |  |  		closesocket(*sock);
 | 
											
												
													
														|  |  		*sock = INVALID_SOCKET;
 |  |  		*sock = INVALID_SOCKET;
 | 
											
												
													
														|  |  		return 0;
 |  |  		return 0;
 | 
											
										
											
												
													
														|  | @@ -9886,11 +9912,11 @@ mg_sort(void *data,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	for (Aidx = 8; Aidx >= 0; Aidx--) {
 |  |  	for (Aidx = 8; Aidx >= 0; Aidx--) {
 | 
											
												
													
														|  |  		gap = A102549[Aidx];
 |  |  		gap = A102549[Aidx];
 | 
											
												
													
														|  | -		if (gap > elemcount / 2) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (gap > ((int)elemcount / 2)) {
 | 
											
												
													
														|  |  			continue;
 |  |  			continue;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  |  		for (i = 0; i < gap; i++) {
 |  |  		for (i = 0; i < gap; i++) {
 | 
											
												
													
														|  | -			for (j = i; j < elemcount; j += gap) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +			for (j = i; j < (int)elemcount; j += gap) {
 | 
											
												
													
														|  |  				memcpy(tmp, (void *)((ptrdiff_t)data + elemsize * j), elemsize);
 |  |  				memcpy(tmp, (void *)((ptrdiff_t)data + elemsize * j), elemsize);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  				for (k = j; k >= gap; k -= gap) {
 |  |  				for (k = j; k >= gap; k -= gap) {
 | 
											
										
											
												
													
														|  | @@ -13516,7 +13542,7 @@ mg_websocket_write_exec(struct mg_connection *conn,
 | 
											
												
													
														|  |  		header[0] = 0xC0u | (unsigned char)((unsigned)opcode & 0xf);
 |  |  		header[0] = 0xC0u | (unsigned char)((unsigned)opcode & 0xf);
 | 
											
												
													
														|  |  		conn->websocket_deflate_state.avail_in = (uInt)dataLen;
 |  |  		conn->websocket_deflate_state.avail_in = (uInt)dataLen;
 | 
											
												
													
														|  |  		conn->websocket_deflate_state.next_in = (unsigned char *)data;
 |  |  		conn->websocket_deflate_state.next_in = (unsigned char *)data;
 | 
											
												
													
														|  | -		deflated_size = (Bytef *)compressBound((uLong)dataLen);
 |  | 
 | 
											
												
													
														|  | 
 |  | +		deflated_size = (size_t)compressBound((uLong)dataLen);
 | 
											
												
													
														|  |  		deflated = mg_calloc(deflated_size, sizeof(Bytef));
 |  |  		deflated = mg_calloc(deflated_size, sizeof(Bytef));
 | 
											
												
													
														|  |  		if (deflated == NULL) {
 |  |  		if (deflated == NULL) {
 | 
											
												
													
														|  |  			mg_cry_internal(
 |  |  			mg_cry_internal(
 | 
											
										
											
												
													
														|  | @@ -17944,8 +17970,8 @@ mg_close_connection(struct mg_connection *conn)
 | 
											
												
													
														|  |  static struct mg_connection *
 |  |  static struct mg_connection *
 | 
											
												
													
														|  |  mg_connect_client_impl(const struct mg_client_options *client_options,
 |  |  mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |                         int use_ssl,
 |  |                         int use_ssl,
 | 
											
												
													
														|  | -                       char *ebuf,
 |  | 
 | 
											
												
													
														|  | -                       size_t ebuf_len)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                       struct mg_init_data *init,
 | 
											
												
													
														|  | 
 |  | +                       const struct mg_error_data *error)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	struct mg_connection *conn = NULL;
 |  |  	struct mg_connection *conn = NULL;
 | 
											
												
													
														|  |  	SOCKET sock;
 |  |  	SOCKET sock;
 | 
											
										
											
												
													
														|  | @@ -17965,12 +17991,17 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  	                                      conn_size + ctx_size + max_req_size);
 |  |  	                                      conn_size + ctx_size + max_req_size);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	if (conn == NULL) {
 |  |  	if (conn == NULL) {
 | 
											
												
													
														|  | -		mg_snprintf(NULL,
 |  | 
 | 
											
												
													
														|  | -		            NULL, /* No truncation check for ebuf */
 |  | 
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | -		            "calloc(): %s",
 |  | 
 | 
											
												
													
														|  | -		            strerror(ERRNO));
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->text_buffer_size > 0)) {
 | 
											
												
													
														|  | 
 |  | +			mg_snprintf(NULL,
 | 
											
												
													
														|  | 
 |  | +			            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | 
 |  | +			            error->text,
 | 
											
												
													
														|  | 
 |  | +			            error->text_buffer_size,
 | 
											
												
													
														|  | 
 |  | +			            "calloc(): %s",
 | 
											
												
													
														|  | 
 |  | +			            strerror(ERRNO));
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -17995,12 +18026,11 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  	                    client_options->host,
 |  |  	                    client_options->host,
 | 
											
												
													
														|  |  	                    client_options->port,
 |  |  	                    client_options->port,
 | 
											
												
													
														|  |  	                    use_ssl,
 |  |  	                    use_ssl,
 | 
											
												
													
														|  | -	                    ebuf,
 |  | 
 | 
											
												
													
														|  | -	                    ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +	                    error,
 | 
											
												
													
														|  |  	                    &sock,
 |  |  	                    &sock,
 | 
											
												
													
														|  |  	                    &sa)) {
 |  |  	                    &sa)) {
 | 
											
												
													
														|  | -		/* ebuf is set by connect_socket,
 |  | 
 | 
											
												
													
														|  | -		 * free all memory and return NULL; */
 |  | 
 | 
											
												
													
														|  | 
 |  | +		/* "error" will be set by connect_socket. */
 | 
											
												
													
														|  | 
 |  | +		/* free all memory and return NULL; */
 | 
											
												
													
														|  |  		mg_free(conn);
 |  |  		mg_free(conn);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -18008,37 +18038,48 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
 |  |  #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
 | 
											
												
													
														|  |  #if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0))                     \
 |  |  #if (defined(OPENSSL_API_1_1) || defined(OPENSSL_API_3_0))                     \
 | 
											
												
													
														|  |      && !defined(NO_SSL_DL)
 |  |      && !defined(NO_SSL_DL)
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	if (use_ssl
 |  |  	if (use_ssl
 | 
											
												
													
														|  |  	    && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(TLS_client_method()))
 |  |  	    && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(TLS_client_method()))
 | 
											
												
													
														|  |  	           == NULL) {
 |  |  	           == NULL) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "SSL_CTX_new error: %s",
 |  |  		            "SSL_CTX_new error: %s",
 | 
											
												
													
														|  |  		            ssl_error());
 |  |  		            ssl_error());
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		closesocket(sock);
 |  |  		closesocket(sock);
 | 
											
												
													
														|  |  		mg_free(conn);
 |  |  		mg_free(conn);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  #else
 |  |  #else
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	if (use_ssl
 |  |  	if (use_ssl
 | 
											
												
													
														|  |  	    && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
 |  |  	    && (conn->dom_ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
 | 
											
												
													
														|  |  	           == NULL) {
 |  |  	           == NULL) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "SSL_CTX_new error: %s",
 |  |  		            "SSL_CTX_new error: %s",
 | 
											
												
													
														|  |  		            ssl_error());
 |  |  		            ssl_error());
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		closesocket(sock);
 |  |  		closesocket(sock);
 | 
											
												
													
														|  |  		mg_free(conn);
 |  |  		mg_free(conn);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */
 |  |  #endif /* OPENSSL_API_1_1 || OPENSSL_API_3_0 */
 | 
											
												
													
														|  |  #endif /* NO_SSL */
 |  |  #endif /* NO_SSL */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -
 |  | 
 | 
											
												
													
														|  |  #if defined(USE_IPV6)
 |  |  #if defined(USE_IPV6)
 | 
											
												
													
														|  |  	len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin)
 |  |  	len = (sa.sa.sa_family == AF_INET) ? sizeof(conn->client.rsa.sin)
 | 
											
												
													
														|  |  	                                   : sizeof(conn->client.rsa.sin6);
 |  |  	                                   : sizeof(conn->client.rsa.sin6);
 | 
											
										
											
												
													
														|  | @@ -18064,9 +18105,12 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  	if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) {
 |  |  	if (0 != pthread_mutex_init(&conn->mutex, &pthread_mutex_attr)) {
 | 
											
												
													
														|  |  		mg_snprintf(NULL,
 |  |  		mg_snprintf(NULL,
 | 
											
												
													
														|  |  		            NULL, /* No truncation check for ebuf */
 |  |  		            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -		            ebuf,
 |  | 
 | 
											
												
													
														|  | -		            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +		            error->text,
 | 
											
												
													
														|  | 
 |  | +		            error->text_buffer_size,
 | 
											
												
													
														|  |  		            "Can not create mutex");
 |  |  		            "Can not create mutex");
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
 |  |  #if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
 | 
											
												
													
														|  |  		SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 |  |  		SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
										
											
												
													
														|  | @@ -18092,9 +18136,13 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  			                      NULL)) {
 |  |  			                      NULL)) {
 | 
											
												
													
														|  |  				mg_snprintf(NULL,
 |  |  				mg_snprintf(NULL,
 | 
											
												
													
														|  |  				            NULL, /* No truncation check for ebuf */
 |  |  				            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -				            ebuf,
 |  | 
 | 
											
												
													
														|  | -				            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +				            error->text,
 | 
											
												
													
														|  | 
 |  | +				            error->text_buffer_size,
 | 
											
												
													
														|  |  				            "Can not use SSL client certificate");
 |  |  				            "Can not use SSL client certificate");
 | 
											
												
													
														|  | 
 |  | +				if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +					*error->code = MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR;
 | 
											
												
													
														|  | 
 |  | +				}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  				SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 |  |  				SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 | 
											
												
													
														|  |  				closesocket(sock);
 |  |  				closesocket(sock);
 | 
											
												
													
														|  |  				mg_free(conn);
 |  |  				mg_free(conn);
 | 
											
										
											
												
													
														|  | @@ -18107,9 +18155,15 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  			                                  client_options->server_cert,
 |  |  			                                  client_options->server_cert,
 | 
											
												
													
														|  |  			                                  NULL)
 |  |  			                                  NULL)
 | 
											
												
													
														|  |  			    != 1) {
 |  |  			    != 1) {
 | 
											
												
													
														|  | -				mg_cry_internal(conn,
 |  | 
 | 
											
												
													
														|  | -				                "SSL_CTX_load_verify_locations error: %s ",
 |  | 
 | 
											
												
													
														|  | -				                ssl_error());
 |  | 
 | 
											
												
													
														|  | 
 |  | +				mg_snprintf(NULL,
 | 
											
												
													
														|  | 
 |  | +				            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | 
 |  | +				            error->text,
 | 
											
												
													
														|  | 
 |  | +				            error->text_buffer_size,
 | 
											
												
													
														|  | 
 |  | +				            "SSL_CTX_load_verify_locations error: %s",
 | 
											
												
													
														|  | 
 |  | +				            ssl_error());
 | 
											
												
													
														|  | 
 |  | +				if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +					*error->code = MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR;
 | 
											
												
													
														|  | 
 |  | +				}
 | 
											
												
													
														|  |  				SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 |  |  				SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 | 
											
												
													
														|  |  				closesocket(sock);
 |  |  				closesocket(sock);
 | 
											
												
													
														|  |  				mg_free(conn);
 |  |  				mg_free(conn);
 | 
											
										
											
												
													
														|  | @@ -18123,9 +18177,12 @@ mg_connect_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  		if (!sslize(conn, SSL_connect, client_options)) {
 |  |  		if (!sslize(conn, SSL_connect, client_options)) {
 | 
											
												
													
														|  |  			mg_snprintf(NULL,
 |  |  			mg_snprintf(NULL,
 | 
											
												
													
														|  |  			            NULL, /* No truncation check for ebuf */
 |  |  			            NULL, /* No truncation check for ebuf */
 | 
											
												
													
														|  | -			            ebuf,
 |  | 
 | 
											
												
													
														|  | -			            ebuf_len,
 |  | 
 | 
											
												
													
														|  | 
 |  | +			            error->text,
 | 
											
												
													
														|  | 
 |  | +			            error->text_buffer_size,
 | 
											
												
													
														|  |  			            "SSL connection error");
 |  |  			            "SSL connection error");
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 |  |  			SSL_CTX_free(conn->dom_ctx->ssl_ctx);
 | 
											
												
													
														|  |  			closesocket(sock);
 |  |  			closesocket(sock);
 | 
											
												
													
														|  |  			mg_free(conn);
 |  |  			mg_free(conn);
 | 
											
										
											
												
													
														|  | @@ -18143,14 +18200,18 @@ mg_connect_client_secure(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |                           char *error_buffer,
 |  |                           char *error_buffer,
 | 
											
												
													
														|  |                           size_t error_buffer_size)
 |  |                           size_t error_buffer_size)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  | -	return mg_connect_client_impl(client_options,
 |  | 
 | 
											
												
													
														|  | -	                              1,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer_size);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	struct mg_init_data init;
 | 
											
												
													
														|  | 
 |  | +	struct mg_error_data error;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	memset(&init, 0, sizeof(init));
 | 
											
												
													
														|  | 
 |  | +	memset(&error, 0, sizeof(error));
 | 
											
												
													
														|  | 
 |  | +	error.text_buffer_size = error_buffer_size;
 | 
											
												
													
														|  | 
 |  | +	error.text = error_buffer;
 | 
											
												
													
														|  | 
 |  | +	return mg_connect_client_impl(client_options, 1, &init, &error);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -struct mg_connection *
 |  | 
 | 
											
												
													
														|  | 
 |  | +CIVETWEB_API struct mg_connection *
 | 
											
												
													
														|  |  mg_connect_client(const char *host,
 |  |  mg_connect_client(const char *host,
 | 
											
												
													
														|  |                    int port,
 |  |                    int port,
 | 
											
												
													
														|  |                    int use_ssl,
 |  |                    int use_ssl,
 | 
											
										
											
												
													
														|  | @@ -18158,16 +18219,23 @@ mg_connect_client(const char *host,
 | 
											
												
													
														|  |                    size_t error_buffer_size)
 |  |                    size_t error_buffer_size)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	struct mg_client_options opts;
 |  |  	struct mg_client_options opts;
 | 
											
												
													
														|  | 
 |  | +	struct mg_init_data init;
 | 
											
												
													
														|  | 
 |  | +	struct mg_error_data error;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	memset(&init, 0, sizeof(init));
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	memset(&error, 0, sizeof(error));
 | 
											
												
													
														|  | 
 |  | +	error.text_buffer_size = error_buffer_size;
 | 
											
												
													
														|  | 
 |  | +	error.text = error_buffer;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	memset(&opts, 0, sizeof(opts));
 |  |  	memset(&opts, 0, sizeof(opts));
 | 
											
												
													
														|  |  	opts.host = host;
 |  |  	opts.host = host;
 | 
											
												
													
														|  |  	opts.port = port;
 |  |  	opts.port = port;
 | 
											
												
													
														|  |  	if (use_ssl) {
 |  |  	if (use_ssl) {
 | 
											
												
													
														|  |  		opts.host_name = host;
 |  |  		opts.host_name = host;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  | -	return mg_connect_client_impl(&opts,
 |  | 
 | 
											
												
													
														|  | -	                              use_ssl,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer_size);
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	return mg_connect_client_impl(&opts, use_ssl, &init, &error);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -18178,7 +18246,7 @@ mg_connect_client2(const char *host,
 | 
											
												
													
														|  |                     int port,
 |  |                     int port,
 | 
											
												
													
														|  |                     const char *path,
 |  |                     const char *path,
 | 
											
												
													
														|  |                     struct mg_init_data *init,
 |  |                     struct mg_init_data *init,
 | 
											
												
													
														|  | -                   struct mg_error_data *error)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                   const struct mg_error_data *error)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	(void)path;
 |  |  	(void)path;
 | 
											
												
													
														|  |  	(void)init;
 |  |  	(void)init;
 | 
											
										
											
												
													
														|  | @@ -18187,7 +18255,9 @@ mg_connect_client2(const char *host,
 | 
											
												
													
														|  |  	/* void *user_data = (init != NULL) ? init->user_data : NULL; -- TODO */
 |  |  	/* void *user_data = (init != NULL) ? init->user_data : NULL; -- TODO */
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	if (error != NULL) {
 |  |  	if (error != NULL) {
 | 
											
												
													
														|  | -		error->code = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (error->code != NULL) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = 0;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		if (error->text_buffer_size > 0) {
 |  |  		if (error->text_buffer_size > 0) {
 | 
											
												
													
														|  |  			*error->text = 0;
 |  |  			*error->text = 0;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
										
											
												
													
														|  | @@ -18202,6 +18272,10 @@ mg_connect_client2(const char *host,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Invalid parameters");
 |  |  			            "Invalid parameters");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -18229,6 +18303,10 @@ mg_connect_client2(const char *host,
 | 
											
												
													
														|  |  			            "Protocol %s not supported",
 |  |  			            "Protocol %s not supported",
 | 
											
												
													
														|  |  			            protocol);
 |  |  			            protocol);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -18256,14 +18334,12 @@ mg_connect_client2(const char *host,
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* TODO: all additional options */
 |  |  	/* TODO: all additional options */
 | 
											
												
													
														|  |  	struct mg_client_options opts;
 |  |  	struct mg_client_options opts;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  	memset(&opts, 0, sizeof(opts));
 |  |  	memset(&opts, 0, sizeof(opts));
 | 
											
												
													
														|  |  	opts.host = host;
 |  |  	opts.host = host;
 | 
											
												
													
														|  |  	opts.port = port;
 |  |  	opts.port = port;
 | 
											
												
													
														|  | -	return mg_connect_client_impl(&opts,
 |  | 
 | 
											
												
													
														|  | -	                              is_ssl,
 |  | 
 | 
											
												
													
														|  | -	                              ((error != NULL) ? error->text : NULL),
 |  | 
 | 
											
												
													
														|  | -	                              ((error != NULL) ? error->text_buffer_size
 |  | 
 | 
											
												
													
														|  | -	                                               : 0));
 |  | 
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	return mg_connect_client_impl(&opts, is_ssl, init, error);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -18908,16 +18984,21 @@ mg_connect_websocket_client_impl(const struct mg_client_options *client_options,
 | 
											
												
													
														|  |  	const char *host = client_options->host;
 |  |  	const char *host = client_options->host;
 | 
											
												
													
														|  |  	int i;
 |  |  	int i;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +	struct mg_init_data init;
 | 
											
												
													
														|  | 
 |  | +	struct mg_error_data error;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +	memset(&init, 0, sizeof(init));
 | 
											
												
													
														|  | 
 |  | +	memset(&error, 0, sizeof(error));
 | 
											
												
													
														|  | 
 |  | +	error.text_buffer_size = error_buffer_size;
 | 
											
												
													
														|  | 
 |  | +	error.text = error_buffer;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  #if defined(__clang__)
 |  |  #if defined(__clang__)
 | 
											
												
													
														|  |  #pragma clang diagnostic push
 |  |  #pragma clang diagnostic push
 | 
											
												
													
														|  |  #pragma clang diagnostic ignored "-Wformat-nonliteral"
 |  |  #pragma clang diagnostic ignored "-Wformat-nonliteral"
 | 
											
												
													
														|  |  #endif
 |  |  #endif
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* Establish the client connection and request upgrade */
 |  |  	/* Establish the client connection and request upgrade */
 | 
											
												
													
														|  | -	conn = mg_connect_client_impl(client_options,
 |  | 
 | 
											
												
													
														|  | -	                              use_ssl,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer,
 |  | 
 | 
											
												
													
														|  | -	                              error_buffer_size);
 |  | 
 | 
											
												
													
														|  | 
 |  | +	conn = mg_connect_client_impl(client_options, use_ssl, &init, &error);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* Connection object will be null if something goes wrong */
 |  |  	/* Connection object will be null if something goes wrong */
 | 
											
												
													
														|  |  	if (conn == NULL) {
 |  |  	if (conn == NULL) {
 | 
											
										
											
												
													
														|  | @@ -19153,6 +19234,7 @@ mg_connect_websocket_client_secure(
 | 
											
												
													
														|  |  	                                        user_data);
 |  |  	                                        user_data);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  struct mg_connection *
 |  |  struct mg_connection *
 | 
											
												
													
														|  |  mg_connect_websocket_client_extensions(const char *host,
 |  |  mg_connect_websocket_client_extensions(const char *host,
 | 
											
												
													
														|  |                                         int port,
 |  |                                         int port,
 | 
											
										
											
												
													
														|  | @@ -19183,6 +19265,7 @@ mg_connect_websocket_client_extensions(const char *host,
 | 
											
												
													
														|  |  	                                        user_data);
 |  |  	                                        user_data);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  struct mg_connection *
 |  |  struct mg_connection *
 | 
											
												
													
														|  |  mg_connect_websocket_client_secure_extensions(
 |  |  mg_connect_websocket_client_secure_extensions(
 | 
											
												
													
														|  |      const struct mg_client_options *client_options,
 |  |      const struct mg_client_options *client_options,
 | 
											
										
											
												
													
														|  | @@ -19210,6 +19293,7 @@ mg_connect_websocket_client_secure_extensions(
 | 
											
												
													
														|  |  	                                        user_data);
 |  |  	                                        user_data);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  /* Prepare connection data structure */
 |  |  /* Prepare connection data structure */
 | 
											
												
													
														|  |  static void
 |  |  static void
 | 
											
												
													
														|  |  init_connection(struct mg_connection *conn)
 |  |  init_connection(struct mg_connection *conn)
 | 
											
										
											
												
													
														|  | @@ -20346,7 +20430,7 @@ legacy_init(const char **options)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  struct mg_context *
 |  |  struct mg_context *
 | 
											
												
													
														|  | -mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 |  | 
 | 
											
												
													
														|  | 
 |  | +mg_start2(struct mg_init_data *init, const struct mg_error_data *error)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	struct mg_context *ctx;
 |  |  	struct mg_context *ctx;
 | 
											
												
													
														|  |  	const char *name, *value, *default_value;
 |  |  	const char *name, *value, *default_value;
 | 
											
										
											
												
													
														|  | @@ -20360,7 +20444,9 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  	struct mg_workerTLS tls;
 |  |  	struct mg_workerTLS tls;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	if (error != NULL) {
 |  |  	if (error != NULL) {
 | 
											
												
													
														|  | -		error->code = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (error->code != NULL) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = 0;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		if (error->text_buffer_size > 0) {
 |  |  		if (error->text_buffer_size > 0) {
 | 
											
												
													
														|  |  			*error->text = 0;
 |  |  			*error->text = 0;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
										
											
												
													
														|  | @@ -20381,11 +20467,16 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Library uninitialized");
 |  |  			            "Library uninitialized");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	/* Allocate context and initialize reasonable general case defaults. */
 |  |  	/* Allocate context and initialize reasonable general case defaults. */
 | 
											
												
													
														|  | -	if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +	ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx));
 | 
											
												
													
														|  | 
 |  | +	if (ctx == NULL) {
 | 
											
												
													
														|  |  		if ((error != NULL) && (error->text_buffer_size > 0)) {
 |  |  		if ((error != NULL) && (error->text_buffer_size > 0)) {
 | 
											
												
													
														|  |  			mg_snprintf(NULL,
 |  |  			mg_snprintf(NULL,
 | 
											
												
													
														|  |  			            NULL, /* No truncation check for error buffers */
 |  |  			            NULL, /* No truncation check for error buffers */
 | 
											
										
											
												
													
														|  | @@ -20394,6 +20485,10 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Out of memory");
 |  |  			            "Out of memory");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -20437,6 +20532,10 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  		mg_free(ctx);
 |  |  		mg_free(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
										
											
												
													
														|  | @@ -20472,9 +20571,15 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  				            "Invalid configuration option: %s",
 |  |  				            "Invalid configuration option: %s",
 | 
											
												
													
														|  |  				            name);
 |  |  				            name);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  			free_context(ctx);
 |  |  			free_context(ctx);
 | 
											
												
													
														|  |  			pthread_setspecific(sTlsKey, NULL);
 |  |  			pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  			return NULL;
 |  |  			return NULL;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		} else if ((value = *options++) == NULL) {
 |  |  		} else if ((value = *options++) == NULL) {
 | 
											
												
													
														|  |  			mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name);
 |  |  			mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name);
 | 
											
												
													
														|  |  			if ((error != NULL) && (error->text_buffer_size > 0)) {
 |  |  			if ((error != NULL) && (error->text_buffer_size > 0)) {
 | 
											
										
											
												
													
														|  | @@ -20485,6 +20590,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  				            "Invalid configuration option value: %s",
 |  |  				            "Invalid configuration option value: %s",
 | 
											
												
													
														|  |  				            name);
 |  |  				            name);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  			free_context(ctx);
 |  |  			free_context(ctx);
 | 
											
												
													
														|  |  			pthread_setspecific(sTlsKey, NULL);
 |  |  			pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  			return NULL;
 |  |  			return NULL;
 | 
											
										
											
												
													
														|  | @@ -20521,6 +20631,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "Invalid configuration option value: %s",
 |  |  			            "Invalid configuration option value: %s",
 | 
											
												
													
														|  |  			            config_options[MAX_REQUEST_SIZE].name);
 |  |  			            config_options[MAX_REQUEST_SIZE].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20542,6 +20657,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "Invalid configuration option value: %s",
 |  |  			            "Invalid configuration option value: %s",
 | 
											
												
													
														|  |  			            config_options[CONNECTION_QUEUE_SIZE].name);
 |  |  			            config_options[CONNECTION_QUEUE_SIZE].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20560,6 +20680,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "Out of memory: Cannot allocate %s",
 |  |  			            "Out of memory: Cannot allocate %s",
 | 
											
												
													
														|  |  			            config_options[CONNECTION_QUEUE_SIZE].name);
 |  |  			            config_options[CONNECTION_QUEUE_SIZE].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20584,6 +20709,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "Invalid configuration option value: %s",
 |  |  			            "Invalid configuration option value: %s",
 | 
											
												
													
														|  |  			            config_options[NUM_THREADS].name);
 |  |  			            config_options[NUM_THREADS].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20601,6 +20731,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "Invalid configuration option value: %s",
 |  |  			            "Invalid configuration option value: %s",
 | 
											
												
													
														|  |  			            config_options[DOCUMENT_ROOT].name);
 |  |  			            config_options[DOCUMENT_ROOT].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20637,6 +20772,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  				            config_options[LUA_BACKGROUND_SCRIPT].name,
 |  |  				            config_options[LUA_BACKGROUND_SCRIPT].name,
 | 
											
												
													
														|  |  				            ebuf);
 |  |  				            ebuf);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  			pthread_mutex_unlock(&ctx->lua_bg_mutex);
 |  |  			pthread_mutex_unlock(&ctx->lua_bg_mutex);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  			free_context(ctx);
 |  |  			free_context(ctx);
 | 
											
										
											
												
													
														|  | @@ -20681,6 +20821,10 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  				            config_options[DOCUMENT_ROOT].name,
 |  |  				            config_options[DOCUMENT_ROOT].name,
 | 
											
												
													
														|  |  				            ebuf);
 |  |  				            ebuf);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_SCRIPT_ERROR;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			pthread_mutex_unlock(&ctx->lua_bg_mutex);
 |  |  			pthread_mutex_unlock(&ctx->lua_bg_mutex);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  			free_context(ctx);
 |  |  			free_context(ctx);
 | 
											
										
											
												
													
														|  | @@ -20712,6 +20856,10 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PASS_FILE;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20732,6 +20880,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20751,6 +20904,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20770,6 +20928,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_PORTS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20790,6 +20953,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_USER_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20809,6 +20977,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_ACL_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20831,6 +21004,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20852,6 +21030,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20875,6 +21058,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20898,6 +21086,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -20924,6 +21117,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  				            err_msg,
 |  |  				            err_msg,
 | 
											
												
													
														|  |  				            i);
 |  |  				            i);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  			free_context(ctx);
 |  |  			free_context(ctx);
 | 
											
												
													
														|  |  			pthread_setspecific(sTlsKey, NULL);
 |  |  			pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  			return NULL;
 |  |  			return NULL;
 | 
											
										
											
												
													
														|  | @@ -20944,6 +21142,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            err_msg);
 |  |  			            err_msg);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  		free_context(ctx);
 |  |  		free_context(ctx);
 | 
											
												
													
														|  |  		pthread_setspecific(sTlsKey, NULL);
 |  |  		pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  		return NULL;
 |  |  		return NULL;
 | 
											
										
											
												
													
														|  | @@ -21001,6 +21204,11 @@ mg_start2(struct mg_init_data *init, struct mg_error_data *error)
 | 
											
												
													
														|  |  					    "Cannot create first worker thread: error %ld",
 |  |  					    "Cannot create first worker thread: error %ld",
 | 
											
												
													
														|  |  					    error_no);
 |  |  					    error_no);
 | 
											
												
													
														|  |  				}
 |  |  				}
 | 
											
												
													
														|  | 
 |  | +				if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +					/* Set error code if pointer for error code is provided */
 | 
											
												
													
														|  | 
 |  | +					*error->code = MG_ERROR_DATA_CODE_OS_ERROR;
 | 
											
												
													
														|  | 
 |  | +				}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  				free_context(ctx);
 |  |  				free_context(ctx);
 | 
											
												
													
														|  |  				pthread_setspecific(sTlsKey, NULL);
 |  |  				pthread_setspecific(sTlsKey, NULL);
 | 
											
												
													
														|  |  				return NULL;
 |  |  				return NULL;
 | 
											
										
											
												
													
														|  | @@ -21035,7 +21243,7 @@ mg_start(const struct mg_callbacks *callbacks,
 | 
											
												
													
														|  |  int
 |  |  int
 | 
											
												
													
														|  |  mg_start_domain2(struct mg_context *ctx,
 |  |  mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |                   const char **options,
 |  |                   const char **options,
 | 
											
												
													
														|  | -                 struct mg_error_data *error)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                 const struct mg_error_data *error)
 | 
											
												
													
														|  |  {
 |  |  {
 | 
											
												
													
														|  |  	const char *name;
 |  |  	const char *name;
 | 
											
												
													
														|  |  	const char *value;
 |  |  	const char *value;
 | 
											
										
											
												
													
														|  | @@ -21045,7 +21253,9 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  	int idx, i;
 |  |  	int idx, i;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	if (error != NULL) {
 |  |  	if (error != NULL) {
 | 
											
												
													
														|  | -		error->code = 0;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if (error->code != NULL) {
 | 
											
												
													
														|  | 
 |  | +			*error->code = 0;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		if (error->text_buffer_size > 0) {
 |  |  		if (error->text_buffer_size > 0) {
 | 
											
												
													
														|  |  			*error->text = 0;
 |  |  			*error->text = 0;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
										
											
												
													
														|  | @@ -21060,6 +21270,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Invalid parameters");
 |  |  			            "Invalid parameters");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Invalid parameter */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INVALID_PARAM;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return -1;
 |  |  		return -1;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -21072,7 +21286,11 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Server already stopped");
 |  |  			            "Server already stopped");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | -		return -1;
 |  | 
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_SERVER_STOPPED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  | 
 |  | +		return -7;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  	new_dom = (struct mg_domain_context *)
 |  |  	new_dom = (struct mg_domain_context *)
 | 
											
										
											
												
													
														|  | @@ -21088,6 +21306,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Out or memory");
 |  |  			            "Out or memory");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_OUT_OF_MEMORY;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		return -6;
 |  |  		return -6;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -21103,6 +21325,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  				            "Invalid option: %s",
 |  |  				            "Invalid option: %s",
 | 
											
												
													
														|  |  				            name);
 |  |  				            name);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			mg_free(new_dom);
 |  |  			mg_free(new_dom);
 | 
											
												
													
														|  |  			return -2;
 |  |  			return -2;
 | 
											
												
													
														|  |  		} else if ((value = *options++) == NULL) {
 |  |  		} else if ((value = *options++) == NULL) {
 | 
											
										
											
												
													
														|  | @@ -21115,6 +21341,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  				            "Invalid option value: %s",
 |  |  				            "Invalid option value: %s",
 | 
											
												
													
														|  |  				            name);
 |  |  				            name);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_INVALID_OPTION;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			mg_free(new_dom);
 |  |  			mg_free(new_dom);
 | 
											
												
													
														|  |  			return -2;
 |  |  			return -2;
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
										
											
												
													
														|  | @@ -21139,6 +21369,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  			            "Mandatory option %s missing",
 |  |  			            "Mandatory option %s missing",
 | 
											
												
													
														|  |  			            config_options[AUTHENTICATION_DOMAIN].name);
 |  |  			            config_options[AUTHENTICATION_DOMAIN].name);
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_MISSING_OPTION;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		mg_free(new_dom);
 |  |  		mg_free(new_dom);
 | 
											
												
													
														|  |  		return -4;
 |  |  		return -4;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -21172,6 +21406,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  			            "%s",
 |  |  			            "%s",
 | 
											
												
													
														|  |  			            "Initializing SSL context failed");
 |  |  			            "Initializing SSL context failed");
 | 
											
												
													
														|  |  		}
 |  |  		}
 | 
											
												
													
														|  | 
 |  | +		if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +			/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +			*error->code = MG_ERROR_DATA_CODE_INIT_TLS_FAILED;
 | 
											
												
													
														|  | 
 |  | +		}
 | 
											
												
													
														|  |  		mg_free(new_dom);
 |  |  		mg_free(new_dom);
 | 
											
												
													
														|  |  		return -3;
 |  |  		return -3;
 | 
											
												
													
														|  |  	}
 |  |  	}
 | 
											
										
											
												
													
														|  | @@ -21198,6 +21436,10 @@ mg_start_domain2(struct mg_context *ctx,
 | 
											
												
													
														|  |  				            new_dom->config[AUTHENTICATION_DOMAIN],
 |  |  				            new_dom->config[AUTHENTICATION_DOMAIN],
 | 
											
												
													
														|  |  				            config_options[AUTHENTICATION_DOMAIN].name);
 |  |  				            config_options[AUTHENTICATION_DOMAIN].name);
 | 
											
												
													
														|  |  			}
 |  |  			}
 | 
											
												
													
														|  | 
 |  | +			if ((error != NULL) && (error->code != NULL)) {
 | 
											
												
													
														|  | 
 |  | +				/* Set error code if pointer for data is provided */
 | 
											
												
													
														|  | 
 |  | +				*error->code = MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN;
 | 
											
												
													
														|  | 
 |  | +			}
 | 
											
												
													
														|  |  			mg_free(new_dom);
 |  |  			mg_free(new_dom);
 | 
											
												
													
														|  |  			mg_unlock_context(ctx);
 |  |  			mg_unlock_context(ctx);
 | 
											
												
													
														|  |  			return -5;
 |  |  			return -5;
 |