hybridsocket.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. var util = require('util');
  2. var EventEmitter = require('events').EventEmitter;
  3. var handler = require('./common/handler');
  4. var protocol = require('pomelo-protocol');
  5. var logger = require('pomelo-logger').getLogger('pomelo', __filename);
  6. var Package = protocol.Package;
  7. var ST_INITED = 0;
  8. var ST_WAIT_ACK = 1;
  9. var ST_WORKING = 2;
  10. var ST_CLOSED = 3;
  11. /**
  12. * Socket class that wraps socket and websocket to provide unified interface for up level.
  13. */
  14. var Socket = function(id, socket) {
  15. EventEmitter.call(this);
  16. this.id = id;
  17. this.socket = socket;
  18. if(!socket._socket) {
  19. this.remoteAddress = {
  20. ip: socket.address().address,
  21. port: socket.address().port
  22. };
  23. } else {
  24. this.remoteAddress = {
  25. ip: socket._socket.remoteAddress,
  26. port: socket._socket.remotePort
  27. };
  28. }
  29. var self = this;
  30. socket.once('close', this.emit.bind(this, 'disconnect'));
  31. socket.on('error', this.emit.bind(this, 'error'));
  32. socket.on('message', function(msg) {
  33. if(msg) {
  34. msg = Package.decode(msg);
  35. handler(self, msg);
  36. }
  37. });
  38. this.state = ST_INITED;
  39. // TODO: any other events?
  40. };
  41. util.inherits(Socket, EventEmitter);
  42. module.exports = Socket;
  43. /**
  44. * Send raw byte data.
  45. *
  46. * @api private
  47. */
  48. Socket.prototype.sendRaw = function(msg) {
  49. if(this.state !== ST_WORKING) {
  50. return;
  51. }
  52. var self = this;
  53. var WS = this.socket.constructor;
  54. if (this.socket.readyState !== WS.OPEN) {
  55. this.state = ST_CLOSED;
  56. return;
  57. }
  58. this.socket.send(msg, {binary: true}, function(err) {
  59. if(!!err) {
  60. logger.error('websocket send binary data failed: %j', err.stack);
  61. return;
  62. }
  63. });
  64. };
  65. /**
  66. * Send byte data package to client.
  67. *
  68. * @param {Buffer} msg byte data
  69. */
  70. Socket.prototype.send = function(msg) {
  71. if(msg instanceof String) {
  72. msg = new Buffer(msg);
  73. } else if(!(msg instanceof Buffer)) {
  74. msg = new Buffer(JSON.stringify(msg));
  75. }
  76. this.sendRaw(Package.encode(Package.TYPE_DATA, msg));
  77. };
  78. /**
  79. * Send byte data packages to client in batch.
  80. *
  81. * @param {Buffer} msgs byte data
  82. */
  83. Socket.prototype.sendBatch = function(msgs) {
  84. var rs = [];
  85. for(var i=0; i<msgs.length; i++) {
  86. var src = Package.encode(Package.TYPE_DATA, msgs[i]);
  87. rs.push(src);
  88. }
  89. this.sendRaw(Buffer.concat(rs));
  90. };
  91. /**
  92. * Send message to client no matter whether handshake.
  93. *
  94. * @api private
  95. */
  96. Socket.prototype.sendForce = function(msg) {
  97. if(this.state === ST_CLOSED) {
  98. return;
  99. }
  100. var WS = this.socket.constructor;
  101. if (this.socket.readyState !== WS.OPEN) {
  102. this.state = ST_CLOSED;
  103. return;
  104. }
  105. this.socket.send(msg, {binary: true});
  106. };
  107. /**
  108. * Response handshake request
  109. *
  110. * @api private
  111. */
  112. Socket.prototype.handshakeResponse = function(resp) {
  113. if(this.state !== ST_INITED) {
  114. return;
  115. }
  116. var WS = this.socket.constructor;
  117. if (this.socket.readyState !== WS.OPEN) {
  118. this.state = ST_CLOSED;
  119. return;
  120. }
  121. this.socket.send(resp, {binary: true});
  122. this.state = ST_WAIT_ACK;
  123. };
  124. /**
  125. * Close the connection.
  126. *
  127. * @api private
  128. */
  129. Socket.prototype.disconnect = function() {
  130. if(this.state === ST_CLOSED) {
  131. return;
  132. }
  133. this.state = ST_CLOSED;
  134. this.socket.emit('close');
  135. this.socket.close();
  136. };