From 2f97a5cc06027be61ac7a4ac9a02939de855ae3e Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 28 Feb 2014 14:48:45 +0000 Subject: [PATCH] Rework HTTP router. --- src/http.c | 5 +++ src/http.h | 8 +++- src/webui.c | 110 +++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/src/http.c b/src/http.c index 3ff0c84c6..e64f8a2e9 100644 --- a/src/http.c +++ b/src/http.c @@ -905,6 +905,9 @@ rspamd_http_entry_free (struct rspamd_http_connection_entry *entry) close (entry->conn->fd); rspamd_http_connection_unref (entry->conn); g_slice_free1 (sizeof (struct rspamd_http_connection_entry), entry); + if (entry->rt->finish_handler) { + entry->rt->finish_handler (entry); + } } } @@ -985,6 +988,7 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_connection_router* rspamd_http_router_new (rspamd_http_router_error_handler_t eh, + rspamd_http_router_finish_handler_t fh, struct timeval *timeout, struct event_base *base) { struct rspamd_http_connection_router* new; @@ -993,6 +997,7 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh, new->paths = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); new->conns = NULL; new->error_handler = eh; + new->finish_handler = fh; new->ev_base = base; if (timeout) { new->tv = *timeout; diff --git a/src/http.h b/src/http.h index 0c2c036f3..ffa2ecca2 100644 --- a/src/http.h +++ b/src/http.h @@ -86,7 +86,9 @@ typedef int (*rspamd_http_finish_handler_t) (struct rspamd_http_connection *conn typedef int (*rspamd_http_router_handler_t) (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg); -typedef void (*rspamd_http_router_error_handler_t) (struct rspamd_http_connection_entry *conn_ent, GError *err); +typedef void (*rspamd_http_router_error_handler_t) (struct rspamd_http_connection_entry *conn_ent, + GError *err); +typedef void (*rspamd_http_router_finish_handler_t) (struct rspamd_http_connection_entry *conn_ent); /** * HTTP connection structure @@ -118,6 +120,7 @@ struct rspamd_http_connection_router { struct timeval *ptv; struct event_base *ev_base; rspamd_http_router_error_handler_t error_handler; + rspamd_http_router_finish_handler_t finish_handler; }; /** @@ -237,10 +240,13 @@ time_t rspamd_http_parse_date (const gchar *header, gsize len); /** * Create new http connection router and the associated HTTP connection + * @param eh error handler callback + * @param fh finish handler callback * @return */ struct rspamd_http_connection_router* rspamd_http_router_new ( rspamd_http_router_error_handler_t eh, + rspamd_http_router_finish_handler_t fh, struct timeval *timeout, struct event_base *base); diff --git a/src/webui.c b/src/webui.c index b2495ef7c..a6af7728f 100644 --- a/src/webui.c +++ b/src/webui.c @@ -111,6 +111,20 @@ struct rspamd_webui_worker_ctx { struct rspamd_worker *worker; }; +struct rspamd_webui_session { + struct rspamd_webui_worker_ctx *ctx; + memory_pool_t *pool; + struct worker_task *task; + struct { + union { + struct in_addr in4; + struct in6_addr in6; + } d; + gboolean ipv6; + gboolean has_addr; + } from_addr; +}; + static sig_atomic_t wanna_die = 0; /* Signal handlers */ @@ -630,25 +644,25 @@ static int rspamd_webui_handle_auth (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; struct rspamd_stat *st; int64_t uptime; gulong data[4]; ucl_object_t *obj; - if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { return 0; } obj = ucl_object_typed_new (UCL_OBJECT); - st = ctx->srv->stat; + st = session->ctx->srv->stat; data[0] = st->actions_stat[METRIC_ACTION_NOACTION]; data[1] = st->actions_stat[METRIC_ACTION_ADD_HEADER] + st->actions_stat[METRIC_ACTION_REWRITE_SUBJECT]; data[2] = st->actions_stat[METRIC_ACTION_GREYLIST]; data[3] = st->actions_stat[METRIC_ACTION_REJECT]; /* Get uptime */ - uptime = time (NULL) - ctx->start_time; + uptime = time (NULL) - session->ctx->start_time; obj = ucl_object_insert_key (obj, ucl_object_fromstring (RVERSION), "version", 0, false); obj = ucl_object_insert_key (obj, ucl_object_fromstring ("ok"), "auth", 0, false); @@ -685,20 +699,20 @@ static int rspamd_webui_handle_symbols (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; GList *cur_gr, *cur_sym; struct symbols_group *gr; struct symbol_def *sym; ucl_object_t *obj, *top, *sym_obj; - if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { return 0; } top = ucl_object_typed_new (UCL_ARRAY); /* Go through all symbols groups */ - cur_gr = ctx->cfg->symbols_groups; + cur_gr = session->ctx->cfg->symbols_groups; while (cur_gr) { gr = cur_gr->data; obj = ucl_object_typed_new (UCL_OBJECT); @@ -744,20 +758,20 @@ static int rspamd_webui_handle_actions (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; struct metric *metric; struct metric_action *act; gint i; ucl_object_t *obj, *top; - if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { return 0; } top = ucl_object_typed_new (UCL_ARRAY); /* Get actions for default metric */ - metric = g_hash_table_lookup (ctx->cfg->metrics, DEFAULT_METRIC); + metric = g_hash_table_lookup (session->ctx->cfg->metrics, DEFAULT_METRIC); if (metric != NULL) { for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { act = &metric->actions[i]; @@ -793,20 +807,20 @@ static int rspamd_webui_handle_maps (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; GList *cur, *tmp = NULL; struct rspamd_map *map; gboolean editable; ucl_object_t *obj, *top; - if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { return 0; } top = ucl_object_typed_new (UCL_ARRAY); /* Iterate over all maps */ - cur = ctx->cfg->maps; + cur = session->ctx->cfg->maps; while (cur) { map = cur->data; if (map->protocol == MAP_PROTO_FILE && map->description != NULL) { @@ -854,7 +868,7 @@ static int rspamd_webui_handle_get_map (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; GList *cur; struct rspamd_map *map; const gchar *idstr; @@ -866,7 +880,7 @@ rspamd_webui_handle_get_map (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *reply; - if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { return 0; } @@ -887,7 +901,7 @@ rspamd_webui_handle_get_map (struct rspamd_http_connection_entry *conn_ent, } /* Now let's be sure that we have map defined in configuration */ - cur = ctx->cfg->maps; + cur = session->ctx->cfg->maps; while (cur) { map = cur->data; if (map->id == id && map->protocol == MAP_PROTO_FILE) { @@ -1051,10 +1065,13 @@ static int rspamd_webui_handle_pie_chart (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; + struct rspamd_webui_worker_ctx *ctx; gdouble data[4], total; ucl_object_t *top, *obj; + ctx = session->ctx; + if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { return 0; } @@ -1111,7 +1128,8 @@ static int rspamd_webui_handle_history (struct rspamd_http_connection_entry *conn_ent, struct rspamd_http_message *msg) { - struct rspamd_webui_worker_ctx *ctx = conn_ent->ud; + struct rspamd_webui_session *session = conn_ent->ud; + struct rspamd_webui_worker_ctx *ctx; struct roll_history_row *row; struct roll_history copied_history; gint i, rows_proc, row_num; @@ -1120,6 +1138,8 @@ rspamd_webui_handle_history (struct rspamd_http_connection_entry *conn_ent, gchar ip_buf[INET6_ADDRSTRLEN]; ucl_object_t *top, *obj; + ctx = session->ctx; + if (!rspamd_webui_check_password (conn_ent, ctx, msg)) { return 0; } @@ -1178,6 +1198,28 @@ rspamd_webui_handle_history (struct rspamd_http_connection_entry *conn_ent, return 0; } + +static int +rspamd_webui_handle_learnspam (struct rspamd_http_connection_entry *conn_ent, + struct rspamd_http_message *msg) +{ + struct rspamd_webui_session *session = conn_ent->ud; + + if (!rspamd_webui_check_password (conn_ent, session->ctx, msg)) { + return 0; + } + + if (msg->body->len == 0) { + msg_err ("got zero length body, cannot continue"); + rspamd_webui_send_error (conn_ent, 400, "Empty body is not permitted"); + return 0; + } + + session->task = construct_task (session->ctx->worker); + session->task->ev_base = session->ctx->ev_base; + + return 0; +} #if 0 /* * Learn spam command handler: @@ -1610,11 +1652,24 @@ rspamd_webui_error_handler (struct rspamd_http_connection_entry *conn_ent, GErro msg_err ("http error occurred: %s", err->message); } +static void +rspamd_webui_finish_handler (struct rspamd_http_connection_entry *conn_ent) +{ + struct rspamd_webui_session *session = conn_ent->ud; + + if (session->pool) { + memory_pool_delete (session->pool); + } + + g_slice_free1 (sizeof (struct rspamd_webui_session), session); +} + static void rspamd_webui_accept_socket (gint fd, short what, void *arg) { struct rspamd_worker *worker = (struct rspamd_worker *) arg; struct rspamd_webui_worker_ctx *ctx; + struct rspamd_webui_session *nsession; gint nfd; union sa_union su; socklen_t addrlen = sizeof (su); @@ -1632,20 +1687,31 @@ rspamd_webui_accept_socket (gint fd, short what, void *arg) return; } + nsession = g_slice_alloc0 (sizeof (struct rspamd_webui_session)); + nsession->pool = memory_pool_new (memory_pool_get_size ()); + nsession->ctx = ctx; + if (su.sa.sa_family == AF_UNIX) { msg_info ("accepted connection from unix socket"); + nsession->from_addr.has_addr = FALSE; } else if (su.sa.sa_family == AF_INET) { msg_info ("accepted connection from %s port %d", inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port)); + nsession->from_addr.has_addr = TRUE; + nsession->from_addr.d.in4.s_addr = su.s4.sin_addr.s_addr; } else if (su.sa.sa_family == AF_INET6) { msg_info ("accepted connection from %s port %d", inet_ntop (su.sa.sa_family, &su.s6.sin6_addr, ip_str, sizeof (ip_str)), ntohs (su.s6.sin6_port)); + memcpy (&nsession->from_addr.d.in6, &su.s6.sin6_addr, + sizeof (struct in6_addr)); + nsession->from_addr.has_addr = TRUE; + nsession->from_addr.ipv6 = TRUE; } - rspamd_http_router_handle_socket (ctx->http, nfd, ctx); + rspamd_http_router_handle_socket (ctx->http, nfd, nsession); } gpointer @@ -1709,7 +1775,8 @@ start_webui_worker (struct rspamd_worker *worker) ctx->srv = worker->srv; /* Accept event */ - ctx->http = rspamd_http_router_new (rspamd_webui_error_handler, &ctx->io_tv, ctx->ev_base); + ctx->http = rspamd_http_router_new (rspamd_webui_error_handler, + rspamd_webui_finish_handler, &ctx->io_tv, ctx->ev_base); /* Add callbacks for different methods */ rspamd_http_router_add_path (ctx->http, PATH_AUTH, rspamd_webui_handle_auth); @@ -1719,10 +1786,9 @@ start_webui_worker (struct rspamd_worker *worker) rspamd_http_router_add_path (ctx->http, PATH_GET_MAP, rspamd_webui_handle_get_map); rspamd_http_router_add_path (ctx->http, PATH_PIE_CHART, rspamd_webui_handle_pie_chart); rspamd_http_router_add_path (ctx->http, PATH_HISTORY, rspamd_webui_handle_history); + rspamd_http_router_add_path (ctx->http, PATH_LEARN_SPAM, rspamd_webui_handle_learnspam); #if 0 rspamd_http_router_add_path (ctx->http, PATH_GRAPH, rspamd_webui_handle_graph, ctx); - - rspamd_http_router_add_path (ctx->http, PATH_LEARN_SPAM, rspamd_webui_handle_learn_spam, ctx); rspamd_http_router_add_path (ctx->http, PATH_LEARN_HAM, rspamd_webui_handle_learn_ham, ctx); rspamd_http_router_add_path (ctx->http, PATH_SAVE_ACTIONS, rspamd_webui_handle_save_actions, ctx); rspamd_http_router_add_path (ctx->http, PATH_SAVE_SYMBOLS, rspamd_webui_handle_save_symbols, ctx); -- 2.39.5