http2: close the http2 connection when no more requests may be sent
Well-behaving HTTP2 servers send two GOAWAY messages. The first message is a warning that indicates that the server is going to stop accepting streams. The second one actually closes the stream. nghttp2 reports this state (and the other state of no more stream identifiers) via the call nghttp2_session_check_request_allowed(). In this state the client should not create more streams on the session (tcp connection), and in curl this means that the server has requested that the connection is closed. It would be also be possible to put the connclose() call into the on_http2_frame_recv() function that triggers on the GOAWAY message. This fixes a bug seen when the client sees the following sequence of frames: // advisory GOAWAY HTTP2 GOAWAY [stream-id = 0, promised-stream-id = -1] ... some additional frames // final GOAWAY HTTP2 GOAWAY [stream-id = 0, promised-stream-id = N ] Before this change, curl will attempt to reuse the connection even after the last stream, will encounter this error: * Found bundle for host localhost: 0x5595f0a694e0 [can multiplex] * Re-using existing connection! (#0) with host localhost * Connected to localhost (::1) port 10443 (#0) * Using Stream ID: 9 (easy handle 0x5595f0a72e30) > GET /index.html?5 HTTP/2 > Host: localhost:10443 > user-agent: curl/7.68.0 > accept: */* > * stopped the pause stream! * Connection #0 to host localhost left intact curl: (16) Error in the HTTP2 framing layer This error may posion the connection cache, causing future requests which resolve to the same curl connection to go through the same error path. Closes #5643
This commit is contained in:
Родитель
1535363e72
Коммит
ef86daf4d3
10
lib/http2.c
10
lib/http2.c
|
@ -1203,6 +1203,13 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
|
|||
}
|
||||
http->stream_id = 0;
|
||||
}
|
||||
|
||||
if(0 == nghttp2_session_check_request_allowed(httpc->h2)) {
|
||||
/* No more requests are allowed in the current session, so the connection
|
||||
may not be reused. This is set when a GOAWAY frame has been received or
|
||||
when the limit of stream identifiers has been reached. */
|
||||
connclose(data->conn, "http/2: No new requests allowed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2075,6 +2082,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
|
|||
|
||||
h2_pri_spec(conn->data, &pri_spec);
|
||||
|
||||
H2BUGF(infof(conn->data, "http2_send request allowed %d (easy handle %p)\n",
|
||||
nghttp2_session_check_request_allowed(h2), (void *)conn->data));
|
||||
|
||||
switch(conn->data->state.httpreq) {
|
||||
case HTTPREQ_POST:
|
||||
case HTTPREQ_POST_FORM:
|
||||
|
|
Загрузка…
Ссылка в новой задаче