From 67a42fc97c64c83e02f6f0d68e5a4a22c71138d3 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Thu, 25 Jul 2024 00:50:30 +0300 Subject: libcurl: update to 8.9.0 --- libs/libcurl/src/cf-h2-proxy.c | 84 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 12 deletions(-) (limited to 'libs/libcurl/src/cf-h2-proxy.c') diff --git a/libs/libcurl/src/cf-h2-proxy.c b/libs/libcurl/src/cf-h2-proxy.c index be9f932ecf..9d62352a8b 100644 --- a/libs/libcurl/src/cf-h2-proxy.c +++ b/libs/libcurl/src/cf-h2-proxy.c @@ -162,8 +162,8 @@ static void h2_tunnel_go_state(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "[%d] new tunnel state 'failed'", ts->stream_id); ts->state = new_state; /* If a proxy-authorization header was used for the proxy, then we should - make sure that it isn't accidentally used for the document request - after we've connected. So let's free and clear it here. */ + make sure that it is not accidentally used for the document request + after we have connected. So let's free and clear it here. */ Curl_safefree(data->state.aptr.proxyuserpwd); break; } @@ -181,7 +181,8 @@ struct cf_h2_proxy_ctx { int32_t goaway_error; int32_t last_stream_id; BIT(conn_closed); - BIT(goaway); + BIT(rcvd_goaway); + BIT(sent_goaway); BIT(nw_out_blocked); }; @@ -694,7 +695,7 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, } break; case NGHTTP2_GOAWAY: - ctx->goaway = TRUE; + ctx->rcvd_goaway = TRUE; break; default: break; @@ -1166,6 +1167,49 @@ static void cf_h2_proxy_destroy(struct Curl_cfilter *cf, } } +static CURLcode cf_h2_proxy_shutdown(struct Curl_cfilter *cf, + struct Curl_easy *data, bool *done) +{ + struct cf_h2_proxy_ctx *ctx = cf->ctx; + struct cf_call_data save; + CURLcode result; + int rv; + + if(!cf->connected || !ctx->h2 || cf->shutdown || ctx->conn_closed) { + *done = TRUE; + return CURLE_OK; + } + + CF_DATA_SAVE(save, cf, data); + + if(!ctx->sent_goaway) { + rv = nghttp2_submit_goaway(ctx->h2, NGHTTP2_FLAG_NONE, + 0, 0, + (const uint8_t *)"shutown", sizeof("shutown")); + if(rv) { + failf(data, "nghttp2_submit_goaway() failed: %s(%d)", + nghttp2_strerror(rv), rv); + result = CURLE_SEND_ERROR; + goto out; + } + ctx->sent_goaway = TRUE; + } + /* GOAWAY submitted, process egress and ingress until nghttp2 is done. */ + result = CURLE_OK; + if(nghttp2_session_want_write(ctx->h2)) + result = proxy_h2_progress_egress(cf, data); + if(!result && nghttp2_session_want_read(ctx->h2)) + result = proxy_h2_progress_ingress(cf, data); + + *done = (ctx->conn_closed || + (!result && !nghttp2_session_want_write(ctx->h2) && + !nghttp2_session_want_read(ctx->h2))); +out: + CF_DATA_RESTORE(cf, save); + cf->shutdown = (result || *done); + return result; +} + static bool cf_h2_proxy_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) { @@ -1182,12 +1226,18 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf, struct easy_pollset *ps) { struct cf_h2_proxy_ctx *ctx = cf->ctx; + struct cf_call_data save; curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); bool want_recv, want_send; - Curl_pollset_check(data, ps, sock, &want_recv, &want_send); + if(!cf->connected && ctx->h2) { + want_send = nghttp2_session_want_write(ctx->h2); + want_recv = nghttp2_session_want_read(ctx->h2); + } + else + Curl_pollset_check(data, ps, sock, &want_recv, &want_send); + if(ctx->h2 && (want_recv || want_send)) { - struct cf_call_data save; bool c_exhaust, s_exhaust; CF_DATA_SAVE(save, cf, data); @@ -1202,6 +1252,14 @@ static void cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf, Curl_pollset_set(data, ps, sock, want_recv, want_send); CF_DATA_RESTORE(cf, save); } + else if(ctx->sent_goaway && !cf->shutdown) { + /* shutdown in progress */ + CF_DATA_SAVE(save, cf, data); + want_send = nghttp2_session_want_write(ctx->h2); + want_recv = nghttp2_session_want_read(ctx->h2); + Curl_pollset_set(data, ps, sock, want_recv, want_send); + CF_DATA_RESTORE(cf, save); + } } static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf, @@ -1214,7 +1272,7 @@ static ssize_t h2_handle_tunnel_close(struct Curl_cfilter *cf, if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) { CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new " "connection", ctx->tunnel.stream_id); - connclose(cf->conn, "REFUSED_STREAM"); /* don't use this anymore */ + connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ return -1; } @@ -1259,7 +1317,8 @@ static ssize_t tunnel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, } else if(ctx->tunnel.reset || (ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) || - (ctx->goaway && ctx->last_stream_id < ctx->tunnel.stream_id)) { + (ctx->rcvd_goaway && + ctx->last_stream_id < ctx->tunnel.stream_id)) { *err = CURLE_RECV_ERROR; nread = -1; } @@ -1306,7 +1365,7 @@ static ssize_t cf_h2_proxy_recv(struct Curl_cfilter *cf, result = proxy_h2_progress_egress(cf, data); if(result == CURLE_AGAIN) { - /* pending data to send, need to be called again. Ideally, we'd + /* pending data to send, need to be called again. Ideally, we would * monitor the socket for POLLOUT, but we might not be in SENDING * transfer state any longer and are unable to make this happen. */ @@ -1418,7 +1477,7 @@ static ssize_t cf_h2_proxy_send(struct Curl_cfilter *cf, /* Unable to send all data, due to connection blocked or H2 window * exhaustion. Data is left in our stream buffer, or nghttp2's internal * frame buffer or our network out buffer. */ - size_t rwin = nghttp2_session_get_stream_remote_window_size( + size_t rwin = (size_t)nghttp2_session_get_stream_remote_window_size( ctx->h2, ctx->tunnel.stream_id); if(rwin == 0) { /* H2 flow window exhaustion. @@ -1489,8 +1548,8 @@ static bool proxy_h2_connisalive(struct Curl_cfilter *cf, return FALSE; if(*input_pending) { - /* This happens before we've sent off a request and the connection is - not in use by any other transfer, there shouldn't be any data here, + /* This happens before we have sent off a request and the connection is + not in use by any other transfer, there should not be any data here, only "protocol frames" */ CURLcode result; ssize_t nread = -1; @@ -1537,6 +1596,7 @@ struct Curl_cftype Curl_cft_h2_proxy = { cf_h2_proxy_destroy, cf_h2_proxy_connect, cf_h2_proxy_close, + cf_h2_proxy_shutdown, Curl_cf_http_proxy_get_host, cf_h2_proxy_adjust_pollset, cf_h2_proxy_data_pending, -- cgit v1.2.3