Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

p2p-media-loader-core

Package Overview
Dependencies
Maintainers
2
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

p2p-media-loader-core - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

6

dist/browser-init-webpack.js
/**
* @license
* Copyright 2018 Novage LLC.

@@ -18,3 +17,5 @@ *

import * as p2pMediaLoaderCore from './index';
import * as p2pMediaLoaderCore from "./index";
import * as debug from "debug";
import * as events from "events";

@@ -26,1 +27,2 @@ if (!window.p2pml) {

window.p2pml.core = p2pMediaLoaderCore;
window.p2pml._shared = {debug, events};
/**
* @license
* Copyright 2018 Novage LLC.

@@ -4,0 +3,0 @@ *

@@ -17,28 +17,12 @@ "use strict";

*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Debug = require("debug");
var stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
var HttpMediaManager = /** @class */ (function (_super) {
__extends(HttpMediaManager, _super);
function HttpMediaManager() {
var _this = _super.call(this) || this;
_this.xhrRequests = new Map();
_this.debug = Debug("p2pml:http-media-manager");
return _this;
const Debug = require("debug");
const stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
class HttpMediaManager extends stringly_typed_event_emitter_1.default {
constructor() {
super();
this.xhrRequests = new Map();
this.debug = Debug("p2pml:http-media-manager");
}
HttpMediaManager.prototype.download = function (segment) {
var _this = this;
download(segment) {
if (this.isDownloading(segment)) {

@@ -48,3 +32,3 @@ return;

this.debug("http segment download", segment.url);
var request = new XMLHttpRequest();
const request = new XMLHttpRequest();
request.open("GET", segment.url, true);

@@ -55,27 +39,27 @@ request.responseType = "arraybuffer";

}
var prevBytesLoaded = 0;
request.onprogress = function (event) {
var bytesLoaded = event.loaded - prevBytesLoaded;
_this.emit("bytes-downloaded", bytesLoaded);
let prevBytesLoaded = 0;
request.onprogress = (event) => {
const bytesLoaded = event.loaded - prevBytesLoaded;
this.emit("bytes-downloaded", bytesLoaded);
prevBytesLoaded = event.loaded;
};
request.onload = function (event) {
_this.xhrRequests.delete(segment.id);
request.onload = (event) => {
this.xhrRequests.delete(segment.id);
if (event.target.status >= 200 && 300 > event.target.status) {
_this.emit("segment-loaded", segment, event.target.response);
this.emit("segment-loaded", segment, event.target.response);
}
else {
_this.emit("segment-error", segment, event);
this.emit("segment-error", segment, event);
}
};
request.onerror = function (event) {
request.onerror = (event) => {
// TODO: retry with timeout?
_this.xhrRequests.delete(segment.id);
_this.emit("segment-error", segment, event);
this.xhrRequests.delete(segment.id);
this.emit("segment-error", segment, event);
};
this.xhrRequests.set(segment.id, request);
request.send();
};
HttpMediaManager.prototype.abort = function (segment) {
var xhr = this.xhrRequests.get(segment.id);
}
abort(segment) {
const xhr = this.xhrRequests.get(segment.id);
if (xhr) {

@@ -86,15 +70,14 @@ xhr.abort();

}
};
HttpMediaManager.prototype.isDownloading = function (segment) {
}
isDownloading(segment) {
return this.xhrRequests.has(segment.id);
};
HttpMediaManager.prototype.getActiveDownloads = function () {
}
getActiveDownloads() {
return this.xhrRequests;
};
HttpMediaManager.prototype.destroy = function () {
this.xhrRequests.forEach(function (xhr) { return xhr.abort(); });
}
destroy() {
this.xhrRequests.forEach(xhr => xhr.abort());
this.xhrRequests.clear();
};
return HttpMediaManager;
}(stringly_typed_event_emitter_1.default)); // end of HttpMediaManager
}
} // end of HttpMediaManager
exports.HttpMediaManager = HttpMediaManager;

@@ -16,3 +16,2 @@ /**

*/
/// <reference types="node" />
import { LoaderInterface, Segment } from "./loader-interface";

@@ -19,0 +18,0 @@ import { EventEmitter } from "events";

@@ -17,26 +17,14 @@ "use strict";

*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Debug = require("debug");
var loader_interface_1 = require("./loader-interface");
var events_1 = require("events");
var http_media_manager_1 = require("./http-media-manager");
var p2p_media_manager_1 = require("./p2p-media-manager");
var media_peer_1 = require("./media-peer");
var segment_internal_1 = require("./segment-internal");
var speed_approximator_1 = require("./speed-approximator");
var getBrowserRtc = require("get-browser-rtc");
var defaultSettings = {
const Debug = require("debug");
const loader_interface_1 = require("./loader-interface");
const events_1 = require("events");
const http_media_manager_1 = require("./http-media-manager");
const p2p_media_manager_1 = require("./p2p-media-manager");
const media_peer_1 = require("./media-peer");
const segment_internal_1 = require("./segment-internal");
const speed_approximator_1 = require("./speed-approximator");
const getBrowserRTC = require("get-browser-rtc");
const Peer = require("simple-peer");
const defaultSettings = {
cachedSegmentExpiration: 5 * 60 * 1000,

@@ -52,100 +40,87 @@ cachedSegmentsCount: 30,

p2pSegmentDownloadTimeout: 60000,
trackerAnnounce: ["wss://tracker.btorrent.xyz/", "wss://tracker.openwebtorrent.com/"],
rtcConfig: require("simple-peer").config
trackerAnnounce: ["wss://tracker.btorrent.xyz", "wss://tracker.openwebtorrent.com", "wss://tracker.fastcast.nz"],
rtcConfig: Peer.config
};
var HybridLoader = /** @class */ (function (_super) {
__extends(HybridLoader, _super);
function HybridLoader(settings) {
if (settings === void 0) { settings = {}; }
var _this = _super.call(this) || this;
_this.debug = Debug("p2pml:hybrid-loader");
_this.segments = new Map();
_this.segmentsQueue = [];
_this.httpDownloadProbabilityTimestamp = -999999;
_this.speedApproximator = new speed_approximator_1.SpeedApproximator();
_this.onPieceBytesDownloaded = function (method, bytes) {
_this.speedApproximator.addBytes(bytes, _this.now());
_this.emit(loader_interface_1.Events.PieceBytesDownloaded, method, bytes);
class HybridLoader extends events_1.EventEmitter {
constructor(settings = {}) {
super();
this.debug = Debug("p2pml:hybrid-loader");
this.segments = new Map();
this.segmentsQueue = [];
this.httpDownloadProbabilityTimestamp = -999999;
this.speedApproximator = new speed_approximator_1.SpeedApproximator();
this.onPieceBytesDownloaded = (method, bytes) => {
this.speedApproximator.addBytes(bytes, this.now());
this.emit(loader_interface_1.Events.PieceBytesDownloaded, method, bytes);
};
_this.onPieceBytesUploaded = function (method, bytes) {
_this.speedApproximator.addBytes(bytes, _this.now());
_this.emit(loader_interface_1.Events.PieceBytesUploaded, method, bytes);
this.onPieceBytesUploaded = (method, bytes) => {
this.speedApproximator.addBytes(bytes, this.now());
this.emit(loader_interface_1.Events.PieceBytesUploaded, method, bytes);
};
_this.onSegmentLoaded = function (segment, data) {
_this.debug("segment loaded", segment.id, segment.url);
var segmentInternal = new segment_internal_1.SegmentInternal(segment.id, segment.url, segment.range, segment.priority, data, _this.speedApproximator.getSpeed(_this.now()));
_this.segments.set(segment.id, segmentInternal);
_this.emitSegmentLoaded(segmentInternal);
_this.processSegmentsQueue();
_this.p2pManager.sendSegmentsMapToAll(_this.createSegmentsMap());
this.onSegmentLoaded = (segment, data) => {
this.debug("segment loaded", segment.id, segment.url);
const segmentInternal = new segment_internal_1.SegmentInternal(segment.id, segment.url, segment.range, segment.priority, data, this.speedApproximator.getSpeed(this.now()));
this.segments.set(segment.id, segmentInternal);
this.emitSegmentLoaded(segmentInternal);
this.processSegmentsQueue();
this.p2pManager.sendSegmentsMapToAll(this.createSegmentsMap());
};
_this.onSegmentError = function (segment, event) {
_this.emit(loader_interface_1.Events.SegmentError, segment, event);
_this.processSegmentsQueue();
this.onSegmentError = (segment, event) => {
this.emit(loader_interface_1.Events.SegmentError, segment, event);
this.processSegmentsQueue();
};
_this.onPeerConnect = function (peer) {
_this.p2pManager.sendSegmentsMap(peer.id, _this.createSegmentsMap());
_this.emit(loader_interface_1.Events.PeerConnect, peer);
this.onPeerConnect = (peer) => {
this.p2pManager.sendSegmentsMap(peer.id, this.createSegmentsMap());
this.emit(loader_interface_1.Events.PeerConnect, peer);
};
_this.onPeerClose = function (peerId) {
_this.emit(loader_interface_1.Events.PeerClose, peerId);
this.onPeerClose = (peerId) => {
this.emit(loader_interface_1.Events.PeerClose, peerId);
};
_this.settings = Object.assign(defaultSettings, settings);
_this.debug("loader settings", _this.settings);
_this.httpManager = _this.createHttpManager();
_this.httpManager.on("segment-loaded", _this.onSegmentLoaded);
_this.httpManager.on("segment-error", _this.onSegmentError);
_this.httpManager.on("bytes-downloaded", function (bytes) { return _this.onPieceBytesDownloaded("http", bytes); });
_this.p2pManager = _this.createP2PManager();
_this.p2pManager.on("segment-loaded", _this.onSegmentLoaded);
_this.p2pManager.on("segment-error", _this.onSegmentError);
_this.p2pManager.on("peer-data-updated", function () { return _this.processSegmentsQueue(); });
_this.p2pManager.on("bytes-downloaded", function (bytes) { return _this.onPieceBytesDownloaded("p2p", bytes); });
_this.p2pManager.on("bytes-uploaded", function (bytes) { return _this.onPieceBytesUploaded("p2p", bytes); });
_this.p2pManager.on("peer-connected", _this.onPeerConnect);
_this.p2pManager.on("peer-closed", _this.onPeerClose);
return _this;
this.settings = Object.assign(defaultSettings, settings);
this.debug("loader settings", this.settings);
this.httpManager = this.createHttpManager();
this.httpManager.on("segment-loaded", this.onSegmentLoaded);
this.httpManager.on("segment-error", this.onSegmentError);
this.httpManager.on("bytes-downloaded", (bytes) => this.onPieceBytesDownloaded("http", bytes));
this.p2pManager = this.createP2PManager();
this.p2pManager.on("segment-loaded", this.onSegmentLoaded);
this.p2pManager.on("segment-error", this.onSegmentError);
this.p2pManager.on("peer-data-updated", () => this.processSegmentsQueue());
this.p2pManager.on("bytes-downloaded", (bytes) => this.onPieceBytesDownloaded("p2p", bytes));
this.p2pManager.on("bytes-uploaded", (bytes) => this.onPieceBytesUploaded("p2p", bytes));
this.p2pManager.on("peer-connected", this.onPeerConnect);
this.p2pManager.on("peer-closed", this.onPeerClose);
}
HybridLoader.isSupported = function () {
var browserRtc = getBrowserRtc();
static isSupported() {
const browserRtc = getBrowserRTC();
return (browserRtc && (browserRtc.RTCPeerConnection.prototype.createDataChannel !== undefined));
};
HybridLoader.prototype.createHttpManager = function () {
}
createHttpManager() {
return new http_media_manager_1.HttpMediaManager();
};
HybridLoader.prototype.createP2PManager = function () {
}
createP2PManager() {
return new p2p_media_manager_1.P2PMediaManager(this.segments, this.settings);
};
HybridLoader.prototype.load = function (segments, swarmId) {
}
load(segments, swarmId) {
this.p2pManager.setSwarmId(swarmId);
this.debug("load segments", segments, this.segmentsQueue);
var updateSegmentsMap = false;
var _loop_1 = function (segment) {
if (!segments.find(function (f) { return f.url == segment.url; })) {
this_1.debug("remove segment", segment.url);
if (this_1.httpManager.isDownloading(segment)) {
let updateSegmentsMap = false;
// stop all http requests and p2p downloads for segments that are not in the new load
for (const segment of this.segmentsQueue) {
if (!segments.find(f => f.url == segment.url)) {
this.debug("remove segment", segment.url);
if (this.httpManager.isDownloading(segment)) {
updateSegmentsMap = true;
this_1.httpManager.abort(segment);
this.httpManager.abort(segment);
}
else {
this_1.p2pManager.abort(segment);
this.p2pManager.abort(segment);
}
this_1.emit(loader_interface_1.Events.SegmentAbort, segment);
this.emit(loader_interface_1.Events.SegmentAbort, segment);
}
};
var this_1 = this;
// stop all http requests and p2p downloads for segments that are not in the new load
for (var _i = 0, _a = this.segmentsQueue; _i < _a.length; _i++) {
var segment = _a[_i];
_loop_1(segment);
}
var _loop_2 = function (segment) {
if (!this_2.segmentsQueue.find(function (f) { return f.url == segment.url; })) {
this_2.debug("add segment", segment.url);
for (const segment of segments) {
if (!this.segmentsQueue.find(f => f.url == segment.url)) {
this.debug("add segment", segment.url);
}
};
var this_2 = this;
for (var _b = 0, segments_1 = segments; _b < segments_1.length; _b++) {
var segment = segments_1[_b];
_loop_2(segment);
}

@@ -161,5 +136,5 @@ // renew segment queue

}
};
HybridLoader.prototype.getSegment = function (id) {
var segment = this.segments.get(id);
}
getSegment(id) {
const segment = this.segments.get(id);
return segment

@@ -170,7 +145,7 @@ ? segment.data

: undefined;
};
HybridLoader.prototype.getSettings = function () {
}
getSettings() {
return this.settings;
};
HybridLoader.prototype.destroy = function () {
}
destroy() {
this.segmentsQueue = [];

@@ -180,10 +155,8 @@ this.httpManager.destroy();

this.segments.clear();
};
HybridLoader.prototype.processSegmentsQueue = function () {
var _this = this;
var startingPriority = this.segmentsQueue.length > 0 ? this.segmentsQueue[0].priority : 0;
}
processSegmentsQueue() {
const startingPriority = this.segmentsQueue.length > 0 ? this.segmentsQueue[0].priority : 0;
this.debug("processSegmentsQueue - starting priority: " + startingPriority);
var pendingCount = 0;
for (var _i = 0, _a = this.segmentsQueue; _i < _a.length; _i++) {
var segment = _a[_i];
let pendingCount = 0;
for (const segment of this.segmentsQueue) {
if (!this.segments.has(segment.id) && !this.httpManager.isDownloading(segment) && !this.p2pManager.isDownloading(segment)) {

@@ -196,12 +169,11 @@ pendingCount++;

}
var downloadedSegmentsCount = this.segmentsQueue.length - pendingCount;
var updateSegmentsMap = false;
for (var index = 0; index < this.segmentsQueue.length; index++) {
var segment = this.segmentsQueue[index];
var segmentPriority = index + startingPriority;
let downloadedSegmentsCount = this.segmentsQueue.length - pendingCount;
let updateSegmentsMap = false;
for (let index = 0; index < this.segmentsQueue.length; index++) {
const segment = this.segmentsQueue[index];
const segmentPriority = index + startingPriority;
if (!this.segments.has(segment.id)) {
if (segmentPriority <= this.settings.requiredSegmentsPriority) {
if (segmentPriority == 0 && !this.httpManager.isDownloading(segment) && this.httpManager.getActiveDownloads().size > 0) {
for (var _b = 0, _c = this.segmentsQueue; _b < _c.length; _b++) {
var s = _c[_b];
for (const s of this.segmentsQueue) {
this.httpManager.abort(s);

@@ -231,3 +203,3 @@ updateSegmentsMap = true;

}
var now = this.now();
const now = this.now();
if (now - this.httpDownloadProbabilityTimestamp < this.settings.httpDownloadProbabilityInterval) {

@@ -239,6 +211,4 @@ return updateSegmentsMap;

}
var pendingQueue = this.segmentsQueue.filter(function (segment) {
return !_this.segments.has(segment.id) &&
!_this.p2pManager.isDownloading(segment);
});
let pendingQueue = this.segmentsQueue.filter(segment => !this.segments.has(segment.id) &&
!this.p2pManager.isDownloading(segment));
downloadedSegmentsCount = this.segmentsQueue.length - pendingQueue.length;

@@ -248,9 +218,8 @@ if (pendingQueue.length == 0 || downloadedSegmentsCount >= this.settings.bufferedSegmentsCount) {

}
var segmentsMap = this.p2pManager.getOvrallSegmentsMap();
pendingQueue = pendingQueue.filter(function (segment) { return !segmentsMap.get(segment.id); });
const segmentsMap = this.p2pManager.getOvrallSegmentsMap();
pendingQueue = pendingQueue.filter(segment => !segmentsMap.get(segment.id));
if (pendingQueue.length == 0) {
return updateSegmentsMap;
}
for (var _d = 0, pendingQueue_1 = pendingQueue; _d < pendingQueue_1.length; _d++) {
var segment = pendingQueue_1[_d];
for (const segment of pendingQueue) {
if (Math.random() <= this.settings.httpDownloadProbability) {

@@ -264,22 +233,21 @@ this.debug("HTTP download (random)", segment.priority, segment.url);

return updateSegmentsMap;
};
HybridLoader.prototype.emitSegmentLoaded = function (segmentInternal) {
}
emitSegmentLoaded(segmentInternal) {
segmentInternal.lastAccessed = this.now();
var segment = new loader_interface_1.Segment(segmentInternal.id, segmentInternal.url, segmentInternal.range, segmentInternal.priority, segmentInternal.data, segmentInternal.downloadSpeed);
const segment = new loader_interface_1.Segment(segmentInternal.id, segmentInternal.url, segmentInternal.range, segmentInternal.priority, segmentInternal.data, segmentInternal.downloadSpeed);
this.emit(loader_interface_1.Events.SegmentLoaded, segment);
};
HybridLoader.prototype.createSegmentsMap = function () {
var segmentsMap = [];
this.segments.forEach(function (value, key) { return segmentsMap.push([key, media_peer_1.MediaPeerSegmentStatus.Loaded]); });
this.httpManager.getActiveDownloads().forEach(function (value, key) { return segmentsMap.push([key, media_peer_1.MediaPeerSegmentStatus.LoadingByHttp]); });
}
createSegmentsMap() {
const segmentsMap = [];
this.segments.forEach((value, key) => segmentsMap.push([key, media_peer_1.MediaPeerSegmentStatus.Loaded]));
this.httpManager.getActiveDownloads().forEach((value, key) => segmentsMap.push([key, media_peer_1.MediaPeerSegmentStatus.LoadingByHttp]));
return segmentsMap;
};
HybridLoader.prototype.collectGarbage = function () {
var _this = this;
var segmentsToDelete = [];
var remainingSegments = [];
}
collectGarbage() {
const segmentsToDelete = [];
const remainingSegments = [];
// Delete old segments
var now = this.now();
this.segments.forEach(function (segment) {
if (now - segment.lastAccessed > _this.settings.cachedSegmentExpiration) {
const now = this.now();
for (const segment of this.segments.values()) {
if (now - segment.lastAccessed > this.settings.cachedSegmentExpiration) {
segmentsToDelete.push(segment.id);

@@ -290,32 +258,24 @@ }

}
});
}
// Delete segments over cached count
var countOverhead = remainingSegments.length - this.settings.cachedSegmentsCount;
let countOverhead = remainingSegments.length - this.settings.cachedSegmentsCount;
if (countOverhead > 0) {
remainingSegments.sort(function (a, b) { return a.lastAccessed - b.lastAccessed; });
var _loop_3 = function (segment) {
if (!this_3.segmentsQueue.find(function (queueSegment) { return queueSegment.id == segment.id; })) {
remainingSegments.sort((a, b) => a.lastAccessed - b.lastAccessed);
for (const segment of remainingSegments) {
if (!this.segmentsQueue.find(queueSegment => queueSegment.id == segment.id)) {
segmentsToDelete.push(segment.id);
countOverhead--;
if (countOverhead == 0) {
return "break";
break;
}
}
};
var this_3 = this;
for (var _i = 0, remainingSegments_1 = remainingSegments; _i < remainingSegments_1.length; _i++) {
var segment = remainingSegments_1[_i];
var state_1 = _loop_3(segment);
if (state_1 === "break")
break;
}
}
segmentsToDelete.forEach(function (id) { return _this.segments.delete(id); });
segmentsToDelete.forEach(id => this.segments.delete(id));
return segmentsToDelete.length > 0;
};
HybridLoader.prototype.now = function () {
}
now() {
return performance.now();
};
return HybridLoader;
}(events_1.EventEmitter)); // end of HybridLoader
}
} // end of HybridLoader
exports.default = HybridLoader;
/**
* @license Apache-2.0
* Copyright 2018 Novage LLC.

@@ -3,0 +4,0 @@ *

"use strict";
/**
* @license Apache-2.0
* Copyright 2018 Novage LLC.

@@ -4,0 +5,0 @@ *

@@ -63,3 +63,3 @@ /**

export interface LoaderInterface {
on(eventName: string | symbol, listener: Function): this;
on(eventName: string, listener: Function): this;
load(segments: Segment[], swarmId: string): void;

@@ -66,0 +66,0 @@ getSegment(id: string): Segment | undefined;

@@ -18,7 +18,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var Segment = /** @class */ (function () {
function Segment(id, url, range, priority, data, downloadSpeed) {
if (priority === void 0) { priority = 0; }
if (data === void 0) { data = undefined; }
if (downloadSpeed === void 0) { downloadSpeed = 0; }
class Segment {
constructor(id, url, range, priority = 0, data = undefined, downloadSpeed = 0) {
this.id = id;

@@ -31,4 +28,3 @@ this.url = url;

}
return Segment;
}());
}
exports.Segment = Segment;

@@ -35,0 +31,0 @@ var Events;

@@ -34,3 +34,2 @@ /**

private timer;
private isSafari11_0;
constructor(peer: any, settings: {

@@ -40,3 +39,2 @@ p2pSegmentDownloadTimeout: number;

});
private detectSafari11_0;
private onPeerConnect;

@@ -43,0 +41,0 @@ private onPeerClose;

@@ -17,18 +17,6 @@ "use strict";

*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Debug = require("debug");
var stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
const Debug = require("debug");
const stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
const buffer_1 = require("buffer");
var MediaPeerCommands;

@@ -47,4 +35,4 @@ (function (MediaPeerCommands) {

})(MediaPeerSegmentStatus = exports.MediaPeerSegmentStatus || (exports.MediaPeerSegmentStatus = {}));
var DownloadingSegment = /** @class */ (function () {
function DownloadingSegment(id, size) {
class DownloadingSegment {
constructor(id, size) {
this.id = id;

@@ -55,49 +43,31 @@ this.size = size;

}
return DownloadingSegment;
}());
var MediaPeer = /** @class */ (function (_super) {
__extends(MediaPeer, _super);
function MediaPeer(peer, settings) {
var _this = _super.call(this) || this;
_this.peer = peer;
_this.settings = settings;
_this.remoteAddress = "";
_this.downloadingSegmentId = null;
_this.downloadingSegment = null;
_this.segmentsMap = new Map();
_this.debug = Debug("p2pml:media-peer");
_this.timer = null;
_this.isSafari11_0 = false;
_this.peer.on("connect", function () { return _this.onPeerConnect(); });
_this.peer.on("close", function () { return _this.onPeerClose(); });
_this.peer.on("error", function (error) { return _this.debug("peer error", _this.id, error, _this); });
_this.peer.on("data", function (data) { return _this.onPeerData(data); });
_this.id = peer.id;
_this.detectSafari11_0();
return _this;
}
class MediaPeer extends stringly_typed_event_emitter_1.default {
constructor(peer, settings) {
super();
this.peer = peer;
this.settings = settings;
this.remoteAddress = "";
this.downloadingSegmentId = null;
this.downloadingSegment = null;
this.segmentsMap = new Map();
this.debug = Debug("p2pml:media-peer");
this.timer = null;
this.peer.on("connect", () => this.onPeerConnect());
this.peer.on("close", () => this.onPeerClose());
this.peer.on("error", (error) => this.debug("peer error", this.id, error, this));
this.peer.on("data", (data) => this.onPeerData(data));
this.id = peer.id;
}
MediaPeer.prototype.detectSafari11_0 = function () {
var userAgent = typeof navigator !== "undefined" ? navigator.userAgent || "" : "";
var isSafari = userAgent.indexOf("Safari") != -1 && userAgent.indexOf("Chrome") == -1;
if (isSafari) {
var match = userAgent.match(/version\/(\d+(\.\d+)?)/i);
var version = (match && match.length > 1 && match[1]) || "";
if (version === "11.0") {
this.isSafari11_0 = true;
this.debug("enable workaround for Safari 11.0");
return;
}
}
};
MediaPeer.prototype.onPeerConnect = function () {
onPeerConnect() {
this.debug("peer connect", this.id, this);
this.remoteAddress = this.peer.remoteAddress;
this.emit("connect", this);
};
MediaPeer.prototype.onPeerClose = function () {
}
onPeerClose() {
this.debug("peer close", this.id, this);
this.terminateSegmentRequest();
this.emit("close", this);
};
MediaPeer.prototype.receiveSegmentPiece = function (data) {
}
receiveSegmentPiece(data) {
if (!this.downloadingSegment) {

@@ -111,8 +81,7 @@ // The segment was not requested or canceled

this.emit("bytes-downloaded", data.byteLength);
var segmentId = this.downloadingSegment.id;
const segmentId = this.downloadingSegment.id;
if (this.downloadingSegment.bytesDownloaded == this.downloadingSegment.size) {
var segmentData = new Uint8Array(this.downloadingSegment.size);
var offset = 0;
for (var _i = 0, _a = this.downloadingSegment.pieces; _i < _a.length; _i++) {
var piece = _a[_i];
const segmentData = new Uint8Array(this.downloadingSegment.size);
let offset = 0;
for (const piece of this.downloadingSegment.pieces) {
segmentData.set(new Uint8Array(piece), offset);

@@ -130,9 +99,9 @@ offset += piece.byteLength;

}
};
MediaPeer.prototype.getJsonCommand = function (data) {
var bytes = new Uint8Array(data);
}
getJsonCommand(data) {
const bytes = new Uint8Array(data);
// Serialized JSON string check by first, second and last characters: '{" .... }'
if (bytes[0] == 123 && bytes[1] == 34 && bytes[data.byteLength - 1] == 125) {
try {
return JSON.parse(new TextDecoder("utf-8").decode(data));
return JSON.parse(new TextDecoder().decode(data));
}

@@ -143,5 +112,5 @@ catch (_a) {

return null;
};
MediaPeer.prototype.onPeerData = function (data) {
var command = this.getJsonCommand(data);
}
onPeerData(data) {
const command = this.getJsonCommand(data);
if (command == null) {

@@ -153,3 +122,3 @@ this.receiveSegmentPiece(data);

this.debug("peer segment download is interrupted by a command", this.id, this);
var segmentId = this.downloadingSegment.id;
const segmentId = this.downloadingSegment.id;
this.terminateSegmentRequest();

@@ -187,22 +156,22 @@ this.emit("segment-error", this, segmentId, "Segment download is interrupted by a command");

}
};
MediaPeer.prototype.sendCommand = function (command) {
}
sendCommand(command) {
this.debug("peer send command", this.id, command, this);
this.peer.write(JSON.stringify(command));
};
MediaPeer.prototype.destroy = function () {
}
destroy() {
this.debug("peer destroy", this.id, this);
this.terminateSegmentRequest();
this.peer.destroy();
};
MediaPeer.prototype.getDownloadingSegmentId = function () {
}
getDownloadingSegmentId() {
return this.downloadingSegmentId;
};
MediaPeer.prototype.getSegmentsMap = function () {
}
getSegmentsMap() {
return this.segmentsMap;
};
MediaPeer.prototype.sendSegmentsMap = function (segments) {
}
sendSegmentsMap(segments) {
this.sendCommand({ "command": MediaPeerCommands.SegmentsMap, "segments": segments });
};
MediaPeer.prototype.sendSegmentData = function (segmentId, data) {
}
sendSegmentData(segmentId, data) {
this.sendCommand({

@@ -213,8 +182,6 @@ "command": MediaPeerCommands.SegmentData,

});
var bytesLeft = data.byteLength;
let bytesLeft = data.byteLength;
while (bytesLeft > 0) {
var bytesToSend = (bytesLeft >= this.settings.webRtcMaxMessageSize ? this.settings.webRtcMaxMessageSize : bytesLeft);
var buffer = this.isSafari11_0 ?
Buffer.from(data.slice(data.byteLength - bytesLeft, data.byteLength - bytesLeft + bytesToSend)) : // workaround for Safari 11.0 bug: https://bugs.webkit.org/show_bug.cgi?id=173052
Buffer.from(data, data.byteLength - bytesLeft, bytesToSend); // avoid memory copying
const bytesToSend = (bytesLeft >= this.settings.webRtcMaxMessageSize ? this.settings.webRtcMaxMessageSize : bytesLeft);
const buffer = buffer_1.Buffer.from(data, data.byteLength - bytesLeft, bytesToSend);
this.peer.write(buffer);

@@ -224,7 +191,7 @@ bytesLeft -= bytesToSend;

this.emit("bytes-uploaded", data.byteLength);
};
MediaPeer.prototype.sendSegmentAbsent = function (segmentId) {
}
sendSegmentAbsent(segmentId) {
this.sendCommand({ "command": MediaPeerCommands.SegmentAbsent, "segment_id": segmentId });
};
MediaPeer.prototype.requestSegment = function (segmentId) {
}
requestSegment(segmentId) {
if (this.downloadingSegmentId) {

@@ -236,23 +203,22 @@ throw new Error("A segment is already downloading: " + this.downloadingSegmentId);

this.runResponseTimeoutTimer();
};
MediaPeer.prototype.cancelSegmentRequest = function () {
}
cancelSegmentRequest() {
if (this.downloadingSegmentId) {
var segmentId = this.downloadingSegmentId;
const segmentId = this.downloadingSegmentId;
this.terminateSegmentRequest();
this.sendCommand({ "command": MediaPeerCommands.CancelSegmentRequest, "segment_id": segmentId });
}
};
MediaPeer.prototype.runResponseTimeoutTimer = function () {
var _this = this;
this.timer = window.setTimeout(function () {
_this.timer = null;
if (!_this.downloadingSegmentId) {
}
runResponseTimeoutTimer() {
this.timer = setTimeout(() => {
this.timer = null;
if (!this.downloadingSegmentId) {
return;
}
var segmentId = _this.downloadingSegmentId;
_this.cancelSegmentRequest();
_this.emit("segment-timeout", _this, segmentId); // TODO: send peer not responding event
const segmentId = this.downloadingSegmentId;
this.cancelSegmentRequest();
this.emit("segment-timeout", this, segmentId); // TODO: send peer not responding event
}, this.settings.p2pSegmentDownloadTimeout);
};
MediaPeer.prototype.cancelResponseTimeoutTimer = function () {
}
cancelResponseTimeoutTimer() {
if (this.timer) {

@@ -262,10 +228,9 @@ clearTimeout(this.timer);

}
};
MediaPeer.prototype.terminateSegmentRequest = function () {
}
terminateSegmentRequest() {
this.downloadingSegmentId = null;
this.downloadingSegment = null;
this.cancelResponseTimeoutTimer();
};
return MediaPeer;
}(stringly_typed_event_emitter_1.default));
}
}
exports.MediaPeer = MediaPeer;

@@ -36,2 +36,3 @@ /**

private debug;
private pendingTrackerClient;
constructor(cachedSegments: Map<string, SegmentInternal>, settings: {

@@ -44,3 +45,3 @@ useP2P: boolean;

});
setSwarmId(swarmId: string): void;
setSwarmId(swarmId: string): Promise<void>;
private createClient;

@@ -47,0 +48,0 @@ private onTrackerPeer;

@@ -17,51 +17,46 @@ "use strict";

*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
var Debug = require("debug");
var bittorrent_tracker_1 = require("bittorrent-tracker");
var crypto_1 = require("crypto");
var stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
var media_peer_1 = require("./media-peer");
var PEER_PROTOCOL_VERSION = 1;
var PeerSegmentRequest = /** @class */ (function () {
function PeerSegmentRequest(peerId, segment) {
const Debug = require("debug");
const bittorrent_tracker_1 = require("bittorrent-tracker");
const stringly_typed_event_emitter_1 = require("./stringly-typed-event-emitter");
const media_peer_1 = require("./media-peer");
const buffer_1 = require("buffer");
const sha1 = require("sha.js/sha1");
const PEER_PROTOCOL_VERSION = 1;
class PeerSegmentRequest {
constructor(peerId, segment) {
this.peerId = peerId;
this.segment = segment;
}
return PeerSegmentRequest;
}());
var P2PMediaManager = /** @class */ (function (_super) {
__extends(P2PMediaManager, _super);
function P2PMediaManager(cachedSegments, settings) {
var _this = _super.call(this) || this;
_this.cachedSegments = cachedSegments;
_this.settings = settings;
_this.trackerClient = null;
_this.peers = new Map();
_this.peerCandidates = new Map();
_this.peerSegmentRequests = new Map();
_this.swarmId = null;
_this.debug = Debug("p2pml:p2p-media-manager");
_this.onPieceBytesDownloaded = function (bytes) {
_this.emit("bytes-downloaded", bytes);
}
class P2PMediaManager extends stringly_typed_event_emitter_1.default {
constructor(cachedSegments, settings) {
super();
this.cachedSegments = cachedSegments;
this.settings = settings;
this.trackerClient = null;
this.peers = new Map();
this.peerCandidates = new Map();
this.peerSegmentRequests = new Map();
this.swarmId = null;
this.debug = Debug("p2pml:p2p-media-manager");
this.pendingTrackerClient = null;
this.onPieceBytesDownloaded = (bytes) => {
this.emit("bytes-downloaded", bytes);
};
_this.onPieceBytesUploaded = function (bytes) {
_this.emit("bytes-uploaded", bytes);
this.onPieceBytesUploaded = (bytes) => {
this.emit("bytes-uploaded", bytes);
};
_this.onPeerConnect = function (peer) {
var connectedPeer = _this.peers.get(peer.id);
this.onPeerConnect = (peer) => {
const connectedPeer = this.peers.get(peer.id);
if (connectedPeer) {
_this.debug("tracker peer already connected (in peer connect)", peer.id, peer);
this.debug("tracker peer already connected (in peer connect)", peer.id, peer);
peer.destroy();

@@ -71,8 +66,7 @@ return;

// First peer with the ID connected
_this.peers.set(peer.id, peer);
this.peers.set(peer.id, peer);
// Destroy all other peer candidates
var peerCandidatesById = _this.peerCandidates.get(peer.id);
const peerCandidatesById = this.peerCandidates.get(peer.id);
if (peerCandidatesById) {
for (var _i = 0, peerCandidatesById_1 = peerCandidatesById; _i < peerCandidatesById_1.length; _i++) {
var peerCandidate = peerCandidatesById_1[_i];
for (const peerCandidate of peerCandidatesById) {
if (peerCandidate != peer) {

@@ -82,14 +76,14 @@ peerCandidate.destroy();

}
_this.peerCandidates.delete(peer.id);
this.peerCandidates.delete(peer.id);
}
_this.emit("peer-connected", { id: peer.id, remoteAddress: peer.remoteAddress });
this.emit("peer-connected", { id: peer.id, remoteAddress: peer.remoteAddress });
};
_this.onPeerClose = function (peer) {
if (_this.peers.get(peer.id) != peer) {
this.onPeerClose = (peer) => {
if (this.peers.get(peer.id) != peer) {
// Try to delete the peer candidate
var peerCandidatesById = _this.peerCandidates.get(peer.id);
const peerCandidatesById = this.peerCandidates.get(peer.id);
if (!peerCandidatesById) {
return;
}
var index = peerCandidatesById.indexOf(peer);
const index = peerCandidatesById.indexOf(peer);
if (index != -1) {

@@ -99,20 +93,20 @@ peerCandidatesById.splice(index, 1);

if (peerCandidatesById.length == 0) {
_this.peerCandidates.delete(peer.id);
this.peerCandidates.delete(peer.id);
}
return;
}
_this.peerSegmentRequests.forEach(function (value, key) {
for (const [key, value] of this.peerSegmentRequests) {
if (value.peerId == peer.id) {
_this.peerSegmentRequests.delete(key);
this.peerSegmentRequests.delete(key);
}
});
_this.peers.delete(peer.id);
_this.emit("peer-data-updated");
_this.emit("peer-closed", peer.id);
}
this.peers.delete(peer.id);
this.emit("peer-data-updated");
this.emit("peer-closed", peer.id);
};
_this.onPeerDataUpdated = function () {
_this.emit("peer-data-updated");
this.onPeerDataUpdated = () => {
this.emit("peer-data-updated");
};
_this.onSegmentRequest = function (peer, segmentId) {
var segment = _this.cachedSegments.get(segmentId);
this.onSegmentRequest = (peer, segmentId) => {
const segment = this.cachedSegments.get(segmentId);
if (segment) {

@@ -125,51 +119,65 @@ peer.sendSegmentData(segmentId, segment.data);

};
_this.onSegmentLoaded = function (peer, segmentId, data) {
var peerSegmentRequest = _this.peerSegmentRequests.get(segmentId);
this.onSegmentLoaded = (peer, segmentId, data) => {
const peerSegmentRequest = this.peerSegmentRequests.get(segmentId);
if (peerSegmentRequest) {
_this.peerSegmentRequests.delete(segmentId);
_this.emit("segment-loaded", peerSegmentRequest.segment, data);
this.peerSegmentRequests.delete(segmentId);
this.emit("segment-loaded", peerSegmentRequest.segment, data);
}
};
_this.onSegmentAbsent = function (peer, segmentId) {
_this.peerSegmentRequests.delete(segmentId);
_this.emit("peer-data-updated");
this.onSegmentAbsent = (peer, segmentId) => {
this.peerSegmentRequests.delete(segmentId);
this.emit("peer-data-updated");
};
_this.onSegmentError = function (peer, segmentId, description) {
var peerSegmentRequest = _this.peerSegmentRequests.get(segmentId);
this.onSegmentError = (peer, segmentId, description) => {
const peerSegmentRequest = this.peerSegmentRequests.get(segmentId);
if (peerSegmentRequest) {
_this.peerSegmentRequests.delete(segmentId);
_this.emit("segment-error", peerSegmentRequest.segment, description);
this.peerSegmentRequests.delete(segmentId);
this.emit("segment-error", peerSegmentRequest.segment, description);
}
};
_this.onSegmentTimeout = function (peer, segmentId) {
var peerSegmentRequest = _this.peerSegmentRequests.get(segmentId);
this.onSegmentTimeout = (peer, segmentId) => {
const peerSegmentRequest = this.peerSegmentRequests.get(segmentId);
if (peerSegmentRequest) {
_this.peerSegmentRequests.delete(segmentId);
this.peerSegmentRequests.delete(segmentId);
peer.destroy();
if (_this.peers.delete(peerSegmentRequest.peerId)) {
_this.emit("peer-data-updated");
if (this.peers.delete(peerSegmentRequest.peerId)) {
this.emit("peer-data-updated");
}
}
};
_this.peerId = crypto_1.createHash("sha1").update((Date.now() + Math.random()).toFixed(12)).digest("hex");
_this.debug("peer ID", _this.peerId);
return _this;
this.peerId = crypto.getRandomValues(new Uint8Array(20)).buffer;
if (this.debug.enabled) {
this.debug("peer ID", buffer_1.Buffer.from(this.peerId).toString("hex"));
}
}
P2PMediaManager.prototype.setSwarmId = function (swarmId) {
if (this.swarmId === swarmId) {
return;
}
this.destroy();
this.swarmId = swarmId;
this.debug("swarm ID", this.swarmId);
this.createClient(crypto_1.createHash("sha1").update(PEER_PROTOCOL_VERSION + this.swarmId).digest("hex"));
};
P2PMediaManager.prototype.createClient = function (infoHash) {
var _this = this;
setSwarmId(swarmId) {
return __awaiter(this, void 0, void 0, function* () {
if (this.swarmId === swarmId) {
return;
}
this.destroy();
this.swarmId = swarmId;
this.debug("swarm ID", this.swarmId);
this.pendingTrackerClient = {
isDestroyed: false
};
const pendingTrackerClient = this.pendingTrackerClient;
// TODO: native browser 'crypto.subtle' implementation doesn't work in Chrome in insecure pages
// TODO: Edge doesn't support SHA-1. Change to SHA-256 once Edge support is required.
// const infoHash = await crypto.subtle.digest("SHA-1", new TextEncoder().encode(PEER_PROTOCOL_VERSION + this.swarmId));
const infoHash = new sha1().update(PEER_PROTOCOL_VERSION + this.swarmId).digest();
// destroy may be called while waiting for the hash to be calculated
if (!pendingTrackerClient.isDestroyed) {
this.pendingTrackerClient = null;
this.createClient(infoHash);
}
});
}
createClient(infoHash) {
if (!this.settings.useP2P) {
return;
}
var clientOptions = {
infoHash: infoHash,
peerId: this.peerId,
const clientOptions = {
infoHash: buffer_1.Buffer.from(infoHash, 0, 20),
peerId: buffer_1.Buffer.from(this.peerId, 0, 20),
announce: this.settings.trackerAnnounce,

@@ -179,9 +187,9 @@ rtcConfig: this.settings.rtcConfig

this.trackerClient = new bittorrent_tracker_1.Client(clientOptions);
this.trackerClient.on("error", function (error) { return _this.debug("tracker error", error); });
this.trackerClient.on("warning", function (error) { return _this.debug("tracker warning", error); });
this.trackerClient.on("update", function (data) { return _this.debug("tracker update", data); });
this.trackerClient.on("error", (error) => this.debug("tracker error", error));
this.trackerClient.on("warning", (error) => this.debug("tracker warning", error));
this.trackerClient.on("update", (data) => this.debug("tracker update", data));
this.trackerClient.on("peer", this.onTrackerPeer.bind(this));
this.trackerClient.start();
};
P2PMediaManager.prototype.onTrackerPeer = function (trackerPeer) {
}
onTrackerPeer(trackerPeer) {
this.debug("tracker peer", trackerPeer.id, trackerPeer);

@@ -193,3 +201,3 @@ if (this.peers.has(trackerPeer.id)) {

}
var peer = new media_peer_1.MediaPeer(trackerPeer, this.settings);
const peer = new media_peer_1.MediaPeer(trackerPeer, this.settings);
peer.on("connect", this.onPeerConnect);

@@ -205,3 +213,3 @@ peer.on("close", this.onPeerClose);

peer.on("bytes-uploaded", this.onPieceBytesUploaded);
var peerCandidatesById = this.peerCandidates.get(peer.id);
let peerCandidatesById = this.peerCandidates.get(peer.id);
if (!peerCandidatesById) {

@@ -212,10 +220,8 @@ peerCandidatesById = [];

peerCandidatesById.push(peer);
};
P2PMediaManager.prototype.download = function (segment) {
}
download(segment) {
if (this.isDownloading(segment)) {
return false;
}
var entries = this.peers.values();
for (var entry = entries.next(); !entry.done; entry = entries.next()) {
var peer = entry.value;
for (const peer of this.peers.values()) {
if ((peer.getDownloadingSegmentId() == null) &&

@@ -229,7 +235,7 @@ (peer.getSegmentsMap().get(segment.id) === media_peer_1.MediaPeerSegmentStatus.Loaded)) {

return false;
};
P2PMediaManager.prototype.abort = function (segment) {
var peerSegmentRequest = this.peerSegmentRequests.get(segment.id);
}
abort(segment) {
const peerSegmentRequest = this.peerSegmentRequests.get(segment.id);
if (peerSegmentRequest) {
var peer = this.peers.get(peerSegmentRequest.peerId);
const peer = this.peers.get(peerSegmentRequest.peerId);
if (peer) {

@@ -240,10 +246,10 @@ peer.cancelSegmentRequest();

}
};
P2PMediaManager.prototype.isDownloading = function (segment) {
}
isDownloading(segment) {
return this.peerSegmentRequests.has(segment.id);
};
P2PMediaManager.prototype.getActiveDownloadsCount = function () {
}
getActiveDownloadsCount() {
return this.peerSegmentRequests.size;
};
P2PMediaManager.prototype.destroy = function () {
}
destroy() {
this.swarmId = null;

@@ -255,36 +261,40 @@ if (this.trackerClient) {

}
this.peers.forEach(function (peer) { return peer.destroy(); });
if (this.pendingTrackerClient) {
this.pendingTrackerClient.isDestroyed = true;
this.pendingTrackerClient = null;
}
this.peers.forEach(peer => peer.destroy());
this.peers.clear();
this.peerSegmentRequests.clear();
this.peerCandidates.forEach(function (peerCandidateById) {
for (var _i = 0, peerCandidateById_1 = peerCandidateById; _i < peerCandidateById_1.length; _i++) {
var peerCandidate = peerCandidateById_1[_i];
for (const peerCandidateById of this.peerCandidates.values()) {
for (const peerCandidate of peerCandidateById) {
peerCandidate.destroy();
}
});
}
this.peerCandidates.clear();
};
P2PMediaManager.prototype.sendSegmentsMapToAll = function (segmentsMap) {
this.peers.forEach(function (peer) { return peer.sendSegmentsMap(segmentsMap); });
};
P2PMediaManager.prototype.sendSegmentsMap = function (peerId, segmentsMap) {
var peer = this.peers.get(peerId);
}
sendSegmentsMapToAll(segmentsMap) {
this.peers.forEach(peer => peer.sendSegmentsMap(segmentsMap));
}
sendSegmentsMap(peerId, segmentsMap) {
const peer = this.peers.get(peerId);
if (peer) {
peer.sendSegmentsMap(segmentsMap);
}
};
P2PMediaManager.prototype.getOvrallSegmentsMap = function () {
var overallSegmentsMap = new Map();
this.peers.forEach(function (peer) { return peer.getSegmentsMap().forEach(function (segmentStatus, segmentId) {
if (segmentStatus === media_peer_1.MediaPeerSegmentStatus.Loaded) {
overallSegmentsMap.set(segmentId, media_peer_1.MediaPeerSegmentStatus.Loaded);
}
getOvrallSegmentsMap() {
const overallSegmentsMap = new Map();
for (const peer of this.peers.values()) {
for (const [segmentId, segmentStatus] of peer.getSegmentsMap()) {
if (segmentStatus === media_peer_1.MediaPeerSegmentStatus.Loaded) {
overallSegmentsMap.set(segmentId, media_peer_1.MediaPeerSegmentStatus.Loaded);
}
else if (!overallSegmentsMap.get(segmentId)) {
overallSegmentsMap.set(segmentId, media_peer_1.MediaPeerSegmentStatus.LoadingByHttp);
}
}
else if (!overallSegmentsMap.get(segmentId)) {
overallSegmentsMap.set(segmentId, media_peer_1.MediaPeerSegmentStatus.LoadingByHttp);
}
}); });
}
return overallSegmentsMap;
};
return P2PMediaManager;
}(stringly_typed_event_emitter_1.default));
}
}
exports.P2PMediaManager = P2PMediaManager;

@@ -18,7 +18,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var SegmentInternal = /** @class */ (function () {
function SegmentInternal(id, url, range, priority, data, downloadSpeed) {
if (priority === void 0) { priority = 0; }
if (data === void 0) { data = undefined; }
if (downloadSpeed === void 0) { downloadSpeed = 0; }
class SegmentInternal {
constructor(id, url, range, priority = 0, data = undefined, downloadSpeed = 0) {
this.id = id;

@@ -32,4 +29,3 @@ this.url = url;

}
return SegmentInternal;
}());
}
exports.SegmentInternal = SegmentInternal;

@@ -18,13 +18,12 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var SMOOTH_INTERVAL = 4 * 1000;
var MEASURE_INTERVAL = 60 * 1000;
var NumberWithTime = /** @class */ (function () {
function NumberWithTime(value, timeStamp) {
const SMOOTH_INTERVAL = 4 * 1000;
const MEASURE_INTERVAL = 60 * 1000;
class NumberWithTime {
constructor(value, timeStamp) {
this.value = value;
this.timeStamp = timeStamp;
}
return NumberWithTime;
}());
var SpeedApproximator = /** @class */ (function () {
function SpeedApproximator() {
}
class SpeedApproximator {
constructor() {
this.lastBytes = [];

@@ -34,3 +33,3 @@ this.currentBytesSum = 0;

}
SpeedApproximator.prototype.addBytes = function (bytes, timeStamp) {
addBytes(bytes, timeStamp) {
this.lastBytes.push(new NumberWithTime(bytes, timeStamp));

@@ -42,11 +41,10 @@ this.currentBytesSum += bytes;

this.lastSpeed.push(new NumberWithTime(this.currentBytesSum / SMOOTH_INTERVAL, timeStamp));
};
}
// in bytes per millisecond
SpeedApproximator.prototype.getSpeed = function (timeStamp) {
getSpeed(timeStamp) {
while (this.lastSpeed.length != 0 && timeStamp - this.lastSpeed[0].timeStamp > MEASURE_INTERVAL) {
this.lastSpeed.shift();
}
var maxSpeed = 0;
for (var _i = 0, _a = this.lastSpeed; _i < _a.length; _i++) {
var speed = _a[_i];
let maxSpeed = 0;
for (const speed of this.lastSpeed) {
if (speed.value > maxSpeed) {

@@ -57,11 +55,10 @@ maxSpeed = speed.value;

return maxSpeed;
};
SpeedApproximator.prototype.getSmoothInterval = function () {
}
getSmoothInterval() {
return SMOOTH_INTERVAL;
};
SpeedApproximator.prototype.getMeasureInterval = function () {
}
getMeasureInterval() {
return MEASURE_INTERVAL;
};
return SpeedApproximator;
}());
}
}
exports.SpeedApproximator = SpeedApproximator;

@@ -16,3 +16,2 @@ /**

*/
/// <reference types="node" />
import { EventEmitter } from "events";

@@ -19,0 +18,0 @@ export default class<T extends string> extends EventEmitter {

@@ -17,32 +17,8 @@ "use strict";

*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
}
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var events_1 = require("events");
var default_1 = /** @class */ (function (_super) {
__extends(default_1, _super);
function default_1() {
return _super !== null && _super.apply(this, arguments) || this;
}
default_1.prototype.on = function (event, listener) { return _super.prototype.on.call(this, event, listener); };
default_1.prototype.emit = function (event) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return _super.prototype.emit.apply(this, [event].concat(args));
};
return default_1;
}(events_1.EventEmitter));
const events_1 = require("events");
class default_1 extends events_1.EventEmitter {
on(event, listener) { return super.on(event, listener); }
emit(event, ...args) { return super.emit(event, ...args); }
}
exports.default = default_1;
{
"name": "p2p-media-loader-core",
"description": "P2P Media Loader core functionality",
"version": "0.2.1",
"version": "0.3.0",
"license": "Apache-2.0",

@@ -27,9 +27,9 @@ "author": "Novage",

"compile": "tsc && copyfiles -f ./lib/*.js ./dist",
"browserify": "mkdirp ./build && browserify -r ./dist/index.js:p2p-media-loader-core ./dist/browser-init.js > ./build/p2p-media-loader-core.js",
"minify": "uglifyjs ./build/p2p-media-loader-core.js -m -c --comments > ./build/p2p-media-loader-core.min.js",
"browserify": "mkdirp ./build && browserify -r ./dist/index.js:p2p-media-loader-core -r debug -r events ./dist/browser-init.js > ./build/p2p-media-loader-core.js",
"minify": "terser ./build/p2p-media-loader-core.js -m -c > ./build/p2p-media-loader-core.min.js",
"build": "npm run compile && npm run browserify && npm run minify",
"webpack:build": "webpack --progress",
"webpack:watch": "webpack --watch --progress",
"lint": "tslint -c ./tslint.json -p ./tsconfig.test.json",
"test": "mocha -r ts-node/register test/*.test.ts"
"lint": "tslint -c ./tslint.json -p ./tsconfig.tslint.json",
"test": "TS_NODE_PROJECT=tsconfig.test.json TS_NODE_CACHE=false mocha -r ts-node/register test/*.test.ts"
},

@@ -42,11 +42,13 @@ "repository": {

"bittorrent-tracker": "^9.10.1",
"crypto-browserify": "^3.12.0",
"debug": "^3.2.6",
"debug": "^4.1.0",
"events": "^3.0.0",
"get-browser-rtc": "^1.0.2"
"get-browser-rtc": "^1.0.2",
"sha.js": "^2.4.11"
},
"devDependencies": {
"@types/assert": "^1.4.0",
"@types/debug": "^0.0.31",
"@types/events": "^1.2.0",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.9",
"@types/node": "^10.12.11",
"browserify": "^16.2.3",

@@ -57,9 +59,9 @@ "browserify-versionify": "^1.0.6",

"mocha": "^5.2.0",
"ts-loader": "^5.3.0",
"terser": "^3.11.0",
"ts-loader": "^5.3.1",
"ts-mockito": "^2.3.1",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6",
"uglify-js": "^3.4.9",
"webpack": "^4.25.1",
"typescript": "^3.2.1",
"webpack": "^4.26.1",
"webpack-cli": "^3.1.2"

@@ -66,0 +68,0 @@ },

@@ -5,3 +5,3 @@ # P2P Media Loader Core

Core functionality for P2P sharing of segmented media streams (i.e. HLS, DASH) using WebRTC.
Core functionality for P2P sharing of segmented media streams (i.e. HLS, MPEG-DASH) using WebRTC.

@@ -8,0 +8,0 @@ Useful links:

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc