From af55b8d80475cc9f064e58c63c30a5dd993b670c Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 26 Jan 2016 18:00:52 +0000 Subject: Try to read from HTTP socket even if we have timeout --- src/libutil/http.c | 96 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/libutil/http.c b/src/libutil/http.c index 340951caf..c05aa9e3b 100644 --- a/src/libutil/http.c +++ b/src/libutil/http.c @@ -922,6 +922,28 @@ call_finish_handler: } } +static gssize +rspamd_http_try_read (gint fd, + struct rspamd_http_connection *conn, + struct rspamd_http_connection_private *priv, + struct _rspamd_http_privbuf *pbuf) +{ + gssize r; + rspamd_fstring_t *buf; + + buf = priv->buf->data; + r = read (fd, buf->str, buf->allocated); + + if (r <= 0) { + return r; + } + else { + buf->len = r; + } + + return r; +} + static void rspamd_http_event_handler (int fd, short what, gpointer ud) { @@ -939,19 +961,22 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) buf = priv->buf->data; if (what == EV_READ) { - r = read (fd, buf->str, buf->allocated); - if (r == -1) { - err = g_error_new (HTTP_ERROR, - errno, - "IO read error: %s", - strerror (errno)); - conn->error_handler (conn, err); - g_error_free (err); + r = rspamd_http_try_read (fd, conn, priv, pbuf); - REF_RELEASE (pbuf); - rspamd_http_connection_unref (conn); + if (r > 0) { + if (http_parser_execute (&priv->parser, &priv->parser_cb, + buf->str, r) != (size_t)r || priv->parser.http_errno != 0) { + err = g_error_new (HTTP_ERROR, priv->parser.http_errno, + "HTTP parser error: %s", + http_errno_description (priv->parser.http_errno)); + conn->error_handler (conn, err); + g_error_free (err); - return; + REF_RELEASE (pbuf); + rspamd_http_connection_unref (conn); + + return; + } } else if (r == 0) { if (!conn->finished) { @@ -969,8 +994,24 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) return; } else { - buf->len = r; + err = g_error_new (HTTP_ERROR, + errno, + "IO read error: %s", + strerror (errno)); + conn->error_handler (conn, err); + g_error_free (err); + + REF_RELEASE (pbuf); + rspamd_http_connection_unref (conn); + + return; + } + } + else if (what == EV_TIMEOUT) { + /* Let's try to read from the socket first */ + r = rspamd_http_try_read (fd, conn, priv, pbuf); + if (r > 0) { if (http_parser_execute (&priv->parser, &priv->parser_cb, buf->str, r) != (size_t)r || priv->parser.http_errno != 0) { err = g_error_new (HTTP_ERROR, priv->parser.http_errno, @@ -985,17 +1026,30 @@ rspamd_http_event_handler (int fd, short what, gpointer ud) return; } } - } - else if (what == EV_TIMEOUT) { - err = g_error_new (HTTP_ERROR, ETIMEDOUT, - "IO timeout"); - conn->error_handler (conn, err); - g_error_free (err); + else if (r == 0) { + if (!conn->finished) { + err = g_error_new (HTTP_ERROR, ETIMEDOUT, + "IO timeout"); + conn->error_handler (conn, err); + g_error_free (err); - REF_RELEASE (pbuf); - rspamd_http_connection_unref (conn); + } + REF_RELEASE (pbuf); + rspamd_http_connection_unref (conn); - return; + return; + } + else { + err = g_error_new (HTTP_ERROR, ETIMEDOUT, + "IO timeout"); + conn->error_handler (conn, err); + g_error_free (err); + + REF_RELEASE (pbuf); + rspamd_http_connection_unref (conn); + + return; + } } else if (what == EV_WRITE) { rspamd_http_write_helper (conn); -- cgit v1.2.3