@chainsafe/libp2p-quic
Version:
A QUIC transport for libp2p
98 lines • 3.64 kB
JavaScript
import { privateKeyToProtobuf } from '@libp2p/crypto/keys';
import { AbortError, serviceCapabilities, transportSymbol } from '@libp2p/interface';
import { QuicConnection } from './connection.js';
import { dialFilter, listenFilter } from './filter.js';
import { QuicListener } from './listener.js';
import * as napi from './napi.js';
import { QuicStreamMuxerFactory } from './stream-muxer.js';
export class QuicTransport {
[Symbol.toStringTag] = 'quic';
[transportSymbol] = true;
[serviceCapabilities] = [
'@libp2p/transport'
];
log;
components;
metrics;
#config;
#clients;
listenFilter;
dialFilter;
constructor(components, options) {
const privateKeyProto = privateKeyToProtobuf(components.privateKey);
const config = { ...options, privateKeyProto };
this.log = components.logger.forComponent('libp2p:quic:transport');
this.components = components;
this.#config = new napi.QuinnConfig(config);
this.#clients = {
ip4: new napi.Client(this.#config, 0),
ip6: new napi.Client(this.#config, 1)
};
this.metrics = {
events: this.components.metrics?.registerCounterGroup('libp2p_quic_dialer_events_total', {
label: 'event',
help: 'Total count of QUIC dialer events by type'
}),
errors: this.components.metrics?.registerCounterGroup('libp2p_quic_dialer_errors_total', {
label: 'event',
help: 'Total count of QUIC dialer errors by type'
})
};
this.listenFilter = listenFilter;
this.dialFilter = dialFilter;
this.log('new');
}
async dial(ma, options) {
if (options.signal?.aborted) {
throw new AbortError();
}
this.log('dialing', ma.toString());
const addr = ma.nodeAddress();
const dialer = addr.family === 4 ? this.#clients.ip4 : this.#clients.ip6;
const dialPromise = dialer.outboundConnection(addr.address, addr.port);
dialPromise
.then(() => this.metrics.events?.increment({ connect: true }))
.catch(() => this.metrics.events?.increment({ error: true }));
const connection = await dialPromise;
let maConn;
try {
maConn = new QuicConnection({
connection,
logger: this.components.logger,
direction: 'outbound',
metrics: this.metrics?.events
});
}
catch (err) {
this.metrics.errors?.increment({ outbound_to_connection: true });
throw err;
}
try {
this.log('new outbound connection %a', maConn.remoteAddr);
return await options.upgrader.upgradeOutbound(maConn, {
skipEncryption: true,
skipProtection: true,
muxerFactory: new QuicStreamMuxerFactory({
connection,
logger: this.components.logger
}),
signal: options.signal
});
}
catch (err) {
this.metrics.errors?.increment({ outbound_upgrade: true });
this.log.error('error upgrading outbound connection - %e', err);
maConn.abort(err);
throw err;
}
}
createListener(options) {
return new QuicListener({
options,
config: this.#config,
logger: this.components.logger,
metrics: this.components.metrics
});
}
}
//# sourceMappingURL=transport.js.map