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",
|
"sprintf-js": "^1.0.3",
|
||||||
"toml": "^2.3.0",
|
"toml": "^2.3.0",
|
||||||
"uuid": "^3.2.1",
|
"uuid": "^3.2.1",
|
||||||
|
"uws": "^10.148.0",
|
||||||
"yamljs": "^0.2.8"
|
"yamljs": "^0.2.8"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -725,6 +725,7 @@ Channel.prototype.handleReadLog = function (user) {
|
||||||
|
|
||||||
Channel.prototype.broadcastToRoom = function (msg, data, ns) {
|
Channel.prototype.broadcastToRoom = function (msg, data, ns) {
|
||||||
sio.instance.in(ns).emit(msg, data);
|
sio.instance.in(ns).emit(msg, data);
|
||||||
|
require('../io/uws').in(ns).emit(msg, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
Channel.prototype.broadcastAll = function (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/ioserver").init(self, webConfig);
|
||||||
|
require("./io/uws").init();
|
||||||
|
|
||||||
// background tasks init ----------------------------------------------
|
// background tasks init ----------------------------------------------
|
||||||
require("./bgtask")(self);
|
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