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

Moved functions to own file

This commit is contained in:
Lammert Bies
2016-11-16 16:25:41 +01:00
parent db43ed14b5
commit 36378478c5
6 changed files with 623 additions and 956 deletions

View File

@@ -44,10 +44,13 @@ BUILD_DIRS = $(BUILD_DIR) $(BUILD_DIR)/src $(BUILD_DIR)/resources
LIB_SOURCES = src/libhttp.c \
src/httplib_accept_new_connection.c \
src/httplib_check_feature.c \
src/httplib_consume_socket.c \
src/httplib_free_context.c \
src/httplib_get_response_code_text.c \
src/httplib_get_system_name.c \
src/httplib_master_thread.c \
src/httplib_process_new_connection.c \
src/httplib_produce_socket.c \
src/httplib_start.c \
src/httplib_stop.c \
src/httplib_version.c \

View File

@@ -0,0 +1,87 @@
/*
* 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
* 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 "libhttp-private.h"
/*
* int XX_httplib_consume_socket( struct mg_context *ctx, struct socket *sp, int thread_index );
*
* The function XX_httplib_consume_socket() takes an accepted socket from the
* queue for further processing.
*/
#if defined(ALTERNATIVE_QUEUE)
int XX_httplib_consume_socket( struct mg_context *ctx, struct socket *sp, int thread_index ) {
ctx->client_socks[thread_index].in_use = 0;
event_wait(ctx->client_wait_events[thread_index]);
*sp = ctx->client_socks[thread_index];
return !ctx->stop_flag;
} /* XX_httplib_consume_socket */
#else /* ALTERNATIVE_QUEUE */
/* Worker threads take accepted socket from the queue */
int XX_httplib_consume_socket( struct mg_context *ctx, struct socket *sp, int thread_index ) {
#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
(void)thread_index;
pthread_mutex_lock(&ctx->thread_mutex);
/* If the queue is empty, wait. We're idle at this point. */
while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
}
/* If we're stopping, sq_head may be equal to sq_tail. */
if (ctx->sq_head > ctx->sq_tail) {
/* Copy socket from the queue and increment tail */
*sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
ctx->sq_tail++;
/* Wrap pointers if needed */
while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
ctx->sq_tail -= QUEUE_SIZE(ctx);
ctx->sq_head -= QUEUE_SIZE(ctx);
}
}
pthread_cond_signal(&ctx->sq_empty);
pthread_mutex_unlock(&ctx->thread_mutex);
return !ctx->stop_flag;
#undef QUEUE_SIZE
} /* XX_httplib_consume_socket */
#endif /* ALTERNATIVE_QUEUE */

View File

@@ -0,0 +1,145 @@
/*
* 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
* 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 "libhttp-private.h"
/*
* void XX_httplib_process_new_connection( struct mg_connection *conn );
*
* The function XX_httplib_process_new_connection() is used to process a new
* incoming connection on a socket.
*/
void XX_httplib_process_new_connection( struct mg_connection *conn ) {
if (conn && conn->ctx) {
struct mg_request_info *ri = &conn->request_info;
int keep_alive_enabled, keep_alive, discard_len;
char ebuf[100];
const char *hostend;
int reqerr, uri_type;
keep_alive_enabled = ! strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
/* Important: on new connection, reset the receiving buffer. Credit
* goes to crule42. */
conn->data_len = 0;
do {
if (!XX_httplib_getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
/* The request sent by the client could not be understood by
* the server, or it was incomplete or a timeout. Send an
* error message and close the connection. */
if (reqerr > 0) {
/*assert(ebuf[0] != '\0');*/
XX_httplib_send_http_error(conn, reqerr, "%s", ebuf);
}
} else if (strcmp(ri->http_version, "1.0") && strcmp(ri->http_version, "1.1")) {
XX_httplib_snprintf(conn, NULL, ebuf, sizeof(ebuf), "Bad HTTP version: [%s]", ri->http_version);
XX_httplib_send_http_error(conn, 505, "%s", ebuf);
}
if (ebuf[0] == '\0') {
uri_type = XX_httplib_get_uri_type(conn->request_info.request_uri);
switch (uri_type) {
case 1:
/* Asterisk */
conn->request_info.local_uri = NULL;
break;
case 2:
/* relative uri */
conn->request_info.local_uri =
conn->request_info.request_uri;
break;
case 3:
case 4:
/* absolute uri (with/without port) */
hostend = XX_httplib_get_rel_url_at_current_server( conn->request_info.request_uri, conn);
if (hostend) conn->request_info.local_uri = hostend;
else conn->request_info.local_uri = NULL;
break;
default:
XX_httplib_snprintf(conn, NULL, ebuf, sizeof(ebuf), "Invalid URI");
XX_httplib_send_http_error(conn, 400, "%s", ebuf);
conn->request_info.local_uri = NULL;
break;
}
/* TODO: cleanup uri, local_uri and request_uri */
conn->request_info.uri = conn->request_info.local_uri;
}
if (ebuf[0] == '\0') {
if (conn->request_info.local_uri) {
/* handle request to local server */
XX_httplib_handle_request(conn);
if (conn->ctx->callbacks.end_request != NULL) conn->ctx->callbacks.end_request(conn, conn->status_code);
XX_httplib_log_access(conn);
} else {
/* TODO: handle non-local request (PROXY) */
conn->must_close = 1;
}
} else conn->must_close = 1;
if (ri->remote_user != NULL) {
XX_httplib_free((void *)ri->remote_user);
/* Important! When having connections with and without auth
* would cause double free and then crash */
ri->remote_user = NULL;
}
/* NOTE(lsm): order is important here. XX_httplib_should_keep_alive() call
* is
* using parsed request, which will be invalid after memmove's
* below.
* Therefore, memorize XX_httplib_should_keep_alive() result now for later
* use
* in loop exit condition. */
keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled && conn->content_len >= 0 && XX_httplib_should_keep_alive(conn);
/* Discard all buffered data for this request */
discard_len = ((conn->content_len >= 0) && (conn->request_len > 0)
&& ((conn->request_len + conn->content_len)
< (int64_t)conn->data_len))
? (int)(conn->request_len + conn->content_len)
: conn->data_len;
/*assert(discard_len >= 0);*/
if (discard_len < 0) break;
conn->data_len -= discard_len;
if (conn->data_len > 0) memmove(conn->buf, conn->buf + discard_len, (size_t)conn->data_len);
/* assert(conn->data_len >= 0); */
/* assert(conn->data_len <= conn->buf_size); */
if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) break;
} while (keep_alive);
}
} /* XX_httplib_process_new_connection */

View File

@@ -0,0 +1,86 @@
/*
* 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
* 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 "libhttp-private.h"
/*
* void XX_httplib_produce_socket( struct mg_context *ctx, const struct socket *sp );
*
* The function XX_httplib_produce_socket() is used to produce a socket.
*/
#if defined(ALTERNATIVE_QUEUE)
void XX_httplib_produce_socket( struct mg_context *ctx, const struct socket *sp ) {
unsigned int i;
for (;;) {
for (i = 0; i < ctx->cfg_worker_threads; i++) {
/* find a free worker slot and signal it */
if (ctx->client_socks[i].in_use == 0) {
ctx->client_socks[i] = *sp;
ctx->client_socks[i].in_use = 1;
event_signal(ctx->client_wait_events[i]);
return;
}
}
/* queue is full */
mg_sleep(1);
}
} /* XX_httplib_produce_socket */
#else /* ALTERNATIVE_QUEUE */
/* Master thread adds accepted socket to a queue */
void XX_httplib_produce_socket(struct mg_context *ctx, const struct socket *sp) {
#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
if (!ctx) return;
pthread_mutex_lock(&ctx->thread_mutex);
/* If the queue is full, wait */
while (ctx->stop_flag == 0
&& ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
(void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
}
if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
/* Copy socket to the queue and increment head */
ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
ctx->sq_head++;
}
pthread_cond_signal(&ctx->sq_full);
pthread_mutex_unlock(&ctx->thread_mutex);
#undef QUEUE_SIZE
} /* XX_httplib_produce_socket */
#endif /* ALTERNATIVE_QUEUE */

View File

@@ -405,6 +405,8 @@ typedef int SOCKET;
WINDOWS / UNIX include block */
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#if !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL (0)
@@ -808,10 +810,16 @@ struct mg_connection * XX_httplib_fc( struct mg_context *ctx );
void XX_httplib_free_context( struct mg_context *ctx );
int XX_httplib_get_option_index( const char *name );
uint64_t XX_httplib_get_random( void );
const char * XX_httplib_get_rel_url_at_current_server( const char *uri, const struct mg_connection *conn );
void XX_httplib_get_system_name( char **sysName );
int XX_httplib_get_uri_type( const char *uri );
int XX_httplib_getreq( struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err );
void XX_httplib_handle_request( struct mg_connection *conn );
int XX_httplib_join_thread( pthread_t threadid );
void XX_httplib_log_access( const struct mg_connection *conn );
void XX_httplib_process_new_connection( struct mg_connection *conn );
void XX_httplib_produce_socket( struct mg_context *ctx, const struct socket *sp );
void XX_httplib_send_http_error( struct mg_connection *, int, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(3, 4);
int XX_httplib_set_acl_option( struct mg_context *ctx );
int XX_httplib_set_gpass_option( struct mg_context *ctx );
int XX_httplib_set_ports_option( struct mg_context *ctx );
@@ -820,6 +828,8 @@ int XX_httplib_set_ssl_option( struct mg_context *ctx );
int XX_httplib_set_tcp_nodelay( SOCKET sock, int nodelay_on );
void XX_httplib_set_thread_name( const char *name );
int XX_httplib_set_uid_option( struct mg_context *ctx );
int XX_httplib_should_keep_alive( const struct mg_connection *conn );
void XX_httplib_snprintf( const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(5, 6);
void XX_httplib_sockaddr_to_string(char *buf, size_t len, const union usa *usa);
void XX_httplib_ssl_get_client_cert_info( struct mg_connection *conn );
int XX_httplib_sslize( struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *) );

File diff suppressed because it is too large Load Diff