From 5d2ecfef56e49a8e4bfad25a582ff1597987f717 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Wed, 6 Nov 2024 20:55:13 +0300 Subject: libcurl: update to 8.11.0 --- libs/libcurl/src/http2.c | 124 +++++++++++++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 48 deletions(-) (limited to 'libs/libcurl/src/http2.c') diff --git a/libs/libcurl/src/http2.c b/libs/libcurl/src/http2.c index cd83e564b1..b9a21d2987 100644 --- a/libs/libcurl/src/http2.c +++ b/libs/libcurl/src/http2.c @@ -254,7 +254,7 @@ static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx) static void free_push_headers(struct h2_stream_ctx *stream) { size_t i; - for(i = 0; ipush_headers_used; i++) + for(i = 0; i < stream->push_headers_used; i++) free(stream->push_headers[i]); Curl_safefree(stream->push_headers); stream->push_headers_used = 0; @@ -299,7 +299,7 @@ static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf, int32_t dwsize; int rv; - dwsize = paused? 0 : cf_h2_get_desired_local_win(cf, data); + dwsize = paused ? 0 : cf_h2_get_desired_local_win(cf, data); if(dwsize != stream->local_window_size) { int32_t wsize = nghttp2_session_get_stream_effective_local_window_size( ctx->h2, stream->id); @@ -498,9 +498,10 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *value, size_t valuelen, uint8_t flags, void *userp); +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) static int error_callback(nghttp2_session *session, const char *msg, size_t len, void *userp); - +#endif static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, struct Curl_easy *data) { @@ -530,7 +531,9 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, nghttp2_session_callbacks_set_on_begin_headers_callback( cbs, on_begin_headers); nghttp2_session_callbacks_set_on_header_callback(cbs, on_header); +#if !defined(CURL_DISABLE_VERBOSE_STRINGS) nghttp2_session_callbacks_set_error_callback(cbs, error_callback); +#endif /* The nghttp2 session is not yet setup, do it */ rc = h2_client_new(cf, cbs); @@ -606,7 +609,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, /* all set, traffic will be send on connect */ result = CURLE_OK; CURL_TRC_CF(data, cf, "[0] created h2 session%s", - ctx->via_h1_upgrade? " (via h1 upgrade)" : ""); + ctx->via_h1_upgrade ? " (via h1 upgrade)" : ""); out: if(cbs) @@ -764,7 +767,7 @@ static CURLcode nw_out_flush(struct Curl_cfilter *cf, } return result; } - return Curl_bufq_is_empty(&ctx->outbufq)? CURLE_OK: CURLE_AGAIN; + return Curl_bufq_is_empty(&ctx->outbufq) ? CURLE_OK : CURLE_AGAIN; } /* @@ -786,8 +789,11 @@ static ssize_t send_callback(nghttp2_session *h2, (void)flags; DEBUGASSERT(data); - nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen, - nw_out_writer, cf, &result); + if(!cf->connected) + nwritten = Curl_bufq_write(&ctx->outbufq, buf, blen, &result); + else + nwritten = Curl_bufq_write_pass(&ctx->outbufq, buf, blen, + nw_out_writer, cf, &result); if(nwritten < 0) { if(result == CURLE_AGAIN) { ctx->nw_out_blocked = 1; @@ -852,7 +858,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header) return NULL; len = strlen(header); - for(i = 0; ipush_headers_used; i++) { + for(i = 0; i < stream->push_headers_used; i++) { if(!strncmp(header, stream->push_headers[i], len)) { /* sub-match, make sure that it is followed by a colon */ if(stream->push_headers[i][len] != ':') @@ -990,11 +996,11 @@ static int push_promise(struct Curl_cfilter *cf, } DEBUGASSERT(stream); - Curl_set_in_callback(data, true); + Curl_set_in_callback(data, TRUE); rv = data->multi->push_cb(data, newhandle, stream->push_headers_used, &heads, data->multi->push_userp); - Curl_set_in_callback(data, false); + Curl_set_in_callback(data, FALSE); /* free the headers again */ free_push_headers(stream); @@ -1113,9 +1119,6 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, return CURLE_RECV_ERROR; } } - if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { - drain_stream(cf, data, stream); - } break; case NGHTTP2_HEADERS: if(stream->bodystarted) { @@ -1131,10 +1134,10 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, return CURLE_RECV_ERROR; /* Only final status code signals the end of header */ - if(stream->status_code / 100 != 1) { + if(stream->status_code / 100 != 1) stream->bodystarted = TRUE; + else stream->status_code = -1; - } h2_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed); @@ -1181,6 +1184,22 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, default: break; } + + if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { + if(!stream->closed && !stream->body_eos && + ((stream->status_code >= 400) || (stream->status_code < 200))) { + /* The server did not give us a positive response and we are not + * done uploading the request body. We need to stop doing that and + * also inform the server that we aborted our side. */ + CURL_TRC_CF(data, cf, "[%d] EOS frame with unfinished upload and " + "HTTP status %d, abort upload by RST", + stream_id, stream->status_code); + nghttp2_submit_rst_stream(ctx->h2, NGHTTP2_FLAG_NONE, + stream->id, NGHTTP2_STREAM_CLOSED); + stream->closed = TRUE; + } + drain_stream(cf, data, stream); + } return CURLE_OK; } @@ -1235,14 +1254,14 @@ static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen) case NGHTTP2_GOAWAY: { char scratch[128]; size_t s_len = sizeof(scratch)/sizeof(scratch[0]); - size_t len = (frame->goaway.opaque_data_len < s_len)? - frame->goaway.opaque_data_len : s_len-1; - if(len) - memcpy(scratch, frame->goaway.opaque_data, len); - scratch[len] = '\0'; - return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', " - "last_stream=%d]", frame->goaway.error_code, - scratch, frame->goaway.last_stream_id); + size_t len = (frame->goaway.opaque_data_len < s_len) ? + frame->goaway.opaque_data_len : s_len-1; + if(len) + memcpy(scratch, frame->goaway.opaque_data, len); + scratch[len] = '\0'; + return msnprintf(buffer, blen, "FRAME[GOAWAY, error=%d, reason='%s', " + "last_stream=%d]", frame->goaway.error_code, + scratch, frame->goaway.last_stream_id); } case NGHTTP2_WINDOW_UPDATE: { return msnprintf(buffer, blen, @@ -1350,7 +1369,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, return 0; } - return on_stream_frame(cf, data_s, frame)? NGHTTP2_ERR_CALLBACK_FAILURE : 0; + return on_stream_frame(cf, data_s, frame) ? NGHTTP2_ERR_CALLBACK_FAILURE : 0; } static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, @@ -1402,8 +1421,8 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, DEBUGASSERT(call_data); /* stream id 0 is the connection, do not look there for streams. */ - data_s = stream_id? - nghttp2_session_get_stream_user_data(session, stream_id) : NULL; + data_s = stream_id ? + nghttp2_session_get_stream_user_data(session, stream_id) : NULL; if(!data_s) { CURL_TRC_CF(call_data, cf, "[%d] on_stream_close, no easy set on stream", stream_id); @@ -1683,7 +1702,7 @@ static ssize_t req_body_read_callback(nghttp2_session *session, *data_flags = NGHTTP2_DATA_FLAG_EOF; return nread; } - return (nread == 0)? NGHTTP2_ERR_DEFERRED : nread; + return (nread == 0) ? NGHTTP2_ERR_DEFERRED : nread; } #if !defined(CURL_DISABLE_VERBOSE_STRINGS) @@ -1773,7 +1792,7 @@ static ssize_t http2_handle_stream_close(struct Curl_cfilter *cf, } else if(stream->reset) { failf(data, "HTTP/2 stream %u was reset", stream->id); - *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2; + *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2; return -1; } @@ -1826,14 +1845,14 @@ out: static int sweight_wanted(const struct Curl_easy *data) { /* 0 weight is not set by user and we take the nghttp2 default one */ - return data->set.priority.weight? + return data->set.priority.weight ? data->set.priority.weight : NGHTTP2_DEFAULT_WEIGHT; } static int sweight_in_effect(const struct Curl_easy *data) { /* 0 weight is not set by user and we take the nghttp2 default one */ - return data->state.priority.weight? + return data->state.priority.weight ? data->state.priority.weight : NGHTTP2_DEFAULT_WEIGHT; } @@ -1849,7 +1868,7 @@ static void h2_pri_spec(struct cf_h2_ctx *ctx, { struct Curl_data_priority *prio = &data->set.priority; struct h2_stream_ctx *depstream = H2_STREAM_CTX(ctx, prio->parent); - int32_t depstream_id = depstream? depstream->id:0; + int32_t depstream_id = depstream ? depstream->id : 0; nghttp2_priority_spec_init(pri_spec, depstream_id, sweight_wanted(data), data->set.priority.exclusive); @@ -1895,6 +1914,11 @@ out: nghttp2_strerror(rv), rv); return CURLE_SEND_ERROR; } + /* Defer flushing during the connect phase so that the SETTINGS and + * other initial frames are sent together with the first request. + * Unless we are 'connect_only' where the request will never come. */ + if(!cf->connected && !cf->conn->connect_only) + return CURLE_OK; return nw_out_flush(cf, data); } @@ -1920,7 +1944,7 @@ static ssize_t stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data, (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) || (ctx->rcvd_goaway && ctx->remote_max_sid < stream->id)) { CURL_TRC_CF(data, cf, "[%d] returning ERR", stream->id); - *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP2; + *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP2; nread = -1; } @@ -1978,8 +2002,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf, } else { CURL_TRC_CF(data, cf, "[0] ingress: read %zd bytes", nread); - data_max_bytes = (data_max_bytes > (size_t)nread)? - (data_max_bytes - (size_t)nread) : 0; + data_max_bytes = (data_max_bytes > (size_t)nread) ? + (data_max_bytes - (size_t)nread) : 0; } if(h2_process_pending_input(cf, data, &result)) @@ -2244,7 +2268,7 @@ static ssize_t h2_submit(struct h2_stream_ctx **pstream, out: CURL_TRC_CF(data, cf, "[%d] submit -> %zd, %d", - stream? stream->id : -1, nwritten, *err); + stream ? stream->id : -1, nwritten, *err); Curl_safefree(nva); *pstream = stream; Curl_dynhds_free(&h2_headers); @@ -2436,6 +2460,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf, struct cf_h2_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; struct cf_call_data save; + bool first_time = FALSE; if(cf->connected) { *done = TRUE; @@ -2457,11 +2482,14 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf, result = cf_h2_ctx_open(cf, data); if(result) goto out; + first_time = TRUE; } - result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE); - if(result) - goto out; + if(!first_time) { + result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE); + if(result) + goto out; + } /* Send out our SETTINGS and ACKs and such. If that blocks, we * have it buffered and can count this filter as being connected */ @@ -2584,7 +2612,7 @@ static CURLcode http2_data_pause(struct Curl_cfilter *cf, Curl_expire(data, 0, EXPIRE_RUN_NOW); } CURL_TRC_CF(data, cf, "[%d] stream now %spaused", stream->id, - pause? "" : "un"); + pause ? "" : "un"); } return CURLE_OK; } @@ -2630,7 +2658,7 @@ static bool cf_h2_data_pending(struct Curl_cfilter *cf, if(ctx && (!Curl_bufq_is_empty(&ctx->inbufq) || (stream && !Curl_bufq_is_empty(&stream->sendbuf)))) return TRUE; - return cf->next? cf->next->cft->has_data_pending(cf->next, data) : FALSE; + return cf->next ? cf->next->cft->has_data_pending(cf->next, data) : FALSE; } static bool cf_h2_is_alive(struct Curl_cfilter *cf, @@ -2681,12 +2709,12 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf, else { effective_max = ctx->max_concurrent_streams; } - *pres1 = (effective_max > INT_MAX)? INT_MAX : (int)effective_max; + *pres1 = (effective_max > INT_MAX) ? INT_MAX : (int)effective_max; CF_DATA_RESTORE(cf, save); return CURLE_OK; case CF_QUERY_STREAM_ERROR: { struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data); - *pres1 = stream? (int)stream->error : 0; + *pres1 = stream ? (int)stream->error : 0; return CURLE_OK; } case CF_QUERY_NEED_FLUSH: { @@ -2701,7 +2729,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf, default: break; } - return cf->next? + return cf->next ? cf->next->cft->query(cf->next, data, query, pres1, pres2) : CURLE_UNKNOWN_OPTION; } @@ -2751,7 +2779,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf, out: if(result) cf_h2_ctx_free(ctx); - *pcf = result? NULL : cf; + *pcf = result ? NULL : cf; return result; } @@ -2782,8 +2810,8 @@ out: return result; } -static bool Curl_cf_is_http2(struct Curl_cfilter *cf, - const struct Curl_easy *data) +static bool cf_is_http2(struct Curl_cfilter *cf, + const struct Curl_easy *data) { (void)data; for(; cf; cf = cf->next) { @@ -2799,7 +2827,7 @@ bool Curl_conn_is_http2(const struct Curl_easy *data, const struct connectdata *conn, int sockindex) { - return conn? Curl_cf_is_http2(conn->cfilter[sockindex], data) : FALSE; + return conn ? cf_is_http2(conn->cfilter[sockindex], data) : FALSE; } bool Curl_http2_may_switch(struct Curl_easy *data, @@ -2851,7 +2879,7 @@ CURLcode Curl_http2_switch_at(struct Curl_cfilter *cf, struct Curl_easy *data) struct Curl_cfilter *cf_h2; CURLcode result; - DEBUGASSERT(!Curl_cf_is_http2(cf, data)); + DEBUGASSERT(!cf_is_http2(cf, data)); result = http2_cfilter_insert_after(cf, data, FALSE); if(result) -- cgit v1.2.3