diff --git a/Makefile b/Makefile index 2f746664..e855484f 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/src/httplib_join_thread.c b/src/httplib_join_thread.c index d1b7b383..847b06db 100644 --- a/src/httplib_join_thread.c +++ b/src/httplib_join_thread.c @@ -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 */ diff --git a/src/httplib_scan_directory.c b/src/httplib_scan_directory.c index 5ce87d6d..c33c2512 100644 --- a/src/httplib_scan_directory.c +++ b/src/httplib_scan_directory.c @@ -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 */ diff --git a/src/httplib_stop.c b/src/httplib_stop.c index 1c383e64..05c70913 100644 --- a/src/httplib_stop.c +++ b/src/httplib_stop.c @@ -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 ); diff --git a/src/httplib_store_body.c b/src/httplib_store_body.c index 7d762ebf..2a63e874 100644 --- a/src/httplib_store_body.c +++ b/src/httplib_store_body.c @@ -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; } diff --git a/src/httplib_substitute_index_file.c b/src/httplib_substitute_index_file.c index 785952e1..37512515 100644 --- a/src/httplib_substitute_index_file.c +++ b/src/httplib_substitute_index_file.c @@ -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; diff --git a/src/httplib_timer.c b/src/httplib_timer.c index 29d09e4b..1cf78ed3 100644 --- a/src/httplib_timer.c +++ b/src/httplib_timer.c @@ -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; utimers->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; utimers->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; diff --git a/src/httplib_tls_dtor.c b/src/httplib_tls_dtor.c index 3b5722e1..d338a387 100644 --- a/src/httplib_tls_dtor.c +++ b/src/httplib_tls_dtor.c @@ -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 ); diff --git a/src/httplib_url_decode.c b/src/httplib_url_decode.c index 00063651..25838e15 100644 --- a/src/httplib_url_decode.c +++ b/src/httplib_url_decode.c @@ -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 */ diff --git a/src/httplib_url_encode.c b/src/httplib_url_encode.c index b914e3eb..33b84d51 100644 --- a/src/httplib_url_encode.c +++ b/src/httplib_url_encode.c @@ -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'; diff --git a/src/httplib_vprintf.c b/src/httplib_vprintf.c index a85c1e57..0366649d 100644 --- a/src/httplib_vprintf.c +++ b/src/httplib_vprintf.c @@ -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; diff --git a/src/httplib_vsnprintf.c b/src/httplib_vsnprintf.c index b5b69065..a561cda4 100644 --- a/src/httplib_vsnprintf.c +++ b/src/httplib_vsnprintf.c @@ -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'; diff --git a/src/httplib_worker_thread.c b/src/httplib_worker_thread.c index ac63c872..22ca32c8 100644 --- a/src/httplib_worker_thread.c +++ b/src/httplib_worker_thread.c @@ -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 );