snapdrop

A Progressive Web App for local file sharing
git clone http://git.hanabi.in/repos/snapdrop.git
Log | Files | Refs | README | LICENSE

commit 983a2d116b1d724f31338ffa6aed45d255aa5f10
parent 87a2dec99269631af924c74d472753f9f3852450
Author: RobinLinus <robinlinus@users.noreply.github.com>
Date:   Tue,  9 Oct 2018 15:47:57 +0200

Merge remote-tracking branch 'origin/dev'

# Conflicts:
#	client/scripts/network.js
#	client/scripts/ui.js
#	server/index.js

Diffstat:
Mclient/scripts/network.js | 40+++++++++++++++++++++++-----------------
Mclient/scripts/ui.js | 14+++++++-------
Mserver/index.js | 85+++++++++++++++++++++++++++++++++++++++++--------------------------------------
3 files changed, 74 insertions(+), 65 deletions(-)

diff --git a/client/scripts/network.js b/client/scripts/network.js @@ -1,3 +1,6 @@ +window.URL = window.URL || window.webkitURL; +window.isRtcSupported = !!(window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection); + class ServerConnection { constructor() { @@ -5,7 +8,6 @@ class ServerConnection { Events.on('beforeunload', e => this._disconnect()); Events.on('pagehide', e => this._disconnect()); document.addEventListener('visibilitychange', e => this._onVisibilityChange()); - } _connect() { @@ -40,12 +42,12 @@ class ServerConnection { this.send({ type: 'pong' }); break; default: - console.error('WS: unkown message type', msg) + console.error('WS: unkown message type', msg); } } send(message) { - if (this._socket.readyState !== this._socket.OPEN) return; + if (!this._isConnected()) return; this._socket.send(JSON.stringify(message)); } @@ -118,7 +120,7 @@ class Peer { type: 'header', name: file.name, mime: file.type, - size: file.size, + size: file.size }); this._chunker = new FileChunker(file, chunk => this._send(chunk), @@ -244,6 +246,7 @@ class RTCPeer extends Peer { this._conn = new RTCPeerConnection(RTCPeer.config); this._conn.onicecandidate = e => this._onIceCandidate(e); this._conn.onconnectionstatechange = e => this._onConnectionStateChange(e); + this._conn.oniceconnectionstatechange = e => this._onIceConnectionStateChange(e); } _openChannel() { @@ -305,6 +308,16 @@ class RTCPeer extends Peer { } } + _onIceConnectionStateChange() { + switch (this._conn.iceConnectionState) { + case 'failed': + console.error('ICE Gathering failed'); + break; + default: + console.log('ICE Gathering', this._conn.iceConnectionState); + } + } + _onError(error) { console.error(error); } @@ -398,8 +411,8 @@ class WSPeer { class FileChunker { constructor(file, onChunk, onPartitionEnd) { - this._chunkSize = 64000; - this._maxPartitionSize = 1e6; + this._chunkSize = 64000; // 64 KB + this._maxPartitionSize = 1e6; // 1 MB this._offset = 0; this._partitionSize = 0; this._file = file; @@ -466,7 +479,7 @@ class FileDigester { this.progress = this._bytesReceived / this._size; if (this._bytesReceived < this._size) return; // we are done - let received = new Blob(this._buffer, { type: this._mime }); + let received = new Blob(this._buffer, { type: this._mime }); let url = URL.createObjectURL(received); this._callback({ name: this._name, @@ -488,20 +501,13 @@ class Events { } } -window.isRtcSupported = !!(window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection); RTCPeer.config = { 'iceServers': [{ - urls: 'stun:stun.stunprotocol.org:3478' - }, { urls: 'stun:stun.l.google.com:19302' }, { - urls: 'turn:turn.bistri.com:80', - credential: 'homeo', - username: 'homeo' - }, { - urls: 'turn:turn.anyfirewall.com:443?transport=tcp', - credential: 'webrtc', - username: 'webrtc' + urls: 'turn:192.158.29.39:3478?transport=tcp', + credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=', + username: '28224511:1379330808' }] } \ No newline at end of file diff --git a/client/scripts/ui.js b/client/scripts/ui.js @@ -25,16 +25,16 @@ class PeersUI { } _onPeerLeft(peerId) { - const peer = $(peerId); - if (!peer) return; - peer.remove(); + const $peer = $(peerId); + if (!$peer) return; + $peer.remove(); } _onFileProgress(progress) { const peerId = progress.sender || progress.recipient; - const peer = $(peerId); - if (!peer) return; - peer.ui.setProgress(progress.progress); + const $peer = $(peerId); + if (!$peer) return; + $peer.ui.setProgress(progress.progress); } _clearPeers() { @@ -237,7 +237,7 @@ class ReceiveDialog extends Dialog { this.show(); if (window.isDownloadSupported) return; - $a.target = "_blank"; // fallback + // $a.target = "_blank"; // fallback } _formatFileSize(bytes) { diff --git a/server/index.js b/server/index.js @@ -4,9 +4,7 @@ class SnapdropServer { constructor(port) { const WebSocket = require('ws'); - this._wss = new WebSocket.Server({ - port: port - }); + this._wss = new WebSocket.Server({ port: port }); this._wss.on('connection', (socket, request) => this._onConnection(new Peer(socket, request))); this._wss.on('headers', (headers, response) => this._onHeaders(headers, response)); @@ -57,7 +55,6 @@ class SnapdropServer { this._rooms[peer.ip] = {}; } - // console.log(peer.id, ' joined the room', peer.ip); // notify all other peers for (const otherPeerId in this._rooms[peer.ip]) { const otherPeer = this._rooms[peer.ip][otherPeerId]; @@ -97,10 +94,7 @@ class SnapdropServer { // notify all other peers for (const otherPeerId in this._rooms[peer.ip]) { const otherPeer = this._rooms[peer.ip][otherPeerId]; - this._send(otherPeer, { - type: 'peer-left', - peerId: peer.id - }); + this._send(otherPeer, { type: 'peer-left', peerId: peer.id }); } } } @@ -109,7 +103,7 @@ class SnapdropServer { if (!peer) return console.error('undefined peer'); if (this._wss.readyState !== this._wss.OPEN) return console.error('Socket is closed'); message = JSON.stringify(message); - peer.socket.send(message, error => console.log(error)); + peer.socket.send(message, error => error ? console.log(error): ''); } _keepAlive(peer) { @@ -145,26 +139,57 @@ class Peer { // set remote ip - if (request.headers['x-forwarded-for']) - this.ip = request.headers['x-forwarded-for'].split(/\s*,\s*/)[0]; - else - this.ip = request.connection.remoteAddress; + this._setIP(request); - if (request.peerId) { - this.id = request.peerId; - } else { - this.id = request.headers.cookie.replace('peerid=', ''); - } // set peer id + this._setPeerId(request) // is WebRTC supported ? this.rtcSupported = request.url.indexOf('webrtc') > -1; // set name - this.setName(request); + this._setName(request); // for keepalive this.timerId = 0; this.lastBeat = Date.now(); } + _setIP(request) { + if (request.headers['x-forwarded-for']) { + this.ip = request.headers['x-forwarded-for'].split(/\s*,\s*/)[0]; + } else { + this.ip = request.connection.remoteAddress; + } + } + + _setPeerId(request) { + if (request.peerId) { + this.id = request.peerId; + } else { + this.id = request.headers.cookie.replace('peerid=', ''); + } + } + + toString() { + return `<Peer id=${this.id} ip=${this.ip} rtcSupported=${this.rtcSupported}>` + } + + _setName(req) { + var ua = parser(req.headers['user-agent']); + this.name = { + model: ua.device.model, + os: ua.os.name, + browser: ua.browser.name, + type: ua.device.type + }; + } + + getInfo() { + return { + id: this.id, + name: this.name, + rtcSupported: this.rtcSupported + } + } + // return uuid of form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx static uuid() { let uuid = '', @@ -190,28 +215,6 @@ class Peer { } return uuid; }; - - toString() { - return `<Peer id=${this.id} ip=${this.ip} rtcSupported=${this.rtcSupported}>` - } - - setName(req) { - var ua = parser(req.headers['user-agent']); - this.name = { - model: ua.device.model, - os: ua.os.name, - browser: ua.browser.name, - type: ua.device.type - }; - } - - getInfo() { - return { - id: this.id, - name: this.name, - rtcSupported: this.rtcSupported - } - } } const server = new SnapdropServer(process.env.PORT || 3000); \ No newline at end of file