From 150771a4c20f5612e4ae8f4f0c2f62dd8d8b2fa9 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 22:51:17 +0800 Subject: [PATCH 01/13] change to es6 syntax with airbnb aslant coding style --- .eslintrc | 3 +++ app.js | 73 ++++++++++++++++++++++++++-------------------------- package.json | 7 +++++ test.js | 1 + 4 files changed, 47 insertions(+), 37 deletions(-) create mode 100644 .eslintrc create mode 100644 test.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e89ba50 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "airbnb" +} \ No newline at end of file diff --git a/app.js b/app.js index bd95ff3..2d2bce1 100644 --- a/app.js +++ b/app.js @@ -1,72 +1,71 @@ -var express = require('express'); -var app = express(); -var fs = require('fs'); -var open = require('open'); -var options = { +'use strict'; + +const express = require('express'); +const app = express(); +const fs = require('fs'); +const open = require('open'); +const options = { key: fs.readFileSync('./fake-keys/privatekey.pem'), - cert: fs.readFileSync('./fake-keys/certificate.pem') + cert: fs.readFileSync('./fake-keys/certificate.pem'), }; -var serverPort = (process.env.PORT || 4443); -var https = require('https'); -var http = require('http'); -var server; +const serverPort = (process.env.PORT || 4443); +const https = require('https'); +const http = require('http'); +let server; if (process.env.LOCAL) { server = https.createServer(options, app); } else { server = http.createServer(app); } -var io = require('socket.io')(server); +const io = require('socket.io')(server); -var roomList = {}; +const socketIdsInRoom = (name) => { + const socketIds = io.nsps['/'].adapter.rooms[name]; + if (socketIds) { + const collection = []; + for (const key in socketIds) { + collection.push(key); + } + return collection; + } + return []; +}; -app.get('/', function(req, res){ +app.get('/', (req, res) => { console.log('get /'); - res.sendFile(__dirname + '/index.html'); + res.sendFile(`${__dirname}/index.html`); }); -server.listen(serverPort, function(){ + +server.listen(serverPort, () => { console.log('server up and running at %s port', serverPort); if (process.env.LOCAL) { - open('https://localhost:' + serverPort) + open(`https://localhost: ${serverPort}`); } }); -function socketIdsInRoom(name) { - var socketIds = io.nsps['/'].adapter.rooms[name]; - if (socketIds) { - var collection = []; - for (var key in socketIds) { - collection.push(key); - } - return collection; - } else { - return []; - } -} - -io.on('connection', function(socket){ +io.on('connection', (socket) => { console.log('connection'); - socket.on('disconnect', function(){ + socket.on('disconnect', () => { console.log('disconnect'); if (socket.room) { - var room = socket.room; + const room = socket.room; io.to(room).emit('leave', socket.id); socket.leave(room); } }); - socket.on('join', function(name, callback){ + socket.on('join', (name, callback) => { console.log('join', name); - var socketIds = socketIdsInRoom(name); + const socketIds = socketIdsInRoom(name); callback(socketIds); socket.join(name); socket.room = name; }); - - socket.on('exchange', function(data){ + socket.on('exchange', (data) => { console.log('exchange', data); data.from = socket.id; - var to = io.sockets.connected[data.to]; + const to = io.sockets.connected[data.to]; to.emit('exchange', data); }); }); diff --git a/package.json b/package.json index 817e379..3c0b8bb 100644 --- a/package.json +++ b/package.json @@ -17,5 +17,12 @@ "express": "^4.11.2", "open": "0.0.5", "socket.io": "1.3.4" + }, + "devDependencies": { + "eslint": "^2.10.2", + "eslint-config-airbnb": "^9.0.1", + "eslint-plugin-import": "^1.10.2", + "eslint-plugin-jsx-a11y": "^1.5.5", + "eslint-plugin-react": "^5.2.2" } } diff --git a/test.js b/test.js new file mode 100644 index 0000000..fa1be37 --- /dev/null +++ b/test.js @@ -0,0 +1 @@ +console.log(`${__dirname}/index.html`); From 5e7c7d231a65f289d726143f671fc49b9638493b Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 22:54:56 +0800 Subject: [PATCH 02/13] test for index.html --- app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app.js b/app.js index 2d2bce1..61c27a7 100644 --- a/app.js +++ b/app.js @@ -18,6 +18,7 @@ if (process.env.LOCAL) { server = http.createServer(app); } const io = require('socket.io')(server); +app.use(express.static(__dirname)); const socketIdsInRoom = (name) => { const socketIds = io.nsps['/'].adapter.rooms[name]; From aa97bba72c9e19f11983f57da952b37381dc6926 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:05:15 +0800 Subject: [PATCH 03/13] change package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c0b8bb..0a20ae0 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "open": "heroku open", "logs": "heroku logs --tail", "deploy": "git push heroku master", - "start": "LOCAL=TRUE node app.js" + "start:local": "LOCAL=TRUE node app.js", + "start": "node app.js", }, "dependencies": { "express": "^4.11.2", From 3995b70117d074252991e134cabd3c0a5d2a8166 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:08:42 +0800 Subject: [PATCH 04/13] remove trailing comma --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a20ae0..6c48279 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "logs": "heroku logs --tail", "deploy": "git push heroku master", "start:local": "LOCAL=TRUE node app.js", - "start": "node app.js", + "start": "node app.js" }, "dependencies": { "express": "^4.11.2", From 55f2f38f57b88ae21cf0f523099b6c4d25fd3c78 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:20:55 +0800 Subject: [PATCH 05/13] guard-for-in --- app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index 61c27a7..e5376b5 100644 --- a/app.js +++ b/app.js @@ -25,7 +25,9 @@ const socketIdsInRoom = (name) => { if (socketIds) { const collection = []; for (const key in socketIds) { - collection.push(key); + if ({}.hasOwnProperty.call(socketIds, key)) { + collection.push(key); + } } return collection; } From 248a44f1f484aeeb26396d753c1969350027ed66 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:23:11 +0800 Subject: [PATCH 06/13] remove test.js --- test.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.js diff --git a/test.js b/test.js deleted file mode 100644 index fa1be37..0000000 --- a/test.js +++ /dev/null @@ -1 +0,0 @@ -console.log(`${__dirname}/index.html`); From 0ec36d3b170ebaa812d1fde3b97f8e8532139602 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:24:51 +0800 Subject: [PATCH 07/13] change file name --- package.json | 4 ++-- app.js => server.js | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename app.js => server.js (100%) diff --git a/package.json b/package.json index 6c48279..e691d77 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "open": "heroku open", "logs": "heroku logs --tail", "deploy": "git push heroku master", - "start:local": "LOCAL=TRUE node app.js", - "start": "node app.js" + "start:local": "LOCAL=TRUE node server.js", + "start": "node server.js" }, "dependencies": { "express": "^4.11.2", diff --git a/app.js b/server.js similarity index 100% rename from app.js rename to server.js From ad5da88350562cd67cddafa973e940c10b543cfb Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Sat, 16 Jul 2016 23:39:30 +0800 Subject: [PATCH 08/13] first commit --- app.js | 188 +++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 202 +---------------------------------------------------- 2 files changed, 189 insertions(+), 201 deletions(-) create mode 100644 app.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..47806b5 --- /dev/null +++ b/app.js @@ -0,0 +1,188 @@ +const socket = io(); +const RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || + window.webkitRTCPeerConnection || window.msRTCPeerConnection; +const RTCSessionDescription = window.RTCSessionDescription || + window.mozRTCSessionDescription || window.webkitRTCSessionDescription || + window.msRTCSessionDescription; +navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || + navigator.webkitGetUserMedia || navigator.msGetUserMedia; + +const configuration = { 'iceServers': [{ 'url': 'stun:stun.l.google.com:19302' }] }; + +var pcPeers = {}; +var selfView = document.getElementById("selfView"); +var remoteViewContainer = document.getElementById("remoteViewContainer"); +var localStream; + +function getLocalStream() { + navigator.getUserMedia({ "audio": true, "video": true }, function (stream) { + localStream = stream; + selfView.src = URL.createObjectURL(stream); + selfView.muted = true; + }, logError); +} + +function join(roomID) { + socket.emit('join', roomID, function(socketIds){ + console.log('join', socketIds); + for (var i in socketIds) { + var socketId = socketIds[i]; + createPC(socketId, true); + } + }); +} + +function createPC(socketId, isOffer) { + var pc = new RTCPeerConnection(configuration); + pcPeers[socketId] = pc; + + pc.onicecandidate = function (event) { + console.log('onicecandidate', event); + if (event.candidate) { + socket.emit('exchange', {'to': socketId, 'candidate': event.candidate }); + } + }; + + function createOffer() { + pc.createOffer(function(desc) { + console.log('createOffer', desc); + pc.setLocalDescription(desc, function () { + console.log('setLocalDescription', pc.localDescription); + socket.emit('exchange', {'to': socketId, 'sdp': pc.localDescription }); + }, logError); + }, logError); + } + + pc.onnegotiationneeded = function () { + console.log('onnegotiationneeded'); + if (isOffer) { + createOffer(); + } + } + + pc.oniceconnectionstatechange = function(event) { + console.log('oniceconnectionstatechange', event); + if (event.target.iceConnectionState === 'connected') { + createDataChannel(); + } + }; + pc.onsignalingstatechange = function(event) { + console.log('onsignalingstatechange', event); + }; + + pc.onaddstream = function (event) { + console.log('onaddstream', event); + var element = document.createElement('video'); + element.id = "remoteView" + socketId; + element.autoplay = 'autoplay'; + element.src = URL.createObjectURL(event.stream); + remoteViewContainer.appendChild(element); + }; + pc.addStream(localStream); + function createDataChannel() { + if (pc.textDataChannel) { + return; + } + var dataChannel = pc.createDataChannel("text"); + + dataChannel.onerror = function (error) { + console.log("dataChannel.onerror", error); + }; + + dataChannel.onmessage = function (event) { + console.log("dataChannel.onmessage:", event.data); + var content = document.getElementById('textRoomContent'); + content.innerHTML = content.innerHTML + '

' + socketId + ': ' + event.data + '

'; + }; + + dataChannel.onopen = function () { + console.log('dataChannel.onopen'); + var textRoom = document.getElementById('textRoom'); + textRoom.style.display = "block"; + }; + + dataChannel.onclose = function () { + console.log("dataChannel.onclose"); + }; + + pc.textDataChannel = dataChannel; + } + return pc; +} + +function exchange(data) { + var fromId = data.from; + var pc; + if (fromId in pcPeers) { + pc = pcPeers[fromId]; + } else { + pc = createPC(fromId, false); + } + + if (data.sdp) { + console.log('exchange sdp', data); + pc.setRemoteDescription(new RTCSessionDescription(data.sdp), function () { + if (pc.remoteDescription.type == "offer") + pc.createAnswer(function(desc) { + console.log('createAnswer', desc); + pc.setLocalDescription(desc, function () { + console.log('setLocalDescription', pc.localDescription); + socket.emit('exchange', {'to': fromId, 'sdp': pc.localDescription }); + }, logError); + }, logError); + }, logError); + } else { + console.log('exchange candidate', data); + pc.addIceCandidate(new RTCIceCandidate(data.candidate)); + } +} + +function leave(socketId) { + console.log('leave', socketId); + var pc = pcPeers[socketId]; + pc.close(); + delete pcPeers[socketId]; + var video = document.getElementById("remoteView" + socketId); + if (video) video.remove(); +} + +socket.on('exchange', function(data){ + exchange(data); +}); +socket.on('leave', function(socketId){ + leave(socketId); +}); + +socket.on('connect', function(data) { + console.log('connect'); + getLocalStream(); +}); + +function logError(error) { + console.log("logError", error); +} + +function press() { + var roomID = document.getElementById('roomID').value; + if (roomID == "") { + alert('Please enter room ID'); + } else { + var roomIDContainer = document.getElementById('roomIDContainer'); + roomIDContainer.parentElement.removeChild(roomIDContainer); + join(roomID); + } +} +function textRoomPress() { + var text = document.getElementById('textRoomInput').value; + if (text == "") { + alert('Enter something'); + } else { + document.getElementById('textRoomInput').value = ''; + var content = document.getElementById('textRoomContent'); + content.innerHTML = content.innerHTML + '

' + 'Me' + ': ' + text + '

'; + for (var key in pcPeers) { + var pc = pcPeers[key]; + pc.textDataChannel.send(text); + } + } +} diff --git a/index.html b/index.html index db0ae72..cdfe230 100644 --- a/index.html +++ b/index.html @@ -20,207 +20,7 @@

Text Room

- + From 66e34e6dd35b8637e27bf2ac66133ea908cbc6d0 Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Mon, 18 Jul 2016 15:48:23 +0800 Subject: [PATCH 12/13] add comments and coding style revision --- app.js | 22 +++++++++++++++------- server.js | 9 ++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/app.js b/app.js index 7a75d7f..27f7da4 100644 --- a/app.js +++ b/app.js @@ -25,10 +25,10 @@ const textRoomPress = () => { document.getElementById('textRoomInput').value = ''; const content = document.getElementById('textRoomContent'); content.innerHTML = `${content.innerHTML}

Me: ${text}

`; - for (const key in pcPeers) { + Object.keys(pcPeers).forEach((key) => { const pc = pcPeers[key]; pc.textDataChannel.send(text); - } + }); } }; @@ -45,9 +45,15 @@ const createPC = (socketId, isOffer) => { pcPeers[socketId] = pc; pc.onicecandidate = (event) => { + // This happens whenever the local ICE agent needs to deliver a message to + // the other peer through the signaling server. + // This lets the ICE agent perform negotiation with the remote peer without the browser + // itself needing to know any specifics about the technology being used for signaling; + // simply implement this method to use whatever messaging technology you choose to send + // the ICE candidate to the remote peer. console.log('onicecandidate', event); if (event.candidate) { - socket.emit('exchange', { 'to': socketId, 'candidate': event.candidate }); + socket.emit('exchange', { to: socketId, candidate: event.candidate }); } }; @@ -56,7 +62,7 @@ const createPC = (socketId, isOffer) => { console.log('createOffer', desc); pc.setLocalDescription(desc, () => { console.log('setLocalDescription', pc.localDescription); - socket.emit('exchange', { 'to': socketId, 'sdp': pc.localDescription }); + socket.emit('exchange', { to: socketId, sdp: pc.localDescription }); }, logError); }, logError); }; @@ -90,6 +96,8 @@ const createPC = (socketId, isOffer) => { pc.textDataChannel = dataChannel; }; + // This event is fired when a change has occurred which requires session negotiation. + // The most common scenario in which this will happen is at the beginning of a connection. pc.onnegotiationneeded = () => { console.log('onnegotiationneeded'); if (isOffer) { @@ -124,7 +132,7 @@ const createPC = (socketId, isOffer) => { const join = (roomID) => { socket.emit('join', roomID, (socketIds) => { console.log('join', socketIds); - for (var i in socketIds) { + for (let i = 0; i < socketIds.length; ++i) { const socketId = socketIds[i]; createPC(socketId, true); } @@ -159,7 +167,7 @@ const exchange = (data) => { console.log('createAnswer', desc); pc.setLocalDescription(desc, () => { console.log('setLocalDescription', pc.localDescription); - socket.emit('exchange', { 'to': fromId, 'sdp': pc.localDescription }); + socket.emit('exchange', { to: fromId, sdp: pc.localDescription }); }, logError); }, logError); } @@ -187,7 +195,7 @@ socket.on('leave', (socketId) => { leave(socketId); }); -socket.on('connect', (data) => { +socket.on('connect', () => { console.log('connect'); getLocalStream(); }); diff --git a/server.js b/server.js index e5376b5..be3e600 100644 --- a/server.js +++ b/server.js @@ -22,13 +22,12 @@ app.use(express.static(__dirname)); const socketIdsInRoom = (name) => { const socketIds = io.nsps['/'].adapter.rooms[name]; + console.log('socketIds', socketIds); if (socketIds) { const collection = []; - for (const key in socketIds) { - if ({}.hasOwnProperty.call(socketIds, key)) { - collection.push(key); - } - } + Object.keys(socketIds).forEach((key) => { + collection.push(key); + }); return collection; } return []; From 15de44f52010e5adb3ede50cd0dfc59279c83b6e Mon Sep 17 00:00:00 2001 From: "SHANG-YU, SU" Date: Thu, 21 Jul 2016 14:09:07 +0800 Subject: [PATCH 13/13] minor fix --- server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.js b/server.js index be3e600..219143d 100644 --- a/server.js +++ b/server.js @@ -41,7 +41,7 @@ app.get('/', (req, res) => { server.listen(serverPort, () => { console.log('server up and running at %s port', serverPort); if (process.env.LOCAL) { - open(`https://localhost: ${serverPort}`); + open(`https://localhost:${serverPort}`); } });