diff options
author | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2019-05-22 18:15:06 (GMT) |
commit | a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f (patch) | |
tree | a4d546a554025fb11ec6cc32e7491b150cde35f3 /Utilities/cmcurl/lib/http2.c | |
parent | 2de8af0121c3ca64dcb82a1220d2ba255aab3553 (diff) | |
parent | b26487c663ec29d972fd61adc2b14ac5880b78c7 (diff) | |
download | CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.zip CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.gz CMake-a39138ef9a7f3e3ec94ae4fd99602ca711bbcf5f.tar.bz2 |
Merge branch 'upstream-curl' into update-curl
* upstream-curl:
curl 2019-05-22 (885ce314)
Diffstat (limited to 'Utilities/cmcurl/lib/http2.c')
-rw-r--r-- | Utilities/cmcurl/lib/http2.c | 76 |
1 files changed, 60 insertions, 16 deletions
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c index 0c5f6db..8e7bc21 100644 --- a/Utilities/cmcurl/lib/http2.c +++ b/Utilities/cmcurl/lib/http2.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -111,8 +111,6 @@ static int http2_perform_getsock(const struct connectdata *conn, int bitmap = GETSOCK_BLANK; (void)numsocks; - /* TODO We should check underlying socket state if it is SSL socket - because of renegotiation. */ sock[0] = conn->sock[FIRSTSOCKET]; /* in a HTTP/2 connection we can basically always get a frame so we should @@ -350,14 +348,14 @@ static const struct Curl_handler Curl_handler_http2_ssl = { int Curl_http2_ver(char *p, size_t len) { nghttp2_info *h2 = nghttp2_version(0); - return snprintf(p, len, " nghttp2/%s", h2->version_str); + return msnprintf(p, len, " nghttp2/%s", h2->version_str); } /* HTTP/2 error code to name based on the Error Code Registry. https://tools.ietf.org/html/rfc7540#page-77 nghttp2_error_code enums are identical. */ -const char *Curl_http2_strerror(uint32_t err) +static const char *http2_strerror(uint32_t err) { #ifndef NGHTTP2_HAS_HTTP2_STRERROR const char *str[] = { @@ -618,6 +616,18 @@ static int push_promise(struct Curl_easy *data, return rv; } +/* + * multi_connchanged() is called to tell that there is a connection in + * this multi handle that has changed state (multiplexing become possible, the + * number of allowed streams changed or similar), and a subsequent use of this + * multi handle should move CONNECT_PEND handles back to CONNECT to have them + * retry. + */ +static void multi_connchanged(struct Curl_multi *multi) +{ + multi->recheckstate = TRUE; +} + static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, void *userp) { @@ -650,7 +660,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, infof(conn->data, "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n", httpc->settings.max_concurrent_streams); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); } } return 0; @@ -800,7 +810,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer" ", stream %u\n", len - nread, stream_id)); - data_s->easy_conn->proto.httpc.pause_stream_id = stream_id; + data_s->conn->proto.httpc.pause_stream_id = stream_id; return NGHTTP2_ERR_PAUSE; } @@ -808,7 +818,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, /* pause execution of nghttp2 if we received data for another handle in order to process them first. */ if(conn->data != data_s) { - data_s->easy_conn->proto.httpc.pause_stream_id = stream_id; + data_s->conn->proto.httpc.pause_stream_id = stream_id; return NGHTTP2_ERR_PAUSE; } @@ -837,7 +847,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, return 0; } H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", - Curl_http2_strerror(error_code), error_code, stream_id)); + http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -854,6 +864,10 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, stream_id); DEBUGASSERT(0); } + if(stream_id == httpc->pause_stream_id) { + H2BUGF(infof(data_s, "Stopped the pause stream!\n")); + httpc->pause_stream_id = 0; + } H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id)); stream->stream_id = 0; /* cleared */ } @@ -953,6 +967,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { char *h; + if(!strcmp(":authority", (const char *)name)) { + /* pseudo headers are lower case */ + int rc = 0; + char *check = aprintf("%s:%d", conn->host.name, conn->remote_port); + if(!check) + /* no memory */ + return NGHTTP2_ERR_CALLBACK_FAILURE; + if(!Curl_strcasecompare(check, (const char *)value)) { + /* This is push is not for the same authority that was asked for in + * the URL. RFC 7540 section 8.2 says: "A client MUST treat a + * PUSH_PROMISE for which the server is not authoritative as a stream + * error of type PROTOCOL_ERROR." + */ + (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + stream_id, NGHTTP2_PROTOCOL_ERROR); + rc = NGHTTP2_ERR_CALLBACK_FAILURE; + } + free(check); + if(rc) + return rc; + } + if(!stream->push_headers) { stream->push_headers_alloc = 10; stream->push_headers = malloc(stream->push_headers_alloc * @@ -1193,7 +1229,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature) /* * Initialize nghttp2 for a Curl connection */ -CURLcode Curl_http2_init(struct connectdata *conn) +static CURLcode http2_init(struct connectdata *conn) { if(!conn->proto.httpc.h2) { int rc; @@ -1427,7 +1463,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, } else if(httpc->error_code != NGHTTP2_NO_ERROR) { failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)", - stream->stream_id, Curl_http2_strerror(httpc->error_code), + stream->stream_id, http2_strerror(httpc->error_code), httpc->error_code); *err = CURLE_HTTP2_STREAM; return -1; @@ -1809,9 +1845,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, CURLcode *err) { /* - * BIG TODO: Currently, we send request in this function, but this - * function is also used to send request body. It would be nice to - * add dedicated function for request. + * Currently, we send request in this function, but this function is also + * used to send request body. It would be nice to add dedicated function for + * request. */ int rv; struct http_conn *httpc = &conn->proto.httpc; @@ -2137,7 +2173,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) else conn->handler = &Curl_handler_http2; - result = Curl_http2_init(conn); + result = http2_init(conn); if(result) { Curl_add_buffer_free(&stream->header_recvbuf); return result; @@ -2159,7 +2195,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn) conn->bundle->multiuse = BUNDLE_MULTIPLEX; infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n"); - Curl_multi_connchanged(conn->data->multi); + multi_connchanged(conn->data->multi); return CURLE_OK; } @@ -2367,6 +2403,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data) Curl_http2_remove_child(data->set.stream_depends_on, data); } +/* Only call this function for a transfer that already got a HTTP/2 + CURLE_HTTP2_STREAM error! */ +bool Curl_h2_http_1_1_error(struct connectdata *conn) +{ + struct http_conn *httpc = &conn->proto.httpc; + return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); +} + #else /* !USE_NGHTTP2 */ /* Satisfy external references even if http2 is not compiled in. */ |