Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
quic: add connection id strategy
Browse files Browse the repository at this point in the history
We currently generate connection ID's randomly. There are,
however, alternative schemes being defined. Later we may
allow user code to select alternative strategies for
generating connection ids. This adds the basic mechanism.

PR-URL: #211
Reviewed-By: Anna Henningsen <[email protected]>
  • Loading branch information
jasnell authored and addaleax committed Dec 11, 2019
1 parent 42fa245 commit 7a5f980
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
30 changes: 24 additions & 6 deletions src/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,22 @@ void JSQuicSessionListener::OnQLog(const uint8_t* data, size_t len) {
&str);
}

// Generates and associates a new connection ID for this QuicSession.
// ngtcp2 will call this multiple times at the start of a new connection
// in order to build a pool of available CIDs.
void RandomConnectionIDStrategy::GetNewConnectionID(
QuicSession* session,
ngtcp2_cid* cid,
uint8_t* token,
size_t cidlen) {
cid->datalen = cidlen;
// cidlen shouldn't ever be zero here but just in case that
// behavior changes in ngtcp2 in the future...
if (cidlen > 0)
EntropySource(cid->data, cidlen);
EntropySource(token, NGTCP2_STATELESS_RESET_TOKENLEN);
}

// Check required capabilities were not excluded from the OpenSSL build:
// - OPENSSL_NO_SSL_TRACE excludes SSL_trace()
// - OPENSSL_NO_STDIO excludes BIO_new_fp()
Expand Down Expand Up @@ -1243,6 +1259,7 @@ QuicSession::QuicSession(
sizeof(recovery_stats_) / sizeof(double),
reinterpret_cast<double*>(&recovery_stats_)) {
PushListener(&default_listener_);
SetConnectionIDStrategory(&default_connection_id_strategy_);
crypto_context_.reset(new QuicCryptoContext(this, ctx, side, options));
application_.reset(SelectApplication(this));
if (rcid != nullptr)
Expand Down Expand Up @@ -1607,6 +1624,11 @@ uint32_t QuicSession::GetNegotiatedVersion() {
return ngtcp2_conn_get_negotiated_version(Connection());
}

void QuicSession::SetConnectionIDStrategory(ConnectionIDStrategy* strategy) {
CHECK_NOT_NULL(strategy);
connection_id_strategy_ = strategy;
}

// Generates and associates a new connection ID for this QuicSession.
// ngtcp2 will call this multiple times at the start of a new connection
// in order to build a pool of available CIDs.
Expand All @@ -1615,12 +1637,8 @@ int QuicSession::GetNewConnectionID(
uint8_t* token,
size_t cidlen) {
DCHECK(!IsFlagSet(QUICSESSION_FLAG_DESTROYED));
cid->datalen = cidlen;
// cidlen shouldn't ever be zero here but just in case that
// behavior changes in ngtcp2 in the future...
if (cidlen > 0)
EntropySource(cid->data, cidlen);
EntropySource(token, NGTCP2_STATELESS_RESET_TOKENLEN);
CHECK_NOT_NULL(connection_id_strategy_);
connection_id_strategy_->GetNewConnectionID(this, cid, token, cidlen);
AssociateCID(cid);
return 0;
}
Expand Down
27 changes: 26 additions & 1 deletion src/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,26 @@ class JSQuicSessionListener : public QuicSessionListener {
friend class QuicSession;
};

// Currently, we generate Connection IDs randomly. In the future,
// however, there may be other strategies that need to be supported.
class ConnectionIDStrategy {
public:
virtual void GetNewConnectionID(
QuicSession* session,
ngtcp2_cid* cid,
uint8_t* token,
size_t cidlen) = 0;
};

class RandomConnectionIDStrategy : public ConnectionIDStrategy {
public:
void GetNewConnectionID(
QuicSession* session,
ngtcp2_cid* cid,
uint8_t* token,
size_t cidlen) override;
};

// The QuicCryptoContext class encapsulates all of the crypto/TLS
// handshake details on behalf of a QuicSession.
class QuicCryptoContext : public MemoryRetainer {
Expand Down Expand Up @@ -911,6 +931,8 @@ class QuicSession : public AsyncWrap,
void PushListener(QuicSessionListener* listener);
void RemoveListener(QuicSessionListener* listener);

void SetConnectionIDStrategory(ConnectionIDStrategy* strategy);

// Tracks whether or not we are currently within an ngtcp2 callback
// function. Certain ngtcp2 APIs are not supposed to be called when
// within a callback. We use this as a gate to check.
Expand Down Expand Up @@ -1267,7 +1289,10 @@ class QuicSession : public AsyncWrap,
size_t connection_close_attempts_ = 0;
size_t connection_close_limit_ = 1;

QuicSessionListener* listener_;
ConnectionIDStrategy* connection_id_strategy_ = nullptr;
RandomConnectionIDStrategy default_connection_id_strategy_;

QuicSessionListener* listener_ = nullptr;
JSQuicSessionListener default_listener_;

TimerPointer idle_;
Expand Down

0 comments on commit 7a5f980

Please sign in to comment.