Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 82 additions & 9 deletions src/QUICClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,47 @@ class QUICClient {
// the client, because the client bridges the push flow from the connection
// to the socket.
socket.connectionMap.set(connection.connectionId, connection);
// Set up intermediate abort signal
const abortController = new AbortController();
const abortHandler = () => {
abortController.abort(ctx.signal.reason);
};
if (ctx.signal.aborted) abortController.abort(ctx.signal.reason);
else ctx.signal.addEventListener('abort', abortHandler);
const handleEventQUICClientErrorSend = (
evt: events.EventQUICClientErrorSend,
) => {
// @ts-ignore: the error contains `code` but not part of the type
const code = evt.detail.code;
switch (code) {
// Thrown due to invalid arguments on linux
case 'EINVAL':
// Thrown due to invalid arguments on macOS
// Falls through
case 'EADDRNOTAVAIL':
// Thrown due to invalid arguments on Win but also for network dropouts on all platforms
// Falls through
case 'ENETUNREACH':
{
abortController.abort(
new errors.ErrorQUICClientInvalidArgument(undefined, {
cause: evt.detail,
}),
);
}
break;
default: // Do nothing
}
};
client.addEventListener(
`${events.EventQUICClientErrorSend.name}-${connection.sendId}`,
handleEventQUICClientErrorSend,
);
try {
await connection.start(undefined, ctx);
await connection.start(undefined, {
timer: ctx.timer,
signal: abortController.signal,
});
} catch (e) {
socket.connectionMap.delete(connection.connectionId);
socket.removeEventListener(
Expand Down Expand Up @@ -284,6 +323,12 @@ class QUICClient {
client.handleEventQUICClientClose,
);
throw e;
} finally {
ctx.signal.removeEventListener('abort', abortHandler);
client.removeEventListener(
`${events.EventQUICClientErrorSend.name}-${connection.sendId}`,
handleEventQUICClientErrorSend,
);
}
address = utils.buildAddress(host_, port);
logger.info(`Created ${this.name} to ${address}`);
Expand Down Expand Up @@ -459,14 +504,42 @@ class QUICClient {
evt.detail.address,
);
} catch (e) {
const e_ = new errors.ErrorQUICClientInternal(
'Failed to send data on the QUICSocket',
{
data: evt.detail,
cause: e,
},
);
this.dispatchEvent(new events.EventQUICClientError({ detail: e_ }));
switch (e.code) {
// Thrown due to invalid arguments on linux
case 'EINVAL':
// Thrown due to invalid arguments on macOS
// Falls through
case 'EADDRNOTAVAIL':
// Thrown due to invalid arguments on Win but also for network dropouts on all platforms
// Falls through
case 'ENETUNREACH':
{
this.dispatchEvent(
new events.EventQUICClientErrorSend(
`${events.EventQUICClientErrorSend.name}-${evt.detail.id}`,
{
detail: e,
},
),
);
}
break;
default:
{
this.dispatchEvent(
new events.EventQUICClientError({
detail: new errors.ErrorQUICClientInternal(
'Failed to send data on the QUICSocket',
{
data: evt.detail,
cause: e,
},
),
}),
);
}
break;
}
}
};

Expand Down
7 changes: 7 additions & 0 deletions src/QUICConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ class QUICConnection {
*/
public readonly streamMap: Map<StreamId, QUICStream> = new Map();

/**
* Unique id used to identify events intended for this connection.
*/
public readonly sendId: string;

protected logger: Logger;
protected socket: QUICSocket;
protected config: QUICConfig;
Expand Down Expand Up @@ -322,6 +327,7 @@ class QUICConnection {
logger?: Logger;
}) {
this.logger = logger ?? new Logger(`${this.constructor.name} ${scid}`);
this.sendId = scid.toString();
if (
config.keepAliveIntervalTime != null &&
config.maxIdleTimeout !== 0 &&
Expand Down Expand Up @@ -876,6 +882,7 @@ class QUICConnection {
this.dispatchEvent(
new events.EventQUICConnectionSend({
detail: {
id: this.sendId,
msg: sendBuffer.subarray(0, sendLength),
port: sendInfo.to.port,
address: sendInfo.to.host,
Expand Down
44 changes: 36 additions & 8 deletions src/QUICServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,42 @@ class QUICServer {
evt.detail.address,
);
} catch (e) {
const e_ = new errors.ErrorQUICServerInternal(
'Failed to send data on the QUICSocket',
{
data: evt.detail,
cause: e,
},
);
this.dispatchEvent(new events.EventQUICServerError({ detail: e_ }));
switch (e.code) {
// Thrown due to invalid arguments on linux
case 'EINVAL':
// Thrown due to invalid arguments on macOS
// Falls through
case 'EADDRNOTAVAIL':
// Thrown due to invalid arguments on Win but also for network dropouts on all platforms
// Falls through
case 'ENETUNREACH':
{
this.dispatchEvent(
new events.EventQUICClientErrorSend(
`${events.EventQUICClientErrorSend.name}-${evt.detail.id}`,
{
detail: e,
},
),
);
}
break;
default:
{
this.dispatchEvent(
new events.EventQUICServerError({
detail: new errors.ErrorQUICServerInternal(
'Failed to send data on the QUICSocket',
{
data: evt.detail,
cause: e,
},
),
}),
);
}
break;
}
}
};

Expand Down
6 changes: 6 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ class ErrorQUICClientSocketNotRunning<T> extends ErrorQUICClient<T> {
'QUIC Client cannot be created with an unstarted shared QUIC socket';
}

class ErrorQUICClientInvalidArgument<T> extends ErrorQUICClient<T> {
static description =
'QUIC Client had a failure relating to an invalid argument';
}

class ErrorQUICClientInvalidHost<T> extends ErrorQUICClient<T> {
static description = 'QUIC Client cannot be created with the specified host';
}
Expand Down Expand Up @@ -293,6 +298,7 @@ export {
ErrorQUICClientDestroyed,
ErrorQUICClientCreateTimeout,
ErrorQUICClientSocketNotRunning,
ErrorQUICClientInvalidArgument,
ErrorQUICClientInvalidHost,
ErrorQUICClientInternal,
ErrorQUICServer,
Expand Down
4 changes: 4 additions & 0 deletions src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class EventQUICClientError extends EventQUICClient<
| ErrorQUICConnectionInternal<unknown>
> {}

class EventQUICClientErrorSend extends EventQUICSocket<Error> {}

class EventQUICClientClose extends EventQUICClient<
| ErrorQUICClientSocketNotRunning<unknown>
| ErrorQUICConnectionLocal<unknown>
Expand Down Expand Up @@ -126,6 +128,7 @@ class EventQUICConnectionClose extends EventQUICConnection<
class EventQUICConnectionStream extends EventQUICConnection<QUICStream> {}

class EventQUICConnectionSend extends EventQUICConnection<{
id: string;
msg: Uint8Array;
port: number;
address: string;
Expand Down Expand Up @@ -193,6 +196,7 @@ export {
EventQUICClientDestroy,
EventQUICClientDestroyed,
EventQUICClientError,
EventQUICClientErrorSend,
EventQUICClientClose,
EventQUICServer,
EventQUICServerStart,
Expand Down
Loading