aboutsummaryrefslogtreecommitdiff
path: root/lib/multi.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2016-03-29 23:56:22 +0200
committerDaniel Stenberg <daniel@haxx.se>2016-03-30 07:52:28 +0200
commit93935c08c1b85482bc86bd6adcc33c1d924eed5e (patch)
tree73ccb34d183d88c546e8e083866f4c3965aa0392 /lib/multi.c
parent6b61d8160d7d251e4da9ad8e05bed131e072d47f (diff)
multi: multi_reconnect_request is the former Curl_reconnect_request
now a file local function in multi.c
Diffstat (limited to 'lib/multi.c')
-rw-r--r--lib/multi.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/lib/multi.c b/lib/multi.c
index 3856a7ac2..e88d7d492 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -990,6 +990,62 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
return rc;
}
+static CURLcode multi_reconnect_request(struct connectdata **connp)
+{
+ CURLcode result = CURLE_OK;
+ struct connectdata *conn = *connp;
+ struct SessionHandle *data = conn->data;
+
+ /* This was a re-use of a connection and we got a write error in the
+ * DO-phase. Then we DISCONNECT this connection and have another attempt to
+ * CONNECT and then DO again! The retry cannot possibly find another
+ * connection to re-use, since we only keep one possible connection for
+ * each. */
+
+ infof(data, "Re-used connection seems dead, get a new one\n");
+
+ connclose(conn, "Reconnect dead connection"); /* enforce close */
+ result = Curl_done(&conn, result, FALSE); /* we are so done with this */
+
+ /* conn may no longer be a good pointer, clear it to avoid mistakes by
+ parent functions */
+ *connp = NULL;
+
+ /*
+ * According to bug report #1330310. We need to check for CURLE_SEND_ERROR
+ * here as well. I figure this could happen when the request failed on a FTP
+ * connection and thus Curl_done() itself tried to use the connection
+ * (again). Slight Lack of feedback in the report, but I don't think this
+ * extra check can do much harm.
+ */
+ if(!result || (CURLE_SEND_ERROR == result)) {
+ bool async;
+ bool protocol_done = TRUE;
+
+ /* Now, redo the connect and get a new connection */
+ result = Curl_connect(data, connp, &async, &protocol_done);
+ if(!result) {
+ /* We have connected or sent away a name resolve query fine */
+
+ conn = *connp; /* setup conn to again point to something nice */
+ if(async) {
+ /* Now, if async is TRUE here, we need to wait for the name
+ to resolve */
+ result = Curl_resolver_wait_resolv(conn, NULL);
+ if(result)
+ return result;
+
+ /* Resolved, continue with the connection */
+ result = Curl_async_resolved(conn, &protocol_done);
+ if(result)
+ return result;
+ }
+ }
+ }
+
+ return result;
+}
+
/*
* do_complete is called when the DO actions are complete.
*
@@ -1022,11 +1078,11 @@ static CURLcode multi_do(struct connectdata **connp, bool *done)
* figure out how to re-establish the connection.
*/
if(!data->multi) {
- result = Curl_reconnect_request(connp);
+ result = multi_reconnect_request(connp);
if(!result) {
/* ... finally back to actually retry the DO phase */
- conn = *connp; /* re-assign conn since Curl_reconnect_request
+ conn = *connp; /* re-assign conn since multi_reconnect_request
creates a new connection */
result = conn->handler->do_it(conn, done);
}