summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2021-01-25 17:59:22 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2021-01-25 21:17:59 +0900
commitd11c3551935f3eff2dfeb915d05b1fc606b33026 (patch)
tree5f97c5b7a438bc9ec6d685181ce8ea1fdafcba85
parentaa8cfa01c8e486a63c1cbd717a12164f26475243 (diff)
downloadcurl-d11c3551935f3eff2dfeb915d05b1fc606b33026.tar.gz
ngtcp2: Fix http3 upload stall
-rw-r--r--lib/vquic/ngtcp2.c109
1 files changed, 54 insertions, 55 deletions
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
index f2fce76ff..9f8cebf24 100644
--- a/lib/vquic/ngtcp2.c
+++ b/lib/vquic/ngtcp2.c
@@ -1289,8 +1289,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
{
struct Curl_easy *data = stream_user_data;
struct HTTP *stream = data->req.p.http;
- (void)conn;
- (void)stream_id;
+ int rv;
(void)user_data;
if(!data->set.postfields) {
@@ -1299,6 +1298,13 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
"cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
datalen, stream->h3out->used));
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
+
+ if(stream->h3out->used == 0) {
+ rv = nghttp3_conn_resume_stream(conn, stream_id);
+ if(rv != 0) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+ }
}
return 0;
}
@@ -1359,7 +1365,7 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
(stream->upload_left <= 0)) {
H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
*pflags = NGHTTP3_DATA_FLAG_EOF;
- return 0;
+ return nread ? 1 : 0;
}
else if(!nread) {
return NGHTTP3_ERR_WOULDBLOCK;
@@ -1755,6 +1761,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
int fin;
nghttp3_vec vec[16];
ssize_t ndatalen;
+ uint32_t flags;
switch(qs->local_addr.ss_family) {
case AF_INET:
@@ -1780,6 +1787,10 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
for(;;) {
outlen = -1;
+ veccnt = 0;
+ stream_id = -1;
+ fin = 0;
+
if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
sizeof(vec) / sizeof(vec[0]));
@@ -1788,64 +1799,52 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
nghttp3_strerror((int)veccnt));
return CURLE_SEND_ERROR;
}
- else if(veccnt > 0) {
- uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
- (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen =
- ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL,
- out, pktlen, &ndatalen,
- flags, stream_id,
- (const ngtcp2_vec *)vec, veccnt, ts);
- if(outlen == 0) {
- break;
- }
- if(outlen < 0) {
- if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
- outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
- assert(ndatalen == -1);
- rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
- if(rv != 0) {
- failf(data,
- "nghttp3_conn_block_stream returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else if(outlen == NGTCP2_ERR_WRITE_MORE) {
- assert(ndatalen > 0);
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
- ndatalen);
- if(rv != 0) {
- failf(data,
- "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
- continue;
- }
- else {
- assert(ndatalen == -1);
- failf(data, "ngtcp2_conn_writev_stream returned error: %s",
- ngtcp2_strerror((int)outlen));
- return CURLE_SEND_ERROR;
- }
+ }
+
+ flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
+ (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,
+ &ndatalen, flags, stream_id,
+ (const ngtcp2_vec *)vec, veccnt, ts);
+ if(outlen == 0) {
+ break;
+ }
+ if(outlen < 0) {
+ if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
+ outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ assert(ndatalen == -1);
+ rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_block_stream returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
- else {
- assert(ndatalen == -1);
+ continue;
+ }
+ else if(outlen == NGTCP2_ERR_WRITE_MORE) {
+ assert(ndatalen >= 0);
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
}
+ continue;
}
- }
- if(outlen < 0) {
- outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, NULL,
- out, pktlen, ts);
- if(outlen < 0) {
- failf(data, "ngtcp2_conn_write_pkt returned error: %s",
+ else {
+ assert(ndatalen == -1);
+ failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR;
}
- if(outlen == 0)
- break;
+ }
+ else if(ndatalen > 0) {
+ rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
+ if(rv != 0) {
+ failf(data, "nghttp3_conn_add_write_offset returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
}
memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);