Fix menu bug on smartphones
[vchess.git] / sockets.js
1 const url = require('url');
2 const sqlite3 = require('sqlite3');
3 const db = new sqlite3.Database(__dirname + "/db/vchess.sqlite");
4
5 // Node version in Ubuntu 16.04 does not know about URL class
6 function getJsonFromUrl(url) {
7 var query = url.substr(2); //starts with "/?"
8 var result = {};
9 query.split("&").forEach(function(part) {
10 var item = part.split("=");
11 result[item[0]] = decodeURIComponent(item[1]);
12 });
13 return result;
14 }
15
16 module.exports = function(wss) {
17 db.serialize(function() {
18 db.all("SELECT * FROM Variants", (err,variants) => {
19 let clients = { "index": {} };
20 let games = {}; //pending games (player sid)
21 for (const v of variants)
22 clients[v.name] = {};
23 // No-op function as a callback when sending messages
24 const noop = () => { };
25 wss.on("connection", (socket, req) => {
26 // const params = new URL("http://localhost" + req.url).searchParams;
27 // const sid = params.get("sid");
28 // const page = params.get("page");
29 var query = getJsonFromUrl(req.url);
30 const sid = query["sid"];
31 const page = query["page"];
32 // Ignore duplicate connections:
33 if (!!clients[page][sid])
34 {
35 socket.send(JSON.stringify({code:"duplicate"}));
36 return;
37 }
38 clients[page][sid] = socket;
39 if (page == "index")
40 {
41 // Send counting info
42 const countings = {};
43 for (const v of variants)
44 countings[v.name] = Object.keys(clients[v.name]).length;
45 socket.send(JSON.stringify({code:"counts",counts:countings}));
46 }
47 else
48 {
49 // Send to every client connected on index an update message for counts
50 Object.keys(clients["index"]).forEach( k => {
51 clients["index"][k].send(
52 JSON.stringify({code:"increase",vname:page}), noop);
53 });
54 // Also notify potential opponents:
55 // hit all clients which check if sid corresponds
56 Object.keys(clients[page]).forEach( k => {
57 clients[page][k].send(JSON.stringify({code:"connect",id:sid}), noop);
58 });
59 socket.on("message", objtxt => {
60 let obj = JSON.parse(objtxt);
61 switch (obj.code)
62 {
63 case "newchat":
64 if (!!clients[page][obj.oppid])
65 {
66 clients[page][obj.oppid].send(
67 JSON.stringify({code:"newchat",msg:obj.msg}), noop);
68 }
69 break;
70 case "newmove":
71 if (!!clients[page][obj.oppid])
72 {
73 clients[page][obj.oppid].send(
74 JSON.stringify({code:"newmove",move:obj.move}), noop);
75 }
76 break;
77 case "ping":
78 if (!!clients[page][obj.oppid])
79 socket.send(JSON.stringify({code:"pong",gameId:obj.gameId}));
80 break;
81 case "myname":
82 // Reveal my username to opponent
83 if (!!clients[page][obj.oppid])
84 {
85 clients[page][obj.oppid].send(JSON.stringify({
86 code:"oppname", name:obj.name}));
87 }
88 break;
89 case "lastate":
90 if (!!clients[page][obj.oppid])
91 {
92 const oppId = obj.oppid;
93 obj.oppid = sid; //I'm oppid for my opponent
94 clients[page][oppId].send(JSON.stringify(obj), noop);
95 }
96 break;
97 case "newgame":
98 if (!!games[page])
99 {
100 // Start a new game
101 const oppId = games[page]["id"];
102 const fen = games[page]["fen"];
103 delete games[page];
104 const mycolor = Math.random() < 0.5 ? 'w' : 'b';
105 socket.send(JSON.stringify(
106 {code:"newgame",fen:fen,oppid:oppId,color:mycolor}));
107 if (!!clients[page][oppId])
108 {
109 clients[page][oppId].send(
110 JSON.stringify(
111 {code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w"}),
112 noop);
113 }
114 }
115 else
116 games[page] = {id:sid, fen:obj.fen}; //wait for opponent
117 break;
118 case "cancelnewgame": //if a user cancel his seek
119 delete games[page];
120 break;
121 case "resign":
122 if (!!clients[page][obj.oppid])
123 clients[page][obj.oppid].send(JSON.stringify({code:"resign"}), noop);
124 break;
125 }
126 });
127 }
128 socket.on("close", () => {
129 delete clients[page][sid];
130 // Remove potential pending game
131 if (!!games[page] && games[page]["id"] == sid)
132 delete games[page];
133 if (page != "index")
134 {
135 // Send to every client connected on index an update message for counts
136 Object.keys(clients["index"]).forEach( k => {
137 clients["index"][k].send(
138 JSON.stringify({code:"decrease",vname:page}), noop);
139 });
140 }
141 // Also notify potential opponents:
142 // hit all clients which check if sid corresponds
143 Object.keys(clients[page]).forEach( k => {
144 clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}), noop);
145 });
146 });
147 });
148 });
149 });
150 }