summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/cf-h2-proxy.c
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2024-07-25 00:50:30 +0300
committerdartraiden <wowemuh@gmail.com>2024-07-25 02:38:23 +0300
commit67a42fc97c64c83e02f6f0d68e5a4a22c71138d3 (patch)
tree21eb2d53a9cd7e645a58662dee11588f56057eee /libs/libcurl/src/cf-h2-proxy.c
parent0a365886f2d06750a707037d894e1492988eb53c (diff)
libcurl: update to 8.9.0
Diffstat (limited to 'libs/libcurl/src/cf-h2-proxy.c')
-rw-r--r--libs/libcurl/src/cf-h2-proxy.c84
1 files changed, 72 insertions, 12 deletions
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,