您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

VideoSIPGW.ts 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import { getLogger } from '@jitsi/logger';
  2. const logger = getLogger('modules/videosipgw/VideoSIPGW');
  3. import { XMPPEvents } from '../../service/xmpp/XMPPEvents';
  4. import JitsiVideoSIPGWSession from './JitsiVideoSIPGWSession';
  5. import * as Constants from './VideoSIPGWConstants';
  6. import ChatRoom from '../xmpp/ChatRoom';
  7. import EventEmitter from '../util/EventEmitter';
  8. export interface ISessionStateChangeEvent {
  9. address: string;
  10. displayName?: string;
  11. newState: string;
  12. oldState?: string;
  13. }
  14. export interface INodeAttributes {
  15. failure_reason?: string;
  16. sipaddress?: string;
  17. state: string;
  18. }
  19. /**
  20. * Main video SIP GW handler. Stores references of all created sessions.
  21. */
  22. export default class VideoSIPGW {
  23. private chatRoom: ChatRoom;
  24. private eventEmitter: EventEmitter;
  25. private sessions: Record<string, JitsiVideoSIPGWSession>;
  26. private sessionStateChangeListener: (event: ISessionStateChangeEvent) => void;
  27. private state?: string;
  28. /**
  29. * Creates new handler.
  30. *
  31. * @param {ChatRoom} chatRoom - Tha chat room to handle.
  32. */
  33. constructor(chatRoom: ChatRoom) {
  34. this.chatRoom = chatRoom;
  35. this.eventEmitter = chatRoom.eventEmitter;
  36. logger.debug('creating VideoSIPGW');
  37. this.sessions = {};
  38. this.sessionStateChangeListener = this.sessionStateChanged.bind(this);
  39. // VideoSIPGW, JitsiConference and ChatRoom are not reusable and no
  40. // more than one VideoSIPGW can be created per JitsiConference,
  41. // so we don't bother to cleanup
  42. chatRoom.addPresenceListener('jibri-sip-call-state',
  43. this.handleJibriSIPState.bind(this));
  44. }
  45. /**
  46. * Handles presence nodes with name: jibri-sip-call-state.
  47. *
  48. * @param {Object} node the presence node Object to handle.
  49. * Object representing part of the presence received over xmpp.
  50. */
  51. handleJibriSIPState(node: { attributes?: INodeAttributes; }): void {
  52. const attributes = node.attributes;
  53. if (!attributes) {
  54. return;
  55. }
  56. logger.debug('Handle video sip gw state : ', attributes);
  57. const newState = attributes.state;
  58. if (newState === this.state) {
  59. return;
  60. }
  61. switch (newState) {
  62. case Constants.STATE_ON:
  63. case Constants.STATE_OFF:
  64. case Constants.STATE_PENDING:
  65. case Constants.STATE_RETRYING:
  66. case Constants.STATE_FAILED: {
  67. const address = attributes.sipaddress;
  68. if (!address) {
  69. return;
  70. }
  71. // find the corresponding session and set its state
  72. const session = this.sessions[address];
  73. if (session) {
  74. session.setState(newState, attributes.failure_reason);
  75. } else {
  76. logger.warn('Video SIP GW session not found:', address);
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * Creates new session and stores its reference if it does not exist or
  83. * returns an error otherwise.
  84. *
  85. * @param {string} sipAddress - The sip address to use.
  86. * @param {string} displayName - The display name to use.
  87. * @returns {JitsiVideoSIPGWSession|Error}
  88. */
  89. createVideoSIPGWSession(sipAddress: string, displayName: string): JitsiVideoSIPGWSession | Error {
  90. if (this.sessions[sipAddress]) {
  91. logger.warn('There was already a Video SIP GW session for address',
  92. sipAddress);
  93. return new Error(Constants.ERROR_SESSION_EXISTS);
  94. }
  95. const session = new JitsiVideoSIPGWSession(
  96. sipAddress, displayName, this.chatRoom);
  97. session.addStateListener(this.sessionStateChangeListener);
  98. this.sessions[sipAddress] = session;
  99. return session;
  100. }
  101. /**
  102. * Listener for session state changed. When a session goes to off or failed
  103. * we delete its reference.
  104. *
  105. * @param {options} event - { address, oldState, newState, displayName }
  106. */
  107. sessionStateChanged(event: ISessionStateChangeEvent): void {
  108. const address = event.address;
  109. if (event.newState === Constants.STATE_OFF
  110. || event.newState === Constants.STATE_FAILED) {
  111. const session = this.sessions[address];
  112. if (!session) {
  113. logger.error('Missing Video SIP GW session with address:',
  114. address);
  115. return;
  116. }
  117. session.removeStateListener(this.sessionStateChangeListener);
  118. delete this.sessions[address];
  119. }
  120. this.eventEmitter.emit(
  121. XMPPEvents.VIDEO_SIP_GW_SESSION_STATE_CHANGED,
  122. event);
  123. }
  124. }