commit 7fd6b2b: [Fix] Fix HTTP(s) client timeout

Vsevolod Stakhov vsevolod at highsecure.ru
Wed Jan 5 21:42:05 UTC 2022


Author: Vsevolod Stakhov
Date: 2022-01-05 21:36:58 +0000
URL: https://github.com/rspamd/rspamd/commit/7fd6b2b76699f3456f6b06ab1ee1d0bb6d8d9069 (HEAD -> master)

[Fix] Fix HTTP(s) client timeout

---
 src/libserver/http/http_connection.c | 88 +++++++++++++++++++-----------------
 src/libserver/ssl_util.c             |  5 +-
 src/libserver/ssl_util.h             |  3 +-
 3 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/src/libserver/http/http_connection.c b/src/libserver/http/http_connection.c
index afd685ae0..d24732819 100644
--- a/src/libserver/http/http_connection.c
+++ b/src/libserver/http/http_connection.c
@@ -91,6 +91,8 @@ static const rspamd_ftok_t last_modified_header = {
 		.len = 13
 };
 
+static void rspamd_http_event_handler (int fd, short what, gpointer ud);
+static void rspamd_http_ssl_err_handler (gpointer ud, GError *err);
 
 
 #define HTTP_ERROR http_error_quark ()
@@ -1030,54 +1032,48 @@ rspamd_http_event_handler (int fd, short what, gpointer ud)
 		}
 	}
 	else if (what == EV_TIMEOUT) {
-		/* Let's try to read from the socket first */
-		r = rspamd_http_try_read (fd, conn, priv, pbuf, &d);
+		if (!priv->ssl) {
+			/* Let's try to read from the socket first */
+			r = rspamd_http_try_read(fd, conn, priv, pbuf, &d);
+
+			if (r > 0) {
+				if (http_parser_execute(&priv->parser, &priv->parser_cb,
+						d, r) != (size_t) r || priv->parser.http_errno != 0) {
+					err = g_error_new(HTTP_ERROR, 400,
+							"HTTP parser error: %s",
+							http_errno_description(priv->parser.http_errno));
+
+					if (!conn->finished) {
+						conn->error_handler(conn, err);
+					}
+					else {
+						msg_err ("got error after HTTP request is finished: %e", err);
+					}
 
-		if (r > 0) {
-			if (http_parser_execute (&priv->parser, &priv->parser_cb,
-					d, r) != (size_t)r || priv->parser.http_errno != 0) {
-				err = g_error_new (HTTP_ERROR, 400,
-						"HTTP parser error: %s",
-						http_errno_description (priv->parser.http_errno));
+					g_error_free(err);
 
-				if (!conn->finished) {
-					conn->error_handler (conn, err);
-				}
-				else {
-					msg_err ("got error after HTTP request is finished: %e", err);
-				}
+					REF_RELEASE (pbuf);
+					rspamd_http_connection_unref(conn);
 
-				g_error_free (err);
+					return;
+				}
+			}
+			else {
+				err = g_error_new(HTTP_ERROR, 408,
+						"IO timeout");
+				conn->error_handler(conn, err);
+				g_error_free(err);
 
 				REF_RELEASE (pbuf);
-				rspamd_http_connection_unref (conn);
+				rspamd_http_connection_unref(conn);
 
 				return;
 			}
 		}
-		else if (r == 0) {
-			if (!conn->finished && !priv->ssl) {
-				err = g_error_new (HTTP_ERROR, 408,
-						"IO timeout");
-				conn->error_handler (conn, err);
-				g_error_free (err);
-
-			}
-			REF_RELEASE (pbuf);
-			rspamd_http_connection_unref (conn);
-
-			return;
-		}
 		else {
-			if (!priv->ssl) {
-				err = g_error_new(HTTP_ERROR, 408,
-						"IO timeout");
-				conn->error_handler(conn, err);
-				g_error_free(err);
-			}
-
+			/* In case of SSL we disable this logic as we already came from SSL handler */
 			REF_RELEASE (pbuf);
-			rspamd_http_connection_unref (conn);
+			rspamd_http_connection_unref(conn);
 
 			return;
 		}
@@ -1536,9 +1532,18 @@ rspamd_http_connection_read_message_common (struct rspamd_http_connection *conn,
 	priv->buf->data = rspamd_fstring_sized_new (8192);
 	priv->flags |= RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
 
-	rspamd_ev_watcher_init (&priv->ev, conn->fd, EV_READ,
-			rspamd_http_event_handler, conn);
-	rspamd_ev_watcher_start (priv->ctx->event_loop, &priv->ev, priv->timeout);
+	if (!priv->ssl) {
+		rspamd_ev_watcher_init(&priv->ev, conn->fd, EV_READ,
+				rspamd_http_event_handler, conn);
+		rspamd_ev_watcher_start(priv->ctx->event_loop, &priv->ev, priv->timeout);
+	}
+	else {
+		rspamd_ssl_connection_restore_handlers (priv->ssl,
+				rspamd_http_event_handler,
+				rspamd_http_ssl_err_handler,
+				conn,
+				EV_READ);
+	}
 
 	priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
 }
@@ -2351,7 +2356,8 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn
 				rspamd_ssl_connection_restore_handlers (priv->ssl,
 						rspamd_http_event_handler,
 						rspamd_http_ssl_err_handler,
-						conn);
+						conn,
+						EV_WRITE);
 			}
 		}
 	}
diff --git a/src/libserver/ssl_util.c b/src/libserver/ssl_util.c
index 319e87a04..0aa859dbf 100644
--- a/src/libserver/ssl_util.c
+++ b/src/libserver/ssl_util.c
@@ -760,14 +760,15 @@ void
 rspamd_ssl_connection_restore_handlers (struct rspamd_ssl_connection *conn,
 										rspamd_ssl_handler_t handler,
 										rspamd_ssl_error_handler_t err_handler,
-										gpointer handler_data)
+										gpointer handler_data,
+										short ev_what)
 {
 	conn->handler = handler;
 	conn->err_handler = err_handler;
 	conn->handler_data = handler_data;
 
 	rspamd_ev_watcher_stop (conn->event_loop, conn->ev);
-	rspamd_ev_watcher_init (conn->ev, conn->fd, EV_WRITE, rspamd_ssl_event_handler, conn);
+	rspamd_ev_watcher_init (conn->ev, conn->fd, ev_what, rspamd_ssl_event_handler, conn);
 	rspamd_ev_watcher_start (conn->event_loop, conn->ev, conn->ev->timeout);
 }
 
diff --git a/src/libserver/ssl_util.h b/src/libserver/ssl_util.h
index f2d591b56..7c804421f 100644
--- a/src/libserver/ssl_util.h
+++ b/src/libserver/ssl_util.h
@@ -66,7 +66,8 @@ gboolean rspamd_ssl_connect_fd (struct rspamd_ssl_connection *conn, gint fd,
 void rspamd_ssl_connection_restore_handlers (struct rspamd_ssl_connection *conn,
 											 rspamd_ssl_handler_t handler,
 											 rspamd_ssl_error_handler_t err_handler,
-											 gpointer handler_data);
+											 gpointer handler_data,
+											 short ev_what);
 
 /**
  * Perform async read from SSL socket


More information about the Commits mailing list