Browse Source
* Add rolling history feature saving last 200 scanned messages.
* Add rolling history feature saving last 200 scanned messages.
Add /history command handler in webui.rspamd-0.5
10 changed files with 403 additions and 8 deletions
-
1lib/CMakeLists.txt
-
3src/main.c
-
3src/main.h
-
15src/protocol.c
-
145src/roll_history.c
-
90src/roll_history.h
-
4src/smtp_utils.c
-
7src/util.c
-
4src/util.h
-
139src/webui.c
@ -0,0 +1,145 @@ |
|||
/* Copyright (c) 2010-2012, Vsevolod Stakhov |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* * Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* * Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY |
|||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY |
|||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
|
|||
|
|||
#include "config.h" |
|||
#include "main.h" |
|||
#include "roll_history.h" |
|||
|
|||
|
|||
/** |
|||
* Returns new roll history |
|||
* @param pool pool for shared memory |
|||
* @return new structure |
|||
*/ |
|||
struct roll_history* |
|||
rspamd_roll_history_new (memory_pool_t *pool) |
|||
{ |
|||
struct roll_history *new; |
|||
|
|||
if (pool == NULL) { |
|||
return NULL; |
|||
} |
|||
|
|||
new = memory_pool_alloc0_shared (pool, sizeof (struct roll_history)); |
|||
new->pool = pool; |
|||
new->mtx = memory_pool_get_mutex (pool); |
|||
|
|||
return new; |
|||
} |
|||
|
|||
struct history_metric_callback_data { |
|||
gchar *pos; |
|||
gint remain; |
|||
}; |
|||
|
|||
static void |
|||
roll_history_symbols_callback (gpointer key, gpointer value, void *user_data) |
|||
{ |
|||
struct history_metric_callback_data *cb = user_data; |
|||
struct symbol *s = value; |
|||
guint wr; |
|||
|
|||
if (cb->remain > 0) { |
|||
wr = rspamd_snprintf (cb->pos, cb->remain, "%s, ", s->name); |
|||
cb->pos += wr; |
|||
cb->remain -= wr; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Update roll history with data from task |
|||
* @param history roll history object |
|||
* @param task task object |
|||
*/ |
|||
void |
|||
rspamd_roll_history_update (struct roll_history *history, struct worker_task *task) |
|||
{ |
|||
gint row_num; |
|||
struct roll_history_row *row; |
|||
struct metric_result *metric_res; |
|||
struct history_metric_callback_data cbdata; |
|||
|
|||
if (history->need_lock) { |
|||
/* Some process is getting history, so wait on a mutex */ |
|||
memory_pool_lock_mutex (history->mtx); |
|||
history->need_lock = FALSE; |
|||
memory_pool_unlock_mutex (history->mtx); |
|||
} |
|||
|
|||
/* First of all obtain check and obtain row number */ |
|||
g_atomic_int_compare_and_exchange (&history->cur_row, HISTORY_MAX_ROWS, 0); |
|||
#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 30)) |
|||
row_num = g_atomic_int_add (&history->cur_row, 1); |
|||
#else |
|||
row_num = g_atomic_int_exchange_and_add (&history->cur_row, 1); |
|||
#endif |
|||
|
|||
if (row_num < HISTORY_MAX_ROWS) { |
|||
row = &history->rows[row_num]; |
|||
row->completed = FALSE; |
|||
} |
|||
else { |
|||
msg_err ("internal error with history roll occured, row number is invalid: %d", row_num); |
|||
return; |
|||
} |
|||
|
|||
/* Add information from task to roll history */ |
|||
memcpy (&row->from_addr, &task->from_addr, sizeof (row->from_addr)); |
|||
memcpy (&row->tv, &task->tv, sizeof (row->tv)); |
|||
|
|||
/* Strings */ |
|||
rspamd_strlcpy (row->message_id, task->message_id, sizeof (row->message_id)); |
|||
if (task->user) { |
|||
rspamd_strlcpy (row->user, task->user, sizeof (row->message_id)); |
|||
} |
|||
else { |
|||
row->user[0] = '\0'; |
|||
} |
|||
|
|||
/* Get default metric */ |
|||
metric_res = g_hash_table_lookup (task->results, DEFAULT_METRIC); |
|||
if (metric_res == NULL) { |
|||
row->symbols[0] = '\0'; |
|||
row->action = METRIC_ACTION_NOACTION; |
|||
} |
|||
else { |
|||
row->score = metric_res->score; |
|||
row->required_score = metric_res->metric->required_score; |
|||
row->action = check_metric_action (metric_res->score, metric_res->metric->required_score, metric_res->metric); |
|||
cbdata.pos = row->symbols; |
|||
cbdata.remain = sizeof (row->symbols); |
|||
g_hash_table_foreach (metric_res->symbols, roll_history_symbols_callback, &cbdata); |
|||
if (cbdata.remain > 0) { |
|||
/* Remove last whitespace and comma */ |
|||
*cbdata.pos-- = '\0'; |
|||
*cbdata.pos-- = '\0'; |
|||
*cbdata.pos = '\0'; |
|||
} |
|||
} |
|||
|
|||
row->scan_time = task->scan_milliseconds; |
|||
row->len = task->msg->len; |
|||
row->completed = TRUE; |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
/* Copyright (c) 2010-2012, Vsevolod Stakhov |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions are met: |
|||
* * Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* * Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY |
|||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY |
|||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
|
|||
#ifndef ROLL_HISTORY_H_ |
|||
#define ROLL_HISTORY_H_ |
|||
|
|||
#include "config.h" |
|||
#include "mem_pool.h" |
|||
|
|||
/* |
|||
* Roll history is a special cycled buffer for checked messages, it is designed for writing history messages |
|||
* and displaying them in webui |
|||
*/ |
|||
|
|||
#define HISTORY_MAX_ID 100 |
|||
#define HISTORY_MAX_SYMBOLS 200 |
|||
#define HISTORY_MAX_USER 20 |
|||
#define HISTORY_MAX_ROWS 200 |
|||
|
|||
struct worker_task; |
|||
|
|||
struct roll_history_row { |
|||
struct timeval tv; |
|||
gchar message_id[HISTORY_MAX_ID]; |
|||
gchar symbols[HISTORY_MAX_SYMBOLS]; |
|||
gchar user[HISTORY_MAX_USER]; |
|||
#ifdef HAVE_INET_PTON |
|||
struct { |
|||
union { |
|||
struct in_addr in4; |
|||
struct in6_addr in6; |
|||
} d; |
|||
gboolean ipv6; |
|||
gboolean has_addr; |
|||
} from_addr; |
|||
#else |
|||
struct in_addr from_addr; |
|||
#endif |
|||
gsize len; |
|||
guint scan_time; |
|||
gint action; |
|||
gdouble score; |
|||
gdouble required_score; |
|||
guint8 completed; |
|||
}; |
|||
|
|||
struct roll_history { |
|||
struct roll_history_row rows[HISTORY_MAX_ROWS]; |
|||
gint cur_row; |
|||
memory_pool_t *pool; |
|||
gboolean need_lock; |
|||
memory_pool_mutex_t *mtx; |
|||
}; |
|||
|
|||
/** |
|||
* Returns new roll history |
|||
* @param pool pool for shared memory |
|||
* @return new structure |
|||
*/ |
|||
struct roll_history* rspamd_roll_history_new (memory_pool_t *pool); |
|||
|
|||
/** |
|||
* Update roll history with data from task |
|||
* @param history roll history object |
|||
* @param task task object |
|||
*/ |
|||
void rspamd_roll_history_update (struct roll_history *history, struct worker_task *task); |
|||
|
|||
#endif /* ROLL_HISTORY_H_ */ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue