forked from renefournier/clicker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
138 lines (122 loc) · 3.5 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
const WebSocket = require("ws");
const Server = WebSocket.Server;
const Geoip = require("geoip-lite");
const Url = require("url");
const port = process.env.PORT || 2424;
const wss = new Server({ port });
let channelStates = {};
wss.on("connection", (ws, req) => {
ws.upgradeReq = req;
var clientID = req.headers["sec-websocket-key"];
console.log("+++ New connection: ", clientID);
console.log(`connection url: ${req.url}`);
var params = Url.parse(req.url, true).query;
console.log("params", params);
// console.log(params.channel.length);
if (!params || !params.channel) {
ws.close();
}
console.log(wss.clients.size, "clients");
ws.channel = params.channel;
if (!channelStates[ws.channel]) {
// IF CHANNEL_ID UNREGISTERED, FIRST CONNECTION IS SPEAKER
// SOURCE OF TRUTH
ws.role = "speaker"; //default
channelStates[ws.channel] = new Array(15).fill({ s: false, p: false });
} else {
// WHAT IF SPEAKER WENT AWAY?
let consoles = 0;
let speakers = 0;
wss.clients.forEach((client) => {
if (client.channel === ws.channel) {
// ONLY DO STATS ON CLIENTS WITH SAME CHANNEL ID
if (client.role === "speaker") {
speakers++;
} else if (client.role === "console") {
consoles++;
}
}
});
console.log("speakers", speakers);
console.log("consoles", consoles);
if (speakers === 0) {
ws.role = "speaker";
} else {
ws.role = "console"; //default
}
}
console.log("---ROLE---", ws.role);
const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
const geo = Geoip.lookup(ip);
console.log("GEO IP", geo, ip);
let data = {
cmd: "state",
state: channelStates[ws.channel]
};
announce(ws.channel, data);
ws.on("message", (msg) => {
var clientID = ws.upgradeReq.headers["sec-websocket-key"];
let data = {};
try {
data = JSON.parse(msg);
} catch (e) {
console.error(e);
}
if (!data) {
return;
}
console.log(
":::",
clientID,
ws.channel,
ws.role,
data,
wss.clients.size + " clients"
);
if (!data.cmd) {
console.log("!!!!!! BYE");
process.exit(0);
}
switch (data.cmd) {
case "tap":
let prev_s = channelStates[ws.channel][data.slide - 1].s;
let prev_p = channelStates[ws.channel][data.slide - 1].p;
let next_s = ws.role === "speaker" ? !prev_s : prev_s;
let next_p = ws.role === "console" ? !prev_p : prev_p;
let newSlide = { s: next_s, p: next_p };
channelStates[ws.channel] = new Array(15).fill({ s: false, p: false });
channelStates[ws.channel][data.slide - 1] = newSlide;
let newData = {
cmd: "state",
state: channelStates[ws.channel]
};
announce(ws.channel, newData);
break;
case "ping": // DO NOTHING
break;
}
});
ws.on("close", () => {
console.log("xxx Closing");
let peers = 0;
wss.clients.forEach((client) => {
if (client.channel === ws.channel) {
peers++;
}
});
if (peers < 1) {
delete channelStates[ws.channel];
}
console.log(channelStates);
});
});
function announce(channel, data) {
console.log("*** announcing ***");
wss.clients.forEach((client) => {
if (client.channel === channel && client.readyState === WebSocket.OPEN) {
console.log("--> Channel ID: ", client.channel);
data.role = client.role;
client.send(JSON.stringify(data));
}
});
}