diff --git a/src/y-webrtc.js b/src/y-webrtc.js index ec60230..91a77c3 100644 --- a/src/y-webrtc.js +++ b/src/y-webrtc.js @@ -174,6 +174,7 @@ export class WebrtcConn { log('establishing connection to ', logging.BOLD, remotePeerId) this.room = room this.remotePeerId = remotePeerId + this.glareToken = undefined this.closed = false this.connected = false this.synced = false @@ -182,7 +183,11 @@ export class WebrtcConn { */ this.peer = new Peer({ initiator, ...room.provider.peerOpts }) this.peer.on('signal', signal => { - publishSignalingMessage(signalingConn, room, { to: remotePeerId, from: room.peerId, type: 'signal', signal }) + if (this.glareToken === undefined) { + // add some randomness to the timestamp of the offer + this.glareToken = Date.now() + Math.random() + } + publishSignalingMessage(signalingConn, room, { to: remotePeerId, from: room.peerId, type: 'signal', token: this.glareToken, signal }) }) this.peer.on('connect', () => { log('connected to ', logging.BOLD, remotePeerId) @@ -515,6 +520,24 @@ export class SignalingConn extends ws.WebsocketClient { } break case 'signal': + if (data.signal.type === 'offer') { + const existingConn = webrtcConns.get(data.from) + if (existingConn) { + const remoteToken = data.token + const localToken = existingConn.glareToken + if (localToken && localToken > remoteToken) { + log('offer rejected: ', data.from) + return + } + // if we don't reject the offer, we will be accepting it and answering it + existingConn.glareToken = undefined + } + } + if (data.signal.type === 'answer') { + log('offer answered by: ', data.from) + const existingConn = webrtcConns.get(data.from) + existingConn.glareToken = undefined + } if (data.to === peerId) { map.setIfUndefined(webrtcConns, data.from, () => new WebrtcConn(this, false, data.from, room)).peer.signal(data.signal) emitPeerChange()