need to do ICE step
[henge/kiak.git] / client.js
1 const body = document.createElement('body')
2 const root = document.createElement('div')
3 document.title = "Strapp.io Client"
4 body.appendChild(root)
5 document.body = body
6 const conf = {"iceServers": [{ "url": "stun:stun.1.google.com:19302" }] }
7 /* Poll the server. Send get request, wait for timeout, send another request.
8 Do this until...? Can be used for either reconnecting or waiting for answer*/
9 function pollServerTimeout(url, data, resolve, reject) {
10 console.log(`Polling server ${url} with ${data}`)
11 const request = new XMLHttpRequest()
12 request.open('GET', url, true)
13 request.setRequestHeader('Content-Type', 'application/json' )
14 request.setRequestHeader('X-Strapp-Type', JSON.stringify(data))
15 request.onreadystatechange = () => {
16 if (request.status === 200) {
17 if(request.readyState === 4) {
18 console.log('Client: Recieved answer from Host')
19 console.log(request)
20 resolve(request.response)
21 }
22 }
23 else if (request.status === 504) {
24 console.log('timed out, resending')
25 pollServerTimeout(url, data, resolve, reject)
26 }
27 else {
28 reject('server unhandled response of status ' + request.status)
29 }
30 }
31 request.send()
32 }
33
34 /* TODO: All this does is wrap a function in a promise */
35 function pollServer(url, clientPubKey, func) {
36 return new Promise((resolve, reject) => {
37 func(url, clientPubKey, resolve, reject )
38 })
39 }
40
41 /* TODO: duplicate in both client.js and host.js */
42 function getPublicKey() {
43 return new Promise( (resolve, reject) => {
44 /* Check local storage for public key */
45 if (!window.localStorage.getItem('public-key')) {
46 console.log('public key is undefined')
47 /* If doesn't exist, generate public and private key pair, store in
48 local storage */
49 crypto.subtle.generateKey(
50 { name:'RSA-OAEP',
51 modulusLength: 2048,
52 publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
53 hash: {name: "SHA-256"}
54 },
55 true,
56 ['encrypt', 'decrypt']
57 ).then((keyPair) => {
58 /* TODO: Do we need to store the private key as well? */
59 crypto.subtle.exportKey('jwk', keyPair.publicKey)
60 .then((exportedKey) => {
61 window.localStorage.setItem('publicKey', exportedKey)
62 console.log('public key is' + window.localStorage.getItem('publicKey'))
63 resolve(exportedKey)
64 })
65
66 })
67 }
68 else {
69 resolve(window.localStorage.getItem('publicKey'))
70 }
71 })
72
73 }
74
75 /* Create, set, and get client Offer. Poll server for host answer.
76 Set host answer as client remoteDescription */
77 const cpc = new RTCPeerConnection(conf)
78 cpc.oniceconnectionstatechange = () => {
79 console.log('iceConnectionState = ' + cpc.iceConnectionState)
80 }
81 cpc.createOffer().then((offer) => {
82 return cpc.setLocalDescription(offer)
83 })
84 .then(() => {
85 console.log('sessionDescriptionInit = ' + cpc.localDescription)
86 getPublicKey().then((cpk) => {
87 console.log('cpk is' + cpk)
88 let offer = {
89 cmd: '> sdp pubKey',
90 sdp: cpc.localDescription,
91 pubKey: cpk
92 }
93 cpc.onicecandidate = (event) => {
94 if (event.candidate) {
95 console.log('Client: Sending ice candidate to host')
96 pollServer(window.location, wsock.send(JSON.stringify({
97 cmd: '> ice pubkey',
98 ice: event.candidate,
99 pubKey: cpk /* TODO: do we need to send this? */
100 })), pollServerTimeout)
101 }
102 else {
103 /* Set up data channel here */
104 console.log('Client: Finished setting up ICE candidates')
105 }
106 }
107 /* TODO: start polling for ice candidates, and then addIceCandidate() to cpc */
108 //pollServer(window.location, {ice}, pollServerTimeout)
109
110
111 /* Poll for answer */
112 return pollServer(window.location, offer, pollServerTimeout)
113 }).then((serverResponse) => {
114 const answer = JSON.parse(serverResponse)
115 console.log(answer)
116 /* TODO: State machine to parse answer */
117 console.log('Setting Remote Description')
118 cpc.setRemoteDescription(answer.sdp)
119 }).catch( (err) => {
120 console.log('error in sdp handshake: ' + err)
121 })
122 }).catch((err) => {
123 console.log(err)
124 })