Join games via invitation URL, instead of anonymously
[sumserum.git] / server.js
1 var port = process.env.OPENSHIFT_NODEJS_PORT || 9999;
2 var ip   = process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1";
3 var http = require('http');
4 var sockjs = require('sockjs');
5 var node_static = require('node-static');
6 var uuid = require('node-uuid');
7
8 // 1. Echo sockjs server
9 var sockjs_opts = {sockjs_url: "http://cdn.sockjs.org/sockjs-0.3.min.js"};
10
11 // key to client connection
12 var clients = {};
13
14 // game id to waiting player
15 var waiting = {};
16 // waiting player to game id
17 var waiting_clients = {};
18
19 // Mapping from id to opponent's id
20 var opp = {};
21
22 function broadcast(from, message) {
23         for(key in clients) if(clients.hasOwnProperty(key)) {
24                 if (key != from) clients[key].write(message);
25         }
26 }
27
28 function send(to, dict) {
29         clients[to].write(JSON.stringify(dict));
30 }
31
32 function error(to, message) {
33         send(to, {meta: "error", error: message});
34 }
35
36 function hookup(p1, p2) {
37         console.log("Trying to hook up " + p1 + " and " + p2);
38         opp[p1] = p2;
39         opp[p2] = p1;
40         send(p1, {meta: "newgame", you: 1});
41         send(p2, {meta: "newgame", you: 2});
42 }
43
44 var sockjs = sockjs.createServer(sockjs_opts);
45
46 sockjs.on('connection', function(conn) {
47         clients[conn.id] = conn;
48
49         conn.on('data', function(message) {
50                 msg = JSON.parse(message);
51                 var meta;
52                 if (meta = msg.meta) {
53                         console.log(conn.id, msg);
54                         if (meta == "hookmeup") {
55                                 if (waiting_clients.hasOwnProperty(conn.id)) {
56                                         var gameid = waiting_clients[conn.id];
57                                         delete waiting[gameid];
58                                         delete waiting_clients[conn.id];
59                                 }
60                                 var gameid = uuid().substr(0,8);
61
62                                 console.log('New waiting game ' + gameid + ' for ' + conn.id);
63                                 waiting[gameid] = conn.id;
64                                 waiting_clients[conn.id] = gameid;
65
66                                 send(conn.id, {meta: "gameid", gameid: gameid});
67                         } else if (meta == "join") {
68                                 if (waiting_clients.hasOwnProperty(conn.id)) {
69                                         var gameid = waiting_clients[conn.id];
70                                         delete waiting[gameid];
71                                         delete waiting_clients[conn.id];
72                                 }
73                                 var gameid = msg.gameid;
74
75                                 console.log('Player ' + conn.id + 'wants to join game ' + gameid);
76                                 if (waiting.hasOwnProperty(gameid)) {
77                                         var oppid = waiting[gameid];
78                                         hookup(oppid, conn.id);
79                                         delete waiting[gameid];
80                                         delete waiting_clients[oppid];
81                                 } else {
82                                         error (conn.id, "No such game to join.");
83                                 }
84                         } else {
85                                 error(conn.id, "Unknown command " + meta);
86                         }
87                 } else {
88                         if (opp.hasOwnProperty(conn.id)) {
89                                 clients[opp[conn.id]].write(message);
90                         } else {
91                                 error(conn.id, "Not in a game.");
92                         }
93                 }
94         });
95
96         conn.on('close', function() {
97                 console.log('closed', conn.id);
98                 if (opp.hasOwnProperty(conn.id)){
99                         send(opp[conn.id], {meta:"left" });
100                         delete opp[opp[conn.id]];
101                         delete opp[conn.id];
102                 }
103                 if (waiting_clients.hasOwnProperty[conn.id]) {
104                         var gameid = waiting_clients[conn.id];
105                         delete waiting_clients[conn.id];
106                         delete waiting[gameid];
107                 }
108                 delete clients[conn.id];
109         });
110 });
111
112 // 2. Static files server
113 var static_directory = new node_static.Server(__dirname+"/client");
114
115 // 3. Usual http stuff
116 var server = http.createServer();
117 server.addListener('request', function(req, res) {
118     static_directory.serve(req, res);
119 });
120 server.addListener('upgrade', function(req,res){
121     res.end();
122 });
123
124 sockjs.installHandlers(server, {prefix:'/game'});
125
126 console.log(' [*] Listening on http://' + ip + ':' + port + '/');
127 server.listen(port, ip);