diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-08-13 17:29:33 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-08-13 23:18:21 +0200 |
commit | 32f6812b5ac3649e21e28d46bfdbf96af2786347 (patch) | |
tree | 8820c051398e0927c1eef8700f33d19eea6ab69c | |
parent | f67883e55a27f9ec4825a283c94c008bba644f06 (diff) | |
download | curl-32f6812b5ac3649e21e28d46bfdbf96af2786347.tar.gz |
c-hyper: initial step for 100-continue support
Enabled test 154
Closes #7568
-rw-r--r-- | lib/c-hyper.c | 59 | ||||
-rw-r--r-- | lib/c-hyper.h | 1 | ||||
-rw-r--r-- | tests/data/DISABLED | 1 |
3 files changed, 57 insertions, 4 deletions
diff --git a/lib/c-hyper.c b/lib/c-hyper.c index 9ad76991c..57ac9af4b 100644 --- a/lib/c-hyper.c +++ b/lib/c-hyper.c @@ -176,7 +176,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) size_t len = hyper_buf_len(chunk); struct Curl_easy *data = (struct Curl_easy *)userdata; struct SingleRequest *k = &data->req; - CURLcode result; + CURLcode result = CURLE_OK; if(0 == k->bodywrites++) { bool done = FALSE; @@ -192,6 +192,20 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) Curl_safefree(data->req.newurl); } #endif + if(data->state.expect100header) { + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + if(data->req.httpcode < 400) { + k->exp100 = EXP100_SEND_DATA; + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + else { /* >= 4xx */ + k->exp100 = EXP100_FAILED; + done = TRUE; + } + } if(data->state.hconnect && (data->req.httpcode/100 != 2)) { done = TRUE; @@ -306,8 +320,25 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, const uint8_t *reasonp; size_t reason_len; CURLcode result = CURLE_OK; + struct SingleRequest *k = &data->req; (void)conn; + if(k->exp100 > EXP100_SEND_DATA) { + struct curltime now = Curl_now(); + timediff_t ms = Curl_timediff(now, k->start100); + if(ms >= data->set.expect_100_timeout) { + /* we've waited long enough, continue anyway */ + k->exp100 = EXP100_SEND_DATA; + k->keepon |= KEEP_SEND; + Curl_expire_done(data, EXPIRE_100_TIMEOUT); + infof(data, "Done waiting for 100-continue"); + if(data->hyp.exp100_waker) { + hyper_waker_wake(data->hyp.exp100_waker); + data->hyp.exp100_waker = NULL; + } + } + } + if(select_res & CURL_CSELECT_IN) { if(h->read_waker) hyper_waker_wake(h->read_waker); @@ -591,9 +622,21 @@ static int uploadstreamed(void *userdata, hyper_context *ctx, { size_t fillcount; struct Curl_easy *data = (struct Curl_easy *)userdata; - CURLcode result = - Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); + CURLcode result; (void)ctx; + + if(data->req.exp100 > EXP100_SEND_DATA) { + if(data->req.exp100 == EXP100_FAILED) + return HYPER_POLL_ERROR; + + /* still waiting confirmation */ + if(data->hyp.exp100_waker) + hyper_waker_free(data->hyp.exp100_waker); + data->hyp.exp100_waker = hyper_context_waker(ctx); + return HYPER_POLL_PENDING; + } + + result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); if(result) { data->state.hresult = result; return HYPER_POLL_ERROR; @@ -628,6 +671,7 @@ static CURLcode bodysend(struct Curl_easy *data, hyper_request *hyperreq, Curl_HttpReq httpreq) { + struct HTTP *http = data->req.p.http; CURLcode result = CURLE_OK; struct dynbuf req; if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) @@ -660,6 +704,7 @@ static CURLcode bodysend(struct Curl_easy *data, result = CURLE_OUT_OF_MEMORY; } } + http->sending = HTTPSEND_BODY; return result; } @@ -938,6 +983,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); } conn->datastream = Curl_hyper_stream; + if(data->state.expect100header) + /* Timeout count starts now since with Hyper we don't know exactly when + the full request has been sent. */ + data->req.start100 = Curl_now(); /* clear userpwd and proxyuserpwd to avoid re-using old credentials * from re-used connections */ @@ -973,6 +1022,10 @@ void Curl_hyper_done(struct Curl_easy *data) hyper_waker_free(h->write_waker); h->write_waker = NULL; } + if(h->exp100_waker) { + hyper_waker_free(h->exp100_waker); + h->exp100_waker = NULL; + } } #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */ diff --git a/lib/c-hyper.h b/lib/c-hyper.h index d60ed78d1..d63defeff 100644 --- a/lib/c-hyper.h +++ b/lib/c-hyper.h @@ -33,6 +33,7 @@ struct hyptransfer { hyper_waker *read_waker; const hyper_executor *exec; hyper_task *endtask; + hyper_waker *exp100_waker; }; size_t Curl_hyper_recv(void *userp, hyper_context *ctx, diff --git a/tests/data/DISABLED b/tests/data/DISABLED index e04eaa8a6..69e03ea8f 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -36,7 +36,6 @@ # hyper support remains EXPERIMENTAL as long as there's a test number # listed below %if hyper -154 155 158 206 |