f3d479d693c191cf812833413d0bab995b9a19a3
[vchess.git] / sockets.js
1 //const url = require('url');
2 const Variants = require("./variants");
3
4 function getJsonFromUrl(url) {
5 var query = url.substr(2); //starts with "/?"
6 var result = {};
7 query.split("&").forEach(function(part) {
8 var item = part.split("=");
9 result[item[0]] = decodeURIComponent(item[1]);
10 });
11 return result;
12 }
13
14 module.exports = function(wss) {
15
16 let clients = { "index": {} };
17 let games = {}; //pending games (player sid)
18 for (const v of Variants)
19 clients[v.name] = {};
20
21 // (resign, newgame, newmove). See https://github.com/websockets/ws/blob/master/lib/websocket.js around line 313
22 // TODO: awaiting newmove, resign, (+newgame?) :: in memory structure (use Redis ?)
23 let newmoves = {};
24 let newresign = {};
25 for (const v of Variants)
26 {
27 newmoves[v.name] = {};
28 newresign[v.name] = {};
29 }
30
31 wss.on("connection", (socket, req) => {
32 //const params = new URL("http://localhost" + req.url).searchParams;
33 var query = getJsonFromUrl(req.url);
34 const sid = query["sid"]; //params.get("sid");
35 const page = query["page"]; //params.get("page");
36 clients[page][sid] = socket;
37 if (page == "index")
38 {
39 // Send counting info
40 const countings = {};
41 for (const v of Variants)
42 countings[v.name] = Object.keys(clients[v.name]).length;
43 socket.send(JSON.stringify({code:"counts",counts:countings}));
44 }
45 else
46 {
47 // Send to every client connected on index an update message for counts
48 Object.keys(clients["index"]).forEach( k => {
49 clients["index"][k].send(JSON.stringify({code:"increase",vname:page}));
50 });
51 // Also notify potential opponents: hit all clients which check if sid corresponds
52 Object.keys(clients[page]).forEach( k => {
53 clients[page][k].send(JSON.stringify({code:"connect",id:sid}));
54 });
55 if (!!newmoves[page][sid])
56 {
57 socket.send(JSON.stringify({code:"newmove",move:newmoves[page][sid]}));
58 delete newmoves[page][sid];
59 }
60 if (!!newresign[page][sid])
61 {
62 socket.send(JSON.stringify({code:"resign"}));
63 delete newresign[page][sid];
64 }
65 socket.on("message", objtxt => {
66 let obj = JSON.parse(objtxt);
67 switch (obj.code)
68 {
69 case "newmove":
70 if (!!clients[page][obj.oppid]) // && clients[page][obj.oppid].readyState == WebSocket.OPEN)
71 clients[page][obj.oppid].send(JSON.stringify({code:"newmove",move:obj.move}));
72 else
73 newmoves[page][obj.oppid] = obj.move;
74 break;
75 case "ping":
76 if (!!clients[page][obj.oppid]) // && clients[page][obj.oppid].readyState == WebSocket.OPEN)
77 socket.send(JSON.stringify({code:"pong"}));
78 break;
79 case "newgame":
80 if (!!games[page])
81 {
82 // Start a new game
83 const oppId = games[page]["id"];
84 const fen = games[page]["fen"];
85 delete games[page];
86 const mycolor = Math.random() < 0.5 ? 'w' : 'b';
87 socket.send(JSON.stringify({code:"newgame",fen:fen,oppid:oppId,color:mycolor}));
88 clients[page][oppId].send(JSON.stringify({code:"newgame",fen:fen,oppid:sid,color:mycolor=="w"?"b":"w"}));
89 }
90 else
91 games[page] = {id:sid, fen:obj.fen}; //wait for opponent
92 break;
93 case "resign":
94 if (!!clients[page][obj.oppid]) // && clients[page][obj.oppid].readyState == WebSocket.OPEN)
95 clients[page][obj.oppid].send(JSON.stringify({code:"resign"}));
96 else
97 newresign[page][obj.oppid] = true;
98 break;
99 }
100 });
101 }
102 socket.on("close", () => {
103 delete clients[page][sid];
104 // Remove potential pending game
105 if (!!games[page] && games[page]["id"] == sid)
106 delete games[page];
107 if (page != "index")
108 {
109 // Send to every client connected on index an update message for counts
110 Object.keys(clients["index"]).forEach( k => {
111 clients["index"][k].send(JSON.stringify({code:"decrease",vname:page}));
112 });
113 }
114 // Also notify potential opponents: hit all clients which check if sid corresponds
115 Object.keys(clients[page]).forEach( k => {
116 clients[page][k].send(JSON.stringify({code:"disconnect",id:sid}));
117 });
118 });
119 });
120 }