need to do ICE step
authorjordan lavatai <jordanlavatai@gmail.com>
Sat, 1 Jul 2017 06:54:54 +0000 (23:54 -0700)
committerjordan lavatai <jordanlavatai@gmail.com>
Sat, 1 Jul 2017 06:54:54 +0000 (23:54 -0700)
client.js
host.js
main.js

index 8813f55..d389945 100644 (file)
--- a/client.js
+++ b/client.js
@@ -3,20 +3,22 @@ const root = document.createElement('div')
 document.title = "Strapp.io Client"
 body.appendChild(root)
 document.body = body
-
+const conf = {"iceServers": [{ "url": "stun:stun.1.google.com:19302" }] }
 /* Poll the server. Send get request, wait for timeout, send another request.
    Do this until...? Can be used for either reconnecting or waiting for answer*/
 function pollServerTimeout(url, data, resolve, reject) {
-  console.log(`Polling server ${url} with`)
-  console.log(data)
+  console.log(`Polling server ${url} with ${data}`)
   const request = new XMLHttpRequest()
   request.open('GET', url, true)
   request.setRequestHeader('Content-Type', 'application/json' )
   request.setRequestHeader('X-Strapp-Type', JSON.stringify(data))
   request.onreadystatechange = () => {
     if (request.status === 200) {
-      console.log(request.response)
-      resolve(request.response)
+      if(request.readyState === 4) {
+        console.log('Client: Recieved answer from Host')
+        console.log(request)
+        resolve(request.response)
+      }
     }
     else if (request.status === 504) {
       console.log('timed out, resending')
@@ -26,7 +28,6 @@ function pollServerTimeout(url, data, resolve, reject) {
       reject('server unhandled response of status ' + request.status)
     }
   }
-  console.log(data)
   request.send()
 }
 
@@ -73,8 +74,10 @@ function getPublicKey() {
 
 /* Create, set, and get client Offer. Poll server for host answer.
    Set host answer as client remoteDescription */
-const cpc = new RTCPeerConnection()
-console.log('creating offer')
+const cpc = new RTCPeerConnection(conf)
+cpc.oniceconnectionstatechange = () => {
+  console.log('iceConnectionState = ' + cpc.iceConnectionState)
+}
 cpc.createOffer().then((offer) => {
   return cpc.setLocalDescription(offer)
 })
@@ -87,16 +90,35 @@ cpc.createOffer().then((offer) => {
       sdp: cpc.localDescription,
       pubKey: cpk
     }
+    cpc.onicecandidate = (event) => {
+      if (event.candidate) {
+        console.log('Client: Sending ice candidate to host')
+        pollServer(window.location, wsock.send(JSON.stringify({
+          cmd: '> ice pubkey',
+          ice: event.candidate,
+          pubKey: cpk /* TODO: do we need to send this? */
+        })), pollServerTimeout)
+      }
+      else {
+        /* Set up data channel here */
+        console.log('Client: Finished setting up ICE candidates')
+      }
+    }
+    /* TODO: start polling for ice candidates, and then addIceCandidate() to cpc */
+    //pollServer(window.location, {ice}, pollServerTimeout)
+
+
     /* Poll for answer */
     return pollServer(window.location, offer, pollServerTimeout)
-  }).then((answer) => {
-    //console.log(answer)
+  }).then((serverResponse) => {
+    const answer = JSON.parse(serverResponse)
+    console.log(answer)
     /* TODO: State machine to parse answer */
+    console.log('Setting Remote Description')
     cpc.setRemoteDescription(answer.sdp)
   }).catch( (err) => {
     console.log('error in sdp handshake: ' + err)
   })
-})
-  .catch((err) => {
+}).catch((err) => {
     console.log(err)
-  })
+})
diff --git a/host.js b/host.js
index dd48d10..34d7c9d 100644 (file)
--- a/host.js
+++ b/host.js
 document.title = "Strapp.io Host"
-const clients = [] //TODO: Change to Map
-if ("WebSocket" in window) {
-  document.addEventListener('DOMContentLoaded', (event) => {
-    const wsock = new WebSocket(`${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
-    wsock.onopen = () => {
-      console.log(`Strapped to ${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
+const conf = {"iceServers": [{ "url": "stun:stun.1.google.com:19302" }] }
+const clients = new Map([])
+const hpk = getPublicKey()
+
+/* 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'))
     }
-    wsock.onmessage = (msg) => {
-      /* Message is offer from client */
-      /* TODO: Determine which client ?? */
-      console.log("Incoming connection " + msg)
-
-      /* TODO: State machine to parse offer */
-
-      /* New Client Connection*/
-      hpc = new RTCPeerConnection()
-
-      hpc.createAnswer().then((offer) => {
-        return hpc.setLocalDescription(offer)
-      }).then(() => {
-        return hpc.setRemoteDescription(msg.sdp)
-      }).then(() => {
-        const hpk = getPublicKey()
-        wsock.send({
+  })
+}
+
+
+function handleNewClientConnection(offer) {
+  /* New Client Connection*/
+  hpc = new RTCPeerConnection(conf)
+  hpc.setRemoteDescription(offer.sdp)
+  .then(() => {
+    hpc.createAnswer().then((answer) => {
+      return hpc.setLocalDescription(answer)
+    })
+    .then(() => {
+      hpk.then(() => {
+        hpc.onicecandidate = (event) => {
+          if (event.candidate) {
+            console.log('Host: Sending ice candidate to client')
+            wsock.send(JSON.stringify({
+              cmd: '< ice pubKey',
+              ice: event.candidate,
+              pubKey: hpk /* TODO: do we need to send this? */
+            }))
+          }
+          else {
+            console.log('Host: Finished setting up ICE candidates')
+          }
+        }
+        console.log('Host: Sending answer to Host')
+        wsock.send(JSON.stringify({
           cmd: '< sdp pubKey',
           sdp: hpc.localDescription,
           pubKey: hpk
-        })
-        clients.push({
+        }))
+        clients.set(offer.pubKey, {
           hostsdp: hpc.localDescription,
-          clientsdp: hpc.remoteDescription,
-          clientPubKey: msg.pubKey
+          clientsdp: hpc.remoteDescription
         })
 
       })
+    }).catch((err) => {
+      console.log(`error in host answer ${err}`)
+    })
+  })
+}
+
+function handleNewIceCandidate(msg) {
+  const hpc = clients.get(msg.pubKey)
+  let candidate = new RTCIceCandidate(msg.ice)
+  hpc.addIceCandidate(candidate)
+}
+
+if ("WebSocket" in window) {
+  document.addEventListener('DOMContentLoaded', (event) => {
+    wsock = new WebSocket(`${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
+    wsock.onopen = () => {
+      console.log(`Strapped to ${_strapp_protocol}://${window.location.hostname}:${_strapp_port}`)
+    }
+
+    wsock.onmessage = (serverMsg) => {
+      /* msg is either offer or ice candidate */
+      console.log(serverMsg.data)
+      let msg = JSON.parse(serverMsg.data)
+
+      const clientID = msg.pubKey
+      const msgType = msg.hasOwnProperty('sdp') ? 'o' : 'i'
+      if (clients.has(clientID)) {
+        switch(msgType) {
+          case 'o':
+          console.log('client exist && sending an offer == error')
+          break
+          case 'i':
+          handleNewIceCandidate(msg)
+          break
+        }
+      }
+      else {
+        switch(msgType) {
+          case 'o':
+          handleNewClientConnection(msg)
+          break
+          case 'i':
+          console.log('client !exist && ice candidate === error')
+          break
+        }
+      }
     }
   })
 }
@@ -43,18 +126,3 @@ else {
     document.body.innerHTML = 'Websockets not supported in your browser'
   })
 }
-/* TODO: duplicate in both client.js and host.jhs */
-function getPublicKey() {
-  /* Check local storage for public key */
-  if (window.localStorage.getItem('public-key') === undefined) {
-    /* If doesn't exist, generate public and private key pair, store in
-    local storage */
-    crypto.subtle.generateKey({name:'RSA-OAEP', length: 192}, true, ['encrypt', 'decrypt'])
-      .then((keyPair) => {
-        /* TODO: Do we need to store the private key as well? */
-        window.localStorage.setItem('public-key', keyPair.type.public.toString())
-      })
-  }
-    console.log(window.localStorage.getItem('public-key'))
-    return window.localStorage.getItem('public-key')
-}
diff --git a/main.js b/main.js
index f123a41..35cffef 100644 (file)
--- a/main.js
+++ b/main.js
@@ -25,15 +25,6 @@ const router = {
   httpd:      undefined,
   wsProtocol: opts['no-tls'] ? 'ws' : 'wss',
   respond:    (request,response) => {
-    let body = []
-    request.on('error', function(err) {
-      console.error(`error is ${err}`);
-    }).on('data', function(chunk) {
-      console.log(`chunk is ${chunk}`)
-      body.push(chunk);
-    }).on('end', function() {
-      console.log(`body is ${body}`)
-    })
     console.log('server handling request')
     const serveFile = (fPath) => {
       fs.readFile(fPath, { encoding: 'utf8' }, (err, data) => {
@@ -82,9 +73,15 @@ const router = {
         //      (this happens when a client connects to an active route with no currently-online host)
       }
       else { /* Client sent offer, waiting for answer */
-        console.log(JSON.parse(request.headers['x-strapp-type']))
+        console.log('Server: Sending client offer to host')
+        route.socket.send(request.headers['x-strapp-type'])
         route.socket.on('message', (hostResponse) => {
+          console.log('Server: Sending host answer to client')
           console.log(hostResponse)
+          response.writeHead(200, { 'Content-Type': 'application/json' })
+          response.write(hostResponse)
+          response.end()
+
         })
       }