diff options
author | Stefan Eissing <stefan@eissing.org> | 2023-04-21 12:04:46 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-04-25 17:49:28 +0200 |
commit | cab2d56ea52b3724495b3dbc5bfef3343d4ecadc (patch) | |
tree | 7aea2eecec9df647106ddb351b6e62d8d6c907f0 /lib/vquic/curl_msh3.c | |
parent | a97e4eb95f86adb6043a3388250f34841440981e (diff) | |
download | curl-cab2d56ea52b3724495b3dbc5bfef3343d4ecadc.tar.gz |
h2/h3: replace `state.drain` counter with `state.dselect_bits`
- `drain` was used by http/2 and http/3 implementations to indicate
that the transfer requires send/recv independant from its socket
poll state. Intended as a counter, it was used as bool flag only.
- a similar mechanism exists on `connectdata->cselect_bits` where
specific protocols can indicate something similar, only for the
whole connection.
- `cselect_bits` are cleard in transfer.c on use and, importantly,
also set when the transfer loop expended its `maxloops` tries.
`drain` was not cleared by transfer and the http2/3 implementations
had to take care of that.
- `dselect_bits` is cleared *and* set by the transfer loop. http2/3
does no longer clear it, only set when new events happen.
This change unifies the handling of socket poll overrides, extending
`cselect_bits` by a easy handle specific value and a common treatment in
transfers.
Closes #11005
Diffstat (limited to 'lib/vquic/curl_msh3.c')
-rw-r--r-- | lib/vquic/curl_msh3.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c index 1e1a15a8f..34ea0bcf6 100644 --- a/lib/vquic/curl_msh3.c +++ b/lib/vquic/curl_msh3.c @@ -189,12 +189,33 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) } } -static void notify_drain(struct Curl_cfilter *cf, +static void drain_stream_from_other_thread(struct Curl_easy *data, + struct stream_ctx *stream) +{ + int bits; + + /* risky */ + bits = CURL_CSELECT_IN; + if(stream && !stream->upload_done) + bits |= CURL_CSELECT_OUT; + if(data->state.dselect_bits != bits) { + data->state.dselect_bits = bits; + /* cannot expire from other thread */ + } +} + +static void drain_stream(struct Curl_cfilter *cf, struct Curl_easy *data) { + struct stream_ctx *stream = H3_STREAM_CTX(data); + int bits; + (void)cf; - if(!data->state.drain) { - data->state.drain = 1; + bits = CURL_CSELECT_IN; + if(stream && !stream->upload_done) + bits |= CURL_CSELECT_OUT; + if(data->state.dselect_bits != bits) { + data->state.dselect_bits = bits; Curl_expire(data, 0, EXPIRE_RUN_NOW); } } @@ -350,7 +371,7 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request, } } - data->state.drain = 1; + drain_stream_from_other_thread(data, stream); msh3_lock_release(&stream->recv_lock); } @@ -469,7 +490,6 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf, nread = 0; out: - data->state.drain = 0; return nread; } @@ -508,7 +528,6 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(stream->recv_error) { failf(data, "request aborted"); - data->state.drain = 0; *err = stream->recv_error; goto out; } @@ -522,10 +541,8 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data, len, nread, *err)); if(nread < 0) goto out; - if(!Curl_bufq_is_empty(&stream->recvbuf) || - stream->closed) { - notify_drain(cf, data); - } + if(stream->closed) + drain_stream(cf, data); } else if(stream->closed) { nread = recv_closed_stream(cf, data, err); @@ -669,15 +686,14 @@ static int cf_msh3_get_select_socks(struct Curl_cfilter *cf, if(stream->recv_error) { bitmap |= GETSOCK_READSOCK(0); - notify_drain(cf, data); + drain_stream(cf, data); } else if(stream->req) { bitmap |= GETSOCK_READSOCK(0); - notify_drain(cf, data); + drain_stream(cf, data); } } - DEBUGF(LOG_CF(data, cf, "select_sock %u -> %d", - (uint32_t)data->state.drain, bitmap)); + DEBUGF(LOG_CF(data, cf, "select_sock -> %d", bitmap)); CF_DATA_RESTORE(cf, save); return bitmap; } @@ -698,6 +714,8 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf, Curl_bufq_len(&stream->recvbuf))); pending = !Curl_bufq_is_empty(&stream->recvbuf); msh3_lock_release(&stream->recv_lock); + if(pending) + drain_stream(cf, (struct Curl_easy *)data); } CF_DATA_RESTORE(cf, save); |