Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
node_modules
dist

18 changes: 18 additions & 0 deletions dist/Meta.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export declare const ControlHeaders: {
FILE_START: number;
FILE_CHUNK: number;
FILE_CHUNK_ACK: number;
FILE_END: number;
TRANSFER_PAUSE: number;
TRANSFER_RESUME: number;
TRANSFER_CANCEL: number;
};
export interface FileSendRequest {
filename: string;
filesizeBytes: number;
}
export interface FileStartMetadata {
fileName: string;
fileSize: number;
fileType: string;
}
13 changes: 13 additions & 0 deletions dist/Meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use strict";
// The first byte in every data sent will be what kind of data it is
Object.defineProperty(exports, "__esModule", { value: true });
exports.ControlHeaders = void 0;
exports.ControlHeaders = {
FILE_START: 0,
FILE_CHUNK: 1,
FILE_CHUNK_ACK: 2,
FILE_END: 3,
TRANSFER_PAUSE: 4,
TRANSFER_RESUME: 5,
TRANSFER_CANCEL: 6
};
37 changes: 37 additions & 0 deletions dist/PeerFileReceive.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Readable } from 'readable-stream';
import { EventEmitter } from 'ee-ts';
import SimplePeer from 'simple-peer';
interface Events {
progress(percentage: number, bytesSent: number): void;
done(receivedFile: File): void;
pause(): void;
paused(): void;
resume(): void;
cancel(): void;
cancelled(): void;
}
export default class PeerFileReceive extends EventEmitter<Events> {
paused: boolean;
cancelled: boolean;
bytesReceived: number;
peer: SimplePeer.Instance;
private rs;
fileName: string;
fileSize: number;
private fileData;
private fileStream;
fileType: string;
constructor(peer: SimplePeer.Instance);
setPeer(peer: SimplePeer.Instance): void;
/**
* Send a message to sender
* @param header Type of message
* @param data Message
*/
private sendPeer;
createReadStream(): Readable;
pause(): void;
resume(): void;
cancel(): void;
}
export {};
159 changes: 159 additions & 0 deletions dist/PeerFileReceive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
"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 readable_stream_1 = require("readable-stream");
var ee_ts_1 = require("ee-ts");
var Meta_1 = require("./Meta");
var ReceiveStream = /** @class */ (function (_super) {
__extends(ReceiveStream, _super);
function ReceiveStream() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* File stream writes here
* @param chunk
* @param encoding
* @param cb
*/
ReceiveStream.prototype._write = function (data, encoding, cb) {
if (data[0] === Meta_1.ControlHeaders.FILE_START) {
var meta = JSON.parse(new TextDecoder().decode(data.slice(1)));
this.emit('start', meta);
}
else if (data[0] === Meta_1.ControlHeaders.FILE_CHUNK) {
this.emit('chunk', data.slice(1));
}
else if (data[0] === Meta_1.ControlHeaders.TRANSFER_PAUSE) {
this.emit('paused');
}
if (data[0] === Meta_1.ControlHeaders.TRANSFER_CANCEL) {
this.emit('cancelled');
this.destroy();
}
else {
cb(null); // Signal that we're ready for more data
}
};
return ReceiveStream;
}(readable_stream_1.Writable));
var PeerFileReceive = /** @class */ (function (_super) {
__extends(PeerFileReceive, _super);
function PeerFileReceive(peer) {
var _this = _super.call(this) || this;
_this.paused = false;
_this.cancelled = false;
_this.bytesReceived = 0;
_this.fileData = [];
_this.fileStream = null;
_this.setPeer(peer);
return _this;
}
// When peer is changed, start a new stream handler and assign events
PeerFileReceive.prototype.setPeer = function (peer) {
var _this = this;
if (this.rs) {
this.rs.destroy();
}
this.rs = new ReceiveStream();
this.peer = peer;
peer.pipe(this.rs);
this.rs.on('start', function (meta) {
_this.fileName = meta.fileName;
_this.fileSize = meta.fileSize;
_this.fileType = meta.fileType;
_this.fileData = [];
});
this.rs.on('chunk', function (chunk) {
_this.fileData.push(chunk);
if (_this.fileStream) {
_this.fileStream.push(chunk);
}
_this.bytesReceived += chunk.byteLength;
if (_this.bytesReceived === _this.fileSize) {
// completed
_this.sendPeer(Meta_1.ControlHeaders.FILE_END);
if (_this.fileStream)
_this.fileStream.push(null); // EOF
var file = new window.File(_this.fileData, _this.fileName, {
type: _this.fileType
});
_this.emit('progress', 100.0, _this.fileSize);
_this.emit('done', file);
}
else {
var percentage = parseFloat((100 * (_this.bytesReceived / _this.fileSize)).toFixed(3));
_this.emit('progress', percentage, _this.bytesReceived);
}
});
this.rs.on('paused', function () {
_this.emit('paused');
});
this.rs.on('cancelled', function () {
_this.emit('cancelled');
});
};
/**
* Send a message to sender
* @param header Type of message
* @param data Message
*/
PeerFileReceive.prototype.sendPeer = function (header, data) {
if (data === void 0) { data = null; }
if (!this.peer.connected)
return;
var resp;
if (data) {
resp = new Uint8Array(1 + data.length);
resp.set(data, 1);
}
else {
resp = new Uint8Array(1);
}
resp[0] = header;
this.peer.send(resp);
};
// Create a stream for receiving file data
PeerFileReceive.prototype.createReadStream = function () {
this.fileStream = new readable_stream_1.Readable({
objectMode: true,
read: function () { } // We'll be using push when we have file chunk
});
return this.fileStream;
};
// Request sender to pause transfer
PeerFileReceive.prototype.pause = function () {
this.sendPeer(Meta_1.ControlHeaders.TRANSFER_PAUSE);
this.paused = true;
this.emit('pause');
};
// Request sender to resume sending file
PeerFileReceive.prototype.resume = function () {
this.sendPeer(Meta_1.ControlHeaders.TRANSFER_RESUME);
this.paused = false;
this.emit('resume');
};
PeerFileReceive.prototype.cancel = function () {
this.cancelled = true;
this.sendPeer(Meta_1.ControlHeaders.TRANSFER_CANCEL);
this.fileData = [];
this.rs.destroy();
this.peer.destroy();
if (this.fileStream)
this.fileStream.destroy();
this.emit('cancel');
};
return PeerFileReceive;
}(ee_ts_1.EventEmitter));
exports.default = PeerFileReceive;
42 changes: 42 additions & 0 deletions dist/PeerFileSend.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { EventEmitter } from 'ee-ts';
import SimplePeer from 'simple-peer';
interface Events {
progress(percentage: number, bytesSent: number): void;
done(): void;
pause(): void;
paused(): void;
resume(): void;
resumed(): void;
cancel(): void;
cancelled(): void;
}
export default class PeerFileSend extends EventEmitter<Events> {
paused: boolean;
cancelled: boolean;
receiverPaused: boolean;
peer: SimplePeer.Instance;
file: File;
private ss;
private offset;
/**
* @param peer Peer to send
* @param file File to send
* @param offset Bytes to start sending from, useful for file resume
*/
constructor(peer: SimplePeer.Instance, file: File, offset?: number);
/**
* Send a message to receiver
* @param header Type of message
* @param data Message
*/
private sendPeer;
private sendFileStartData;
setPeer(peer: SimplePeer.Instance): void;
_resume(): void;
start(): void;
_pause(): void;
pause(): void;
resume(): void;
cancel(): void;
}
export {};
Loading