index.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Adapter = void 0;
  4. const events_1 = require("events");
  5. class Adapter extends events_1.EventEmitter {
  6. /**
  7. * In-memory adapter constructor.
  8. *
  9. * @param {Namespace} nsp
  10. */
  11. constructor(nsp) {
  12. super();
  13. this.nsp = nsp;
  14. this.rooms = new Map();
  15. this.sids = new Map();
  16. this.encoder = nsp.server.encoder;
  17. }
  18. /**
  19. * To be overridden
  20. */
  21. init() { }
  22. /**
  23. * To be overridden
  24. */
  25. close() { }
  26. /**
  27. * Returns the number of Socket.IO servers in the cluster
  28. *
  29. * @public
  30. */
  31. serverCount() {
  32. return Promise.resolve(1);
  33. }
  34. /**
  35. * Adds a socket to a list of room.
  36. *
  37. * @param {SocketId} id the socket id
  38. * @param {Set<Room>} rooms a set of rooms
  39. * @public
  40. */
  41. addAll(id, rooms) {
  42. if (!this.sids.has(id)) {
  43. this.sids.set(id, new Set());
  44. }
  45. for (const room of rooms) {
  46. this.sids.get(id).add(room);
  47. if (!this.rooms.has(room)) {
  48. this.rooms.set(room, new Set());
  49. this.emit("create-room", room);
  50. }
  51. if (!this.rooms.get(room).has(id)) {
  52. this.rooms.get(room).add(id);
  53. this.emit("join-room", room, id);
  54. }
  55. }
  56. }
  57. /**
  58. * Removes a socket from a room.
  59. *
  60. * @param {SocketId} id the socket id
  61. * @param {Room} room the room name
  62. */
  63. del(id, room) {
  64. if (this.sids.has(id)) {
  65. this.sids.get(id).delete(room);
  66. }
  67. this._del(room, id);
  68. }
  69. _del(room, id) {
  70. const _room = this.rooms.get(room);
  71. if (_room != null) {
  72. const deleted = _room.delete(id);
  73. if (deleted) {
  74. this.emit("leave-room", room, id);
  75. }
  76. if (_room.size === 0 && this.rooms.delete(room)) {
  77. this.emit("delete-room", room);
  78. }
  79. }
  80. }
  81. /**
  82. * Removes a socket from all rooms it's joined.
  83. *
  84. * @param {SocketId} id the socket id
  85. */
  86. delAll(id) {
  87. if (!this.sids.has(id)) {
  88. return;
  89. }
  90. for (const room of this.sids.get(id)) {
  91. this._del(room, id);
  92. }
  93. this.sids.delete(id);
  94. }
  95. /**
  96. * Broadcasts a packet.
  97. *
  98. * Options:
  99. * - `flags` {Object} flags for this packet
  100. * - `except` {Array} sids that should be excluded
  101. * - `rooms` {Array} list of rooms to broadcast to
  102. *
  103. * @param {Object} packet the packet object
  104. * @param {Object} opts the options
  105. * @public
  106. */
  107. broadcast(packet, opts) {
  108. const flags = opts.flags || {};
  109. const packetOpts = {
  110. preEncoded: true,
  111. volatile: flags.volatile,
  112. compress: flags.compress
  113. };
  114. packet.nsp = this.nsp.name;
  115. const encodedPackets = this.encoder.encode(packet);
  116. this.apply(opts, socket => {
  117. if (typeof socket.notifyOutgoingListeners === "function") {
  118. socket.notifyOutgoingListeners(packet);
  119. }
  120. socket.client.writeToEngine(encodedPackets, packetOpts);
  121. });
  122. }
  123. /**
  124. * Broadcasts a packet and expects multiple acknowledgements.
  125. *
  126. * Options:
  127. * - `flags` {Object} flags for this packet
  128. * - `except` {Array} sids that should be excluded
  129. * - `rooms` {Array} list of rooms to broadcast to
  130. *
  131. * @param {Object} packet the packet object
  132. * @param {Object} opts the options
  133. * @param clientCountCallback - the number of clients that received the packet
  134. * @param ack - the callback that will be called for each client response
  135. *
  136. * @public
  137. */
  138. broadcastWithAck(packet, opts, clientCountCallback, ack) {
  139. const flags = opts.flags || {};
  140. const packetOpts = {
  141. preEncoded: true,
  142. volatile: flags.volatile,
  143. compress: flags.compress
  144. };
  145. packet.nsp = this.nsp.name;
  146. // we can use the same id for each packet, since the _ids counter is common (no duplicate)
  147. packet.id = this.nsp._ids++;
  148. const encodedPackets = this.encoder.encode(packet);
  149. let clientCount = 0;
  150. this.apply(opts, socket => {
  151. // track the total number of acknowledgements that are expected
  152. clientCount++;
  153. // call the ack callback for each client response
  154. socket.acks.set(packet.id, ack);
  155. if (typeof socket.notifyOutgoingListeners === "function") {
  156. socket.notifyOutgoingListeners(packet);
  157. }
  158. socket.client.writeToEngine(encodedPackets, packetOpts);
  159. });
  160. clientCountCallback(clientCount);
  161. }
  162. /**
  163. * Gets a list of sockets by sid.
  164. *
  165. * @param {Set<Room>} rooms the explicit set of rooms to check.
  166. */
  167. sockets(rooms) {
  168. const sids = new Set();
  169. this.apply({ rooms }, socket => {
  170. sids.add(socket.id);
  171. });
  172. return Promise.resolve(sids);
  173. }
  174. /**
  175. * Gets the list of rooms a given socket has joined.
  176. *
  177. * @param {SocketId} id the socket id
  178. */
  179. socketRooms(id) {
  180. return this.sids.get(id);
  181. }
  182. /**
  183. * Returns the matching socket instances
  184. *
  185. * @param opts - the filters to apply
  186. */
  187. fetchSockets(opts) {
  188. const sockets = [];
  189. this.apply(opts, socket => {
  190. sockets.push(socket);
  191. });
  192. return Promise.resolve(sockets);
  193. }
  194. /**
  195. * Makes the matching socket instances join the specified rooms
  196. *
  197. * @param opts - the filters to apply
  198. * @param rooms - the rooms to join
  199. */
  200. addSockets(opts, rooms) {
  201. this.apply(opts, socket => {
  202. socket.join(rooms);
  203. });
  204. }
  205. /**
  206. * Makes the matching socket instances leave the specified rooms
  207. *
  208. * @param opts - the filters to apply
  209. * @param rooms - the rooms to leave
  210. */
  211. delSockets(opts, rooms) {
  212. this.apply(opts, socket => {
  213. rooms.forEach(room => socket.leave(room));
  214. });
  215. }
  216. /**
  217. * Makes the matching socket instances disconnect
  218. *
  219. * @param opts - the filters to apply
  220. * @param close - whether to close the underlying connection
  221. */
  222. disconnectSockets(opts, close) {
  223. this.apply(opts, socket => {
  224. socket.disconnect(close);
  225. });
  226. }
  227. apply(opts, callback) {
  228. const rooms = opts.rooms;
  229. const except = this.computeExceptSids(opts.except);
  230. if (rooms.size) {
  231. const ids = new Set();
  232. for (const room of rooms) {
  233. if (!this.rooms.has(room))
  234. continue;
  235. for (const id of this.rooms.get(room)) {
  236. if (ids.has(id) || except.has(id))
  237. continue;
  238. const socket = this.nsp.sockets.get(id);
  239. if (socket) {
  240. callback(socket);
  241. ids.add(id);
  242. }
  243. }
  244. }
  245. }
  246. else {
  247. for (const [id] of this.sids) {
  248. if (except.has(id))
  249. continue;
  250. const socket = this.nsp.sockets.get(id);
  251. if (socket)
  252. callback(socket);
  253. }
  254. }
  255. }
  256. computeExceptSids(exceptRooms) {
  257. const exceptSids = new Set();
  258. if (exceptRooms && exceptRooms.size > 0) {
  259. for (const room of exceptRooms) {
  260. if (this.rooms.has(room)) {
  261. this.rooms.get(room).forEach(sid => exceptSids.add(sid));
  262. }
  263. }
  264. }
  265. return exceptSids;
  266. }
  267. /**
  268. * Send a packet to the other Socket.IO servers in the cluster
  269. * @param packet - an array of arguments, which may include an acknowledgement callback at the end
  270. */
  271. serverSideEmit(packet) {
  272. console.warn("this adapter does not support the serverSideEmit() functionality");
  273. }
  274. }
  275. exports.Adapter = Adapter;