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

Commit

Permalink
quic: make alpn configurable + a fix
Browse files Browse the repository at this point in the history
Since it will be possible to do raw quic in addition to http3,
make the alpn configurable
  • Loading branch information
jasnell committed May 20, 2019
1 parent 5872063 commit e9d8fb4
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 50 deletions.
27 changes: 19 additions & 8 deletions lib/internal/quic/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ class QuicSocket extends EventEmitter {
#sessions = new Set();
#state = kSocketUnbound;
#type = undefined;
#alpn = undefined;

constructor(options) {
const {
Expand Down Expand Up @@ -501,7 +502,8 @@ class QuicSocket extends EventEmitter {
this.#serverSecureContext.context,
address,
type,
port);
port,
this.#alpn);
process.nextTick(emit.bind(this, 'listening'));
}

Expand Down Expand Up @@ -530,6 +532,10 @@ class QuicSocket extends EventEmitter {
...options
};

const { alpn } = options;
if (alpn !== undefined && typeof alpn !== 'string')
throw new ERR_INVALID_ARG_TYPE('options.alpn', 'string', alpn);

if (callback) {
if (typeof callback !== 'function')
throw new ERR_INVALID_CALLBACK();
Expand All @@ -542,6 +548,7 @@ class QuicSocket extends EventEmitter {
// since we do not need to access this anywhere else.
this.#serverSecureContext = createSecureContext(options, initSecureContext);
this.#serverListening = true;
this.#alpn = alpn;

const doListen =
continueListen.bind(
Expand Down Expand Up @@ -1142,6 +1149,7 @@ function setSocketAfterBind(socket, callback) {
}

class QuicClientSession extends QuicSession {
#alpn = undefined;
#handleReady = false;
#ipv6Only = undefined;
#minDHSize = undefined;
Expand All @@ -1162,19 +1170,21 @@ class QuicClientSession extends QuicSession {
};

const {
servername,
port,
ipv6Only,
minDHSize,
remoteTransportParams,
sessionTicket,
alpn,
dcid,
ipv6Only,
maxCidLen,
minCidLen,
minDHSize,
port,
preferredAddressPolicy,
remoteTransportParams,
servername,
sessionTicket,
} = validateQuicClientSessionOptions(options);

super(socket, servername);
this.#alpn = alpn;
this.#transportParams =
validateTransportParams(
options,
Expand Down Expand Up @@ -1215,7 +1225,8 @@ class QuicClientSession extends QuicSession {
this.#remoteTransportParams,
this.#sessionTicket,
this.#dcid,
this.#preferredAddressPolicy);
this.#preferredAddressPolicy,
this.#alpn);
// We no longer need these, unset them so
// memory can be garbage collected.
this.#remoteTransportParams = undefined;
Expand Down
29 changes: 17 additions & 12 deletions lib/internal/quic/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,17 @@ function validateTransportParams(params, maxCidLen, minCidLen) {
function validateQuicClientSessionOptions(options) {
const {
address,
servername = address,
port = 0,
ipv6Only = false,
minDHSize = 1024,
remoteTransportParams,
sessionTicket,
alpn,
dcid: dcid_value,
ipv6Only = false,
maxCidLen = NGTCP2_MAX_CIDLEN,
minCidLen = NGTCP2_MIN_CIDLEN,
minDHSize = 1024,
port = 0,
preferredAddressPolicy = 'ignore',
remoteTransportParams,
servername = address,
sessionTicket,
} = { ...options };

if (typeof minDHSize !== 'number')
Expand Down Expand Up @@ -224,6 +225,9 @@ function validateQuicClientSessionOptions(options) {
sessionTicket);
}

if (alpn !== undefined && typeof alpn !== 'string')
throw new ERR_INVALID_ARG_TYPE('options.alpn', 'string', alpn);

validateNumberInBoundedRange(
maxCidLen,
'options.maxCidLen',
Expand Down Expand Up @@ -276,19 +280,20 @@ function validateQuicClientSessionOptions(options) {

return {
address,
servername,
port,
ipv6Only,
minDHSize,
remoteTransportParams,
sessionTicket,
alpn,
dcid,
ipv6Only,
maxCidLen,
minCidLen,
minDHSize,
port,
preferredAddressPolicy:
preferredAddressPolicy === 'accept' ?
QUIC_PREFERRED_ADDRESS_ACCEPT :
QUIC_PREFERRED_ADDRESS_IGNORE,
remoteTransportParams,
servername,
sessionTicket,
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/node_quic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ int ALPN_Select_Proto_CB(SSL* ssl,

switch (version) {
case NGTCP2_PROTO_VER:
alpn = reinterpret_cast<const uint8_t*>(NGTCP2_ALPN_H3);
alpnlen = strsize(NGTCP2_ALPN_H3);
alpn = reinterpret_cast<const uint8_t*>(session->GetALPN().c_str());
alpnlen = session->GetALPN().length();
break;
default:
// Unexpected QUIC protocol version
Expand Down
57 changes: 42 additions & 15 deletions src/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,8 @@ QuicSession::QuicSession(
QuicSocket* socket,
Local<Object> wrap,
SecureContext* ctx,
AsyncWrap::ProviderType type) :
AsyncWrap::ProviderType type,
const std::string& alpn) :
AsyncWrap(socket->env(), wrap, type),
rx_crypto_level_(NGTCP2_CRYPTO_LEVEL_INITIAL),
tx_crypto_level_(NGTCP2_CRYPTO_LEVEL_INITIAL),
Expand All @@ -740,6 +741,7 @@ QuicSession::QuicSession(
current_ngtcp2_memory_(0),
max_cid_len_(NGTCP2_MAX_CIDLEN),
min_cid_len_(NGTCP2_MIN_CIDLEN),
alpn_(alpn),
allocator_(this) {
ssl_.reset(SSL_new(ctx->ctx_.get()));
SSL_CTX_set_keylog_callback(ctx->ctx_.get(), OnKeylog);
Expand All @@ -761,6 +763,10 @@ QuicSession::~QuicSession() {
ngtcp2_conn_del(connection_);
}

const std::string& QuicSession::GetALPN() {
return alpn_;
}

void QuicSession::Keylog(const char* line) {
if (LIKELY(state_[IDX_QUIC_SESSION_STATE_KEYLOG_ENABLED] == 0))
return;
Expand Down Expand Up @@ -1918,11 +1924,14 @@ QuicServerSession::QuicServerSession(
const struct sockaddr* addr,
const ngtcp2_cid* dcid,
const ngtcp2_cid* ocid,
uint32_t version) :
QuicSession(socket,
wrap,
socket->GetServerSecureContext(),
AsyncWrap::PROVIDER_QUICSERVERSESSION),
uint32_t version,
const std::string& alpn) :
QuicSession(
socket,
wrap,
socket->GetServerSecureContext(),
AsyncWrap::PROVIDER_QUICSERVERSESSION,
alpn),
pscid_{},
rcid_(*rcid),
draining_(false) {
Expand Down Expand Up @@ -2081,7 +2090,8 @@ std::shared_ptr<QuicSession> QuicServerSession::New(
const struct sockaddr* addr,
const ngtcp2_cid* dcid,
const ngtcp2_cid* ocid,
uint32_t version) {
uint32_t version,
const std::string& alpn) {
std::shared_ptr<QuicSession> session;
Local<Object> obj;
if (!socket->env()
Expand All @@ -2097,7 +2107,8 @@ std::shared_ptr<QuicSession> QuicServerSession::New(
addr,
dcid,
ocid,
version));
version,
alpn));

session->AddToSocket(socket);
return session;
Expand Down Expand Up @@ -2445,7 +2456,8 @@ std::shared_ptr<QuicSession> QuicClientSession::New(
Local<Value> early_transport_params,
Local<Value> session_ticket,
Local<Value> dcid,
int select_preferred_address_policy) {
int select_preferred_address_policy,
const std::string& alpn) {
std::shared_ptr<QuicSession> session;
Local<Object> obj;
if (!socket->env()
Expand All @@ -2466,7 +2478,8 @@ std::shared_ptr<QuicSession> QuicClientSession::New(
early_transport_params,
session_ticket,
dcid,
select_preferred_address_policy);
select_preferred_address_policy,
alpn);

session->AddToSocket(socket);
session->Start();
Expand All @@ -2485,8 +2498,14 @@ QuicClientSession::QuicClientSession(
Local<Value> early_transport_params,
Local<Value> session_ticket,
Local<Value> dcid,
int select_preferred_address_policy) :
QuicSession(socket, wrap, context, AsyncWrap::PROVIDER_QUICCLIENTSESSION),
int select_preferred_address_policy,
const std::string& alpn) :
QuicSession(
socket,
wrap,
context,
AsyncWrap::PROVIDER_QUICCLIENTSESSION,
alpn),
resumption_(false),
hostname_(hostname),
select_preferred_address_policy_(select_preferred_address_policy) {
Expand Down Expand Up @@ -2707,8 +2726,8 @@ int QuicClientSession::SetSession(SSL_SESSION* session) {
void QuicClientSession::InitTLS_Post() {
SSL_set_connect_state(ssl());

const uint8_t* alpn = reinterpret_cast<const uint8_t*>(NGTCP2_ALPN_H3);
size_t alpnlen = strsize(NGTCP2_ALPN_H3);
const uint8_t* alpn = reinterpret_cast<const uint8_t*>(GetALPN().c_str());
size_t alpnlen = GetALPN().length();
SSL_set_alpn_protos(ssl(), alpn, alpnlen);

// If the hostname is an IP address and we have no additional
Expand Down Expand Up @@ -3333,6 +3352,13 @@ void NewQuicClientSession(const FunctionCallbackInfo<Value>& args) {
USE(args[10]->Int32Value(
env->context()).To(&select_preferred_address_policy));

std::string alpn(NGTCP2_ALPN_H3);
if (args[11]->IsString()) {
Utf8Value val(env->isolate(), args[11]);
alpn = val.length();
alpn += *val;
}

socket->ReceiveStart();

std::shared_ptr<QuicSession> session =
Expand All @@ -3345,7 +3371,8 @@ void NewQuicClientSession(const FunctionCallbackInfo<Value>& args) {
args[7],
args[8],
args[9],
select_preferred_address_policy);
select_preferred_address_policy,
alpn);

socket->SendPendingData();

Expand Down
18 changes: 13 additions & 5 deletions src/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,15 @@ class QuicSession : public AsyncWrap,
QuicSocket* socket,
v8::Local<v8::Object> wrap,
crypto::SecureContext* ctx,
AsyncWrap::ProviderType provider);
AsyncWrap::ProviderType provider,
const std::string& alpn);
~QuicSession() override;

void AddStream(QuicStream* stream);
void Close();
void Closing();
void Destroy();
const std::string& GetALPN();
void GetLocalTransportParams(
ngtcp2_transport_params* params);
uint32_t GetNegotiatedVersion();
Expand Down Expand Up @@ -582,6 +584,8 @@ class QuicSession : public AsyncWrap,
size_t max_cid_len_;
size_t min_cid_len_;

std::string alpn_;

mem::Allocator<ngtcp2_mem> allocator_;

friend class QuicServerSession;
Expand All @@ -601,7 +605,8 @@ class QuicServerSession : public QuicSession {
const struct sockaddr* addr,
const ngtcp2_cid* dcid,
const ngtcp2_cid* ocid,
uint32_t version);
uint32_t version,
const std::string& alpn = NGTCP2_ALPN_H3);

void AddToSocket(QuicSocket* socket) override;

Expand Down Expand Up @@ -631,7 +636,8 @@ class QuicServerSession : public QuicSession {
const struct sockaddr* addr,
const ngtcp2_cid* dcid,
const ngtcp2_cid* ocid,
uint32_t version);
uint32_t version,
const std::string& alpn);

void DisassociateCID(
const ngtcp2_cid* cid) override;
Expand Down Expand Up @@ -731,7 +737,8 @@ class QuicClientSession : public QuicSession {
v8::Local<v8::Value> session_ticket,
v8::Local<v8::Value> dcid,
int select_preferred_address_policy =
QUIC_PREFERRED_ADDRESS_IGNORE);
QUIC_PREFERRED_ADDRESS_IGNORE,
const std::string& alpn = NGTCP2_ALPN_H3);

QuicClientSession(
QuicSocket* socket,
Expand All @@ -744,7 +751,8 @@ class QuicClientSession : public QuicSession {
v8::Local<v8::Value> early_transport_params,
v8::Local<v8::Value> session_ticket,
v8::Local<v8::Value> dcid,
int select_preferred_address_policy);
int select_preferred_address_policy,
const std::string& alpn);

void AddToSocket(QuicSocket* socket) override;

Expand Down
Loading

0 comments on commit e9d8fb4

Please sign in to comment.