forked from TCEC-Chess/tcecgui
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathchat_server.js
140 lines (127 loc) · 2.86 KB
/
chat_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
139
140
// chat_server.js
// @authors octopoulo <[email protected]>, Aloril <[email protected]>
// @version 2022-05-21
/*
globals
console, exports, require
*/
'use strict';
let Module = require('./js/chess-wasm.js'),
{Stringify} = require('./js/common.js'),
Net = require('net');
let frc = false,
LS = console.log,
port = 8090,
server = new Net.Server();
server.listen(port, () => {
LS(`Server listening for connection requests on socket localhost:${port}.`);
});
let chess,
voting = {}; //indexed by fen, supports 1-2 clients
/**
* Load chess-wasm
*/
async function loadWasm()
{
let instance = await Module();
chess = new instance.Chess();
LS('chess library loaded');
}
function vote(data)
{
LS('vote, data=' + Stringify(data));
if (typeof data.fen == "string") { //needed because fen string here don't match fen strings in Python
let lst = data.fen.split(" ");
data.fen = lst[0] + " " + lst[1] + " " + lst[5];
}
if (!(data.fen in voting) || typeof data.move != "string" || data.move.length > 5)
{
LS('Not found');
return;
}
if (!data.time)
{
LS('Old GUI, no voting');
return;
}
let entry = voting[data.fen],
move = data.move;
LS('entry: ' + Stringify(entry.votes) + ' ' + Stringify(entry.byIP));
if (!(move in entry.votes))
{
entry.votes[move] = 0;
}
if (data.ip in entry.byIP)
{
if (entry.byIP[data.ip] == move)
{
LS("Same move as earlier: " + move);
return;
}
LS(`Reduce vote: ${entry.byIP[data.ip]} by ${data.ip}`);
entry.votes[entry.byIP[data.ip]]--;
}
entry.votes[move]++;
entry.byIP[data.ip] = move;
let msg = Stringify({
fen: data.fen,
votes: Object.entries(entry.votes),
});
LS(`Sending data: ${msg}.`);
LS('---');
entry.socket.write(msg.length.toString().padStart(4, " ") + msg);
}
server.on('connection', async socket => {
let ip = socket.remoteAddress;
LS(`A new connection has been established: ${ip}.`);
if (ip != '::ffff:127.0.0.1')
{
LS('Not local connection, closing');
socket.destroy();
return;
}
if (!chess)
await loadWasm();
socket.on('data', chunk => {
// CHECK THIS: FIX: handle 2 messages in one packet or incomplete packets:
// Error can triggered by "go movetime 100" for example. Could use same method as chat_engine.read_votes does.
LS('data');
let data, text;
try
{
text = chunk.toString();
data = JSON.parse(text);
}
catch (e)
{
LS(`bad data: ${data}, text: ${text}`);
LS(e);
return;
}
if (data.voting != undefined)
{
if (data.voting)
{
voting[data.fen] = {
votes: {},
byIP: {},
socket: socket
};
LS("created empty voting");
}
else if (data.fen in voting)
{
delete voting[data.fen];
LS("deleted voting");
}
}
LS(`Data received from client: ${text}`);
});
socket.on('end', () => {
LS('Closing connection with the client');
});
socket.on('error', err => {
LS(`Error: ${err}`);
});
});
exports.vote = vote;