From 87def67d9785d4bd109ac875b02a253f0eaa4849 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Mon, 3 Feb 2020 16:18:24 +0000 Subject: [PATCH] [Rework] Stop using of uthash for http headers --- src/client/rspamc.c | 6 +-- src/libserver/protocol.c | 6 +-- src/libutil/http_connection.c | 89 +++++++++++++++++++++++------------ src/libutil/http_message.c | 82 +++++++++++++++++++++----------- src/libutil/http_private.h | 9 ++-- src/lua/lua_http.c | 12 ++--- 6 files changed, 130 insertions(+), 74 deletions(-) diff --git a/src/client/rspamc.c b/src/client/rspamc.c index 075f0a487..6ca3de668 100644 --- a/src/client/rspamc.c +++ b/src/client/rspamc.c @@ -1277,11 +1277,11 @@ rspamc_stat_output (FILE *out, ucl_object_t *obj) static void rspamc_output_headers (FILE *out, struct rspamd_http_message *msg) { - struct rspamd_http_header *h, *htmp; + struct rspamd_http_header *h; - HASH_ITER (hh, msg->headers, h, htmp) { + kh_foreach_value (msg->headers, h, { rspamd_fprintf (out, "%T: %T\n", &h->name, &h->value); - } + }); rspamd_fprintf (out, "\n"); } diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index 20237a7bf..a700ad180 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -450,10 +450,10 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, { rspamd_ftok_t *hn_tok, *hv_tok, srch; gboolean has_ip = FALSE, seen_settings_header = FALSE; - struct rspamd_http_header *header, *h, *htmp; + struct rspamd_http_header *header, *h; gchar *ntok; - HASH_ITER (hh, msg->headers, header, htmp) { + kh_foreach_value (msg->headers, header, { DL_FOREACH (header, h) { ntok = rspamd_mempool_ftokdup (task->task_pool, &h->name); hn_tok = rspamd_mempool_alloc (task->task_pool, sizeof (*hn_tok)); @@ -702,7 +702,7 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, rspamd_task_add_request_header (task, hn_tok, hv_tok); } - } + }); /* End of kh_foreach_value */ if (seen_settings_header && task->settings_elt) { msg_warn_task ("ignore settings id %s as settings header is also presented", diff --git a/src/libutil/http_connection.c b/src/libutil/http_connection.c index a71c6fe75..3848788d6 100644 --- a/src/libutil/http_connection.c +++ b/src/libutil/http_connection.c @@ -243,6 +243,8 @@ rspamd_http_finish_header (struct rspamd_http_connection *conn, struct rspamd_http_connection_private *priv) { struct rspamd_http_header *hdr; + khiter_t k; + gint r; priv->header->combined = rspamd_fstring_append (priv->header->combined, "\r\n", 2); @@ -252,12 +254,15 @@ rspamd_http_finish_header (struct rspamd_http_connection *conn, priv->header->name.len + 2; priv->header->name.begin = priv->header->combined->str; - HASH_FIND (hh, priv->msg->headers, priv->header->name.begin, - priv->header->name.len, hdr); + k = kh_put (rspamd_http_headers_hash, priv->msg->headers, &priv->header->name, + &r); - if (hdr == NULL) { - HASH_ADD_KEYPTR (hh, priv->msg->headers, priv->header->name.begin, - priv->header->name.len, priv->header); + if (r != 0) { + kh_value (priv->msg->headers, k) = priv->header; + hdr = NULL; + } + else { + hdr = kh_value (priv->msg->headers, k); } DL_APPEND (hdr, priv->header); @@ -565,7 +570,7 @@ rspamd_http_decrypt_message (struct rspamd_http_connection *conn, const guchar *nm; gsize dec_len; struct rspamd_http_message *msg = priv->msg; - struct rspamd_http_header *hdr, *hdrtmp, *hcur, *hcurtmp; + struct rspamd_http_header *hdr, *hcur, *hcurtmp; struct http_parser decrypted_parser; struct http_parser_settings decrypted_cb; enum rspamd_cryptobox_mode mode; @@ -589,16 +594,15 @@ rspamd_http_decrypt_message (struct rspamd_http_connection *conn, } /* Cleanup message */ - HASH_ITER (hh, msg->headers, hdr, hdrtmp) { - HASH_DELETE (hh, msg->headers, hdr); - + kh_foreach_value (msg->headers, hdr, { DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { rspamd_fstring_free (hcur->combined); g_free (hcur); } - } + }); - msg->headers = NULL; + kh_destroy (rspamd_http_headers_hash, msg->headers); + msg->headers = kh_init (rspamd_http_headers_hash); if (msg->url != NULL) { msg->url = rspamd_fstring_assign (msg->url, "", 0); @@ -1325,7 +1329,7 @@ struct rspamd_http_message * rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) { struct rspamd_http_message *new_msg; - struct rspamd_http_header *hdr, *nhdr, *nhdrs, *thdr, *hcur; + struct rspamd_http_header *hdr, *nhdr, *nhdrs, *hcur; const gchar *old_body; gsize old_len; struct stat st; @@ -1420,7 +1424,7 @@ rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) new_msg->date = msg->date; new_msg->last_modified = msg->last_modified; - HASH_ITER (hh, msg->headers, hdr, thdr) { + kh_foreach_value (msg->headers, hdr, { nhdrs = NULL; DL_FOREACH (hdr, hcur) { @@ -1429,17 +1433,25 @@ rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err) nhdr->combined = rspamd_fstring_new_init (hcur->combined->str, hcur->combined->len); nhdr->name.begin = nhdr->combined->str + - (hcur->name.begin - hcur->combined->str); + (hcur->name.begin - hcur->combined->str); nhdr->name.len = hcur->name.len; nhdr->value.begin = nhdr->combined->str + - (hcur->value.begin - hcur->combined->str); + (hcur->value.begin - hcur->combined->str); nhdr->value.len = hcur->value.len; DL_APPEND (nhdrs, nhdr); } - HASH_ADD_KEYPTR (hh, new_msg->headers, nhdrs->name.begin, - nhdrs->name.len, nhdrs); - } + gint r; + khiter_t k = kh_put (rspamd_http_headers_hash, new_msg->headers, + &nhdrs->name,&r); + + if (r != 0) { + kh_value (new_msg->headers, k) = nhdrs; + } + else { + DL_CONCAT (kh_value (new_msg->headers, k), nhdrs); + } + }); return new_msg; } @@ -1550,7 +1562,7 @@ rspamd_http_connection_encrypt_message ( const guchar *nm; gint i, cnt; guint outlen; - struct rspamd_http_header *hdr, *htmp, *hcur; + struct rspamd_http_header *hdr, *hcur; enum rspamd_cryptobox_mode mode; mode = rspamd_keypair_alg (priv->local_key); @@ -1585,12 +1597,12 @@ rspamd_http_connection_encrypt_message ( } - HASH_ITER (hh, msg->headers, hdr, htmp) { + kh_foreach_value (msg->headers, hdr, { DL_FOREACH (hdr, hcur) { segments[i].data = hcur->combined->str; segments[i++].len = hcur->combined->len; } - } + }); /* crlfp should point now at the second crlf */ segments[i].data = crlfp; @@ -1915,7 +1927,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn gboolean allow_shared) { struct rspamd_http_connection_private *priv = conn->priv; - struct rspamd_http_header *hdr, *htmp, *hcur; + struct rspamd_http_header *hdr, *hcur; gchar repbuf[512], *pbody; gint i, hdrcount, meth_len = 0, preludelen = 0; gsize bodylen, enclen = 0; @@ -1988,14 +2000,29 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn } if (priv->ctx->config.user_agent && conn->type == RSPAMD_HTTP_CLIENT) { - struct rspamd_http_header *found = NULL; + rspamd_ftok_t srch; + khiter_t k; + gint r; + + RSPAMD_FTOK_ASSIGN (&srch, "User-Agent"); - HASH_FIND (hh, msg->headers, "User-Agent", - sizeof ("User-Agent") - 1, found); + k = kh_put (rspamd_http_headers_hash, msg->headers, &srch,&r); - if (!found) { - rspamd_http_message_add_header (msg, "User-Agent", + if (r != 0) { + hdr = g_malloc0 (sizeof (struct rspamd_http_header)); + guint vlen = strlen (priv->ctx->config.user_agent); + hdr->combined = rspamd_fstring_sized_new (srch.len + vlen + 4); + rspamd_printf_fstring (&hdr->combined, "%T: %*s\r\n", &srch, vlen, priv->ctx->config.user_agent); + hdr->name.begin = hdr->combined->str; + hdr->name.len = srch.len; + hdr->value.begin = hdr->combined->str + srch.len + 2; + hdr->value.len = vlen; + hdr->prev = hdr; /* for utlists */ + + kh_value (msg->headers, k) = hdr; + /* as we searched using static buffer */ + kh_key (msg->headers, k) = &hdr->name; } } @@ -2117,7 +2144,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn hdrcount = 0; if (msg->method < HTTP_SYMBOLS) { - HASH_ITER (hh, msg->headers, hdr, htmp) { + kh_foreach_value (msg->headers, hdr, { DL_FOREACH (hdr, hcur) { /* */ priv->wr_total += hcur->combined->len; @@ -2125,7 +2152,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn priv->outlen ++; hdrcount ++; } - } + }); } /* Allocate iov */ @@ -2195,12 +2222,12 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn else { i = 1; if (msg->method < HTTP_SYMBOLS) { - HASH_ITER (hh, msg->headers, hdr, htmp) { + kh_foreach_value (msg->headers, hdr, { DL_FOREACH (hdr, hcur) { priv->out[i].iov_base = hcur->combined->str; priv->out[i++].iov_len = hcur->combined->len; } - } + }); priv->out[i].iov_base = "\r\n"; priv->out[i++].iov_len = 2; diff --git a/src/libutil/http_message.c b/src/libutil/http_message.c index 13241034c..ca3523cac 100644 --- a/src/libutil/http_message.c +++ b/src/libutil/http_message.c @@ -39,6 +39,7 @@ rspamd_http_new_message (enum rspamd_http_message_type type) new->port = 80; new->type = type; new->method = HTTP_INVALID; + new->headers = kh_init (rspamd_http_headers_hash); REF_INIT_RETAIN (new, rspamd_http_message_free); @@ -468,18 +469,16 @@ rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg) void rspamd_http_message_free (struct rspamd_http_message *msg) { - struct rspamd_http_header *hdr, *htmp, *hcur, *hcurtmp; - - - HASH_ITER (hh, msg->headers, hdr, htmp) { - HASH_DEL (msg->headers, hdr); + struct rspamd_http_header *hdr, *hcur, *hcurtmp; + kh_foreach_value (msg->headers, hdr, { DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { rspamd_fstring_free (hcur->combined); g_free (hcur); } - } + }); + kh_destroy (rspamd_http_headers_hash, msg->headers); rspamd_http_message_storage_cleanup (msg); if (msg->url != NULL) { @@ -520,8 +519,10 @@ rspamd_http_message_add_header_len (struct rspamd_http_message *msg, const gchar *value, gsize len) { - struct rspamd_http_header *hdr, *found = NULL; + struct rspamd_http_header *hdr, *found; guint nlen, vlen; + khiter_t k; + gint r; if (msg != NULL && name != NULL && value != NULL) { hdr = g_malloc0 (sizeof (struct rspamd_http_header)); @@ -535,12 +536,15 @@ rspamd_http_message_add_header_len (struct rspamd_http_message *msg, hdr->value.begin = hdr->combined->str + nlen + 2; hdr->value.len = vlen; - HASH_FIND (hh, msg->headers, hdr->name.begin, - hdr->name.len, found); + k = kh_put (rspamd_http_headers_hash, msg->headers, &hdr->name, + &r); - if (found == NULL) { - HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin, - hdr->name.len, hdr); + if (r != 0) { + kh_value (msg->headers, k) = hdr; + found = NULL; + } + else { + found = kh_value (msg->headers, k); } DL_APPEND (found, hdr); @@ -564,6 +568,8 @@ rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, { struct rspamd_http_header *hdr, *found = NULL; guint nlen, vlen; + khiter_t k; + gint r; if (msg != NULL && name != NULL && value != NULL) { hdr = g_malloc0 (sizeof (struct rspamd_http_header)); @@ -576,12 +582,15 @@ rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg, hdr->value.begin = hdr->combined->str + nlen + 2; hdr->value.len = vlen; - HASH_FIND (hh, msg->headers, hdr->name.begin, - hdr->name.len, found); + k = kh_put (rspamd_http_headers_hash, msg->headers, &hdr->name, + &r); - if (found == NULL) { - HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin, - hdr->name.len, hdr); + if (r != 0) { + kh_value (msg->headers, k) = hdr; + found = NULL; + } + else { + found = kh_value (msg->headers, k); } DL_APPEND (found, hdr); @@ -592,15 +601,19 @@ const rspamd_ftok_t * rspamd_http_message_find_header (struct rspamd_http_message *msg, const gchar *name) { - struct rspamd_http_header *hdr; const rspamd_ftok_t *res = NULL; + rspamd_ftok_t srch; guint slen = strlen (name); + khiter_t k; if (msg != NULL) { - HASH_FIND (hh, msg->headers, name, slen, hdr); + srch.begin = name; + srch.len = slen; + + k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); - if (hdr) { - res = &hdr->value; + if (k != kh_end (msg->headers)) { + res = &(kh_value (msg->headers, k)->value); } } @@ -614,14 +627,23 @@ rspamd_http_message_find_header_multiple ( { GPtrArray *res = NULL; struct rspamd_http_header *hdr, *cur; + rspamd_ftok_t srch; + khiter_t k; + guint cnt = 0; guint slen = strlen (name); if (msg != NULL) { - HASH_FIND (hh, msg->headers, name, slen, hdr); + srch.begin = name; + srch.len = slen; - if (hdr) { - res = g_ptr_array_sized_new (4); + k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); + + if (k != kh_end (msg->headers)) { + hdr = kh_value (msg->headers, k); + + LL_COUNT (hdr, cur, cnt); + res = g_ptr_array_sized_new (cnt); LL_FOREACH (hdr, cur) { g_ptr_array_add (res, &cur->value); @@ -641,12 +663,18 @@ rspamd_http_message_remove_header (struct rspamd_http_message *msg, struct rspamd_http_header *hdr, *hcur, *hcurtmp; gboolean res = FALSE; guint slen = strlen (name); + rspamd_ftok_t srch; + khiter_t k; if (msg != NULL) { - HASH_FIND (hh, msg->headers, name, slen, hdr); + srch.begin = name; + srch.len = slen; + + k = kh_get (rspamd_http_headers_hash, msg->headers, &srch); - if (hdr) { - HASH_DEL (msg->headers, hdr); + if (k != kh_end (msg->headers)) { + hdr = kh_value (msg->headers, k); + kh_del (rspamd_http_headers_hash, msg->headers, k); res = TRUE; DL_FOREACH_SAFE (hdr, hcur, hcurtmp) { diff --git a/src/libutil/http_private.h b/src/libutil/http_private.h index 53c9a81f2..f2270277b 100644 --- a/src/libutil/http_private.h +++ b/src/libutil/http_private.h @@ -24,8 +24,6 @@ #include "ref.h" #include "upstream.h" #include "khash.h" -#define HASH_CASELESS -#include "uthash_strcase.h" #ifdef __cplusplus extern "C" { @@ -38,10 +36,13 @@ struct rspamd_http_header { rspamd_fstring_t *combined; rspamd_ftok_t name; rspamd_ftok_t value; - UT_hash_handle hh; struct rspamd_http_header *prev, *next; }; +KHASH_INIT (rspamd_http_headers_hash, rspamd_ftok_t *, + struct rspamd_http_header *, 1, + rspamd_ftok_icase_hash, rspamd_ftok_icase_equal); + /** * HTTP message structure, used for requests and replies */ @@ -49,7 +50,7 @@ struct rspamd_http_message { rspamd_fstring_t *url; GString *host; rspamd_fstring_t *status; - struct rspamd_http_header *headers; + khash_t (rspamd_http_headers_hash) *headers; struct _rspamd_body_buf_s { /* Data start */ diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c index 6ad5e6d21..677db488f 100644 --- a/src/lua/lua_http.c +++ b/src/lua/lua_http.c @@ -221,7 +221,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_message *msg) { struct lua_http_cbdata *cbd = (struct lua_http_cbdata *)conn->ud; - struct rspamd_http_header *h, *htmp; + struct rspamd_http_header *h; const gchar *body; gsize body_len; @@ -275,7 +275,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, /* Headers */ lua_newtable (L); - HASH_ITER (hh, msg->headers, h, htmp) { + kh_foreach_value (msg->headers, h, { /* * Lowercase header name, as Lua cannot search in caseless matter */ @@ -283,7 +283,7 @@ lua_http_finish_handler (struct rspamd_http_connection *conn, lua_pushlstring (L, h->name.begin, h->name.len); lua_pushlstring (L, h->value.begin, h->value.len); lua_settable (L, -3); - } + }); if (cbd->item) { /* Replace watcher to deal with nested calls */ @@ -313,7 +313,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, lua_State *L = cbd->thread->lua_state; const gchar *body; gsize body_len; - struct rspamd_http_header *h, *htmp; + struct rspamd_http_header *h; if (err) { lua_pushstring (L, err); @@ -363,7 +363,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, lua_pushliteral (L, "headers"); lua_newtable (L); - HASH_ITER (hh, msg->headers, h, htmp) { + kh_foreach_value (msg->headers, h, { /* * Lowercase header name, as Lua cannot search in caseless matter */ @@ -371,7 +371,7 @@ lua_http_resume_handler (struct rspamd_http_connection *conn, lua_pushlstring (L, h->name.begin, h->name.len); lua_pushlstring (L, h->value.begin, h->value.len); lua_settable (L, -3); - } + }); lua_settable (L, -3); } -- 2.39.5