video/comms/webRTC-over-websockets/websocket-server.js

196 lines
7.1 KiB
JavaScript

var WebSocketServer = require('websocket').server;
var http = require('http');
var fs = require('fs');
var people = {};
var connectionDict = {};
var rooms = {};
var numberOfConnections = 0;
var roster = {};
var settings = {
websocketPort: 1337,
refreshRate : 5000,
autoCall : true,
acceptNewUsers : false
}
fs.readFile(process.argv[2] || './settings.json', function(err, data) {
if (err) {
console.log('No settings.json found ('+err+'). Using default settings');
} else {
settings = JSON.parse(data.toString('utf8', 0, data.length));
}
console.log(settings);
});
fs.readFile('data/people.json', 'utf8', function (err, data) {
if (err) throw err;
var obj = JSON.parse(data.toString('utf8', 0, data.length));
roster.people = obj;
for(var i=0; i< obj.length; i ++){
people[obj[i].id] = 'off';
};
console.log('Loaded ' + obj.length + ' people from people.json file');
});
fs.readFile('data/rooms.json', 'utf8', function (err, data) {
if (err) throw err;
var obj = JSON.parse(data.toString('utf8', 0, data.length));
roster.rooms = obj;
console.log('Loaded ' + obj.length + ' rooms from rooms.json file');
});
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets serve we don't have to implement anything.
}).listen(settings.websocketPort, function() {
console.log('Socket server is listening on port ' + settings.websocketPort);
});
wsServer = new WebSocketServer({
httpServer: server
});
setInterval(sendPresence, settings.refreshRate);
// This callback function is called every time someone tries to connect to the WebSocket server
// if the type of message is presence, it will send the broadcast. If the type is room, it will send the offer type as multicast,
// if from and to field are defined, and connection.name that maches to exists, it will send the unicast.
// Otherwise, it will send the broadcast.
wsServer.on('request', function(request) {
numberOfConnections ++;
console.log('Connection from origin ' + request.origin);
var connection = request.accept(null, request.origin);
console.log('Connection address ' + connection.remoteAddress);
console.log('Number of connections ' + numberOfConnections);
connection.on('message', function(message) {
if (message.type === 'utf8') {
// process WebSocket message
console.log('Received Message ' + message.utf8Data);
//parse the message
msg = JSON.parse(message.utf8Data);
var type = msg.type;
var from = msg.from;
var to = msg.to;
var name;
//accept only messages that are authorized, in simple case, we assume that the
//first call is the presence with a name of the caller
if(type !== 'presence' && connection.name === undefined){
console.log('connection not allowed, name not provided');
return;
}
//after presence message, socket connection is 'named', only such connections participate later.
if(type === 'presence'){
name = msg.name;
if(people[name] === undefined && !settings.acceptNewUsers){
console.log('Unknown user not allowed');
return;
}
var status = msg.status;
if(status === 'on'){
connection.name = name;
connectionDict[name] = connection;
console.log('adding '+ name)
people[name] = 'on';
if(settings.sendRoster){
connection.send(JSON.stringify({type: "roster", people: roster.people, rooms: roster.rooms}));
}
} else {
remove(name);
}
} else if(type === 'room'){
if(rooms[to] === undefined)
rooms[to] = [];
console.log('Number of people in the room ' + rooms[to].length);
console.log('Sending multicast from ' + from + ": to room "+ to);
if(settings.autoCall){
for(var i = 0; i < rooms[to].length; i ++){
var x = rooms[to][i];
if(connectionDict[x] !== undefined){
console.log('Sending offer from ' + from + ": to "+ x);
sendOffer(connectionDict[x], from, x);
}
}
}
if(rooms[to].indexOf(from) < 0)
rooms[to].push(from);
return;
} else if(to !== undefined && from !== undefined){
if(connectionDict[to] !== undefined && people[to] !== 'off'){
console.log('Sending unicast from ' + from + ":"+ to);
connectionDict[to].send(message.utf8Data, sendCallback);
}
} else {
console.log("message couldn't be passed to " + to);
}
return;
}
console.log('Sending broadcast from '+ from);
// broadcast message to all clients that have name attached
for(var client in connectionDict){
if(client !== name){
console.log('Sending data to '+ client);
connectionDict[client].send(message.utf8Data, sendCallback);
}
}
});
connection.on('close', function(conn) {
console.log('Peer disconnected.');
numberOfConnections --;
remove(connection.name);
});
});
function sendOffer(connection, _from, _to){
connection.send(JSON.stringify({type: 's-offer', from: _from, to: _to}), sendCallback);
}
function sendPresence(){
for(var _name in people){
for(var client in connectionDict){
if(people[_name] === 'off'){
console.log('Person '+ _name + '[off] -> ' + client);
connectionDict[client].send(JSON.stringify({type: 'presence', name: _name, status: 'off'}), sendCallback);
} else if(people[_name] === 'on'){
console.log('Person '+ _name + '[on] -> ' + client);
connectionDict[client].send(JSON.stringify({type: 'presence', name: _name, status: 'on'}), sendCallback);
}
}
}
for(var room in rooms){
for(var i = 0; i < rooms[room].length; i ++){
var client = rooms[room][i];
if(connectionDict[client] !== undefined){
console.log('Room '+ room + ' -> ' + client);
connectionDict[client].send(JSON.stringify({type: 'presence', name: room,
status: 'on', room: true}), sendCallback);
}
}
}
}
function remove(name){
if(name !== undefined && name !== null){
console.log('removing '+ name);
people[name] = 'off';
delete connectionDict[name];
}
}
function sendCallback(err) {
if (err){
console.error("send() error: " + err);
}
}