index.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**
  2. * Module dependencies.
  3. */
  4. var Emitter = require('events').EventEmitter;
  5. var parser = require('socket.io-parser');
  6. /**
  7. * Module exports.
  8. */
  9. module.exports = Adapter;
  10. /**
  11. * Memory adapter constructor.
  12. *
  13. * @param {Namespace} nsp
  14. * @api public
  15. */
  16. function Adapter(nsp){
  17. this.nsp = nsp;
  18. this.rooms = {};
  19. this.sids = {};
  20. this.encoder = new parser.Encoder();
  21. }
  22. /**
  23. * Inherits from `EventEmitter`.
  24. */
  25. Adapter.prototype.__proto__ = Emitter.prototype;
  26. /**
  27. * Adds a socket to a room.
  28. *
  29. * @param {String} socket id
  30. * @param {String} room name
  31. * @param {Function} callback
  32. * @api public
  33. */
  34. Adapter.prototype.add = function(id, room, fn){
  35. this.sids[id] = this.sids[id] || {};
  36. this.sids[id][room] = true;
  37. this.rooms[room] = this.rooms[room] || Room();
  38. this.rooms[room].add(id);
  39. if (fn) process.nextTick(fn.bind(null, null));
  40. };
  41. /**
  42. * Removes a socket from a room.
  43. *
  44. * @param {String} socket id
  45. * @param {String} room name
  46. * @param {Function} callback
  47. * @api public
  48. */
  49. Adapter.prototype.del = function(id, room, fn){
  50. this.sids[id] = this.sids[id] || {};
  51. delete this.sids[id][room];
  52. if (this.rooms.hasOwnProperty(room)) {
  53. this.rooms[room].del(id);
  54. if (this.rooms[room].length === 0) delete this.rooms[room];
  55. }
  56. if (fn) process.nextTick(fn.bind(null, null));
  57. };
  58. /**
  59. * Removes a socket from all rooms it's joined.
  60. *
  61. * @param {String} socket id
  62. * @param {Function} callback
  63. * @api public
  64. */
  65. Adapter.prototype.delAll = function(id, fn){
  66. var rooms = this.sids[id];
  67. if (rooms) {
  68. for (var room in rooms) {
  69. if (this.rooms.hasOwnProperty(room)) {
  70. this.rooms[room].del(id);
  71. if (this.rooms[room].length === 0) delete this.rooms[room];
  72. }
  73. }
  74. }
  75. delete this.sids[id];
  76. if (fn) process.nextTick(fn.bind(null, null));
  77. };
  78. /**
  79. * Broadcasts a packet.
  80. *
  81. * Options:
  82. * - `flags` {Object} flags for this packet
  83. * - `except` {Array} sids that should be excluded
  84. * - `rooms` {Array} list of rooms to broadcast to
  85. *
  86. * @param {Object} packet object
  87. * @api public
  88. */
  89. Adapter.prototype.broadcast = function(packet, opts){
  90. var rooms = opts.rooms || [];
  91. var except = opts.except || [];
  92. var flags = opts.flags || {};
  93. var packetOpts = {
  94. preEncoded: true,
  95. volatile: flags.volatile,
  96. compress: flags.compress
  97. };
  98. var ids = {};
  99. var self = this;
  100. var socket;
  101. packet.nsp = this.nsp.name;
  102. this.encoder.encode(packet, function(encodedPackets) {
  103. if (rooms.length) {
  104. for (var i = 0; i < rooms.length; i++) {
  105. var room = self.rooms[rooms[i]];
  106. if (!room) continue;
  107. var sockets = room.sockets;
  108. for (var id in sockets) {
  109. if (sockets.hasOwnProperty(id)) {
  110. if (ids[id] || ~except.indexOf(id)) continue;
  111. socket = self.nsp.connected[id];
  112. if (socket) {
  113. socket.packet(encodedPackets, packetOpts);
  114. ids[id] = true;
  115. }
  116. }
  117. }
  118. }
  119. } else {
  120. for (var id in self.sids) {
  121. if (self.sids.hasOwnProperty(id)) {
  122. if (~except.indexOf(id)) continue;
  123. socket = self.nsp.connected[id];
  124. if (socket) socket.packet(encodedPackets, packetOpts);
  125. }
  126. }
  127. }
  128. });
  129. };
  130. /**
  131. * Gets a list of clients by sid.
  132. *
  133. * @param {Array} explicit set of rooms to check.
  134. * @api public
  135. */
  136. Adapter.prototype.clients = function(rooms, fn){
  137. if ('function' == typeof rooms){
  138. fn = rooms;
  139. rooms = null;
  140. }
  141. rooms = rooms || [];
  142. var ids = {};
  143. var self = this;
  144. var sids = [];
  145. var socket;
  146. if (rooms.length) {
  147. for (var i = 0; i < rooms.length; i++) {
  148. var room = self.rooms[rooms[i]];
  149. if (!room) continue;
  150. var sockets = room.sockets;
  151. for (var id in sockets) {
  152. if (sockets.hasOwnProperty(id)) {
  153. if (ids[id]) continue;
  154. socket = self.nsp.connected[id];
  155. if (socket) {
  156. sids.push(id);
  157. ids[id] = true;
  158. }
  159. }
  160. }
  161. }
  162. } else {
  163. for (var id in self.sids) {
  164. if (self.sids.hasOwnProperty(id)) {
  165. socket = self.nsp.connected[id];
  166. if (socket) sids.push(id);
  167. }
  168. }
  169. }
  170. if (fn) process.nextTick(fn.bind(null, null, sids));
  171. };
  172. /**
  173. * Room constructor.
  174. *
  175. * @api private
  176. */
  177. function Room(){
  178. if (!(this instanceof Room)) return new Room();
  179. this.sockets = {};
  180. this.length = 0;
  181. }
  182. /**
  183. * Adds a socket to a room.
  184. *
  185. * @param {String} socket id
  186. * @api private
  187. */
  188. Room.prototype.add = function(id){
  189. if (!this.sockets.hasOwnProperty(id)) {
  190. this.sockets[id] = true;
  191. this.length++;
  192. }
  193. };
  194. /**
  195. * Removes a socket from a room.
  196. *
  197. * @param {String} socket id
  198. * @api private
  199. */
  200. Room.prototype.del = function(id){
  201. if (this.sockets.hasOwnProperty(id)) {
  202. delete this.sockets[id];
  203. this.length--;
  204. }
  205. };