Browse Source

Added plugin callbacks for content and close handling

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent
commit
066d0f5342
  1. 43
      src/connection.c
  2. 20
      src/plugin.c
  3. 24
      src/plugin.h
  4. 6
      src/server.c
  5. 2
      src/server.h

43
src/connection.c

@ -268,6 +268,7 @@ void connection_state_machine(server *srv, connection *con) {
connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER);
action_enter(con, srv->mainaction);
break;
case CON_STATE_READ_REQUEST_HEADER:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "reading request header");
@ -291,6 +292,7 @@ void connection_state_machine(server *srv, connection *con) {
break;
}
break;
case CON_STATE_VALIDATE_REQUEST_HEADER:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "validating request header");
@ -298,6 +300,7 @@ void connection_state_machine(server *srv, connection *con) {
connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST_HEADER);
request_validate_header(srv, con);
break;
case CON_STATE_HANDLE_REQUEST_HEADER:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "handle request header");
@ -318,6 +321,7 @@ void connection_state_machine(server *srv, connection *con) {
break;
}
break;
case CON_STATE_READ_REQUEST_CONTENT:
case CON_STATE_HANDLE_RESPONSE_HEADER:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
@ -332,7 +336,10 @@ void connection_state_machine(server *srv, connection *con) {
ev_io_add_events(srv->loop, &con->sock.watcher, EV_WRITE);
}
parse_request_body(srv, con);
/* TODO: call plugin content_handler */
if (con->content_handler)
con->content_handler->handle_content(srv, con, con->content_handler);
switch (action_execute(srv, con)) {
case ACTION_WAIT_FOR_EVENT:
done = TRUE;
@ -346,6 +353,7 @@ void connection_state_machine(server *srv, connection *con) {
break;
}
break;
case CON_STATE_WRITE_RESPONSE:
if (con->in->is_closed && con->raw_out->is_closed) {
connection_set_state(srv, con, CON_STATE_RESPONSE_END);
@ -359,11 +367,16 @@ void connection_state_machine(server *srv, connection *con) {
}
response_send_headers(srv, con);
}
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "write response");
}
parse_request_body(srv, con);
/* TODO: call plugin content_handler */
if (con->content_handler)
con->content_handler->handle_content(srv, con, con->content_handler);
forward_response_body(srv, con);
if (con->in->is_closed && con->raw_out->is_closed) {
@ -372,11 +385,14 @@ void connection_state_machine(server *srv, connection *con) {
}
if (con->state == CON_STATE_WRITE_RESPONSE) done = TRUE;
break;
case CON_STATE_RESPONSE_END:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "response end (keep_alive = %i)", con->keep_alive);
}
/* TODO: call plugin callbacks */
plugins_handle_close(srv, con);
if (con->keep_alive) {
connection_reset_keep_alive(srv, con);
} else {
@ -384,19 +400,25 @@ void connection_state_machine(server *srv, connection *con) {
done = TRUE;
}
break;
case CON_STATE_CLOSE:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "connection closed");
}
/* TODO: call plugin callbacks */
plugins_handle_close(srv, con);
con_put(srv, con);
done = TRUE;
break;
case CON_STATE_ERROR:
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING)) {
TRACE(srv, "%s", "connection closed (error)");
}
/* TODO: call plugin callbacks */
plugins_handle_close(srv, con);
con_put(srv, con);
done = TRUE;
break;
@ -410,6 +432,13 @@ void connection_handle_direct(server *srv, connection *con) {
}
void connection_handle_indirect(server *srv, connection *con, plugin *p) {
connection_set_state(srv, con, CON_STATE_READ_REQUEST_CONTENT);
con->content_handler = p;
if (!p) {
connection_handle_direct(srv, con);
} else if (p->handle_content) {
connection_set_state(srv, con, CON_STATE_READ_REQUEST_CONTENT);
con->content_handler = p;
} else {
CON_ERROR(srv, con, "Indirect plugin '%s' handler has no handle_content callback", p->name);
internal_error(srv, con);
}
}

20
src/plugin.c

@ -270,3 +270,23 @@ gboolean call_setup(server *srv, const char *name, option *opt) {
return TRUE;
}
void plugins_prepare_callbacks(server *srv) {
GHashTableIter iter;
plugin *p;
g_hash_table_iter_init(&iter, srv->plugins);
while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &p)) {
if (p->handle_close)
g_array_append_val(srv->plugins_handle_close, p);
}
}
void plugins_handle_close(server *srv, connection *con) {
GArray *a = srv->plugins_handle_close;
guint i, len = a->len;
for (i = 0; i < len; i++) {
plugin *p = g_array_index(a, plugin*, i);
p->handle_close(srv, con, p);
}
}

24
src/plugin.h

@ -41,15 +41,31 @@ typedef void (*PluginFreeOption) (server *srv, plugin *p, size_t ndx, gpo
typedef action* (*PluginCreateAction) (server *srv, plugin *p, option *opt);
typedef gboolean (*PluginSetup) (server *srv, plugin *p, option *opt);
typedef void (*PluginHandleContent) (server *srv, connection *con, plugin *p);
typedef void (*PluginHandleClose) (server *srv, connection *con, plugin *p);
struct plugin {
size_t version;
const gchar *name; /**< name of the plugin */
gpointer data; /**< private plugin data */
gpointer data; /**< private plugin data */
size_t opt_base_index;
PluginFree free; /**< called before plugin is unloaded */
PluginFree free; /**< called before plugin is unloaded */
/** called if plugin registered as indirect handler with connection_handle_indirect(srv, con, p)
* - after response headers are created:
* connection_set_state(srv, con, CON_STATE_HANDLE_RESPONSE_HEADER)
* - after content is generated close output queue:
* con->out->is_closed = TRUE
*/
PluginHandleContent handle_content;
/** called for every plugin after connection got closed (response end, reset by peer, error)
* the plugins code must not depend on any order of plugins loaded
*/
PluginHandleClose handle_close;
const plugin_option *options;
const plugin_action *actions;
@ -104,11 +120,15 @@ struct server_setup {
/* Needed my modules to register their plugin(s) */
LI_API gboolean plugin_register(server *srv, const gchar *name, PluginInit init);
/* Internal needed functions */
LI_API void plugin_free(server *srv, plugin *p);
LI_API gboolean parse_option(server *srv, const char *name, option *opt, option_set *mark);
LI_API void release_option(server *srv, option_set *mark); /**< Does not free the option_set memory */
LI_API void plugins_prepare_callbacks(server *srv);
LI_API void plugins_handle_close(server *srv, connection *con);
/* Needed for config frontends */
/** For parsing 'somemod.option = "somevalue"' */
LI_API action* option_action(server *srv, const gchar *name, option *value);

6
src/server.c

@ -110,6 +110,8 @@ server* server_new() {
srv->actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_action_free);
srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free);
srv->plugins_handle_close = g_array_new(FALSE, TRUE, sizeof(plugin*));
srv->mainaction = NULL;
srv->exiting = FALSE;
@ -165,6 +167,8 @@ void server_free(server* srv) {
g_hash_table_destroy(srv->actions);
g_hash_table_destroy(srv->setups);
g_array_free(srv->plugins_handle_close, TRUE);
action_release(srv, srv->mainaction);
g_string_free(srv->tmp_str, TRUE);
@ -284,6 +288,8 @@ void server_start(server *srv) {
srv->option_count = g_hash_table_size(srv->options);
srv->option_def_values = g_slice_alloc0(srv->option_count * sizeof(*srv->option_def_values));
plugins_prepare_callbacks(srv);
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);

2
src/server.h

@ -39,6 +39,8 @@ struct server {
GHashTable *actions; /**< const gchar* => (server_action*) */
GHashTable *setups; /**< const gchar* => (server_setup*) */
GArray *plugins_handle_close; /** list of handle_close callbacks */
size_t option_count; /**< set to size of option hash table */
gpointer *option_def_values;
struct action *mainaction;

Loading…
Cancel
Save