curl_ngtcp2.c 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386
  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. #if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
  26. #include <ngtcp2/ngtcp2.h>
  27. #include <nghttp3/nghttp3.h>
  28. #ifdef USE_OPENSSL
  29. #include <openssl/err.h>
  30. #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
  31. #include <ngtcp2/ngtcp2_crypto_boringssl.h>
  32. #else
  33. #include <ngtcp2/ngtcp2_crypto_quictls.h>
  34. #endif
  35. #include "vtls/openssl.h"
  36. #elif defined(USE_GNUTLS)
  37. #include <ngtcp2/ngtcp2_crypto_gnutls.h>
  38. #include "vtls/gtls.h"
  39. #elif defined(USE_WOLFSSL)
  40. #include <ngtcp2/ngtcp2_crypto_wolfssl.h>
  41. #endif
  42. #include "urldata.h"
  43. #include "sendf.h"
  44. #include "strdup.h"
  45. #include "rand.h"
  46. #include "multiif.h"
  47. #include "strcase.h"
  48. #include "cfilters.h"
  49. #include "cf-socket.h"
  50. #include "connect.h"
  51. #include "progress.h"
  52. #include "strerror.h"
  53. #include "dynbuf.h"
  54. #include "http1.h"
  55. #include "select.h"
  56. #include "inet_pton.h"
  57. #include "vquic.h"
  58. #include "vquic_int.h"
  59. #include "vquic-tls.h"
  60. #include "vtls/keylog.h"
  61. #include "vtls/vtls.h"
  62. #include "curl_ngtcp2.h"
  63. #include "warnless.h"
  64. /* The last 3 #include files should be in this order */
  65. #include "curl_printf.h"
  66. #include "curl_memory.h"
  67. #include "memdebug.h"
  68. #define QUIC_MAX_STREAMS (256*1024)
  69. #define QUIC_MAX_DATA (1*1024*1024)
  70. #define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
  71. /* A stream window is the maximum amount we need to buffer for
  72. * each active transfer. We use HTTP/3 flow control and only ACK
  73. * when we take things out of the buffer.
  74. * Chunk size is large enough to take a full DATA frame */
  75. #define H3_STREAM_WINDOW_SIZE (128 * 1024)
  76. #define H3_STREAM_CHUNK_SIZE (16 * 1024)
  77. /* The pool keeps spares around and half of a full stream windows
  78. * seems good. More does not seem to improve performance.
  79. * The benefit of the pool is that stream buffer to not keep
  80. * spares. So memory consumption goes down when streams run empty,
  81. * have a large upload done, etc. */
  82. #define H3_STREAM_POOL_SPARES \
  83. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE ) / 2
  84. /* Receive and Send max number of chunks just follows from the
  85. * chunk size and window size */
  86. #define H3_STREAM_RECV_CHUNKS \
  87. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
  88. #define H3_STREAM_SEND_CHUNKS \
  89. (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE)
  90. /*
  91. * Store ngtcp2 version info in this buffer.
  92. */
  93. void Curl_ngtcp2_ver(char *p, size_t len)
  94. {
  95. const ngtcp2_info *ng2 = ngtcp2_version(0);
  96. const nghttp3_info *ht3 = nghttp3_version(0);
  97. (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
  98. ng2->version_str, ht3->version_str);
  99. }
  100. struct cf_ngtcp2_ctx {
  101. struct cf_quic_ctx q;
  102. struct ssl_peer peer;
  103. struct quic_tls_ctx tls;
  104. ngtcp2_path connected_path;
  105. ngtcp2_conn *qconn;
  106. ngtcp2_cid dcid;
  107. ngtcp2_cid scid;
  108. uint32_t version;
  109. ngtcp2_settings settings;
  110. ngtcp2_transport_params transport_params;
  111. ngtcp2_ccerr last_error;
  112. ngtcp2_crypto_conn_ref conn_ref;
  113. struct cf_call_data call_data;
  114. nghttp3_conn *h3conn;
  115. nghttp3_settings h3settings;
  116. struct curltime started_at; /* time the current attempt started */
  117. struct curltime handshake_at; /* time connect handshake finished */
  118. struct curltime reconnect_at; /* time the next attempt should start */
  119. struct bufc_pool stream_bufcp; /* chunk pool for streams */
  120. size_t max_stream_window; /* max flow window for one stream */
  121. uint64_t max_idle_ms; /* max idle time for QUIC connection */
  122. int qlogfd;
  123. };
  124. /* How to access `call_data` from a cf_ngtcp2 filter */
  125. #undef CF_CTX_CALL_DATA
  126. #define CF_CTX_CALL_DATA(cf) \
  127. ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
  128. /**
  129. * All about the H3 internals of a stream
  130. */
  131. struct h3_stream_ctx {
  132. int64_t id; /* HTTP/3 protocol identifier */
  133. struct bufq sendbuf; /* h3 request body */
  134. struct bufq recvbuf; /* h3 response body */
  135. struct h1_req_parser h1; /* h1 request parsing */
  136. size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
  137. size_t upload_blocked_len; /* the amount written last and EGAINed */
  138. size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
  139. uint64_t error3; /* HTTP/3 stream error code */
  140. curl_off_t upload_left; /* number of request bytes left to upload */
  141. int status_code; /* HTTP status code */
  142. bool resp_hds_complete; /* we have a complete, final response */
  143. bool closed; /* TRUE on stream close */
  144. bool reset; /* TRUE on stream reset */
  145. bool send_closed; /* stream is local closed */
  146. BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
  147. };
  148. #define H3_STREAM_CTX(d) ((struct h3_stream_ctx *)(((d) && (d)->req.p.http)? \
  149. ((struct HTTP *)(d)->req.p.http)->h3_ctx \
  150. : NULL))
  151. #define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
  152. #define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
  153. H3_STREAM_CTX(d)->id : -2)
  154. static CURLcode h3_data_setup(struct Curl_cfilter *cf,
  155. struct Curl_easy *data)
  156. {
  157. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  158. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  159. if(!data || !data->req.p.http) {
  160. failf(data, "initialization failure, transfer not http initialized");
  161. return CURLE_FAILED_INIT;
  162. }
  163. if(stream)
  164. return CURLE_OK;
  165. stream = calloc(1, sizeof(*stream));
  166. if(!stream)
  167. return CURLE_OUT_OF_MEMORY;
  168. stream->id = -1;
  169. /* on send, we control how much we put into the buffer */
  170. Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp,
  171. H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE);
  172. stream->sendbuf_len_in_flight = 0;
  173. /* on recv, we need a flexible buffer limit since we also write
  174. * headers to it that are not counted against the nghttp3 flow limits. */
  175. Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp,
  176. H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
  177. stream->recv_buf_nonflow = 0;
  178. Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN);
  179. H3_STREAM_LCTX(data) = stream;
  180. return CURLE_OK;
  181. }
  182. static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
  183. {
  184. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  185. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  186. (void)cf;
  187. if(stream) {
  188. CURL_TRC_CF(data, cf, "[%"PRId64"] easy handle is done", stream->id);
  189. if(ctx->h3conn && !stream->closed) {
  190. nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream->id);
  191. nghttp3_conn_close_stream(ctx->h3conn, stream->id,
  192. NGHTTP3_H3_REQUEST_CANCELLED);
  193. nghttp3_conn_set_stream_user_data(ctx->h3conn, stream->id, NULL);
  194. ngtcp2_conn_set_stream_user_data(ctx->qconn, stream->id, NULL);
  195. stream->closed = TRUE;
  196. }
  197. Curl_bufq_free(&stream->sendbuf);
  198. Curl_bufq_free(&stream->recvbuf);
  199. Curl_h1_req_parse_free(&stream->h1);
  200. free(stream);
  201. H3_STREAM_LCTX(data) = NULL;
  202. }
  203. }
  204. static struct Curl_easy *get_stream_easy(struct Curl_cfilter *cf,
  205. struct Curl_easy *data,
  206. int64_t stream_id)
  207. {
  208. struct Curl_easy *sdata;
  209. (void)cf;
  210. if(H3_STREAM_ID(data) == stream_id) {
  211. return data;
  212. }
  213. else {
  214. DEBUGASSERT(data->multi);
  215. for(sdata = data->multi->easyp; sdata; sdata = sdata->next) {
  216. if((sdata->conn == data->conn) && H3_STREAM_ID(sdata) == stream_id) {
  217. return sdata;
  218. }
  219. }
  220. }
  221. return NULL;
  222. }
  223. static void h3_drain_stream(struct Curl_cfilter *cf,
  224. struct Curl_easy *data)
  225. {
  226. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  227. unsigned char bits;
  228. (void)cf;
  229. bits = CURL_CSELECT_IN;
  230. if(stream && stream->upload_left && !stream->send_closed)
  231. bits |= CURL_CSELECT_OUT;
  232. if(data->state.select_bits != bits) {
  233. data->state.select_bits = bits;
  234. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  235. }
  236. }
  237. /* ngtcp2 default congestion controller does not perform pacing. Limit
  238. the maximum packet burst to MAX_PKT_BURST packets. */
  239. #define MAX_PKT_BURST 10
  240. struct pkt_io_ctx {
  241. struct Curl_cfilter *cf;
  242. struct Curl_easy *data;
  243. ngtcp2_tstamp ts;
  244. size_t pkt_count;
  245. ngtcp2_path_storage ps;
  246. };
  247. static void pktx_update_time(struct pkt_io_ctx *pktx,
  248. struct Curl_cfilter *cf)
  249. {
  250. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  251. vquic_ctx_update_time(&ctx->q);
  252. pktx->ts = ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
  253. ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
  254. }
  255. static void pktx_init(struct pkt_io_ctx *pktx,
  256. struct Curl_cfilter *cf,
  257. struct Curl_easy *data)
  258. {
  259. pktx->cf = cf;
  260. pktx->data = data;
  261. pktx->pkt_count = 0;
  262. ngtcp2_path_storage_zero(&pktx->ps);
  263. pktx_update_time(pktx, cf);
  264. }
  265. static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
  266. struct Curl_easy *data,
  267. struct pkt_io_ctx *pktx);
  268. static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
  269. struct Curl_easy *data,
  270. struct pkt_io_ctx *pktx);
  271. static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
  272. uint64_t datalen, void *user_data,
  273. void *stream_user_data);
  274. static ngtcp2_conn *get_conn(ngtcp2_crypto_conn_ref *conn_ref)
  275. {
  276. struct Curl_cfilter *cf = conn_ref->user_data;
  277. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  278. return ctx->qconn;
  279. }
  280. #ifdef DEBUG_NGTCP2
  281. static void quic_printf(void *user_data, const char *fmt, ...)
  282. {
  283. struct Curl_cfilter *cf = user_data;
  284. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  285. (void)ctx; /* TODO: need an easy handle to infof() message */
  286. va_list ap;
  287. va_start(ap, fmt);
  288. vfprintf(stderr, fmt, ap);
  289. va_end(ap);
  290. fprintf(stderr, "\n");
  291. }
  292. #endif
  293. static void qlog_callback(void *user_data, uint32_t flags,
  294. const void *data, size_t datalen)
  295. {
  296. struct Curl_cfilter *cf = user_data;
  297. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  298. (void)flags;
  299. if(ctx->qlogfd != -1) {
  300. ssize_t rc = write(ctx->qlogfd, data, datalen);
  301. if(rc == -1) {
  302. /* on write error, stop further write attempts */
  303. close(ctx->qlogfd);
  304. ctx->qlogfd = -1;
  305. }
  306. }
  307. }
  308. static void quic_settings(struct cf_ngtcp2_ctx *ctx,
  309. struct Curl_easy *data,
  310. struct pkt_io_ctx *pktx)
  311. {
  312. ngtcp2_settings *s = &ctx->settings;
  313. ngtcp2_transport_params *t = &ctx->transport_params;
  314. ngtcp2_settings_default(s);
  315. ngtcp2_transport_params_default(t);
  316. #ifdef DEBUG_NGTCP2
  317. s->log_printf = quic_printf;
  318. #else
  319. s->log_printf = NULL;
  320. #endif
  321. (void)data;
  322. s->initial_ts = pktx->ts;
  323. s->handshake_timeout = QUIC_HANDSHAKE_TIMEOUT;
  324. s->max_window = 100 * ctx->max_stream_window;
  325. s->max_stream_window = ctx->max_stream_window;
  326. t->initial_max_data = 10 * ctx->max_stream_window;
  327. t->initial_max_stream_data_bidi_local = ctx->max_stream_window;
  328. t->initial_max_stream_data_bidi_remote = ctx->max_stream_window;
  329. t->initial_max_stream_data_uni = ctx->max_stream_window;
  330. t->initial_max_streams_bidi = QUIC_MAX_STREAMS;
  331. t->initial_max_streams_uni = QUIC_MAX_STREAMS;
  332. t->max_idle_timeout = (ctx->max_idle_ms * NGTCP2_MILLISECONDS);
  333. if(ctx->qlogfd != -1) {
  334. s->qlog_write = qlog_callback;
  335. }
  336. }
  337. static int init_ngh3_conn(struct Curl_cfilter *cf);
  338. static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
  339. {
  340. (void)user_data;
  341. (void)tconn;
  342. return 0;
  343. }
  344. static void report_consumed_data(struct Curl_cfilter *cf,
  345. struct Curl_easy *data,
  346. size_t consumed)
  347. {
  348. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  349. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  350. if(!stream)
  351. return;
  352. /* the HTTP/1.1 response headers are written to the buffer, but
  353. * consuming those does not count against flow control. */
  354. if(stream->recv_buf_nonflow) {
  355. if(consumed >= stream->recv_buf_nonflow) {
  356. consumed -= stream->recv_buf_nonflow;
  357. stream->recv_buf_nonflow = 0;
  358. }
  359. else {
  360. stream->recv_buf_nonflow -= consumed;
  361. consumed = 0;
  362. }
  363. }
  364. if(consumed > 0) {
  365. CURL_TRC_CF(data, cf, "[%" PRId64 "] ACK %zu bytes of DATA",
  366. stream->id, consumed);
  367. ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id,
  368. consumed);
  369. ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
  370. }
  371. }
  372. static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
  373. int64_t stream_id, uint64_t offset,
  374. const uint8_t *buf, size_t buflen,
  375. void *user_data, void *stream_user_data)
  376. {
  377. struct Curl_cfilter *cf = user_data;
  378. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  379. nghttp3_ssize nconsumed;
  380. int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0;
  381. struct Curl_easy *data = stream_user_data;
  382. (void)offset;
  383. (void)data;
  384. nconsumed =
  385. nghttp3_conn_read_stream(ctx->h3conn, stream_id, buf, buflen, fin);
  386. CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd",
  387. stream_id, buflen, nconsumed);
  388. if(nconsumed < 0) {
  389. if(!data) {
  390. struct Curl_easy *cdata = CF_DATA_CURRENT(cf);
  391. CURL_TRC_CF(cdata, cf, "[%" PRId64 "] nghttp3 error on stream not "
  392. "used by us, ignored", stream_id);
  393. return 0;
  394. }
  395. ngtcp2_ccerr_set_application_error(
  396. &ctx->last_error,
  397. nghttp3_err_infer_quic_app_error_code((int)nconsumed), NULL, 0);
  398. return NGTCP2_ERR_CALLBACK_FAILURE;
  399. }
  400. /* number of bytes inside buflen which consists of framing overhead
  401. * including QPACK HEADERS. In other words, it does not consume payload of
  402. * DATA frame. */
  403. ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);
  404. ngtcp2_conn_extend_max_offset(tconn, nconsumed);
  405. return 0;
  406. }
  407. static int
  408. cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
  409. uint64_t offset, uint64_t datalen, void *user_data,
  410. void *stream_user_data)
  411. {
  412. struct Curl_cfilter *cf = user_data;
  413. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  414. int rv;
  415. (void)stream_id;
  416. (void)tconn;
  417. (void)offset;
  418. (void)datalen;
  419. (void)stream_user_data;
  420. rv = nghttp3_conn_add_ack_offset(ctx->h3conn, stream_id, datalen);
  421. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  422. return NGTCP2_ERR_CALLBACK_FAILURE;
  423. }
  424. return 0;
  425. }
  426. static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
  427. int64_t stream3_id, uint64_t app_error_code,
  428. void *user_data, void *stream_user_data)
  429. {
  430. struct Curl_cfilter *cf = user_data;
  431. struct Curl_easy *data = stream_user_data;
  432. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  433. int rv;
  434. (void)tconn;
  435. (void)data;
  436. /* stream is closed... */
  437. if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
  438. app_error_code = NGHTTP3_H3_NO_ERROR;
  439. }
  440. rv = nghttp3_conn_close_stream(ctx->h3conn, stream3_id,
  441. app_error_code);
  442. CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(err=%"
  443. PRIu64 ") -> %d", stream3_id, app_error_code, rv);
  444. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  445. ngtcp2_ccerr_set_application_error(
  446. &ctx->last_error, nghttp3_err_infer_quic_app_error_code(rv), NULL, 0);
  447. return NGTCP2_ERR_CALLBACK_FAILURE;
  448. }
  449. return 0;
  450. }
  451. static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
  452. uint64_t final_size, uint64_t app_error_code,
  453. void *user_data, void *stream_user_data)
  454. {
  455. struct Curl_cfilter *cf = user_data;
  456. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  457. struct Curl_easy *data = stream_user_data;
  458. int rv;
  459. (void)tconn;
  460. (void)final_size;
  461. (void)app_error_code;
  462. (void)data;
  463. rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
  464. CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
  465. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  466. return NGTCP2_ERR_CALLBACK_FAILURE;
  467. }
  468. return 0;
  469. }
  470. static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
  471. uint64_t app_error_code, void *user_data,
  472. void *stream_user_data)
  473. {
  474. struct Curl_cfilter *cf = user_data;
  475. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  476. int rv;
  477. (void)tconn;
  478. (void)app_error_code;
  479. (void)stream_user_data;
  480. rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id);
  481. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  482. return NGTCP2_ERR_CALLBACK_FAILURE;
  483. }
  484. return 0;
  485. }
  486. static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
  487. uint64_t max_streams,
  488. void *user_data)
  489. {
  490. (void)tconn;
  491. (void)max_streams;
  492. (void)user_data;
  493. return 0;
  494. }
  495. static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
  496. uint64_t max_data, void *user_data,
  497. void *stream_user_data)
  498. {
  499. struct Curl_cfilter *cf = user_data;
  500. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  501. struct Curl_easy *data = CF_DATA_CURRENT(cf);
  502. struct Curl_easy *s_data;
  503. struct h3_stream_ctx *stream;
  504. int rv;
  505. (void)tconn;
  506. (void)max_data;
  507. (void)stream_user_data;
  508. rv = nghttp3_conn_unblock_stream(ctx->h3conn, stream_id);
  509. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  510. return NGTCP2_ERR_CALLBACK_FAILURE;
  511. }
  512. s_data = get_stream_easy(cf, data, stream_id);
  513. stream = H3_STREAM_CTX(s_data);
  514. if(stream && stream->quic_flow_blocked) {
  515. CURL_TRC_CF(data, cf, "[%" PRId64 "] unblock quic flow", stream_id);
  516. stream->quic_flow_blocked = FALSE;
  517. h3_drain_stream(cf, data);
  518. }
  519. return 0;
  520. }
  521. static void cb_rand(uint8_t *dest, size_t destlen,
  522. const ngtcp2_rand_ctx *rand_ctx)
  523. {
  524. CURLcode result;
  525. (void)rand_ctx;
  526. result = Curl_rand(NULL, dest, destlen);
  527. if(result) {
  528. /* cb_rand is only used for non-cryptographic context. If Curl_rand
  529. failed, just fill 0 and call it *random*. */
  530. memset(dest, 0, destlen);
  531. }
  532. }
  533. static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
  534. uint8_t *token, size_t cidlen,
  535. void *user_data)
  536. {
  537. CURLcode result;
  538. (void)tconn;
  539. (void)user_data;
  540. result = Curl_rand(NULL, cid->data, cidlen);
  541. if(result)
  542. return NGTCP2_ERR_CALLBACK_FAILURE;
  543. cid->datalen = cidlen;
  544. result = Curl_rand(NULL, token, NGTCP2_STATELESS_RESET_TOKENLEN);
  545. if(result)
  546. return NGTCP2_ERR_CALLBACK_FAILURE;
  547. return 0;
  548. }
  549. static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level,
  550. void *user_data)
  551. {
  552. struct Curl_cfilter *cf = user_data;
  553. (void)tconn;
  554. if(level != NGTCP2_ENCRYPTION_LEVEL_1RTT) {
  555. return 0;
  556. }
  557. if(init_ngh3_conn(cf) != CURLE_OK) {
  558. return NGTCP2_ERR_CALLBACK_FAILURE;
  559. }
  560. return 0;
  561. }
  562. static ngtcp2_callbacks ng_callbacks = {
  563. ngtcp2_crypto_client_initial_cb,
  564. NULL, /* recv_client_initial */
  565. ngtcp2_crypto_recv_crypto_data_cb,
  566. cb_handshake_completed,
  567. NULL, /* recv_version_negotiation */
  568. ngtcp2_crypto_encrypt_cb,
  569. ngtcp2_crypto_decrypt_cb,
  570. ngtcp2_crypto_hp_mask_cb,
  571. cb_recv_stream_data,
  572. cb_acked_stream_data_offset,
  573. NULL, /* stream_open */
  574. cb_stream_close,
  575. NULL, /* recv_stateless_reset */
  576. ngtcp2_crypto_recv_retry_cb,
  577. cb_extend_max_local_streams_bidi,
  578. NULL, /* extend_max_local_streams_uni */
  579. cb_rand,
  580. cb_get_new_connection_id,
  581. NULL, /* remove_connection_id */
  582. ngtcp2_crypto_update_key_cb, /* update_key */
  583. NULL, /* path_validation */
  584. NULL, /* select_preferred_addr */
  585. cb_stream_reset,
  586. NULL, /* extend_max_remote_streams_bidi */
  587. NULL, /* extend_max_remote_streams_uni */
  588. cb_extend_max_stream_data,
  589. NULL, /* dcid_status */
  590. NULL, /* handshake_confirmed */
  591. NULL, /* recv_new_token */
  592. ngtcp2_crypto_delete_crypto_aead_ctx_cb,
  593. ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
  594. NULL, /* recv_datagram */
  595. NULL, /* ack_datagram */
  596. NULL, /* lost_datagram */
  597. ngtcp2_crypto_get_path_challenge_data_cb,
  598. cb_stream_stop_sending,
  599. NULL, /* version_negotiation */
  600. cb_recv_rx_key,
  601. NULL, /* recv_tx_key */
  602. NULL, /* early_data_rejected */
  603. };
  604. /**
  605. * Connection maintenance like timeouts on packet ACKs etc. are done by us, not
  606. * the OS like for TCP. POLL events on the socket therefore are not
  607. * sufficient.
  608. * ngtcp2 tells us when it wants to be invoked again. We handle that via
  609. * the `Curl_expire()` mechanisms.
  610. */
  611. static CURLcode check_and_set_expiry(struct Curl_cfilter *cf,
  612. struct Curl_easy *data,
  613. struct pkt_io_ctx *pktx)
  614. {
  615. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  616. struct pkt_io_ctx local_pktx;
  617. ngtcp2_tstamp expiry;
  618. if(!pktx) {
  619. pktx_init(&local_pktx, cf, data);
  620. pktx = &local_pktx;
  621. }
  622. else {
  623. pktx_update_time(pktx, cf);
  624. }
  625. expiry = ngtcp2_conn_get_expiry(ctx->qconn);
  626. if(expiry != UINT64_MAX) {
  627. if(expiry <= pktx->ts) {
  628. CURLcode result;
  629. int rv = ngtcp2_conn_handle_expiry(ctx->qconn, pktx->ts);
  630. if(rv) {
  631. failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
  632. ngtcp2_strerror(rv));
  633. ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
  634. return CURLE_SEND_ERROR;
  635. }
  636. result = cf_progress_ingress(cf, data, pktx);
  637. if(result)
  638. return result;
  639. result = cf_progress_egress(cf, data, pktx);
  640. if(result)
  641. return result;
  642. /* ask again, things might have changed */
  643. expiry = ngtcp2_conn_get_expiry(ctx->qconn);
  644. }
  645. if(expiry > pktx->ts) {
  646. ngtcp2_duration timeout = expiry - pktx->ts;
  647. if(timeout % NGTCP2_MILLISECONDS) {
  648. timeout += NGTCP2_MILLISECONDS;
  649. }
  650. Curl_expire(data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
  651. }
  652. }
  653. return CURLE_OK;
  654. }
  655. static void cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf,
  656. struct Curl_easy *data,
  657. struct easy_pollset *ps)
  658. {
  659. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  660. bool want_recv, want_send;
  661. if(!ctx->qconn)
  662. return;
  663. Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send);
  664. if(want_recv || want_send) {
  665. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  666. struct cf_call_data save;
  667. bool c_exhaust, s_exhaust;
  668. CF_DATA_SAVE(save, cf, data);
  669. c_exhaust = want_send && (!ngtcp2_conn_get_cwnd_left(ctx->qconn) ||
  670. !ngtcp2_conn_get_max_data_left(ctx->qconn));
  671. s_exhaust = want_send && stream && stream->id >= 0 &&
  672. stream->quic_flow_blocked;
  673. want_recv = (want_recv || c_exhaust || s_exhaust);
  674. want_send = (!s_exhaust && want_send) ||
  675. !Curl_bufq_is_empty(&ctx->q.sendbuf);
  676. Curl_pollset_set(data, ps, ctx->q.sockfd, want_recv, want_send);
  677. CF_DATA_RESTORE(cf, save);
  678. }
  679. }
  680. static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
  681. uint64_t app_error_code, void *user_data,
  682. void *stream_user_data)
  683. {
  684. struct Curl_cfilter *cf = user_data;
  685. struct Curl_easy *data = stream_user_data;
  686. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  687. (void)conn;
  688. (void)stream_id;
  689. /* we might be called by nghttp3 after we already cleaned up */
  690. if(!stream)
  691. return 0;
  692. stream->closed = TRUE;
  693. stream->error3 = app_error_code;
  694. if(stream->error3 != NGHTTP3_H3_NO_ERROR) {
  695. stream->reset = TRUE;
  696. stream->send_closed = TRUE;
  697. CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRId64,
  698. stream->id, stream->error3);
  699. }
  700. else {
  701. CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id);
  702. }
  703. h3_drain_stream(cf, data);
  704. return 0;
  705. }
  706. /*
  707. * write_resp_raw() copies response data in raw format to the `data`'s
  708. * receive buffer. If not enough space is available, it appends to the
  709. * `data`'s overflow buffer.
  710. */
  711. static CURLcode write_resp_raw(struct Curl_cfilter *cf,
  712. struct Curl_easy *data,
  713. const void *mem, size_t memlen,
  714. bool flow)
  715. {
  716. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  717. CURLcode result = CURLE_OK;
  718. ssize_t nwritten;
  719. (void)cf;
  720. if(!stream) {
  721. return CURLE_RECV_ERROR;
  722. }
  723. nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result);
  724. if(nwritten < 0) {
  725. return result;
  726. }
  727. if(!flow)
  728. stream->recv_buf_nonflow += (size_t)nwritten;
  729. if((size_t)nwritten < memlen) {
  730. /* This MUST not happen. Our recbuf is dimensioned to hold the
  731. * full max_stream_window and then some for this very reason. */
  732. DEBUGASSERT(0);
  733. return CURLE_RECV_ERROR;
  734. }
  735. return result;
  736. }
  737. static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
  738. const uint8_t *buf, size_t buflen,
  739. void *user_data, void *stream_user_data)
  740. {
  741. struct Curl_cfilter *cf = user_data;
  742. struct Curl_easy *data = stream_user_data;
  743. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  744. CURLcode result;
  745. (void)conn;
  746. (void)stream3_id;
  747. if(!stream)
  748. return NGHTTP3_ERR_CALLBACK_FAILURE;
  749. result = write_resp_raw(cf, data, buf, buflen, TRUE);
  750. if(result) {
  751. CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, ERROR receiving %d",
  752. stream->id, buflen, result);
  753. return NGHTTP3_ERR_CALLBACK_FAILURE;
  754. }
  755. CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu", stream->id, buflen);
  756. h3_drain_stream(cf, data);
  757. return 0;
  758. }
  759. static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream3_id,
  760. size_t consumed, void *user_data,
  761. void *stream_user_data)
  762. {
  763. struct Curl_cfilter *cf = user_data;
  764. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  765. (void)conn;
  766. (void)stream_user_data;
  767. /* nghttp3 has consumed bytes on the QUIC stream and we need to
  768. * tell the QUIC connection to increase its flow control */
  769. ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream3_id, consumed);
  770. ngtcp2_conn_extend_max_offset(ctx->qconn, consumed);
  771. return 0;
  772. }
  773. static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
  774. int fin, void *user_data, void *stream_user_data)
  775. {
  776. struct Curl_cfilter *cf = user_data;
  777. struct Curl_easy *data = stream_user_data;
  778. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  779. CURLcode result = CURLE_OK;
  780. (void)conn;
  781. (void)stream_id;
  782. (void)fin;
  783. (void)cf;
  784. if(!stream)
  785. return 0;
  786. /* add a CRLF only if we've received some headers */
  787. result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
  788. if(result) {
  789. return -1;
  790. }
  791. CURL_TRC_CF(data, cf, "[%" PRId64 "] end_headers, status=%d",
  792. stream_id, stream->status_code);
  793. if(stream->status_code / 100 != 1) {
  794. stream->resp_hds_complete = TRUE;
  795. }
  796. h3_drain_stream(cf, data);
  797. return 0;
  798. }
  799. static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
  800. int32_t token, nghttp3_rcbuf *name,
  801. nghttp3_rcbuf *value, uint8_t flags,
  802. void *user_data, void *stream_user_data)
  803. {
  804. struct Curl_cfilter *cf = user_data;
  805. nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
  806. nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
  807. struct Curl_easy *data = stream_user_data;
  808. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  809. CURLcode result = CURLE_OK;
  810. (void)conn;
  811. (void)stream_id;
  812. (void)token;
  813. (void)flags;
  814. (void)cf;
  815. /* we might have cleaned up this transfer already */
  816. if(!stream)
  817. return 0;
  818. if(token == NGHTTP3_QPACK_TOKEN__STATUS) {
  819. char line[14]; /* status line is always 13 characters long */
  820. size_t ncopy;
  821. result = Curl_http_decode_status(&stream->status_code,
  822. (const char *)h3val.base, h3val.len);
  823. if(result)
  824. return -1;
  825. ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n",
  826. stream->status_code);
  827. CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, line);
  828. result = write_resp_raw(cf, data, line, ncopy, FALSE);
  829. if(result) {
  830. return -1;
  831. }
  832. }
  833. else {
  834. /* store as an HTTP1-style header */
  835. CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s",
  836. stream_id, (int)h3name.len, h3name.base,
  837. (int)h3val.len, h3val.base);
  838. result = write_resp_raw(cf, data, h3name.base, h3name.len, FALSE);
  839. if(result) {
  840. return -1;
  841. }
  842. result = write_resp_raw(cf, data, ": ", 2, FALSE);
  843. if(result) {
  844. return -1;
  845. }
  846. result = write_resp_raw(cf, data, h3val.base, h3val.len, FALSE);
  847. if(result) {
  848. return -1;
  849. }
  850. result = write_resp_raw(cf, data, "\r\n", 2, FALSE);
  851. if(result) {
  852. return -1;
  853. }
  854. }
  855. return 0;
  856. }
  857. static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id,
  858. uint64_t app_error_code, void *user_data,
  859. void *stream_user_data)
  860. {
  861. struct Curl_cfilter *cf = user_data;
  862. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  863. int rv;
  864. (void)conn;
  865. (void)stream_user_data;
  866. rv = ngtcp2_conn_shutdown_stream_read(ctx->qconn, 0, stream_id,
  867. app_error_code);
  868. if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
  869. return NGTCP2_ERR_CALLBACK_FAILURE;
  870. }
  871. return 0;
  872. }
  873. static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
  874. uint64_t app_error_code, void *user_data,
  875. void *stream_user_data) {
  876. struct Curl_cfilter *cf = user_data;
  877. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  878. struct Curl_easy *data = stream_user_data;
  879. int rv;
  880. (void)conn;
  881. (void)data;
  882. rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id,
  883. app_error_code);
  884. CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv);
  885. if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) {
  886. return NGTCP2_ERR_CALLBACK_FAILURE;
  887. }
  888. return 0;
  889. }
  890. static nghttp3_callbacks ngh3_callbacks = {
  891. cb_h3_acked_req_body, /* acked_stream_data */
  892. cb_h3_stream_close,
  893. cb_h3_recv_data,
  894. cb_h3_deferred_consume,
  895. NULL, /* begin_headers */
  896. cb_h3_recv_header,
  897. cb_h3_end_headers,
  898. NULL, /* begin_trailers */
  899. cb_h3_recv_header,
  900. NULL, /* end_trailers */
  901. cb_h3_stop_sending,
  902. NULL, /* end_stream */
  903. cb_h3_reset_stream,
  904. NULL, /* shutdown */
  905. NULL /* recv_settings */
  906. };
  907. static int init_ngh3_conn(struct Curl_cfilter *cf)
  908. {
  909. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  910. CURLcode result;
  911. int rc;
  912. int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
  913. if(ngtcp2_conn_get_streams_uni_left(ctx->qconn) < 3) {
  914. return CURLE_QUIC_CONNECT_ERROR;
  915. }
  916. nghttp3_settings_default(&ctx->h3settings);
  917. rc = nghttp3_conn_client_new(&ctx->h3conn,
  918. &ngh3_callbacks,
  919. &ctx->h3settings,
  920. nghttp3_mem_default(),
  921. cf);
  922. if(rc) {
  923. result = CURLE_OUT_OF_MEMORY;
  924. goto fail;
  925. }
  926. rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &ctrl_stream_id, NULL);
  927. if(rc) {
  928. result = CURLE_QUIC_CONNECT_ERROR;
  929. goto fail;
  930. }
  931. rc = nghttp3_conn_bind_control_stream(ctx->h3conn, ctrl_stream_id);
  932. if(rc) {
  933. result = CURLE_QUIC_CONNECT_ERROR;
  934. goto fail;
  935. }
  936. rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_enc_stream_id, NULL);
  937. if(rc) {
  938. result = CURLE_QUIC_CONNECT_ERROR;
  939. goto fail;
  940. }
  941. rc = ngtcp2_conn_open_uni_stream(ctx->qconn, &qpack_dec_stream_id, NULL);
  942. if(rc) {
  943. result = CURLE_QUIC_CONNECT_ERROR;
  944. goto fail;
  945. }
  946. rc = nghttp3_conn_bind_qpack_streams(ctx->h3conn, qpack_enc_stream_id,
  947. qpack_dec_stream_id);
  948. if(rc) {
  949. result = CURLE_QUIC_CONNECT_ERROR;
  950. goto fail;
  951. }
  952. return CURLE_OK;
  953. fail:
  954. return result;
  955. }
  956. static ssize_t recv_closed_stream(struct Curl_cfilter *cf,
  957. struct Curl_easy *data,
  958. struct h3_stream_ctx *stream,
  959. CURLcode *err)
  960. {
  961. ssize_t nread = -1;
  962. (void)cf;
  963. if(stream->reset) {
  964. failf(data,
  965. "HTTP/3 stream %" PRId64 " reset by server", stream->id);
  966. *err = stream->resp_hds_complete? CURLE_PARTIAL_FILE : CURLE_HTTP3;
  967. goto out;
  968. }
  969. else if(!stream->resp_hds_complete) {
  970. failf(data,
  971. "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting"
  972. " all response header fields, treated as error",
  973. stream->id);
  974. *err = CURLE_HTTP3;
  975. goto out;
  976. }
  977. *err = CURLE_OK;
  978. nread = 0;
  979. out:
  980. return nread;
  981. }
  982. /* incoming data frames on the h3 stream */
  983. static ssize_t cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
  984. char *buf, size_t len, CURLcode *err)
  985. {
  986. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  987. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  988. ssize_t nread = -1;
  989. struct cf_call_data save;
  990. struct pkt_io_ctx pktx;
  991. (void)ctx;
  992. CF_DATA_SAVE(save, cf, data);
  993. DEBUGASSERT(cf->connected);
  994. DEBUGASSERT(ctx);
  995. DEBUGASSERT(ctx->qconn);
  996. DEBUGASSERT(ctx->h3conn);
  997. *err = CURLE_OK;
  998. pktx_init(&pktx, cf, data);
  999. if(!stream) {
  1000. *err = CURLE_RECV_ERROR;
  1001. goto out;
  1002. }
  1003. if(!Curl_bufq_is_empty(&stream->recvbuf)) {
  1004. nread = Curl_bufq_read(&stream->recvbuf,
  1005. (unsigned char *)buf, len, err);
  1006. if(nread < 0) {
  1007. CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
  1008. "-> %zd, %d", stream->id, len, nread, *err);
  1009. goto out;
  1010. }
  1011. report_consumed_data(cf, data, nread);
  1012. }
  1013. if(cf_progress_ingress(cf, data, &pktx)) {
  1014. *err = CURLE_RECV_ERROR;
  1015. nread = -1;
  1016. goto out;
  1017. }
  1018. /* recvbuf had nothing before, maybe after progressing ingress? */
  1019. if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) {
  1020. nread = Curl_bufq_read(&stream->recvbuf,
  1021. (unsigned char *)buf, len, err);
  1022. if(nread < 0) {
  1023. CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) "
  1024. "-> %zd, %d", stream->id, len, nread, *err);
  1025. goto out;
  1026. }
  1027. report_consumed_data(cf, data, nread);
  1028. }
  1029. if(nread > 0) {
  1030. h3_drain_stream(cf, data);
  1031. }
  1032. else {
  1033. if(stream->closed) {
  1034. nread = recv_closed_stream(cf, data, stream, err);
  1035. goto out;
  1036. }
  1037. *err = CURLE_AGAIN;
  1038. nread = -1;
  1039. }
  1040. out:
  1041. if(cf_progress_egress(cf, data, &pktx)) {
  1042. *err = CURLE_SEND_ERROR;
  1043. nread = -1;
  1044. }
  1045. else {
  1046. CURLcode result2 = check_and_set_expiry(cf, data, &pktx);
  1047. if(result2) {
  1048. *err = result2;
  1049. nread = -1;
  1050. }
  1051. }
  1052. CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(len=%zu) -> %zd, %d",
  1053. stream? stream->id : -1, len, nread, *err);
  1054. CF_DATA_RESTORE(cf, save);
  1055. return nread;
  1056. }
  1057. static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
  1058. uint64_t datalen, void *user_data,
  1059. void *stream_user_data)
  1060. {
  1061. struct Curl_cfilter *cf = user_data;
  1062. struct Curl_easy *data = stream_user_data;
  1063. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1064. size_t skiplen;
  1065. (void)cf;
  1066. if(!stream)
  1067. return 0;
  1068. /* The server acknowledged `datalen` of bytes from our request body.
  1069. * This is a delta. We have kept this data in `sendbuf` for
  1070. * re-transmissions and can free it now. */
  1071. if(datalen >= (uint64_t)stream->sendbuf_len_in_flight)
  1072. skiplen = stream->sendbuf_len_in_flight;
  1073. else
  1074. skiplen = (size_t)datalen;
  1075. Curl_bufq_skip(&stream->sendbuf, skiplen);
  1076. stream->sendbuf_len_in_flight -= skiplen;
  1077. /* Everything ACKed, we resume upload processing */
  1078. if(!stream->sendbuf_len_in_flight) {
  1079. int rv = nghttp3_conn_resume_stream(conn, stream_id);
  1080. if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
  1081. return NGTCP2_ERR_CALLBACK_FAILURE;
  1082. }
  1083. }
  1084. return 0;
  1085. }
  1086. static nghttp3_ssize
  1087. cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
  1088. nghttp3_vec *vec, size_t veccnt,
  1089. uint32_t *pflags, void *user_data,
  1090. void *stream_user_data)
  1091. {
  1092. struct Curl_cfilter *cf = user_data;
  1093. struct Curl_easy *data = stream_user_data;
  1094. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1095. ssize_t nwritten = 0;
  1096. size_t nvecs = 0;
  1097. (void)cf;
  1098. (void)conn;
  1099. (void)stream_id;
  1100. (void)user_data;
  1101. (void)veccnt;
  1102. if(!stream)
  1103. return NGHTTP3_ERR_CALLBACK_FAILURE;
  1104. /* nghttp3 keeps references to the sendbuf data until it is ACKed
  1105. * by the server (see `cb_h3_acked_req_body()` for updates).
  1106. * `sendbuf_len_in_flight` is the amount of bytes in `sendbuf`
  1107. * that we have already passed to nghttp3, but which have not been
  1108. * ACKed yet.
  1109. * Any amount beyond `sendbuf_len_in_flight` we need still to pass
  1110. * to nghttp3. Do that now, if we can. */
  1111. if(stream->sendbuf_len_in_flight < Curl_bufq_len(&stream->sendbuf)) {
  1112. nvecs = 0;
  1113. while(nvecs < veccnt &&
  1114. Curl_bufq_peek_at(&stream->sendbuf,
  1115. stream->sendbuf_len_in_flight,
  1116. (const unsigned char **)&vec[nvecs].base,
  1117. &vec[nvecs].len)) {
  1118. stream->sendbuf_len_in_flight += vec[nvecs].len;
  1119. nwritten += vec[nvecs].len;
  1120. ++nvecs;
  1121. }
  1122. DEBUGASSERT(nvecs > 0); /* we SHOULD have been be able to peek */
  1123. }
  1124. if(nwritten > 0 && stream->upload_left != -1)
  1125. stream->upload_left -= nwritten;
  1126. /* When we stopped sending and everything in `sendbuf` is "in flight",
  1127. * we are at the end of the request body. */
  1128. if(stream->upload_left == 0) {
  1129. *pflags = NGHTTP3_DATA_FLAG_EOF;
  1130. stream->send_closed = TRUE;
  1131. }
  1132. else if(!nwritten) {
  1133. /* Not EOF, and nothing to give, we signal WOULDBLOCK. */
  1134. CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN",
  1135. stream->id);
  1136. return NGHTTP3_ERR_WOULDBLOCK;
  1137. }
  1138. CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> "
  1139. "%d vecs%s with %zu (buffered=%zu, left=%"
  1140. CURL_FORMAT_CURL_OFF_T ")",
  1141. stream->id, (int)nvecs,
  1142. *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
  1143. nwritten, Curl_bufq_len(&stream->sendbuf),
  1144. stream->upload_left);
  1145. return (nghttp3_ssize)nvecs;
  1146. }
  1147. /* Index where :authority header field will appear in request header
  1148. field list. */
  1149. #define AUTHORITY_DST_IDX 3
  1150. static ssize_t h3_stream_open(struct Curl_cfilter *cf,
  1151. struct Curl_easy *data,
  1152. const void *buf, size_t len,
  1153. CURLcode *err)
  1154. {
  1155. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1156. struct h3_stream_ctx *stream = NULL;
  1157. struct dynhds h2_headers;
  1158. size_t nheader;
  1159. nghttp3_nv *nva = NULL;
  1160. int rc = 0;
  1161. unsigned int i;
  1162. ssize_t nwritten = -1;
  1163. nghttp3_data_reader reader;
  1164. nghttp3_data_reader *preader = NULL;
  1165. Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
  1166. *err = h3_data_setup(cf, data);
  1167. if(*err)
  1168. goto out;
  1169. stream = H3_STREAM_CTX(data);
  1170. DEBUGASSERT(stream);
  1171. if(!stream) {
  1172. *err = CURLE_FAILED_INIT;
  1173. goto out;
  1174. }
  1175. nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err);
  1176. if(nwritten < 0)
  1177. goto out;
  1178. if(!stream->h1.done) {
  1179. /* need more data */
  1180. goto out;
  1181. }
  1182. DEBUGASSERT(stream->h1.req);
  1183. *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
  1184. if(*err) {
  1185. nwritten = -1;
  1186. goto out;
  1187. }
  1188. /* no longer needed */
  1189. Curl_h1_req_parse_free(&stream->h1);
  1190. nheader = Curl_dynhds_count(&h2_headers);
  1191. nva = malloc(sizeof(nghttp3_nv) * nheader);
  1192. if(!nva) {
  1193. *err = CURLE_OUT_OF_MEMORY;
  1194. nwritten = -1;
  1195. goto out;
  1196. }
  1197. for(i = 0; i < nheader; ++i) {
  1198. struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i);
  1199. nva[i].name = (unsigned char *)e->name;
  1200. nva[i].namelen = e->namelen;
  1201. nva[i].value = (unsigned char *)e->value;
  1202. nva[i].valuelen = e->valuelen;
  1203. nva[i].flags = NGHTTP3_NV_FLAG_NONE;
  1204. }
  1205. rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, data);
  1206. if(rc) {
  1207. failf(data, "can get bidi streams");
  1208. *err = CURLE_SEND_ERROR;
  1209. goto out;
  1210. }
  1211. switch(data->state.httpreq) {
  1212. case HTTPREQ_POST:
  1213. case HTTPREQ_POST_FORM:
  1214. case HTTPREQ_POST_MIME:
  1215. case HTTPREQ_PUT:
  1216. /* known request body size or -1 */
  1217. if(data->state.infilesize != -1)
  1218. stream->upload_left = data->state.infilesize;
  1219. else
  1220. /* data sending without specifying the data amount up front */
  1221. stream->upload_left = -1; /* unknown */
  1222. break;
  1223. default:
  1224. /* there is not request body */
  1225. stream->upload_left = 0; /* no request body */
  1226. break;
  1227. }
  1228. stream->send_closed = (stream->upload_left == 0);
  1229. if(!stream->send_closed) {
  1230. reader.read_data = cb_h3_read_req_body;
  1231. preader = &reader;
  1232. }
  1233. rc = nghttp3_conn_submit_request(ctx->h3conn, stream->id,
  1234. nva, nheader, preader, data);
  1235. if(rc) {
  1236. switch(rc) {
  1237. case NGHTTP3_ERR_CONN_CLOSING:
  1238. CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
  1239. "connection is closing", stream->id);
  1240. break;
  1241. default:
  1242. CURL_TRC_CF(data, cf, "h3sid[%"PRId64"] failed to send -> %d (%s)",
  1243. stream->id, rc, ngtcp2_strerror(rc));
  1244. break;
  1245. }
  1246. *err = CURLE_SEND_ERROR;
  1247. nwritten = -1;
  1248. goto out;
  1249. }
  1250. if(Curl_trc_is_verbose(data)) {
  1251. infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s",
  1252. stream->id, data->state.url);
  1253. for(i = 0; i < nheader; ++i) {
  1254. infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id,
  1255. (int)nva[i].namelen, nva[i].name,
  1256. (int)nva[i].valuelen, nva[i].value);
  1257. }
  1258. }
  1259. out:
  1260. free(nva);
  1261. Curl_dynhds_free(&h2_headers);
  1262. return nwritten;
  1263. }
  1264. static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
  1265. const void *buf, size_t len, CURLcode *err)
  1266. {
  1267. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1268. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1269. ssize_t sent = 0;
  1270. struct cf_call_data save;
  1271. struct pkt_io_ctx pktx;
  1272. CURLcode result;
  1273. CF_DATA_SAVE(save, cf, data);
  1274. DEBUGASSERT(cf->connected);
  1275. DEBUGASSERT(ctx->qconn);
  1276. DEBUGASSERT(ctx->h3conn);
  1277. pktx_init(&pktx, cf, data);
  1278. *err = CURLE_OK;
  1279. result = cf_progress_ingress(cf, data, &pktx);
  1280. if(result) {
  1281. *err = result;
  1282. sent = -1;
  1283. }
  1284. if(!stream || stream->id < 0) {
  1285. sent = h3_stream_open(cf, data, buf, len, err);
  1286. if(sent < 0) {
  1287. CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err);
  1288. goto out;
  1289. }
  1290. stream = H3_STREAM_CTX(data);
  1291. }
  1292. else if(stream->upload_blocked_len) {
  1293. /* the data in `buf` has already been submitted or added to the
  1294. * buffers, but have been EAGAINed on the last invocation. */
  1295. DEBUGASSERT(len >= stream->upload_blocked_len);
  1296. if(len < stream->upload_blocked_len) {
  1297. /* Did we get called again with a smaller `len`? This should not
  1298. * happen. We are not prepared to handle that. */
  1299. failf(data, "HTTP/3 send again with decreased length");
  1300. *err = CURLE_HTTP3;
  1301. sent = -1;
  1302. goto out;
  1303. }
  1304. sent = (ssize_t)stream->upload_blocked_len;
  1305. stream->upload_blocked_len = 0;
  1306. }
  1307. else if(stream->closed) {
  1308. if(stream->resp_hds_complete) {
  1309. /* Server decided to close the stream after having sent us a final
  1310. * response. This is valid if it is not interested in the request
  1311. * body. This happens on 30x or 40x responses.
  1312. * We silently discard the data sent, since this is not a transport
  1313. * error situation. */
  1314. CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data"
  1315. "on closed stream with response", stream->id);
  1316. *err = CURLE_OK;
  1317. sent = (ssize_t)len;
  1318. goto out;
  1319. }
  1320. CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) "
  1321. "-> stream closed", stream->id, len);
  1322. *err = CURLE_HTTP3;
  1323. sent = -1;
  1324. goto out;
  1325. }
  1326. else {
  1327. sent = Curl_bufq_write(&stream->sendbuf, buf, len, err);
  1328. CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to "
  1329. "sendbuf(len=%zu) -> %zd, %d",
  1330. stream->id, len, sent, *err);
  1331. if(sent < 0) {
  1332. goto out;
  1333. }
  1334. (void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
  1335. }
  1336. result = cf_progress_egress(cf, data, &pktx);
  1337. if(result) {
  1338. *err = result;
  1339. sent = -1;
  1340. }
  1341. if(stream && sent > 0 && stream->sendbuf_len_in_flight) {
  1342. /* We have unacknowledged DATA and cannot report success to our
  1343. * caller. Instead we EAGAIN and remember how much we have already
  1344. * "written" into our various internal connection buffers. */
  1345. stream->upload_blocked_len = sent;
  1346. CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu), "
  1347. "%zu bytes in flight -> EGAIN", stream->id, len,
  1348. stream->sendbuf_len_in_flight);
  1349. *err = CURLE_AGAIN;
  1350. sent = -1;
  1351. }
  1352. out:
  1353. result = check_and_set_expiry(cf, data, &pktx);
  1354. if(result) {
  1355. *err = result;
  1356. sent = -1;
  1357. }
  1358. CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %zd, %d",
  1359. stream? stream->id : -1, len, sent, *err);
  1360. CF_DATA_RESTORE(cf, save);
  1361. return sent;
  1362. }
  1363. static CURLcode qng_verify_peer(struct Curl_cfilter *cf,
  1364. struct Curl_easy *data)
  1365. {
  1366. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1367. cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
  1368. cf->conn->httpversion = 30;
  1369. cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX;
  1370. return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer);
  1371. }
  1372. static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen,
  1373. struct sockaddr_storage *remote_addr,
  1374. socklen_t remote_addrlen, int ecn,
  1375. void *userp)
  1376. {
  1377. struct pkt_io_ctx *pktx = userp;
  1378. struct cf_ngtcp2_ctx *ctx = pktx->cf->ctx;
  1379. ngtcp2_pkt_info pi;
  1380. ngtcp2_path path;
  1381. int rv;
  1382. ++pktx->pkt_count;
  1383. ngtcp2_addr_init(&path.local, (struct sockaddr *)&ctx->q.local_addr,
  1384. ctx->q.local_addrlen);
  1385. ngtcp2_addr_init(&path.remote, (struct sockaddr *)remote_addr,
  1386. remote_addrlen);
  1387. pi.ecn = (uint8_t)ecn;
  1388. rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, pkt, pktlen, pktx->ts);
  1389. if(rv) {
  1390. CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)",
  1391. ngtcp2_strerror(rv), rv);
  1392. if(!ctx->last_error.error_code) {
  1393. if(rv == NGTCP2_ERR_CRYPTO) {
  1394. ngtcp2_ccerr_set_tls_alert(&ctx->last_error,
  1395. ngtcp2_conn_get_tls_alert(ctx->qconn),
  1396. NULL, 0);
  1397. }
  1398. else {
  1399. ngtcp2_ccerr_set_liberr(&ctx->last_error, rv, NULL, 0);
  1400. }
  1401. }
  1402. if(rv == NGTCP2_ERR_CRYPTO)
  1403. /* this is a "TLS problem", but a failed certificate verification
  1404. is a common reason for this */
  1405. return CURLE_PEER_FAILED_VERIFICATION;
  1406. return CURLE_RECV_ERROR;
  1407. }
  1408. return CURLE_OK;
  1409. }
  1410. static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
  1411. struct Curl_easy *data,
  1412. struct pkt_io_ctx *pktx)
  1413. {
  1414. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1415. struct pkt_io_ctx local_pktx;
  1416. size_t pkts_chunk = 128, i;
  1417. size_t pkts_max = 10 * pkts_chunk;
  1418. CURLcode result = CURLE_OK;
  1419. if(!pktx) {
  1420. pktx_init(&local_pktx, cf, data);
  1421. pktx = &local_pktx;
  1422. }
  1423. else {
  1424. pktx_update_time(pktx, cf);
  1425. }
  1426. result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data);
  1427. if(result)
  1428. return result;
  1429. for(i = 0; i < pkts_max; i += pkts_chunk) {
  1430. pktx->pkt_count = 0;
  1431. result = vquic_recv_packets(cf, data, &ctx->q, pkts_chunk,
  1432. recv_pkt, pktx);
  1433. if(result) /* error */
  1434. break;
  1435. if(pktx->pkt_count < pkts_chunk) /* got less than we could */
  1436. break;
  1437. /* give egress a chance before we receive more */
  1438. result = cf_progress_egress(cf, data, pktx);
  1439. if(result) /* error */
  1440. break;
  1441. }
  1442. return result;
  1443. }
  1444. /**
  1445. * Read a network packet to send from ngtcp2 into `buf`.
  1446. * Return number of bytes written or -1 with *err set.
  1447. */
  1448. static ssize_t read_pkt_to_send(void *userp,
  1449. unsigned char *buf, size_t buflen,
  1450. CURLcode *err)
  1451. {
  1452. struct pkt_io_ctx *x = userp;
  1453. struct cf_ngtcp2_ctx *ctx = x->cf->ctx;
  1454. nghttp3_vec vec[16];
  1455. nghttp3_ssize veccnt;
  1456. ngtcp2_ssize ndatalen;
  1457. uint32_t flags;
  1458. int64_t stream_id;
  1459. int fin;
  1460. ssize_t nwritten, n;
  1461. veccnt = 0;
  1462. stream_id = -1;
  1463. fin = 0;
  1464. /* ngtcp2 may want to put several frames from different streams into
  1465. * this packet. `NGTCP2_WRITE_STREAM_FLAG_MORE` tells it to do so.
  1466. * When `NGTCP2_ERR_WRITE_MORE` is returned, we *need* to make
  1467. * another iteration.
  1468. * When ngtcp2 is happy (because it has no other frame that would fit
  1469. * or it has nothing more to send), it returns the total length
  1470. * of the assembled packet. This may be 0 if there was nothing to send. */
  1471. nwritten = 0;
  1472. *err = CURLE_OK;
  1473. for(;;) {
  1474. if(ctx->h3conn && ngtcp2_conn_get_max_data_left(ctx->qconn)) {
  1475. veccnt = nghttp3_conn_writev_stream(ctx->h3conn, &stream_id, &fin, vec,
  1476. sizeof(vec) / sizeof(vec[0]));
  1477. if(veccnt < 0) {
  1478. failf(x->data, "nghttp3_conn_writev_stream returned error: %s",
  1479. nghttp3_strerror((int)veccnt));
  1480. ngtcp2_ccerr_set_application_error(
  1481. &ctx->last_error,
  1482. nghttp3_err_infer_quic_app_error_code((int)veccnt), NULL, 0);
  1483. *err = CURLE_SEND_ERROR;
  1484. return -1;
  1485. }
  1486. }
  1487. flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
  1488. (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
  1489. n = ngtcp2_conn_writev_stream(ctx->qconn, &x->ps.path,
  1490. NULL, buf, buflen,
  1491. &ndatalen, flags, stream_id,
  1492. (const ngtcp2_vec *)vec, veccnt, x->ts);
  1493. if(n == 0) {
  1494. /* nothing to send */
  1495. *err = CURLE_AGAIN;
  1496. nwritten = -1;
  1497. goto out;
  1498. }
  1499. else if(n < 0) {
  1500. switch(n) {
  1501. case NGTCP2_ERR_STREAM_DATA_BLOCKED: {
  1502. struct h3_stream_ctx *stream = H3_STREAM_CTX(x->data);
  1503. DEBUGASSERT(ndatalen == -1);
  1504. nghttp3_conn_block_stream(ctx->h3conn, stream_id);
  1505. CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow",
  1506. stream_id);
  1507. DEBUGASSERT(stream);
  1508. if(stream)
  1509. stream->quic_flow_blocked = TRUE;
  1510. n = 0;
  1511. break;
  1512. }
  1513. case NGTCP2_ERR_STREAM_SHUT_WR:
  1514. DEBUGASSERT(ndatalen == -1);
  1515. nghttp3_conn_shutdown_stream_write(ctx->h3conn, stream_id);
  1516. n = 0;
  1517. break;
  1518. case NGTCP2_ERR_WRITE_MORE:
  1519. /* ngtcp2 wants to send more. update the flow of the stream whose data
  1520. * is in the buffer and continue */
  1521. DEBUGASSERT(ndatalen >= 0);
  1522. n = 0;
  1523. break;
  1524. default:
  1525. DEBUGASSERT(ndatalen == -1);
  1526. failf(x->data, "ngtcp2_conn_writev_stream returned error: %s",
  1527. ngtcp2_strerror((int)n));
  1528. ngtcp2_ccerr_set_liberr(&ctx->last_error, (int)n, NULL, 0);
  1529. *err = CURLE_SEND_ERROR;
  1530. nwritten = -1;
  1531. goto out;
  1532. }
  1533. }
  1534. if(ndatalen >= 0) {
  1535. /* we add the amount of data bytes to the flow windows */
  1536. int rv = nghttp3_conn_add_write_offset(ctx->h3conn, stream_id, ndatalen);
  1537. if(rv) {
  1538. failf(x->data, "nghttp3_conn_add_write_offset returned error: %s\n",
  1539. nghttp3_strerror(rv));
  1540. return CURLE_SEND_ERROR;
  1541. }
  1542. }
  1543. if(n > 0) {
  1544. /* packet assembled, leave */
  1545. nwritten = n;
  1546. goto out;
  1547. }
  1548. }
  1549. out:
  1550. return nwritten;
  1551. }
  1552. static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
  1553. struct Curl_easy *data,
  1554. struct pkt_io_ctx *pktx)
  1555. {
  1556. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1557. ssize_t nread;
  1558. size_t max_payload_size, path_max_payload_size, max_pktcnt;
  1559. size_t pktcnt = 0;
  1560. size_t gsolen = 0; /* this disables gso until we have a clue */
  1561. CURLcode curlcode;
  1562. struct pkt_io_ctx local_pktx;
  1563. if(!pktx) {
  1564. pktx_init(&local_pktx, cf, data);
  1565. pktx = &local_pktx;
  1566. }
  1567. else {
  1568. pktx_update_time(pktx, cf);
  1569. ngtcp2_path_storage_zero(&pktx->ps);
  1570. }
  1571. curlcode = vquic_flush(cf, data, &ctx->q);
  1572. if(curlcode) {
  1573. if(curlcode == CURLE_AGAIN) {
  1574. Curl_expire(data, 1, EXPIRE_QUIC);
  1575. return CURLE_OK;
  1576. }
  1577. return curlcode;
  1578. }
  1579. /* In UDP, there is a maximum theoretical packet paload length and
  1580. * a minimum payload length that is "guarantueed" to work.
  1581. * To detect if this minimum payload can be increased, ngtcp2 sends
  1582. * now and then a packet payload larger than the minimum. It that
  1583. * is ACKed by the peer, both parties know that it works and
  1584. * the subsequent packets can use a larger one.
  1585. * This is called PMTUD (Path Maximum Transmission Unit Discovery).
  1586. * Since a PMTUD might be rejected right on send, we do not want it
  1587. * be followed by other packets of lesser size. Because those would
  1588. * also fail then. So, if we detect a PMTUD while buffering, we flush.
  1589. */
  1590. max_payload_size = ngtcp2_conn_get_max_tx_udp_payload_size(ctx->qconn);
  1591. path_max_payload_size =
  1592. ngtcp2_conn_get_path_max_tx_udp_payload_size(ctx->qconn);
  1593. /* maximum number of packets buffered before we flush to the socket */
  1594. max_pktcnt = CURLMIN(MAX_PKT_BURST,
  1595. ctx->q.sendbuf.chunk_size / max_payload_size);
  1596. for(;;) {
  1597. /* add the next packet to send, if any, to our buffer */
  1598. nread = Curl_bufq_sipn(&ctx->q.sendbuf, max_payload_size,
  1599. read_pkt_to_send, pktx, &curlcode);
  1600. if(nread < 0) {
  1601. if(curlcode != CURLE_AGAIN)
  1602. return curlcode;
  1603. /* Nothing more to add, flush and leave */
  1604. curlcode = vquic_send(cf, data, &ctx->q, gsolen);
  1605. if(curlcode) {
  1606. if(curlcode == CURLE_AGAIN) {
  1607. Curl_expire(data, 1, EXPIRE_QUIC);
  1608. return CURLE_OK;
  1609. }
  1610. return curlcode;
  1611. }
  1612. goto out;
  1613. }
  1614. DEBUGASSERT(nread > 0);
  1615. if(pktcnt == 0) {
  1616. /* first packet in buffer. This is either of a known, "good"
  1617. * payload size or it is a PMTUD. We'll see. */
  1618. gsolen = (size_t)nread;
  1619. }
  1620. else if((size_t)nread > gsolen ||
  1621. (gsolen > path_max_payload_size && (size_t)nread != gsolen)) {
  1622. /* The just added packet is a PMTUD *or* the one(s) before the
  1623. * just added were PMTUD and the last one is smaller.
  1624. * Flush the buffer before the last add. */
  1625. curlcode = vquic_send_tail_split(cf, data, &ctx->q,
  1626. gsolen, nread, nread);
  1627. if(curlcode) {
  1628. if(curlcode == CURLE_AGAIN) {
  1629. Curl_expire(data, 1, EXPIRE_QUIC);
  1630. return CURLE_OK;
  1631. }
  1632. return curlcode;
  1633. }
  1634. pktcnt = 0;
  1635. continue;
  1636. }
  1637. if(++pktcnt >= max_pktcnt || (size_t)nread < gsolen) {
  1638. /* Reached MAX_PKT_BURST *or*
  1639. * the capacity of our buffer *or*
  1640. * last add was shorter than the previous ones, flush */
  1641. curlcode = vquic_send(cf, data, &ctx->q, gsolen);
  1642. if(curlcode) {
  1643. if(curlcode == CURLE_AGAIN) {
  1644. Curl_expire(data, 1, EXPIRE_QUIC);
  1645. return CURLE_OK;
  1646. }
  1647. return curlcode;
  1648. }
  1649. /* pktbuf has been completely sent */
  1650. pktcnt = 0;
  1651. }
  1652. }
  1653. out:
  1654. return CURLE_OK;
  1655. }
  1656. /*
  1657. * Called from transfer.c:data_pending to know if we should keep looping
  1658. * to receive more data from the connection.
  1659. */
  1660. static bool cf_ngtcp2_data_pending(struct Curl_cfilter *cf,
  1661. const struct Curl_easy *data)
  1662. {
  1663. const struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1664. (void)cf;
  1665. return stream && !Curl_bufq_is_empty(&stream->recvbuf);
  1666. }
  1667. static CURLcode h3_data_pause(struct Curl_cfilter *cf,
  1668. struct Curl_easy *data,
  1669. bool pause)
  1670. {
  1671. /* TODO: there seems right now no API in ngtcp2 to shrink/enlarge
  1672. * the streams windows. As we do in HTTP/2. */
  1673. if(!pause) {
  1674. h3_drain_stream(cf, data);
  1675. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  1676. }
  1677. return CURLE_OK;
  1678. }
  1679. static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
  1680. struct Curl_easy *data,
  1681. int event, int arg1, void *arg2)
  1682. {
  1683. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1684. CURLcode result = CURLE_OK;
  1685. struct cf_call_data save;
  1686. CF_DATA_SAVE(save, cf, data);
  1687. (void)arg1;
  1688. (void)arg2;
  1689. switch(event) {
  1690. case CF_CTRL_DATA_SETUP:
  1691. break;
  1692. case CF_CTRL_DATA_PAUSE:
  1693. result = h3_data_pause(cf, data, (arg1 != 0));
  1694. break;
  1695. case CF_CTRL_DATA_DETACH:
  1696. h3_data_done(cf, data);
  1697. break;
  1698. case CF_CTRL_DATA_DONE:
  1699. h3_data_done(cf, data);
  1700. break;
  1701. case CF_CTRL_DATA_DONE_SEND: {
  1702. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1703. if(stream && !stream->send_closed) {
  1704. stream->send_closed = TRUE;
  1705. stream->upload_left = Curl_bufq_len(&stream->sendbuf);
  1706. (void)nghttp3_conn_resume_stream(ctx->h3conn, stream->id);
  1707. }
  1708. break;
  1709. }
  1710. case CF_CTRL_DATA_IDLE: {
  1711. struct h3_stream_ctx *stream = H3_STREAM_CTX(data);
  1712. CURL_TRC_CF(data, cf, "data idle");
  1713. if(stream && !stream->closed) {
  1714. result = check_and_set_expiry(cf, data, NULL);
  1715. if(result)
  1716. CURL_TRC_CF(data, cf, "data idle, check_and_set_expiry -> %d", result);
  1717. }
  1718. break;
  1719. }
  1720. default:
  1721. break;
  1722. }
  1723. CF_DATA_RESTORE(cf, save);
  1724. return result;
  1725. }
  1726. static void cf_ngtcp2_ctx_clear(struct cf_ngtcp2_ctx *ctx)
  1727. {
  1728. struct cf_call_data save = ctx->call_data;
  1729. if(ctx->qlogfd != -1) {
  1730. close(ctx->qlogfd);
  1731. }
  1732. Curl_vquic_tls_cleanup(&ctx->tls);
  1733. vquic_ctx_free(&ctx->q);
  1734. if(ctx->h3conn)
  1735. nghttp3_conn_del(ctx->h3conn);
  1736. if(ctx->qconn)
  1737. ngtcp2_conn_del(ctx->qconn);
  1738. Curl_bufcp_free(&ctx->stream_bufcp);
  1739. Curl_ssl_peer_cleanup(&ctx->peer);
  1740. memset(ctx, 0, sizeof(*ctx));
  1741. ctx->qlogfd = -1;
  1742. ctx->call_data = save;
  1743. }
  1744. static void cf_ngtcp2_close(struct Curl_cfilter *cf, struct Curl_easy *data)
  1745. {
  1746. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1747. struct cf_call_data save;
  1748. CF_DATA_SAVE(save, cf, data);
  1749. if(ctx && ctx->qconn) {
  1750. char buffer[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
  1751. struct pkt_io_ctx pktx;
  1752. ngtcp2_ssize rc;
  1753. CURL_TRC_CF(data, cf, "close");
  1754. pktx_init(&pktx, cf, data);
  1755. rc = ngtcp2_conn_write_connection_close(ctx->qconn, NULL, /* path */
  1756. NULL, /* pkt_info */
  1757. (uint8_t *)buffer, sizeof(buffer),
  1758. &ctx->last_error, pktx.ts);
  1759. if(rc > 0) {
  1760. while((send(ctx->q.sockfd, buffer, (SEND_TYPE_ARG3)rc, 0) == -1) &&
  1761. SOCKERRNO == EINTR);
  1762. }
  1763. cf_ngtcp2_ctx_clear(ctx);
  1764. }
  1765. cf->connected = FALSE;
  1766. CF_DATA_RESTORE(cf, save);
  1767. }
  1768. static void cf_ngtcp2_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
  1769. {
  1770. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1771. struct cf_call_data save;
  1772. CF_DATA_SAVE(save, cf, data);
  1773. CURL_TRC_CF(data, cf, "destroy");
  1774. if(ctx) {
  1775. cf_ngtcp2_ctx_clear(ctx);
  1776. free(ctx);
  1777. }
  1778. cf->ctx = NULL;
  1779. /* No CF_DATA_RESTORE(cf, save) possible */
  1780. (void)save;
  1781. }
  1782. static CURLcode tls_ctx_setup(struct quic_tls_ctx *ctx,
  1783. struct Curl_cfilter *cf,
  1784. struct Curl_easy *data)
  1785. {
  1786. (void)cf;
  1787. #ifdef USE_OPENSSL
  1788. #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
  1789. if(ngtcp2_crypto_boringssl_configure_client_context(ctx->ssl_ctx) != 0) {
  1790. failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
  1791. return CURLE_FAILED_INIT;
  1792. }
  1793. #else
  1794. if(ngtcp2_crypto_quictls_configure_client_context(ctx->ssl_ctx) != 0) {
  1795. failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
  1796. return CURLE_FAILED_INIT;
  1797. }
  1798. #endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */
  1799. #elif defined(USE_GNUTLS)
  1800. if(ngtcp2_crypto_gnutls_configure_client_session(ctx->gtls->session) != 0) {
  1801. failf(data, "ngtcp2_crypto_gnutls_configure_client_session failed");
  1802. return CURLE_FAILED_INIT;
  1803. }
  1804. #elif defined(USE_WOLFSSL)
  1805. if(ngtcp2_crypto_wolfssl_configure_client_context(ctx->ssl_ctx) != 0) {
  1806. failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed");
  1807. return CURLE_FAILED_INIT;
  1808. }
  1809. #endif
  1810. return CURLE_OK;
  1811. }
  1812. /*
  1813. * Might be called twice for happy eyeballs.
  1814. */
  1815. static CURLcode cf_connect_start(struct Curl_cfilter *cf,
  1816. struct Curl_easy *data,
  1817. struct pkt_io_ctx *pktx)
  1818. {
  1819. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1820. int rc;
  1821. int rv;
  1822. CURLcode result;
  1823. const struct Curl_sockaddr_ex *sockaddr = NULL;
  1824. int qfd;
  1825. ctx->version = NGTCP2_PROTO_VER_MAX;
  1826. ctx->max_stream_window = H3_STREAM_WINDOW_SIZE;
  1827. ctx->max_idle_ms = CURL_QUIC_MAX_IDLE_MS;
  1828. Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE,
  1829. H3_STREAM_POOL_SPARES);
  1830. result = Curl_ssl_peer_init(&ctx->peer, cf);
  1831. if(result)
  1832. return result;
  1833. #define H3_ALPN "\x2h3\x5h3-29"
  1834. result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer,
  1835. H3_ALPN, sizeof(H3_ALPN) - 1,
  1836. tls_ctx_setup, &ctx->conn_ref);
  1837. if(result)
  1838. return result;
  1839. ctx->dcid.datalen = NGTCP2_MAX_CIDLEN;
  1840. result = Curl_rand(data, ctx->dcid.data, NGTCP2_MAX_CIDLEN);
  1841. if(result)
  1842. return result;
  1843. ctx->scid.datalen = NGTCP2_MAX_CIDLEN;
  1844. result = Curl_rand(data, ctx->scid.data, NGTCP2_MAX_CIDLEN);
  1845. if(result)
  1846. return result;
  1847. (void)Curl_qlogdir(data, ctx->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
  1848. ctx->qlogfd = qfd; /* -1 if failure above */
  1849. quic_settings(ctx, data, pktx);
  1850. result = vquic_ctx_init(&ctx->q);
  1851. if(result)
  1852. return result;
  1853. Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
  1854. &sockaddr, NULL, NULL, NULL, NULL);
  1855. if(!sockaddr)
  1856. return CURLE_QUIC_CONNECT_ERROR;
  1857. ctx->q.local_addrlen = sizeof(ctx->q.local_addr);
  1858. rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr,
  1859. &ctx->q.local_addrlen);
  1860. if(rv == -1)
  1861. return CURLE_QUIC_CONNECT_ERROR;
  1862. ngtcp2_addr_init(&ctx->connected_path.local,
  1863. (struct sockaddr *)&ctx->q.local_addr,
  1864. ctx->q.local_addrlen);
  1865. ngtcp2_addr_init(&ctx->connected_path.remote,
  1866. &sockaddr->sa_addr, sockaddr->addrlen);
  1867. rc = ngtcp2_conn_client_new(&ctx->qconn, &ctx->dcid, &ctx->scid,
  1868. &ctx->connected_path,
  1869. NGTCP2_PROTO_VER_V1, &ng_callbacks,
  1870. &ctx->settings, &ctx->transport_params,
  1871. NULL, cf);
  1872. if(rc)
  1873. return CURLE_QUIC_CONNECT_ERROR;
  1874. #ifdef USE_GNUTLS
  1875. ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.gtls->session);
  1876. #else
  1877. ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ssl);
  1878. #endif
  1879. ngtcp2_ccerr_default(&ctx->last_error);
  1880. ctx->conn_ref.get_conn = get_conn;
  1881. ctx->conn_ref.user_data = cf;
  1882. return CURLE_OK;
  1883. }
  1884. static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
  1885. struct Curl_easy *data,
  1886. bool blocking, bool *done)
  1887. {
  1888. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1889. CURLcode result = CURLE_OK;
  1890. struct cf_call_data save;
  1891. struct curltime now;
  1892. struct pkt_io_ctx pktx;
  1893. if(cf->connected) {
  1894. *done = TRUE;
  1895. return CURLE_OK;
  1896. }
  1897. /* Connect the UDP filter first */
  1898. if(!cf->next->connected) {
  1899. result = Curl_conn_cf_connect(cf->next, data, blocking, done);
  1900. if(result || !*done)
  1901. return result;
  1902. }
  1903. *done = FALSE;
  1904. now = Curl_now();
  1905. pktx_init(&pktx, cf, data);
  1906. CF_DATA_SAVE(save, cf, data);
  1907. if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) {
  1908. /* Not time yet to attempt the next connect */
  1909. CURL_TRC_CF(data, cf, "waiting for reconnect time");
  1910. goto out;
  1911. }
  1912. if(!ctx->qconn) {
  1913. ctx->started_at = now;
  1914. result = cf_connect_start(cf, data, &pktx);
  1915. if(result)
  1916. goto out;
  1917. result = cf_progress_egress(cf, data, &pktx);
  1918. /* we do not expect to be able to recv anything yet */
  1919. goto out;
  1920. }
  1921. result = cf_progress_ingress(cf, data, &pktx);
  1922. if(result)
  1923. goto out;
  1924. result = cf_progress_egress(cf, data, &pktx);
  1925. if(result)
  1926. goto out;
  1927. if(ngtcp2_conn_get_handshake_completed(ctx->qconn)) {
  1928. ctx->handshake_at = now;
  1929. CURL_TRC_CF(data, cf, "handshake complete after %dms",
  1930. (int)Curl_timediff(now, ctx->started_at));
  1931. result = qng_verify_peer(cf, data);
  1932. if(!result) {
  1933. CURL_TRC_CF(data, cf, "peer verified");
  1934. cf->connected = TRUE;
  1935. cf->conn->alpn = CURL_HTTP_VERSION_3;
  1936. *done = TRUE;
  1937. connkeep(cf->conn, "HTTP/3 default");
  1938. }
  1939. }
  1940. out:
  1941. if(result == CURLE_RECV_ERROR && ctx->qconn &&
  1942. ngtcp2_conn_in_draining_period(ctx->qconn)) {
  1943. /* When a QUIC server instance is shutting down, it may send us a
  1944. * CONNECTION_CLOSE right away. Our connection then enters the DRAINING
  1945. * state. The CONNECT may work in the near future again. Indicate
  1946. * that as a "weird" reply. */
  1947. result = CURLE_WEIRD_SERVER_REPLY;
  1948. }
  1949. #ifndef CURL_DISABLE_VERBOSE_STRINGS
  1950. if(result) {
  1951. const char *r_ip = NULL;
  1952. int r_port = 0;
  1953. Curl_cf_socket_peek(cf->next, data, NULL, NULL,
  1954. &r_ip, &r_port, NULL, NULL);
  1955. infof(data, "QUIC connect to %s port %u failed: %s",
  1956. r_ip, r_port, curl_easy_strerror(result));
  1957. }
  1958. #endif
  1959. if(!result && ctx->qconn) {
  1960. result = check_and_set_expiry(cf, data, &pktx);
  1961. }
  1962. if(result || *done)
  1963. CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done);
  1964. CF_DATA_RESTORE(cf, save);
  1965. return result;
  1966. }
  1967. static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
  1968. struct Curl_easy *data,
  1969. int query, int *pres1, void *pres2)
  1970. {
  1971. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  1972. struct cf_call_data save;
  1973. switch(query) {
  1974. case CF_QUERY_MAX_CONCURRENT: {
  1975. const ngtcp2_transport_params *rp;
  1976. DEBUGASSERT(pres1);
  1977. CF_DATA_SAVE(save, cf, data);
  1978. rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
  1979. if(rp)
  1980. *pres1 = (rp->initial_max_streams_bidi > INT_MAX)?
  1981. INT_MAX : (int)rp->initial_max_streams_bidi;
  1982. else /* not arrived yet? */
  1983. *pres1 = Curl_multi_max_concurrent_streams(data->multi);
  1984. CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1);
  1985. CF_DATA_RESTORE(cf, save);
  1986. return CURLE_OK;
  1987. }
  1988. case CF_QUERY_CONNECT_REPLY_MS:
  1989. if(ctx->q.got_first_byte) {
  1990. timediff_t ms = Curl_timediff(ctx->q.first_byte_at, ctx->started_at);
  1991. *pres1 = (ms < INT_MAX)? (int)ms : INT_MAX;
  1992. }
  1993. else
  1994. *pres1 = -1;
  1995. return CURLE_OK;
  1996. case CF_QUERY_TIMER_CONNECT: {
  1997. struct curltime *when = pres2;
  1998. if(ctx->q.got_first_byte)
  1999. *when = ctx->q.first_byte_at;
  2000. return CURLE_OK;
  2001. }
  2002. case CF_QUERY_TIMER_APPCONNECT: {
  2003. struct curltime *when = pres2;
  2004. if(cf->connected)
  2005. *when = ctx->handshake_at;
  2006. return CURLE_OK;
  2007. }
  2008. default:
  2009. break;
  2010. }
  2011. return cf->next?
  2012. cf->next->cft->query(cf->next, data, query, pres1, pres2) :
  2013. CURLE_UNKNOWN_OPTION;
  2014. }
  2015. static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
  2016. struct Curl_easy *data,
  2017. bool *input_pending)
  2018. {
  2019. struct cf_ngtcp2_ctx *ctx = cf->ctx;
  2020. bool alive = FALSE;
  2021. const ngtcp2_transport_params *rp;
  2022. struct cf_call_data save;
  2023. CF_DATA_SAVE(save, cf, data);
  2024. *input_pending = FALSE;
  2025. if(!ctx->qconn)
  2026. goto out;
  2027. /* Both sides of the QUIC connection announce they max idle times in
  2028. * the transport parameters. Look at the minimum of both and if
  2029. * we exceed this, regard the connection as dead. The other side
  2030. * may have completely purged it and will no longer respond
  2031. * to any packets from us. */
  2032. rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
  2033. if(rp) {
  2034. timediff_t idletime;
  2035. uint64_t idle_ms = ctx->max_idle_ms;
  2036. if(rp->max_idle_timeout &&
  2037. (rp->max_idle_timeout / NGTCP2_MILLISECONDS) < idle_ms)
  2038. idle_ms = (rp->max_idle_timeout / NGTCP2_MILLISECONDS);
  2039. idletime = Curl_timediff(Curl_now(), ctx->q.last_io);
  2040. if(idletime > 0 && (uint64_t)idletime > idle_ms)
  2041. goto out;
  2042. }
  2043. if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending))
  2044. goto out;
  2045. alive = TRUE;
  2046. if(*input_pending) {
  2047. CURLcode result;
  2048. /* This happens before we've sent off a request and the connection is
  2049. not in use by any other transfer, there shouldn't be any data here,
  2050. only "protocol frames" */
  2051. *input_pending = FALSE;
  2052. result = cf_progress_ingress(cf, data, NULL);
  2053. CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result);
  2054. alive = result? FALSE : TRUE;
  2055. }
  2056. out:
  2057. CF_DATA_RESTORE(cf, save);
  2058. return alive;
  2059. }
  2060. struct Curl_cftype Curl_cft_http3 = {
  2061. "HTTP/3",
  2062. CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
  2063. 0,
  2064. cf_ngtcp2_destroy,
  2065. cf_ngtcp2_connect,
  2066. cf_ngtcp2_close,
  2067. Curl_cf_def_get_host,
  2068. cf_ngtcp2_adjust_pollset,
  2069. cf_ngtcp2_data_pending,
  2070. cf_ngtcp2_send,
  2071. cf_ngtcp2_recv,
  2072. cf_ngtcp2_data_event,
  2073. cf_ngtcp2_conn_is_alive,
  2074. Curl_cf_def_conn_keep_alive,
  2075. cf_ngtcp2_query,
  2076. };
  2077. CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf,
  2078. struct Curl_easy *data,
  2079. struct connectdata *conn,
  2080. const struct Curl_addrinfo *ai)
  2081. {
  2082. struct cf_ngtcp2_ctx *ctx = NULL;
  2083. struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
  2084. CURLcode result;
  2085. (void)data;
  2086. ctx = calloc(1, sizeof(*ctx));
  2087. if(!ctx) {
  2088. result = CURLE_OUT_OF_MEMORY;
  2089. goto out;
  2090. }
  2091. ctx->qlogfd = -1;
  2092. cf_ngtcp2_ctx_clear(ctx);
  2093. result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
  2094. if(result)
  2095. goto out;
  2096. result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
  2097. if(result)
  2098. goto out;
  2099. cf->conn = conn;
  2100. udp_cf->conn = cf->conn;
  2101. udp_cf->sockindex = cf->sockindex;
  2102. cf->next = udp_cf;
  2103. out:
  2104. *pcf = (!result)? cf : NULL;
  2105. if(result) {
  2106. if(udp_cf)
  2107. Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
  2108. Curl_safefree(cf);
  2109. Curl_safefree(ctx);
  2110. }
  2111. return result;
  2112. }
  2113. bool Curl_conn_is_ngtcp2(const struct Curl_easy *data,
  2114. const struct connectdata *conn,
  2115. int sockindex)
  2116. {
  2117. struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
  2118. (void)data;
  2119. for(; cf; cf = cf->next) {
  2120. if(cf->cft == &Curl_cft_http3)
  2121. return TRUE;
  2122. if(cf->cft->flags & CF_TYPE_IP_CONNECT)
  2123. return FALSE;
  2124. }
  2125. return FALSE;
  2126. }
  2127. #endif