diff --git a/include/libhttp.h b/include/libhttp.h index a4df8953..afcbed0a 100644 --- a/include/libhttp.h +++ b/include/libhttp.h @@ -904,8 +904,8 @@ LIBHTTP_API int httplib_atomic_inc( volatile int *addr ); LIBHTTP_API int httplib_base64_encode( const unsigned char *src, int src_len, char *dst, int dst_len ); LIBHTTP_API unsigned httplib_check_feature( unsigned feature ); LIBHTTP_API int httplib_closedir( DIR *dir ); -LIBHTTP_API struct httplib_connection * httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size ); -LIBHTTP_API struct httplib_connection * httplib_connect_client_secure( struct httplib_context *ctx, const struct httplib_client_options *client_options, char *error_buffer, size_t error_buffer_size ); +LIBHTTP_API struct httplib_connection * httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl ); +LIBHTTP_API struct httplib_connection * httplib_connect_client_secure( struct httplib_context *ctx, const struct httplib_client_options *client_options ); LIBHTTP_API struct httplib_connection * httplib_connect_websocket_client( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, httplib_websocket_data_handler data_func, httplib_websocket_close_handler close_func, void *user_data ); LIBHTTP_API struct httplib_context * httplib_create_client_context( const struct httplib_callbacks *callbacks, const struct httplib_option_t *options ); LIBHTTP_API void httplib_cry( enum debug_level_t debug_level, const struct httplib_context *ctx, const struct httplib_connection *conn, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(4, 5); diff --git a/src/httplib_connect_client.c b/src/httplib_connect_client.c index 01e69a5a..8ddbaabb 100644 --- a/src/httplib_connect_client.c +++ b/src/httplib_connect_client.c @@ -30,7 +30,7 @@ #include "httplib_ssl.h" #include "httplib_string.h" -static struct httplib_connection * httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl, char *ebuf, size_t ebuf_len ); +static struct httplib_connection * httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl ); /* * struct httplib_connection *httplib_connect_client_secure( struct httplib_context_*ctx, const struct httplib_client_options *client options, char *error buffer, size_t error_buffer_size ); @@ -40,20 +40,20 @@ static struct httplib_connection * httplib_connect_client_impl( struct httplib_c * information, or NULL if an error occured. */ -LIBHTTP_API struct httplib_connection *httplib_connect_client_secure( struct httplib_context *ctx, const struct httplib_client_options *client_options, char *error_buffer, size_t error_buffer_size ) { +LIBHTTP_API struct httplib_connection *httplib_connect_client_secure( struct httplib_context *ctx, const struct httplib_client_options *client_options ) { - return httplib_connect_client_impl( ctx, client_options, 1, error_buffer, error_buffer_size ); + return httplib_connect_client_impl( ctx, client_options, true ); } /* httplib_connect_client_secure */ /* - * struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size ); + * struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl ); * * The function httplib_connect_client() connects to a remote server as a client * with the options of the connection provided as parameters. */ -struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size ) { +struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, const char *host, int port, int use_ssl ) { struct httplib_client_options opts; @@ -61,20 +61,20 @@ struct httplib_connection *httplib_connect_client( struct httplib_context *ctx, opts.host = host; opts.port = port; - return httplib_connect_client_impl( ctx, &opts, use_ssl, error_buffer, error_buffer_size ); + return httplib_connect_client_impl( ctx, &opts, use_ssl ); } /* httplib_connect_client */ /* - * static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl, char *ebuf, size_t ebuf_len ); + * static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl ); * * The function httplib_connect_client_impl() is the background function doing the * heavy lifting to make connections as a client to remote servers. */ -static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl, char *ebuf, size_t ebuf_len ) { +static struct httplib_connection *httplib_connect_client_impl( struct httplib_context *ctx, const struct httplib_client_options *client_options, int use_ssl ) { struct httplib_connection *conn; SOCKET sock; @@ -85,18 +85,18 @@ static struct httplib_connection *httplib_connect_client_impl( struct httplib_co if ( ctx == NULL ) return NULL; - if ( ! XX_httplib_connect_socket( client_options->host, client_options->port, use_ssl, ebuf, ebuf_len, &sock, &sa ) ) return NULL; + if ( ! XX_httplib_connect_socket( ctx, client_options->host, client_options->port, use_ssl, &sock, &sa ) ) return NULL; if ( (conn = httplib_calloc( 1, sizeof(*conn) + MAX_REQUEST_SIZE )) == NULL ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "calloc(): %s", httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): calloc(): %s", __func__, __LINE__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); closesocket( sock ); } #ifndef NO_SSL else if ( use_ssl && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "SSL_CTX_new error" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): SSL_CTX_new error", __func__, __LINE__ ); closesocket( sock ); conn = httplib_free( conn ); } @@ -113,7 +113,7 @@ static struct httplib_connection *httplib_connect_client_impl( struct httplib_co conn->client.sock = sock; conn->client.lsa = sa; - if ( getsockname( sock, psa, &len ) != 0 ) httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s: getsockname() failed: %s", __func__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); + if ( getsockname( sock, psa, &len ) != 0 ) httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): getsockname() failed: %s", __func__, __LINE__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); conn->client.has_ssl = (use_ssl) ? true : false; httplib_pthread_mutex_init( &conn->mutex, &XX_httplib_pthread_mutex_attr ); @@ -137,7 +137,7 @@ static struct httplib_connection *httplib_connect_client_impl( struct httplib_co if ( ! XX_httplib_ssl_use_pem_file( ctx, client_options->client_cert ) ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "Can not use SSL client certificate" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): can not use SSL client certificate", __func__, __LINE__ ); SSL_CTX_free( conn->client_ssl_ctx ); closesocket( sock ); conn = httplib_free( conn ); @@ -154,7 +154,7 @@ static struct httplib_connection *httplib_connect_client_impl( struct httplib_co if ( ! XX_httplib_sslize( conn, conn->client_ssl_ctx, SSL_connect ) ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "SSL connection error" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): SSL connection error", __func__, __LINE__ ); SSL_CTX_free( conn->client_ssl_ctx ); closesocket( sock ); conn = httplib_free( conn ); diff --git a/src/httplib_connect_socket.c b/src/httplib_connect_socket.c index 1cf42363..5e30ccf2 100644 --- a/src/httplib_connect_socket.c +++ b/src/httplib_connect_socket.c @@ -41,26 +41,26 @@ * has been established. */ -bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, SOCKET *sock, union usa *sa ) { +bool XX_httplib_connect_socket( struct httplib_context *ctx, const char *host, int port, int use_ssl, SOCKET *sock, union usa *sa ) { int ip_ver; char error_string[ERROR_STRING_LEN]; + if ( ctx == NULL ) return false; + ip_ver = 0; *sock = INVALID_SOCKET; memset( sa, 0, sizeof(*sa) ); - if ( ebuf_len > 0 ) *ebuf = 0; - if ( host == NULL ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "%s", "NULL host" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): NULL host", __func__, __LINE__ ); return false; } if ( port < 0 || ! XX_httplib_is_valid_port( (unsigned)port) ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "%s", "invalid port" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): invalid port", __func__, __LINE__ ); return false; } @@ -68,7 +68,7 @@ bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *e if ( use_ssl && SSLv23_client_method == NULL ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "%s", "SSL is not initialized" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): SSL is not initialized", __func__, __LINE__ ); return false; } #else /* NO_SSL */ @@ -112,7 +112,7 @@ bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *e if ( ip_ver == 0 ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "%s", "host not found" ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): host not found", __func__, __LINE__ ); return false; } @@ -121,8 +121,8 @@ bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *e if ( *sock == INVALID_SOCKET ) { - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "socket(): %s", httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); - return 0; + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): socket(): %s", __func__, __LINE__, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); + return false; } XX_httplib_set_close_on_exec( *sock ); @@ -134,7 +134,7 @@ bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *e * Not connected */ - XX_httplib_snprintf( NULL, NULL, ebuf, ebuf_len, "connect(%s:%d): %s", host, port, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): connect(%s:%d): %s", __func__, __LINE__, host, port, httplib_error_string( ERRNO, error_string, ERROR_STRING_LEN ) ); closesocket( *sock ); *sock = INVALID_SOCKET; diff --git a/src/httplib_connect_websocket_client.c b/src/httplib_connect_websocket_client.c index 823d824e..46ef7c30 100644 --- a/src/httplib_connect_websocket_client.c +++ b/src/httplib_connect_websocket_client.c @@ -43,7 +43,13 @@ struct httplib_connection *httplib_connect_websocket_client( struct httplib_cont static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw=="; const char *handshake_req; - conn = NULL; + if ( ctx == NULL ) return NULL; + + if ( ctx->status != CTX_STATUS_TERMINATED ) { + + httplib_cry( DEBUG_LEVEL_CRASH, ctx, NULL, "%s (%u): client context not in terminated state", __func__, __LINE__ ); + return NULL; + } if ( origin != NULL ) handshake_req = "GET %s HTTP/1.1\r\n" "Host: %s\r\n" @@ -67,22 +73,15 @@ struct httplib_connection *httplib_connect_websocket_client( struct httplib_cont */ conn = httplib_download( ctx, host, port, use_ssl, error_buffer, error_buffer_size, handshake_req, path, host, magic, origin ); + if ( conn == NULL ) { - /* - * Connection object will be null if something goes wrong - */ + httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "%s (%u): Init of download failed", __func__, __LINE__ ); + return NULL; + } - if ( conn == NULL || strcmp( conn->request_info.request_uri, "101" ) ) { + if ( strcmp( conn->request_info.request_uri, "101" ) ) { - if ( ! *error_buffer ) { - - /* - * if there is a connection, but it did not return 101, - * error_buffer is not yet set - */ - - XX_httplib_snprintf( conn, NULL, error_buffer, error_buffer_size, "Unexpected server reply" ); - } + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): unexpected server reply \"%s\"", __func__, __LINE__, conn->request_info.request_uri ); conn = httplib_free( conn ); return NULL; @@ -95,6 +94,8 @@ struct httplib_connection *httplib_connect_websocket_client( struct httplib_cont if ( ctx->workerthreadids == NULL ) { + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): out of memory allocating worker thread IDs", __func__, __LINE__ ); + ctx->num_threads = 0; ctx->user_data = NULL; conn = httplib_free( conn ); @@ -106,6 +107,8 @@ struct httplib_connection *httplib_connect_websocket_client( struct httplib_cont if ( thread_data == NULL ) { + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): out of memory allocating thread data", __func__, __LINE__ ); + ctx->workerthreadids = httplib_free( ctx->workerthreadids ); ctx->num_threads = 0; ctx->user_data = NULL; @@ -127,11 +130,13 @@ struct httplib_connection *httplib_connect_websocket_client( struct httplib_cont if ( XX_httplib_start_thread_with_id( XX_httplib_websocket_client_thread, thread_data, ctx->workerthreadids) != 0 ) { + httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%u): thread failed to start", __func__, __LINE__ ); + thread_data = httplib_free( thread_data ); ctx->workerthreadids = httplib_free( ctx->workerthreadids ); + conn = httplib_free( conn ); ctx->num_threads = 0; ctx->user_data = NULL; - conn = httplib_free( conn ); return NULL; } diff --git a/src/httplib_create_client_context.c b/src/httplib_create_client_context.c index 8501dbf1..a91d54c3 100644 --- a/src/httplib_create_client_context.c +++ b/src/httplib_create_client_context.c @@ -54,6 +54,7 @@ struct httplib_context *httplib_create_client_context( const struct httplib_call ctx->callbacks.exit_context = exit_callback; ctx->ctx_type = CTX_TYPE_CLIENT; + ctx->status = CTX_STATUS_TERMINATED; return ctx; diff --git a/src/httplib_destroy_client_context.c b/src/httplib_destroy_client_context.c index e7d30885..f16edd81 100644 --- a/src/httplib_destroy_client_context.c +++ b/src/httplib_destroy_client_context.c @@ -38,6 +38,7 @@ void httplib_destroy_client_context( struct httplib_context *ctx ) { XX_httplib_free_config_options( ctx ); - ctx = httplib_free( ctx ); + ctx->workerthreadids = httplib_free( ctx->workerthreadids ); + ctx = httplib_free( ctx ); } /* httplib_destroy_client_context */ diff --git a/src/httplib_download.c b/src/httplib_download.c index e618ddbc..0c52ce31 100644 --- a/src/httplib_download.c +++ b/src/httplib_download.c @@ -47,13 +47,13 @@ struct httplib_connection * httplib_download( struct httplib_context *ctx, const va_start( ap, fmt ); ebuf[0] = '\0'; - conn = httplib_connect_client( ctx, host, port, use_ssl, ebuf, ebuf_len ); + conn = httplib_connect_client( ctx, host, port, use_ssl ); if ( conn != NULL ) { i = XX_httplib_vprintf( conn, fmt, ap ); - if (i <= 0) XX_httplib_snprintf( conn, NULL, ebuf, ebuf_len, "%s", "Error sending request" ); + if ( i <= 0 ) httplib_cry( DEBUG_LEVEL_ERROR, ctx, conn, "%s (%d): error sending request", __func__, __LINE__ ); else { XX_httplib_getreq( conn, ebuf, ebuf_len, &reqerr ); @@ -67,11 +67,13 @@ struct httplib_connection * httplib_download( struct httplib_context *ctx, const } } + else i = 0; + /* * if an error occured, close the connection */ - if ( ebuf[0] != '\0' && conn != NULL ) { + if ( i <= 0 && conn != NULL ) { httplib_close_connection( conn ); conn = NULL; diff --git a/src/httplib_main.h b/src/httplib_main.h index 73d981ba..58ff40e2 100644 --- a/src/httplib_main.h +++ b/src/httplib_main.h @@ -797,7 +797,7 @@ void XX_httplib_close_all_listening_sockets( struct httplib_context *ctx ); void XX_httplib_close_connection( struct httplib_connection *conn ); void XX_httplib_close_socket_gracefully( struct httplib_connection *conn ); int WINCDECL XX_httplib_compare_dir_entries( const void *p1, const void *p2 ); -bool XX_httplib_connect_socket( const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, SOCKET *sock, union usa *sa ); +bool XX_httplib_connect_socket( struct httplib_context *ctx, const char *host, int port, int use_ssl, SOCKET *sock, union usa *sa ); void XX_httplib_construct_etag( char *buf, size_t buf_len, const struct file *filep ); int XX_httplib_consume_socket( struct httplib_context *ctx, struct socket *sp, int thread_index ); void XX_httplib_delete_file( struct httplib_connection *conn, const char *path ); diff --git a/src/httplib_websocket_client_thread.c b/src/httplib_websocket_client_thread.c index 8db756d6..0dca836d 100644 --- a/src/httplib_websocket_client_thread.c +++ b/src/httplib_websocket_client_thread.c @@ -39,24 +39,24 @@ LIBHTTP_THREAD XX_httplib_websocket_client_thread( void *data ) { struct websocket_client_thread_data *cdata; cdata = data; + if ( cdata == NULL || cdata->conn == NULL || cdata->conn->ctx == NULL ) return LIBHTTP_THREAD_RETNULL; + + cdata->conn->ctx->status = CTX_STATUS_RUNNING; XX_httplib_set_thread_name( "ws-client" ); - if ( cdata->conn->ctx != NULL ) { - - /* - * 3 indicates a websocket client thread - * TODO: check if conn->ctx can be set - */ - - if ( cdata->conn->ctx->callbacks.init_thread != NULL ) cdata->conn->ctx->callbacks.init_thread( cdata->conn->ctx, 3 ); - } + if ( cdata->conn->ctx->callbacks.init_thread != NULL ) cdata->conn->ctx->callbacks.init_thread( cdata->conn->ctx, 3 ); XX_httplib_read_websocket( cdata->conn, cdata->data_handler, cdata->callback_data ); if ( cdata->close_handler != NULL ) cdata->close_handler( cdata->conn, cdata->callback_data ); - cdata = httplib_free( cdata ); + cdata->conn->ctx->workerthreadids = httplib_free( cdata->conn->ctx->workerthreadids ); + cdata->conn = httplib_free( cdata->conn ); + cdata = httplib_free( cdata ); + cdata->conn->ctx->user_data = NULL; + cdata->conn->ctx->num_threads = 0; + cdata->conn->ctx->status = CTX_STATUS_TERMINATED; return LIBHTTP_THREAD_RETNULL;