adding test files
[henge/kiak.git] / host.js
1 document.title = "Strapp.io Host"
2
3
4 const conf = {"iceServers": [{ "urls": "stun:stun.1.google.com:19302" }] }
5 const clients = new Map([])
6 const iceCandidates = []
7 let dataChannel
8 let screenStream /* TODO: Remove if can access localStreams */
9 let tracks = []
10 let hpk
11
12 /* TODO: duplicate in both client.js and host.jhs */
13 function getPublicKey() {
14 return new Promise( (resolve, reject) => {
15 /* Check local storage for public key */
16 if (!window.localStorage.getItem('public-key')) {
17 console.log('public key is undefined')
18 /* If doesn't exist, generate public and private key pair, store in
19 local storage */
20 crypto.subtle.generateKey(
21 { name:'RSA-OAEP',
22 modulusLength: 2048,
23 publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
24 hash: {name: "SHA-256"}
25 },
26 true,
27 ['encrypt', 'decrypt']
28 ).then((keyPair) => {
29 /* TODO: Do we need to store the private key as well? */
30 crypto.subtle.exportKey('jwk', keyPair.publicKey)
31 .then((exportedKey) => {
32 window.localStorage.setItem('publicKey', exportedKey)
33 console.log('public key is' + window.localStorage.getItem('publicKey'))
34 resolve(exportedKey)
35 })
36
37 })
38 }
39 else {
40 resolve(window.localStorage.getItem('publicKey'))
41 }
42 })
43 }
44
45 function sendClientICE(clientPubKey, hostPubKey, iceCandidate) {
46 console.log('Host: Allocating ice candidate for client')
47 console.log(iceCandidate)
48 iceCandidates.push(JSON.stringify({
49 cmd: "< ice pubKey",
50 ice: iceCandidate,
51 hostPubKey: hostPubKey, /* TODO: do we need to send this? */
52 clientPubKey: clientPubKey,
53 iceState: "a"
54 }))
55 }
56
57 function handleNewClientConnection(offer) {
58 /* New Client Connection*/
59 hpc = new RTCPeerConnection(conf)
60 //console.log(offer)
61 clients.set(offer.pubKey, hpc)
62 hpc.setRemoteDescription(offer.sdp)
63 .then(() => {
64 hpc.createAnswer().then((answer) => {
65 return hpc.setLocalDescription(answer)
66 })
67 .then(() => {
68
69 hpc.onicecandidate = (event) => {
70 if (event.candidate) {
71 sendClientICE(offer.pubKey, hpk.n, event.candidate)
72 }
73 else {
74 console.log('Host: Finished allocating ICE candidates')
75 }
76 }
77 console.log('Host: Sending answer to Client ')
78 wsock.send(JSON.stringify({
79 cmd: '< sdp pubKey',
80 sdp: hpc.localDescription,
81 hostPubKey: hpk.n,
82 clientPubKey: offer.pubKey
83 }))
84
85 }).catch((err) => {
86 console.log(`error in host answer ${err}`)
87 })
88 })
89 hpc.oniceconnectionstatechange = () => {
90 console.log('iceConnectionState = ' + hpc.iceConnectionState)
91 }
92 hpc.ondatachannel = (evt) => {
93 dataChannel = evt.channel
94 dataChannel.onmessage = (msg) => {
95 let clientMessage = JSON.parse(msg.data)
96 console.log(`client message is ${clientMessage}`)
97 hpc.setRemoteDescription(clientMessage.sdp).then(() => {
98 console.log('should be streaming now')
99 })
100 }
101 dataChannel.onopen = () => {
102 /* If !screenStream, gUM */
103 screenStream.getTracks().forEach( (track) => {
104 hpc.addTrack(track, screenStream)
105 })
106 console.log(hpc.getSenders())
107 /* Create offer */
108 hpc.createOffer().then((offer) => {
109 return hpc.setLocalDescription(offer)
110 }).then( () => {
111 dataChannel.send(JSON.stringify({
112 "cmd": "< screen dataChannel",
113 "sdp": hpc.localDescription,
114 "pubKey": hpc['hpk'].n
115 }))
116 })
117 }
118 }
119 hpc.onnegotiationneeded = () => {
120 console.log('negotiation needed')
121 }
122
123 }
124
125 function handleNewIceSubmission(msg) {
126 console.log('Host: Adding new ice candidate')
127 const hpc = clients.get(msg.pubKey)
128 let candidate = new RTCIceCandidate(msg.ice)
129 hpc.addIceCandidate(candidate)
130 }
131
132 function handleIceRequest(msg) {
133 console.log('Host: Handling ice candidate request')
134 console.log(iceCandidates)
135 const hpc = clients.get(msg.pubKey)
136 const iceCandidate = iceCandidates.pop()
137 if (iceCandidate !== undefined) {
138 wsock.send(iceCandidate)
139 } else {
140 if (hpc.iceGatheringState.localeCompare('gathering') === 0) {
141 wsock.send(`{"cmd" : "< ice pubKey", "clientPubKey":"${msg.pubKey}", "iceState": "g"}`)
142 }
143 else if (hpc.iceGatheringState.localeCompare('complete') === 0) {
144 wsock.send(`{"cmd" : "< ice pubKey", "clientPubKey":"${msg.pubKey}", "iceState": "c"}`)
145 }
146
147 }
148
149 }
150 if ("WebSocket" in window) {
151 document.addEventListener('DOMContentLoaded', (event) => {
152 document.body.innerHTML = '<div>Choose options for client</div> <video autoplay></video>'
153 navigator.mediaDevices.getUserMedia({
154 video : { mediaSource: "screen",
155 width: {max: '1920'},
156 height: {max: '1080'},
157 frameRate: {max: '10'}} })
158 .then(function(mediaStream) {
159 let video = document.querySelector('video')
160 screenStream = mediaStream
161 console.log(mediaStream)
162 video.srcObject = mediaStream
163 console.log('Grabbed media')
164 video.onloadedmetadata = function(e) {
165 console.log(e)
166 video.play()
167 }
168 })
169 .catch(function(err) {
170 document.body.innerHTML = 'Help me help you. Reload the page and allow screen sharing!'
171 console.log(err);
172 }); // always check for errors at the end.
173
174 getPublicKey()
175 .then((hpkVal) => {
176 hpk = hpkVal
177 })
178 wsock = new WebSocket(`${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
179 wsock.onopen = () => {
180 console.log(`Strapped to ${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
181 }
182
183 wsock.onmessage = (serverMsg) => {
184 /* msg is either offer or ice candidate or ice candidate request*/
185
186 /* What if data null? */
187 console.log(`serverMsg = ${serverMsg.data}`)
188 let msg = JSON.parse(serverMsg.data)
189
190 const clientID = msg.pubKey
191
192 /* TODO: redo this trash */
193 if (clients.has(clientID)) {
194 if (msg.ice) {
195 handleNewIceSubmission(msg)
196 } else if (msg.sdp) {
197 //handleRepeatedOffer
198 } else {
199 handleIceRequest(msg)
200 }
201 }
202 else {
203 if (msg.ice) {
204 console.log('Host: Client that doesnt exist is sending ice submissions')
205 } else if (msg.sdp) {
206 handleNewClientConnection(msg)
207 } else {
208 console.log('Host: Client that doesnt exist is sending ice requests')
209 }
210 }
211 }
212
213
214
215 })
216 }
217 else {
218 document.addEventListener('DOMContentLoaded', () => {
219 document.body.innerHTML = 'Websockets not supported in your browser'
220 })
221 }