summaryrefslogtreecommitdiff
path: root/server.js
diff options
context:
space:
mode:
Diffstat (limited to 'server.js')
-rw-r--r--server.js205
1 files changed, 107 insertions, 98 deletions
diff --git a/server.js b/server.js
index 6c4caee..be67657 100644
--- a/server.js
+++ b/server.js
@@ -4,8 +4,9 @@ const fs = require('fs');
const crypto = require('crypto');
const http = require('http');
const https = require('https');
-const socket_io = require('socket.io');
+const { WebSocketServer } = require('ws');
const express = require('express');
+const url = require('url');
const compression = require('compression');
const sqlite3 = require('better-sqlite3');
@@ -100,10 +101,10 @@ app.locals.SITE_NAME = SITE_NAME;
let http_port = process.env.HTTP_PORT || 8080;
let http_server = http.createServer(app);
-let http_io = socket_io(http_server);
+let http_wss = new WebSocketServer({server: http_server});
http_server.keepAliveTimeout = 0;
http_server.listen(http_port, '0.0.0.0', () => console.log('listening HTTP on *:' + http_port));
-let io = http_io;
+let wss = http_wss;
let https_port = process.env.HTTPS_PORT;
if (https_port) {
@@ -111,13 +112,10 @@ if (https_port) {
key: fs.readFileSync(process.env.SSL_KEY || "key.pem"),
cert: fs.readFileSync(process.env.SSL_CERT || "cert.pem")
}, app);
- let https_io = socket_io(https_server);
+ let https_wss = new WebSocketServer({server: https_server});
https_server.listen(https_port, '0.0.0.0', () => console.log('listening HTTPS on *:' + https_port));
- http_server.keepAliveTimeout=0;
- io = {
- use: function (fn) { http_io.use(fn); https_io.use(fn); },
- on: function (ev,fn) { http_io.on(ev,fn); https_io.on(ev,fn); },
- };
+ https_server.keepAliveTimeout = 0;
+ wss = { on: function (ev,fn) { http_wss.on(ev,fn); https_wss.on(ev,fn); } };
}
/*
@@ -129,19 +127,16 @@ function random_seed() {
}
function LOG(req, ...msg) {
- let name;
- if (req.user)
- name = `"${req.user.name}" <${req.user.mail}>`;
- else
- name = "guest";
let time = new Date().toISOString().substring(0,19).replace("T", " ");
+ let name = req.user ? `"${req.user.name}" <${req.user.mail}>` : "guest";
console.log(time, req.connection.remoteAddress, name, ...msg);
}
function SLOG(socket, ...msg) {
let time = new Date().toISOString().substring(0,19).replace("T", " ");
- console.log(time, socket.request.connection.remoteAddress, socket.user_name,
- socket.title_id + "/" + socket.game_id + "/" + socket.role, ...msg);
+ let name = socket.user ? `"${socket.user.name}" <${socket.user.mail}>` : "guest";
+ console.log(time, socket.ip, name,
+ "WS /" + socket.title_id + "/" + socket.game_id + "/" + socket.role, ...msg);
}
function human_date(time) {
@@ -287,19 +282,6 @@ app.use(function (req, res, next) {
return next();
});
-io.use(function (socket, next) {
- let sid = login_cookie(socket.request);
- if (sid)
- socket.user_id = login_sql_select.get(sid);
- else
- socket.user_id = 0;
- if (socket.user_id)
- socket.user_name = SQL_SELECT_USER_NAME.get(socket.user_id);
- else
- socket.user_name = "guest";
- return next();
-});
-
function must_be_logged_in(req, res, next) {
if (!req.user)
return res.redirect('/login?redirect=' + encodeURIComponent(req.originalUrl));
@@ -1378,7 +1360,7 @@ app.get('/:title_id/play\::game_id\::role', must_be_logged_in, function (req, re
let game_id = req.params.game_id;
let role = req.params.role;
if (!SQL_AUTHORIZE_GAME_ROLE.get(title_id, game_id, role, user_id))
- return res.send("You are not assigned that role.");
+ return res.status(404).send("Invalid game ID.");
return res.sendFile(__dirname + '/public/' + title_id + '/play.html');
});
@@ -1515,7 +1497,7 @@ function mail_ready_to_start_notification(user, game_id, interval) {
function mail_your_turn_notification_to_offline_users(game_id, old_active, active) {
function is_online(game_id, user_id) {
for (let other of clients[game_id])
- if (other.user_id === user_id)
+ if (other.user && other.user.user_id === user_id)
return true;
return false;
}
@@ -1572,21 +1554,25 @@ setInterval(notify_ready_to_start_reminder, 5 * 60 * 1000);
let clients = {};
+function send_message(socket, cmd, arg) {
+ socket.send(JSON.stringify([cmd, arg]));
+}
+
function send_state(socket, state) {
try {
let view = socket.rules.view(state, socket.role);
- if (socket.log_length < view.log.length)
- view.log_start = socket.log_length;
+ if (socket.seen < view.log.length)
+ view.log_start = socket.seen;
else
view.log_start = view.log.length;
- socket.log_length = view.log.length;
+ socket.seen = view.log.length;
view.log = view.log.slice(view.log_start);
if (state.state === 'game_over')
view.game_over = 1;
- socket.emit('state', view);
+ send_message(socket, 'state', view);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1624,7 +1610,7 @@ function on_action(socket, action, arg) {
put_replay(socket.game_id, socket.role, action, arg);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1638,7 +1624,7 @@ function on_resign(socket) {
put_replay(socket.game_id, socket.role, 'resign', null);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1648,25 +1634,25 @@ function on_getchat(socket, seen) {
if (chat.length > 0)
SLOG(socket, "GETCHAT", seen, chat.length);
for (let i = 0; i < chat.length; ++i)
- socket.emit('chat', chat[i]);
+ send_message(socket, 'chat', chat[i]);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
function on_chat(socket, message) {
message = message.substring(0,4000);
try {
- let chat = SQL_INSERT_GAME_CHAT.get(socket.game_id, socket.user_id, message);
- chat[2] = socket.user_name;
+ let chat = SQL_INSERT_GAME_CHAT.get(socket.game_id, socket.user.user_id, message);
+ chat[2] = socket.user.name;
SLOG(socket, "CHAT");
for (let other of clients[socket.game_id])
if (other.role !== "Observer")
- other.emit('chat', chat);
+ send_message(other, 'chat', chat);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1675,11 +1661,11 @@ function on_debug(socket) {
try {
let game_state = SQL_SELECT_GAME_STATE.get(socket.game_id);
if (!game_state)
- return socket.emit('error', "No game with that ID.");
- socket.emit('debug', game_state);
+ return send_message(socket, 'error', "No game with that ID.");
+ send_message(socket, 'debug', game_state);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1688,16 +1674,16 @@ function on_save(socket) {
try {
let game_state = SQL_SELECT_GAME_STATE.get(socket.game_id);
if (!game_state)
- return socket.emit('error', "No game with that ID.");
- socket.emit('save', game_state);
+ return send_message(socket, 'error', "No game with that ID.");
+ send_message(socket, 'save', game_state);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
function on_restore(socket, state_text) {
- SLOG(socket, 'RESTORE');
+ SLOG(socket, "RESTORE");
try {
let state = JSON.parse(state_text);
state.seed = random_seed(); // reseed!
@@ -1709,7 +1695,7 @@ function on_restore(socket, state_text) {
send_state(other, state);
} catch (err) {
console.log(err);
- return socket.emit('error', err.toString());
+ return send_message(socket, 'error', err.toString());
}
}
@@ -1718,89 +1704,112 @@ function broadcast_presence(game_id) {
for (let socket of clients[game_id])
presence[socket.role] = true;
for (let socket of clients[game_id])
- socket.emit('presence', presence);
+ send_message(socket, 'presence', presence);
+}
+
+function on_restart(socket, scenario) {
+ try {
+ let seed = random_seed();
+ let state = socket.rules.setup(seed, scenario, {}, socket.players);
+ put_replay(socket.game_id, null, 'setup', [seed, scenario, null, socket.players]);
+ for (let other of clients[socket.game_id]) {
+ other.seen = 0;
+ send_state(other, state);
+ }
+ let state_text = JSON.stringify(state);
+ SQL_UPDATE_GAME_RESULT.run(1, null, socket.game_id);
+ SQL_UPDATE_GAME_STATE.run(socket.game_id, state_text, state.active);
+ } catch (err) {
+ console.log(err);
+ return send_message(socket, 'error', err.toString());
+ }
}
-io.on('connection', (socket) => {
- socket.title_id = socket.handshake.query.title || "unknown";
- socket.game_id = socket.handshake.query.game | 0;
- socket.role = socket.handshake.query.role;
- socket.log_length = 0;
+function handle_message(socket, cmd, arg) {
+ switch (cmd) {
+ case 'action': on_action(socket, arg[0], arg[1]); break;
+ case 'resign': on_resign(socket); break;
+ case 'getchat': on_getchat(socket, arg); break;
+ case 'chat': on_chat(socket, arg); break;
+ case 'debug': on_debug(socket); break;
+ case 'save': on_save(socket); break;
+ case 'restore': on_restore(socket, arg); break;
+ case 'restart': on_restart(socket, arg); break;
+ }
+}
+
+wss.on('connection', (socket, req, client) => {
+ let u = url.parse(req.url, true);
+ if (u.pathname !== '/play-socket')
+ return setTimeout(() => socket.close(1000, "Invalid request."), 30000);
+ req.query = u.query;
+
+ let user_id = 0;
+ let sid = login_cookie(req);
+ if (sid)
+ user_id = login_sql_select.get(sid);
+ if (user_id)
+ socket.user = SQL_SELECT_USER_INFO.get(user_id);
+
+ socket.ip = req.connection.remoteAddress;
+ socket.title_id = req.query.title || "unknown";
+ socket.game_id = req.query.game | 0;
+ socket.role = req.query.role;
+ socket.seen = req.query.seen | 0;
socket.rules = RULES[socket.title_id];
- SLOG(socket, "CONNECT");
+ SLOG(socket, "OPEN " + socket.seen);
try {
let title_id = SQL_SELECT_GAME_TITLE.get(socket.game_id);
if (title_id !== socket.title_id)
- return socket.emit('error', "Invalid game ID.");
+ return socket.close(1000, "Invalid game ID.");
- let players = SQL_SELECT_PLAYERS_JOIN.all(socket.game_id);
+ let players = socket.players = SQL_SELECT_PLAYERS_JOIN.all(socket.game_id);
if (socket.role !== "Observer") {
- if (!socket.user_id)
- return socket.emit('error', "You are not logged in!");
+ if (!socket.user)
+ return socket.close(1000, "You are not logged in!");
if (socket.role && socket.role !== 'undefined' && socket.role !== 'null') {
- let me = players.find(p => p.user_id === socket.user_id && p.role === socket.role);
- if (!me) {
- socket.role = "Observer";
- return socket.emit('error', "You aren't assigned that role!");
- }
+ let me = players.find(p => p.user_id === socket.user.user_id && p.role === socket.role);
+ if (!me)
+ return socket.close(1000, "You aren't assigned that role!");
} else {
- let me = players.find(p => p.user_id === socket.user_id);
+ let me = players.find(p => p.user_id === socket.user.user_id);
socket.role = me ? me.role : "Observer";
}
}
- socket.emit('roles', socket.role, players);
+ if (socket.seen === 0)
+ send_message(socket, 'players', [socket.role, players]);
if (clients[socket.game_id])
clients[socket.game_id].push(socket);
else
clients[socket.game_id] = [ socket ];
- socket.on('disconnect', () => {
- SLOG(socket, "DISCONNECT");
+ socket.on('close', (code, reason) => {
+ SLOG(socket, "CLOSE " + code);
clients[socket.game_id].splice(clients[socket.game_id].indexOf(socket), 1);
- if (socket.role !== "Observer")
- broadcast_presence(socket.game_id);
+ broadcast_presence(socket.game_id);
});
if (socket.role !== "Observer") {
- socket.on('action', (action, arg) => on_action(socket, action, arg));
- socket.on('resign', () => on_resign(socket));
- socket.on('getchat', (seen) => on_getchat(socket, seen));
- socket.on('chat', (message) => on_chat(socket, message));
-
- socket.on('debug', () => on_debug(socket));
- socket.on('save', () => on_save(socket));
- socket.on('restore', (state) => on_restore(socket, state));
- socket.on('restart', (scenario) => {
+ socket.on('message', (data) => {
try {
- let seed = random_seed();
- let state = socket.rules.setup(seed, scenario, {}, players);
- put_replay(socket.game_id, null, 'setup', [seed, scenario, null, players]);
- for (let other of clients[socket.game_id]) {
- other.log_length = 0;
- send_state(other, state);
- }
- let state_text = JSON.stringify(state);
- SQL_UPDATE_GAME_RESULT.run(1, null, socket.game_id);
- SQL_UPDATE_GAME_STATE.run(socket.game_id, state_text, state.active);
+ let [ cmd, arg ] = JSON.parse(data);
+ handle_message(socket, cmd, arg);
} catch (err) {
- console.log(err);
- return socket.emit('error', err.toString());
+ send_message(socket, 'error', err);
}
});
}
broadcast_presence(socket.game_id);
-
send_state(socket, get_game_state(socket.game_id));
-
} catch (err) {
console.log(err);
- socket.emit('error', err.message);
+ socket.close(1000, err.message);
}
});