mirror of
https://github.com/curl/curl.git
synced 2026-08-25 23:13:38 +03:00
mime: fix unpausing of readers
When unpausing a transfer, check if the reader pause state differs in addition to the "keepon" flags. Reported-by: 包布丁 Fixes #18848 Closes #19178
This commit is contained in:
parent
76d2852550
commit
40f7cd2bdd
6 changed files with 68 additions and 14 deletions
|
|
@ -1165,7 +1165,8 @@ CURLcode curl_easy_pause(CURL *d, int action)
|
||||||
send_paused = Curl_xfer_send_is_paused(data);
|
send_paused = Curl_xfer_send_is_paused(data);
|
||||||
send_paused_new = (action & CURLPAUSE_SEND);
|
send_paused_new = (action & CURLPAUSE_SEND);
|
||||||
|
|
||||||
if(send_paused != send_paused_new) {
|
if((send_paused != send_paused_new) ||
|
||||||
|
(send_paused_new != Curl_creader_is_paused(data))) {
|
||||||
changed = TRUE;
|
changed = TRUE;
|
||||||
result = Curl_1st_err(result, Curl_xfer_pause_send(data, send_paused_new));
|
result = Curl_1st_err(result, Curl_xfer_pause_send(data, send_paused_new));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1442,6 +1442,7 @@ CURLcode Curl_creader_unpause(struct Curl_easy *data)
|
||||||
|
|
||||||
while(reader) {
|
while(reader) {
|
||||||
result = reader->crt->cntrl(data, reader, CURL_CRCNTRL_UNPAUSE);
|
result = reader->crt->cntrl(data, reader, CURL_CRCNTRL_UNPAUSE);
|
||||||
|
CURL_TRC_READ(data, "unpausing %s -> %d", reader->crt->name, result);
|
||||||
if(result)
|
if(result)
|
||||||
break;
|
break;
|
||||||
reader = reader->next;
|
reader = reader->next;
|
||||||
|
|
|
||||||
|
|
@ -671,6 +671,25 @@ class TestUpload:
|
||||||
])
|
])
|
||||||
r.check_stats(count=1, http_status=200, exitcode=0)
|
r.check_stats(count=1, http_status=200, exitcode=0)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("proto", ['http/1.1'])
|
||||||
|
def test_07_63_upload_exp100_paused(self, env: Env, httpd, nghttpx, proto):
|
||||||
|
read_delay = 1
|
||||||
|
url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]'\
|
||||||
|
f'&read_delay={read_delay}s'
|
||||||
|
upload_size = 128 * 1024
|
||||||
|
client = LocalClient(name='cli_hx_upload', env=env)
|
||||||
|
if not client.exists():
|
||||||
|
pytest.skip(f'example client not built: {client.name}')
|
||||||
|
r = client.run(args=[
|
||||||
|
'-n', '1',
|
||||||
|
'-S', f'{upload_size}',
|
||||||
|
'-P', '1',
|
||||||
|
'-M', 'MIME',
|
||||||
|
'-r', f'{env.domain1}:{env.port_for(proto)}:127.0.0.1',
|
||||||
|
'-V', proto, url
|
||||||
|
])
|
||||||
|
r.check_exit_code(0)
|
||||||
|
|
||||||
# nghttpx is the only server we have that supports TLS early data and
|
# nghttpx is the only server we have that supports TLS early data and
|
||||||
# has a limit of 16k it announces
|
# has a limit of 16k it announces
|
||||||
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx")
|
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx")
|
||||||
|
|
|
||||||
|
|
@ -575,11 +575,13 @@ class Httpd:
|
||||||
return
|
return
|
||||||
local_dir = os.path.dirname(inspect.getfile(Httpd))
|
local_dir = os.path.dirname(inspect.getfile(Httpd))
|
||||||
out_dir = os.path.join(self.env.gen_dir, 'mod_curltest')
|
out_dir = os.path.join(self.env.gen_dir, 'mod_curltest')
|
||||||
|
in_source = os.path.join(local_dir, 'mod_curltest/mod_curltest.c')
|
||||||
out_source = os.path.join(out_dir, 'mod_curltest.c')
|
out_source = os.path.join(out_dir, 'mod_curltest.c')
|
||||||
if not os.path.exists(out_dir):
|
if not os.path.exists(out_dir):
|
||||||
os.mkdir(out_dir)
|
os.mkdir(out_dir)
|
||||||
if not os.path.exists(out_source):
|
if not os.path.exists(out_source) or \
|
||||||
shutil.copy(os.path.join(local_dir, 'mod_curltest/mod_curltest.c'), out_source)
|
os.stat(in_source).st_mtime > os.stat(out_source).st_mtime:
|
||||||
|
shutil.copy(in_source, out_source)
|
||||||
p = subprocess.run([
|
p = subprocess.run([
|
||||||
self.env.apxs, '-c', out_source
|
self.env.apxs, '-c', out_source
|
||||||
], capture_output=True, cwd=out_dir)
|
], capture_output=True, cwd=out_dir)
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ static int curltest_echo_handler(request_rec *r)
|
||||||
char buffer[8192];
|
char buffer[8192];
|
||||||
const char *ct;
|
const char *ct;
|
||||||
apr_off_t die_after_len = -1, total_read_len = 0;
|
apr_off_t die_after_len = -1, total_read_len = 0;
|
||||||
|
apr_time_t read_delay = 0;
|
||||||
int just_die = 0, die_after_100 = 0;
|
int just_die = 0, die_after_100 = 0;
|
||||||
long l;
|
long l;
|
||||||
|
|
||||||
|
|
@ -221,6 +222,12 @@ static int curltest_echo_handler(request_rec *r)
|
||||||
die_after_100 = 1;
|
die_after_100 = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if(!strcmp("read_delay", arg)) {
|
||||||
|
rv = duration_parse(&read_delay, val, "s");
|
||||||
|
if(APR_SUCCESS == rv) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -258,6 +265,12 @@ static int curltest_echo_handler(request_rec *r)
|
||||||
apr_table_setn(r->headers_out, "Request-TE",
|
apr_table_setn(r->headers_out, "Request-TE",
|
||||||
apr_table_get(r->headers_in, "TE"));
|
apr_table_get(r->headers_in, "TE"));
|
||||||
|
|
||||||
|
if(read_delay) {
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||||
|
"put_handler: read_delay");
|
||||||
|
apr_sleep(read_delay);
|
||||||
|
}
|
||||||
|
|
||||||
bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||||
/* copy any request body into the response */
|
/* copy any request body into the response */
|
||||||
rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
|
rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
|
||||||
|
|
@ -637,6 +650,8 @@ static int curltest_put_handler(request_rec *r)
|
||||||
ap_set_content_type(r, ct ? ct : "text/plain");
|
ap_set_content_type(r, ct ? ct : "text/plain");
|
||||||
|
|
||||||
if(read_delay) {
|
if(read_delay) {
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||||
|
"put_handler: read_delay");
|
||||||
apr_sleep(read_delay);
|
apr_sleep(read_delay);
|
||||||
}
|
}
|
||||||
bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ struct transfer_u {
|
||||||
CURL *easy;
|
CURL *easy;
|
||||||
const char *method;
|
const char *method;
|
||||||
char filename[128];
|
char filename[128];
|
||||||
|
curl_mime *mime;
|
||||||
FILE *out;
|
FILE *out;
|
||||||
curl_off_t send_total;
|
curl_off_t send_total;
|
||||||
curl_off_t recv_size;
|
curl_off_t recv_size;
|
||||||
|
|
@ -158,18 +159,28 @@ static int setup_hx_upload(CURL *hnd, const char *url, struct transfer_u *t,
|
||||||
if(use_earlydata)
|
if(use_earlydata)
|
||||||
curl_easy_setopt(hnd, CURLOPT_SSL_OPTIONS, CURLSSLOPT_EARLYDATA);
|
curl_easy_setopt(hnd, CURLOPT_SSL_OPTIONS, CURLSSLOPT_EARLYDATA);
|
||||||
|
|
||||||
if(!t->method || !strcmp("PUT", t->method))
|
if(!strcmp("MIME", t->method)) {
|
||||||
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
curl_mimepart *part;
|
||||||
else if(!strcmp("POST", t->method))
|
t->mime = curl_mime_init(hnd);
|
||||||
curl_easy_setopt(hnd, CURLOPT_POST, 1L);
|
part = curl_mime_addpart(t->mime);
|
||||||
else {
|
curl_mime_name(part, "file");
|
||||||
curl_mfprintf(stderr, "unsupported method '%s'\n", t->method);
|
curl_mime_data_cb(part, -1, my_read_cb, NULL, NULL, t);
|
||||||
return 1;
|
curl_easy_setopt(hnd, CURLOPT_MIMEPOST, t->mime);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(!t->method || !strcmp("PUT", t->method))
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L);
|
||||||
|
else if(!strcmp("POST", t->method))
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_POST, 1L);
|
||||||
|
else {
|
||||||
|
curl_mfprintf(stderr, "unsupported method '%s'\n", t->method);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, my_read_cb);
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_READDATA, t);
|
||||||
|
if(announce_length)
|
||||||
|
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, t->send_total);
|
||||||
}
|
}
|
||||||
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, my_read_cb);
|
|
||||||
curl_easy_setopt(hnd, CURLOPT_READDATA, t);
|
|
||||||
if(announce_length)
|
|
||||||
curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, t->send_total);
|
|
||||||
|
|
||||||
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
|
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L);
|
||||||
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, my_progress_u_cb);
|
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, my_progress_u_cb);
|
||||||
|
|
@ -488,6 +499,7 @@ static CURLcode test_cli_hx_upload(const char *URL)
|
||||||
|
|
||||||
} while(active_transfers); /* as long as we have transfers going */
|
} while(active_transfers); /* as long as we have transfers going */
|
||||||
|
|
||||||
|
curl_mfprintf(stderr, "all transfers done, cleanup multi\n");
|
||||||
curl_multi_cleanup(multi_handle);
|
curl_multi_cleanup(multi_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,9 +513,13 @@ static CURLcode test_cli_hx_upload(const char *URL)
|
||||||
curl_easy_cleanup(t->easy);
|
curl_easy_cleanup(t->easy);
|
||||||
t->easy = NULL;
|
t->easy = NULL;
|
||||||
}
|
}
|
||||||
|
if(t->mime) {
|
||||||
|
curl_mime_free(t->mime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(transfer_u);
|
free(transfer_u);
|
||||||
curl_share_cleanup(share);
|
curl_share_cleanup(share);
|
||||||
|
curl_slist_free_all(host);
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue