224 lines
4.9 KiB
JavaScript
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;
|
|
}
|
|
} |