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