1
0
mirror of https://github.com/lammertb/libhttp.git synced 2026-01-27 08:02:47 +03:00

Code cleanup

This commit is contained in:
Lammert Bies
2016-12-21 08:59:36 +01:00
parent 87cdc3e4c2
commit 53ceec7eca
13 changed files with 374 additions and 227 deletions

View File

@@ -253,7 +253,7 @@ OBJLIST = \
${OBJDIR}httplib_is_valid_http_method${OBJEXT} \
${OBJDIR}httplib_is_valid_port${OBJEXT} \
${OBJDIR}httplib_is_websocket_protocol${OBJEXT} \
${OBJDIR}httplib_join_thread${OBJEXT} \
${OBJDIR}httplib_pthread_join${OBJEXT} \
${OBJDIR}httplib_kill${OBJEXT} \
${OBJDIR}httplib_load_dll${OBJEXT} \
${OBJDIR}httplib_lock_unlock_connection${OBJEXT} \
@@ -817,7 +817,7 @@ ${OBJDIR}httplib_is_websocket_protocol${OBJEXT} : ${SRCDIR}httplib_is_websock
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h
${OBJDIR}httplib_join_thread${OBJEXT} : ${SRCDIR}httplib_join_thread.c \
${OBJDIR}httplib_pthread_join${OBJEXT} : ${SRCDIR}httplib_pthread_join.c \
${SRCDIR}httplib_main.h \
${INCDIR}libhttp.h

View File

@@ -22,44 +22,51 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
#if defined(_WIN32)
/*
* int httplib_pthread_join( pthread_t thread, void **value_ptr );
*
* The platform independent function httplib_pthread_join() suspends the
* current thread and waits until another thread has terminated. Succes is
* returned with 0, while an error code is returned otherwise. The function is
* a wrapper around pthread_join() on systems which support it, or own code
* which emulates the same functionality otherwise.
*
* On systems which do not support pthread_join() natively, the value_ptr
* parameter is ignored.
*/
/* Wait for a thread to finish. */
int XX_httplib_join_thread( pthread_t threadid ) {
int httplib_pthread_join( pthread_t thread, void **value_ptr ) {
#if defined(_WIN32)
int result;
DWORD dwevent;
result = -1;
dwevent = WaitForSingleObject(threadid, INFINITE);
if (dwevent == WAIT_FAILED) {
} else {
if (dwevent == WAIT_OBJECT_0) {
CloseHandle(threadid);
result = 0;
}
UNUSED_PARAMETER(value_ptr);
result = -1;
dwevent = WaitForSingleObject( threadid, INFINITE );
if ( dwevent == WAIT_FAILED ) {
}
else if ( dwevent == WAIT_OBJECT_0 ) {
CloseHandle( threadid );
result = 0;
}
return result;
} /* XX_httplib_join_thread */
#else /* _WIN32 */
#else
return pthread_join( thread, value_ptr );
#endif /* _WIN32 */
/* Wait for a thread to finish. */
int XX_httplib_join_thread( pthread_t threadid ) {
int result;
result = pthread_join(threadid, NULL);
return result;
} /* XX_httplib_join_thread */
#endif /* _WIN32 */
} /* httplib_pthread_join */

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -36,38 +36,44 @@ int XX_httplib_scan_directory( struct httplib_connection *conn, const char *dir,
struct de de;
int truncated;
if ((dirp = httplib_opendir( dir)) == NULL) {
return 0;
} else {
de.conn = conn;
dirp = httplib_opendir( dir );
if ( dirp == NULL ) return 0;
while ((dp = httplib_readdir(dirp)) != NULL) {
/* Do not show current dir and hidden files */
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") || XX_httplib_must_hide_file(conn, dp->d_name)) continue;
de.conn = conn;
XX_httplib_snprintf( conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
while ( (dp = httplib_readdir(dirp)) != NULL ) {
/* If we don't memset stat structure to zero, mtime will have
* garbage and strftime() will segfault later on in
* XX_httplib_print_dir_entry(). memset is required only if XX_httplib_stat()
* fails. For more details, see
* http://code.google.com/p/mongoose/issues/detail?id=79 */
memset(&de.file, 0, sizeof(de.file));
/*
* Do not show current dir and hidden files
*/
if (truncated) {
/* If the path is not complete, skip processing. */
continue;
}
if ( ! strcmp( dp->d_name, "." ) || ! strcmp(dp->d_name, "..") || XX_httplib_must_hide_file( conn, dp->d_name ) ) continue;
if (!XX_httplib_stat(conn, path, &de.file)) {
httplib_cry(conn, "%s: XX_httplib_stat(%s) failed: %s", __func__, path, strerror(ERRNO));
}
de.file_name = dp->d_name;
cb(&de, data);
XX_httplib_snprintf( conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name );
/*
* If we don't memset stat structure to zero, mtime will have
* garbage and strftime() will segfault later on in
* XX_httplib_print_dir_entry(). memset is required only if XX_httplib_stat()
* fails. For more details, see
* http://code.google.com/p/mongoose/issues/detail?id=79
*/
memset( &de.file, 0, sizeof(de.file) );
if ( truncated ) continue; /* If the path is not complete, skip processing. */
if ( ! XX_httplib_stat( conn, path, &de.file ) ) {
httplib_cry( conn, "%s: XX_httplib_stat(%s) failed: %s", __func__, path, strerror(ERRNO) );
}
httplib_closedir(dirp);
de.file_name = dp->d_name;
cb( &de, data );
}
httplib_closedir( dirp );
return 1;
} /* XX_httplib_scan_directory */

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -38,18 +38,28 @@ void httplib_stop( struct httplib_context *ctx ) {
pthread_t mt;
if ( ctx == NULL ) return;
/* We don't use a lock here. Calling httplib_stop with the same ctx from
* two threads is not allowed. */
if ( ctx == NULL ) return;
/*
* We don't use a lock here. Calling httplib_stop with the same ctx from
* two threads is not allowed.
*/
mt = ctx->masterthreadid;
if ( mt == 0 ) return;
ctx->masterthreadid = 0;
/* Set stop flag, so all threads know they have to exit. */
/*
* Set stop flag, so all threads know they have to exit.
*/
ctx->stop_flag = 1;
/* Wait until everything has stopped. */
/*
* Wait until everything has stopped.
*/
while ( ctx->stop_flag != 2 ) httplib_sleep( 10 );
XX_httplib_join_thread( mt );

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -52,12 +52,19 @@ int64_t httplib_store_body( struct httplib_connection *conn, const char *path )
ret = XX_httplib_put_dir( conn, path );
if ( ret < 0 ) {
/* -1 for path too long,
* -2 for path can not be created. */
/*
* -1 for path too long,
* -2 for path can not be created.
*/
return ret;
}
if ( ret != 1 ) {
/* Return 0 means, path itself is a directory. */
/*
* Return 0 means, path itself is a directory.
*/
return 0;
}

View File

@@ -22,59 +22,86 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
#include "httplib_string.h"
/*
* int XX_httplib_substitute_index_file( struct httplib_connection *conn, char *path, size_t path_len, struct file *filep );
* bool XX_httplib_substitute_index_file( struct httplib_connection *conn, char *path, size_t path_len, struct file *filep );
*
* The function XX_httplib_substiture_index_file() tries to find an index file
* matching a given directory path. The function returns 1 of an index file has
* been found and 0 if the file could not be found. If a file could be located,
* it's stats are returnd in stp.
* matching a given directory path. The function returns true of an index file
* has been found and false if the file could not be found. If a file could be
* located, it's stats are returnd in stp.
*/
#if !defined(NO_FILES)
int XX_httplib_substitute_index_file( struct httplib_connection *conn, char *path, size_t path_len, struct file *filep ) {
if ( conn == NULL || conn->ctx == NULL ) return 0;
const char *list = conn->ctx->config[INDEX_FILES];
const char *list;
struct file file = STRUCT_FILE_INITIALIZER;
struct vec filename_vec;
size_t n = strlen(path);
int found = 0;
size_t n;
bool found;
/* The 'path' given to us points to the directory. Remove all trailing
if ( conn == NULL || conn->ctx == NULL || path == NULL ) return 0;
list = conn->ctx->config[INDEX_FILES];
n = strlen( path );
found = false;
/*
* The 'path' given to us points to the directory. Remove all trailing
* directory separator characters from the end of the path, and
* then append single directory separator character. */
while (n > 0 && path[n - 1] == '/') n--;
* then append single directory separator character.
*/
while ( n > 0 && path[n - 1] == '/' ) n--;
path[n] = '/';
/* Traverse index files list. For each entry, append it to the given
* path and see if the file exists. If it exists, break the loop */
while ((list = XX_httplib_next_option(list, &filename_vec, NULL)) != NULL) {
/* Ignore too long entries that may overflow path buffer */
if (filename_vec.len > path_len - (n + 2)) continue;
/*
* Traverse index files list. For each entry, append it to the given
* path and see if the file exists. If it exists, break the loop
*/
/* Prepare full path to the index file */
httplib_strlcpy( path + n + 1, filename_vec.ptr, filename_vec.len + 1 );
while ( (list = XX_httplib_next_option( list, &filename_vec, NULL )) != NULL ) {
/*
* Ignore too long entries that may overflow path buffer
*/
if ( filename_vec.len > path_len - (n+2) ) continue;
/*
* Prepare full path to the index file
*/
httplib_strlcpy( path+n+1, filename_vec.ptr, filename_vec.len + 1 );
/*
* Does it exist?
*/
if ( XX_httplib_stat( conn, path, &file ) ) {
/*
* Yes it does, break the loop
*/
/* Does it exist? */
if (XX_httplib_stat(conn, path, &file)) {
/* Yes it does, break the loop */
*filep = file;
found = 1;
found = true;
break;
}
}
/* If no index file exists, restore directory path */
if (!found) path[n] = '\0';
/*
* If no index file exists, restore directory path
*/
if ( ! found ) path[n] = '\0';
return found;

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 1.9
*/
#include "httplib_main.h"
@@ -43,27 +43,30 @@ struct ttimer {
};
struct ttimers {
pthread_t threadid; /* Timer thread ID */
pthread_mutex_t mutex; /* Protects timer lists */
struct ttimer timers[MAX_TIMERS]; /* List of timers */
unsigned timer_count; /* Current size of timer list */
pthread_t threadid; /* Timer thread ID */
pthread_mutex_t mutex; /* Protects timer lists */
struct ttimer timers[MAX_TIMERS]; /* List of timers */
unsigned timer_count; /* Current size of timer list */
};
static int timer_add( struct httplib_context *ctx, double next_time, double period, int is_relative, taction action, void *arg ) {
unsigned u;
unsigned v;
int error = 0;
int error;
struct timespec now;
double dt; /* double time */
if (ctx->stop_flag) return 0;
if ( ctx == NULL || ctx->stop_flag ) return 0;
clock_gettime(CLOCK_MONOTONIC, &now);
dt = (double)now.tv_sec;
error = 0;
clock_gettime( CLOCK_MONOTONIC, &now );
dt = (double)now.tv_sec;
dt += now.tv_nsec * 1.0E-9;
/* HCP24: if is_relative = 0 and next_time < now
/*
* HCP24: if is_relative = 0 and next_time < now
* action will be called so fast as possible
* if additional period > 0
* action will be called so fast as possible
@@ -73,30 +76,37 @@ static int timer_add( struct httplib_context *ctx, double next_time, double peri
* if next_time < now then we set next_time = now.
* The first callback will be so fast as possible (now)
* but the next callback on period
*/
*/
if ( is_relative ) next_time += dt;
else if ( next_time < dt ) next_time = dt;
httplib_pthread_mutex_lock( & ctx->timers->mutex );
if (ctx->timers->timer_count == MAX_TIMERS) {
error = 1;
} else {
for (u = 0; u < ctx->timers->timer_count; u++) {
if ( ctx->timers->timer_count == MAX_TIMERS ) error = 1;
else {
for (u=0; u<ctx->timers->timer_count; u++) {
if (ctx->timers->timers[u].time > next_time) {
/* HCP24: moving all timers > next_time */
for (v = ctx->timers->timer_count; v > u; v--) {
ctx->timers->timers[v] = ctx->timers->timers[v - 1];
}
/*
* HCP24: moving all timers > next_time
*/
for (v=ctx->timers->timer_count; v>u; v--) ctx->timers->timers[v] = ctx->timers->timers[v - 1];
break;
}
}
ctx->timers->timers[u].time = next_time;
ctx->timers->timers[u].period = period;
ctx->timers->timers[u].action = action;
ctx->timers->timers[u].arg = arg;
ctx->timers->timer_count++;
}
httplib_pthread_mutex_unlock( & ctx->timers->mutex );
return error;
} /* timer_add */
@@ -110,37 +120,32 @@ static void timer_thread_run( void *thread_func_param ) {
int re_schedule;
struct ttimer t;
httplib_set_thread_name("timer");
httplib_set_thread_name( "timer" );
if (ctx->callbacks.init_thread) {
/* Timer thread */
ctx->callbacks.init_thread(ctx, 2);
}
if ( ctx->callbacks.init_thread ) ctx->callbacks.init_thread( ctx, 2 ); /* Timer thread */
#if defined(HAVE_CLOCK_NANOSLEEP) /* Linux with librt */
/* TODO */
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request, &request)
== EINTR) { /*nop*/
;
}
while ( clock_nanosleep( CLOCK_MONOTONIC, TIMER_ABSTIME, &request, &request ) == EINTR ) { /*nop*/ ; }
#else /* HAVE_CLOCK_NANOSLEEP */
clock_gettime(CLOCK_MONOTONIC, &now);
clock_gettime( CLOCK_MONOTONIC, &now );
d = (double)now.tv_sec + (double)now.tv_nsec * 1.0E-9;
while (ctx->stop_flag == 0) {
while ( ctx->stop_flag == 0 ) {
httplib_pthread_mutex_lock( & ctx->timers->mutex );
if (ctx->timers->timer_count > 0 && d >= ctx->timers->timers[0].time) {
if ( ctx->timers->timer_count > 0 && d >= ctx->timers->timers[0].time ) {
t = ctx->timers->timers[0];
for (u = 1; u < ctx->timers->timer_count; u++) {
ctx->timers->timers[u - 1] = ctx->timers->timers[u];
}
for (u=1; u<ctx->timers->timer_count; u++) ctx->timers->timers[u-1] = ctx->timers->timers[u];
ctx->timers->timer_count--;
httplib_pthread_mutex_unlock( & ctx->timers->mutex );
re_schedule = t.action(t.arg);
if (re_schedule && (t.period > 0)) {
timer_add(ctx, t.time + t.period, t.period, 0, t.action, t.arg);
}
re_schedule = t.action( t.arg );
if ( re_schedule && t.period > 0 ) timer_add( ctx, t.time + t.period, t.period, 0, t.action, t.arg );
continue;
}
@@ -175,10 +180,13 @@ static void * timer_thread( void *thread_func_param ) {
static int timers_init( struct httplib_context *ctx ) {
ctx->timers = (struct ttimers *)httplib_calloc(sizeof(struct ttimers), 1);
ctx->timers = httplib_calloc( sizeof(struct ttimers), 1 );
httplib_pthread_mutex_init( & ctx->timers->mutex, NULL );
/* Start timer thread */
/*
* Start timer thread
*/
httplib_start_thread_with_id(timer_thread, ctx, &ctx->timers->threadid);
return 0;

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -39,12 +39,14 @@
void XX_httplib_tls_dtor( void *key ) {
struct httplib_workerTLS *tls = (struct httplib_workerTLS *)key;
struct httplib_workerTLS *tls;
tls = key;
/* key == httplib_pthread_getspecific( XX_httplib_sTlsKey ); */
if ( tls != NULL ) {
if (tls->is_master == 2) {
if ( tls->is_master == 2 ) {
tls->is_master = -3; /* Mark memory as dead */
httplib_free( tls );

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -36,17 +36,24 @@ int httplib_url_decode( const char *src, int src_len, char *dst, int dst_len, in
int a;
int b;
for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
if (i < src_len - 2 && src[i] == '%'
&& isxdigit(*(const unsigned char *)(src + i + 1))
&& isxdigit(*(const unsigned char *)(src + i + 2))) {
a = tolower(*(const unsigned char *)(src + i + 1));
b = tolower(*(const unsigned char *)(src + i + 2));
i = 0;
j = 0;
while ( i < src_len && j < dst_len-1 ) {
if ( i < src_len - 2 && src[i] == '%' && isxdigit(*(const unsigned char *)(src + i + 1)) && isxdigit(*(const unsigned char *)(src + i + 2)) ) {
a = tolower(*(const unsigned char *)(src + i + 1));
b = tolower(*(const unsigned char *)(src + i + 2));
dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
i += 2;
} else if (is_form_url_encoded && src[i] == '+') {
dst[j] = ' ';
} else dst[j] = src[i];
i += 2;
}
else if (is_form_url_encoded && src[i] == '+') dst[j] = ' ';
else dst[j] = src[i];
i++;
j++;
}
dst[j] = '\0'; /* Null-terminate the destination */

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -31,19 +31,31 @@ int httplib_url_encode( const char *src, char *dst, size_t dst_len ) {
static const char *dont_escape = "._-$,;~()";
static const char *hex = "0123456789abcdef";
char *pos = dst;
const char *end = dst + dst_len - 1;
char *pos;
const char *end;
if ( dst == NULL || dst_len < 1 ) return 0;
if ( src == NULL ) { dst[0] = '\0'; return 0; }
pos = dst;
end = dst + dst_len - 1;
while ( *src != '\0' && pos < end ) {
if ( isalnum(*(const unsigned char *)src) || strchr( dont_escape, *(const unsigned char *)src ) != NULL ) *pos = *src;
else if ( pos + 2 < end ) {
for (; *src != '\0' && pos < end; src++, pos++) {
if (isalnum(*(const unsigned char *)src)
|| strchr(dont_escape, *(const unsigned char *)src) != NULL) {
*pos = *src;
} else if (pos + 2 < end) {
pos[0] = '%';
pos[1] = hex[(*(const unsigned char *)src) >> 4];
pos[2] = hex[(*(const unsigned char *)src) & 0xf];
pos += 2;
} else break;
pos += 2;
}
else break;
src++;
pos++;
}
*pos = '\0';

View File

@@ -22,41 +22,52 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
#include "httplib_memory.h"
#include "httplib_string.h"
/* Alternative alloc_vprintf() for non-compliant C runtimes */
/*
* Alternative alloc_vprintf() for non-compliant C runtimes
*/
static int alloc_vprintf2( char **buf, const char *fmt, va_list ap ) {
va_list ap_copy;
size_t size = MG_BUF_LEN / 4;
int len = -1;
size_t size;
int len;
size = MG_BUF_LEN / 4;
len = -1;
*buf = NULL;
while (len < 0) {
if (*buf) httplib_free( *buf );
while ( len < 0 ) {
if ( *buf != NULL ) httplib_free( *buf );
size *= 4;
*buf = httplib_malloc( size );
if (!*buf) break;
if ( *buf == NULL ) break;
va_copy(ap_copy, ap);
len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
va_end(ap_copy);
(*buf)[size - 1] = 0;
va_copy( ap_copy, ap );
len = vsnprintf_impl( *buf, size - 1, fmt, ap_copy );
va_end( ap_copy );
(*buf)[size-1] = 0;
}
return len;
}
/* Print message to buffer. If buffer is large enough to hold the message,
/*
* Print message to buffer. If buffer is large enough to hold the message,
* return buffer. If buffer is to small, allocate large enough buffer on heap,
* and return allocated buffer. */
* and return allocated buffer.
*/
static int alloc_vprintf( char **out_buf, char *prealloc_buf, size_t prealloc_size, const char *fmt, va_list ap ) {
va_list ap_copy;
@@ -71,37 +82,60 @@ static int alloc_vprintf( char **out_buf, char *prealloc_buf, size_t prealloc_si
* On second pass, actually print the message.
*/
va_copy(ap_copy, ap);
len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
va_end(ap_copy);
va_copy( ap_copy, ap );
len = vsnprintf_impl( NULL, 0, fmt, ap_copy );
va_end( ap_copy );
if (len < 0) {
/* C runtime is not standard compliant, vsnprintf() returned -1.
if ( len < 0 ) {
/*
* C runtime is not standard compliant, vsnprintf() returned -1.
* Switch to alternative code path that uses incremental allocations.
*/
va_copy(ap_copy, ap);
len = alloc_vprintf2(out_buf, fmt, ap);
va_end(ap_copy);
} else if ((size_t)(len) >= prealloc_size) {
/* The pre-allocated buffer not large enough. */
/* Allocate a new buffer. */
va_copy( ap_copy, ap );
len = alloc_vprintf2( out_buf, fmt, ap );
va_end( ap_copy );
}
else if ( (size_t)(len) >= prealloc_size ) {
/*
* The pre-allocated buffer not large enough.
* Allocate a new buffer.
*/
*out_buf = httplib_malloc( (size_t)(len) + 1 );
if (!*out_buf) {
/* Allocation failed. Return -1 as "out of memory" error. */
if ( *out_buf == NULL ) {
/*
* Allocation failed. Return -1 as "out of memory" error.
*/
return -1;
}
/* Buffer allocation successful. Store the string there. */
va_copy(ap_copy, ap);
vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy);
va_end(ap_copy);
} else {
/* The pre-allocated buffer is large enough.
* Use it to store the string and return the address. */
va_copy(ap_copy, ap);
vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy);
va_end(ap_copy);
/*
* Buffer allocation successful. Store the string there.
*/
va_copy( ap_copy, ap );
vsnprintf_impl( *out_buf, (size_t)(len) + 1, fmt, ap_copy );
va_end( ap_copy );
}
else {
/*
* The pre-allocated buffer is large enough.
* Use it to store the string and return the address.
*/
va_copy( ap_copy, ap );
vsnprintf_impl( prealloc_buf, prealloc_size, fmt, ap_copy );
va_end( ap_copy );
*out_buf = prealloc_buf;
}
@@ -113,11 +147,13 @@ static int alloc_vprintf( char **out_buf, char *prealloc_buf, size_t prealloc_si
int XX_httplib_vprintf( struct httplib_connection *conn, const char *fmt, va_list ap ) {
char mem[MG_BUF_LEN];
char *buf = NULL;
char *buf;
int len;
if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) len = httplib_write(conn, buf, (size_t)len);
if (buf != mem && buf != NULL) httplib_free( buf );
buf = NULL;
if ( (len = alloc_vprintf( &buf, mem, sizeof(mem), fmt, ap )) > 0 ) len = httplib_write( conn, buf, (size_t)len );
if ( buf != mem && buf != NULL ) httplib_free( buf );
return len;

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -36,7 +36,7 @@
void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated, char *buf, size_t buflen, const char *fmt, va_list ap ) {
int n;
int ok;
bool ok;
if ( buf == NULL || buflen < 1 ) return;
@@ -47,20 +47,20 @@ void XX_httplib_vsnprintf( const struct httplib_connection *conn, int *truncated
* indirectly by XX_httplib_snprintf */
#endif
n = (int)vsnprintf_impl( buf, buflen, fmt, ap );
ok = (n >= 0) && ((size_t)n < buflen);
n = (int)vsnprintf_impl( buf, buflen, fmt, ap );
ok = (n >= 0) && ((size_t)n < buflen);
#ifdef __clang__
#pragma clang diagnostic pop
#endif
if (ok) {
if ( ok ) {
if ( truncated != NULL ) *truncated = 0;
}
else {
if ( truncated != NULL ) *truncated = 1;
httplib_cry(conn, "truncating vsnprintf buffer: [%.*s]", (int)((buflen > 200) ? 200 : (buflen - 1)), buf);
httplib_cry( conn, "truncating vsnprintf buffer: [%.*s]", (int)((buflen > 200) ? 200 : (buflen - 1)), buf );
n = (int)buflen - 1;
}
buf[n] = '\0';

View File

@@ -22,7 +22,7 @@
* THE SOFTWARE.
*
* ============
* Release: 1.8
* Release: 2.0
*/
#include "httplib_main.h"
@@ -41,17 +41,19 @@ static void * worker_thread_run( struct worker_thread_args *thread_args );
* operating system.
*/
#ifdef _WIN32
unsigned __stdcall XX_httplib_worker_thread( void *thread_func_param ) {
#else
void *XX_httplib_worker_thread( void *thread_func_param ) {
#endif
LIBHTTP_THREAD XX_httplib_worker_thread( void *thread_func_param ) {
struct worker_thread_args *pwta = (struct worker_thread_args *)thread_func_param;
worker_thread_run( pwta );
httplib_free( thread_func_param );
struct worker_thread_args *pwta;
return 0;
if ( thread_func_param != NULL ) {
pwta = thread_func_param;
worker_thread_run( pwta );
httplib_free( thread_func_param );
}
return LIBHTTP_THREAD_RETNULL;
} /* XX_httplib_worker_thread */
@@ -70,45 +72,56 @@ static void *worker_thread_run( struct worker_thread_args *thread_args ) {
struct httplib_connection *conn;
struct httplib_workerTLS tls;
if ( thread_args == NULL ) return NULL;
ctx = thread_args->ctx;
XX_httplib_set_thread_name( "worker" );
tls.is_master = 0;
tls.thread_idx = (unsigned)httplib_atomic_inc(&XX_httplib_thread_idx_max);
tls.thread_idx = (unsigned)httplib_atomic_inc( & XX_httplib_thread_idx_max );
#if defined(_WIN32)
tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
tls.pthread_cond_helper_mutex = CreateEvent( NULL, FALSE, FALSE, NULL );
#endif
if ( ctx->callbacks.init_thread != NULL ) ctx->callbacks.init_thread( ctx, 1 ); /* call init_thread for a worker thread (type 1) */
conn = httplib_calloc( 1, sizeof(*conn) + MAX_REQUEST_SIZE );
if ( conn == NULL ) httplib_cry( XX_httplib_fc(ctx), "%s", "Cannot create new connection struct, OOM");
if ( conn == NULL ) httplib_cry( XX_httplib_fc(ctx), "%s", "Cannot create new connection struct, OOM" );
else {
httplib_pthread_setspecific( XX_httplib_sTlsKey, &tls );
conn->buf_size = MAX_REQUEST_SIZE;
conn->buf = (char *)(conn + 1);
conn->buf = (char *)(conn+1);
conn->ctx = ctx;
conn->thread_index = thread_args->index;
conn->request_info.user_data = ctx->user_data;
/* Allocate a mutex for this connection to allow communication both
/*
* Allocate a mutex for this connection to allow communication both
* within the request handler and from elsewhere in the application
*/
pthread_mutex_init( & conn->mutex, &XX_httplib_pthread_mutex_attr );
/* Call XX_httplib_consume_socket() even when ctx->stop_flag > 0, to let it
/*
* Call XX_httplib_consume_socket() even when ctx->stop_flag > 0, to let it
* signal sq_empty condvar to wake up the master waiting in
* produce_socket() */
while (XX_httplib_consume_socket(ctx, &conn->client, conn->thread_index)) {
* produce_socket()
*/
conn->conn_birth_time = time(NULL);
while ( XX_httplib_consume_socket( ctx, &conn->client, conn->thread_index ) ) {
/* Fill in IP, port info early so even if SSL setup below fails,
* error handler would have the corresponding info.
* Thanks to Johannes Winkelmann for the patch.
*/
conn->conn_birth_time = time( NULL );
/*
* Fill in IP, port info early so even if SSL setup below fails,
* error handler would have the corresponding info.
* Thanks to Johannes Winkelmann for the patch.
*/
#if defined(USE_IPV6)
if ( conn->client.rsa.sa.sa_family == AF_INET6 ) conn->request_info.remote_port = ntohs(conn->client.rsa.sin6.sin6_port);
if ( conn->client.rsa.sa.sa_family == AF_INET6 ) conn->request_info.remote_port = ntohs( conn->client.rsa.sin6.sin6_port );
else
#endif
@@ -116,22 +129,34 @@ static void *worker_thread_run( struct worker_thread_args *thread_args ) {
conn->request_info.remote_port = ntohs(conn->client.rsa.sin.sin_port);
}
XX_httplib_sockaddr_to_string(conn->request_info.remote_addr, sizeof(conn->request_info.remote_addr), &conn->client.rsa);
XX_httplib_sockaddr_to_string( conn->request_info.remote_addr, sizeof(conn->request_info.remote_addr), &conn->client.rsa );
conn->request_info.is_ssl = conn->client.is_ssl;
if (conn->client.is_ssl) {
if ( conn->client.is_ssl ) {
#ifndef NO_SSL
/* HTTPS connection */
/*
* HTTPS connection
*/
if ( XX_httplib_sslize( conn, conn->ctx->ssl_ctx, SSL_accept ) ) {
/* Get SSL client certificate information (if set) */
/*
* Get SSL client certificate information (if set)
*/
XX_httplib_ssl_get_client_cert_info( conn );
/* process HTTPS connection */
/*
* process HTTPS connection
*/
XX_httplib_process_new_connection( conn );
/* Free client certificate info */
/*
* Free client certificate info
*/
if ( conn->request_info.client_cert != NULL ) {
httplib_free( (void *)conn->request_info.client_cert->subject );