occaecatidicta
Version:
275 lines (229 loc) • 8.39 kB
text/typescript
import { getLogger } from 'omelox-logger'; let logger = getLogger('omelox-admin', 'MasterSocket');
import * as Constants from '../util/constants';
import * as protocol from '../util/protocol';
import { MasterAgent, AuthServerRequest, AuthUserRequest } from './masterAgent';
import * as net from 'net';
import { MqttSocket } from '../protocol/mqtt/mqttServer';
import { AdminUserInfo, ServerInfo } from '../util/constants';
export class MasterSocket {
id: string = null;
type: string = null;
info: string | ServerInfo = null;
agent: MasterAgent = null;
socket: MqttSocket = null;
username: string = null;
registered = false;
onRegister(_msg: AuthUserRequest | AuthServerRequest & {type: string}) {
if (!_msg || !_msg.type) {
return;
}
let self = this;
let serverId = _msg.id;
let serverType = _msg.type;
let socket = this.socket;
if (serverType === Constants.TYPE_CLIENT) {
let msg = _msg as AuthUserRequest;
// client connection not join the map
this.id = serverId;
this.type = serverType;
this.info = 'client';
this.agent.doAuthUser(msg, socket, function (err: Error) {
if (err) {
return socket.disconnect();
}
self.username = msg.username;
self.registered = true;
});
return;
} // end of if(serverType === 'client')
if (serverType === Constants.TYPE_MONITOR) {
if (!serverId) {
return;
}
let msg = _msg as AuthServerRequest;
// if is a normal server
this.id = serverId;
this.type = msg.serverType;
this.info = msg.info;
this.agent.doAuthServer(msg, socket, function (err) {
if (err) {
return socket.disconnect();
}
self.registered = true;
});
this.repushQosMessage(serverId);
return;
} // end of if(serverType === 'monitor')
this.agent.doSend(socket, 'register', {
code: protocol.PRO_FAIL,
msg: 'unknown auth master type'
});
socket.disconnect();
}
onMonitor(msg: any) {
let socket = this.socket;
if (!this.registered) {
// not register yet, ignore any message
// kick connections
socket.disconnect();
return;
}
let self = this;
let type = this.type;
if (type === Constants.TYPE_CLIENT) {
logger.error('invalid message from monitor, but current connect type is client.');
return;
}
msg = protocol.parse(msg);
let respId = msg.respId;
if (respId) {
// a response from monitor
let cb = self.agent.callbacks[respId];
if (!cb) {
logger.warn('unknown resp id:' + respId);
return;
}
let id = this.id;
if (self.agent.msgMap[id]) {
delete self.agent.msgMap[id][respId];
}
delete self.agent.callbacks[respId];
return cb(msg.error, msg.body);
}
// a request or a notify from monitor
self.agent.consoleService.execute(msg.moduleId, 'masterHandler', msg.body, function (err, res) {
if (protocol.isRequest(msg)) {
let resp = protocol.composeResponse(msg, err, res);
if (resp) {
self.agent.doSend(socket, 'monitor', resp);
}
} else {
// notify should not have a callback
logger.warn('notify should not have a callback.');
}
});
}
onClient(msg: any) {
let socket = this.socket;
if (!this.registered) {
// not register yet, ignore any message
// kick connections
return socket.disconnect();
}
let type = this.type;
if (type !== Constants.TYPE_CLIENT) {
logger.error('invalid message to client, but current connect type is ' + type);
return;
}
msg = protocol.parse(msg);
let msgCommand = msg.command;
let msgModuleId = msg.moduleId;
let msgBody = msg.body;
let self = this;
if (msgCommand) {
// a command from client
self.agent.consoleService.command(msgCommand, msgModuleId, msgBody, function (err, res) {
if (protocol.isRequest(msg)) {
let resp = protocol.composeResponse(msg, err, res);
if (resp) {
self.agent.doSend(socket, 'client', resp);
}
} else {
// notify should not have a callback
logger.warn('notify should not have a callback.');
}
});
} else {
// a request or a notify from client
// and client should not have any response to master for master would not request anything from client
self.agent.consoleService.execute(msgModuleId, 'clientHandler', msgBody, function (err, res) {
if (protocol.isRequest(msg)) {
let resp = protocol.composeResponse(msg, err, res);
if (resp) {
self.agent.doSend(socket, 'client', resp);
}
} else {
// notify should not have a callback
logger.warn('notify should not have a callback.');
}
});
}
}
onReconnect(msg: any, pid ?: string) {
// reconnect a new connection
if (!msg || !msg.type) {
return;
}
let serverId = msg.id;
if (!serverId) {
return;
}
let socket = this.socket;
// if is a normal server
if (this.agent.idMap[serverId]) {
// id has been registered
this.agent.doSend(socket, 'reconnect_ok', {
code: protocol.PRO_FAIL,
msg: 'id has been registered. id:' + serverId
});
return;
}
let msgServerType = msg.serverType;
let record = this.agent.addConnection(serverId, msgServerType, msg.pid, msg.info, socket);
this.id = serverId;
this.type = msgServerType;
this.registered = true;
msg.info.pid = pid;
this.info = msg.info;
this.agent.doSend(socket, 'reconnect_ok', {
code: protocol.PRO_OK,
msg: 'ok'
});
this.agent.emit('reconnect', msg.info);
this.repushQosMessage(serverId);
}
onDisconnect() {
let socket = this.socket;
if (socket) {
delete this.agent.sockets[socket.id];
}
let registered = this.registered;
if (!registered) {
return;
}
let id = this.id;
let type = this.type;
let info = this.info;
let username = this.username;
logger.debug('disconnect %s %s %j', id, type, info);
if (registered) {
this.agent.removeConnection(id, type, info as ServerInfo);
this.agent.emit('disconnect', id, type, info);
}
if (type === Constants.TYPE_CLIENT && registered) {
logger.info('client user ' + username + ' exit');
}
this.registered = false;
this.id = null;
this.type = null;
}
repushQosMessage(serverId: string) {
let socket = this.socket;
// repush qos message
let qosMsgs = this.agent.msgMap[serverId];
if (!qosMsgs) {
return;
}
logger.debug('repush qos message %j', qosMsgs);
for (let reqId in qosMsgs) {
let qosMsg = qosMsgs[reqId];
let moduleId = qosMsg['moduleId'];
let tmsg = qosMsg['msg'];
this.agent.sendToMonitor(socket, Number(reqId), moduleId, tmsg);
}
}
onError(err: Error) {
// logger.error('server %s error %s', this.id, err.stack);
// this.onDisconnect();
}
}