commit 05d6d35: [Feature] Allow to skip DNS resolution for keep-alive connections

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Dec 9 14:07:04 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-12-09 14:02:18 +0000
URL: https://github.com/rspamd/rspamd/commit/05d6d354ec99e800007828137315b42be332c719 (HEAD -> master)

[Feature] Allow to skip DNS resolution for keep-alive connections

---
 src/libserver/http/http_context.c | 56 ++++++++++++++++++++++++++++++++-------
 src/libserver/http/http_context.h | 20 +++++++++++---
 src/libserver/http/http_private.h |  1 +
 src/lua/lua_http.c                | 42 ++++++++++++++++++-----------
 4 files changed, 91 insertions(+), 28 deletions(-)

diff --git a/src/libserver/http/http_context.c b/src/libserver/http/http_context.c
index b56f1c4c0..2dbaff0a4 100644
--- a/src/libserver/http/http_context.c
+++ b/src/libserver/http/http_context.c
@@ -365,19 +365,18 @@ rspamd_http_context_default (void)
 gint32
 rspamd_keep_alive_key_hash (struct rspamd_keepalive_hash_key *k)
 {
-	guint32 h;
+	rspamd_cryptobox_fast_hash_state_t hst;
 
-	h = rspamd_inet_address_port_hash (k->addr);
+	rspamd_cryptobox_fast_hash_init (&hst, 0);
 
 	if (k->host) {
-		h ^= rspamd_cryptobox_fast_hash (k->host, strlen (k->host), h);
+		rspamd_cryptobox_fast_hash_update (&hst, k->host, strlen (k->host));
 	}
 
-	if (k->is_ssl) {
-		h = ~h;
-	}
+	rspamd_cryptobox_fast_hash_update (&hst, &k->port, sizeof(k->port));
+	rspamd_cryptobox_fast_hash_update (&hst, &k->is_ssl, sizeof(k->is_ssl));
 
-	return (gint32)h;
+	return rspamd_cryptobox_fast_hash_final (&hst);
 }
 
 bool
@@ -389,12 +388,12 @@ rspamd_keep_alive_key_equal (struct rspamd_keepalive_hash_key *k1,
 	}
 
 	if (k1->host && k2->host) {
-		if (rspamd_inet_address_port_equal (k1->addr, k2->addr)) {
+		if (k1->port == k2->port) {
 			return strcmp (k1->host, k2->host) == 0;
 		}
 	}
 	else if (!k1->host && !k2->host) {
-		return rspamd_inet_address_port_equal (k1->addr, k2->addr);
+		return (k1->port == k2->port);
 	}
 
 	/* One has host and another has no host */
@@ -410,8 +409,13 @@ rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx,
 	struct rspamd_keepalive_hash_key hk, *phk;
 	khiter_t k;
 
+	if (ctx == NULL) {
+		ctx = rspamd_http_context_default ();
+	}
+
 	hk.addr = (rspamd_inet_addr_t *)addr;
 	hk.host = (gchar *)host;
+	hk.port = rspamd_inet_address_get_port (addr);
 	hk.is_ssl = is_ssl;
 
 	k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk);
@@ -471,6 +475,37 @@ rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx,
 	return NULL;
 }
 
+const rspamd_inet_addr_t *
+rspamd_http_context_has_keepalive(struct rspamd_http_context *ctx,
+								  const gchar *host,
+								  unsigned port,
+								  bool is_ssl)
+{
+	struct rspamd_keepalive_hash_key hk, *phk;
+	khiter_t k;
+
+	if (ctx == NULL) {
+		ctx = rspamd_http_context_default ();
+	}
+
+	hk.host = (gchar *)host;
+	hk.port = port;
+	hk.is_ssl = is_ssl;
+
+	k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk);
+
+	if (k != kh_end (ctx->keep_alive_hash)) {
+		phk = kh_key (ctx->keep_alive_hash, k);
+		GQueue *conns = &phk->conns;
+
+		if (g_queue_get_length(conns) > 0) {
+			return phk->addr;
+		}
+	}
+
+	return NULL;
+}
+
 void
 rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx,
 									  struct rspamd_http_connection *conn,
@@ -484,6 +519,7 @@ rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx,
 	hk.addr = (rspamd_inet_addr_t *)addr;
 	hk.host = (gchar *)host;
 	hk.is_ssl = is_ssl;
+	hk.port = rspamd_inet_address_get_port (addr);
 
 	k = kh_get (rspamd_keep_alive_hash, ctx->keep_alive_hash, &hk);
 
@@ -504,6 +540,8 @@ rspamd_http_context_prepare_keepalive(struct rspamd_http_context *ctx,
 		phk->host = g_strdup (host);
 		phk->is_ssl = is_ssl;
 		phk->addr = rspamd_inet_address_copy (addr);
+		phk->port = hk.port;
+
 
 		kh_put (rspamd_keep_alive_hash, ctx->keep_alive_hash, phk, &r);
 		conn->keepalive_hash_key = phk;
diff --git a/src/libserver/http/http_context.h b/src/libserver/http/http_context.h
index f42164dba..635da7ba5 100644
--- a/src/libserver/http/http_context.h
+++ b/src/libserver/http/http_context.h
@@ -74,9 +74,23 @@ struct rspamd_http_context *rspamd_http_context_default (void);
  * @param host
  * @return
  */
-struct rspamd_http_connection *
-rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx, const rspamd_inet_addr_t *addr, const gchar *host,
-									bool is_ssl);
+struct rspamd_http_connection * rspamd_http_context_check_keepalive(struct rspamd_http_context *ctx,
+		const rspamd_inet_addr_t *addr,
+		const gchar *host,
+		bool is_ssl);
+
+/**
+ * Checks if there is a valid keepalive connection
+ * @param ctx
+ * @param addr
+ * @param host
+ * @param is_ssl
+ * @return
+ */
+const rspamd_inet_addr_t *rspamd_http_context_has_keepalive(struct rspamd_http_context *ctx,
+									   const gchar *host,
+									   unsigned port,
+									   bool is_ssl);
 
 /**
  * Prepares keepalive key for a connection by creating a new entry or by reusing existent
diff --git a/src/libserver/http/http_private.h b/src/libserver/http/http_private.h
index c6a5b497b..0e48d9f3c 100644
--- a/src/libserver/http/http_private.h
+++ b/src/libserver/http/http_private.h
@@ -87,6 +87,7 @@ struct rspamd_keepalive_hash_key {
 	rspamd_inet_addr_t *addr;
 	gchar *host;
 	gboolean is_ssl;
+	unsigned port;
 	GQueue conns;
 };
 
diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c
index 1fee9e313..85aa04e1f 100644
--- a/src/lua/lua_http.c
+++ b/src/lua/lua_http.c
@@ -389,6 +389,7 @@ lua_http_make_connection (struct lua_http_cbdata *cbd)
 {
 	rspamd_inet_address_set_port (cbd->addr, cbd->msg->port);
 	unsigned http_opts = RSPAMD_HTTP_CLIENT_SIMPLE;
+	struct rspamd_http_message *msg = cbd->msg;
 
 	if (cbd->msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL) {
 		http_opts |= RSPAMD_HTTP_CLIENT_SSL;
@@ -1036,20 +1037,6 @@ lua_http_request (lua_State *L)
 	}
 
 
-	const rspamd_ftok_t *host_header_tok = rspamd_http_message_find_header (msg, "Host");
-	if (host_header_tok != NULL) {
-		if (msg->host) {
-			g_string_free (msg->host, true);
-		}
-		msg->host = g_string_new_len (host_header_tok->begin, host_header_tok->len);
-		cbd->host = msg->host->str;
-	}
-	else {
-		if (msg->host) {
-			cbd->host = msg->host->str;
-		}
-	}
-
 	if (body) {
 		if (gzip) {
 			if (rspamd_fstring_gzip (&body)) {
@@ -1064,8 +1051,31 @@ lua_http_request (lua_State *L)
 		cbd->session = session;
 	}
 
-	if (msg->host && rspamd_parse_inet_address (&cbd->addr,
-			msg->host->str, msg->host->len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
+	bool numeric_ip = false;
+
+	/* Check if we can skip resolving */
+	if (msg->host) {
+		cbd->host = msg->host->str;
+
+		if (cbd->flags & RSPAMD_LUA_HTTP_FLAG_KEEP_ALIVE) {
+			const rspamd_inet_addr_t *ka_addr = rspamd_http_context_has_keepalive(NULL,
+					msg->host->str, msg->port, msg->flags & RSPAMD_HTTP_FLAG_WANT_SSL);
+
+			if (ka_addr) {
+				cbd->addr = rspamd_inet_address_copy(ka_addr);
+				numeric_ip = true;
+			}
+		}
+
+		if (!cbd->addr) {
+			if (rspamd_parse_inet_address (&cbd->addr,
+					msg->host->str, msg->host->len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
+				numeric_ip = true;
+			}
+		}
+	}
+
+	if (numeric_ip) {
 		/* Host is numeric IP, no need to resolve */
 		gboolean ret;
 


More information about the Commits mailing list