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
This commit is contained in:
Daniel Stenberg 2018-04-19 20:03:30 +02:00
parent 7645c6bd5e
commit d122df5972
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
4 changed files with 31 additions and 9 deletions

View file

@ -1106,7 +1106,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
struct http_conn *httpc = &conn->proto.httpc;
if(http->header_recvbuf) {
H2BUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
@ -1376,7 +1375,15 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
if(httpc->error_code != NGHTTP2_NO_ERROR) {
if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
stream->stream_id));
connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
data->state.refused_stream = TRUE;
*err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
return -1;
}
else if(httpc->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
stream->stream_id, Curl_http2_strerror(httpc->error_code),
httpc->error_code);
@ -1604,9 +1611,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
if(nread == 0) {
failf(data, "Unexpected EOF");
*err = CURLE_RECV_ERROR;
return -1;
H2BUGF(infof(data, "end of stream\n"));
*err = CURLE_OK;
return 0;
}
H2BUGF(infof(data, "nread=%zd\n", nread));