quiche.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, 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. #error #include <quiche.h>
  27. #include <openssl/err.h>
  28. #include <openssl/ssl.h>
  29. #include "urldata.h"
  30. #include "sendf.h"
  31. #include "strdup.h"
  32. #include "rand.h"
  33. #include "quic.h"
  34. #include "strcase.h"
  35. #include "multiif.h"
  36. #include "connect.h"
  37. #include "strerror.h"
  38. #error #include "vquic.h"
  39. #include "transfer.h"
  40. #include "h2h3.h"
  41. #include "vtls/openssl.h"
  42. #include "vtls/keylog.h"
  43. /* The last 3 #include files should be in this order */
  44. #include "curl_printf.h"
  45. #include "curl_memory.h"
  46. #include "memdebug.h"
  47. #define DEBUG_HTTP3
  48. /* #define DEBUG_QUICHE */
  49. #ifdef DEBUG_HTTP3
  50. #define H3BUGF(x) x
  51. #else
  52. #define H3BUGF(x) do { } while(0)
  53. #endif
  54. #define QUIC_MAX_STREAMS (256*1024)
  55. #define QUIC_MAX_DATA (1*1024*1024)
  56. #define QUIC_IDLE_TIMEOUT (60 * 1000) /* milliseconds */
  57. static CURLcode process_ingress(struct Curl_easy *data,
  58. curl_socket_t sockfd,
  59. struct quicsocket *qs);
  60. static CURLcode flush_egress(struct Curl_easy *data, curl_socket_t sockfd,
  61. struct quicsocket *qs);
  62. static CURLcode http_request(struct Curl_easy *data, const void *mem,
  63. size_t len);
  64. static Curl_recv h3_stream_recv;
  65. static Curl_send h3_stream_send;
  66. static int quiche_getsock(struct Curl_easy *data,
  67. struct connectdata *conn, curl_socket_t *socks)
  68. {
  69. struct SingleRequest *k = &data->req;
  70. int bitmap = GETSOCK_BLANK;
  71. socks[0] = conn->sock[FIRSTSOCKET];
  72. /* in a HTTP/2 connection we can basically always get a frame so we should
  73. always be ready for one */
  74. bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
  75. /* we're still uploading or the HTTP/2 layer wants to send data */
  76. if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
  77. bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
  78. return bitmap;
  79. }
  80. static CURLcode qs_disconnect(struct Curl_easy *data,
  81. struct quicsocket *qs)
  82. {
  83. DEBUGASSERT(qs);
  84. if(qs->conn) {
  85. (void)quiche_conn_close(qs->conn, TRUE, 0, NULL, 0);
  86. /* flushing the egress is not a failsafe way to deliver all the
  87. outstanding packets, but we also don't want to get stuck here... */
  88. (void)flush_egress(data, qs->sockfd, qs);
  89. quiche_conn_free(qs->conn);
  90. qs->conn = NULL;
  91. }
  92. if(qs->h3config)
  93. quiche_h3_config_free(qs->h3config);
  94. if(qs->h3c)
  95. quiche_h3_conn_free(qs->h3c);
  96. if(qs->cfg) {
  97. quiche_config_free(qs->cfg);
  98. qs->cfg = NULL;
  99. }
  100. return CURLE_OK;
  101. }
  102. static CURLcode quiche_disconnect(struct Curl_easy *data,
  103. struct connectdata *conn,
  104. bool dead_connection)
  105. {
  106. struct quicsocket *qs = conn->quic;
  107. (void)dead_connection;
  108. return qs_disconnect(data, qs);
  109. }
  110. void Curl_quic_disconnect(struct Curl_easy *data,
  111. struct connectdata *conn,
  112. int tempindex)
  113. {
  114. if(conn->transport == TRNSPRT_QUIC)
  115. qs_disconnect(data, &conn->hequic[tempindex]);
  116. }
  117. static unsigned int quiche_conncheck(struct Curl_easy *data,
  118. struct connectdata *conn,
  119. unsigned int checks_to_perform)
  120. {
  121. (void)data;
  122. (void)conn;
  123. (void)checks_to_perform;
  124. return CONNRESULT_NONE;
  125. }
  126. static CURLcode quiche_do(struct Curl_easy *data, bool *done)
  127. {
  128. struct HTTP *stream = data->req.p.http;
  129. stream->h3req = FALSE; /* not sent */
  130. return Curl_http(data, done);
  131. }
  132. static const struct Curl_handler Curl_handler_http3 = {
  133. "HTTPS", /* scheme */
  134. ZERO_NULL, /* setup_connection */
  135. quiche_do, /* do_it */
  136. Curl_http_done, /* done */
  137. ZERO_NULL, /* do_more */
  138. ZERO_NULL, /* connect_it */
  139. ZERO_NULL, /* connecting */
  140. ZERO_NULL, /* doing */
  141. quiche_getsock, /* proto_getsock */
  142. quiche_getsock, /* doing_getsock */
  143. ZERO_NULL, /* domore_getsock */
  144. quiche_getsock, /* perform_getsock */
  145. quiche_disconnect, /* disconnect */
  146. ZERO_NULL, /* readwrite */
  147. quiche_conncheck, /* connection_check */
  148. ZERO_NULL, /* attach connection */
  149. PORT_HTTP, /* defport */
  150. CURLPROTO_HTTPS, /* protocol */
  151. CURLPROTO_HTTP, /* family */
  152. PROTOPT_SSL | PROTOPT_STREAM /* flags */
  153. };
  154. #ifdef DEBUG_QUICHE
  155. static void quiche_debug_log(const char *line, void *argp)
  156. {
  157. (void)argp;
  158. fprintf(stderr, "%s\n", line);
  159. }
  160. #endif
  161. static void keylog_callback(const SSL *ssl, const char *line)
  162. {
  163. (void)ssl;
  164. Curl_tls_keylog_write_line(line);
  165. }
  166. static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
  167. {
  168. SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
  169. SSL_CTX_set_alpn_protos(ssl_ctx,
  170. (const uint8_t *)QUICHE_H3_APPLICATION_PROTOCOL,
  171. sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1);
  172. SSL_CTX_set_default_verify_paths(ssl_ctx);
  173. /* Open the file if a TLS or QUIC backend has not done this before. */
  174. Curl_tls_keylog_open();
  175. if(Curl_tls_keylog_enabled()) {
  176. SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
  177. }
  178. {
  179. struct connectdata *conn = data->conn;
  180. if(conn->ssl_config.verifypeer) {
  181. const char * const ssl_cafile = conn->ssl_config.CAfile;
  182. const char * const ssl_capath = conn->ssl_config.CApath;
  183. if(ssl_cafile || ssl_capath) {
  184. SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
  185. /* tell OpenSSL where to find CA certificates that are used to verify
  186. the server's certificate. */
  187. if(!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cafile, ssl_capath)) {
  188. /* Fail if we insist on successfully verifying the server. */
  189. failf(data, "error setting certificate verify locations:"
  190. " CAfile: %s CApath: %s",
  191. ssl_cafile ? ssl_cafile : "none",
  192. ssl_capath ? ssl_capath : "none");
  193. return NULL;
  194. }
  195. infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
  196. infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
  197. }
  198. #ifdef CURL_CA_FALLBACK
  199. else {
  200. /* verifying the peer without any CA certificates won't work so
  201. use openssl's built-in default as fallback */
  202. SSL_CTX_set_default_verify_paths(ssl_ctx);
  203. }
  204. #endif
  205. }
  206. }
  207. return ssl_ctx;
  208. }
  209. static int quic_init_ssl(struct quicsocket *qs, struct connectdata *conn)
  210. {
  211. /* this will need some attention when HTTPS proxy over QUIC get fixed */
  212. const char * const hostname = conn->host.name;
  213. DEBUGASSERT(!qs->ssl);
  214. qs->ssl = SSL_new(qs->sslctx);
  215. SSL_set_app_data(qs->ssl, qs);
  216. /* set SNI */
  217. SSL_set_tlsext_host_name(qs->ssl, hostname);
  218. return 0;
  219. }
  220. CURLcode Curl_quic_connect(struct Curl_easy *data,
  221. struct connectdata *conn, curl_socket_t sockfd,
  222. int sockindex,
  223. const struct sockaddr *addr, socklen_t addrlen)
  224. {
  225. CURLcode result;
  226. struct quicsocket *qs = &conn->hequic[sockindex];
  227. char ipbuf[40];
  228. int port;
  229. int rv;
  230. #ifdef DEBUG_QUICHE
  231. /* initialize debug log callback only once */
  232. static int debug_log_init = 0;
  233. if(!debug_log_init) {
  234. quiche_enable_debug_logging(quiche_debug_log, NULL);
  235. debug_log_init = 1;
  236. }
  237. #endif
  238. (void)addr;
  239. (void)addrlen;
  240. qs->sockfd = sockfd;
  241. qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
  242. if(!qs->cfg) {
  243. failf(data, "can't create quiche config");
  244. return CURLE_FAILED_INIT;
  245. }
  246. quiche_config_set_max_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT);
  247. quiche_config_set_initial_max_data(qs->cfg, QUIC_MAX_DATA);
  248. quiche_config_set_initial_max_stream_data_bidi_local(qs->cfg, QUIC_MAX_DATA);
  249. quiche_config_set_initial_max_stream_data_bidi_remote(qs->cfg,
  250. QUIC_MAX_DATA);
  251. quiche_config_set_initial_max_stream_data_uni(qs->cfg, QUIC_MAX_DATA);
  252. quiche_config_set_initial_max_streams_bidi(qs->cfg, QUIC_MAX_STREAMS);
  253. quiche_config_set_initial_max_streams_uni(qs->cfg, QUIC_MAX_STREAMS);
  254. quiche_config_set_application_protos(qs->cfg,
  255. (uint8_t *)
  256. QUICHE_H3_APPLICATION_PROTOCOL,
  257. sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
  258. - 1);
  259. qs->sslctx = quic_ssl_ctx(data);
  260. if(!qs->sslctx)
  261. return CURLE_QUIC_CONNECT_ERROR;
  262. if(quic_init_ssl(qs, conn))
  263. return CURLE_QUIC_CONNECT_ERROR;
  264. result = Curl_rand(data, qs->scid, sizeof(qs->scid));
  265. if(result)
  266. return result;
  267. qs->local_addrlen = sizeof(qs->local_addr);
  268. rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
  269. &qs->local_addrlen);
  270. if(rv == -1)
  271. return CURLE_QUIC_CONNECT_ERROR;
  272. qs->conn = quiche_conn_new_with_tls((const uint8_t *) qs->scid,
  273. sizeof(qs->scid), NULL, 0,
  274. (struct sockaddr *)&qs->local_addr,
  275. qs->local_addrlen, addr, addrlen,
  276. qs->cfg, qs->ssl, false);
  277. if(!qs->conn) {
  278. failf(data, "can't create quiche connection");
  279. return CURLE_OUT_OF_MEMORY;
  280. }
  281. /* Known to not work on Windows */
  282. #if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
  283. {
  284. int qfd;
  285. (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
  286. if(qfd != -1)
  287. quiche_conn_set_qlog_fd(qs->conn, qfd,
  288. "qlog title", "curl qlog");
  289. }
  290. #endif
  291. result = flush_egress(data, sockfd, qs);
  292. if(result)
  293. return result;
  294. /* extract the used address as a string */
  295. if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
  296. char buffer[STRERROR_LEN];
  297. failf(data, "ssrem inet_ntop() failed with errno %d: %s",
  298. SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
  299. return CURLE_BAD_FUNCTION_ARGUMENT;
  300. }
  301. infof(data, "Connect socket %d over QUIC to %s:%ld",
  302. sockfd, ipbuf, port);
  303. Curl_persistconninfo(data, conn, NULL, -1);
  304. /* for connection reuse purposes: */
  305. conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
  306. {
  307. unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
  308. unsigned alpn_len, offset = 0;
  309. /* Replace each ALPN length prefix by a comma. */
  310. while(offset < sizeof(alpn_protocols) - 1) {
  311. alpn_len = alpn_protocols[offset];
  312. alpn_protocols[offset] = ',';
  313. offset += 1 + alpn_len;
  314. }
  315. infof(data, "Sent QUIC client Initial, ALPN: %s",
  316. alpn_protocols + 1);
  317. }
  318. return CURLE_OK;
  319. }
  320. static CURLcode quiche_has_connected(struct Curl_easy *data,
  321. struct connectdata *conn,
  322. int sockindex,
  323. int tempindex)
  324. {
  325. CURLcode result;
  326. struct quicsocket *qs = conn->quic = &conn->hequic[tempindex];
  327. conn->recv[sockindex] = h3_stream_recv;
  328. conn->send[sockindex] = h3_stream_send;
  329. conn->handler = &Curl_handler_http3;
  330. conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  331. conn->httpversion = 30;
  332. conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  333. if(conn->ssl_config.verifyhost) {
  334. X509 *server_cert;
  335. server_cert = SSL_get_peer_certificate(qs->ssl);
  336. if(!server_cert) {
  337. return CURLE_PEER_FAILED_VERIFICATION;
  338. }
  339. result = Curl_ossl_verifyhost(data, conn, server_cert);
  340. X509_free(server_cert);
  341. if(result)
  342. return result;
  343. infof(data, "Verified certificate just fine");
  344. }
  345. else
  346. infof(data, "Skipped certificate verification");
  347. qs->h3config = quiche_h3_config_new();
  348. if(!qs->h3config)
  349. return CURLE_OUT_OF_MEMORY;
  350. /* Create a new HTTP/3 connection on the QUIC connection. */
  351. qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
  352. if(!qs->h3c) {
  353. result = CURLE_OUT_OF_MEMORY;
  354. goto fail;
  355. }
  356. if(conn->hequic[1-tempindex].cfg) {
  357. qs = &conn->hequic[1-tempindex];
  358. quiche_config_free(qs->cfg);
  359. quiche_conn_free(qs->conn);
  360. qs->cfg = NULL;
  361. qs->conn = NULL;
  362. }
  363. if(data->set.ssl.certinfo)
  364. /* asked to gather certificate info */
  365. (void)Curl_ossl_certchain(data, qs->ssl);
  366. return CURLE_OK;
  367. fail:
  368. quiche_h3_config_free(qs->h3config);
  369. quiche_h3_conn_free(qs->h3c);
  370. return result;
  371. }
  372. /*
  373. * This function gets polled to check if this QUIC connection has connected.
  374. */
  375. CURLcode Curl_quic_is_connected(struct Curl_easy *data,
  376. struct connectdata *conn,
  377. int sockindex,
  378. bool *done)
  379. {
  380. CURLcode result;
  381. struct quicsocket *qs = &conn->hequic[sockindex];
  382. curl_socket_t sockfd = conn->tempsock[sockindex];
  383. result = process_ingress(data, sockfd, qs);
  384. if(result)
  385. goto error;
  386. result = flush_egress(data, sockfd, qs);
  387. if(result)
  388. goto error;
  389. if(quiche_conn_is_established(qs->conn)) {
  390. *done = TRUE;
  391. result = quiche_has_connected(data, conn, 0, sockindex);
  392. DEBUGF(infof(data, "quiche established connection"));
  393. }
  394. return result;
  395. error:
  396. qs_disconnect(data, qs);
  397. return result;
  398. }
  399. static CURLcode process_ingress(struct Curl_easy *data, int sockfd,
  400. struct quicsocket *qs)
  401. {
  402. ssize_t recvd;
  403. uint8_t *buf = (uint8_t *)data->state.buffer;
  404. size_t bufsize = data->set.buffer_size;
  405. struct sockaddr_storage from;
  406. socklen_t from_len;
  407. quiche_recv_info recv_info;
  408. DEBUGASSERT(qs->conn);
  409. /* in case the timeout expired */
  410. quiche_conn_on_timeout(qs->conn);
  411. do {
  412. from_len = sizeof(from);
  413. recvd = recvfrom(sockfd, buf, bufsize, 0,
  414. (struct sockaddr *)&from, &from_len);
  415. if((recvd < 0) && ((SOCKERRNO == EAGAIN) || (SOCKERRNO == EWOULDBLOCK)))
  416. break;
  417. if(recvd < 0) {
  418. failf(data, "quiche: recvfrom() unexpectedly returned %zd "
  419. "(errno: %d, socket %d)", recvd, SOCKERRNO, sockfd);
  420. return CURLE_RECV_ERROR;
  421. }
  422. recv_info.from = (struct sockaddr *) &from;
  423. recv_info.from_len = from_len;
  424. recv_info.to = (struct sockaddr *) &qs->local_addr;
  425. recv_info.to_len = qs->local_addrlen;
  426. recvd = quiche_conn_recv(qs->conn, buf, recvd, &recv_info);
  427. if(recvd == QUICHE_ERR_DONE)
  428. break;
  429. if(recvd < 0) {
  430. if(QUICHE_ERR_TLS_FAIL == recvd) {
  431. long verify_ok = SSL_get_verify_result(qs->ssl);
  432. if(verify_ok != X509_V_OK) {
  433. failf(data, "SSL certificate problem: %s",
  434. X509_verify_cert_error_string(verify_ok));
  435. return CURLE_PEER_FAILED_VERIFICATION;
  436. }
  437. }
  438. failf(data, "quiche_conn_recv() == %zd", recvd);
  439. return CURLE_RECV_ERROR;
  440. }
  441. } while(1);
  442. return CURLE_OK;
  443. }
  444. /*
  445. * flush_egress drains the buffers and sends off data.
  446. * Calls failf() on errors.
  447. */
  448. static CURLcode flush_egress(struct Curl_easy *data, int sockfd,
  449. struct quicsocket *qs)
  450. {
  451. ssize_t sent;
  452. uint8_t out[1200];
  453. int64_t timeout_ns;
  454. quiche_send_info send_info;
  455. do {
  456. sent = quiche_conn_send(qs->conn, out, sizeof(out), &send_info);
  457. if(sent == QUICHE_ERR_DONE)
  458. break;
  459. if(sent < 0) {
  460. failf(data, "quiche_conn_send returned %zd", sent);
  461. return CURLE_SEND_ERROR;
  462. }
  463. sent = send(sockfd, out, sent, 0);
  464. if(sent < 0) {
  465. failf(data, "send() returned %zd", sent);
  466. return CURLE_SEND_ERROR;
  467. }
  468. } while(1);
  469. /* time until the next timeout event, as nanoseconds. */
  470. timeout_ns = quiche_conn_timeout_as_nanos(qs->conn);
  471. if(timeout_ns)
  472. /* expire uses milliseconds */
  473. Curl_expire(data, (timeout_ns + 999999) / 1000000, EXPIRE_QUIC);
  474. return CURLE_OK;
  475. }
  476. struct h3h1header {
  477. char *dest;
  478. size_t destlen; /* left to use */
  479. size_t nlen; /* used */
  480. };
  481. static int cb_each_header(uint8_t *name, size_t name_len,
  482. uint8_t *value, size_t value_len,
  483. void *argp)
  484. {
  485. struct h3h1header *headers = (struct h3h1header *)argp;
  486. size_t olen = 0;
  487. if((name_len == 7) && !strncmp(H2H3_PSEUDO_STATUS, (char *)name, 7)) {
  488. msnprintf(headers->dest,
  489. headers->destlen, "HTTP/3 %.*s\n",
  490. (int) value_len, value);
  491. }
  492. else if(!headers->nlen) {
  493. return CURLE_HTTP3;
  494. }
  495. else {
  496. msnprintf(headers->dest,
  497. headers->destlen, "%.*s: %.*s\n",
  498. (int)name_len, name, (int) value_len, value);
  499. }
  500. olen = strlen(headers->dest);
  501. headers->destlen -= olen;
  502. headers->nlen += olen;
  503. headers->dest += olen;
  504. return 0;
  505. }
  506. static ssize_t h3_stream_recv(struct Curl_easy *data,
  507. int sockindex,
  508. char *buf,
  509. size_t buffersize,
  510. CURLcode *curlcode)
  511. {
  512. ssize_t recvd = -1;
  513. ssize_t rcode;
  514. struct connectdata *conn = data->conn;
  515. struct quicsocket *qs = conn->quic;
  516. curl_socket_t sockfd = conn->sock[sockindex];
  517. quiche_h3_event *ev;
  518. int rc;
  519. struct h3h1header headers;
  520. struct HTTP *stream = data->req.p.http;
  521. headers.dest = buf;
  522. headers.destlen = buffersize;
  523. headers.nlen = 0;
  524. if(process_ingress(data, sockfd, qs)) {
  525. infof(data, "h3_stream_recv returns on ingress");
  526. *curlcode = CURLE_RECV_ERROR;
  527. return -1;
  528. }
  529. if(qs->h3_recving) {
  530. /* body receiving state */
  531. rcode = quiche_h3_recv_body(qs->h3c, qs->conn, stream->stream3_id,
  532. (unsigned char *)buf, buffersize);
  533. if(rcode <= 0) {
  534. recvd = -1;
  535. qs->h3_recving = FALSE;
  536. /* fall through into the while loop below */
  537. }
  538. else
  539. recvd = rcode;
  540. }
  541. while(recvd < 0) {
  542. int64_t s = quiche_h3_conn_poll(qs->h3c, qs->conn, &ev);
  543. if(s < 0)
  544. /* nothing more to do */
  545. break;
  546. if(s != stream->stream3_id) {
  547. /* another transfer, ignore for now */
  548. infof(data, "Got h3 for stream %u, expects %u",
  549. s, stream->stream3_id);
  550. continue;
  551. }
  552. switch(quiche_h3_event_type(ev)) {
  553. case QUICHE_H3_EVENT_HEADERS:
  554. rc = quiche_h3_event_for_each_header(ev, cb_each_header, &headers);
  555. if(rc) {
  556. *curlcode = rc;
  557. failf(data, "Error in HTTP/3 response header");
  558. break;
  559. }
  560. recvd = headers.nlen;
  561. break;
  562. case QUICHE_H3_EVENT_DATA:
  563. if(!stream->firstbody) {
  564. /* add a header-body separator CRLF */
  565. buf[0] = '\r';
  566. buf[1] = '\n';
  567. buf += 2;
  568. buffersize -= 2;
  569. stream->firstbody = TRUE;
  570. recvd = 2; /* two bytes already */
  571. }
  572. else
  573. recvd = 0;
  574. rcode = quiche_h3_recv_body(qs->h3c, qs->conn, s, (unsigned char *)buf,
  575. buffersize);
  576. if(rcode <= 0) {
  577. recvd = -1;
  578. break;
  579. }
  580. qs->h3_recving = TRUE;
  581. recvd += rcode;
  582. break;
  583. case QUICHE_H3_EVENT_RESET:
  584. streamclose(conn, "Stream reset");
  585. *curlcode = CURLE_PARTIAL_FILE;
  586. return -1;
  587. case QUICHE_H3_EVENT_FINISHED:
  588. streamclose(conn, "End of stream");
  589. recvd = 0; /* end of stream */
  590. break;
  591. default:
  592. break;
  593. }
  594. quiche_h3_event_free(ev);
  595. }
  596. if(flush_egress(data, sockfd, qs)) {
  597. *curlcode = CURLE_SEND_ERROR;
  598. return -1;
  599. }
  600. *curlcode = (-1 == recvd)? CURLE_AGAIN : CURLE_OK;
  601. if(recvd >= 0)
  602. /* Get this called again to drain the event queue */
  603. Curl_expire(data, 0, EXPIRE_QUIC);
  604. data->state.drain = (recvd >= 0) ? 1 : 0;
  605. return recvd;
  606. }
  607. static ssize_t h3_stream_send(struct Curl_easy *data,
  608. int sockindex,
  609. const void *mem,
  610. size_t len,
  611. CURLcode *curlcode)
  612. {
  613. ssize_t sent;
  614. struct connectdata *conn = data->conn;
  615. struct quicsocket *qs = conn->quic;
  616. curl_socket_t sockfd = conn->sock[sockindex];
  617. struct HTTP *stream = data->req.p.http;
  618. if(!stream->h3req) {
  619. CURLcode result = http_request(data, mem, len);
  620. if(result) {
  621. *curlcode = CURLE_SEND_ERROR;
  622. return -1;
  623. }
  624. sent = len;
  625. }
  626. else {
  627. sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
  628. (uint8_t *)mem, len, FALSE);
  629. if(sent == QUICHE_H3_ERR_DONE) {
  630. sent = 0;
  631. }
  632. else if(sent < 0) {
  633. *curlcode = CURLE_SEND_ERROR;
  634. return -1;
  635. }
  636. }
  637. if(flush_egress(data, sockfd, qs)) {
  638. *curlcode = CURLE_SEND_ERROR;
  639. return -1;
  640. }
  641. *curlcode = CURLE_OK;
  642. return sent;
  643. }
  644. /*
  645. * Store quiche version info in this buffer.
  646. */
  647. void Curl_quic_ver(char *p, size_t len)
  648. {
  649. (void)msnprintf(p, len, "quiche/%s", quiche_version());
  650. }
  651. /* Index where :authority header field will appear in request header
  652. field list. */
  653. #define AUTHORITY_DST_IDX 3
  654. static CURLcode http_request(struct Curl_easy *data, const void *mem,
  655. size_t len)
  656. {
  657. struct connectdata *conn = data->conn;
  658. struct HTTP *stream = data->req.p.http;
  659. size_t nheader;
  660. int64_t stream3_id;
  661. quiche_h3_header *nva = NULL;
  662. struct quicsocket *qs = conn->quic;
  663. CURLcode result = CURLE_OK;
  664. struct h2h3req *hreq = NULL;
  665. stream->h3req = TRUE; /* senf off! */
  666. result = Curl_pseudo_headers(data, mem, len, &hreq);
  667. if(result)
  668. goto fail;
  669. nheader = hreq->entries;
  670. nva = malloc(sizeof(quiche_h3_header) * nheader);
  671. if(!nva) {
  672. result = CURLE_OUT_OF_MEMORY;
  673. goto fail;
  674. }
  675. else {
  676. unsigned int i;
  677. for(i = 0; i < nheader; i++) {
  678. nva[i].name = (unsigned char *)hreq->header[i].name;
  679. nva[i].name_len = hreq->header[i].namelen;
  680. nva[i].value = (unsigned char *)hreq->header[i].value;
  681. nva[i].value_len = hreq->header[i].valuelen;
  682. }
  683. }
  684. switch(data->state.httpreq) {
  685. case HTTPREQ_POST:
  686. case HTTPREQ_POST_FORM:
  687. case HTTPREQ_POST_MIME:
  688. case HTTPREQ_PUT:
  689. if(data->state.infilesize != -1)
  690. stream->upload_left = data->state.infilesize;
  691. else
  692. /* data sending without specifying the data amount up front */
  693. stream->upload_left = -1; /* unknown, but not zero */
  694. stream3_id = quiche_h3_send_request(qs->h3c, qs->conn, nva, nheader,
  695. stream->upload_left ? FALSE: TRUE);
  696. if((stream3_id >= 0) && data->set.postfields) {
  697. ssize_t sent = quiche_h3_send_body(qs->h3c, qs->conn, stream3_id,
  698. (uint8_t *)data->set.postfields,
  699. stream->upload_left, TRUE);
  700. if(sent <= 0) {
  701. failf(data, "quiche_h3_send_body failed");
  702. result = CURLE_SEND_ERROR;
  703. }
  704. stream->upload_left = 0; /* nothing left to send */
  705. }
  706. break;
  707. default:
  708. stream3_id = quiche_h3_send_request(qs->h3c, qs->conn, nva, nheader,
  709. TRUE);
  710. break;
  711. }
  712. Curl_safefree(nva);
  713. if(stream3_id < 0) {
  714. H3BUGF(infof(data, "quiche_h3_send_request returned %d",
  715. stream3_id));
  716. result = CURLE_SEND_ERROR;
  717. goto fail;
  718. }
  719. infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
  720. stream3_id, (void *)data);
  721. stream->stream3_id = stream3_id;
  722. Curl_pseudo_free(hreq);
  723. return CURLE_OK;
  724. fail:
  725. free(nva);
  726. Curl_pseudo_free(hreq);
  727. return result;
  728. }
  729. /*
  730. * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
  731. */
  732. CURLcode Curl_quic_done_sending(struct Curl_easy *data)
  733. {
  734. struct connectdata *conn = data->conn;
  735. DEBUGASSERT(conn);
  736. if(conn->handler == &Curl_handler_http3) {
  737. /* only for HTTP/3 transfers */
  738. ssize_t sent;
  739. struct HTTP *stream = data->req.p.http;
  740. struct quicsocket *qs = conn->quic;
  741. stream->upload_done = TRUE;
  742. sent = quiche_h3_send_body(qs->h3c, qs->conn, stream->stream3_id,
  743. NULL, 0, TRUE);
  744. if(sent < 0)
  745. return CURLE_SEND_ERROR;
  746. }
  747. return CURLE_OK;
  748. }
  749. /*
  750. * Called from http.c:Curl_http_done when a request completes.
  751. */
  752. void Curl_quic_done(struct Curl_easy *data, bool premature)
  753. {
  754. (void)data;
  755. (void)premature;
  756. }
  757. /*
  758. * Called from transfer.c:data_pending to know if we should keep looping
  759. * to receive more data from the connection.
  760. */
  761. bool Curl_quic_data_pending(const struct Curl_easy *data)
  762. {
  763. (void)data;
  764. return FALSE;
  765. }
  766. /*
  767. * Called from transfer.c:Curl_readwrite when neither HTTP level read
  768. * nor write is performed. It is a good place to handle timer expiry
  769. * for QUIC transport.
  770. */
  771. CURLcode Curl_quic_idle(struct Curl_easy *data)
  772. {
  773. (void)data;
  774. return CURLE_OK;
  775. }
  776. #endif