From 81227d766b6cd49042c042ac18c66bd9ec661d47 Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Mon, 13 Oct 2008 21:36:35 +0200 Subject: [PATCH] Add counters to the context. This counters allow to keep a state for the filter of a message. Signed-off-by: Florent Bruneau --- postlicyd/filter.c | 39 ++++++++++++++++++++++++++++++++++++++ postlicyd/filter.h | 18 ++++++++++++++++++ postlicyd/main-postlicyd.c | 15 +++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/postlicyd/filter.c b/postlicyd/filter.c index d145f42..14bfc9b 100644 --- a/postlicyd/filter.c +++ b/postlicyd/filter.c @@ -50,6 +50,8 @@ static filter_async_handler_t async_handler = NULL; static const filter_hook_t default_hook = { .type = 0, .value = (char*)"DUNNO", + .counter = -1, + .cost = 0, .postfix = true, .async = false, .filter_id = 0 @@ -58,6 +60,8 @@ static const filter_hook_t default_hook = { static const filter_hook_t async_hook = { .type = 0, .value = NULL, + .counter = -1, + .cost = 0, .postfix = false, .async = true, .filter_id = 0 @@ -288,6 +292,35 @@ bool filter_add_hook(filter_t *filter, const char *name, int name_len, return false; } hook.async = false; + + /* Value format is (counter:id:incr)?(postfix:reply|filter_name) + */ + if (strncmp(value, "counter:", 8) == 0) { + char *end = NULL; + value += 8; + hook.counter = strtol(value, &end, 10); + if (end == value || *end != ':') { + err("hook %s, cannot read counter id", htokens[hook.type]); + return false; + } else if (hook.counter < 0 || hook.counter >= MAX_COUNTERS) { + err("hook %s, invalid counter id %d", htokens[hook.type], hook.counter); + return false; + } + value = end + 1; + hook.cost = strtol(value, &end, 10); + if (end == value || *end != ':') { + err("hook %s, cannot read counter increment", htokens[hook.type]); + return false; + } else if (hook.cost < 0) { + err("hook %s, invalid counter increment value %d", htokens[hook.type], + hook.cost); + return false; + } + value = end + 1; + } else { + hook.counter = -1; + hook.cost = 0; + } hook.postfix = (strncmp(value, "postfix:", 8) == 0); if (hook.postfix && query_format(NULL, 0, value + 8, NULL) == -1) { err("invalid formatted text \"%s\"", value + 8); @@ -319,6 +352,12 @@ void filter_context_wipe(filter_context_t *context) } } +void filter_context_clean(filter_context_t *context) +{ + p_clear(&context->counters, 1); + context->instance[0] = '\0'; +} + void filter_post_async_result(filter_context_t *context, filter_result_t result) { const filter_t *filter = context->current_filter; diff --git a/postlicyd/filter.h b/postlicyd/filter.h index dcbaecb..c2c7a4f 100644 --- a/postlicyd/filter.h +++ b/postlicyd/filter.h @@ -52,9 +52,13 @@ typedef struct filter_hook_t { filter_result_t type; char *value; + int counter; + int cost; + unsigned postfix:1; unsigned async:1; int filter_id; + } filter_hook_t; ARRAY(filter_hook_t) @@ -82,13 +86,24 @@ typedef struct filter_t { } filter_t; ARRAY(filter_t) +#define MAX_COUNTERS (64) + /** Context of the query. To be filled with data to use when * performing asynchronous filtering. */ typedef struct filter_context_t { + /* filter context + */ const filter_t *current_filter; void *contexts[FTK_count]; + /* message context + */ + char instance[64]; + uint32_t counters[MAX_COUNTERS]; + + /* connection context + */ void *data; } filter_context_t; @@ -273,6 +288,9 @@ void filter_context_prepare(filter_context_t *context, void* qctx); __attribute__((nonnull)) void filter_context_wipe(filter_context_t *context); +__attribute__((nonnull)) +void filter_context_clean(filter_context_t *context); + __attribute__((nonnull)) void filter_post_async_result(filter_context_t *context, filter_result_t result); diff --git a/postlicyd/main-postlicyd.c b/postlicyd/main-postlicyd.c index fa31a1e..bf68941 100644 --- a/postlicyd/main-postlicyd.c +++ b/postlicyd/main-postlicyd.c @@ -110,6 +110,17 @@ static void policy_answer(server_t *pcy, const char *message) static const filter_t *next_filter(server_t *pcy, const filter_t *filter, const query_t *query, const filter_hook_t *hook, bool *ok) { + if (hook != NULL) { + query_context_t *context = pcy->data; + if (hook->counter >= 0 && hook->counter < MAX_COUNTERS && hook->cost > 0) { + context->context.counters[hook->counter] += hook->cost; + debug("request client=%s, from=<%s>, to=<%s>: added %d to counter %d (now %u)", + query->client_name, + query->sender == NULL ? "undefined" : query->sender, + query->recipient == NULL ? "undefined" : query->recipient, + hook->cost, hook->counter, context->context.counters[hook->counter]); + } + } if (hook == NULL) { warn("request client=%s, from=<%s>, to=<%s>: aborted", query->client_name, @@ -205,6 +216,10 @@ static int policy_run(server_t *pcy, void* vconfig) if (!query_parse(pcy->data, pcy->ibuf.data)) return -1; query->eoq = eoq + strlen("\n\n"); + if (query->instance == NULL || strcmp(context->context.instance, query->instance) != 0) { + filter_context_clean(&context->context); + m_strcat(context->context.instance, 64, query->instance); + } epoll_modify(pcy->fd, 0, pcy); return policy_process(pcy, mconfig) ? 0 : -1; } -- 2.20.1