]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Allow to skip DNS resolution for keep-alive connections
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Dec 2021 14:02:18 +0000 (14:02 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 9 Dec 2021 14:02:18 +0000 (14:02 +0000)
src/libserver/http/http_context.c
src/libserver/http/http_context.h
src/libserver/http/http_private.h
src/lua/lua_http.c

index b56f1c4c08231ca76fc41416781a65b26fb7888c..2dbaff0a4d7342da82b96fafbd9c10b0043d6b23 100644 (file)
@@ -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;
index f42164dba66fedb4630561165f0065b7490f294a..635da7ba59a6b911a589adf91933e70116bd3c04 100644 (file)
@@ -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
index c6a5b497bb2d19d32e4ed03ec49d2cf0172f3bfb..0e48d9f3cad9b0920552c0bec7803cd897fbc6ad 100644 (file)
@@ -87,6 +87,7 @@ struct rspamd_keepalive_hash_key {
        rspamd_inet_addr_t *addr;
        gchar *host;
        gboolean is_ssl;
+       unsigned port;
        GQueue conns;
 };
 
index 1fee9e31343d8c2ee04e5e1488d8867e92990461..85aa04e1f3c715b2847e6848139db4129e066e1d 100644 (file)
@@ -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;