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

@ -17,7 +17,8 @@ class ServerConnection {
Events.on('pagehide', _ => this._disconnect());
document.addEventListener(window.visibilityChangeEvent, _ => this._onVisibilityChange());
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('regenerate-room-secret', e => this.send({ type: 'regenerate-room-secret', roomSecret: e.detail}));
Events.on('resend-peers', _ => this.send({ type: 'resend-peers'}));
@ -46,10 +47,6 @@ class ServerConnection {
if (this._isReconnect) Events.fire('notify-user', 'Connected.');
}
_sendRoomSecrets(roomSecrets) {
this.send({ type: 'room-secrets', roomSecrets: roomSecrets });
}
_onPairDeviceInitiate() {
if (!this._isConnected()) {
Events.fire('notify-user', 'You need to be online to pair devices.');
@ -143,10 +140,9 @@ class ServerConnection {
_onPeers(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");
BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerId => {
if (!peerId) return;
console.log("successfully removed other peerIds from localStorage");
});
}
}
@ -156,10 +152,16 @@ class ServerConnection {
sessionStorage.setItem("peerId", msg.message.peerId);
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 => {
if (peerId) return;
console.log("successfully added peerId from localStorage");
if (!peerId) return;
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);
@ -230,9 +232,9 @@ class ServerConnection {
class Peer {
constructor(serverConnection, peerId, roomType, roomSecret) {
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
this._server = serverConnection;
this._isCaller = !!peerId;
this._isCaller = isCaller;
this._peerId = peerId;
this._roomType = roomType;
this._updateRoomSecret(roomSecret);
@ -252,15 +254,14 @@ class Peer {
this.sendJSON({type: 'display-name-changed', displayName: displayName});
}
_isSameBrowser() {
return BrowserTabsConnector.peerIsSameBrowser(this._peerId);
}
_updateRoomSecret(roomSecret) {
// if peer is another browser tab, peer is not identifiable with roomSecret as browser tabs share all roomSecrets
// -> abort
if (BrowserTabsConnector.peerIsSameBrowser(this._peerId)) {
this._roomSecret = "";
return;
}
if (this._roomSecret && this._roomSecret !== roomSecret) {
// -> 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
PersistentStorage.deleteRoomSecret(this._roomSecret).then(deletedRoomSecret => {
if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret);
@ -269,7 +270,7 @@ class Peer {
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
console.log('RoomSecret is regenerated to increase security')
Events.fire('regenerate-room-secret', this._roomSecret);
@ -614,15 +615,15 @@ class Peer {
class RTCPeer extends Peer {
constructor(serverConnection, peerId, roomType, roomSecret) {
super(serverConnection, peerId, roomType, roomSecret);
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
super(serverConnection, isCaller, peerId, roomType, roomSecret);
this.rtcSupported = true;
if (!this._isCaller) return; // we will listen for a caller
this._connect(peerId, true);
this._connect();
}
_connect(peerId) {
if (!this._conn || this._conn.signalingState === "closed") this._openConnection(peerId);
_connect() {
if (!this._conn || this._conn.signalingState === "closed") this._openConnection();
if (this._isCaller) {
this._openChannel();
@ -631,8 +632,7 @@ class RTCPeer extends Peer {
}
}
_openConnection(peerId) {
this._peerId = peerId;
_openConnection() {
this._conn = new RTCPeerConnection(window.rtcConfig);
this._conn.onicecandidate = e => this._onIceCandidate(e);
this._conn.onicecandidateerror = e => this._onError(e);
@ -664,7 +664,7 @@ class RTCPeer extends Peer {
}
onServerMessage(message) {
if (!this._conn) this._connect(message.sender.id, false);
if (!this._conn) this._connect();
if (message.sdp) {
this._conn.setRemoteDescription(message.sdp)
@ -749,7 +749,7 @@ class RTCPeer extends Peer {
console.log('RTC: channel closed', this._peerId);
Events.fire('peer-disconnected', this._peerId);
if (!this._isCaller) return;
this._connect(this._peerId, true); // reopen the channel
this._connect(); // reopen the channel
}
_onConnectionStateChange() {
@ -800,7 +800,7 @@ class RTCPeer extends Peer {
// only reconnect if peer is caller
if (!this._isCaller) return;
this._connect(this._peerId);
this._connect();
}
_isConnected() {
@ -819,8 +819,8 @@ class RTCPeer extends Peer {
class WSPeer extends Peer {
constructor(serverConnection, peerId, roomType, roomSecret) {
super(serverConnection, peerId, roomType, roomSecret);
constructor(serverConnection, isCaller, peerId, roomType, roomSecret) {
super(serverConnection, isCaller, peerId, roomType, roomSecret);
this.rtcSupported = false;
if (!this._isCaller) return; // we will listen for a caller
this._sendSignal();
@ -886,41 +886,52 @@ class PeersManager {
this.peers[peerId].onServerMessage(message);
}
_refreshExistingPeer(peerId, roomType, roomSecret) {
const peer = this.peers[peerId];
if (peer) {
const roomTypeIsSecret = roomType === "secret";
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
_refreshPeer(peer, roomType, roomSecret) {
if (!peer) return false;
// if roomSecrets differs peer is already connected -> abort but update roomSecret and reevaluate auto accept
if (roomTypeIsSecret && roomSecretsDiffer) {
peer._updateRoomSecret(roomSecret);
peer._evaluateAutoAccept();
const roomTypeIsSecret = roomType === "secret";
const roomSecretsDiffer = peer._roomSecret !== roomSecret;
return true;
}
const roomTypesDiffer = peer._roomType !== roomType;
// if roomTypes differ peer is already connected -> abort
if (roomTypesDiffer) return true;
peer.refresh();
// if roomSecrets differs peer is already connected -> abort but update roomSecret and reevaluate auto accept
if (roomTypeIsSecret && roomSecretsDiffer) {
peer._updateRoomSecret(roomSecret);
peer._evaluateAutoAccept();
return true;
}
// peer does not yet exist: return false
return false;
const roomTypesDiffer = peer._roomType !== roomType;
// if roomTypes differ peer is already connected -> abort
if (roomTypesDiffer) return true;
peer.refresh();
return true;
}
_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) {
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) {
@ -929,18 +940,6 @@ class PeersManager {
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) {
this.peers[detail.to]._respondToFileTransferRequest(detail.accepted);
}
@ -972,6 +971,15 @@ class PeersManager {
if (message.disconnect === true) {
// if user actively disconnected from PairDrop server, disconnect all peer to peer connections immediately
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) {
for (const peerId in this.peers) {
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;
}
}