From 154a17b6ee5097642e2330fb14ba52e317b95430 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 14 Dec 2018 09:21:47 +0100 Subject: [PATCH] pingpong: ignore regular timeout in disconnect phase The timeout set with CURLOPT_TIMEOUT is no longer used when disconnecting from one of the pingpong protocols (FTP, IMAP, SMTP, POP3). Reported-by: jasal82 on github Fixes #3264 Closes #3374 --- lib/ftp.c | 6 +++--- lib/imap.c | 11 ++++++----- lib/pingpong.c | 9 +++++---- lib/pingpong.h | 7 ++++--- lib/pop3.c | 9 +++++---- lib/smtp.c | 11 ++++++----- 6 files changed, 29 insertions(+), 24 deletions(-) diff --git a/lib/ftp.c b/lib/ftp.c index 581df09d7..c5f954000 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -655,7 +655,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ while(!*ftpcode && !result) { /* check and reset timeout value every lap */ - time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */ + time_t timeout = Curl_pp_state_timeout(pp, FALSE); time_t interval_ms; if(timeout <= 0) { @@ -3054,7 +3054,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done) { struct ftp_conn *ftpc = &conn->proto.ftpc; - CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE); + CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE); /* Check for the state outside of the Curl_socket_check() return code checks since at times we are in fact already in this state when this function @@ -3071,7 +3071,7 @@ static CURLcode ftp_block_statemach(struct connectdata *conn) CURLcode result = CURLE_OK; while(ftpc->state != FTP_STOP) { - result = Curl_pp_statemach(pp, TRUE); + result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */); if(result) break; } diff --git a/lib/imap.c b/lib/imap.c index a8320e3f1..161b28983 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -1362,19 +1362,20 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) return result; } - result = Curl_pp_statemach(&imapc->pp, FALSE); + result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE); *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE; return result; } -static CURLcode imap_block_statemach(struct connectdata *conn) +static CURLcode imap_block_statemach(struct connectdata *conn, + bool disconnecting) { CURLcode result = CURLE_OK; struct imap_conn *imapc = &conn->proto.imapc; while(imapc->state != IMAP_STOP && !result) - result = Curl_pp_statemach(&imapc->pp, TRUE); + result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting); return result; } @@ -1497,7 +1498,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status, non-blocking DONE operations! */ if(!result) - result = imap_block_statemach(conn); + result = imap_block_statemach(conn, FALSE); } /* Cleanup our per-request based variables */ @@ -1635,7 +1636,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection) point! */ if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart) if(!imap_perform_logout(conn)) - (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */ + (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */ /* Disconnect from the server */ Curl_pp_disconnect(&imapc->pp); diff --git a/lib/pingpong.c b/lib/pingpong.c index 2e93d201f..e9568ee3d 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -44,7 +44,7 @@ /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -time_t Curl_pp_state_timeout(struct pingpong *pp) +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting) { struct connectdata *conn = pp->conn; struct Curl_easy *data = conn->data; @@ -62,7 +62,7 @@ time_t Curl_pp_state_timeout(struct pingpong *pp) timeout_ms = response_time - Curl_timediff(Curl_now(), pp->response); /* spent time */ - if(data->set.timeout) { + if(data->set.timeout && !disconnecting) { /* if timeout is requested, find out how much remaining time we have */ time_t timeout2_ms = data->set.timeout - /* timeout time */ Curl_timediff(Curl_now(), conn->now); /* spent time */ @@ -77,13 +77,14 @@ time_t Curl_pp_state_timeout(struct pingpong *pp) /* * Curl_pp_statemach() */ -CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting) { struct connectdata *conn = pp->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; time_t interval_ms; - time_t timeout_ms = Curl_pp_state_timeout(pp); + time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting); struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; diff --git a/lib/pingpong.h b/lib/pingpong.h index 5ac8df876..dbe1f8d3d 100644 --- a/lib/pingpong.h +++ b/lib/pingpong.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -81,14 +81,15 @@ struct pingpong { * called repeatedly until done. Set 'wait' to make it wait a while on the * socket if there's no traffic. */ -CURLcode Curl_pp_statemach(struct pingpong *pp, bool block); +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting); /* initialize stuff to prepare for reading a fresh new response */ void Curl_pp_init(struct pingpong *pp); /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -time_t Curl_pp_state_timeout(struct pingpong *pp); +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); /*********************************************************************** diff --git a/lib/pop3.c b/lib/pop3.c index 05853f001..d755e81e0 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -1025,19 +1025,20 @@ static CURLcode pop3_multi_statemach(struct connectdata *conn, bool *done) return result; } - result = Curl_pp_statemach(&pop3c->pp, FALSE); + result = Curl_pp_statemach(&pop3c->pp, FALSE, FALSE); *done = (pop3c->state == POP3_STOP) ? TRUE : FALSE; return result; } -static CURLcode pop3_block_statemach(struct connectdata *conn) +static CURLcode pop3_block_statemach(struct connectdata *conn, + bool disconnecting) { CURLcode result = CURLE_OK; struct pop3_conn *pop3c = &conn->proto.pop3c; while(pop3c->state != POP3_STOP && !result) - result = Curl_pp_statemach(&pop3c->pp, TRUE); + result = Curl_pp_statemach(&pop3c->pp, TRUE, disconnecting); return result; } @@ -1235,7 +1236,7 @@ static CURLcode pop3_disconnect(struct connectdata *conn, bool dead_connection) point! */ if(!dead_connection && pop3c->pp.conn && pop3c->pp.conn->bits.protoconnstart) if(!pop3_perform_quit(conn)) - (void)pop3_block_statemach(conn); /* ignore errors on QUIT */ + (void)pop3_block_statemach(conn, TRUE); /* ignore errors on QUIT */ /* Disconnect from the server */ Curl_pp_disconnect(&pop3c->pp); diff --git a/lib/smtp.c b/lib/smtp.c index 587562306..84fc68e41 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -1080,19 +1080,20 @@ static CURLcode smtp_multi_statemach(struct connectdata *conn, bool *done) return result; } - result = Curl_pp_statemach(&smtpc->pp, FALSE); + result = Curl_pp_statemach(&smtpc->pp, FALSE, FALSE); *done = (smtpc->state == SMTP_STOP) ? TRUE : FALSE; return result; } -static CURLcode smtp_block_statemach(struct connectdata *conn) +static CURLcode smtp_block_statemach(struct connectdata *conn, + bool disconnecting) { CURLcode result = CURLE_OK; struct smtp_conn *smtpc = &conn->proto.smtpc; while(smtpc->state != SMTP_STOP && !result) - result = Curl_pp_statemach(&smtpc->pp, TRUE); + result = Curl_pp_statemach(&smtpc->pp, TRUE, disconnecting); return result; } @@ -1253,7 +1254,7 @@ static CURLcode smtp_done(struct connectdata *conn, CURLcode status, the smtp_multi_statemach function but we have no general support for non-blocking DONE operations! */ - result = smtp_block_statemach(conn); + result = smtp_block_statemach(conn, FALSE); } /* Clear the transfer mode for the next request */ @@ -1360,7 +1361,7 @@ static CURLcode smtp_disconnect(struct connectdata *conn, bool dead_connection) point! */ if(!dead_connection && smtpc->pp.conn && smtpc->pp.conn->bits.protoconnstart) if(!smtp_perform_quit(conn)) - (void)smtp_block_statemach(conn); /* ignore errors on QUIT */ + (void)smtp_block_statemach(conn, TRUE); /* ignore errors on QUIT */ /* Disconnect from the server */ Curl_pp_disconnect(&smtpc->pp);