Skip to content
This repository was archived by the owner on Aug 11, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions src/quic/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1997,6 +1997,22 @@ bool QuicSession::SendConnectionClose() {
// serialize the connection close once but may end up transmitting
// it multiple times; whereas for clients, we will serialize it
// once and send once only.
QuicError error = last_error();

// If initial keys have not yet been installed, use the alternative
// ImmediateConnectionClose to send a stateless connection close to
// the peer.
if (crypto_context()->write_crypto_level() ==
NGTCP2_CRYPTO_LEVEL_INITIAL) {
socket()->ImmediateConnectionClose(
dcid(),
scid_,
local_address_,
remote_address_,
error.code);
return true;
}

switch (crypto_context_->side()) {
case NGTCP2_CRYPTO_SIDE_SERVER: {
// If we're not already in the closing period,
Expand All @@ -2005,7 +2021,7 @@ bool QuicSession::SendConnectionClose() {
// already started, skip this.
if (!is_in_closing_period() &&
(!WritePackets("server connection close - write packets") ||
!StartClosingPeriod())) {
!StartClosingPeriod())) {
return false;
}

Expand All @@ -2016,18 +2032,16 @@ bool QuicSession::SendConnectionClose() {
}
case NGTCP2_CRYPTO_SIDE_CLIENT: {
UpdateIdleTimer();
auto packet = QuicPacket::Create(
"client connection close");
QuicError error = last_error();
auto packet = QuicPacket::Create("client connection close");

// If we're not already in the closing period,
// first attempt to write any pending packets, then
// start the closing period. Note that the behavior
// here is different than the server
if (!is_in_closing_period() &&
!WritePackets("client connection close - write packets"))
!WritePackets("client connection close - write packets")) {
return false;

}
ssize_t nwrite =
SelectCloseFn(error.family)(
connection(),
Expand Down
21 changes: 16 additions & 5 deletions src/quic/node_quic_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,16 +693,18 @@ bool QuicSocket::SendRetry(

// Shutdown a connection prematurely, before a QuicSession is created.
void QuicSocket::ImmediateConnectionClose(
const ngtcp2_pkt_hd& hd,
const QuicCID& scid,
const QuicCID& dcid,
const SocketAddress& local_addr,
const SocketAddress& remote_addr,
int32_t reason) {
Debug(this, "Sending stateless connection close to %s", scid);
auto packet = QuicPacket::Create("immediate connection close");
ssize_t nwrite = ngtcp2_crypto_write_connection_close(
packet->data(),
packet->length(),
&hd.scid,
&hd.dcid,
scid.cid(),
dcid.cid(),
reason);
if (nwrite > 0) {
packet->set_length(nwrite);
Expand Down Expand Up @@ -760,7 +762,12 @@ BaseObjectPtr<QuicSession> QuicSocket::AcceptInitialPacket(
max_connections_per_host_) {
Debug(this, "QuicSocket is busy or connection count exceeded");
IncrementStat(&QuicSocketStats::server_busy_count);
ImmediateConnectionClose(hd, local_addr, remote_addr, NGTCP2_SERVER_BUSY);
ImmediateConnectionClose(
QuicCID(hd.scid),
QuicCID(hd.dcid),
local_addr,
remote_addr,
NGTCP2_SERVER_BUSY);
return {};
}

Expand Down Expand Up @@ -789,7 +796,11 @@ BaseObjectPtr<QuicSession> QuicSocket::AcceptInitialPacket(
token_secret_,
retry_token_expiration_)) {
Debug(this, "Invalid retry token was detected. Failing.");
ImmediateConnectionClose(hd, local_addr, remote_addr);
ImmediateConnectionClose(
QuicCID(hd.scid),
QuicCID(hd.dcid),
local_addr,
remote_addr);
return {};
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/quic/node_quic_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,13 @@ class QuicSocket : public AsyncWrap,

inline void AddEndpoint(QuicEndpoint* endpoint, bool preferred = false);

void ImmediateConnectionClose(
const QuicCID& scid,
const QuicCID& dcid,
const SocketAddress& local_addr,
const SocketAddress& remote_addr,
int32_t reason = NGTCP2_INVALID_TOKEN);

private:
static void OnAlloc(
uv_handle_t* handle,
Expand All @@ -405,11 +412,6 @@ class QuicSocket : public AsyncWrap,
const SocketAddress& local_addr,
const SocketAddress& remote_addr,
unsigned int flags);
void ImmediateConnectionClose(
const ngtcp2_pkt_hd& hd,
const SocketAddress& local_addr,
const SocketAddress& remote_addr,
int32_t reason = NGTCP2_INVALID_TOKEN);

BaseObjectPtr<QuicSession> AcceptInitialPacket(
uint32_t version,
Expand Down