document.title = "Strapp.io Host" const conf = {"iceServers": [{ "urls": "stun:stun.1.google.com:19302" }] } const clients = new Map([]) const iceCandidates = [] let dataChannel let screenStream /* TODO: Remove if can access localStreams */ let tracks = [] let hpk /* TODO: duplicate in both client.js and host.jhs */ function getPublicKey() { return new Promise( (resolve, reject) => { /* Check local storage for public key */ if (!window.localStorage.getItem('public-key')) { console.log('public key is undefined') /* If doesn't exist, generate public and private key pair, store in local storage */ crypto.subtle.generateKey( { name:'RSA-OAEP', modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]), hash: {name: "SHA-256"} }, true, ['encrypt', 'decrypt'] ).then((keyPair) => { /* TODO: Do we need to store the private key as well? */ crypto.subtle.exportKey('jwk', keyPair.publicKey) .then((exportedKey) => { window.localStorage.setItem('publicKey', exportedKey) console.log('public key is' + window.localStorage.getItem('publicKey')) resolve(exportedKey) }) }) } else { resolve(window.localStorage.getItem('publicKey')) } }) } function sendClientICE(clientPubKey, hostPubKey, iceCandidate) { console.log('Host: Allocating ice candidate for client') console.log(iceCandidate) iceCandidates.push(JSON.stringify({ cmd: "< ice pubKey", ice: iceCandidate, hostPubKey: hostPubKey, /* TODO: do we need to send this? */ clientPubKey: clientPubKey, iceState: "a" })) } function handleNewClientConnection(pubKey, sdpOffer) { /* New Client Connection*/ hpc = new RTCPeerConnection(conf) console.log('handleNewClientConnections()') console.log(sdpOffer) clients.set(pubKey, hpc) console.log(pubKey) hpc.setRemoteDescription(sdpOffer) .then(() => { hpc.createAnswer().then((answer) => { return hpc.setLocalDescription(answer) }) .then(() => { hpc.onicecandidate = (event) => { if (event.candidate) { sendClientICE(pubKey, hpk.n, event.candidate) } else { console.log('Host: Finished allocating ICE candidates') } } console.log('Host: Sending answer to Client ') wsock.send(JSON.stringify({ cmd: '< sdp pubKey', sdp: hpc.localDescription, hostPubKey: hpk.n, clientPubKey: pubKey })) }).catch((err) => { console.log(`error in host answer ${err}`) }) }).catch((error) => { console.log(`error in setRemoteDescription ${error}`) }) hpc.oniceconnectionstatechange = () => { console.log('iceConnectionState = ' + hpc.iceConnectionState) } hpc.ondatachannel = (evt) => { dataChannel = evt.channel dataChannel.onmessage = (msg) => { let clientMessage = JSON.parse(msg.data) console.log(`client message is ${clientMessage}`) hpc.setRemoteDescription(clientMessage.sdp).then(() => { console.log('should be streaming now') }) } dataChannel.onopen = () => { /* If !screenStream, gUM */ screenStream.getTracks().forEach( (track) => { hpc.addTrack(track, screenStream) }) console.log(hpc.getSenders()) /* Create offer */ hpc.createOffer().then((offer) => { return hpc.setLocalDescription(offer) }).then( () => { dataChannel.send(JSON.stringify({ "cmd": "< screen dataChannel", "sdp": hpc.localDescription, "pubKey": hpc['hpk'].n })) }) } } hpc.onnegotiationneeded = () => { console.log('negotiation needed') } } function handleNewIceCandidate(msg) { console.log('Host: Adding new ice candidate') const hpc = clients.get(msg.pubKey) let candidate = new RTCIceCandidate(msg.ice) hpc.addIceCandidate(candidate) } function handleIceRequest(msg) { console.log('Host: Handling ice candidate request') console.log(iceCandidates) const hpc = clients.get(msg.pubKey) const iceCandidate = iceCandidates.pop() if (iceCandidate !== undefined) { wsock.send(iceCandidate) } else { if (hpc.iceGatheringState.localeCompare('gathering') === 0) { wsock.send(`{"cmd" : "< ice pubKey", "clientPubKey":"${msg.pubKey}", "iceState": "g"}`) } else if (hpc.iceGatheringState.localeCompare('complete') === 0) { wsock.send(`{"cmd" : "< ice pubKey", "clientPubKey":"${msg.pubKey}", "iceState": "c"}`) } } } if ("WebSocket" in window) { document.addEventListener('DOMContentLoaded', (event) => { document.body.innerHTML = '