UNPKG

npaw-plugin-nwf

Version:
261 lines (260 loc) 9.1 kB
import { VideoSegment } from '../Storage/VideoSegment'; import Emitter from '../Utils/Emitter'; import P2PLoader from './../Loaders/P2PLoader'; import * as peer from 'simple-peer'; /** * @class * @description Peer class, abstraction of all the logic that contains one unique peer used by the p2p client * @extends Emitter * @exports Peer */ export default class Peer extends Emitter { id: string; private _peer; /** * V2 protocol: remote peer's cache indexed by segmentId. Replaces the flat * `string[]` map of v1. Insertion order matters for LRU-style eviction when * the peer reports its declared storageSize. Parity with iOS/Android * `remoteSegments`. */ private _remoteSegments; private _activeDownloads; private _lastResponses; private _lastSent; private _decoder; private _identifierShort; private _downloaded; private _totalDownloaded; private _totalDownloadedBytes; private _totalDownloadTime; consecutiveHaveSegment: number; timeouts: number; downloadingProcessActive: boolean; private _version; private _totalSendBytes; private _totalSendTime; private _totalSendSegments; private _loader; private _lastLatencyP2P; private _lastLatencySegment; private _lastBandwith; /** EMA of per-peer transfer speed in bytes/sec. -1 means no data yet. Parity with iOS/Android. */ private _avgBytesPerSecond; private _transferSamples; private _answer; private _ip; private _segmendDataMessages; private _lastSegmendDataMessagesTime; private _destroyed; foreSegmentsInfo: boolean; isAhead: boolean; isBehind: boolean; timeGap: number; private _operationId; getIceAnswer(): any; totalErrors: number; private _cancel; private testLatencyDone; private testBandwidthDone; private testLatencyResult; private testBandwidthResult; getTotalSendBytes(): number; getTotalSendTime(): number; getTotalSendSegments(): number; getDownloadedBytes(): number; getDownloadedChunks(): number; getDownloadBandwidth(): number; getLastLatencyP2P(): number; getLastLatencySegment(): number; getLastBandwith(): number; getIp(): any; getLastResponses(): responseStorageObject[]; /** * Constructs peer. * @param {peer} peer Peer data. */ constructor(loader: P2PLoader, peer: peer, answer: any); getVersion(): number; /** * Returns if the peer is currently managing an active download. * @returns {boolean} If the peer is on an active download. * @public */ isDownloading(): boolean; getSegmentDataMessages(): number; getLastSegmentDataMessagesTime(): number; addTimeout(): void; decayTimeout(): void; /** * Returns whether the remote peer currently has the segment usable for serving. * Matches iOS/Android v2 filter: READY always, ACQUIRING only while its lease is * still valid. Anything else (FAILED, EVICTED, UNKNOWN) is considered absent. */ hasSegment(segmentId: string): boolean; /** * Returns the raw remote state for a segment, or undefined if absent. * Useful for leader-election decisions (PRIMARY/BACKUP/NONE). */ remoteSegmentState(segmentId: string): RemoteSegmentState | undefined; /** * Applies an incoming SEGMENT_STATE message to the peer's remote cache mirror. * `leaseMs` is relative (ms-from-now); we store the absolute expiry timestamp. */ updateSegmentState(segmentId: string, state: string, role: string, leaseMs?: number): void; /** * Clears all tracked remote segments. Called on peer disconnect and on * swarm switch (parity with iOS `resetRemoteKeys`). */ resetRemoteKeys(): void; /** * Records a completed P2P transfer from this peer and updates the EMA of * per-peer bandwidth. Parity with iOS `Peer.recordTransferSpeed`. */ recordTransferSpeed(bytes: number, elapsedMs: number): void; /** True once we have enough samples to trust `getAvgBytesPerSecond`. */ hasSpeedData(): boolean; getAvgBytesPerSecond(): number; /** * Sends a SEGMENT_STATE announcement to this peer. Used by the local CDN * capture path to pre-announce an ACQUIRING segment (early announcement), * and later to confirm READY / FAILED. Parity with Android `sendSegmentState`. */ sendSegmentState(segmentId: string, state: string, role: string, leaseMs?: number): Promise<void>; /** * Destroys this peer, uses the same code executed on close peer event. * @public */ destroy(): void; /** * Callback for peer connect event, saves the address and notifies it. * @private */ private _onConnect; /** * Callback for peer error event, checks if we need to close it. * @private */ private _onError; /** * Callback for peer close event, fails the requests. * @private */ private _onClose; /** * Reset values of the download to allow more requests. * @private */ private _endDownload; /** * Callback method for peers response. * @param {ArrayBuffer} data Message received from the peer. * @private */ private _onData; /** * Requests a video segment with its id. * @param {string} id Id of the segment to request. * @public */ request(id: string, firstByteTimeoutMs?: number): void; /** * @public */ ping(id: string): void; /** * @public */ pong(id: string, time: number): void; /** * Cancel a video segment request with its id. * @param {string} id Id of the segment to cancel. * @public */ private _cancelRequest; /** * Sends the segment map object. * @param {map} map Segment map object. * @public */ sendMap(map: map): Promise<void>; /** * Given a segment and its id, sends it to the peer split in messages if needed. * @param {string} id Id of the segment. * @param {VideoSegment} segment The segment to send itself. * @param {number} identifier Identifier of the message. * @public */ sendSegment(id: string, segment: VideoSegment, operationId: number): Promise<void>; private getByteArrayFromIdentifier; private getIdentifierFromByteArray; /** * V2 upload path: same wire format as `sendSegment` but accepts a raw * byte array instead of a VideoSegment. Used to serve READY payloads that * live in the DiskSegmentStore rather than the legacy SegmentStorage. */ sendRawSegment(id: string, bytes: Uint8Array, operationId: number): Promise<void>; /** * Sends a message of no segment available to the peer. * @param {string} id Id of the segment. * @public */ sendNoSegment(id: string, operationId: number): void; /** * Sends the segment map object. * @param {map} map Segment map object. * @public */ sendNewSegmentAvailable(segmentId: string, size: number, storageSize: number, createdAt: number): Promise<void>; /** * Sends the given object to the peer. * @param {peerMessage} msg Message to send. * @param {number} id ID number to send in first bytes of the message. * @private */ private _send; /** * Returns the IDs of segments that this remote peer currently has available to serve. * Filters the full remote-state map through the same rule as `hasSegment` so legacy * callers that do `getSegmentMap().indexOf(id) >= 0` keep working against v2 state. * @public */ getSegmentMap(): map; /** * Total count of tracked remote segments (includes states not visible via * `getSegmentMap()`, used for storage-size trimming parity with iOS/Android). */ getRemoteSegmentsSize(): number; /** * Starts the peer timeout for the download. * @param {string} id Id of the peer. * @private */ private _startTimeout; /** * Returns the timestamp of the oldest request stored in the lastResponses object, or 0 if is empty. * @returns {number} Timestamp of the oldest stored request. * @public */ getOldestRequestTS(): number; /** * Returns the bytes downloaded/uploaded from the Peer the last -defined- seconds. * Definition in constants: StatsSettings.totalDataInterval * @returns {number} Bytes downloaded. * @private */ private static _getLastSecondsTraffic; /** * Returns the bytes downloaded from the peers the last -defined- seconds. 60 By default. * Definition in constants: StatsSettings.totalDataInterval * @returns {number} Bytes downloaded. * @public */ getLastDownloadsTraffic(): number; /** * Returns the bytes uploaded from the peers the last -defined- seconds. 60 By default. * Definition in constants: StatsSettings.totalDataInterval * @returns {number} Bytes downloaded. * @public */ getLastUploadsTraffic(): number; }