You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.0 KiB
66 lines
2.0 KiB
import {
|
|
CONNECTION_DIAGNOSTIC_EVENTS,
|
|
CONNECTION_FRAME_TYPE_PONG
|
|
} from './consts.ts';
|
|
import { emitConnectionDiagnostic, type ConnectionDiagnostics } from './diagnostics.ts';
|
|
import { assertConnectionFrame } from './serializer.ts';
|
|
import type { ConnectionAckRegistry } from './acks.ts';
|
|
import type { ConnectionChannelRegistry } from './channel-registry.ts';
|
|
import type { ConnectionEventBus } from './connection-events.ts';
|
|
import type { ConnectionStateTracker } from './connection-state.ts';
|
|
import type { ConnectionHeartbeat } from './heartbeat.ts';
|
|
import type {
|
|
ConnectionChannelMap,
|
|
ConnectionFrame,
|
|
ConnectionMessageMeta,
|
|
ConnectionSerializer
|
|
} from './types.ts';
|
|
|
|
export interface RouteConnectionMessageInput<TChannels extends ConnectionChannelMap> {
|
|
readonly name: string;
|
|
readonly raw: string | ArrayBuffer;
|
|
readonly serializer: ConnectionSerializer;
|
|
readonly state: ConnectionStateTracker;
|
|
readonly heartbeat: ConnectionHeartbeat;
|
|
readonly acks: ConnectionAckRegistry;
|
|
readonly channels: ConnectionChannelRegistry<TChannels>;
|
|
readonly events: ConnectionEventBus;
|
|
readonly diagnostics: ConnectionDiagnostics;
|
|
}
|
|
|
|
export function routeConnectionMessage<TChannels extends ConnectionChannelMap>(
|
|
input: RouteConnectionMessageInput<TChannels>
|
|
): void {
|
|
const receivedAt = input.state.touchMessage();
|
|
input.heartbeat.received();
|
|
let frame: ConnectionFrame;
|
|
try {
|
|
frame = input.serializer.decode(input.raw);
|
|
assertConnectionFrame(frame);
|
|
} catch (err) {
|
|
input.state.setError(err);
|
|
emitConnectionDiagnostic(input.diagnostics, CONNECTION_DIAGNOSTIC_EVENTS.FRAME_DECODE_FAILED, {
|
|
error: err
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (frame.replyTo !== undefined) {
|
|
input.acks.resolveFromFrame(frame);
|
|
return;
|
|
}
|
|
if (frame.type === CONNECTION_FRAME_TYPE_PONG) return;
|
|
|
|
const meta: ConnectionMessageMeta = {
|
|
connection: input.name,
|
|
topic: frame.topic,
|
|
receivedAt,
|
|
generation: input.state.generation
|
|
};
|
|
|
|
if (frame.topic !== undefined) {
|
|
input.channels.receive(frame.topic, frame, meta);
|
|
}
|
|
input.events.emitGlobal(frame, meta);
|
|
}
|