Skip to content

Commit 55a5ec1

Browse files
authored
Merge pull request #73 from MatrixAI/feature-ID-and-logging-fix
feat: expose more `connectionId` information and update error logging levels
2 parents 4ae2d24 + e4fe848 commit 55a5ec1

File tree

10 files changed

+129
-44
lines changed

10 files changed

+129
-44
lines changed

src/QUICClient.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -315,19 +315,8 @@ class QUICClient {
315315
*/
316316
protected handleEventQUICClientError = (evt: events.EventQUICClientError) => {
317317
const error = evt.detail;
318-
if (
319-
(error instanceof errors.ErrorQUICConnectionLocal ||
320-
error instanceof errors.ErrorQUICConnectionPeer) &&
321-
((!error.data.isApp &&
322-
error.data.errorCode === ConnectionErrorCode.NoError) ||
323-
(error.data.isApp && error.data.errorCode === 0))
324-
) {
325-
// Log out the excpetion as an info when it is graceful
326-
this.logger.info(utils.formatError(error));
327-
} else {
328-
// Log out the exception as an error when it is not graceful
329-
this.logger.error(utils.formatError(error));
330-
}
318+
// Log out the error
319+
this.logger.info(utils.formatError(error));
331320
if (
332321
error instanceof errors.ErrorQUICClientInternal ||
333322
error instanceof errors.ErrorQUICConnectionInternal

src/QUICConnection.ts

Lines changed: 46 additions & 20 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
*/
@@ -186,19 +181,8 @@ class QUICConnection {
186181
) => {
187182
const error = evt.detail;
188183
this.errorLast = error;
189-
if (
190-
(error instanceof errors.ErrorQUICConnectionLocal ||
191-
error instanceof errors.ErrorQUICConnectionPeer) &&
192-
((!error.data.isApp &&
193-
error.data.errorCode === ConnectionErrorCode.NoError) ||
194-
(error.data.isApp && error.data.errorCode === 0))
195-
) {
196-
// Log out the excpetion as an info when it is graceful
197-
this.logger.info(utils.formatError(error));
198-
} else {
199-
// Log out the exception as an error when it is not graceful
200-
this.logger.error(utils.formatError(error));
201-
}
184+
// Log out error for debugging
185+
this.logger.info(utils.formatError(error));
202186
if (error instanceof errors.ErrorQUICConnectionInternal) {
203187
throw error;
204188
}
@@ -381,7 +365,6 @@ class QUICConnection {
381365
}
382366
this.type = type;
383367
this.conn = conn!;
384-
this.connectionId = scid;
385368
this.socket = socket;
386369
this.config = config;
387370
if (this.config.cert != null) {
@@ -413,6 +396,49 @@ class QUICConnection {
413396
this.resolveClosedP = resolveClosedP;
414397
}
415398

399+
/**
400+
* This is the source connection ID.
401+
*/
402+
public get connectionId() {
403+
const sourceId = this.conn.sourceId();
404+
// Zero copy construction of QUICConnectionId
405+
return new QUICConnectionId(
406+
sourceId.buffer,
407+
sourceId.byteOffset,
408+
sourceId.byteLength,
409+
);
410+
}
411+
412+
/**
413+
* This is the destination connection ID.
414+
* This is only fully known after establishing the connection
415+
*/
416+
@ready(new errors.ErrorQUICConnectionNotRunning())
417+
public get connectionIdPeer() {
418+
const destinationId = this.conn.destinationId();
419+
// Zero copy construction of QUICConnectionId
420+
return new QUICConnectionId(
421+
destinationId.buffer,
422+
destinationId.byteOffset,
423+
destinationId.byteLength,
424+
);
425+
}
426+
427+
/**
428+
* A common ID between the client and server connection.
429+
* Used to identify connection pairs more easily.
430+
*/
431+
@ready(new errors.ErrorQUICConnectionNotRunning())
432+
public get connectionIdShared() {
433+
const sourceId = this.conn.sourceId();
434+
const destinationId = this.conn.destinationId();
435+
if (Buffer.compare(sourceId, destinationId) <= 0) {
436+
return new QUICConnectionId(Buffer.concat([sourceId, destinationId]));
437+
} else {
438+
return new QUICConnectionId(Buffer.concat([destinationId, sourceId]));
439+
}
440+
}
441+
416442
public get remoteHost(): Host {
417443
return this._remoteHost;
418444
}

src/QUICServer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class QUICServer {
7272
*/
7373
protected handleEventQUICServerError = (evt: events.EventQUICServerError) => {
7474
const error = evt.detail;
75-
this.logger.error(utils.formatError(error));
75+
// Log out error for debugging
76+
this.logger.info(utils.formatError(error));
7677
if (error instanceof errors.ErrorQUICServerInternal) {
7778
throw error;
7879
}

src/QUICSocket.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ class QUICSocket {
5656

5757
protected handleEventQUICSocketError = (evt: events.EventQUICSocketError) => {
5858
const error = evt.detail;
59-
this.logger.error(utils.formatError(error));
59+
// Log out error for debugging
60+
this.logger.debug(utils.formatError(error));
6061
};
6162

6263
protected handleEventQUICSocketClose = async () => {

src/QUICStream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ class QUICStream implements ReadableWritablePair<Uint8Array, Uint8Array> {
150150
protected handleEventQUICStreamError = (evt: events.EventQUICStreamError) => {
151151
const error = evt.detail;
152152
if (error instanceof errors.ErrorQUICStreamInternal) {
153-
this.logger.error(utils.formatError(error));
153+
// Log out error for debugging
154+
this.logger.debug(utils.formatError(error));
154155
throw error;
155156
}
156157
if (

tests/QUICClient.test.ts

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import * as testsUtils from './utils';
1515
import { generateTLSConfig, sleep } from './utils';
1616

1717
describe(QUICClient.name, () => {
18-
const logger = new Logger(`${QUICClient.name} Test`, LogLevel.SILENT, [
18+
const logger = new Logger(`${QUICClient.name} Test`, LogLevel.WARN, [
1919
new StreamHandler(
2020
formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`,
2121
),
@@ -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
});

tests/QUICServer.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as errors from '@/errors';
1010
import * as testsUtils from './utils';
1111

1212
describe(QUICServer.name, () => {
13-
const logger = new Logger(`${QUICServer.name} Test`, LogLevel.SILENT, [
13+
const logger = new Logger(`${QUICServer.name} Test`, LogLevel.WARN, [
1414
new StreamHandler(
1515
formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`,
1616
),

tests/QUICSocket.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import * as events from '@/events';
1313
import * as testsUtils from './utils';
1414

1515
describe(QUICSocket.name, () => {
16-
const logger = new Logger(`${QUICSocket.name} Test`, LogLevel.SILENT, [
16+
const logger = new Logger(`${QUICSocket.name} Test`, LogLevel.WARN, [
1717
new StreamHandler(),
1818
]);
1919
// This has to be setup asynchronously due to key generation
@@ -296,7 +296,7 @@ describe(QUICSocket.name, () => {
296296
test('error and close event lifecycle', async () => {
297297
// We expect error logs
298298
const socketLogger = logger.getChild('abc');
299-
socketLogger.setLevel(LogLevel.SILENT);
299+
socketLogger.setLevel(LogLevel.WARN);
300300
const socket = new QUICSocket({
301301
logger: socketLogger,
302302
});
@@ -865,7 +865,7 @@ describe(QUICSocket.name, () => {
865865
};
866866
// We expect lots of error logs
867867
const socketLogger = logger.getChild('abc');
868-
socketLogger.setLevel(LogLevel.SILENT);
868+
socketLogger.setLevel(LogLevel.WARN);
869869
const socket = new QUICSocket({
870870
logger: socketLogger,
871871
});

tests/QUICStream.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as testsUtils from './utils';
1010
import { generateTLSConfig } from './utils';
1111

1212
describe(QUICStream.name, () => {
13-
const logger = new Logger(`${QUICStream.name} Test`, LogLevel.SILENT, [
13+
const logger = new Logger(`${QUICStream.name} Test`, LogLevel.WARN, [
1414
new StreamHandler(
1515
formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`,
1616
),

tests/concurrency.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { generateTLSConfig, handleStreamProm, sleep } from './utils';
1212
import * as testsUtils from './utils';
1313

1414
describe('Concurrency tests', () => {
15-
const logger = new Logger(`${QUICClient.name} Test`, LogLevel.SILENT, [
15+
const logger = new Logger(`${QUICClient.name} Test`, LogLevel.WARN, [
1616
new StreamHandler(
1717
formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`,
1818
),

0 commit comments

Comments
 (0)