Update embedded civetweb 1.13 -> 1.14

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2021-06-08 09:57:18 +02:00
parent a2aca98d25
commit 82e9a316da
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
11 changed files with 1459 additions and 1255 deletions

View File

@ -32,7 +32,7 @@ int api_handler(struct mg_connection *conn, void *ignored)
log_debug(DEBUG_API, "Requested API URI: %s %s ? %s",
api.request->request_method,
api.request->local_uri,
api.request->local_uri_raw,
api.request->query_string);
int ret = 0;
@ -239,7 +239,7 @@ int api_handler(struct mg_connection *conn, void *ignored)
ret = send_json_error(&api, 404,
"not_found",
"Not found",
api.request->local_uri);
api.request->local_uri_raw);
}
// Free JSON-parsed payload memory (if allocated)

View File

@ -33,7 +33,7 @@ int api_docs(struct ftl_conn *api)
(serve_index && strcmp(docs_files[i].path, "index.html") == 0))
{
// Send the file
mg_send_http_ok(api->conn, docs_files[i].mime_type, NULL, docs_files[i].content_size);
mg_send_http_ok(api->conn, docs_files[i].mime_type, docs_files[i].content_size);
return mg_write(api->conn, docs_files[i].content, docs_files[i].content_size);
}
}

View File

@ -419,7 +419,7 @@ int api_list(struct ftl_conn *api)
return send_json_error(api, 400,
"bad_request",
"Invalid request: Specified endpoint not available",
api->request->local_uri);
api->request->local_uri_raw);
}
if(api->method == HTTP_GET)

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2020 the Civetweb developers
/* Copyright (c) 2013-2021 the Civetweb developers
* Copyright (c) 2004-2013 Sergey Lyubka
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -23,9 +23,9 @@
#ifndef CIVETWEB_HEADER_INCLUDED
#define CIVETWEB_HEADER_INCLUDED
#define CIVETWEB_VERSION "1.13"
#define CIVETWEB_VERSION "1.14"
#define CIVETWEB_VERSION_MAJOR (1)
#define CIVETWEB_VERSION_MINOR (13)
#define CIVETWEB_VERSION_MINOR (14)
#define CIVETWEB_VERSION_PATCH (0)
#ifndef CIVETWEB_API
@ -98,8 +98,13 @@ enum {
/* Will only work, if USE_ZLIB is set. */
MG_FEATURES_COMPRESSION = 0x200u,
/* Collect server status information. */
/* Will only work, if USE_SERVER_STATS is set. */
/* HTTP/2 support enabled. */
MG_FEATURES_HTTP2 = 0x400u,
/* Support unix domain sockets. */
MG_FEATURES_X_DOMAIN_SOCKET = 0x800u,
/* Bit mask for all feature defines. */
MG_FEATURES_ALL = 0xFFFFu
};
@ -146,9 +151,13 @@ struct mg_request_info {
const char *request_method; /* "GET", "POST", etc */
const char *request_uri; /* URL-decoded URI (absolute or relative,
* as in the request) */
const char *local_uri; /* URL-decoded URI (relative). Can be NULL
const char *local_uri_raw; /* URL-decoded URI (relative). Can be NULL
* if the request_uri does not address a
* resource at the server host. */
const char *local_uri; /* Same as local_uri_raw, however, cleaned
* so a path like
* allowed_dir/../forbidden_file
* is not possible. */
#if defined(MG_LEGACY_INTERFACE) /* 2017-02-04, deprecated 2014-09-14 */
const char *uri; /* Deprecated: use local_uri instead */
#endif
@ -161,8 +170,11 @@ struct mg_request_info {
long long content_length; /* Length (in bytes) of the request body,
can be -1 if no length was given. */
int remote_port; /* Client's port */
int is_ssl; /* 1 if SSL-ed, 0 if not */
int remote_port; /* Port at client side */
int server_port; /* Port at server side (one of the listening
ports) */
int is_ssl; /* 1 if HTTPS or WS is used (SSL/TLS used),
0 if not */
void *user_data; /* User data pointer passed to mg_start() */
void *conn_data; /* Connection-specific user data */
@ -319,14 +331,20 @@ struct mg_callbacks {
application-maintained list of clients.
Using this callback for websocket connections is deprecated: Use
mg_set_websocket_handler instead.
Connection specific data:
If memory has been allocated for the connection specific user data
(mg_request_info->conn_data, mg_get_user_connection_data),
this is the last chance to free it.
*/
void (*connection_close)(const struct mg_connection *);
/* Called after civetweb has closed a connection. The per-context mutex is
locked when this is invoked.
Connection specific data:
If memory has been allocated for the connection specific user data
(mg_request_info->conn_data, mg_get_user_connection_data),
this is the last chance to free it.
*/
void (*connection_closed)(const struct mg_connection *);
/* init_lua is called when civetweb is about to serve Lua server page.
exit_lua is called when the Lua processing is complete.
Both will work only if Lua support is enabled.
@ -560,7 +578,7 @@ typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
*/
struct mg_websocket_subprotocols {
int nb_subprotocols;
char **subprotocols;
const char **subprotocols;
};
/* mg_set_websocket_handler
@ -644,7 +662,14 @@ CIVETWEB_API void *mg_get_thread_pointer(const struct mg_connection *conn);
/* Set user data for the current connection. */
/* Note: This function is deprecated. Use the init_connection callback
/* Note: CivetWeb callbacks use "struct mg_connection *conn" as input
when mg_read/mg_write callbacks are allowed in the callback,
while "const struct mg_connection *conn" is used as input in case
calling mg_read/mg_write is not allowed.
Setting the user connection data will modify the connection
object represented by mg_connection *, but it will not read from
or write to the connection. */
/* Note: An alternative is to use the init_connection callback
instead to initialize the user connection data pointer. It is
reccomended to supply a pointer to some user defined data structure
as conn_data initializer in init_connection. In case it is required
@ -652,7 +677,7 @@ CIVETWEB_API void *mg_get_thread_pointer(const struct mg_connection *conn);
data pointer in the user defined data structure and modify that
pointer. In either case, after the init_connection callback, only
calls to mg_get_user_connection_data should be required. */
CIVETWEB_API void mg_set_user_connection_data(struct mg_connection *conn,
CIVETWEB_API void mg_set_user_connection_data(const struct mg_connection *conn,
void *data);
@ -956,8 +981,6 @@ extern char pi_hole_extra_headers[PIHOLE_HEADERS_MAXLEN];
* Parameters:
* conn: Current connection handle.
* mime_type: Set Content-Type for the following content.
* additional_header: Pi-hole addition for sending custom additional
* information (like settingcookies)
* content_length: Size of the following content, if content_length >= 0.
* Will set transfer-encoding to chunked, if set to -1.
* Return:
@ -965,7 +988,6 @@ extern char pi_hole_extra_headers[PIHOLE_HEADERS_MAXLEN];
*/
CIVETWEB_API int mg_send_http_ok(struct mg_connection *conn,
const char *mime_type,
const char *additional_headers,
long long content_length);
@ -1435,6 +1457,19 @@ mg_connect_websocket_client(const char *host,
mg_websocket_close_handler close_func,
void *user_data);
CIVETWEB_API struct mg_connection *
mg_connect_websocket_client_extensions(const char *host,
int port,
int use_ssl,
char *error_buffer,
size_t error_buffer_size,
const char *path,
const char *origin,
const char *extensions,
mg_websocket_data_handler data_func,
mg_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)
Parameters:
@ -1481,6 +1516,17 @@ CIVETWEB_API struct mg_connection *mg_connect_websocket_client_secure(
mg_websocket_close_handler close_func,
void *user_data);
CIVETWEB_API struct mg_connection *
mg_connect_websocket_client_secure_extensions(
const struct mg_client_options *client_options,
char *error_buffer,
size_t error_buffer_size,
const char *path,
const char *origin,
const char *extensions,
mg_websocket_data_handler data_func,
mg_websocket_close_handler close_func,
void *user_data);
#if defined(MG_LEGACY_INTERFACE) /* 2019-11-02 */
enum { TIMEOUT_INFINITE = -1 };
@ -1644,6 +1690,14 @@ CIVETWEB_API int
mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen);
/* Disable HTTP keep-alive on a per-connection basis.
Reference: https://github.com/civetweb/civetweb/issues/727
Parameters:
conn: Current connection handle.
*/
CIVETWEB_API void mg_disable_connection_keep_alive(struct mg_connection *conn);
#if defined(MG_EXPERIMENTAL_INTERFACES)
/* Get connection information. Useful for server diagnosis.
Parameters:

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2016-2020 the Civetweb developers
/* Copyright (c) 2016-2021 the Civetweb developers
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -683,7 +683,7 @@ mg_handle_form_request(struct mg_connection *conn,
if (part_no == 0) {
int d = 0;
while ((buf[d] != '-') && (d < buf_fill)) {
while ((d < buf_fill) && (buf[d] != '-')) {
d++;
}
if ((d > 0) && (buf[d] == '-')) {
@ -962,9 +962,7 @@ mg_handle_form_request(struct mg_connection *conn,
mg_free(boundary);
return -1;
}
if (r == 0) {
all_data_read = (buf_fill == 0);
}
/* r==0 already handled, all_data_read is false here */
buf_fill += r;
buf[buf_fill] = 0;
@ -979,7 +977,7 @@ mg_handle_form_request(struct mg_connection *conn,
}
}
towrite = (size_t)(next - hend);
towrite = (next ? (size_t)(next - hend) : 0);
if (field_storage == MG_FORM_FIELD_STORAGE_GET) {
/* Call callback */
@ -1043,9 +1041,13 @@ mg_handle_form_request(struct mg_connection *conn,
}
/* Remove from the buffer */
used = next - buf + 2;
memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used);
buf_fill -= (int)used;
if (next) {
used = next - buf + 2;
memmove(buf, buf + (size_t)used, sizeof(buf) - (size_t)used);
buf_fill -= (int)used;
} else {
buf_fill = 0;
}
}
/* All parts handled */

View File

@ -8,7 +8,7 @@
*/
#if defined(NO_RESPONSE_BUFFERING) && defined(USE_HTTP2)
#error "HTTP2 currently works only if NO_RESPONSE_BUFFERING is not set"
#error "HTTP2 works only if NO_RESPONSE_BUFFERING is not set"
#endif
@ -40,13 +40,22 @@ free_buffered_response_header_list(struct mg_connection *conn)
static void
send_http1_response_status_line(struct mg_connection *conn)
{
const char *status_txt;
const char *http_version = conn->request_info.http_version;
int status_code = conn->status_code;
if ((status_code < 100) || (status_code > 999)) {
/* Set invalid status code to "500 Internal Server Error" */
status_code = 500;
}
if (!http_version) {
http_version = "1.0";
}
/* mg_get_response_code_text will never return NULL */
const char *txt = mg_get_response_code_text(conn, conn->status_code);
mg_printf(conn,
"HTTP/%s %i %s\r\n",
conn->request_info.http_version,
conn->status_code,
txt);
status_txt = mg_get_response_code_text(conn, conn->status_code);
mg_printf(conn, "HTTP/%s %i %s\r\n", http_version, status_code, status_txt);
}
@ -142,7 +151,8 @@ mg_response_header_add(struct mg_connection *conn,
conn->response_info.http_headers[hidx].name =
mg_strdup_ctx(header, conn->phys_ctx);
if (value_len >= 0) {
char *hbuf = mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
char *hbuf =
(char *)mg_malloc_ctx((unsigned)value_len + 1, conn->phys_ctx);
if (hbuf) {
memcpy(hbuf, value, (unsigned)value_len);
hbuf[value_len] = 0;
@ -231,7 +241,7 @@ mg_response_header_add_lines(struct mg_connection *conn,
}
#if defined USE_HTTP2
#if defined(USE_HTTP2)
static int http2_send_response_headers(struct mg_connection *conn);
#endif
@ -272,14 +282,12 @@ mg_response_header_send(struct mg_connection *conn)
conn->request_state = 2;
#if !defined(NO_RESPONSE_BUFFERING)
#if defined(USE_HTTP2)
if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
#if defined USE_HTTP2
int ret = http2_send_response_headers(conn);
return ret ? 0 : 0; /* todo */
#else
return -2;
#endif
}
#endif
/* Send */
send_http1_response_status_line(conn);

View File

@ -1,19 +1,25 @@
/* This file is part of the CivetWeb web server.
* See https://github.com/civetweb/civetweb/
* (C) 2014-2018 by the CivetWeb authors, MIT license.
* (C) 2014-2021 by the CivetWeb authors, MIT license.
*/
#if !defined(MAX_TIMERS)
#define MAX_TIMERS MAX_WORKER_THREADS
#endif
#if !defined(TIMER_RESOLUTION)
/* Timer resolution in ms */
#define TIMER_RESOLUTION (10)
#endif
typedef int (*taction)(void *arg);
typedef void (*tcancelaction)(void *arg);
struct ttimer {
double time;
double period;
taction action;
void *arg;
tcancelaction cancel;
};
struct ttimers {
@ -66,7 +72,8 @@ timer_add(struct mg_context *ctx,
double period,
int is_relative,
taction action,
void *arg)
void *arg,
tcancelaction cancel)
{
int error = 0;
double now;
@ -126,6 +133,7 @@ timer_add(struct mg_context *ctx,
ctx->timers->timers[u].period = period;
ctx->timers->timers[u].action = action;
ctx->timers->timers[u].arg = arg;
ctx->timers->timers[u].cancel = cancel;
ctx->timers->timer_count++;
}
pthread_mutex_unlock(&ctx->timers->mutex);
@ -139,7 +147,7 @@ timer_thread_run(void *thread_func_param)
struct mg_context *ctx = (struct mg_context *)thread_func_param;
double d;
unsigned u;
int re_schedule;
int action_res;
struct ttimer t;
mg_set_thread_name("timer");
@ -149,39 +157,65 @@ timer_thread_run(void *thread_func_param)
ctx->callbacks.init_thread(ctx, 2);
}
/* Timer main loop */
d = timer_getcurrenttime(ctx);
while (ctx->stop_flag == 0) {
while (STOP_FLAG_IS_ZERO(&ctx->stop_flag)) {
pthread_mutex_lock(&ctx->timers->mutex);
if ((ctx->timers->timer_count > 0)
&& (d >= ctx->timers->timers[0].time)) {
/* Timer list is sorted. First action should run now. */
/* Store active timer in "t" */
t = ctx->timers->timers[0];
/* Shift all other timers */
for (u = 1; u < ctx->timers->timer_count; u++) {
ctx->timers->timers[u - 1] = ctx->timers->timers[u];
}
ctx->timers->timer_count--;
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);
/* Call timer action */
action_res = t.action(t.arg);
/* action_res == 1: reschedule */
/* action_res == 0: do not reschedule, free(arg) */
if ((action_res > 0) && (t.period > 0)) {
/* Should schedule timer again */
timer_add(ctx,
t.time + t.period,
t.period,
0,
t.action,
t.arg,
t.cancel);
} else {
/* Allow user to free timer argument */
if (t.cancel != NULL) {
t.cancel(t.arg);
}
}
continue;
} else {
pthread_mutex_unlock(&ctx->timers->mutex);
}
/* 10 ms seems reasonable.
* A faster loop (smaller sleep value) increases CPU load,
* a slower loop (higher sleep value) decreases timer accuracy.
*/
#if defined(_WIN32)
Sleep(10);
#else
usleep(10000);
#endif
/* TIMER_RESOLUTION = 10 ms seems reasonable.
* A faster loop (smaller sleep value) increases CPU load,
* a slower loop (higher sleep value) decreases timer accuracy.
*/
mg_sleep(TIMER_RESOLUTION);
d = timer_getcurrenttime(ctx);
}
/* Remove remaining timers */
for (u = 0; u < ctx->timers->timer_count; u++) {
t = ctx->timers->timers[u];
if (t.cancel != NULL) {
t.cancel(t.arg);
}
}
}

View File

@ -48,7 +48,7 @@ const char* json_formatter(const cJSON *object)
int send_http(struct ftl_conn *api, const char *mime_type,
const char *msg)
{
mg_send_http_ok(api->conn, mime_type, NULL, strlen(msg));
mg_send_http_ok(api->conn, mime_type, strlen(msg));
return mg_write(api->conn, msg, strlen(msg));
}
@ -276,22 +276,24 @@ bool get_double_var(const char *source, const char *var, double *num)
const char* __attribute__((pure)) startsWith(const char *path, struct ftl_conn *api)
{
if(strncmp(path, api->request->local_uri, strlen(path)) == 0)
if(api->request->local_uri[strlen(path)] == '/')
// We use local_uri_raw here to get the unescaped URI, see
// https://github.com/civetweb/civetweb/pull/975
if(strncmp(path, api->request->local_uri_raw, strlen(path)) == 0)
if(api->request->local_uri_raw[strlen(path)] == '/')
{
// Path match with argument after ".../"
if(api->action_path != NULL)
free(api->action_path);
api->action_path = strdup(api->request->local_uri);
api->action_path = strdup(api->request->local_uri_raw);
api->action_path[strlen(path)] = '\0';
return api->request->local_uri + strlen(path) + 1u;
return api->request->local_uri_raw + strlen(path) + 1u;
}
else if(strlen(path) == strlen(api->request->local_uri))
else if(strlen(path) == strlen(api->request->local_uri_raw))
{
// Path match directly, no argument
if(api->action_path != NULL)
free(api->action_path);
api->action_path = strdup(api->request->local_uri);
api->action_path = strdup(api->request->local_uri_raw);
return "";
}
else

View File

@ -44,7 +44,7 @@ int ph7_handler(struct mg_connection *conn, void *cbdata)
/* Handler may access the request info using mg_get_request_info */
const struct mg_request_info *req_info = mg_get_request_info(conn);
const char *local_uri = req_info->local_uri + 1u;
const char *local_uri = req_info->local_uri_raw + 1u;
// Build full path of PHP script on our machine
const size_t webroot_len = strlen(httpsettings.webroot);

View File

@ -65,7 +65,7 @@ static int redirect_root_handler(struct mg_connection *conn, void *input)
// Get requested URI
const struct mg_request_info *request = mg_get_request_info(conn);
const char *uri = request->local_uri;
const char *uri = request->local_uri_raw;
log_debug(DEBUG_API, "URI: %s", uri);
}