summaryrefslogtreecommitdiff
path: root/lib/transfer.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2018-04-19 20:03:30 +0200
committerDaniel Stenberg <daniel@haxx.se>2018-04-20 22:19:23 +0200
commitd122df5972fc01e39ae28e6bca705237d7e3318a (patch)
treed9e4fb9758169cf53c59789635dcd5640657b4bb /lib/transfer.c
parent7645c6bd5ea6c337414a264b37f50995b0f9e7d2 (diff)
downloadcurl-d122df5972fc01e39ae28e6bca705237d7e3318a.tar.gz
http2: handle GOAWAY properly
When receiving REFUSED_STREAM, mark the connection for close and retry streams accordingly on another/fresh connection. Reported-by: Terry Wu Fixes #2416 Fixes #1618 Closes #2510
Diffstat (limited to 'lib/transfer.c')
-rw-r--r--lib/transfer.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/lib/transfer.c b/lib/transfer.c
index b5614f55f..9712a7f7e 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -1926,7 +1926,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
char **url)
{
struct Curl_easy *data = conn->data;
-
+ bool retry = FALSE;
*url = NULL;
/* if we're talking upload, we can't do the checks below, unless the protocol
@@ -1939,7 +1939,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
conn->bits.reuse &&
(!data->set.opt_no_body
|| (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
- (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ (data->set.rtspreq != RTSPREQ_RECEIVE))
/* We got no data, we attempted to re-use a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
@@ -1947,6 +1947,19 @@ CURLcode Curl_retry_request(struct connectdata *conn,
This might happen if the connection was left alive when we were
done using it before, but that was closed when we wanted to read from
it again. Bad luck. Retry the same request on a fresh connect! */
+ retry = TRUE;
+ else if(data->state.refused_stream &&
+ (data->req.bytecount + data->req.headerbytecount == 0) ) {
+ /* This was sent on a refused stream, safe to rerun. A refused stream
+ error can typically only happen on HTTP/2 level if the stream is safe
+ to issue again, but the nghttp2 API can deliver the message to other
+ streams as well, which is why this adds the check the data counters
+ too. */
+ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ data->state.refused_stream = FALSE; /* clear again */
+ retry = TRUE;
+ }
+ if(retry) {
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)