xref: /aosp_15_r20/external/curl/lib/c-hyper.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.haxx.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker 
25*6236dae4SAndroid Build Coastguard Worker /* Curl's integration with Hyper. This replaces certain functions in http.c,
26*6236dae4SAndroid Build Coastguard Worker  * based on configuration #defines. This implementation supports HTTP/1.1 but
27*6236dae4SAndroid Build Coastguard Worker  * not HTTP/2.
28*6236dae4SAndroid Build Coastguard Worker  */
29*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
30*6236dae4SAndroid Build Coastguard Worker 
31*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER)
32*6236dae4SAndroid Build Coastguard Worker 
33*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
34*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
35*6236dae4SAndroid Build Coastguard Worker #endif
36*6236dae4SAndroid Build Coastguard Worker 
37*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
38*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
39*6236dae4SAndroid Build Coastguard Worker #endif
40*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
41*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
42*6236dae4SAndroid Build Coastguard Worker #endif
43*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NET_IF_H
44*6236dae4SAndroid Build Coastguard Worker #include <net/if.h>
45*6236dae4SAndroid Build Coastguard Worker #endif
46*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
47*6236dae4SAndroid Build Coastguard Worker #include <sys/ioctl.h>
48*6236dae4SAndroid Build Coastguard Worker #endif
49*6236dae4SAndroid Build Coastguard Worker 
50*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_PARAM_H
51*6236dae4SAndroid Build Coastguard Worker #include <sys/param.h>
52*6236dae4SAndroid Build Coastguard Worker #endif
53*6236dae4SAndroid Build Coastguard Worker 
54*6236dae4SAndroid Build Coastguard Worker #include <hyper.h>
55*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
56*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
57*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
58*6236dae4SAndroid Build Coastguard Worker #include "headers.h"
59*6236dae4SAndroid Build Coastguard Worker #include "transfer.h"
60*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
61*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
62*6236dae4SAndroid Build Coastguard Worker #include "content_encoding.h"
63*6236dae4SAndroid Build Coastguard Worker #include "ws.h"
64*6236dae4SAndroid Build Coastguard Worker 
65*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
66*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
67*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
68*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
69*6236dae4SAndroid Build Coastguard Worker 
70*6236dae4SAndroid Build Coastguard Worker 
71*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_hyper_add(struct Curl_easy *data);
72*6236dae4SAndroid Build Coastguard Worker 
73*6236dae4SAndroid Build Coastguard Worker typedef enum {
74*6236dae4SAndroid Build Coastguard Worker     USERDATA_NOT_SET = 0, /* for tasks with no userdata set; must be zero */
75*6236dae4SAndroid Build Coastguard Worker     USERDATA_RESP_BODY
76*6236dae4SAndroid Build Coastguard Worker } userdata_t;
77*6236dae4SAndroid Build Coastguard Worker 
Curl_hyper_recv(void * userp,hyper_context * ctx,uint8_t * buf,size_t buflen)78*6236dae4SAndroid Build Coastguard Worker size_t Curl_hyper_recv(void *userp, hyper_context *ctx,
79*6236dae4SAndroid Build Coastguard Worker                        uint8_t *buf, size_t buflen)
80*6236dae4SAndroid Build Coastguard Worker {
81*6236dae4SAndroid Build Coastguard Worker   struct hyp_io_ctx *io_ctx = userp;
82*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = io_ctx->data;
83*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
84*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
85*6236dae4SAndroid Build Coastguard Worker   ssize_t nread;
86*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(conn);
87*6236dae4SAndroid Build Coastguard Worker   (void)ctx;
88*6236dae4SAndroid Build Coastguard Worker 
89*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Curl_hyper_recv(%zu)", buflen));
90*6236dae4SAndroid Build Coastguard Worker   result = Curl_conn_recv(data, io_ctx->sockindex,
91*6236dae4SAndroid Build Coastguard Worker                           (char *)buf, buflen, &nread);
92*6236dae4SAndroid Build Coastguard Worker   if(result == CURLE_AGAIN) {
93*6236dae4SAndroid Build Coastguard Worker     /* would block, register interest */
94*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> EAGAIN", buflen));
95*6236dae4SAndroid Build Coastguard Worker     if(data->hyp.read_waker)
96*6236dae4SAndroid Build Coastguard Worker       hyper_waker_free(data->hyp.read_waker);
97*6236dae4SAndroid Build Coastguard Worker     data->hyp.read_waker = hyper_context_waker(ctx);
98*6236dae4SAndroid Build Coastguard Worker     if(!data->hyp.read_waker) {
99*6236dae4SAndroid Build Coastguard Worker       failf(data, "Couldn't make the read hyper_context_waker");
100*6236dae4SAndroid Build Coastguard Worker       return HYPER_IO_ERROR;
101*6236dae4SAndroid Build Coastguard Worker     }
102*6236dae4SAndroid Build Coastguard Worker     return HYPER_IO_PENDING;
103*6236dae4SAndroid Build Coastguard Worker   }
104*6236dae4SAndroid Build Coastguard Worker   else if(result) {
105*6236dae4SAndroid Build Coastguard Worker     failf(data, "Curl_read failed");
106*6236dae4SAndroid Build Coastguard Worker     return HYPER_IO_ERROR;
107*6236dae4SAndroid Build Coastguard Worker   }
108*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Curl_hyper_recv(%zu) -> %zd", buflen, nread));
109*6236dae4SAndroid Build Coastguard Worker   return (size_t)nread;
110*6236dae4SAndroid Build Coastguard Worker }
111*6236dae4SAndroid Build Coastguard Worker 
Curl_hyper_send(void * userp,hyper_context * ctx,const uint8_t * buf,size_t buflen)112*6236dae4SAndroid Build Coastguard Worker size_t Curl_hyper_send(void *userp, hyper_context *ctx,
113*6236dae4SAndroid Build Coastguard Worker                        const uint8_t *buf, size_t buflen)
114*6236dae4SAndroid Build Coastguard Worker {
115*6236dae4SAndroid Build Coastguard Worker   struct hyp_io_ctx *io_ctx = userp;
116*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = io_ctx->data;
117*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
118*6236dae4SAndroid Build Coastguard Worker   size_t nwrote;
119*6236dae4SAndroid Build Coastguard Worker 
120*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Curl_hyper_send(%zu)", buflen));
121*6236dae4SAndroid Build Coastguard Worker   result = Curl_conn_send(data, io_ctx->sockindex,
122*6236dae4SAndroid Build Coastguard Worker                           (void *)buf, buflen, FALSE, &nwrote);
123*6236dae4SAndroid Build Coastguard Worker   if(result == CURLE_AGAIN) {
124*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "Curl_hyper_send(%zu) -> EAGAIN", buflen));
125*6236dae4SAndroid Build Coastguard Worker     /* would block, register interest */
126*6236dae4SAndroid Build Coastguard Worker     if(data->hyp.write_waker)
127*6236dae4SAndroid Build Coastguard Worker       hyper_waker_free(data->hyp.write_waker);
128*6236dae4SAndroid Build Coastguard Worker     data->hyp.write_waker = hyper_context_waker(ctx);
129*6236dae4SAndroid Build Coastguard Worker     if(!data->hyp.write_waker) {
130*6236dae4SAndroid Build Coastguard Worker       failf(data, "Couldn't make the write hyper_context_waker");
131*6236dae4SAndroid Build Coastguard Worker       return HYPER_IO_ERROR;
132*6236dae4SAndroid Build Coastguard Worker     }
133*6236dae4SAndroid Build Coastguard Worker     return HYPER_IO_PENDING;
134*6236dae4SAndroid Build Coastguard Worker   }
135*6236dae4SAndroid Build Coastguard Worker   else if(result) {
136*6236dae4SAndroid Build Coastguard Worker     failf(data, "Curl_write failed");
137*6236dae4SAndroid Build Coastguard Worker     return HYPER_IO_ERROR;
138*6236dae4SAndroid Build Coastguard Worker   }
139*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Curl_hyper_send(%zu) -> %zd", buflen, nwrote));
140*6236dae4SAndroid Build Coastguard Worker   return (size_t)nwrote;
141*6236dae4SAndroid Build Coastguard Worker }
142*6236dae4SAndroid Build Coastguard Worker 
hyper_each_header(void * userdata,const uint8_t * name,size_t name_len,const uint8_t * value,size_t value_len)143*6236dae4SAndroid Build Coastguard Worker static int hyper_each_header(void *userdata,
144*6236dae4SAndroid Build Coastguard Worker                              const uint8_t *name,
145*6236dae4SAndroid Build Coastguard Worker                              size_t name_len,
146*6236dae4SAndroid Build Coastguard Worker                              const uint8_t *value,
147*6236dae4SAndroid Build Coastguard Worker                              size_t value_len)
148*6236dae4SAndroid Build Coastguard Worker {
149*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = (struct Curl_easy *)userdata;
150*6236dae4SAndroid Build Coastguard Worker   size_t len;
151*6236dae4SAndroid Build Coastguard Worker   char *headp;
152*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
153*6236dae4SAndroid Build Coastguard Worker   int writetype;
154*6236dae4SAndroid Build Coastguard Worker 
155*6236dae4SAndroid Build Coastguard Worker   if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) {
156*6236dae4SAndroid Build Coastguard Worker     failf(data, "Too long response header");
157*6236dae4SAndroid Build Coastguard Worker     data->state.hresult = CURLE_TOO_LARGE;
158*6236dae4SAndroid Build Coastguard Worker     return HYPER_ITER_BREAK;
159*6236dae4SAndroid Build Coastguard Worker   }
160*6236dae4SAndroid Build Coastguard Worker 
161*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_reset(&data->state.headerb);
162*6236dae4SAndroid Build Coastguard Worker   if(name_len) {
163*6236dae4SAndroid Build Coastguard Worker     if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n",
164*6236dae4SAndroid Build Coastguard Worker                      (int) name_len, name, (int) value_len, value))
165*6236dae4SAndroid Build Coastguard Worker       return HYPER_ITER_BREAK;
166*6236dae4SAndroid Build Coastguard Worker   }
167*6236dae4SAndroid Build Coastguard Worker   else {
168*6236dae4SAndroid Build Coastguard Worker     if(Curl_dyn_addn(&data->state.headerb, STRCONST("\r\n")))
169*6236dae4SAndroid Build Coastguard Worker       return HYPER_ITER_BREAK;
170*6236dae4SAndroid Build Coastguard Worker   }
171*6236dae4SAndroid Build Coastguard Worker   len = Curl_dyn_len(&data->state.headerb);
172*6236dae4SAndroid Build Coastguard Worker   headp = Curl_dyn_ptr(&data->state.headerb);
173*6236dae4SAndroid Build Coastguard Worker 
174*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_header(data, headp, len);
175*6236dae4SAndroid Build Coastguard Worker   if(result) {
176*6236dae4SAndroid Build Coastguard Worker     data->state.hresult = result;
177*6236dae4SAndroid Build Coastguard Worker     return HYPER_ITER_BREAK;
178*6236dae4SAndroid Build Coastguard Worker   }
179*6236dae4SAndroid Build Coastguard Worker 
180*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_IN, headp, len);
181*6236dae4SAndroid Build Coastguard Worker 
182*6236dae4SAndroid Build Coastguard Worker   writetype = CLIENTWRITE_HEADER;
183*6236dae4SAndroid Build Coastguard Worker   if(data->state.hconnect)
184*6236dae4SAndroid Build Coastguard Worker     writetype |= CLIENTWRITE_CONNECT;
185*6236dae4SAndroid Build Coastguard Worker   if(data->req.httpcode/100 == 1)
186*6236dae4SAndroid Build Coastguard Worker     writetype |= CLIENTWRITE_1XX;
187*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_write(data, writetype, headp, len);
188*6236dae4SAndroid Build Coastguard Worker   if(result) {
189*6236dae4SAndroid Build Coastguard Worker     data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
190*6236dae4SAndroid Build Coastguard Worker     return HYPER_ITER_BREAK;
191*6236dae4SAndroid Build Coastguard Worker   }
192*6236dae4SAndroid Build Coastguard Worker 
193*6236dae4SAndroid Build Coastguard Worker   result = Curl_bump_headersize(data, len, FALSE);
194*6236dae4SAndroid Build Coastguard Worker   if(result) {
195*6236dae4SAndroid Build Coastguard Worker     data->state.hresult = result;
196*6236dae4SAndroid Build Coastguard Worker     return HYPER_ITER_BREAK;
197*6236dae4SAndroid Build Coastguard Worker   }
198*6236dae4SAndroid Build Coastguard Worker   return HYPER_ITER_CONTINUE;
199*6236dae4SAndroid Build Coastguard Worker }
200*6236dae4SAndroid Build Coastguard Worker 
hyper_body_chunk(void * userdata,const hyper_buf * chunk)201*6236dae4SAndroid Build Coastguard Worker static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
202*6236dae4SAndroid Build Coastguard Worker {
203*6236dae4SAndroid Build Coastguard Worker   char *buf = (char *)hyper_buf_bytes(chunk);
204*6236dae4SAndroid Build Coastguard Worker   size_t len = hyper_buf_len(chunk);
205*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = (struct Curl_easy *)userdata;
206*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
207*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
208*6236dae4SAndroid Build Coastguard Worker 
209*6236dae4SAndroid Build Coastguard Worker   if(!k->bodywritten) {
210*6236dae4SAndroid Build Coastguard Worker #if defined(USE_NTLM)
211*6236dae4SAndroid Build Coastguard Worker     struct connectdata *conn = data->conn;
212*6236dae4SAndroid Build Coastguard Worker     if(conn->bits.close &&
213*6236dae4SAndroid Build Coastguard Worker        (((data->req.httpcode == 401) &&
214*6236dae4SAndroid Build Coastguard Worker          (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
215*6236dae4SAndroid Build Coastguard Worker         ((data->req.httpcode == 407) &&
216*6236dae4SAndroid Build Coastguard Worker          (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
217*6236dae4SAndroid Build Coastguard Worker       infof(data, "Connection closed while negotiating NTLM");
218*6236dae4SAndroid Build Coastguard Worker       data->state.authproblem = TRUE;
219*6236dae4SAndroid Build Coastguard Worker       Curl_safefree(data->req.newurl);
220*6236dae4SAndroid Build Coastguard Worker     }
221*6236dae4SAndroid Build Coastguard Worker #endif
222*6236dae4SAndroid Build Coastguard Worker     if(Curl_http_exp100_is_selected(data)) {
223*6236dae4SAndroid Build Coastguard Worker       if(data->req.httpcode < 400) {
224*6236dae4SAndroid Build Coastguard Worker         Curl_http_exp100_got100(data);
225*6236dae4SAndroid Build Coastguard Worker         if(data->hyp.send_body_waker) {
226*6236dae4SAndroid Build Coastguard Worker           hyper_waker_wake(data->hyp.send_body_waker);
227*6236dae4SAndroid Build Coastguard Worker           data->hyp.send_body_waker = NULL;
228*6236dae4SAndroid Build Coastguard Worker         }
229*6236dae4SAndroid Build Coastguard Worker       }
230*6236dae4SAndroid Build Coastguard Worker       else { /* >= 4xx */
231*6236dae4SAndroid Build Coastguard Worker         Curl_req_abort_sending(data);
232*6236dae4SAndroid Build Coastguard Worker       }
233*6236dae4SAndroid Build Coastguard Worker     }
234*6236dae4SAndroid Build Coastguard Worker     if(data->state.hconnect && (data->req.httpcode/100 != 2) &&
235*6236dae4SAndroid Build Coastguard Worker        data->state.authproxy.done) {
236*6236dae4SAndroid Build Coastguard Worker       data->req.done = TRUE;
237*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OK;
238*6236dae4SAndroid Build Coastguard Worker     }
239*6236dae4SAndroid Build Coastguard Worker     else
240*6236dae4SAndroid Build Coastguard Worker       result = Curl_http_firstwrite(data);
241*6236dae4SAndroid Build Coastguard Worker     if(result || data->req.done) {
242*6236dae4SAndroid Build Coastguard Worker       infof(data, "Return early from hyper_body_chunk");
243*6236dae4SAndroid Build Coastguard Worker       data->state.hresult = result;
244*6236dae4SAndroid Build Coastguard Worker       return HYPER_ITER_BREAK;
245*6236dae4SAndroid Build Coastguard Worker     }
246*6236dae4SAndroid Build Coastguard Worker   }
247*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_write(data, CLIENTWRITE_BODY, buf, len);
248*6236dae4SAndroid Build Coastguard Worker 
249*6236dae4SAndroid Build Coastguard Worker   if(result) {
250*6236dae4SAndroid Build Coastguard Worker     data->state.hresult = result;
251*6236dae4SAndroid Build Coastguard Worker     return HYPER_ITER_BREAK;
252*6236dae4SAndroid Build Coastguard Worker   }
253*6236dae4SAndroid Build Coastguard Worker 
254*6236dae4SAndroid Build Coastguard Worker   return HYPER_ITER_CONTINUE;
255*6236dae4SAndroid Build Coastguard Worker }
256*6236dae4SAndroid Build Coastguard Worker 
257*6236dae4SAndroid Build Coastguard Worker /*
258*6236dae4SAndroid Build Coastguard Worker  * Hyper does not consider the status line, the first line in an HTTP/1
259*6236dae4SAndroid Build Coastguard Worker  * response, to be a header. The libcurl API does. This function sends the
260*6236dae4SAndroid Build Coastguard Worker  * status line in the header callback. */
status_line(struct Curl_easy * data,struct connectdata * conn,uint16_t http_status,int http_version,const uint8_t * reason,size_t rlen)261*6236dae4SAndroid Build Coastguard Worker static CURLcode status_line(struct Curl_easy *data,
262*6236dae4SAndroid Build Coastguard Worker                             struct connectdata *conn,
263*6236dae4SAndroid Build Coastguard Worker                             uint16_t http_status,
264*6236dae4SAndroid Build Coastguard Worker                             int http_version,
265*6236dae4SAndroid Build Coastguard Worker                             const uint8_t *reason, size_t rlen)
266*6236dae4SAndroid Build Coastguard Worker {
267*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
268*6236dae4SAndroid Build Coastguard Worker   size_t len;
269*6236dae4SAndroid Build Coastguard Worker   const char *vstr;
270*6236dae4SAndroid Build Coastguard Worker   int writetype;
271*6236dae4SAndroid Build Coastguard Worker   vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
272*6236dae4SAndroid Build Coastguard Worker     (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
273*6236dae4SAndroid Build Coastguard Worker 
274*6236dae4SAndroid Build Coastguard Worker   /* We need to set 'httpcodeq' for functions that check the response code in
275*6236dae4SAndroid Build Coastguard Worker      a single place. */
276*6236dae4SAndroid Build Coastguard Worker   data->req.httpcode = http_status;
277*6236dae4SAndroid Build Coastguard Worker   data->req.httpversion = http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
278*6236dae4SAndroid Build Coastguard Worker                           (http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
279*6236dae4SAndroid Build Coastguard Worker   if(data->state.hconnect)
280*6236dae4SAndroid Build Coastguard Worker     /* CONNECT */
281*6236dae4SAndroid Build Coastguard Worker     data->info.httpproxycode = http_status;
282*6236dae4SAndroid Build Coastguard Worker   else {
283*6236dae4SAndroid Build Coastguard Worker     conn->httpversion = (unsigned char)data->req.httpversion;
284*6236dae4SAndroid Build Coastguard Worker     if(http_version == HYPER_HTTP_VERSION_1_0)
285*6236dae4SAndroid Build Coastguard Worker       data->state.httpwant = CURL_HTTP_VERSION_1_0;
286*6236dae4SAndroid Build Coastguard Worker 
287*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_statusline(data, conn);
288*6236dae4SAndroid Build Coastguard Worker     if(result)
289*6236dae4SAndroid Build Coastguard Worker       return result;
290*6236dae4SAndroid Build Coastguard Worker   }
291*6236dae4SAndroid Build Coastguard Worker 
292*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_reset(&data->state.headerb);
293*6236dae4SAndroid Build Coastguard Worker 
294*6236dae4SAndroid Build Coastguard Worker   result = Curl_dyn_addf(&data->state.headerb, "HTTP/%s %03d %.*s\r\n",
295*6236dae4SAndroid Build Coastguard Worker                          vstr,
296*6236dae4SAndroid Build Coastguard Worker                          (int)http_status,
297*6236dae4SAndroid Build Coastguard Worker                          (int)rlen, reason);
298*6236dae4SAndroid Build Coastguard Worker   if(result)
299*6236dae4SAndroid Build Coastguard Worker     return result;
300*6236dae4SAndroid Build Coastguard Worker   len = Curl_dyn_len(&data->state.headerb);
301*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb),
302*6236dae4SAndroid Build Coastguard Worker              len);
303*6236dae4SAndroid Build Coastguard Worker 
304*6236dae4SAndroid Build Coastguard Worker   writetype = CLIENTWRITE_HEADER|CLIENTWRITE_STATUS;
305*6236dae4SAndroid Build Coastguard Worker   if(data->state.hconnect)
306*6236dae4SAndroid Build Coastguard Worker     writetype |= CLIENTWRITE_CONNECT;
307*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_write(data, writetype,
308*6236dae4SAndroid Build Coastguard Worker                              Curl_dyn_ptr(&data->state.headerb), len);
309*6236dae4SAndroid Build Coastguard Worker   if(result)
310*6236dae4SAndroid Build Coastguard Worker     return result;
311*6236dae4SAndroid Build Coastguard Worker 
312*6236dae4SAndroid Build Coastguard Worker   result = Curl_bump_headersize(data, len, FALSE);
313*6236dae4SAndroid Build Coastguard Worker   return result;
314*6236dae4SAndroid Build Coastguard Worker }
315*6236dae4SAndroid Build Coastguard Worker 
316*6236dae4SAndroid Build Coastguard Worker /*
317*6236dae4SAndroid Build Coastguard Worker  * Hyper does not pass on the last empty response header. The libcurl API
318*6236dae4SAndroid Build Coastguard Worker  * does. This function sends an empty header in the header callback.
319*6236dae4SAndroid Build Coastguard Worker  */
empty_header(struct Curl_easy * data)320*6236dae4SAndroid Build Coastguard Worker static CURLcode empty_header(struct Curl_easy *data)
321*6236dae4SAndroid Build Coastguard Worker {
322*6236dae4SAndroid Build Coastguard Worker   CURLcode result = Curl_http_size(data);
323*6236dae4SAndroid Build Coastguard Worker   if(!result) {
324*6236dae4SAndroid Build Coastguard Worker     result = hyper_each_header(data, NULL, 0, NULL, 0) ?
325*6236dae4SAndroid Build Coastguard Worker       CURLE_WRITE_ERROR : CURLE_OK;
326*6236dae4SAndroid Build Coastguard Worker     if(result)
327*6236dae4SAndroid Build Coastguard Worker       failf(data, "hyperstream: could not pass blank header");
328*6236dae4SAndroid Build Coastguard Worker     /* Hyper does chunked decoding itself. If it was added during
329*6236dae4SAndroid Build Coastguard Worker      * response header processing, remove it again. */
330*6236dae4SAndroid Build Coastguard Worker     Curl_cwriter_remove_by_name(data, "chunked");
331*6236dae4SAndroid Build Coastguard Worker   }
332*6236dae4SAndroid Build Coastguard Worker   return result;
333*6236dae4SAndroid Build Coastguard Worker }
334*6236dae4SAndroid Build Coastguard Worker 
Curl_hyper_stream(struct Curl_easy * data,struct connectdata * conn,int * didwhat,int select_res)335*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_hyper_stream(struct Curl_easy *data,
336*6236dae4SAndroid Build Coastguard Worker                            struct connectdata *conn,
337*6236dae4SAndroid Build Coastguard Worker                            int *didwhat,
338*6236dae4SAndroid Build Coastguard Worker                            int select_res)
339*6236dae4SAndroid Build Coastguard Worker {
340*6236dae4SAndroid Build Coastguard Worker   hyper_response *resp = NULL;
341*6236dae4SAndroid Build Coastguard Worker   uint16_t http_status;
342*6236dae4SAndroid Build Coastguard Worker   int http_version;
343*6236dae4SAndroid Build Coastguard Worker   hyper_headers *headers = NULL;
344*6236dae4SAndroid Build Coastguard Worker   hyper_body *resp_body = NULL;
345*6236dae4SAndroid Build Coastguard Worker   struct hyptransfer *h = &data->hyp;
346*6236dae4SAndroid Build Coastguard Worker   hyper_task *task;
347*6236dae4SAndroid Build Coastguard Worker   hyper_task *foreach;
348*6236dae4SAndroid Build Coastguard Worker   const uint8_t *reasonp;
349*6236dae4SAndroid Build Coastguard Worker   size_t reason_len;
350*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
351*6236dae4SAndroid Build Coastguard Worker   struct SingleRequest *k = &data->req;
352*6236dae4SAndroid Build Coastguard Worker   (void)conn;
353*6236dae4SAndroid Build Coastguard Worker 
354*6236dae4SAndroid Build Coastguard Worker   if(data->hyp.send_body_waker) {
355*6236dae4SAndroid Build Coastguard Worker     /* If there is still something to upload, wake it to give it
356*6236dae4SAndroid Build Coastguard Worker      * another try. */
357*6236dae4SAndroid Build Coastguard Worker     hyper_waker_wake(data->hyp.send_body_waker);
358*6236dae4SAndroid Build Coastguard Worker     data->hyp.send_body_waker = NULL;
359*6236dae4SAndroid Build Coastguard Worker   }
360*6236dae4SAndroid Build Coastguard Worker 
361*6236dae4SAndroid Build Coastguard Worker   if(select_res & CURL_CSELECT_IN) {
362*6236dae4SAndroid Build Coastguard Worker     if(h->read_waker)
363*6236dae4SAndroid Build Coastguard Worker       hyper_waker_wake(h->read_waker);
364*6236dae4SAndroid Build Coastguard Worker     h->read_waker = NULL;
365*6236dae4SAndroid Build Coastguard Worker   }
366*6236dae4SAndroid Build Coastguard Worker   if(select_res & CURL_CSELECT_OUT) {
367*6236dae4SAndroid Build Coastguard Worker     if(h->write_waker)
368*6236dae4SAndroid Build Coastguard Worker       hyper_waker_wake(h->write_waker);
369*6236dae4SAndroid Build Coastguard Worker     h->write_waker = NULL;
370*6236dae4SAndroid Build Coastguard Worker   }
371*6236dae4SAndroid Build Coastguard Worker 
372*6236dae4SAndroid Build Coastguard Worker   while(1) {
373*6236dae4SAndroid Build Coastguard Worker     hyper_task_return_type t;
374*6236dae4SAndroid Build Coastguard Worker     task = hyper_executor_poll(h->exec);
375*6236dae4SAndroid Build Coastguard Worker     if(!task) {
376*6236dae4SAndroid Build Coastguard Worker       *didwhat = KEEP_RECV;
377*6236dae4SAndroid Build Coastguard Worker       break;
378*6236dae4SAndroid Build Coastguard Worker     }
379*6236dae4SAndroid Build Coastguard Worker     t = hyper_task_type(task);
380*6236dae4SAndroid Build Coastguard Worker     if(t == HYPER_TASK_ERROR) {
381*6236dae4SAndroid Build Coastguard Worker       hyper_error *hypererr = hyper_task_value(task);
382*6236dae4SAndroid Build Coastguard Worker       hyper_task_free(task);
383*6236dae4SAndroid Build Coastguard Worker       if(data->state.hresult) {
384*6236dae4SAndroid Build Coastguard Worker         /* override Hyper's view, might not even be an error */
385*6236dae4SAndroid Build Coastguard Worker         result = data->state.hresult;
386*6236dae4SAndroid Build Coastguard Worker         infof(data, "hyperstream is done (by early callback)");
387*6236dae4SAndroid Build Coastguard Worker       }
388*6236dae4SAndroid Build Coastguard Worker       else {
389*6236dae4SAndroid Build Coastguard Worker         uint8_t errbuf[256];
390*6236dae4SAndroid Build Coastguard Worker         size_t errlen = hyper_error_print(hypererr, errbuf, sizeof(errbuf));
391*6236dae4SAndroid Build Coastguard Worker         hyper_code code = hyper_error_code(hypererr);
392*6236dae4SAndroid Build Coastguard Worker         failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf);
393*6236dae4SAndroid Build Coastguard Worker         switch(code) {
394*6236dae4SAndroid Build Coastguard Worker         case HYPERE_ABORTED_BY_CALLBACK:
395*6236dae4SAndroid Build Coastguard Worker           result = CURLE_OK;
396*6236dae4SAndroid Build Coastguard Worker           goto out;
397*6236dae4SAndroid Build Coastguard Worker         case HYPERE_UNEXPECTED_EOF:
398*6236dae4SAndroid Build Coastguard Worker           if(!data->req.bytecount)
399*6236dae4SAndroid Build Coastguard Worker             result = CURLE_GOT_NOTHING;
400*6236dae4SAndroid Build Coastguard Worker           else
401*6236dae4SAndroid Build Coastguard Worker             result = CURLE_RECV_ERROR;
402*6236dae4SAndroid Build Coastguard Worker           goto out;
403*6236dae4SAndroid Build Coastguard Worker         case HYPERE_INVALID_PEER_MESSAGE:
404*6236dae4SAndroid Build Coastguard Worker           /* bump headerbytecount to avoid the count remaining at zero and
405*6236dae4SAndroid Build Coastguard Worker              appearing to not having read anything from the peer at all */
406*6236dae4SAndroid Build Coastguard Worker           data->req.headerbytecount++;
407*6236dae4SAndroid Build Coastguard Worker           result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */
408*6236dae4SAndroid Build Coastguard Worker           goto out;
409*6236dae4SAndroid Build Coastguard Worker         default:
410*6236dae4SAndroid Build Coastguard Worker           result = CURLE_RECV_ERROR;
411*6236dae4SAndroid Build Coastguard Worker           goto out;
412*6236dae4SAndroid Build Coastguard Worker         }
413*6236dae4SAndroid Build Coastguard Worker       }
414*6236dae4SAndroid Build Coastguard Worker       data->req.done = TRUE;
415*6236dae4SAndroid Build Coastguard Worker       hyper_error_free(hypererr);
416*6236dae4SAndroid Build Coastguard Worker       break;
417*6236dae4SAndroid Build Coastguard Worker     }
418*6236dae4SAndroid Build Coastguard Worker     else if(t == HYPER_TASK_EMPTY) {
419*6236dae4SAndroid Build Coastguard Worker       void *userdata = hyper_task_userdata(task);
420*6236dae4SAndroid Build Coastguard Worker       hyper_task_free(task);
421*6236dae4SAndroid Build Coastguard Worker       if(userdata == (void *)USERDATA_RESP_BODY) {
422*6236dae4SAndroid Build Coastguard Worker         /* end of transfer */
423*6236dae4SAndroid Build Coastguard Worker         data->req.done = TRUE;
424*6236dae4SAndroid Build Coastguard Worker         infof(data, "hyperstream is done");
425*6236dae4SAndroid Build Coastguard Worker         if(!k->bodywritten) {
426*6236dae4SAndroid Build Coastguard Worker           /* hyper does not always call the body write callback */
427*6236dae4SAndroid Build Coastguard Worker           result = Curl_http_firstwrite(data);
428*6236dae4SAndroid Build Coastguard Worker         }
429*6236dae4SAndroid Build Coastguard Worker         break;
430*6236dae4SAndroid Build Coastguard Worker       }
431*6236dae4SAndroid Build Coastguard Worker       else {
432*6236dae4SAndroid Build Coastguard Worker         /* A background task for hyper; ignore */
433*6236dae4SAndroid Build Coastguard Worker         DEBUGF(infof(data, "hyper: some background task done"));
434*6236dae4SAndroid Build Coastguard Worker         continue;
435*6236dae4SAndroid Build Coastguard Worker       }
436*6236dae4SAndroid Build Coastguard Worker     }
437*6236dae4SAndroid Build Coastguard Worker     else if(t == HYPER_TASK_RESPONSE) {
438*6236dae4SAndroid Build Coastguard Worker       resp = hyper_task_value(task);
439*6236dae4SAndroid Build Coastguard Worker       hyper_task_free(task);
440*6236dae4SAndroid Build Coastguard Worker 
441*6236dae4SAndroid Build Coastguard Worker       *didwhat = KEEP_RECV;
442*6236dae4SAndroid Build Coastguard Worker       if(!resp) {
443*6236dae4SAndroid Build Coastguard Worker         failf(data, "hyperstream: could not get response");
444*6236dae4SAndroid Build Coastguard Worker         result = CURLE_RECV_ERROR;
445*6236dae4SAndroid Build Coastguard Worker         goto out;
446*6236dae4SAndroid Build Coastguard Worker       }
447*6236dae4SAndroid Build Coastguard Worker 
448*6236dae4SAndroid Build Coastguard Worker       http_status = hyper_response_status(resp);
449*6236dae4SAndroid Build Coastguard Worker       http_version = hyper_response_version(resp);
450*6236dae4SAndroid Build Coastguard Worker       reasonp = hyper_response_reason_phrase(resp);
451*6236dae4SAndroid Build Coastguard Worker       reason_len = hyper_response_reason_phrase_len(resp);
452*6236dae4SAndroid Build Coastguard Worker 
453*6236dae4SAndroid Build Coastguard Worker       if(http_status == 417 && Curl_http_exp100_is_selected(data)) {
454*6236dae4SAndroid Build Coastguard Worker         infof(data, "Got 417 while waiting for a 100");
455*6236dae4SAndroid Build Coastguard Worker         data->state.disableexpect = TRUE;
456*6236dae4SAndroid Build Coastguard Worker         data->req.newurl = strdup(data->state.url);
457*6236dae4SAndroid Build Coastguard Worker         Curl_req_abort_sending(data);
458*6236dae4SAndroid Build Coastguard Worker       }
459*6236dae4SAndroid Build Coastguard Worker 
460*6236dae4SAndroid Build Coastguard Worker       result = status_line(data, conn,
461*6236dae4SAndroid Build Coastguard Worker                            http_status, http_version, reasonp, reason_len);
462*6236dae4SAndroid Build Coastguard Worker       if(result)
463*6236dae4SAndroid Build Coastguard Worker         goto out;
464*6236dae4SAndroid Build Coastguard Worker 
465*6236dae4SAndroid Build Coastguard Worker       headers = hyper_response_headers(resp);
466*6236dae4SAndroid Build Coastguard Worker       if(!headers) {
467*6236dae4SAndroid Build Coastguard Worker         failf(data, "hyperstream: could not get response headers");
468*6236dae4SAndroid Build Coastguard Worker         result = CURLE_RECV_ERROR;
469*6236dae4SAndroid Build Coastguard Worker         goto out;
470*6236dae4SAndroid Build Coastguard Worker       }
471*6236dae4SAndroid Build Coastguard Worker 
472*6236dae4SAndroid Build Coastguard Worker       /* the headers are already received */
473*6236dae4SAndroid Build Coastguard Worker       hyper_headers_foreach(headers, hyper_each_header, data);
474*6236dae4SAndroid Build Coastguard Worker       if(data->state.hresult) {
475*6236dae4SAndroid Build Coastguard Worker         result = data->state.hresult;
476*6236dae4SAndroid Build Coastguard Worker         goto out;
477*6236dae4SAndroid Build Coastguard Worker       }
478*6236dae4SAndroid Build Coastguard Worker 
479*6236dae4SAndroid Build Coastguard Worker       result = empty_header(data);
480*6236dae4SAndroid Build Coastguard Worker       if(result)
481*6236dae4SAndroid Build Coastguard Worker         goto out;
482*6236dae4SAndroid Build Coastguard Worker 
483*6236dae4SAndroid Build Coastguard Worker       k->deductheadercount =
484*6236dae4SAndroid Build Coastguard Worker         (100 <= http_status && 199 >= http_status) ? k->headerbytecount : 0;
485*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_WEBSOCKETS
486*6236dae4SAndroid Build Coastguard Worker       if(k->upgr101 == UPGR101_WS) {
487*6236dae4SAndroid Build Coastguard Worker         if(http_status == 101) {
488*6236dae4SAndroid Build Coastguard Worker           /* verify the response */
489*6236dae4SAndroid Build Coastguard Worker           result = Curl_ws_accept(data, NULL, 0);
490*6236dae4SAndroid Build Coastguard Worker           if(result)
491*6236dae4SAndroid Build Coastguard Worker             goto out;
492*6236dae4SAndroid Build Coastguard Worker         }
493*6236dae4SAndroid Build Coastguard Worker         else {
494*6236dae4SAndroid Build Coastguard Worker           failf(data, "Expected 101, got %u", k->httpcode);
495*6236dae4SAndroid Build Coastguard Worker           result = CURLE_HTTP_RETURNED_ERROR;
496*6236dae4SAndroid Build Coastguard Worker           goto out;
497*6236dae4SAndroid Build Coastguard Worker         }
498*6236dae4SAndroid Build Coastguard Worker       }
499*6236dae4SAndroid Build Coastguard Worker #endif
500*6236dae4SAndroid Build Coastguard Worker 
501*6236dae4SAndroid Build Coastguard Worker       /* Curl_http_auth_act() checks what authentication methods that are
502*6236dae4SAndroid Build Coastguard Worker        * available and decides which one (if any) to use. It will set 'newurl'
503*6236dae4SAndroid Build Coastguard Worker        * if an auth method was picked. */
504*6236dae4SAndroid Build Coastguard Worker       result = Curl_http_auth_act(data);
505*6236dae4SAndroid Build Coastguard Worker       if(result)
506*6236dae4SAndroid Build Coastguard Worker         goto out;
507*6236dae4SAndroid Build Coastguard Worker 
508*6236dae4SAndroid Build Coastguard Worker       resp_body = hyper_response_body(resp);
509*6236dae4SAndroid Build Coastguard Worker       if(!resp_body) {
510*6236dae4SAndroid Build Coastguard Worker         failf(data, "hyperstream: could not get response body");
511*6236dae4SAndroid Build Coastguard Worker         result = CURLE_RECV_ERROR;
512*6236dae4SAndroid Build Coastguard Worker         goto out;
513*6236dae4SAndroid Build Coastguard Worker       }
514*6236dae4SAndroid Build Coastguard Worker       foreach = hyper_body_foreach(resp_body, hyper_body_chunk, data);
515*6236dae4SAndroid Build Coastguard Worker       if(!foreach) {
516*6236dae4SAndroid Build Coastguard Worker         failf(data, "hyperstream: body foreach failed");
517*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
518*6236dae4SAndroid Build Coastguard Worker         goto out;
519*6236dae4SAndroid Build Coastguard Worker       }
520*6236dae4SAndroid Build Coastguard Worker       hyper_task_set_userdata(foreach, (void *)USERDATA_RESP_BODY);
521*6236dae4SAndroid Build Coastguard Worker       if(HYPERE_OK != hyper_executor_push(h->exec, foreach)) {
522*6236dae4SAndroid Build Coastguard Worker         failf(data, "Couldn't hyper_executor_push the body-foreach");
523*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
524*6236dae4SAndroid Build Coastguard Worker         goto out;
525*6236dae4SAndroid Build Coastguard Worker       }
526*6236dae4SAndroid Build Coastguard Worker 
527*6236dae4SAndroid Build Coastguard Worker       hyper_response_free(resp);
528*6236dae4SAndroid Build Coastguard Worker       resp = NULL;
529*6236dae4SAndroid Build Coastguard Worker     }
530*6236dae4SAndroid Build Coastguard Worker     else {
531*6236dae4SAndroid Build Coastguard Worker       DEBUGF(infof(data, "hyper: unhandled tasktype %x", t));
532*6236dae4SAndroid Build Coastguard Worker     }
533*6236dae4SAndroid Build Coastguard Worker   } /* while(1) */
534*6236dae4SAndroid Build Coastguard Worker 
535*6236dae4SAndroid Build Coastguard Worker   if(!result && Curl_xfer_needs_flush(data)) {
536*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "Curl_hyper_stream(), connection needs flush"));
537*6236dae4SAndroid Build Coastguard Worker     result = Curl_xfer_flush(data);
538*6236dae4SAndroid Build Coastguard Worker   }
539*6236dae4SAndroid Build Coastguard Worker 
540*6236dae4SAndroid Build Coastguard Worker out:
541*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "Curl_hyper_stream() -> %d", result));
542*6236dae4SAndroid Build Coastguard Worker   if(resp)
543*6236dae4SAndroid Build Coastguard Worker     hyper_response_free(resp);
544*6236dae4SAndroid Build Coastguard Worker   return result;
545*6236dae4SAndroid Build Coastguard Worker }
546*6236dae4SAndroid Build Coastguard Worker 
debug_request(struct Curl_easy * data,const char * method,const char * path)547*6236dae4SAndroid Build Coastguard Worker static CURLcode debug_request(struct Curl_easy *data,
548*6236dae4SAndroid Build Coastguard Worker                               const char *method,
549*6236dae4SAndroid Build Coastguard Worker                               const char *path)
550*6236dae4SAndroid Build Coastguard Worker {
551*6236dae4SAndroid Build Coastguard Worker   char *req = aprintf("%s %s HTTP/1.1\r\n", method, path);
552*6236dae4SAndroid Build Coastguard Worker   if(!req)
553*6236dae4SAndroid Build Coastguard Worker     return CURLE_OUT_OF_MEMORY;
554*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_OUT, req, strlen(req));
555*6236dae4SAndroid Build Coastguard Worker   free(req);
556*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
557*6236dae4SAndroid Build Coastguard Worker }
558*6236dae4SAndroid Build Coastguard Worker 
559*6236dae4SAndroid Build Coastguard Worker /*
560*6236dae4SAndroid Build Coastguard Worker  * Given a full header line "name: value" (optional CRLF in the input, should
561*6236dae4SAndroid Build Coastguard Worker  * be in the output), add to Hyper and send to the debug callback.
562*6236dae4SAndroid Build Coastguard Worker  *
563*6236dae4SAndroid Build Coastguard Worker  * Supports multiple headers.
564*6236dae4SAndroid Build Coastguard Worker  */
565*6236dae4SAndroid Build Coastguard Worker 
Curl_hyper_header(struct Curl_easy * data,hyper_headers * headers,const char * line)566*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers,
567*6236dae4SAndroid Build Coastguard Worker                            const char *line)
568*6236dae4SAndroid Build Coastguard Worker {
569*6236dae4SAndroid Build Coastguard Worker   const char *p;
570*6236dae4SAndroid Build Coastguard Worker   const char *n;
571*6236dae4SAndroid Build Coastguard Worker   size_t nlen;
572*6236dae4SAndroid Build Coastguard Worker   const char *v;
573*6236dae4SAndroid Build Coastguard Worker   size_t vlen;
574*6236dae4SAndroid Build Coastguard Worker   bool newline = TRUE;
575*6236dae4SAndroid Build Coastguard Worker   int numh = 0;
576*6236dae4SAndroid Build Coastguard Worker 
577*6236dae4SAndroid Build Coastguard Worker   if(!line)
578*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
579*6236dae4SAndroid Build Coastguard Worker   n = line;
580*6236dae4SAndroid Build Coastguard Worker   do {
581*6236dae4SAndroid Build Coastguard Worker     size_t linelen = 0;
582*6236dae4SAndroid Build Coastguard Worker 
583*6236dae4SAndroid Build Coastguard Worker     p = strchr(n, ':');
584*6236dae4SAndroid Build Coastguard Worker     if(!p)
585*6236dae4SAndroid Build Coastguard Worker       /* this is fine if we already added at least one header */
586*6236dae4SAndroid Build Coastguard Worker       return numh ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
587*6236dae4SAndroid Build Coastguard Worker     nlen = p - n;
588*6236dae4SAndroid Build Coastguard Worker     p++; /* move past the colon */
589*6236dae4SAndroid Build Coastguard Worker     while(*p == ' ')
590*6236dae4SAndroid Build Coastguard Worker       p++;
591*6236dae4SAndroid Build Coastguard Worker     v = p;
592*6236dae4SAndroid Build Coastguard Worker     p = strchr(v, '\r');
593*6236dae4SAndroid Build Coastguard Worker     if(!p) {
594*6236dae4SAndroid Build Coastguard Worker       p = strchr(v, '\n');
595*6236dae4SAndroid Build Coastguard Worker       if(p)
596*6236dae4SAndroid Build Coastguard Worker         linelen = 1; /* LF only */
597*6236dae4SAndroid Build Coastguard Worker       else {
598*6236dae4SAndroid Build Coastguard Worker         p = strchr(v, '\0');
599*6236dae4SAndroid Build Coastguard Worker         newline = FALSE; /* no newline */
600*6236dae4SAndroid Build Coastguard Worker       }
601*6236dae4SAndroid Build Coastguard Worker     }
602*6236dae4SAndroid Build Coastguard Worker     else
603*6236dae4SAndroid Build Coastguard Worker       linelen = 2; /* CRLF ending */
604*6236dae4SAndroid Build Coastguard Worker     linelen += (p - n);
605*6236dae4SAndroid Build Coastguard Worker     vlen = p - v;
606*6236dae4SAndroid Build Coastguard Worker 
607*6236dae4SAndroid Build Coastguard Worker     if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen,
608*6236dae4SAndroid Build Coastguard Worker                                       (uint8_t *)v, vlen)) {
609*6236dae4SAndroid Build Coastguard Worker       failf(data, "hyper refused to add header '%s'", line);
610*6236dae4SAndroid Build Coastguard Worker       return CURLE_OUT_OF_MEMORY;
611*6236dae4SAndroid Build Coastguard Worker     }
612*6236dae4SAndroid Build Coastguard Worker     if(data->set.verbose) {
613*6236dae4SAndroid Build Coastguard Worker       char *ptr = NULL;
614*6236dae4SAndroid Build Coastguard Worker       if(!newline) {
615*6236dae4SAndroid Build Coastguard Worker         ptr = aprintf("%.*s\r\n", (int)linelen, line);
616*6236dae4SAndroid Build Coastguard Worker         if(!ptr)
617*6236dae4SAndroid Build Coastguard Worker           return CURLE_OUT_OF_MEMORY;
618*6236dae4SAndroid Build Coastguard Worker         Curl_debug(data, CURLINFO_HEADER_OUT, ptr, linelen + 2);
619*6236dae4SAndroid Build Coastguard Worker         free(ptr);
620*6236dae4SAndroid Build Coastguard Worker       }
621*6236dae4SAndroid Build Coastguard Worker       else
622*6236dae4SAndroid Build Coastguard Worker         Curl_debug(data, CURLINFO_HEADER_OUT, (char *)n, linelen);
623*6236dae4SAndroid Build Coastguard Worker     }
624*6236dae4SAndroid Build Coastguard Worker     numh++;
625*6236dae4SAndroid Build Coastguard Worker     n += linelen;
626*6236dae4SAndroid Build Coastguard Worker   } while(newline);
627*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
628*6236dae4SAndroid Build Coastguard Worker }
629*6236dae4SAndroid Build Coastguard Worker 
request_target(struct Curl_easy * data,struct connectdata * conn,const char * method,hyper_request * req)630*6236dae4SAndroid Build Coastguard Worker static CURLcode request_target(struct Curl_easy *data,
631*6236dae4SAndroid Build Coastguard Worker                                struct connectdata *conn,
632*6236dae4SAndroid Build Coastguard Worker                                const char *method,
633*6236dae4SAndroid Build Coastguard Worker                                hyper_request *req)
634*6236dae4SAndroid Build Coastguard Worker {
635*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
636*6236dae4SAndroid Build Coastguard Worker   struct dynbuf r;
637*6236dae4SAndroid Build Coastguard Worker 
638*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&r, DYN_HTTP_REQUEST);
639*6236dae4SAndroid Build Coastguard Worker 
640*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_target(data, conn, &r);
641*6236dae4SAndroid Build Coastguard Worker   if(result)
642*6236dae4SAndroid Build Coastguard Worker     return result;
643*6236dae4SAndroid Build Coastguard Worker 
644*6236dae4SAndroid Build Coastguard Worker   if(hyper_request_set_uri(req, (uint8_t *)Curl_dyn_uptr(&r),
645*6236dae4SAndroid Build Coastguard Worker                                        Curl_dyn_len(&r))) {
646*6236dae4SAndroid Build Coastguard Worker     failf(data, "error setting uri to hyper");
647*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
648*6236dae4SAndroid Build Coastguard Worker   }
649*6236dae4SAndroid Build Coastguard Worker   else
650*6236dae4SAndroid Build Coastguard Worker     result = debug_request(data, method, Curl_dyn_ptr(&r));
651*6236dae4SAndroid Build Coastguard Worker 
652*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&r);
653*6236dae4SAndroid Build Coastguard Worker 
654*6236dae4SAndroid Build Coastguard Worker   return result;
655*6236dae4SAndroid Build Coastguard Worker }
656*6236dae4SAndroid Build Coastguard Worker 
uploadstreamed(void * userdata,hyper_context * ctx,hyper_buf ** chunk)657*6236dae4SAndroid Build Coastguard Worker static int uploadstreamed(void *userdata, hyper_context *ctx,
658*6236dae4SAndroid Build Coastguard Worker                           hyper_buf **chunk)
659*6236dae4SAndroid Build Coastguard Worker {
660*6236dae4SAndroid Build Coastguard Worker   size_t fillcount;
661*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = (struct Curl_easy *)userdata;
662*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
663*6236dae4SAndroid Build Coastguard Worker   char *xfer_ulbuf;
664*6236dae4SAndroid Build Coastguard Worker   size_t xfer_ulblen;
665*6236dae4SAndroid Build Coastguard Worker   bool eos;
666*6236dae4SAndroid Build Coastguard Worker   int rc = HYPER_POLL_ERROR;
667*6236dae4SAndroid Build Coastguard Worker   (void)ctx;
668*6236dae4SAndroid Build Coastguard Worker 
669*6236dae4SAndroid Build Coastguard Worker   result = Curl_multi_xfer_ulbuf_borrow(data, &xfer_ulbuf, &xfer_ulblen);
670*6236dae4SAndroid Build Coastguard Worker   if(result)
671*6236dae4SAndroid Build Coastguard Worker     goto out;
672*6236dae4SAndroid Build Coastguard Worker 
673*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &fillcount, &eos);
674*6236dae4SAndroid Build Coastguard Worker   if(result)
675*6236dae4SAndroid Build Coastguard Worker     goto out;
676*6236dae4SAndroid Build Coastguard Worker 
677*6236dae4SAndroid Build Coastguard Worker   if(fillcount) {
678*6236dae4SAndroid Build Coastguard Worker     hyper_buf *copy = hyper_buf_copy((uint8_t *)xfer_ulbuf, fillcount);
679*6236dae4SAndroid Build Coastguard Worker     if(copy)
680*6236dae4SAndroid Build Coastguard Worker       *chunk = copy;
681*6236dae4SAndroid Build Coastguard Worker     else {
682*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
683*6236dae4SAndroid Build Coastguard Worker       goto out;
684*6236dae4SAndroid Build Coastguard Worker     }
685*6236dae4SAndroid Build Coastguard Worker     /* increasing the writebytecount here is a little premature but we
686*6236dae4SAndroid Build Coastguard Worker        do not know exactly when the body is sent */
687*6236dae4SAndroid Build Coastguard Worker     data->req.writebytecount += fillcount;
688*6236dae4SAndroid Build Coastguard Worker     if(eos)
689*6236dae4SAndroid Build Coastguard Worker       data->req.eos_read = TRUE;
690*6236dae4SAndroid Build Coastguard Worker     Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
691*6236dae4SAndroid Build Coastguard Worker     rc = HYPER_POLL_READY;
692*6236dae4SAndroid Build Coastguard Worker   }
693*6236dae4SAndroid Build Coastguard Worker   else if(eos) {
694*6236dae4SAndroid Build Coastguard Worker     data->req.eos_read = TRUE;
695*6236dae4SAndroid Build Coastguard Worker     *chunk = NULL;
696*6236dae4SAndroid Build Coastguard Worker     rc = HYPER_POLL_READY;
697*6236dae4SAndroid Build Coastguard Worker   }
698*6236dae4SAndroid Build Coastguard Worker   else {
699*6236dae4SAndroid Build Coastguard Worker     /* paused, save a waker */
700*6236dae4SAndroid Build Coastguard Worker     if(data->hyp.send_body_waker)
701*6236dae4SAndroid Build Coastguard Worker       hyper_waker_free(data->hyp.send_body_waker);
702*6236dae4SAndroid Build Coastguard Worker     data->hyp.send_body_waker = hyper_context_waker(ctx);
703*6236dae4SAndroid Build Coastguard Worker     rc = HYPER_POLL_PENDING;
704*6236dae4SAndroid Build Coastguard Worker   }
705*6236dae4SAndroid Build Coastguard Worker 
706*6236dae4SAndroid Build Coastguard Worker   if(!data->req.upload_done && data->req.eos_read) {
707*6236dae4SAndroid Build Coastguard Worker     DEBUGF(infof(data, "hyper: uploadstreamed(), upload is done"));
708*6236dae4SAndroid Build Coastguard Worker     result = Curl_req_set_upload_done(data);
709*6236dae4SAndroid Build Coastguard Worker   }
710*6236dae4SAndroid Build Coastguard Worker 
711*6236dae4SAndroid Build Coastguard Worker out:
712*6236dae4SAndroid Build Coastguard Worker   Curl_multi_xfer_ulbuf_release(data, xfer_ulbuf);
713*6236dae4SAndroid Build Coastguard Worker   data->state.hresult = result;
714*6236dae4SAndroid Build Coastguard Worker   DEBUGF(infof(data, "hyper: uploadstreamed() -> %d", result));
715*6236dae4SAndroid Build Coastguard Worker   return rc;
716*6236dae4SAndroid Build Coastguard Worker }
717*6236dae4SAndroid Build Coastguard Worker 
718*6236dae4SAndroid Build Coastguard Worker /*
719*6236dae4SAndroid Build Coastguard Worker  * finalize_request() sets up last headers and optional body settings
720*6236dae4SAndroid Build Coastguard Worker  */
finalize_request(struct Curl_easy * data,hyper_headers * headers,hyper_request * hyperreq,Curl_HttpReq httpreq)721*6236dae4SAndroid Build Coastguard Worker static CURLcode finalize_request(struct Curl_easy *data,
722*6236dae4SAndroid Build Coastguard Worker                                  hyper_headers *headers,
723*6236dae4SAndroid Build Coastguard Worker                                  hyper_request *hyperreq,
724*6236dae4SAndroid Build Coastguard Worker                                  Curl_HttpReq httpreq)
725*6236dae4SAndroid Build Coastguard Worker {
726*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
727*6236dae4SAndroid Build Coastguard Worker   struct dynbuf req;
728*6236dae4SAndroid Build Coastguard Worker   if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
729*6236dae4SAndroid Build Coastguard Worker     Curl_pgrsSetUploadSize(data, 0); /* no request body */
730*6236dae4SAndroid Build Coastguard Worker   }
731*6236dae4SAndroid Build Coastguard Worker   else {
732*6236dae4SAndroid Build Coastguard Worker     hyper_body *body;
733*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_init(&req, DYN_HTTP_REQUEST);
734*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_req_complete(data, &req, httpreq);
735*6236dae4SAndroid Build Coastguard Worker     if(result)
736*6236dae4SAndroid Build Coastguard Worker       return result;
737*6236dae4SAndroid Build Coastguard Worker 
738*6236dae4SAndroid Build Coastguard Worker     /* if the "complete" above did produce more than the closing line,
739*6236dae4SAndroid Build Coastguard Worker        parse the added headers */
740*6236dae4SAndroid Build Coastguard Worker     if(Curl_dyn_len(&req) != 2 || strcmp(Curl_dyn_ptr(&req), "\r\n")) {
741*6236dae4SAndroid Build Coastguard Worker       result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
742*6236dae4SAndroid Build Coastguard Worker       if(result)
743*6236dae4SAndroid Build Coastguard Worker         return result;
744*6236dae4SAndroid Build Coastguard Worker     }
745*6236dae4SAndroid Build Coastguard Worker 
746*6236dae4SAndroid Build Coastguard Worker     Curl_dyn_free(&req);
747*6236dae4SAndroid Build Coastguard Worker 
748*6236dae4SAndroid Build Coastguard Worker     body = hyper_body_new();
749*6236dae4SAndroid Build Coastguard Worker     hyper_body_set_userdata(body, data);
750*6236dae4SAndroid Build Coastguard Worker     hyper_body_set_data_func(body, uploadstreamed);
751*6236dae4SAndroid Build Coastguard Worker 
752*6236dae4SAndroid Build Coastguard Worker     if(HYPERE_OK != hyper_request_set_body(hyperreq, body)) {
753*6236dae4SAndroid Build Coastguard Worker       /* fail */
754*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
755*6236dae4SAndroid Build Coastguard Worker     }
756*6236dae4SAndroid Build Coastguard Worker   }
757*6236dae4SAndroid Build Coastguard Worker 
758*6236dae4SAndroid Build Coastguard Worker   return cr_hyper_add(data);
759*6236dae4SAndroid Build Coastguard Worker }
760*6236dae4SAndroid Build Coastguard Worker 
cookies(struct Curl_easy * data,struct connectdata * conn,hyper_headers * headers)761*6236dae4SAndroid Build Coastguard Worker static CURLcode cookies(struct Curl_easy *data,
762*6236dae4SAndroid Build Coastguard Worker                         struct connectdata *conn,
763*6236dae4SAndroid Build Coastguard Worker                         hyper_headers *headers)
764*6236dae4SAndroid Build Coastguard Worker {
765*6236dae4SAndroid Build Coastguard Worker   struct dynbuf req;
766*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
767*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_init(&req, DYN_HTTP_REQUEST);
768*6236dae4SAndroid Build Coastguard Worker 
769*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_cookies(data, conn, &req);
770*6236dae4SAndroid Build Coastguard Worker   if(!result)
771*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, Curl_dyn_ptr(&req));
772*6236dae4SAndroid Build Coastguard Worker   Curl_dyn_free(&req);
773*6236dae4SAndroid Build Coastguard Worker   return result;
774*6236dae4SAndroid Build Coastguard Worker }
775*6236dae4SAndroid Build Coastguard Worker 
776*6236dae4SAndroid Build Coastguard Worker /* called on 1xx responses */
http1xx_cb(void * arg,struct hyper_response * resp)777*6236dae4SAndroid Build Coastguard Worker static void http1xx_cb(void *arg, struct hyper_response *resp)
778*6236dae4SAndroid Build Coastguard Worker {
779*6236dae4SAndroid Build Coastguard Worker   struct Curl_easy *data = (struct Curl_easy *)arg;
780*6236dae4SAndroid Build Coastguard Worker   hyper_headers *headers = NULL;
781*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
782*6236dae4SAndroid Build Coastguard Worker   uint16_t http_status;
783*6236dae4SAndroid Build Coastguard Worker   int http_version;
784*6236dae4SAndroid Build Coastguard Worker   const uint8_t *reasonp;
785*6236dae4SAndroid Build Coastguard Worker   size_t reason_len;
786*6236dae4SAndroid Build Coastguard Worker 
787*6236dae4SAndroid Build Coastguard Worker   infof(data, "Got HTTP 1xx informational");
788*6236dae4SAndroid Build Coastguard Worker 
789*6236dae4SAndroid Build Coastguard Worker   http_status = hyper_response_status(resp);
790*6236dae4SAndroid Build Coastguard Worker   http_version = hyper_response_version(resp);
791*6236dae4SAndroid Build Coastguard Worker   reasonp = hyper_response_reason_phrase(resp);
792*6236dae4SAndroid Build Coastguard Worker   reason_len = hyper_response_reason_phrase_len(resp);
793*6236dae4SAndroid Build Coastguard Worker 
794*6236dae4SAndroid Build Coastguard Worker   result = status_line(data, data->conn,
795*6236dae4SAndroid Build Coastguard Worker                        http_status, http_version, reasonp, reason_len);
796*6236dae4SAndroid Build Coastguard Worker   if(!result) {
797*6236dae4SAndroid Build Coastguard Worker     headers = hyper_response_headers(resp);
798*6236dae4SAndroid Build Coastguard Worker     if(!headers) {
799*6236dae4SAndroid Build Coastguard Worker       failf(data, "hyperstream: could not get 1xx response headers");
800*6236dae4SAndroid Build Coastguard Worker       result = CURLE_RECV_ERROR;
801*6236dae4SAndroid Build Coastguard Worker     }
802*6236dae4SAndroid Build Coastguard Worker   }
803*6236dae4SAndroid Build Coastguard Worker   data->state.hresult = result;
804*6236dae4SAndroid Build Coastguard Worker 
805*6236dae4SAndroid Build Coastguard Worker   if(!result) {
806*6236dae4SAndroid Build Coastguard Worker     /* the headers are already received */
807*6236dae4SAndroid Build Coastguard Worker     hyper_headers_foreach(headers, hyper_each_header, data);
808*6236dae4SAndroid Build Coastguard Worker     /* this callback also sets data->state.hresult on error */
809*6236dae4SAndroid Build Coastguard Worker 
810*6236dae4SAndroid Build Coastguard Worker     if(empty_header(data))
811*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
812*6236dae4SAndroid Build Coastguard Worker   }
813*6236dae4SAndroid Build Coastguard Worker 
814*6236dae4SAndroid Build Coastguard Worker   if(data->state.hresult)
815*6236dae4SAndroid Build Coastguard Worker     infof(data, "ERROR in 1xx, bail out");
816*6236dae4SAndroid Build Coastguard Worker }
817*6236dae4SAndroid Build Coastguard Worker 
818*6236dae4SAndroid Build Coastguard Worker /*
819*6236dae4SAndroid Build Coastguard Worker  * Curl_http() gets called from the generic multi_do() function when an HTTP
820*6236dae4SAndroid Build Coastguard Worker  * request is to be performed. This creates and sends a properly constructed
821*6236dae4SAndroid Build Coastguard Worker  * HTTP request.
822*6236dae4SAndroid Build Coastguard Worker  */
Curl_http(struct Curl_easy * data,bool * done)823*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_http(struct Curl_easy *data, bool *done)
824*6236dae4SAndroid Build Coastguard Worker {
825*6236dae4SAndroid Build Coastguard Worker   struct connectdata *conn = data->conn;
826*6236dae4SAndroid Build Coastguard Worker   struct hyptransfer *h = &data->hyp;
827*6236dae4SAndroid Build Coastguard Worker   hyper_io *io = NULL;
828*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_options *options = NULL;
829*6236dae4SAndroid Build Coastguard Worker   hyper_task *task = NULL; /* for the handshake */
830*6236dae4SAndroid Build Coastguard Worker   hyper_task *sendtask = NULL; /* for the send */
831*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn *client = NULL;
832*6236dae4SAndroid Build Coastguard Worker   hyper_request *req = NULL;
833*6236dae4SAndroid Build Coastguard Worker   hyper_headers *headers = NULL;
834*6236dae4SAndroid Build Coastguard Worker   hyper_task *handshake = NULL;
835*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
836*6236dae4SAndroid Build Coastguard Worker   const char *p_accept; /* Accept: string */
837*6236dae4SAndroid Build Coastguard Worker   const char *method;
838*6236dae4SAndroid Build Coastguard Worker   Curl_HttpReq httpreq;
839*6236dae4SAndroid Build Coastguard Worker   const char *te = NULL; /* transfer-encoding */
840*6236dae4SAndroid Build Coastguard Worker   hyper_code rc;
841*6236dae4SAndroid Build Coastguard Worker 
842*6236dae4SAndroid Build Coastguard Worker   /* Always consider the DO phase done after this function call, even if there
843*6236dae4SAndroid Build Coastguard Worker      may be parts of the request that is not yet sent, since we can deal with
844*6236dae4SAndroid Build Coastguard Worker      the rest of the request in the PERFORM phase. */
845*6236dae4SAndroid Build Coastguard Worker   *done = TRUE;
846*6236dae4SAndroid Build Coastguard Worker   result = Curl_client_start(data);
847*6236dae4SAndroid Build Coastguard Worker   if(result)
848*6236dae4SAndroid Build Coastguard Worker     goto out;
849*6236dae4SAndroid Build Coastguard Worker 
850*6236dae4SAndroid Build Coastguard Worker   /* Add collecting of headers written to client. For a new connection,
851*6236dae4SAndroid Build Coastguard Worker    * we might have done that already, but reuse
852*6236dae4SAndroid Build Coastguard Worker    * or multiplex needs it here as well. */
853*6236dae4SAndroid Build Coastguard Worker   result = Curl_headers_init(data);
854*6236dae4SAndroid Build Coastguard Worker   if(result)
855*6236dae4SAndroid Build Coastguard Worker     goto out;
856*6236dae4SAndroid Build Coastguard Worker 
857*6236dae4SAndroid Build Coastguard Worker   infof(data, "Time for the Hyper dance");
858*6236dae4SAndroid Build Coastguard Worker   memset(h, 0, sizeof(struct hyptransfer));
859*6236dae4SAndroid Build Coastguard Worker 
860*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_host(data, conn);
861*6236dae4SAndroid Build Coastguard Worker   if(result)
862*6236dae4SAndroid Build Coastguard Worker     goto out;
863*6236dae4SAndroid Build Coastguard Worker 
864*6236dae4SAndroid Build Coastguard Worker   Curl_http_method(data, conn, &method, &httpreq);
865*6236dae4SAndroid Build Coastguard Worker 
866*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data->req.bytecount ==  0);
867*6236dae4SAndroid Build Coastguard Worker 
868*6236dae4SAndroid Build Coastguard Worker   /* setup the authentication headers */
869*6236dae4SAndroid Build Coastguard Worker   {
870*6236dae4SAndroid Build Coastguard Worker     char *pq = NULL;
871*6236dae4SAndroid Build Coastguard Worker     if(data->state.up.query) {
872*6236dae4SAndroid Build Coastguard Worker       pq = aprintf("%s?%s", data->state.up.path, data->state.up.query);
873*6236dae4SAndroid Build Coastguard Worker       if(!pq) {
874*6236dae4SAndroid Build Coastguard Worker         result = CURLE_OUT_OF_MEMORY;
875*6236dae4SAndroid Build Coastguard Worker         goto out;
876*6236dae4SAndroid Build Coastguard Worker       }
877*6236dae4SAndroid Build Coastguard Worker     }
878*6236dae4SAndroid Build Coastguard Worker     result = Curl_http_output_auth(data, conn, method, httpreq,
879*6236dae4SAndroid Build Coastguard Worker                                    (pq ? pq : data->state.up.path), FALSE);
880*6236dae4SAndroid Build Coastguard Worker     free(pq);
881*6236dae4SAndroid Build Coastguard Worker     if(result)
882*6236dae4SAndroid Build Coastguard Worker       goto out;
883*6236dae4SAndroid Build Coastguard Worker   }
884*6236dae4SAndroid Build Coastguard Worker 
885*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_req_set_reader(data, httpreq, &te);
886*6236dae4SAndroid Build Coastguard Worker   if(result)
887*6236dae4SAndroid Build Coastguard Worker     goto out;
888*6236dae4SAndroid Build Coastguard Worker 
889*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_range(data, httpreq);
890*6236dae4SAndroid Build Coastguard Worker   if(result)
891*6236dae4SAndroid Build Coastguard Worker     goto out;
892*6236dae4SAndroid Build Coastguard Worker 
893*6236dae4SAndroid Build Coastguard Worker   result = Curl_http_useragent(data);
894*6236dae4SAndroid Build Coastguard Worker   if(result)
895*6236dae4SAndroid Build Coastguard Worker     goto out;
896*6236dae4SAndroid Build Coastguard Worker 
897*6236dae4SAndroid Build Coastguard Worker   io = hyper_io_new();
898*6236dae4SAndroid Build Coastguard Worker   if(!io) {
899*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't create hyper IO");
900*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
901*6236dae4SAndroid Build Coastguard Worker     goto out;
902*6236dae4SAndroid Build Coastguard Worker   }
903*6236dae4SAndroid Build Coastguard Worker   /* tell Hyper how to read/write network data */
904*6236dae4SAndroid Build Coastguard Worker   h->io_ctx.data = data;
905*6236dae4SAndroid Build Coastguard Worker   h->io_ctx.sockindex = FIRSTSOCKET;
906*6236dae4SAndroid Build Coastguard Worker   hyper_io_set_userdata(io, &h->io_ctx);
907*6236dae4SAndroid Build Coastguard Worker   hyper_io_set_read(io, Curl_hyper_recv);
908*6236dae4SAndroid Build Coastguard Worker   hyper_io_set_write(io, Curl_hyper_send);
909*6236dae4SAndroid Build Coastguard Worker 
910*6236dae4SAndroid Build Coastguard Worker   /* create an executor to poll futures */
911*6236dae4SAndroid Build Coastguard Worker   if(!h->exec) {
912*6236dae4SAndroid Build Coastguard Worker     h->exec = hyper_executor_new();
913*6236dae4SAndroid Build Coastguard Worker     if(!h->exec) {
914*6236dae4SAndroid Build Coastguard Worker       failf(data, "Couldn't create hyper executor");
915*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
916*6236dae4SAndroid Build Coastguard Worker       goto out;
917*6236dae4SAndroid Build Coastguard Worker     }
918*6236dae4SAndroid Build Coastguard Worker   }
919*6236dae4SAndroid Build Coastguard Worker 
920*6236dae4SAndroid Build Coastguard Worker   options = hyper_clientconn_options_new();
921*6236dae4SAndroid Build Coastguard Worker   if(!options) {
922*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't create hyper client options");
923*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
924*6236dae4SAndroid Build Coastguard Worker     goto out;
925*6236dae4SAndroid Build Coastguard Worker   }
926*6236dae4SAndroid Build Coastguard Worker   if(conn->alpn == CURL_HTTP_VERSION_2) {
927*6236dae4SAndroid Build Coastguard Worker     failf(data, "ALPN protocol h2 not supported with Hyper");
928*6236dae4SAndroid Build Coastguard Worker     result = CURLE_UNSUPPORTED_PROTOCOL;
929*6236dae4SAndroid Build Coastguard Worker     goto out;
930*6236dae4SAndroid Build Coastguard Worker   }
931*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_options_set_preserve_header_case(options, 1);
932*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_options_set_preserve_header_order(options, 1);
933*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_options_http1_allow_multiline_headers(options, 1);
934*6236dae4SAndroid Build Coastguard Worker 
935*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_options_exec(options, h->exec);
936*6236dae4SAndroid Build Coastguard Worker 
937*6236dae4SAndroid Build Coastguard Worker   /* "Both the `io` and the `options` are consumed in this function call" */
938*6236dae4SAndroid Build Coastguard Worker   handshake = hyper_clientconn_handshake(io, options);
939*6236dae4SAndroid Build Coastguard Worker   if(!handshake) {
940*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't create hyper client handshake");
941*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
942*6236dae4SAndroid Build Coastguard Worker     goto out;
943*6236dae4SAndroid Build Coastguard Worker   }
944*6236dae4SAndroid Build Coastguard Worker   io = NULL;
945*6236dae4SAndroid Build Coastguard Worker   options = NULL;
946*6236dae4SAndroid Build Coastguard Worker 
947*6236dae4SAndroid Build Coastguard Worker   if(HYPERE_OK != hyper_executor_push(h->exec, handshake)) {
948*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't hyper_executor_push the handshake");
949*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
950*6236dae4SAndroid Build Coastguard Worker     goto out;
951*6236dae4SAndroid Build Coastguard Worker   }
952*6236dae4SAndroid Build Coastguard Worker   handshake = NULL; /* ownership passed on */
953*6236dae4SAndroid Build Coastguard Worker 
954*6236dae4SAndroid Build Coastguard Worker   task = hyper_executor_poll(h->exec);
955*6236dae4SAndroid Build Coastguard Worker   if(!task) {
956*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't hyper_executor_poll the handshake");
957*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
958*6236dae4SAndroid Build Coastguard Worker     goto out;
959*6236dae4SAndroid Build Coastguard Worker   }
960*6236dae4SAndroid Build Coastguard Worker 
961*6236dae4SAndroid Build Coastguard Worker   client = hyper_task_value(task);
962*6236dae4SAndroid Build Coastguard Worker   hyper_task_free(task);
963*6236dae4SAndroid Build Coastguard Worker 
964*6236dae4SAndroid Build Coastguard Worker   req = hyper_request_new();
965*6236dae4SAndroid Build Coastguard Worker   if(!req) {
966*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't hyper_request_new");
967*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
968*6236dae4SAndroid Build Coastguard Worker     goto out;
969*6236dae4SAndroid Build Coastguard Worker   }
970*6236dae4SAndroid Build Coastguard Worker 
971*6236dae4SAndroid Build Coastguard Worker   if(!Curl_use_http_1_1plus(data, conn)) {
972*6236dae4SAndroid Build Coastguard Worker     if(HYPERE_OK != hyper_request_set_version(req,
973*6236dae4SAndroid Build Coastguard Worker                                               HYPER_HTTP_VERSION_1_0)) {
974*6236dae4SAndroid Build Coastguard Worker       failf(data, "error setting HTTP version");
975*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
976*6236dae4SAndroid Build Coastguard Worker       goto out;
977*6236dae4SAndroid Build Coastguard Worker     }
978*6236dae4SAndroid Build Coastguard Worker   }
979*6236dae4SAndroid Build Coastguard Worker 
980*6236dae4SAndroid Build Coastguard Worker   if(hyper_request_set_method(req, (uint8_t *)method, strlen(method))) {
981*6236dae4SAndroid Build Coastguard Worker     failf(data, "error setting method");
982*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
983*6236dae4SAndroid Build Coastguard Worker     goto out;
984*6236dae4SAndroid Build Coastguard Worker   }
985*6236dae4SAndroid Build Coastguard Worker 
986*6236dae4SAndroid Build Coastguard Worker   result = request_target(data, conn, method, req);
987*6236dae4SAndroid Build Coastguard Worker   if(result)
988*6236dae4SAndroid Build Coastguard Worker     goto out;
989*6236dae4SAndroid Build Coastguard Worker 
990*6236dae4SAndroid Build Coastguard Worker   headers = hyper_request_headers(req);
991*6236dae4SAndroid Build Coastguard Worker   if(!headers) {
992*6236dae4SAndroid Build Coastguard Worker     failf(data, "hyper_request_headers");
993*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
994*6236dae4SAndroid Build Coastguard Worker     goto out;
995*6236dae4SAndroid Build Coastguard Worker   }
996*6236dae4SAndroid Build Coastguard Worker 
997*6236dae4SAndroid Build Coastguard Worker   rc = hyper_request_on_informational(req, http1xx_cb, data);
998*6236dae4SAndroid Build Coastguard Worker   if(rc) {
999*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
1000*6236dae4SAndroid Build Coastguard Worker     goto out;
1001*6236dae4SAndroid Build Coastguard Worker   }
1002*6236dae4SAndroid Build Coastguard Worker 
1003*6236dae4SAndroid Build Coastguard Worker   if(data->state.aptr.host) {
1004*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, data->state.aptr.host);
1005*6236dae4SAndroid Build Coastguard Worker     if(result)
1006*6236dae4SAndroid Build Coastguard Worker       goto out;
1007*6236dae4SAndroid Build Coastguard Worker   }
1008*6236dae4SAndroid Build Coastguard Worker 
1009*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1010*6236dae4SAndroid Build Coastguard Worker   if(data->state.aptr.proxyuserpwd) {
1011*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, data->state.aptr.proxyuserpwd);
1012*6236dae4SAndroid Build Coastguard Worker     if(result)
1013*6236dae4SAndroid Build Coastguard Worker       goto out;
1014*6236dae4SAndroid Build Coastguard Worker   }
1015*6236dae4SAndroid Build Coastguard Worker #endif
1016*6236dae4SAndroid Build Coastguard Worker 
1017*6236dae4SAndroid Build Coastguard Worker   if(data->state.aptr.userpwd) {
1018*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, data->state.aptr.userpwd);
1019*6236dae4SAndroid Build Coastguard Worker     if(result)
1020*6236dae4SAndroid Build Coastguard Worker       goto out;
1021*6236dae4SAndroid Build Coastguard Worker   }
1022*6236dae4SAndroid Build Coastguard Worker 
1023*6236dae4SAndroid Build Coastguard Worker   if((data->state.use_range && data->state.aptr.rangeline)) {
1024*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, data->state.aptr.rangeline);
1025*6236dae4SAndroid Build Coastguard Worker     if(result)
1026*6236dae4SAndroid Build Coastguard Worker       goto out;
1027*6236dae4SAndroid Build Coastguard Worker   }
1028*6236dae4SAndroid Build Coastguard Worker 
1029*6236dae4SAndroid Build Coastguard Worker   if(data->set.str[STRING_USERAGENT] &&
1030*6236dae4SAndroid Build Coastguard Worker      *data->set.str[STRING_USERAGENT] &&
1031*6236dae4SAndroid Build Coastguard Worker      data->state.aptr.uagent) {
1032*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, data->state.aptr.uagent);
1033*6236dae4SAndroid Build Coastguard Worker     if(result)
1034*6236dae4SAndroid Build Coastguard Worker       goto out;
1035*6236dae4SAndroid Build Coastguard Worker   }
1036*6236dae4SAndroid Build Coastguard Worker 
1037*6236dae4SAndroid Build Coastguard Worker   p_accept = Curl_checkheaders(data,
1038*6236dae4SAndroid Build Coastguard Worker                                STRCONST("Accept")) ? NULL : "Accept: */*\r\n";
1039*6236dae4SAndroid Build Coastguard Worker   if(p_accept) {
1040*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, p_accept);
1041*6236dae4SAndroid Build Coastguard Worker     if(result)
1042*6236dae4SAndroid Build Coastguard Worker       goto out;
1043*6236dae4SAndroid Build Coastguard Worker   }
1044*6236dae4SAndroid Build Coastguard Worker   if(te) {
1045*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, te);
1046*6236dae4SAndroid Build Coastguard Worker     if(result)
1047*6236dae4SAndroid Build Coastguard Worker       goto out;
1048*6236dae4SAndroid Build Coastguard Worker   }
1049*6236dae4SAndroid Build Coastguard Worker 
1050*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_ALTSVC
1051*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.altused && !Curl_checkheaders(data, STRCONST("Alt-Used"))) {
1052*6236dae4SAndroid Build Coastguard Worker     char *altused = aprintf("Alt-Used: %s:%d\r\n",
1053*6236dae4SAndroid Build Coastguard Worker                             conn->conn_to_host.name, conn->conn_to_port);
1054*6236dae4SAndroid Build Coastguard Worker     if(!altused) {
1055*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
1056*6236dae4SAndroid Build Coastguard Worker       goto out;
1057*6236dae4SAndroid Build Coastguard Worker     }
1058*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, altused);
1059*6236dae4SAndroid Build Coastguard Worker     if(result)
1060*6236dae4SAndroid Build Coastguard Worker       goto out;
1061*6236dae4SAndroid Build Coastguard Worker     free(altused);
1062*6236dae4SAndroid Build Coastguard Worker   }
1063*6236dae4SAndroid Build Coastguard Worker #endif
1064*6236dae4SAndroid Build Coastguard Worker 
1065*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1066*6236dae4SAndroid Build Coastguard Worker   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy &&
1067*6236dae4SAndroid Build Coastguard Worker      !Curl_checkheaders(data, STRCONST("Proxy-Connection")) &&
1068*6236dae4SAndroid Build Coastguard Worker      !Curl_checkProxyheaders(data, conn, STRCONST("Proxy-Connection"))) {
1069*6236dae4SAndroid Build Coastguard Worker     result = Curl_hyper_header(data, headers, "Proxy-Connection: Keep-Alive");
1070*6236dae4SAndroid Build Coastguard Worker     if(result)
1071*6236dae4SAndroid Build Coastguard Worker       goto out;
1072*6236dae4SAndroid Build Coastguard Worker   }
1073*6236dae4SAndroid Build Coastguard Worker #endif
1074*6236dae4SAndroid Build Coastguard Worker 
1075*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.ref);
1076*6236dae4SAndroid Build Coastguard Worker   if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) {
1077*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.ref = aprintf("Referer: %s\r\n", data->state.referer);
1078*6236dae4SAndroid Build Coastguard Worker     if(!data->state.aptr.ref)
1079*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
1080*6236dae4SAndroid Build Coastguard Worker     else
1081*6236dae4SAndroid Build Coastguard Worker       result = Curl_hyper_header(data, headers, data->state.aptr.ref);
1082*6236dae4SAndroid Build Coastguard Worker     if(result)
1083*6236dae4SAndroid Build Coastguard Worker       goto out;
1084*6236dae4SAndroid Build Coastguard Worker   }
1085*6236dae4SAndroid Build Coastguard Worker 
1086*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_LIBZ
1087*6236dae4SAndroid Build Coastguard Worker   /* we only consider transfer-encoding magic if libz support is built-in */
1088*6236dae4SAndroid Build Coastguard Worker   result = Curl_transferencode(data);
1089*6236dae4SAndroid Build Coastguard Worker   if(result)
1090*6236dae4SAndroid Build Coastguard Worker     goto out;
1091*6236dae4SAndroid Build Coastguard Worker   result = Curl_hyper_header(data, headers, data->state.aptr.te);
1092*6236dae4SAndroid Build Coastguard Worker   if(result)
1093*6236dae4SAndroid Build Coastguard Worker     goto out;
1094*6236dae4SAndroid Build Coastguard Worker #endif
1095*6236dae4SAndroid Build Coastguard Worker 
1096*6236dae4SAndroid Build Coastguard Worker   if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) &&
1097*6236dae4SAndroid Build Coastguard Worker      data->set.str[STRING_ENCODING]) {
1098*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->state.aptr.accept_encoding);
1099*6236dae4SAndroid Build Coastguard Worker     data->state.aptr.accept_encoding =
1100*6236dae4SAndroid Build Coastguard Worker       aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
1101*6236dae4SAndroid Build Coastguard Worker     if(!data->state.aptr.accept_encoding)
1102*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OUT_OF_MEMORY;
1103*6236dae4SAndroid Build Coastguard Worker     else
1104*6236dae4SAndroid Build Coastguard Worker       result = Curl_hyper_header(data, headers,
1105*6236dae4SAndroid Build Coastguard Worker                                  data->state.aptr.accept_encoding);
1106*6236dae4SAndroid Build Coastguard Worker     if(result)
1107*6236dae4SAndroid Build Coastguard Worker       goto out;
1108*6236dae4SAndroid Build Coastguard Worker   }
1109*6236dae4SAndroid Build Coastguard Worker   else
1110*6236dae4SAndroid Build Coastguard Worker     Curl_safefree(data->state.aptr.accept_encoding);
1111*6236dae4SAndroid Build Coastguard Worker 
1112*6236dae4SAndroid Build Coastguard Worker   result = cookies(data, conn, headers);
1113*6236dae4SAndroid Build Coastguard Worker   if(result)
1114*6236dae4SAndroid Build Coastguard Worker     goto out;
1115*6236dae4SAndroid Build Coastguard Worker 
1116*6236dae4SAndroid Build Coastguard Worker   if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS))
1117*6236dae4SAndroid Build Coastguard Worker     result = Curl_ws_request(data, headers);
1118*6236dae4SAndroid Build Coastguard Worker 
1119*6236dae4SAndroid Build Coastguard Worker   result = Curl_add_timecondition(data, headers);
1120*6236dae4SAndroid Build Coastguard Worker   if(result)
1121*6236dae4SAndroid Build Coastguard Worker     goto out;
1122*6236dae4SAndroid Build Coastguard Worker 
1123*6236dae4SAndroid Build Coastguard Worker   result = Curl_add_custom_headers(data, FALSE, headers);
1124*6236dae4SAndroid Build Coastguard Worker   if(result)
1125*6236dae4SAndroid Build Coastguard Worker     goto out;
1126*6236dae4SAndroid Build Coastguard Worker 
1127*6236dae4SAndroid Build Coastguard Worker   result = finalize_request(data, headers, req, httpreq);
1128*6236dae4SAndroid Build Coastguard Worker   if(result)
1129*6236dae4SAndroid Build Coastguard Worker     goto out;
1130*6236dae4SAndroid Build Coastguard Worker 
1131*6236dae4SAndroid Build Coastguard Worker   Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
1132*6236dae4SAndroid Build Coastguard Worker 
1133*6236dae4SAndroid Build Coastguard Worker   if(data->req.upload_chunky && data->req.authneg) {
1134*6236dae4SAndroid Build Coastguard Worker     data->req.upload_chunky = TRUE;
1135*6236dae4SAndroid Build Coastguard Worker   }
1136*6236dae4SAndroid Build Coastguard Worker   else {
1137*6236dae4SAndroid Build Coastguard Worker     data->req.upload_chunky = FALSE;
1138*6236dae4SAndroid Build Coastguard Worker   }
1139*6236dae4SAndroid Build Coastguard Worker   sendtask = hyper_clientconn_send(client, req);
1140*6236dae4SAndroid Build Coastguard Worker   if(!sendtask) {
1141*6236dae4SAndroid Build Coastguard Worker     failf(data, "hyper_clientconn_send");
1142*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
1143*6236dae4SAndroid Build Coastguard Worker     goto out;
1144*6236dae4SAndroid Build Coastguard Worker   }
1145*6236dae4SAndroid Build Coastguard Worker   req = NULL;
1146*6236dae4SAndroid Build Coastguard Worker 
1147*6236dae4SAndroid Build Coastguard Worker   if(HYPERE_OK != hyper_executor_push(h->exec, sendtask)) {
1148*6236dae4SAndroid Build Coastguard Worker     failf(data, "Couldn't hyper_executor_push the send");
1149*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
1150*6236dae4SAndroid Build Coastguard Worker     goto out;
1151*6236dae4SAndroid Build Coastguard Worker   }
1152*6236dae4SAndroid Build Coastguard Worker   sendtask = NULL; /* ownership passed on */
1153*6236dae4SAndroid Build Coastguard Worker 
1154*6236dae4SAndroid Build Coastguard Worker   hyper_clientconn_free(client);
1155*6236dae4SAndroid Build Coastguard Worker   client = NULL;
1156*6236dae4SAndroid Build Coastguard Worker 
1157*6236dae4SAndroid Build Coastguard Worker   if((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) {
1158*6236dae4SAndroid Build Coastguard Worker     /* HTTP GET/HEAD download */
1159*6236dae4SAndroid Build Coastguard Worker     Curl_pgrsSetUploadSize(data, 0); /* nothing */
1160*6236dae4SAndroid Build Coastguard Worker     result = Curl_req_set_upload_done(data);
1161*6236dae4SAndroid Build Coastguard Worker     if(result)
1162*6236dae4SAndroid Build Coastguard Worker       goto out;
1163*6236dae4SAndroid Build Coastguard Worker   }
1164*6236dae4SAndroid Build Coastguard Worker 
1165*6236dae4SAndroid Build Coastguard Worker   Curl_xfer_setup1(data, CURL_XFER_SENDRECV, -1, TRUE);
1166*6236dae4SAndroid Build Coastguard Worker   conn->datastream = Curl_hyper_stream;
1167*6236dae4SAndroid Build Coastguard Worker 
1168*6236dae4SAndroid Build Coastguard Worker   /* clear userpwd and proxyuserpwd to avoid reusing old credentials
1169*6236dae4SAndroid Build Coastguard Worker    * from reused connections */
1170*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.userpwd);
1171*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1172*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(data->state.aptr.proxyuserpwd);
1173*6236dae4SAndroid Build Coastguard Worker #endif
1174*6236dae4SAndroid Build Coastguard Worker 
1175*6236dae4SAndroid Build Coastguard Worker out:
1176*6236dae4SAndroid Build Coastguard Worker   if(result) {
1177*6236dae4SAndroid Build Coastguard Worker     if(io)
1178*6236dae4SAndroid Build Coastguard Worker       hyper_io_free(io);
1179*6236dae4SAndroid Build Coastguard Worker     if(options)
1180*6236dae4SAndroid Build Coastguard Worker       hyper_clientconn_options_free(options);
1181*6236dae4SAndroid Build Coastguard Worker     if(handshake)
1182*6236dae4SAndroid Build Coastguard Worker       hyper_task_free(handshake);
1183*6236dae4SAndroid Build Coastguard Worker     if(client)
1184*6236dae4SAndroid Build Coastguard Worker       hyper_clientconn_free(client);
1185*6236dae4SAndroid Build Coastguard Worker     if(req)
1186*6236dae4SAndroid Build Coastguard Worker       hyper_request_free(req);
1187*6236dae4SAndroid Build Coastguard Worker   }
1188*6236dae4SAndroid Build Coastguard Worker   return result;
1189*6236dae4SAndroid Build Coastguard Worker }
1190*6236dae4SAndroid Build Coastguard Worker 
Curl_hyper_done(struct Curl_easy * data)1191*6236dae4SAndroid Build Coastguard Worker void Curl_hyper_done(struct Curl_easy *data)
1192*6236dae4SAndroid Build Coastguard Worker {
1193*6236dae4SAndroid Build Coastguard Worker   struct hyptransfer *h = &data->hyp;
1194*6236dae4SAndroid Build Coastguard Worker   if(h->exec) {
1195*6236dae4SAndroid Build Coastguard Worker     hyper_executor_free(h->exec);
1196*6236dae4SAndroid Build Coastguard Worker     h->exec = NULL;
1197*6236dae4SAndroid Build Coastguard Worker   }
1198*6236dae4SAndroid Build Coastguard Worker   if(h->read_waker) {
1199*6236dae4SAndroid Build Coastguard Worker     hyper_waker_free(h->read_waker);
1200*6236dae4SAndroid Build Coastguard Worker     h->read_waker = NULL;
1201*6236dae4SAndroid Build Coastguard Worker   }
1202*6236dae4SAndroid Build Coastguard Worker   if(h->write_waker) {
1203*6236dae4SAndroid Build Coastguard Worker     hyper_waker_free(h->write_waker);
1204*6236dae4SAndroid Build Coastguard Worker     h->write_waker = NULL;
1205*6236dae4SAndroid Build Coastguard Worker   }
1206*6236dae4SAndroid Build Coastguard Worker   if(h->send_body_waker) {
1207*6236dae4SAndroid Build Coastguard Worker     hyper_waker_free(h->send_body_waker);
1208*6236dae4SAndroid Build Coastguard Worker     h->send_body_waker = NULL;
1209*6236dae4SAndroid Build Coastguard Worker   }
1210*6236dae4SAndroid Build Coastguard Worker }
1211*6236dae4SAndroid Build Coastguard Worker 
cr_hyper_unpause(struct Curl_easy * data,struct Curl_creader * reader)1212*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_hyper_unpause(struct Curl_easy *data,
1213*6236dae4SAndroid Build Coastguard Worker                                  struct Curl_creader *reader)
1214*6236dae4SAndroid Build Coastguard Worker {
1215*6236dae4SAndroid Build Coastguard Worker   (void)reader;
1216*6236dae4SAndroid Build Coastguard Worker   if(data->hyp.send_body_waker) {
1217*6236dae4SAndroid Build Coastguard Worker     hyper_waker_wake(data->hyp.send_body_waker);
1218*6236dae4SAndroid Build Coastguard Worker     data->hyp.send_body_waker = NULL;
1219*6236dae4SAndroid Build Coastguard Worker   }
1220*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
1221*6236dae4SAndroid Build Coastguard Worker }
1222*6236dae4SAndroid Build Coastguard Worker 
1223*6236dae4SAndroid Build Coastguard Worker /* Hyper client reader, handling unpausing */
1224*6236dae4SAndroid Build Coastguard Worker static const struct Curl_crtype cr_hyper_protocol = {
1225*6236dae4SAndroid Build Coastguard Worker   "cr-hyper",
1226*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_init,
1227*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_read,
1228*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_close,
1229*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_needs_rewind,
1230*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_total_length,
1231*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_resume_from,
1232*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_rewind,
1233*6236dae4SAndroid Build Coastguard Worker   cr_hyper_unpause,
1234*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_is_paused,
1235*6236dae4SAndroid Build Coastguard Worker   Curl_creader_def_done,
1236*6236dae4SAndroid Build Coastguard Worker   sizeof(struct Curl_creader)
1237*6236dae4SAndroid Build Coastguard Worker };
1238*6236dae4SAndroid Build Coastguard Worker 
cr_hyper_add(struct Curl_easy * data)1239*6236dae4SAndroid Build Coastguard Worker static CURLcode cr_hyper_add(struct Curl_easy *data)
1240*6236dae4SAndroid Build Coastguard Worker {
1241*6236dae4SAndroid Build Coastguard Worker   struct Curl_creader *reader = NULL;
1242*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
1243*6236dae4SAndroid Build Coastguard Worker 
1244*6236dae4SAndroid Build Coastguard Worker   result = Curl_creader_create(&reader, data, &cr_hyper_protocol,
1245*6236dae4SAndroid Build Coastguard Worker                                CURL_CR_PROTOCOL);
1246*6236dae4SAndroid Build Coastguard Worker   if(!result)
1247*6236dae4SAndroid Build Coastguard Worker     result = Curl_creader_add(data, reader);
1248*6236dae4SAndroid Build Coastguard Worker 
1249*6236dae4SAndroid Build Coastguard Worker   if(result && reader)
1250*6236dae4SAndroid Build Coastguard Worker     Curl_creader_free(data, reader);
1251*6236dae4SAndroid Build Coastguard Worker   return result;
1252*6236dae4SAndroid Build Coastguard Worker }
1253*6236dae4SAndroid Build Coastguard Worker 
1254*6236dae4SAndroid Build Coastguard Worker #endif /* !defined(CURL_DISABLE_HTTP) && defined(USE_HYPER) */
1255