196 lines
7.1 KiB
JavaScript
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);
|
|
}
|
|
}
|
|
|