curl_quiche.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 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. #include <quiche.h>
  27. #include <openssl/err.h>
  28. #include <openssl/ssl.h>
  29. #include "bufq.h"
  30. #include "hash.h"
  31. #include "urldata.h"
  32. #include "cfilters.h"
  33. #include "cf-socket.h"
  34. #include "sendf.h"
  35. #include "strdup.h"
  36. #include "rand.h"
  37. #include "strcase.h"
  38. #include "multiif.h"
  39. #include "connect.h"
  40. #include "progress.h"
  41. #include "strerror.h"
  42. #include "http1.h"
  43. #include "vquic.h"
  44. #include "vquic_int.h"
  45. #include "vquic-tls.h"
  46. #include "curl_quiche.h"
  47. #include "transfer.h"
  48. #include "inet_pton.h"
  49. #include "vtls/openssl.h"
  50. #include "vtls/keylog.h"
  51. #include "vtls/vtls.h"
  52. /* The last 3 #include files should be in this order */
  53. #include "curl_printf.h"
  54. #include "curl_memory.h"
  55. #include "memdebug.h"
  56. /* HTTP/3 error values defined in RFC 9114, ch. 8.1 */
  57. #define CURL_H3_NO_ERROR (0x0100)
  58. #define QUIC_MAX_STREAMS (100)
  59. #define H3_STREAM_WINDOW_SIZE (128 * 1024)
  60. #define H3_STREAM_CHUNK_SIZE (16 * 1024)
  61. /* The pool keeps spares around and half of a full stream windows
  62. * seems good. More does not seem to improve performance.
  63. * The benefit of the pool is that stream buffer to not keep
  64. * spares. So memory consumption goes down when streams run empty,
  65. * have a large upload done, etc. */
  66. #define H3_STREAM_POOL_SPARES \
  67. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
  68. /* Receive and Send max number of chunks just follows from the
  69. * chunk size and window size */
  70. #define H3_STREAM_RECV_CHUNKS \
  71. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
  72. #define H3_STREAM_SEND_CHUNKS \
  73. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
  74. /*
  75. * Store quiche version info in this buffer.
  76. */
  77. void Curl_quiche_ver(char *p, size_t len)
  78. {
  79. (void)msnprintf(p, len, "quiche/%s", quiche_version());
  80. }
  81. struct cf_quiche_ctx {
  82. struct cf_quic_ctx q;
  83. struct ssl_peer peer;
  84. struct curl_tls_ctx tls;
  85. quiche_conn *qconn;
  86. quiche_config *cfg;
  87. quiche_h3_conn *h3c;
  88. quiche_h3_config *h3config;
  89. uint8_t scid[QUICHE_MAX_CONN_ID_LEN];
  90. struct curltime started_at; /* time the current attempt started */
  91. struct curltime handshake_at; /* time connect handshake finished */
  92. struct curltime reconnect_at; /* time the next attempt should start */
  93. struct bufc_pool stream_bufcp; /* chunk pool for streams */
  94. struct Curl_hash streams; /* hash `data->id` to `stream_ctx` */
  95. curl_off_t data_recvd;
  96. curl_uint64_t max_idle_ms; /* max idle time for QUIC conn */
  97. BIT(goaway); /* got GOAWAY from server */
  98. BIT(x509_store_setup); /* if x509 store has been set up */
  99. };
  100. #ifdef DEBUG_QUICHE
  101. static void quiche_debug_log(const char *line, void *argp)
  102. {
  103. (void)argp;
  104. fprintf(stderr, "%s\n", line);
  105. }
  106. #endif
  107. static void cf_quiche_ctx_clear(struct cf_quiche_ctx *ctx)
  108. {
  109. if(ctx) {
  110. if(ctx->h3c)
  111. quiche_h3_conn_free(ctx->h3c);
  112. if(ctx->h3config)
  113. quiche_h3_config_free(ctx->h3config);
  114. if(ctx->qconn)
  115. quiche_conn_free(ctx->qconn);
  116. if(ctx->cfg)
  117. quiche_config_free(ctx->cfg);
  118. /* quiche just freed it */
  119. ctx->tls.ossl.ssl = NULL;
  120. Curl_vquic_tls_cleanup(&ctx->tls);
  121. Curl_ssl_peer_cleanup(&ctx->peer);
  122. vquic_ctx_free(&ctx->q);
  123. Curl_bufcp_free(&ctx->stream_bufcp);
  124. Curl_hash_clean(&ctx->streams);
  125. Curl_hash_destroy(&ctx->streams);
  126. memset(ctx, 0, sizeof(*ctx));
  127. }
  128. }
  129. /**
  130. * All about the H3 internals of a stream
  131. */
  132. struct stream_ctx {
  133. curl_uint64_t id; /* HTTP/3 protocol stream identifier */
  134. struct bufq recvbuf; /* h3 response */
  135. struct h1_req_parser h1; /* h1 request parsing */
  136. curl_uint64_t error3; /* HTTP/3 stream error code */
  137. curl_off_t upload_left; /* number of request bytes left to upload */
  138. BIT(opened); /* TRUE after stream has been opened */
  139. BIT(closed); /* TRUE on stream close */
  140. BIT(reset); /* TRUE on stream reset */
  141. BIT(send_closed); /* stream is locally closed */
  142. BIT(resp_hds_complete); /* final response has been received */
  143. BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */
  144. BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
  145. };
  146. #define H3_STREAM_CTX(ctx,data) ((struct stream_ctx *)(\
  147. data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
  148. static void h3_stream_ctx_free(struct stream_ctx *stream)
  149. {
  150. Curl_bufq_free(&stream->recvbuf);
  151. Curl_h1_req_parse_free(&stream->h1);
  152. free(stream);
  153. }
  154. static void h3_stream_hash_free(void *stream)
  155. {
  156. DEBUGASSERT(stream);
  157. h3_stream_ctx_free((struct stream_ctx *)stream);
  158. }
  159. static void check_resumes(struct Curl_cfilter *cf,
  160. struct Curl_easy *data)
  161. {
  162. struct cf_quiche_ctx *ctx = cf->ctx;
  163. struct Curl_easy *sdata;
  164. struct stream_ctx *stream;
  165. DEBUGASSERT(data->multi);
  166. for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
  167. if(sdata->conn == data->conn) {
  168. stream = H3_STREAM_CTX(ctx, sdata);
  169. if(stream && stream->quic_flow_blocked) {
  170. stream->quic_flow_blocked = FALSE;
  171. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  172. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] unblock", stream->id);
  173. }
  174. }
  175. }
  176. }
  177. static CURLcode h3_data_setup(struct Curl_cfilter *cf,
  178. struct Curl_easy *data)
  179. {
  180. struct cf_quiche_ctx *ctx = cf->ctx;
  181. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  182. if(stream)
  183. return CURLE_OK;
  184. stream = calloc(1, sizeof(*stream));
  185. if(!stream)
  186. return CURLE_OUT_OF_MEMORY;
  187. stream->id = -1;
  188. Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
  189. H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
  190. Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
  191. if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) {
  192. h3_stream_ctx_free(stream);
  193. return CURLE_OUT_OF_MEMORY;
  194. }
  195. return CURLE_OK;
  196. }
  197. static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
  198. {
  199. struct cf_quiche_ctx *ctx = cf->ctx;
  200. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  201. (void)cf;
  202. if(stream) {
  203. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] easy handle is done", stream->id);
  204. if(ctx->qconn && !stream->closed) {
  205. quiche_conn_stream_shutdown(ctx->qconn, stream->id,
  206. QUICHE_SHUTDOWN_READ, CURL_H3_NO_ERROR);
  207. if(!stream->send_closed) {
  208. quiche_conn_stream_shutdown(ctx->qconn, stream->id,
  209. QUICHE_SHUTDOWN_WRITE, CURL_H3_NO_ERROR);
  210. stream->send_closed = TRUE;
  211. }
  212. stream->closed = TRUE;
  213. }
  214. Curl_hash_offt_remove(&ctx->streams, data->id);
  215. }
  216. }
  217. static void drain_stream(struct Curl_cfilter *cf,
  218. struct Curl_easy *data)
  219. {
  220. struct cf_quiche_ctx *ctx = cf->ctx;
  221. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  222. unsigned char bits;
  223. (void)cf;
  224. bits = CURL_CSELECT_IN;
  225. if(stream && !stream->send_closed && stream->upload_left)
  226. bits |= CURL_CSELECT_OUT;
  227. if(data->state.select_bits != bits) {
  228. data->state.select_bits = bits;
  229. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  230. }
  231. }
  232. static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
  233. struct Curl_easy *data,
  234. curl_uint64_t stream_id,
  235. struct stream_ctx **pstream)
  236. {
  237. struct cf_quiche_ctx *ctx = cf->ctx;
  238. struct Curl_easy *sdata;
  239. struct stream_ctx *stream;
  240. (void)cf;
  241. stream = H3_STREAM_CTX(ctx, data);
  242. if(stream && stream->id == stream_id) {
  243. *pstream = stream;
  244. return data;
  245. }
  246. else {
  247. DEBUGASSERT(data->multi);
  248. for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
  249. if(sdata->conn != data->conn)
  250. continue;
  251. stream = H3_STREAM_CTX(ctx, sdata);
  252. if(stream && stream->id == stream_id) {
  253. *pstream = stream;
  254. return sdata;
  255. }
  256. }
  257. }
  258. *pstream = NULL;
  259. return NULL;
  260. }
  261. static void cf_quiche_expire_conn_transfers(struct Curl_cfilter *cf,
  262. struct Curl_easy *data)
  263. {
  264. struct Curl_easy *sdata;
  265. DEBUGASSERT(data->multi);
  266. CURL_TRC_CF(data, cf, "expiring all transfers on this connection");
  267. for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
  268. if(sdata == data || sdata->conn != data->conn)
  269. continue;
  270. Curl_expire(sdata, 0, EXPIRE_RUN_NOW);
  271. }
  272. }
  273. /*
  274. * write_resp_raw() copies response data in raw format to the `data`'s
  275. * receive buffer. If not enough space is available, it appends to the
  276. * `data`'s overflow buffer.
  277. */
  278. static CURLcode write_resp_raw(struct Curl_cfilter *cf,
  279. struct Curl_easy *data,
  280. const void *mem, size_t memlen)
  281. {
  282. struct cf_quiche_ctx *ctx = cf->ctx;
  283. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  284. CURLcode result = CURLE_OK;
  285. ssize_t nwritten;
  286. (void)cf;
  287. if(!stream)
  288. return CURLE_RECV_ERROR;
  289. nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
  290. if(nwritten < 0)
  291. return result;
  292. if((size_t)nwritten < memlen) {
  293. /* This MUST not happen. Our recbuf is dimensioned to hold the
  294. * full max_stream_window and then some for this very reason. */
  295. DEBUGASSERT(0);
  296. return CURLE_RECV_ERROR;
  297. }
  298. return result;
  299. }
  300. struct cb_ctx {
  301. struct Curl_cfilter *cf;
  302. struct Curl_easy *data;
  303. };
  304. static int cb_each_header(uint8_t *name, size_t name_len,
  305. uint8_t *value, size_t value_len,
  306. void *argp)
  307. {
  308. struct cb_ctx *x = argp;
  309. struct cf_quiche_ctx *ctx = x->cf->ctx;
  310. struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
  311. CURLcode result;
  312. if(!stream)
  313. return CURLE_OK;
  314. if((name_len == 7) && !strncmp(HTTP_PSEUDO_STATUS, (char *)name, 7)) {
  315. CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRIu64 "] status: %.*s",
  316. stream->id, (int)value_len, value);
  317. result = write_resp_raw(x->cf, x->data, "HTTP/3 ", sizeof("HTTP/3 ") - 1);
  318. if(!result)
  319. result = write_resp_raw(x->cf, x->data, value, value_len);
  320. if(!result)
  321. result = write_resp_raw(x->cf, x->data, " \r\n", 3);
  322. }
  323. else {
  324. CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRIu64 "] header: %.*s: %.*s",
  325. stream->id, (int)name_len, name,
  326. (int)value_len, value);
  327. result = write_resp_raw(x->cf, x->data, name, name_len);
  328. if(!result)
  329. result = write_resp_raw(x->cf, x->data, ": ", 2);
  330. if(!result)
  331. result = write_resp_raw(x->cf, x->data, value, value_len);
  332. if(!result)
  333. result = write_resp_raw(x->cf, x->data, "\r\n", 2);
  334. }
  335. if(result) {
  336. CURL_TRC_CF(x->data, x->cf, "[%"CURL_PRIu64"] on header error %d",
  337. stream->id, result);
  338. }
  339. return result;
  340. }
  341. static ssize_t stream_resp_read(void *reader_ctx,
  342. unsigned char *buf, size_t len,
  343. CURLcode *err)
  344. {
  345. struct cb_ctx *x = reader_ctx;
  346. struct cf_quiche_ctx *ctx = x->cf->ctx;
  347. struct stream_ctx *stream = H3_STREAM_CTX(ctx, x->data);
  348. ssize_t nread;
  349. if(!stream) {
  350. *err = CURLE_RECV_ERROR;
  351. return -1;
  352. }
  353. nread = quiche_h3_recv_body(ctx->h3c, ctx->qconn, stream->id,
  354. buf, len);
  355. if(nread >= 0) {
  356. *err = CURLE_OK;
  357. return nread;
  358. }
  359. else {
  360. *err = CURLE_AGAIN;
  361. return -1;
  362. }
  363. }
  364. static CURLcode cf_recv_body(struct Curl_cfilter *cf,
  365. struct Curl_easy *data)
  366. {
  367. struct cf_quiche_ctx *ctx = cf->ctx;
  368. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  369. ssize_t nwritten;
  370. struct cb_ctx cb_ctx;
  371. CURLcode result = CURLE_OK;
  372. if(!stream)
  373. return CURLE_RECV_ERROR;
  374. if(!stream->resp_hds_complete) {
  375. result = write_resp_raw(cf, data, "\r\n", 2);
  376. if(result)
  377. return result;
  378. stream->resp_hds_complete = TRUE;
  379. }
  380. cb_ctx.cf = cf;
  381. cb_ctx.data = data;
  382. nwritten = Curl_bufq_slurp(&stream->recvbuf,
  383. stream_resp_read, &cb_ctx, &result);
  384. if(nwritten < 0 && result != CURLE_AGAIN) {
  385. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] recv_body error %zd",
  386. stream->id, nwritten);
  387. failf(data, "Error %d in HTTP/3 response body for stream[%"CURL_PRIu64"]",
  388. result, stream->id);
  389. stream->closed = TRUE;
  390. stream->reset = TRUE;
  391. stream->send_closed = TRUE;
  392. streamclose(cf->conn, "Reset of stream");
  393. return result;
  394. }
  395. return CURLE_OK;
  396. }
  397. #ifdef DEBUGBUILD
  398. static const char *cf_ev_name(quiche_h3_event *ev)
  399. {
  400. switch(quiche_h3_event_type(ev)) {
  401. case QUICHE_H3_EVENT_HEADERS:
  402. return "HEADERS";
  403. case QUICHE_H3_EVENT_DATA:
  404. return "DATA";
  405. case QUICHE_H3_EVENT_RESET:
  406. return "RESET";
  407. case QUICHE_H3_EVENT_FINISHED:
  408. return "FINISHED";
  409. case QUICHE_H3_EVENT_GOAWAY:
  410. return "GOAWAY";
  411. default:
  412. return "Unknown";
  413. }
  414. }
  415. #else
  416. #define cf_ev_name(x) ""
  417. #endif
  418. static CURLcode h3_process_event(struct Curl_cfilter *cf,
  419. struct Curl_easy *data,
  420. struct stream_ctx *stream,
  421. quiche_h3_event *ev)
  422. {
  423. struct cb_ctx cb_ctx;
  424. CURLcode result = CURLE_OK;
  425. int rc;
  426. if(!stream)
  427. return CURLE_OK;
  428. switch(quiche_h3_event_type(ev)) {
  429. case QUICHE_H3_EVENT_HEADERS:
  430. stream->resp_got_header = TRUE;
  431. cb_ctx.cf = cf;
  432. cb_ctx.data = data;
  433. rc = quiche_h3_event_for_each_header(ev, cb_each_header, &cb_ctx);
  434. if(rc) {
  435. failf(data, "Error %d in HTTP/3 response header for stream[%"
  436. CURL_PRIu64"]", rc, stream->id);
  437. return CURLE_RECV_ERROR;
  438. }
  439. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] <- [HEADERS]", stream->id);
  440. break;
  441. case QUICHE_H3_EVENT_DATA:
  442. if(!stream->closed) {
  443. result = cf_recv_body(cf, data);
  444. }
  445. break;
  446. case QUICHE_H3_EVENT_RESET:
  447. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] RESET", stream->id);
  448. stream->closed = TRUE;
  449. stream->reset = TRUE;
  450. stream->send_closed = TRUE;
  451. streamclose(cf->conn, "Reset of stream");
  452. break;
  453. case QUICHE_H3_EVENT_FINISHED:
  454. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] CLOSED", stream->id);
  455. if(!stream->resp_hds_complete) {
  456. result = write_resp_raw(cf, data, "\r\n", 2);
  457. if(result)
  458. return result;
  459. stream->resp_hds_complete = TRUE;
  460. }
  461. stream->closed = TRUE;
  462. streamclose(cf->conn, "End of stream");
  463. break;
  464. case QUICHE_H3_EVENT_GOAWAY:
  465. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] <- [GOAWAY]", stream->id);
  466. break;
  467. default:
  468. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] recv, unhandled event %d",
  469. stream->id, quiche_h3_event_type(ev));
  470. break;
  471. }
  472. return result;
  473. }
  474. static CURLcode cf_poll_events(struct Curl_cfilter *cf,
  475. struct Curl_easy *data)
  476. {
  477. struct cf_quiche_ctx *ctx = cf->ctx;
  478. struct stream_ctx *stream = NULL;
  479. struct Curl_easy *sdata;
  480. quiche_h3_event *ev;
  481. CURLcode result;
  482. /* Take in the events and distribute them to the transfers. */
  483. while(ctx->h3c) {
  484. curl_int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev);
  485. if(stream3_id == QUICHE_H3_ERR_DONE) {
  486. break;
  487. }
  488. else if(stream3_id < 0) {
  489. CURL_TRC_CF(data, cf, "error poll: %"CURL_PRId64, stream3_id);
  490. return CURLE_HTTP3;
  491. }
  492. sdata = get_stream_easy(cf, data, stream3_id, &stream);
  493. if(!sdata || !stream) {
  494. CURL_TRC_CF(data, cf, "discard event %s for unknown [%"CURL_PRId64"]",
  495. cf_ev_name(ev), stream3_id);
  496. }
  497. else {
  498. result = h3_process_event(cf, sdata, stream, ev);
  499. drain_stream(cf, sdata);
  500. if(result) {
  501. CURL_TRC_CF(data, cf, "error processing event %s "
  502. "for [%"CURL_PRIu64"] -> %d", cf_ev_name(ev),
  503. stream3_id, result);
  504. if(data == sdata) {
  505. /* Only report this error to the caller if it is about the
  506. * transfer we were called with. Otherwise we fail a transfer
  507. * due to a problem in another one. */
  508. quiche_h3_event_free(ev);
  509. return result;
  510. }
  511. }
  512. quiche_h3_event_free(ev);
  513. }
  514. }
  515. return CURLE_OK;
  516. }
  517. struct recv_ctx {
  518. struct Curl_cfilter *cf;
  519. struct Curl_easy *data;
  520. int pkts;
  521. };
  522. static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
  523. struct sockaddr_storage *remote_addr,
  524. socklen_t remote_addrlen, int ecn,
  525. void *userp)
  526. {
  527. struct recv_ctx *r = userp;
  528. struct cf_quiche_ctx *ctx = r->cf->ctx;
  529. quiche_recv_info recv_info;
  530. ssize_t nread;
  531. (void)ecn;
  532. ++r->pkts;
  533. recv_info.to = (struct sockaddr *)&ctx->q.local_addr;
  534. recv_info.to_len = ctx->q.local_addrlen;
  535. recv_info.from = (struct sockaddr *)remote_addr;
  536. recv_info.from_len = remote_addrlen;
  537. nread = quiche_conn_recv(ctx->qconn, (unsigned char *)pkt, pktlen,
  538. &recv_info);
  539. if(nread < 0) {
  540. if(QUICHE_ERR_DONE == nread) {
  541. CURL_TRC_CF(r->data, r->cf, "ingress, quiche is DONE");
  542. return CURLE_OK;
  543. }
  544. else if(QUICHE_ERR_TLS_FAIL == nread) {
  545. long verify_ok = SSL_get_verify_result(ctx->tls.ossl.ssl);
  546. if(verify_ok != X509_V_OK) {
  547. failf(r->data, "SSL certificate problem: %s",
  548. X509_verify_cert_error_string(verify_ok));
  549. return CURLE_PEER_FAILED_VERIFICATION;
  550. }
  551. }
  552. else {
  553. failf(r->data, "quiche_conn_recv() == %zd", nread);
  554. return CURLE_RECV_ERROR;
  555. }
  556. }
  557. else if((size_t)nread < pktlen) {
  558. CURL_TRC_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes",
  559. nread, pktlen);
  560. }
  561. return CURLE_OK;
  562. }
  563. static CURLcode cf_process_ingress(struct Curl_cfilter *cf,
  564. struct Curl_easy *data)
  565. {
  566. struct cf_quiche_ctx *ctx = cf->ctx;
  567. struct recv_ctx rctx;
  568. CURLcode result;
  569. DEBUGASSERT(ctx->qconn);
  570. result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
  571. if(result)
  572. return result;
  573. rctx.cf = cf;
  574. rctx.data = data;
  575. rctx.pkts = 0;
  576. result = vquic_recv_packets(cf, data, &ctx->q, 1000, recv_pkt, &rctx);
  577. if(result)
  578. return result;
  579. if(rctx.pkts > 0) {
  580. /* quiche digested ingress packets. It might have opened flow control
  581. * windows again. */
  582. check_resumes(cf, data);
  583. }
  584. return cf_poll_events(cf, data);
  585. }
  586. struct read_ctx {
  587. struct Curl_cfilter *cf;
  588. struct Curl_easy *data;
  589. quiche_send_info send_info;
  590. };
  591. static ssize_t read_pkt_to_send(void *userp,
  592. unsigned char *buf, size_t buflen,
  593. CURLcode *err)
  594. {
  595. struct read_ctx *x = userp;
  596. struct cf_quiche_ctx *ctx = x->cf->ctx;
  597. ssize_t nwritten;
  598. nwritten = quiche_conn_send(ctx->qconn, buf, buflen, &x->send_info);
  599. if(nwritten == QUICHE_ERR_DONE) {
  600. *err = CURLE_AGAIN;
  601. return -1;
  602. }
  603. if(nwritten < 0) {
  604. failf(x->data, "quiche_conn_send returned %zd", nwritten);
  605. *err = CURLE_SEND_ERROR;
  606. return -1;
  607. }
  608. *err = CURLE_OK;
  609. return nwritten;
  610. }
  611. /*
  612. * flush_egress drains the buffers and sends off data.
  613. * Calls failf() on errors.
  614. */
  615. static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
  616. struct Curl_easy *data)
  617. {
  618. struct cf_quiche_ctx *ctx = cf->ctx;
  619. ssize_t nread;
  620. CURLcode result;
  621. curl_int64_t expiry_ns;
  622. curl_int64_t timeout_ns;
  623. struct read_ctx readx;
  624. size_t pkt_count, gsolen;
  625. expiry_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
  626. if(!expiry_ns) {
  627. quiche_conn_on_timeout(ctx->qconn);
  628. if(quiche_conn_is_closed(ctx->qconn)) {
  629. if(quiche_conn_is_timed_out(ctx->qconn))
  630. failf(data, "connection closed by idle timeout");
  631. else
  632. failf(data, "connection closed by server");
  633. /* Connection timed out, expire all transfers belonging to it
  634. * as will not get any more POLL events here. */
  635. cf_quiche_expire_conn_transfers(cf, data);
  636. return CURLE_SEND_ERROR;
  637. }
  638. }
  639. result = vquic_flush(cf, data, &ctx->q);
  640. if(result) {
  641. if(result == CURLE_AGAIN) {
  642. Curl_expire(data, 1, EXPIRE_QUIC);
  643. return CURLE_OK;
  644. }
  645. return result;
  646. }
  647. readx.cf = cf;
  648. readx.data = data;
  649. memset(&readx.send_info, 0, sizeof(readx.send_info));
  650. pkt_count = 0;
  651. gsolen = quiche_conn_max_send_udp_payload_size(ctx->qconn);
  652. for(;;) {
  653. /* add the next packet to send, if any, to our buffer */
  654. nread = Curl_bufq_sipn(&ctx->q.sendbuf, 0,
  655. read_pkt_to_send, &readx, &result);
  656. if(nread < 0) {
  657. if(result != CURLE_AGAIN)
  658. return result;
  659. /* Nothing more to add, flush and leave */
  660. result = vquic_send(cf, data, &ctx->q, gsolen);
  661. if(result) {
  662. if(result == CURLE_AGAIN) {
  663. Curl_expire(data, 1, EXPIRE_QUIC);
  664. return CURLE_OK;
  665. }
  666. return result;
  667. }
  668. goto out;
  669. }
  670. ++pkt_count;
  671. if((size_t)nread < gsolen || pkt_count >= MAX_PKT_BURST) {
  672. result = vquic_send(cf, data, &ctx->q, gsolen);
  673. if(result) {
  674. if(result == CURLE_AGAIN) {
  675. Curl_expire(data, 1, EXPIRE_QUIC);
  676. return CURLE_OK;
  677. }
  678. goto out;
  679. }
  680. pkt_count = 0;
  681. }
  682. }
  683. out:
  684. timeout_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
  685. if(timeout_ns % 1000000)
  686. timeout_ns += 1000000;
  687. /* expire resolution is milliseconds */
  688. Curl_expire(data, (timeout_ns / 1000000), EXPIRE_QUIC);
  689. return result;
  690. }
  691. static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
  692. struct Curl_easy *data,
  693. CURLcode *err)
  694. {
  695. struct cf_quiche_ctx *ctx = cf->ctx;
  696. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  697. ssize_t nread = -1;
  698. DEBUGASSERT(stream);
  699. if(stream->reset) {
  700. failf(data,
  701. "HTTP/3 stream %" CURL_PRIu64 " reset by server", stream->id);
  702. *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP3;
  703. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_recv, was reset -> %d",
  704. stream->id, *err);
  705. }
  706. else if(!stream->resp_got_header) {
  707. failf(data,
  708. "HTTP/3 stream %" CURL_PRIu64 " was closed cleanly, but before "
  709. "getting all response header fields, treated as error",
  710. stream->id);
  711. /* *err = CURLE_PARTIAL_FILE; */
  712. *err = CURLE_HTTP3;
  713. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_recv, closed incomplete"
  714. " -> %d", stream->id, *err);
  715. }
  716. else {
  717. *err = CURLE_OK;
  718. nread = 0;
  719. }
  720. return nread;
  721. }
  722. static ssize_t cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  723. char *buf, size_t len, CURLcode *err)
  724. {
  725. struct cf_quiche_ctx *ctx = cf->ctx;
  726. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  727. ssize_t nread = -1;
  728. CURLcode result;
  729. vquic_ctx_update_time(&ctx->q);
  730. if(!stream) {
  731. *err = CURLE_RECV_ERROR;
  732. return -1;
  733. }
  734. if(!Curl_bufq_is_empty(&stream->recvbuf)) {
  735. nread = Curl_bufq_read(&stream->recvbuf,
  736. (unsigned char *)buf, len, err);
  737. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] read recvbuf(len=%zu) "
  738. "-> %zd, %d", stream->id, len, nread, *err);
  739. if(nread < 0)
  740. goto out;
  741. }
  742. if(cf_process_ingress(cf, data)) {
  743. CURL_TRC_CF(data, cf, "cf_recv, error on ingress");
  744. *err = CURLE_RECV_ERROR;
  745. nread = -1;
  746. goto out;
  747. }
  748. /* recvbuf had nothing before, maybe after progressing ingress? */
  749. if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
  750. nread = Curl_bufq_read(&stream->recvbuf,
  751. (unsigned char *)buf, len, err);
  752. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] read recvbuf(len=%zu) "
  753. "-> %zd, %d", stream->id, len, nread, *err);
  754. if(nread < 0)
  755. goto out;
  756. }
  757. if(nread > 0) {
  758. if(stream->closed)
  759. drain_stream(cf, data);
  760. }
  761. else {
  762. if(stream->closed) {
  763. nread = recv_closed_stream(cf, data, err);
  764. goto out;
  765. }
  766. else if(quiche_conn_is_draining(ctx->qconn)) {
  767. failf(data, "QUIC connection is draining");
  768. *err = CURLE_HTTP3;
  769. nread = -1;
  770. goto out;
  771. }
  772. *err = CURLE_AGAIN;
  773. nread = -1;
  774. }
  775. out:
  776. result = cf_flush_egress(cf, data);
  777. if(result) {
  778. CURL_TRC_CF(data, cf, "cf_recv, flush egress failed");
  779. *err = result;
  780. nread = -1;
  781. }
  782. if(nread > 0)
  783. ctx->data_recvd += nread;
  784. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] cf_recv(total=%"
  785. CURL_FORMAT_CURL_OFF_T ") -> %zd, %d",
  786. stream->id, ctx->data_recvd, nread, *err);
  787. return nread;
  788. }
  789. /* Index where :authority header field will appear in request header
  790. field list. */
  791. #define AUTHORITY_DST_IDX 3
  792. static ssize_t h3_open_stream(struct Curl_cfilter *cf,
  793. struct Curl_easy *data,
  794. const void *buf, size_t len,
  795. CURLcode *err)
  796. {
  797. struct cf_quiche_ctx *ctx = cf->ctx;
  798. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  799. size_t nheader, i;
  800. curl_int64_t stream3_id;
  801. struct dynhds h2_headers;
  802. quiche_h3_header *nva = NULL;
  803. ssize_t nwritten;
  804. if(!stream) {
  805. *err = h3_data_setup(cf, data);
  806. if(*err) {
  807. return -1;
  808. }
  809. stream = H3_STREAM_CTX(ctx, data);
  810. DEBUGASSERT(stream);
  811. }
  812. Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
  813. DEBUGASSERT(stream);
  814. nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
  815. if(nwritten < 0)
  816. goto out;
  817. if(!stream->h1.done) {
  818. /* need more data */
  819. goto out;
  820. }
  821. DEBUGASSERT(stream->h1.req);
  822. *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
  823. if(*err) {
  824. nwritten = -1;
  825. goto out;
  826. }
  827. /* no longer needed */
  828. Curl_h1_req_parse_free(&stream->h1);
  829. nheader = Curl_dynhds_count(&h2_headers);
  830. nva = malloc(sizeof(quiche_h3_header) * nheader);
  831. if(!nva) {
  832. *err = CURLE_OUT_OF_MEMORY;
  833. nwritten = -1;
  834. goto out;
  835. }
  836. for(i = 0; i < nheader; ++i) {
  837. struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
  838. nva[i].name = (unsigned char *)e->name;
  839. nva[i].name_len = e->namelen;
  840. nva[i].value = (unsigned char *)e->value;
  841. nva[i].value_len = e->valuelen;
  842. }
  843. switch(data->state.httpreq) {
  844. case HTTPREQ_POST:
  845. case HTTPREQ_POST_FORM:
  846. case HTTPREQ_POST_MIME:
  847. case HTTPREQ_PUT:
  848. if(data->state.infilesize != -1)
  849. stream->upload_left = data->state.infilesize;
  850. else
  851. /* data sending without specifying the data amount up front */
  852. stream->upload_left = -1; /* unknown */
  853. break;
  854. default:
  855. stream->upload_left = 0; /* no request body */
  856. break;
  857. }
  858. if(stream->upload_left == 0)
  859. stream->send_closed = TRUE;
  860. stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader,
  861. stream->send_closed);
  862. if(stream3_id < 0) {
  863. if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) {
  864. /* quiche seems to report this error if the connection window is
  865. * exhausted. Which happens frequently and intermittent. */
  866. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] blocked", stream->id);
  867. stream->quic_flow_blocked = TRUE;
  868. *err = CURLE_AGAIN;
  869. nwritten = -1;
  870. goto out;
  871. }
  872. else {
  873. CURL_TRC_CF(data, cf, "send_request(%s) -> %" CURL_PRIu64,
  874. data->state.url, stream3_id);
  875. }
  876. *err = CURLE_SEND_ERROR;
  877. nwritten = -1;
  878. goto out;
  879. }
  880. DEBUGASSERT(!stream->opened);
  881. *err = CURLE_OK;
  882. stream->id = stream3_id;
  883. stream->opened = TRUE;
  884. stream->closed = FALSE;
  885. stream->reset = FALSE;
  886. if(Curl_trc_is_verbose(data)) {
  887. infof(data, "[HTTP/3] [%" CURL_PRIu64 "] OPENED stream for %s",
  888. stream->id, data->state.url);
  889. for(i = 0; i < nheader; ++i) {
  890. infof(data, "[HTTP/3] [%" CURL_PRIu64 "] [%.*s: %.*s]", stream->id,
  891. (int)nva[i].name_len, nva[i].name,
  892. (int)nva[i].value_len, nva[i].value);
  893. }
  894. }
  895. out:
  896. free(nva);
  897. Curl_dynhds_free(&h2_headers);
  898. return nwritten;
  899. }
  900. static ssize_t cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  901. const void *buf, size_t len, CURLcode *err)
  902. {
  903. struct cf_quiche_ctx *ctx = cf->ctx;
  904. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  905. CURLcode result;
  906. ssize_t nwritten;
  907. vquic_ctx_update_time(&ctx->q);
  908. *err = cf_process_ingress(cf, data);
  909. if(*err) {
  910. nwritten = -1;
  911. goto out;
  912. }
  913. if(!stream || !stream->opened) {
  914. nwritten = h3_open_stream(cf, data, buf, len, err);
  915. if(nwritten < 0)
  916. goto out;
  917. stream = H3_STREAM_CTX(ctx, data);
  918. }
  919. else if(stream->closed) {
  920. if(stream->resp_hds_complete) {
  921. /* sending request body on a stream that has been closed by the
  922. * server. If the server has send us a final response, we should
  923. * silently discard the send data.
  924. * This happens for example on redirects where the server, instead
  925. * of reading the full request body just closed the stream after
  926. * sending the 30x response.
  927. * This is sort of a race: had the transfer loop called recv first,
  928. * it would see the response and stop/discard sending on its own- */
  929. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] discarding data"
  930. "on closed stream with response", stream->id);
  931. *err = CURLE_OK;
  932. nwritten = (ssize_t)len;
  933. goto out;
  934. }
  935. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
  936. "-> stream closed", stream->id, len);
  937. *err = CURLE_HTTP3;
  938. nwritten = -1;
  939. goto out;
  940. }
  941. else {
  942. bool eof = (stream->upload_left >= 0 &&
  943. (curl_off_t)len >= stream->upload_left);
  944. nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id,
  945. (uint8_t *)buf, len, eof);
  946. if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) {
  947. /* TODO: we seem to be blocked on flow control and should HOLD
  948. * sending. But when do we open again? */
  949. if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) {
  950. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
  951. "-> window exhausted", stream->id, len);
  952. stream->quic_flow_blocked = TRUE;
  953. }
  954. *err = CURLE_AGAIN;
  955. nwritten = -1;
  956. goto out;
  957. }
  958. else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) {
  959. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
  960. "-> invalid stream state", stream->id, len);
  961. *err = CURLE_HTTP3;
  962. nwritten = -1;
  963. goto out;
  964. }
  965. else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) {
  966. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
  967. "-> exceeds size", stream->id, len);
  968. *err = CURLE_SEND_ERROR;
  969. nwritten = -1;
  970. goto out;
  971. }
  972. else if(nwritten < 0) {
  973. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send_body(len=%zu) "
  974. "-> quiche err %zd", stream->id, len, nwritten);
  975. *err = CURLE_SEND_ERROR;
  976. nwritten = -1;
  977. goto out;
  978. }
  979. else {
  980. /* quiche accepted all or at least a part of the buf */
  981. if(stream->upload_left > 0) {
  982. stream->upload_left = (nwritten < stream->upload_left)?
  983. (stream->upload_left - nwritten) : 0;
  984. }
  985. if(stream->upload_left == 0)
  986. stream->send_closed = TRUE;
  987. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] send body(len=%zu, "
  988. "left=%" CURL_FORMAT_CURL_OFF_T ") -> %zd",
  989. stream->id, len, stream->upload_left, nwritten);
  990. *err = CURLE_OK;
  991. }
  992. }
  993. out:
  994. result = cf_flush_egress(cf, data);
  995. if(result) {
  996. *err = result;
  997. nwritten = -1;
  998. }
  999. CURL_TRC_CF(data, cf, "[%" CURL_PRIu64 "] cf_send(len=%zu) -> %zd, %d",
  1000. stream? stream->id : -1, len, nwritten, *err);
  1001. return nwritten;
  1002. }
  1003. static bool stream_is_writeable(struct Curl_cfilter *cf,
  1004. struct Curl_easy *data)
  1005. {
  1006. struct cf_quiche_ctx *ctx = cf->ctx;
  1007. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  1008. return stream && (quiche_conn_stream_writable(
  1009. ctx->qconn, (curl_uint64_t)stream->id, 1) > 0);
  1010. }
  1011. static void cf_quiche_adjust_pollset(struct Curl_cfilter *cf,
  1012. struct Curl_easy *data,
  1013. struct easy_pollset *ps)
  1014. {
  1015. struct cf_quiche_ctx *ctx = cf->ctx;
  1016. bool want_recv, want_send;
  1017. if(!ctx->qconn)
  1018. return;
  1019. Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
  1020. if(want_recv || want_send) {
  1021. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  1022. bool c_exhaust, s_exhaust;
  1023. c_exhaust = FALSE; /* Have not found any call in quiche that tells
  1024. us if the connection itself is blocked */
  1025. s_exhaust = want_send && stream && stream->opened &&
  1026. (stream->quic_flow_blocked || !stream_is_writeable(cf, data));
  1027. want_recv = (want_recv || c_exhaust || s_exhaust);
  1028. want_send = (!s_exhaust && want_send) ||
  1029. !Curl_bufq_is_empty(&ctx->q.sendbuf);
  1030. Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
  1031. }
  1032. }
  1033. /*
  1034. * Called from transfer.c:data_pending to know if we should keep looping
  1035. * to receive more data from the connection.
  1036. */
  1037. static bool cf_quiche_data_pending(struct Curl_cfilter *cf,
  1038. const struct Curl_easy *data)
  1039. {
  1040. struct cf_quiche_ctx *ctx = cf->ctx;
  1041. const struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  1042. (void)cf;
  1043. return stream && !Curl_bufq_is_empty(&stream->recvbuf);
  1044. }
  1045. static CURLcode h3_data_pause(struct Curl_cfilter *cf,
  1046. struct Curl_easy *data,
  1047. bool pause)
  1048. {
  1049. /* TODO: there seems right now no API in quiche to shrink/enlarge
  1050. * the streams windows. As we do in HTTP/2. */
  1051. if(!pause) {
  1052. drain_stream(cf, data);
  1053. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  1054. }
  1055. return CURLE_OK;
  1056. }
  1057. static CURLcode cf_quiche_data_event(struct Curl_cfilter *cf,
  1058. struct Curl_easy *data,
  1059. int event, int arg1, void *arg2)
  1060. {
  1061. struct cf_quiche_ctx *ctx = cf->ctx;
  1062. CURLcode result = CURLE_OK;
  1063. (void)arg1;
  1064. (void)arg2;
  1065. switch(event) {
  1066. case CF_CTRL_DATA_SETUP:
  1067. break;
  1068. case CF_CTRL_DATA_PAUSE:
  1069. result = h3_data_pause(cf, data, (arg1 != 0));
  1070. break;
  1071. case CF_CTRL_DATA_DETACH:
  1072. h3_data_done(cf, data);
  1073. break;
  1074. case CF_CTRL_DATA_DONE:
  1075. h3_data_done(cf, data);
  1076. break;
  1077. case CF_CTRL_DATA_DONE_SEND: {
  1078. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  1079. if(stream && !stream->send_closed) {
  1080. unsigned char body[1];
  1081. ssize_t sent;
  1082. stream->send_closed = TRUE;
  1083. stream->upload_left = 0;
  1084. body[0] = 'X';
  1085. sent = cf_quiche_send(cf, data, body, 0, &result);
  1086. CURL_TRC_CF(data, cf, "[%"CURL_PRIu64"] DONE_SEND -> %zd, %d",
  1087. stream->id, sent, result);
  1088. }
  1089. break;
  1090. }
  1091. case CF_CTRL_DATA_IDLE: {
  1092. struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
  1093. if(stream && !stream->closed) {
  1094. result = cf_flush_egress(cf, data);
  1095. if(result)
  1096. CURL_TRC_CF(data, cf, "data idle, flush egress -> %d", result);
  1097. }
  1098. break;
  1099. }
  1100. default:
  1101. break;
  1102. }
  1103. return result;
  1104. }
  1105. static CURLcode cf_connect_start(struct Curl_cfilter *cf,
  1106. struct Curl_easy *data)
  1107. {
  1108. struct cf_quiche_ctx *ctx = cf->ctx;
  1109. int rv;
  1110. CURLcode result;
  1111. const struct Curl_sockaddr_ex *sockaddr;
  1112. DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD);
  1113. #ifdef DEBUG_QUICHE
  1114. /* initialize debug log callback only once */
  1115. static int debug_log_init = 0;
  1116. if(!debug_log_init) {
  1117. quiche_enable_debug_logging(quiche_debug_log, NULL);
  1118. debug_log_init = 1;
  1119. }
  1120. #endif
  1121. ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
  1122. Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
  1123. H3_STREAM_POOL_SPARES);
  1124. Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
  1125. ctx->data_recvd = 0;
  1126. result = vquic_ctx_init(&ctx->q);
  1127. if(result)
  1128. return result;
  1129. result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC);
  1130. if(result)
  1131. return result;
  1132. ctx->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
  1133. if(!ctx->cfg) {
  1134. failf(data, "can't create quiche config");
  1135. return CURLE_FAILED_INIT;
  1136. }
  1137. quiche_config_enable_pacing(ctx->cfg, false);
  1138. quiche_config_set_max_idle_timeout(ctx->cfg, ctx->max_idle_ms * 1000);
  1139. quiche_config_set_initial_max_data(ctx->cfg, (1 * 1024 * 1024)
  1140. /* (QUIC_MAX_STREAMS/2) * H3_STREAM_WINDOW_SIZE */);
  1141. quiche_config_set_initial_max_streams_bidi(ctx->cfg, QUIC_MAX_STREAMS);
  1142. quiche_config_set_initial_max_streams_uni(ctx->cfg, QUIC_MAX_STREAMS);
  1143. quiche_config_set_initial_max_stream_data_bidi_local(ctx->cfg,
  1144. H3_STREAM_WINDOW_SIZE);
  1145. quiche_config_set_initial_max_stream_data_bidi_remote(ctx->cfg,
  1146. H3_STREAM_WINDOW_SIZE);
  1147. quiche_config_set_initial_max_stream_data_uni(ctx->cfg,
  1148. H3_STREAM_WINDOW_SIZE);
  1149. quiche_config_set_disable_active_migration(ctx->cfg, TRUE);
  1150. quiche_config_set_max_connection_window(ctx->cfg,
  1151. 10 * QUIC_MAX_STREAMS * H3_STREAM_WINDOW_SIZE);
  1152. quiche_config_set_max_stream_window(ctx->cfg, 10 * H3_STREAM_WINDOW_SIZE);
  1153. quiche_config_set_application_protos(ctx->cfg,
  1154. (uint8_t *)
  1155. QUICHE_H3_APPLICATION_PROTOCOL,
  1156. sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
  1157. - 1);
  1158. result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
  1159. QUICHE_H3_APPLICATION_PROTOCOL,
  1160. sizeof(QUICHE_H3_APPLICATION_PROTOCOL) - 1,
  1161. NULL, NULL, cf);
  1162. if(result)
  1163. return result;
  1164. result = Curl_rand(data, ctx->scid, sizeof(ctx->scid));
  1165. if(result)
  1166. return result;
  1167. Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd, &sockaddr, NULL);
  1168. ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
  1169. rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
  1170. &ctx->q.local_addrlen);
  1171. if(rv == -1)
  1172. return CURLE_QUIC_CONNECT_ERROR;
  1173. ctx->qconn = quiche_conn_new_with_tls((const uint8_t *)ctx->scid,
  1174. sizeof(ctx->scid), NULL, 0,
  1175. (struct sockaddr *)&ctx->q.local_addr,
  1176. ctx->q.local_addrlen,
  1177. &sockaddr->sa_addr, sockaddr->addrlen,
  1178. ctx->cfg, ctx->tls.ossl.ssl, false);
  1179. if(!ctx->qconn) {
  1180. failf(data, "can't create quiche connection");
  1181. return CURLE_OUT_OF_MEMORY;
  1182. }
  1183. /* Known to not work on Windows */
  1184. #if !defined(_WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
  1185. {
  1186. int qfd;
  1187. (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
  1188. if(qfd != -1)
  1189. quiche_conn_set_qlog_fd(ctx->qconn, qfd,
  1190. "qlog title", "curl qlog");
  1191. }
  1192. #endif
  1193. result = cf_flush_egress(cf, data);
  1194. if(result)
  1195. return result;
  1196. {
  1197. unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
  1198. unsigned alpn_len, offset = 0;
  1199. /* Replace each ALPN length prefix by a comma. */
  1200. while(offset < sizeof(alpn_protocols) - 1) {
  1201. alpn_len = alpn_protocols[offset];
  1202. alpn_protocols[offset] = ',';
  1203. offset += 1 + alpn_len;
  1204. }
  1205. CURL_TRC_CF(data, cf, "Sent QUIC client Initial, ALPN: %s",
  1206. alpn_protocols + 1);
  1207. }
  1208. return CURLE_OK;
  1209. }
  1210. static CURLcode cf_quiche_verify_peer(struct Curl_cfilter *cf,
  1211. struct Curl_easy *data)
  1212. {
  1213. struct cf_quiche_ctx *ctx = cf->ctx;
  1214. cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  1215. cf->conn->httpversion = 30;
  1216. cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  1217. return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
  1218. }
  1219. static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
  1220. struct Curl_easy *data,
  1221. bool blocking, bool *done)
  1222. {
  1223. struct cf_quiche_ctx *ctx = cf->ctx;
  1224. CURLcode result = CURLE_OK;
  1225. if(cf->connected) {
  1226. *done = TRUE;
  1227. return CURLE_OK;
  1228. }
  1229. /* Connect the UDP filter first */
  1230. if(!cf->next->connected) {
  1231. result = Curl_conn_cf_connect(cf->next, data, blocking, done);
  1232. if(result || !*done)
  1233. return result;
  1234. }
  1235. *done = FALSE;
  1236. vquic_ctx_update_time(&ctx->q);
  1237. if(ctx->reconnect_at.tv_sec &&
  1238. Curl_timediff(ctx->q.last_op, ctx->reconnect_at) < 0) {
  1239. /* Not time yet to attempt the next connect */
  1240. CURL_TRC_CF(data, cf, "waiting for reconnect time");
  1241. goto out;
  1242. }
  1243. if(!ctx->qconn) {
  1244. result = cf_connect_start(cf, data);
  1245. if(result)
  1246. goto out;
  1247. ctx->started_at = ctx->q.last_op;
  1248. result = cf_flush_egress(cf, data);
  1249. /* we do not expect to be able to recv anything yet */
  1250. goto out;
  1251. }
  1252. result = cf_process_ingress(cf, data);
  1253. if(result)
  1254. goto out;
  1255. result = cf_flush_egress(cf, data);
  1256. if(result)
  1257. goto out;
  1258. if(quiche_conn_is_established(ctx->qconn)) {
  1259. ctx->handshake_at = ctx->q.last_op;
  1260. CURL_TRC_CF(data, cf, "handshake complete after %dms",
  1261. (int)Curl_timediff(ctx->handshake_at, ctx->started_at));
  1262. result = cf_quiche_verify_peer(cf, data);
  1263. if(!result) {
  1264. CURL_TRC_CF(data, cf, "peer verified");
  1265. ctx->h3config = quiche_h3_config_new();
  1266. if(!ctx->h3config) {
  1267. result = CURLE_OUT_OF_MEMORY;
  1268. goto out;
  1269. }
  1270. /* Create a new HTTP/3 connection on the QUIC connection. */
  1271. ctx->h3c = quiche_h3_conn_new_with_transport(ctx->qconn, ctx->h3config);
  1272. if(!ctx->h3c) {
  1273. result = CURLE_OUT_OF_MEMORY;
  1274. goto out;
  1275. }
  1276. cf->connected = TRUE;
  1277. cf->conn->alpn = CURL_HTTP_VERSION_3;
  1278. *done = TRUE;
  1279. connkeep(cf->conn, "HTTP/3 default");
  1280. }
  1281. }
  1282. else if(quiche_conn_is_draining(ctx->qconn)) {
  1283. /* When a QUIC server instance is shutting down, it may send us a
  1284. * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
  1285. * state. The CONNECT may work in the near future again. Indicate
  1286. * that as a "weird" reply. */
  1287. result = CURLE_WEIRD_SERVER_REPLY;
  1288. }
  1289. out:
  1290. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  1291. if(result && result != CURLE_AGAIN) {
  1292. struct ip_quadruple ip;
  1293. Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
  1294. infof(data, "connect to %s port %u failed: %s",
  1295. ip.remote_ip, ip.remote_port, curl_easy_strerror(result));
  1296. }
  1297. #endif
  1298. return result;
  1299. }
  1300. static void cf_quiche_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  1301. {
  1302. struct cf_quiche_ctx *ctx = cf->ctx;
  1303. if(ctx) {
  1304. if(ctx->qconn) {
  1305. vquic_ctx_update_time(&ctx->q);
  1306. (void)quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
  1307. /* flushing the egress is not a failsafe way to deliver all the
  1308. outstanding packets, but we also don't want to get stuck here... */
  1309. (void)cf_flush_egress(cf, data);
  1310. }
  1311. cf_quiche_ctx_clear(ctx);
  1312. }
  1313. }
  1314. static void cf_quiche_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
  1315. {
  1316. struct cf_quiche_ctx *ctx = cf->ctx;
  1317. (void)data;
  1318. cf_quiche_ctx_clear(ctx);
  1319. free(ctx);
  1320. cf->ctx = NULL;
  1321. }
  1322. static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
  1323. struct Curl_easy *data,
  1324. int query, int *pres1, void *pres2)
  1325. {
  1326. struct cf_quiche_ctx *ctx = cf->ctx;
  1327. switch(query) {
  1328. case CF_QUERY_MAX_CONCURRENT: {
  1329. curl_uint64_t max_streams = CONN_INUSE(cf->conn);
  1330. if(!ctx->goaway) {
  1331. max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn);
  1332. }
  1333. *pres1 = (max_streams > INT_MAX)? INT_MAX : (int)max_streams;
  1334. CURL_TRC_CF(data, cf, "query: MAX_CONCURRENT -> %d", *pres1);
  1335. return CURLE_OK;
  1336. }
  1337. case CF_QUERY_CONNECT_REPLY_MS:
  1338. if(ctx->q.got_first_byte) {
  1339. timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
  1340. *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
  1341. }
  1342. else
  1343. *pres1 = -1;
  1344. return CURLE_OK;
  1345. case CF_QUERY_TIMER_CONNECT: {
  1346. struct curltime *when = pres2;
  1347. if(ctx->q.got_first_byte)
  1348. *when = ctx->q.first_byte_at;
  1349. return CURLE_OK;
  1350. }
  1351. case CF_QUERY_TIMER_APPCONNECT: {
  1352. struct curltime *when = pres2;
  1353. if(cf->connected)
  1354. *when = ctx->handshake_at;
  1355. return CURLE_OK;
  1356. }
  1357. default:
  1358. break;
  1359. }
  1360. return cf->next?
  1361. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  1362. CURLE_UNKNOWN_OPTION;
  1363. }
  1364. static bool cf_quiche_conn_is_alive(struct Curl_cfilter *cf,
  1365. struct Curl_easy *data,
  1366. bool *input_pending)
  1367. {
  1368. struct cf_quiche_ctx *ctx = cf->ctx;
  1369. bool alive = TRUE;
  1370. *input_pending = FALSE;
  1371. if(!ctx->qconn)
  1372. return FALSE;
  1373. /* Both sides of the QUIC connection announce they max idle times in
  1374. * the transport parameters. Look at the minimum of both and if
  1375. * we exceed this, regard the connection as dead. The other side
  1376. * may have completely purged it and will no longer respond
  1377. * to any packets from us. */
  1378. {
  1379. quiche_transport_params qpeerparams;
  1380. timediff_t idletime;
  1381. curl_uint64_t idle_ms = ctx->max_idle_ms;
  1382. if(quiche_conn_peer_transport_params(ctx->qconn, &qpeerparams) &&
  1383. qpeerparams.peer_max_idle_timeout &&
  1384. qpeerparams.peer_max_idle_timeout < idle_ms)
  1385. idle_ms = qpeerparams.peer_max_idle_timeout;
  1386. idletime = Curl_timediff(Curl_now(), cf->conn->lastused);
  1387. if(idletime > 0 && (curl_uint64_t)idletime > idle_ms)
  1388. return FALSE;
  1389. }
  1390. if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
  1391. return FALSE;
  1392. if(*input_pending) {
  1393. /* This happens before we've sent off a request and the connection is
  1394. not in use by any other transfer, there shouldn't be any data here,
  1395. only "protocol frames" */
  1396. *input_pending = FALSE;
  1397. if(cf_process_ingress(cf, data))
  1398. alive = FALSE;
  1399. else {
  1400. alive = TRUE;
  1401. }
  1402. }
  1403. return alive;
  1404. }
  1405. struct Curl_cftype Curl_cft_http3 = {
  1406. "HTTP/3",
  1407. CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
  1408. 0,
  1409. cf_quiche_destroy,
  1410. cf_quiche_connect,
  1411. cf_quiche_close,
  1412. Curl_cf_def_get_host,
  1413. cf_quiche_adjust_pollset,
  1414. cf_quiche_data_pending,
  1415. cf_quiche_send,
  1416. cf_quiche_recv,
  1417. cf_quiche_data_event,
  1418. cf_quiche_conn_is_alive,
  1419. Curl_cf_def_conn_keep_alive,
  1420. cf_quiche_query,
  1421. };
  1422. CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf,
  1423. struct Curl_easy *data,
  1424. struct connectdata *conn,
  1425. const struct Curl_addrinfo *ai)
  1426. {
  1427. struct cf_quiche_ctx *ctx = NULL;
  1428. struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
  1429. CURLcode result;
  1430. (void)data;
  1431. (void)conn;
  1432. ctx = calloc(1, sizeof(*ctx));
  1433. if(!ctx) {
  1434. result = CURLE_OUT_OF_MEMORY;
  1435. goto out;
  1436. }
  1437. result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
  1438. if(result)
  1439. goto out;
  1440. result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
  1441. if(result)
  1442. goto out;
  1443. udp_cf->conn = cf->conn;
  1444. udp_cf->sockindex = cf->sockindex;
  1445. cf->next = udp_cf;
  1446. out:
  1447. *pcf = (!result)? cf : NULL;
  1448. if(result) {
  1449. if(udp_cf)
  1450. Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
  1451. Curl_safefree(cf);
  1452. Curl_safefree(ctx);
  1453. }
  1454. return result;
  1455. }
  1456. bool Curl_conn_is_quiche(const struct Curl_easy *data,
  1457. const struct connectdata *conn,
  1458. int sockindex)
  1459. {
  1460. struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
  1461. (void)data;
  1462. for(; cf; cf = cf->next) {
  1463. if(cf->cft == &Curl_cft_http3)
  1464. return TRUE;
  1465. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  1466. return FALSE;
  1467. }
  1468. return FALSE;
  1469. }
  1470. #endif