"use strict";
const handler = require('./common/handler');
const protocol = require('@sex-pomelo/sex-pomelo-protocol');
const Package = protocol.Package;
const EventEmitter = require('events').EventEmitter;
const logger = require('@sex-pomelo/sex-pomelo-logger').getLogger('pomelo', __filename);
const ST_INITED = 0;
const ST_WAIT_ACK = 1;
const ST_WORKING = 2;
const ST_CLOSED = 3;
/**
*
* @class udpsocket
* @constructor
* @memberof UdpConnector
*/
class Socket extends EventEmitter
{
constructor(id, socket, peer) {
super();
this.id = id;
this.socket = socket;
this.peer = peer;
this.host = peer.address;
this.port = peer.port;
this.remoteAddress = {
ip: this.host,
port: this.port
};
let self = this;
this.on('package', function(pkg) {
if(!!pkg) {
pkg = Package.decode(pkg);
handler(self, pkg);
}
});
this.state = ST_INITED;
}
/**
* Send byte data package to client.
*
* @param {Buffer} msg byte data
*/
send(msg) {
if(this.state !== ST_WORKING) {
return;
}
if( typeof(msg) === 'string') {
msg = Buffer.from(msg);
} else if(!(msg instanceof Buffer)) {
msg = Buffer.from(JSON.stringify(msg));
}
this.sendRaw(Package.encode(Package.TYPE_DATA, msg));
}
sendRaw(msg) {
this.socket.send(msg, 0, msg.length, this.port, this.host, function(err, bytes) {
if(!!err) {
logger.error('send msg to remote with err: %j', err.stack);
return;
}
});
}
sendForce (msg) {
if(this.state === ST_CLOSED) {
return;
}
this.sendRaw(msg);
}
handshakeResponse(resp) {
if(this.state !== ST_INITED) {
return;
}
this.sendRaw(resp);
this.state = ST_WAIT_ACK;
}
sendBatch(msgs) {
if(this.state !== ST_WORKING) {
return;
}
let rs = [];
for(let i=0; i<msgs.length; i++) {
let src = Package.encode(Package.TYPE_DATA, msgs[i]);
rs.push(src);
}
this.sendRaw(Buffer.concat(rs));
}
disconnect() {
if(this.state === ST_CLOSED) {
return;
}
this.state = ST_CLOSED;
this.emit('disconnect', 'the connection is disconnected.');
}
}
module.exports = Socket;