mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-20 23:16:13 -04:00
fix check whether peer is same browser
This commit is contained in:
parent
ae9909f596
commit
347f9b87c0
5 changed files with 213 additions and 167 deletions
4
index.js
4
index.js
|
@ -133,7 +133,6 @@ class PairDropServer {
|
||||||
type: 'rtc-config',
|
type: 'rtc-config',
|
||||||
config: rtcConfig
|
config: rtcConfig
|
||||||
});
|
});
|
||||||
this._joinRoom(peer);
|
|
||||||
|
|
||||||
// send displayName
|
// send displayName
|
||||||
this._send(peer, {
|
this._send(peer, {
|
||||||
|
@ -162,6 +161,9 @@ class PairDropServer {
|
||||||
case 'pong':
|
case 'pong':
|
||||||
sender.lastBeat = Date.now();
|
sender.lastBeat = Date.now();
|
||||||
break;
|
break;
|
||||||
|
case 'join-ip-room':
|
||||||
|
this._joinRoom(sender);
|
||||||
|
break;
|
||||||
case 'room-secrets':
|
case 'room-secrets':
|
||||||
this._onRoomSecrets(sender, message);
|
this._onRoomSecrets(sender, message);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,7 +19,8 @@ class ServerConnection {
|
||||||
Events.on('pagehide', _ => this._disconnect());
|
Events.on('pagehide', _ => this._disconnect());
|
||||||
document.addEventListener(window.visibilityChangeEvent, _ => this._onVisibilityChange());
|
document.addEventListener(window.visibilityChangeEvent, _ => this._onVisibilityChange());
|
||||||
if (navigator.connection) navigator.connection.addEventListener('change', _ => this._reconnect());
|
if (navigator.connection) navigator.connection.addEventListener('change', _ => this._reconnect());
|
||||||
Events.on('room-secrets', e => this._sendRoomSecrets(e.detail));
|
Events.on('room-secrets', e => this.send({ type: 'room-secrets', roomSecrets: e.detail }));
|
||||||
|
Events.on('join-ip-room', e => this.send({ type: 'join-ip-room'}));
|
||||||
Events.on('room-secrets-deleted', e => this.send({ type: 'room-secrets-deleted', roomSecrets: e.detail}));
|
Events.on('room-secrets-deleted', e => this.send({ type: 'room-secrets-deleted', roomSecrets: e.detail}));
|
||||||
Events.on('regenerate-room-secret', e => this.send({ type: 'regenerate-room-secret', roomSecret: e.detail}));
|
Events.on('regenerate-room-secret', e => this.send({ type: 'regenerate-room-secret', roomSecret: e.detail}));
|
||||||
Events.on('resend-peers', _ => this.send({ type: 'resend-peers'}));
|
Events.on('resend-peers', _ => this.send({ type: 'resend-peers'}));
|
||||||
|
@ -48,10 +49,6 @@ class ServerConnection {
|
||||||
if (this._isReconnect) Events.fire('notify-user', 'Connected.');
|
if (this._isReconnect) Events.fire('notify-user', 'Connected.');
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendRoomSecrets(roomSecrets) {
|
|
||||||
this.send({ type: 'room-secrets', roomSecrets: roomSecrets });
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPairDeviceInitiate() {
|
_onPairDeviceInitiate() {
|
||||||
if (!this._isConnected()) {
|
if (!this._isConnected()) {
|
||||||
Events.fire('notify-user', 'You need to be online to pair devices.');
|
Events.fire('notify-user', 'You need to be online to pair devices.');
|
||||||
|
@ -131,13 +128,6 @@ class ServerConnection {
|
||||||
|
|
||||||
_onPeers(msg) {
|
_onPeers(msg) {
|
||||||
Events.fire('peers', msg);
|
Events.fire('peers', msg);
|
||||||
if (msg.roomType === "ip" && msg.peers.length === 0) {
|
|
||||||
BrowserTabsConnector.removePeerIdsFromLocalStorage();
|
|
||||||
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
|
||||||
if (peerId) return;
|
|
||||||
console.log("successfully added peerId from localStorage");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDisplayName(msg) {
|
_onDisplayName(msg) {
|
||||||
|
@ -145,10 +135,16 @@ class ServerConnection {
|
||||||
sessionStorage.setItem("peerId", msg.message.peerId);
|
sessionStorage.setItem("peerId", msg.message.peerId);
|
||||||
sessionStorage.setItem("peerIdHash", msg.message.peerIdHash);
|
sessionStorage.setItem("peerIdHash", msg.message.peerIdHash);
|
||||||
|
|
||||||
// Add peerId to localStorage to mark it on other PairDrop tabs on the same browser
|
// Add peerId to localStorage to mark it for other PairDrop tabs on the same browser
|
||||||
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
||||||
if (peerId) return;
|
if (!peerId) return;
|
||||||
console.log("successfully added peerId from localStorage");
|
console.log("successfully added peerId to localStorage");
|
||||||
|
|
||||||
|
// Only now join rooms
|
||||||
|
Events.fire('join-ip-room');
|
||||||
|
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
||||||
|
Events.fire('room-secrets', roomSecrets);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.fire('display-name', msg);
|
Events.fire('display-name', msg);
|
||||||
|
@ -219,9 +215,9 @@ class ServerConnection {
|
||||||
|
|
||||||
class Peer {
|
class Peer {
|
||||||
|
|
||||||
constructor(serverConnection, peerId, roomType, roomSecret) {
|
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
|
||||||
this._server = serverConnection;
|
this._server = serverConnection;
|
||||||
this._isCaller = !!peerId;
|
this._isCaller = isCaller;
|
||||||
this._peerId = peerId;
|
this._peerId = peerId;
|
||||||
this._roomType = roomType;
|
this._roomType = roomType;
|
||||||
this._updateRoomSecret(roomSecret);
|
this._updateRoomSecret(roomSecret);
|
||||||
|
@ -241,15 +237,14 @@ class Peer {
|
||||||
this.sendJSON({type: 'display-name-changed', displayName: displayName});
|
this.sendJSON({type: 'display-name-changed', displayName: displayName});
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateRoomSecret(roomSecret) {
|
_isSameBrowser() {
|
||||||
// if peer is another browser tab, peer is not identifiable with roomSecret as browser tabs share all roomSecrets
|
return BrowserTabsConnector.peerIsSameBrowser(this._peerId);
|
||||||
// -> abort
|
|
||||||
if (BrowserTabsConnector.peerIsSameBrowser(this._peerId)) {
|
|
||||||
this._roomSecret = "";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._roomSecret && this._roomSecret !== roomSecret) {
|
_updateRoomSecret(roomSecret) {
|
||||||
|
// if peer is another browser tab, peer is not identifiable with roomSecret as browser tabs share all roomSecrets
|
||||||
|
// -> do not delete duplicates and do not regenerate room secrets
|
||||||
|
if (!this._isSameBrowser() && this._roomSecret && this._roomSecret !== roomSecret) {
|
||||||
// remove old roomSecrets to prevent multiple pairings with same peer
|
// remove old roomSecrets to prevent multiple pairings with same peer
|
||||||
PersistentStorage.deleteRoomSecret(this._roomSecret).then(deletedRoomSecret => {
|
PersistentStorage.deleteRoomSecret(this._roomSecret).then(deletedRoomSecret => {
|
||||||
if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret);
|
if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret);
|
||||||
|
@ -258,7 +253,7 @@ class Peer {
|
||||||
|
|
||||||
this._roomSecret = roomSecret;
|
this._roomSecret = roomSecret;
|
||||||
|
|
||||||
if (this._roomSecret && this._roomSecret.length !== 256 && this._isCaller) {
|
if (!this._isSameBrowser() && this._roomSecret && this._roomSecret.length !== 256 && this._isCaller) {
|
||||||
// increase security by increasing roomSecret length
|
// increase security by increasing roomSecret length
|
||||||
console.log('RoomSecret is regenerated to increase security')
|
console.log('RoomSecret is regenerated to increase security')
|
||||||
Events.fire('regenerate-room-secret', this._roomSecret);
|
Events.fire('regenerate-room-secret', this._roomSecret);
|
||||||
|
@ -603,15 +598,15 @@ class Peer {
|
||||||
|
|
||||||
class RTCPeer extends Peer {
|
class RTCPeer extends Peer {
|
||||||
|
|
||||||
constructor(serverConnection, peerId, roomType, roomSecret) {
|
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
|
||||||
super(serverConnection, peerId, roomType, roomSecret);
|
super(serverConnection, isCaller, peerId, roomType, roomSecret);
|
||||||
this.rtcSupported = true;
|
this.rtcSupported = true;
|
||||||
if (!this._isCaller) return; // we will listen for a caller
|
if (!this._isCaller) return; // we will listen for a caller
|
||||||
this._connect(peerId, true);
|
this._connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
_connect(peerId) {
|
_connect() {
|
||||||
if (!this._conn || this._conn.signalingState === "closed") this._openConnection(peerId);
|
if (!this._conn || this._conn.signalingState === "closed") this._openConnection();
|
||||||
|
|
||||||
if (this._isCaller) {
|
if (this._isCaller) {
|
||||||
this._openChannel();
|
this._openChannel();
|
||||||
|
@ -620,8 +615,7 @@ class RTCPeer extends Peer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_openConnection(peerId) {
|
_openConnection() {
|
||||||
this._peerId = peerId;
|
|
||||||
this._conn = new RTCPeerConnection(window.rtcConfig);
|
this._conn = new RTCPeerConnection(window.rtcConfig);
|
||||||
this._conn.onicecandidate = e => this._onIceCandidate(e);
|
this._conn.onicecandidate = e => this._onIceCandidate(e);
|
||||||
this._conn.onicecandidateerror = e => this._onError(e);
|
this._conn.onicecandidateerror = e => this._onError(e);
|
||||||
|
@ -653,7 +647,7 @@ class RTCPeer extends Peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
onServerMessage(message) {
|
onServerMessage(message) {
|
||||||
if (!this._conn) this._connect(message.sender.id, false);
|
if (!this._conn) this._connect();
|
||||||
|
|
||||||
if (message.sdp) {
|
if (message.sdp) {
|
||||||
this._conn.setRemoteDescription(message.sdp)
|
this._conn.setRemoteDescription(message.sdp)
|
||||||
|
@ -738,7 +732,7 @@ class RTCPeer extends Peer {
|
||||||
console.log('RTC: channel closed', this._peerId);
|
console.log('RTC: channel closed', this._peerId);
|
||||||
Events.fire('peer-disconnected', this._peerId);
|
Events.fire('peer-disconnected', this._peerId);
|
||||||
if (!this._isCaller) return;
|
if (!this._isCaller) return;
|
||||||
this._connect(this._peerId, true); // reopen the channel
|
this._connect(); // reopen the channel
|
||||||
}
|
}
|
||||||
|
|
||||||
_onConnectionStateChange() {
|
_onConnectionStateChange() {
|
||||||
|
@ -789,7 +783,7 @@ class RTCPeer extends Peer {
|
||||||
// only reconnect if peer is caller
|
// only reconnect if peer is caller
|
||||||
if (!this._isCaller) return;
|
if (!this._isCaller) return;
|
||||||
|
|
||||||
this._connect(this._peerId);
|
this._connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
_isConnected() {
|
_isConnected() {
|
||||||
|
@ -833,9 +827,9 @@ class PeersManager {
|
||||||
this.peers[peerId].onServerMessage(message);
|
this.peers[peerId].onServerMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshExistingPeer(peerId, roomType, roomSecret) {
|
_refreshPeer(peer, roomType, roomSecret) {
|
||||||
const peer = this.peers[peerId];
|
if (!peer) return false;
|
||||||
if (peer) {
|
|
||||||
const roomTypeIsSecret = roomType === "secret";
|
const roomTypeIsSecret = roomType === "secret";
|
||||||
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
|
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
|
||||||
|
|
||||||
|
@ -856,21 +850,24 @@ class PeersManager {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// peer does not yet exist: return false
|
|
||||||
return false;
|
_createOrRefreshPeer(isCaller, peerId, roomType, roomSecret) {
|
||||||
|
const peer = this.peers[peerId];
|
||||||
|
if (peer) {
|
||||||
|
this._refreshPeer(peer, roomType, roomSecret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.peers[peerId] = new RTCPeer(this._server, isCaller, peerId, roomType, roomSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeerJoined(message) {
|
_onPeerJoined(message) {
|
||||||
if (this._refreshExistingPeer(message.peer.id, message.roomType, message.roomSecret)) return;
|
this._createOrRefreshPeer(false, message.peer.id, message.roomType, message.roomSecret);
|
||||||
|
|
||||||
this.peers[message.peer.id] = new RTCPeer(this._server, undefined, message.roomType, message.roomSecret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeers(message) {
|
_onPeers(message) {
|
||||||
message.peers.forEach(messagePeer => {
|
message.peers.forEach(peer => {
|
||||||
if (this._refreshExistingPeer(messagePeer.id, message.roomType, message.roomSecret)) return;
|
this._createOrRefreshPeer(true, peer.id, message.roomType, message.roomSecret);
|
||||||
|
|
||||||
this.peers[messagePeer.id] = new RTCPeer(this._server, messagePeer.id, message.roomType, message.roomSecret);
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,6 +899,15 @@ class PeersManager {
|
||||||
if (message.disconnect === true) {
|
if (message.disconnect === true) {
|
||||||
// if user actively disconnected from PairDrop server, disconnect all peer to peer connections immediately
|
// if user actively disconnected from PairDrop server, disconnect all peer to peer connections immediately
|
||||||
Events.fire('peer-disconnected', message.peerId);
|
Events.fire('peer-disconnected', message.peerId);
|
||||||
|
|
||||||
|
// If no peers are connected anymore, we can safely assume that no other tab on the same browser is connected:
|
||||||
|
// Tidy up peerIds in localStorage
|
||||||
|
if (Object.keys(this.peers).length === 0) {
|
||||||
|
BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerIds => {
|
||||||
|
if (!peerIds) return;
|
||||||
|
console.log("successfully removed other peerIds from localStorage");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,7 +968,8 @@ class PeersManager {
|
||||||
_getPeerIdFromRoomSecret(roomSecret) {
|
_getPeerIdFromRoomSecret(roomSecret) {
|
||||||
for (const peerId in this.peers) {
|
for (const peerId in this.peers) {
|
||||||
const peer = this.peers[peerId];
|
const peer = this.peers[peerId];
|
||||||
if (peer._roomSecret === roomSecret) {
|
// peer must have same roomSecret and not be on the same browser.
|
||||||
|
if (peer._roomSecret === roomSecret && !peer._isSameBrowser()) {
|
||||||
return peer._peerId;
|
return peer._peerId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,8 +169,12 @@ class PeersUI {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer.sameBrowser = _ => BrowserTabsConnector.peerIsSameBrowser(peer.id);
|
peer.sameBrowser = _ => BrowserTabsConnector.peerIsSameBrowser(peer.id);
|
||||||
|
|
||||||
|
if (!(roomType === "secret" && peer.sameBrowser())) {
|
||||||
peer.roomTypes = [roomType];
|
peer.roomTypes = [roomType];
|
||||||
peer.roomSecret = roomSecret;
|
peer.roomSecret = roomSecret;
|
||||||
|
}
|
||||||
|
|
||||||
this.peers[peer.id] = peer;
|
this.peers[peer.id] = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,10 +1030,7 @@ class PairDeviceDialog extends Dialog {
|
||||||
|
|
||||||
_onWsConnected() {
|
_onWsConnected() {
|
||||||
this.$pairDeviceBtn.removeAttribute('hidden');
|
this.$pairDeviceBtn.removeAttribute('hidden');
|
||||||
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
|
||||||
Events.fire('room-secrets', roomSecrets);
|
|
||||||
this._evaluateNumberRoomSecrets();
|
this._evaluateNumberRoomSecrets();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_pairDeviceInitiate() {
|
_pairDeviceInitiate() {
|
||||||
|
@ -1972,13 +1973,18 @@ class PersistentStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getAllRoomSecrets() {
|
static async getAllRoomSecrets() {
|
||||||
|
try {
|
||||||
const roomSecrets = await this.getAllRoomSecretEntries();
|
const roomSecrets = await this.getAllRoomSecretEntries();
|
||||||
let secrets = [];
|
let secrets = [];
|
||||||
for (let i=0; i<roomSecrets.length; i++) {
|
for (let i = 0; i < roomSecrets.length; i++) {
|
||||||
secrets.push(roomSecrets[i].secret);
|
secrets.push(roomSecrets[i].secret);
|
||||||
}
|
}
|
||||||
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
||||||
return(secrets);
|
return(secrets);
|
||||||
|
} catch (e) {
|
||||||
|
this.logBrowserNotCapable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getAllRoomSecretEntries() {
|
static getAllRoomSecretEntries() {
|
||||||
|
@ -2167,11 +2173,13 @@ class BrowserTabsConnector {
|
||||||
|
|
||||||
let peerIdsBrowser = [];
|
let peerIdsBrowser = [];
|
||||||
let peerIdsBrowserOld = JSON.parse(localStorage.getItem("peerIdsBrowser"));
|
let peerIdsBrowserOld = JSON.parse(localStorage.getItem("peerIdsBrowser"));
|
||||||
|
|
||||||
if (peerIdsBrowserOld) peerIdsBrowser.push(...peerIdsBrowserOld);
|
if (peerIdsBrowserOld) peerIdsBrowser.push(...peerIdsBrowserOld);
|
||||||
peerIdsBrowser.push(peerId);
|
peerIdsBrowser.push(peerId);
|
||||||
peerIdsBrowser = peerIdsBrowser.filter(onlyUnique);
|
peerIdsBrowser = peerIdsBrowser.filter(onlyUnique);
|
||||||
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
||||||
return peerId;
|
|
||||||
|
return peerIdsBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removePeerIdFromLocalStorage(peerId) {
|
static async removePeerIdFromLocalStorage(peerId) {
|
||||||
|
@ -2182,8 +2190,14 @@ class BrowserTabsConnector {
|
||||||
return peerId;
|
return peerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static removePeerIdsFromLocalStorage() {
|
|
||||||
localStorage.removeItem("peerIdsBrowser");
|
static async removeOtherPeerIdsFromLocalStorage() {
|
||||||
|
const peerId = sessionStorage.getItem("peerId");
|
||||||
|
if (!peerId) return false;
|
||||||
|
|
||||||
|
let peerIdsBrowser = [peerId];
|
||||||
|
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
||||||
|
return peerIdsBrowser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ class ServerConnection {
|
||||||
Events.on('pagehide', _ => this._disconnect());
|
Events.on('pagehide', _ => this._disconnect());
|
||||||
document.addEventListener(window.visibilityChangeEvent, _ => this._onVisibilityChange());
|
document.addEventListener(window.visibilityChangeEvent, _ => this._onVisibilityChange());
|
||||||
if (navigator.connection) navigator.connection.addEventListener('change', _ => this._reconnect());
|
if (navigator.connection) navigator.connection.addEventListener('change', _ => this._reconnect());
|
||||||
Events.on('room-secrets', e => this._sendRoomSecrets(e.detail));
|
Events.on('room-secrets', e => this.send({ type: 'room-secrets', roomSecrets: e.detail }));
|
||||||
|
Events.on('join-ip-room', e => this.send({ type: 'join-ip-room'}));
|
||||||
Events.on('room-secrets-deleted', e => this.send({ type: 'room-secrets-deleted', roomSecrets: e.detail}));
|
Events.on('room-secrets-deleted', e => this.send({ type: 'room-secrets-deleted', roomSecrets: e.detail}));
|
||||||
Events.on('regenerate-room-secret', e => this.send({ type: 'regenerate-room-secret', roomSecret: e.detail}));
|
Events.on('regenerate-room-secret', e => this.send({ type: 'regenerate-room-secret', roomSecret: e.detail}));
|
||||||
Events.on('resend-peers', _ => this.send({ type: 'resend-peers'}));
|
Events.on('resend-peers', _ => this.send({ type: 'resend-peers'}));
|
||||||
|
@ -46,10 +47,6 @@ class ServerConnection {
|
||||||
if (this._isReconnect) Events.fire('notify-user', 'Connected.');
|
if (this._isReconnect) Events.fire('notify-user', 'Connected.');
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendRoomSecrets(roomSecrets) {
|
|
||||||
this.send({ type: 'room-secrets', roomSecrets: roomSecrets });
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPairDeviceInitiate() {
|
_onPairDeviceInitiate() {
|
||||||
if (!this._isConnected()) {
|
if (!this._isConnected()) {
|
||||||
Events.fire('notify-user', 'You need to be online to pair devices.');
|
Events.fire('notify-user', 'You need to be online to pair devices.');
|
||||||
|
@ -143,10 +140,9 @@ class ServerConnection {
|
||||||
_onPeers(msg) {
|
_onPeers(msg) {
|
||||||
Events.fire('peers', msg);
|
Events.fire('peers', msg);
|
||||||
if (msg.roomType === "ip" && msg.peers.length === 0) {
|
if (msg.roomType === "ip" && msg.peers.length === 0) {
|
||||||
BrowserTabsConnector.removePeerIdsFromLocalStorage();
|
BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerId => {
|
||||||
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
if (!peerId) return;
|
||||||
if (peerId) return;
|
console.log("successfully removed other peerIds from localStorage");
|
||||||
console.log("successfully added peerId from localStorage");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,10 +152,16 @@ class ServerConnection {
|
||||||
sessionStorage.setItem("peerId", msg.message.peerId);
|
sessionStorage.setItem("peerId", msg.message.peerId);
|
||||||
sessionStorage.setItem("peerIdHash", msg.message.peerIdHash);
|
sessionStorage.setItem("peerIdHash", msg.message.peerIdHash);
|
||||||
|
|
||||||
// Add peerId to localStorage to mark it on other PairDrop tabs on the same browser
|
// Add peerId to localStorage to mark it for other PairDrop tabs on the same browser
|
||||||
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => {
|
||||||
if (peerId) return;
|
if (!peerId) return;
|
||||||
console.log("successfully added peerId from localStorage");
|
console.log("successfully added peerId to localStorage");
|
||||||
|
|
||||||
|
// Only now join rooms
|
||||||
|
Events.fire('join-ip-room');
|
||||||
|
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
||||||
|
Events.fire('room-secrets', roomSecrets);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.fire('display-name', msg);
|
Events.fire('display-name', msg);
|
||||||
|
@ -230,9 +232,9 @@ class ServerConnection {
|
||||||
|
|
||||||
class Peer {
|
class Peer {
|
||||||
|
|
||||||
constructor(serverConnection, peerId, roomType, roomSecret) {
|
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
|
||||||
this._server = serverConnection;
|
this._server = serverConnection;
|
||||||
this._isCaller = !!peerId;
|
this._isCaller = isCaller;
|
||||||
this._peerId = peerId;
|
this._peerId = peerId;
|
||||||
this._roomType = roomType;
|
this._roomType = roomType;
|
||||||
this._updateRoomSecret(roomSecret);
|
this._updateRoomSecret(roomSecret);
|
||||||
|
@ -252,15 +254,14 @@ class Peer {
|
||||||
this.sendJSON({type: 'display-name-changed', displayName: displayName});
|
this.sendJSON({type: 'display-name-changed', displayName: displayName});
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateRoomSecret(roomSecret) {
|
_isSameBrowser() {
|
||||||
// if peer is another browser tab, peer is not identifiable with roomSecret as browser tabs share all roomSecrets
|
return BrowserTabsConnector.peerIsSameBrowser(this._peerId);
|
||||||
// -> abort
|
|
||||||
if (BrowserTabsConnector.peerIsSameBrowser(this._peerId)) {
|
|
||||||
this._roomSecret = "";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._roomSecret && this._roomSecret !== roomSecret) {
|
_updateRoomSecret(roomSecret) {
|
||||||
|
// if peer is another browser tab, peer is not identifiable with roomSecret as browser tabs share all roomSecrets
|
||||||
|
// -> do not delete duplicates and do not regenerate room secrets
|
||||||
|
if (!this._isSameBrowser() && this._roomSecret && this._roomSecret !== roomSecret) {
|
||||||
// remove old roomSecrets to prevent multiple pairings with same peer
|
// remove old roomSecrets to prevent multiple pairings with same peer
|
||||||
PersistentStorage.deleteRoomSecret(this._roomSecret).then(deletedRoomSecret => {
|
PersistentStorage.deleteRoomSecret(this._roomSecret).then(deletedRoomSecret => {
|
||||||
if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret);
|
if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret);
|
||||||
|
@ -269,7 +270,7 @@ class Peer {
|
||||||
|
|
||||||
this._roomSecret = roomSecret;
|
this._roomSecret = roomSecret;
|
||||||
|
|
||||||
if (this._roomSecret && this._roomSecret.length !== 256 && this._isCaller) {
|
if (!this._isSameBrowser() && this._roomSecret && this._roomSecret.length !== 256 && this._isCaller) {
|
||||||
// increase security by increasing roomSecret length
|
// increase security by increasing roomSecret length
|
||||||
console.log('RoomSecret is regenerated to increase security')
|
console.log('RoomSecret is regenerated to increase security')
|
||||||
Events.fire('regenerate-room-secret', this._roomSecret);
|
Events.fire('regenerate-room-secret', this._roomSecret);
|
||||||
|
@ -614,15 +615,15 @@ class Peer {
|
||||||
|
|
||||||
class RTCPeer extends Peer {
|
class RTCPeer extends Peer {
|
||||||
|
|
||||||
constructor(serverConnection, peerId, roomType, roomSecret) {
|
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
|
||||||
super(serverConnection, peerId, roomType, roomSecret);
|
super(serverConnection, isCaller, peerId, roomType, roomSecret);
|
||||||
this.rtcSupported = true;
|
this.rtcSupported = true;
|
||||||
if (!this._isCaller) return; // we will listen for a caller
|
if (!this._isCaller) return; // we will listen for a caller
|
||||||
this._connect(peerId, true);
|
this._connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
_connect(peerId) {
|
_connect() {
|
||||||
if (!this._conn || this._conn.signalingState === "closed") this._openConnection(peerId);
|
if (!this._conn || this._conn.signalingState === "closed") this._openConnection();
|
||||||
|
|
||||||
if (this._isCaller) {
|
if (this._isCaller) {
|
||||||
this._openChannel();
|
this._openChannel();
|
||||||
|
@ -631,8 +632,7 @@ class RTCPeer extends Peer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_openConnection(peerId) {
|
_openConnection() {
|
||||||
this._peerId = peerId;
|
|
||||||
this._conn = new RTCPeerConnection(window.rtcConfig);
|
this._conn = new RTCPeerConnection(window.rtcConfig);
|
||||||
this._conn.onicecandidate = e => this._onIceCandidate(e);
|
this._conn.onicecandidate = e => this._onIceCandidate(e);
|
||||||
this._conn.onicecandidateerror = e => this._onError(e);
|
this._conn.onicecandidateerror = e => this._onError(e);
|
||||||
|
@ -664,7 +664,7 @@ class RTCPeer extends Peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
onServerMessage(message) {
|
onServerMessage(message) {
|
||||||
if (!this._conn) this._connect(message.sender.id, false);
|
if (!this._conn) this._connect();
|
||||||
|
|
||||||
if (message.sdp) {
|
if (message.sdp) {
|
||||||
this._conn.setRemoteDescription(message.sdp)
|
this._conn.setRemoteDescription(message.sdp)
|
||||||
|
@ -749,7 +749,7 @@ class RTCPeer extends Peer {
|
||||||
console.log('RTC: channel closed', this._peerId);
|
console.log('RTC: channel closed', this._peerId);
|
||||||
Events.fire('peer-disconnected', this._peerId);
|
Events.fire('peer-disconnected', this._peerId);
|
||||||
if (!this._isCaller) return;
|
if (!this._isCaller) return;
|
||||||
this._connect(this._peerId, true); // reopen the channel
|
this._connect(); // reopen the channel
|
||||||
}
|
}
|
||||||
|
|
||||||
_onConnectionStateChange() {
|
_onConnectionStateChange() {
|
||||||
|
@ -800,7 +800,7 @@ class RTCPeer extends Peer {
|
||||||
// only reconnect if peer is caller
|
// only reconnect if peer is caller
|
||||||
if (!this._isCaller) return;
|
if (!this._isCaller) return;
|
||||||
|
|
||||||
this._connect(this._peerId);
|
this._connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
_isConnected() {
|
_isConnected() {
|
||||||
|
@ -819,8 +819,8 @@ class RTCPeer extends Peer {
|
||||||
|
|
||||||
class WSPeer extends Peer {
|
class WSPeer extends Peer {
|
||||||
|
|
||||||
constructor(serverConnection, peerId, roomType, roomSecret) {
|
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
|
||||||
super(serverConnection, peerId, roomType, roomSecret);
|
super(serverConnection, isCaller, peerId, roomType, roomSecret);
|
||||||
this.rtcSupported = false;
|
this.rtcSupported = false;
|
||||||
if (!this._isCaller) return; // we will listen for a caller
|
if (!this._isCaller) return; // we will listen for a caller
|
||||||
this._sendSignal();
|
this._sendSignal();
|
||||||
|
@ -886,9 +886,9 @@ class PeersManager {
|
||||||
this.peers[peerId].onServerMessage(message);
|
this.peers[peerId].onServerMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
_refreshExistingPeer(peerId, roomType, roomSecret) {
|
_refreshPeer(peer, roomType, roomSecret) {
|
||||||
const peer = this.peers[peerId];
|
if (!peer) return false;
|
||||||
if (peer) {
|
|
||||||
const roomTypeIsSecret = roomType === "secret";
|
const roomTypeIsSecret = roomType === "secret";
|
||||||
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
|
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
|
||||||
|
|
||||||
|
@ -909,18 +909,29 @@ class PeersManager {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// peer does not yet exist: return false
|
|
||||||
return false;
|
_createOrRefreshPeer(isCaller, peerId, roomType, roomSecret, rtcSupported) {
|
||||||
|
const peer = this.peers[peerId];
|
||||||
|
if (peer) {
|
||||||
|
this._refreshPeer(peer, roomType, roomSecret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.isRtcSupported && rtcSupported) {
|
||||||
|
this.peers[peerId] = new RTCPeer(this._server,isCaller, peerId, roomType, roomSecret);
|
||||||
|
} else {
|
||||||
|
this.peers[peerId] = new WSPeer(this._server, isCaller, peerId, roomType, roomSecret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeerJoined(message) {
|
_onPeerJoined(message) {
|
||||||
if (this._refreshExistingPeer(message.peer.id, message.roomType, message.roomSecret)) return;
|
this._createOrRefreshPeer(false, message.peer.id, message.roomType, message.roomSecret, message.peer.rtcSupported);
|
||||||
|
|
||||||
if (window.isRtcSupported && message.sender.rtcSupported) {
|
|
||||||
this.peers[message.peer.id] = new RTCPeer(this._server, undefined, message.roomType, message.roomSecret);
|
|
||||||
} else {
|
|
||||||
this.peers[message.peer.id] = new WSPeer(this._server, undefined, message.roomType, message.roomSecret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onPeers(message) {
|
||||||
|
message.peers.forEach(peer => {
|
||||||
|
this._createOrRefreshPeer(true, peer.id, message.roomType, message.roomSecret, peer.rtcSupported);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWsRelay(message) {
|
_onWsRelay(message) {
|
||||||
|
@ -929,18 +940,6 @@ class PeersManager {
|
||||||
this.peers[messageJSON.sender.id]._onMessage(message);
|
this.peers[messageJSON.sender.id]._onMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeers(message) {
|
|
||||||
message.peers.forEach(messagePeer => {
|
|
||||||
if (this._refreshExistingPeer(messagePeer.id, message.roomType, message.roomSecret)) return;
|
|
||||||
|
|
||||||
if (window.isRtcSupported && messagePeer.rtcSupported) {
|
|
||||||
this.peers[messagePeer.id] = new RTCPeer(this._server, messagePeer.id, message.roomType, message.roomSecret);
|
|
||||||
} else {
|
|
||||||
this.peers[messagePeer.id] = new WSPeer(this._server, messagePeer.id, message.roomType, message.roomSecret);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRespondToFileTransferRequest(detail) {
|
_onRespondToFileTransferRequest(detail) {
|
||||||
this.peers[detail.to]._respondToFileTransferRequest(detail.accepted);
|
this.peers[detail.to]._respondToFileTransferRequest(detail.accepted);
|
||||||
}
|
}
|
||||||
|
@ -972,6 +971,15 @@ class PeersManager {
|
||||||
if (message.disconnect === true) {
|
if (message.disconnect === true) {
|
||||||
// if user actively disconnected from PairDrop server, disconnect all peer to peer connections immediately
|
// if user actively disconnected from PairDrop server, disconnect all peer to peer connections immediately
|
||||||
Events.fire('peer-disconnected', message.peerId);
|
Events.fire('peer-disconnected', message.peerId);
|
||||||
|
|
||||||
|
// If no peers are connected anymore, we can safely assume that no other tab on the same browser is connected:
|
||||||
|
// Tidy up peerIds in localStorage
|
||||||
|
if (Object.keys(this.peers).length === 0) {
|
||||||
|
BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerIds => {
|
||||||
|
if (!peerIds) return;
|
||||||
|
console.log("successfully removed other peerIds from localStorage");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,7 +1048,8 @@ class PeersManager {
|
||||||
_getPeerIdFromRoomSecret(roomSecret) {
|
_getPeerIdFromRoomSecret(roomSecret) {
|
||||||
for (const peerId in this.peers) {
|
for (const peerId in this.peers) {
|
||||||
const peer = this.peers[peerId];
|
const peer = this.peers[peerId];
|
||||||
if (peer._roomSecret === roomSecret) {
|
// peer must have same roomSecret and not be on the same browser.
|
||||||
|
if (peer._roomSecret === roomSecret && !peer._isSameBrowser()) {
|
||||||
return peer._peerId;
|
return peer._peerId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,8 +169,12 @@ class PeersUI {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer.sameBrowser = _ => BrowserTabsConnector.peerIsSameBrowser(peer.id);
|
peer.sameBrowser = _ => BrowserTabsConnector.peerIsSameBrowser(peer.id);
|
||||||
|
|
||||||
|
if (!(roomType === "secret" && peer.sameBrowser())) {
|
||||||
peer.roomTypes = [roomType];
|
peer.roomTypes = [roomType];
|
||||||
peer.roomSecret = roomSecret;
|
peer.roomSecret = roomSecret;
|
||||||
|
}
|
||||||
|
|
||||||
this.peers[peer.id] = peer;
|
this.peers[peer.id] = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,10 +1031,7 @@ class PairDeviceDialog extends Dialog {
|
||||||
|
|
||||||
_onWsConnected() {
|
_onWsConnected() {
|
||||||
this.$pairDeviceBtn.removeAttribute('hidden');
|
this.$pairDeviceBtn.removeAttribute('hidden');
|
||||||
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
|
||||||
Events.fire('room-secrets', roomSecrets);
|
|
||||||
this._evaluateNumberRoomSecrets();
|
this._evaluateNumberRoomSecrets();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_pairDeviceInitiate() {
|
_pairDeviceInitiate() {
|
||||||
|
@ -1973,13 +1974,18 @@ class PersistentStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getAllRoomSecrets() {
|
static async getAllRoomSecrets() {
|
||||||
|
try {
|
||||||
const roomSecrets = await this.getAllRoomSecretEntries();
|
const roomSecrets = await this.getAllRoomSecretEntries();
|
||||||
let secrets = [];
|
let secrets = [];
|
||||||
for (let i=0; i<roomSecrets.length; i++) {
|
for (let i = 0; i < roomSecrets.length; i++) {
|
||||||
secrets.push(roomSecrets[i].secret);
|
secrets.push(roomSecrets[i].secret);
|
||||||
}
|
}
|
||||||
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
||||||
return(secrets);
|
return(secrets);
|
||||||
|
} catch (e) {
|
||||||
|
this.logBrowserNotCapable();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getAllRoomSecretEntries() {
|
static getAllRoomSecretEntries() {
|
||||||
|
@ -2168,11 +2174,13 @@ class BrowserTabsConnector {
|
||||||
|
|
||||||
let peerIdsBrowser = [];
|
let peerIdsBrowser = [];
|
||||||
let peerIdsBrowserOld = JSON.parse(localStorage.getItem("peerIdsBrowser"));
|
let peerIdsBrowserOld = JSON.parse(localStorage.getItem("peerIdsBrowser"));
|
||||||
|
|
||||||
if (peerIdsBrowserOld) peerIdsBrowser.push(...peerIdsBrowserOld);
|
if (peerIdsBrowserOld) peerIdsBrowser.push(...peerIdsBrowserOld);
|
||||||
peerIdsBrowser.push(peerId);
|
peerIdsBrowser.push(peerId);
|
||||||
peerIdsBrowser = peerIdsBrowser.filter(onlyUnique);
|
peerIdsBrowser = peerIdsBrowser.filter(onlyUnique);
|
||||||
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
||||||
return peerId;
|
|
||||||
|
return peerIdsBrowser;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removePeerIdFromLocalStorage(peerId) {
|
static async removePeerIdFromLocalStorage(peerId) {
|
||||||
|
@ -2183,8 +2191,14 @@ class BrowserTabsConnector {
|
||||||
return peerId;
|
return peerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static removePeerIdsFromLocalStorage() {
|
|
||||||
localStorage.removeItem("peerIdsBrowser");
|
static async removeOtherPeerIdsFromLocalStorage() {
|
||||||
|
const peerId = sessionStorage.getItem("peerId");
|
||||||
|
if (!peerId) return false;
|
||||||
|
|
||||||
|
let peerIdsBrowser = [peerId];
|
||||||
|
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
|
||||||
|
return peerIdsBrowser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue