xref: /aosp_15_r20/external/curl/lib/cf-https-connect.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.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 #include "curl_setup.h"
26*6236dae4SAndroid Build Coastguard Worker 
27*6236dae4SAndroid Build Coastguard Worker #if !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER)
28*6236dae4SAndroid Build Coastguard Worker 
29*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
30*6236dae4SAndroid Build Coastguard Worker #include <curl/curl.h>
31*6236dae4SAndroid Build Coastguard Worker #include "curl_trc.h"
32*6236dae4SAndroid Build Coastguard Worker #include "cfilters.h"
33*6236dae4SAndroid Build Coastguard Worker #include "connect.h"
34*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
35*6236dae4SAndroid Build Coastguard Worker #include "cf-https-connect.h"
36*6236dae4SAndroid Build Coastguard Worker #include "http2.h"
37*6236dae4SAndroid Build Coastguard Worker #include "vquic/vquic.h"
38*6236dae4SAndroid Build Coastguard Worker 
39*6236dae4SAndroid Build Coastguard Worker /* The last 3 #include files should be in this order */
40*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
41*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
42*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
43*6236dae4SAndroid Build Coastguard Worker 
44*6236dae4SAndroid Build Coastguard Worker 
45*6236dae4SAndroid Build Coastguard Worker typedef enum {
46*6236dae4SAndroid Build Coastguard Worker   CF_HC_INIT,
47*6236dae4SAndroid Build Coastguard Worker   CF_HC_CONNECT,
48*6236dae4SAndroid Build Coastguard Worker   CF_HC_SUCCESS,
49*6236dae4SAndroid Build Coastguard Worker   CF_HC_FAILURE
50*6236dae4SAndroid Build Coastguard Worker } cf_hc_state;
51*6236dae4SAndroid Build Coastguard Worker 
52*6236dae4SAndroid Build Coastguard Worker struct cf_hc_baller {
53*6236dae4SAndroid Build Coastguard Worker   const char *name;
54*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *cf;
55*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
56*6236dae4SAndroid Build Coastguard Worker   struct curltime started;
57*6236dae4SAndroid Build Coastguard Worker   int reply_ms;
58*6236dae4SAndroid Build Coastguard Worker   BIT(enabled);
59*6236dae4SAndroid Build Coastguard Worker   BIT(shutdown);
60*6236dae4SAndroid Build Coastguard Worker };
61*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_reset(struct cf_hc_baller * b,struct Curl_easy * data)62*6236dae4SAndroid Build Coastguard Worker static void cf_hc_baller_reset(struct cf_hc_baller *b,
63*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data)
64*6236dae4SAndroid Build Coastguard Worker {
65*6236dae4SAndroid Build Coastguard Worker   if(b->cf) {
66*6236dae4SAndroid Build Coastguard Worker     Curl_conn_cf_close(b->cf, data);
67*6236dae4SAndroid Build Coastguard Worker     Curl_conn_cf_discard_chain(&b->cf, data);
68*6236dae4SAndroid Build Coastguard Worker     b->cf = NULL;
69*6236dae4SAndroid Build Coastguard Worker   }
70*6236dae4SAndroid Build Coastguard Worker   b->result = CURLE_OK;
71*6236dae4SAndroid Build Coastguard Worker   b->reply_ms = -1;
72*6236dae4SAndroid Build Coastguard Worker }
73*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_is_active(struct cf_hc_baller * b)74*6236dae4SAndroid Build Coastguard Worker static bool cf_hc_baller_is_active(struct cf_hc_baller *b)
75*6236dae4SAndroid Build Coastguard Worker {
76*6236dae4SAndroid Build Coastguard Worker   return b->enabled && b->cf && !b->result;
77*6236dae4SAndroid Build Coastguard Worker }
78*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_has_started(struct cf_hc_baller * b)79*6236dae4SAndroid Build Coastguard Worker static bool cf_hc_baller_has_started(struct cf_hc_baller *b)
80*6236dae4SAndroid Build Coastguard Worker {
81*6236dae4SAndroid Build Coastguard Worker   return !!b->cf;
82*6236dae4SAndroid Build Coastguard Worker }
83*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_reply_ms(struct cf_hc_baller * b,struct Curl_easy * data)84*6236dae4SAndroid Build Coastguard Worker static int cf_hc_baller_reply_ms(struct cf_hc_baller *b,
85*6236dae4SAndroid Build Coastguard Worker                                  struct Curl_easy *data)
86*6236dae4SAndroid Build Coastguard Worker {
87*6236dae4SAndroid Build Coastguard Worker   if(b->reply_ms < 0)
88*6236dae4SAndroid Build Coastguard Worker     b->cf->cft->query(b->cf, data, CF_QUERY_CONNECT_REPLY_MS,
89*6236dae4SAndroid Build Coastguard Worker                       &b->reply_ms, NULL);
90*6236dae4SAndroid Build Coastguard Worker   return b->reply_ms;
91*6236dae4SAndroid Build Coastguard Worker }
92*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_data_pending(struct cf_hc_baller * b,const struct Curl_easy * data)93*6236dae4SAndroid Build Coastguard Worker static bool cf_hc_baller_data_pending(struct cf_hc_baller *b,
94*6236dae4SAndroid Build Coastguard Worker                                       const struct Curl_easy *data)
95*6236dae4SAndroid Build Coastguard Worker {
96*6236dae4SAndroid Build Coastguard Worker   return b->cf && !b->result && b->cf->cft->has_data_pending(b->cf, data);
97*6236dae4SAndroid Build Coastguard Worker }
98*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_needs_flush(struct cf_hc_baller * b,struct Curl_easy * data)99*6236dae4SAndroid Build Coastguard Worker static bool cf_hc_baller_needs_flush(struct cf_hc_baller *b,
100*6236dae4SAndroid Build Coastguard Worker                                      struct Curl_easy *data)
101*6236dae4SAndroid Build Coastguard Worker {
102*6236dae4SAndroid Build Coastguard Worker   return b->cf && !b->result && Curl_conn_cf_needs_flush(b->cf, data);
103*6236dae4SAndroid Build Coastguard Worker }
104*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_cntrl(struct cf_hc_baller * b,struct Curl_easy * data,int event,int arg1,void * arg2)105*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_baller_cntrl(struct cf_hc_baller *b,
106*6236dae4SAndroid Build Coastguard Worker                                    struct Curl_easy *data,
107*6236dae4SAndroid Build Coastguard Worker                                    int event, int arg1, void *arg2)
108*6236dae4SAndroid Build Coastguard Worker {
109*6236dae4SAndroid Build Coastguard Worker   if(b->cf && !b->result)
110*6236dae4SAndroid Build Coastguard Worker     return Curl_conn_cf_cntrl(b->cf, data, FALSE, event, arg1, arg2);
111*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
112*6236dae4SAndroid Build Coastguard Worker }
113*6236dae4SAndroid Build Coastguard Worker 
114*6236dae4SAndroid Build Coastguard Worker struct cf_hc_ctx {
115*6236dae4SAndroid Build Coastguard Worker   cf_hc_state state;
116*6236dae4SAndroid Build Coastguard Worker   const struct Curl_dns_entry *remotehost;
117*6236dae4SAndroid Build Coastguard Worker   struct curltime started;  /* when connect started */
118*6236dae4SAndroid Build Coastguard Worker   CURLcode result;          /* overall result */
119*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_baller h3_baller;
120*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_baller h21_baller;
121*6236dae4SAndroid Build Coastguard Worker   unsigned int soft_eyeballs_timeout_ms;
122*6236dae4SAndroid Build Coastguard Worker   unsigned int hard_eyeballs_timeout_ms;
123*6236dae4SAndroid Build Coastguard Worker };
124*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_init(struct cf_hc_baller * b,struct Curl_cfilter * cf,struct Curl_easy * data,const char * name,int transport)125*6236dae4SAndroid Build Coastguard Worker static void cf_hc_baller_init(struct cf_hc_baller *b,
126*6236dae4SAndroid Build Coastguard Worker                               struct Curl_cfilter *cf,
127*6236dae4SAndroid Build Coastguard Worker                               struct Curl_easy *data,
128*6236dae4SAndroid Build Coastguard Worker                               const char *name,
129*6236dae4SAndroid Build Coastguard Worker                               int transport)
130*6236dae4SAndroid Build Coastguard Worker {
131*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
132*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *save = cf->next;
133*6236dae4SAndroid Build Coastguard Worker 
134*6236dae4SAndroid Build Coastguard Worker   b->name = name;
135*6236dae4SAndroid Build Coastguard Worker   cf->next = NULL;
136*6236dae4SAndroid Build Coastguard Worker   b->started = Curl_now();
137*6236dae4SAndroid Build Coastguard Worker   b->result = Curl_cf_setup_insert_after(cf, data, ctx->remotehost,
138*6236dae4SAndroid Build Coastguard Worker                                          transport, CURL_CF_SSL_ENABLE);
139*6236dae4SAndroid Build Coastguard Worker   b->cf = cf->next;
140*6236dae4SAndroid Build Coastguard Worker   cf->next = save;
141*6236dae4SAndroid Build Coastguard Worker }
142*6236dae4SAndroid Build Coastguard Worker 
cf_hc_baller_connect(struct cf_hc_baller * b,struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)143*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b,
144*6236dae4SAndroid Build Coastguard Worker                                      struct Curl_cfilter *cf,
145*6236dae4SAndroid Build Coastguard Worker                                      struct Curl_easy *data,
146*6236dae4SAndroid Build Coastguard Worker                                      bool *done)
147*6236dae4SAndroid Build Coastguard Worker {
148*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *save = cf->next;
149*6236dae4SAndroid Build Coastguard Worker 
150*6236dae4SAndroid Build Coastguard Worker   cf->next = b->cf;
151*6236dae4SAndroid Build Coastguard Worker   b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
152*6236dae4SAndroid Build Coastguard Worker   b->cf = cf->next; /* it might mutate */
153*6236dae4SAndroid Build Coastguard Worker   cf->next = save;
154*6236dae4SAndroid Build Coastguard Worker   return b->result;
155*6236dae4SAndroid Build Coastguard Worker }
156*6236dae4SAndroid Build Coastguard Worker 
cf_hc_reset(struct Curl_cfilter * cf,struct Curl_easy * data)157*6236dae4SAndroid Build Coastguard Worker static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data)
158*6236dae4SAndroid Build Coastguard Worker {
159*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
160*6236dae4SAndroid Build Coastguard Worker 
161*6236dae4SAndroid Build Coastguard Worker   if(ctx) {
162*6236dae4SAndroid Build Coastguard Worker     cf_hc_baller_reset(&ctx->h3_baller, data);
163*6236dae4SAndroid Build Coastguard Worker     cf_hc_baller_reset(&ctx->h21_baller, data);
164*6236dae4SAndroid Build Coastguard Worker     ctx->state = CF_HC_INIT;
165*6236dae4SAndroid Build Coastguard Worker     ctx->result = CURLE_OK;
166*6236dae4SAndroid Build Coastguard Worker     ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout;
167*6236dae4SAndroid Build Coastguard Worker     ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 2;
168*6236dae4SAndroid Build Coastguard Worker   }
169*6236dae4SAndroid Build Coastguard Worker }
170*6236dae4SAndroid Build Coastguard Worker 
baller_connected(struct Curl_cfilter * cf,struct Curl_easy * data,struct cf_hc_baller * winner)171*6236dae4SAndroid Build Coastguard Worker static CURLcode baller_connected(struct Curl_cfilter *cf,
172*6236dae4SAndroid Build Coastguard Worker                                  struct Curl_easy *data,
173*6236dae4SAndroid Build Coastguard Worker                                  struct cf_hc_baller *winner)
174*6236dae4SAndroid Build Coastguard Worker {
175*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
176*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
177*6236dae4SAndroid Build Coastguard Worker   int reply_ms;
178*6236dae4SAndroid Build Coastguard Worker 
179*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(winner->cf);
180*6236dae4SAndroid Build Coastguard Worker   if(winner != &ctx->h3_baller)
181*6236dae4SAndroid Build Coastguard Worker     cf_hc_baller_reset(&ctx->h3_baller, data);
182*6236dae4SAndroid Build Coastguard Worker   if(winner != &ctx->h21_baller)
183*6236dae4SAndroid Build Coastguard Worker     cf_hc_baller_reset(&ctx->h21_baller, data);
184*6236dae4SAndroid Build Coastguard Worker 
185*6236dae4SAndroid Build Coastguard Worker   reply_ms = cf_hc_baller_reply_ms(winner, data);
186*6236dae4SAndroid Build Coastguard Worker   if(reply_ms >= 0)
187*6236dae4SAndroid Build Coastguard Worker     CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
188*6236dae4SAndroid Build Coastguard Worker                 winner->name, (int)Curl_timediff(Curl_now(), winner->started),
189*6236dae4SAndroid Build Coastguard Worker                 reply_ms);
190*6236dae4SAndroid Build Coastguard Worker   else
191*6236dae4SAndroid Build Coastguard Worker     CURL_TRC_CF(data, cf, "deferred handshake %s: %dms",
192*6236dae4SAndroid Build Coastguard Worker                 winner->name, (int)Curl_timediff(Curl_now(), winner->started));
193*6236dae4SAndroid Build Coastguard Worker 
194*6236dae4SAndroid Build Coastguard Worker   cf->next = winner->cf;
195*6236dae4SAndroid Build Coastguard Worker   winner->cf = NULL;
196*6236dae4SAndroid Build Coastguard Worker 
197*6236dae4SAndroid Build Coastguard Worker   switch(cf->conn->alpn) {
198*6236dae4SAndroid Build Coastguard Worker   case CURL_HTTP_VERSION_3:
199*6236dae4SAndroid Build Coastguard Worker     break;
200*6236dae4SAndroid Build Coastguard Worker   case CURL_HTTP_VERSION_2:
201*6236dae4SAndroid Build Coastguard Worker #ifdef USE_NGHTTP2
202*6236dae4SAndroid Build Coastguard Worker     /* Using nghttp2, we add the filter "below" us, so when the conn
203*6236dae4SAndroid Build Coastguard Worker      * closes, we tear it down for a fresh reconnect */
204*6236dae4SAndroid Build Coastguard Worker     result = Curl_http2_switch_at(cf, data);
205*6236dae4SAndroid Build Coastguard Worker     if(result) {
206*6236dae4SAndroid Build Coastguard Worker       ctx->state = CF_HC_FAILURE;
207*6236dae4SAndroid Build Coastguard Worker       ctx->result = result;
208*6236dae4SAndroid Build Coastguard Worker       return result;
209*6236dae4SAndroid Build Coastguard Worker     }
210*6236dae4SAndroid Build Coastguard Worker #endif
211*6236dae4SAndroid Build Coastguard Worker     break;
212*6236dae4SAndroid Build Coastguard Worker   default:
213*6236dae4SAndroid Build Coastguard Worker     break;
214*6236dae4SAndroid Build Coastguard Worker   }
215*6236dae4SAndroid Build Coastguard Worker   ctx->state = CF_HC_SUCCESS;
216*6236dae4SAndroid Build Coastguard Worker   cf->connected = TRUE;
217*6236dae4SAndroid Build Coastguard Worker   return result;
218*6236dae4SAndroid Build Coastguard Worker }
219*6236dae4SAndroid Build Coastguard Worker 
220*6236dae4SAndroid Build Coastguard Worker 
time_to_start_h21(struct Curl_cfilter * cf,struct Curl_easy * data,struct curltime now)221*6236dae4SAndroid Build Coastguard Worker static bool time_to_start_h21(struct Curl_cfilter *cf,
222*6236dae4SAndroid Build Coastguard Worker                               struct Curl_easy *data,
223*6236dae4SAndroid Build Coastguard Worker                               struct curltime now)
224*6236dae4SAndroid Build Coastguard Worker {
225*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
226*6236dae4SAndroid Build Coastguard Worker   timediff_t elapsed_ms;
227*6236dae4SAndroid Build Coastguard Worker 
228*6236dae4SAndroid Build Coastguard Worker   if(!ctx->h21_baller.enabled || cf_hc_baller_has_started(&ctx->h21_baller))
229*6236dae4SAndroid Build Coastguard Worker     return FALSE;
230*6236dae4SAndroid Build Coastguard Worker 
231*6236dae4SAndroid Build Coastguard Worker   if(!ctx->h3_baller.enabled || !cf_hc_baller_is_active(&ctx->h3_baller))
232*6236dae4SAndroid Build Coastguard Worker     return TRUE;
233*6236dae4SAndroid Build Coastguard Worker 
234*6236dae4SAndroid Build Coastguard Worker   elapsed_ms = Curl_timediff(now, ctx->started);
235*6236dae4SAndroid Build Coastguard Worker   if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
236*6236dae4SAndroid Build Coastguard Worker     CURL_TRC_CF(data, cf, "hard timeout of %dms reached, starting h21",
237*6236dae4SAndroid Build Coastguard Worker                 ctx->hard_eyeballs_timeout_ms);
238*6236dae4SAndroid Build Coastguard Worker     return TRUE;
239*6236dae4SAndroid Build Coastguard Worker   }
240*6236dae4SAndroid Build Coastguard Worker 
241*6236dae4SAndroid Build Coastguard Worker   if(elapsed_ms >= ctx->soft_eyeballs_timeout_ms) {
242*6236dae4SAndroid Build Coastguard Worker     if(cf_hc_baller_reply_ms(&ctx->h3_baller, data) < 0) {
243*6236dae4SAndroid Build Coastguard Worker       CURL_TRC_CF(data, cf, "soft timeout of %dms reached, h3 has not "
244*6236dae4SAndroid Build Coastguard Worker                   "seen any data, starting h21",
245*6236dae4SAndroid Build Coastguard Worker                   ctx->soft_eyeballs_timeout_ms);
246*6236dae4SAndroid Build Coastguard Worker       return TRUE;
247*6236dae4SAndroid Build Coastguard Worker     }
248*6236dae4SAndroid Build Coastguard Worker     /* set the effective hard timeout again */
249*6236dae4SAndroid Build Coastguard Worker     Curl_expire(data, ctx->hard_eyeballs_timeout_ms - elapsed_ms,
250*6236dae4SAndroid Build Coastguard Worker                 EXPIRE_ALPN_EYEBALLS);
251*6236dae4SAndroid Build Coastguard Worker   }
252*6236dae4SAndroid Build Coastguard Worker   return FALSE;
253*6236dae4SAndroid Build Coastguard Worker }
254*6236dae4SAndroid Build Coastguard Worker 
cf_hc_connect(struct Curl_cfilter * cf,struct Curl_easy * data,bool blocking,bool * done)255*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
256*6236dae4SAndroid Build Coastguard Worker                               struct Curl_easy *data,
257*6236dae4SAndroid Build Coastguard Worker                               bool blocking, bool *done)
258*6236dae4SAndroid Build Coastguard Worker {
259*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
260*6236dae4SAndroid Build Coastguard Worker   struct curltime now;
261*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
262*6236dae4SAndroid Build Coastguard Worker 
263*6236dae4SAndroid Build Coastguard Worker   (void)blocking;
264*6236dae4SAndroid Build Coastguard Worker   if(cf->connected) {
265*6236dae4SAndroid Build Coastguard Worker     *done = TRUE;
266*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
267*6236dae4SAndroid Build Coastguard Worker   }
268*6236dae4SAndroid Build Coastguard Worker 
269*6236dae4SAndroid Build Coastguard Worker   *done = FALSE;
270*6236dae4SAndroid Build Coastguard Worker   now = Curl_now();
271*6236dae4SAndroid Build Coastguard Worker   switch(ctx->state) {
272*6236dae4SAndroid Build Coastguard Worker   case CF_HC_INIT:
273*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(!ctx->h3_baller.cf);
274*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(!ctx->h21_baller.cf);
275*6236dae4SAndroid Build Coastguard Worker     DEBUGASSERT(!cf->next);
276*6236dae4SAndroid Build Coastguard Worker     CURL_TRC_CF(data, cf, "connect, init");
277*6236dae4SAndroid Build Coastguard Worker     ctx->started = now;
278*6236dae4SAndroid Build Coastguard Worker     if(ctx->h3_baller.enabled) {
279*6236dae4SAndroid Build Coastguard Worker       cf_hc_baller_init(&ctx->h3_baller, cf, data, "h3", TRNSPRT_QUIC);
280*6236dae4SAndroid Build Coastguard Worker       if(ctx->h21_baller.enabled)
281*6236dae4SAndroid Build Coastguard Worker         Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
282*6236dae4SAndroid Build Coastguard Worker     }
283*6236dae4SAndroid Build Coastguard Worker     else if(ctx->h21_baller.enabled)
284*6236dae4SAndroid Build Coastguard Worker       cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
285*6236dae4SAndroid Build Coastguard Worker                         cf->conn->transport);
286*6236dae4SAndroid Build Coastguard Worker     ctx->state = CF_HC_CONNECT;
287*6236dae4SAndroid Build Coastguard Worker     FALLTHROUGH();
288*6236dae4SAndroid Build Coastguard Worker 
289*6236dae4SAndroid Build Coastguard Worker   case CF_HC_CONNECT:
290*6236dae4SAndroid Build Coastguard Worker     if(cf_hc_baller_is_active(&ctx->h3_baller)) {
291*6236dae4SAndroid Build Coastguard Worker       result = cf_hc_baller_connect(&ctx->h3_baller, cf, data, done);
292*6236dae4SAndroid Build Coastguard Worker       if(!result && *done) {
293*6236dae4SAndroid Build Coastguard Worker         result = baller_connected(cf, data, &ctx->h3_baller);
294*6236dae4SAndroid Build Coastguard Worker         goto out;
295*6236dae4SAndroid Build Coastguard Worker       }
296*6236dae4SAndroid Build Coastguard Worker     }
297*6236dae4SAndroid Build Coastguard Worker 
298*6236dae4SAndroid Build Coastguard Worker     if(time_to_start_h21(cf, data, now)) {
299*6236dae4SAndroid Build Coastguard Worker       cf_hc_baller_init(&ctx->h21_baller, cf, data, "h21",
300*6236dae4SAndroid Build Coastguard Worker                         cf->conn->transport);
301*6236dae4SAndroid Build Coastguard Worker     }
302*6236dae4SAndroid Build Coastguard Worker 
303*6236dae4SAndroid Build Coastguard Worker     if(cf_hc_baller_is_active(&ctx->h21_baller)) {
304*6236dae4SAndroid Build Coastguard Worker       CURL_TRC_CF(data, cf, "connect, check h21");
305*6236dae4SAndroid Build Coastguard Worker       result = cf_hc_baller_connect(&ctx->h21_baller, cf, data, done);
306*6236dae4SAndroid Build Coastguard Worker       if(!result && *done) {
307*6236dae4SAndroid Build Coastguard Worker         result = baller_connected(cf, data, &ctx->h21_baller);
308*6236dae4SAndroid Build Coastguard Worker         goto out;
309*6236dae4SAndroid Build Coastguard Worker       }
310*6236dae4SAndroid Build Coastguard Worker     }
311*6236dae4SAndroid Build Coastguard Worker 
312*6236dae4SAndroid Build Coastguard Worker     if((!ctx->h3_baller.enabled || ctx->h3_baller.result) &&
313*6236dae4SAndroid Build Coastguard Worker        (!ctx->h21_baller.enabled || ctx->h21_baller.result)) {
314*6236dae4SAndroid Build Coastguard Worker       /* both failed or disabled. we give up */
315*6236dae4SAndroid Build Coastguard Worker       CURL_TRC_CF(data, cf, "connect, all failed");
316*6236dae4SAndroid Build Coastguard Worker       result = ctx->result = ctx->h3_baller.enabled ?
317*6236dae4SAndroid Build Coastguard Worker         ctx->h3_baller.result : ctx->h21_baller.result;
318*6236dae4SAndroid Build Coastguard Worker       ctx->state = CF_HC_FAILURE;
319*6236dae4SAndroid Build Coastguard Worker       goto out;
320*6236dae4SAndroid Build Coastguard Worker     }
321*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OK;
322*6236dae4SAndroid Build Coastguard Worker     *done = FALSE;
323*6236dae4SAndroid Build Coastguard Worker     break;
324*6236dae4SAndroid Build Coastguard Worker 
325*6236dae4SAndroid Build Coastguard Worker   case CF_HC_FAILURE:
326*6236dae4SAndroid Build Coastguard Worker     result = ctx->result;
327*6236dae4SAndroid Build Coastguard Worker     cf->connected = FALSE;
328*6236dae4SAndroid Build Coastguard Worker     *done = FALSE;
329*6236dae4SAndroid Build Coastguard Worker     break;
330*6236dae4SAndroid Build Coastguard Worker 
331*6236dae4SAndroid Build Coastguard Worker   case CF_HC_SUCCESS:
332*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OK;
333*6236dae4SAndroid Build Coastguard Worker     cf->connected = TRUE;
334*6236dae4SAndroid Build Coastguard Worker     *done = TRUE;
335*6236dae4SAndroid Build Coastguard Worker     break;
336*6236dae4SAndroid Build Coastguard Worker   }
337*6236dae4SAndroid Build Coastguard Worker 
338*6236dae4SAndroid Build Coastguard Worker out:
339*6236dae4SAndroid Build Coastguard Worker   CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
340*6236dae4SAndroid Build Coastguard Worker   return result;
341*6236dae4SAndroid Build Coastguard Worker }
342*6236dae4SAndroid Build Coastguard Worker 
cf_hc_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)343*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_shutdown(struct Curl_cfilter *cf,
344*6236dae4SAndroid Build Coastguard Worker                                struct Curl_easy *data, bool *done)
345*6236dae4SAndroid Build Coastguard Worker {
346*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
347*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_baller *ballers[2];
348*6236dae4SAndroid Build Coastguard Worker   size_t i;
349*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
350*6236dae4SAndroid Build Coastguard Worker 
351*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
352*6236dae4SAndroid Build Coastguard Worker   if(cf->connected) {
353*6236dae4SAndroid Build Coastguard Worker     *done = TRUE;
354*6236dae4SAndroid Build Coastguard Worker     return CURLE_OK;
355*6236dae4SAndroid Build Coastguard Worker   }
356*6236dae4SAndroid Build Coastguard Worker 
357*6236dae4SAndroid Build Coastguard Worker   /* shutdown all ballers that have not done so already. If one fails,
358*6236dae4SAndroid Build Coastguard Worker    * continue shutting down others until all are shutdown. */
359*6236dae4SAndroid Build Coastguard Worker   ballers[0] = &ctx->h3_baller;
360*6236dae4SAndroid Build Coastguard Worker   ballers[1] = &ctx->h21_baller;
361*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
362*6236dae4SAndroid Build Coastguard Worker     struct cf_hc_baller *b = ballers[i];
363*6236dae4SAndroid Build Coastguard Worker     bool bdone = FALSE;
364*6236dae4SAndroid Build Coastguard Worker     if(!cf_hc_baller_is_active(b) || b->shutdown)
365*6236dae4SAndroid Build Coastguard Worker       continue;
366*6236dae4SAndroid Build Coastguard Worker     b->result = b->cf->cft->do_shutdown(b->cf, data, &bdone);
367*6236dae4SAndroid Build Coastguard Worker     if(b->result || bdone)
368*6236dae4SAndroid Build Coastguard Worker       b->shutdown = TRUE; /* treat a failed shutdown as done */
369*6236dae4SAndroid Build Coastguard Worker   }
370*6236dae4SAndroid Build Coastguard Worker 
371*6236dae4SAndroid Build Coastguard Worker   *done = TRUE;
372*6236dae4SAndroid Build Coastguard Worker   for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
373*6236dae4SAndroid Build Coastguard Worker     if(ballers[i] && !ballers[i]->shutdown)
374*6236dae4SAndroid Build Coastguard Worker       *done = FALSE;
375*6236dae4SAndroid Build Coastguard Worker   }
376*6236dae4SAndroid Build Coastguard Worker   if(*done) {
377*6236dae4SAndroid Build Coastguard Worker     for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
378*6236dae4SAndroid Build Coastguard Worker       if(ballers[i] && ballers[i]->result)
379*6236dae4SAndroid Build Coastguard Worker         result = ballers[i]->result;
380*6236dae4SAndroid Build Coastguard Worker     }
381*6236dae4SAndroid Build Coastguard Worker   }
382*6236dae4SAndroid Build Coastguard Worker   CURL_TRC_CF(data, cf, "shutdown -> %d, done=%d", result, *done);
383*6236dae4SAndroid Build Coastguard Worker   return result;
384*6236dae4SAndroid Build Coastguard Worker }
385*6236dae4SAndroid Build Coastguard Worker 
cf_hc_adjust_pollset(struct Curl_cfilter * cf,struct Curl_easy * data,struct easy_pollset * ps)386*6236dae4SAndroid Build Coastguard Worker static void cf_hc_adjust_pollset(struct Curl_cfilter *cf,
387*6236dae4SAndroid Build Coastguard Worker                                   struct Curl_easy *data,
388*6236dae4SAndroid Build Coastguard Worker                                   struct easy_pollset *ps)
389*6236dae4SAndroid Build Coastguard Worker {
390*6236dae4SAndroid Build Coastguard Worker   if(!cf->connected) {
391*6236dae4SAndroid Build Coastguard Worker     struct cf_hc_ctx *ctx = cf->ctx;
392*6236dae4SAndroid Build Coastguard Worker     struct cf_hc_baller *ballers[2];
393*6236dae4SAndroid Build Coastguard Worker     size_t i;
394*6236dae4SAndroid Build Coastguard Worker 
395*6236dae4SAndroid Build Coastguard Worker     ballers[0] = &ctx->h3_baller;
396*6236dae4SAndroid Build Coastguard Worker     ballers[1] = &ctx->h21_baller;
397*6236dae4SAndroid Build Coastguard Worker     for(i = 0; i < sizeof(ballers)/sizeof(ballers[0]); i++) {
398*6236dae4SAndroid Build Coastguard Worker       struct cf_hc_baller *b = ballers[i];
399*6236dae4SAndroid Build Coastguard Worker       if(!cf_hc_baller_is_active(b))
400*6236dae4SAndroid Build Coastguard Worker         continue;
401*6236dae4SAndroid Build Coastguard Worker       Curl_conn_cf_adjust_pollset(b->cf, data, ps);
402*6236dae4SAndroid Build Coastguard Worker     }
403*6236dae4SAndroid Build Coastguard Worker     CURL_TRC_CF(data, cf, "adjust_pollset -> %d socks", ps->num);
404*6236dae4SAndroid Build Coastguard Worker   }
405*6236dae4SAndroid Build Coastguard Worker }
406*6236dae4SAndroid Build Coastguard Worker 
cf_hc_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)407*6236dae4SAndroid Build Coastguard Worker static bool cf_hc_data_pending(struct Curl_cfilter *cf,
408*6236dae4SAndroid Build Coastguard Worker                                const struct Curl_easy *data)
409*6236dae4SAndroid Build Coastguard Worker {
410*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
411*6236dae4SAndroid Build Coastguard Worker 
412*6236dae4SAndroid Build Coastguard Worker   if(cf->connected)
413*6236dae4SAndroid Build Coastguard Worker     return cf->next->cft->has_data_pending(cf->next, data);
414*6236dae4SAndroid Build Coastguard Worker 
415*6236dae4SAndroid Build Coastguard Worker   CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
416*6236dae4SAndroid Build Coastguard Worker   return cf_hc_baller_data_pending(&ctx->h3_baller, data)
417*6236dae4SAndroid Build Coastguard Worker          || cf_hc_baller_data_pending(&ctx->h21_baller, data);
418*6236dae4SAndroid Build Coastguard Worker }
419*6236dae4SAndroid Build Coastguard Worker 
cf_get_max_baller_time(struct Curl_cfilter * cf,struct Curl_easy * data,int query)420*6236dae4SAndroid Build Coastguard Worker static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
421*6236dae4SAndroid Build Coastguard Worker                                               struct Curl_easy *data,
422*6236dae4SAndroid Build Coastguard Worker                                               int query)
423*6236dae4SAndroid Build Coastguard Worker {
424*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
425*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *cfb;
426*6236dae4SAndroid Build Coastguard Worker   struct curltime t, tmax;
427*6236dae4SAndroid Build Coastguard Worker 
428*6236dae4SAndroid Build Coastguard Worker   memset(&tmax, 0, sizeof(tmax));
429*6236dae4SAndroid Build Coastguard Worker   memset(&t, 0, sizeof(t));
430*6236dae4SAndroid Build Coastguard Worker   cfb = ctx->h21_baller.enabled ? ctx->h21_baller.cf : NULL;
431*6236dae4SAndroid Build Coastguard Worker   if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
432*6236dae4SAndroid Build Coastguard Worker     if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
433*6236dae4SAndroid Build Coastguard Worker       tmax = t;
434*6236dae4SAndroid Build Coastguard Worker   }
435*6236dae4SAndroid Build Coastguard Worker   memset(&t, 0, sizeof(t));
436*6236dae4SAndroid Build Coastguard Worker   cfb = ctx->h3_baller.enabled ? ctx->h3_baller.cf : NULL;
437*6236dae4SAndroid Build Coastguard Worker   if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
438*6236dae4SAndroid Build Coastguard Worker     if((t.tv_sec || t.tv_usec) && Curl_timediff_us(t, tmax) > 0)
439*6236dae4SAndroid Build Coastguard Worker       tmax = t;
440*6236dae4SAndroid Build Coastguard Worker   }
441*6236dae4SAndroid Build Coastguard Worker   return tmax;
442*6236dae4SAndroid Build Coastguard Worker }
443*6236dae4SAndroid Build Coastguard Worker 
cf_hc_query(struct Curl_cfilter * cf,struct Curl_easy * data,int query,int * pres1,void * pres2)444*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_query(struct Curl_cfilter *cf,
445*6236dae4SAndroid Build Coastguard Worker                             struct Curl_easy *data,
446*6236dae4SAndroid Build Coastguard Worker                             int query, int *pres1, void *pres2)
447*6236dae4SAndroid Build Coastguard Worker {
448*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
449*6236dae4SAndroid Build Coastguard Worker 
450*6236dae4SAndroid Build Coastguard Worker   if(!cf->connected) {
451*6236dae4SAndroid Build Coastguard Worker     switch(query) {
452*6236dae4SAndroid Build Coastguard Worker     case CF_QUERY_TIMER_CONNECT: {
453*6236dae4SAndroid Build Coastguard Worker       struct curltime *when = pres2;
454*6236dae4SAndroid Build Coastguard Worker       *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_CONNECT);
455*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
456*6236dae4SAndroid Build Coastguard Worker     }
457*6236dae4SAndroid Build Coastguard Worker     case CF_QUERY_TIMER_APPCONNECT: {
458*6236dae4SAndroid Build Coastguard Worker       struct curltime *when = pres2;
459*6236dae4SAndroid Build Coastguard Worker       *when = cf_get_max_baller_time(cf, data, CF_QUERY_TIMER_APPCONNECT);
460*6236dae4SAndroid Build Coastguard Worker       return CURLE_OK;
461*6236dae4SAndroid Build Coastguard Worker     }
462*6236dae4SAndroid Build Coastguard Worker     case CF_QUERY_NEED_FLUSH: {
463*6236dae4SAndroid Build Coastguard Worker       if(cf_hc_baller_needs_flush(&ctx->h3_baller, data)
464*6236dae4SAndroid Build Coastguard Worker          || cf_hc_baller_needs_flush(&ctx->h21_baller, data)) {
465*6236dae4SAndroid Build Coastguard Worker         *pres1 = TRUE;
466*6236dae4SAndroid Build Coastguard Worker         return CURLE_OK;
467*6236dae4SAndroid Build Coastguard Worker       }
468*6236dae4SAndroid Build Coastguard Worker       break;
469*6236dae4SAndroid Build Coastguard Worker     }
470*6236dae4SAndroid Build Coastguard Worker     default:
471*6236dae4SAndroid Build Coastguard Worker       break;
472*6236dae4SAndroid Build Coastguard Worker     }
473*6236dae4SAndroid Build Coastguard Worker   }
474*6236dae4SAndroid Build Coastguard Worker   return cf->next ?
475*6236dae4SAndroid Build Coastguard Worker     cf->next->cft->query(cf->next, data, query, pres1, pres2) :
476*6236dae4SAndroid Build Coastguard Worker     CURLE_UNKNOWN_OPTION;
477*6236dae4SAndroid Build Coastguard Worker }
478*6236dae4SAndroid Build Coastguard Worker 
cf_hc_cntrl(struct Curl_cfilter * cf,struct Curl_easy * data,int event,int arg1,void * arg2)479*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_cntrl(struct Curl_cfilter *cf,
480*6236dae4SAndroid Build Coastguard Worker                             struct Curl_easy *data,
481*6236dae4SAndroid Build Coastguard Worker                             int event, int arg1, void *arg2)
482*6236dae4SAndroid Build Coastguard Worker {
483*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
484*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
485*6236dae4SAndroid Build Coastguard Worker 
486*6236dae4SAndroid Build Coastguard Worker   if(!cf->connected) {
487*6236dae4SAndroid Build Coastguard Worker     result = cf_hc_baller_cntrl(&ctx->h3_baller, data, event, arg1, arg2);
488*6236dae4SAndroid Build Coastguard Worker     if(!result || (result == CURLE_AGAIN))
489*6236dae4SAndroid Build Coastguard Worker       result = cf_hc_baller_cntrl(&ctx->h21_baller, data, event, arg1, arg2);
490*6236dae4SAndroid Build Coastguard Worker     if(result == CURLE_AGAIN)
491*6236dae4SAndroid Build Coastguard Worker       result = CURLE_OK;
492*6236dae4SAndroid Build Coastguard Worker   }
493*6236dae4SAndroid Build Coastguard Worker   return result;
494*6236dae4SAndroid Build Coastguard Worker }
495*6236dae4SAndroid Build Coastguard Worker 
cf_hc_close(struct Curl_cfilter * cf,struct Curl_easy * data)496*6236dae4SAndroid Build Coastguard Worker static void cf_hc_close(struct Curl_cfilter *cf, struct Curl_easy *data)
497*6236dae4SAndroid Build Coastguard Worker {
498*6236dae4SAndroid Build Coastguard Worker   CURL_TRC_CF(data, cf, "close");
499*6236dae4SAndroid Build Coastguard Worker   cf_hc_reset(cf, data);
500*6236dae4SAndroid Build Coastguard Worker   cf->connected = FALSE;
501*6236dae4SAndroid Build Coastguard Worker 
502*6236dae4SAndroid Build Coastguard Worker   if(cf->next) {
503*6236dae4SAndroid Build Coastguard Worker     cf->next->cft->do_close(cf->next, data);
504*6236dae4SAndroid Build Coastguard Worker     Curl_conn_cf_discard_chain(&cf->next, data);
505*6236dae4SAndroid Build Coastguard Worker   }
506*6236dae4SAndroid Build Coastguard Worker }
507*6236dae4SAndroid Build Coastguard Worker 
cf_hc_destroy(struct Curl_cfilter * cf,struct Curl_easy * data)508*6236dae4SAndroid Build Coastguard Worker static void cf_hc_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
509*6236dae4SAndroid Build Coastguard Worker {
510*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx = cf->ctx;
511*6236dae4SAndroid Build Coastguard Worker 
512*6236dae4SAndroid Build Coastguard Worker   (void)data;
513*6236dae4SAndroid Build Coastguard Worker   CURL_TRC_CF(data, cf, "destroy");
514*6236dae4SAndroid Build Coastguard Worker   cf_hc_reset(cf, data);
515*6236dae4SAndroid Build Coastguard Worker   Curl_safefree(ctx);
516*6236dae4SAndroid Build Coastguard Worker }
517*6236dae4SAndroid Build Coastguard Worker 
518*6236dae4SAndroid Build Coastguard Worker struct Curl_cftype Curl_cft_http_connect = {
519*6236dae4SAndroid Build Coastguard Worker   "HTTPS-CONNECT",
520*6236dae4SAndroid Build Coastguard Worker   0,
521*6236dae4SAndroid Build Coastguard Worker   CURL_LOG_LVL_NONE,
522*6236dae4SAndroid Build Coastguard Worker   cf_hc_destroy,
523*6236dae4SAndroid Build Coastguard Worker   cf_hc_connect,
524*6236dae4SAndroid Build Coastguard Worker   cf_hc_close,
525*6236dae4SAndroid Build Coastguard Worker   cf_hc_shutdown,
526*6236dae4SAndroid Build Coastguard Worker   Curl_cf_def_get_host,
527*6236dae4SAndroid Build Coastguard Worker   cf_hc_adjust_pollset,
528*6236dae4SAndroid Build Coastguard Worker   cf_hc_data_pending,
529*6236dae4SAndroid Build Coastguard Worker   Curl_cf_def_send,
530*6236dae4SAndroid Build Coastguard Worker   Curl_cf_def_recv,
531*6236dae4SAndroid Build Coastguard Worker   cf_hc_cntrl,
532*6236dae4SAndroid Build Coastguard Worker   Curl_cf_def_conn_is_alive,
533*6236dae4SAndroid Build Coastguard Worker   Curl_cf_def_conn_keep_alive,
534*6236dae4SAndroid Build Coastguard Worker   cf_hc_query,
535*6236dae4SAndroid Build Coastguard Worker };
536*6236dae4SAndroid Build Coastguard Worker 
cf_hc_create(struct Curl_cfilter ** pcf,struct Curl_easy * data,const struct Curl_dns_entry * remotehost,bool try_h3,bool try_h21)537*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_hc_create(struct Curl_cfilter **pcf,
538*6236dae4SAndroid Build Coastguard Worker                              struct Curl_easy *data,
539*6236dae4SAndroid Build Coastguard Worker                              const struct Curl_dns_entry *remotehost,
540*6236dae4SAndroid Build Coastguard Worker                              bool try_h3, bool try_h21)
541*6236dae4SAndroid Build Coastguard Worker {
542*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *cf = NULL;
543*6236dae4SAndroid Build Coastguard Worker   struct cf_hc_ctx *ctx;
544*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
545*6236dae4SAndroid Build Coastguard Worker 
546*6236dae4SAndroid Build Coastguard Worker   (void)data;
547*6236dae4SAndroid Build Coastguard Worker   ctx = calloc(1, sizeof(*ctx));
548*6236dae4SAndroid Build Coastguard Worker   if(!ctx) {
549*6236dae4SAndroid Build Coastguard Worker     result = CURLE_OUT_OF_MEMORY;
550*6236dae4SAndroid Build Coastguard Worker     goto out;
551*6236dae4SAndroid Build Coastguard Worker   }
552*6236dae4SAndroid Build Coastguard Worker   ctx->remotehost = remotehost;
553*6236dae4SAndroid Build Coastguard Worker   ctx->h3_baller.enabled = try_h3;
554*6236dae4SAndroid Build Coastguard Worker   ctx->h21_baller.enabled = try_h21;
555*6236dae4SAndroid Build Coastguard Worker 
556*6236dae4SAndroid Build Coastguard Worker   result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx);
557*6236dae4SAndroid Build Coastguard Worker   if(result)
558*6236dae4SAndroid Build Coastguard Worker     goto out;
559*6236dae4SAndroid Build Coastguard Worker   ctx = NULL;
560*6236dae4SAndroid Build Coastguard Worker   cf_hc_reset(cf, data);
561*6236dae4SAndroid Build Coastguard Worker 
562*6236dae4SAndroid Build Coastguard Worker out:
563*6236dae4SAndroid Build Coastguard Worker   *pcf = result ? NULL : cf;
564*6236dae4SAndroid Build Coastguard Worker   free(ctx);
565*6236dae4SAndroid Build Coastguard Worker   return result;
566*6236dae4SAndroid Build Coastguard Worker }
567*6236dae4SAndroid Build Coastguard Worker 
cf_http_connect_add(struct Curl_easy * data,struct connectdata * conn,int sockindex,const struct Curl_dns_entry * remotehost,bool try_h3,bool try_h21)568*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_http_connect_add(struct Curl_easy *data,
569*6236dae4SAndroid Build Coastguard Worker                                     struct connectdata *conn,
570*6236dae4SAndroid Build Coastguard Worker                                     int sockindex,
571*6236dae4SAndroid Build Coastguard Worker                                     const struct Curl_dns_entry *remotehost,
572*6236dae4SAndroid Build Coastguard Worker                                     bool try_h3, bool try_h21)
573*6236dae4SAndroid Build Coastguard Worker {
574*6236dae4SAndroid Build Coastguard Worker   struct Curl_cfilter *cf;
575*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
576*6236dae4SAndroid Build Coastguard Worker 
577*6236dae4SAndroid Build Coastguard Worker   DEBUGASSERT(data);
578*6236dae4SAndroid Build Coastguard Worker   result = cf_hc_create(&cf, data, remotehost, try_h3, try_h21);
579*6236dae4SAndroid Build Coastguard Worker   if(result)
580*6236dae4SAndroid Build Coastguard Worker     goto out;
581*6236dae4SAndroid Build Coastguard Worker   Curl_conn_cf_add(data, conn, sockindex, cf);
582*6236dae4SAndroid Build Coastguard Worker out:
583*6236dae4SAndroid Build Coastguard Worker   return result;
584*6236dae4SAndroid Build Coastguard Worker }
585*6236dae4SAndroid Build Coastguard Worker 
Curl_cf_https_setup(struct Curl_easy * data,struct connectdata * conn,int sockindex,const struct Curl_dns_entry * remotehost)586*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_cf_https_setup(struct Curl_easy *data,
587*6236dae4SAndroid Build Coastguard Worker                              struct connectdata *conn,
588*6236dae4SAndroid Build Coastguard Worker                              int sockindex,
589*6236dae4SAndroid Build Coastguard Worker                              const struct Curl_dns_entry *remotehost)
590*6236dae4SAndroid Build Coastguard Worker {
591*6236dae4SAndroid Build Coastguard Worker   bool try_h3 = FALSE, try_h21 = TRUE; /* defaults, for now */
592*6236dae4SAndroid Build Coastguard Worker   CURLcode result = CURLE_OK;
593*6236dae4SAndroid Build Coastguard Worker 
594*6236dae4SAndroid Build Coastguard Worker   (void)sockindex;
595*6236dae4SAndroid Build Coastguard Worker   (void)remotehost;
596*6236dae4SAndroid Build Coastguard Worker 
597*6236dae4SAndroid Build Coastguard Worker   if(!conn->bits.tls_enable_alpn)
598*6236dae4SAndroid Build Coastguard Worker     goto out;
599*6236dae4SAndroid Build Coastguard Worker 
600*6236dae4SAndroid Build Coastguard Worker   if(data->state.httpwant == CURL_HTTP_VERSION_3ONLY) {
601*6236dae4SAndroid Build Coastguard Worker     result = Curl_conn_may_http3(data, conn);
602*6236dae4SAndroid Build Coastguard Worker     if(result) /* cannot do it */
603*6236dae4SAndroid Build Coastguard Worker       goto out;
604*6236dae4SAndroid Build Coastguard Worker     try_h3 = TRUE;
605*6236dae4SAndroid Build Coastguard Worker     try_h21 = FALSE;
606*6236dae4SAndroid Build Coastguard Worker   }
607*6236dae4SAndroid Build Coastguard Worker   else if(data->state.httpwant >= CURL_HTTP_VERSION_3) {
608*6236dae4SAndroid Build Coastguard Worker     /* We assume that silently not even trying H3 is ok here */
609*6236dae4SAndroid Build Coastguard Worker     /* TODO: should we fail instead? */
610*6236dae4SAndroid Build Coastguard Worker     try_h3 = (Curl_conn_may_http3(data, conn) == CURLE_OK);
611*6236dae4SAndroid Build Coastguard Worker     try_h21 = TRUE;
612*6236dae4SAndroid Build Coastguard Worker   }
613*6236dae4SAndroid Build Coastguard Worker 
614*6236dae4SAndroid Build Coastguard Worker   result = cf_http_connect_add(data, conn, sockindex, remotehost,
615*6236dae4SAndroid Build Coastguard Worker                                try_h3, try_h21);
616*6236dae4SAndroid Build Coastguard Worker out:
617*6236dae4SAndroid Build Coastguard Worker   return result;
618*6236dae4SAndroid Build Coastguard Worker }
619*6236dae4SAndroid Build Coastguard Worker 
620*6236dae4SAndroid Build Coastguard Worker #endif /* !defined(CURL_DISABLE_HTTP) && !defined(USE_HYPER) */
621