UNPKG

p2p-media-loader-core

Version:
151 lines 5.31 kB
import * as Utils from "../utils/utils.js"; import * as Command from "./commands/index.js"; export class PeerProtocol { constructor(connection, peerConfig, eventHandlers, eventTarget) { Object.defineProperty(this, "connection", { enumerable: true, configurable: true, writable: true, value: connection }); Object.defineProperty(this, "peerConfig", { enumerable: true, configurable: true, writable: true, value: peerConfig }); Object.defineProperty(this, "eventHandlers", { enumerable: true, configurable: true, writable: true, value: eventHandlers }); Object.defineProperty(this, "commandChunks", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "uploadingContext", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "onChunkDownloaded", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "onChunkUploaded", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "onDataReceived", { enumerable: true, configurable: true, writable: true, value: (data) => { if (Command.isCommandChunk(data)) { this.receivingCommandBytes(data); } else { this.eventHandlers.onSegmentChunkReceived(data); this.onChunkDownloaded(data.byteLength, "p2p", this.connection.idUtf8); } } }); this.onChunkDownloaded = eventTarget.getEventDispatcher("onChunkDownloaded"); this.onChunkUploaded = eventTarget.getEventDispatcher("onChunkUploaded"); connection.on("data", this.onDataReceived); } sendCommand(command) { const binaryCommandBuffers = Command.serializePeerCommand(command, this.peerConfig.webRtcMaxMessageSize); for (const buffer of binaryCommandBuffers) { this.connection.write(buffer); } } stopUploadingSegmentData() { this.uploadingContext?.stopUploading(); this.uploadingContext = undefined; } getUploadingRequestId() { return this.uploadingContext?.requestId; } async splitSegmentDataToChunksAndUploadAsync(data, requestId) { if (this.uploadingContext) { throw new Error(`Some segment data is already uploading.`); } const chunks = getBufferChunks(data, this.peerConfig.webRtcMaxMessageSize); const { promise, resolve, reject } = Utils.getControlledPromise(); let isUploadingSegmentData = false; const uploadingContext = { stopUploading: () => { isUploadingSegmentData = false; }, requestId, }; this.uploadingContext = uploadingContext; const sendChunk = () => { if (!isUploadingSegmentData) { reject(); return; } while (true) { const chunk = chunks.next().value; if (!chunk) { resolve(); break; } const drained = this.connection.write(chunk); this.onChunkUploaded(chunk.byteLength, this.connection.idUtf8); if (!drained) break; } }; try { this.connection.on("drain", sendChunk); isUploadingSegmentData = true; sendChunk(); await promise; } finally { this.connection.off("drain", sendChunk); if (this.uploadingContext === uploadingContext) { this.uploadingContext = undefined; } } } receivingCommandBytes(buffer) { if (!this.commandChunks) { this.commandChunks = new Command.BinaryCommandChunksJoiner((commandBuffer) => { this.commandChunks = undefined; const command = Command.deserializeCommand(commandBuffer); this.eventHandlers.onCommandReceived(command); }); } try { this.commandChunks.addCommandChunk(buffer); } catch (err) { if (!(err instanceof Command.BinaryCommandJoiningError)) return; this.commandChunks = undefined; } } } function* getBufferChunks(data, maxChunkSize) { let bytesLeft = data.byteLength; while (bytesLeft > 0) { const bytesToSend = bytesLeft >= maxChunkSize ? maxChunkSize : bytesLeft; const from = data.byteLength - bytesLeft; const buffer = data.slice(from, from + bytesToSend); bytesLeft -= bytesToSend; yield buffer; } } //# sourceMappingURL=peer-protocol.js.map