-
Notifications
You must be signed in to change notification settings - Fork 7
/
server.js
executable file
·173 lines (130 loc) · 4.86 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
var cluster = require( "cluster" )
var os = require( "os" );
var express = require( "express" );
var http = require( "http" );
var sockets = require( "socket.io" );
var redis = require( "redis" );
var sessions = require( "cookie-sessions" );
var participationModule = require('./lib/participation')
// Use this to control how many people are allowed in a room.
var MAXIMUM_ROOM_SIZE = parseInt(process.env.NODE_WAITING_LIST_SIZE) || 4;
/*************************
* Cluster
*************************/
if (cluster.isMaster) {
var numCPUs = os.cpus().length;
for (var i = 0; i < numCPUs; i++)
cluster.fork();
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
cluster.fork();
});
} else {
/***************************************
* HTTP Request Communication
***************************************/
var app = express();
// Create participation object to track room capacity.
var participation = participationModule.Participation( MAXIMUM_ROOM_SIZE, redis.createClient() );
//************ MIDDLEWARE **************
app.configure(function() {
app.set( 'views', __dirname + '/views/' );
app.set( 'view engine', 'jade' );
app.use( express.static(__dirname + '/public') );
app.use( sessions( { secret: process.env.NODE_SESSION_SECRET || "careful, this isn't really secret", session_key: '_redis-waiting-list' } ) );
});
/* Make sure the user has an id */
function checkId( request, response, next ) {
if ( ! request.session )
request.session = {}
if ( ! request.session.id ) {
// generate random string
for (var i=0,sessionId='',r; r=parseInt(Math.random()*36), i<5; i++)
sessionId += r < 10 ? r : String.fromCharCode(87+r);
request.session.id = sessionId;
}
next();
}
/* Check participation to see if the room is full.
If it is, direct user to the 'waiting_room' page instead. */
function checkCapacity( request, response, next ) {
return participation.check( request.params.room, request.session.id, withStatus );
function withStatus( err, status ) {
if (err)
return next(err);
if (status && status.status === 'ready')
return next();
return response.render('waiting_room', {id:request.params.room, status:status} )
}
}
//************* ROUTES ********************
// Handle default route
app.get("/", function( request, response ) {
return response.render( 'index' );
});
// Handle status request
// Handle room
app.get("/:room", checkId, checkCapacity, function( request, response) {
return response.render( 'room', {id:request.params.room, userId:request.session.id} );
});
// Handle status checks
app.get( "/:room/waiting-list", checkId, function(request, response, next) {
return participation.check(request.params.room, request.session.id, respondWithStatus);
function respondWithStatus(err, status) {
if (err) return next(err);
return response.send(status);
}
});
//********** START SERVER *****************
var applicationServer = http.createServer(app);
var port = parseInt(process.env.NODE_PORT) || 8234;
applicationServer.listen( port );
console.log( "Listening on port " + port );
/*************************
* Web Socket Communication
*************************/
// Initialize socket.io using redis store
var io = sockets.listen( applicationServer );
io.set( 'log level', 2 );
// Use redis store to support multi-process/server communication
var RedisStore = require('socket.io/lib/stores/redis');
io.set('store', new RedisStore({
redisPub : redis.createClient(),
redisSub : redis.createClient(),
redisClient : redis.createClient()
}));
function updateRoomCount( roomId ) {
return participation.count(roomId, withCount);
function withCount( err, count ) {
if ( err )
return console.log(err);
io.sockets.in(roomId).json.emit('message', {count:count})
}
}
// Use join message to register as a participant
function join( socket, message ) {
socket.join(message.roomId);
participation.connect(message.roomId, message.userId, null);
// use socket to track state
socket.roomId = message.roomId;
socket.userId = message.userId;
updateRoomCount( message.roomId );
}
io.sockets.on( 'connection', function( socket ) {
socket.on( 'message', function( body ) {
for ( var type in body ) {
var message = body[type];
if ( type === 'join' )
join( socket, message );
else if (message.room)
io.sockets.in(message.room).json.emit('message',body);
}
} );
socket.on( 'disconnect', function() {
// disconnect from room
if (socket.roomId)
participation.disconnect(socket.roomId, socket.userId, null);
updateRoomCount( socket.roomId );
} );
} );
}