123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- 'use strict';
-
- const assert = require('bsert');
- const EventEmitter = require('events');
- const Packet = require('./packet');
- const WebSocket = require('./backend');
- const Socket = require('./socket');
-
- class Server extends EventEmitter {
- constructor(options = {}) {
- super();
-
- assert(!options.protocols || Array.isArray(options.protocols));
-
- this.protocols = options.protocols || undefined;
- this.sockets = new Set();
- this.channels = new Map();
- this.mounts = [];
- this.mounted = false;
- }
-
- handleSocket(socket) {
- this.add(socket);
-
- socket.on('close', () => {
- this.remove(socket);
- });
-
- this.emit('socket', socket);
-
- for (const server of this.mounts)
- server.emit('socket', socket);
- }
-
- mount(server) {
- assert(!server.mounted);
- server.mounted = true;
- server.sockets = this.sockets;
- server.channels = this.channels;
- this.mounts.push(server);
- }
-
- async open() {
- ;
- }
-
- async close() {
- if (this.mounted)
- return;
-
- for (const socket of this.sockets)
- socket.destroy();
- }
-
- attach(server) {
- const onUpgrade = (req, socket, body) => {
- if (!socket.remoteAddress) {
- socket.destroy();
- return;
- }
-
- if (!WebSocket.isWebSocket(req)) {
- socket.destroy();
- return;
- }
-
- const ws = new WebSocket(req, socket, body, this.protocols);
- const sock = Socket.accept(this, req, socket, ws);
-
- this.handleSocket(sock);
- };
-
- server.on('upgrade', (req, socket, body) => {
- try {
- onUpgrade(req, socket, body);
- } catch (e) {
- this.emit('error', e);
- }
- });
-
- return this;
- }
-
- add(socket) {
- this.sockets.add(socket);
- }
-
- remove(socket) {
- for (const name of socket.channels)
- this.leave(socket, name);
-
- assert(this.sockets.delete(socket));
- }
-
- join(socket, name) {
- if (socket.channels.has(name))
- return false;
-
- if (!this.channels.has(name))
- this.channels.set(name, new Set());
-
- const sockets = this.channels.get(name);
-
- sockets.add(socket);
- socket.channels.add(name);
-
- return true;
- }
-
- leave(socket, name) {
- if (!socket.channels.has(name))
- return false;
-
- const sockets = this.channels.get(name);
-
- assert(sockets);
- assert(sockets.delete(socket));
-
- if (sockets.size === 0)
- this.channels.delete(name);
-
- socket.channels.delete(name);
-
- return true;
- }
-
- channel(name) {
- const sockets = this.channels.get(name);
-
- if (!sockets)
- return null;
-
- assert(sockets.size > 0);
-
- return sockets;
- }
-
- event(args) {
- assert(args.length > 0, 'Event must be present.');
- assert(typeof args[0] === 'string', 'Event must be a string.');
- const packet = new Packet();
- packet.type = Packet.types.EVENT;
- packet.setData(args);
- return packet;
- }
-
- to(name, ...args) {
- const sockets = this.channels.get(name);
-
- if (!sockets)
- return;
-
- assert(sockets.size > 0);
-
- // Pre-serialize for speed.
- const packet = this.event(args);
-
- for (const socket of sockets)
- socket.sendPacket(packet);
- }
-
- all(...args) {
- // Pre-serialize for speed.
- const packet = this.event(args);
-
- for (const socket of this.sockets)
- socket.sendPacket(packet);
- }
-
- static attach(parent, options) {
- const server = new this(options);
- return server.attach(parent);
- }
-
- static createServer(options) {
- return new this(options);
- }
- }
-
- module.exports = Server;
|