summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/http2.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-12-09 16:45:25 (GMT)
committerBrad King <brad.king@kitware.com>2020-12-09 16:45:25 (GMT)
commit54931fdff020f72bbd157fd1640a0fef52e4f183 (patch)
tree31e7f9ea89fb8ab0e17fe17efd881ea947962a4a /Utilities/cmcurl/lib/http2.c
parent4cd65e5d882333e48155cf8b5bb52d088aa63cdf (diff)
parent5aacc593a961fe9ee1427c03d18fba8947a9e33d (diff)
downloadCMake-54931fdff020f72bbd157fd1640a0fef52e4f183.zip
CMake-54931fdff020f72bbd157fd1640a0fef52e4f183.tar.gz
CMake-54931fdff020f72bbd157fd1640a0fef52e4f183.tar.bz2
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2020-12-09 (e0528597)
Diffstat (limited to 'Utilities/cmcurl/lib/http2.c')
-rw-r--r--Utilities/cmcurl/lib/http2.c178
1 files changed, 60 insertions, 118 deletions
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index d316da8..b138fb4 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -9,7 +9,7 @@
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -257,7 +257,7 @@ static unsigned int http2_conncheck(struct connectdata *check,
/* called from http_setup_conn */
void Curl_http2_setup_req(struct Curl_easy *data)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
http->bodystarted = FALSE;
http->status_code = -1;
http->pausedata = NULL;
@@ -300,6 +300,7 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_STREAM /* flags */
};
@@ -321,6 +322,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_conncheck, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
+ CURLPROTO_HTTP, /* family */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
@@ -391,7 +393,7 @@ char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num)
if(!h || !GOOD_EASY_HANDLE(h->data))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
if(num < stream->push_headers_used)
return stream->push_headers[num];
}
@@ -413,7 +415,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
!strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
else {
- struct HTTP *stream = h->data->req.protop;
+ struct HTTP *stream = h->data->req.p.http;
size_t len = strlen(header);
size_t i;
for(i = 0; i<stream->push_headers_used; i++) {
@@ -460,7 +462,7 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
(void)Curl_close(&second);
}
else {
- second->req.protop = http;
+ second->req.p.http = http;
Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
Curl_http2_setup_req(second);
second->state.stream_weight = data->state.stream_weight;
@@ -537,7 +539,7 @@ static int push_promise(struct Curl_easy *data,
/* ask the application */
H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
- stream = data->req.protop;
+ stream = data->req.p.http;
if(!stream) {
failf(data, "Internal NULL stream!\n");
(void)Curl_close(&newhandle);
@@ -567,13 +569,13 @@ static int push_promise(struct Curl_easy *data,
if(rv) {
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
/* denied, kill off the new handle again */
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
(void)Curl_close(&newhandle);
goto fail;
}
- newstream = newhandle->req.protop;
+ newstream = newhandle->req.p.http;
newstream->stream_id = frame->promised_stream_id;
newhandle->req.maxdownload = -1;
newhandle->req.size = -1;
@@ -583,8 +585,8 @@ static int push_promise(struct Curl_easy *data,
rc = Curl_multi_add_perform(data->multi, newhandle, conn);
if(rc) {
infof(data, "failed to add handle to multi\n");
- http2_stream_free(newhandle->req.protop);
- newhandle->req.protop = NULL;
+ http2_stream_free(newhandle->req.p.http);
+ newhandle->req.p.http = NULL;
Curl_close(&newhandle);
rv = CURL_PUSH_DENY;
goto fail;
@@ -667,7 +669,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
@@ -783,7 +785,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -849,7 +851,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
}
H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
nghttp2_http2_strerror(error_code), error_code, stream_id));
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -894,7 +896,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream || !stream->bodystarted) {
return 0;
}
@@ -952,7 +954,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream) {
failf(data_s, "Internal NULL stream! 5\n");
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1100,7 +1102,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
internal error more than anything else! */
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream = data_s->req.protop;
+ stream = data_s->req.p.http;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -1161,7 +1163,7 @@ static void populate_settings(struct connectdata *conn,
void Curl_http2_done(struct Curl_easy *data, bool premature)
{
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
/* there might be allocated resources done before this got the 'h2' pointer
@@ -1207,13 +1209,6 @@ 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");
- }
}
/*
@@ -1288,7 +1283,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
httpc->local_settings,
httpc->local_settings_num);
- if(!binlen) {
+ if(binlen <= 0) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
Curl_dyn_free(req);
return CURLE_FAILED_INIT;
@@ -1371,6 +1366,14 @@ static int h2_process_pending_input(struct connectdata *conn,
return -1;
}
+ if(nghttp2_session_check_request_allowed(httpc->h2) == 0) {
+ /* 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(conn, "http/2: No new requests allowed");
+ }
+
if(should_close_session(httpc)) {
H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
@@ -1383,7 +1386,6 @@ static int h2_process_pending_input(struct connectdata *conn,
}
return -1;
}
-
return 0;
}
@@ -1398,7 +1400,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
(conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = conn->data->req.p.http;
struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2;
@@ -1494,8 +1496,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
break;
len = lf + 1 - trailp;
- if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
+ Curl_debug(data, CURLINFO_HEADER_IN, trailp, len);
/* pass the trailers one by one to the callback */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailp, len);
if(result) {
@@ -1522,7 +1523,7 @@ static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
struct HTTP *depstream = (data->set.stream_depends_on?
- data->set.stream_depends_on->req.protop:NULL);
+ data->set.stream_depends_on->req.p.http:NULL);
int32_t depstream_id = depstream? depstream->stream_id:0;
nghttp2_priority_spec_init(pri_spec, depstream_id, data->set.stream_weight,
data->set.stream_depends_e);
@@ -1539,7 +1540,7 @@ static void h2_pri_spec(struct Curl_easy *data,
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
if((data->set.stream_weight != data->state.stream_weight) ||
(data->set.stream_depends_e != data->state.stream_depends_e) ||
(data->set.stream_depends_on != data->state.stream_depends_on) ) {
@@ -1564,12 +1565,10 @@ static int h2_session_send(struct Curl_easy *data,
static ssize_t http2_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
- CURLcode result = CURLE_OK;
- ssize_t rv;
ssize_t nread;
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data = conn->data;
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
@@ -1632,8 +1631,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
}
@@ -1661,8 +1659,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(conn, httpc, &result) != 0) {
- *err = result;
+ if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
}
@@ -1688,7 +1685,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
return -1;
}
else {
- char *inbuf;
/* remember where to store incoming data for this stream and how big the
buffer is */
stream->mem = mem;
@@ -1697,16 +1693,15 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
if(httpc->inbuflen == 0) {
nread = ((Curl_recv *)httpc->recv_underlying)(
- conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, err);
if(nread == -1) {
- if(result != CURLE_AGAIN)
+ if(*err != CURLE_AGAIN)
failf(data, "Failed receiving HTTP2 data");
else if(stream->closed)
/* received when the stream was already closed! */
return http2_handle_stream_close(conn, data, stream, err);
- *err = result;
return -1;
}
@@ -1719,47 +1714,18 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
- inbuf = httpc->inbuf;
+
+ DEBUGASSERT(httpc->nread_inbuf == 0);
}
else {
nread = httpc->inbuflen - httpc->nread_inbuf;
- inbuf = httpc->inbuf + httpc->nread_inbuf;
-
+ (void)nread; /* silence warning, used in debug */
H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
- rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
- if(nghttp2_is_fatal((int)rv)) {
- failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
- rv, nghttp2_strerror((int)rv));
- *err = CURLE_RECV_ERROR;
- return -1;
- }
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
- if(nread == rv) {
- H2BUGF(infof(data, "All data in connection buffer processed\n"));
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += rv;
- H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
- httpc->inbuflen - httpc->nread_inbuf));
- }
- /* Always send pending frames in nghttp2 session, because
- nghttp2_session_mem_recv() may queue new frame */
- rv = h2_session_send(data, httpc->h2);
- if(rv != 0) {
- *err = CURLE_SEND_ERROR;
- return -1;
- }
-
- if(should_close_session(httpc)) {
- H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
+ if(h2_process_pending_input(conn, httpc, err) != 0)
return -1;
- }
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
@@ -1874,7 +1840,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
*/
int rv;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = conn->data->req.p.http;
nghttp2_nv *nva = NULL;
size_t nheader;
size_t i;
@@ -2104,7 +2070,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
if(acc > MAX_ACC) {
infof(conn->data, "http2_send: Warning: The cumulative length of all "
- "headers exceeds %zu bytes and that could cause the "
+ "headers exceeds %d bytes and that could cause the "
"stream to be rejected.\n", MAX_ACC);
}
}
@@ -2112,7 +2078,7 @@ 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));
+ nghttp2_session_check_request_allowed(h2), (void *)conn->data));
switch(conn->data->state.httpreq) {
case HTTPREQ_POST:
@@ -2138,7 +2104,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
Curl_safefree(nva);
if(stream_id < 0) {
- H2BUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(conn->data,
+ "http2_send() nghttp2_submit_request error (%s)%d\n",
+ nghttp2_strerror(stream_id), stream_id));
*err = CURLE_SEND_ERROR;
return -1;
}
@@ -2148,10 +2116,13 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->stream_id = stream_id;
/* this does not call h2_session_send() since there can not have been any
- * priority upodate since the nghttp2_submit_request() call above */
+ * priority update since the nghttp2_submit_request() call above */
rv = nghttp2_session_send(h2);
-
if(rv != 0) {
+ H2BUGF(infof(conn->data,
+ "http2_send() nghttp2_session_send error (%s)%d\n",
+ nghttp2_strerror(rv), rv));
+
*err = CURLE_SEND_ERROR;
return -1;
}
@@ -2183,7 +2154,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
{
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = conn->data->req.p.http;
DEBUGASSERT(conn->data->state.buffer);
@@ -2236,9 +2207,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
int rv;
- ssize_t nproc;
struct Curl_easy *data = conn->data;
- struct HTTP *stream = conn->data->req.protop;
+ struct HTTP *stream = conn->data->req.p.http;
result = Curl_http2_setup(conn);
if(result)
@@ -2299,7 +2269,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
data into stream->mem, overwriting data already there. */
if(H2_BUFSIZE < nread) {
failf(data, "connection buffer size is too small to store data following "
- "HTTP Upgrade response header: buflen=%zu, datalen=%zu",
+ "HTTP Upgrade response header: buflen=%d, datalen=%zu",
H2_BUFSIZE, nread);
return CURLE_HTTP2;
}
@@ -2310,41 +2280,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
if(nread)
memcpy(httpc->inbuf, mem, nread);
- httpc->inbuflen = nread;
-
- nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
- httpc->inbuflen);
-
- if(nghttp2_is_fatal((int)nproc)) {
- failf(data, "nghttp2_session_mem_recv() failed: %s(%d)",
- nghttp2_strerror((int)nproc), (int)nproc);
- return CURLE_HTTP2;
- }
-
- H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
-
- if((ssize_t)nread == nproc) {
- httpc->inbuflen = 0;
- httpc->nread_inbuf = 0;
- }
- else {
- httpc->nread_inbuf += nproc;
- }
- /* Try to send some frames since we may read SETTINGS already. */
- rv = h2_session_send(data, httpc->h2);
+ httpc->inbuflen = nread;
- if(rv != 0) {
- failf(data, "nghttp2_session_send() failed: %s(%d)",
- nghttp2_strerror(rv), rv);
- return CURLE_HTTP2;
- }
+ DEBUGASSERT(httpc->nread_inbuf == 0);
- if(should_close_session(httpc)) {
- H2BUGF(infof(data,
- "nghttp2_session_send(): nothing to do in this session\n"));
+ if(-1 == h2_process_pending_input(conn, httpc, &result))
return CURLE_HTTP2;
- }
return CURLE_OK;
}
@@ -2358,7 +2300,7 @@ CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
return CURLE_OK;
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
else {
- struct HTTP *stream = data->req.protop;
+ struct HTTP *stream = data->req.p.http;
struct http_conn *httpc = &data->conn->proto.httpc;
uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
int rv = nghttp2_session_set_local_window_size(httpc->h2,