@sex-pomelo/sex-pomelo
Version:
[![NPM version][npm-image-pomelo]][npm-url-pomelo] [![NPM version][npm-image-down]][npm-url-pomelo]
144 lines (120 loc) • 3.16 kB
JavaScript
"use strict";
const EventEmitter = require('events').EventEmitter;
const handler = require('./common/handler');
const protocol = require('@sex-pomelo/sex-pomelo-protocol');
const reFilename = __filename.substring(__filename.indexOf("node_modules"))
const logger = require('@sex-pomelo/sex-pomelo-logger').getLogger('pomelo', reFilename);
const Package = protocol.Package;
const ST_INITED = 0;
const ST_WAIT_ACK = 1;
const ST_WORKING = 2;
const ST_CLOSED = 3;
class Socket extends EventEmitter
{
constructor(id, socket) {
super();
this.id = id;
this.socket = socket;
if(!socket._socket) {
this.remoteAddress = {
ip: (socket._socket.pomeloXffIP !== undefined) ?socket._socket.pomeloXffIP : socket.address().address,
port: socket.address().port
};
} else {
this.remoteAddress = {
ip: (socket._socket.pomeloXffIP !== undefined) ?socket._socket.pomeloXffIP : socket._socket.remoteAddress,
port: socket._socket.remotePort
};
}
let self = this;
socket.once('close', this.emit.bind(this, 'disconnect'));
socket.on('error', this.emit.bind(this, 'error'));
socket.on('message', function(msg) {
if(msg) {
msg = Package.decode(msg);
handler(self, msg);
}
});
this.state = ST_INITED;
// TODO: any other events?
}
/**
* Send raw byte data.
*
* @api private
*/
sendRaw(msg) {
if(this.state !== ST_WORKING) {
return;
}
this.socket.send(msg, {binary: true}, function(err) {
if(!!err) {
logger.info('websocket send binary data failed: %j', err.stack);
return;
}
});
}
/**
* Send byte data package to client.
*
* @param {Buffer} msg byte data
*/
send(msg) {
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));
}
/**
* Send byte data packages to client in batch.
*
* @param {Buffer} msgs byte data
*/
sendBatch(msgs) {
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));
};
/**
* Send message to client no matter whether handshake.
*
* @api private
*/
sendForce(msg) {
if(this.state === ST_CLOSED) {
return;
}
this.socket.send(msg, {binary: true});
};
/**
* Response handshake request
*
* @api private
*/
handshakeResponse(resp) {
if(this.state !== ST_INITED) {
return;
}
this.socket.send(resp, {binary: true});
this.state = ST_WAIT_ACK;
};
/**
* Close the connection.
*
* @api private
*/
disconnect() {
if(this.state === ST_CLOSED) {
return;
}
this.state = ST_CLOSED;
this.socket.emit('close');
this.socket.close();
};
}
module.exports = Socket;