From 93935c08c1b85482bc86bd6adcc33c1d924eed5e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 29 Mar 2016 23:56:22 +0200 Subject: multi: multi_reconnect_request is the former Curl_reconnect_request now a file local function in multi.c --- lib/multi.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'lib/multi.c') 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); } -- cgit v1.2.3