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