eazy-pomelo
Version:
NetEase Pomelo Of EazyGame OEM
124 lines (99 loc) • 4.01 kB
JavaScript
const net = require('net');
const util = require('util');
const dgram = require('dgram');
const EventEmitter = require('events').EventEmitter;
const utils = require('../util/utils');
const KCPSocket = require('./kcpsocket');
const Kick = require('./commands/kick');
const Handshake = require('./commands/handshake');
const Heartbeat = require('./commands/heartbeat');
const coder = require('./common/coder');
const DEFAULT_SOCKET_TIMEOUT = 90; //second
var curId = 1;
var Connector = function(port, host, opts) {
if (!(this instanceof Connector)) {
return new Connector(port, host, opts);
}
EventEmitter.call(this);
this.opts = opts || {};
this.host = host;
this.port = port;
this.useDict = opts.useDict;
this.useProtobuf = opts.useProtobuf;
this.clients = {};
this.handshake = null;
this.heartbeat = null;
}
util.inherits(Connector, EventEmitter);
module.exports = Connector;
Connector.prototype.start = function(cb) {
let self = this;
let app = require('../pomelo').app;
this.connector = app.components.__connector__.connector;
this.dictionary = app.components.__dictionary__;
this.protobuf = app.components.__protobuf__;
this.decodeIO_protobuf = app.components.__decodeIO__protobuf__;
//this.server = net.createServer();
this.socket = dgram.createSocket(this.opts.udpType || 'udp4');
this.socket.on('message', function(msg, peer){
//console.log(peer);
self.bindSocket(self.socket, peer.address, peer.port, msg);
});
this.socket.on('error', function(error) {
return;
});
this.socket.bind(this.port);
//this.server.listen(this.port);
process.nextTick(cb);
}
Connector.prototype.bindSocket = function(socket, address, port, msg) {
let self = this;
let key = genKey(address, port);
let kcpsocket = self.clients[key];
let opts = self.opts;
if (!kcpsocket) {
self.clients[key] = new KCPSocket(curId++, socket, address, port, opts);
kcpsocket = self.clients[key];
self.handshake = self.handshake || new Handshake(opts);
if (!self.heartbeat) {
if(!opts.heartbeat) {
opts.heartbeat = Math.max(1, opts.interval / 1000);
opts.timeout = opts.heartbeat * 2;
}
if ((opts.heartbeat * 1000) < opts.interval) {
console.warn('heartbeat interval must longer than kcp interval');
opts.heartbeat = opts.interval;
}
if ((opts.timeout * 1000) < 2 * opts.interval) {
console.warn('timeout must longer than kcp interval * 2');
opts.timeout = opts.heartbeat * 2;
}
self.heartbeat = new Heartbeat(utils.extends(opts, {disconnectOnTimeout: true}));
}
kcpsocket.on('handshake', self.handshake.handle.bind(self.handshake, kcpsocket));
kcpsocket.on('heartbeat', self.heartbeat.handle.bind(self.heartbeat, kcpsocket));
//kcpsocket.on('disconnect', self.heartbeat.clear.bind(self.heartbeat, kcpsocket.id));
kcpsocket.on('disconnect', function(){
self.heartbeat.clear(kcpsocket.id);
Kick.handle(kcpsocket, 'disconnet');
process.nextTick(function() {
kcpsocket.removeAllListeners();
delete self.clients[key];
});
});
//kcpsocket.on('closing', Kick.handle.bind(null, kcpsocket));
self.emit('connection', kcpsocket);
}
if (!!msg) {
kcpsocket.emit('input', msg);
}
}
Connector.prototype.stop = function(force, cb) {
this.socket.close();
process.nextTick(cb);
};
Connector.decode = Connector.prototype.decode = coder.decode;
Connector.encode = Connector.prototype.encode = coder.encode;
var genKey = function(address, port) {
return address + ':' + port;
}