Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding websocket inside #20

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AppRTC - NodeJS implementation of the Google WebRTC Demo

## About
AppRTC-node-server is a straight port of the AppRTC Python Server from the Google WebRTC Demo to run entirely in the NodeJS environment.
AppRTC-node-server is a straight port of the AppRTC Python Server from the Google WebRTC Demo to run entirely in the NodeJS environment with Websocket built in.

## Notes
This still a work in progress. We are in the process of cleaning up the code and making several enhancements:
Expand Down Expand Up @@ -29,4 +29,4 @@ The apprtc-node-server uses ExpressJS. To run the node server after setup just e
node ./bin/www
```

Navigate to `http://localhost:3000` to run the WebRTC Demo
Navigate to `http://<ip_host>:<port>` to run the WebRTC Demo, such as: `http://107.113.191.149:8080`
47 changes: 45 additions & 2 deletions bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
var app = require('../app');
var debug = require('debug')('AppRTC-node-server:server');
var http = require('http');
var Websocket = require('ws');

var IP_HOST = '107.113.191.149';
var WSS_PORT = '8080';

/**
* Get port from environment and store in Express.
*/

var port = normalizePort(process.env.PORT || '3000');
var port = normalizePort(process.env.PORT || WSS_PORT);
app.set('port', port);

/**
Expand All @@ -21,11 +25,49 @@ app.set('port', port);

var server = http.createServer(app);

/** lampv
* Create websocket server
*/
var webSockets = [];
var wss = new Websocket.Server({server});
wss.on('connection', function connection(ws){
ws.on('message', function incoming(message){
console.log('received: %s', message);
var jsonMsg = JSON.parse(message);

if(jsonMsg.cmd === 'register'){
ws.roomid = jsonMsg.roomid;
ws.clientid = jsonMsg.clientid;
webSockets.push(ws);
console.log('roomid:' + ws.roomid + ' clientid:' + ws.clientid + ' webSockets.length:' + webSockets.length);
}else if(jsonMsg.cmd === 'send'){
console.log('webSockets.length:' + webSockets.length);

for(i = 0; i < webSockets.length; i++){
var socket = webSockets[i];
var msgText = JSON.parse(jsonMsg.msg);
console.log('socket.clientid:' + socket.clientid);

if(socket !== ws && socket.roomid == ws.roomid && socket.readyState === socket.OPEN){
console.log('send message from:' + socket.clientid + ' to ' + ws.clientid);
socket.send(message);
}
}
}
});

ws.on('close', function(){
console.log('ws close');
webSockets.splice(webSockets.indexOf(ws), 1);
});
});

/**
* Listen on provided port, on all network interfaces.
*/
var ip_host = IP_HOST;

server.listen(port);
server.listen(port, ip_host);
server.on('error', onError);
server.on('listening', onListening);

Expand Down Expand Up @@ -87,4 +129,5 @@ function onListening() {
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
console.log('Listening on ' + ip_host + ' and ' + bind);
}
3 changes: 2 additions & 1 deletion lib/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Room = function() {

this.removeClient = function(clientId, callback) {
delete clientMap[clientId];
var clientIds = Object.keys(clientMap);
var otherClient = clientIds.length > 0 ? clientMap[clientIds[0]] : null;
callback(null, true, otherClient);
};
Expand Down Expand Up @@ -102,4 +103,4 @@ Rooms = function() {
}
};

module.exports = Rooms;
module.exports = Rooms;
72 changes: 60 additions & 12 deletions routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,46 @@ var router = express.Router();
var Rooms = require('../lib/rooms.js');
var rooms = new Rooms();

var IP_HOST = '107.113.191.149';
var WSS_PORT = '8080';

var constants = {
LOOPBACK_CLIENT_ID: 'LOOPBACK_CLIENT_ID',
TURN_BASE_URL: 'https://computeengineondemand.appspot.com',
TURN_URL_TEMPLATE: '%s/turn?username=%s&key=%s',
CEOD_KEY: '4080218913',
WSS_HOST_ACTIVE_HOST_KEY: 'wss_host_active_host', //memcache key for the active collider host.
WSS_HOST_PORT_PAIRS: ['apprtc-ws.webrtc.org:443', 'apprtc-ws-2.webrtc.org:443'],
//WSS_HOST_PORT_PAIRS: ['apprtc-ws.webrtc.org:443', 'apprtc-ws-2.webrtc.org:443'],
WSS_HOST_PORT_PAIRS: [IP_HOST + ':' + WSS_PORT, IP_HOST + ':' + WSS_PORT],
RESPONSE_ERROR: 'ERROR',
RESPONSE_UNKNOWN_ROOM: 'UNKNOWN_ROOM',
RESPONSE_UNKNOWN_CLIENT: 'UNKNOWN_CLIENT',
RESPONSE_ROOM_FULL: 'FULL',
RESPONSE_DUPLICATE_CLIENT: 'DUPLICATE_CLIENT',
RESPONSE_SUCCESS: 'SUCCESS',
RESPONSE_INVALID_REQUEST: 'INVALID_REQUEST'

};


constants.TURN_SERVER_OVERRIDE = [
{
"urls": [
"turn:173.194.72.127:19305?transport=udp",
"turn:[2404:6800:4008:C01::7F]:19305?transport=udp",
"turn:173.194.72.127:443?transport=tcp",
"turn:[2404:6800:4008:C01::7F]:443?transport=tcp"
],
"username": "CKjCuLwFEgahxNRjuTAYzc/s6OMT",
"credential": "u1SQDR/SQsPQIxXNWQT7czc/G4c="
},
{
"urls": [
"stun:stun.l.google.com:19302"
]
}
]

function generateRandom(length) {
console.log('function generateRandom');
var word = '';
for (var i = 0; i < length; i++) {
word += Math.floor((Math.random() * 10));
Expand All @@ -36,6 +56,7 @@ function generateRandom(length) {

// HD is on by default for desktop Chrome, but not Android or Firefox (yet)
function getHDDefault(userAgent) {
console.log('function getHDDefault');
if (userAgent.indexOf('Android') > -1 || userAgent.indexOf('Chrome') == -1) {
return false;
}
Expand All @@ -44,6 +65,7 @@ function getHDDefault(userAgent) {

// iceServers will be filled in by the TURN HTTP request.
function makePCConfig(iceTransports) {
console.log('function makePCConfig');
var config = { iceServers: [] };
if (iceTransports) {
config.iceTransports = iceTransports;
Expand All @@ -52,6 +74,7 @@ function makePCConfig(iceTransports) {
}

function maybeAddConstraint(constraints, param, constraint) {
console.log('function maybeAddConstraint');
var object = {};
if (param && param.toLowerCase() == 'true') {
object[constraint] = true;
Expand All @@ -64,6 +87,7 @@ function maybeAddConstraint(constraints, param, constraint) {
}

function makePCConstraints(dtls, dscp, ipv6) {
console.log('function makePCConstraints');
var constraints = { optional: [] };
maybeAddConstraint(constraints, dtls, 'DtlsSrtpKeyAgreement');
maybeAddConstraint(constraints, dscp, 'googDscp');
Expand All @@ -72,6 +96,7 @@ function makePCConstraints(dtls, dscp, ipv6) {
}

function addMediaTrackConstraint(trackConstraints, constraintString) {
console.log('function addMediaTrackConstraint');
var tokens = constraintString.split(':');
var mandatory = true;
if (tokens.length == 2) {
Expand Down Expand Up @@ -100,6 +125,7 @@ function addMediaTrackConstraint(trackConstraints, constraintString) {
}

function makeMediaTrackConstraints(constraintsString) {
console.log('function makeMediaTrackConstraints');
var trackConstraints;
if (!constraintsString || constraintsString.toLowerCase() == 'true') {
trackConstraints = true;
Expand All @@ -117,6 +143,7 @@ function makeMediaTrackConstraints(constraintsString) {
}

function makeMediaStreamConstraints(audio, video, firefoxFakeDevice) {
console.log('function makeMediaStreamConstraints');
var streamConstraints = {
audio: makeMediaTrackConstraints(audio),
video: makeMediaTrackConstraints(video)
Expand All @@ -126,9 +153,10 @@ function makeMediaStreamConstraints(audio, video, firefoxFakeDevice) {
}

function getWSSParameters(req) {
console.log('function getWSSParameters');
var wssHostPortPair = req.query['wshpp'];
var wssTLS = req.query['wstls'];

console.log('wssTLS: ' + wssTLS);
if (!wssHostPortPair) {
// Attempt to get a wss server from the status provided by prober,
// if that fails, use fallback value.
Expand All @@ -143,8 +171,9 @@ function getWSSParameters(req) {
wssHostPortPair = constants.WSS_HOST_PORT_PAIRS[0];
//}
}

if (wssTLS && wssTLS == 'false') {
// lampv: adding wssTLS === underfined
if ((wssTLS && wssTLS == 'false') || wssTLS === undefined) {
//if (wssTLS && wssTLS == 'false') {
return {
wssUrl: 'ws://' + wssHostPortPair + '/ws',
wssPostUrl: 'http://' + wssHostPortPair,
Expand All @@ -160,11 +189,13 @@ function getWSSParameters(req) {
}

function getVersionInfo() {
console.log('function getVersionInfo');
//TODO: parse version_info.json
return undefined;
}

function getRoomParameters(req, roomId, clientId, isInitiator) {
console.log('function getRoomParameters');
var errorMessages = [];
var userAgent = req.headers['user-agent'];
//Which ICE candidates to allow. This is useful for forcing a call to run over TURN, by setting it=relay.
Expand Down Expand Up @@ -285,7 +316,8 @@ function getRoomParameters(req, roomId, clientId, isInitiator) {
'wss_url': wssUrl,
'wss_post_url': wssPostUrl,
'bypass_join_confirmation': JSON.stringify(bypassJoinConfirmation),
'version_info': JSON.stringify(getVersionInfo())
'version_info': JSON.stringify(getVersionInfo()),
'turn_server_override': constants.TURN_SERVER_OVERRIDE
};

var protocol = req.headers['x-forwarded-proto'];
Expand All @@ -305,11 +337,14 @@ function getRoomParameters(req, roomId, clientId, isInitiator) {
}

function getCacheKeyForRoom(host, roomId) {
console.log('function getCacheKeyForRoom');
return host + "/" + roomId;
}

function addClientToRoom(req, roomId, clientId, isLoopback, callback) {
console.log('function addClientToRoom');
var key = getCacheKeyForRoom(req.headers.host, roomId);
console.log('key:' + key);
rooms.createIfNotExist(key, function(error, room) {
if (error) {
callback(error);
Expand All @@ -335,15 +370,15 @@ function addClientToRoom(req, roomId, clientId, isLoopback, callback) {
}
var messages = otherClient ? otherClient.messages : [];
if (otherClient) otherClient.clearMessages();
console.log('Added client ' + clientId + ' in room ' + roomId);
console.log('Added client ' + clientId + ' in room ' + roomId + ' room: '+ room);
callback(null, { is_initiator: client.isInitiator, messages: messages, room_state: room.toString() });
});
}

});
}

function saveMessageFromClient(host, roomId, clientId, message, callback) {
console.log('function saveMessageFromClient');
var text = message;
var key = getCacheKeyForRoom(host, roomId);
rooms.get(key, function(error, room) {
Expand All @@ -358,19 +393,21 @@ function saveMessageFromClient(host, roomId, clientId, message, callback) {
} else {
var client = room.getClient(clientId);
client.addMessage(text);
console.log('Saved message for client ' + clientId + ':' + client.toString() + ' in room ' + roomId);
console.log('Saved message for client ' + clientId + ':' + client.toString() + ' in room ' + roomId + ' msg:' + text);
callback(null, true);
}
});
}

router.get('/', function(req, res, next) {
// Parse out parameters from request.
console.log('router.get //');
var params = getRoomParameters(req, null, null, null);
res.render("index_template", params);
});

router.post('/join/:roomId', function(req, res, next) {
console.log('router.post //join//:roomId');
var roomId = req.params.roomId;
var clientId = generateRandom(8);
var isLoopback = req.query['debug'] == 'loopback';
Expand All @@ -395,6 +432,7 @@ router.post('/join/:roomId', function(req, res, next) {
});

router.post('/message/:roomId/:clientId', function(req, res, next) {
console.log('post //message//:roomId//:clientId');
var roomId = req.params.roomId;
var clientId = req.params.clientId;
var message = req.body;
Expand All @@ -414,8 +452,8 @@ router.post('/message/:roomId/:clientId', function(req, res, next) {
console.log('Forwarding message to collider from room ' + roomId + ' client ' + clientId);
var wssParams = getWSSParameters(req);
var postOptions = {
host: 'apprtc-ws.webrtc.org',//wssParams.host,
port: 443,
host: IP_HOST,//wssParams.host,
port: WSS_PORT,
path: '/' + roomId + '/' + clientId,
method: 'POST'
};
Expand All @@ -435,6 +473,7 @@ router.post('/message/:roomId/:clientId', function(req, res, next) {
});

router.get('/r/:roomId', function(req, res, next) {
console.log('router.get //r//:roomId');
var roomId = req.params.roomId;
var key = getCacheKeyForRoom(req.headers.host, roomId);
rooms.get(key, function(error, room) {
Expand All @@ -456,6 +495,7 @@ router.get('/r/:roomId', function(req, res, next) {
});

router.post('/leave/:roomId/:clientId', function(req, res, next) {
console.log('router.post //leave//:roomID//:clientId');
var roomId = req.params.roomId;
var clientId = req.params.clientId;
var key = getCacheKeyForRoom(req.headers.host, roomId);
Expand All @@ -469,9 +509,11 @@ router.post('/leave/:roomId/:clientId', function(req, res, next) {
} else {
room.removeClient(clientId, function(error, isRemoved, otherClient) {
if (error) {
console.log('send respond error');
res.send({ result: error });
return;
}

if (room.hasClient(constants.LOOPBACK_CLIENT_ID)) {
room.removeClient(constants.LOOPBACK_CLIENT_ID, function(error, isRemoved) {
res.send({ result: constants.RESPONSE_SUCCESS });
Expand All @@ -484,6 +526,12 @@ router.post('/leave/:roomId/:clientId', function(req, res, next) {
});
}
});
console.log('send respond success');
res.send({ result: constants.RESPONSE_SUCCESS });
});

router.post('/DELETE/:roomId/:clientId', function(req, res, next){
console.log('router.post //DELETE//:roomID//:clientId');
res.send({ result: constants.RESPONSE_SUCCESS });
});

Expand Down