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

Commit

Permalink
quic: use UDP code from dgram
Browse files Browse the repository at this point in the history
This simplifies the code quite a bit.
  • Loading branch information
addaleax committed Oct 9, 2019
1 parent 641b7ed commit a684292
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 674 deletions.
130 changes: 56 additions & 74 deletions lib/internal/quic/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ const {
owner_symbol,
},
} = require('internal/async_hooks');
const dgram = require('dgram');
const internalDgram = require('internal/dgram');

const {
constants: {
UV_UDP_IPV6ONLY,
UV_UDP_REUSEADDR,
}
} = internalBinding('udp_wrap');

const {
writeGeneric,
Expand All @@ -59,7 +68,6 @@ const {
const {
codes: {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_CALLBACK,
ERR_OUT_OF_RANGE,
ERR_QUIC_ERROR,
Expand Down Expand Up @@ -90,8 +98,6 @@ const {
constants: {
AF_INET,
AF_INET6,
UV_UDP_IPV6ONLY,
UV_UDP_REUSEADDR,
NGTCP2_ALPN_H3,
NGTCP2_MAX_CIDLEN,
NGTCP2_MIN_CIDLEN,
Expand Down Expand Up @@ -221,11 +227,6 @@ function setTransportParams(config) {
sessionConfig[IDX_QUIC_SESSION_CONFIG_COUNT] = flags;
}

// Called when the socket has been bound and is ready for use
function onSocketReady(fd) {
this[owner_symbol][kReady](fd);
}

// Called when the socket is closed
function onSocketClose() {
this[owner_symbol].destroy();
Expand Down Expand Up @@ -436,7 +437,6 @@ function onSessionSilentClose(statelessReset, code, family) {

// Register the callbacks with the QUIC internal binding.
setCallbacks({
onSocketReady,
onSocketClose,
onSocketError,
onSocketServerBusy,
Expand Down Expand Up @@ -620,6 +620,8 @@ class QuicSocket extends EventEmitter {
#type = undefined;
#alpn = undefined;
#stats = undefined;
#udpSocket = undefined;
#udpHandle = undefined;

constructor(options = {}) {
const {
Expand Down Expand Up @@ -667,11 +669,17 @@ class QuicSocket extends EventEmitter {
const socketOptions =
(validateAddress ? QUICSOCKET_OPTIONS_VALIDATE_ADDRESS : 0) |
(validateAddressLRU ? QUICSOCKET_OPTIONS_VALIDATE_ADDRESS_LRU : 0);
this.#udpSocket = dgram.createSocket(type === AF_INET6 ? 'udp6' : 'udp4');
// TODO(addaleax): Ideally, we would not be needing to store the handle
// separately, and only pass it to the QuicSocketHandle constructor.
this.#udpHandle = this.#udpSocket[internalDgram.kStateSymbol].handle;
const handle =
new QuicSocketHandle(
this.#udpHandle,
socketOptions,
retryTokenTimeout,
maxConnectionsPerHost);
this.#udpHandle.quicSocket = handle;
handle[owner_symbol] = this;
this[async_id_symbol] = handle.getAsyncId();
this[kSetHandle](handle);
Expand Down Expand Up @@ -728,14 +736,16 @@ class QuicSocket extends EventEmitter {
const flags =
(this.#reuseAddr ? UV_UDP_REUSEADDR : 0) ||
(this.#ipv6Only ? UV_UDP_IPV6ONLY : 0);
const ret = this[kHandle].bind(this.#type, ip, this.#port || 0, flags);
const ret = this.#udpHandle.bind(ip, this.#port || 0, flags);
if (ret) {
this.destroy(exceptionWithHostPort(ret, 'bind', ip, this.#port || 0));
return;
}

if (typeof callback === 'function')
callback();

this[kReady](this.#udpHandle.fd);
}

// The kReady function is called after the socket has been bound to the
Expand Down Expand Up @@ -913,20 +923,23 @@ class QuicSocket extends EventEmitter {
if (handle !== undefined) {
this[kSetHandle]();
handle[owner_symbol] = undefined;
handle.close((err) => {
// If an error occurs while attempting to close, it will take
// precedence over any original error specified on the args
// TODO(@jasnell): Alternatively we might set the original
// error as a property on the new error.
if (err) error = err;

// Capture a copy of the stats as they will no longer be
// available once this function returns.
this.#stats = new BigInt64Array(handle.stats);

if (error) process.nextTick(emit.bind(this, 'error', error));
process.nextTick(emit.bind(this, 'close'));
});
handle.ondone = () => {
this.#udpSocket.close((err) => {
// If an error occurs while attempting to close, it will take
// precedence over any original error specified on the args
// TODO(@jasnell): Alternatively we might set the original
// error as a property on the new error.
if (err) error = err;

// Capture a copy of the stats as they will no longer be
// available once this function returns.
this.#stats = new BigInt64Array(handle.stats);

if (error) process.nextTick(emit.bind(this, 'error', error));
process.nextTick(emit.bind(this, 'close'));
});
};
handle.waitForPendingCallbacks();
}
}

Expand Down Expand Up @@ -1064,14 +1077,14 @@ class QuicSocket extends EventEmitter {
ref() {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('ref');
this[kHandle].ref();
this.#udpSocket.ref();
return this;
}

unref() {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('unref');
this[kHandle].unref();
this.#udpSocket.unref();
return this;
}

Expand All @@ -1082,11 +1095,16 @@ class QuicSocket extends EventEmitter {
get address() {
const out = {};
if (this.#state !== kSocketDestroyed) {
const err = this[kHandle].getsockname(out);
// If err is returned, socket is not bound.
// Return empty object
if (err)
return {};
try {
return this.#udpSocket.address();
} catch (err) {
if (err.code === 'EBADF') {
// If there is an EBADF error, the socket is not bound.
// Return empty object
return {};
}
throw err;
}
}
return out;
}
Expand Down Expand Up @@ -1114,85 +1132,49 @@ class QuicSocket extends EventEmitter {
setTTL(ttl) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('setTTL');
if (typeof ttl !== 'number')
throw new ERR_INVALID_ARG_TYPE('ttl', 'number', ttl);
if (ttl < 1 || ttl > 255)
throw new ERR_INVALID_ARG_VALUE('ttl', ttl);
const err = this[kHandle].setTTL(ttl);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.setTTL(ttl);
return this;
}

setMulticastTTL(ttl) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('setMulticastTTL');
if (typeof ttl !== 'number')
throw new ERR_INVALID_ARG_TYPE('ttl', 'number', ttl);
if (ttl < 1 || ttl > 255)
throw new ERR_INVALID_ARG_VALUE('ttl', ttl);
const err = this[kHandle].setMulticastTTL(ttl);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.setMulticastTTL(ttl);
return this;
}

setBroadcast(on = true) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('setBroadcast');
if (typeof on !== 'boolean')
throw new ERR_INVALID_ARG_TYPE('on', 'boolean', on);
const err = this[kHandle].setBroadcast(on);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.setBroadcast(on);
return this;
}

setMulticastLoopback(on = true) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('setMulticastLoopback');
if (typeof on !== 'boolean')
throw new ERR_INVALID_ARG_TYPE('on', 'boolean', on);
const err = this[kHandle].setMulticastLoopback(on);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.setMulticastLoopback(on);
return this;
}

setMulticastInterface(iface) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('setMulticastInterface');
if (typeof iface !== 'string')
throw new ERR_INVALID_ARG_TYPE('iface', 'string', iface);
const err = this[kHandle].setMulticastInterface(iface);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.setMulticastInterface(iface);
return this;
}

addMembership(address, iface) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('addMembership');
if (typeof address !== 'string')
throw new ERR_INVALID_ARG_TYPE('address', 'string', address);
if (typeof iface !== 'string')
throw new ERR_INVALID_ARG_TYPE('iface', 'string', iface);
const err = this[kHandle].addMembership(address, iface);
if (err)
throw errnoException(err, 'addMembership');
this.#udpSocket.addMembership(address, iface);
return this;
}

dropMembership(address, iface) {
if (this.#state === kSocketDestroyed)
throw new ERR_QUICSOCKET_DESTROYED('dropMembership');
if (typeof address !== 'string')
throw new ERR_INVALID_ARG_TYPE('address', 'string', address);
if (typeof iface !== 'string')
throw new ERR_INVALID_ARG_TYPE('iface', 'string', iface);
const err = this[kHandle].dropMembership(address, iface);
if (err)
throw errnoException(err, 'dropMembership');
this.#udpSocket.dropMembership(address, iface);
return this;
}

Expand Down
1 change: 1 addition & 0 deletions src/async_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ namespace node {
V(QUERYWRAP) \
V(QUICCLIENTSESSION) \
V(QUICSERVERSESSION) \
V(QUICSENDWRAP) \
V(QUICSOCKET) \
V(QUICSTREAM) \
V(SHUTDOWNWRAP) \
Expand Down
1 change: 0 additions & 1 deletion src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ constexpr size_t kFsStatsBufferLength =
# define QUIC_ENVIRONMENT_STRONG_PERSISTENT_VALUES(V) \
V(quic_on_socket_close_function, v8::Function) \
V(quic_on_socket_error_function, v8::Function) \
V(quic_on_socket_ready_function, v8::Function) \
V(quic_on_socket_server_busy_function, v8::Function) \
V(quic_on_session_cert_function, v8::Function) \
V(quic_on_session_client_hello_function, v8::Function) \
Expand Down
3 changes: 0 additions & 3 deletions src/node_quic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ void QuicSetCallbacks(const FunctionCallbackInfo<Value>& args) {
env->set_quic_on_##callback##_function(fn.As<Function>()); \
} while (0)

SETFUNCTION("onSocketReady", socket_ready);
SETFUNCTION("onSocketClose", socket_close);
SETFUNCTION("onSocketError", socket_error);
SETFUNCTION("onSessionReady", session_ready);
Expand Down Expand Up @@ -164,8 +163,6 @@ void Initialize(Local<Object> target,
NODE_DEFINE_CONSTANT(constants, SSL_OP_SINGLE_ECDH_USE);
NODE_DEFINE_CONSTANT(constants, TLS1_3_VERSION);
NODE_DEFINE_CONSTANT(constants, UV_EBADF);
NODE_DEFINE_CONSTANT(constants, UV_UDP_IPV6ONLY);
NODE_DEFINE_CONSTANT(constants, UV_UDP_REUSEADDR);

NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_ACTIVE_CONNECTION_ID_LIMIT);
NODE_DEFINE_CONSTANT(constants, IDX_QUIC_SESSION_MAX_STREAM_DATA_BIDI_LOCAL);
Expand Down
Loading

0 comments on commit a684292

Please sign in to comment.