summaryrefslogtreecommitdiff
path: root/lib/vquic/curl_msh3.c
diff options
context:
space:
mode:
authorStefan Eissing <stefan@eissing.org>2023-04-21 12:04:46 +0200
committerDaniel Stenberg <daniel@haxx.se>2023-04-25 17:49:28 +0200
commitcab2d56ea52b3724495b3dbc5bfef3343d4ecadc (patch)
tree7aea2eecec9df647106ddb351b6e62d8d6c907f0 /lib/vquic/curl_msh3.c
parenta97e4eb95f86adb6043a3388250f34841440981e (diff)
downloadcurl-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.c46
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);