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