diff options
Diffstat (limited to 'src/shrpx_quic_connection_handler.cc')
-rw-r--r-- | src/shrpx_quic_connection_handler.cc | 172 |
1 files changed, 89 insertions, 83 deletions
diff --git a/src/shrpx_quic_connection_handler.cc b/src/shrpx_quic_connection_handler.cc index b810aa6..f10cc83 100644 --- a/src/shrpx_quic_connection_handler.cc +++ b/src/shrpx_quic_connection_handler.cc @@ -63,17 +63,18 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_info &pi, - const uint8_t *data, size_t datalen) { + std::span<const uint8_t> data) { int rv; ngtcp2_version_cid vc; - rv = ngtcp2_pkt_decode_version_cid(&vc, data, datalen, SHRPX_QUIC_SCIDLEN); + rv = ngtcp2_pkt_decode_version_cid(&vc, data.data(), data.size(), + SHRPX_QUIC_SCIDLEN); switch (rv) { case 0: break; case NGTCP2_ERR_VERSION_NEGOTIATION: - send_version_negotiation(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr); + send_version_negotiation(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr); return 0; default: @@ -97,7 +98,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (cwit != std::end(close_waits_)) { auto cw = (*cwit).second; - cw->handle_packet(faddr, remote_addr, local_addr, pi, data, datalen); + cw->handle_packet(faddr, remote_addr, local_addr, pi, data); return 0; } @@ -114,7 +115,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (cwit != std::end(close_waits_)) { auto cw = (*cwit).second; - cw->handle_packet(faddr, remote_addr, local_addr, pi, data, datalen); + cw->handle_packet(faddr, remote_addr, local_addr, pi, data); return 0; } @@ -145,7 +146,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, decrypted_dcid.worker); if (quic_lwp) { if (conn_handler->forward_quic_packet_to_lingering_worker_process( - quic_lwp, remote_addr, local_addr, pi, data, datalen) == 0) { + quic_lwp, remote_addr, local_addr, pi, data) == 0) { return 0; } @@ -169,11 +170,10 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, ngtcp2_pkt_hd hd; ngtcp2_cid odcid, *podcid = nullptr; - const uint8_t *token = nullptr; - size_t tokenlen = 0; + std::span<const uint8_t> token; ngtcp2_token_type token_type = NGTCP2_TOKEN_TYPE_UNKNOWN; - switch (ngtcp2_accept(&hd, data, datalen)) { + switch (ngtcp2_accept(&hd, data.data(), data.size())) { case 0: { // If we get Initial and it has the Worker ID of this worker, it // is likely that client is intentionally use the prefix. Just @@ -197,14 +197,15 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, if (worker_->get_graceful_shutdown()) { send_connection_close(faddr, hd.version, hd.dcid, hd.scid, remote_addr, local_addr, NGTCP2_CONNECTION_REFUSED, - datalen * 3); + data.size() * 3); return 0; } if (hd.tokenlen == 0) { if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -223,9 +224,9 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, auto qkm = select_quic_keying_material( *qkms.get(), vc.dcid[0] & SHRPX_QUIC_DCID_KM_ID_MASK); - if (verify_retry_token(odcid, hd.token, hd.tokenlen, hd.version, + if (verify_retry_token(odcid, {hd.token, hd.tokenlen}, hd.version, hd.dcid, &remote_addr.su.sa, remote_addr.len, - qkm->secret.data(), qkm->secret.size()) != 0) { + qkm->secret) != 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Failed to validate Retry token from remote=" << util::to_numeric_addr(&remote_addr); @@ -235,7 +236,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, // with INVALID_TOKEN. send_connection_close(faddr, hd.version, hd.dcid, hd.scid, remote_addr, local_addr, NGTCP2_INVALID_TOKEN, - datalen * 3); + data.size() * 3); return 0; } @@ -245,8 +246,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } podcid = &odcid; - token = hd.token; - tokenlen = hd.tokenlen; + token = {hd.token, hd.tokenlen}; token_type = NGTCP2_TOKEN_TYPE_RETRY; break; @@ -265,8 +265,9 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -277,17 +278,17 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, auto qkm = select_quic_keying_material( *qkms.get(), hd.token[NGTCP2_CRYPTO_MAX_REGULAR_TOKENLEN]); - if (verify_token(hd.token, hd.tokenlen - 1, &remote_addr.su.sa, - remote_addr.len, qkm->secret.data(), - qkm->secret.size()) != 0) { + if (verify_token({hd.token, hd.tokenlen}, &remote_addr.su.sa, + remote_addr.len, qkm->secret) != 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Failed to validate token from remote=" << util::to_numeric_addr(&remote_addr); } if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -300,16 +301,16 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, << util::to_numeric_addr(&remote_addr); } - token = hd.token; - tokenlen = hd.tokenlen; + token = {hd.token, hd.tokenlen}; token_type = NGTCP2_TOKEN_TYPE_NEW_TOKEN; break; } default: if (quicconf.upstream.require_token) { - send_retry(faddr, vc.version, vc.dcid, vc.dcidlen, vc.scid, - vc.scidlen, remote_addr, local_addr, datalen * 3); + send_retry(faddr, vc.version, {vc.dcid, vc.dcidlen}, + {vc.scid, vc.scidlen}, remote_addr, local_addr, + data.size() * 3); return 0; } @@ -322,16 +323,15 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, default: if (!(data[0] & 0x80) && vc.dcidlen == SHRPX_QUIC_SCIDLEN && decrypted_dcid.worker != worker_->get_worker_id()) { - if (!config->single_thread && - conn_handler->forward_quic_packet(faddr, remote_addr, local_addr, - pi, decrypted_dcid.worker, data, - datalen) == 0) { + if (!config->single_thread && conn_handler->forward_quic_packet( + faddr, remote_addr, local_addr, pi, + decrypted_dcid.worker, data) == 0) { return 0; } - if (datalen >= SHRPX_QUIC_SCIDLEN + 22) { - send_stateless_reset(faddr, datalen, vc.dcid, vc.dcidlen, remote_addr, - local_addr); + if (data.size() >= SHRPX_QUIC_SCIDLEN + 22) { + send_stateless_reset(faddr, data.size(), {vc.dcid, vc.dcidlen}, + remote_addr, local_addr); } } @@ -339,7 +339,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, } handler = handle_new_connection(faddr, remote_addr, local_addr, hd, podcid, - token, tokenlen, token_type); + token, token_type); if (handler == nullptr) { return 0; } @@ -347,8 +347,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, handler = (*it).second; } - if (handler->read_quic(faddr, remote_addr, local_addr, pi, data, datalen) != - 0) { + if (handler->read_quic(faddr, remote_addr, local_addr, pi, data) != 0) { delete handler; return 0; } @@ -361,7 +360,7 @@ int QUICConnectionHandler::handle_packet(const UpstreamAddr *faddr, ClientHandler *QUICConnectionHandler::handle_new_connection( const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, const ngtcp2_pkt_hd &hd, const ngtcp2_cid *odcid, - const uint8_t *token, size_t tokenlen, ngtcp2_token_type token_type) { + std::span<const uint8_t> token, ngtcp2_token_type token_type) { std::array<char, NI_MAXHOST> host; std::array<char, NI_MAXSERV> service; int rv; @@ -412,7 +411,7 @@ ClientHandler *QUICConnectionHandler::handle_new_connection( StringRef{service.data()}, remote_addr.su.sa.sa_family, faddr); auto upstream = std::make_unique<Http3Upstream>(handler.get()); - if (upstream->init(faddr, remote_addr, local_addr, hd, odcid, token, tokenlen, + if (upstream->init(faddr, remote_addr, local_addr, hd, odcid, token, token_type) != 0) { return nullptr; } @@ -450,8 +449,8 @@ uint32_t generate_reserved_version(const Address &addr, uint32_t version) { } // namespace int QUICConnectionHandler::send_retry( - const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, - size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, + const UpstreamAddr *faddr, uint32_t version, + std::span<const uint8_t> ini_dcid, std::span<const uint8_t> ini_scid, const Address &remote_addr, const Address &local_addr, size_t max_pktlen) { std::array<char, NI_MAXHOST> host; std::array<char, NI_MAXSERV> port; @@ -476,25 +475,25 @@ int QUICConnectionHandler::send_retry( return -1; } - std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> token; - size_t tokenlen; - ngtcp2_cid idcid, iscid; - ngtcp2_cid_init(&idcid, ini_dcid, ini_dcidlen); - ngtcp2_cid_init(&iscid, ini_scid, ini_scidlen); + ngtcp2_cid_init(&idcid, ini_dcid.data(), ini_dcid.size()); + ngtcp2_cid_init(&iscid, ini_scid.data(), ini_scid.size()); + + std::array<uint8_t, NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN> tokenbuf; - if (generate_retry_token(token.data(), tokenlen, version, &remote_addr.su.sa, - remote_addr.len, retry_scid, idcid, - qkm.secret.data(), qkm.secret.size()) != 0) { + auto token = + generate_retry_token(tokenbuf, version, &remote_addr.su.sa, + remote_addr.len, retry_scid, idcid, qkm.secret); + if (!token) { return -1; } std::vector<uint8_t> buf; buf.resize(std::min(max_pktlen, static_cast<size_t>(256))); - auto nwrite = - ngtcp2_crypto_write_retry(buf.data(), buf.size(), version, &iscid, - &retry_scid, &idcid, token.data(), tokenlen); + auto nwrite = ngtcp2_crypto_write_retry(buf.data(), buf.size(), version, + &iscid, &retry_scid, &idcid, + token->data(), token->size()); if (nwrite < 0) { LOG(ERROR) << "ngtcp2_crypto_write_retry: " << ngtcp2_strerror(nwrite); return -1; @@ -503,8 +502,8 @@ int QUICConnectionHandler::send_retry( buf.resize(nwrite); quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, - &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), buf.size(), 0); + &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, buf, + buf.size()); if (generate_quic_hashed_connection_id(idcid, remote_addr, local_addr, idcid) != 0) { @@ -528,13 +527,13 @@ int QUICConnectionHandler::send_retry( } int QUICConnectionHandler::send_version_negotiation( - const UpstreamAddr *faddr, uint32_t version, const uint8_t *ini_dcid, - size_t ini_dcidlen, const uint8_t *ini_scid, size_t ini_scidlen, + const UpstreamAddr *faddr, uint32_t version, + std::span<const uint8_t> ini_dcid, std::span<const uint8_t> ini_scid, const Address &remote_addr, const Address &local_addr) { - std::array<uint32_t, 2> sv{ + auto sv = std::to_array({ generate_reserved_version(remote_addr, version), NGTCP2_PROTO_VER_V1, - }; + }); std::array<uint8_t, NGTCP2_MAX_UDP_PAYLOAD_SIZE> buf; @@ -542,22 +541,25 @@ int QUICConnectionHandler::send_version_negotiation( util::random_bytes(&rand_byte, &rand_byte + 1, worker_->get_randgen()); auto nwrite = ngtcp2_pkt_write_version_negotiation( - buf.data(), buf.size(), rand_byte, ini_scid, ini_scidlen, ini_dcid, - ini_dcidlen, sv.data(), sv.size()); + buf.data(), buf.size(), rand_byte, ini_scid.data(), ini_scid.size(), + ini_dcid.data(), ini_dcid.size(), sv.data(), sv.size()); if (nwrite < 0) { LOG(ERROR) << "ngtcp2_pkt_write_version_negotiation: " << ngtcp2_strerror(nwrite); return -1; } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } -int QUICConnectionHandler::send_stateless_reset( - const UpstreamAddr *faddr, size_t pktlen, const uint8_t *dcid, - size_t dcidlen, const Address &remote_addr, const Address &local_addr) { +int QUICConnectionHandler::send_stateless_reset(const UpstreamAddr *faddr, + size_t pktlen, + std::span<const uint8_t> dcid, + const Address &remote_addr, + const Address &local_addr) { if (stateless_reset_bucket_ == 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Stateless Reset bucket has been depleted"; @@ -572,25 +574,24 @@ int QUICConnectionHandler::send_stateless_reset( ev_timer_again(worker_->get_loop(), &stateless_reset_bucket_regen_timer_); } - int rv; std::array<uint8_t, NGTCP2_STATELESS_RESET_TOKENLEN> token; ngtcp2_cid cid; - ngtcp2_cid_init(&cid, dcid, dcidlen); + ngtcp2_cid_init(&cid, dcid.data(), dcid.size()); auto conn_handler = worker_->get_connection_handler(); auto &qkms = conn_handler->get_quic_keying_materials(); auto &qkm = qkms->keying_materials.front(); - rv = generate_quic_stateless_reset_token(token.data(), cid, qkm.secret.data(), - qkm.secret.size()); - if (rv != 0) { + if (auto rv = generate_quic_stateless_reset_token( + token.data(), cid, qkm.secret.data(), qkm.secret.size()); + rv != 0) { return -1; } // SCID + minimum expansion - NGTCP2_STATELESS_RESET_TOKENLEN constexpr size_t max_rand_byteslen = - SHRPX_QUIC_SCIDLEN + 22 - NGTCP2_STATELESS_RESET_TOKENLEN; + NGTCP2_MAX_CIDLEN + 22 - NGTCP2_STATELESS_RESET_TOKENLEN; size_t rand_byteslen; @@ -621,12 +622,13 @@ int QUICConnectionHandler::send_stateless_reset( if (LOG_ENABLED(INFO)) { LOG(INFO) << "Send stateless_reset to remote=" << util::to_numeric_addr(&remote_addr) - << " dcid=" << util::format_hex(dcid, dcidlen); + << " dcid=" << util::format_hex(dcid); } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } int QUICConnectionHandler::send_connection_close( @@ -649,13 +651,16 @@ int QUICConnectionHandler::send_connection_close( LOG(INFO) << "Send Initial CONNECTION_CLOSE with error_code=" << log::hex << error_code << log::dec << " to remote=" << util::to_numeric_addr(&remote_addr) - << " dcid=" << util::format_hex(ini_scid.data, ini_scid.datalen) - << " scid=" << util::format_hex(ini_dcid.data, ini_dcid.datalen); + << " dcid=" + << util::format_hex(std::span{ini_scid.data, ini_scid.datalen}) + << " scid=" + << util::format_hex(std::span{ini_dcid.data, ini_dcid.datalen}); } + auto pkt = std::span{std::begin(buf), static_cast<size_t>(nwrite)}; return quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - buf.data(), nwrite, 0); + pkt, pkt.size()); } void QUICConnectionHandler::add_connection_id(const ngtcp2_cid &cid, @@ -735,23 +740,24 @@ CloseWait::~CloseWait() { int CloseWait::handle_packet(const UpstreamAddr *faddr, const Address &remote_addr, const Address &local_addr, - const ngtcp2_pkt_info &pi, const uint8_t *data, - size_t datalen) { + const ngtcp2_pkt_info &pi, + std::span<const uint8_t> data) { if (pkt.empty()) { return 0; } ++num_pkts_recv; - bytes_recv += datalen; + bytes_recv += data.size(); if (bytes_sent + pkt.size() > 3 * bytes_recv || next_pkts_recv > num_pkts_recv) { return 0; } - if (quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, - &local_addr.su.sa, local_addr.len, ngtcp2_pkt_info{}, - pkt.data(), pkt.size(), 0) != 0) { + auto rv = quic_send_packet(faddr, &remote_addr.su.sa, remote_addr.len, + &local_addr.su.sa, local_addr.len, + ngtcp2_pkt_info{}, pkt, pkt.size()); + if (rv != 0) { return -1; } |