From 7fd6b2b76699f3456f6b06ab1ee1d0bb6d8d9069 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 5 Jan 2022 21:36:58 +0000 Subject: [PATCH] [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 -- 2.39.5