Skip to content

Commit 47f209e

Browse files
committed
feat: expose more connectionId information
Changes: * Exposed connection destination ID * Created a common ID that is identical for both sides of the connection. Derived from the source and destination ID. * The `quiche` connection is now the Source Of Truth for these IDs. The destinationId is only know after establishing and is only valid while running. * Added test demonstrating the new Ids and how they relate to each other. Related: MatrixAI/Polykey#609 [ci skip]
1 parent 4ae2d24 commit 47f209e

File tree

2 files changed

+100
-8
lines changed

2 files changed

+100
-8
lines changed

src/QUICConnection.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { PromiseCancellable } from '@matrixai/async-cancellable';
22
import type { ContextTimed, ContextTimedInput } from '@matrixai/contexts';
33
import type QUICSocket from './QUICSocket';
4-
import type QUICConnectionId from './QUICConnectionId';
54
import type {
65
Host,
76
Port,
@@ -25,6 +24,7 @@ import {
2524
} from '@matrixai/async-init/dist/StartStop';
2625
import { timedCancellable, context } from '@matrixai/contexts/dist/decorators';
2726
import { buildQuicheConfig, minIdleTimeout } from './config';
27+
import QUICConnectionId from './QUICConnectionId';
2828
import QUICStream from './QUICStream';
2929
import { quiche, ConnectionErrorCode } from './native';
3030
import * as utils from './utils';
@@ -44,11 +44,6 @@ class QUICConnection {
4444
*/
4545
public readonly type: 'client' | 'server';
4646

47-
/**
48-
* This is the source connection ID.
49-
*/
50-
public readonly connectionId: QUICConnectionId;
51-
5247
/**
5348
* Resolves once the connection has closed.
5449
*/
@@ -381,7 +376,6 @@ class QUICConnection {
381376
}
382377
this.type = type;
383378
this.conn = conn!;
384-
this.connectionId = scid;
385379
this.socket = socket;
386380
this.config = config;
387381
if (this.config.cert != null) {
@@ -413,6 +407,37 @@ class QUICConnection {
413407
this.resolveClosedP = resolveClosedP;
414408
}
415409

410+
/**
411+
* This is the source connection ID.
412+
*/
413+
public get connectionId() {
414+
return new QUICConnectionId(this.conn.sourceId());
415+
}
416+
417+
/**
418+
* This is the destination connection ID.
419+
* This is only fully known after establishing the connection
420+
*/
421+
@ready(new errors.ErrorQUICConnectionNotRunning())
422+
public get connectionIdPeer() {
423+
return new QUICConnectionId(this.conn.destinationId());
424+
}
425+
426+
/**
427+
* A common ID between the client and server connection.
428+
* Used to identify connection pairs more easily.
429+
*/
430+
@ready(new errors.ErrorQUICConnectionNotRunning())
431+
public get connectionIdShared() {
432+
const sourceId = this.conn.sourceId();
433+
const destinationId = this.conn.destinationId();
434+
if (Buffer.compare(sourceId, destinationId) <= 0) {
435+
return new QUICConnectionId(Buffer.concat([sourceId, destinationId]));
436+
} else {
437+
return new QUICConnectionId(Buffer.concat([destinationId, sourceId]));
438+
}
439+
}
440+
416441
public get remoteHost(): Host {
417442
return this._remoteHost;
418443
}

tests/QUICClient.test.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1654,7 +1654,7 @@ describe(QUICClient.name, () => {
16541654
await server.stop();
16551655
});
16561656
});
1657-
test('Connections are established and secured quickly', async () => {
1657+
test('connections are established and secured quickly', async () => {
16581658
const tlsConfigServer = await testsUtils.generateTLSConfig(defaultType);
16591659

16601660
const connectionEventProm = promise<events.EventQUICServerConnection>();
@@ -1808,6 +1808,73 @@ describe(QUICClient.name, () => {
18081808
errors.ErrorQUICConnectionIdleTimeout,
18091809
);
18101810

1811+
await client.destroy({ force: true });
1812+
await server.stop({ force: true });
1813+
});
1814+
test('connections share the same id information', async () => {
1815+
const tlsConfigServer = await testsUtils.generateTLSConfig(defaultType);
1816+
1817+
const { p: serverConnectionP, resolveP: serverConnectionResolveP } =
1818+
promise<QUICConnection>();
1819+
const server = new QUICServer({
1820+
crypto: {
1821+
key,
1822+
ops: serverCryptoOps,
1823+
},
1824+
logger: logger.getChild(QUICServer.name),
1825+
config: {
1826+
key: tlsConfigServer.leafKeyPairPEM.privateKey,
1827+
cert: tlsConfigServer.leafCertPEM,
1828+
verifyPeer: false,
1829+
},
1830+
});
1831+
socketCleanMethods.extractSocket(server);
1832+
server.addEventListener(
1833+
events.EventQUICServerConnection.name,
1834+
(evt: events.EventQUICServerConnection) => {
1835+
serverConnectionResolveP(evt.detail);
1836+
},
1837+
);
1838+
await server.start({
1839+
host: localhost,
1840+
});
1841+
// If the server is slow to respond then this will time out.
1842+
// Then main cause of this was the server not processing the initial packet
1843+
// that creates the `QUICConnection`, as a result, the whole creation waited
1844+
// an extra 1 second for the client to retry the initial packet.
1845+
const client = await QUICClient.createQUICClient(
1846+
{
1847+
host: localhost,
1848+
port: server.port,
1849+
localHost: localhost,
1850+
crypto: {
1851+
ops: clientCryptoOps,
1852+
},
1853+
logger: logger.getChild(QUICClient.name),
1854+
config: {
1855+
verifyPeer: false,
1856+
},
1857+
},
1858+
{ timer: 500 },
1859+
);
1860+
socketCleanMethods.extractSocket(client);
1861+
1862+
const clientConn = client.connection;
1863+
const serverConn = await serverConnectionP;
1864+
1865+
expect(
1866+
Buffer.compare(clientConn.connectionId, serverConn.connectionIdPeer),
1867+
).toBe(0);
1868+
expect(
1869+
Buffer.compare(clientConn.connectionIdPeer, serverConn.connectionId),
1870+
).toBe(0);
1871+
expect(
1872+
Buffer.compare(
1873+
clientConn.connectionIdShared,
1874+
serverConn.connectionIdShared,
1875+
),
1876+
).toBe(0);
1877+
18111878
await client.destroy({ force: true });
18121879
await server.stop({ force: true });
18131880
});

0 commit comments

Comments
 (0)