fix check whether peer is same browser

This commit is contained in:
schlagmichdoch 2023-05-11 21:04:10 +02:00
parent ae9909f596
commit 347f9b87c0
5 changed files with 213 additions and 167 deletions

View file

@ -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;

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }

View file

@ -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;
} }
} }