aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/lib/c-hyper.c
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.ru>2022-04-10 23:38:39 +0300
committershadchin <shadchin@yandex-team.ru>2022-04-10 23:38:39 +0300
commitd0d27ff451c16dbec7fbc99206cba32803c52cc6 (patch)
tree9ab7a06c0bb58e38fe848af1bb8623f468900ba6 /contrib/libs/curl/lib/c-hyper.c
parent37591f1db8ea08ea964badf4ff15f8a923271524 (diff)
downloadydb-d0d27ff451c16dbec7fbc99206cba32803c52cc6.tar.gz
CONTRIB-2513 Update contrib/libs/curl to 7.79.1
ref:cfccba5015904b0f0cadfc018200e2a1b4d50ae6
Diffstat (limited to 'contrib/libs/curl/lib/c-hyper.c')
-rw-r--r--contrib/libs/curl/lib/c-hyper.c159
1 files changed, 127 insertions, 32 deletions
diff --git a/contrib/libs/curl/lib/c-hyper.c b/contrib/libs/curl/lib/c-hyper.c
index 361035d85a4..b9180fec52e 100644
--- a/contrib/libs/curl/lib/c-hyper.c
+++ b/contrib/libs/curl/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,8 +192,20 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
Curl_safefree(data->req.newurl);
}
#endif
- if(data->state.hconnect &&
- (data->req.httpcode/100 != 2)) {
+ 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;
+ }
+ }
+ if(data->state.hconnect && (data->req.httpcode/100 != 2)) {
done = TRUE;
result = CURLE_OK;
}
@@ -245,6 +257,9 @@ static CURLcode status_line(struct Curl_easy *data,
conn->httpversion =
http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
(http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
+ if(http_version == HYPER_HTTP_VERSION_1_0)
+ data->state.httpwant = CURL_HTTP_VERSION_1_0;
+
data->req.httpcode = http_status;
result = Curl_http_statusline(data, conn);
@@ -306,8 +321,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);
@@ -341,8 +373,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
hyper_task_free(task);
if(t == HYPER_TASK_ERROR) {
- hyper_code errnum = hyper_error_code(hypererr);
- if(errnum == HYPERE_ABORTED_BY_CALLBACK) {
+ if(data->state.hresult) {
/* override Hyper's view, might not even be an error */
result = data->state.hresult;
infof(data, "hyperstream is done (by early callback)");
@@ -352,7 +383,9 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
hyper_code code = hyper_error_code(hypererr);
failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
+ if(code == HYPERE_ABORTED_BY_CALLBACK)
+ result = CURLE_OK;
+ else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
result = CURLE_GOT_NOTHING;
else if(code == HYPERE_INVALID_PEER_MESSAGE)
result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
@@ -367,6 +400,11 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
/* end of transfer */
*done = TRUE;
infof(data, "hyperstream is done!");
+ if(!k->bodywrites) {
+ /* hyper doesn't always call the body write callback */
+ bool stilldone;
+ result = Curl_http_firstwrite(data, data->conn, &stilldone);
+ }
break;
}
else if(t != HYPER_TASK_RESPONSE) {
@@ -523,7 +561,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
free(ptr);
}
else
- Curl_debug(data, CURLINFO_HEADER_OUT, (char *)line, linelen);
+ Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
}
numh++;
n += linelen;
@@ -564,6 +602,16 @@ static int uploadpostfields(void *userdata, hyper_context *ctx,
{
struct Curl_easy *data = (struct Curl_easy *)userdata;
(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;
+ }
if(data->req.upload_done)
*chunk = NULL; /* nothing more to deliver */
else {
@@ -590,9 +638,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;
@@ -627,6 +687,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))
@@ -659,6 +720,7 @@ static CURLcode bodysend(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
}
}
+ http->sending = HTTPSEND_BODY;
return result;
}
@@ -677,6 +739,48 @@ static CURLcode cookies(struct Curl_easy *data,
return result;
}
+/* called on 1xx responses */
+static void http1xx_cb(void *arg, struct hyper_response *resp)
+{
+ struct Curl_easy *data = (struct Curl_easy *)arg;
+ hyper_headers *headers = NULL;
+ CURLcode result = CURLE_OK;
+ uint16_t http_status;
+ int http_version;
+ const uint8_t *reasonp;
+ size_t reason_len;
+
+ infof(data, "Got HTTP 1xx informational");
+
+ http_status = hyper_response_status(resp);
+ http_version = hyper_response_version(resp);
+ reasonp = hyper_response_reason_phrase(resp);
+ reason_len = hyper_response_reason_phrase_len(resp);
+
+ result = status_line(data, data->conn,
+ http_status, http_version, reasonp, reason_len);
+ if(!result) {
+ headers = hyper_response_headers(resp);
+ if(!headers) {
+ failf(data, "hyperstream: couldn't get 1xx response headers");
+ result = CURLE_RECV_ERROR;
+ }
+ }
+ data->state.hresult = result;
+
+ if(!result) {
+ /* the headers are already received */
+ hyper_headers_foreach(headers, hyper_each_header, data);
+ /* this callback also sets data->state.hresult on error */
+
+ if(empty_header(data))
+ result = CURLE_OUT_OF_MEMORY;
+ }
+
+ if(data->state.hresult)
+ infof(data, "ERROR in 1xx, bail out!");
+}
+
/*
* Curl_http() gets called from the generic multi_do() function when a HTTP
* request is to be performed. This creates and sends a properly constructed
@@ -694,13 +798,13 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
hyper_request *req = NULL;
hyper_headers *headers = NULL;
hyper_task *handshake = NULL;
- hyper_error *hypererr = NULL;
CURLcode result;
const char *p_accept; /* Accept: string */
const char *method;
Curl_HttpReq httpreq;
bool h2 = FALSE;
const char *te = NULL; /* transfer-encoding */
+ hyper_code rc;
/* Always consider the DO phase done after this function call, even if there
may be parts of the request that is not yet sent, since we can deal with
@@ -804,7 +908,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
- if(data->state.httpwant == CURL_HTTP_VERSION_1_0) {
+ if(!Curl_use_http_1_1plus(data, conn)) {
if(HYPERE_OK != hyper_request_set_version(req,
HYPER_HTTP_VERSION_1_0)) {
failf(data, "error setting HTTP version");
@@ -827,6 +931,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
goto error;
}
+ rc = hyper_request_on_informational(req, http1xx_cb, data);
+ if(rc)
+ return CURLE_OUT_OF_MEMORY;
+
result = Curl_http_body(data, conn, httpreq, &te);
if(result)
return result;
@@ -932,24 +1040,16 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
hyper_clientconn_free(client);
- do {
- task = hyper_executor_poll(h->exec);
- if(task) {
- bool error = hyper_task_type(task) == HYPER_TASK_ERROR;
- if(error)
- hypererr = hyper_task_value(task);
- hyper_task_free(task);
- if(error)
- goto error;
- }
- } while(task);
-
if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
/* HTTP GET/HEAD download */
Curl_pgrsSetUploadSize(data, 0); /* nothing */
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 */
@@ -967,15 +1067,6 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
if(handshake)
hyper_task_free(handshake);
- if(hypererr) {
- uint8_t errbuf[256];
- size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
- hyper_code code = hyper_error_code(hypererr);
- failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
- hyper_error_free(hypererr);
- if(data->state.hresult)
- return data->state.hresult;
- }
return CURLE_OUT_OF_MEMORY;
}
@@ -994,6 +1085,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) */