summaryrefslogtreecommitdiff
path: root/lib/http2.c
diff options
context:
space:
mode:
authorStefan Eissing <stefan@eissing.org>2023-04-26 12:38:22 +0200
committerDaniel Stenberg <daniel@haxx.se>2023-04-26 23:24:46 +0200
commitacd82c8bfd743d0f743a1c1296890738832ac83e (patch)
treefc4da775326efd7562f6217f41929b703902431c /lib/http2.c
parent21575b26fe33099e087b8beaac9bc43fa8597874 (diff)
downloadcurl-acd82c8bfd743d0f743a1c1296890738832ac83e.tar.gz
tests/http: more tests with specific clients
- Makefile support for building test specific clients in tests/http/clients - auto-make of clients when invoking pytest - added test_09_02 for server PUSH_PROMISEs using clients/h2-serverpush - added test_02_21 for lib based downloads and pausing/unpausing transfers curl url parser: - added internal method `curl_url_set_authority()` for setting the authority part of a url (used for PUSH_PROMISE) http2: - made logging of PUSH_PROMISE handling nicer Placing python test requirements in requirements.txt files - separate files to base test suite and http tests since use and module lists differ - using the files in the gh workflows websocket test cases, fixes for we and bufq - bufq: account for spare chunks in space calculation - bufq: reset chunks that are skipped empty - ws: correctly encode frames with 126 bytes payload - ws: update frame meta information on first call of collect callback that fills user buffer - test client ws-data: some test/reporting improvements Closes #11006
Diffstat (limited to 'lib/http2.c')
-rw-r--r--lib/http2.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/lib/http2.c b/lib/http2.c
index 726f5a64b..62eed3c35 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -38,6 +38,7 @@
#include "strcase.h"
#include "multiif.h"
#include "url.h"
+#include "urlapi-int.h"
#include "cfilters.h"
#include "connect.h"
#include "strtoofft.h"
@@ -768,7 +769,7 @@ static int set_transfer_url(struct Curl_easy *data,
v = curl_pushheader_byname(hp, HTTP_PSEUDO_AUTHORITY);
if(v) {
- uc = curl_url_set(u, CURLUPART_HOST, v, 0);
+ uc = curl_url_set_authority(u, v, CURLU_DISALLOW_USER);
if(uc) {
rc = 2;
goto fail;
@@ -950,8 +951,15 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
switch(frame->hd.type) {
case NGHTTP2_DATA:
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[DATA len=%zu pad=%zu], "
+ "buffered=%zu, window=%d/%d",
+ stream_id, frame->hd.length, frame->data.padlen,
+ Curl_bufq_len(&stream->recvbuf),
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id)));
/* If !body started on this stream, then receiving DATA is illegal. */
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv frame DATA", stream_id));
if(!stream->bodystarted) {
rv = nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE,
stream_id, NGHTTP2_PROTOCOL_ERROR);
@@ -965,7 +973,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
}
break;
case NGHTTP2_HEADERS:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv frame HEADERS", stream_id));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[HEADERS]", stream_id));
if(stream->bodystarted) {
/* Only valid HEADERS after body started is trailer HEADERS. We
buffer them in on_header callback. */
@@ -993,7 +1001,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
drain_stream(cf, data, stream);
break;
case NGHTTP2_PUSH_PROMISE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv PUSH_PROMISE", stream_id));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[PUSH_PROMISE]", stream_id));
rv = push_promise(cf, data, &frame->push_promise);
if(rv) { /* deny! */
DEBUGASSERT((rv > CURL_PUSH_OK) && (rv <= CURL_PUSH_ERROROUT));
@@ -1010,13 +1018,13 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
}
break;
case NGHTTP2_RST_STREAM:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv RST", stream_id));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FARME[RST]", stream_id));
stream->closed = TRUE;
stream->reset = TRUE;
drain_stream(cf, data, stream);
break;
case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv WINDOW_UPDATE", stream_id));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[WINDOW_UPDATE]", stream_id));
if((data->req.keepon & KEEP_SEND_HOLD) &&
(data->req.keepon & KEEP_SEND)) {
data->req.keepon &= ~KEEP_SEND_HOLD;
@@ -1026,7 +1034,7 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf,
}
break;
default:
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] recv frame %x",
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] FRAME[%x]",
stream_id, frame->hd.type));
break;
}
@@ -1048,7 +1056,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
switch(frame->hd.type) {
case NGHTTP2_SETTINGS: {
uint32_t max_conn = ctx->max_concurrent_streams;
- DEBUGF(LOG_CF(data, cf, "recv frame SETTINGS"));
+ DEBUGF(LOG_CF(data, cf, "FRAME[SETTINGS]"));
ctx->max_concurrent_streams = nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
ctx->enable_push = nghttp2_session_get_remote_settings(
@@ -1070,7 +1078,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ctx->goaway_error = frame->goaway.error_code;
ctx->last_stream_id = frame->goaway.last_stream_id;
if(data) {
- DEBUGF(LOG_CF(data, cf, "recv GOAWAY, error=%d, last_stream=%u",
+ DEBUGF(LOG_CF(data, cf, "FRAME[GOAWAY, error=%d, last_stream=%u]",
ctx->goaway_error, ctx->last_stream_id));
infof(data, "received GOAWAY, error=%d, last_stream=%u",
ctx->goaway_error, ctx->last_stream_id);
@@ -1078,7 +1086,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
break;
case NGHTTP2_WINDOW_UPDATE:
- DEBUGF(LOG_CF(data, cf, "recv frame WINDOW_UPDATE"));
+ DEBUGF(LOG_CF(data, cf, "FRAME[WINDOW_UPDATE]"));
break;
default:
DEBUGF(LOG_CF(data, cf, "recv frame %x on 0", frame->hd.type));
@@ -1139,10 +1147,6 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
drain_stream(cf, data_s, stream);
DEBUGASSERT((size_t)nwritten == len);
- DEBUGF(LOG_CF(data_s, cf, "[h2sid=%d] %zd/%zu DATA recvd, "
- "(buffer now holds %zu)",
- stream_id, nwritten, len, Curl_bufq_len(&stream->recvbuf)));
-
return 0;
}
@@ -1675,11 +1679,13 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
if(nread < 0) {
if(stream->closed) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning CLOSE", stream->id));
nread = http2_handle_stream_close(cf, data, stream, err);
}
else if(stream->reset ||
(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) ||
(ctx->goaway && ctx->last_stream_id < stream->id)) {
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] returning ERR", stream->id));
*err = stream->bodystarted? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
nread = -1;
}
@@ -1730,7 +1736,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
Curl_bufq_len(&ctx->inbufq), nread, result)); */
if(nread < 0) {
if(result != CURLE_AGAIN) {
- failf(data, "Failed receiving HTTP2 data");
+ failf(data, "Failed receiving HTTP2 data: %d(%s)", result,
+ curl_easy_strerror(result));
return result;
}
break;
@@ -1762,12 +1769,6 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
CF_DATA_SAVE(save, cf, data);
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_recv: win %u/%u",
- stream->id,
- nghttp2_session_get_local_window_size(ctx->h2),
- nghttp2_session_get_stream_local_window_size(ctx->h2,
- stream->id)
- ));
nread = stream_recv(cf, data, buf, len, err);
if(nread < 0 && *err != CURLE_AGAIN)
goto out;
@@ -1794,8 +1795,6 @@ static ssize_t cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
stream->resp_hds_len = 0;
}
if(data_consumed) {
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] increase window by %zu",
- stream->id, data_consumed));
nghttp2_session_consume(ctx->h2, stream->id, data_consumed);
}
}
@@ -1813,8 +1812,15 @@ out:
*err = result;
nread = -1;
}
- DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_recv(len=%zu) -> %zd %d",
- stream->id, len, nread, *err));
+ DEBUGF(LOG_CF(data, cf, "[h2sid=%d] cf_recv(len=%zu) -> %zd %d, "
+ "buffered=%zu, window=%d/%d",
+ stream->id, len, nread, *err,
+ Curl_bufq_len(&stream->recvbuf),
+ nghttp2_session_get_stream_effective_recv_data_length(
+ ctx->h2, stream->id),
+ nghttp2_session_get_stream_effective_local_window_size(
+ ctx->h2, stream->id)));
+
CF_DATA_RESTORE(cf, save);
return nread;
}
@@ -2205,6 +2211,9 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf,
return CURLE_HTTP2;
}
+ if(!pause)
+ drain_stream(cf, data, stream);
+
/* make sure the window update gets sent */
result = h2_progress_egress(cf, data);
if(result)