[
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\ncommit_images\n"
  },
  {
    "path": "README.md",
    "content": "# react-native-webrtc-server\nThe signaling server for https://github.com/oney/react-native-webrtc   \nYou can checkout this demo https://github.com/oney/RCTWebRTCDemo  \nDemo server: https://react-native-webrtc.herokuapp.com/\n\n# Get started\n\n1. `npm install`\n2. `npm start`\n"
  },
  {
    "path": "app.js",
    "content": "var express = require('express');\nvar app = express();\nvar fs = require('fs');\nvar open = require('open');\nvar options = {\n  key: fs.readFileSync('./fake-keys/privatekey.pem'),\n  cert: fs.readFileSync('./fake-keys/certificate.pem')\n};\nvar serverPort = (process.env.PORT  || 4443);\nvar https = require('https');\nvar http = require('http');\nvar server;\nif (process.env.LOCAL) {\n  server = https.createServer(options, app);\n} else {\n  server = http.createServer(app);\n}\nvar io = require('socket.io')(server);\n\nvar roomList = {};\n\napp.get('/', function(req, res){\n  console.log('get /');\n  res.sendFile(__dirname + '/index.html');\n});\nserver.listen(serverPort, function(){\n  console.log('server up and running at %s port', serverPort);\n  if (process.env.LOCAL) {\n    open('https://localhost:' + serverPort)\n  }\n});\n\nfunction socketIdsInRoom(name) {\n  var socketIds = io.nsps['/'].adapter.rooms[name];\n  if (socketIds) {\n    var collection = [];\n    for (var key in socketIds) {\n      collection.push(key);\n    }\n    return collection;\n  } else {\n    return [];\n  }\n}\n\nio.on('connection', function(socket){\n  console.log('connection');\n  socket.on('disconnect', function(){\n    console.log('disconnect');\n    if (socket.room) {\n      var room = socket.room;\n      io.to(room).emit('leave', socket.id);\n      socket.leave(room);\n    }\n  });\n\n  socket.on('join', function(name, callback){\n    console.log('join', name);\n    var socketIds = socketIdsInRoom(name);\n    callback(socketIds);\n    socket.join(name);\n    socket.room = name;\n  });\n\n\n  socket.on('exchange', function(data){\n    console.log('exchange', data);\n    data.from = socket.id;\n    var to = io.sockets.connected[data.to];\n    to.emit('exchange', data);\n  });\n});\n"
  },
  {
    "path": "fake-keys/certificate.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIICjTCCAfYCCQC8xCdh8aBfxDANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC\nVVMxEzARBgNVBAgTCldhc2hpbmd0b24xETAPBgNVBAcTCFJpY2hsYW5kMQ0wCwYD\nVQQKFAQmeWV0MQswCQYDVQQLFAImITEVMBMGA1UEAxMMTmF0aGFuIEZyaXR6MSAw\nHgYJKoZIhvcNAQkBFhFuYXRoYW5AYW5keWV0Lm5ldDAeFw0xMTEwMTkwNjI2Mzha\nFw0xMTExMTgwNjI2MzhaMIGKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu\nZ3RvbjERMA8GA1UEBxMIUmljaGxhbmQxDTALBgNVBAoUBCZ5ZXQxCzAJBgNVBAsU\nAiYhMRUwEwYDVQQDEwxOYXRoYW4gRnJpdHoxIDAeBgkqhkiG9w0BCQEWEW5hdGhh\nbkBhbmR5ZXQubmV0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRKUxB1pLV\nRQ/dcUEP1p1oTIg0GoEvMPl6s7kC2Mroyovn/FaCzsgvwYhuwIeA6qgYoNIkSkXM\nQRmtfTpBvJNqM6A7jpUUmYuaUgqdrh5GZ5FGJjgAGIRJBWtovqxnCaHcmBYxlj0o\n/nxDmzgK655WBso7nwpixrzbsV3x7ZG45QIDAQABMA0GCSqGSIb3DQEBBQUAA4GB\nALeMY0Og6SfSNXzvATyR1BYSjJCG19AwR/vafK4vB6ejta37TGEPOM66BdtxH8J7\nT3QuMki9Eqid0zPATOttTlAhBeDGzPOzD4ohJu55PwY0jTJ2+qFUiDKmmCuaUbC6\nJCt3LWcZMvkkMfsk1HgyUEKat/Lrs/iaVU6TDMFa52v5\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "fake-keys/privatekey.pem",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDRKUxB1pLVRQ/dcUEP1p1oTIg0GoEvMPl6s7kC2Mroyovn/FaC\nzsgvwYhuwIeA6qgYoNIkSkXMQRmtfTpBvJNqM6A7jpUUmYuaUgqdrh5GZ5FGJjgA\nGIRJBWtovqxnCaHcmBYxlj0o/nxDmzgK655WBso7nwpixrzbsV3x7ZG45QIDAQAB\nAoGBAJQzUtkDlJ6QhKE+8f6q7nVMZOWmMgqiBOMwHNMrkPpJKcCCRzoAEk/kLSts\nN5bcraZlrQARsEr9hZgrtu+FEl1ROdKc6B3bJ5B6FigwY7m8/Z3+YdgwqV6NJGQk\n3twY4PoJEdeZ7GX2QnX8RDjyFvLaZ12jiDic30Nrn1gwvOCxAkEA9Dp5r9yg4DT/\nV4SE5+NPCJmeV7zwfW3XUQHWD4TaFbOCjnjWB/BnrrjXhvd3VNzwajrJvqq/UiM4\nbAG4VLz0CwJBANs+IYm3tYfeP5YsYJVMOJ5TcOAZ3T9jMF+QC9/ObwepW4D1woRr\nrCYxe01JyZpqqWnfeIUoJ70QL9uP8AgTrM8CQFFqGNymKL71C9XJ6GBA5zzPsPhA\nlM7LSgbIHOrJd8XaNIB4CalV28pj9f0ZC5+vkzlmZZB47RRdh1aB8EfXQWcCQGa8\nKI8WLNRsCrPeO6v6OZXHV99Lf2eSnTpKj6XiYBjg/WXiw7G1mseS7Ep9RyE61gQs\nmZccB/MKQMLMIhhGz/UCQQDog5KBVaMhwrw1hwZ5gDyZs2YrE75522BnAU1ajQj+\nVmTkcBwCtfnbXsWcHnYQnLlvz2Bi9ov2JncmJ5F1kiIw\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>react-native-webrtc server</title>\n  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n<div id=\"textRoom\" style=\"display: none;\">\n  <div id=\"textRoomContent\">\n    <h3>Text Room</h3>\n  </div>\n  <input id=\"textRoomInput\" >\n  <button onclick=\"textRoomPress();\">Send</button>\n</div>\n<video id=\"selfView\" autoplay></video>\n<div id=\"remoteViewContainer\"></div>\n<div id=\"roomIDContainer\">\n  <input id=\"roomID\" value=\"abc\">\n  <button onclick=\"press();\">Join/Create room</button>\n</div>\n</body>\n<script src=\"/socket.io/socket.io.js\"></script>\n<script type=\"text/javascript\">\nvar socket = io();\n\nvar RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;\nvar RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription || window.msRTCSessionDescription;\nnavigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia;\n\nvar twilioIceServers = [\n     { url: 'stun:global.stun.twilio.com:3478?transport=udp' }\n     // { url: 'turn:global.turn.twilio.com:3478?transport=udp',\n     //   username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',\n     //   credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' },\n     // { url: 'turn:global.turn.twilio.com:3478?transport=tcp',\n     //   username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',\n     //   credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' },\n     // { url: 'turn:global.turn.twilio.com:443?transport=tcp',\n     //   username: 'ea757ad2c42b932c7f2abe480295e7eb039dc2b13b78c86bc412818ed51e5eea',\n     //   credential: 'MPnnojPRoPDI+B3kLONGF9P440Lb8NkrTq+FxxJBVro=' } \n];\nvar configuration = {\"iceServers\": [{\"url\": \"stun:stun.l.google.com:19302\"}]};\n// configuration.iceServers = twilioIceServers;\n\nvar pcPeers = {};\nvar selfView = document.getElementById(\"selfView\");\nvar remoteViewContainer = document.getElementById(\"remoteViewContainer\");\nvar localStream;\n\nfunction getLocalStream() {\n  navigator.getUserMedia({ \"audio\": true, \"video\": true }, function (stream) {\n    localStream = stream;\n    selfView.src = URL.createObjectURL(stream);\n    selfView.muted = true;\n  }, logError);\n}\n\nfunction join(roomID) {\n  socket.emit('join', roomID, function(socketIds){\n    console.log('join', socketIds);\n    for (var i in socketIds) {\n      var socketId = socketIds[i];\n      createPC(socketId, true);\n    }\n  });\n}\n\nfunction createPC(socketId, isOffer) {\n  var pc = new RTCPeerConnection(configuration);\n  pcPeers[socketId] = pc;\n\n  pc.onicecandidate = function (event) {\n    console.log('onicecandidate', event);\n    if (event.candidate) {\n      socket.emit('exchange', {'to': socketId, 'candidate': event.candidate });\n    }\n  };\n\n  function createOffer() {\n    pc.createOffer(function(desc) {\n      console.log('createOffer', desc);\n      pc.setLocalDescription(desc, function () {\n        console.log('setLocalDescription', pc.localDescription);\n        socket.emit('exchange', {'to': socketId, 'sdp': pc.localDescription });\n      }, logError);\n    }, logError);\n  }\n\n  pc.onnegotiationneeded = function () {\n    console.log('onnegotiationneeded');\n    if (isOffer) {\n      createOffer();\n    }\n  }\n\n  pc.oniceconnectionstatechange = function(event) {\n    console.log('oniceconnectionstatechange', event);\n    if (event.target.iceConnectionState === 'connected') {\n      createDataChannel();\n    }\n  };\n  pc.onsignalingstatechange = function(event) {\n    console.log('onsignalingstatechange', event);\n  };\n\n  pc.onaddstream = function (event) {\n    console.log('onaddstream', event);\n    var element = document.createElement('video');\n    element.id = \"remoteView\" + socketId;\n    element.autoplay = 'autoplay';\n    element.src = URL.createObjectURL(event.stream);\n    remoteViewContainer.appendChild(element);\n  };\n  pc.addStream(localStream);\n  function createDataChannel() {\n    if (pc.textDataChannel) {\n      return;\n    }\n    var dataChannel = pc.createDataChannel(\"text\");\n\n    dataChannel.onerror = function (error) {\n      console.log(\"dataChannel.onerror\", error);\n    };\n\n    dataChannel.onmessage = function (event) {\n      console.log(\"dataChannel.onmessage:\", event.data);\n      var content = document.getElementById('textRoomContent');\n      content.innerHTML = content.innerHTML + '<p>' + socketId + ': ' + event.data + '</p>';\n    };\n\n    dataChannel.onopen = function () {\n      console.log('dataChannel.onopen');\n      var textRoom = document.getElementById('textRoom');\n      textRoom.style.display = \"block\";\n    };\n\n    dataChannel.onclose = function () {\n      console.log(\"dataChannel.onclose\");\n    };\n\n    pc.textDataChannel = dataChannel;\n  }\n  return pc;\n}\n\nfunction exchange(data) {\n  var fromId = data.from;\n  var pc;\n  if (fromId in pcPeers) {\n    pc = pcPeers[fromId];\n  } else {\n    pc = createPC(fromId, false);\n  }\n\n  if (data.sdp) {\n    console.log('exchange sdp', data);\n    pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () {\n      if (pc.remoteDescription.type == \"offer\")\n        pc.createAnswer(function(desc) {\n          console.log('createAnswer', desc);\n          pc.setLocalDescription(desc, function () {\n            console.log('setLocalDescription', pc.localDescription);\n            socket.emit('exchange', {'to': fromId, 'sdp': pc.localDescription });\n          }, logError);\n        }, logError);\n    }, logError);\n  } else {\n    console.log('exchange candidate', data);\n    pc.addIceCandidate(new RTCIceCandidate(data.candidate));\n  }\n}\n\nfunction leave(socketId) {\n  console.log('leave', socketId);\n  var pc = pcPeers[socketId];\n  pc.close();\n  delete pcPeers[socketId];\n  var video = document.getElementById(\"remoteView\" + socketId);\n  if (video) video.remove();\n}\n\nsocket.on('exchange', function(data){\n  exchange(data);\n});\nsocket.on('leave', function(socketId){\n  leave(socketId);\n});\n\nsocket.on('connect', function(data) {\n  console.log('connect');\n  getLocalStream();\n});\n\nfunction logError(error) {\n  console.log(\"logError\", error);\n}\n\nfunction press() {\n  var roomID = document.getElementById('roomID').value;\n  if (roomID == \"\") {\n    alert('Please enter room ID');\n  } else {\n    var roomIDContainer = document.getElementById('roomIDContainer');\n    roomIDContainer.parentElement.removeChild(roomIDContainer);\n    join(roomID);\n  }\n}\nfunction textRoomPress() {\n  var text = document.getElementById('textRoomInput').value;\n  if (text == \"\") {\n    alert('Enter something');\n  } else {\n    document.getElementById('textRoomInput').value = '';\n    var content = document.getElementById('textRoomContent');\n    content.innerHTML = content.innerHTML + '<p>' + 'Me' + ': ' + text + '</p>';\n    for (var key in pcPeers) {\n      var pc = pcPeers[key];\n      pc.textDataChannel.send(text);\n    }\n  }\n}\n\n</script>\n<script>\n  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){\n  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),\n  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)\n  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');\n\n  ga('create', 'UA-68314333-1', 'auto');\n  ga('send', 'pageview');\n\n</script>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-native-webrtc-server\",\n  \"version\": \"0.0.1\",\n  \"description\": \"react-native-webrtc server\",\n  \"main\": \"app.js\",\n  \"author\": \"Oney\",\n  \"engines\": {\n    \"node\": \"v4.1.0\"\n  },\n  \"scripts\": {\n    \"open\": \"heroku open\",\n    \"logs\": \"heroku logs --tail\",\n    \"deploy\": \"git push heroku master\",\n    \"start\": \"LOCAL=TRUE node app.js\"\n  },\n  \"dependencies\": {\n    \"express\": \"^4.11.2\",\n    \"open\": \"0.0.5\",\n    \"socket.io\": \"1.3.4\"\n  }\n}\n"
  }
]