1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
44 #ifdef HAVE_SYS_PARAM_H
45 #include <sys/param.h>
54 #include "content_encoding.h"
56 /* The last 3 #include files should be in this order */
57 #include "curl_printf.h"
58 #include "curl_memory.h"
61 size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
62 uint8_t *buf, size_t buflen)
64 struct Curl_easy *data = userp;
65 struct connectdata *conn = data->conn;
71 result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread);
72 if(result == CURLE_AGAIN) {
73 /* would block, register interest */
74 if(data->hyp.read_waker)
75 hyper_waker_free(data->hyp.read_waker);
76 data->hyp.read_waker = hyper_context_waker(ctx);
77 if(!data->hyp.read_waker) {
78 failf(data, "Couldn't make the read hyper_context_waker");
79 return HYPER_IO_ERROR;
81 return HYPER_IO_PENDING;
84 failf(data, "Curl_read failed");
85 return HYPER_IO_ERROR;
90 size_t Curl_hyper_send(void *userp, hyper_context *ctx,
91 const uint8_t *buf, size_t buflen)
93 struct Curl_easy *data = userp;
94 struct connectdata *conn = data->conn;
98 result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote);
99 if(result == CURLE_AGAIN) {
100 /* would block, register interest */
101 if(data->hyp.write_waker)
102 hyper_waker_free(data->hyp.write_waker);
103 data->hyp.write_waker = hyper_context_waker(ctx);
104 if(!data->hyp.write_waker) {
105 failf(data, "Couldn't make the write hyper_context_waker");
106 return HYPER_IO_ERROR;
108 return HYPER_IO_PENDING;
111 failf(data, "Curl_write failed");
112 return HYPER_IO_ERROR;
114 return (size_t)nwrote;
117 static int hyper_each_header(void *userdata,
120 const uint8_t *value,
123 struct Curl_easy *data = (struct Curl_easy *)userdata;
129 if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
130 failf(data, "Too long response header");
131 data->state.hresult = CURLE_OUT_OF_MEMORY;
132 return HYPER_ITER_BREAK;
135 if(!data->req.bytecount)
136 Curl_pgrsTime(data, TIMER_STARTTRANSFER);
138 Curl_dyn_reset(&data->state.headerb);
140 if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
141 (int) name_len, name, (int) value_len, value))
142 return HYPER_ITER_BREAK;
145 if(Curl_dyn_addn(&data->state.headerb, STRCONST("\r\n")))
146 return HYPER_ITER_BREAK;
148 len = Curl_dyn_len(&data->state.headerb);
149 headp = Curl_dyn_ptr(&data->state.headerb);
151 result = Curl_http_header(data, data->conn, headp);
153 data->state.hresult = result;
154 return HYPER_ITER_BREAK;
157 Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
159 if(!data->state.hconnect || !data->set.suppress_connect_headers) {
160 writetype = CLIENTWRITE_HEADER;
161 if(data->set.include_header)
162 writetype |= CLIENTWRITE_BODY;
163 result = Curl_client_write(data, writetype, headp, len);
165 data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
166 return HYPER_ITER_BREAK;
170 data->info.header_size += (long)len;
171 data->req.headerbytecount += (long)len;
172 return HYPER_ITER_CONTINUE;
175 static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
177 char *buf = (char *)hyper_buf_bytes(chunk);
178 size_t len = hyper_buf_len(chunk);
179 struct Curl_easy *data = (struct Curl_easy *)userdata;
180 struct SingleRequest *k = &data->req;
181 CURLcode result = CURLE_OK;
183 if(0 == k->bodywrites++) {
185 #if defined(USE_NTLM)
186 struct connectdata *conn = data->conn;
187 if(conn->bits.close &&
188 (((data->req.httpcode == 401) &&
189 (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
190 ((data->req.httpcode == 407) &&
191 (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
192 infof(data, "Connection closed while negotiating NTLM");
193 data->state.authproblem = TRUE;
194 Curl_safefree(data->req.newurl);
197 if(data->state.expect100header) {
198 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
199 if(data->req.httpcode < 400) {
200 k->exp100 = EXP100_SEND_DATA;
201 if(data->hyp.exp100_waker) {
202 hyper_waker_wake(data->hyp.exp100_waker);
203 data->hyp.exp100_waker = NULL;
207 k->exp100 = EXP100_FAILED;
210 if(data->state.hconnect && (data->req.httpcode/100 != 2) &&
211 data->state.authproxy.done) {
216 result = Curl_http_firstwrite(data, data->conn, &done);
218 infof(data, "Return early from hyper_body_chunk");
219 data->state.hresult = result;
220 return HYPER_ITER_BREAK;
224 return HYPER_ITER_CONTINUE;
226 return HYPER_ITER_CONTINUE;
227 Curl_debug(data, CURLINFO_DATA_IN, buf, len);
228 if(!data->set.http_ce_skip && k->writer_stack)
229 /* content-encoded data */
230 result = Curl_unencode_write(data, k->writer_stack, buf, len);
232 result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
235 data->state.hresult = result;
236 return HYPER_ITER_BREAK;
239 data->req.bytecount += len;
240 Curl_pgrsSetDownloadCounter(data, data->req.bytecount);
241 return HYPER_ITER_CONTINUE;
245 * Hyper does not consider the status line, the first line in a HTTP/1
246 * response, to be a header. The libcurl API does. This function sends the
247 * status line in the header callback. */
248 static CURLcode status_line(struct Curl_easy *data,
249 struct connectdata *conn,
250 uint16_t http_status,
252 const uint8_t *reason, size_t rlen)
258 vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
259 (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
261 http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
262 (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
263 if(http_version == HYPER_HTTP_VERSION_1_0)
264 data->state.httpwant = CURL_HTTP_VERSION_1_0;
266 if(data->state.hconnect)
268 data->info.httpproxycode = http_status;
270 /* We need to set 'httpcodeq' for functions that check the response code in
272 data->req.httpcode = http_status;
274 result = Curl_http_statusline(data, conn);
278 Curl_dyn_reset(&data->state.headerb);
280 result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
286 len = Curl_dyn_len(&data->state.headerb);
287 Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
290 if(!data->state.hconnect || !data->set.suppress_connect_headers) {
291 writetype = CLIENTWRITE_HEADER;
292 if(data->set.include_header)
293 writetype |= CLIENTWRITE_BODY;
294 result = Curl_client_write(data, writetype,
295 Curl_dyn_ptr(&data->state.headerb), len);
299 data->info.header_size += (long)len;
300 data->req.headerbytecount += (long)len;
301 data->req.httpcode = http_status;
306 * Hyper does not pass on the last empty response header. The libcurl API
307 * does. This function sends an empty header in the header callback.
309 static CURLcode empty_header(struct Curl_easy *data)
311 CURLcode result = Curl_http_size(data);
313 result = hyper_each_header(data, NULL, 0, NULL, 0) ?
314 CURLE_WRITE_ERROR : CURLE_OK;
316 failf(data, "hyperstream: couldn't pass blank header");
321 CURLcode Curl_hyper_stream(struct Curl_easy *data,
322 struct connectdata *conn,
327 hyper_response *resp = NULL;
328 uint16_t http_status;
330 hyper_headers *headers = NULL;
331 hyper_body *resp_body = NULL;
332 struct hyptransfer *h = &data->hyp;
335 hyper_error *hypererr = NULL;
336 const uint8_t *reasonp;
338 CURLcode result = CURLE_OK;
339 struct SingleRequest *k = &data->req;
342 if(k->exp100 > EXP100_SEND_DATA) {
343 struct curltime now = Curl_now();
344 timediff_t ms = Curl_timediff(now, k->start100);
345 if(ms >= data->set.expect_100_timeout) {
346 /* we've waited long enough, continue anyway */
347 k->exp100 = EXP100_SEND_DATA;
348 k->keepon |= KEEP_SEND;
349 Curl_expire_done(data, EXPIRE_100_TIMEOUT);
350 infof(data, "Done waiting for 100-continue");
351 if(data->hyp.exp100_waker) {
352 hyper_waker_wake(data->hyp.exp100_waker);
353 data->hyp.exp100_waker = NULL;
358 if(select_res & CURL_CSELECT_IN) {
360 hyper_waker_wake(h->read_waker);
361 h->read_waker = NULL;
363 if(select_res & CURL_CSELECT_OUT) {
365 hyper_waker_wake(h->write_waker);
366 h->write_waker = NULL;
371 hyper_task_return_type t;
372 task = hyper_executor_poll(h->exec);
374 *didwhat = KEEP_RECV;
377 t = hyper_task_type(task);
379 case HYPER_TASK_ERROR:
380 hypererr = hyper_task_value(task);
382 case HYPER_TASK_RESPONSE:
383 resp = hyper_task_value(task);
388 hyper_task_free(task);
390 if(t == HYPER_TASK_ERROR) {
391 if(data->state.hresult) {
392 /* override Hyper's view, might not even be an error */
393 result = data->state.hresult;
394 infof(data, "hyperstream is done (by early callback)");
398 size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
399 hyper_code code = hyper_error_code(hypererr);
400 failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
401 if(code == HYPERE_ABORTED_BY_CALLBACK)
403 else if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount)
404 result = CURLE_GOT_NOTHING;
405 else if(code == HYPERE_INVALID_PEER_MESSAGE)
406 result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
408 result = CURLE_RECV_ERROR;
411 hyper_error_free(hypererr);
414 else if(h->endtask == task) {
415 /* end of transfer */
417 infof(data, "hyperstream is done");
419 /* hyper doesn't always call the body write callback */
421 result = Curl_http_firstwrite(data, data->conn, &stilldone);
425 else if(t != HYPER_TASK_RESPONSE) {
426 *didwhat = KEEP_RECV;
429 /* HYPER_TASK_RESPONSE */
431 *didwhat = KEEP_RECV;
433 failf(data, "hyperstream: couldn't get response");
434 return CURLE_RECV_ERROR;
437 http_status = hyper_response_status(resp);
438 http_version = hyper_response_version(resp);
439 reasonp = hyper_response_reason_phrase(resp);
440 reason_len = hyper_response_reason_phrase_len(resp);
442 if(http_status == 417 && data->state.expect100header) {
443 infof(data, "Got 417 while waiting for a 100");
444 data->state.disableexpect = TRUE;
445 data->req.newurl = strdup(data->state.url);
446 Curl_done_sending(data, k);
449 result = status_line(data, conn,
450 http_status, http_version, reasonp, reason_len);
454 headers = hyper_response_headers(resp);
456 failf(data, "hyperstream: couldn't get response headers");
457 result = CURLE_RECV_ERROR;
461 /* the headers are already received */
462 hyper_headers_foreach(headers, hyper_each_header, data);
463 if(data->state.hresult) {
464 result = data->state.hresult;
468 result = empty_header(data);
472 /* Curl_http_auth_act() checks what authentication methods that are
473 * available and decides which one (if any) to use. It will set 'newurl'
474 * if an auth method was picked. */
475 result = Curl_http_auth_act(data);
479 resp_body = hyper_response_body(resp);
481 failf(data, "hyperstream: couldn't get response body");
482 result = CURLE_RECV_ERROR;
485 foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
487 failf(data, "hyperstream: body foreach failed");
488 result = CURLE_OUT_OF_MEMORY;
491 DEBUGASSERT(hyper_task_type(foreach) == HYPER_TASK_EMPTY);
492 if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
493 failf(data, "Couldn't hyper_executor_push the body-foreach");
494 result = CURLE_OUT_OF_MEMORY;
497 h->endtask = foreach;
499 hyper_response_free(resp);
503 hyper_response_free(resp);
507 static CURLcode debug_request(struct Curl_easy *data,
512 char *req = aprintf("%s %s HTTP/%s\r\n", method, path,
515 return CURLE_OUT_OF_MEMORY;
516 Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
522 * Given a full header line "name: value" (optional CRLF in the input, should
523 * be in the output), add to Hyper and send to the debug callback.
525 * Supports multiple headers.
528 CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
547 /* this is fine if we already added at least one header */
548 return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
550 p++; /* move past the colon */
558 linelen = 1; /* LF only */
561 newline = FALSE; /* no newline */
565 linelen = 2; /* CRLF ending */
569 if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
570 (uint8_t *)v, vlen)) {
571 failf(data, "hyper refused to add header '%s'", line);
572 return CURLE_OUT_OF_MEMORY;
574 if(data->set.verbose) {
577 ptr = aprintf("%.*s\r\n", (int)linelen, line);
579 return CURLE_OUT_OF_MEMORY;
580 Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
584 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
592 static CURLcode request_target(struct Curl_easy *data,
593 struct connectdata *conn,
601 Curl_dyn_init(&r, DYN_HTTP_REQUEST);
603 result = Curl_http_target(data, conn, &r);
607 if(h2 && hyper_request_set_uri_parts(req,
609 (uint8_t *)data->state.up.scheme,
610 strlen(data->state.up.scheme),
612 (uint8_t *)conn->host.name,
613 strlen(conn->host.name),
615 (uint8_t *)Curl_dyn_uptr(&r),
617 failf(data, "error setting uri parts to hyper");
618 result = CURLE_OUT_OF_MEMORY;
620 else if(!h2 && hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
622 failf(data, "error setting uri to hyper");
623 result = CURLE_OUT_OF_MEMORY;
626 result = debug_request(data, method, Curl_dyn_ptr(&r), h2);
633 static int uploadpostfields(void *userdata, hyper_context *ctx,
636 struct Curl_easy *data = (struct Curl_easy *)userdata;
638 if(data->req.exp100 > EXP100_SEND_DATA) {
639 if(data->req.exp100 == EXP100_FAILED)
640 return HYPER_POLL_ERROR;
642 /* still waiting confirmation */
643 if(data->hyp.exp100_waker)
644 hyper_waker_free(data->hyp.exp100_waker);
645 data->hyp.exp100_waker = hyper_context_waker(ctx);
646 return HYPER_POLL_PENDING;
648 if(data->req.upload_done)
649 *chunk = NULL; /* nothing more to deliver */
651 /* send everything off in a single go */
652 hyper_buf *copy = hyper_buf_copy(data->set.postfields,
653 (size_t)data->req.p.http->postsize);
657 data->state.hresult = CURLE_OUT_OF_MEMORY;
658 return HYPER_POLL_ERROR;
660 /* increasing the writebytecount here is a little premature but we
661 don't know exactly when the body is sent*/
662 data->req.writebytecount += (size_t)data->req.p.http->postsize;
663 Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
664 data->req.upload_done = TRUE;
666 return HYPER_POLL_READY;
669 static int uploadstreamed(void *userdata, hyper_context *ctx,
673 struct Curl_easy *data = (struct Curl_easy *)userdata;
677 if(data->req.exp100 > EXP100_SEND_DATA) {
678 if(data->req.exp100 == EXP100_FAILED)
679 return HYPER_POLL_ERROR;
681 /* still waiting confirmation */
682 if(data->hyp.exp100_waker)
683 hyper_waker_free(data->hyp.exp100_waker);
684 data->hyp.exp100_waker = hyper_context_waker(ctx);
685 return HYPER_POLL_PENDING;
688 result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
690 data->state.hresult = result;
691 return HYPER_POLL_ERROR;
697 hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount);
701 data->state.hresult = CURLE_OUT_OF_MEMORY;
702 return HYPER_POLL_ERROR;
704 /* increasing the writebytecount here is a little premature but we
705 don't know exactly when the body is sent*/
706 data->req.writebytecount += fillcount;
707 Curl_pgrsSetUploadCounter(data, fillcount);
709 return HYPER_POLL_READY;
713 * bodysend() sets up headers in the outgoing request for a HTTP transfer that
717 static CURLcode bodysend(struct Curl_easy *data,
718 struct connectdata *conn,
719 hyper_headers *headers,
720 hyper_request *hyperreq,
721 Curl_HttpReq httpreq)
723 struct HTTP *http = data->req.p.http;
724 CURLcode result = CURLE_OK;
726 if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD))
727 Curl_pgrsSetUploadSize(data, 0); /* no request body */
730 Curl_dyn_init(&req, DYN_HTTP_REQUEST);
731 result = Curl_http_bodysend(data, conn, &req, httpreq);
734 result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
738 body = hyper_body_new();
739 hyper_body_set_userdata(body, data);
740 if(data->set.postfields)
741 hyper_body_set_data_func(body, uploadpostfields);
743 result = Curl_get_upload_buffer(data);
746 /* init the "upload from here" pointer */
747 data->req.upload_fromhere = data->state.ulbuf;
748 hyper_body_set_data_func(body, uploadstreamed);
750 if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
752 hyper_body_free(body);
753 result = CURLE_OUT_OF_MEMORY;
756 http->sending = HTTPSEND_BODY;
760 static CURLcode cookies(struct Curl_easy *data,
761 struct connectdata *conn,
762 hyper_headers *headers)
766 Curl_dyn_init(&req, DYN_HTTP_REQUEST);
768 result = Curl_http_cookies(data, conn, &req);
770 result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
775 /* called on 1xx responses */
776 static void http1xx_cb(void *arg, struct hyper_response *resp)
778 struct Curl_easy *data = (struct Curl_easy *)arg;
779 hyper_headers *headers = NULL;
780 CURLcode result = CURLE_OK;
781 uint16_t http_status;
783 const uint8_t *reasonp;
786 infof(data, "Got HTTP 1xx informational");
788 http_status = hyper_response_status(resp);
789 http_version = hyper_response_version(resp);
790 reasonp = hyper_response_reason_phrase(resp);
791 reason_len = hyper_response_reason_phrase_len(resp);
793 result = status_line(data, data->conn,
794 http_status, http_version, reasonp, reason_len);
796 headers = hyper_response_headers(resp);
798 failf(data, "hyperstream: couldn't get 1xx response headers");
799 result = CURLE_RECV_ERROR;
802 data->state.hresult = result;
805 /* the headers are already received */
806 hyper_headers_foreach(headers, hyper_each_header, data);
807 /* this callback also sets data->state.hresult on error */
809 if(empty_header(data))
810 result = CURLE_OUT_OF_MEMORY;
813 if(data->state.hresult)
814 infof(data, "ERROR in 1xx, bail out");
818 * Curl_http() gets called from the generic multi_do() function when a HTTP
819 * request is to be performed. This creates and sends a properly constructed
822 CURLcode Curl_http(struct Curl_easy *data, bool *done)
824 struct connectdata *conn = data->conn;
825 struct hyptransfer *h = &data->hyp;
827 hyper_clientconn_options *options = NULL;
828 hyper_task *task = NULL; /* for the handshake */
829 hyper_task *sendtask = NULL; /* for the send */
830 hyper_clientconn *client = NULL;
831 hyper_request *req = NULL;
832 hyper_headers *headers = NULL;
833 hyper_task *handshake = NULL;
835 const char *p_accept; /* Accept: string */
837 Curl_HttpReq httpreq;
839 const char *te = NULL; /* transfer-encoding */
842 /* Always consider the DO phase done after this function call, even if there
843 may be parts of the request that is not yet sent, since we can deal with
844 the rest of the request in the PERFORM phase. */
847 infof(data, "Time for the Hyper dance");
848 memset(h, 0, sizeof(struct hyptransfer));
850 result = Curl_http_host(data, conn);
854 Curl_http_method(data, conn, &method, &httpreq);
856 /* setup the authentication headers */
859 if(data->state.up.query) {
860 pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
862 return CURLE_OUT_OF_MEMORY;
864 result = Curl_http_output_auth(data, conn, method, httpreq,
865 (pq ? pq : data->state.up.path), FALSE);
871 result = Curl_http_resume(data, conn, httpreq);
875 result = Curl_http_range(data, httpreq);
879 result = Curl_http_useragent(data);
885 failf(data, "Couldn't create hyper IO");
886 result = CURLE_OUT_OF_MEMORY;
889 /* tell Hyper how to read/write network data */
890 hyper_io_set_userdata(io, data);
891 hyper_io_set_read(io, Curl_hyper_recv);
892 hyper_io_set_write(io, Curl_hyper_send);
894 /* create an executor to poll futures */
896 h->exec = hyper_executor_new();
898 failf(data, "Couldn't create hyper executor");
899 result = CURLE_OUT_OF_MEMORY;
904 options = hyper_clientconn_options_new();
906 failf(data, "Couldn't create hyper client options");
907 result = CURLE_OUT_OF_MEMORY;
910 if(conn->negnpn == CURL_HTTP_VERSION_2) {
911 hyper_clientconn_options_http2(options, 1);
914 hyper_clientconn_options_set_preserve_header_case(options, 1);
915 hyper_clientconn_options_set_preserve_header_order(options, 1);
917 hyper_clientconn_options_exec(options, h->exec);
919 /* "Both the `io` and the `options` are consumed in this function call" */
920 handshake = hyper_clientconn_handshake(io, options);
922 failf(data, "Couldn't create hyper client handshake");
923 result = CURLE_OUT_OF_MEMORY;
929 if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
930 failf(data, "Couldn't hyper_executor_push the handshake");
931 result = CURLE_OUT_OF_MEMORY;
934 handshake = NULL; /* ownership passed on */
936 task = hyper_executor_poll(h->exec);
938 failf(data, "Couldn't hyper_executor_poll the handshake");
939 result = CURLE_OUT_OF_MEMORY;
943 client = hyper_task_value(task);
944 hyper_task_free(task);
946 req = hyper_request_new();
948 failf(data, "Couldn't hyper_request_new");
949 result = CURLE_OUT_OF_MEMORY;
953 if(!Curl_use_http_1_1plus(data, conn)) {
954 if(HYPERE_OK != hyper_request_set_version(req,
955 HYPER_HTTP_VERSION_1_0)) {
956 failf(data, "error setting HTTP version");
957 result = CURLE_OUT_OF_MEMORY;
962 if(!h2 && !data->state.disableexpect) {
963 data->state.expect100header = TRUE;
967 if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
968 failf(data, "error setting method");
969 result = CURLE_OUT_OF_MEMORY;
973 result = request_target(data, conn, method, h2, req);
977 headers = hyper_request_headers(req);
979 failf(data, "hyper_request_headers");
980 result = CURLE_OUT_OF_MEMORY;
984 rc = hyper_request_on_informational(req, http1xx_cb, data);
986 result = CURLE_OUT_OF_MEMORY;
990 result = Curl_http_body(data, conn, httpreq, &te);
995 if(data->state.aptr.host) {
996 result = Curl_hyper_header(data, headers, data->state.aptr.host);
1002 /* For HTTP/2, we show the Host: header as if we sent it, to make it look
1003 like for HTTP/1 but it isn't actually sent since :authority is then
1005 result = Curl_debug(data, CURLINFO_HEADER_OUT, data->state.aptr.host,
1006 strlen(data->state.aptr.host));
1011 if(data->state.aptr.proxyuserpwd) {
1012 result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
1017 if(data->state.aptr.userpwd) {
1018 result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
1023 if((data->state.use_range && data->state.aptr.rangeline)) {
1024 result = Curl_hyper_header(data, headers, data->state.aptr.rangeline);
1029 if(data->set.str[STRING_USERAGENT] &&
1030 *data->set.str[STRING_USERAGENT] &&
1031 data->state.aptr.uagent) {
1032 result = Curl_hyper_header(data, headers, data->state.aptr.uagent);
1037 p_accept = Curl_checkheaders(data,
1038 STRCONST("Accept"))?NULL:"Accept: */*\r\n";
1040 result = Curl_hyper_header(data, headers, p_accept);
1045 result = Curl_hyper_header(data, headers, te);
1050 #ifndef CURL_DISABLE_PROXY
1051 if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
1052 !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
1053 !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
1054 result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive");
1060 Curl_safefree(data->state.aptr.ref);
1061 if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
1062 data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
1063 if(!data->state.aptr.ref)
1064 result = CURLE_OUT_OF_MEMORY;
1066 result = Curl_hyper_header(data, headers, data->state.aptr.ref);
1071 if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
1072 data->set.str[STRING_ENCODING]) {
1073 Curl_safefree(data->state.aptr.accept_encoding);
1074 data->state.aptr.accept_encoding =
1075 aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1076 if(!data->state.aptr.accept_encoding)
1077 result = CURLE_OUT_OF_MEMORY;
1079 result = Curl_hyper_header(data, headers,
1080 data->state.aptr.accept_encoding);
1085 Curl_safefree(data->state.aptr.accept_encoding);
1088 /* we only consider transfer-encoding magic if libz support is built-in */
1089 result = Curl_transferencode(data);
1092 result = Curl_hyper_header(data, headers, data->state.aptr.te);
1097 result = cookies(data, conn, headers);
1101 result = Curl_add_timecondition(data, headers);
1105 result = Curl_add_custom_headers(data, FALSE, headers);
1109 result = bodysend(data, conn, headers, req, httpreq);
1113 result = Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
1117 data->req.upload_chunky = FALSE;
1118 sendtask = hyper_clientconn_send(client, req);
1120 failf(data, "hyper_clientconn_send");
1121 result = CURLE_OUT_OF_MEMORY;
1125 if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
1126 failf(data, "Couldn't hyper_executor_push the send");
1127 result = CURLE_OUT_OF_MEMORY;
1131 hyper_clientconn_free(client);
1133 if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
1134 /* HTTP GET/HEAD download */
1135 Curl_pgrsSetUploadSize(data, 0); /* nothing */
1136 Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
1138 conn->datastream = Curl_hyper_stream;
1139 if(data->state.expect100header)
1140 /* Timeout count starts now since with Hyper we don't know exactly when
1141 the full request has been sent. */
1142 data->req.start100 = Curl_now();
1144 /* clear userpwd and proxyuserpwd to avoid re-using old credentials
1145 * from re-used connections */
1146 Curl_safefree(data->state.aptr.userpwd);
1147 Curl_safefree(data->state.aptr.proxyuserpwd);
1150 DEBUGASSERT(result);
1155 hyper_clientconn_options_free(options);
1158 hyper_task_free(handshake);
1163 void Curl_hyper_done(struct Curl_easy *data)
1165 struct hyptransfer *h = &data->hyp;
1167 hyper_executor_free(h->exec);
1171 hyper_waker_free(h->read_waker);
1172 h->read_waker = NULL;
1174 if(h->write_waker) {
1175 hyper_waker_free(h->write_waker);
1176 h->write_waker = NULL;
1178 if(h->exp100_waker) {
1179 hyper_waker_free(h->exp100_waker);
1180 h->exp100_waker = NULL;
1184 #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */