1
0
mirror of https://github.com/lammertb/libhttp.git synced 2025-08-06 05:02:40 +03:00

Client contexts are now real, not fake

This commit is contained in:
Lammert Bies
2016-12-31 21:32:02 +01:00
parent 712b91296c
commit f5e401578b
19 changed files with 845 additions and 597 deletions

View File

@@ -189,6 +189,7 @@ OBJLIST = \
${OBJDIR}extern_md5${OBJEXT} \
${OBJDIR}extern_sha1${OBJEXT} \
${OBJDIR}extern_ssl_lut${OBJEXT} \
${OBJDIR}httplib_abort_start${OBJEXT} \
${OBJDIR}httplib_accept_new_connection${OBJEXT} \
${OBJDIR}httplib_addenv${OBJEXT} \
${OBJDIR}httplib_atomic_dec${OBJEXT} \
@@ -204,14 +205,15 @@ OBJLIST = \
${OBJDIR}httplib_close_socket_gracefully${OBJEXT} \
${OBJDIR}httplib_closedir${OBJEXT} \
${OBJDIR}httplib_compare_dir_entries${OBJEXT} \
${OBJDIR}httplib_config_options${OBJEXT} \
${OBJDIR}httplib_connect_client${OBJEXT} \
${OBJDIR}httplib_connect_socket${OBJEXT} \
${OBJDIR}httplib_connect_websocket_client${OBJEXT} \
${OBJDIR}httplib_construct_etag${OBJEXT} \
${OBJDIR}httplib_consume_socket${OBJEXT} \
${OBJDIR}httplib_create_client_context${OBJEXT} \
${OBJDIR}httplib_cry${OBJEXT} \
${OBJDIR}httplib_delete_file${OBJEXT} \
${OBJDIR}httplib_destroy_client_context${OBJEXT} \
${OBJDIR}httplib_difftimespec${OBJEXT} \
${OBJDIR}httplib_dir_scan_callback${OBJEXT} \
${OBJDIR}httplib_discard_unread_request_data${OBJEXT} \
@@ -223,6 +225,7 @@ OBJLIST = \
${OBJDIR}httplib_fgets${OBJEXT} \
${OBJDIR}httplib_fopen${OBJEXT} \
${OBJDIR}httplib_forward_body_data${OBJEXT} \
${OBJDIR}httplib_free_config_options${OBJEXT} \
${OBJDIR}httplib_free_context${OBJEXT} \
${OBJDIR}httplib_get_builtin_mime_type${OBJEXT} \
${OBJDIR}httplib_get_context${OBJEXT} \
@@ -260,6 +263,7 @@ OBJLIST = \
${OBJDIR}httplib_handle_websocket_request${OBJEXT} \
${OBJDIR}httplib_header_has_option${OBJEXT} \
${OBJDIR}httplib_inet_pton${OBJEXT} \
${OBJDIR}httplib_init_options${OBJEXT} \
${OBJDIR}httplib_initialize_ssl${OBJEXT} \
${OBJDIR}httplib_interpret_uri${OBJEXT} \
${OBJDIR}httplib_is_authorized_for_put${OBJEXT} \
@@ -270,6 +274,7 @@ OBJLIST = \
${OBJDIR}httplib_is_valid_http_method${OBJEXT} \
${OBJDIR}httplib_is_valid_port${OBJEXT} \
${OBJDIR}httplib_is_websocket_protocol${OBJEXT} \
${OBJDIR}httplib_process_options${OBJEXT} \
${OBJDIR}httplib_pthread_join${OBJEXT} \
${OBJDIR}httplib_kill${OBJEXT} \
${OBJDIR}httplib_load_dll${OBJEXT} \
@@ -375,6 +380,8 @@ OBJLIST = \
${OBJDIR}httplib_strndup${OBJEXT} \
${OBJDIR}httplib_substitute_index_file${OBJEXT} \
${OBJDIR}httplib_suggest_connection_header${OBJEXT} \
${OBJDIR}httplib_system_exit${OBJEXT} \
${OBJDIR}httplib_system_init${OBJEXT} \
${OBJDIR}httplib_timer${OBJEXT} \
${OBJDIR}httplib_tls_dtor${OBJEXT} \
${OBJDIR}httplib_uninitialize_ssl${OBJEXT} \
@@ -448,6 +455,10 @@ ${OBJDIR}extern_ssl_lut${OBJEXT} : ${SRCDIR}extern_ssl_lut.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_abort_start${OBJEXT} : ${SRCDIR}httplib_abort_start.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_accept_new_connection${OBJEXT} : ${SRCDIR}httplib_accept_new_connection.c \
${SRCDIR}httplib_ssl.h \
${SRCDIR}httplib_main.h \
@@ -517,10 +528,6 @@ ${OBJDIR}httplib_compare_dir_entries${OBJEXT} : ${SRCDIR}httplib_compare_dir_
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_config_options${OBJEXT} : ${SRCDIR}httplib_config_options.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_connect_client${OBJEXT} : ${SRCDIR}httplib_connect_client.c \
${SRCDIR}httplib_pthread.h \
${SRCDIR}httplib_ssl.h \
@@ -550,6 +557,10 @@ ${OBJDIR}httplib_consume_socket${OBJEXT} : ${SRCDIR}httplib_consume_socket.c
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_create_client_context${OBJEXT} : ${SRCDIR}httplib_create_client_context.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_cry${OBJEXT} : ${SRCDIR}httplib_cry.c \
${SRCDIR}httplib_ssl.h \
${SRCDIR}httplib_main.h \
@@ -559,6 +570,10 @@ ${OBJDIR}httplib_delete_file${OBJEXT} : ${SRCDIR}httplib_delete_file.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_destroy_client_context${OBJEXT} : ${SRCDIR}httplib_destroy_client_context.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_difftimespec${OBJEXT} : ${SRCDIR}httplib_difftimespec.c \
${SRCDIR}httplib_utils.h \
${SRCDIR}httplib_main.h \
@@ -606,6 +621,10 @@ ${OBJDIR}httplib_forward_body_data${OBJEXT} : ${SRCDIR}httplib_forward_body_d
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_free_config_options${OBJEXT} : ${SRCDIR}httplib_free_config_options.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_free_context${OBJEXT} : ${SRCDIR}httplib_free_context.c \
${SRCDIR}httplib_pthread.h \
${SRCDIR}httplib_ssl.h \
@@ -776,6 +795,10 @@ ${OBJDIR}httplib_inet_pton${OBJEXT} : ${SRCDIR}httplib_inet_pton.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_init_options${OBJEXT} : ${SRCDIR}httplib_init_options.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_initialize_ssl${OBJEXT} : ${SRCDIR}httplib_initialize_ssl.c \
${SRCDIR}httplib_pthread.h \
${SRCDIR}httplib_ssl.h \
@@ -821,6 +844,10 @@ ${OBJDIR}httplib_is_websocket_protocol${OBJEXT} : ${SRCDIR}httplib_is_websock
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_process_options${OBJEXT} : ${SRCDIR}httplib_process_options.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_pthread_join${OBJEXT} : ${SRCDIR}httplib_pthread_join.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
@@ -1303,6 +1330,14 @@ ${OBJDIR}httplib_substitute_index_file${OBJEXT} : ${SRCDIR}httplib_substitute
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_system_exit${OBJEXT} : ${SRCDIR}httplib_system_exit.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_system_init${OBJEXT} : ${SRCDIR}httplib_system_init.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_suggest_connection_header${OBJEXT} : ${SRCDIR}httplib_suggest_connection_header.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h

View File

@@ -667,14 +667,6 @@ LIBHTTP_API int httplib_get_cookie(const char *cookie, const char *var_name, cha
conn = httplib_download("google.com", 80, 0, ebuf, sizeof(ebuf),
"%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
*/
LIBHTTP_API struct httplib_connection *
httplib_download(const char *host,
int port,
int use_ssl,
char *error_buffer,
size_t error_buffer_size,
PRINTF_FORMAT_STRING(const char *request_fmt),
...) PRINTF_ARGS(6, 7);
/* Close the connection opened by httplib_download(). */
@@ -841,16 +833,6 @@ LIBHTTP_API char *httplib_md5(char buf[33], ...);
On success, valid httplib_connection object.
On error, NULL. Se error_buffer for details.
*/
LIBHTTP_API struct httplib_connection *httplib_connect_websocket_client( 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);
/* Connect to a TCP server as a client (can be used to connect to a HTTP server)
@@ -865,7 +847,6 @@ LIBHTTP_API struct httplib_connection *httplib_connect_websocket_client( const c
On success, valid httplib_connection object.
On error, NULL. Se error_buffer for details.
*/
LIBHTTP_API struct httplib_connection *httplib_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size);
struct httplib_client_options {
@@ -877,7 +858,6 @@ struct httplib_client_options {
};
LIBHTTP_API struct httplib_connection *httplib_connect_client_secure(const struct httplib_client_options *client_options, char *error_buffer, size_t error_buffer_size);
enum debug_level_t {
@@ -924,7 +904,13 @@ 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_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_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);
LIBHTTP_API void httplib_destroy_client_context( struct httplib_context *ctx );
LIBHTTP_API struct httplib_connection * httplib_download( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, PRINTF_FORMAT_STRING(const char *request_fmt), ...) PRINTF_ARGS(7, 8);
LIBHTTP_API char * httplib_error_string( int error_code, char *buf, size_t buf_len );
LIBHTTP_API const char * httplib_get_builtin_mime_type( const char *file_name );
LIBHTTP_API enum debug_level_t httplib_get_debug_level( struct httplib_context *ctx );
@@ -967,6 +953,8 @@ LIBHTTP_API char * httplib_strdup( const char *str );
LIBHTTP_API void httplib_strlcpy( char *dst, const char *src, size_t len );
LIBHTTP_API int httplib_strncasecmp( const char *s1, const char *s2, size_t len );
LIBHTTP_API char * httplib_strndup( const char *str, size_t len );
LIBHTTP_API int httplib_system_exit( void );
LIBHTTP_API int httplib_system_init( void );
LIBHTTP_API const char * httplib_version( void );
#ifdef __cplusplus

56
src/httplib_abort_start.c Normal file
View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* struct httplib_context *XX_httplib_abort_start( struct httplib_context *ctx, const char *fmt, ... );
*
* The function XX_httplib_abort_start() is called to do some cleanup work when
* an error occured initializing a context. The function returns NULL which is
* then further returned to the calling party.
*/
struct httplib_context *XX_httplib_abort_start( struct httplib_context *ctx, const char *fmt, ... ) {
va_list ap;
char buf[MG_BUF_LEN];
if ( ctx == NULL ) return NULL;
if ( fmt != NULL ) {
va_start( ap, fmt );
vsnprintf_impl( buf, sizeof(buf), fmt, ap );
va_end( ap );
buf[sizeof(buf)-1] = 0;
httplib_cry( DEBUG_LEVEL_CRASH, ctx, NULL, "%s", buf );
}
XX_httplib_free_context( ctx );
httplib_pthread_setspecific( XX_httplib_sTlsKey, NULL );
return NULL;
} /* XX_httplib_abort_start */

View File

@@ -30,30 +30,30 @@
#include "httplib_ssl.h"
#include "httplib_string.h"
static struct httplib_connection * httplib_connect_client_impl( 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, char *ebuf, size_t ebuf_len );
/*
* struct httplib_connection *httplib_connect_client_secure( const struct httplib_client_options *client options, char *error buffer, size_t error_buffer_size );
* 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 );
*
* The function httplib_connect_client_secure() creates a secure connection as a
* client to a remote server and returns a pointer to the connection
* information, or NULL if an error occured.
*/
LIBHTTP_API struct httplib_connection *httplib_connect_client_secure( 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, char *error_buffer, size_t error_buffer_size ) {
return httplib_connect_client_impl( client_options, 1, error_buffer, error_buffer_size );
return httplib_connect_client_impl( ctx, client_options, 1, error_buffer, error_buffer_size );
} /* httplib_connect_client_secure */
/*
* struct httplib_connection *httplib_connect_client( 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, char *error_buffer, size_t error_buffer_size );
*
* 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( 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, char *error_buffer, size_t error_buffer_size ) {
struct httplib_client_options opts;
@@ -61,22 +61,21 @@ struct httplib_connection * httplib_connect_client( const char *host, int port,
opts.host = host;
opts.port = port;
return httplib_connect_client_impl( &opts, use_ssl, error_buffer, error_buffer_size );
return httplib_connect_client_impl( ctx, &opts, use_ssl, error_buffer, error_buffer_size );
} /* httplib_connect_client */
/*
* static struct httplib_connection *httplib_connect_client_impl( 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, char *ebuf, size_t ebuf_len );
*
* 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( 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, char *ebuf, size_t ebuf_len ) {
static struct httplib_context fake_ctx;
struct httplib_connection *conn;
SOCKET sock;
union usa sa;
@@ -84,6 +83,8 @@ static struct httplib_connection *httplib_connect_client_impl( const struct http
struct sockaddr *psa;
char error_string[ERROR_STRING_LEN];
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 ( (conn = httplib_calloc( 1, sizeof(*conn) + MAX_REQUEST_SIZE )) == NULL ) {
@@ -108,11 +109,11 @@ static struct httplib_connection *httplib_connect_client_impl( const struct http
conn->buf_size = MAX_REQUEST_SIZE;
conn->buf = (char *)(conn + 1);
conn->ctx = &fake_ctx;
conn->ctx = ctx;
conn->client.sock = sock;
conn->client.lsa = sa;
if ( getsockname( sock, psa, &len ) != 0 ) httplib_cry( DEBUG_LEVEL_ERROR, &fake_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: getsockname() failed: %s", __func__, 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 );
@@ -120,7 +121,7 @@ static struct httplib_connection *httplib_connect_client_impl( const struct http
#ifndef NO_SSL
if ( use_ssl ) {
fake_ctx.ssl_ctx = conn->client_ssl_ctx;
ctx->ssl_ctx = conn->client_ssl_ctx;
/*
* TODO: Check ssl_verify_peer and ssl_ca_path here.
@@ -134,7 +135,7 @@ static struct httplib_connection *httplib_connect_client_impl( const struct http
if ( client_options->client_cert ) {
if ( ! XX_httplib_ssl_use_pem_file( &fake_ctx, client_options->client_cert ) ) {
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" );
SSL_CTX_free( conn->client_ssl_ctx );

View File

@@ -36,16 +36,14 @@
* returned, otherwise NULL.
*/
struct httplib_connection *httplib_connect_websocket_client( 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 ) {
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 ) {
struct httplib_connection *conn;
struct httplib_context *newctx;
struct websocket_client_thread_data *thread_data;
static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
const char *handshake_req;
conn = NULL;
newctx = NULL;
if ( origin != NULL ) handshake_req = "GET %s HTTP/1.1\r\n"
"Host: %s\r\n"
@@ -68,7 +66,7 @@ struct httplib_connection *httplib_connect_websocket_client( const char *host, i
* Establish the client connection and request upgrade
*/
conn = httplib_download( host, port, use_ssl, error_buffer, error_buffer_size, handshake_req, path, host, magic, origin );
conn = httplib_download( ctx, host, port, use_ssl, error_buffer, error_buffer_size, handshake_req, path, host, magic, origin );
/*
* Connection object will be null if something goes wrong
@@ -90,35 +88,27 @@ struct httplib_connection *httplib_connect_websocket_client( const char *host, i
return NULL;
}
/*
* For client connections, httplib_context is fake. Since we need to set a
* callback function, we need to create a copy and modify it.
*/
ctx->user_data = user_data;
ctx->ctx_type = CTX_TYPE_CLIENT;
ctx->num_threads = 1; /* one worker thread will be created */
ctx->workerthreadids = httplib_calloc( ctx->num_threads, sizeof(pthread_t) );
newctx = httplib_malloc( sizeof(struct httplib_context) );
if ( newctx == NULL ) { conn = httplib_free( conn ); return NULL; }
if ( ctx->workerthreadids == NULL ) {
*newctx = *conn->ctx;
newctx->user_data = user_data;
newctx->ctx_type = CTX_TYPE_CLIENT;
newctx->num_threads = 1; /* one worker thread will be created */
newctx->workerthreadids = httplib_calloc( newctx->num_threads, sizeof(pthread_t) );
if ( newctx->workerthreadids == NULL ) {
newctx = httplib_free( newctx );
ctx->num_threads = 0;
ctx->user_data = NULL;
conn = httplib_free( conn );
return NULL;
}
conn->ctx = newctx;
thread_data = httplib_calloc( sizeof(struct websocket_client_thread_data), 1 );
if ( thread_data == NULL ) {
newctx->workerthreadids = httplib_free( newctx->workerthreadids );
newctx = httplib_free( newctx );
ctx->workerthreadids = httplib_free( ctx->workerthreadids );
ctx->num_threads = 0;
ctx->user_data = NULL;
conn = httplib_free( conn );
return NULL;
@@ -135,11 +125,12 @@ struct httplib_connection *httplib_connect_websocket_client( const char *host, i
* called on the client connection
*/
if ( XX_httplib_start_thread_with_id( XX_httplib_websocket_client_thread, thread_data, newctx->workerthreadids) != 0 ) {
if ( XX_httplib_start_thread_with_id( XX_httplib_websocket_client_thread, thread_data, ctx->workerthreadids) != 0 ) {
thread_data = httplib_free( thread_data );
newctx->workerthreadids = httplib_free( newctx->workerthreadids );
newctx = httplib_free( newctx );
ctx->workerthreadids = httplib_free( ctx->workerthreadids );
ctx->num_threads = 0;
ctx->user_data = NULL;
conn = httplib_free( conn );
return NULL;

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* struct httplib_context *httplib_create_client_context( const struct httplib_option_t *options );
*
* The function httplib_create_client_context() creates a context to be used
* for one simultaneous client connection. It is not possible to use one client
* context for multiple connections at the same time, because the contect
* contains SSL context information which is specific for one connection.
*/
struct httplib_context *httplib_create_client_context( const struct httplib_option_t *options ) {
struct httplib_context *ctx;
ctx = httplib_calloc( 1, sizeof(struct httplib_context) );
if ( ctx == NULL ) return NULL;
if ( XX_httplib_init_options( ctx ) ) return NULL;
if ( XX_httplib_process_options( ctx, options ) ) return NULL;
return ctx;
} /* httplib_create_client_context */

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* void httplib_destroy_client_context( struct httplib_context *ctx );
*
* The function httplib_destroy_client_context() destroys the context for a
* client connection. This function should not be called for server contexts.
* Use httplib_stop() for server contexts instead.
*/
void httplib_destroy_client_context( struct httplib_context *ctx ) {
if ( ctx == NULL ) return;
XX_httplib_free_config_options( ctx );
httplib_free( ctx );
} /* httplib_destroy_client_context */

View File

@@ -35,17 +35,19 @@
* and returns a pointer to the connection on success, or NULL on error.
*/
struct httplib_connection * httplib_download( const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt, ... ) {
struct httplib_connection * httplib_download( struct httplib_context *ctx, const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len, const char *fmt, ... ) {
struct httplib_connection *conn;
va_list ap;
int i;
int reqerr;
if ( ctx == NULL ) return NULL;
va_start( ap, fmt );
ebuf[0] = '\0';
conn = httplib_connect_client( host, port, use_ssl, ebuf, ebuf_len );
conn = httplib_connect_client( ctx, host, port, use_ssl, ebuf, ebuf_len );
if ( conn != NULL ) {

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* void XX_httplib_free_config_options( struct htptlib_context *ctx );
*
* The function XX_httplib_free_config_options() returns all the from the heap
* allocated space to store config options back to the heap.
*/
void XX_httplib_free_config_options( struct httplib_context *ctx ) {
if ( ctx == NULL ) return;
ctx->access_control_allow_origin = httplib_free( ctx->access_control_allow_origin );
ctx->access_control_list = httplib_free( ctx->access_control_list );
ctx->access_log_file = httplib_free( ctx->access_log_file );
ctx->authentication_domain = httplib_free( ctx->authentication_domain );
ctx->cgi_environment = httplib_free( ctx->cgi_environment );
ctx->cgi_interpreter = httplib_free( ctx->cgi_interpreter );
ctx->document_root = httplib_free( ctx->document_root );
ctx->error_log_file = httplib_free( ctx->error_log_file );
ctx->error_pages = httplib_free( ctx->error_pages );
ctx->extra_mime_types = httplib_free( ctx->extra_mime_types );
ctx->global_auth_file = httplib_free( ctx->global_auth_file );
ctx->hide_file_pattern = httplib_free( ctx->hide_file_pattern );
ctx->index_files = httplib_free( ctx->index_files );
ctx->listening_ports = httplib_free( ctx->listening_ports );
ctx->protect_uri = httplib_free( ctx->protect_uri );
ctx->put_delete_auth_file = httplib_free( ctx->put_delete_auth_file );
ctx->run_as_user = httplib_free( ctx->run_as_user );
ctx->ssi_pattern = httplib_free( ctx->ssi_pattern );
ctx->ssl_ca_file = httplib_free( ctx->ssl_ca_file );
ctx->ssl_ca_path = httplib_free( ctx->ssl_ca_path );
ctx->ssl_certificate = httplib_free( ctx->ssl_certificate );
ctx->ssl_cipher_list = httplib_free( ctx->ssl_cipher_list );
ctx->throttle = httplib_free( ctx->throttle );
ctx->url_rewrite_patterns = httplib_free( ctx->url_rewrite_patterns );
ctx->websocket_root = httplib_free( ctx->websocket_root );
} /* XX_httplib_free_config_options */

View File

@@ -74,35 +74,7 @@ void XX_httplib_free_context( struct httplib_context *ctx ) {
timers_exit( ctx );
#endif
/*
* Deallocate config parameters
*/
ctx->access_control_allow_origin = httplib_free( ctx->access_control_allow_origin );
ctx->access_control_list = httplib_free( ctx->access_control_list );
ctx->access_log_file = httplib_free( ctx->access_log_file );
ctx->authentication_domain = httplib_free( ctx->authentication_domain );
ctx->cgi_environment = httplib_free( ctx->cgi_environment );
ctx->cgi_interpreter = httplib_free( ctx->cgi_interpreter );
ctx->document_root = httplib_free( ctx->document_root );
ctx->error_log_file = httplib_free( ctx->error_log_file );
ctx->error_pages = httplib_free( ctx->error_pages );
ctx->extra_mime_types = httplib_free( ctx->extra_mime_types );
ctx->global_auth_file = httplib_free( ctx->global_auth_file );
ctx->hide_file_pattern = httplib_free( ctx->hide_file_pattern );
ctx->index_files = httplib_free( ctx->index_files );
ctx->listening_ports = httplib_free( ctx->listening_ports );
ctx->protect_uri = httplib_free( ctx->protect_uri );
ctx->put_delete_auth_file = httplib_free( ctx->put_delete_auth_file );
ctx->run_as_user = httplib_free( ctx->run_as_user );
ctx->ssi_pattern = httplib_free( ctx->ssi_pattern );
ctx->ssl_ca_file = httplib_free( ctx->ssl_ca_file );
ctx->ssl_ca_path = httplib_free( ctx->ssl_ca_path );
ctx->ssl_certificate = httplib_free( ctx->ssl_certificate );
ctx->ssl_cipher_list = httplib_free( ctx->ssl_cipher_list );
ctx->throttle = httplib_free( ctx->throttle );
ctx->url_rewrite_patterns = httplib_free( ctx->url_rewrite_patterns );
ctx->websocket_root = httplib_free( ctx->websocket_root );
XX_httplib_free_config_options( ctx );
/*
* Deallocate request handlers

118
src/httplib_init_options.c Normal file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* bool XX_httplib_init_options( struct httplib_context *ctx );
*
* The function XX_httplib_init_options() sets the options of a newly created
* context to reasonablei default values. When succesful, the function returns
* false. Otherwise true is returned, and the function already performed a
* cleanup.
*/
bool XX_httplib_init_options( struct httplib_context *ctx ) {
if ( ctx == NULL ) return true;
ctx->access_control_allow_origin = NULL;
ctx->access_control_list = NULL;
ctx->access_log_file = NULL;
ctx->allow_sendfile_call = true;
ctx->authentication_domain = NULL;
ctx->cgi_environment = NULL;
ctx->cgi_interpreter = NULL;
ctx->cgi_pattern = NULL;
ctx->debug_level = DEBUG_LEVEL_WARNING;
ctx->decode_url = true;
ctx->document_root = NULL;
ctx->enable_directory_listing = true;
ctx->enable_keep_alive = false;
ctx->error_log_file = NULL;
ctx->error_pages = NULL;
ctx->extra_mime_types = NULL;
ctx->global_auth_file = NULL;
ctx->hide_file_pattern = NULL;
ctx->index_files = NULL;
ctx->listening_ports = NULL;
ctx->num_threads = 50;
ctx->protect_uri = NULL;
ctx->put_delete_auth_file = NULL;
ctx->request_timeout = 30000;
ctx->run_as_user = NULL;
ctx->ssi_pattern = NULL;
ctx->ssl_ca_file = NULL;
ctx->ssl_ca_path = NULL;
ctx->ssl_certificate = NULL;
ctx->ssl_cipher_list = NULL;
ctx->ssl_protocol_version = 0;
ctx->ssl_short_trust = false;
ctx->ssl_verify_depth = 9;
ctx->ssl_verify_paths = true;
ctx->ssl_verify_peer = false;
ctx->static_file_max_age = 0;
ctx->throttle = NULL;
ctx->tcp_nodelay = false;
ctx->url_rewrite_patterns = NULL;
ctx->websocket_root = NULL;
ctx->websocket_timeout = 30000;
if ( (ctx->access_control_allow_origin = httplib_strdup( "*" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"access_control_allow_origin\"" );
return true;
}
if ( (ctx->authentication_domain = httplib_strdup( "example.com" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"authentication_domain\"" );
return true;
}
if ( (ctx->cgi_pattern = httplib_strdup( "**.cgi$|**.pl$|**.php$" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"cgi_pattern\"" );
return true;
}
if ( (ctx->index_files = httplib_strdup( "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"index_files\"" );
return true;
}
if ( (ctx->listening_ports = httplib_strdup( "8080" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"listening_ports\"" );
return true;
}
if ( (ctx->ssi_pattern = httplib_strdup( "**.shtml$|**.shtm$" )) == NULL ) {
XX_httplib_abort_start( ctx, "Out of memory creating context allocating \"ssi_pattern\"" );
return true;
}
return false;
} /* XX_httplib_init_options */

View File

@@ -786,6 +786,7 @@ void SHA1Final( unsigned char digest[20], SHA1_CTX *context );
void SHA1Init( SHA1_CTX *context );
void SHA1Update( SHA1_CTX *context, const unsigned char *data, uint32_t len );
struct httplib_context *XX_httplib_abort_start( struct httplib_context *ctx, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
void XX_httplib_accept_new_connection( const struct socket *listener, struct httplib_context *ctx );
bool XX_httplib_authorize( struct httplib_connection *conn, struct file *filep );
const char * XX_httplib_builtin_mime_ext( int index );
@@ -808,6 +809,7 @@ void XX_httplib_fclose_on_exec( struct file *filep, struct httplib_connection
const char * XX_httplib_fgets( char *buf, size_t size, struct file *filep, char **p );
bool XX_httplib_fopen( const struct httplib_connection *conn, const char *path, const char *mode, struct file *filep );
bool XX_httplib_forward_body_data( struct httplib_connection *conn, FILE *fp, SOCKET sock, SSL *ssl );
void XX_httplib_free_config_options( struct httplib_context *ctx );
void XX_httplib_free_context( struct httplib_context *ctx );
const char * XX_httplib_get_header( const struct httplib_request_info *ri, const char *name );
void XX_httplib_get_mime_type( struct httplib_context *ctx, const char *path, struct vec *vec );
@@ -828,6 +830,7 @@ void XX_httplib_handle_ssi_file_request( struct httplib_connection *conn, cons
void XX_httplib_handle_static_file_request( struct httplib_connection *conn, const char *path, struct file *filep, const char *mime_type, const char *additional_headers );
void XX_httplib_handle_websocket_request( struct httplib_connection *conn, const char *path, int is_callback_resource, httplib_websocket_connect_handler ws_connect_handler, httplib_websocket_ready_handler ws_ready_handler, httplib_websocket_data_handler ws_data_handler, httplib_websocket_close_handler ws_close_handler, void *cbData );
bool XX_httplib_header_has_option( const char *header, const char *option );
bool XX_httplib_init_options( struct httplib_context *ctx );
void XX_httplib_interpret_uri( struct httplib_connection *conn, char *filename, size_t filename_buf_len, struct file *filep, bool *is_found, bool *is_script_resource, bool *is_websocket_request, bool *is_put_or_delete_request );
bool XX_httplib_is_authorized_for_put( struct httplib_connection *conn );
bool XX_httplib_is_file_in_memory( const struct httplib_connection *conn, const char *path, struct file *filep );
@@ -857,6 +860,7 @@ void XX_httplib_path_to_unicode( const char *path, wchar_t *wbuf, size_t wbuf_
void XX_httplib_prepare_cgi_environment( struct httplib_connection *conn, const char *prog, struct cgi_environment *env );
void XX_httplib_print_dir_entry( struct de *de );
void XX_httplib_process_new_connection( struct httplib_connection *conn );
bool XX_httplib_process_options( struct httplib_context *ctx, const struct httplib_option_t *options );
void XX_httplib_produce_socket( struct httplib_context *ctx, const struct socket *sp );
int XX_httplib_pull( FILE *fp, struct httplib_connection *conn, char *buf, int len, double timeout );
int XX_httplib_pull_all( FILE *fp, struct httplib_connection *conn, char *buf, int len );
@@ -929,3 +933,5 @@ extern pthread_mutexattr_t XX_httplib_pthread_mutex_attr;
#endif /* _WIN32 */
extern const struct uriprot_tp XX_httplib_abs_uri_protocols[];
extern int XX_httplib_sTlsInit;
extern pthread_key_t XX_httplib_sTlsKey;

View File

@@ -0,0 +1,338 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config );
static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, enum debug_level_t *config );
static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_int( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, int *config, int minval, int maxval );
static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
/*
* bool XX_httplib_process_options( struct httplib_context *ctx, const struct httplib_option_t *options );
*
* The function process_options() processes the user supplied options and adds
* them to the central option list of the context. If en error occurs, the
* function returns true, otherwise FALSE is returned. In case of an error all
* cleanup is already done before returning and an error message has been
* generated.
*/
bool XX_httplib_process_options( struct httplib_context *ctx, const struct httplib_option_t *options ) {
if ( ctx == NULL ) return true;
while ( options != NULL && options->name != NULL ) {
if ( check_str( ctx, options, "access_control_allow_origin", & ctx->access_control_allow_origin ) ) return true;
if ( check_str( ctx, options, "access_control_list", & ctx->access_control_list ) ) return true;
if ( check_file( ctx, options, "access_log_file", & ctx->access_log_file ) ) return true;
if ( check_bool( ctx, options, "allow_sendfile_call", & ctx->allow_sendfile_call ) ) return true;
if ( check_str( ctx, options, "authentication_domain", & ctx->authentication_domain ) ) return true;
if ( check_str( ctx, options, "cgi_environment", & ctx->cgi_environment ) ) return true;
if ( check_file( ctx, options, "cgi_interpreter", & ctx->cgi_interpreter ) ) return true;
if ( check_patt( ctx, options, "cgi_pattern", & ctx->cgi_pattern ) ) return true;
if ( check_dbg( ctx, options, "debug_level", & ctx->debug_level ) ) return true;
if ( check_bool( ctx, options, "decode_url", & ctx->decode_url ) ) return true;
if ( check_dir( ctx, options, "document_root", & ctx->document_root ) ) return true;
if ( check_bool( ctx, options, "enable_directory_listing", & ctx->enable_directory_listing ) ) return true;
if ( check_bool( ctx, options, "enable_keep_alive", & ctx->enable_keep_alive ) ) return true;
if ( check_file( ctx, options, "error_log_file", & ctx->error_log_file ) ) return true;
if ( check_dir( ctx, options, "error_pages", & ctx->error_pages ) ) return true;
if ( check_str( ctx, options, "extra_mime_types", & ctx->extra_mime_types ) ) return true;
if ( check_file( ctx, options, "global_auth_file", & ctx->global_auth_file ) ) return true;
if ( check_patt( ctx, options, "hide_file_pattern", & ctx->hide_file_pattern ) ) return true;
if ( check_str( ctx, options, "index_files", & ctx->index_files ) ) return true;
if ( check_str( ctx, options, "listening_ports", & ctx->listening_ports ) ) return true;
if ( check_int( ctx, options, "num_threads", & ctx->num_threads, 1, INT_MAX ) ) return true;
if ( check_str( ctx, options, "protect_uri", & ctx->protect_uri ) ) return true;
if ( check_file( ctx, options, "put_delete_auth_file", & ctx->put_delete_auth_file ) ) return true;
if ( check_int( ctx, options, "request_timeout", & ctx->request_timeout, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "run_as_user", & ctx->run_as_user ) ) return true;
if ( check_patt( ctx, options, "ssi_pattern", & ctx->ssi_pattern ) ) return true;
if ( check_file( ctx, options, "ssl_ca_file", & ctx->ssl_ca_file ) ) return true;
if ( check_dir( ctx, options, "ssl_ca_path", & ctx->ssl_ca_path ) ) return true;
if ( check_file( ctx, options, "ssl_certificate", & ctx->ssl_certificate ) ) return true;
if ( check_str( ctx, options, "ssl_cipher_list", & ctx->ssl_cipher_list ) ) return true;
if ( check_int( ctx, options, "ssl_protocol_version", & ctx->ssl_protocol_version, 0, 4 ) ) return true;
if ( check_bool( ctx, options, "ssl_short_trust", & ctx->ssl_short_trust ) ) return true;
if ( check_int( ctx, options, "ssl_verify_depth", & ctx->ssl_verify_depth, 0, 9 ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_paths", & ctx->ssl_verify_paths ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_peer", & ctx->ssl_verify_peer ) ) return true;
if ( check_int( ctx, options, "static_file_max_age", & ctx->static_file_max_age, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "throttle", & ctx->throttle ) ) return true;
if ( check_bool( ctx, options, "tcp_nodelay", & ctx->tcp_nodelay ) ) return true;
if ( check_str( ctx, options, "url_rewrite_patterns", & ctx->url_rewrite_patterns ) ) return true;
if ( check_dir( ctx, options, "websocket_root", & ctx->websocket_root ) ) return true;
if ( check_int( ctx, options, "websocket_timeout", & ctx->websocket_timeout, 0, INT_MAX ) ) return true;
/*
* TODO: Currently silently ignoring unrecognized options
*/
options++;
}
return false;
} /* XX_httplib_process_options */
/*
* static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config );
*
* The function check_bool() checks if an option is equal to a boolean config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found, also
* false is returned.
*/
static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing boolean option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_bool( option->value, config ) ) return false;
XX_httplib_abort_start( ctx, "Invalid boolean value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_bool */
/*
* static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_dir() checks if an option is equal to a directory config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing directory option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_dir */
/*
* static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_patt() checks if an option is equal to a pattern config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing pattern option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_patt */
/*
* static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_file() checks if an option is equal to a filename config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing file option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_file */
/*
* static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_str() checks if an option is equal to a string config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing string option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
XX_httplib_abort_start( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_str */
/*
* static bool check_int( struct httplib_context *ctx, const struct httplib_opion_t *option, const char *name, int *config, int minval, int maxval );
*
* The function check_int() checks in an option is equal to an integer config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found and is
* valud, also false is returned.
*/
static bool check_int( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, int *config, int minval, int maxval ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing integer option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, & val ) ) {
if ( val < minval ) { XX_httplib_abort_start( ctx, "Integer \"%s\" too small for option \"%s\"", option->value, option->name ); return true; }
if ( val > maxval ) { XX_httplib_abort_start( ctx, "Integer \"%s\" too large for option \"%s\"", option->value, option->name ); return true; }
*config = val;
return false;
}
XX_httplib_abort_start( ctx, "Invalid integer value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_int */
/*
* static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name );
*
* The function check_dbg() checks if an option is equal to a debug level
* config parameter and stores the value if that is the case. If the value
* cannot be recognized, true is returned and the function performs a complete
* cleanup. If the option name could not be found, the function returns false
* to indicate that the search should go on. If the value could be found and is
* valid, also false is returned.
*/
static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, enum debug_level_t *config ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
XX_httplib_abort_start( ctx, "Internal error parsing debug level option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, &val ) ) {
switch ( val ) {
case DEBUG_LEVEL_NONE :
case DEBUG_LEVEL_CRASH :
case DEBUG_LEVEL_ERROR :
case DEBUG_LEVEL_WARNING :
case DEBUG_LEVEL_INFO :
*config = val;
return false;
}
}
XX_httplib_abort_start( ctx, "Invalid value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_dbg */

View File

@@ -23,5 +23,4 @@
extern pthread_mutex_t * XX_httplib_ssl_mutexes;
extern pthread_key_t XX_httplib_sTlsKey;
extern int XX_httplib_thread_idx_max;

View File

@@ -150,6 +150,5 @@ void XX_httplib_uninitialize_ssl( struct httplib_context *ctx );
extern int XX_httplib_cryptolib_users;
extern struct ssl_func XX_httplib_crypto_sw[];
extern struct ssl_func XX_httplib_ssl_sw[];
extern int XX_httplib_sTlsInit;
#endif /* NO_SSL */

View File

@@ -31,16 +31,6 @@
#include "httplib_string.h"
#include "httplib_utils.h"
static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config );
static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, enum debug_level_t *config );
static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_int( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, int *config, int minval, int maxval );
static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
static struct httplib_context * cleanup( struct httplib_context *ctx, PRINTF_FORMAT_STRING(const char *fmt), ...) PRINTF_ARGS(2, 3);
static bool process_options( struct httplib_context *ctx, const struct httplib_option_t *options );
/*
* struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks, void *user_data, const struct httplib_t *options );
*
@@ -56,19 +46,6 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
void (*exit_callback)(const struct httplib_context *ctx);
struct httplib_workerTLS tls;
#if defined(_WIN32)
/*
* Yes, this is Windows and nothing works out of the box. We first have
* to initialize socket communications by telling Windows which socket
* version we want to use. 2.2 in this case.
*/
WSADATA data;
WSAStartup( MAKEWORD(2, 2), &data );
#endif /* _WIN32 */
/*
* No memory for the ctx structure is the only error which we
* don't log through httplib_cry() for the simple reason that we do not
@@ -78,7 +55,7 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
*/
exit_callback = NULL;
ctx = httplib_calloc( 1, sizeof(*ctx) );
ctx = httplib_calloc( 1, sizeof(struct httplib_context) );
if ( ctx == NULL ) return NULL;
@@ -145,17 +122,18 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
#endif
httplib_pthread_setspecific( XX_httplib_sTlsKey, & tls );
if ( httplib_pthread_mutex_init( & ctx->thread_mutex, &XX_httplib_pthread_mutex_attr ) ) return cleanup( ctx, "Cannot initialize thread mutex" );
if ( httplib_pthread_mutex_init( & ctx->thread_mutex, &XX_httplib_pthread_mutex_attr ) ) return XX_httplib_abort_start( ctx, "Cannot initialize thread mutex" );
#if !defined(ALTERNATIVE_QUEUE)
if ( httplib_pthread_cond_init( & ctx->sq_empty, NULL ) ) return cleanup( ctx, "Cannot initialize empty queue condition" );
if ( httplib_pthread_cond_init( & ctx->sq_full, NULL ) ) return cleanup( ctx, "Cannot initialize full queue condition" );
if ( httplib_pthread_cond_init( & ctx->sq_empty, NULL ) ) return XX_httplib_abort_start( ctx, "Cannot initialize empty queue condition" );
if ( httplib_pthread_cond_init( & ctx->sq_full, NULL ) ) return XX_httplib_abort_start( ctx, "Cannot initialize full queue condition" );
#endif
if ( httplib_pthread_mutex_init( & ctx->nonce_mutex, & XX_httplib_pthread_mutex_attr ) ) return cleanup( ctx, "Cannot initialize nonce mutex" );
if ( httplib_pthread_mutex_init( & ctx->nonce_mutex, & XX_httplib_pthread_mutex_attr ) ) return XX_httplib_abort_start( ctx, "Cannot initialize nonce mutex" );
ctx->user_data = user_data;
ctx->handlers = NULL;
if ( process_options( ctx, options ) ) return NULL;
if ( XX_httplib_init_options( ctx ) ) return NULL;
if ( XX_httplib_process_options( ctx, options ) ) return NULL;
XX_httplib_get_system_name( & ctx->systemName );
@@ -164,13 +142,13 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
* be initialized before listening ports. UID must be set last.
*/
if ( ! XX_httplib_set_gpass_option( ctx ) ) return cleanup( ctx, "Error setting gpass option" );
if ( ! XX_httplib_set_gpass_option( ctx ) ) return XX_httplib_abort_start( ctx, "Error setting gpass option" );
#if !defined(NO_SSL)
if ( ! XX_httplib_set_ssl_option( ctx ) ) return cleanup( ctx, "Error setting SSL option" );
if ( ! XX_httplib_set_ssl_option( ctx ) ) return XX_httplib_abort_start( ctx, "Error setting SSL option" );
#endif
if ( ! XX_httplib_set_ports_option( ctx ) ) return cleanup( ctx, "Error setting ports option" );
if ( ! XX_httplib_set_uid_option( ctx ) ) return cleanup( ctx, "Error setting UID option" );
if ( ! XX_httplib_set_acl_option( ctx ) ) return cleanup( ctx, "Error setting ACL option" );
if ( ! XX_httplib_set_ports_option( ctx ) ) return XX_httplib_abort_start( ctx, "Error setting ports option" );
if ( ! XX_httplib_set_uid_option( ctx ) ) return XX_httplib_abort_start( ctx, "Error setting UID option" );
if ( ! XX_httplib_set_acl_option( ctx ) ) return XX_httplib_abort_start( ctx, "Error setting ACL option" );
#if !defined(_WIN32)
@@ -183,33 +161,33 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
#endif /* !_WIN32 */
if ( ctx->num_threads < 1 ) return cleanup( ctx, "No worker thread number specified" );
if ( ctx->num_threads < 1 ) return XX_httplib_abort_start( ctx, "No worker thread number specified" );
if ( ctx->num_threads > MAX_WORKER_THREADS ) return cleanup( ctx, "Too many worker threads" );
if ( ctx->num_threads > MAX_WORKER_THREADS ) return XX_httplib_abort_start( ctx, "Too many worker threads" );
if ( ctx->num_threads > 0 ) {
ctx->workerthreadids = httplib_calloc( ctx->num_threads, sizeof(pthread_t) );
if ( ctx->workerthreadids == NULL ) return cleanup( ctx, "Not enough memory for worker thread ID array" );
if ( ctx->workerthreadids == NULL ) return XX_httplib_abort_start( ctx, "Not enough memory for worker thread ID array" );
#if defined(ALTERNATIVE_QUEUE)
ctx->client_wait_events = httplib_calloc( sizeof(ctx->client_wait_events[0]), ctx->num_threads );
if ( ctx->client_wait_events == NULL ) return cleanup( ctx, "Not enough memory for worker event array" );
if ( ctx->client_wait_events == NULL ) return XX_httplib_abort_start( ctx, "Not enough memory for worker event array" );
ctx->client_socks = httplib_calloc( sizeof(ctx->client_socks[0]), ctx->num_threads );
if ( ctx->client_socks == NULL ) return cleanup( ctx, "Not enough memory for worker socket array" );
if ( ctx->client_socks == NULL ) return XX_httplib_abort_start( ctx, "Not enough memory for worker socket array" );
for (i=0; i<ctx->num_threads; i++) {
ctx->client_wait_events[i] = event_create();
if ( ctx->client_wait_events[i] == 0 ) return cleanup( ctx, "Error creating worker event %u", i );
if ( ctx->client_wait_events[i] == 0 ) return XX_httplib_abort_start( ctx, "Error creating worker event %u", i );
}
#endif
}
#if defined(USE_TIMERS)
if ( timers_init( ctx ) != 0 ) return cleanup( ctx, "Error creating timers" );
if ( timers_init( ctx ) != 0 ) return XX_httplib_abort_start( ctx, "Error creating timers" );
#endif
/*
@@ -255,7 +233,7 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
if ( i > 0 ) httplib_cry( DEBUG_LEVEL_ERROR, ctx, NULL, "Cannot start worker thread %i: error %ld", i + 1, (long)ERRNO );
else return cleanup( ctx, "Cannot create worker threads: error %ld", (long)ERRNO );
else return XX_httplib_abort_start( ctx, "Cannot create worker threads: error %ld", (long)ERRNO );
break;
}
@@ -266,439 +244,3 @@ struct httplib_context *httplib_start( const struct httplib_callbacks *callbacks
return ctx;
} /* httplib_start */
/*
* static bool process_options( struct httplib_context *ctx, const struct httplib_option_t *options );
*
* The function process_options() processes the user supplied options and adds
* them to the central option list of the context. If en error occurs, the
* function returns true, otherwise FALSE is returned. In case of an error all
* cleanup is already done before returning and an error message has been
* generated.
*/
static bool process_options( struct httplib_context *ctx, const struct httplib_option_t *options ) {
if ( ctx == NULL ) return false;
ctx->access_control_allow_origin = NULL;
ctx->access_control_list = NULL;
ctx->access_log_file = NULL;
ctx->allow_sendfile_call = true;
ctx->authentication_domain = NULL;
ctx->cgi_environment = NULL;
ctx->cgi_interpreter = NULL;
ctx->cgi_pattern = NULL;
ctx->debug_level = DEBUG_LEVEL_WARNING;
ctx->decode_url = true;
ctx->document_root = NULL;
ctx->enable_directory_listing = true;
ctx->enable_keep_alive = false;
ctx->error_log_file = NULL;
ctx->error_pages = NULL;
ctx->extra_mime_types = NULL;
ctx->global_auth_file = NULL;
ctx->hide_file_pattern = NULL;
ctx->index_files = NULL;
ctx->listening_ports = NULL;
ctx->num_threads = 50;
ctx->protect_uri = NULL;
ctx->put_delete_auth_file = NULL;
ctx->request_timeout = 30000;
ctx->run_as_user = NULL;
ctx->ssi_pattern = NULL;
ctx->ssl_ca_file = NULL;
ctx->ssl_ca_path = NULL;
ctx->ssl_certificate = NULL;
ctx->ssl_cipher_list = NULL;
ctx->ssl_protocol_version = 0;
ctx->ssl_short_trust = false;
ctx->ssl_verify_depth = 9;
ctx->ssl_verify_paths = true;
ctx->ssl_verify_peer = false;
ctx->static_file_max_age = 0;
ctx->throttle = NULL;
ctx->tcp_nodelay = false;
ctx->url_rewrite_patterns = NULL;
ctx->websocket_root = NULL;
ctx->websocket_timeout = 30000;
if ( (ctx->access_control_allow_origin = httplib_strdup( "*" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"access_control_allow_origin\"" );
return true;
}
if ( (ctx->authentication_domain = httplib_strdup( "example.com" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"authentication_domain\"" );
return true;
}
if ( (ctx->cgi_pattern = httplib_strdup( "**.cgi$|**.pl$|**.php$" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"cgi_pattern\"" );
return true;
}
if ( (ctx->index_files = httplib_strdup( "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"index_files\"" );
return true;
}
if ( (ctx->listening_ports = httplib_strdup( "8080" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"listening_ports\"" );
return true;
}
if ( (ctx->ssi_pattern = httplib_strdup( "**.shtml$|**.shtm$" )) == NULL ) {
cleanup( ctx, "Out of memory creating context allocating \"ssi_pattern\"" );
return true;
}
while ( options != NULL && options->name != NULL ) {
if ( check_str( ctx, options, "access_control_allow_origin", & ctx->access_control_allow_origin ) ) return true;
if ( check_str( ctx, options, "access_control_list", & ctx->access_control_list ) ) return true;
if ( check_file( ctx, options, "access_log_file", & ctx->access_log_file ) ) return true;
if ( check_bool( ctx, options, "allow_sendfile_call", & ctx->allow_sendfile_call ) ) return true;
if ( check_str( ctx, options, "authentication_domain", & ctx->authentication_domain ) ) return true;
if ( check_str( ctx, options, "cgi_environment", & ctx->cgi_environment ) ) return true;
if ( check_file( ctx, options, "cgi_interpreter", & ctx->cgi_interpreter ) ) return true;
if ( check_patt( ctx, options, "cgi_pattern", & ctx->cgi_pattern ) ) return true;
if ( check_dbg( ctx, options, "debug_level", & ctx->debug_level ) ) return true;
if ( check_bool( ctx, options, "decode_url", & ctx->decode_url ) ) return true;
if ( check_dir( ctx, options, "document_root", & ctx->document_root ) ) return true;
if ( check_bool( ctx, options, "enable_directory_listing", & ctx->enable_directory_listing ) ) return true;
if ( check_bool( ctx, options, "enable_keep_alive", & ctx->enable_keep_alive ) ) return true;
if ( check_file( ctx, options, "error_log_file", & ctx->error_log_file ) ) return true;
if ( check_dir( ctx, options, "error_pages", & ctx->error_pages ) ) return true;
if ( check_str( ctx, options, "extra_mime_types", & ctx->extra_mime_types ) ) return true;
if ( check_file( ctx, options, "global_auth_file", & ctx->global_auth_file ) ) return true;
if ( check_patt( ctx, options, "hide_file_pattern", & ctx->hide_file_pattern ) ) return true;
if ( check_str( ctx, options, "index_files", & ctx->index_files ) ) return true;
if ( check_str( ctx, options, "listening_ports", & ctx->listening_ports ) ) return true;
if ( check_int( ctx, options, "num_threads", & ctx->num_threads, 1, INT_MAX ) ) return true;
if ( check_str( ctx, options, "protect_uri", & ctx->protect_uri ) ) return true;
if ( check_file( ctx, options, "put_delete_auth_file", & ctx->put_delete_auth_file ) ) return true;
if ( check_int( ctx, options, "request_timeout", & ctx->request_timeout, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "run_as_user", & ctx->run_as_user ) ) return true;
if ( check_patt( ctx, options, "ssi_pattern", & ctx->ssi_pattern ) ) return true;
if ( check_file( ctx, options, "ssl_ca_file", & ctx->ssl_ca_file ) ) return true;
if ( check_dir( ctx, options, "ssl_ca_path", & ctx->ssl_ca_path ) ) return true;
if ( check_file( ctx, options, "ssl_certificate", & ctx->ssl_certificate ) ) return true;
if ( check_str( ctx, options, "ssl_cipher_list", & ctx->ssl_cipher_list ) ) return true;
if ( check_int( ctx, options, "ssl_protocol_version", & ctx->ssl_protocol_version, 0, 4 ) ) return true;
if ( check_bool( ctx, options, "ssl_short_trust", & ctx->ssl_short_trust ) ) return true;
if ( check_int( ctx, options, "ssl_verify_depth", & ctx->ssl_verify_depth, 0, 9 ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_paths", & ctx->ssl_verify_paths ) ) return true;
if ( check_bool( ctx, options, "ssl_verify_peer", & ctx->ssl_verify_peer ) ) return true;
if ( check_int( ctx, options, "static_file_max_age", & ctx->static_file_max_age, 0, INT_MAX ) ) return true;
if ( check_str( ctx, options, "throttle", & ctx->throttle ) ) return true;
if ( check_bool( ctx, options, "tcp_nodelay", & ctx->tcp_nodelay ) ) return true;
if ( check_str( ctx, options, "url_rewrite_patterns", & ctx->url_rewrite_patterns ) ) return true;
if ( check_dir( ctx, options, "websocket_root", & ctx->websocket_root ) ) return true;
if ( check_int( ctx, options, "websocket_timeout", & ctx->websocket_timeout, 0, INT_MAX ) ) return true;
/*
* TODO: Currently silently ignoring unrecognized options
*/
options++;
}
return false;
} /* process_options */
/*
* static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config );
*
* The function check_bool() checks if an option is equal to a boolean config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found, also
* false is returned.
*/
static bool check_bool( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, bool *config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing boolean option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_bool( option->value, config ) ) return false;
cleanup( ctx, "Invalid boolean value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_bool */
/*
* static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_dir() checks if an option is equal to a directory config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_dir( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing directory option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
cleanup( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_dir */
/*
* static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_patt() checks if an option is equal to a pattern config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_patt( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing pattern option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
cleanup( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_patt */
/*
* static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_file() checks if an option is equal to a filename config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_file( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing file option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
cleanup( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_file */
/*
* static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config );
*
* The function check_str() checks if an option is equal to a string config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. IF the value could be found, also
* false is returned.
*/
static bool check_str( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, char **config ) {
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing string option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
*config = httplib_free( *config );
if ( option->value == NULL ) return false;
*config = httplib_strdup( option->value );
if ( *config != NULL ) return false;
cleanup( ctx, "Out of memory assigning value \"%s\" to option \"%s\"", option->value, option->name );
return true;
} /* check_str */
/*
* static bool check_int( struct httplib_context *ctx, const struct httplib_opion_t *option, const char *name, int *config, int minval, int maxval );
*
* The function check_int() checks in an option is equal to an integer config
* parameter and stores the value if that is the case. If the value cannot be
* recognized, true is returned and the function performs a complete cleanup.
* If the option name could not be found, the function returns false to
* indicate that the search should go on. If the value could be found and is
* valud, also false is returned.
*/
static bool check_int( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, int *config, int minval, int maxval ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing integer option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, & val ) ) {
if ( val < minval ) { cleanup( ctx, "Integer \"%s\" too small for option \"%s\"", option->value, option->name ); return true; }
if ( val > maxval ) { cleanup( ctx, "Integer \"%s\" too large for option \"%s\"", option->value, option->name ); return true; }
*config = val;
return false;
}
cleanup( ctx, "Invalid integer value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_int */
/*
* static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name );
*
* The function check_dbg() checks if an option is equal to a debug level
* config parameter and stores the value if that is the case. If the value
* cannot be recognized, true is returned and the function performs a complete
* cleanup. If the option name could not be found, the function returns false
* to indicate that the search should go on. If the value could be found and is
* valid, also false is returned.
*/
static bool check_dbg( struct httplib_context *ctx, const struct httplib_option_t *option, const char *name, enum debug_level_t *config ) {
int val;
if ( ctx == NULL || option == NULL || option->name == NULL || name == NULL || config == NULL ) {
cleanup( ctx, "Internal error parsing debug level option" );
return true;
}
if ( httplib_strcasecmp( option->name, name ) ) return false;
if ( ! XX_httplib_option_value_to_int( option->value, &val ) ) {
switch ( val ) {
case DEBUG_LEVEL_NONE :
case DEBUG_LEVEL_CRASH :
case DEBUG_LEVEL_ERROR :
case DEBUG_LEVEL_WARNING :
case DEBUG_LEVEL_INFO :
*config = val;
return false;
}
}
cleanup( ctx, "Invalid value \"%s\" for option \"%s\"", option->value, option->name );
return true;
} /* check_dbg */
/*
* static struct httplib_context *cleanup( struct httplib_context *ctx, const char *fmt, ... );
*
* The function cleanup() is called to do some cleanup work when an error
* occured initializing a context. The function returns NULL which is then
* further returned to the calling party.
*/
static struct httplib_context *cleanup( struct httplib_context *ctx, const char *fmt, ... ) {
va_list ap;
char buf[MG_BUF_LEN];
if ( ctx == NULL ) return NULL;
if ( fmt != NULL ) {
va_start( ap, fmt );
vsnprintf_impl( buf, sizeof(buf), fmt, ap );
va_end( ap );
buf[sizeof(buf)-1] = 0;
httplib_cry( DEBUG_LEVEL_CRASH, ctx, NULL, "%s", buf );
}
XX_httplib_free_context( ctx );
httplib_pthread_setspecific( XX_httplib_sTlsKey, NULL );
return NULL;
} /* cleanup */

View File

@@ -69,8 +69,4 @@ void httplib_stop( struct httplib_context *ctx ) {
httplib_pthread_join( mt, NULL );
XX_httplib_free_context( ctx );
#if defined(_WIN32)
WSACleanup();
#endif /* _WIN32 */
} /* httplib_stop */

49
src/httplib_system_exit.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "httplib_main.h"
/*
* int httplib_system_exit( void );
*
* The function httplib_system_exit() is called after all processing with other
* LibHTTP function is completed to deinitialize socket communications. The
* function returns 0 when successful, and -1 if an error occured.
*
* Please note that this function terminates socket communications for all
* threads and it should therefore be called only when all running threads have
* terminated.
*/
int httplib_system_exit( void ) {
#if defined(_WIN32)
return ( WSACleanup() ) ? -1 : 0;
#else /* _WIN32 */
return 0;
#endif /* _WIN32 */
} /* httplib_system_exit */

View File

@@ -1,7 +1,5 @@
/*
* Copyright (c) 2016 Lammert Bies
* Copyright (c) 2013-2016 the Civetweb developers
* Copyright (c) 2004-2013 Sergey Lyubka
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,20 +18,29 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* ============
* Release: 2.0
*/
#include "httplib_main.h"
/*
* Check if the XX_httplib_config_options and the corresponding enum have
* compatible sizes
* int httplib_system_init( void );
*
* The function httplib_system_init() is called before any other LibHTTP
* functions to do some basic initialisation. The function returns 0 when
* successful and -1 if an error occured.
*/
/*
* TODO: LJB: Move to test functions
*/
int httplib_system_init( void ) {
// httplib_static_assert((sizeof(XX_httplib_config_options) / sizeof(XX_httplib_config_options[0])) == (NUM_OPTIONS + 1), "XX_httplib_config_options and enum not sync");
#if defined(_WIN32)
WSADATA data;
return ( WSAStartup( MAKEWORD(2,2), &data ) ) ? -1 : 0;
#else /* _WIN32 */
return 0;
#endif /* _WIN32 */
} /* httplib_system_init */