curl_quiche.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at https://curl.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * SPDX-License-Identifier: curl
  22. *
  23. ***************************************************************************/
  24. #include "curl_setup.h"
  25. #ifdef USE_QUICHE
  26. #include <quiche.h>
  27. #include <openssl/err.h>
  28. #include <openssl/ssl.h>
  29. #include "urldata.h"
  30. #include "cfilters.h"
  31. #include "cf-socket.h"
  32. #include "sendf.h"
  33. #include "strdup.h"
  34. #include "rand.h"
  35. #include "strcase.h"
  36. #include "multiif.h"
  37. #include "connect.h"
  38. #include "progress.h"
  39. #include "strerror.h"
  40. #include "vquic.h"
  41. #include "vquic_int.h"
  42. #include "curl_quiche.h"
  43. #include "transfer.h"
  44. #include "h2h3.h"
  45. #include "vtls/openssl.h"
  46. #include "vtls/keylog.h"
  47. /* The last 3 #include files should be in this order */
  48. #include "curl_printf.h"
  49. #include "curl_memory.h"
  50. #include "memdebug.h"
  51. #define QUIC_MAX_STREAMS (256*1024)
  52. #define QUIC_MAX_DATA (1*1024*1024)
  53. #define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
  54. /* how many UDP packets to send max in one call */
  55. #define MAX_PKT_BURST 10
  56. #define MAX_UDP_PAYLOAD_SIZE 1452
  57. /*
  58. * Store quiche version info in this buffer.
  59. */
  60. void Curl_quiche_ver(char *p, size_t len)
  61. {
  62. (void)msnprintf(p, len, "quiche/%s", quiche_version());
  63. }
  64. static void keylog_callback(const SSL *ssl, const char *line)
  65. {
  66. (void)ssl;
  67. Curl_tls_keylog_write_line(line);
  68. }
  69. static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
  70. {
  71. SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
  72. SSL_CTX_set_alpn_protos(ssl_ctx,
  73. (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
  74. sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
  75. SSL_CTX_set_default_verify_paths(ssl_ctx);
  76. /* Open the file if a TLS or QUIC backend has not done this before. */
  77. Curl_tls_keylog_open();
  78. if(Curl_tls_keylog_enabled()) {
  79. SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
  80. }
  81. {
  82. struct connectdata *conn = data->conn;
  83. if(conn->ssl_config.verifypeer) {
  84. const char * const ssl_cafile = conn->ssl_config.CAfile;
  85. const char * const ssl_capath = conn->ssl_config.CApath;
  86. if(ssl_cafile || ssl_capath) {
  87. SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
  88. /* tell OpenSSL where to find CA certificates that are used to verify
  89. the server's certificate. */
  90. if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
  91. /* Fail if we insist on successfully verifying the server. */
  92. failf(data, "error setting certificate verify locations:"
  93. " CAfile: %s CApath: %s",
  94. ssl_cafile ? ssl_cafile : "none",
  95. ssl_capath ? ssl_capath : "none");
  96. return NULL;
  97. }
  98. infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
  99. infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
  100. }
  101. #ifdef CURL_CA_FALLBACK
  102. else {
  103. /* verifying the peer without any CA certificates won't work so
  104. use openssl's built-in default as fallback */
  105. SSL_CTX_set_default_verify_paths(ssl_ctx);
  106. }
  107. #endif
  108. }
  109. }
  110. return ssl_ctx;
  111. }
  112. struct quic_handshake {
  113. char *buf; /* pointer to the buffer */
  114. size_t alloclen; /* size of allocation */
  115. size_t len; /* size of content in buffer */
  116. size_t nread; /* how many bytes have been read */
  117. };
  118. struct h3_event_node {
  119. struct h3_event_node *next;
  120. quiche_h3_event *ev;
  121. };
  122. struct cf_quiche_ctx {
  123. struct cf_quic_ctx q;
  124. quiche_conn *qconn;
  125. quiche_config *cfg;
  126. quiche_h3_conn *h3c;
  127. quiche_h3_config *h3config;
  128. uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
  129. SSL_CTX *sslctx;
  130. SSL *ssl;
  131. struct curltime started_at; /* time the current attempt started */
  132. struct curltime handshake_at; /* time connect handshake finished */
  133. struct curltime first_byte_at; /* when first byte was recvd */
  134. struct curltime reconnect_at; /* time the next attempt should start */
  135. BIT(goaway); /* got GOAWAY from server */
  136. BIT(got_first_byte); /* if first byte was received */
  137. };
  138. #ifdef DEBUG_QUICHE
  139. static void quiche_debug_log(const char *line, void *argp)
  140. {
  141. (void)argp;
  142. fprintf(stderr, "%s\n", line);
  143. }
  144. #endif
  145. static void h3_clear_pending(struct Curl_easy *data)
  146. {
  147. struct HTTP *stream = data->req.p.http;
  148. if(stream->pending) {
  149. struct h3_event_node *node, *next;
  150. for(node = stream->pending; node; node = next) {
  151. next = node->next;
  152. quiche_h3_event_free(node->ev);
  153. free(node);
  154. }
  155. stream->pending = NULL;
  156. }
  157. }
  158. static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
  159. {
  160. if(ctx) {
  161. vquic_ctx_free(&ctx->q);
  162. if(ctx->qconn)
  163. quiche_conn_free(ctx->qconn);
  164. if(ctx->h3config)
  165. quiche_h3_config_free(ctx->h3config);
  166. if(ctx->h3c)
  167. quiche_h3_conn_free(ctx->h3c);
  168. if(ctx->cfg)
  169. quiche_config_free(ctx->cfg);
  170. memset(ctx, 0, sizeof(*ctx));
  171. }
  172. }
  173. static void notify_drain(struct Curl_cfilter *cf,
  174. struct Curl_easy *data)
  175. {
  176. (void)cf;
  177. data->state.drain = 1;
  178. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  179. }
  180. static CURLcode h3_add_event(struct Curl_cfilter *cf,
  181. struct Curl_easy *data,
  182. int64_t stream3_id, quiche_h3_event *ev)
  183. {
  184. struct Curl_easy *mdata;
  185. struct h3_event_node *node, **pnext;
  186. DEBUGASSERT(data->multi);
  187. for(mdata = data->multi->easyp; mdata; mdata = mdata->next) {
  188. if(mdata->req.p.http && mdata->req.p.http->stream3_id == stream3_id) {
  189. break;
  190. }
  191. }
  192. if(!mdata) {
  193. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] event discarded, easy handle "
  194. "not found", stream3_id));
  195. quiche_h3_event_free(ev);
  196. return CURLE_OK;
  197. }
  198. node = calloc(sizeof(*node), 1);
  199. if(!node) {
  200. quiche_h3_event_free(ev);
  201. return CURLE_OUT_OF_MEMORY;
  202. }
  203. node->ev = ev;
  204. /* append to process them in order of arrival */
  205. pnext = &mdata->req.p.http->pending;
  206. while(*pnext) {
  207. pnext = &((*pnext)->next);
  208. }
  209. *pnext = node;
  210. notify_drain(cf, mdata);
  211. return CURLE_OK;
  212. }
  213. struct h3h1header {
  214. char *dest;
  215. size_t destlen; /* left to use */
  216. size_t nlen; /* used */
  217. };
  218. static int cb_each_header(uint8_t *name, size_t name_len,
  219. uint8_t *value, size_t value_len,
  220. void *argp)
  221. {
  222. struct h3h1header *headers = (struct h3h1header *)argp;
  223. size_t olen = 0;
  224. if((name_len == 7) && !strncmp(H2H3_PSEUDO_STATUS, (char *)name, 7)) {
  225. msnprintf(headers->dest,
  226. headers->destlen, "HTTP/3 %.*s \r\n",
  227. (int) value_len, value);
  228. }
  229. else if(!headers->nlen) {
  230. return CURLE_HTTP3;
  231. }
  232. else {
  233. msnprintf(headers->dest,
  234. headers->destlen, "%.*s: %.*s\r\n",
  235. (int)name_len, name, (int) value_len, value);
  236. }
  237. olen = strlen(headers->dest);
  238. headers->destlen -= olen;
  239. headers->nlen += olen;
  240. headers->dest += olen;
  241. return 0;
  242. }
  243. static ssize_t cf_recv_body(struct Curl_cfilter *cf,
  244. struct Curl_easy *data,
  245. char *buf, size_t len,
  246. CURLcode *err)
  247. {
  248. struct cf_quiche_ctx *ctx = cf->ctx;
  249. struct HTTP *stream = data->req.p.http;
  250. ssize_t nread;
  251. size_t offset = 0;
  252. if(!stream->firstbody) {
  253. /* add a header-body separator CRLF */
  254. offset = 2;
  255. }
  256. nread = quiche_h3_recv_body(ctx->h3c, ctx->qconn, stream->stream3_id,
  257. (unsigned char *)buf + offset, len - offset);
  258. if(nread >= 0) {
  259. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][DATA] len=%zd",
  260. stream->stream3_id, nread));
  261. if(!stream->firstbody) {
  262. stream->firstbody = TRUE;
  263. buf[0] = '\r';
  264. buf[1] = '\n';
  265. nread += offset;
  266. }
  267. }
  268. else if(nread == -1) {
  269. *err = CURLE_AGAIN;
  270. stream->h3_recving_data = FALSE;
  271. }
  272. else {
  273. failf(data, "Error %zd in HTTP/3 response body for stream[%"PRId64"]",
  274. nread, stream->stream3_id);
  275. stream->closed = TRUE;
  276. stream->reset = TRUE;
  277. streamclose(cf->conn, "Reset of stream");
  278. stream->h3_recving_data = FALSE;
  279. nread = -1;
  280. *err = stream->h3_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
  281. }
  282. return nread;
  283. }
  284. #ifdef DEBUGBUILD
  285. static const char *cf_ev_name(quiche_h3_event *ev)
  286. {
  287. switch(quiche_h3_event_type(ev)) {
  288. case QUICHE_H3_EVENT_HEADERS:
  289. return "HEADERS";
  290. case QUICHE_H3_EVENT_DATA:
  291. return "DATA";
  292. case QUICHE_H3_EVENT_RESET:
  293. return "RESET";
  294. case QUICHE_H3_EVENT_FINISHED:
  295. return "FINISHED";
  296. case QUICHE_H3_EVENT_GOAWAY:
  297. return "GOAWAY";
  298. default:
  299. return "Unknown";
  300. }
  301. }
  302. #else
  303. #define cf_ev_name(x) ""
  304. #endif
  305. static ssize_t h3_process_event(struct Curl_cfilter *cf,
  306. struct Curl_easy *data,
  307. char *buf, size_t len,
  308. int64_t stream3_id,
  309. quiche_h3_event *ev,
  310. CURLcode *err)
  311. {
  312. struct HTTP *stream = data->req.p.http;
  313. ssize_t recvd = 0;
  314. int rc;
  315. struct h3h1header headers;
  316. DEBUGASSERT(stream3_id == stream->stream3_id);
  317. *err = CURLE_OK;
  318. switch(quiche_h3_event_type(ev)) {
  319. case QUICHE_H3_EVENT_HEADERS:
  320. stream->h3_got_header = TRUE;
  321. headers.dest = buf;
  322. headers.destlen = len;
  323. headers.nlen = 0;
  324. rc = quiche_h3_event_for_each_header(ev, cb_each_header, &headers);
  325. if(rc) {
  326. failf(data, "Error %d in HTTP/3 response header for stream[%"PRId64"]",
  327. rc, stream3_id);
  328. *err = CURLE_RECV_ERROR;
  329. recvd = -1;
  330. break;
  331. }
  332. recvd = headers.nlen;
  333. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][HEADERS] len=%zd",
  334. stream3_id, recvd));
  335. break;
  336. case QUICHE_H3_EVENT_DATA:
  337. DEBUGASSERT(!stream->closed);
  338. stream->h3_recving_data = TRUE;
  339. recvd = cf_recv_body(cf, data, buf, len, err);
  340. if(recvd < 0) {
  341. if(*err != CURLE_AGAIN)
  342. return -1;
  343. recvd = 0;
  344. }
  345. break;
  346. case QUICHE_H3_EVENT_RESET:
  347. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][RESET]", stream3_id));
  348. stream->closed = TRUE;
  349. stream->reset = TRUE;
  350. /* streamclose(cf->conn, "Reset of stream");*/
  351. stream->h3_recving_data = FALSE;
  352. break;
  353. case QUICHE_H3_EVENT_FINISHED:
  354. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][FINISHED]", stream3_id));
  355. stream->closed = TRUE;
  356. /* streamclose(cf->conn, "End of stream");*/
  357. stream->h3_recving_data = FALSE;
  358. break;
  359. case QUICHE_H3_EVENT_GOAWAY:
  360. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"][GOAWAY]", stream3_id));
  361. break;
  362. default:
  363. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv, unhandled event %d",
  364. stream3_id, quiche_h3_event_type(ev)));
  365. break;
  366. }
  367. return recvd;
  368. }
  369. static ssize_t h3_process_pending(struct Curl_cfilter *cf,
  370. struct Curl_easy *data,
  371. char *buf, size_t len,
  372. CURLcode *err)
  373. {
  374. struct HTTP *stream = data->req.p.http;
  375. struct h3_event_node *node = stream->pending, **pnext = &stream->pending;
  376. ssize_t recvd = 0, erecvd;
  377. *err = CURLE_OK;
  378. DEBUGASSERT(stream);
  379. while(node && len) {
  380. erecvd = h3_process_event(cf, data, buf, len,
  381. stream->stream3_id, node->ev, err);
  382. quiche_h3_event_free(node->ev);
  383. *pnext = node->next;
  384. free(node);
  385. node = *pnext;
  386. if(erecvd < 0) {
  387. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] process event -> %d",
  388. stream->stream3_id, *err));
  389. return erecvd;
  390. }
  391. recvd += erecvd;
  392. *err = CURLE_OK;
  393. buf += erecvd;
  394. len -= erecvd;
  395. }
  396. return recvd;
  397. }
  398. static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
  399. struct Curl_easy *data)
  400. {
  401. struct cf_quiche_ctx *ctx = cf->ctx;
  402. int64_t stream3_id = data->req.p.http? data->req.p.http->stream3_id : -1;
  403. uint8_t buf[65536];
  404. int bufsize = (int)sizeof(buf);
  405. struct sockaddr_storage remote_addr;
  406. socklen_t remote_addrlen;
  407. quiche_recv_info recv_info;
  408. ssize_t recvd, nread;
  409. ssize_t total = 0, pkts = 0;
  410. DEBUGASSERT(ctx->qconn);
  411. /* in case the timeout expired */
  412. quiche_conn_on_timeout(ctx->qconn);
  413. do {
  414. remote_addrlen = sizeof(remote_addr);
  415. while((recvd = recvfrom(ctx->q.sockfd, (char *)buf, bufsize, 0,
  416. (struct sockaddr *)&remote_addr,
  417. &remote_addrlen)) == -1 &&
  418. SOCKERRNO == EINTR)
  419. ;
  420. if(recvd < 0) {
  421. if((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)) {
  422. break;
  423. }
  424. if(SOCKERRNO == ECONNREFUSED) {
  425. const char *r_ip;
  426. int r_port;
  427. Curl_cf_socket_peek(cf->next, data, NULL, NULL,
  428. &r_ip, &r_port, NULL, NULL);
  429. failf(data, "quiche: connection to %s:%u refused",
  430. r_ip, r_port);
  431. return CURLE_COULDNT_CONNECT;
  432. }
  433. failf(data, "quiche: recvfrom() unexpectedly returned %zd "
  434. "(errno: %d, socket %d)", recvd, SOCKERRNO, ctx->q.sockfd);
  435. return CURLE_RECV_ERROR;
  436. }
  437. total += recvd;
  438. ++pkts;
  439. if(recvd > 0 && !ctx->got_first_byte) {
  440. ctx->first_byte_at = Curl_now();
  441. ctx->got_first_byte = TRUE;
  442. }
  443. recv_info.from = (struct sockaddr *) &remote_addr;
  444. recv_info.from_len = remote_addrlen;
  445. recv_info.to = (struct sockaddr *) &ctx->q.local_addr;
  446. recv_info.to_len = ctx->q.local_addrlen;
  447. nread = quiche_conn_recv(ctx->qconn, buf, recvd, &recv_info);
  448. if(nread < 0) {
  449. if(QUICHE_ERR_DONE == nread) {
  450. DEBUGF(LOG_CF(data, cf, "ingress, quiche is DONE"));
  451. return CURLE_OK;
  452. }
  453. else if(QUICHE_ERR_TLS_FAIL == nread) {
  454. long verify_ok = SSL_get_verify_result(ctx->ssl);
  455. if(verify_ok != X509_V_OK) {
  456. failf(data, "SSL certificate problem: %s",
  457. X509_verify_cert_error_string(verify_ok));
  458. return CURLE_PEER_FAILED_VERIFICATION;
  459. }
  460. }
  461. else {
  462. failf(data, "quiche_conn_recv() == %zd", nread);
  463. return CURLE_RECV_ERROR;
  464. }
  465. }
  466. else if(nread < recvd) {
  467. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] ingress, quiche only "
  468. "accepted %zd/%zd bytes",
  469. stream3_id, nread, recvd));
  470. }
  471. } while(pkts < 1000); /* arbitrary */
  472. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] ingress, recvd %zd bytes "
  473. "in %zd packets", stream3_id, total, pkts));
  474. return CURLE_OK;
  475. }
  476. /*
  477. * flush_egress drains the buffers and sends off data.
  478. * Calls failf() on errors.
  479. */
  480. static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
  481. struct Curl_easy *data)
  482. {
  483. struct cf_quiche_ctx *ctx = cf->ctx;
  484. int64_t stream3_id = data->req.p.http? data->req.p.http->stream3_id : -1;
  485. quiche_send_info send_info;
  486. ssize_t outlen, total_len = 0;
  487. size_t max_udp_payload_size =
  488. quiche_conn_max_send_udp_payload_size(ctx->qconn);
  489. size_t gsolen = max_udp_payload_size;
  490. size_t sent, pktcnt = 0;
  491. CURLcode result;
  492. int64_t timeout_ns;
  493. ctx->q.no_gso = TRUE;
  494. if(ctx->q.num_blocked_pkt) {
  495. result = vquic_send_blocked_pkt(cf, data, &ctx->q);
  496. if(result) {
  497. if(result == CURLE_AGAIN) {
  498. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] egress, still not "
  499. "able to send blocked packet", stream3_id));
  500. Curl_expire(data, 1, EXPIRE_QUIC);
  501. return CURLE_OK;
  502. }
  503. goto out;
  504. }
  505. }
  506. for(;;) {
  507. outlen = quiche_conn_send(ctx->qconn, ctx->q.pktbuf, max_udp_payload_size,
  508. &send_info);
  509. if(outlen == QUICHE_ERR_DONE) {
  510. result = CURLE_OK;
  511. goto out;
  512. }
  513. if(outlen < 0) {
  514. failf(data, "quiche_conn_send returned %zd", outlen);
  515. result = CURLE_SEND_ERROR;
  516. goto out;
  517. }
  518. /* send the pktbuf *before* the last addition */
  519. result = vquic_send_packet(cf, data, &ctx->q, ctx->q.pktbuf,
  520. outlen, gsolen, &sent);
  521. ++pktcnt;
  522. total_len += outlen;
  523. if(result) {
  524. if(result == CURLE_AGAIN) {
  525. /* blocked, add the pktbuf *before* and *at* the last addition
  526. * separately to the blocked packages */
  527. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] egress, pushing blocked "
  528. "packet with %zd bytes", stream3_id, outlen));
  529. vquic_push_blocked_pkt(cf, &ctx->q, ctx->q.pktbuf, outlen, gsolen);
  530. Curl_expire(data, 1, EXPIRE_QUIC);
  531. return CURLE_OK;
  532. }
  533. goto out;
  534. }
  535. }
  536. out:
  537. timeout_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
  538. if(timeout_ns % 1000000)
  539. timeout_ns += 1000000;
  540. /* expire resolution is milliseconds */
  541. Curl_expire(data, (timeout_ns / 1000000), EXPIRE_QUIC);
  542. if(pktcnt)
  543. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] egress, sent %zd packets "
  544. "with %zd bytes", stream3_id, pktcnt, total_len));
  545. return result;
  546. }
  547. static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
  548. struct Curl_easy *data,
  549. CURLcode *err)
  550. {
  551. struct HTTP *stream = data->req.p.http;
  552. ssize_t nread = -1;
  553. if(stream->reset) {
  554. failf(data,
  555. "HTTP/3 stream %" PRId64 " reset by server", stream->stream3_id);
  556. *err = stream->h3_got_header? CURLE_PARTIAL_FILE : CURLE_RECV_ERROR;
  557. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, was reset -> %d",
  558. stream->stream3_id, *err));
  559. goto out;
  560. }
  561. if(!stream->h3_got_header) {
  562. failf(data,
  563. "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
  564. " all response header fields, treated as error",
  565. stream->stream3_id);
  566. /* *err = CURLE_PARTIAL_FILE; */
  567. *err = CURLE_RECV_ERROR;
  568. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed incomplete"
  569. " -> %d", stream->stream3_id, *err));
  570. goto out;
  571. }
  572. else {
  573. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_recv, closed ok"
  574. " -> %d", stream->stream3_id, *err));
  575. }
  576. *err = CURLE_OK;
  577. nread = 0;
  578. out:
  579. return nread;
  580. }
  581. static CURLcode cf_poll_events(struct Curl_cfilter *cf,
  582. struct Curl_easy *data)
  583. {
  584. struct cf_quiche_ctx *ctx = cf->ctx;
  585. struct HTTP *stream = data->req.p.http;
  586. quiche_h3_event *ev;
  587. /* Take in the events and distribute them to the transfers. */
  588. while(1) {
  589. int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev);
  590. if(stream3_id < 0) {
  591. /* nothing more to do */
  592. break;
  593. }
  594. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] recv, queue event %s "
  595. "for [h3sid=%"PRId64"]",
  596. stream? stream->stream3_id : -1, cf_ev_name(ev),
  597. stream3_id));
  598. if(h3_add_event(cf, data, stream3_id, ev) != CURLE_OK) {
  599. return CURLE_OUT_OF_MEMORY;
  600. }
  601. }
  602. return CURLE_OK;
  603. }
  604. static ssize_t cf_recv_transfer_data(struct Curl_cfilter *cf,
  605. struct Curl_easy *data,
  606. char *buf, size_t len,
  607. CURLcode *err)
  608. {
  609. struct HTTP *stream = data->req.p.http;
  610. ssize_t recvd = -1;
  611. size_t offset = 0;
  612. if(stream->h3_recving_data) {
  613. /* try receiving body first */
  614. recvd = cf_recv_body(cf, data, buf, len, err);
  615. if(recvd < 0) {
  616. if(*err != CURLE_AGAIN)
  617. return -1;
  618. recvd = 0;
  619. }
  620. if(recvd > 0) {
  621. offset = recvd;
  622. }
  623. }
  624. if(offset < len && stream->pending) {
  625. /* process any pending events for `data` first. if there are,
  626. * return so the transfer can handle those. We do not want to
  627. * progress ingress while events are pending here. */
  628. recvd = h3_process_pending(cf, data, buf + offset, len - offset, err);
  629. if(recvd < 0) {
  630. if(*err != CURLE_AGAIN)
  631. return -1;
  632. recvd = 0;
  633. }
  634. if(recvd > 0) {
  635. offset += recvd;
  636. }
  637. }
  638. if(offset) {
  639. *err = CURLE_OK;
  640. return offset;
  641. }
  642. *err = CURLE_AGAIN;
  643. return 0;
  644. }
  645. static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  646. char *buf, size_t len, CURLcode *err)
  647. {
  648. struct HTTP *stream = data->req.p.http;
  649. ssize_t recvd = -1;
  650. *err = CURLE_AGAIN;
  651. recvd = cf_recv_transfer_data(cf, data, buf, len, err);
  652. if(recvd)
  653. goto out;
  654. if(stream->closed) {
  655. recvd = recv_closed_stream(cf, data, err);
  656. goto out;
  657. }
  658. /* we did get nothing from the quiche buffers or pending events.
  659. * Take in more data from the connection, any error is fatal */
  660. if(cf_process_ingress(cf, data)) {
  661. DEBUGF(LOG_CF(data, cf, "h3_stream_recv returns on ingress"));
  662. *err = CURLE_RECV_ERROR;
  663. recvd = -1;
  664. goto out;
  665. }
  666. /* poll quiche and distribute the events to the transfers */
  667. *err = cf_poll_events(cf, data);
  668. if(*err) {
  669. recvd = -1;
  670. goto out;
  671. }
  672. /* try to receive again for this transfer */
  673. recvd = cf_recv_transfer_data(cf, data, buf, len, err);
  674. if(recvd)
  675. goto out;
  676. if(stream->closed) {
  677. recvd = recv_closed_stream(cf, data, err);
  678. goto out;
  679. }
  680. recvd = -1;
  681. *err = CURLE_AGAIN;
  682. data->state.drain = 0;
  683. out:
  684. if(cf_flush_egress(cf, data)) {
  685. DEBUGF(LOG_CF(data, cf, "cf_recv, flush egress failed"));
  686. *err = CURLE_SEND_ERROR;
  687. return -1;
  688. }
  689. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] cf_recv -> %zd, err=%d",
  690. stream->stream3_id, recvd, *err));
  691. if(recvd > 0)
  692. notify_drain(cf, data);
  693. return recvd;
  694. }
  695. /* Index where :authority header field will appear in request header
  696. field list. */
  697. #define AUTHORITY_DST_IDX 3
  698. static CURLcode cf_http_request(struct Curl_cfilter *cf,
  699. struct Curl_easy *data,
  700. const void *mem,
  701. size_t len)
  702. {
  703. struct cf_quiche_ctx *ctx = cf->ctx;
  704. struct HTTP *stream = data->req.p.http;
  705. size_t nheader;
  706. int64_t stream3_id;
  707. quiche_h3_header *nva = NULL;
  708. CURLcode result = CURLE_OK;
  709. struct h2h3req *hreq = NULL;
  710. stream->h3req = TRUE; /* send off! */
  711. stream->closed = FALSE;
  712. stream->reset = FALSE;
  713. result = Curl_pseudo_headers(data, mem, len, NULL, &hreq);
  714. if(result)
  715. goto fail;
  716. nheader = hreq->entries;
  717. nva = malloc(sizeof(quiche_h3_header) * nheader);
  718. if(!nva) {
  719. result = CURLE_OUT_OF_MEMORY;
  720. goto fail;
  721. }
  722. else {
  723. unsigned int i;
  724. for(i = 0; i < nheader; i++) {
  725. nva[i].name = (unsigned char *)hreq->header[i].name;
  726. nva[i].name_len = hreq->header[i].namelen;
  727. nva[i].value = (unsigned char *)hreq->header[i].value;
  728. nva[i].value_len = hreq->header[i].valuelen;
  729. }
  730. }
  731. switch(data->state.httpreq) {
  732. case HTTPREQ_POST:
  733. case HTTPREQ_POST_FORM:
  734. case HTTPREQ_POST_MIME:
  735. case HTTPREQ_PUT:
  736. if(data->state.infilesize != -1)
  737. stream->upload_left = data->state.infilesize;
  738. else
  739. /* data sending without specifying the data amount up front */
  740. stream->upload_left = -1; /* unknown, but not zero */
  741. stream->upload_done = !stream->upload_left;
  742. stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
  743. stream->upload_done);
  744. break;
  745. default:
  746. stream->upload_left = 0;
  747. stream->upload_done = TRUE;
  748. stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
  749. TRUE);
  750. break;
  751. }
  752. Curl_safefree(nva);
  753. if(stream3_id < 0) {
  754. if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
  755. DEBUGF(LOG_CF(data, cf, "send_request(%s, body_len=%ld) rejected "
  756. "with H3_ERR_STREAM_BLOCKED",
  757. data->state.url, (long)stream->upload_left));
  758. result = CURLE_AGAIN;
  759. goto fail;
  760. }
  761. else {
  762. DEBUGF(LOG_CF(data, cf, "send_request(%s, body_len=%ld) -> %" PRId64,
  763. data->state.url, (long)stream->upload_left, stream3_id));
  764. }
  765. result = CURLE_SEND_ERROR;
  766. goto fail;
  767. }
  768. stream->stream3_id = stream3_id;
  769. infof(data, "Using HTTP/3 Stream ID: %" PRId64 " (easy handle %p)",
  770. stream3_id, (void *)data);
  771. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] opened for %s",
  772. stream3_id, data->state.url));
  773. Curl_pseudo_free(hreq);
  774. return CURLE_OK;
  775. fail:
  776. free(nva);
  777. Curl_pseudo_free(hreq);
  778. return result;
  779. }
  780. static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  781. const void *buf, size_t len, CURLcode *err)
  782. {
  783. struct cf_quiche_ctx *ctx = cf->ctx;
  784. struct HTTP *stream = data->req.p.http;
  785. ssize_t nwritten;
  786. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] cf_send(len=%zu) start",
  787. stream->h3req? stream->stream3_id : -1, len));
  788. *err = cf_process_ingress(cf, data);
  789. if(*err)
  790. return -1;
  791. if(!stream->h3req) {
  792. CURLcode result = cf_http_request(cf, data, buf, len);
  793. if(result) {
  794. *err = result;
  795. return -1;
  796. }
  797. nwritten = len;
  798. }
  799. else {
  800. nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->stream3_id,
  801. (uint8_t *)buf, len, FALSE);
  802. DEBUGF(LOG_CF(data, cf, "[h3sid=%" PRId64 "] send body(len=%zu) -> %zd",
  803. stream->stream3_id, len, nwritten));
  804. if(nwritten == QUICHE_H3_ERR_DONE) {
  805. /* no error, nothing to do (flow control?) */
  806. *err = CURLE_AGAIN;
  807. nwritten = -1;
  808. }
  809. else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
  810. DEBUGF(LOG_CF(data, cf, "send_body(len=%zu) -> exceeds size", len));
  811. *err = CURLE_SEND_ERROR;
  812. nwritten = -1;
  813. }
  814. else if(nwritten < 0) {
  815. DEBUGF(LOG_CF(data, cf, "send_body(len=%zu) -> SEND_ERROR", len));
  816. *err = CURLE_SEND_ERROR;
  817. nwritten = -1;
  818. }
  819. else {
  820. *err = CURLE_OK;
  821. }
  822. }
  823. if(cf_flush_egress(cf, data)) {
  824. *err = CURLE_SEND_ERROR;
  825. return -1;
  826. }
  827. return nwritten;
  828. }
  829. static bool stream_is_writeable(struct Curl_cfilter *cf,
  830. struct Curl_easy *data)
  831. {
  832. struct cf_quiche_ctx *ctx = cf->ctx;
  833. struct HTTP *stream = data->req.p.http;
  834. /* surely, there must be a better way */
  835. quiche_stream_iter *qiter = quiche_conn_writable(ctx->qconn);
  836. if(qiter) {
  837. uint64_t stream_id;
  838. while(quiche_stream_iter_next(qiter, &stream_id)) {
  839. if(stream_id == (uint64_t)stream->stream3_id)
  840. return TRUE;
  841. }
  842. quiche_stream_iter_free(qiter);
  843. }
  844. return FALSE;
  845. }
  846. static int cf_quiche_get_select_socks(struct Curl_cfilter *cf,
  847. struct Curl_easy *data,
  848. curl_socket_t *socks)
  849. {
  850. struct cf_quiche_ctx *ctx = cf->ctx;
  851. struct SingleRequest *k = &data->req;
  852. int rv = GETSOCK_BLANK;
  853. socks[0] = ctx->q.sockfd;
  854. /* in an HTTP/3 connection we can basically always get a frame so we should
  855. always be ready for one */
  856. rv |= GETSOCK_READSOCK(0);
  857. /* we're still uploading or the HTTP/3 layer wants to send data */
  858. if(((k->keepon & KEEP_SENDBITS) == KEEP_SEND)
  859. && stream_is_writeable(cf, data))
  860. rv |= GETSOCK_WRITESOCK(0);
  861. return rv;
  862. }
  863. /*
  864. * Called from transfer.c:data_pending to know if we should keep looping
  865. * to receive more data from the connection.
  866. */
  867. static bool cf_quiche_data_pending(struct Curl_cfilter *cf,
  868. const struct Curl_easy *data)
  869. {
  870. struct HTTP *stream = data->req.p.http;
  871. if(stream->pending) {
  872. DEBUGF(LOG_CF((struct Curl_easy *)data, cf,
  873. "[h3sid=%"PRId64"] has event pending", stream->stream3_id));
  874. return TRUE;
  875. }
  876. if(stream->h3_recving_data) {
  877. DEBUGF(LOG_CF((struct Curl_easy *)data, cf,
  878. "[h3sid=%"PRId64"] is receiving DATA", stream->stream3_id));
  879. return TRUE;
  880. }
  881. if(data->state.drain) {
  882. DEBUGF(LOG_CF((struct Curl_easy *)data, cf,
  883. "[h3sid=%"PRId64"] is draining", stream->stream3_id));
  884. return TRUE;
  885. }
  886. return FALSE;
  887. }
  888. static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
  889. struct Curl_easy *data,
  890. int event, int arg1, void *arg2)
  891. {
  892. struct cf_quiche_ctx *ctx = cf->ctx;
  893. CURLcode result = CURLE_OK;
  894. (void)arg1;
  895. (void)arg2;
  896. switch(event) {
  897. case CF_CTRL_DATA_DONE: {
  898. struct HTTP *stream = data->req.p.http;
  899. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] easy handle is %s",
  900. stream->stream3_id, arg1? "cancelled" : "done"));
  901. h3_clear_pending(data);
  902. break;
  903. }
  904. case CF_CTRL_DATA_DONE_SEND: {
  905. struct HTTP *stream = data->req.p.http;
  906. ssize_t sent;
  907. stream->upload_done = TRUE;
  908. sent = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->stream3_id,
  909. NULL, 0, TRUE);
  910. DEBUGF(LOG_CF(data, cf, "[h3sid=%"PRId64"] send_body FINISHED",
  911. stream->stream3_id));
  912. if(sent < 0)
  913. return CURLE_SEND_ERROR;
  914. break;
  915. }
  916. case CF_CTRL_DATA_IDLE:
  917. /* anything to do? */
  918. break;
  919. default:
  920. break;
  921. }
  922. return result;
  923. }
  924. static CURLcode cf_verify_peer(struct Curl_cfilter *cf,
  925. struct Curl_easy *data)
  926. {
  927. struct cf_quiche_ctx *ctx = cf->ctx;
  928. CURLcode result = CURLE_OK;
  929. cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  930. cf->conn->httpversion = 30;
  931. cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  932. if(cf->conn->ssl_config.verifyhost) {
  933. X509 *server_cert;
  934. server_cert = SSL_get_peer_certificate(ctx->ssl);
  935. if(!server_cert) {
  936. result = CURLE_PEER_FAILED_VERIFICATION;
  937. goto out;
  938. }
  939. result = Curl_ossl_verifyhost(data, cf->conn, server_cert);
  940. X509_free(server_cert);
  941. if(result)
  942. goto out;
  943. }
  944. else
  945. DEBUGF(LOG_CF(data, cf, "Skipped certificate verification"));
  946. ctx->h3config = quiche_h3_config_new();
  947. if(!ctx->h3config) {
  948. result = CURLE_OUT_OF_MEMORY;
  949. goto out;
  950. }
  951. /* Create a new HTTP/3 connection on the QUIC connection. */
  952. ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
  953. if(!ctx->h3c) {
  954. result = CURLE_OUT_OF_MEMORY;
  955. goto out;
  956. }
  957. if(data->set.ssl.certinfo)
  958. /* asked to gather certificate info */
  959. (void)Curl_ossl_certchain(data, ctx->ssl);
  960. out:
  961. if(result) {
  962. if(ctx->h3config) {
  963. quiche_h3_config_free(ctx->h3config);
  964. ctx->h3config = NULL;
  965. }
  966. if(ctx->h3c) {
  967. quiche_h3_conn_free(ctx->h3c);
  968. ctx->h3c = NULL;
  969. }
  970. }
  971. return result;
  972. }
  973. static CURLcode cf_connect_start(struct Curl_cfilter *cf,
  974. struct Curl_easy *data)
  975. {
  976. struct cf_quiche_ctx *ctx = cf->ctx;
  977. int rv;
  978. CURLcode result;
  979. const struct Curl_sockaddr_ex *sockaddr;
  980. DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD);
  981. #ifdef DEBUG_QUICHE
  982. /* initialize debug log callback only once */
  983. static int debug_log_init = 0;
  984. if(!debug_log_init) {
  985. quiche_enable_debug_logging(quiche_debug_log, NULL);
  986. debug_log_init = 1;
  987. }
  988. #endif
  989. result = vquic_ctx_init(&ctx->q, MAX_UDP_PAYLOAD_SIZE * MAX_PKT_BURST);
  990. if(result)
  991. return result;
  992. ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
  993. if(!ctx->cfg) {
  994. failf(data, "can't create quiche config");
  995. return CURLE_FAILED_INIT;
  996. }
  997. quiche_config_set_max_idle_timeout(ctx->cfg, QUIC_IDLE_TIMEOUT);
  998. quiche_config_set_initial_max_data(ctx->cfg, QUIC_MAX_DATA);
  999. quiche_config_set_initial_max_stream_data_bidi_local(
  1000. ctx->cfg, QUIC_MAX_DATA);
  1001. quiche_config_set_initial_max_stream_data_bidi_remote(
  1002. ctx->cfg, QUIC_MAX_DATA);
  1003. quiche_config_set_initial_max_stream_data_uni(ctx->cfg, QUIC_MAX_DATA);
  1004. quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
  1005. quiche_config_set_initial_max_streams_uni(ctx->cfg, QUIC_MAX_STREAMS);
  1006. quiche_config_set_application_protos(ctx->cfg,
  1007. (uint8_t *)
  1008. QUICHE_H3_APPLICATION_PROTOCOL,
  1009. sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
  1010. - 1);
  1011. DEBUGASSERT(!ctx->ssl);
  1012. DEBUGASSERT(!ctx->sslctx);
  1013. ctx->sslctx = quic_ssl_ctx(data);
  1014. if(!ctx->sslctx)
  1015. return CURLE_QUIC_CONNECT_ERROR;
  1016. ctx->ssl = SSL_new(ctx->sslctx);
  1017. if(!ctx->ssl)
  1018. return CURLE_QUIC_CONNECT_ERROR;
  1019. SSL_set_app_data(ctx->ssl, cf);
  1020. SSL_set_tlsext_host_name(ctx->ssl, cf->conn->host.name);
  1021. result = Curl_rand(data, ctx->scid, sizeof(ctx->scid));
  1022. if(result)
  1023. return result;
  1024. Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
  1025. &sockaddr, NULL, NULL, NULL, NULL);
  1026. ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
  1027. rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
  1028. &ctx->q.local_addrlen);
  1029. if(rv == -1)
  1030. return CURLE_QUIC_CONNECT_ERROR;
  1031. ctx->qconn = quiche_conn_new_with_tls((const uint8_t *)ctx->scid,
  1032. sizeof(ctx->scid), NULL, 0,
  1033. (struct sockaddr *)&ctx->q.local_addr,
  1034. ctx->q.local_addrlen,
  1035. &sockaddr->sa_addr, sockaddr->addrlen,
  1036. ctx->cfg, ctx->ssl, false);
  1037. if(!ctx->qconn) {
  1038. failf(data, "can't create quiche connection");
  1039. return CURLE_OUT_OF_MEMORY;
  1040. }
  1041. /* Known to not work on Windows */
  1042. #if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
  1043. {
  1044. int qfd;
  1045. (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
  1046. if(qfd != -1)
  1047. quiche_conn_set_qlog_fd(ctx->qconn, qfd,
  1048. "qlog title", "curl qlog");
  1049. }
  1050. #endif
  1051. result = cf_flush_egress(cf, data);
  1052. if(result)
  1053. return result;
  1054. {
  1055. unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
  1056. unsigned alpn_len, offset = 0;
  1057. /* Replace each ALPN length prefix by a comma. */
  1058. while(offset < sizeof(alpn_protocols) - 1) {
  1059. alpn_len = alpn_protocols[offset];
  1060. alpn_protocols[offset] = ',';
  1061. offset += 1 + alpn_len;
  1062. }
  1063. DEBUGF(LOG_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
  1064. alpn_protocols + 1));
  1065. }
  1066. return CURLE_OK;
  1067. }
  1068. static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
  1069. struct Curl_easy *data,
  1070. bool blocking, bool *done)
  1071. {
  1072. struct cf_quiche_ctx *ctx = cf->ctx;
  1073. CURLcode result = CURLE_OK;
  1074. struct curltime now;
  1075. if(cf->connected) {
  1076. *done = TRUE;
  1077. return CURLE_OK;
  1078. }
  1079. /* Connect the UDP filter first */
  1080. if(!cf->next->connected) {
  1081. result = Curl_conn_cf_connect(cf->next, data, blocking, done);
  1082. if(result || !*done)
  1083. return result;
  1084. }
  1085. *done = FALSE;
  1086. now = Curl_now();
  1087. if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
  1088. /* Not time yet to attempt the next connect */
  1089. DEBUGF(LOG_CF(data, cf, "waiting for reconnect time"));
  1090. goto out;
  1091. }
  1092. if(!ctx->qconn) {
  1093. result = cf_connect_start(cf, data);
  1094. if(result)
  1095. goto out;
  1096. ctx->started_at = now;
  1097. result = cf_flush_egress(cf, data);
  1098. /* we do not expect to be able to recv anything yet */
  1099. goto out;
  1100. }
  1101. result = cf_process_ingress(cf, data);
  1102. if(result)
  1103. goto out;
  1104. result = cf_flush_egress(cf, data);
  1105. if(result)
  1106. goto out;
  1107. if(quiche_conn_is_established(ctx->qconn)) {
  1108. DEBUGF(LOG_CF(data, cf, "handshake complete after %dms",
  1109. (int)Curl_timediff(now, ctx->started_at)));
  1110. ctx->handshake_at = now;
  1111. result = cf_verify_peer(cf, data);
  1112. if(!result) {
  1113. DEBUGF(LOG_CF(data, cf, "peer verified"));
  1114. cf->connected = TRUE;
  1115. cf->conn->alpn = CURL_HTTP_VERSION_3;
  1116. *done = TRUE;
  1117. connkeep(cf->conn, "HTTP/3 default");
  1118. }
  1119. }
  1120. else if(quiche_conn_is_draining(ctx->qconn)) {
  1121. /* When a QUIC server instance is shutting down, it may send us a
  1122. * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
  1123. * state.
  1124. * This may be a stopping of the service or it may be that the server
  1125. * is reloading and a new instance will start serving soon.
  1126. * In any case, we tear down our socket and start over with a new one.
  1127. * We re-open the underlying UDP cf right now, but do not start
  1128. * connecting until called again.
  1129. */
  1130. int reconn_delay_ms = 200;
  1131. DEBUGF(LOG_CF(data, cf, "connect, remote closed, reconnect after %dms",
  1132. reconn_delay_ms));
  1133. Curl_conn_cf_close(cf->next, data);
  1134. cf_quiche_ctx_clear(ctx);
  1135. result = Curl_conn_cf_connect(cf->next, data, FALSE, done);
  1136. if(!result && *done) {
  1137. *done = FALSE;
  1138. ctx->reconnect_at = Curl_now();
  1139. ctx->reconnect_at.tv_usec += reconn_delay_ms * 1000;
  1140. Curl_expire(data, reconn_delay_ms, EXPIRE_QUIC);
  1141. result = CURLE_OK;
  1142. }
  1143. }
  1144. out:
  1145. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  1146. if(result && result != CURLE_AGAIN) {
  1147. const char *r_ip;
  1148. int r_port;
  1149. Curl_cf_socket_peek(cf->next, data, NULL, NULL,
  1150. &r_ip, &r_port, NULL, NULL);
  1151. infof(data, "connect to %s port %u failed: %s",
  1152. r_ip, r_port, curl_easy_strerror(result));
  1153. }
  1154. #endif
  1155. return result;
  1156. }
  1157. static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  1158. {
  1159. struct cf_quiche_ctx *ctx = cf->ctx;
  1160. (void)data;
  1161. if(ctx) {
  1162. if(ctx->qconn) {
  1163. (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
  1164. /* flushing the egress is not a failsafe way to deliver all the
  1165. outstanding packets, but we also don't want to get stuck here... */
  1166. (void)cf_flush_egress(cf, data);
  1167. }
  1168. cf_quiche_ctx_clear(ctx);
  1169. }
  1170. }
  1171. static void cf_quiche_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
  1172. {
  1173. struct cf_quiche_ctx *ctx = cf->ctx;
  1174. (void)data;
  1175. cf_quiche_ctx_clear(ctx);
  1176. free(ctx);
  1177. cf->ctx = NULL;
  1178. }
  1179. static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
  1180. struct Curl_easy *data,
  1181. int query, int *pres1, void *pres2)
  1182. {
  1183. struct cf_quiche_ctx *ctx = cf->ctx;
  1184. switch(query) {
  1185. case CF_QUERY_MAX_CONCURRENT: {
  1186. uint64_t max_streams = CONN_INUSE(cf->conn);
  1187. if(!ctx->goaway) {
  1188. max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
  1189. }
  1190. *pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
  1191. DEBUGF(LOG_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1));
  1192. return CURLE_OK;
  1193. }
  1194. case CF_QUERY_CONNECT_REPLY_MS:
  1195. if(ctx->got_first_byte) {
  1196. timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at);
  1197. *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
  1198. }
  1199. else
  1200. *pres1 = -1;
  1201. return CURLE_OK;
  1202. case CF_QUERY_TIMER_CONNECT: {
  1203. struct curltime *when = pres2;
  1204. if(ctx->got_first_byte)
  1205. *when = ctx->first_byte_at;
  1206. return CURLE_OK;
  1207. }
  1208. case CF_QUERY_TIMER_APPCONNECT: {
  1209. struct curltime *when = pres2;
  1210. if(cf->connected)
  1211. *when = ctx->handshake_at;
  1212. return CURLE_OK;
  1213. }
  1214. default:
  1215. break;
  1216. }
  1217. return cf->next?
  1218. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  1219. CURLE_UNKNOWN_OPTION;
  1220. }
  1221. static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
  1222. struct Curl_easy *data,
  1223. bool *input_pending)
  1224. {
  1225. bool alive = TRUE;
  1226. *input_pending = FALSE;
  1227. if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
  1228. return FALSE;
  1229. if(*input_pending) {
  1230. /* This happens before we've sent off a request and the connection is
  1231. not in use by any other transfer, there shouldn't be any data here,
  1232. only "protocol frames" */
  1233. *input_pending = FALSE;
  1234. Curl_attach_connection(data, cf->conn);
  1235. if(cf_process_ingress(cf, data))
  1236. alive = FALSE;
  1237. else {
  1238. alive = TRUE;
  1239. }
  1240. Curl_detach_connection(data);
  1241. }
  1242. return alive;
  1243. }
  1244. struct Curl_cftype Curl_cft_http3 = {
  1245. "HTTP/3",
  1246. CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
  1247. 0,
  1248. cf_quiche_destroy,
  1249. cf_quiche_connect,
  1250. cf_quiche_close,
  1251. Curl_cf_def_get_host,
  1252. cf_quiche_get_select_socks,
  1253. cf_quiche_data_pending,
  1254. cf_quiche_send,
  1255. cf_quiche_recv,
  1256. cf_quiche_data_event,
  1257. cf_quiche_conn_is_alive,
  1258. Curl_cf_def_conn_keep_alive,
  1259. cf_quiche_query,
  1260. };
  1261. CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
  1262. struct Curl_easy *data,
  1263. struct connectdata *conn,
  1264. const struct Curl_addrinfo *ai)
  1265. {
  1266. struct cf_quiche_ctx *ctx = NULL;
  1267. struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
  1268. CURLcode result;
  1269. (void)data;
  1270. (void)conn;
  1271. ctx = calloc(sizeof(*ctx), 1);
  1272. if(!ctx) {
  1273. result = CURLE_OUT_OF_MEMORY;
  1274. goto out;
  1275. }
  1276. result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
  1277. if(result)
  1278. goto out;
  1279. result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
  1280. if(result)
  1281. goto out;
  1282. udp_cf->conn = cf->conn;
  1283. udp_cf->sockindex = cf->sockindex;
  1284. cf->next = udp_cf;
  1285. out:
  1286. *pcf = (!result)? cf : NULL;
  1287. if(result) {
  1288. if(udp_cf)
  1289. Curl_conn_cf_discard(udp_cf, data);
  1290. Curl_safefree(cf);
  1291. Curl_safefree(ctx);
  1292. }
  1293. return result;
  1294. }
  1295. bool Curl_conn_is_quiche(const struct Curl_easy *data,
  1296. const struct connectdata *conn,
  1297. int sockindex)
  1298. {
  1299. struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
  1300. (void)data;
  1301. for(; cf; cf = cf->next) {
  1302. if(cf->cft == &Curl_cft_http3)
  1303. return TRUE;
  1304. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  1305. return FALSE;
  1306. }
  1307. return FALSE;
  1308. }
  1309. #endif