sioconnector.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. var util = require('util');
  2. var EventEmitter = require('events').EventEmitter;
  3. var sio = require('socket.io')();
  4. var SioSocket = require('./siosocket');
  5. var PKG_ID_BYTES = 4;
  6. var PKG_ROUTE_LENGTH_BYTES = 1;
  7. var PKG_HEAD_BYTES = PKG_ID_BYTES + PKG_ROUTE_LENGTH_BYTES;
  8. var curId = 1;
  9. /**
  10. * Connector that manager low level connection and protocol bewteen server and client.
  11. * Develper can provide their own connector to switch the low level prototol, such as tcp or probuf.
  12. */
  13. var Connector = function (port, host, opts) {
  14. if (!(this instanceof Connector)) {
  15. return new Connector(port, host, opts);
  16. }
  17. EventEmitter.call(this);
  18. this.port = port;
  19. this.host = host;
  20. this.opts = opts;
  21. this.heartbeats = opts.heartbeats || true;
  22. this.closeTimeout = opts.closeTimeout || 60;
  23. this.heartbeatTimeout = opts.heartbeatTimeout || 60;
  24. this.heartbeatInterval = opts.heartbeatInterval || 25;
  25. };
  26. util.inherits(Connector, EventEmitter);
  27. module.exports = Connector;
  28. /**
  29. * Start connector to listen the specified port
  30. */
  31. Connector.prototype.start = function (cb) {
  32. var self = this;
  33. // issue https://github.com/NetEase/pomelo-cn/issues/174
  34. if (!!this.opts) {
  35. this.wsocket = sio.listen(this.port, this.opts);
  36. }
  37. else {
  38. this.wsocket = sio.listen(this.port, {
  39. transports: [
  40. 'websocket', 'htmlfile', 'xhr-polling', 'jsonp-polling', 'flashsocket'
  41. ]
  42. });
  43. }
  44. this.wsocket.set('close timeout', this.closeTimeout);
  45. this.wsocket.set('heartbeat timeout', this.heartbeatTimeout);
  46. this.wsocket.set('heartbeat interval', this.heartbeatInterval);
  47. this.wsocket.set('heartbeats', this.heartbeats);
  48. // this.wsocket.set('log level', 1);
  49. this.wsocket.sockets.on('connection', function (socket) {
  50. var siosocket = new SioSocket(curId++, socket);
  51. self.emit('connection', siosocket);
  52. siosocket.on('closing', function (reason) {
  53. siosocket.send({ route: 'onKick', reason: reason });
  54. });
  55. });
  56. process.nextTick(cb);
  57. };
  58. /**
  59. * Stop connector
  60. */
  61. Connector.prototype.stop = function (force, cb) {
  62. this.wsocket.server.close();
  63. process.nextTick(cb);
  64. };
  65. Connector.encode = Connector.prototype.encode = function (reqId, route, msg) {
  66. if (reqId) {
  67. return composeResponse(reqId, route, msg);
  68. } else {
  69. return composePush(route, msg);
  70. }
  71. };
  72. /**
  73. * Decode client message package.
  74. *
  75. * Package format:
  76. * message id: 4bytes big-endian integer
  77. * route length: 1byte
  78. * route: route length bytes
  79. * body: the rest bytes
  80. *
  81. * @param {String} data socket.io package from client
  82. * @return {Object} message object
  83. */
  84. Connector.decode = Connector.prototype.decode = function (msg) {
  85. var index = 0;
  86. var id = parseIntField(msg, index, PKG_ID_BYTES);
  87. index += PKG_ID_BYTES;
  88. var routeLen = parseIntField(msg, index, PKG_ROUTE_LENGTH_BYTES);
  89. var route = msg.substr(PKG_HEAD_BYTES, routeLen);
  90. var body = msg.substr(PKG_HEAD_BYTES + routeLen);
  91. return {
  92. id: id,
  93. route: route,
  94. body: JSON.parse(body)
  95. };
  96. };
  97. var composeResponse = function (msgId, route, msgBody) {
  98. return {
  99. id: msgId,
  100. body: msgBody
  101. };
  102. };
  103. var composePush = function (route, msgBody) {
  104. return JSON.stringify({ route: route, body: msgBody });
  105. };
  106. var parseIntField = function (str, offset, len) {
  107. var res = 0;
  108. for (var i = 0; i < len; i++) {
  109. if (i > 0) {
  110. res <<= 8;
  111. }
  112. res |= str.charCodeAt(offset + i) & 0xff;
  113. }
  114. return res;
  115. };