[core] use config_plugin_values_init()

This commit is contained in:
Glenn Strauss 2019-11-15 20:26:54 -05:00
parent 83633a9f06
commit ed62e354ff
25 changed files with 1200 additions and 942 deletions

View File

@ -13,7 +13,6 @@
#include "chunk.h"
#include "http_kv.h"
#include "sock_addr.h"
#include "etag.h"
struct fdevents; /* declaration */
struct stat_cache; /* declaration */
@ -76,57 +75,52 @@ typedef struct {
} physical;
typedef struct {
array *mimetypes;
const array *mimetypes;
/* virtual-servers */
buffer *document_root;
buffer *server_name;
buffer *error_handler;
buffer *error_handler_404;
buffer *server_tag;
buffer *errorfile_prefix;
const buffer *document_root;
const buffer *server_name;
const buffer *server_tag;
const buffer *error_handler;
const buffer *error_handler_404;
const buffer *errorfile_prefix;
unsigned short high_precision_timestamps;
unsigned short max_keep_alive_requests;
unsigned short max_keep_alive_idle;
unsigned short max_read_idle;
unsigned short max_write_idle;
unsigned short use_xattr;
unsigned short follow_symlink;
unsigned short range_requests;
unsigned short stream_request_body;
unsigned short stream_response_body;
unsigned short error_intercept;
unsigned char high_precision_timestamps;
unsigned char allow_http11;
unsigned char follow_symlink;
unsigned char etag_flags;
unsigned char force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */
unsigned char use_xattr;
unsigned char range_requests;
unsigned char error_intercept;
/* debug */
unsigned short log_file_not_found;
unsigned short log_request_header;
unsigned short log_request_handling;
unsigned short log_response_header;
unsigned short log_condition_handling;
unsigned short log_timeouts;
unsigned char log_file_not_found;
unsigned char log_request_header;
unsigned char log_request_handling;
unsigned char log_response_header;
unsigned char log_condition_handling;
unsigned char log_timeouts;
unsigned short allow_http11;
unsigned short etag_use_inode;
unsigned short etag_use_mtime;
unsigned short etag_use_size;
unsigned short force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */
unsigned int http_parseopts;
unsigned int max_request_size;
unsigned short kbytes_per_second; /* connection kb/s limit */
unsigned int bytes_per_second; /* connection bytes/sec limit */
unsigned int global_bytes_per_second;/*total bytes/sec limit for scope*/
/* configside */
unsigned short global_kbytes_per_second; /* */
off_t global_bytes_per_second_cnt;
/* server-wide traffic-shaper
*
* each context has the counter which is inited once
* a second by the global_kbytes_per_second config-var
* a second by the global_bytes_per_second config-var
*
* as soon as global_kbytes_per_second gets below 0
* as soon as global_bytes_per_second gets below 0
* the connected conns are "offline" a little bit
*
* the problem:
@ -135,25 +129,6 @@ typedef struct {
*
*/
off_t *global_bytes_per_second_cnt_ptr; /* */
/*
* global_bytes_per_second_cnt_ptr must be the final member above this point
* members above this point are patched per connection
*/
/* global or per-socket config; not patched per connection */
unsigned short use_ipv6, set_v6only; /* set_v6only is only a temporary option */
unsigned short defer_accept;
unsigned short ssl_enabled; /* only interesting for setting up listening sockets. don't use at runtime */
int listen_backlog;
buffer *socket_perms;
#if defined(__FreeBSD__) || defined(__NetBSD__) \
|| defined(__OpenBSD__) || defined(__DragonFly__)
buffer *bsd_accept_filter;
#endif
} specific_config;
/* the order of the items should be the same as they are processed
@ -193,9 +168,9 @@ typedef struct cond_cache_t {
cond_result_t result;
/* result without preconditions (must never be "skip") */
cond_result_t local_result;
const buffer *comp_value; /* just a pointer */
int patterncount;
int matches[3 * 10];
const buffer *comp_value; /* just a pointer */
} cond_cache_t;
struct connection {
@ -280,9 +255,6 @@ struct connection {
struct server_socket *srv_socket; /* reference to the server-socket */
int (* network_write)(struct server *srv, struct connection *con, chunkqueue *cq, off_t max_bytes);
int (* network_read)(struct server *srv, struct connection *con, chunkqueue *cq, off_t max_bytes);
/* etag handling */
etag_flags_t etag_flags;
};
typedef struct {
@ -297,56 +269,52 @@ typedef struct {
} mtime_cache_type;
typedef struct {
void *ptr;
void *ptr;
uint32_t used;
uint32_t size;
} buffer_plugin;
typedef struct {
unsigned int max_request_field_size;
int stat_cache_engine;
const char *xattr_name;
unsigned int log_state_handling;
unsigned char log_request_header_on_error;
unsigned short http_header_strict;
unsigned short http_host_strict;
unsigned short http_host_normalize;
/*(used sparsely, if at all, after config at startup)*/
unsigned char http_header_strict;
unsigned char http_host_strict;
unsigned char http_host_normalize;
unsigned char http_method_get_body;
unsigned char high_precision_timestamps;
unsigned short http_url_normalize;
unsigned short http_method_get_body;
unsigned short high_precision_timestamps;
unsigned short max_worker;
unsigned short max_fds;
unsigned short max_conns;
unsigned short log_state_handling;
unsigned short log_request_header_on_error;
unsigned short port;
time_t loadts;
double loadavg[3];
int stat_cache_engine;
unsigned int upload_temp_file_size;
array *upload_tempdirs;
buffer *xattr_name;
unsigned short dont_daemonize;
unsigned short preflight_check;
unsigned short enable_cores;
unsigned short reject_expect_100_with_417; /*(ignored)*/
unsigned short compat_module_load;
unsigned short systemd_socket_activation;
unsigned short errorlog_use_syslog;
buffer *errorlog_file;
buffer *breakagelog_file;
buffer *syslog_facility;
buffer *bindhost;
buffer *changeroot;
buffer *username;
buffer *groupname;
unsigned char dont_daemonize;
unsigned char preflight_check;
unsigned char enable_cores;
unsigned char compat_module_load;
unsigned char systemd_socket_activation;
unsigned char errorlog_use_syslog;
const buffer *errorlog_file;
const buffer *breakagelog_file;
const buffer *syslog_facility;
const buffer *bindhost;
const buffer *changeroot;
const buffer *username;
const buffer *groupname;
const buffer *network_backend;
const char *event_handler;
buffer *pid_file;
buffer *event_handler;
buffer *modules_dir;
buffer *network_backend;
array *modules;
} server_config;
@ -406,10 +374,6 @@ struct server {
buffer *ts_date_str;
log_error_st *errh;
/* config-file */
array *config_context;
specific_config **config_storage;
/**
* The status array can carry all the status information you want
* the key to the array is <module-prefix>.<name>
@ -430,14 +394,22 @@ struct server {
/* caches */
mtime_cache_type mtime_cache[FILE_CACHE_MAX];
time_t loadts;
double loadavg[3];
/* config-file */
void *config_data_base;
array *config_context;
array empty_array;
/* members used at start-up or rarely used */
server_socket_array srv_sockets;
server_socket_array srv_sockets_inherited;
buffer_plugin plugins;
array *config_touched;
short int config_deprecated;
short int config_unsupported;
unsigned char config_deprecated;
unsigned char config_unsupported;
int event_handler;
time_t startup_ts;

View File

@ -28,7 +28,7 @@
static size_t chunk_buf_sz = 4096;
static chunk *chunks, *chunks_oversized;
static chunk *chunk_buffers;
static array *chunkqueue_default_tempdirs = NULL;
static const array *chunkqueue_default_tempdirs = NULL;
static off_t chunkqueue_default_tempfile_size = DEFAULT_TEMPFILE_SIZE;
void chunkqueue_set_chunk_size (size_t sz)
@ -438,7 +438,7 @@ void chunkqueue_use_memory(chunkqueue *cq, size_t len) {
}
}
void chunkqueue_set_tempdirs_default (array *tempdirs, off_t upload_temp_file_size) {
void chunkqueue_set_tempdirs_default (const array *tempdirs, off_t upload_temp_file_size) {
chunkqueue_default_tempdirs = tempdirs;
chunkqueue_default_tempfile_size
= (0 == upload_temp_file_size) ? DEFAULT_TEMPFILE_SIZE
@ -446,7 +446,7 @@ void chunkqueue_set_tempdirs_default (array *tempdirs, off_t upload_temp_file_si
: upload_temp_file_size;
}
void chunkqueue_set_tempdirs(chunkqueue *cq, array *tempdirs, off_t upload_temp_file_size) {
void chunkqueue_set_tempdirs(chunkqueue *cq, const array *tempdirs, off_t upload_temp_file_size) {
force_assert(NULL != cq);
cq->tempdirs = tempdirs;
cq->upload_temp_file_size

View File

@ -42,7 +42,7 @@ typedef struct {
off_t bytes_in, bytes_out;
array *tempdirs;
const array *tempdirs;
off_t upload_temp_file_size;
unsigned int tempdir_idx;
} chunkqueue;
@ -60,8 +60,8 @@ chunkqueue *chunkqueue_init(void);
void chunkqueue_set_chunk_size (size_t sz);
void chunkqueue_set_tempdirs_default_reset (void);
void chunkqueue_set_tempdirs_default (array *tempdirs, off_t upload_temp_file_size);
void chunkqueue_set_tempdirs(chunkqueue *cq, array *tempdirs, off_t upload_temp_file_size);
void chunkqueue_set_tempdirs_default (const array *tempdirs, off_t upload_temp_file_size);
void chunkqueue_set_tempdirs(chunkqueue *cq, const array *tempdirs, off_t upload_temp_file_size);
void chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len); /* copies "fn" */
void chunkqueue_append_file_fd(chunkqueue *cq, buffer *fn, int fd, off_t offset, off_t len); /* copies "fn" */
void chunkqueue_append_mem(chunkqueue *cq, const char *mem, size_t len); /* copies memory */

File diff suppressed because it is too large Load Diff

View File

@ -128,7 +128,13 @@ int config_parse_file(server *srv, config_t *context, const char *fn);
__attribute_cold__
int config_parse_cmd(server *srv, config_t *context, const char *cmd);
void config_patch_connection(server *srv, connection *con);
__attribute_cold__
void config_free_config(void *p);
void config_reset_config_bytes_sec(void *p);
void config_reset_config(server *srv, connection *con);
void config_patch_config(server *srv, connection *con);
void config_cond_cache_reset(server *srv, connection *con);
void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item);
@ -150,7 +156,7 @@ typedef enum { T_CONFIG_SCOPE_UNSET,
T_CONFIG_SCOPE_CONNECTION
} config_scope_type_t;
typedef struct {
typedef struct config_plugin_value {
int k_id;
config_values_type_t vtype;
union v_u {

View File

@ -290,8 +290,8 @@ static handler_t connection_handle_read_body_unknown(server *srv, connection *co
static off_t connection_write_throttle(server *srv, connection *con, off_t max_bytes) {
UNUSED(srv);
if (con->conf.global_kbytes_per_second) {
off_t limit = con->conf.global_kbytes_per_second * 1024 - *(con->conf.global_bytes_per_second_cnt_ptr);
if (con->conf.global_bytes_per_second) {
off_t limit = (off_t)con->conf.global_bytes_per_second - *(con->conf.global_bytes_per_second_cnt_ptr);
if (limit <= 0) {
/* we reached the global traffic limit */
con->traffic_limit_reached = 1;
@ -302,8 +302,8 @@ static off_t connection_write_throttle(server *srv, connection *con, off_t max_b
}
}
if (con->conf.kbytes_per_second) {
off_t limit = con->conf.kbytes_per_second * 1024 - con->bytes_written_cur_second;
if (con->conf.bytes_per_second) {
off_t limit = (off_t)con->conf.bytes_per_second - con->bytes_written_cur_second;
if (limit <= 0) {
/* we reached the traffic limit */
con->traffic_limit_reached = 1;
@ -362,7 +362,8 @@ int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, of
written = cq->bytes_out - written;
con->bytes_written += written;
con->bytes_written_cur_second += written;
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
if (con->conf.global_bytes_per_second_cnt_ptr)
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
return ret;
}
@ -391,7 +392,8 @@ static int connection_write_100_continue(server *srv, connection *con) {
written = cq->bytes_out - written;
con->bytes_written += written;
con->bytes_written_cur_second += written;
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
if (con->conf.global_bytes_per_second_cnt_ptr)
*(con->conf.global_bytes_per_second_cnt_ptr) += written;
if (rc < 0) {
con->state = CON_STATE_ERROR;

View File

@ -535,17 +535,6 @@ static void connection_handle_write_state(server *srv, connection *con) {
}
static void connection_reset_config(server *srv, connection *con) {
/* initialize specific_config (con->conf) from top-level specific_config */
specific_config * const s = srv->config_storage[0];
const size_t len = /* offsetof() */
(uintptr_t)&((specific_config *)0)->global_bytes_per_second_cnt_ptr;
con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
con->server_name = s->server_name;
memcpy(&con->conf, s, len);
}
__attribute_cold__
static connection *connection_init(server *srv) {
connection *con;
@ -599,7 +588,7 @@ static connection *connection_init(server *srv) {
con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
force_assert(NULL != con->cond_cache);
connection_reset_config(srv, con);
config_reset_config(srv, con);
return con;
}
@ -710,7 +699,7 @@ static int connection_reset(server *srv, connection *con) {
/*con->error_handler_saved_method = HTTP_METHOD_UNSET;*/
/*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/
connection_reset_config(srv, con);
config_reset_config(srv, con);
return 0;
}
@ -1177,7 +1166,7 @@ static int connection_handle_request(server *srv, connection *con) {
con->error_handler_saved_status = 65535; /* >= 1000 */
}
} else if (con->http_status >= 400) {
buffer *error_handler = NULL;
const buffer *error_handler = NULL;
if (!buffer_string_is_empty(con->conf.error_handler)) {
error_handler = con->conf.error_handler;
} else if ((con->http_status == 404 || con->http_status == 403)
@ -1236,7 +1225,7 @@ static int connection_handle_request(server *srv, connection *con) {
break;
case HANDLER_COMEBACK:
if (con->mode == DIRECT && buffer_is_empty(con->physical.path)) {
connection_reset_config(srv, con);
config_reset_config(srv, con);
}
return 1;
case HANDLER_ERROR:
@ -1464,12 +1453,11 @@ static void connection_check_timeout (server * const srv, const time_t cur_ts, c
}
}
/* we don't like div by zero */
if (0 == (t_diff = cur_ts - con->connection_start)) t_diff = 1;
if (con->traffic_limit_reached &&
(con->conf.kbytes_per_second == 0 ||
((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))){
(con->conf.bytes_per_second == 0 ||
con->bytes_written < (off_t)con->conf.bytes_per_second * t_diff)) {
/* enable connection again */
con->traffic_limit_reached = 0;
@ -1514,8 +1502,8 @@ void connection_graceful_shutdown_maint (server *srv) {
con->keep_alive = 0; /* disable keep-alive */
con->conf.kbytes_per_second = 0; /* disable rate limit */
con->conf.global_kbytes_per_second = 0; /* disable rate limit */
con->conf.bytes_per_second = 0; /* disable rate limit */
con->conf.global_bytes_per_second = 0; /* disable rate limit */
if (con->traffic_limit_reached) {
con->traffic_limit_reached = 0;
changed = 1;

View File

@ -143,7 +143,7 @@ int etag_is_equal(const buffer *etag, const char *line, int weak_ok) {
return 0;
}
int etag_create(buffer *etag, const struct stat *st, etag_flags_t flags) {
int etag_create(buffer *etag, const struct stat *st, int flags) {
if (0 == flags) return 0;
buffer_clear(etag);

View File

@ -9,7 +9,7 @@ struct stat; /* declaration */
typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t;
int etag_is_equal(const buffer *etag, const char *matches, int weak_ok);
int etag_create(buffer *etag, const struct stat *st, etag_flags_t flags);
int etag_create(buffer *etag, const struct stat *st, int flags);
int etag_mutate(buffer *mut, buffer *etag);

View File

@ -56,7 +56,7 @@ int fdevent_config(server *srv) {
{ FDEVENT_HANDLER_UNSET, NULL }
};
if (buffer_string_is_empty(srv->srvconf.event_handler)) {
if (NULL == srv->srvconf.event_handler) {
/* choose a good default
*
* the event_handler list is sorted by 'goodness'
@ -71,24 +71,23 @@ int fdevent_config(server *srv) {
return -1;
}
buffer_copy_string(srv->srvconf.event_handler, event_handlers[0].name);
srv->srvconf.event_handler = event_handlers[0].name;
} else {
/*
* User override
*/
for (size_t i = 0; event_handlers[i].name; i++) {
if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler)) {
srv->event_handler = event_handlers[i].et;
break;
}
}
if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
log_error_write(srv, __FILE__, __LINE__, "sb",
"the selected event-handler in unknown or not supported:",
srv->srvconf.event_handler );
log_error(srv->errh, __FILE__, __LINE__,
"the selected event-handler in unknown or not supported: %s",
srv->srvconf.event_handler);
return -1;
}
}
@ -245,8 +244,10 @@ fdevents *fdevent_init(server *srv) {
free(ev->fdarray);
free(ev);
log_error_write(srv, __FILE__, __LINE__, "sBS",
"event-handler failed:", srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\"");
log_error(srv->errh, __FILE__, __LINE__,
"event-handler failed: %s; "
"try to set server.event-handler = \"poll\" or \"select\"",
srv->srvconf.event_handler);
return NULL;
}
@ -270,8 +271,11 @@ void fdevent_free(fdevents *ev) {
int fdevent_reset(fdevents *ev) {
int rc = (NULL != ev->reset) ? ev->reset(ev) : 0;
if (-1 == rc) {
log_error_write(ev->srv, __FILE__, __LINE__, "sBS",
"event-handler failed:", ev->srv->srvconf.event_handler, "; try to set server.event-handler = \"poll\" or \"select\"");
const char *event_handler = ev->srv->srvconf.event_handler;
log_error(ev->srv->errh, __FILE__, __LINE__,
"event-handler failed: %s; "
"try to set server.event-handler = \"poll\" or \"select\"",
event_handler ? event_handler : "");
}
return rc;
}

View File

@ -510,7 +510,7 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
}
if (allow_caching) {
if (con->etag_flags != 0 && !buffer_string_is_empty(stat_cache_etag_get(sce, con->etag_flags))) {
if (con->conf.etag_flags != 0 && !buffer_string_is_empty(stat_cache_etag_get(sce, con->conf.etag_flags))) {
if (NULL == http_header_response_get(con, HTTP_HEADER_ETAG, CONST_STR_LEN("ETag"))) {
/* generate e-tag */
etag_mutate(con->physical.etag, sce->etag);

View File

@ -563,7 +563,7 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, in
return 0;
}
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->srvconf.loadavg[0]) {
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->loadavg[0]) {
return -1;
}
@ -699,7 +699,7 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p,
if (sce->st.st_size > 128 * 1024 * 1024) return -1;
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->srvconf.loadavg[0]) {
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->loadavg[0]) {
return -1;
}
@ -851,7 +851,7 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
*/
if (sce->st.st_size < 128) return HANDLER_GO_ON;
stat_cache_etag_get(sce, con->etag_flags);
stat_cache_etag_get(sce, con->conf.etag_flags);
/* check if mimetype is in compress-config */
content_type = NULL;

View File

@ -1198,7 +1198,7 @@ CONNECTION_FUNC(mod_deflate_handle_response_start) {
}
}
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->srvconf.loadavg[0]) {
if (0.0 < p->conf.max_loadavg && p->conf.max_loadavg < srv->loadavg[0]) {
return HANDLER_GO_ON;
}

View File

@ -997,7 +997,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf
if (con->conf.use_xattr) {
memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
attrlen = sizeof(attrval) - 1;
if (attr_get(path, srv->srvconf.xattr_name->ptr, attrval, &attrlen, 0) == 0) {
if (attr_get(path, srv->srvconf.xattr_name, attrval, &attrlen, 0) == 0) {
attrval[attrlen] = '\0';
content_type = attrval;
}
@ -1005,7 +1005,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf
#elif defined(HAVE_EXTATTR)
if (con->conf.use_xattr) {
memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
if(-1 != (attrlen = extattr_get_file(path, EXTATTR_NAMESPACE_USER, srv->srvconf.xattr_name->ptr, attrval, sizeof(attrval)-1))) {
if(-1 != (attrlen = extattr_get_file(path, EXTATTR_NAMESPACE_USER, srv->srvconf.xattr_name, attrval, sizeof(attrval)-1))) {
attrval[attrlen] = '\0';
content_type = attrval;
}

View File

@ -361,7 +361,7 @@ static int magnet_stat(lua_State *L) {
lua_pushinteger(L, sce->st.st_ino);
lua_setfield(L, -2, "st_ino");
if (!buffer_string_is_empty(stat_cache_etag_get(sce, con->etag_flags))) {
if (!buffer_string_is_empty(stat_cache_etag_get(sce, con->conf.etag_flags))) {
/* we have to mutate the etag */
etag_mutate(srv->tmp_buf, sce->etag);
lua_pushlstring(L, CONST_BUF_LEN(srv->tmp_buf));

View File

@ -74,7 +74,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c
break;
}
stat_cache_etag_get(sce, con->etag_flags);
stat_cache_etag_get(sce, con->conf.etag_flags);
if (!buffer_is_equal(sce->etag, sc->etag)) {
/* the etag is outdated, reload the function */
lua_pop(sc->L, 1);
@ -115,7 +115,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c
}
if (HANDLER_GO_ON == stat_cache_get_entry(srv, con, sc->name, &sce)) {
buffer_copy_buffer(sc->etag, stat_cache_etag_get(sce, con->etag_flags));
buffer_copy_buffer(sc->etag, stat_cache_etag_get(sce, con->conf.etag_flags));
}
force_assert(lua_isfunction(sc->L, -1));

View File

@ -1266,7 +1266,7 @@ static int mod_ssi_handle_request(server *srv, connection *con, handler_ctx *p)
if (st.st_mtime < include_file_last_mtime)
st.st_mtime = include_file_last_mtime;
etag_create(con->physical.etag, &st, con->etag_flags);
etag_create(con->physical.etag, &st, con->conf.etag_flags);
etag_mutate(con->physical.etag, con->physical.etag);
http_header_response_set(con, HTTP_HEADER_ETAG, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));

View File

@ -168,7 +168,7 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
}
if (!p->conf.etags_used) con->etag_flags = 0;
if (!p->conf.etags_used) con->conf.etag_flags = 0;
http_response_send_file(srv, con, con->physical.path);
return HANDLER_FINISHED;

View File

@ -797,7 +797,7 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con) {
#endif
mod_status_header_append(b, "Network Engine");
mod_status_row_append(b, "fd-Event-Handler", srv->srvconf.event_handler->ptr);
mod_status_row_append(b, "fd-Event-Handler", srv->srvconf.event_handler);
mod_status_header_append(b, "Config-File-Settings");

View File

@ -2129,12 +2129,12 @@ webdav_fcopyfile_sz (int ifd, int ofd, off_t isz)
static int
webdav_if_match_or_unmodified_since (connection * const con, struct stat *st)
{
const buffer *im = (0 != con->etag_flags)
const buffer *im = (0 != con->conf.etag_flags)
? http_header_request_get(con, HTTP_HEADER_OTHER,
CONST_STR_LEN("If-Match"))
: NULL;
const buffer *inm = (0 != con->etag_flags)
const buffer *inm = (0 != con->conf.etag_flags)
? http_header_request_get(con, HTTP_HEADER_IF_NONE_MATCH,
CONST_STR_LEN("If-None-Match"))
: NULL;
@ -2151,7 +2151,7 @@ webdav_if_match_or_unmodified_since (connection * const con, struct stat *st)
buffer *etagb = con->physical.etag;
if (NULL != st && (NULL != im || NULL != inm)) {
etag_create(etagb, st, con->etag_flags);
etag_create(etagb, st, con->conf.etag_flags);
etag_mutate(etagb, etagb);
}
@ -2187,9 +2187,9 @@ webdav_response_etag (const plugin_config * const pconf,
connection * const con, struct stat *st)
{
server *srv = pconf->srv;
if (0 != con->etag_flags) {
if (0 != con->conf.etag_flags) {
buffer *etagb = con->physical.etag;
etag_create(etagb, st, con->etag_flags);
etag_create(etagb, st, con->conf.etag_flags);
stat_cache_update_entry(srv,CONST_BUF_LEN(con->physical.path),st,etagb);
etag_mutate(etagb, etagb);
http_header_response_set(con, HTTP_HEADER_ETAG,
@ -3056,9 +3056,9 @@ webdav_propfind_live_props (const webdav_propfind_bufs * const restrict pb,
if (pnum != WEBDAV_PROP_ALL) return 0;/* found *//*(else fall through)*/
__attribute_fallthrough__
case WEBDAV_PROP_GETETAG:
if (0 != pb->con->etag_flags) {
if (0 != pb->con->conf.etag_flags) {
buffer *etagb = pb->con->physical.etag;
etag_create(etagb, &pb->st, pb->con->etag_flags);
etag_create(etagb, &pb->st, pb->con->conf.etag_flags);
etag_mutate(etagb, etagb);
buffer_append_string_len(b, CONST_STR_LEN(
"<D:getetag>"));
@ -3643,7 +3643,7 @@ webdav_has_lock (connection * const con,
if (*p != ']') break; /* invalid syntax */
if (p == etag) continue; /* ignore entity-tag if empty */
if (notflag) continue;/* ignore entity-tag in NOT context */
if (0 == con->etag_flags) continue; /* ignore entity-tag */
if (0==con->conf.etag_flags) continue; /*ignore entity-tag*/
struct stat st;
if (0 != lstat(con->physical.path->ptr, &st)) {
http_status_set_error(con,412);/* Precondition Failed */
@ -3651,7 +3651,7 @@ webdav_has_lock (connection * const con,
}
if (S_ISDIR(st.st_mode)) continue;/*we ignore etag if dir*/
buffer *etagb = con->physical.etag;
etag_create(etagb, &st, con->etag_flags);
etag_create(etagb, &st, con->conf.etag_flags);
etag_mutate(etagb, etagb);
*p = '\0';
int ematch = etag_is_equal(etagb, etag, 0);
@ -4201,7 +4201,7 @@ mod_webdav_put_0 (connection * const con, const plugin_config * const pconf)
O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
WEBDAV_FILE_MODE);
if (fd >= 0) {
if (0 != con->etag_flags) {
if (0 != con->conf.etag_flags) {
/*(skip sending etag if fstat() error; not expected)*/
struct stat st;
if (0 == fstat(fd, &st)) webdav_response_etag(pconf, con, &st);
@ -4358,7 +4358,8 @@ mod_webdav_put_linkat_rename (connection * const con,
unlink(pathtemp);
}
if (0 != con->etag_flags && http_status_get(con) < 300) { /*(201, 204)*/
if (0 != con->conf.etag_flags
&& http_status_get(con) < 300) { /*(201, 204)*/
/*(skip sending etag if fstat() error; not expected)*/
if (0 == fstat(c->file.fd, &st))
webdav_response_etag(pconf, con, &st);
@ -4415,9 +4416,9 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
mod_webdav_write_cq(con, con->request_content_queue, fd);
struct stat st;
if (0 != con->etag_flags && !http_status_is_set(con)) {
if (0 != con->conf.etag_flags && !http_status_is_set(con)) {
/*(skip sending etag if fstat() error; not expected)*/
if (0 != fstat(fd, &st)) con->etag_flags = 0;
if (0 != fstat(fd, &st)) con->conf.etag_flags = 0;
}
const int wc = close(fd);
@ -4426,7 +4427,7 @@ mod_webdav_put_deprecated_unsafe_partial_put_compat (connection * const con,
if (!http_status_is_set(con)) {
http_status_set_fin(con, 204); /* No Content */
if (0 != con->etag_flags) webdav_response_etag(pconf, con, &st);
if (0 != con->conf.etag_flags) webdav_response_etag(pconf, con, &st);
}
return HANDLER_FINISHED;
@ -4530,9 +4531,9 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
mod_webdav_write_cq(con, cq, fd);
struct stat st;
if (0 != con->etag_flags && !http_status_is_set(con)) {
if (0 != con->conf.etag_flags && !http_status_is_set(con)) {
/*(skip sending etag if fstat() error; not expected)*/
if (0 != fstat(fd, &st)) con->etag_flags = 0;
if (0 != fstat(fd, &st)) con->conf.etag_flags = 0;
}
const int wc = close(fd);
@ -4547,7 +4548,7 @@ mod_webdav_put (connection * const con, const plugin_config * const pconf)
if (201 == http_status_get(con))
webdav_parent_modified(pconf, con->physical.path);
if (0 == rename(pathtemp, con->physical.path->ptr)) {
if (0 != con->etag_flags) webdav_response_etag(pconf, con, &st);
if (0 != con->conf.etag_flags) webdav_response_etag(pconf,con,&st);
}
else {
if (errno == EISDIR)
@ -5371,7 +5372,7 @@ mod_webdav_lock (connection * const con, const plugin_config * const pconf)
: -1;
if (fd >= 0) {
/*(skip sending etag if fstat() error; not expected)*/
if (0 != fstat(fd, &st)) con->etag_flags = 0;
if (0 != fstat(fd, &st)) con->conf.etag_flags = 0;
close(fd);
created = 1;
webdav_parent_modified(pconf, con->physical.path);
@ -5432,7 +5433,7 @@ mod_webdav_lock (connection * const con, const plugin_config * const pconf)
CONST_STR_LEN("Lock-Token"),
lockstr, sizeof(lockstr)-1);
webdav_xml_doc_lock_acquired(con, pconf, &lockdata);
if (0 != con->etag_flags && !S_ISDIR(st.st_mode))
if (0 != con->conf.etag_flags && !S_ISDIR(st.st_mode))
webdav_response_etag(pconf, con, &st);
http_status_set_fin(con, created ? 201 : 200); /* Created | OK */
}

View File

@ -5,6 +5,7 @@
#include "fdevent.h"
#include "log.h"
#include "connections.h"
#include "plugin.h"
#include "configfile.h"
#include "sock_addr.h"
@ -137,10 +138,60 @@ static void network_srv_sockets_append(server *srv, server_socket *srv_socket) {
srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
}
static int network_server_init(server *srv, buffer *host_token, size_t sidx, int stdin_fd) {
typedef struct {
/* global or per-socket config; not patched per connection */
int listen_backlog;
unsigned char ssl_enabled;
unsigned char use_ipv6;
unsigned char set_v6only; /* set_v6only is only a temporary option */
unsigned char defer_accept;
const buffer *socket_perms;
const buffer *bsd_accept_filter;
} network_socket_config;
typedef struct {
PLUGIN_DATA;
network_socket_config defaults;
network_socket_config conf;
} network_plugin_data;
static void network_merge_config_cpv(network_socket_config * const pconf, const config_plugin_value_t * const cpv) {
switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
case 0: /* ssl.engine */
pconf->ssl_enabled = (0 != cpv->v.u);
break;
case 1: /* server.listen-backlog */
pconf->listen_backlog = (int)cpv->v.u;
break;
case 2: /* server.socket-perms */
pconf->socket_perms = cpv->v.b;
break;
case 3: /* server.bsd-accept-filter */
pconf->bsd_accept_filter = cpv->v.b;
break;
case 4: /* server.defer-accept */
pconf->defer_accept = (0 != cpv->v.u);
break;
case 5: /* server.use-ipv6 */
pconf->use_ipv6 = (0 != cpv->v.u);
break;
case 6: /* server.set-v6only */
pconf->set_v6only = (0 != cpv->v.u);
break;
default:/* should not happen */
return;
}
}
static void network_merge_config(network_socket_config * const pconf, const config_plugin_value_t *cpv) {
do {
network_merge_config_cpv(pconf, cpv);
} while ((++cpv)->k_id != -1);
}
static int network_server_init(server *srv, network_socket_config *s, buffer *host_token, size_t sidx, int stdin_fd) {
server_socket *srv_socket;
const char *host;
specific_config *s = srv->config_storage[sidx];
socklen_t addr_len = sizeof(sock_addr);
sock_addr addr;
int family = 0;
@ -156,7 +207,6 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int
* binary addresses are matched further below) */
for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
if (buffer_is_equal(srv->srv_sockets.ptr[i]->srv_token, host_token)) {
buffer_copy_buffer(host_token, srv->srv_sockets.ptr[i]->srv_token);
return 0;
}
}
@ -398,7 +448,7 @@ int network_close(server *srv) {
return 0;
}
static int network_socket_activation_nfds(server *srv, int nfds) {
static int network_socket_activation_nfds(server *srv, network_socket_config *s, int nfds) {
buffer *host = buffer_init();
socklen_t addr_len;
sock_addr addr;
@ -412,7 +462,7 @@ static int network_socket_activation_nfds(server *srv, int nfds) {
break;
}
network_host_normalize_addr_str(host, &addr);
rc = network_server_init(srv, host, 0, fd);
rc = network_server_init(srv, s, host, 0, fd);
if (0 != rc) break;
srv->srv_sockets.ptr[srv->srv_sockets.used-1]->sidx = (unsigned short)~0u;
}
@ -422,13 +472,13 @@ static int network_socket_activation_nfds(server *srv, int nfds) {
return rc;
}
static int network_socket_activation_from_env(server *srv) {
static int network_socket_activation_from_env(server *srv, network_socket_config *s) {
char *listen_pid = getenv("LISTEN_PID");
char *listen_fds = getenv("LISTEN_FDS");
pid_t lpid = listen_pid ? (pid_t)strtoul(listen_pid,NULL,10) : 0;
int nfds = listen_fds ? atoi(listen_fds) : 0;
int rc = (lpid == getpid() && nfds > 0)
? network_socket_activation_nfds(srv, nfds)
? network_socket_activation_nfds(srv, s, nfds)
: 0;
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
@ -438,85 +488,151 @@ static int network_socket_activation_from_env(server *srv) {
}
int network_init(server *srv, int stdin_fd) {
#ifdef __WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (0 != WSAStartup(wVersionRequested, &wsaData)) {
/* Tell the user that we could not find a usable WinSock DLL */
return -1;
}
#endif
/*(network params used during setup (from $SERVER["socket"] condition))*/
static const config_plugin_keys_t cpk[] = {
{ CONST_STR_LEN("ssl.engine"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.listen-backlog"),
T_CONFIG_INT,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.socket-perms"),
T_CONFIG_STRING,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.bsd-accept-filter"),
T_CONFIG_STRING,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.defer-accept"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.use-ipv6"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ CONST_STR_LEN("server.set-v6only"),
T_CONFIG_BOOL,
T_CONFIG_SCOPE_CONNECTION }
,{ NULL, 0,
T_CONFIG_UNSET,
T_CONFIG_SCOPE_UNSET }
};
if (0 != network_write_init(srv)) return -1;
#ifdef __WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
if (0 != WSAStartup(wVersionRequested, &wsaData)) {
/* Tell the user that we could not find a usable WinSock DLL */
return -1;
}
#endif
if (srv->srvconf.systemd_socket_activation) {
for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
srv->srv_sockets_inherited.ptr[i]->sidx = (unsigned short)~0u;
}
if (0 != network_socket_activation_from_env(srv)) return -1;
if (0 == srv->srv_sockets_inherited.used) {
srv->srvconf.systemd_socket_activation = 0;
}
}
if (0 != network_write_init(srv)) return -1;
/* process srv->srvconf.bindhost
* (skip if systemd socket activation is enabled and bindhost is empty; do not additionally listen on "*") */
if (!srv->srvconf.systemd_socket_activation || !buffer_string_is_empty(srv->srvconf.bindhost)) {
int rc;
buffer *b = buffer_init();
buffer_copy_buffer(b, srv->srvconf.bindhost);
if (b->ptr[0] != '/') { /*(skip adding port if unix socket path)*/
buffer_append_string_len(b, CONST_STR_LEN(":"));
buffer_append_int(b, srv->srvconf.port);
}
network_plugin_data np;
memset(&np, 0, sizeof(network_plugin_data));
network_plugin_data *p = &np;
rc = (-1 == stdin_fd || 0 == srv->srv_sockets.used)
? network_server_init(srv, b, 0, stdin_fd)
: close(stdin_fd);/*(graceful restart listening to "/dev/stdin")*/
buffer_free(b);
if (0 != rc) return -1;
}
if (!config_plugin_values_init(srv, p, cpk, "network"))
return HANDLER_ERROR;
/* check for $SERVER["socket"] */
for (uint32_t i = 1; i < srv->config_context->used; ++i) {
config_cond_info cfginfo;
config_get_config_cond_info(srv, i, &cfginfo);
buffer *host_token;
*(const buffer **)&host_token = cfginfo.string;
/*(cfginfo.string is modified during config)*/
p->defaults.listen_backlog = 1024;
p->defaults.defer_accept = 0;
p->defaults.use_ipv6 = 0;
p->defaults.set_v6only = 1;
/* not our stage */
if (COMP_SERVER_SOCKET != cfginfo.comp) continue;
/* initialize p->defaults from global config context */
if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
if (-1 != cpv->k_id)
network_merge_config(&p->defaults, cpv);
}
if (cfginfo.cond == CONFIG_COND_NE) {
socklen_t addr_len = sizeof(sock_addr);
sock_addr addr;
if (0 != network_host_parse_addr(srv, &addr, &addr_len, host_token, srv->config_storage[i]->use_ipv6)) {
return -1;
}
network_host_normalize_addr_str(host_token, &addr);
continue;
}
int rc = 0;
do {
if (cfginfo.cond != CONFIG_COND_EQ) continue;
if (srv->srvconf.systemd_socket_activation) {
for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
srv->srv_sockets_inherited.ptr[i]->sidx = (unsigned short)~0u;
}
rc = network_socket_activation_from_env(srv, &p->defaults);
if (0 != rc) break;
if (0 == srv->srv_sockets_inherited.used) {
srv->srvconf.systemd_socket_activation = 0;
}
}
if (0 != network_server_init(srv, host_token, i, -1)) return -1;
}
/* process srv->srvconf.bindhost
* (skip if systemd socket activation is enabled and bindhost is empty;
* do not additionally listen on "*") */
if (!srv->srvconf.systemd_socket_activation
|| !buffer_string_is_empty(srv->srvconf.bindhost)) {
buffer *b = buffer_init();
buffer_copy_buffer(b, srv->srvconf.bindhost);
if (b->ptr[0] != '/') { /*(skip adding port if unix socket path)*/
buffer_append_string_len(b, CONST_STR_LEN(":"));
buffer_append_int(b, srv->srvconf.port);
}
if (srv->srvconf.systemd_socket_activation) {
/* activate any inherited sockets not explicitly listed in config file */
server_socket *srv_socket;
for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
if ((unsigned short)~0u != srv->srv_sockets_inherited.ptr[i]->sidx) continue;
srv->srv_sockets_inherited.ptr[i]->sidx = 0;
srv_socket = calloc(1, sizeof(server_socket));
force_assert(NULL != srv_socket);
memcpy(srv_socket, srv->srv_sockets_inherited.ptr[i], sizeof(server_socket));
network_srv_sockets_append(srv, srv_socket);
}
}
rc = (-1 == stdin_fd || 0 == srv->srv_sockets.used)
? network_server_init(srv, &p->defaults, b, 0, stdin_fd)
: close(stdin_fd);/*(graceful restart listening to "/dev/stdin")*/
buffer_free(b);
if (0 != rc) break;
}
return 0;
/* check for $SERVER["socket"] */
for (uint32_t i = 1; i < srv->config_context->used; ++i) {
config_cond_info cfginfo;
config_get_config_cond_info(srv, i, &cfginfo);
if (COMP_SERVER_SOCKET != cfginfo.comp) continue;/* not our stage */
buffer *host_token;
*(const buffer **)&host_token = cfginfo.string;
/*(cfginfo.string is modified during config)*/
memcpy(&p->conf, &p->defaults, sizeof(network_socket_config));
for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) {
if ((int)i != p->cvlist[j].k_id) continue;
const config_plugin_value_t *cpv =
p->cvlist + p->cvlist[j].v.u2[0];
network_merge_config(&p->conf, cpv);
break;
}
if (cfginfo.cond == CONFIG_COND_EQ) {
rc = network_server_init(srv, &p->conf, host_token, i, -1);
if (0 != rc) break;
}
else if (cfginfo.cond == CONFIG_COND_NE) {
socklen_t addr_len = sizeof(sock_addr);
sock_addr addr;
rc = network_host_parse_addr(srv, &addr, &addr_len,
host_token, p->conf.use_ipv6);
if (0 != rc) break;
network_host_normalize_addr_str(host_token, &addr);
}
}
if (0 != rc) break;
if (srv->srvconf.systemd_socket_activation) {
/* activate any inherited sockets not explicitly listed in config */
server_socket *srv_socket;
for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
if ((unsigned short)~0u
!= srv->srv_sockets_inherited.ptr[i]->sidx)
continue;
srv->srv_sockets_inherited.ptr[i]->sidx = 0;
srv_socket = calloc(1, sizeof(server_socket));
force_assert(NULL != srv_socket);
memcpy(srv_socket, srv->srv_sockets_inherited.ptr[i],
sizeof(server_socket));
network_srv_sockets_append(srv, srv_socket);
}
}
} while (0);
free(p->cvlist);
return rc;
}
void network_unregister_sock(server *srv, server_socket *srv_socket) {

View File

@ -35,12 +35,11 @@ static int http_response_omit_header(connection *con, const data_string * const
&& buffer_eq_icase_ssn(ds->key.ptr+sizeof("X-LIGHTTPD-")-1,
CONST_STR_LEN("KBytes-per-second"))) {
/* "X-LIGHTTPD-KBytes-per-second" */
long limit = strtol(ds->value.ptr, NULL, 10);
off_t limit = strtol(ds->value.ptr, NULL, 10) << 10; /*(*=1024)*/
if (limit > 0
&& (limit < con->conf.kbytes_per_second
|| 0 == con->conf.kbytes_per_second)) {
if (limit > USHRT_MAX) limit= USHRT_MAX;
con->conf.kbytes_per_second = limit;
&& (limit < con->conf.bytes_per_second
|| 0 == con->conf.bytes_per_second)) {
con->conf.bytes_per_second = limit;
}
}
return 1;
@ -59,6 +58,7 @@ int http_response_write_header(server *srv, connection *con) {
http_status_append(b, con->http_status);
/* disable keep-alive if requested */
if (con->request_count > con->conf.max_keep_alive_requests || 0 == con->conf.max_keep_alive_idle) {
con->keep_alive = 0;
} else if (0 != con->request.content_length
@ -435,7 +435,7 @@ handler_t http_response_prepare(server *srv, connection *con) {
| (1 << COMP_HTTP_URL)