mirror of https://github.com/calzoneman/sync.git
Initial experiment for UWS support
This commit is contained in:
parent
3db751b65f
commit
fb5f92b7ee
|
@ -41,6 +41,7 @@
|
|||
"sprintf-js": "^1.0.3",
|
||||
"toml": "^2.3.0",
|
||||
"uuid": "^3.2.1",
|
||||
"uws": "^10.148.0",
|
||||
"yamljs": "^0.2.8"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -725,6 +725,7 @@ Channel.prototype.handleReadLog = function (user) {
|
|||
|
||||
Channel.prototype.broadcastToRoom = function (msg, data, ns) {
|
||||
sio.instance.in(ns).emit(msg, data);
|
||||
require('../io/uws').in(ns).emit(msg, data);
|
||||
};
|
||||
|
||||
Channel.prototype.broadcastAll = function (msg, data) {
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
import { EventEmitter } from 'events';
|
||||
import { Multimap } from '../util/multimap';
|
||||
import User from '../user';
|
||||
|
||||
const rooms = new Multimap();
|
||||
|
||||
class UWSWrapper extends EventEmitter {
|
||||
constructor(socket, context) {
|
||||
super();
|
||||
|
||||
this._uwsSocket = socket;
|
||||
this._joined = new Set();
|
||||
this._connected = true;
|
||||
this.context = context;
|
||||
|
||||
this._uwsSocket.on('message', message => {
|
||||
this._emit.apply(this, this._decode(message));
|
||||
});
|
||||
|
||||
this._uwsSocket.on('close', () => {
|
||||
this._connected = false;
|
||||
|
||||
for (let room of this._joined) {
|
||||
rooms.delete(room, this);
|
||||
}
|
||||
|
||||
this._joined.clear();
|
||||
this._emit('disconnect');
|
||||
});
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this._uwsSocket.terminate();
|
||||
}
|
||||
|
||||
get disconnected() {
|
||||
return !this._connected;
|
||||
}
|
||||
|
||||
emit(frame, ...args) {
|
||||
this._uwsSocket.send(encode(frame, args));
|
||||
}
|
||||
|
||||
join(room) {
|
||||
this._joined.add(room);
|
||||
rooms.set(room, this);
|
||||
}
|
||||
|
||||
leave(room) {
|
||||
this._joined.delete(room);
|
||||
rooms.delete(room, this);
|
||||
}
|
||||
|
||||
typecheckedOn(frame, typeDef, cb) {
|
||||
this.on(frame, cb);
|
||||
}
|
||||
|
||||
typecheckedOnce(frame, typeDef, cb) {
|
||||
this.once(frame, cb);
|
||||
}
|
||||
|
||||
_decode(message) {
|
||||
// TODO: handle error and kill clients with protocol violations
|
||||
return JSON.parse(message);
|
||||
}
|
||||
}
|
||||
|
||||
Object.assign(UWSWrapper.prototype, { _emit: EventEmitter.prototype.emit });
|
||||
|
||||
function encode(frame, args) {
|
||||
return JSON.stringify([frame].concat(args));
|
||||
}
|
||||
|
||||
function inRoom(room) {
|
||||
return {
|
||||
emit(frame, ...args) {
|
||||
const encoded = encode(frame, args);
|
||||
|
||||
for (let wrapper of rooms.get(room)) {
|
||||
wrapper._uwsSocket.send(encoded);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { UWSWrapper };
|
||||
exports['in'] = inRoom;
|
||||
|
||||
export function init() {
|
||||
const uws = require('uws');
|
||||
|
||||
const server = new uws.Server({ port: 3000 });
|
||||
|
||||
server.on('connection', socket => {
|
||||
const wrap = new UWSWrapper(
|
||||
socket,
|
||||
{
|
||||
aliases: [],
|
||||
ipSessionFirstSeen: new Date(),
|
||||
torConnection: false,
|
||||
ipAddress: null
|
||||
}
|
||||
);
|
||||
new User(wrap, '127.0.0.1', null);
|
||||
});
|
||||
}
|
|
@ -190,6 +190,7 @@ var Server = function () {
|
|||
});
|
||||
|
||||
require("./io/ioserver").init(self, webConfig);
|
||||
require("./io/uws").init();
|
||||
|
||||
// background tasks init ----------------------------------------------
|
||||
require("./bgtask")(self);
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
class Multimap {
|
||||
constructor() {
|
||||
this._items = new Map();
|
||||
}
|
||||
|
||||
get(key) {
|
||||
if (this._items.has(key)) {
|
||||
return this._items.get(key);
|
||||
}
|
||||
|
||||
return new Set();
|
||||
}
|
||||
|
||||
has(key, value) {
|
||||
if (!this._items.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._items.get(key).has(value);
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
if (!this._items.has(key)) {
|
||||
this._items.set(key, new Set());
|
||||
}
|
||||
|
||||
return this._items.get(key).add(value);
|
||||
}
|
||||
|
||||
delete(key, value) {
|
||||
if (!this._items.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const res = this._items.get(key).delete(value);
|
||||
|
||||
if (this._items.get(key).size == 0) {
|
||||
this._items.delete(key);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export { Multimap };
|
|
@ -0,0 +1,34 @@
|
|||
const assert = require('assert');
|
||||
const { Multimap } = require('../../lib/util/multimap');
|
||||
|
||||
describe('Multimap', () => {
|
||||
let map;
|
||||
|
||||
beforeEach(() => {
|
||||
map = new Multimap();
|
||||
});
|
||||
|
||||
it('returns the empty set for an unset key', () => {
|
||||
assert.deepEqual(map.get('unknown'), new Set());
|
||||
});
|
||||
|
||||
it('returns a set of values for a given key', () => {
|
||||
map.set('a', 1);
|
||||
map.set('a', 2);
|
||||
map.set('a', 1);
|
||||
|
||||
assert.deepEqual(map.get('a'), new Set([1, 2]));
|
||||
});
|
||||
|
||||
it('deletes a value for a given key', () => {
|
||||
map.set('a', 1);
|
||||
map.set('a', 2);
|
||||
map.delete('a', 1);
|
||||
|
||||
assert.deepEqual(map.get('a'), new Set([2]));
|
||||
|
||||
map.delete('a', 2);
|
||||
|
||||
assert.deepEqual(map.get('a'), new Set());
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue