@aptpod/iscp-ts
Version:
iSCP 2.0 client library for TypeScript
381 lines • 23.3 kB
JavaScript
"use strict";
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Wire_instances, _Wire_requestSequence, _Wire_reader, _Wire_writer, _Wire_unreliableReader, _Wire_unreliableWriter, _Wire_pingTimeout, _Wire_pingInterval, _Wire_logger, _Wire_replyMessageTransformStreamMap, _Wire_replyCallTransformStreamMap, _Wire_abortController, _Wire_cancelledResolver, _Wire_requestPing, _Wire_sendPong, _Wire_sendMessageAndWaitResponse, _Wire_readLoop, _Wire_readUnreliableLoop, _Wire_keepAliveLoop;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Wire = void 0;
const web_streams_polyfill_1 = require("web-streams-polyfill");
const exceptions_1 = require("./exceptions");
const message_1 = require("./message");
const constant_1 = require("./constant");
const ticker_1 = require("./utils/ticker");
const timeout_1 = require("./utils/timeout");
const resolver_1 = require("./utils/resolver");
const signal_abort_listener_1 = require("./utils/signal-abort-listener");
const CANCEL = 'cancel';
class Wire {
constructor(config) {
_Wire_instances.add(this);
_Wire_requestSequence.set(this, void 0);
_Wire_reader.set(this, void 0);
_Wire_writer.set(this, void 0);
_Wire_unreliableReader.set(this, void 0);
_Wire_unreliableWriter.set(this, void 0);
_Wire_pingTimeout.set(this, void 0);
_Wire_pingInterval.set(this, void 0);
_Wire_logger.set(this, void 0);
_Wire_replyMessageTransformStreamMap.set(this, void 0);
_Wire_replyCallTransformStreamMap.set(this, void 0);
_Wire_abortController.set(this, void 0);
_Wire_cancelledResolver.set(this, void 0);
__classPrivateFieldSet(this, _Wire_requestSequence, config.requestSequence, "f");
__classPrivateFieldSet(this, _Wire_reader, config.reader, "f");
__classPrivateFieldSet(this, _Wire_writer, config.writer, "f");
__classPrivateFieldSet(this, _Wire_unreliableReader, config.unreliableReader, "f");
__classPrivateFieldSet(this, _Wire_unreliableWriter, config.unreliableWriter, "f");
__classPrivateFieldSet(this, _Wire_pingInterval, config.pingInterval, "f");
__classPrivateFieldSet(this, _Wire_pingTimeout, config.pingTimeout, "f");
__classPrivateFieldSet(this, _Wire_logger, config.logger, "f");
__classPrivateFieldSet(this, _Wire_replyMessageTransformStreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Wire_replyCallTransformStreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Wire_abortController, new AbortController(), "f");
__classPrivateFieldSet(this, _Wire_cancelledResolver, new resolver_1.Resolver(), "f");
this.onDisconnect = async () => { };
this.onUpstreamChunkAck = async () => { };
this.onDownstreamChunk = async () => { };
this.onDownstreamMetadata = async () => { };
this.onDownstreamChunkAckComplete = async () => { };
this.onDownstreamCall = async () => { };
this.onPingTimeout = async () => { };
this.onError = async () => { };
}
async start() {
await Promise.all([__classPrivateFieldGet(this, _Wire_instances, "m", _Wire_readLoop).call(this), __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_readUnreliableLoop).call(this), __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_keepAliveLoop).call(this)]).finally(() => {
__classPrivateFieldGet(this, _Wire_cancelledResolver, "f").resolve();
});
}
async cancel() {
__classPrivateFieldGet(this, _Wire_abortController, "f").abort();
await __classPrivateFieldGet(this, _Wire_cancelledResolver, "f").wait();
}
async connect(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send ConnectRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.ConnectResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `recv ConnectResponse. [requestId=${response.requestId}]`);
return response;
}
async disconnect(request) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, 'send Disconnect.');
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, request);
}
async openUpstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamOpenRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.UpstreamOpenResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamOpenResponse. [requestId=${response.requestId}]`);
return response;
}
async resumeUpstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamResumeRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.UpstreamResumeResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamResumeResponse. [requestId=${response.requestId}]`);
return response;
}
async closeUpstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamCloseRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.UpstreamCloseResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
// @todo set timeout
timeout: 2,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamCloseResponse. [requestId=${response.requestId}]`);
return response;
}
async sendUpstreamChunk(message) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamChunk.`);
if (__classPrivateFieldGet(this, _Wire_unreliableWriter, "f")) {
await __classPrivateFieldGet(this, _Wire_unreliableWriter, "f").call(this, message);
return;
}
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, message);
}
async upstreamMetadata(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamMetadata. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.UpstreamMetadataAck,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamMetadata. [requestId=${response.requestId}]`);
return response;
}
async openDownstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send DownstreamOpenRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.DownstreamOpenResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamOpenResponse. [requestId=${response.requestId}]`);
return response;
}
async resumeDownstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send DownstreamResumeRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.DownstreamResumeResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamResumeRequest. [requestId=${response.requestId}]`);
return response;
}
async closeDownstream(request) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send DownstreamCloseRequest. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.DownstreamCloseResponse,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
// @todo set timeout
timeout: 2,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamCloseResponse. [requestId=${response.requestId}]`);
return response;
}
async sendDownstreamChunkAck(message) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send DownstreamChunkAck.`);
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, message);
}
async sendDownstreamMetadataAck(message) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send DownstreamMetadataAck.`);
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, message);
}
async sendUpstreamCall(message, timeout) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send UpstreamCall. [callId=${message.callId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message,
expectedResponseClass: message_1.UpstreamCallAck,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyCallTransformStreamMap, "f"),
replayIdGetter: ({ callId }) => callId,
timeout,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamCallAck. [callId=${message.callId}]`);
return response;
}
}
exports.Wire = Wire;
_Wire_requestSequence = new WeakMap(), _Wire_reader = new WeakMap(), _Wire_writer = new WeakMap(), _Wire_unreliableReader = new WeakMap(), _Wire_unreliableWriter = new WeakMap(), _Wire_pingTimeout = new WeakMap(), _Wire_pingInterval = new WeakMap(), _Wire_logger = new WeakMap(), _Wire_replyMessageTransformStreamMap = new WeakMap(), _Wire_replyCallTransformStreamMap = new WeakMap(), _Wire_abortController = new WeakMap(), _Wire_cancelledResolver = new WeakMap(), _Wire_instances = new WeakSet(), _Wire_requestPing =
//
// Private Methods
//
async function _Wire_requestPing(request, timeout) {
request.requestId = __classPrivateFieldGet(this, _Wire_requestSequence, "f").next();
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `send Ping. [requestId=${request.requestId}]`);
const response = await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendMessageAndWaitResponse).call(this, {
message: request,
expectedResponseClass: message_1.Pong,
replayTransformStreamMap: __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f"),
replayIdGetter: ({ requestId }) => requestId,
timeout,
});
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive Pong. [requestId=${response.requestId}]`);
return response;
}, _Wire_sendPong = async function _Wire_sendPong(message) {
try {
__classPrivateFieldGet(this, _Wire_logger, "f").debug(constant_1.LOGGER_TAG.CONN, `send Pong. [requestId=${message.requestId}].`);
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, new message_1.Pong({
requestId: message.requestId,
extensionFields: new message_1.PongExtensionFields(),
}));
}
catch (error) {
__classPrivateFieldGet(this, _Wire_logger, "f").warn(constant_1.LOGGER_TAG.CONN, `failed to send pong[${message.requestId}].`);
}
}, _Wire_sendMessageAndWaitResponse = async function _Wire_sendMessageAndWaitResponse(config) {
const { message, expectedResponseClass, replayTransformStreamMap, replayIdGetter, timeout } = config;
const replayId = replayIdGetter(message);
try {
const replayTransformStream = new web_streams_polyfill_1.TransformStream();
replayTransformStreamMap.set(replayId, replayTransformStream);
await __classPrivateFieldGet(this, _Wire_writer, "f").call(this, message);
const run = replayTransformStream.readable.getReader().read();
const timeout_ = new timeout_1.Timeout();
const response = typeof timeout === 'undefined'
? await run
: await Promise.race([run, timeout_.run(new exceptions_1.ISCPTimeoutError(), timeout * 1e3)]).finally(() => {
timeout_.cancel();
});
if (response instanceof exceptions_1.ISCPTimeoutError) {
throw response;
}
if (response.done) {
throw new exceptions_1.ISCPException('Cancelled');
}
if (!(response.value instanceof expectedResponseClass)) {
throw new exceptions_1.ISCPException();
}
return response.value;
}
finally {
replayTransformStreamMap.delete(replayId);
}
}, _Wire_readLoop = async function _Wire_readLoop() {
const abortSignalListener = new signal_abort_listener_1.AbortSignalListener({
signal: __classPrivateFieldGet(this, _Wire_abortController, "f").signal,
});
for (;;) {
try {
const promiseAbort = abortSignalListener.createPromise(CANCEL);
const message = await Promise.race([__classPrivateFieldGet(this, _Wire_reader, "f").call(this), promiseAbort.resolve()]).finally(() => {
promiseAbort.cancel();
});
if (message === CANCEL) {
break;
}
if (message instanceof message_1.Disconnect) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive Disconnect.`);
await this.onDisconnect(message);
}
if (message instanceof message_1.Ping) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive Ping.`);
await __classPrivateFieldGet(this, _Wire_instances, "m", _Wire_sendPong).call(this, message);
}
if (message instanceof message_1.UpstreamChunkAck) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive UpstreamChunkAck.`);
await this.onUpstreamChunkAck(message);
}
if (message instanceof message_1.DownstreamChunk) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamChunk.`);
await this.onDownstreamChunk(message);
}
if (message instanceof message_1.DownstreamMetadata) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamMetadata.`);
await this.onDownstreamMetadata(message);
}
if (message instanceof message_1.DownstreamChunkAckComplete) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamChunkAckComplete.`);
await this.onDownstreamChunkAckComplete(message);
}
if (message instanceof message_1.UpstreamCallAck) {
const replayCallTransformStream = __classPrivateFieldGet(this, _Wire_replyCallTransformStreamMap, "f").get(message.callId);
const writer = replayCallTransformStream?.writable.getWriter();
await writer?.write(message);
await writer?.close();
}
if (message instanceof message_1.DownstreamCall) {
__classPrivateFieldGet(this, _Wire_logger, "f").info(constant_1.LOGGER_TAG.CONN, `receive DownstreamCall.`);
await this.onDownstreamCall(message);
}
if (message instanceof message_1.RequestMessage) {
const replayMessageTransformStream = __classPrivateFieldGet(this, _Wire_replyMessageTransformStreamMap, "f").get(message.requestId);
const writer = replayMessageTransformStream?.writable.getWriter();
await writer?.write(message);
await writer?.close();
}
}
catch (error) {
if (error instanceof exceptions_1.ISCPTransportClosedError) {
break;
}
throw error;
}
}
}, _Wire_readUnreliableLoop = async function _Wire_readUnreliableLoop() {
if (__classPrivateFieldGet(this, _Wire_unreliableReader, "f")) {
const abortSignalListener = new signal_abort_listener_1.AbortSignalListener({
signal: __classPrivateFieldGet(this, _Wire_abortController, "f").signal,
});
for (;;) {
try {
const promiseAbort = abortSignalListener.createPromise(CANCEL);
const message = await Promise.race([__classPrivateFieldGet(this, _Wire_unreliableReader, "f").call(this), promiseAbort.resolve()]).finally(() => {
promiseAbort.cancel();
});
if (message === CANCEL) {
break;
}
if (message instanceof message_1.DownstreamChunk) {
await this.onDownstreamChunk(message);
}
}
catch (error) {
if (error instanceof exceptions_1.ISCPTransportClosedError) {
break;
}
throw error;
}
}
}
}, _Wire_keepAliveLoop = async function _Wire_keepAliveLoop() {
const abortSignalListener = new signal_abort_listener_1.AbortSignalListener({
signal: __classPrivateFieldGet(this, _Wire_abortController, "f").signal,
});
const ticker = ticker_1.Ticker.of({
delayMs: __classPrivateFieldGet(this, _Wire_pingInterval, "f") * 1e3,
signal: __classPrivateFieldGet(this, _Wire_abortController, "f").signal,
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const _ of ticker) {
try {
const promiseAbort = abortSignalListener.createPromise(CANCEL);
const result = await Promise.race([
__classPrivateFieldGet(this, _Wire_instances, "m", _Wire_requestPing).call(this, new message_1.Ping({
requestId: 0,
extensionFields: new message_1.PingExtensionFields(),
}), __classPrivateFieldGet(this, _Wire_pingTimeout, "f")),
promiseAbort.resolve(),
]).finally(() => {
promiseAbort.cancel();
});
if (result === CANCEL) {
break;
}
}
catch (error) {
if (error instanceof exceptions_1.ISCPTimeoutError) {
__classPrivateFieldGet(this, _Wire_logger, "f").error(constant_1.LOGGER_TAG.CONN, `ping pong timeout. [timeout=${__classPrivateFieldGet(this, _Wire_pingTimeout, "f")}]`);
this.onPingTimeout();
continue;
}
__classPrivateFieldGet(this, _Wire_logger, "f").error(constant_1.LOGGER_TAG.CONN, error);
}
}
};
//# sourceMappingURL=wire.js.map