@@ -1489,6 +1489,7 @@ rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted, | |||
{ | |||
gchar datebuf[64]; | |||
gint meth_len = 0; | |||
const gchar *conn_type = "close"; | |||
if (conn->type == RSPAMD_HTTP_SERVER) { | |||
/* Format reply */ | |||
@@ -1619,6 +1620,10 @@ rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted, | |||
} | |||
} | |||
else { | |||
if (conn->opts & RSPAMD_HTTP_CLIENT_KEEP_ALIVE) { | |||
conn_type = "keep-alive"; | |||
} | |||
/* Format request */ | |||
enclen += msg->url->len + strlen (http_method_str (msg->method)) + 1; | |||
@@ -1629,14 +1634,20 @@ rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted, | |||
"%s %s HTTP/1.0\r\n" | |||
"Content-Length: %z\r\n" | |||
"Content-Type: application/octet-stream\r\n", | |||
"Connection: %s\r\n", | |||
"POST", | |||
"/post", enclen); | |||
"/post", | |||
enclen, | |||
conn_type); | |||
} | |||
else { | |||
rspamd_printf_fstring (buf, | |||
"%s %V HTTP/1.0\r\n" | |||
"Content-Length: %z\r\n", | |||
http_method_str (msg->method), msg->url, bodylen); | |||
"Content-Length: %z\r\n" | |||
"Connection: %s\r\n", | |||
http_method_str (msg->method), msg->url, bodylen, | |||
conn_type); | |||
if (bodylen > 0) { | |||
if (mime_type == NULL) { | |||
mime_type = "text/plain"; | |||
@@ -1653,38 +1664,53 @@ rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted, | |||
if (host != NULL) { | |||
rspamd_printf_fstring (buf, | |||
"%s %s HTTP/1.1\r\n" | |||
"Connection: close\r\n" | |||
"Connection: %s\r\n" | |||
"Host: %s\r\n" | |||
"Content-Length: %z\r\n" | |||
"Content-Type: application/octet-stream\r\n", | |||
"POST", "/post", host, enclen); | |||
"POST", | |||
"/post", | |||
conn_type, | |||
host, | |||
enclen); | |||
} | |||
else { | |||
rspamd_printf_fstring (buf, | |||
"%s %s HTTP/1.1\r\n" | |||
"Connection: close\r\n" | |||
"Connection: %s\r\n" | |||
"Host: %V\r\n" | |||
"Content-Length: %z\r\n" | |||
"Content-Type: application/octet-stream\r\n", | |||
"POST", "/post", msg->host, enclen); | |||
"POST", | |||
"/post", | |||
conn_type, | |||
msg->host, | |||
enclen); | |||
} | |||
} | |||
else { | |||
if (host != NULL) { | |||
rspamd_printf_fstring (buf, | |||
"%s %V HTTP/1.1\r\nConnection: close\r\n" | |||
"%s %V HTTP/1.1\r\n" | |||
"Connection: %s\r\n" | |||
"Host: %s\r\n" | |||
"Content-Length: %z\r\n", | |||
http_method_str (msg->method), msg->url, host, | |||
http_method_str (msg->method), | |||
msg->url, | |||
conn_type, | |||
host, | |||
bodylen); | |||
} | |||
else { | |||
rspamd_printf_fstring (buf, | |||
"%s %V HTTP/1.1\r\n" | |||
"Connection: close\r\n" | |||
"Connection: %s\r\n" | |||
"Host: %V\r\n" | |||
"Content-Length: %z\r\n", | |||
http_method_str (msg->method), msg->url, msg->host, | |||
http_method_str (msg->method), | |||
msg->url, | |||
conn_type, | |||
msg->host, | |||
bodylen); | |||
} | |||
@@ -29,6 +29,7 @@ | |||
#include "ref.h" | |||
#include "http_message.h" | |||
#include "http_util.h" | |||
#include "addr.h" | |||
#include <event.h> | |||
@@ -73,10 +74,6 @@ struct rspamd_storage_shmem { | |||
* Do not verify server's certificate | |||
*/ | |||
#define RSPAMD_HTTP_FLAG_SSL_NOVERIFY (1 << 6) | |||
/** | |||
* Do not verify server's certificate | |||
*/ | |||
#define RSPAMD_HTTP_FLAG_KEEPALIVE (1 << 7) | |||
/** | |||
* Options for HTTP connection | |||
*/ | |||
@@ -132,6 +129,14 @@ struct rspamd_http_connection *rspamd_http_connection_new ( | |||
unsigned opts, | |||
enum rspamd_http_connection_type type); | |||
struct rspamd_http_connection *rspamd_http_connection_new_keepalive ( | |||
struct rspamd_http_context *ctx, | |||
rspamd_http_body_handler_t body_handler, | |||
rspamd_http_error_handler_t error_handler, | |||
rspamd_http_finish_handler_t finish_handler, | |||
rspamd_inet_addr_t *addr, | |||
const gchar *host); | |||
/** | |||
* Set key pointed by an opaque pointer |
@@ -207,4 +207,35 @@ rspamd_http_context_default (void) | |||
g_assert (default_ctx != NULL); | |||
return default_ctx; | |||
} | |||
gint32 | |||
rspamd_keep_alive_key_hash (struct rspamd_keepalive_hash_key k) | |||
{ | |||
gint32 h; | |||
h = rspamd_inet_address_port_hash (k.addr); | |||
if (k.host) { | |||
h = rspamd_cryptobox_fast_hash (k.host, strlen (k.host), h); | |||
} | |||
return h; | |||
} | |||
bool | |||
rspamd_keep_alive_key_equal (struct rspamd_keepalive_hash_key k1, | |||
struct rspamd_keepalive_hash_key k2) | |||
{ | |||
if (k1.host && k2.host) { | |||
if (rspamd_inet_address_port_equal (k1.addr, k2.addr)) { | |||
return strcmp (k1.host, k2.host); | |||
} | |||
} | |||
else if (!k1.host && !k2.host) { | |||
return rspamd_inet_address_port_equal (k1.addr, k2.addr); | |||
} | |||
/* One has host and another has no host */ | |||
return false; | |||
} |
@@ -22,6 +22,7 @@ | |||
#include "keypair.h" | |||
#include "keypairs_cache.h" | |||
#include "ref.h" | |||
#include "khash.h" | |||
#define HASH_CASELESS | |||
#include "uthash_strcase.h" | |||
@@ -76,6 +77,18 @@ struct rspamd_http_message { | |||
ref_entry_t ref; | |||
}; | |||
struct rspamd_keepalive_hash_key { | |||
rspamd_inet_addr_t *addr; | |||
gchar *host; | |||
}; | |||
gint32 rspamd_keep_alive_key_hash (struct rspamd_keepalive_hash_key k); | |||
bool rspamd_keep_alive_key_equal (struct rspamd_keepalive_hash_key k1, | |||
struct rspamd_keepalive_hash_key k2); | |||
KHASH_INIT (rspamd_keep_alive_hash, struct rspamd_keepalive_hash_key, | |||
GQueue, true, rspamd_keep_alive_key_hash, rspamd_keep_alive_key_equal); | |||
struct rspamd_http_context { | |||
struct rspamd_http_context_cfg config; | |||
struct rspamd_keypair_cache *client_kp_cache; | |||
@@ -85,6 +98,7 @@ struct rspamd_http_context { | |||
gpointer ssl_ctx_noverify; | |||
struct event_base *ev_base; | |||
struct event client_rotate_ev; | |||
khash_t (rspamd_keep_alive_hash) *keep_alive_hash; | |||
}; | |||
#define HTTP_ERROR http_error_quark () |