Added plugin callbacks for content and close handling
parent
6d6fc095ab
commit
066d0f5342
|
@ -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
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
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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…
Reference in New Issue