diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-01-18 18:20:54 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2014-01-18 18:20:54 +0000 |
commit | e2f2eed337ecdb17c897fe7e04626dfffe32f2a2 (patch) | |
tree | 25f39a0aef9ed9eacc117407cc3824b16acccb9c /src/protocol.c | |
parent | f5933d697d2cd9854afcbc7421efda353e165aea (diff) | |
download | rspamd-e2f2eed337ecdb17c897fe7e04626dfffe32f2a2.tar.gz rspamd-e2f2eed337ecdb17c897fe7e04626dfffe32f2a2.zip |
Parse HTTP requests, cleanup the code.
--HG--
extra : rebase_source : 6b35fbf55fc9fe65d7f033620670bb210928e9b4
Diffstat (limited to 'src/protocol.c')
-rw-r--r-- | src/protocol.c | 659 |
1 files changed, 198 insertions, 461 deletions
diff --git a/src/protocol.c b/src/protocol.c index 02ba94e39..3351a5195 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -97,161 +97,109 @@ static GList *custom_commands = NULL; -/* XXX: remove this legacy sometimes */ -static const gchar * -str_action_metric_spamc (enum rspamd_metric_action action) -{ - switch (action) { - case METRIC_ACTION_REJECT: - return "reject"; - case METRIC_ACTION_SOFT_REJECT: - return "soft reject"; - case METRIC_ACTION_REWRITE_SUBJECT: - return "rewrite subject"; - case METRIC_ACTION_ADD_HEADER: - return "add header"; - case METRIC_ACTION_GREYLIST: - return "greylist"; - case METRIC_ACTION_NOACTION: - return "no action"; - case METRIC_ACTION_MAX: - return "invalid max action"; - } - return "unknown action"; -} - -static inline const gchar * -rspamc_proto_str (guint ver) +/* + * Remove <> from the fixed string and copy it to the pool + */ +static gchar * +rspamd_protocol_escape_braces (GString *in) { + gint len = 0; + gchar *orig, *p; - if (G_LIKELY (ver == 12)) { - return "1.2"; + orig = in->str; + while ((g_ascii_isspace (*orig) || *orig == '<') && orig - in->str < (gint)in->len) { + orig ++; } - else if (G_UNLIKELY (ver == 11)) { - return "1.1"; - } - else if (G_UNLIKELY (ver == 13)) { - return "1.3"; - } - else if (G_UNLIKELY (ver == 14)) { - return "1.4"; - } - else if (G_UNLIKELY (ver == 15)) { - return "1.5"; - } - else { - return "1.0"; - } -} -gchar * -separate_command (f_str_t * in, gchar c) -{ - guint r = 0; - gchar *p = in->begin, *b; - b = p; + g_string_erase (in, 0, orig - in->str); - while (r < in->len) { - if (*p == c) { - *p = '\0'; - in->begin = p + 1; - in->len -= r + 1; - return b; - } - else if (*p == '\0') { - /* Actually we cannot allow several \0 characters in string, so write to the log about it */ - msg_warn ("cannot separate command with \0 character, this can be an attack attempt"); - return NULL; - } - p++; - r++; + p = orig; + while ((!g_ascii_isspace (*p) && *p != '>') && p - in->str < (gint)in->len) { + p ++; + len ++; } - return NULL; + g_string_truncate (in, len); + + return in->str; } static gboolean -parse_check_command (struct worker_task *task, gchar *token) +rspamd_protocol_handle_url (struct worker_task *task, struct rspamd_http_message *msg) { GList *cur; struct custom_command *cmd; + const gchar *p; + + if (msg->url == NULL || msg->url->len == 0) { + task->last_error = "command is absent"; + task->error_code = 400; + return FALSE; + } + + if (msg->url->str[0] == '/') { + p = &msg->url->str[1]; + } + else { + p = msg->url->str; + } - switch (token[0]) { + switch (*p) { case 'c': case 'C': /* check */ - if (g_ascii_strcasecmp (token + 1, MSG_CMD_CHECK + 1) == 0) { + if (g_ascii_strcasecmp (p + 1, MSG_CMD_CHECK + 1) == 0) { task->cmd = CMD_CHECK; } else { - debug_task ("bad command: %s", token); - return FALSE; + goto err; } break; case 's': case 'S': /* symbols, skip */ - if (g_ascii_strcasecmp (token + 1, MSG_CMD_SYMBOLS + 1) == 0) { + if (g_ascii_strcasecmp (p + 1, MSG_CMD_SYMBOLS + 1) == 0) { task->cmd = CMD_SYMBOLS; } - else if (g_ascii_strcasecmp (token + 1, MSG_CMD_SKIP + 1) == 0) { + else if (g_ascii_strcasecmp (p + 1, MSG_CMD_SKIP + 1) == 0) { task->cmd = CMD_SKIP; } else { - debug_task ("bad command: %s", token); - return FALSE; + goto err; } break; case 'p': case 'P': /* ping, process */ - if (g_ascii_strcasecmp (token + 1, MSG_CMD_PING + 1) == 0) { + if (g_ascii_strcasecmp (p + 1, MSG_CMD_PING + 1) == 0) { task->cmd = CMD_PING; } - else if (g_ascii_strcasecmp (token + 1, MSG_CMD_PROCESS + 1) == 0) { + else if (g_ascii_strcasecmp (p + 1, MSG_CMD_PROCESS + 1) == 0) { task->cmd = CMD_PROCESS; } else { - debug_task ("bad command: %s", token); - return FALSE; + goto err; } break; case 'r': case 'R': /* report, report_ifspam */ - if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT + 1) == 0) { + if (g_ascii_strcasecmp (p + 1, MSG_CMD_REPORT + 1) == 0) { task->cmd = CMD_REPORT; } - else if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) { + else if (g_ascii_strcasecmp (p + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) { task->cmd = CMD_REPORT_IFSPAM; } else { - debug_task ("bad command: %s", token); - return FALSE; - } - break; - case 'l': - case 'L': - if (g_ascii_strcasecmp (token + 1, MSG_CMD_LEARN + 1) == 0) { - if (task->allow_learn) { - task->cmd = CMD_LEARN; - } - else { - msg_info ("learning is disabled"); - return FALSE; - } - } - else { - debug_task ("bad command: %s", token); - return FALSE; + goto err; } break; default: cur = custom_commands; while (cur) { cmd = cur->data; - if (g_ascii_strcasecmp (token, cmd->name) == 0) { + if (g_ascii_strcasecmp (p, cmd->name) == 0) { task->cmd = CMD_OTHER; task->custom_cmd = cmd; break; @@ -260,402 +208,191 @@ parse_check_command (struct worker_task *task, gchar *token) } if (cur == NULL) { - debug_task ("bad command: %s", token); - return FALSE; + goto err; } break; } return TRUE; + +err: + debug_task ("bad command: %s", p); + task->last_error = "invalid command"; + task->error_code = 400; + return FALSE; } static gboolean -parse_rspamc_command (struct worker_task *task, f_str_t * line) +rspamd_protocol_handle_headers (struct worker_task *task, struct rspamd_http_message *msg) { - gchar *token; + gchar *headern, *err, *tmp; + gboolean res = TRUE; + struct rspamd_http_header *h; - /* Separate line */ - token = separate_command (line, ' '); - if (line == NULL || token == NULL) { - debug_task ("bad command"); - return FALSE; - } + LL_FOREACH (msg->headers, h) { + headern = h->name->str; - if (!parse_check_command (task, token)) { - return FALSE; - } - - if (g_ascii_strncasecmp (line->begin, RSPAMC_GREETING, sizeof (RSPAMC_GREETING) - 1) == 0) { - task->proto = RSPAMC_PROTO; - task->proto_ver = 10; - if (*(line->begin + sizeof (RSPAMC_GREETING) - 1) == '/') { - /* Extract protocol version */ - token = line->begin + sizeof (RSPAMC_GREETING); - if (strncmp (token, RSPAMC_PROTO_1_1, sizeof (RSPAMC_PROTO_1_1) - 1) == 0) { - task->proto_ver = 11; + switch (headern[0]) { + case 'd': + case 'D': + if (g_ascii_strcasecmp (headern, DELIVER_TO_HEADER) == 0) { + task->deliver_to = rspamd_protocol_escape_braces (h->value); + debug_task ("read deliver-to header, value: %s", task->deliver_to); } - else if (strncmp (token, RSPAMC_PROTO_1_2, sizeof (RSPAMC_PROTO_1_2) - 1) == 0) { - task->proto_ver = 12; + else { + debug_task ("wrong header: %s", headern); + res = FALSE; } - else if (strncmp (token, RSPAMC_PROTO_1_3, sizeof (RSPAMC_PROTO_1_3) - 1) == 0) { - task->proto_ver = 13; + break; + case 'h': + case 'H': + if (g_ascii_strcasecmp (headern, HELO_HEADER) == 0) { + task->helo = h->value->str; + debug_task ("read helo header, value: %s", task->helo); } - } - } - else if (g_ascii_strncasecmp (line->begin, SPAMC_GREETING, sizeof (SPAMC_GREETING) - 1) == 0) { - task->proto = SPAMC_PROTO; - task->proto_ver = 12; - } - else { - return FALSE; - } - - task->state = READ_HEADER; - - return TRUE; -} - -static gboolean -parse_http_command (struct worker_task *task, f_str_t * line) -{ - guint8 *p, *end, *c; - gint state = 0, next_state = 0; - gchar *cmd; - - p = line->begin; - c = p; - end = p + line->len; - task->proto = RSPAMC_PROTO; - - while (p < end) { - switch (state) { - case 0: - /* Expect GET or POST here */ - if ((end - p > 3 && - (*p == 'G' || *p == 'g') && - (p[1] == 'E' || p[1] == 'e') && - (p[2] == 'T' || p[2] == 't')) || - (end - p > 4 && - (*p == 'P' || *p == 'p') && - (p[1] == 'O' || p[1] == 'o') && - (p[2] == 'S' || p[2] == 's') && - (p[3] == 'T' || p[3] == 't'))) { - state = 99; - next_state = 1; - p += (*p == 'g' || *p == 'G') ? 3 : 4; + else if (g_ascii_strcasecmp (headern, HOSTNAME_HEADER) == 0) { + task->hostname = h->value->str; + debug_task ("read hostname header, value: %s", task->hostname); } else { - msg_info ("invalid HTTP request: %V", line); - return FALSE; + debug_task ("wrong header: %s", headern); + res = FALSE; } break; - case 1: - /* Get command or path */ - if (!g_ascii_isspace (*p)) { - p ++; + case 'f': + case 'F': + if (g_ascii_strcasecmp (headern, FROM_HEADER) == 0) { + task->from = rspamd_protocol_escape_braces (h->value); + debug_task ("read from header, value: %s", task->from); } else { - /* Copy command */ - cmd = memory_pool_alloc (task->task_pool, p - c + 1); - rspamd_strlcpy (cmd, c, p - c + 1); - /* Skip the first '/' */ - if (*cmd == '/') { - cmd ++; - } - if (!parse_check_command (task, cmd)) { - /* Assume that command is symbols */ - task->cmd = CMD_SYMBOLS; - } - state = 99; - next_state = 2; + debug_task ("wrong header: %s", headern); + res = FALSE; } break; - case 2: - /* Get HTTP/1.0 or HTTP/1.1 */ - if (p == end - 1) { - /* We are at the end */ - if (g_ascii_strncasecmp (c, "HTTP/1.0", sizeof ("HTTP/1.0") - 1) == 0 || - g_ascii_strncasecmp (c, "HTTP/1.1", sizeof ("HTTP/1.1") - 1) == 0) { - task->state = READ_HEADER; - return TRUE; - } + case 'j': + case 'J': + if (g_ascii_strcasecmp (headern, JSON_HEADER) == 0) { + task->is_json = parse_flag (h->value->str); } else { - p ++; + debug_task ("wrong header: %s", headern); + res = FALSE; } break; - case 99: - /* Skip spaces */ - if (g_ascii_isspace (*p)) { - p ++; + case 'q': + case 'Q': + if (g_ascii_strcasecmp (headern, QUEUE_ID_HEADER) == 0) { + task->queue_id = h->value->str; + debug_task ("read queue_id header, value: %s", task->queue_id); } else { - state = next_state; - c = p; + debug_task ("wrong header: %s", headern); + res = FALSE; } break; - } - } - - return FALSE; -} - -static gboolean -parse_command (struct worker_task *task, f_str_t * line) -{ - task->proto_ver = 11; - - if (! task->is_http) { - return parse_rspamc_command (task, line); - } - else { - return parse_http_command (task, line); - } - - /* Unreached */ - return FALSE; -} - -static gboolean -parse_header (struct worker_task *task, f_str_t * line) -{ - gchar *headern, *err, *tmp; - gboolean res = TRUE; - - /* Check end of headers */ - if (line->len == 0) { - debug_task ("got empty line, assume it as end of headers"); - if (task->cmd == CMD_PING || task->cmd == CMD_SKIP) { - task->state = WRITE_REPLY; - } - else { - if (task->content_length > 0) { - if (task->cmd == CMD_LEARN) { - if (task->statfile != NULL) { - rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length); - task->state = READ_MESSAGE; - } - else { - task->last_error = "Unknown statfile"; - task->error_code = RSPAMD_STATFILE_ERROR; - task->state = WRITE_ERROR; - return FALSE; - } - } - else { - rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length); - task->state = READ_MESSAGE; - task->msg = memory_pool_alloc0 (task->task_pool, sizeof (f_str_t)); - } + case 'r': + case 'R': + if (g_ascii_strcasecmp (headern, RCPT_HEADER) == 0) { + tmp = rspamd_protocol_escape_braces (h->value); + task->rcpt = g_list_prepend (task->rcpt, tmp); + debug_task ("read rcpt header, value: %s", tmp); } - else if (task->cmd != CMD_LEARN && task->cmd != CMD_OTHER) { - rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_ANY, 0); - task->state = READ_MESSAGE; - task->msg = memory_pool_alloc0 (task->task_pool, sizeof (f_str_t)); + else if (g_ascii_strcasecmp (headern, NRCPT_HEADER) == 0) { + task->nrcpt = strtoul (h->value->str, &err, 10); + debug_task ("read rcpt header, value: %d", (gint)task->nrcpt); } else { - task->last_error = "Unknown content length"; - task->error_code = RSPAMD_LENGTH_ERROR; - task->state = WRITE_ERROR; - return FALSE; + msg_info ("wrong header: %s", headern); + res = FALSE; } - } - return TRUE; - } - - headern = separate_command (line, ':'); - - if (line == NULL || headern == NULL) { - return FALSE; - } - /* Eat whitespaces */ - g_strstrip (headern); - fstrstrip (line); - - switch (headern[0]) { - case 'c': - case 'C': - /* content-length */ - if (g_ascii_strncasecmp (headern, CONTENT_LENGTH_HEADER, sizeof (CONTENT_LENGTH_HEADER) - 1) == 0) { - if (task->content_length == 0) { - tmp = memory_pool_fstrdup (task->task_pool, line); - task->content_length = strtoul (tmp, &err, 10); - debug_task ("read Content-Length header, value: %ul", (guint32)task->content_length); - } - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'd': - case 'D': - /* Deliver-To */ - if (g_ascii_strncasecmp (headern, DELIVER_TO_HEADER, sizeof (DELIVER_TO_HEADER) - 1) == 0) { - task->deliver_to = escape_braces_addr_fstr (task->task_pool, line); - debug_task ("read deliver-to header, value: %s", task->deliver_to); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'h': - case 'H': - /* helo */ - if (g_ascii_strncasecmp (headern, HELO_HEADER, sizeof (HELO_HEADER) - 1) == 0) { - task->helo = memory_pool_fstrdup (task->task_pool, line); - debug_task ("read helo header, value: %s", task->helo); - } - else if (g_ascii_strncasecmp (headern, HOSTNAME_HEADER, sizeof (HOSTNAME_HEADER) - 1) == 0) { - task->hostname = memory_pool_fstrdup (task->task_pool, line); - debug_task ("read hostname header, value: %s", task->hostname); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'f': - case 'F': - /* from */ - if (g_ascii_strncasecmp (headern, FROM_HEADER, sizeof (FROM_HEADER) - 1) == 0) { - task->from = escape_braces_addr_fstr (task->task_pool, line); - debug_task ("read from header, value: %s", task->from); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'j': - case 'J': - /* json */ - if (g_ascii_strncasecmp (headern, JSON_HEADER, sizeof (JSON_HEADER) - 1) == 0) { - task->is_json = parse_flag (memory_pool_fstrdup (task->task_pool, line)); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'q': - case 'Q': - /* Queue id */ - if (g_ascii_strncasecmp (headern, QUEUE_ID_HEADER, sizeof (QUEUE_ID_HEADER) - 1) == 0) { - task->queue_id = memory_pool_fstrdup (task->task_pool, line); - debug_task ("read queue_id header, value: %s", task->queue_id); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'r': - case 'R': - /* rcpt */ - if (g_ascii_strncasecmp (headern, RCPT_HEADER, sizeof (RCPT_HEADER) - 1) == 0) { - tmp = escape_braces_addr_fstr (task->task_pool, line); - task->rcpt = g_list_prepend (task->rcpt, tmp); - debug_task ("read rcpt header, value: %s", tmp); - } - else if (g_ascii_strncasecmp (headern, NRCPT_HEADER, sizeof (NRCPT_HEADER) - 1) == 0) { - tmp = memory_pool_fstrdup (task->task_pool, line); - task->nrcpt = strtoul (tmp, &err, 10); - debug_task ("read rcpt header, value: %d", (gint)task->nrcpt); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'i': - case 'I': - /* ip_addr */ - if (g_ascii_strncasecmp (headern, IP_ADDR_HEADER, sizeof (IP_ADDR_HEADER) - 1) == 0) { - tmp = memory_pool_fstrdup (task->task_pool, line); + break; + case 'i': + case 'I': + if (g_ascii_strcasecmp (headern, IP_ADDR_HEADER) == 0) { + tmp = h->value->str; #ifdef HAVE_INET_PTON - if (g_ascii_strncasecmp (tmp, "IPv6:", 5) == 0) { - if (inet_pton (AF_INET6, tmp + 6, &task->from_addr.d.in6) == 1) { - task->from_addr.ipv6 = TRUE; - } - else { - msg_err ("bad ip header: '%s'", tmp); - return FALSE; - } - task->from_addr.has_addr = TRUE; - } - else { - if (inet_pton (AF_INET, tmp, &task->from_addr.d.in4) != 1) { - /* Try ipv6 */ - if (inet_pton (AF_INET6, tmp, &task->from_addr.d.in6) == 1) { + if (g_ascii_strncasecmp (tmp, "IPv6:", 5) == 0) { + if (inet_pton (AF_INET6, tmp + 6, &task->from_addr.d.in6) == 1) { task->from_addr.ipv6 = TRUE; } else { msg_err ("bad ip header: '%s'", tmp); return FALSE; } + task->from_addr.has_addr = TRUE; } else { - task->from_addr.ipv6 = FALSE; + if (inet_pton (AF_INET, tmp, &task->from_addr.d.in4) != 1) { + /* Try ipv6 */ + if (inet_pton (AF_INET6, tmp, &task->from_addr.d.in6) == 1) { + task->from_addr.ipv6 = TRUE; + } + else { + msg_err ("bad ip header: '%s'", tmp); + return FALSE; + } + } + else { + task->from_addr.ipv6 = FALSE; + } + task->from_addr.has_addr = TRUE; } - task->from_addr.has_addr = TRUE; - } #else - if (!inet_aton (tmp, &task->from_addr)) { - msg_err ("bad ip header: '%s'", tmp); - return FALSE; - } + if (!inet_aton (tmp, &task->from_addr)) { + msg_err ("bad ip header: '%s'", tmp); + return FALSE; + } #endif - debug_task ("read IP header, value: %s", tmp); - } - else { - msg_info ("wrong header: %s", headern); - res = FALSE; - } - break; - case 'p': - case 'P': - /* Pass header */ - if (g_ascii_strncasecmp (headern, PASS_HEADER, sizeof (PASS_HEADER) - 1) == 0) { - if (line->len == sizeof ("all") - 1 && g_ascii_strncasecmp (line->begin, "all", sizeof ("all") - 1) == 0) { - task->pass_all_filters = TRUE; - msg_info ("pass all filters"); - } - } - else { - res = FALSE; - } - break; - case 's': - case 'S': - if (g_ascii_strncasecmp (headern, SUBJECT_HEADER, sizeof (SUBJECT_HEADER) - 1) == 0) { - task->subject = memory_pool_fstrdup (task->task_pool, line); - } - else if (g_ascii_strncasecmp (headern, STATFILE_HEADER, sizeof (STATFILE_HEADER) - 1) == 0) { - task->statfile = memory_pool_fstrdup (task->task_pool, line); - } - else { - res = FALSE; - } - break; - case 'u': - case 'U': - if (g_ascii_strncasecmp (headern, USER_HEADER, sizeof (USER_HEADER) - 1) == 0) { - task->user = memory_pool_fstrdup (task->task_pool, line); - } - else { + debug_task ("read IP header, value: %s", tmp); + } + else { + debug_task ("wrong header: %s", headern); + res = FALSE; + } + break; + case 'p': + case 'P': + if (g_ascii_strcasecmp (headern, PASS_HEADER) == 0) { + if (h->value->len == sizeof ("all") - 1 && + g_ascii_strcasecmp (h->value->str, "all") == 0) { + task->pass_all_filters = TRUE; + debug_task ("pass all filters"); + } + } + else { + res = FALSE; + } + break; + case 's': + case 'S': + if (g_ascii_strcasecmp (headern, SUBJECT_HEADER) == 0) { + task->subject = h->value->str; + } + else { + res = FALSE; + } + break; + case 'u': + case 'U': + if (g_ascii_strcasecmp (headern, USER_HEADER) == 0) { + task->user = h->value->str; + } + else { + res = FALSE; + } + break; + default: + debug_task ("wrong header: %s", headern); res = FALSE; + break; } - break; - default: - msg_info ("wrong header: %s", headern); - res = FALSE; - break; } if (!res && task->cfg->strict_protocol_headers) { msg_err ("deny processing of a request with incorrect or unknown headers"); + task->last_error = "invalid header"; + task->error_code = 400; return FALSE; } @@ -663,18 +400,13 @@ parse_header (struct worker_task *task, f_str_t * line) } gboolean -read_rspamd_input_line (struct worker_task *task, f_str_t * line) +rspamd_protocol_handle_request (struct worker_task *task, + struct rspamd_http_message *msg) { - switch (task->state) { - case READ_COMMAND: - return parse_command (task, line); - break; - case READ_HEADER: - return parse_header (task, line); - break; - default: - return FALSE; + if (rspamd_protocol_handle_url (task, msg)) { + return rspamd_protocol_handle_headers (task, msg); } + return FALSE; } @@ -878,7 +610,17 @@ rspamd_metric_result_ucl (struct worker_task *task, struct metric_result *mres, if (logbuf->str[logbuf->len - 1] == ',') { logbuf->len --; } - rspamd_printf_gstring (logbuf, "]), "); + +#ifdef HAVE_CLOCK_GETTIME + rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,", + task->msg->len, calculate_check_time (&task->tv, &task->ts, + task->cfg->clock_res, &task->scan_milliseconds), task->dns_requests); +#else + rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,", + task->msg->len, + calculate_check_time (&task->tv, task->cfg->clock_res, &task->scan_milliseconds), + task->dns_requests); +#endif return obj; } @@ -992,10 +734,12 @@ write_check_reply (struct rspamd_http_message *msg, struct worker_task *task) write_hashes_to_log (task, logbuf); msg_info ("%v", logbuf); + g_string_free (logbuf, TRUE); msg->body = g_string_sized_new (BUFSIZ); func.ud = msg->body; ucl_object_emit_full (top, UCL_EMIT_JSON_COMPACT, &func); + ucl_object_unref (top); /* Increase counters */ task->worker->srv->stat->messages_scanned++; @@ -1006,7 +750,7 @@ write_check_reply (struct rspamd_http_message *msg, struct worker_task *task) } gboolean -write_reply (struct worker_task *task) +rspamd_protocol_write_reply (struct worker_task *task) { struct rspamd_http_message *msg; @@ -1038,13 +782,6 @@ write_reply (struct worker_task *task) "text/plain", task, task->sock, &task->tv, task->ev_base); task->state = CLOSING_CONNECTION; break; - case CMD_LEARN: - msg->code = task->error_code; - rspamd_http_connection_write_message (task->http_conn, msg, NULL, - "text/plain", task, task->sock, &task->tv, task->ev_base); - task->state = CLOSING_CONNECTION; - return TRUE; - break; case CMD_OTHER: task->state = CLOSING_CONNECTION; return task->custom_cmd->func (task); |