You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

strophe.emuc.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import { getLogger } from '@jitsi/logger';
  2. import $ from 'jquery';
  3. import { Strophe } from 'strophe.js';
  4. import { CONNECTION_REDIRECTED } from '../../JitsiConnectionEvents';
  5. import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
  6. import ChatRoom from './ChatRoom';
  7. import { ConnectionPluginListenable } from './ConnectionPlugin';
  8. const logger = getLogger(__filename);
  9. /**
  10. * MUC connection plugin.
  11. */
  12. export default class MucConnectionPlugin extends ConnectionPluginListenable {
  13. /**
  14. *
  15. * @param xmpp
  16. */
  17. constructor(xmpp) {
  18. super();
  19. this.xmpp = xmpp;
  20. this.rooms = {};
  21. }
  22. /**
  23. *
  24. * @param connection
  25. */
  26. init(connection) {
  27. super.init(connection);
  28. // add handlers (just once)
  29. this.connection.addHandler(this.onPresence.bind(this), null,
  30. 'presence', null, null, null, null);
  31. this.connection.addHandler(this.onPresenceUnavailable.bind(this),
  32. null, 'presence', 'unavailable', null);
  33. this.connection.addHandler(this.onPresenceError.bind(this), null,
  34. 'presence', 'error', null);
  35. this.connection.addHandler(this.onMessage.bind(this), null,
  36. 'message', null, null);
  37. this.connection.addHandler(this.onMute.bind(this),
  38. 'http://jitsi.org/jitmeet/audio', 'iq', 'set', null, null);
  39. this.connection.addHandler(this.onMuteVideo.bind(this),
  40. 'http://jitsi.org/jitmeet/video', 'iq', 'set', null, null);
  41. this.connection.addHandler(this.onVisitors.bind(this),
  42. 'jitsi:visitors', 'iq', 'set', null, null);
  43. }
  44. /**
  45. *
  46. * @param jid
  47. * @param password
  48. * @param options
  49. */
  50. createRoom(jid, password, options) {
  51. const roomJid = Strophe.getBareJidFromJid(jid);
  52. if (this.isRoomCreated(roomJid)) {
  53. const errmsg = 'You are already in the room!';
  54. logger.error(errmsg);
  55. throw new Error(errmsg);
  56. }
  57. this.rooms[roomJid] = new ChatRoom(this.connection, jid,
  58. password, this.xmpp, options);
  59. this.eventEmitter.emit(
  60. XMPPEvents.EMUC_ROOM_ADDED, this.rooms[roomJid]);
  61. return this.rooms[roomJid];
  62. }
  63. /**
  64. * Check if a room with the passed JID is already created.
  65. *
  66. * @param {string} roomJid - The JID of the room.
  67. * @returns {boolean}
  68. */
  69. isRoomCreated(roomJid) {
  70. return roomJid in this.rooms;
  71. }
  72. /**
  73. *
  74. * @param jid
  75. */
  76. doLeave(jid) {
  77. this.eventEmitter.emit(
  78. XMPPEvents.EMUC_ROOM_REMOVED, this.rooms[jid]);
  79. delete this.rooms[jid];
  80. }
  81. /**
  82. *
  83. * @param pres
  84. */
  85. onPresence(pres) {
  86. const from = pres.getAttribute('from');
  87. // What is this for? A workaround for something?
  88. if (pres.getAttribute('type')) {
  89. return true;
  90. }
  91. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  92. if (!room) {
  93. return true;
  94. }
  95. // Parse status.
  96. if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]'
  97. + '>status[code="201"]').length) {
  98. room.createNonAnonymousRoom();
  99. }
  100. room.onPresence(pres);
  101. return true;
  102. }
  103. /**
  104. *
  105. * @param pres
  106. */
  107. onPresenceUnavailable(pres) {
  108. const from = pres.getAttribute('from');
  109. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  110. if (!room) {
  111. return true;
  112. }
  113. room.onPresenceUnavailable(pres, from);
  114. return true;
  115. }
  116. /**
  117. *
  118. * @param pres
  119. */
  120. onPresenceError(pres) {
  121. const from = pres.getAttribute('from');
  122. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  123. if (!room) {
  124. return true;
  125. }
  126. room.onPresenceError(pres, from);
  127. return true;
  128. }
  129. /**
  130. *
  131. * @param msg
  132. */
  133. onMessage(msg) {
  134. // FIXME: this is a hack. but jingle on muc makes nickchanges hard
  135. const from = msg.getAttribute('from');
  136. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  137. if (!room) {
  138. return true;
  139. }
  140. room.onMessage(msg, from);
  141. return true;
  142. }
  143. /**
  144. * TODO: Document
  145. * @param iq
  146. */
  147. onMute(iq) {
  148. const from = iq.getAttribute('from');
  149. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  150. // Returning false would result in the listener being deregistered by Strophe
  151. if (!room) {
  152. return true;
  153. }
  154. room.onMute(iq);
  155. return true;
  156. }
  157. /**
  158. * TODO: Document
  159. * @param iq
  160. */
  161. onMuteVideo(iq) {
  162. const from = iq.getAttribute('from');
  163. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  164. // Returning false would result in the listener being deregistered by Strophe
  165. if (!room) {
  166. return true;
  167. }
  168. room.onMuteVideo(iq);
  169. return true;
  170. }
  171. /**
  172. * A visitor IQ is received, pass it to the room.
  173. * @param iq The received iq.
  174. * @returns {boolean}
  175. */
  176. onVisitors(iq) {
  177. const from = iq.getAttribute('from');
  178. const room = this.rooms[Strophe.getBareJidFromJid(from)];
  179. if (!room) {
  180. return true;
  181. }
  182. const visitors = $(iq).find('>visitors[xmlns="jitsi:visitors"]');
  183. const response = $(iq).find('promotion-response');
  184. if (visitors.length && response.length) {
  185. if (String(response.attr('allow')).toLowerCase() === 'true') {
  186. logger.info('Promotion request accepted. Redirected to main room.');
  187. this.xmpp.eventEmitter.emit(
  188. CONNECTION_REDIRECTED, undefined, visitors.attr('focusjid'), response.attr('username'));
  189. } else {
  190. logger.info('Promotion request rejected.');
  191. this.xmpp.eventEmitter.emit(XMPPEvents.VISITORS_REJECTION);
  192. }
  193. }
  194. return true;
  195. }
  196. }