summaryrefslogtreecommitdiffstats
path: root/src/shrpx_quic_connection_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/shrpx_quic_connection_handler.cc')
-rw-r--r--src/shrpx_quic_connection_handler.cc172
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;
}