diff options
author | Stefan Eissing <stefan@eissing.org> | 2023-04-26 12:38:22 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-04-26 23:24:46 +0200 |
commit | acd82c8bfd743d0f743a1c1296890738832ac83e (patch) | |
tree | fc4da775326efd7562f6217f41929b703902431c /lib/http2.c | |
parent | 21575b26fe33099e087b8beaac9bc43fa8597874 (diff) | |
download | curl-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.c | 59 |
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) |