UNPKG

@skyway-sdk/core

Version:

The official Next Generation JavaScript SDK for SkyWay

131 lines 4.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteDataStream = exports.remoteDataStreamMessageBufferMaxSize = void 0; const common_1 = require("@skyway-sdk/common"); const util_1 = require("../../../util"); const data_1 = require("../local/data"); const base_1 = require("./base"); const log = new common_1.Logger('packages/core/src/media/stream/remote/data.ts'); const textEncoder = new TextEncoder(); /**@internal */ exports.remoteDataStreamMessageBufferMaxSize = 10 * 1024 * 1024; class RemoteDataStream extends base_1.RemoteStreamBase { /**@internal */ constructor(id, /**@internal */ _datachannel) { super(id, 'data'); this._datachannel = _datachannel; this._isEnabled = true; this._bufferingUntilFirstListener = true; this._bufferedMessages = []; this._bufferedMessageSize = 0; this._hasWarnedBufferOverflow = false; this.contentType = 'data'; this.onData = new common_1.Event(() => { this._queueFlushBufferedMessages(); }); _datachannel.onmessage = ({ data }) => { if (!this._isEnabled) { return; } const parsed = this._parseMessage(data); if (this._bufferingUntilFirstListener) { this._bufferIncomingMessage(parsed); return; } this.onData.emit(parsed); }; _datachannel.onclose = () => { this._clearBufferedMessages(); }; } /**@internal */ setIsEnabled(b) { this._isEnabled = b; if (!b) { // Streamが無効化された場合はバッファリングしているデータを破棄する this._clearBufferedMessages(); } } _parseMessage(data) { if (typeof data === 'string' && data.startsWith(data_1.objectFlag)) { try { return JSON.parse(data.slice(data_1.objectFlag.length)); } catch (_a) { return data; } } return data; } _bufferIncomingMessage(data) { const size = this._estimateMessageSize(data); if (this._bufferedMessageSize + size > exports.remoteDataStreamMessageBufferMaxSize) { if (!this._hasWarnedBufferOverflow) { log.warn((0, util_1.createWarnPayload)({ operationName: 'RemoteDataStream._bufferIncomingMessage', detail: 'remote data stream receive buffer overflowed before onData listener was set; dropping newly received data', payload: { streamId: this.id, bufferSize: this._bufferedMessageSize, incomingDataSize: size, maxBufferSize: exports.remoteDataStreamMessageBufferMaxSize, }, })); this._hasWarnedBufferOverflow = true; } return; } this._bufferedMessages.push(data); this._bufferedMessageSize += size; } _flushBufferedMessages() { if (!this._bufferingUntilFirstListener || this.onData.length === 0) { return; } this._bufferingUntilFirstListener = false; const bufferedMessages = this._bufferedMessages; this._bufferedMessages = []; this._bufferedMessageSize = 0; this._hasWarnedBufferOverflow = false; // 無効なStreamのデータはユーザに渡さない if (!this._isEnabled) { return; } bufferedMessages.forEach((data) => { this.onData.emit(data); }); } _clearBufferedMessages() { this._bufferedMessages = []; this._bufferedMessageSize = 0; this._hasWarnedBufferOverflow = false; } _estimateMessageSize(data) { if (typeof data === 'string') { return textEncoder.encode(data).byteLength; } if (data instanceof Blob) { return data.size; } if (data instanceof ArrayBuffer) { return data.byteLength; } if (ArrayBuffer.isView(data)) { return data.byteLength; } return textEncoder.encode(JSON.stringify(data)).byteLength; } _queueFlushBufferedMessages() { if (!this._bufferingUntilFirstListener || this.onData.length === 0) { return; } queueMicrotask(() => { this._flushBufferedMessages(); }); } } exports.RemoteDataStream = RemoteDataStream; //# sourceMappingURL=data.js.map