Browse Source

Enabled options, moved some initializing

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent
commit
b8e3535546
  1. 47
      src/connection.c
  2. 2
      src/connection.h
  3. 12
      src/lighttpd.c
  4. 3
      src/log.h
  5. 1
      src/network.c
  6. 3
      src/options.c
  7. 2
      src/options.h
  8. 11
      src/plugin.c
  9. 11
      src/plugin.h
  10. 31
      src/plugin_core.c
  11. 87
      src/server.c
  12. 7
      src/server.h

47
src/connection.c

@ -2,6 +2,7 @@
#include "connection.h"
#include "network.h"
#include "utils.h"
#include "plugin_core.h"
void con_put(server *srv, connection *con); /* server.c */
@ -118,10 +119,8 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) {
ev_io_rem_events(loop, w, EV_WRITE);
break;
}
CON_TRACE(srv, con, "cq->len: raw_out=%i, out=%i", (int) con->raw_out->length, (int) con->out->length);
}
if (con->raw_out->length == 0) {
CON_TRACE(srv, con, "%s", "stop write");
ev_io_rem_events(loop, w, EV_WRITE);
dojoblist = TRUE;
}
@ -153,6 +152,8 @@ connection* connection_new(server *srv) {
action_stack_init(&con->action_stack);
con->options = g_slice_copy(srv->option_count * sizeof(*srv->option_def_values), srv->option_def_values);
request_init(&con->request, con->raw_in);
physical_init(&con->physical);
response_init(&con->response);
@ -186,6 +187,8 @@ void connection_reset(server *srv, connection *con) {
action_stack_reset(srv, &con->action_stack);
memcpy(con->options, srv->option_def_values, srv->option_count * sizeof(*srv->option_def_values));
request_reset(&con->request);
physical_reset(&con->physical);
response_reset(&con->response);
@ -207,6 +210,8 @@ void connection_reset_keep_alive(server *srv, connection *con) {
action_stack_reset(srv, &con->action_stack);
memcpy(con->options, srv->option_def_values, srv->option_count * sizeof(*srv->option_def_values));
request_reset(&con->request);
physical_reset(&con->physical);
response_reset(&con->response);
@ -238,6 +243,8 @@ void connection_free(server *srv, connection *con) {
action_stack_clear(srv, &con->action_stack);
g_slice_free1(srv->option_count * sizeof(*srv->option_def_values), con->options);
request_clear(&con->request);
physical_clear(&con->physical);
response_clear(&con->response);
@ -262,7 +269,9 @@ void connection_state_machine(server *srv, connection *con) {
action_enter(con, srv->mainaction);
break;
case CON_STATE_READ_REQUEST_HEADER:
TRACE(srv, "%s", "reading request header");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "reading request header");
}
switch(http_request_parse(srv, con, &con->request.parser_ctx)) {
case HANDLER_FINISHED:
case HANDLER_GO_ON:
@ -283,12 +292,16 @@ void connection_state_machine(server *srv, connection *con) {
}
break;
case CON_STATE_VALIDATE_REQUEST_HEADER:
TRACE(srv, "%s", "validating request header");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "validating request header");
}
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
request_validate_header(srv, con);
break;
case CON_STATE_HANDLE_REQUEST_HEADER:
TRACE(srv, "%s", "handle request header");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "handle request header");
}
switch (action_execute(srv, con)) {
case ACTION_WAIT_FOR_EVENT:
done = TRUE;
@ -307,7 +320,9 @@ void connection_state_machine(server *srv, connection *con) {
break;
case CON_STATE_READ_REQUEST_CONTENT:
case CON_STATE_HANDLE_RESPONSE_HEADER:
TRACE(srv, "%s", "read request/handle response header");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "read request/handle response header");
}
parse_request_body(srv, con);
/* TODO: call plugin content_handler */
switch (action_execute(srv, con)) {
@ -331,10 +346,14 @@ void connection_state_machine(server *srv, connection *con) {
if (!con->response_headers_sent) {
con->response_headers_sent = TRUE;
TRACE(srv, "%s", "write response headers");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "write response headers");
}
response_send_headers(srv, con);
}
TRACE(srv, "%s", "write response");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "write response");
}
parse_request_body(srv, con);
/* TODO: call plugin content_handler */
forward_response_body(srv, con);
@ -346,7 +365,9 @@ void connection_state_machine(server *srv, connection *con) {
if (con->state == CON_STATE_WRITE_RESPONSE) done = TRUE;
break;
case CON_STATE_RESPONSE_END:
TRACE(srv, "response end (keep_alive = %i)", con->keep_alive);
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "response end (keep_alive = %i)", con->keep_alive);
}
/* TODO: call plugin callbacks */
if (con->keep_alive) {
connection_reset_keep_alive(srv, con);
@ -356,13 +377,17 @@ void connection_state_machine(server *srv, connection *con) {
}
break;
case CON_STATE_CLOSE:
TRACE(srv, "%s", "connection closed");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "connection closed");
}
/* TODO: call plugin callbacks */
con_put(srv, con);
done = TRUE;
break;
case CON_STATE_ERROR:
TRACE(srv, "%s", "connection closed (error)");
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "connection closed (error)");
}
/* TODO: call plugin callbacks */
con_put(srv, con);
done = TRUE;

2
src/connection.h

@ -79,7 +79,7 @@ struct connection {
action_stack action_stack;
gpointer *options; /* TODO: options */
gpointer *options;
request request;
physical physical;

12
src/lighttpd.c

@ -53,8 +53,6 @@ int main(int argc, char *argv[]) {
srv = server_new();
log_init(srv);
plugin_register(srv, "core", plugin_core_init);
/* if no path is specified for the config, read lighttpd.conf from current directory */
@ -115,19 +113,9 @@ int main(int argc, char *argv[]) {
log_warning(srv, NULL, "test %s", "foo1"); /* duplicate won't be logged */
log_warning(srv, NULL, "test %s", "foo2");
log_debug(srv, NULL, "test %s", "message");
log_thread_start(srv);
server_start(srv);
log_error(srv, NULL, "error %d", 23);
g_atomic_int_set(&srv->rotate_logs, TRUE);
log_warning(srv, NULL, "test %s", "foo3");
log_warning(srv, NULL, "test %s", "foo4");
g_atomic_int_set(&srv->exiting, TRUE);
log_thread_wakeup(srv);
g_thread_join(srv->log_thread);
server_free(srv);
return 0;

3
src/log.h

@ -16,6 +16,9 @@ LI_API const char *remove_path(const char *path);
#define ERROR(srv, fmt, ...) \
log_write(srv, NULL, "%s.%d: (error) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)
#define INFO(srv, ...) \
log_write(srv, NULL, __VA_ARGS__)
#define TRACE(srv, fmt, ...) \
log_write(srv, NULL, "%s.%d: (trace) "fmt, REMOVE_PATH(__FILE__), __LINE__, __VA_ARGS__)

1
src/network.c

@ -49,6 +49,7 @@ network_status_t network_write(server *srv, connection *con, int fd, chunkqueue
#endif
return len ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT;
case ECONNRESET:
case EPIPE:
return NETWORK_STATUS_CONNECTION_CLOSE;
default:
CON_ERROR(srv, con, "oops, write to fd=%d failed: %s (%d)", fd, strerror(errno), errno );

3
src/options.c

@ -122,7 +122,7 @@ void option_list_free(GArray *optlist) {
g_array_free(optlist, TRUE);
}
/* Extract value from option, destroy option */
/* Extract value from option, option set to none */
gpointer option_extract_value(option *opt) {
gpointer val = NULL;
if (!opt) return NULL;
@ -153,6 +153,5 @@ gpointer option_extract_value(option *opt) {
break;
}
opt->type = OPTION_NONE;
g_slice_free(option, opt);
return val;
}

2
src/options.h

@ -62,7 +62,7 @@ LI_API const char* option_type_string(option_type type);
LI_API void option_list_free(GArray *optlist);
/* Extract value from option, destroy option */
/* Extract value from option, option set to none */
LI_API gpointer option_extract_value(option *opt);
#endif

11
src/plugin.c

@ -50,6 +50,11 @@ static void plugin_free_setups(server *srv, plugin *p) {
void plugin_free(server *srv, plugin *p) {
if (!p) return;
if (srv->state == SERVER_RUNNING) {
ERROR(srv, "Cannot free plugin '%s' while server is running", p->name);
return;
}
g_hash_table_remove(srv->plugins, p->name);
plugin_free_options(srv, p);
plugin_free_actions(srv, p);
@ -66,6 +71,11 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
return FALSE;
}
if (srv->state != SERVER_STARTING) {
ERROR(srv, "Cannot register plugin '%s' after server was started", name);
return FALSE;
}
if (g_hash_table_lookup(srv->plugins, name)) {
ERROR(srv, "Module '%s' already registered", name);
return FALSE;
@ -75,6 +85,7 @@ gboolean plugin_register(server *srv, const gchar *name, PluginInit init) {
g_hash_table_insert(srv->plugins, (gchar*) p->name, p);
init(srv, p);
p->opt_base_index = g_hash_table_size(srv->options);
if (p->options) {
size_t i;

11
src/plugin.h

@ -47,6 +47,8 @@ struct plugin {
gpointer data; /**< private plugin data */
size_t opt_base_index;
PluginFree free; /**< called before plugin is unloaded */
const plugin_option *options;
@ -110,9 +112,16 @@ LI_API void release_option(server *srv, option_set *mark); /**< Does not free th
/* Needed for config frontends */
/** For parsing 'somemod.option = "somevalue"' */
LI_API action* option_action(server *srv, const gchar *name, option *value);
/** For parsing 'somemod.action value', e.g. 'rewrite "/url" => "/destination"' */
/** For parsing 'somemod.action value', e.g. 'rewrite "/url" => "/destination"'
* You need to free the option after it (it should be of type NONE then)
*/
LI_API action* create_action(server *srv, const gchar *name, option *value);
/** For setup function, e.g. 'listen "127.0.0.1:8080"' */
LI_API gboolean call_setup(server *srv, const char *name, option *opt);
/* needs connection *con and plugin *p */
#define OPTION(idx) _OPTION(con, p, idx)
#define _OPTION(con, p, idx) (con->options[p->opt_base_index + idx])
#define _OPTION_ABS(con, idx) (con->options[idx])
#endif

31
src/plugin_core.c

@ -1,5 +1,6 @@
#include "base.h"
#include "plugin_core.h"
static action* core_list(server *srv, plugin* p, option *opt) {
action *a;
@ -63,6 +64,30 @@ static action* core_when(server *srv, plugin* p, option *opt) {
return a;
}
static action* core_set(server *srv, plugin* p, option *opt) {
option *value, *opt_name;
action *a;
UNUSED(p);
if (opt->type != OPTION_LIST) {
ERROR(srv, "expected list, got %s", option_type_string(opt->type));
return NULL;
}
if (opt->value.opt_list->len != 2) {
ERROR(srv, "expected list with length 2, has length %u", opt->value.opt_list->len);
return NULL;
}
opt_name = g_array_index(opt->value.opt_list, option*, 0);
value = g_array_index(opt->value.opt_list, option*, 1);
if (opt_name->type != OPTION_STRING) {
ERROR(srv, "expected string as first parameter, got %s", option_type_string(opt_name->type));
return NULL;
}
a = option_action(srv, opt_name->value.opt_string->str, value);
option_free(opt);
return a;
}
static action_result core_handle_static(server *srv, connection *con, gpointer param) {
UNUSED(param);
/* TODO: handle static files */
@ -154,18 +179,22 @@ static gboolean core_listen(server *srv, plugin* p, option *opt) {
}
TRACE(srv, "will listen to '%s'", opt->value.opt_string->str);
option_free(opt);
return TRUE;
}
static const plugin_option options[] = {
{ "static-file.exclude", OPTION_LIST, NULL, NULL },
{ "debug.log-request-handling", OPTION_BOOLEAN, NULL, NULL},
{ "log.level", OPTION_STRING, NULL, NULL },
{ "static-file.exclude", OPTION_LIST, NULL, NULL },
{ NULL, 0, NULL, NULL }
};
static const plugin_action actions[] = {
{ "list", core_list },
{ "when", core_when },
{ "set", core_set },
{ "static", core_static },
{ "test", core_test },
{ NULL, NULL }

87
src/server.c

@ -54,6 +54,37 @@ static void server_setup_free(gpointer _ss) {
g_slice_free(server_setup, _ss);
}
static struct ev_signal
sig_w_INT,
sig_w_TERM,
sig_w_PIPE;
static void sigint_cb(struct ev_loop *loop, struct ev_signal *w, int revents) {
server *srv = (server*) w->data;
UNUSED(revents);
if (!srv->exiting) {
INFO(srv, "Got signal, shutdown");
server_exit(srv);
} else {
INFO(srv, "Got second signal, force shutdown");
ev_unloop (loop, EVUNLOOP_ALL);
}
}
static void sigpipe_cb(struct ev_loop *loop, struct ev_signal *w, int revents) {
/* ignore */
UNUSED(loop); UNUSED(w); UNUSED(revents);
}
#define CATCH_SIGNAL(loop, cb, n) do {\
my_ev_init(&sig_w_##n, cb); \
ev_signal_set(&sig_w_##n, SIG##n); \
ev_signal_start(loop, &sig_w_##n); \
sig_w_##n.data = srv; \
ev_unref(loop); /* Signal watchers shouldn't keep loop alive */ \
} while (0)
server* server_new() {
server* srv = g_slice_new0(server);
@ -65,6 +96,10 @@ server* server_new() {
fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?");
}
CATCH_SIGNAL(srv->loop, sigint_cb, INT);
CATCH_SIGNAL(srv->loop, sigint_cb, TERM);
CATCH_SIGNAL(srv->loop, sigpipe_cb, PIPE);
srv->connections_active = 0;
srv->connections = g_array_new(FALSE, TRUE, sizeof(connection*));
srv->sockets = g_array_new(FALSE, TRUE, sizeof(server_socket*));
@ -83,6 +118,8 @@ server* server_new() {
srv->last_generated_date_ts = 0;
srv->ts_date_str = g_string_sized_new(255);
log_init(srv);
return srv;
}
@ -134,13 +171,16 @@ void server_free(server* srv) {
g_string_free(srv->ts_date_str, TRUE);
/* free logs */
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, srv->logs);
while (g_hash_table_iter_next(&iter, &k, &v)) {
log_free(srv, v);
g_thread_join(srv->log_thread);
{
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, srv->logs);
while (g_hash_table_iter_next(&iter, &k, &v)) {
log_free(srv, v);
}
g_hash_table_destroy(srv->logs);
}
g_hash_table_destroy(srv->logs);
g_mutex_free(srv->log_mutex);
g_async_queue_unref(srv->log_queue);
@ -229,28 +269,6 @@ void server_listen(server *srv, int fd) {
g_array_append_val(srv->sockets, sock);
}
static void sigint_cb(struct ev_loop *loop, struct ev_signal *w, int revents) {
UNUSED(w); UNUSED(revents);
ev_unloop (loop, EVUNLOOP_ALL);
}
static void sigpipe_cb(struct ev_loop *loop, struct ev_signal *w, int revents) {
/* ignore */
UNUSED(loop); UNUSED(w); UNUSED(revents);
}
static struct ev_signal
sig_w_INT,
sig_w_TERM,
sig_w_PIPE;
#define CATCH_SIGNAL(loop, cb, n) do {\
my_ev_init(&sig_w_##n, cb); \
ev_signal_set(&sig_w_##n, SIG##n); \
ev_signal_start(loop, &sig_w_##n); \
} while (0)
void server_start(server *srv) {
guint i;
if (srv->state == SERVER_STOPPING || srv->state == SERVER_RUNNING) return; /* no restart after stop */
@ -262,14 +280,16 @@ void server_start(server *srv) {
return;
}
/* TODO: get default values for options */
srv->option_count = g_hash_table_size(srv->options);
srv->option_def_values = g_slice_alloc0(srv->option_count * sizeof(*srv->option_def_values));
for (i = 0; i < srv->sockets->len; i++) {
server_socket *sock = g_array_index(srv->sockets, server_socket*, i);
ev_io_start(srv->loop, &sock->watcher);
}
CATCH_SIGNAL(srv->loop, sigint_cb, INT);
CATCH_SIGNAL(srv->loop, sigint_cb, TERM);
CATCH_SIGNAL(srv->loop, sigpipe_cb, PIPE);
log_thread_start(srv);
ev_loop(srv->loop, 0);
}
@ -286,7 +306,7 @@ void server_stop(server *srv) {
}
void server_exit(server *srv) {
srv->exiting = TRUE;
g_atomic_int_set(&srv->exiting, TRUE);
server_stop(srv);
{ /* force closing sockets */
@ -295,8 +315,11 @@ void server_exit(server *srv) {
server_rem_closing_socket(srv, (server_closing_socket*) iter->data);
}
}
log_thread_wakeup(srv);
}
void joblist_append(server *srv, connection *con) {
connection_state_machine(srv, con);
}

7
src/server.h

@ -39,7 +39,8 @@ struct server {
GHashTable *actions; /**< const gchar* => (server_action*) */
GHashTable *setups; /**< const gchar* => (server_setup*) */
gpointer *option_def_values; /* TODO: options */
size_t option_count; /**< set to size of option hash table */
gpointer *option_def_values;
struct action *mainaction;
gboolean exiting;
@ -65,8 +66,12 @@ LI_API void server_free(server* srv);
LI_API void server_listen(server *srv, int fd);
/* Start accepting connection, use log files, no new plugins after that */
LI_API void server_start(server *srv);
/* stop accepting connections, turn keep-alive off */
LI_API void server_stop(server *srv);
/* close connections, close logs, stop log-thread */
LI_API void server_exit(server *srv);
LI_API void joblist_append(server *srv, connection *con);

Loading…
Cancel
Save