72 lines
2.6 KiB
JavaScript
72 lines
2.6 KiB
JavaScript
// WSTS protocol layer — sits between the raw WebSocket and the event pool.
|
|
// Routes incoming frames to either a correlated reply handler (numeric id) or
|
|
// a named signal handler (string id). Outbound frames are encoded by the codec.
|
|
|
|
import { WSTSCodec } from './codec.js';
|
|
|
|
export default class WSTSProtocol {
|
|
constructor(mwse) {
|
|
this.mwse = mwse;
|
|
this.codec = new WSTSCodec();
|
|
this._listen();
|
|
}
|
|
|
|
_listen() {
|
|
this.mwse.server.onRecaivePack(raw => this.PackAnalyze(raw));
|
|
}
|
|
|
|
// ---- Outbound -------------------------------------------------------
|
|
|
|
// SendOnly: fire-and-forget WOM frame — no id, no pending waiter.
|
|
SendOnly(pack) {
|
|
this.mwse.server.tranferToServer(this.codec.encode([pack, 'R']));
|
|
}
|
|
|
|
// SendRequest: request expecting exactly one reply (action 'R' → server replies 'E').
|
|
SendRequest(pack, id) {
|
|
this.mwse.server.tranferToServer(this.codec.encode([pack, id, 'R']));
|
|
}
|
|
|
|
// StartStream: request expecting multiple replies (server replies 'C' until done).
|
|
StartStream(pack, id) {
|
|
this.mwse.server.tranferToServer(this.codec.encode([pack, id, 'S']));
|
|
}
|
|
|
|
// SendRaw: bypass codec (used by internal tooling only).
|
|
SendRaw(pack) {
|
|
this.mwse.server.tranferToServer(JSON.stringify(pack));
|
|
}
|
|
|
|
// ---- Inbound --------------------------------------------------------
|
|
|
|
// PackAnalyze routes one decoded frame to the right listener.
|
|
// raw may be a string (JSON) or an ArrayBuffer (binary, when #42 lands).
|
|
PackAnalyze(raw) {
|
|
const data = this.codec.decode(raw);
|
|
const [payload, id, action] = data;
|
|
|
|
if (typeof id === 'number') {
|
|
// Correlated reply: numeric id maps to a pending request.
|
|
const entry = this.mwse.EventPooling.events.get(id);
|
|
if (entry) {
|
|
entry[0](payload, action);
|
|
if (action === 'E') {
|
|
// 'E'nd — one-shot request fulfilled; remove the waiter.
|
|
this.mwse.EventPooling.events.delete(id);
|
|
}
|
|
// 'C'ontinue — stream replies stay in the map until the server closes.
|
|
} else {
|
|
console.warn('MWSE: reply for unknown request id', id);
|
|
}
|
|
} else {
|
|
// Signal: string id (signal name) fans out to all registered listeners.
|
|
const listeners = this.mwse.EventPooling.signals.get(id);
|
|
if (listeners) {
|
|
for (const cb of listeners) cb(payload);
|
|
} else {
|
|
console.warn('MWSE: unhandled signal', id);
|
|
}
|
|
}
|
|
}
|
|
}
|