2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2021 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "shrpx_http3_upstream.h"
27 #include <sys/types.h>
30 #include <netinet/udp.h>
34 #include <ngtcp2/ngtcp2_crypto.h>
36 #include "shrpx_client_handler.h"
37 #include "shrpx_downstream.h"
38 #include "shrpx_downstream_connection.h"
39 #include "shrpx_log.h"
40 #include "shrpx_quic.h"
41 #include "shrpx_worker.h"
42 #include "shrpx_http.h"
43 #include "shrpx_connection_handler.h"
45 # include "shrpx_mruby.h"
53 void idle_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
54 auto upstream = static_cast<Http3Upstream *>(w->data);
56 if (LOG_ENABLED(INFO)) {
57 ULOG(INFO, upstream) << "QUIC idle timeout";
60 upstream->idle_close();
62 auto handler = upstream->get_client_handler();
69 void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
70 auto upstream = static_cast<Http3Upstream *>(w->data);
72 if (upstream->handle_expiry() != 0 || upstream->on_write() != 0) {
79 auto handler = upstream->get_client_handler();
86 void shutdown_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
87 auto upstream = static_cast<Http3Upstream *>(w->data);
88 auto handler = upstream->get_client_handler();
90 if (upstream->submit_goaway() != 0) {
97 void prepare_cb(struct ev_loop *loop, ev_prepare *w, int revent) {
98 auto upstream = static_cast<Http3Upstream *>(w->data);
99 auto handler = upstream->get_client_handler();
101 if (upstream->check_shutdown() != 0) {
108 size_t downstream_queue_size(Worker *worker) {
109 auto &downstreamconf = *worker->get_downstream_config();
111 if (get_config()->http2_proxy) {
112 return downstreamconf.connections_per_host;
115 return downstreamconf.connections_per_frontend;
119 Http3Upstream::Http3Upstream(ClientHandler *handler)
121 max_udp_payload_size_{SHRPX_QUIC_MAX_UDP_PAYLOAD_SIZE},
127 downstream_queue_{downstream_queue_size(handler->get_worker()),
128 !get_config()->http2_proxy},
130 retry_close_{false} {
131 ev_timer_init(&timer_, timeoutcb, 0., 0.);
134 auto config = get_config();
135 auto &quicconf = config->quic;
137 ev_timer_init(&idle_timer_, idle_timeoutcb, 0.,
138 quicconf.upstream.timeout.idle);
139 idle_timer_.data = this;
141 ev_timer_init(&shutdown_timer_, shutdown_timeout_cb, 0., 0.);
142 shutdown_timer_.data = this;
144 ev_prepare_init(&prep_, prepare_cb);
146 ev_prepare_start(handler_->get_loop(), &prep_);
149 Http3Upstream::~Http3Upstream() {
150 auto loop = handler_->get_loop();
152 ev_prepare_stop(loop, &prep_);
153 ev_timer_stop(loop, &shutdown_timer_);
154 ev_timer_stop(loop, &idle_timer_);
155 ev_timer_stop(loop, &timer_);
157 nghttp3_conn_del(httpconn_);
159 ngtcp2_conn_del(conn_);
161 if (qlog_fd_ != -1) {
167 void log_printf(void *user_data, const char *fmt, ...) {
169 std::array<char, 4096> buf;
172 auto nwrite = vsnprintf(buf.data(), buf.size(), fmt, ap);
175 if (static_cast<size_t>(nwrite) >= buf.size()) {
176 nwrite = buf.size() - 1;
179 buf[nwrite++] = '\n';
181 while (write(fileno(stderr), buf.data(), nwrite) == -1 && errno == EINTR)
187 void qlog_write(void *user_data, uint32_t flags, const void *data,
189 auto upstream = static_cast<Http3Upstream *>(user_data);
191 upstream->qlog_write(data, datalen, flags & NGTCP2_QLOG_WRITE_FLAG_FIN);
195 void Http3Upstream::qlog_write(const void *data, size_t datalen, bool fin) {
196 assert(qlog_fd_ != -1);
200 while ((nwrite = write(qlog_fd_, data, datalen)) == -1 && errno == EINTR)
210 void rand(uint8_t *dest, size_t destlen, const ngtcp2_rand_ctx *rand_ctx) {
211 util::random_bytes(dest, dest + destlen,
212 *static_cast<std::mt19937 *>(rand_ctx->native_handle));
217 int get_new_connection_id(ngtcp2_conn *conn, ngtcp2_cid *cid, uint8_t *token,
218 size_t cidlen, void *user_data) {
219 auto upstream = static_cast<Http3Upstream *>(user_data);
220 auto handler = upstream->get_client_handler();
221 auto worker = handler->get_worker();
222 auto conn_handler = worker->get_connection_handler();
223 auto &qkms = conn_handler->get_quic_keying_materials();
224 auto &qkm = qkms->keying_materials.front();
226 if (generate_quic_connection_id(*cid, cidlen, worker->get_cid_prefix(),
227 qkm.id, qkm.cid_encryption_key.data()) != 0) {
228 return NGTCP2_ERR_CALLBACK_FAILURE;
231 if (generate_quic_stateless_reset_token(token, *cid, qkm.secret.data(),
232 qkm.secret.size()) != 0) {
233 return NGTCP2_ERR_CALLBACK_FAILURE;
236 auto quic_connection_handler = worker->get_quic_connection_handler();
238 quic_connection_handler->add_connection_id(*cid, handler);
245 int remove_connection_id(ngtcp2_conn *conn, const ngtcp2_cid *cid,
247 auto upstream = static_cast<Http3Upstream *>(user_data);
248 auto handler = upstream->get_client_handler();
249 auto worker = handler->get_worker();
250 auto quic_conn_handler = worker->get_quic_connection_handler();
252 quic_conn_handler->remove_connection_id(*cid);
258 void Http3Upstream::http_begin_request_headers(int64_t stream_id) {
260 std::make_unique<Downstream>(this, handler_->get_mcpool(), stream_id);
261 nghttp3_conn_set_stream_user_data(httpconn_, stream_id, downstream.get());
263 downstream->reset_upstream_rtimer();
265 handler_->repeat_read_timer();
267 auto &req = downstream->request();
271 add_pending_downstream(std::move(downstream));
274 void Http3Upstream::add_pending_downstream(
275 std::unique_ptr<Downstream> downstream) {
276 downstream_queue_.add_pending(std::move(downstream));
280 int recv_stream_data(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
281 uint64_t offset, const uint8_t *data, size_t datalen,
282 void *user_data, void *stream_user_data) {
283 auto upstream = static_cast<Http3Upstream *>(user_data);
285 if (upstream->recv_stream_data(flags, stream_id, data, datalen) != 0) {
286 return NGTCP2_ERR_CALLBACK_FAILURE;
293 int Http3Upstream::recv_stream_data(uint32_t flags, int64_t stream_id,
294 const uint8_t *data, size_t datalen) {
297 auto nconsumed = nghttp3_conn_read_stream(
298 httpconn_, stream_id, data, datalen, flags & NGTCP2_STREAM_DATA_FLAG_FIN);
300 ULOG(ERROR, this) << "nghttp3_conn_read_stream: "
301 << nghttp3_strerror(nconsumed);
302 last_error_ = quic::err_application(nconsumed);
306 ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, nconsumed);
307 ngtcp2_conn_extend_max_offset(conn_, nconsumed);
313 int stream_close(ngtcp2_conn *conn, uint32_t flags, int64_t stream_id,
314 uint64_t app_error_code, void *user_data,
315 void *stream_user_data) {
316 auto upstream = static_cast<Http3Upstream *>(user_data);
318 if (!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
319 app_error_code = NGHTTP3_H3_NO_ERROR;
322 if (upstream->stream_close(stream_id, app_error_code) != 0) {
323 return NGTCP2_ERR_CALLBACK_FAILURE;
330 int Http3Upstream::stream_close(int64_t stream_id, uint64_t app_error_code) {
335 auto rv = nghttp3_conn_close_stream(httpconn_, stream_id, app_error_code);
339 case NGHTTP3_ERR_STREAM_NOT_FOUND:
340 if (ngtcp2_is_bidi_stream(stream_id)) {
341 ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
345 ULOG(ERROR, this) << "nghttp3_conn_close_stream: " << nghttp3_strerror(rv);
346 last_error_ = quic::err_application(rv);
354 int acked_stream_data_offset(ngtcp2_conn *conn, int64_t stream_id,
355 uint64_t offset, uint64_t datalen, void *user_data,
356 void *stream_user_data) {
357 auto upstream = static_cast<Http3Upstream *>(user_data);
359 if (upstream->acked_stream_data_offset(stream_id, datalen) != 0) {
360 return NGTCP2_ERR_CALLBACK_FAILURE;
367 int Http3Upstream::acked_stream_data_offset(int64_t stream_id,
373 auto rv = nghttp3_conn_add_ack_offset(httpconn_, stream_id, datalen);
375 ULOG(ERROR, this) << "nghttp3_conn_add_ack_offset: "
376 << nghttp3_strerror(rv);
384 int extend_max_stream_data(ngtcp2_conn *conn, int64_t stream_id,
385 uint64_t max_data, void *user_data,
386 void *stream_user_data) {
387 auto upstream = static_cast<Http3Upstream *>(user_data);
389 if (upstream->extend_max_stream_data(stream_id) != 0) {
390 return NGTCP2_ERR_CALLBACK_FAILURE;
397 int Http3Upstream::extend_max_stream_data(int64_t stream_id) {
402 auto rv = nghttp3_conn_unblock_stream(httpconn_, stream_id);
404 ULOG(ERROR, this) << "nghttp3_conn_unblock_stream: "
405 << nghttp3_strerror(rv);
413 int extend_max_remote_streams_bidi(ngtcp2_conn *conn, uint64_t max_streams,
415 auto upstream = static_cast<Http3Upstream *>(user_data);
417 upstream->extend_max_remote_streams_bidi(max_streams);
423 void Http3Upstream::extend_max_remote_streams_bidi(uint64_t max_streams) {
424 nghttp3_conn_set_max_client_streams_bidi(httpconn_, max_streams);
428 int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
429 uint64_t app_error_code, void *user_data,
430 void *stream_user_data) {
431 auto upstream = static_cast<Http3Upstream *>(user_data);
433 if (upstream->http_shutdown_stream_read(stream_id) != 0) {
434 return NGTCP2_ERR_CALLBACK_FAILURE;
441 int Http3Upstream::http_shutdown_stream_read(int64_t stream_id) {
446 auto rv = nghttp3_conn_shutdown_stream_read(httpconn_, stream_id);
448 ULOG(ERROR, this) << "nghttp3_conn_shutdown_stream_read: "
449 << nghttp3_strerror(rv);
457 int stream_stop_sending(ngtcp2_conn *conn, int64_t stream_id,
458 uint64_t app_error_code, void *user_data,
459 void *stream_user_data) {
460 auto upstream = static_cast<Http3Upstream *>(user_data);
462 if (upstream->http_shutdown_stream_read(stream_id) != 0) {
463 return NGTCP2_ERR_CALLBACK_FAILURE;
471 int handshake_completed(ngtcp2_conn *conn, void *user_data) {
472 auto upstream = static_cast<Http3Upstream *>(user_data);
474 if (upstream->handshake_completed() != 0) {
475 return NGTCP2_ERR_CALLBACK_FAILURE;
482 int Http3Upstream::handshake_completed() {
483 handler_->set_alpn_from_conn();
485 auto alpn = handler_->get_alpn();
487 ULOG(ERROR, this) << "NO ALPN was negotiated";
491 std::array<uint8_t, NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN> token;
494 auto path = ngtcp2_conn_get_path(conn_);
495 auto worker = handler_->get_worker();
496 auto conn_handler = worker->get_connection_handler();
497 auto &qkms = conn_handler->get_quic_keying_materials();
498 auto &qkm = qkms->keying_materials.front();
500 if (generate_token(token.data(), tokenlen, path->remote.addr,
501 path->remote.addrlen, qkm.secret.data(),
502 qkm.secret.size()) != 0) {
506 auto rv = ngtcp2_conn_submit_new_token(conn_, token.data(), tokenlen);
508 ULOG(ERROR, this) << "ngtcp2_conn_submit_new_token: "
509 << ngtcp2_strerror(rv);
516 int Http3Upstream::init(const UpstreamAddr *faddr, const Address &remote_addr,
517 const Address &local_addr,
518 const ngtcp2_pkt_hd &initial_hd,
519 const ngtcp2_cid *odcid, const uint8_t *token,
523 auto worker = handler_->get_worker();
524 auto conn_handler = worker->get_connection_handler();
526 auto callbacks = ngtcp2_callbacks{
527 nullptr, // client_initial
528 ngtcp2_crypto_recv_client_initial_cb,
529 ngtcp2_crypto_recv_crypto_data_cb,
530 shrpx::handshake_completed,
531 nullptr, // recv_version_negotiation
532 ngtcp2_crypto_encrypt_cb,
533 ngtcp2_crypto_decrypt_cb,
534 ngtcp2_crypto_hp_mask_cb,
535 shrpx::recv_stream_data,
536 shrpx::acked_stream_data_offset,
537 nullptr, // stream_open
539 nullptr, // recv_stateless_reset
540 nullptr, // recv_retry
541 nullptr, // extend_max_local_streams_bidi
542 nullptr, // extend_max_local_streams_uni
544 get_new_connection_id,
545 remove_connection_id,
546 ngtcp2_crypto_update_key_cb,
547 nullptr, // path_validation
548 nullptr, // select_preferred_addr
550 shrpx::extend_max_remote_streams_bidi,
551 nullptr, // extend_max_remote_streams_uni
552 shrpx::extend_max_stream_data,
553 nullptr, // dcid_status
554 nullptr, // handshake_confirmed
555 nullptr, // recv_new_token
556 ngtcp2_crypto_delete_crypto_aead_ctx_cb,
557 ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
558 nullptr, // recv_datagram
559 nullptr, // ack_datagram
560 nullptr, // lost_datagram
561 ngtcp2_crypto_get_path_challenge_data_cb,
562 shrpx::stream_stop_sending,
565 auto config = get_config();
566 auto &quicconf = config->quic;
567 auto &http3conf = config->http3;
569 auto &qkms = conn_handler->get_quic_keying_materials();
570 auto &qkm = qkms->keying_materials.front();
574 if (generate_quic_connection_id(scid, SHRPX_QUIC_SCIDLEN,
575 worker->get_cid_prefix(), qkm.id,
576 qkm.cid_encryption_key.data()) != 0) {
580 ngtcp2_settings settings;
581 ngtcp2_settings_default(&settings);
582 if (quicconf.upstream.debug.log) {
583 settings.log_printf = log_printf;
586 if (!quicconf.upstream.qlog.dir.empty()) {
587 auto fd = open_qlog_file(quicconf.upstream.qlog.dir, scid);
590 settings.qlog.odcid = initial_hd.dcid;
591 settings.qlog.write = shrpx::qlog_write;
595 settings.initial_ts = quic_timestamp();
596 settings.initial_rtt = static_cast<ngtcp2_tstamp>(
597 quicconf.upstream.initial_rtt * NGTCP2_SECONDS);
598 settings.cc_algo = quicconf.upstream.congestion_controller;
599 settings.max_window = http3conf.upstream.max_connection_window_size;
600 settings.max_stream_window = http3conf.upstream.max_window_size;
601 settings.max_udp_payload_size = SHRPX_QUIC_MAX_UDP_PAYLOAD_SIZE;
602 settings.assume_symmetric_path = 1;
603 settings.rand_ctx.native_handle = &worker->get_randgen();
604 settings.token = ngtcp2_vec{const_cast<uint8_t *>(token), tokenlen};
606 ngtcp2_transport_params params;
607 ngtcp2_transport_params_default(¶ms);
608 params.initial_max_streams_bidi = http3conf.upstream.max_concurrent_streams;
609 // The minimum number of unidirectional streams required for HTTP/3.
610 params.initial_max_streams_uni = 3;
611 params.initial_max_data = http3conf.upstream.connection_window_size;
612 params.initial_max_stream_data_bidi_remote = http3conf.upstream.window_size;
613 params.initial_max_stream_data_uni = http3conf.upstream.window_size;
614 params.max_idle_timeout = static_cast<ngtcp2_tstamp>(
615 quicconf.upstream.timeout.idle * NGTCP2_SECONDS);
617 #ifdef OPENSSL_IS_BORINGSSL
618 if (quicconf.upstream.early_data) {
619 ngtcp2_transport_params early_data_params{
620 .initial_max_stream_data_bidi_local =
621 params.initial_max_stream_data_bidi_local,
622 .initial_max_stream_data_bidi_remote =
623 params.initial_max_stream_data_bidi_remote,
624 .initial_max_stream_data_uni = params.initial_max_stream_data_uni,
625 .initial_max_data = params.initial_max_data,
626 .initial_max_streams_bidi = params.initial_max_streams_bidi,
627 .initial_max_streams_uni = params.initial_max_streams_uni,
630 // TODO include HTTP/3 SETTINGS
632 std::array<uint8_t, 128> quic_early_data_ctx;
634 auto quic_early_data_ctxlen = ngtcp2_encode_transport_params(
635 quic_early_data_ctx.data(), quic_early_data_ctx.size(),
636 NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS, &early_data_params);
638 assert(quic_early_data_ctxlen > 0);
639 assert(static_cast<size_t>(quic_early_data_ctxlen) <=
640 quic_early_data_ctx.size());
642 if (SSL_set_quic_early_data_context(handler_->get_ssl(),
643 quic_early_data_ctx.data(),
644 quic_early_data_ctxlen) != 1) {
645 ULOG(ERROR, this) << "SSL_set_quic_early_data_context failed";
649 #endif // OPENSSL_IS_BORINGSSL
652 params.original_dcid = *odcid;
653 params.retry_scid = initial_hd.dcid;
654 params.retry_scid_present = 1;
656 params.original_dcid = initial_hd.dcid;
659 rv = generate_quic_stateless_reset_token(
660 params.stateless_reset_token, scid, qkm.secret.data(), qkm.secret.size());
662 ULOG(ERROR, this) << "generate_quic_stateless_reset_token failed";
665 params.stateless_reset_token_present = 1;
667 auto path = ngtcp2_path{
668 {local_addr.len, const_cast<sockaddr *>(&local_addr.su.sa)},
669 {remote_addr.len, const_cast<sockaddr *>(&remote_addr.su.sa)},
670 const_cast<UpstreamAddr *>(faddr),
673 rv = ngtcp2_conn_server_new(&conn_, &initial_hd.scid, &scid, &path,
674 initial_hd.version, &callbacks, &settings,
675 ¶ms, nullptr, this);
677 ULOG(ERROR, this) << "ngtcp2_conn_server_new: " << ngtcp2_strerror(rv);
681 ngtcp2_conn_set_tls_native_handle(conn_, handler_->get_ssl());
683 auto quic_connection_handler = worker->get_quic_connection_handler();
685 if (generate_quic_hashed_connection_id(hashed_scid_, remote_addr, local_addr,
686 initial_hd.dcid) != 0) {
690 quic_connection_handler->add_connection_id(hashed_scid_, handler_);
691 quic_connection_handler->add_connection_id(scid, handler_);
696 int Http3Upstream::on_read() { return 0; }
698 int Http3Upstream::on_write() {
699 if (write_streams() != 0) {
708 int Http3Upstream::write_streams() {
709 std::array<nghttp3_vec, 16> vec;
710 std::array<uint8_t, 64_k> buf;
711 auto max_udp_payload_size = std::min(
712 max_udp_payload_size_, ngtcp2_conn_get_path_max_udp_payload_size(conn_));
714 std::min(static_cast<size_t>(64_k), ngtcp2_conn_get_send_quantum(conn_)) /
715 max_udp_payload_size;
717 uint8_t *bufpos = buf.data();
718 ngtcp2_path_storage ps, prev_ps;
721 auto ts = quic_timestamp();
723 ngtcp2_path_storage_zero(&ps);
724 ngtcp2_path_storage_zero(&prev_ps);
726 auto config = get_config();
727 auto &quicconf = config->quic;
729 if (quicconf.upstream.congestion_controller != NGTCP2_CC_ALGO_BBR) {
730 max_pktcnt = std::min(max_pktcnt, static_cast<size_t>(10));
734 int64_t stream_id = -1;
736 nghttp3_ssize sveccnt = 0;
738 if (httpconn_ && ngtcp2_conn_get_max_data_left(conn_)) {
739 sveccnt = nghttp3_conn_writev_stream(httpconn_, &stream_id, &fin,
740 vec.data(), vec.size());
742 ULOG(ERROR, this) << "nghttp3_conn_writev_stream: "
743 << nghttp3_strerror(sveccnt);
744 last_error_ = quic::err_application(sveccnt);
745 return handle_error();
749 ngtcp2_ssize ndatalen;
751 auto vcnt = static_cast<size_t>(sveccnt);
753 uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE;
755 flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
758 auto nwrite = ngtcp2_conn_writev_stream(
759 conn_, &ps.path, &pi, bufpos, max_udp_payload_size, &ndatalen, flags,
760 stream_id, reinterpret_cast<const ngtcp2_vec *>(v), vcnt, ts);
763 case NGTCP2_ERR_STREAM_DATA_BLOCKED:
764 assert(ndatalen == -1);
765 rv = nghttp3_conn_block_stream(httpconn_, stream_id);
768 << "nghttp3_conn_block_stream: " << nghttp3_strerror(rv);
769 last_error_ = quic::err_application(rv);
770 return handle_error();
773 case NGTCP2_ERR_STREAM_SHUT_WR:
774 assert(ndatalen == -1);
775 rv = nghttp3_conn_shutdown_stream_write(httpconn_, stream_id);
778 << "nghttp3_conn_shutdown_stream_write: " << nghttp3_strerror(rv);
779 last_error_ = quic::err_application(rv);
780 return handle_error();
783 case NGTCP2_ERR_WRITE_MORE:
784 assert(ndatalen >= 0);
785 rv = nghttp3_conn_add_write_offset(httpconn_, stream_id, ndatalen);
788 << "nghttp3_conn_add_write_offset: " << nghttp3_strerror(rv);
789 last_error_ = quic::err_application(rv);
790 return handle_error();
795 assert(ndatalen == -1);
797 ULOG(ERROR, this) << "ngtcp2_conn_writev_stream: "
798 << ngtcp2_strerror(nwrite);
800 last_error_ = quic::err_transport(nwrite);
802 handler_->get_connection()->wlimit.stopw();
804 return handle_error();
805 } else if (ndatalen >= 0) {
806 rv = nghttp3_conn_add_write_offset(httpconn_, stream_id, ndatalen);
808 ULOG(ERROR, this) << "nghttp3_conn_add_write_offset: "
809 << nghttp3_strerror(rv);
810 last_error_ = quic::err_application(rv);
811 return handle_error();
816 if (bufpos - buf.data()) {
817 send_packet(static_cast<UpstreamAddr *>(prev_ps.path.user_data),
818 prev_ps.path.remote.addr, prev_ps.path.remote.addrlen,
819 prev_ps.path.local.addr, prev_ps.path.local.addrlen,
820 buf.data(), bufpos - buf.data(), max_udp_payload_size);
825 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
827 handler_->get_connection()->wlimit.stopw();
836 ngtcp2_path_copy(&prev_ps.path, &ps.path);
837 } else if (!ngtcp2_path_eq(&prev_ps.path, &ps.path)) {
838 send_packet(static_cast<UpstreamAddr *>(prev_ps.path.user_data),
839 prev_ps.path.remote.addr, prev_ps.path.remote.addrlen,
840 prev_ps.path.local.addr, prev_ps.path.local.addrlen,
841 buf.data(), bufpos - buf.data() - nwrite,
842 max_udp_payload_size);
844 send_packet(static_cast<UpstreamAddr *>(ps.path.user_data),
845 ps.path.remote.addr, ps.path.remote.addrlen,
846 ps.path.local.addr, ps.path.local.addrlen, bufpos - nwrite,
847 nwrite, max_udp_payload_size);
849 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
852 handler_->signal_write();
857 if (++pktcnt == max_pktcnt ||
858 static_cast<size_t>(nwrite) < max_udp_payload_size) {
859 send_packet(static_cast<UpstreamAddr *>(ps.path.user_data),
860 ps.path.remote.addr, ps.path.remote.addrlen,
861 ps.path.local.addr, ps.path.local.addrlen, buf.data(),
862 bufpos - buf.data(), max_udp_payload_size);
864 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
867 handler_->signal_write();
871 #else // !UDP_SEGMENT
872 send_packet(static_cast<UpstreamAddr *>(ps.path.user_data),
873 ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr,
874 ps.path.local.addrlen, buf.data(), bufpos - buf.data(), 0);
876 if (++pktcnt == max_pktcnt) {
877 ngtcp2_conn_update_pkt_tx_time(conn_, ts);
880 handler_->signal_write();
886 #endif // !UDP_SEGMENT
892 int Http3Upstream::on_timeout(Downstream *downstream) { return 0; }
894 int Http3Upstream::on_downstream_abort_request(Downstream *downstream,
895 unsigned int status_code) {
898 rv = error_reply(downstream, status_code);
904 handler_->signal_write();
909 int Http3Upstream::on_downstream_abort_request_with_https_redirect(
910 Downstream *downstream) {
913 rv = redirect_to_https(downstream);
918 handler_->signal_write();
924 infer_upstream_shutdown_stream_error_code(uint32_t downstream_error_code) {
925 // NGHTTP2_REFUSED_STREAM is important because it tells upstream
927 switch (downstream_error_code) {
928 case NGHTTP2_NO_ERROR:
929 return NGHTTP3_H3_NO_ERROR;
930 case NGHTTP2_REFUSED_STREAM:
931 return NGHTTP3_H3_REQUEST_REJECTED;
933 return NGHTTP3_H3_INTERNAL_ERROR;
938 int Http3Upstream::downstream_read(DownstreamConnection *dconn) {
939 auto downstream = dconn->get_downstream();
941 if (downstream->get_response_state() == DownstreamState::MSG_RESET) {
942 // The downstream stream was reset (canceled). In this case,
943 // RST_STREAM to the upstream and delete downstream connection
944 // here. Deleting downstream will be taken place at
945 // on_stream_close_callback.
946 shutdown_stream(downstream,
947 infer_upstream_shutdown_stream_error_code(
948 downstream->get_response_rst_stream_error_code()));
949 downstream->pop_downstream_connection();
952 } else if (downstream->get_response_state() ==
953 DownstreamState::MSG_BAD_HEADER) {
954 if (error_reply(downstream, 502) != 0) {
957 downstream->pop_downstream_connection();
961 auto rv = downstream->on_read();
962 if (rv == SHRPX_ERR_EOF) {
963 if (downstream->get_request_header_sent()) {
964 return downstream_eof(dconn);
966 return SHRPX_ERR_RETRY;
968 if (rv == SHRPX_ERR_DCONN_CANCELED) {
969 downstream->pop_downstream_connection();
970 handler_->signal_write();
974 if (rv != SHRPX_ERR_NETWORK) {
975 if (LOG_ENABLED(INFO)) {
976 DCLOG(INFO, dconn) << "HTTP parser failure";
979 return downstream_error(dconn, Downstream::EVENT_ERROR);
982 if (downstream->can_detach_downstream_connection()) {
984 downstream->detach_downstream_connection();
988 handler_->signal_write();
990 // At this point, downstream may be deleted.
995 int Http3Upstream::downstream_write(DownstreamConnection *dconn) {
997 rv = dconn->on_write();
998 if (rv == SHRPX_ERR_NETWORK) {
999 return downstream_error(dconn, Downstream::EVENT_ERROR);
1007 int Http3Upstream::downstream_eof(DownstreamConnection *dconn) {
1008 auto downstream = dconn->get_downstream();
1010 if (LOG_ENABLED(INFO)) {
1011 DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id();
1014 // Delete downstream connection. If we don't delete it here, it will
1015 // be pooled in on_stream_close_callback.
1016 downstream->pop_downstream_connection();
1017 // dconn was deleted
1019 // downstream wil be deleted in on_stream_close_callback.
1020 if (downstream->get_response_state() == DownstreamState::HEADER_COMPLETE) {
1021 // Server may indicate the end of the request by EOF
1022 if (LOG_ENABLED(INFO)) {
1023 ULOG(INFO, this) << "Downstream body was ended by EOF";
1025 downstream->set_response_state(DownstreamState::MSG_COMPLETE);
1027 // For tunneled connection, MSG_COMPLETE signals
1028 // downstream_read_data_callback to send RST_STREAM after pending
1029 // response body is sent. This is needed to ensure that RST_STREAM
1030 // is sent after all pending data are sent.
1031 on_downstream_body_complete(downstream);
1032 } else if (downstream->get_response_state() !=
1033 DownstreamState::MSG_COMPLETE) {
1034 // If stream was not closed, then we set MSG_COMPLETE and let
1035 // on_stream_close_callback delete downstream.
1036 if (error_reply(downstream, 502) != 0) {
1040 handler_->signal_write();
1041 // At this point, downstream may be deleted.
1045 int Http3Upstream::downstream_error(DownstreamConnection *dconn, int events) {
1046 auto downstream = dconn->get_downstream();
1048 if (LOG_ENABLED(INFO)) {
1049 if (events & Downstream::EVENT_ERROR) {
1050 DCLOG(INFO, dconn) << "Downstream network/general error";
1052 DCLOG(INFO, dconn) << "Timeout";
1054 if (downstream->get_upgraded()) {
1055 DCLOG(INFO, dconn) << "Note: this is tunnel connection";
1059 // Delete downstream connection. If we don't delete it here, it will
1060 // be pooled in on_stream_close_callback.
1061 downstream->pop_downstream_connection();
1062 // dconn was deleted
1065 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1066 // For SSL tunneling, we issue RST_STREAM. For other types of
1067 // stream, we don't have to do anything since response was
1069 if (downstream->get_upgraded()) {
1070 shutdown_stream(downstream, NGHTTP3_H3_NO_ERROR);
1073 if (downstream->get_response_state() == DownstreamState::HEADER_COMPLETE) {
1074 if (downstream->get_upgraded()) {
1075 on_downstream_body_complete(downstream);
1077 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
1080 unsigned int status;
1081 if (events & Downstream::EVENT_TIMEOUT) {
1082 if (downstream->get_request_header_sent()) {
1090 if (error_reply(downstream, status) != 0) {
1094 downstream->set_response_state(DownstreamState::MSG_COMPLETE);
1096 handler_->signal_write();
1097 // At this point, downstream may be deleted.
1101 ClientHandler *Http3Upstream::get_client_handler() const { return handler_; }
1104 nghttp3_ssize downstream_read_data_callback(nghttp3_conn *conn,
1105 int64_t stream_id, nghttp3_vec *vec,
1106 size_t veccnt, uint32_t *pflags,
1107 void *conn_user_data,
1108 void *stream_user_data) {
1109 auto upstream = static_cast<Http3Upstream *>(conn_user_data);
1110 auto downstream = static_cast<Downstream *>(stream_user_data);
1114 auto body = downstream->get_response_buf();
1118 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1119 *pflags |= NGHTTP3_DATA_FLAG_EOF;
1120 } else if (body->rleft_mark() == 0) {
1121 downstream->disable_upstream_wtimer();
1122 return NGHTTP3_ERR_WOULDBLOCK;
1125 downstream->reset_upstream_wtimer();
1127 veccnt = body->riovec_mark(reinterpret_cast<struct iovec *>(vec), veccnt);
1129 assert((*pflags & NGHTTP3_DATA_FLAG_EOF) || veccnt);
1131 downstream->response_sent_body_length += nghttp3_vec_len(vec, veccnt);
1133 if ((*pflags & NGHTTP3_DATA_FLAG_EOF) &&
1134 upstream->shutdown_stream_read(stream_id, NGHTTP3_H3_NO_ERROR) != 0) {
1135 return NGHTTP3_ERR_CALLBACK_FAILURE;
1142 int Http3Upstream::on_downstream_header_complete(Downstream *downstream) {
1145 const auto &req = downstream->request();
1146 auto &resp = downstream->response();
1148 auto &balloc = downstream->get_block_allocator();
1150 if (LOG_ENABLED(INFO)) {
1151 if (downstream->get_non_final_response()) {
1152 DLOG(INFO, downstream) << "HTTP non-final response header";
1154 DLOG(INFO, downstream) << "HTTP response header completed";
1158 auto config = get_config();
1159 auto &httpconf = config->http;
1161 if (!config->http2_proxy && !httpconf.no_location_rewrite) {
1162 downstream->rewrite_location_response_header(req.scheme);
1166 if (!downstream->get_non_final_response()) {
1167 auto dconn = downstream->get_downstream_connection();
1168 const auto &group = dconn->get_downstream_addr_group();
1170 const auto &dmruby_ctx = group->shared_addr->mruby_ctx;
1172 if (dmruby_ctx->run_on_response_proc(downstream) != 0) {
1173 if (error_reply(downstream, 500) != 0) {
1176 // Returning -1 will signal deletion of dconn.
1180 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1185 auto worker = handler_->get_worker();
1186 auto mruby_ctx = worker->get_mruby_context();
1188 if (mruby_ctx->run_on_response_proc(downstream) != 0) {
1189 if (error_reply(downstream, 500) != 0) {
1192 // Returning -1 will signal deletion of dconn.
1196 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1200 #endif // HAVE_MRUBY
1202 auto nva = std::vector<nghttp3_nv>();
1203 // 4 means :status and possible server, via, and set-cookie (for
1204 // affinity cookie) header field.
1205 nva.reserve(resp.fs.headers().size() + 4 +
1206 httpconf.add_response_headers.size());
1208 if (downstream->get_non_final_response()) {
1209 auto response_status = http2::stringify_status(balloc, resp.http_status);
1211 nva.push_back(http3::make_nv_ls_nocopy(":status", response_status));
1213 http3::copy_headers_to_nva_nocopy(nva, resp.fs.headers(),
1214 http2::HDOP_STRIP_ALL);
1216 if (LOG_ENABLED(INFO)) {
1217 log_response_headers(downstream, nva);
1220 rv = nghttp3_conn_submit_info(httpconn_, downstream->get_stream_id(),
1221 nva.data(), nva.size());
1223 resp.fs.clear_headers();
1226 ULOG(FATAL, this) << "nghttp3_conn_submit_info() failed";
1233 auto striphd_flags = http2::HDOP_STRIP_ALL & ~http2::HDOP_STRIP_VIA;
1234 StringRef response_status;
1236 if (req.connect_proto == ConnectProto::WEBSOCKET && resp.http_status == 101) {
1237 response_status = http2::stringify_status(balloc, 200);
1238 striphd_flags |= http2::HDOP_STRIP_SEC_WEBSOCKET_ACCEPT;
1240 response_status = http2::stringify_status(balloc, resp.http_status);
1243 nva.push_back(http3::make_nv_ls_nocopy(":status", response_status));
1245 http3::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), striphd_flags);
1247 if (!config->http2_proxy && !httpconf.no_server_rewrite) {
1248 nva.push_back(http3::make_nv_ls_nocopy("server", httpconf.server_name));
1250 auto server = resp.fs.header(http2::HD_SERVER);
1252 nva.push_back(http3::make_nv_ls_nocopy("server", (*server).value));
1256 if (!req.regular_connect_method() || !downstream->get_upgraded()) {
1257 auto affinity_cookie = downstream->get_affinity_cookie_to_send();
1258 if (affinity_cookie) {
1259 auto dconn = downstream->get_downstream_connection();
1261 auto &group = dconn->get_downstream_addr_group();
1262 auto &shared_addr = group->shared_addr;
1263 auto &cookieconf = shared_addr->affinity.cookie;
1265 http::require_cookie_secure_attribute(cookieconf.secure, req.scheme);
1266 auto cookie_str = http::create_affinity_cookie(
1267 balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure);
1268 nva.push_back(http3::make_nv_ls_nocopy("set-cookie", cookie_str));
1272 auto via = resp.fs.header(http2::HD_VIA);
1273 if (httpconf.no_via) {
1275 nva.push_back(http3::make_nv_ls_nocopy("via", (*via).value));
1278 // we don't create more than 16 bytes in
1279 // http::create_via_header_value.
1282 len += via->value.size() + 2;
1285 auto iov = make_byte_ref(balloc, len + 1);
1288 p = std::copy(std::begin(via->value), std::end(via->value), p);
1289 p = util::copy_lit(p, ", ");
1291 p = http::create_via_header_value(p, resp.http_major, resp.http_minor);
1294 nva.push_back(http3::make_nv_ls_nocopy("via", StringRef{iov.base, p}));
1297 for (auto &p : httpconf.add_response_headers) {
1298 nva.push_back(http3::make_nv_nocopy(p.name, p.value));
1301 if (LOG_ENABLED(INFO)) {
1302 log_response_headers(downstream, nva);
1305 nghttp3_data_reader data_read;
1306 data_read.read_data = downstream_read_data_callback;
1308 nghttp3_data_reader *data_readptr;
1310 if (downstream->expect_response_body() ||
1311 downstream->expect_response_trailer()) {
1312 data_readptr = &data_read;
1314 data_readptr = nullptr;
1317 rv = nghttp3_conn_submit_response(httpconn_, downstream->get_stream_id(),
1318 nva.data(), nva.size(), data_readptr);
1320 ULOG(FATAL, this) << "nghttp3_conn_submit_response() failed";
1325 downstream->reset_upstream_wtimer();
1326 } else if (shutdown_stream_read(downstream->get_stream_id(),
1327 NGHTTP3_H3_NO_ERROR) != 0) {
1334 int Http3Upstream::on_downstream_body(Downstream *downstream,
1335 const uint8_t *data, size_t len,
1337 auto body = downstream->get_response_buf();
1338 body->append(data, len);
1341 nghttp3_conn_resume_stream(httpconn_, downstream->get_stream_id());
1343 downstream->ensure_upstream_wtimer();
1349 int Http3Upstream::on_downstream_body_complete(Downstream *downstream) {
1350 if (LOG_ENABLED(INFO)) {
1351 DLOG(INFO, downstream) << "HTTP response completed";
1354 auto &resp = downstream->response();
1356 if (!downstream->validate_response_recv_body_length()) {
1357 shutdown_stream(downstream, NGHTTP3_H3_GENERAL_PROTOCOL_ERROR);
1358 resp.connection_close = true;
1362 nghttp3_conn_resume_stream(httpconn_, downstream->get_stream_id());
1363 downstream->ensure_upstream_wtimer();
1368 void Http3Upstream::on_handler_delete() {
1369 for (auto d = downstream_queue_.get_downstreams(); d; d = d->dlnext) {
1370 if (d->get_dispatch_state() == DispatchState::ACTIVE &&
1371 d->accesslog_ready()) {
1372 handler_->write_accesslog(d);
1376 auto worker = handler_->get_worker();
1377 auto quic_conn_handler = worker->get_quic_connection_handler();
1379 std::vector<ngtcp2_cid> scids(ngtcp2_conn_get_num_scid(conn_) + 1);
1380 ngtcp2_conn_get_scid(conn_, scids.data());
1381 scids.back() = hashed_scid_;
1383 for (auto &cid : scids) {
1384 quic_conn_handler->remove_connection_id(cid);
1387 if (idle_close_ || retry_close_) {
1391 // If this is not idle close, send CONNECTION_CLOSE.
1392 if (!ngtcp2_conn_is_in_closing_period(conn_) &&
1393 !ngtcp2_conn_is_in_draining_period(conn_)) {
1394 ngtcp2_path_storage ps;
1396 conn_close_.resize(SHRPX_QUIC_CONN_CLOSE_PKTLEN);
1398 ngtcp2_path_storage_zero(&ps);
1400 auto nwrite = ngtcp2_conn_write_connection_close(
1401 conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(),
1402 NGTCP2_NO_ERROR, quic_timestamp());
1404 if (nwrite != NGTCP2_ERR_INVALID_STATE) {
1405 ULOG(ERROR, this) << "ngtcp2_conn_write_connection_close: "
1406 << ngtcp2_strerror(nwrite);
1412 conn_close_.resize(nwrite);
1414 send_packet(static_cast<UpstreamAddr *>(ps.path.user_data),
1415 ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr,
1416 ps.path.local.addrlen, conn_close_.data(), nwrite, 0);
1420 static_cast<ev_tstamp>(ngtcp2_conn_get_pto(conn_) * 3) / NGTCP2_SECONDS;
1422 if (LOG_ENABLED(INFO)) {
1423 ULOG(INFO, this) << "Enter close-wait period " << d << "s with "
1424 << conn_close_.size() << " bytes sentinel packet";
1427 auto cw = std::make_unique<CloseWait>(worker, std::move(scids),
1428 std::move(conn_close_), d);
1430 quic_conn_handler->add_close_wait(cw.get());
1435 int Http3Upstream::on_downstream_reset(Downstream *downstream, bool no_retry) {
1438 if (downstream->get_dispatch_state() != DispatchState::ACTIVE) {
1439 // This is error condition when we failed push_request_headers()
1440 // in initiate_downstream(). Otherwise, we have
1441 // DispatchState::ACTIVE state, or we did not set
1442 // DownstreamConnection.
1443 downstream->pop_downstream_connection();
1444 handler_->signal_write();
1449 if (!downstream->request_submission_ready()) {
1450 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1451 // We have got all response body already. Send it off.
1452 downstream->pop_downstream_connection();
1455 // pushed stream is handled here
1456 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
1457 downstream->pop_downstream_connection();
1459 handler_->signal_write();
1464 downstream->pop_downstream_connection();
1466 downstream->add_retry();
1468 std::unique_ptr<DownstreamConnection> dconn;
1472 if (no_retry || downstream->no_more_retry()) {
1476 // downstream connection is clean; we can retry with new
1477 // downstream connection.
1480 auto dconn = handler_->get_downstream_connection(rv, downstream);
1485 rv = downstream->attach_downstream_connection(std::move(dconn));
1491 rv = downstream->push_request_headers();
1499 if (rv == SHRPX_ERR_TLS_REQUIRED) {
1500 rv = on_downstream_abort_request_with_https_redirect(downstream);
1502 rv = on_downstream_abort_request(downstream, 502);
1505 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
1507 downstream->pop_downstream_connection();
1509 handler_->signal_write();
1514 void Http3Upstream::pause_read(IOCtrlReason reason) {}
1516 int Http3Upstream::resume_read(IOCtrlReason reason, Downstream *downstream,
1518 consume(downstream->get_stream_id(), consumed);
1520 auto &req = downstream->request();
1522 req.consume(consumed);
1524 handler_->signal_write();
1529 int Http3Upstream::send_reply(Downstream *downstream, const uint8_t *body,
1533 nghttp3_data_reader data_read, *data_read_ptr = nullptr;
1536 data_read.read_data = downstream_read_data_callback;
1537 data_read_ptr = &data_read;
1540 const auto &resp = downstream->response();
1541 auto config = get_config();
1542 auto &httpconf = config->http;
1544 auto &balloc = downstream->get_block_allocator();
1546 const auto &headers = resp.fs.headers();
1547 auto nva = std::vector<nghttp3_nv>();
1548 // 2 for :status and server
1549 nva.reserve(2 + headers.size() + httpconf.add_response_headers.size());
1551 auto response_status = http2::stringify_status(balloc, resp.http_status);
1553 nva.push_back(http3::make_nv_ls_nocopy(":status", response_status));
1555 for (auto &kv : headers) {
1556 if (kv.name.empty() || kv.name[0] == ':') {
1560 case http2::HD_CONNECTION:
1561 case http2::HD_KEEP_ALIVE:
1562 case http2::HD_PROXY_CONNECTION:
1564 case http2::HD_TRANSFER_ENCODING:
1565 case http2::HD_UPGRADE:
1568 nva.push_back(http3::make_nv_nocopy(kv.name, kv.value, kv.no_index));
1571 if (!resp.fs.header(http2::HD_SERVER)) {
1572 nva.push_back(http3::make_nv_ls_nocopy("server", config->http.server_name));
1575 for (auto &p : httpconf.add_response_headers) {
1576 nva.push_back(http3::make_nv_nocopy(p.name, p.value));
1579 rv = nghttp3_conn_submit_response(httpconn_, downstream->get_stream_id(),
1580 nva.data(), nva.size(), data_read_ptr);
1581 if (nghttp3_err_is_fatal(rv)) {
1582 ULOG(FATAL, this) << "nghttp3_conn_submit_response() failed: "
1583 << nghttp3_strerror(rv);
1587 auto buf = downstream->get_response_buf();
1589 buf->append(body, bodylen);
1591 downstream->set_response_state(DownstreamState::MSG_COMPLETE);
1593 if (data_read_ptr) {
1594 downstream->reset_upstream_wtimer();
1597 if (shutdown_stream_read(downstream->get_stream_id(), NGHTTP3_H3_NO_ERROR) !=
1605 int Http3Upstream::initiate_push(Downstream *downstream, const StringRef &uri) {
1609 int Http3Upstream::response_riovec(struct iovec *iov, int iovcnt) const {
1613 void Http3Upstream::response_drain(size_t n) {}
1615 bool Http3Upstream::response_empty() const { return false; }
1618 Http3Upstream::on_downstream_push_promise(Downstream *downstream,
1619 int32_t promised_stream_id) {
1623 int Http3Upstream::on_downstream_push_promise_complete(
1624 Downstream *downstream, Downstream *promised_downstream) {
1628 bool Http3Upstream::push_enabled() const { return false; }
1630 void Http3Upstream::cancel_premature_downstream(
1631 Downstream *promised_downstream) {}
1633 int Http3Upstream::on_read(const UpstreamAddr *faddr,
1634 const Address &remote_addr,
1635 const Address &local_addr, const uint8_t *data,
1638 ngtcp2_pkt_info pi{};
1640 auto path = ngtcp2_path{
1643 const_cast<sockaddr *>(&local_addr.su.sa),
1647 const_cast<sockaddr *>(&remote_addr.su.sa),
1649 const_cast<UpstreamAddr *>(faddr),
1652 rv = ngtcp2_conn_read_pkt(conn_, &path, &pi, data, datalen, quic_timestamp());
1655 case NGTCP2_ERR_DRAINING:
1657 case NGTCP2_ERR_RETRY: {
1658 auto worker = handler_->get_worker();
1659 auto quic_conn_handler = worker->get_quic_connection_handler();
1662 const uint8_t *dcid, *scid;
1663 size_t dcidlen, scidlen;
1665 rv = ngtcp2_pkt_decode_version_cid(&version, &dcid, &dcidlen, &scid,
1666 &scidlen, data, datalen,
1667 SHRPX_QUIC_SCIDLEN);
1672 if (worker->get_graceful_shutdown()) {
1673 ngtcp2_cid ini_dcid, ini_scid;
1675 ngtcp2_cid_init(&ini_dcid, dcid, dcidlen);
1676 ngtcp2_cid_init(&ini_scid, scid, scidlen);
1678 quic_conn_handler->send_connection_close(
1679 faddr, version, ini_dcid, ini_scid, remote_addr, local_addr,
1680 NGTCP2_CONNECTION_REFUSED);
1685 retry_close_ = true;
1687 quic_conn_handler->send_retry(handler_->get_upstream_addr(), version,
1688 dcid, dcidlen, scid, scidlen, remote_addr,
1693 case NGTCP2_ERR_REQUIRED_TRANSPORT_PARAM:
1694 case NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM:
1695 case NGTCP2_ERR_TRANSPORT_PARAM:
1696 // If rv indicates transport_parameters related error, we should
1697 // send TRANSPORT_PARAMETER_ERROR even if last_error_.code is
1698 // already set. This is because OpenSSL might set Alert.
1699 last_error_ = quic::err_transport(rv);
1701 case NGTCP2_ERR_DROP_CONN:
1704 if (!last_error_.code) {
1705 last_error_ = quic::err_transport(rv);
1709 ULOG(ERROR, this) << "ngtcp2_conn_read_pkt: " << ngtcp2_strerror(rv);
1711 return handle_error();
1719 int Http3Upstream::send_packet(const UpstreamAddr *faddr,
1720 const sockaddr *remote_sa, size_t remote_salen,
1721 const sockaddr *local_sa, size_t local_salen,
1722 const uint8_t *data, size_t datalen,
1724 auto rv = quic_send_packet(faddr, remote_sa, remote_salen, local_sa,
1725 local_salen, data, datalen, gso_size);
1729 // With GSO, sendmsg may fail with EINVAL if UDP payload is too
1733 max_udp_payload_size_ = NGTCP2_MAX_UDP_PAYLOAD_SIZE;
1742 int Http3Upstream::handle_error() {
1743 if (ngtcp2_conn_is_in_closing_period(conn_)) {
1747 ngtcp2_path_storage ps;
1750 ngtcp2_path_storage_zero(&ps);
1752 auto ts = quic_timestamp();
1754 conn_close_.resize(SHRPX_QUIC_CONN_CLOSE_PKTLEN);
1756 ngtcp2_ssize nwrite;
1758 if (last_error_.type == quic::ErrorType::Transport) {
1759 nwrite = ngtcp2_conn_write_connection_close(
1760 conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(),
1761 last_error_.code, ts);
1763 ULOG(ERROR, this) << "ngtcp2_conn_write_connection_close: "
1764 << ngtcp2_strerror(nwrite);
1768 nwrite = ngtcp2_conn_write_application_close(
1769 conn_, &ps.path, &pi, conn_close_.data(), conn_close_.size(),
1770 last_error_.code, ts);
1772 ULOG(ERROR, this) << "ngtcp2_conn_write_application_close: "
1773 << ngtcp2_strerror(nwrite);
1778 conn_close_.resize(nwrite);
1780 send_packet(static_cast<UpstreamAddr *>(ps.path.user_data),
1781 ps.path.remote.addr, ps.path.remote.addrlen, ps.path.local.addr,
1782 ps.path.local.addrlen, conn_close_.data(), nwrite, 0);
1787 int Http3Upstream::on_rx_secret(ngtcp2_crypto_level level,
1788 const uint8_t *secret, size_t secretlen) {
1789 if (ngtcp2_crypto_derive_and_install_rx_key(conn_, nullptr, nullptr, nullptr,
1790 level, secret, secretlen) != 0) {
1791 ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_rx_key failed";
1798 int Http3Upstream::on_tx_secret(ngtcp2_crypto_level level,
1799 const uint8_t *secret, size_t secretlen) {
1800 if (ngtcp2_crypto_derive_and_install_tx_key(conn_, nullptr, nullptr, nullptr,
1801 level, secret, secretlen) != 0) {
1802 ULOG(ERROR, this) << "ngtcp2_crypto_derive_and_install_tx_key failed";
1806 if (level == NGTCP2_CRYPTO_LEVEL_APPLICATION && setup_httpconn() != 0) {
1813 int Http3Upstream::add_crypto_data(ngtcp2_crypto_level level,
1814 const uint8_t *data, size_t datalen) {
1815 int rv = ngtcp2_conn_submit_crypto_data(conn_, level, data, datalen);
1818 ULOG(ERROR, this) << "ngtcp2_conn_submit_crypto_data: "
1819 << ngtcp2_strerror(rv);
1826 void Http3Upstream::set_tls_alert(uint8_t alert) { tls_alert_ = alert; }
1828 int Http3Upstream::handle_expiry() {
1831 auto ts = quic_timestamp();
1833 rv = ngtcp2_conn_handle_expiry(conn_, ts);
1835 ULOG(ERROR, this) << "ngtcp2_conn_handle_expiry: " << ngtcp2_strerror(rv);
1836 last_error_ = quic::err_transport(rv);
1837 return handle_error();
1843 void Http3Upstream::reset_idle_timer() {
1844 auto ts = quic_timestamp();
1845 auto idle_ts = ngtcp2_conn_get_idle_expiry(conn_);
1847 idle_timer_.repeat =
1848 idle_ts > ts ? static_cast<ev_tstamp>(idle_ts - ts) / NGTCP2_SECONDS
1851 ev_timer_again(handler_->get_loop(), &idle_timer_);
1854 void Http3Upstream::reset_timer() {
1855 auto ts = quic_timestamp();
1856 auto expiry_ts = ngtcp2_conn_get_expiry(conn_);
1858 timer_.repeat = expiry_ts > ts
1859 ? static_cast<ev_tstamp>(expiry_ts - ts) / NGTCP2_SECONDS
1862 ev_timer_again(handler_->get_loop(), &timer_);
1866 int http_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
1867 size_t nconsumed, void *user_data,
1868 void *stream_user_data) {
1869 auto upstream = static_cast<Http3Upstream *>(user_data);
1871 upstream->consume(stream_id, nconsumed);
1878 int http_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
1879 uint64_t datalen, void *user_data,
1880 void *stream_user_data) {
1881 auto upstream = static_cast<Http3Upstream *>(user_data);
1882 auto downstream = static_cast<Downstream *>(stream_user_data);
1886 if (upstream->http_acked_stream_data(downstream, datalen) != 0) {
1887 return NGHTTP3_ERR_CALLBACK_FAILURE;
1894 int Http3Upstream::http_acked_stream_data(Downstream *downstream,
1896 if (LOG_ENABLED(INFO)) {
1897 ULOG(INFO, this) << "Stream " << downstream->get_stream_id() << " "
1898 << datalen << " bytes acknowledged";
1901 auto body = downstream->get_response_buf();
1902 auto drained = body->drain_mark(datalen);
1905 assert(datalen == drained);
1907 if (downstream->resume_read(SHRPX_NO_BUFFER, datalen) != 0) {
1915 int http_begin_request_headers(nghttp3_conn *conn, int64_t stream_id,
1916 void *user_data, void *stream_user_data) {
1917 if (!ngtcp2_is_bidi_stream(stream_id)) {
1921 auto upstream = static_cast<Http3Upstream *>(user_data);
1922 upstream->http_begin_request_headers(stream_id);
1929 int http_recv_request_header(nghttp3_conn *conn, int64_t stream_id,
1930 int32_t token, nghttp3_rcbuf *name,
1931 nghttp3_rcbuf *value, uint8_t flags,
1932 void *user_data, void *stream_user_data) {
1933 auto upstream = static_cast<Http3Upstream *>(user_data);
1934 auto downstream = static_cast<Downstream *>(stream_user_data);
1936 if (!downstream || downstream->get_stop_reading()) {
1940 if (upstream->http_recv_request_header(downstream, token, name, value,
1942 return NGHTTP3_ERR_CALLBACK_FAILURE;
1949 int Http3Upstream::http_recv_request_header(Downstream *downstream,
1951 nghttp3_rcbuf *name,
1952 nghttp3_rcbuf *value,
1954 auto namebuf = nghttp3_rcbuf_get_buf(name);
1955 auto valuebuf = nghttp3_rcbuf_get_buf(value);
1956 auto &req = downstream->request();
1957 auto config = get_config();
1958 auto &httpconf = config->http;
1960 if (req.fs.buffer_size() + namebuf.len + valuebuf.len >
1961 httpconf.request_header_field_buffer ||
1962 req.fs.num_fields() >= httpconf.max_request_header_fields) {
1963 downstream->set_stop_reading(true);
1965 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
1969 if (LOG_ENABLED(INFO)) {
1970 ULOG(INFO, this) << "Too large or many header field size="
1971 << req.fs.buffer_size() + namebuf.len + valuebuf.len
1972 << ", num=" << req.fs.num_fields() + 1;
1975 if (error_reply(downstream, 431) != 0) {
1976 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
1982 auto token = http2::lookup_token(namebuf.base, namebuf.len);
1983 auto no_index = flags & NGHTTP3_NV_FLAG_NEVER_INDEX;
1985 downstream->add_rcbuf(name);
1986 downstream->add_rcbuf(value);
1988 req.fs.add_header_token(StringRef{namebuf.base, namebuf.len},
1989 StringRef{valuebuf.base, valuebuf.len}, no_index,
1995 int http_end_request_headers(nghttp3_conn *conn, int64_t stream_id,
1996 void *user_data, void *stream_user_data) {
1997 auto upstream = static_cast<Http3Upstream *>(user_data);
1998 auto handler = upstream->get_client_handler();
1999 auto downstream = static_cast<Downstream *>(stream_user_data);
2001 if (!downstream || downstream->get_stop_reading()) {
2005 if (upstream->http_end_request_headers(downstream) != 0) {
2006 return NGHTTP3_ERR_CALLBACK_FAILURE;
2009 downstream->reset_upstream_rtimer();
2010 handler->stop_read_timer();
2016 int Http3Upstream::http_end_request_headers(Downstream *downstream) {
2017 auto lgconf = log_config();
2018 lgconf->update_tstamp(std::chrono::system_clock::now());
2019 auto &req = downstream->request();
2020 req.tstamp = lgconf->tstamp;
2022 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
2026 auto &nva = req.fs.headers();
2028 if (LOG_ENABLED(INFO)) {
2029 std::stringstream ss;
2030 for (auto &nv : nva) {
2031 if (nv.name == "authorization") {
2032 ss << TTY_HTTP_HD << nv.name << TTY_RST << ": <redacted>\n";
2035 ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n";
2037 ULOG(INFO, this) << "HTTP request headers. stream_id="
2038 << downstream->get_stream_id() << "\n"
2042 auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
2043 if (content_length) {
2044 // libnghttp2 guarantees this can be parsed
2045 req.fs.content_length = util::parse_uint(content_length->value);
2048 // presence of mandatory header fields are guaranteed by libnghttp2.
2049 auto authority = req.fs.header(http2::HD__AUTHORITY);
2050 auto path = req.fs.header(http2::HD__PATH);
2051 auto method = req.fs.header(http2::HD__METHOD);
2052 auto scheme = req.fs.header(http2::HD__SCHEME);
2054 auto method_token = http2::lookup_method_token(method->value);
2055 if (method_token == -1) {
2056 if (error_reply(downstream, 501) != 0) {
2057 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
2062 auto faddr = handler_->get_upstream_addr();
2064 auto config = get_config();
2066 // For HTTP/2 proxy, we require :authority.
2067 if (method_token != HTTP_CONNECT && config->http2_proxy &&
2068 faddr->alt_mode == UpstreamAltMode::NONE && !authority) {
2069 shutdown_stream(downstream, NGHTTP2_PROTOCOL_ERROR);
2073 req.method = method_token;
2075 req.scheme = scheme->value;
2078 // nghttp2 library guarantees either :authority or host exist
2080 req.no_authority = true;
2081 authority = req.fs.header(http2::HD_HOST);
2085 req.authority = authority->value;
2089 if (method_token == HTTP_OPTIONS &&
2090 path->value == StringRef::from_lit("*")) {
2091 // Server-wide OPTIONS request. Path is empty.
2092 } else if (config->http2_proxy &&
2093 faddr->alt_mode == UpstreamAltMode::NONE) {
2094 req.path = path->value;
2096 req.path = http2::rewrite_clean_path(downstream->get_block_allocator(),
2101 auto connect_proto = req.fs.header(http2::HD__PROTOCOL);
2102 if (connect_proto) {
2103 if (connect_proto->value != "websocket") {
2104 if (error_reply(downstream, 400) != 0) {
2105 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
2109 req.connect_proto = ConnectProto::WEBSOCKET;
2112 // We are not sure that request has body or not at the moment.
2113 req.http2_expect_body = true;
2115 downstream->inspect_http2_request();
2117 downstream->set_request_state(DownstreamState::HEADER_COMPLETE);
2120 auto upstream = downstream->get_upstream();
2121 auto handler = upstream->get_client_handler();
2122 auto worker = handler->get_worker();
2123 auto mruby_ctx = worker->get_mruby_context();
2125 if (mruby_ctx->run_on_request_proc(downstream) != 0) {
2126 if (error_reply(downstream, 500) != 0) {
2127 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
2131 #endif // HAVE_MRUBY
2133 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
2137 start_downstream(downstream);
2142 void Http3Upstream::start_downstream(Downstream *downstream) {
2143 if (downstream_queue_.can_activate(downstream->request().authority)) {
2144 initiate_downstream(downstream);
2148 downstream_queue_.mark_blocked(downstream);
2151 void Http3Upstream::initiate_downstream(Downstream *downstream) {
2154 DownstreamConnection *dconn_ptr;
2157 auto dconn = handler_->get_downstream_connection(rv, downstream);
2159 if (rv == SHRPX_ERR_TLS_REQUIRED) {
2160 rv = redirect_to_https(downstream);
2162 rv = error_reply(downstream, 502);
2165 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
2168 downstream->set_request_state(DownstreamState::CONNECT_FAIL);
2169 downstream_queue_.mark_failure(downstream);
2175 dconn_ptr = dconn.get();
2176 #endif // HAVE_MRUBY
2177 rv = downstream->attach_downstream_connection(std::move(dconn));
2184 const auto &group = dconn_ptr->get_downstream_addr_group();
2186 const auto &mruby_ctx = group->shared_addr->mruby_ctx;
2187 if (mruby_ctx->run_on_request_proc(downstream) != 0) {
2188 if (error_reply(downstream, 500) != 0) {
2189 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
2192 downstream_queue_.mark_failure(downstream);
2197 if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) {
2201 #endif // HAVE_MRUBY
2203 rv = downstream->push_request_headers();
2206 if (error_reply(downstream, 502) != 0) {
2207 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
2210 downstream_queue_.mark_failure(downstream);
2215 downstream_queue_.mark_active(downstream);
2217 auto &req = downstream->request();
2218 if (!req.http2_expect_body) {
2219 rv = downstream->end_upload_data();
2221 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
2227 int http_recv_data(nghttp3_conn *conn, int64_t stream_id, const uint8_t *data,
2228 size_t datalen, void *user_data, void *stream_user_data) {
2229 auto upstream = static_cast<Http3Upstream *>(user_data);
2230 auto downstream = static_cast<Downstream *>(stream_user_data);
2232 if (upstream->http_recv_data(downstream, data, datalen) != 0) {
2233 return NGHTTP3_ERR_CALLBACK_FAILURE;
2240 int Http3Upstream::http_recv_data(Downstream *downstream, const uint8_t *data,
2242 downstream->reset_upstream_rtimer();
2244 if (downstream->push_upload_data_chunk(data, datalen) != 0) {
2245 if (downstream->get_response_state() != DownstreamState::MSG_COMPLETE) {
2246 shutdown_stream(downstream, NGHTTP3_H3_INTERNAL_ERROR);
2249 consume(downstream->get_stream_id(), datalen);
2258 int http_end_stream(nghttp3_conn *conn, int64_t stream_id, void *user_data,
2259 void *stream_user_data) {
2260 auto upstream = static_cast<Http3Upstream *>(user_data);
2261 auto downstream = static_cast<Downstream *>(stream_user_data);
2263 if (!downstream || downstream->get_stop_reading()) {
2267 if (upstream->http_end_stream(downstream) != 0) {
2268 return NGHTTP3_ERR_CALLBACK_FAILURE;
2275 int Http3Upstream::http_end_stream(Downstream *downstream) {
2276 downstream->disable_upstream_rtimer();
2278 if (downstream->end_upload_data() != 0) {
2279 if (downstream->get_response_state() != DownstreamState::MSG_COMPLETE) {
2280 shutdown_stream(downstream, NGHTTP2_INTERNAL_ERROR);
2284 downstream->set_request_state(DownstreamState::MSG_COMPLETE);
2290 int http_stream_close(nghttp3_conn *conn, int64_t stream_id,
2291 uint64_t app_error_code, void *conn_user_data,
2292 void *stream_user_data) {
2293 auto upstream = static_cast<Http3Upstream *>(conn_user_data);
2294 auto downstream = static_cast<Downstream *>(stream_user_data);
2300 if (upstream->http_stream_close(downstream, app_error_code) != 0) {
2301 return NGHTTP3_ERR_CALLBACK_FAILURE;
2308 int Http3Upstream::http_stream_close(Downstream *downstream,
2309 uint64_t app_error_code) {
2310 auto stream_id = downstream->get_stream_id();
2312 if (LOG_ENABLED(INFO)) {
2313 ULOG(INFO, this) << "Stream stream_id=" << stream_id
2314 << " is being closed with app_error_code="
2317 auto body = downstream->get_response_buf();
2319 ULOG(INFO, this) << "response unacked_left=" << body->rleft()
2320 << " not_sent=" << body->rleft_mark();
2323 auto &req = downstream->request();
2325 consume(stream_id, req.unconsumed_body_length);
2327 req.unconsumed_body_length = 0;
2329 ngtcp2_conn_extend_max_streams_bidi(conn_, 1);
2331 if (downstream->get_request_state() == DownstreamState::CONNECT_FAIL) {
2332 remove_downstream(downstream);
2333 // downstream was deleted
2338 if (downstream->can_detach_downstream_connection()) {
2340 downstream->detach_downstream_connection();
2343 downstream->set_request_state(DownstreamState::STREAM_CLOSED);
2345 // At this point, downstream read may be paused.
2347 // If shrpx_downstream::push_request_headers() failed, the
2348 // error is handled here.
2349 remove_downstream(downstream);
2350 // downstream was deleted
2356 int http_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
2357 uint64_t app_error_code, void *user_data,
2358 void *stream_user_data) {
2359 auto upstream = static_cast<Http3Upstream *>(user_data);
2361 if (upstream->http_send_stop_sending(stream_id, app_error_code) != 0) {
2362 return NGHTTP3_ERR_CALLBACK_FAILURE;
2369 int Http3Upstream::http_send_stop_sending(int64_t stream_id,
2370 uint64_t app_error_code) {
2371 auto rv = ngtcp2_conn_shutdown_stream_read(conn_, stream_id, app_error_code);
2372 if (ngtcp2_err_is_fatal(rv)) {
2373 ULOG(ERROR, this) << "ngtcp2_conn_shutdown_stream_read: "
2374 << ngtcp2_strerror(rv);
2382 int http_reset_stream(nghttp3_conn *conn, int64_t stream_id,
2383 uint64_t app_error_code, void *user_data,
2384 void *stream_user_data) {
2385 auto upstream = static_cast<Http3Upstream *>(user_data);
2387 if (upstream->http_reset_stream(stream_id, app_error_code) != 0) {
2388 return NGHTTP3_ERR_CALLBACK_FAILURE;
2395 int Http3Upstream::http_reset_stream(int64_t stream_id,
2396 uint64_t app_error_code) {
2397 auto rv = ngtcp2_conn_shutdown_stream_write(conn_, stream_id, app_error_code);
2398 if (ngtcp2_err_is_fatal(rv)) {
2399 ULOG(ERROR, this) << "ngtcp2_conn_shutdown_stream_write: "
2400 << ngtcp2_strerror(rv);
2407 int Http3Upstream::setup_httpconn() {
2410 if (ngtcp2_conn_get_max_local_streams_uni(conn_) < 3) {
2414 nghttp3_callbacks callbacks{
2415 shrpx::http_acked_stream_data,
2416 shrpx::http_stream_close,
2417 shrpx::http_recv_data,
2418 http_deferred_consume,
2419 shrpx::http_begin_request_headers,
2420 shrpx::http_recv_request_header,
2421 shrpx::http_end_request_headers,
2422 nullptr, // begin_trailers
2423 nullptr, // recv_trailer
2424 nullptr, // end_trailers
2425 shrpx::http_send_stop_sending,
2426 shrpx::http_end_stream,
2427 shrpx::http_reset_stream,
2430 auto config = get_config();
2432 nghttp3_settings settings;
2433 nghttp3_settings_default(&settings);
2434 settings.qpack_max_table_capacity = 4_k;
2436 if (!config->http2_proxy) {
2437 settings.enable_connect_protocol = 1;
2440 auto mem = nghttp3_mem_default();
2442 rv = nghttp3_conn_server_new(&httpconn_, &callbacks, &settings, mem, this);
2444 ULOG(ERROR, this) << "nghttp3_conn_server_new: " << nghttp3_strerror(rv);
2448 ngtcp2_transport_params params;
2449 ngtcp2_conn_get_local_transport_params(conn_, ¶ms);
2451 nghttp3_conn_set_max_client_streams_bidi(httpconn_,
2452 params.initial_max_streams_bidi);
2454 int64_t ctrl_stream_id;
2456 rv = ngtcp2_conn_open_uni_stream(conn_, &ctrl_stream_id, nullptr);
2458 ULOG(ERROR, this) << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv);
2462 rv = nghttp3_conn_bind_control_stream(httpconn_, ctrl_stream_id);
2464 ULOG(ERROR, this) << "nghttp3_conn_bind_control_stream: "
2465 << nghttp3_strerror(rv);
2469 int64_t qpack_enc_stream_id, qpack_dec_stream_id;
2471 rv = ngtcp2_conn_open_uni_stream(conn_, &qpack_enc_stream_id, nullptr);
2473 ULOG(ERROR, this) << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv);
2477 rv = ngtcp2_conn_open_uni_stream(conn_, &qpack_dec_stream_id, nullptr);
2479 ULOG(ERROR, this) << "ngtcp2_conn_open_uni_stream: " << ngtcp2_strerror(rv);
2483 rv = nghttp3_conn_bind_qpack_streams(httpconn_, qpack_enc_stream_id,
2484 qpack_dec_stream_id);
2486 ULOG(ERROR, this) << "nghttp3_conn_bind_qpack_streams: "
2487 << nghttp3_strerror(rv);
2494 int Http3Upstream::error_reply(Downstream *downstream,
2495 unsigned int status_code) {
2497 auto &resp = downstream->response();
2499 auto &balloc = downstream->get_block_allocator();
2501 auto html = http::create_error_html(balloc, status_code);
2502 resp.http_status = status_code;
2503 auto body = downstream->get_response_buf();
2505 downstream->set_response_state(DownstreamState::MSG_COMPLETE);
2507 nghttp3_data_reader data_read;
2508 data_read.read_data = downstream_read_data_callback;
2510 auto lgconf = log_config();
2511 lgconf->update_tstamp(std::chrono::system_clock::now());
2513 auto response_status = http2::stringify_status(balloc, status_code);
2514 auto content_length = util::make_string_ref_uint(balloc, html.size());
2515 auto date = make_string_ref(balloc, lgconf->tstamp->time_http);
2517 auto nva = std::array<nghttp3_nv, 5>{
2518 {http3::make_nv_ls_nocopy(":status", response_status),
2519 http3::make_nv_ll("content-type", "text/html; charset=UTF-8"),
2520 http3::make_nv_ls_nocopy("server", get_config()->http.server_name),
2521 http3::make_nv_ls_nocopy("content-length", content_length),
2522 http3::make_nv_ls_nocopy("date", date)}};
2524 rv = nghttp3_conn_submit_response(httpconn_, downstream->get_stream_id(),
2525 nva.data(), nva.size(), &data_read);
2526 if (nghttp3_err_is_fatal(rv)) {
2527 ULOG(FATAL, this) << "nghttp3_conn_submit_response() failed: "
2528 << nghttp3_strerror(rv);
2532 downstream->reset_upstream_wtimer();
2534 if (shutdown_stream_read(downstream->get_stream_id(), NGHTTP3_H3_NO_ERROR) !=
2542 int Http3Upstream::shutdown_stream(Downstream *downstream,
2543 uint64_t app_error_code) {
2544 auto stream_id = downstream->get_stream_id();
2546 if (LOG_ENABLED(INFO)) {
2547 ULOG(INFO, this) << "Shutdown stream_id=" << stream_id
2548 << " with app_error_code=" << app_error_code;
2551 auto rv = ngtcp2_conn_shutdown_stream(conn_, stream_id, app_error_code);
2553 ULOG(FATAL, this) << "ngtcp2_conn_shutdown_stream() failed: "
2554 << ngtcp2_strerror(rv);
2561 int Http3Upstream::shutdown_stream_read(int64_t stream_id,
2562 uint64_t app_error_code) {
2564 ngtcp2_conn_shutdown_stream_read(conn_, stream_id, NGHTTP3_H3_NO_ERROR);
2565 if (ngtcp2_err_is_fatal(rv)) {
2566 ULOG(FATAL, this) << "ngtcp2_conn_shutdown_stream_read: "
2567 << ngtcp2_strerror(rv);
2574 int Http3Upstream::redirect_to_https(Downstream *downstream) {
2575 auto &req = downstream->request();
2576 if (req.regular_connect_method() || req.scheme != "http") {
2577 return error_reply(downstream, 400);
2580 auto authority = util::extract_host(req.authority);
2581 if (authority.empty()) {
2582 return error_reply(downstream, 400);
2585 auto &balloc = downstream->get_block_allocator();
2586 auto config = get_config();
2587 auto &httpconf = config->http;
2590 if (httpconf.redirect_https_port == StringRef::from_lit("443")) {
2591 loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority,
2594 loc = concat_string_ref(balloc, StringRef::from_lit("https://"), authority,
2595 StringRef::from_lit(":"),
2596 httpconf.redirect_https_port, req.path);
2599 auto &resp = downstream->response();
2600 resp.http_status = 308;
2601 resp.fs.add_header_token(StringRef::from_lit("location"), loc, false,
2602 http2::HD_LOCATION);
2604 return send_reply(downstream, nullptr, 0);
2607 void Http3Upstream::consume(int64_t stream_id, size_t nconsumed) {
2608 ngtcp2_conn_extend_max_stream_offset(conn_, stream_id, nconsumed);
2609 ngtcp2_conn_extend_max_offset(conn_, nconsumed);
2612 void Http3Upstream::remove_downstream(Downstream *downstream) {
2613 if (downstream->accesslog_ready()) {
2614 handler_->write_accesslog(downstream);
2617 nghttp3_conn_set_stream_user_data(httpconn_, downstream->get_stream_id(),
2620 auto next_downstream = downstream_queue_.remove_and_get_blocked(downstream);
2622 if (next_downstream) {
2623 initiate_downstream(next_downstream);
2626 if (downstream_queue_.get_downstreams() == nullptr) {
2627 // There is no downstream at the moment. Start idle timer now.
2628 handler_->repeat_read_timer();
2632 void Http3Upstream::log_response_headers(
2633 Downstream *downstream, const std::vector<nghttp3_nv> &nva) const {
2634 std::stringstream ss;
2635 for (auto &nv : nva) {
2636 ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": "
2637 << StringRef{nv.value, nv.valuelen} << "\n";
2639 ULOG(INFO, this) << "HTTP response headers. stream_id="
2640 << downstream->get_stream_id() << "\n"
2644 int Http3Upstream::check_shutdown() {
2645 auto worker = handler_->get_worker();
2647 if (!worker->get_graceful_shutdown()) {
2651 ev_prepare_stop(handler_->get_loop(), &prep_);
2653 return start_graceful_shutdown();
2656 int Http3Upstream::start_graceful_shutdown() {
2659 if (ev_is_active(&shutdown_timer_)) {
2663 rv = nghttp3_conn_submit_shutdown_notice(httpconn_);
2665 ULOG(FATAL, this) << "nghttp3_conn_submit_shutdown_notice: "
2666 << nghttp3_strerror(rv);
2670 handler_->signal_write();
2672 auto t = ngtcp2_conn_get_pto(conn_);
2674 ev_timer_set(&shutdown_timer_, static_cast<ev_tstamp>(t * 3) / NGTCP2_SECONDS,
2676 ev_timer_start(handler_->get_loop(), &shutdown_timer_);
2681 int Http3Upstream::submit_goaway() {
2684 rv = nghttp3_conn_shutdown(httpconn_);
2686 ULOG(FATAL, this) << "nghttp3_conn_shutdown: " << nghttp3_strerror(rv);
2690 handler_->signal_write();
2695 void Http3Upstream::idle_close() { idle_close_ = true; }
2697 int Http3Upstream::open_qlog_file(const StringRef &dir,
2698 const ngtcp2_cid &scid) const {
2699 std::array<char, sizeof("20141115T125824.741+0900")> buf;
2701 auto path = dir.str();
2704 util::format_iso8601_basic(buf.data(), std::chrono::system_clock::now());
2706 path += util::format_hex(scid.data, scid.datalen);
2712 while ((fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
2713 S_IRUSR | S_IWUSR | S_IRGRP)) == -1 &&
2717 while ((fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
2718 S_IRUSR | S_IWUSR | S_IRGRP)) == -1 &&
2723 util::make_socket_closeonexec(fd);
2725 #endif // !O_CLOEXEC
2729 ULOG(ERROR, this) << "Failed to open qlog file " << path
2730 << ": errno=" << error;
2737 } // namespace shrpx