Lines Matching +full:nghttp3 +full:- +full:version
21 * SPDX-License-Identifier: curl
32 #include <nghttp3/nghttp3.h>
42 #include "cf-socket.h"
52 #include "vquic-tls.h"
99 ((struct cf_osslq_ctx *)(cf)->ctx)->call_data
175 switch(addr->family) { in make_bio_addr()
178 (struct sockaddr_in * const)(void *)&addr->sa_addr; in make_bio_addr()
179 if(!BIO_ADDR_rawmake(ba, AF_INET, &sin->sin_addr, in make_bio_addr()
180 sizeof(sin->sin_addr), sin->sin_port)) { in make_bio_addr()
189 (struct sockaddr_in6 * const)(void *)&addr->sa_addr; in make_bio_addr()
190 if(!BIO_ADDR_rawmake(ba, AF_INET6, &sin->sin6_addr, in make_bio_addr()
191 sizeof(sin->sin6_addr), sin->sin6_port)) { in make_bio_addr()
229 DEBUGASSERT(!s->ssl); in cf_osslq_stream_open()
230 Curl_bufq_initp(&s->recvbuf, bufcp, 1, BUFQ_OPT_NONE); in cf_osslq_stream_open()
231 s->ssl = SSL_new_stream(conn, flags); in cf_osslq_stream_open()
232 if(!s->ssl) { in cf_osslq_stream_open()
235 s->id = SSL_get_stream_id(s->ssl); in cf_osslq_stream_open()
236 SSL_set_app_data(s->ssl, user_data); in cf_osslq_stream_open()
242 if(s->ssl) { in cf_osslq_stream_cleanup()
243 SSL_set_app_data(s->ssl, NULL); in cf_osslq_stream_cleanup()
244 SSL_free(s->ssl); in cf_osslq_stream_cleanup()
246 Curl_bufq_free(&s->recvbuf); in cf_osslq_stream_cleanup()
252 if(s->ssl) { in cf_osslq_stream_close()
253 SSL_free(s->ssl); in cf_osslq_stream_close()
254 s->ssl = NULL; in cf_osslq_stream_close()
272 if(h3->conn) in cf_osslq_h3conn_cleanup()
273 nghttp3_conn_del(h3->conn); in cf_osslq_h3conn_cleanup()
274 cf_osslq_stream_cleanup(&h3->s_ctrl); in cf_osslq_h3conn_cleanup()
275 cf_osslq_stream_cleanup(&h3->s_qpack_enc); in cf_osslq_h3conn_cleanup()
276 cf_osslq_stream_cleanup(&h3->s_qpack_dec); in cf_osslq_h3conn_cleanup()
277 for(i = 0; i < h3->remote_ctrl_n; ++i) { in cf_osslq_h3conn_cleanup()
278 cf_osslq_stream_cleanup(&h3->remote_ctrl[i]); in cf_osslq_h3conn_cleanup()
293 struct Curl_hash streams; /* hash `data->id` to `h3_stream_ctx` */
305 struct cf_call_data save = ctx->call_data; in cf_osslq_ctx_clear()
307 cf_osslq_h3conn_cleanup(&ctx->h3); in cf_osslq_ctx_clear()
308 Curl_vquic_tls_cleanup(&ctx->tls); in cf_osslq_ctx_clear()
309 vquic_ctx_free(&ctx->q); in cf_osslq_ctx_clear()
310 Curl_bufcp_free(&ctx->stream_bufcp); in cf_osslq_ctx_clear()
311 Curl_hash_clean(&ctx->streams); in cf_osslq_ctx_clear()
312 Curl_hash_destroy(&ctx->streams); in cf_osslq_ctx_clear()
313 Curl_ssl_peer_cleanup(&ctx->peer); in cf_osslq_ctx_clear()
316 ctx->call_data = save; in cf_osslq_ctx_clear()
321 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_close()
325 if(ctx && ctx->tls.ossl.ssl) { in cf_osslq_close()
331 cf->connected = FALSE; in cf_osslq_close()
337 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_destroy()
347 cf->ctx = NULL; in cf_osslq_destroy()
357 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_h3conn_add_stream()
360 if(h3->remote_ctrl_n >= ARRAYSIZE(h3->remote_ctrl)) { in cf_osslq_h3conn_add_stream()
369 struct cf_osslq_stream *nstream = &h3->remote_ctrl[h3->remote_ctrl_n++]; in cf_osslq_h3conn_add_stream()
370 nstream->id = stream_id; in cf_osslq_h3conn_add_stream()
371 nstream->ssl = stream_ssl; in cf_osslq_h3conn_add_stream()
372 Curl_bufq_initp(&nstream->recvbuf, &ctx->stream_bufcp, 1, BUFQ_OPT_NONE); in cf_osslq_h3conn_add_stream()
378 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reject remote non-uni-read" in cf_osslq_h3conn_add_stream()
391 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_ssl_err()
410 lerr = SSL_get_verify_result(ctx->tls.ossl.ssl); in cf_osslq_ssl_err()
412 ssl_config->certverifyresult = lerr; in cf_osslq_ssl_err()
422 OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */ in cf_osslq_ssl_err()
432 ctx->protocol_shutdown = TRUE; in cf_osslq_ssl_err()
443 /* If we e.g. use SSLv2 request-method and the server doesn't like us in cf_osslq_ssl_err()
452 Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip); in cf_osslq_ssl_err()
457 ctx->peer.dispname, ip.remote_port, ip.remote_ip); in cf_osslq_ssl_err()
469 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_verify_peer()
471 cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ in cf_osslq_verify_peer()
472 cf->conn->httpversion = 30; in cf_osslq_verify_peer()
473 cf->conn->bundle->multiuse = BUNDLE_MULTIPLEX; in cf_osslq_verify_peer()
475 return Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer); in cf_osslq_verify_peer()
501 data? Curl_hash_offt_get(&(ctx)->streams, (data)->id) : NULL))
505 cf_osslq_stream_cleanup(&stream->s); in h3_stream_ctx_free()
506 Curl_bufq_free(&stream->sendbuf); in h3_stream_ctx_free()
507 Curl_bufq_free(&stream->recvbuf); in h3_stream_ctx_free()
508 Curl_h1_req_parse_free(&stream->h1); in h3_stream_ctx_free()
521 struct cf_osslq_ctx *ctx = cf->ctx; in h3_data_setup()
524 if(!data || !data->req.p.http) { in h3_data_setup()
536 stream->s.id = -1; in h3_data_setup()
538 Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp, in h3_data_setup()
540 stream->sendbuf_len_in_flight = 0; in h3_data_setup()
542 * headers to it that are not counted against the nghttp3 flow limits. */ in h3_data_setup()
543 Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp, in h3_data_setup()
545 stream->recv_buf_nonflow = 0; in h3_data_setup()
546 Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); in h3_data_setup()
548 if(!Curl_hash_offt_set(&ctx->streams, data->id, stream)) { in h3_data_setup()
558 struct cf_osslq_ctx *ctx = cf->ctx; in h3_data_done()
564 stream->s.id); in h3_data_done()
565 if(ctx->h3.conn && !stream->closed) { in h3_data_done()
566 nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id); in h3_data_done()
567 nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id, in h3_data_done()
569 nghttp3_conn_set_stream_user_data(ctx->h3.conn, stream->s.id, NULL); in h3_data_done()
570 stream->closed = TRUE; in h3_data_done()
573 Curl_hash_offt_remove(&ctx->streams, data->id); in h3_data_done()
581 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_get_qstream()
585 if(stream && stream->s.id == stream_id) { in cf_osslq_get_qstream()
586 return &stream->s; in cf_osslq_get_qstream()
588 else if(ctx->h3.s_ctrl.id == stream_id) { in cf_osslq_get_qstream()
589 return &ctx->h3.s_ctrl; in cf_osslq_get_qstream()
591 else if(ctx->h3.s_qpack_enc.id == stream_id) { in cf_osslq_get_qstream()
592 return &ctx->h3.s_qpack_enc; in cf_osslq_get_qstream()
594 else if(ctx->h3.s_qpack_dec.id == stream_id) { in cf_osslq_get_qstream()
595 return &ctx->h3.s_qpack_dec; in cf_osslq_get_qstream()
598 DEBUGASSERT(data->multi); in cf_osslq_get_qstream()
599 for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { in cf_osslq_get_qstream()
600 if(sdata->conn != data->conn) in cf_osslq_get_qstream()
603 if(stream && stream->s.id == stream_id) { in cf_osslq_get_qstream()
604 return &stream->s; in cf_osslq_get_qstream()
614 struct cf_osslq_ctx *ctx = cf->ctx; in h3_drain_stream()
620 if(stream && stream->upload_left && !stream->send_closed) in h3_drain_stream()
622 if(data->state.select_bits != bits) { in h3_drain_stream()
623 data->state.select_bits = bits; in h3_drain_stream()
645 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_stream_close()
651 /* we might be called by nghttp3 after we already cleaned up */ in cb_h3_stream_close()
655 stream->closed = TRUE; in cb_h3_stream_close()
656 stream->error3 = app_error_code; in cb_h3_stream_close()
657 if(stream->error3 != NGHTTP3_H3_NO_ERROR) { in cb_h3_stream_close()
658 stream->reset = TRUE; in cb_h3_stream_close()
659 stream->send_closed = TRUE; in cb_h3_stream_close()
661 stream->s.id, stream->error3); in cb_h3_stream_close()
664 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] CLOSED", stream->s.id); in cb_h3_stream_close()
680 struct cf_osslq_ctx *ctx = cf->ctx; in write_resp_raw()
689 nwritten = Curl_bufq_write(&stream->recvbuf, mem, memlen, &result); in write_resp_raw()
695 stream->recv_buf_nonflow += (size_t)nwritten; in write_resp_raw()
711 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_recv_data()
725 stream->s.id, buflen, result); in cb_h3_recv_data()
728 stream->download_recvd += (curl_off_t)buflen; in cb_h3_recv_data()
730 stream->s.id, buflen, stream->download_recvd); in cb_h3_recv_data()
740 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_deferred_consume()
748 stream->s.id, consumed); in cb_h3_deferred_consume()
759 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_recv_header()
779 result = Curl_http_decode_status(&stream->status_code, in cb_h3_recv_header()
782 return -1; in cb_h3_recv_header()
784 stream->status_code); in cb_h3_recv_header()
788 return -1; in cb_h3_recv_header()
792 /* store as an HTTP1-style header */ in cb_h3_recv_header()
798 return -1; in cb_h3_recv_header()
802 return -1; in cb_h3_recv_header()
806 return -1; in cb_h3_recv_header()
810 return -1; in cb_h3_recv_header()
820 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_end_headers()
835 return -1; in cb_h3_end_headers()
839 stream_id, stream->status_code); in cb_h3_end_headers()
840 if(stream->status_code / 100 != 1) { in cb_h3_end_headers()
841 stream->resp_hds_complete = TRUE; in cb_h3_end_headers()
852 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_stop_sending()
859 if(!stream || !stream->s.ssl) in cb_h3_stop_sending()
863 cf_osslq_stream_close(&stream->s); in cb_h3_stop_sending()
871 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_reset_stream()
878 if(stream && stream->s.ssl) { in cb_h3_reset_stream()
881 rv = !SSL_stream_reset(stream->s.ssl, &args, sizeof(args)); in cb_h3_reset_stream()
882 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] reset -> %d", stream_id, rv); in cb_h3_reset_stream()
897 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_read_req_body()
910 /* nghttp3 keeps references to the sendbuf data until it is ACKed in cb_h3_read_req_body()
913 * that we have already passed to nghttp3, but which have not been in cb_h3_read_req_body()
916 * to nghttp3. Do that now, if we can. */ in cb_h3_read_req_body()
917 if(stream->sendbuf_len_in_flight < Curl_bufq_len(&stream->sendbuf)) { in cb_h3_read_req_body()
920 Curl_bufq_peek_at(&stream->sendbuf, in cb_h3_read_req_body()
921 stream->sendbuf_len_in_flight, in cb_h3_read_req_body()
924 stream->sendbuf_len_in_flight += vec[nvecs].len; in cb_h3_read_req_body()
931 if(nwritten > 0 && stream->upload_left != -1) in cb_h3_read_req_body()
932 stream->upload_left -= nwritten; in cb_h3_read_req_body()
936 if(stream->upload_left == 0) { in cb_h3_read_req_body()
938 stream->send_closed = TRUE; in cb_h3_read_req_body()
942 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> AGAIN", in cb_h3_read_req_body()
943 stream->s.id); in cb_h3_read_req_body()
947 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] read req body -> " in cb_h3_read_req_body()
950 stream->s.id, (int)nvecs, in cb_h3_read_req_body()
952 nwritten, Curl_bufq_len(&stream->sendbuf), in cb_h3_read_req_body()
953 stream->upload_left); in cb_h3_read_req_body()
962 struct cf_osslq_ctx *ctx = cf->ctx; in cb_h3_acked_stream_data()
972 * re-transmissions and can free it now. */ in cb_h3_acked_stream_data()
973 if(datalen >= (uint64_t)stream->sendbuf_len_in_flight) in cb_h3_acked_stream_data()
974 skiplen = stream->sendbuf_len_in_flight; in cb_h3_acked_stream_data()
977 Curl_bufq_skip(&stream->sendbuf, skiplen); in cb_h3_acked_stream_data()
978 stream->sendbuf_len_in_flight -= skiplen; in cb_h3_acked_stream_data()
981 if(!stream->sendbuf_len_in_flight) { in cb_h3_acked_stream_data()
1011 struct cf_osslq_h3conn *h3 = &ctx->h3; in cf_osslq_h3conn_init()
1015 nghttp3_settings_default(&h3->settings); in cf_osslq_h3conn_init()
1016 rc = nghttp3_conn_client_new(&h3->conn, in cf_osslq_h3conn_init()
1018 &h3->settings, in cf_osslq_h3conn_init()
1026 result = cf_osslq_stream_open(&h3->s_ctrl, conn, in cf_osslq_h3conn_init()
1028 &ctx->stream_bufcp, NULL); in cf_osslq_h3conn_init()
1033 result = cf_osslq_stream_open(&h3->s_qpack_enc, conn, in cf_osslq_h3conn_init()
1035 &ctx->stream_bufcp, NULL); in cf_osslq_h3conn_init()
1040 result = cf_osslq_stream_open(&h3->s_qpack_dec, conn, in cf_osslq_h3conn_init()
1042 &ctx->stream_bufcp, NULL); in cf_osslq_h3conn_init()
1048 rc = nghttp3_conn_bind_control_stream(h3->conn, h3->s_ctrl.id); in cf_osslq_h3conn_init()
1053 rc = nghttp3_conn_bind_qpack_streams(h3->conn, h3->s_qpack_enc.id, in cf_osslq_h3conn_init()
1054 h3->s_qpack_dec.id); in cf_osslq_h3conn_init()
1068 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_ctx_start()
1075 Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, in cf_osslq_ctx_start()
1077 Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free); in cf_osslq_ctx_start()
1078 result = Curl_ssl_peer_init(&ctx->peer, cf, TRNSPRT_QUIC); in cf_osslq_ctx_start()
1083 result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, in cf_osslq_ctx_start()
1084 H3_ALPN, sizeof(H3_ALPN) - 1, in cf_osslq_ctx_start()
1089 result = vquic_ctx_init(&ctx->q); in cf_osslq_ctx_start()
1094 Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd, &peer_addr, NULL); in cf_osslq_ctx_start()
1098 ctx->q.local_addrlen = sizeof(ctx->q.local_addr); in cf_osslq_ctx_start()
1099 rv = getsockname(ctx->q.sockfd, (struct sockaddr *)&ctx->q.local_addr, in cf_osslq_ctx_start()
1100 &ctx->q.local_addrlen); in cf_osslq_ctx_start()
1101 if(rv == -1) in cf_osslq_ctx_start()
1110 /* Type conversions, see #12861: OpenSSL wants an `int`, but on 64-bit in cf_osslq_ctx_start()
1114 if(ctx->q.sockfd > INT_MAX) { in cf_osslq_ctx_start()
1120 bio = BIO_new_dgram((int)ctx->q.sockfd, BIO_NOCLOSE); in cf_osslq_ctx_start()
1122 bio = BIO_new_dgram(ctx->q.sockfd, BIO_NOCLOSE); in cf_osslq_ctx_start()
1129 if(!SSL_set1_initial_peer_addr(ctx->tls.ossl.ssl, baddr)) { in cf_osslq_ctx_start()
1134 if(!SSL_set_blocking_mode(ctx->tls.ossl.ssl, 0)) { in cf_osslq_ctx_start()
1142 if(!SSL_set_feature_request_uint(ctx->tls.ossl.ssl, in cf_osslq_ctx_start()
1151 SSL_set_bio(ctx->tls.ossl.ssl, bio, bio); in cf_osslq_ctx_start()
1153 SSL_set_connect_state(ctx->tls.ossl.ssl); in cf_osslq_ctx_start()
1154 SSL_set_incoming_stream_policy(ctx->tls.ossl.ssl, in cf_osslq_ctx_start()
1157 result = cf_osslq_h3conn_init(ctx, ctx->tls.ossl.ssl, cf); in cf_osslq_ctx_start()
1164 CURL_TRC_CF(data, cf, "QUIC tls init -> %d", result); in cf_osslq_ctx_start()
1183 rv = SSL_read_ex(x->s->ssl, buf, len, &nread); in h3_quic_recv()
1185 int detail = SSL_get_error(x->s->ssl, rv); in h3_quic_recv()
1188 return -1; in h3_quic_recv()
1191 CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRId64 "] h3_quic_recv -> EOS", in h3_quic_recv()
1192 x->s->id); in h3_quic_recv()
1193 x->s->recvd_eos = TRUE; in h3_quic_recv()
1196 else if(SSL_get_stream_read_state(x->s->ssl) == in h3_quic_recv()
1199 SSL_get_stream_read_error_code(x->s->ssl, &app_error_code); in h3_quic_recv()
1200 CURL_TRC_CF(x->data, x->cf, "[%" CURL_PRId64 "] h3_quic_recv -> RESET, " in h3_quic_recv()
1202 x->s->id, rv, (curl_uint64_t)app_error_code); in h3_quic_recv()
1204 x->s->reset = TRUE; in h3_quic_recv()
1206 x->s->recvd_eos = TRUE; in h3_quic_recv()
1210 *err = cf_osslq_ssl_err(x->cf, x->data, detail, CURLE_RECV_ERROR); in h3_quic_recv()
1211 return -1; in h3_quic_recv()
1221 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_stream_recv()
1229 if(s->closed) in cf_osslq_stream_recv()
1235 while(s->ssl && !s->closed && !eagain && in cf_osslq_stream_recv()
1237 if(Curl_bufq_is_empty(&s->recvbuf) && !s->recvd_eos) { in cf_osslq_stream_recv()
1238 while(!eagain && !s->recvd_eos && !Curl_bufq_is_full(&s->recvbuf)) { in cf_osslq_stream_recv()
1239 nread = Curl_bufq_sipn(&s->recvbuf, 0, h3_quic_recv, &x, &result); in cf_osslq_stream_recv()
1249 /* Forward what we have to nghttp3 */ in cf_osslq_stream_recv()
1250 if(!Curl_bufq_is_empty(&s->recvbuf)) { in cf_osslq_stream_recv()
1254 while(Curl_bufq_peek(&s->recvbuf, &buf, &blen)) { in cf_osslq_stream_recv()
1255 nread = nghttp3_conn_read_stream(ctx->h3.conn, s->id, in cf_osslq_stream_recv()
1258 "to nghttp3 -> %zd", s->id, blen, nread); in cf_osslq_stream_recv()
1267 * all data that we passed is not owned by nghttp3. */ in cf_osslq_stream_recv()
1268 Curl_bufq_skip(&s->recvbuf, blen); in cf_osslq_stream_recv()
1274 if(Curl_bufq_is_empty(&s->recvbuf) && !s->closed) { in cf_osslq_stream_recv()
1276 if(s->reset) { in cf_osslq_stream_recv()
1278 if(!SSL_get_stream_read_error_code(s->ssl, &app_error)) { in cf_osslq_stream_recv()
1283 rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id, app_error); in cf_osslq_stream_recv()
1284 s->closed = TRUE; in cf_osslq_stream_recv()
1292 else if(s->recvd_eos) { in cf_osslq_stream_recv()
1293 rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id, in cf_osslq_stream_recv()
1295 s->closed = TRUE; in cf_osslq_stream_recv()
1296 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] close nghttp3 stream -> %d", in cf_osslq_stream_recv()
1297 s->id, rv); in cf_osslq_stream_recv()
1309 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_osslq_stream_recv -> %d", in cf_osslq_stream_recv()
1310 s->id, result); in cf_osslq_stream_recv()
1317 struct cf_osslq_ctx *ctx = cf->ctx; in cf_progress_ingress()
1320 if(!ctx->tls.ossl.ssl) in cf_progress_ingress()
1327 SSL *snew = SSL_accept_stream(ctx->tls.ossl.ssl, in cf_progress_ingress()
1332 (void)cf_osslq_h3conn_add_stream(&ctx->h3, snew, cf, data); in cf_progress_ingress()
1335 if(!SSL_handle_events(ctx->tls.ossl.ssl)) { in cf_progress_ingress()
1336 int detail = SSL_get_error(ctx->tls.ossl.ssl, 0); in cf_progress_ingress()
1340 if(ctx->h3.conn) { in cf_progress_ingress()
1342 for(i = 0; i < ctx->h3.remote_ctrl_n; ++i) { in cf_progress_ingress()
1343 result = cf_osslq_stream_recv(&ctx->h3.remote_ctrl[i], cf, data); in cf_progress_ingress()
1349 if(ctx->h3.conn) { in cf_progress_ingress()
1353 DEBUGASSERT(data->multi); in cf_progress_ingress()
1354 for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { in cf_progress_ingress()
1355 if(sdata->conn == data->conn && CURL_WANT_RECV(sdata)) { in cf_progress_ingress()
1357 if(stream && !stream->closed && in cf_progress_ingress()
1358 !Curl_bufq_is_full(&stream->recvbuf)) { in cf_progress_ingress()
1359 result = cf_osslq_stream_recv(&stream->s, cf, sdata); in cf_progress_ingress()
1368 CURL_TRC_CF(data, cf, "progress_ingress -> %d", result); in cf_progress_ingress()
1376 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_check_and_unblock()
1380 if(ctx->h3.conn) { in cf_osslq_check_and_unblock()
1381 for(sdata = data->multi->easyp; sdata; sdata = sdata->next) { in cf_osslq_check_and_unblock()
1382 if(sdata->conn == data->conn) { in cf_osslq_check_and_unblock()
1384 if(stream && stream->s.ssl && stream->s.send_blocked && in cf_osslq_check_and_unblock()
1385 !SSL_want_write(stream->s.ssl)) { in cf_osslq_check_and_unblock()
1386 nghttp3_conn_unblock_stream(ctx->h3.conn, stream->s.id); in cf_osslq_check_and_unblock()
1387 stream->s.send_blocked = FALSE; in cf_osslq_check_and_unblock()
1400 struct cf_osslq_ctx *ctx = cf->ctx; in h3_send_streams()
1403 if(!ctx->tls.ossl.ssl || !ctx->h3.conn) in h3_send_streams()
1416 n = nghttp3_conn_writev_stream(ctx->h3.conn, &stream_id, &eos, in h3_send_streams()
1438 DEBUGASSERT(s->id == stream_id); in h3_send_streams()
1443 /* Without stream->s.ssl, we closed that already, so in h3_send_streams()
1449 ok = !s->ssl || SSL_write_ex2(s->ssl, vec[i].base, vec[i].len, flags, in h3_send_streams()
1455 ok = !s->ssl || SSL_write_ex(s->ssl, vec[i].base, vec[i].len, in h3_send_streams()
1460 * from nghttp3's point of view */ in h3_send_streams()
1462 s->id, vec[i].len); in h3_send_streams()
1466 int detail = SSL_get_error(s->ssl, 0); in h3_send_streams()
1472 "QUIC blocked", s->id, vec[i].len); in h3_send_streams()
1474 nghttp3_conn_block_stream(ctx->h3.conn, s->id); in h3_send_streams()
1475 s->send_blocked = blocked = TRUE; in h3_send_streams()
1479 s->id, vec[i].len, detail); in h3_send_streams()
1486 if(acked_len > 0 || (eos && !s->send_blocked)) { in h3_send_streams()
1488 * nghttp3 that it can move forward on it */ in h3_send_streams()
1489 ctx->q.last_io = Curl_now(); in h3_send_streams()
1490 rv = nghttp3_conn_add_write_offset(ctx->h3.conn, s->id, acked_len); in h3_send_streams()
1497 rv = nghttp3_conn_add_ack_offset(ctx->h3.conn, s->id, acked_len); in h3_send_streams()
1505 "to QUIC, eos=%d", s->id, acked_len, total_len, eos); in h3_send_streams()
1508 if(eos && !s->send_blocked && !eos_written) { in h3_send_streams()
1510 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] closing QUIC stream", s->id); in h3_send_streams()
1511 SSL_stream_conclude(s->ssl, 0); in h3_send_streams()
1516 CURL_TRC_CF(data, cf, "h3_send_streams -> %d", result); in h3_send_streams()
1523 struct cf_osslq_ctx *ctx = cf->ctx; in cf_progress_egress()
1526 if(!ctx->tls.ossl.ssl) in cf_progress_egress()
1534 if(!SSL_handle_events(ctx->tls.ossl.ssl)) { in cf_progress_egress()
1535 int detail = SSL_get_error(ctx->tls.ossl.ssl, 0); in cf_progress_egress()
1542 CURL_TRC_CF(data, cf, "progress_egress -> %d", result); in cf_progress_egress()
1549 struct cf_osslq_ctx *ctx = cf->ctx; in check_and_set_expiry()
1555 if(ctx->tls.ossl.ssl && in check_and_set_expiry()
1556 SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite) && in check_and_set_expiry()
1567 if(SSL_get_event_timeout(ctx->tls.ossl.ssl, &tv, &is_infinite)) { in check_and_set_expiry()
1584 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_connect()
1590 if(cf->connected) { in cf_osslq_connect()
1596 if(!cf->next->connected) { in cf_osslq_connect()
1597 result = Curl_conn_cf_connect(cf->next, data, blocking, done); in cf_osslq_connect()
1606 if(ctx->reconnect_at.tv_sec && Curl_timediff(now, ctx->reconnect_at) < 0) { in cf_osslq_connect()
1612 if(!ctx->tls.ossl.ssl) { in cf_osslq_connect()
1613 ctx->started_at = now; in cf_osslq_connect()
1619 if(!ctx->got_first_byte) { in cf_osslq_connect()
1620 int readable = SOCKET_READABLE(ctx->q.sockfd, 0); in cf_osslq_connect()
1622 ctx->got_first_byte = TRUE; in cf_osslq_connect()
1623 ctx->first_byte_at = Curl_now(); in cf_osslq_connect()
1628 err = SSL_do_handshake(ctx->tls.ossl.ssl); in cf_osslq_connect()
1632 ctx->handshake_at = now; in cf_osslq_connect()
1633 ctx->q.last_io = now; in cf_osslq_connect()
1635 (int)Curl_timediff(now, ctx->started_at)); in cf_osslq_connect()
1639 cf->connected = TRUE; in cf_osslq_connect()
1640 cf->conn->alpn = CURL_HTTP_VERSION_3; in cf_osslq_connect()
1642 connkeep(cf->conn, "HTTP/3 default"); in cf_osslq_connect()
1646 int detail = SSL_get_error(ctx->tls.ossl.ssl, err); in cf_osslq_connect()
1649 ctx->q.last_io = now; in cf_osslq_connect()
1650 CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_RECV"); in cf_osslq_connect()
1651 result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data); in cf_osslq_connect()
1654 ctx->q.last_io = now; in cf_osslq_connect()
1655 CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_SEND"); in cf_osslq_connect()
1660 ctx->q.last_io = now; in cf_osslq_connect()
1661 CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_ASYNC"); in cf_osslq_connect()
1677 if(result == CURLE_RECV_ERROR && ctx->tls.ossl.ssl && in cf_osslq_connect()
1678 ctx->protocol_shutdown) { in cf_osslq_connect()
1690 Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip); in cf_osslq_connect()
1698 CURL_TRC_CF(data, cf, "connect -> %d, done=%d", result, *done); in cf_osslq_connect()
1708 struct cf_osslq_ctx *ctx = cf->ctx; in h3_stream_open()
1715 ssize_t nwritten = -1; in h3_stream_open()
1731 nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err); in h3_stream_open()
1734 if(!stream->h1.done) { in h3_stream_open()
1738 DEBUGASSERT(stream->h1.req); in h3_stream_open()
1740 *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data); in h3_stream_open()
1742 nwritten = -1; in h3_stream_open()
1746 Curl_h1_req_parse_free(&stream->h1); in h3_stream_open()
1752 nwritten = -1; in h3_stream_open()
1758 nva[i].name = (unsigned char *)e->name; in h3_stream_open()
1759 nva[i].namelen = e->namelen; in h3_stream_open()
1760 nva[i].value = (unsigned char *)e->value; in h3_stream_open()
1761 nva[i].valuelen = e->valuelen; in h3_stream_open()
1765 DEBUGASSERT(stream->s.id == -1); in h3_stream_open()
1766 *err = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0, in h3_stream_open()
1767 &ctx->stream_bufcp, data); in h3_stream_open()
1774 switch(data->state.httpreq) { in h3_stream_open()
1779 /* known request body size or -1 */ in h3_stream_open()
1780 if(data->state.infilesize != -1) in h3_stream_open()
1781 stream->upload_left = data->state.infilesize; in h3_stream_open()
1784 stream->upload_left = -1; /* unknown */ in h3_stream_open()
1788 stream->upload_left = 0; /* no request body */ in h3_stream_open()
1792 stream->send_closed = (stream->upload_left == 0); in h3_stream_open()
1793 if(!stream->send_closed) { in h3_stream_open()
1798 rc = nghttp3_conn_submit_request(ctx->h3.conn, stream->s.id, in h3_stream_open()
1804 "connection is closing", stream->s.id); in h3_stream_open()
1807 CURL_TRC_CF(data, cf, "h3sid[%"CURL_PRId64 "] failed to send -> %d (%s)", in h3_stream_open()
1808 stream->s.id, rc, nghttp3_strerror(rc)); in h3_stream_open()
1812 nwritten = -1; in h3_stream_open()
1818 stream->s.id, data->state.url); in h3_stream_open()
1821 stream->s.id, in h3_stream_open()
1836 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_send()
1843 DEBUGASSERT(cf->connected); in cf_osslq_send()
1844 DEBUGASSERT(ctx->tls.ossl.ssl); in cf_osslq_send()
1845 DEBUGASSERT(ctx->h3.conn); in cf_osslq_send()
1851 nwritten = -1; in cf_osslq_send()
1858 nwritten = -1; in cf_osslq_send()
1862 if(!stream || stream->s.id < 0) { in cf_osslq_send()
1865 CURL_TRC_CF(data, cf, "failed to open stream -> %d", *err); in cf_osslq_send()
1870 else if(stream->upload_blocked_len) { in cf_osslq_send()
1873 DEBUGASSERT(len >= stream->upload_blocked_len); in cf_osslq_send()
1874 if(len < stream->upload_blocked_len) { in cf_osslq_send()
1879 nwritten = -1; in cf_osslq_send()
1882 nwritten = (ssize_t)stream->upload_blocked_len; in cf_osslq_send()
1883 stream->upload_blocked_len = 0; in cf_osslq_send()
1885 else if(stream->closed) { in cf_osslq_send()
1886 if(stream->resp_hds_complete) { in cf_osslq_send()
1893 "on closed stream with response", stream->s.id); in cf_osslq_send()
1899 "-> stream closed", stream->s.id, len); in cf_osslq_send()
1901 nwritten = -1; in cf_osslq_send()
1905 nwritten = Curl_bufq_write(&stream->sendbuf, buf, len, err); in cf_osslq_send()
1907 "sendbuf(len=%zu) -> %zd, %d", in cf_osslq_send()
1908 stream->s.id, len, nwritten, *err); in cf_osslq_send()
1913 (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id); in cf_osslq_send()
1919 nwritten = -1; in cf_osslq_send()
1922 if(stream && nwritten > 0 && stream->sendbuf_len_in_flight) { in cf_osslq_send()
1926 stream->upload_blocked_len = nwritten; in cf_osslq_send()
1928 "%zu bytes in flight -> EGAIN", stream->s.id, len, in cf_osslq_send()
1929 stream->sendbuf_len_in_flight); in cf_osslq_send()
1931 nwritten = -1; in cf_osslq_send()
1936 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_send(len=%zu) -> %zd, %d", in cf_osslq_send()
1937 stream? stream->s.id : -1, len, nwritten, *err); in cf_osslq_send()
1947 ssize_t nread = -1; in recv_closed_stream()
1950 if(stream->reset) { in recv_closed_stream()
1953 stream->s.id); in recv_closed_stream()
1954 *err = data->req.bytecount? CURLE_PARTIAL_FILE : CURLE_HTTP3; in recv_closed_stream()
1957 else if(!stream->resp_hds_complete) { in recv_closed_stream()
1962 stream->s.id); in recv_closed_stream()
1976 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_recv()
1978 ssize_t nread = -1; in cf_osslq_recv()
1984 DEBUGASSERT(cf->connected); in cf_osslq_recv()
1986 DEBUGASSERT(ctx->tls.ossl.ssl); in cf_osslq_recv()
1987 DEBUGASSERT(ctx->h3.conn); in cf_osslq_recv()
1995 if(!Curl_bufq_is_empty(&stream->recvbuf)) { in cf_osslq_recv()
1996 nread = Curl_bufq_read(&stream->recvbuf, in cf_osslq_recv()
2000 "-> %zd, %d", stream->s.id, len, nread, *err); in cf_osslq_recv()
2008 nread = -1; in cf_osslq_recv()
2013 if(nread < 0 && !Curl_bufq_is_empty(&stream->recvbuf)) { in cf_osslq_recv()
2014 nread = Curl_bufq_read(&stream->recvbuf, in cf_osslq_recv()
2018 "-> %zd, %d", stream->s.id, len, nread, *err); in cf_osslq_recv()
2027 if(stream->closed) { in cf_osslq_recv()
2032 nread = -1; in cf_osslq_recv()
2038 nread = -1; in cf_osslq_recv()
2044 nread = -1; in cf_osslq_recv()
2047 CURL_TRC_CF(data, cf, "[%" CURL_PRId64 "] cf_recv(len=%zu) -> %zd, %d", in cf_osslq_recv()
2048 stream? stream->s.id : -1, len, nread, *err); in cf_osslq_recv()
2060 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_data_pending()
2063 return stream && !Curl_bufq_is_empty(&stream->recvbuf); in cf_osslq_data_pending()
2070 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_data_event()
2091 if(stream && !stream->send_closed) { in cf_osslq_data_event()
2092 stream->send_closed = TRUE; in cf_osslq_data_event()
2093 stream->upload_left = Curl_bufq_len(&stream->sendbuf); in cf_osslq_data_event()
2094 (void)nghttp3_conn_resume_stream(ctx->h3.conn, stream->s.id); in cf_osslq_data_event()
2101 if(stream && !stream->closed) { in cf_osslq_data_event()
2117 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_conn_is_alive()
2123 if(!ctx->tls.ossl.ssl) in cf_osslq_conn_is_alive()
2130 uint64_t idle_ms = ctx->max_idle_ms; in cf_osslq_conn_is_alive()
2131 if(!SSL_get_value_uint(ctx->tls.ossl.ssl, in cf_osslq_conn_is_alive()
2139 idletime = Curl_timediff(Curl_now(), ctx->q.last_io); in cf_osslq_conn_is_alive()
2146 if(!cf->next || !cf->next->cft->is_alive(cf->next, data, input_pending)) in cf_osslq_conn_is_alive()
2157 CURL_TRC_CF(data, cf, "is_alive, progress ingress -> %d", result); in cf_osslq_conn_is_alive()
2170 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_adjust_pollset()
2172 if(!ctx->tls.ossl.ssl) { in cf_osslq_adjust_pollset()
2175 else if(!cf->connected) { in cf_osslq_adjust_pollset()
2178 Curl_pollset_set(data, ps, ctx->q.sockfd, in cf_osslq_adjust_pollset()
2179 SSL_net_read_desired(ctx->tls.ossl.ssl), in cf_osslq_adjust_pollset()
2180 SSL_net_write_desired(ctx->tls.ossl.ssl)); in cf_osslq_adjust_pollset()
2186 Curl_pollset_check(data, ps, ctx->q.sockfd, &want_recv, &want_send); in cf_osslq_adjust_pollset()
2188 Curl_pollset_set(data, ps, ctx->q.sockfd, in cf_osslq_adjust_pollset()
2189 SSL_net_read_desired(ctx->tls.ossl.ssl), in cf_osslq_adjust_pollset()
2190 SSL_net_write_desired(ctx->tls.ossl.ssl)); in cf_osslq_adjust_pollset()
2199 struct cf_osslq_ctx *ctx = cf->ctx; in cf_osslq_query()
2206 if(!SSL_get_value_uint(ctx->tls.ossl.ssl, SSL_VALUE_CLASS_GENERIC, in cf_osslq_query()
2212 v += CONN_INUSE(cf->conn); in cf_osslq_query()
2217 CURL_TRC_CF(data, cf, "query max_conncurrent -> %d", *pres1); in cf_osslq_query()
2221 if(ctx->got_first_byte) { in cf_osslq_query()
2222 timediff_t ms = Curl_timediff(ctx->first_byte_at, ctx->started_at); in cf_osslq_query()
2226 *pres1 = -1; in cf_osslq_query()
2230 if(ctx->got_first_byte) in cf_osslq_query()
2231 *when = ctx->first_byte_at; in cf_osslq_query()
2236 if(cf->connected) in cf_osslq_query()
2237 *when = ctx->handshake_at; in cf_osslq_query()
2243 return cf->next? in cf_osslq_query()
2244 cf->next->cft->query(cf->next, data, query, pres1, pres2) : in cf_osslq_query()
2291 cf->conn = conn; in Curl_cf_osslq_create()
2292 udp_cf->conn = cf->conn; in Curl_cf_osslq_create()
2293 udp_cf->sockindex = cf->sockindex; in Curl_cf_osslq_create()
2294 cf->next = udp_cf; in Curl_cf_osslq_create()
2311 struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL; in Curl_conn_is_osslq()
2314 for(; cf; cf = cf->next) { in Curl_conn_is_osslq()
2315 if(cf->cft == &Curl_cft_http3) in Curl_conn_is_osslq()
2317 if(cf->cft->flags & CF_TYPE_IP_CONNECT) in Curl_conn_is_osslq()
2324 * Store ngtcp2 version info in this buffer.
2329 (void)msnprintf(p, len, "nghttp3/%s", ht3->version_str); in Curl_osslq_ver()