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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* @flow */
  2. import Logger from 'jitsi-meet-logger';
  3. import { CONFERENCE_WILL_JOIN } from '../base/conference';
  4. import {
  5. SIP_GW_AVAILABILITY_CHANGED,
  6. SIP_GW_INVITE_ROOMS
  7. } from './actionTypes';
  8. import {
  9. JitsiConferenceEvents,
  10. JitsiSIPVideoGWStatus
  11. } from '../base/lib-jitsi-meet';
  12. import { MiddlewareRegistry } from '../base/redux';
  13. import {
  14. Notification,
  15. showErrorNotification,
  16. showNotification,
  17. showWarningNotification
  18. } from '../notifications';
  19. const logger = Logger.getLogger(__filename);
  20. /**
  21. * Middleware that captures conference video sip gw events and stores
  22. * the global sip gw availability in redux or show appropriate notification
  23. * for sip gw sessions.
  24. * Captures invitation actions that create sip gw sessions or display
  25. * appropriate error/warning notifications.
  26. *
  27. * @param {Store} store - The redux store.
  28. * @returns {Function}
  29. */
  30. MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
  31. const result = next(action);
  32. switch (action.type) {
  33. case CONFERENCE_WILL_JOIN: {
  34. const conference = getState()['features/base/conference'].joining;
  35. conference.on(
  36. JitsiConferenceEvents.VIDEO_SIP_GW_AVAILABILITY_CHANGED,
  37. (...args) => dispatch(_availabilityChanged(...args)));
  38. conference.on(
  39. JitsiConferenceEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED,
  40. event => {
  41. const toDispatch = _sessionStateChanged(event);
  42. // sessionStateChanged can decide there is nothing to dispatch
  43. if (toDispatch) {
  44. dispatch(toDispatch);
  45. }
  46. });
  47. break;
  48. }
  49. case SIP_GW_INVITE_ROOMS: {
  50. const { status } = getState()['features/videosipgw'];
  51. if (status === JitsiSIPVideoGWStatus.STATUS_UNDEFINED) {
  52. dispatch(showErrorNotification({
  53. descriptionKey: 'recording.unavailable',
  54. descriptionArguments: {
  55. serviceName: '$t(videoSIPGW.serviceName)'
  56. },
  57. titleKey: 'videoSIPGW.unavailableTitle'
  58. }));
  59. return;
  60. } else if (status === JitsiSIPVideoGWStatus.STATUS_BUSY) {
  61. dispatch(showWarningNotification({
  62. descriptionKey: 'videoSIPGW.busy',
  63. titleKey: 'videoSIPGW.busyTitle'
  64. }));
  65. return;
  66. } else if (status !== JitsiSIPVideoGWStatus.STATUS_AVAILABLE) {
  67. logger.error(`Unknown sip videogw status ${status}`);
  68. return;
  69. }
  70. for (const room of action.rooms) {
  71. const { id: sipAddress, name: displayName } = room;
  72. if (sipAddress && displayName) {
  73. const newSession = action.conference
  74. .createVideoSIPGWSession(sipAddress, displayName);
  75. if (newSession instanceof Error) {
  76. const e = newSession;
  77. if (e) {
  78. switch (e.message) {
  79. case JitsiSIPVideoGWStatus.ERROR_NO_CONNECTION: {
  80. dispatch(showErrorNotification({
  81. descriptionKey: 'videoSIPGW.errorInvite',
  82. titleKey: 'videoSIPGW.errorInviteTitle'
  83. }));
  84. return;
  85. }
  86. case JitsiSIPVideoGWStatus.ERROR_SESSION_EXISTS: {
  87. dispatch(showWarningNotification({
  88. titleKey: 'videoSIPGW.errorAlreadyInvited',
  89. titleArguments: { displayName }
  90. }));
  91. return;
  92. }
  93. }
  94. }
  95. logger.error(
  96. 'Unknown error trying to create sip videogw session',
  97. e);
  98. return;
  99. }
  100. newSession.start();
  101. } else {
  102. logger.error(`No display name or sip number for ${
  103. JSON.stringify(room)}`);
  104. }
  105. }
  106. }
  107. }
  108. return result;
  109. });
  110. /**
  111. * Signals that sip gw availability had changed.
  112. *
  113. * @param {string} status - The new status of the service.
  114. * @returns {{
  115. * type: SIP_GW_AVAILABILITY_CHANGED,
  116. * status: string
  117. * }}
  118. * @private
  119. */
  120. function _availabilityChanged(status: string) {
  121. return {
  122. type: SIP_GW_AVAILABILITY_CHANGED,
  123. status
  124. };
  125. }
  126. /**
  127. * Signals that a session we created has a change in its status.
  128. *
  129. * @param {string} event - The event describing the session state change.
  130. * @returns {{
  131. * type: SHOW_NOTIFICATION
  132. * }}|null
  133. * @private
  134. */
  135. function _sessionStateChanged(
  136. event: Object) {
  137. switch (event.newState) {
  138. case JitsiSIPVideoGWStatus.STATE_PENDING: {
  139. return showNotification(
  140. Notification, {
  141. titleKey: 'videoSIPGW.pending',
  142. titleArguments: {
  143. displayName: event.displayName
  144. }
  145. }, 2000);
  146. }
  147. case JitsiSIPVideoGWStatus.STATE_FAILED: {
  148. return showErrorNotification({
  149. titleKey: 'videoSIPGW.errorInviteFailedTitle',
  150. titleArguments: {
  151. displayName: event.displayName
  152. },
  153. descriptionKey: 'videoSIPGW.errorInviteFailed'
  154. });
  155. }
  156. }
  157. // nothing to show
  158. return null;
  159. }