*
* 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 */
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]);
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);
#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, ...);
* 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;
/* 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 */
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;
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 */
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) {
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! */
}
}
-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);
***************************************************************************/
#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
*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 */
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);
/* 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
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;
}
}
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;
}
-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;
/* 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;
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 */
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,
/* 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