ws-playground/server/server.js

224 lines
4.9 KiB
JavaScript

const WebSocket = require("ws");
const wss = new WebSocket.Server({port: 3001});
function users() {
results = [];
wss.clients.forEach(function(client) {
// goes inside "data"
results.push({
"user": client.user,
"status": client.readyState,
});
});
return results;
}
function send(payload) {
let message = JSON.stringify({
"to": payload.to,
"from": payload.from,
"type": payload.type,
"subject": payload.subject || "",
"body": payload.body,
"data": payload.data || {},
"date": Date.now()
});
// work as 'array', not 'set'
let clients = Array.from(wss.clients);
if(!clients.length) return false;
let to = clients.find(function(client) {
console.log('user', client.user);
if(client.user === payload.to) {
client.send(message);
return true;
}
});
// carbon copy
if(to && payload.type === 'message') {
let from = clients.find(function(client) {
if(client.user === payload.from) {
client.send(message);
return true;
}
});
}
console.log('sent', !!to);
return !!to;
}
function message(payload) {
return {
"type": payload.type || "message",
"to": payload.to,
"from": payload.from || "",
"subject": payload.subject || "",
"body": payload.body || "",
"data": payload.data || {},
"date": Date.now()
}
}
function broadcast(data) {
wss.clients.forEach(function(client) {
client.send(JSON.stringify(data));
});
}
wss.on('connection', function(client) {
console.log('client connected');
client.on('message', function(payload) {
console.log('RECIEVED:', payload);
try {
payload = JSON.parse(payload);
switch(payload.type) {
case 'register':
// attach user id
client.user = payload.user;
broadcast({type: "clients", data: users(), "date": Date.now()});
console.log('CLIENT REGISTERED', client.user);
break;
case 'clients':
// update clients on page
break;
case 'message':
console.log('message', payload);
return send(payload);
case 'broadcast':
payload.date = Date.now();
broadcast(payload);
case 'notification':
return send(payload);
}
} catch(err) {
console.log(err);
}
});
client.on('close', function(e) {
console.log('client left', e);
broadcast({type: "clients", data: users(), "date": Date.now()});
});
client.on('error', function(e) {
console.log('client error', e);
});
});
wss.on('error', function(err) {
console.log('ERROR', err);
});
wss.on('close', function(e) {
console.log('close', e);
});
process.on('SIGINT', function () {
console.log("Caught interrupt signal");
broadcast({type: "offline", "date": Date.now()});
process.exit();
});
function opcodes() {
/*
0 Continuation Frame [RFC6455]
1 Text Frame [RFC6455]
2 Binary Frame [RFC6455]
3-7 Unassigned
8 Connection Close Frame [RFC6455]
9 Ping Frame [RFC6455]
10 Pong Frame [RFC6455]
11-15 Unassigned
*/
}
function close(code) {
switch(code) {
case 1000:
return 'Normal Closure';
case 1001:
return 'Going Away';
case 1002:
return 'Protocol Error';
case 1003:
return 'Unsupported Data';
case 1004:
return 'Reserved';
case 1005:
return 'No Status Rcvd';
case 1006:
return 'Abnormal Closure';
case 1007:
return 'Invalid frame payload data';
case 1008:
return 'Policy Violation';
case 1009:
return 'Message Too Big';
case 1010:
return 'Mandatory Ext.';
case 1011:
return 'Internal Error';
case 1012:
return 'Service Restart';
case 1013:
return 'Try Again Later';
case 1014:
return 'Invalid Proxy/Gateway Response';
case 1015:
return 'TLS Handshake';
default:
return 'Reserved for Private Use';
}
}
class SocketServer extends WebSocket.Server {
constructor(opts) {
super(opts);
}
users() {
results = [];
this.clients.forEach(function(client) {
// goes inside "data"
results.push({
"user": client.user,
"status": client.readyState,
});
});
return results;
}
}