Files
ms/packages/websocket/src/socket-io/index.ts
2020-06-30 14:02:18 +08:00

224 lines
7.5 KiB
TypeScript

import { EventEmitter } from 'events'
import { ServerEvent } from './constants'
import { Namespace } from './namespace'
import { Client } from './client'
import { SocketIO } from './interfaces'
import { Parser } from './parser'
import { PacketTypes, SubPacketTypes } from './types'
import { Packet } from './packet'
import { Socket } from './socket'
import { Adapter } from './adapter'
interface ServerOptions extends SocketIO.ServerOptions {
event?: EventEmitter
root?: string
}
interface WebSocketServer extends EventEmitter {
close(): void
}
class Server implements SocketIO.Server {
private websocketServer: WebSocketServer
private allClients: { [key: string]: Client }
engine: { ws: any }
nsps: { [namespace: string]: Namespace }
sockets: Namespace
json: SocketIO.Server
volatile: SocketIO.Server
local: SocketIO.Server
parser = new Parser();
_adapter: Adapter
options: ServerOptions
constructor(instance: any, options: ServerOptions) {
if (!instance) { throw new Error('instance can\'t be undefiend!') }
this.allClients = {}
this.nsps = {}
this.sockets = new Namespace('/', this)
this.nsps['/'] = this.sockets
if (instance.class.name.startsWith('io.netty.channel')) {
let { NettyWebSocketServer } = require("../server")
this.websocketServer = new NettyWebSocketServer(instance, Object.assign({
event: new EventEmitter(),
path: '/socket.io',
root: root + '/wwwroot'
}, options))
} else {
let { TomcatWebSocketServer } = require("../tomcat/server")
this.websocketServer = new TomcatWebSocketServer(instance, options)
}
this.initServer()
}
checkRequest(req: any, fn: (err: any, success: boolean) => void): void {
throw new Error("Method not implemented.")
}
serveClient(): boolean
serveClient(v: boolean): SocketIO.Server
serveClient(v?: any): boolean | SocketIO.Server {
throw new Error("Method not implemented.")
}
path(): string
path(v: string): SocketIO.Server
path(v?: any): string | SocketIO.Server {
if (!arguments.length) return this.options.path
this.options.path = v.replace(/\/$/, '')
return this
}
adapter(): Adapter
adapter(v: any): SocketIO.Server
adapter(v?: any): Adapter | SocketIO.Server {
if (!arguments.length) return this._adapter
this._adapter = v
for (var i in this.nsps) {
if (this.nsps.hasOwnProperty(i)) {
this.nsps[i].initAdapter()
}
}
return this
}
origins(): string | string[]
origins(v: string | string[]): SocketIO.Server
origins(fn: (origin: string, callback: (error: string, success: boolean) => void) => void): SocketIO.Server
origins(fn?: any): string | string[] | SocketIO.Server {
throw new Error("Method not implemented.")
}
attach(srv: any, opts?: SocketIO.ServerOptions): SocketIO.Server
attach(port: number, opts?: SocketIO.ServerOptions): SocketIO.Server
attach(port: any, opts?: any): SocketIO.Server {
throw new Error("Method not implemented.")
}
listen(srv: any, opts?: SocketIO.ServerOptions): SocketIO.Server
listen(port: number, opts?: SocketIO.ServerOptions): SocketIO.Server
listen(port: any, opts?: any): SocketIO.Server {
throw new Error("Method not implemented.")
}
bind(srv: any): SocketIO.Server {
throw new Error("Method not implemented.")
}
onconnection(socket: Client): SocketIO.Server {
this.allClients[socket.id] = socket
socket.packet({
type: PacketTypes.OPEN,
data: {
sid: socket.id,
upgrades: [],
pingInterval: 25000,
pingTimeout: 5000
}
})
this.sockets.add(socket)
return this
}
of(nsp: string): Namespace {
if (!this.nsps[nsp]) {
this.nsps[nsp] = new Namespace(nsp, this)
}
return this.nsps[nsp]
}
close(fn?: () => void): void {
for (let socket in this.sockets.sockets) {
this.sockets.sockets[socket].onclose()
}
this.websocketServer.close()
}
on(event: "connection", listener: (socket: SocketIO.Socket) => void): SocketIO.Namespace
on(event: "connect", listener: (socket: SocketIO.Socket) => void): SocketIO.Namespace
on(event: string, listener: Function): SocketIO.Namespace
on(event: any, listener: any): SocketIO.Namespace {
return this.sockets.on(event, listener)
}
to(room: string): SocketIO.Namespace {
return this.sockets.to(room)
}
in(room: string): SocketIO.Namespace {
return this.sockets.in(room)
}
use(fn: (socket: SocketIO.Socket, fn: (err?: any) => void) => void): SocketIO.Namespace {
return this.sockets.use(fn)
}
emit(event: string, ...args: any[]): SocketIO.Namespace {
// @ts-ignore
return this.sockets.emit(event, ...args)
}
send(...args: any[]): SocketIO.Namespace {
return this.sockets.send(...args)
}
write(...args: any[]): SocketIO.Namespace {
return this.sockets.write(...args)
}
clients(...args: any[]): SocketIO.Namespace {
return this.sockets.clients(args[0])
}
compress(...args: any[]): SocketIO.Namespace {
return this.sockets.compress(args[0])
}
// ===============================
checkNamespace(name, query, fn) {
fn(false)
};
private initServer() {
this.websocketServer.on(ServerEvent.connect, (socket: SocketIO.EngineSocket) => {
let client = new Client(this, socket)
this.onconnection(client)
})
this.websocketServer.on(ServerEvent.message, (socket: SocketIO.EngineSocket, text) => {
this.processPacket(this.parser.decode(text), this.allClients[socket.id])
})
this.websocketServer.on(ServerEvent.disconnect, (socket: SocketIO.EngineSocket, reason) => {
this.allClients[socket.id].onclose(reason)
delete this.allClients[socket.id]
})
this.websocketServer.on(ServerEvent.error, (socket: SocketIO.EngineSocket, cause) => {
if (socket.listeners(ServerEvent.error).length) {
socket.emit(ServerEvent.error, cause)
} else {
console.error(`client ${socket.id} cause error: ${cause}`)
}
})
}
private processPacket(packet: Packet, client: Client) {
switch (packet.type) {
case PacketTypes.PING:
client.packet({
type: PacketTypes.PONG,
data: packet.data
})
break
case PacketTypes.UPGRADE:
break
case PacketTypes.MESSAGE:
this.processSubPacket(packet, client)
break
case PacketTypes.CLOSE:
client.onclose()
break
}
}
private processSubPacket(packet: Packet, client: Client) {
let namespace = this.nsps[packet.nsp]
if (!namespace) {
client.packet({
type: PacketTypes.MESSAGE,
sub_type: SubPacketTypes.ERROR,
data: 'not support dynamic namespace: ' + packet.nsp
})
client.disconnect()
return
}
namespace.process(packet, client)
}
}
export {
Server,
Socket,
Client,
ServerOptions
}