2020-03-21 07:47:42 +00:00
|
|
|
import { EventEmitter } from 'events'
|
|
|
|
import { Parser } from './parser'
|
|
|
|
import { Packet } from './packet';
|
2020-03-23 10:33:12 +00:00
|
|
|
import { NettyClient } from '../server';
|
2020-03-21 07:47:42 +00:00
|
|
|
import { SocketIO } from './interfaces'
|
2020-03-23 10:33:12 +00:00
|
|
|
import { Server, Socket } from './index';
|
|
|
|
import { PacketTypes, SubPacketTypes } from './types';
|
2020-03-21 07:47:42 +00:00
|
|
|
|
|
|
|
const parser = new Parser();
|
|
|
|
|
2020-03-22 16:58:53 +00:00
|
|
|
export class Client extends EventEmitter implements SocketIO.Client {
|
2020-03-23 10:33:12 +00:00
|
|
|
server: Server;
|
|
|
|
conn: NettyClient;
|
2020-03-21 07:47:42 +00:00
|
|
|
request: any;
|
2020-03-23 10:33:12 +00:00
|
|
|
sockets: { [id: string]: Socket; };
|
2020-03-21 07:47:42 +00:00
|
|
|
nsps: { [nsp: string]: SocketIO.Socket; };
|
2020-03-23 10:33:12 +00:00
|
|
|
connectBuffer: any;
|
2020-03-21 07:47:42 +00:00
|
|
|
|
2020-03-23 10:33:12 +00:00
|
|
|
constructor(server: Server, nettyClient: NettyClient) {
|
2020-03-22 16:58:53 +00:00
|
|
|
super();
|
|
|
|
this.server = server;
|
|
|
|
this.conn = nettyClient;
|
2020-03-23 10:33:12 +00:00
|
|
|
this.request = nettyClient.request;
|
|
|
|
this.sockets = {};
|
|
|
|
this.nsps = {};
|
2020-03-21 07:47:42 +00:00
|
|
|
}
|
|
|
|
get id() {
|
2020-03-23 10:33:12 +00:00
|
|
|
return this.conn.id;
|
2020-03-21 07:47:42 +00:00
|
|
|
}
|
2020-03-23 10:33:12 +00:00
|
|
|
connect(name, query) {
|
|
|
|
if (this.server.nsps[name]) {
|
|
|
|
// console.debug(`connecting to namespace ${name}`);
|
|
|
|
return this.doConnect(name, query);
|
|
|
|
}
|
|
|
|
this.server.checkNamespace(name, query, (dynamicNsp) => {
|
|
|
|
if (dynamicNsp) {
|
|
|
|
// console.debug('dynamic namespace %s was created', dynamicNsp.name);
|
|
|
|
this.doConnect(name, query);
|
|
|
|
} else {
|
|
|
|
// console.debug('creation of namespace %s was denied', name);
|
|
|
|
this.packet({
|
|
|
|
type: PacketTypes.MESSAGE,
|
|
|
|
sub_type: SubPacketTypes.ERROR,
|
|
|
|
nsp: name,
|
|
|
|
data: 'Invalid namespace'
|
|
|
|
});
|
|
|
|
}
|
2020-03-21 07:47:42 +00:00
|
|
|
})
|
|
|
|
}
|
2020-03-23 10:33:12 +00:00
|
|
|
doConnect(name, query) {
|
|
|
|
var nsp = this.server.of(name);
|
|
|
|
if ('/' != name && !this.nsps['/']) {
|
|
|
|
this.connectBuffer.push(name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var socket = nsp.add(this, query, () => {
|
|
|
|
this.sockets[socket.id] = socket;
|
|
|
|
this.nsps[nsp.name] = socket;
|
|
|
|
|
|
|
|
if ('/' == nsp.name && this.connectBuffer.length > 0) {
|
|
|
|
this.connectBuffer.forEach(this.connect, this);
|
|
|
|
this.connectBuffer = [];
|
|
|
|
}
|
|
|
|
});
|
2020-03-22 16:58:53 +00:00
|
|
|
}
|
2020-03-21 07:47:42 +00:00
|
|
|
packet(packet: Packet) {
|
2020-03-23 10:33:12 +00:00
|
|
|
this.conn.send(parser.encode(packet))
|
|
|
|
}
|
|
|
|
onclose(reason: string) {
|
|
|
|
// debug('client close with reason %s', reason);
|
|
|
|
// ignore a potential subsequent `close` event
|
|
|
|
this.destroy();
|
|
|
|
// `nsps` and `sockets` are cleaned up seamlessly
|
|
|
|
for (var id in this.sockets) {
|
|
|
|
if (this.sockets.hasOwnProperty(id)) {
|
|
|
|
this.sockets[id].onclose(reason);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.sockets = {};
|
|
|
|
// this.decoder.destroy(); // clean up decoder
|
|
|
|
};
|
|
|
|
close() {
|
|
|
|
// if ('open' == this.conn.readyState) {
|
|
|
|
// debug('forcing transport close');
|
|
|
|
this.conn.close();
|
|
|
|
this.onclose('forced server close');
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
remove(socket: Socket) {
|
|
|
|
if (this.sockets.hasOwnProperty(socket.id)) {
|
|
|
|
var nsp = this.sockets[socket.id].nsp.name;
|
|
|
|
delete this.sockets[socket.id];
|
|
|
|
delete this.nsps[nsp];
|
|
|
|
} else {
|
|
|
|
// debug('ignoring remove for %s', socket.id);
|
|
|
|
}
|
2020-03-21 07:47:42 +00:00
|
|
|
}
|
2020-03-23 10:33:12 +00:00
|
|
|
destroy() {
|
|
|
|
// this.conn.removeListener('data', this.ondata);
|
|
|
|
// this.conn.removeListener('error', this.onerror);
|
|
|
|
// this.conn.removeListener('close', this.onclose);
|
|
|
|
// this.decoder.removeListener('decoded', this.ondecoded);
|
|
|
|
};
|
2020-03-21 07:47:42 +00:00
|
|
|
}
|