From d60c22572b49cde9b839a59510580df079d2d5e2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 12 May 2004 12:06:39 +0000 Subject: [PATCH] Curl_done() and the protocol-specific conn->curl_done() functions now all take a CURLcode as a second argument, that is non-zero when Curl_done() is called after an error was returned from Curl_do() (or similar). --- lib/ftp.c | 33 +++++++++++++++++++++++++-------- lib/ftp.h | 2 +- lib/http.c | 4 +++- lib/http.h | 2 +- lib/multi.c | 8 ++++---- lib/telnet.c | 4 +++- lib/telnet.h | 2 +- lib/transfer.c | 8 +++++--- lib/url.c | 12 +++++++++--- lib/url.h | 2 +- lib/urldata.h | 2 +- 11 files changed, 54 insertions(+), 25 deletions(-) diff --git a/lib/ftp.c b/lib/ftp.c index e4a687884..6287b4fa5 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -738,13 +738,14 @@ CURLcode Curl_ftp_connect(struct connectdata *conn) * * Input argument is already checked for validity. */ -CURLcode Curl_ftp_done(struct connectdata *conn) +CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status) { struct SessionHandle *data = conn->data; struct FTP *ftp = conn->proto.ftp; ssize_t nread; int ftpcode; CURLcode result=CURLE_OK; + bool was_ctl_valid = ftp->ctl_valid; /* free the dir tree and file parts */ @@ -784,8 +785,24 @@ CURLcode Curl_ftp_done(struct connectdata *conn) result = CURLE_FTP_COULDNT_RETR_FILE; } } - - ftp->ctl_valid = was_ctl_valid; + + switch(status) { + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_COULDNT_SET_BINARY: + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_FTP_ACCESS_DENIED: + /* the connection stays alive fine even though this happened */ + /* fall-through */ + case CURLE_OK: /* doesn't affect the control connection's status */ + ftp->ctl_valid = was_ctl_valid; + break; + default: /* by default, an error means the control connection is + wedged and should not be used anymore */ + ftp->ctl_valid = FALSE; + break; + } #ifdef HAVE_KRB4 Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]); @@ -794,12 +811,12 @@ CURLcode Curl_ftp_done(struct connectdata *conn) sclose(conn->sock[SECONDARYSOCKET]); conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; - if(!ftp->no_transfer) { + if(!ftp->no_transfer && !status) { /* Let's see what the server says about the transfer we just performed, - but lower the timeout as sometimes this connection has died while - the data has been transfered. This happens when doing through NATs - etc that abandon old silent connections. - */ + * but lower the timeout as sometimes this connection has died while the + * data has been transfered. This happens when doing through NATs etc that + * abandon old silent connections. + */ ftp->response_time = 60; /* give it only a minute for now */ result = Curl_GetFTPResponse(&nread, conn, &ftpcode); diff --git a/lib/ftp.h b/lib/ftp.h index 3d0ab7dac..dc7cf79c0 100644 --- a/lib/ftp.h +++ b/lib/ftp.h @@ -25,7 +25,7 @@ #ifndef CURL_DISABLE_FTP CURLcode Curl_ftp(struct connectdata *conn); -CURLcode Curl_ftp_done(struct connectdata *conn); +CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode); CURLcode Curl_ftp_connect(struct connectdata *conn); CURLcode Curl_ftp_disconnect(struct connectdata *conn); CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...); diff --git a/lib/http.c b/lib/http.c index 48bffa904..41b0398de 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1172,10 +1172,12 @@ CURLcode Curl_http_connect(struct connectdata *conn) * has been performed. */ -CURLcode Curl_http_done(struct connectdata *conn) +CURLcode Curl_http_done(struct connectdata *conn, + CURLcode status) { struct SessionHandle *data; struct HTTP *http; + (void)status; /* no use for us */ data=conn->data; http=conn->proto.http; diff --git a/lib/http.h b/lib/http.h index 944314a55..2d3b39dca 100644 --- a/lib/http.h +++ b/lib/http.h @@ -35,7 +35,7 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn, /* protocol-specific functions set up to be called by the main engine */ CURLcode Curl_http(struct connectdata *conn); -CURLcode Curl_http_done(struct connectdata *conn); +CURLcode Curl_http_done(struct connectdata *, CURLcode); CURLcode Curl_http_connect(struct connectdata *conn); /* The following functions are defined in http_chunks.c */ diff --git a/lib/multi.c b/lib/multi.c index 0476b1d19..fe03a5dde 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -329,7 +329,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) char *gotourl; Curl_posttransfer(easy->easy_handle); - easy->result = Curl_done(easy->easy_conn); + easy->result = Curl_done(easy->easy_conn, CURLE_OK); if(CURLE_OK == easy->result) { gotourl = strdup(easy->easy_handle->change.url); easy->easy_handle->change.url_changed = FALSE; @@ -491,7 +491,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) easy->easy_conn->sock[SECONDARYSOCKET]=-1; } Curl_posttransfer(easy->easy_handle); - Curl_done(easy->easy_conn); + Curl_done(easy->easy_conn, easy->result); } /* after the transfer is done, go DONE */ @@ -504,7 +504,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) if(easy->easy_conn->newurl) { char *newurl = easy->easy_conn->newurl; easy->easy_conn->newurl = NULL; - easy->result = Curl_done(easy->easy_conn); + easy->result = Curl_done(easy->easy_conn, CURLE_OK); if(easy->result == CURLE_OK) easy->result = Curl_follow(easy->easy_handle, newurl); if(CURLE_OK == easy->result) { @@ -520,7 +520,7 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles) break; case CURLM_STATE_DONE: /* post-transfer command */ - easy->result = Curl_done(easy->easy_conn); + easy->result = Curl_done(easy->easy_conn, CURLE_OK); /* after we have DONE what we're supposed to do, go COMPLETED, and it doesn't matter what the Curl_done() returned! */ diff --git a/lib/telnet.c b/lib/telnet.c index 0408d7320..fb4ba5e00 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -1063,9 +1063,11 @@ void telrcv(struct connectdata *conn, } } -CURLcode Curl_telnet_done(struct connectdata *conn) +CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode status) { struct TELNET *tn = (struct TELNET *)conn->proto.telnet; + (void)status; /* unused */ + curl_slist_free_all(tn->telnet_vars); free(conn->proto.telnet); diff --git a/lib/telnet.h b/lib/telnet.h index 2b6f22bcb..86dd99b6f 100644 --- a/lib/telnet.h +++ b/lib/telnet.h @@ -25,6 +25,6 @@ ***************************************************************************/ #ifndef CURL_DISABLE_TELNET CURLcode Curl_telnet(struct connectdata *conn); -CURLcode Curl_telnet_done(struct connectdata *conn); +CURLcode Curl_telnet_done(struct connectdata *conn, CURLcode); #endif #endif diff --git a/lib/transfer.c b/lib/transfer.c index 67f328971..95dbf568a 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -853,6 +853,8 @@ CURLcode Curl_readwrite(struct connectdata *conn, *ptr = '\0'; /* zero terminate */ conn->newurl = strdup(start); /* clone string */ *ptr = backup; /* restore ending letter */ + if(!conn->newurl) + return CURLE_OUT_OF_MEMORY; } } #if 0 /* for consideration */ @@ -1967,7 +1969,7 @@ CURLcode Curl_perform(struct SessionHandle *data) to the new URL */ urlchanged = data->change.url_changed; if ((CURLE_OK == res) && urlchanged) { - res = Curl_done(conn); + res = Curl_done(conn, res); if(CURLE_OK == res) { char *gotourl = strdup(data->change.url); res = Curl_follow(data, gotourl); @@ -2024,14 +2026,14 @@ CURLcode Curl_perform(struct SessionHandle *data) /* Always run Curl_done(), even if some of the previous calls failed, but return the previous (original) error code */ - res2 = Curl_done(conn); + res2 = Curl_done(conn, res); if(CURLE_OK == res) res = res2; } else /* Curl_do() failed, clean up left-overs in the done-call */ - res2 = Curl_done(conn); + res2 = Curl_done(conn, res); /* * Important: 'conn' cannot be used here, since it may have been closed diff --git a/lib/url.c b/lib/url.c index 2d10998ab..96b02f45a 100644 --- a/lib/url.c +++ b/lib/url.c @@ -3229,6 +3229,8 @@ static CURLcode SetupConnection(struct connectdata *conn, Curl_safefree(conn->allocptr.uagent); conn->allocptr.uagent = aprintf("User-Agent: %s\015\012", data->set.useragent); + if(!conn->allocptr.uagent) + return CURLE_OUT_OF_MEMORY; } } @@ -3236,6 +3238,8 @@ static CURLcode SetupConnection(struct connectdata *conn, Curl_safefree(conn->allocptr.accept_encoding); conn->allocptr.accept_encoding = aprintf("Accept-Encoding: %s\015\012", data->set.encoding); + if(!conn->allocptr.accept_encoding) + return CURLE_OUT_OF_MEMORY; } conn->bytecount = 0; @@ -3340,7 +3344,9 @@ CURLcode Curl_async_resolved(struct connectdata *conn) } -CURLcode Curl_done(struct connectdata *conn) +CURLcode Curl_done(struct connectdata *conn, + CURLcode status) /* an error if this is called after an + error was detected */ { struct SessionHandle *data=conn->data; CURLcode result; @@ -3371,7 +3377,7 @@ CURLcode Curl_done(struct connectdata *conn) /* this calls the protocol-specific function pointer previously set */ if(conn->curl_done) - result = conn->curl_done(conn); + result = conn->curl_done(conn, status); else result = CURLE_OK; @@ -3423,7 +3429,7 @@ CURLcode Curl_do(struct connectdata **connp) infof(data, "Re-used connection seems dead, get a new one\n"); conn->bits.close = TRUE; /* enforce close of this connection */ - result = Curl_done(conn); /* we are so done with this */ + result = Curl_done(conn, result); /* we are so done with this */ /* conn is no longer a good pointer */ diff --git a/lib/url.h b/lib/url.h index 170c107db..ff7951333 100644 --- a/lib/url.h +++ b/lib/url.h @@ -35,7 +35,7 @@ CURLcode Curl_connect(struct SessionHandle *, struct connectdata **, CURLcode Curl_async_resolved(struct connectdata *conn); CURLcode Curl_do(struct connectdata **); CURLcode Curl_do_more(struct connectdata *); -CURLcode Curl_done(struct connectdata *); +CURLcode Curl_done(struct connectdata *, CURLcode); CURLcode Curl_disconnect(struct connectdata *); CURLcode Curl_protocol_connect(struct connectdata *conn); bool Curl_ssl_config_matches(struct ssl_config_data* data, diff --git a/lib/urldata.h b/lib/urldata.h index f50026a09..643d3e7d3 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -482,7 +482,7 @@ struct connectdata { /* These two functions MUST be set by the curl_connect() function to be be protocol dependent */ CURLcode (*curl_do)(struct connectdata *); - CURLcode (*curl_done)(struct connectdata *); + CURLcode (*curl_done)(struct connectdata *, CURLcode); /* If the curl_do() function is better made in two halves, this * curl_do_more() function will be called afterwards, if set. For example