113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.haxx.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci/* Curl's integration with Hyper. This replaces certain functions in http.c, 2613498266Sopenharmony_ci * based on configuration #defines. This implementation supports HTTP/1.1 but 2713498266Sopenharmony_ci * not HTTP/2. 2813498266Sopenharmony_ci */ 2913498266Sopenharmony_ci#include "curl_setup.h" 3013498266Sopenharmony_ci 3113498266Sopenharmony_ci#if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) 3213498266Sopenharmony_ci 3313498266Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 3413498266Sopenharmony_ci#include <netinet/in.h> 3513498266Sopenharmony_ci#endif 3613498266Sopenharmony_ci 3713498266Sopenharmony_ci#ifdef HAVE_NETDB_H 3813498266Sopenharmony_ci#include <netdb.h> 3913498266Sopenharmony_ci#endif 4013498266Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 4113498266Sopenharmony_ci#include <arpa/inet.h> 4213498266Sopenharmony_ci#endif 4313498266Sopenharmony_ci#ifdef HAVE_NET_IF_H 4413498266Sopenharmony_ci#include <net/if.h> 4513498266Sopenharmony_ci#endif 4613498266Sopenharmony_ci#ifdef HAVE_SYS_IOCTL_H 4713498266Sopenharmony_ci#include <sys/ioctl.h> 4813498266Sopenharmony_ci#endif 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci#ifdef HAVE_SYS_PARAM_H 5113498266Sopenharmony_ci#include <sys/param.h> 5213498266Sopenharmony_ci#endif 5313498266Sopenharmony_ci 5413498266Sopenharmony_ci#include <hyper.h> 5513498266Sopenharmony_ci#include "urldata.h" 5613498266Sopenharmony_ci#include "sendf.h" 5713498266Sopenharmony_ci#include "transfer.h" 5813498266Sopenharmony_ci#include "multiif.h" 5913498266Sopenharmony_ci#include "progress.h" 6013498266Sopenharmony_ci#include "content_encoding.h" 6113498266Sopenharmony_ci#include "ws.h" 6213498266Sopenharmony_ci 6313498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 6413498266Sopenharmony_ci#include "curl_printf.h" 6513498266Sopenharmony_ci#include "curl_memory.h" 6613498266Sopenharmony_ci#include "memdebug.h" 6713498266Sopenharmony_ci 6813498266Sopenharmony_citypedef enum { 6913498266Sopenharmony_ci USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */ 7013498266Sopenharmony_ci USERDATA_RESP_BODY 7113498266Sopenharmony_ci} userdata_t; 7213498266Sopenharmony_ci 7313498266Sopenharmony_cisize_t Curl_hyper_recv(void *userp, hyper_context *ctx, 7413498266Sopenharmony_ci uint8_t *buf, size_t buflen) 7513498266Sopenharmony_ci{ 7613498266Sopenharmony_ci struct Curl_easy *data = userp; 7713498266Sopenharmony_ci struct connectdata *conn = data->conn; 7813498266Sopenharmony_ci CURLcode result; 7913498266Sopenharmony_ci ssize_t nread; 8013498266Sopenharmony_ci DEBUGASSERT(conn); 8113498266Sopenharmony_ci (void)ctx; 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen)); 8413498266Sopenharmony_ci result = Curl_read(data, conn->sockfd, (char *)buf, buflen, &nread); 8513498266Sopenharmony_ci if(result == CURLE_AGAIN) { 8613498266Sopenharmony_ci /* would block, register interest */ 8713498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen)); 8813498266Sopenharmony_ci if(data->hyp.read_waker) 8913498266Sopenharmony_ci hyper_waker_free(data->hyp.read_waker); 9013498266Sopenharmony_ci data->hyp.read_waker = hyper_context_waker(ctx); 9113498266Sopenharmony_ci if(!data->hyp.read_waker) { 9213498266Sopenharmony_ci failf(data, "Couldn't make the read hyper_context_waker"); 9313498266Sopenharmony_ci return HYPER_IO_ERROR; 9413498266Sopenharmony_ci } 9513498266Sopenharmony_ci return HYPER_IO_PENDING; 9613498266Sopenharmony_ci } 9713498266Sopenharmony_ci else if(result) { 9813498266Sopenharmony_ci failf(data, "Curl_read failed"); 9913498266Sopenharmony_ci return HYPER_IO_ERROR; 10013498266Sopenharmony_ci } 10113498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread)); 10213498266Sopenharmony_ci return (size_t)nread; 10313498266Sopenharmony_ci} 10413498266Sopenharmony_ci 10513498266Sopenharmony_cisize_t Curl_hyper_send(void *userp, hyper_context *ctx, 10613498266Sopenharmony_ci const uint8_t *buf, size_t buflen) 10713498266Sopenharmony_ci{ 10813498266Sopenharmony_ci struct Curl_easy *data = userp; 10913498266Sopenharmony_ci struct connectdata *conn = data->conn; 11013498266Sopenharmony_ci CURLcode result; 11113498266Sopenharmony_ci ssize_t nwrote; 11213498266Sopenharmony_ci 11313498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen)); 11413498266Sopenharmony_ci result = Curl_write(data, conn->sockfd, (void *)buf, buflen, &nwrote); 11513498266Sopenharmony_ci if(!result && !nwrote) 11613498266Sopenharmony_ci result = CURLE_AGAIN; 11713498266Sopenharmony_ci if(result == CURLE_AGAIN) { 11813498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen)); 11913498266Sopenharmony_ci /* would block, register interest */ 12013498266Sopenharmony_ci if(data->hyp.write_waker) 12113498266Sopenharmony_ci hyper_waker_free(data->hyp.write_waker); 12213498266Sopenharmony_ci data->hyp.write_waker = hyper_context_waker(ctx); 12313498266Sopenharmony_ci if(!data->hyp.write_waker) { 12413498266Sopenharmony_ci failf(data, "Couldn't make the write hyper_context_waker"); 12513498266Sopenharmony_ci return HYPER_IO_ERROR; 12613498266Sopenharmony_ci } 12713498266Sopenharmony_ci return HYPER_IO_PENDING; 12813498266Sopenharmony_ci } 12913498266Sopenharmony_ci else if(result) { 13013498266Sopenharmony_ci failf(data, "Curl_write failed"); 13113498266Sopenharmony_ci return HYPER_IO_ERROR; 13213498266Sopenharmony_ci } 13313498266Sopenharmony_ci DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote)); 13413498266Sopenharmony_ci return (size_t)nwrote; 13513498266Sopenharmony_ci} 13613498266Sopenharmony_ci 13713498266Sopenharmony_cistatic int hyper_each_header(void *userdata, 13813498266Sopenharmony_ci const uint8_t *name, 13913498266Sopenharmony_ci size_t name_len, 14013498266Sopenharmony_ci const uint8_t *value, 14113498266Sopenharmony_ci size_t value_len) 14213498266Sopenharmony_ci{ 14313498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)userdata; 14413498266Sopenharmony_ci size_t len; 14513498266Sopenharmony_ci char *headp; 14613498266Sopenharmony_ci CURLcode result; 14713498266Sopenharmony_ci int writetype; 14813498266Sopenharmony_ci 14913498266Sopenharmony_ci if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) { 15013498266Sopenharmony_ci failf(data, "Too long response header"); 15113498266Sopenharmony_ci data->state.hresult = CURLE_TOO_LARGE; 15213498266Sopenharmony_ci return HYPER_ITER_BREAK; 15313498266Sopenharmony_ci } 15413498266Sopenharmony_ci 15513498266Sopenharmony_ci if(!data->req.bytecount) 15613498266Sopenharmony_ci Curl_pgrsTime(data, TIMER_STARTTRANSFER); 15713498266Sopenharmony_ci 15813498266Sopenharmony_ci Curl_dyn_reset(&data->state.headerb); 15913498266Sopenharmony_ci if(name_len) { 16013498266Sopenharmony_ci if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n", 16113498266Sopenharmony_ci (int) name_len, name, (int) value_len, value)) 16213498266Sopenharmony_ci return HYPER_ITER_BREAK; 16313498266Sopenharmony_ci } 16413498266Sopenharmony_ci else { 16513498266Sopenharmony_ci if(Curl_dyn_addn(&data->state.headerb, STRCONST("\r\n"))) 16613498266Sopenharmony_ci return HYPER_ITER_BREAK; 16713498266Sopenharmony_ci } 16813498266Sopenharmony_ci len = Curl_dyn_len(&data->state.headerb); 16913498266Sopenharmony_ci headp = Curl_dyn_ptr(&data->state.headerb); 17013498266Sopenharmony_ci 17113498266Sopenharmony_ci result = Curl_http_header(data, data->conn, headp); 17213498266Sopenharmony_ci if(result) { 17313498266Sopenharmony_ci data->state.hresult = result; 17413498266Sopenharmony_ci return HYPER_ITER_BREAK; 17513498266Sopenharmony_ci } 17613498266Sopenharmony_ci 17713498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_IN, headp, len); 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci writetype = CLIENTWRITE_HEADER; 18013498266Sopenharmony_ci if(data->state.hconnect) 18113498266Sopenharmony_ci writetype |= CLIENTWRITE_CONNECT; 18213498266Sopenharmony_ci if(data->req.httpcode/100 == 1) 18313498266Sopenharmony_ci writetype |= CLIENTWRITE_1XX; 18413498266Sopenharmony_ci result = Curl_client_write(data, writetype, headp, len); 18513498266Sopenharmony_ci if(result) { 18613498266Sopenharmony_ci data->state.hresult = CURLE_ABORTED_BY_CALLBACK; 18713498266Sopenharmony_ci return HYPER_ITER_BREAK; 18813498266Sopenharmony_ci } 18913498266Sopenharmony_ci 19013498266Sopenharmony_ci result = Curl_bump_headersize(data, len, FALSE); 19113498266Sopenharmony_ci if(result) { 19213498266Sopenharmony_ci data->state.hresult = result; 19313498266Sopenharmony_ci return HYPER_ITER_BREAK; 19413498266Sopenharmony_ci } 19513498266Sopenharmony_ci return HYPER_ITER_CONTINUE; 19613498266Sopenharmony_ci} 19713498266Sopenharmony_ci 19813498266Sopenharmony_cistatic int hyper_body_chunk(void *userdata, const hyper_buf *chunk) 19913498266Sopenharmony_ci{ 20013498266Sopenharmony_ci char *buf = (char *)hyper_buf_bytes(chunk); 20113498266Sopenharmony_ci size_t len = hyper_buf_len(chunk); 20213498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)userdata; 20313498266Sopenharmony_ci struct SingleRequest *k = &data->req; 20413498266Sopenharmony_ci CURLcode result = CURLE_OK; 20513498266Sopenharmony_ci 20613498266Sopenharmony_ci if(0 == k->bodywrites) { 20713498266Sopenharmony_ci bool done = FALSE; 20813498266Sopenharmony_ci#if defined(USE_NTLM) 20913498266Sopenharmony_ci struct connectdata *conn = data->conn; 21013498266Sopenharmony_ci if(conn->bits.close && 21113498266Sopenharmony_ci (((data->req.httpcode == 401) && 21213498266Sopenharmony_ci (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || 21313498266Sopenharmony_ci ((data->req.httpcode == 407) && 21413498266Sopenharmony_ci (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { 21513498266Sopenharmony_ci infof(data, "Connection closed while negotiating NTLM"); 21613498266Sopenharmony_ci data->state.authproblem = TRUE; 21713498266Sopenharmony_ci Curl_safefree(data->req.newurl); 21813498266Sopenharmony_ci } 21913498266Sopenharmony_ci#endif 22013498266Sopenharmony_ci if(data->state.expect100header) { 22113498266Sopenharmony_ci Curl_expire_done(data, EXPIRE_100_TIMEOUT); 22213498266Sopenharmony_ci if(data->req.httpcode < 400) { 22313498266Sopenharmony_ci k->exp100 = EXP100_SEND_DATA; 22413498266Sopenharmony_ci if(data->hyp.exp100_waker) { 22513498266Sopenharmony_ci hyper_waker_wake(data->hyp.exp100_waker); 22613498266Sopenharmony_ci data->hyp.exp100_waker = NULL; 22713498266Sopenharmony_ci } 22813498266Sopenharmony_ci } 22913498266Sopenharmony_ci else { /* >= 4xx */ 23013498266Sopenharmony_ci k->exp100 = EXP100_FAILED; 23113498266Sopenharmony_ci } 23213498266Sopenharmony_ci } 23313498266Sopenharmony_ci if(data->state.hconnect && (data->req.httpcode/100 != 2) && 23413498266Sopenharmony_ci data->state.authproxy.done) { 23513498266Sopenharmony_ci done = TRUE; 23613498266Sopenharmony_ci result = CURLE_OK; 23713498266Sopenharmony_ci } 23813498266Sopenharmony_ci else 23913498266Sopenharmony_ci result = Curl_http_firstwrite(data, data->conn, &done); 24013498266Sopenharmony_ci if(result || done) { 24113498266Sopenharmony_ci infof(data, "Return early from hyper_body_chunk"); 24213498266Sopenharmony_ci data->state.hresult = result; 24313498266Sopenharmony_ci return HYPER_ITER_BREAK; 24413498266Sopenharmony_ci } 24513498266Sopenharmony_ci } 24613498266Sopenharmony_ci result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len); 24713498266Sopenharmony_ci 24813498266Sopenharmony_ci if(result) { 24913498266Sopenharmony_ci data->state.hresult = result; 25013498266Sopenharmony_ci return HYPER_ITER_BREAK; 25113498266Sopenharmony_ci } 25213498266Sopenharmony_ci 25313498266Sopenharmony_ci return HYPER_ITER_CONTINUE; 25413498266Sopenharmony_ci} 25513498266Sopenharmony_ci 25613498266Sopenharmony_ci/* 25713498266Sopenharmony_ci * Hyper does not consider the status line, the first line in an HTTP/1 25813498266Sopenharmony_ci * response, to be a header. The libcurl API does. This function sends the 25913498266Sopenharmony_ci * status line in the header callback. */ 26013498266Sopenharmony_cistatic CURLcode status_line(struct Curl_easy *data, 26113498266Sopenharmony_ci struct connectdata *conn, 26213498266Sopenharmony_ci uint16_t http_status, 26313498266Sopenharmony_ci int http_version, 26413498266Sopenharmony_ci const uint8_t *reason, size_t rlen) 26513498266Sopenharmony_ci{ 26613498266Sopenharmony_ci CURLcode result; 26713498266Sopenharmony_ci size_t len; 26813498266Sopenharmony_ci const char *vstr; 26913498266Sopenharmony_ci int writetype; 27013498266Sopenharmony_ci vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" : 27113498266Sopenharmony_ci (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0"); 27213498266Sopenharmony_ci 27313498266Sopenharmony_ci /* We need to set 'httpcodeq' for functions that check the response code in 27413498266Sopenharmony_ci a single place. */ 27513498266Sopenharmony_ci data->req.httpcode = http_status; 27613498266Sopenharmony_ci 27713498266Sopenharmony_ci if(data->state.hconnect) 27813498266Sopenharmony_ci /* CONNECT */ 27913498266Sopenharmony_ci data->info.httpproxycode = http_status; 28013498266Sopenharmony_ci else { 28113498266Sopenharmony_ci conn->httpversion = 28213498266Sopenharmony_ci http_version == HYPER_HTTP_VERSION_1_1 ? 11 : 28313498266Sopenharmony_ci (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10); 28413498266Sopenharmony_ci if(http_version == HYPER_HTTP_VERSION_1_0) 28513498266Sopenharmony_ci data->state.httpwant = CURL_HTTP_VERSION_1_0; 28613498266Sopenharmony_ci 28713498266Sopenharmony_ci result = Curl_http_statusline(data, conn); 28813498266Sopenharmony_ci if(result) 28913498266Sopenharmony_ci return result; 29013498266Sopenharmony_ci } 29113498266Sopenharmony_ci 29213498266Sopenharmony_ci Curl_dyn_reset(&data->state.headerb); 29313498266Sopenharmony_ci 29413498266Sopenharmony_ci result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n", 29513498266Sopenharmony_ci vstr, 29613498266Sopenharmony_ci (int)http_status, 29713498266Sopenharmony_ci (int)rlen, reason); 29813498266Sopenharmony_ci if(result) 29913498266Sopenharmony_ci return result; 30013498266Sopenharmony_ci len = Curl_dyn_len(&data->state.headerb); 30113498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), 30213498266Sopenharmony_ci len); 30313498266Sopenharmony_ci 30413498266Sopenharmony_ci writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS; 30513498266Sopenharmony_ci if(data->state.hconnect) 30613498266Sopenharmony_ci writetype |= CLIENTWRITE_CONNECT; 30713498266Sopenharmony_ci result = Curl_client_write(data, writetype, 30813498266Sopenharmony_ci Curl_dyn_ptr(&data->state.headerb), len); 30913498266Sopenharmony_ci if(result) 31013498266Sopenharmony_ci return result; 31113498266Sopenharmony_ci 31213498266Sopenharmony_ci result = Curl_bump_headersize(data, len, FALSE); 31313498266Sopenharmony_ci return result; 31413498266Sopenharmony_ci} 31513498266Sopenharmony_ci 31613498266Sopenharmony_ci/* 31713498266Sopenharmony_ci * Hyper does not pass on the last empty response header. The libcurl API 31813498266Sopenharmony_ci * does. This function sends an empty header in the header callback. 31913498266Sopenharmony_ci */ 32013498266Sopenharmony_cistatic CURLcode empty_header(struct Curl_easy *data) 32113498266Sopenharmony_ci{ 32213498266Sopenharmony_ci CURLcode result = Curl_http_size(data); 32313498266Sopenharmony_ci if(!result) { 32413498266Sopenharmony_ci result = hyper_each_header(data, NULL, 0, NULL, 0) ? 32513498266Sopenharmony_ci CURLE_WRITE_ERROR : CURLE_OK; 32613498266Sopenharmony_ci if(result) 32713498266Sopenharmony_ci failf(data, "hyperstream: couldn't pass blank header"); 32813498266Sopenharmony_ci /* Hyper does chunked decoding itself. If it was added during 32913498266Sopenharmony_ci * response header processing, remove it again. */ 33013498266Sopenharmony_ci Curl_cwriter_remove_by_name(data, "chunked"); 33113498266Sopenharmony_ci } 33213498266Sopenharmony_ci return result; 33313498266Sopenharmony_ci} 33413498266Sopenharmony_ci 33513498266Sopenharmony_ciCURLcode Curl_hyper_stream(struct Curl_easy *data, 33613498266Sopenharmony_ci struct connectdata *conn, 33713498266Sopenharmony_ci int *didwhat, 33813498266Sopenharmony_ci bool *done, 33913498266Sopenharmony_ci int select_res) 34013498266Sopenharmony_ci{ 34113498266Sopenharmony_ci hyper_response *resp = NULL; 34213498266Sopenharmony_ci uint16_t http_status; 34313498266Sopenharmony_ci int http_version; 34413498266Sopenharmony_ci hyper_headers *headers = NULL; 34513498266Sopenharmony_ci hyper_body *resp_body = NULL; 34613498266Sopenharmony_ci struct hyptransfer *h = &data->hyp; 34713498266Sopenharmony_ci hyper_task *task; 34813498266Sopenharmony_ci hyper_task *foreach; 34913498266Sopenharmony_ci const uint8_t *reasonp; 35013498266Sopenharmony_ci size_t reason_len; 35113498266Sopenharmony_ci CURLcode result = CURLE_OK; 35213498266Sopenharmony_ci struct SingleRequest *k = &data->req; 35313498266Sopenharmony_ci (void)conn; 35413498266Sopenharmony_ci 35513498266Sopenharmony_ci if(k->exp100 > EXP100_SEND_DATA) { 35613498266Sopenharmony_ci struct curltime now = Curl_now(); 35713498266Sopenharmony_ci timediff_t ms = Curl_timediff(now, k->start100); 35813498266Sopenharmony_ci if(ms >= data->set.expect_100_timeout) { 35913498266Sopenharmony_ci /* we've waited long enough, continue anyway */ 36013498266Sopenharmony_ci k->exp100 = EXP100_SEND_DATA; 36113498266Sopenharmony_ci k->keepon |= KEEP_SEND; 36213498266Sopenharmony_ci Curl_expire_done(data, EXPIRE_100_TIMEOUT); 36313498266Sopenharmony_ci infof(data, "Done waiting for 100-continue"); 36413498266Sopenharmony_ci if(data->hyp.exp100_waker) { 36513498266Sopenharmony_ci hyper_waker_wake(data->hyp.exp100_waker); 36613498266Sopenharmony_ci data->hyp.exp100_waker = NULL; 36713498266Sopenharmony_ci } 36813498266Sopenharmony_ci } 36913498266Sopenharmony_ci } 37013498266Sopenharmony_ci 37113498266Sopenharmony_ci if(select_res & CURL_CSELECT_IN) { 37213498266Sopenharmony_ci if(h->read_waker) 37313498266Sopenharmony_ci hyper_waker_wake(h->read_waker); 37413498266Sopenharmony_ci h->read_waker = NULL; 37513498266Sopenharmony_ci } 37613498266Sopenharmony_ci if(select_res & CURL_CSELECT_OUT) { 37713498266Sopenharmony_ci if(h->write_waker) 37813498266Sopenharmony_ci hyper_waker_wake(h->write_waker); 37913498266Sopenharmony_ci h->write_waker = NULL; 38013498266Sopenharmony_ci } 38113498266Sopenharmony_ci 38213498266Sopenharmony_ci *done = FALSE; 38313498266Sopenharmony_ci do { 38413498266Sopenharmony_ci hyper_task_return_type t; 38513498266Sopenharmony_ci task = hyper_executor_poll(h->exec); 38613498266Sopenharmony_ci if(!task) { 38713498266Sopenharmony_ci *didwhat = KEEP_RECV; 38813498266Sopenharmony_ci break; 38913498266Sopenharmony_ci } 39013498266Sopenharmony_ci t = hyper_task_type(task); 39113498266Sopenharmony_ci if(t == HYPER_TASK_ERROR) { 39213498266Sopenharmony_ci hyper_error *hypererr = hyper_task_value(task); 39313498266Sopenharmony_ci hyper_task_free(task); 39413498266Sopenharmony_ci if(data->state.hresult) { 39513498266Sopenharmony_ci /* override Hyper's view, might not even be an error */ 39613498266Sopenharmony_ci result = data->state.hresult; 39713498266Sopenharmony_ci infof(data, "hyperstream is done (by early callback)"); 39813498266Sopenharmony_ci } 39913498266Sopenharmony_ci else { 40013498266Sopenharmony_ci uint8_t errbuf[256]; 40113498266Sopenharmony_ci size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf)); 40213498266Sopenharmony_ci hyper_code code = hyper_error_code(hypererr); 40313498266Sopenharmony_ci failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); 40413498266Sopenharmony_ci switch(code) { 40513498266Sopenharmony_ci case HYPERE_ABORTED_BY_CALLBACK: 40613498266Sopenharmony_ci result = CURLE_OK; 40713498266Sopenharmony_ci break; 40813498266Sopenharmony_ci case HYPERE_UNEXPECTED_EOF: 40913498266Sopenharmony_ci if(!data->req.bytecount) 41013498266Sopenharmony_ci result = CURLE_GOT_NOTHING; 41113498266Sopenharmony_ci else 41213498266Sopenharmony_ci result = CURLE_RECV_ERROR; 41313498266Sopenharmony_ci break; 41413498266Sopenharmony_ci case HYPERE_INVALID_PEER_MESSAGE: 41513498266Sopenharmony_ci /* bump headerbytecount to avoid the count remaining at zero and 41613498266Sopenharmony_ci appearing to not having read anything from the peer at all */ 41713498266Sopenharmony_ci data->req.headerbytecount++; 41813498266Sopenharmony_ci result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */ 41913498266Sopenharmony_ci break; 42013498266Sopenharmony_ci default: 42113498266Sopenharmony_ci result = CURLE_RECV_ERROR; 42213498266Sopenharmony_ci break; 42313498266Sopenharmony_ci } 42413498266Sopenharmony_ci } 42513498266Sopenharmony_ci *done = TRUE; 42613498266Sopenharmony_ci hyper_error_free(hypererr); 42713498266Sopenharmony_ci break; 42813498266Sopenharmony_ci } 42913498266Sopenharmony_ci else if(t == HYPER_TASK_EMPTY) { 43013498266Sopenharmony_ci void *userdata = hyper_task_userdata(task); 43113498266Sopenharmony_ci hyper_task_free(task); 43213498266Sopenharmony_ci if((userdata_t)userdata == USERDATA_RESP_BODY) { 43313498266Sopenharmony_ci /* end of transfer */ 43413498266Sopenharmony_ci *done = TRUE; 43513498266Sopenharmony_ci infof(data, "hyperstream is done"); 43613498266Sopenharmony_ci if(!k->bodywrites) { 43713498266Sopenharmony_ci /* hyper doesn't always call the body write callback */ 43813498266Sopenharmony_ci bool stilldone; 43913498266Sopenharmony_ci result = Curl_http_firstwrite(data, data->conn, &stilldone); 44013498266Sopenharmony_ci } 44113498266Sopenharmony_ci break; 44213498266Sopenharmony_ci } 44313498266Sopenharmony_ci else { 44413498266Sopenharmony_ci /* A background task for hyper; ignore */ 44513498266Sopenharmony_ci continue; 44613498266Sopenharmony_ci } 44713498266Sopenharmony_ci } 44813498266Sopenharmony_ci 44913498266Sopenharmony_ci DEBUGASSERT(HYPER_TASK_RESPONSE); 45013498266Sopenharmony_ci 45113498266Sopenharmony_ci resp = hyper_task_value(task); 45213498266Sopenharmony_ci hyper_task_free(task); 45313498266Sopenharmony_ci 45413498266Sopenharmony_ci *didwhat = KEEP_RECV; 45513498266Sopenharmony_ci if(!resp) { 45613498266Sopenharmony_ci failf(data, "hyperstream: couldn't get response"); 45713498266Sopenharmony_ci return CURLE_RECV_ERROR; 45813498266Sopenharmony_ci } 45913498266Sopenharmony_ci 46013498266Sopenharmony_ci http_status = hyper_response_status(resp); 46113498266Sopenharmony_ci http_version = hyper_response_version(resp); 46213498266Sopenharmony_ci reasonp = hyper_response_reason_phrase(resp); 46313498266Sopenharmony_ci reason_len = hyper_response_reason_phrase_len(resp); 46413498266Sopenharmony_ci 46513498266Sopenharmony_ci if(http_status == 417 && data->state.expect100header) { 46613498266Sopenharmony_ci infof(data, "Got 417 while waiting for a 100"); 46713498266Sopenharmony_ci data->state.disableexpect = TRUE; 46813498266Sopenharmony_ci data->req.newurl = strdup(data->state.url); 46913498266Sopenharmony_ci Curl_done_sending(data, k); 47013498266Sopenharmony_ci } 47113498266Sopenharmony_ci 47213498266Sopenharmony_ci result = status_line(data, conn, 47313498266Sopenharmony_ci http_status, http_version, reasonp, reason_len); 47413498266Sopenharmony_ci if(result) 47513498266Sopenharmony_ci break; 47613498266Sopenharmony_ci 47713498266Sopenharmony_ci headers = hyper_response_headers(resp); 47813498266Sopenharmony_ci if(!headers) { 47913498266Sopenharmony_ci failf(data, "hyperstream: couldn't get response headers"); 48013498266Sopenharmony_ci result = CURLE_RECV_ERROR; 48113498266Sopenharmony_ci break; 48213498266Sopenharmony_ci } 48313498266Sopenharmony_ci 48413498266Sopenharmony_ci /* the headers are already received */ 48513498266Sopenharmony_ci hyper_headers_foreach(headers, hyper_each_header, data); 48613498266Sopenharmony_ci if(data->state.hresult) { 48713498266Sopenharmony_ci result = data->state.hresult; 48813498266Sopenharmony_ci break; 48913498266Sopenharmony_ci } 49013498266Sopenharmony_ci 49113498266Sopenharmony_ci result = empty_header(data); 49213498266Sopenharmony_ci if(result) 49313498266Sopenharmony_ci break; 49413498266Sopenharmony_ci 49513498266Sopenharmony_ci k->deductheadercount = 49613498266Sopenharmony_ci (100 <= http_status && 199 >= http_status)?k->headerbytecount:0; 49713498266Sopenharmony_ci#ifdef USE_WEBSOCKETS 49813498266Sopenharmony_ci if(k->upgr101 == UPGR101_WS) { 49913498266Sopenharmony_ci if(http_status == 101) { 50013498266Sopenharmony_ci /* verify the response */ 50113498266Sopenharmony_ci result = Curl_ws_accept(data, NULL, 0); 50213498266Sopenharmony_ci if(result) 50313498266Sopenharmony_ci return result; 50413498266Sopenharmony_ci } 50513498266Sopenharmony_ci else { 50613498266Sopenharmony_ci failf(data, "Expected 101, got %u", k->httpcode); 50713498266Sopenharmony_ci result = CURLE_HTTP_RETURNED_ERROR; 50813498266Sopenharmony_ci break; 50913498266Sopenharmony_ci } 51013498266Sopenharmony_ci } 51113498266Sopenharmony_ci#endif 51213498266Sopenharmony_ci 51313498266Sopenharmony_ci /* Curl_http_auth_act() checks what authentication methods that are 51413498266Sopenharmony_ci * available and decides which one (if any) to use. It will set 'newurl' 51513498266Sopenharmony_ci * if an auth method was picked. */ 51613498266Sopenharmony_ci result = Curl_http_auth_act(data); 51713498266Sopenharmony_ci if(result) 51813498266Sopenharmony_ci break; 51913498266Sopenharmony_ci 52013498266Sopenharmony_ci resp_body = hyper_response_body(resp); 52113498266Sopenharmony_ci if(!resp_body) { 52213498266Sopenharmony_ci failf(data, "hyperstream: couldn't get response body"); 52313498266Sopenharmony_ci result = CURLE_RECV_ERROR; 52413498266Sopenharmony_ci break; 52513498266Sopenharmony_ci } 52613498266Sopenharmony_ci foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data); 52713498266Sopenharmony_ci if(!foreach) { 52813498266Sopenharmony_ci failf(data, "hyperstream: body foreach failed"); 52913498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 53013498266Sopenharmony_ci break; 53113498266Sopenharmony_ci } 53213498266Sopenharmony_ci hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY); 53313498266Sopenharmony_ci if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) { 53413498266Sopenharmony_ci failf(data, "Couldn't hyper_executor_push the body-foreach"); 53513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 53613498266Sopenharmony_ci break; 53713498266Sopenharmony_ci } 53813498266Sopenharmony_ci 53913498266Sopenharmony_ci hyper_response_free(resp); 54013498266Sopenharmony_ci resp = NULL; 54113498266Sopenharmony_ci } while(1); 54213498266Sopenharmony_ci if(resp) 54313498266Sopenharmony_ci hyper_response_free(resp); 54413498266Sopenharmony_ci return result; 54513498266Sopenharmony_ci} 54613498266Sopenharmony_ci 54713498266Sopenharmony_cistatic CURLcode debug_request(struct Curl_easy *data, 54813498266Sopenharmony_ci const char *method, 54913498266Sopenharmony_ci const char *path) 55013498266Sopenharmony_ci{ 55113498266Sopenharmony_ci char *req = aprintf("%s %s HTTP/1.1\r\n", method, path); 55213498266Sopenharmony_ci if(!req) 55313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 55413498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req)); 55513498266Sopenharmony_ci free(req); 55613498266Sopenharmony_ci return CURLE_OK; 55713498266Sopenharmony_ci} 55813498266Sopenharmony_ci 55913498266Sopenharmony_ci/* 56013498266Sopenharmony_ci * Given a full header line "name: value" (optional CRLF in the input, should 56113498266Sopenharmony_ci * be in the output), add to Hyper and send to the debug callback. 56213498266Sopenharmony_ci * 56313498266Sopenharmony_ci * Supports multiple headers. 56413498266Sopenharmony_ci */ 56513498266Sopenharmony_ci 56613498266Sopenharmony_ciCURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, 56713498266Sopenharmony_ci const char *line) 56813498266Sopenharmony_ci{ 56913498266Sopenharmony_ci const char *p; 57013498266Sopenharmony_ci const char *n; 57113498266Sopenharmony_ci size_t nlen; 57213498266Sopenharmony_ci const char *v; 57313498266Sopenharmony_ci size_t vlen; 57413498266Sopenharmony_ci bool newline = TRUE; 57513498266Sopenharmony_ci int numh = 0; 57613498266Sopenharmony_ci 57713498266Sopenharmony_ci if(!line) 57813498266Sopenharmony_ci return CURLE_OK; 57913498266Sopenharmony_ci n = line; 58013498266Sopenharmony_ci do { 58113498266Sopenharmony_ci size_t linelen = 0; 58213498266Sopenharmony_ci 58313498266Sopenharmony_ci p = strchr(n, ':'); 58413498266Sopenharmony_ci if(!p) 58513498266Sopenharmony_ci /* this is fine if we already added at least one header */ 58613498266Sopenharmony_ci return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT; 58713498266Sopenharmony_ci nlen = p - n; 58813498266Sopenharmony_ci p++; /* move past the colon */ 58913498266Sopenharmony_ci while(*p == ' ') 59013498266Sopenharmony_ci p++; 59113498266Sopenharmony_ci v = p; 59213498266Sopenharmony_ci p = strchr(v, '\r'); 59313498266Sopenharmony_ci if(!p) { 59413498266Sopenharmony_ci p = strchr(v, '\n'); 59513498266Sopenharmony_ci if(p) 59613498266Sopenharmony_ci linelen = 1; /* LF only */ 59713498266Sopenharmony_ci else { 59813498266Sopenharmony_ci p = strchr(v, '\0'); 59913498266Sopenharmony_ci newline = FALSE; /* no newline */ 60013498266Sopenharmony_ci } 60113498266Sopenharmony_ci } 60213498266Sopenharmony_ci else 60313498266Sopenharmony_ci linelen = 2; /* CRLF ending */ 60413498266Sopenharmony_ci linelen += (p - n); 60513498266Sopenharmony_ci vlen = p - v; 60613498266Sopenharmony_ci 60713498266Sopenharmony_ci if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen, 60813498266Sopenharmony_ci (uint8_t *)v, vlen)) { 60913498266Sopenharmony_ci failf(data, "hyper refused to add header '%s'", line); 61013498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 61113498266Sopenharmony_ci } 61213498266Sopenharmony_ci if(data->set.verbose) { 61313498266Sopenharmony_ci char *ptr = NULL; 61413498266Sopenharmony_ci if(!newline) { 61513498266Sopenharmony_ci ptr = aprintf("%.*s\r\n", (int)linelen, line); 61613498266Sopenharmony_ci if(!ptr) 61713498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 61813498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2); 61913498266Sopenharmony_ci free(ptr); 62013498266Sopenharmony_ci } 62113498266Sopenharmony_ci else 62213498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen); 62313498266Sopenharmony_ci } 62413498266Sopenharmony_ci numh++; 62513498266Sopenharmony_ci n += linelen; 62613498266Sopenharmony_ci } while(newline); 62713498266Sopenharmony_ci return CURLE_OK; 62813498266Sopenharmony_ci} 62913498266Sopenharmony_ci 63013498266Sopenharmony_cistatic CURLcode request_target(struct Curl_easy *data, 63113498266Sopenharmony_ci struct connectdata *conn, 63213498266Sopenharmony_ci const char *method, 63313498266Sopenharmony_ci hyper_request *req) 63413498266Sopenharmony_ci{ 63513498266Sopenharmony_ci CURLcode result; 63613498266Sopenharmony_ci struct dynbuf r; 63713498266Sopenharmony_ci 63813498266Sopenharmony_ci Curl_dyn_init(&r, DYN_HTTP_REQUEST); 63913498266Sopenharmony_ci 64013498266Sopenharmony_ci result = Curl_http_target(data, conn, &r); 64113498266Sopenharmony_ci if(result) 64213498266Sopenharmony_ci return result; 64313498266Sopenharmony_ci 64413498266Sopenharmony_ci if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r), 64513498266Sopenharmony_ci Curl_dyn_len(&r))) { 64613498266Sopenharmony_ci failf(data, "error setting uri to hyper"); 64713498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 64813498266Sopenharmony_ci } 64913498266Sopenharmony_ci else 65013498266Sopenharmony_ci result = debug_request(data, method, Curl_dyn_ptr(&r)); 65113498266Sopenharmony_ci 65213498266Sopenharmony_ci Curl_dyn_free(&r); 65313498266Sopenharmony_ci 65413498266Sopenharmony_ci return result; 65513498266Sopenharmony_ci} 65613498266Sopenharmony_ci 65713498266Sopenharmony_cistatic int uploadpostfields(void *userdata, hyper_context *ctx, 65813498266Sopenharmony_ci hyper_buf **chunk) 65913498266Sopenharmony_ci{ 66013498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)userdata; 66113498266Sopenharmony_ci (void)ctx; 66213498266Sopenharmony_ci if(data->req.exp100 > EXP100_SEND_DATA) { 66313498266Sopenharmony_ci if(data->req.exp100 == EXP100_FAILED) 66413498266Sopenharmony_ci return HYPER_POLL_ERROR; 66513498266Sopenharmony_ci 66613498266Sopenharmony_ci /* still waiting confirmation */ 66713498266Sopenharmony_ci if(data->hyp.exp100_waker) 66813498266Sopenharmony_ci hyper_waker_free(data->hyp.exp100_waker); 66913498266Sopenharmony_ci data->hyp.exp100_waker = hyper_context_waker(ctx); 67013498266Sopenharmony_ci return HYPER_POLL_PENDING; 67113498266Sopenharmony_ci } 67213498266Sopenharmony_ci if(data->req.upload_done) 67313498266Sopenharmony_ci *chunk = NULL; /* nothing more to deliver */ 67413498266Sopenharmony_ci else { 67513498266Sopenharmony_ci /* send everything off in a single go */ 67613498266Sopenharmony_ci hyper_buf *copy = hyper_buf_copy(data->set.postfields, 67713498266Sopenharmony_ci (size_t)data->req.p.http->postsize); 67813498266Sopenharmony_ci if(copy) 67913498266Sopenharmony_ci *chunk = copy; 68013498266Sopenharmony_ci else { 68113498266Sopenharmony_ci data->state.hresult = CURLE_OUT_OF_MEMORY; 68213498266Sopenharmony_ci return HYPER_POLL_ERROR; 68313498266Sopenharmony_ci } 68413498266Sopenharmony_ci /* increasing the writebytecount here is a little premature but we 68513498266Sopenharmony_ci don't know exactly when the body is sent */ 68613498266Sopenharmony_ci data->req.writebytecount += (size_t)data->req.p.http->postsize; 68713498266Sopenharmony_ci Curl_pgrsSetUploadCounter(data, data->req.writebytecount); 68813498266Sopenharmony_ci data->req.upload_done = TRUE; 68913498266Sopenharmony_ci } 69013498266Sopenharmony_ci return HYPER_POLL_READY; 69113498266Sopenharmony_ci} 69213498266Sopenharmony_ci 69313498266Sopenharmony_cistatic int uploadstreamed(void *userdata, hyper_context *ctx, 69413498266Sopenharmony_ci hyper_buf **chunk) 69513498266Sopenharmony_ci{ 69613498266Sopenharmony_ci size_t fillcount; 69713498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)userdata; 69813498266Sopenharmony_ci struct connectdata *conn = (struct connectdata *)data->conn; 69913498266Sopenharmony_ci CURLcode result; 70013498266Sopenharmony_ci (void)ctx; 70113498266Sopenharmony_ci 70213498266Sopenharmony_ci if(data->req.exp100 > EXP100_SEND_DATA) { 70313498266Sopenharmony_ci if(data->req.exp100 == EXP100_FAILED) 70413498266Sopenharmony_ci return HYPER_POLL_ERROR; 70513498266Sopenharmony_ci 70613498266Sopenharmony_ci /* still waiting confirmation */ 70713498266Sopenharmony_ci if(data->hyp.exp100_waker) 70813498266Sopenharmony_ci hyper_waker_free(data->hyp.exp100_waker); 70913498266Sopenharmony_ci data->hyp.exp100_waker = hyper_context_waker(ctx); 71013498266Sopenharmony_ci return HYPER_POLL_PENDING; 71113498266Sopenharmony_ci } 71213498266Sopenharmony_ci 71313498266Sopenharmony_ci if(data->req.upload_chunky && conn->bits.authneg) { 71413498266Sopenharmony_ci fillcount = 0; 71513498266Sopenharmony_ci data->req.upload_chunky = FALSE; 71613498266Sopenharmony_ci result = CURLE_OK; 71713498266Sopenharmony_ci } 71813498266Sopenharmony_ci else { 71913498266Sopenharmony_ci result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, 72013498266Sopenharmony_ci &fillcount); 72113498266Sopenharmony_ci } 72213498266Sopenharmony_ci if(result) { 72313498266Sopenharmony_ci data->state.hresult = result; 72413498266Sopenharmony_ci return HYPER_POLL_ERROR; 72513498266Sopenharmony_ci } 72613498266Sopenharmony_ci if(!fillcount) { 72713498266Sopenharmony_ci if((data->req.keepon & KEEP_SEND_PAUSE) != KEEP_SEND_PAUSE) 72813498266Sopenharmony_ci /* done! */ 72913498266Sopenharmony_ci *chunk = NULL; 73013498266Sopenharmony_ci else { 73113498266Sopenharmony_ci /* paused, save a waker */ 73213498266Sopenharmony_ci if(data->hyp.send_body_waker) 73313498266Sopenharmony_ci hyper_waker_free(data->hyp.send_body_waker); 73413498266Sopenharmony_ci data->hyp.send_body_waker = hyper_context_waker(ctx); 73513498266Sopenharmony_ci return HYPER_POLL_PENDING; 73613498266Sopenharmony_ci } 73713498266Sopenharmony_ci } 73813498266Sopenharmony_ci else { 73913498266Sopenharmony_ci hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); 74013498266Sopenharmony_ci if(copy) 74113498266Sopenharmony_ci *chunk = copy; 74213498266Sopenharmony_ci else { 74313498266Sopenharmony_ci data->state.hresult = CURLE_OUT_OF_MEMORY; 74413498266Sopenharmony_ci return HYPER_POLL_ERROR; 74513498266Sopenharmony_ci } 74613498266Sopenharmony_ci /* increasing the writebytecount here is a little premature but we 74713498266Sopenharmony_ci don't know exactly when the body is sent */ 74813498266Sopenharmony_ci data->req.writebytecount += fillcount; 74913498266Sopenharmony_ci Curl_pgrsSetUploadCounter(data, data->req.writebytecount); 75013498266Sopenharmony_ci } 75113498266Sopenharmony_ci return HYPER_POLL_READY; 75213498266Sopenharmony_ci} 75313498266Sopenharmony_ci 75413498266Sopenharmony_ci/* 75513498266Sopenharmony_ci * bodysend() sets up headers in the outgoing request for an HTTP transfer that 75613498266Sopenharmony_ci * sends a body 75713498266Sopenharmony_ci */ 75813498266Sopenharmony_ci 75913498266Sopenharmony_cistatic CURLcode bodysend(struct Curl_easy *data, 76013498266Sopenharmony_ci struct connectdata *conn, 76113498266Sopenharmony_ci hyper_headers *headers, 76213498266Sopenharmony_ci hyper_request *hyperreq, 76313498266Sopenharmony_ci Curl_HttpReq httpreq) 76413498266Sopenharmony_ci{ 76513498266Sopenharmony_ci struct HTTP *http = data->req.p.http; 76613498266Sopenharmony_ci CURLcode result = CURLE_OK; 76713498266Sopenharmony_ci struct dynbuf req; 76813498266Sopenharmony_ci if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) 76913498266Sopenharmony_ci Curl_pgrsSetUploadSize(data, 0); /* no request body */ 77013498266Sopenharmony_ci else { 77113498266Sopenharmony_ci hyper_body *body; 77213498266Sopenharmony_ci Curl_dyn_init(&req, DYN_HTTP_REQUEST); 77313498266Sopenharmony_ci result = Curl_http_bodysend(data, conn, &req, httpreq); 77413498266Sopenharmony_ci 77513498266Sopenharmony_ci if(!result) 77613498266Sopenharmony_ci result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req)); 77713498266Sopenharmony_ci 77813498266Sopenharmony_ci Curl_dyn_free(&req); 77913498266Sopenharmony_ci 78013498266Sopenharmony_ci body = hyper_body_new(); 78113498266Sopenharmony_ci hyper_body_set_userdata(body, data); 78213498266Sopenharmony_ci if(data->set.postfields) 78313498266Sopenharmony_ci hyper_body_set_data_func(body, uploadpostfields); 78413498266Sopenharmony_ci else { 78513498266Sopenharmony_ci result = Curl_get_upload_buffer(data); 78613498266Sopenharmony_ci if(result) { 78713498266Sopenharmony_ci hyper_body_free(body); 78813498266Sopenharmony_ci return result; 78913498266Sopenharmony_ci } 79013498266Sopenharmony_ci /* init the "upload from here" pointer */ 79113498266Sopenharmony_ci data->req.upload_fromhere = data->state.ulbuf; 79213498266Sopenharmony_ci hyper_body_set_data_func(body, uploadstreamed); 79313498266Sopenharmony_ci } 79413498266Sopenharmony_ci if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) { 79513498266Sopenharmony_ci /* fail */ 79613498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 79713498266Sopenharmony_ci } 79813498266Sopenharmony_ci } 79913498266Sopenharmony_ci http->sending = HTTPSEND_BODY; 80013498266Sopenharmony_ci return result; 80113498266Sopenharmony_ci} 80213498266Sopenharmony_ci 80313498266Sopenharmony_cistatic CURLcode cookies(struct Curl_easy *data, 80413498266Sopenharmony_ci struct connectdata *conn, 80513498266Sopenharmony_ci hyper_headers *headers) 80613498266Sopenharmony_ci{ 80713498266Sopenharmony_ci struct dynbuf req; 80813498266Sopenharmony_ci CURLcode result; 80913498266Sopenharmony_ci Curl_dyn_init(&req, DYN_HTTP_REQUEST); 81013498266Sopenharmony_ci 81113498266Sopenharmony_ci result = Curl_http_cookies(data, conn, &req); 81213498266Sopenharmony_ci if(!result) 81313498266Sopenharmony_ci result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req)); 81413498266Sopenharmony_ci Curl_dyn_free(&req); 81513498266Sopenharmony_ci return result; 81613498266Sopenharmony_ci} 81713498266Sopenharmony_ci 81813498266Sopenharmony_ci/* called on 1xx responses */ 81913498266Sopenharmony_cistatic void http1xx_cb(void *arg, struct hyper_response *resp) 82013498266Sopenharmony_ci{ 82113498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)arg; 82213498266Sopenharmony_ci hyper_headers *headers = NULL; 82313498266Sopenharmony_ci CURLcode result = CURLE_OK; 82413498266Sopenharmony_ci uint16_t http_status; 82513498266Sopenharmony_ci int http_version; 82613498266Sopenharmony_ci const uint8_t *reasonp; 82713498266Sopenharmony_ci size_t reason_len; 82813498266Sopenharmony_ci 82913498266Sopenharmony_ci infof(data, "Got HTTP 1xx informational"); 83013498266Sopenharmony_ci 83113498266Sopenharmony_ci http_status = hyper_response_status(resp); 83213498266Sopenharmony_ci http_version = hyper_response_version(resp); 83313498266Sopenharmony_ci reasonp = hyper_response_reason_phrase(resp); 83413498266Sopenharmony_ci reason_len = hyper_response_reason_phrase_len(resp); 83513498266Sopenharmony_ci 83613498266Sopenharmony_ci result = status_line(data, data->conn, 83713498266Sopenharmony_ci http_status, http_version, reasonp, reason_len); 83813498266Sopenharmony_ci if(!result) { 83913498266Sopenharmony_ci headers = hyper_response_headers(resp); 84013498266Sopenharmony_ci if(!headers) { 84113498266Sopenharmony_ci failf(data, "hyperstream: couldn't get 1xx response headers"); 84213498266Sopenharmony_ci result = CURLE_RECV_ERROR; 84313498266Sopenharmony_ci } 84413498266Sopenharmony_ci } 84513498266Sopenharmony_ci data->state.hresult = result; 84613498266Sopenharmony_ci 84713498266Sopenharmony_ci if(!result) { 84813498266Sopenharmony_ci /* the headers are already received */ 84913498266Sopenharmony_ci hyper_headers_foreach(headers, hyper_each_header, data); 85013498266Sopenharmony_ci /* this callback also sets data->state.hresult on error */ 85113498266Sopenharmony_ci 85213498266Sopenharmony_ci if(empty_header(data)) 85313498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 85413498266Sopenharmony_ci } 85513498266Sopenharmony_ci 85613498266Sopenharmony_ci if(data->state.hresult) 85713498266Sopenharmony_ci infof(data, "ERROR in 1xx, bail out"); 85813498266Sopenharmony_ci} 85913498266Sopenharmony_ci 86013498266Sopenharmony_ci/* 86113498266Sopenharmony_ci * Curl_http() gets called from the generic multi_do() function when an HTTP 86213498266Sopenharmony_ci * request is to be performed. This creates and sends a properly constructed 86313498266Sopenharmony_ci * HTTP request. 86413498266Sopenharmony_ci */ 86513498266Sopenharmony_ciCURLcode Curl_http(struct Curl_easy *data, bool *done) 86613498266Sopenharmony_ci{ 86713498266Sopenharmony_ci struct connectdata *conn = data->conn; 86813498266Sopenharmony_ci struct hyptransfer *h = &data->hyp; 86913498266Sopenharmony_ci hyper_io *io = NULL; 87013498266Sopenharmony_ci hyper_clientconn_options *options = NULL; 87113498266Sopenharmony_ci hyper_task *task = NULL; /* for the handshake */ 87213498266Sopenharmony_ci hyper_task *sendtask = NULL; /* for the send */ 87313498266Sopenharmony_ci hyper_clientconn *client = NULL; 87413498266Sopenharmony_ci hyper_request *req = NULL; 87513498266Sopenharmony_ci hyper_headers *headers = NULL; 87613498266Sopenharmony_ci hyper_task *handshake = NULL; 87713498266Sopenharmony_ci CURLcode result; 87813498266Sopenharmony_ci const char *p_accept; /* Accept: string */ 87913498266Sopenharmony_ci const char *method; 88013498266Sopenharmony_ci Curl_HttpReq httpreq; 88113498266Sopenharmony_ci const char *te = NULL; /* transfer-encoding */ 88213498266Sopenharmony_ci hyper_code rc; 88313498266Sopenharmony_ci 88413498266Sopenharmony_ci /* Always consider the DO phase done after this function call, even if there 88513498266Sopenharmony_ci may be parts of the request that is not yet sent, since we can deal with 88613498266Sopenharmony_ci the rest of the request in the PERFORM phase. */ 88713498266Sopenharmony_ci *done = TRUE; 88813498266Sopenharmony_ci Curl_client_cleanup(data); 88913498266Sopenharmony_ci 89013498266Sopenharmony_ci infof(data, "Time for the Hyper dance"); 89113498266Sopenharmony_ci memset(h, 0, sizeof(struct hyptransfer)); 89213498266Sopenharmony_ci 89313498266Sopenharmony_ci result = Curl_http_host(data, conn); 89413498266Sopenharmony_ci if(result) 89513498266Sopenharmony_ci return result; 89613498266Sopenharmony_ci 89713498266Sopenharmony_ci Curl_http_method(data, conn, &method, &httpreq); 89813498266Sopenharmony_ci 89913498266Sopenharmony_ci DEBUGASSERT(data->req.bytecount == 0); 90013498266Sopenharmony_ci 90113498266Sopenharmony_ci /* setup the authentication headers */ 90213498266Sopenharmony_ci { 90313498266Sopenharmony_ci char *pq = NULL; 90413498266Sopenharmony_ci if(data->state.up.query) { 90513498266Sopenharmony_ci pq = aprintf("%s?%s", data->state.up.path, data->state.up.query); 90613498266Sopenharmony_ci if(!pq) 90713498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 90813498266Sopenharmony_ci } 90913498266Sopenharmony_ci result = Curl_http_output_auth(data, conn, method, httpreq, 91013498266Sopenharmony_ci (pq ? pq : data->state.up.path), FALSE); 91113498266Sopenharmony_ci free(pq); 91213498266Sopenharmony_ci if(result) 91313498266Sopenharmony_ci return result; 91413498266Sopenharmony_ci } 91513498266Sopenharmony_ci 91613498266Sopenharmony_ci result = Curl_http_resume(data, conn, httpreq); 91713498266Sopenharmony_ci if(result) 91813498266Sopenharmony_ci return result; 91913498266Sopenharmony_ci 92013498266Sopenharmony_ci result = Curl_http_range(data, httpreq); 92113498266Sopenharmony_ci if(result) 92213498266Sopenharmony_ci return result; 92313498266Sopenharmony_ci 92413498266Sopenharmony_ci result = Curl_http_useragent(data); 92513498266Sopenharmony_ci if(result) 92613498266Sopenharmony_ci return result; 92713498266Sopenharmony_ci 92813498266Sopenharmony_ci io = hyper_io_new(); 92913498266Sopenharmony_ci if(!io) { 93013498266Sopenharmony_ci failf(data, "Couldn't create hyper IO"); 93113498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 93213498266Sopenharmony_ci goto error; 93313498266Sopenharmony_ci } 93413498266Sopenharmony_ci /* tell Hyper how to read/write network data */ 93513498266Sopenharmony_ci hyper_io_set_userdata(io, data); 93613498266Sopenharmony_ci hyper_io_set_read(io, Curl_hyper_recv); 93713498266Sopenharmony_ci hyper_io_set_write(io, Curl_hyper_send); 93813498266Sopenharmony_ci 93913498266Sopenharmony_ci /* create an executor to poll futures */ 94013498266Sopenharmony_ci if(!h->exec) { 94113498266Sopenharmony_ci h->exec = hyper_executor_new(); 94213498266Sopenharmony_ci if(!h->exec) { 94313498266Sopenharmony_ci failf(data, "Couldn't create hyper executor"); 94413498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 94513498266Sopenharmony_ci goto error; 94613498266Sopenharmony_ci } 94713498266Sopenharmony_ci } 94813498266Sopenharmony_ci 94913498266Sopenharmony_ci options = hyper_clientconn_options_new(); 95013498266Sopenharmony_ci if(!options) { 95113498266Sopenharmony_ci failf(data, "Couldn't create hyper client options"); 95213498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 95313498266Sopenharmony_ci goto error; 95413498266Sopenharmony_ci } 95513498266Sopenharmony_ci if(conn->alpn == CURL_HTTP_VERSION_2) { 95613498266Sopenharmony_ci failf(data, "ALPN protocol h2 not supported with Hyper"); 95713498266Sopenharmony_ci result = CURLE_UNSUPPORTED_PROTOCOL; 95813498266Sopenharmony_ci goto error; 95913498266Sopenharmony_ci } 96013498266Sopenharmony_ci hyper_clientconn_options_set_preserve_header_case(options, 1); 96113498266Sopenharmony_ci hyper_clientconn_options_set_preserve_header_order(options, 1); 96213498266Sopenharmony_ci hyper_clientconn_options_http1_allow_multiline_headers(options, 1); 96313498266Sopenharmony_ci 96413498266Sopenharmony_ci hyper_clientconn_options_exec(options, h->exec); 96513498266Sopenharmony_ci 96613498266Sopenharmony_ci /* "Both the `io` and the `options` are consumed in this function call" */ 96713498266Sopenharmony_ci handshake = hyper_clientconn_handshake(io, options); 96813498266Sopenharmony_ci if(!handshake) { 96913498266Sopenharmony_ci failf(data, "Couldn't create hyper client handshake"); 97013498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 97113498266Sopenharmony_ci goto error; 97213498266Sopenharmony_ci } 97313498266Sopenharmony_ci io = NULL; 97413498266Sopenharmony_ci options = NULL; 97513498266Sopenharmony_ci 97613498266Sopenharmony_ci if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) { 97713498266Sopenharmony_ci failf(data, "Couldn't hyper_executor_push the handshake"); 97813498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 97913498266Sopenharmony_ci goto error; 98013498266Sopenharmony_ci } 98113498266Sopenharmony_ci handshake = NULL; /* ownership passed on */ 98213498266Sopenharmony_ci 98313498266Sopenharmony_ci task = hyper_executor_poll(h->exec); 98413498266Sopenharmony_ci if(!task) { 98513498266Sopenharmony_ci failf(data, "Couldn't hyper_executor_poll the handshake"); 98613498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 98713498266Sopenharmony_ci goto error; 98813498266Sopenharmony_ci } 98913498266Sopenharmony_ci 99013498266Sopenharmony_ci client = hyper_task_value(task); 99113498266Sopenharmony_ci hyper_task_free(task); 99213498266Sopenharmony_ci 99313498266Sopenharmony_ci req = hyper_request_new(); 99413498266Sopenharmony_ci if(!req) { 99513498266Sopenharmony_ci failf(data, "Couldn't hyper_request_new"); 99613498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 99713498266Sopenharmony_ci goto error; 99813498266Sopenharmony_ci } 99913498266Sopenharmony_ci 100013498266Sopenharmony_ci if(!Curl_use_http_1_1plus(data, conn)) { 100113498266Sopenharmony_ci if(HYPERE_OK != hyper_request_set_version(req, 100213498266Sopenharmony_ci HYPER_HTTP_VERSION_1_0)) { 100313498266Sopenharmony_ci failf(data, "error setting HTTP version"); 100413498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 100513498266Sopenharmony_ci goto error; 100613498266Sopenharmony_ci } 100713498266Sopenharmony_ci } 100813498266Sopenharmony_ci else { 100913498266Sopenharmony_ci if(!data->state.disableexpect) { 101013498266Sopenharmony_ci data->state.expect100header = TRUE; 101113498266Sopenharmony_ci } 101213498266Sopenharmony_ci } 101313498266Sopenharmony_ci 101413498266Sopenharmony_ci if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) { 101513498266Sopenharmony_ci failf(data, "error setting method"); 101613498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 101713498266Sopenharmony_ci goto error; 101813498266Sopenharmony_ci } 101913498266Sopenharmony_ci 102013498266Sopenharmony_ci result = request_target(data, conn, method, req); 102113498266Sopenharmony_ci if(result) 102213498266Sopenharmony_ci goto error; 102313498266Sopenharmony_ci 102413498266Sopenharmony_ci headers = hyper_request_headers(req); 102513498266Sopenharmony_ci if(!headers) { 102613498266Sopenharmony_ci failf(data, "hyper_request_headers"); 102713498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 102813498266Sopenharmony_ci goto error; 102913498266Sopenharmony_ci } 103013498266Sopenharmony_ci 103113498266Sopenharmony_ci rc = hyper_request_on_informational(req, http1xx_cb, data); 103213498266Sopenharmony_ci if(rc) { 103313498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 103413498266Sopenharmony_ci goto error; 103513498266Sopenharmony_ci } 103613498266Sopenharmony_ci 103713498266Sopenharmony_ci result = Curl_http_body(data, conn, httpreq, &te); 103813498266Sopenharmony_ci if(result) 103913498266Sopenharmony_ci goto error; 104013498266Sopenharmony_ci 104113498266Sopenharmony_ci if(data->state.aptr.host) { 104213498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.host); 104313498266Sopenharmony_ci if(result) 104413498266Sopenharmony_ci goto error; 104513498266Sopenharmony_ci } 104613498266Sopenharmony_ci 104713498266Sopenharmony_ci if(data->state.aptr.proxyuserpwd) { 104813498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd); 104913498266Sopenharmony_ci if(result) 105013498266Sopenharmony_ci goto error; 105113498266Sopenharmony_ci } 105213498266Sopenharmony_ci 105313498266Sopenharmony_ci if(data->state.aptr.userpwd) { 105413498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.userpwd); 105513498266Sopenharmony_ci if(result) 105613498266Sopenharmony_ci goto error; 105713498266Sopenharmony_ci } 105813498266Sopenharmony_ci 105913498266Sopenharmony_ci if((data->state.use_range && data->state.aptr.rangeline)) { 106013498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.rangeline); 106113498266Sopenharmony_ci if(result) 106213498266Sopenharmony_ci goto error; 106313498266Sopenharmony_ci } 106413498266Sopenharmony_ci 106513498266Sopenharmony_ci if(data->set.str[STRING_USERAGENT] && 106613498266Sopenharmony_ci *data->set.str[STRING_USERAGENT] && 106713498266Sopenharmony_ci data->state.aptr.uagent) { 106813498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.uagent); 106913498266Sopenharmony_ci if(result) 107013498266Sopenharmony_ci goto error; 107113498266Sopenharmony_ci } 107213498266Sopenharmony_ci 107313498266Sopenharmony_ci p_accept = Curl_checkheaders(data, 107413498266Sopenharmony_ci STRCONST("Accept"))?NULL:"Accept: */*\r\n"; 107513498266Sopenharmony_ci if(p_accept) { 107613498266Sopenharmony_ci result = Curl_hyper_header(data, headers, p_accept); 107713498266Sopenharmony_ci if(result) 107813498266Sopenharmony_ci goto error; 107913498266Sopenharmony_ci } 108013498266Sopenharmony_ci if(te) { 108113498266Sopenharmony_ci result = Curl_hyper_header(data, headers, te); 108213498266Sopenharmony_ci if(result) 108313498266Sopenharmony_ci goto error; 108413498266Sopenharmony_ci } 108513498266Sopenharmony_ci 108613498266Sopenharmony_ci#ifndef CURL_DISABLE_ALTSVC 108713498266Sopenharmony_ci if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) { 108813498266Sopenharmony_ci char *altused = aprintf("Alt-Used: %s:%d\r\n", 108913498266Sopenharmony_ci conn->conn_to_host.name, conn->conn_to_port); 109013498266Sopenharmony_ci if(!altused) { 109113498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 109213498266Sopenharmony_ci goto error; 109313498266Sopenharmony_ci } 109413498266Sopenharmony_ci result = Curl_hyper_header(data, headers, altused); 109513498266Sopenharmony_ci if(result) 109613498266Sopenharmony_ci goto error; 109713498266Sopenharmony_ci free(altused); 109813498266Sopenharmony_ci } 109913498266Sopenharmony_ci#endif 110013498266Sopenharmony_ci 110113498266Sopenharmony_ci#ifndef CURL_DISABLE_PROXY 110213498266Sopenharmony_ci if(conn->bits.httpproxy && !conn->bits.tunnel_proxy && 110313498266Sopenharmony_ci !Curl_checkheaders(data, STRCONST("Proxy-Connection")) && 110413498266Sopenharmony_ci !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) { 110513498266Sopenharmony_ci result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive"); 110613498266Sopenharmony_ci if(result) 110713498266Sopenharmony_ci goto error; 110813498266Sopenharmony_ci } 110913498266Sopenharmony_ci#endif 111013498266Sopenharmony_ci 111113498266Sopenharmony_ci Curl_safefree(data->state.aptr.ref); 111213498266Sopenharmony_ci if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) { 111313498266Sopenharmony_ci data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer); 111413498266Sopenharmony_ci if(!data->state.aptr.ref) 111513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 111613498266Sopenharmony_ci else 111713498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.ref); 111813498266Sopenharmony_ci if(result) 111913498266Sopenharmony_ci goto error; 112013498266Sopenharmony_ci } 112113498266Sopenharmony_ci 112213498266Sopenharmony_ci#ifdef HAVE_LIBZ 112313498266Sopenharmony_ci /* we only consider transfer-encoding magic if libz support is built-in */ 112413498266Sopenharmony_ci result = Curl_transferencode(data); 112513498266Sopenharmony_ci if(result) 112613498266Sopenharmony_ci goto error; 112713498266Sopenharmony_ci result = Curl_hyper_header(data, headers, data->state.aptr.te); 112813498266Sopenharmony_ci if(result) 112913498266Sopenharmony_ci goto error; 113013498266Sopenharmony_ci#endif 113113498266Sopenharmony_ci 113213498266Sopenharmony_ci if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) && 113313498266Sopenharmony_ci data->set.str[STRING_ENCODING]) { 113413498266Sopenharmony_ci Curl_safefree(data->state.aptr.accept_encoding); 113513498266Sopenharmony_ci data->state.aptr.accept_encoding = 113613498266Sopenharmony_ci aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); 113713498266Sopenharmony_ci if(!data->state.aptr.accept_encoding) 113813498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 113913498266Sopenharmony_ci else 114013498266Sopenharmony_ci result = Curl_hyper_header(data, headers, 114113498266Sopenharmony_ci data->state.aptr.accept_encoding); 114213498266Sopenharmony_ci if(result) 114313498266Sopenharmony_ci goto error; 114413498266Sopenharmony_ci } 114513498266Sopenharmony_ci else 114613498266Sopenharmony_ci Curl_safefree(data->state.aptr.accept_encoding); 114713498266Sopenharmony_ci 114813498266Sopenharmony_ci result = cookies(data, conn, headers); 114913498266Sopenharmony_ci if(result) 115013498266Sopenharmony_ci goto error; 115113498266Sopenharmony_ci 115213498266Sopenharmony_ci if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS)) 115313498266Sopenharmony_ci result = Curl_ws_request(data, headers); 115413498266Sopenharmony_ci 115513498266Sopenharmony_ci result = Curl_add_timecondition(data, headers); 115613498266Sopenharmony_ci if(result) 115713498266Sopenharmony_ci goto error; 115813498266Sopenharmony_ci 115913498266Sopenharmony_ci result = Curl_add_custom_headers(data, FALSE, headers); 116013498266Sopenharmony_ci if(result) 116113498266Sopenharmony_ci goto error; 116213498266Sopenharmony_ci 116313498266Sopenharmony_ci result = bodysend(data, conn, headers, req, httpreq); 116413498266Sopenharmony_ci if(result) 116513498266Sopenharmony_ci goto error; 116613498266Sopenharmony_ci 116713498266Sopenharmony_ci Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2); 116813498266Sopenharmony_ci 116913498266Sopenharmony_ci if(data->req.upload_chunky && conn->bits.authneg) { 117013498266Sopenharmony_ci data->req.upload_chunky = TRUE; 117113498266Sopenharmony_ci } 117213498266Sopenharmony_ci else { 117313498266Sopenharmony_ci data->req.upload_chunky = FALSE; 117413498266Sopenharmony_ci } 117513498266Sopenharmony_ci sendtask = hyper_clientconn_send(client, req); 117613498266Sopenharmony_ci if(!sendtask) { 117713498266Sopenharmony_ci failf(data, "hyper_clientconn_send"); 117813498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 117913498266Sopenharmony_ci goto error; 118013498266Sopenharmony_ci } 118113498266Sopenharmony_ci req = NULL; 118213498266Sopenharmony_ci 118313498266Sopenharmony_ci if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) { 118413498266Sopenharmony_ci failf(data, "Couldn't hyper_executor_push the send"); 118513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 118613498266Sopenharmony_ci goto error; 118713498266Sopenharmony_ci } 118813498266Sopenharmony_ci sendtask = NULL; /* ownership passed on */ 118913498266Sopenharmony_ci 119013498266Sopenharmony_ci hyper_clientconn_free(client); 119113498266Sopenharmony_ci client = NULL; 119213498266Sopenharmony_ci 119313498266Sopenharmony_ci if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) { 119413498266Sopenharmony_ci /* HTTP GET/HEAD download */ 119513498266Sopenharmony_ci Curl_pgrsSetUploadSize(data, 0); /* nothing */ 119613498266Sopenharmony_ci Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1); 119713498266Sopenharmony_ci } 119813498266Sopenharmony_ci conn->datastream = Curl_hyper_stream; 119913498266Sopenharmony_ci if(data->state.expect100header) 120013498266Sopenharmony_ci /* Timeout count starts now since with Hyper we don't know exactly when 120113498266Sopenharmony_ci the full request has been sent. */ 120213498266Sopenharmony_ci data->req.start100 = Curl_now(); 120313498266Sopenharmony_ci 120413498266Sopenharmony_ci /* clear userpwd and proxyuserpwd to avoid reusing old credentials 120513498266Sopenharmony_ci * from reused connections */ 120613498266Sopenharmony_ci Curl_safefree(data->state.aptr.userpwd); 120713498266Sopenharmony_ci Curl_safefree(data->state.aptr.proxyuserpwd); 120813498266Sopenharmony_ci return CURLE_OK; 120913498266Sopenharmony_cierror: 121013498266Sopenharmony_ci DEBUGASSERT(result); 121113498266Sopenharmony_ci if(io) 121213498266Sopenharmony_ci hyper_io_free(io); 121313498266Sopenharmony_ci 121413498266Sopenharmony_ci if(options) 121513498266Sopenharmony_ci hyper_clientconn_options_free(options); 121613498266Sopenharmony_ci 121713498266Sopenharmony_ci if(handshake) 121813498266Sopenharmony_ci hyper_task_free(handshake); 121913498266Sopenharmony_ci 122013498266Sopenharmony_ci if(client) 122113498266Sopenharmony_ci hyper_clientconn_free(client); 122213498266Sopenharmony_ci 122313498266Sopenharmony_ci if(req) 122413498266Sopenharmony_ci hyper_request_free(req); 122513498266Sopenharmony_ci 122613498266Sopenharmony_ci return result; 122713498266Sopenharmony_ci} 122813498266Sopenharmony_ci 122913498266Sopenharmony_civoid Curl_hyper_done(struct Curl_easy *data) 123013498266Sopenharmony_ci{ 123113498266Sopenharmony_ci struct hyptransfer *h = &data->hyp; 123213498266Sopenharmony_ci if(h->exec) { 123313498266Sopenharmony_ci hyper_executor_free(h->exec); 123413498266Sopenharmony_ci h->exec = NULL; 123513498266Sopenharmony_ci } 123613498266Sopenharmony_ci if(h->read_waker) { 123713498266Sopenharmony_ci hyper_waker_free(h->read_waker); 123813498266Sopenharmony_ci h->read_waker = NULL; 123913498266Sopenharmony_ci } 124013498266Sopenharmony_ci if(h->write_waker) { 124113498266Sopenharmony_ci hyper_waker_free(h->write_waker); 124213498266Sopenharmony_ci h->write_waker = NULL; 124313498266Sopenharmony_ci } 124413498266Sopenharmony_ci if(h->exp100_waker) { 124513498266Sopenharmony_ci hyper_waker_free(h->exp100_waker); 124613498266Sopenharmony_ci h->exp100_waker = NULL; 124713498266Sopenharmony_ci } 124813498266Sopenharmony_ci} 124913498266Sopenharmony_ci 125013498266Sopenharmony_ci#endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */ 1251