commit 87def67: [Rework] Stop using of uthash for http headers

Vsevolod Stakhov vsevolod at highsecure.ru
Mon Feb 3 16:21:07 UTC 2020


Author: Vsevolod Stakhov
Date: 2020-02-03 16:18:24 +0000
URL: https://github.com/rspamd/rspamd/commit/87def67d9785d4bd109ac875b02a253f0eaa4849 (HEAD -> master)

[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) {
 				/* <name: value\r\n> */
 				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);
 	}


More information about the Commits mailing list