Skip to content

Commit

Permalink
quic: update quic impl to use latest ngtcp2/nghttp3
Browse files Browse the repository at this point in the history
PR-URL: #51291
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
  • Loading branch information
jasnell committed Dec 29, 2023
1 parent 86ca72a commit 0bf1548
Show file tree
Hide file tree
Showing 14 changed files with 237 additions and 200 deletions.
26 changes: 13 additions & 13 deletions src/quic/application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ BaseObjectPtr<Packet> Session::Application::CreateStreamDataPacket() {
return Packet::Create(env(),
session_->endpoint_.get(),
session_->remote_address_,
ngtcp2_conn_get_max_udp_payload_size(*session_),
ngtcp2_conn_get_max_tx_udp_payload_size(*session_),
"stream data");
}

Expand Down Expand Up @@ -291,18 +291,18 @@ ssize_t Session::Application::WriteVStream(PathStorage* path,
uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_NONE;
if (stream_data.remaining > 0) flags |= NGTCP2_WRITE_STREAM_FLAG_MORE;
if (stream_data.fin) flags |= NGTCP2_WRITE_STREAM_FLAG_FIN;
ssize_t ret =
ngtcp2_conn_writev_stream(*session_,
&path->path,
nullptr,
buf,
ngtcp2_conn_get_max_udp_payload_size(*session_),
ndatalen,
flags,
stream_data.id,
stream_data.buf,
stream_data.count,
uv_hrtime());
ssize_t ret = ngtcp2_conn_writev_stream(
*session_,
&path->path,
nullptr,
buf,
ngtcp2_conn_get_max_tx_udp_payload_size(*session_),
ndatalen,
flags,
stream_data.id,
stream_data.buf,
stream_data.count,
uv_hrtime());
return ret;
}

Expand Down
5 changes: 2 additions & 3 deletions src/quic/bindingdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class Endpoint;
class Packet;

enum class Side {
CLIENT = NGTCP2_CRYPTO_SIDE_CLIENT,
SERVER = NGTCP2_CRYPTO_SIDE_SERVER,
CLIENT,
SERVER,
};

enum class EndpointLabel {
Expand Down Expand Up @@ -119,7 +119,6 @@ constexpr size_t kMaxVectorCount = 16;
V(alpn, "alpn") \
V(application_options, "application") \
V(bbr, "bbr") \
V(bbr2, "bbr2") \
V(ca, "ca") \
V(certs, "certs") \
V(cc_algorithm, "cc") \
Expand Down
24 changes: 12 additions & 12 deletions src/quic/data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,15 @@ std::string TypeName(QuicError::Type type) {
} // namespace

QuicError::QuicError(const std::string_view reason)
: reason_(reason), ptr_(&error_) {}
: reason_(reason), error_(), ptr_(&error_) {
ngtcp2_ccerr_default(&error_);
}

QuicError::QuicError(const ngtcp2_connection_close_error* ptr)
QuicError::QuicError(const ngtcp2_ccerr* ptr)
: reason_(reinterpret_cast<const char*>(ptr->reason), ptr->reasonlen),
ptr_(ptr) {}

QuicError::QuicError(const ngtcp2_connection_close_error& error)
QuicError::QuicError(const ngtcp2_ccerr& error)
: reason_(reinterpret_cast<const char*>(error.reason), error.reasonlen),
error_(error),
ptr_(&error_) {}
Expand Down Expand Up @@ -175,11 +177,11 @@ const std::string_view QuicError::reason() const {
return reason_;
}

QuicError::operator const ngtcp2_connection_close_error&() const {
QuicError::operator const ngtcp2_ccerr&() const {
return *ptr_;
}

QuicError::operator const ngtcp2_connection_close_error*() const {
QuicError::operator const ngtcp2_ccerr*() const {
return ptr_;
}

Expand Down Expand Up @@ -212,15 +214,15 @@ void QuicError::MemoryInfo(MemoryTracker* tracker) const {
QuicError QuicError::ForTransport(error_code code,
const std::string_view reason) {
QuicError error(reason);
ngtcp2_connection_close_error_set_transport_error(
ngtcp2_ccerr_set_transport_error(
&error.error_, code, error.reason_c_str(), reason.length());
return error;
}

QuicError QuicError::ForApplication(error_code code,
const std::string_view reason) {
QuicError error(reason);
ngtcp2_connection_close_error_set_application_error(
ngtcp2_ccerr_set_application_error(
&error.error_, code, error.reason_c_str(), reason.length());
return error;
}
Expand All @@ -235,22 +237,20 @@ QuicError QuicError::ForIdleClose(const std::string_view reason) {

QuicError QuicError::ForNgtcp2Error(int code, const std::string_view reason) {
QuicError error(reason);
ngtcp2_connection_close_error_set_transport_error_liberr(
ngtcp2_ccerr_set_liberr(
&error.error_, code, error.reason_c_str(), reason.length());
return error;
}

QuicError QuicError::ForTlsAlert(int code, const std::string_view reason) {
QuicError error(reason);
ngtcp2_connection_close_error_set_transport_error_tls_alert(
ngtcp2_ccerr_set_tls_alert(
&error.error_, code, error.reason_c_str(), reason.length());
return error;
}

QuicError QuicError::FromConnectionClose(ngtcp2_conn* session) {
QuicError error;
ngtcp2_conn_get_connection_close_error(session, &error.error_);
return error;
return QuicError(ngtcp2_conn_get_ccerr(session));
}

QuicError QuicError::TRANSPORT_NO_ERROR =
Expand Down
25 changes: 12 additions & 13 deletions src/quic/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,29 +71,28 @@ class QuicError final : public MemoryRetainer {
static constexpr error_code QUIC_APP_NO_ERROR = 65280;

enum class Type {
TRANSPORT = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT,
APPLICATION = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION,
VERSION_NEGOTIATION =
NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_VERSION_NEGOTIATION,
IDLE_CLOSE = NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT_IDLE_CLOSE,
TRANSPORT = NGTCP2_CCERR_TYPE_TRANSPORT,
APPLICATION = NGTCP2_CCERR_TYPE_APPLICATION,
VERSION_NEGOTIATION = NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION,
IDLE_CLOSE = NGTCP2_CCERR_TYPE_IDLE_CLOSE,
};

static constexpr error_code QUIC_ERROR_TYPE_TRANSPORT =
NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT;
NGTCP2_CCERR_TYPE_TRANSPORT;
static constexpr error_code QUIC_ERROR_TYPE_APPLICATION =
NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION;
NGTCP2_CCERR_TYPE_APPLICATION;

explicit QuicError(const std::string_view reason = "");
explicit QuicError(const ngtcp2_connection_close_error* ptr);
explicit QuicError(const ngtcp2_connection_close_error& error);
explicit QuicError(const ngtcp2_ccerr* ptr);
explicit QuicError(const ngtcp2_ccerr& error);

Type type() const;
error_code code() const;
const std::string_view reason() const;
uint64_t frame_type() const;

operator const ngtcp2_connection_close_error&() const;
operator const ngtcp2_connection_close_error*() const;
operator const ngtcp2_ccerr&() const;
operator const ngtcp2_ccerr*() const;

// Returns false if the QuicError uses a no_error code with type
// transport or application.
Expand Down Expand Up @@ -130,8 +129,8 @@ class QuicError final : public MemoryRetainer {
const uint8_t* reason_c_str() const;

std::string reason_;
ngtcp2_connection_close_error error_ = ngtcp2_connection_close_error();
const ngtcp2_connection_close_error* ptr_ = nullptr;
ngtcp2_ccerr error_;
const ngtcp2_ccerr* ptr_ = nullptr;
};

} // namespace quic
Expand Down
27 changes: 15 additions & 12 deletions src/quic/endpoint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ namespace quic {
#define ENDPOINT_CC(V) \
V(RENO, reno) \
V(CUBIC, cubic) \
V(BBR, bbr) \
V(BBR2, bbr2)
V(BBR, bbr)

struct Endpoint::State {
#define V(_, name, type) type name;
Expand Down Expand Up @@ -427,11 +426,15 @@ int Endpoint::UDP::Bind(const Endpoint::Options& options) {
}

void Endpoint::UDP::Ref() {
if (!is_closed()) uv_ref(reinterpret_cast<uv_handle_t*>(&impl_->handle_));
if (!is_closed_or_closing()) {
uv_ref(reinterpret_cast<uv_handle_t*>(&impl_->handle_));
}
}

void Endpoint::UDP::Unref() {
if (!is_closed()) uv_unref(reinterpret_cast<uv_handle_t*>(&impl_->handle_));
if (!is_closed_or_closing()) {
uv_unref(reinterpret_cast<uv_handle_t*>(&impl_->handle_));
}
}

int Endpoint::UDP::Start() {
Expand Down Expand Up @@ -476,7 +479,7 @@ Endpoint::UDP::operator bool() const {
}

SocketAddress Endpoint::UDP::local_address() const {
DCHECK(!is_closed() && is_bound());
DCHECK(!is_closed_or_closing() && is_bound());
return SocketAddress::FromSockName(impl_->handle_);
}

Expand Down Expand Up @@ -1012,7 +1015,7 @@ void Endpoint::Receive(const uv_buf_t& buf,

if (options_.validate_address) {
// If there is no token, generate and send one.
if (hd.token.len == 0) {
if (hd.tokenlen == 0) {
SendRetry(PathDescriptor{
version,
dcid,
Expand All @@ -1027,9 +1030,9 @@ void Endpoint::Receive(const uv_buf_t& buf,

// We have two kinds of tokens, each prefixed with a different magic
// byte.
switch (hd.token.base[0]) {
switch (hd.token[0]) {
case RetryToken::kTokenMagic: {
RetryToken token(hd.token.base, hd.token.len);
RetryToken token(hd.token, hd.tokenlen);
auto ocid = token.Validate(
version,
remote_address,
Expand All @@ -1055,7 +1058,7 @@ void Endpoint::Receive(const uv_buf_t& buf,
break;
}
case RegularToken::kTokenMagic: {
RegularToken token(hd.token.base, hd.token.len);
RegularToken token(hd.token, hd.tokenlen);
if (!token.Validate(
version,
remote_address,
Expand All @@ -1072,8 +1075,8 @@ void Endpoint::Receive(const uv_buf_t& buf,
// if a retry is sent.
return true;
}
hd.token.base = nullptr;
hd.token.len = 0;
hd.token = nullptr;
hd.tokenlen = 0;
break;
}
default: {
Expand All @@ -1093,7 +1096,7 @@ void Endpoint::Receive(const uv_buf_t& buf,
// so we don't have to do this dance again for this endpoint
// instance.
addrLRU_.Upsert(remote_address)->validated = true;
} else if (hd.token.len > 0) {
} else if (hd.tokenlen > 0) {
// If validation is turned off and there is a token, that's weird.
// The peer should only have a token if we sent it to them and we
// wouldn't have sent it unless validation was turned on. Let's
Expand Down
7 changes: 3 additions & 4 deletions src/quic/endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class Endpoint final : public AsyncWrap, public Packet::Listener {
static constexpr auto QUIC_CC_ALGO_RENO = NGTCP2_CC_ALGO_RENO;
static constexpr auto QUIC_CC_ALGO_CUBIC = NGTCP2_CC_ALGO_CUBIC;
static constexpr auto QUIC_CC_ALGO_BBR = NGTCP2_CC_ALGO_BBR;
static constexpr auto QUIC_CC_ALGO_BBR2 = NGTCP2_CC_ALGO_BBR2;

// Endpoint configuration options
struct Options final : public MemoryRetainer {
Expand Down Expand Up @@ -131,9 +130,9 @@ class Endpoint final : public AsyncWrap, public Packet::Listener {
#endif // DEBUG

// There are several common congestion control algorithms that ngtcp2 uses
// to determine how it manages the flow control window: RENO, CUBIC, BBR,
// and BBR2. The details of how each works is not relevant here. The choice
// of which to use by default is arbitrary and we can choose whichever we'd
// to determine how it manages the flow control window: RENO, CUBIC, and
// BBR. The details of how each works is not relevant here. The choice of
// which to use by default is arbitrary and we can choose whichever we'd
// like. Additional performance profiling will be needed to determine which
// is the better of the two for our needs.
ngtcp2_cc_algo cc_algorithm = NGTCP2_CC_ALGO_CUBIC;
Expand Down
27 changes: 15 additions & 12 deletions src/quic/preferredaddress.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ std::optional<const PreferredAddress::AddressInfo> get_address_info(
if (!paddr.ipv4_present) return std::nullopt;
PreferredAddress::AddressInfo address;
address.family = FAMILY;
address.port = paddr.ipv4_port;
address.port = paddr.ipv4.sin_port;
if (uv_inet_ntop(
FAMILY, paddr.ipv4_addr, address.host, sizeof(address.host)) == 0) {
FAMILY, &paddr.ipv4.sin_addr, address.host, sizeof(address.host)) ==
0) {
address.address = address.host;
}
return address;
} else {
if (!paddr.ipv6_present) return std::nullopt;
PreferredAddress::AddressInfo address;
address.family = FAMILY;
address.port = paddr.ipv6_port;
if (uv_inet_ntop(
FAMILY, paddr.ipv6_addr, address.host, sizeof(address.host)) == 0) {
address.port = paddr.ipv6.sin6_port;
if (uv_inet_ntop(FAMILY,
&paddr.ipv6.sin6_addr,
address.host,
sizeof(address.host)) == 0) {
address.address = address.host;
}
return address;
Expand All @@ -50,20 +53,20 @@ std::optional<const PreferredAddress::AddressInfo> get_address_info(
template <int FAMILY>
void copy_to_transport_params(ngtcp2_transport_params* params,
const sockaddr* addr) {
params->preferred_address_present = true;
params->preferred_addr_present = true;
if constexpr (FAMILY == AF_INET) {
const sockaddr_in* src = reinterpret_cast<const sockaddr_in*>(addr);
params->preferred_address.ipv4_port = SocketAddress::GetPort(addr);
memcpy(params->preferred_address.ipv4_addr,
params->preferred_addr.ipv4.sin_port = SocketAddress::GetPort(addr);
memcpy(&params->preferred_addr.ipv4.sin_addr,
&src->sin_addr,
sizeof(params->preferred_address.ipv4_addr));
sizeof(params->preferred_addr.ipv4.sin_addr));
} else {
DCHECK_EQ(FAMILY, AF_INET6);
const sockaddr_in6* src = reinterpret_cast<const sockaddr_in6*>(addr);
params->preferred_address.ipv6_port = SocketAddress::GetPort(addr);
memcpy(params->preferred_address.ipv6_addr,
params->preferred_addr.ipv6.sin6_port = SocketAddress::GetPort(addr);
memcpy(&params->preferred_addr.ipv6.sin6_addr,
&src->sin6_addr,
sizeof(params->preferred_address.ipv4_addr));
sizeof(params->preferred_addr.ipv4.sin_addr));
}
UNREACHABLE();
}
Expand Down
Loading

0 comments on commit 0bf1548

Please sign in to comment.