Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* global $iq, Strophe */
  2. import { getLogger } from 'jitsi-meet-logger';
  3. const logger = getLogger(__filename);
  4. import ConnectionPlugin from './ConnectionPlugin';
  5. import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
  6. /**
  7. * Ping every 10 sec
  8. */
  9. const PING_INTERVAL = 10000;
  10. /**
  11. * Ping timeout error after 15 sec of waiting.
  12. */
  13. const PING_TIMEOUT = 15000;
  14. /**
  15. * Will close the connection after 3 consecutive ping errors.
  16. */
  17. const PING_THRESHOLD = 3;
  18. /**
  19. * XEP-0199 ping plugin.
  20. *
  21. * Registers "urn:xmpp:ping" namespace under Strophe.NS.PING.
  22. */
  23. class PingConnectionPlugin extends ConnectionPlugin {
  24. /**
  25. * Contructs new object
  26. * @param {XMPP} xmpp the xmpp module.
  27. * @constructor
  28. */
  29. constructor(xmpp) {
  30. super();
  31. this.failedPings = 0;
  32. this.xmpp = xmpp;
  33. }
  34. /**
  35. * Initializes the plugin. Method called by Strophe.
  36. * @param connection Strophe connection instance.
  37. */
  38. init(connection) {
  39. super.init(connection);
  40. Strophe.addNamespace('PING', 'urn:xmpp:ping');
  41. }
  42. /* eslint-disable max-params */
  43. /**
  44. * Sends "ping" to given <tt>jid</tt>
  45. * @param jid the JID to which ping request will be sent.
  46. * @param success callback called on success.
  47. * @param error callback called on error.
  48. * @param timeout ms how long are we going to wait for the response. On
  49. * timeout <tt>error<//t> callback is called with undefined error argument.
  50. */
  51. ping(jid, success, error, timeout) {
  52. const iq = $iq({
  53. type: 'get',
  54. to: jid
  55. });
  56. iq.c('ping', { xmlns: Strophe.NS.PING });
  57. this.connection.sendIQ(iq, success, error, timeout);
  58. }
  59. /* eslint-enable max-params */
  60. /**
  61. * Checks if given <tt>jid</tt> has XEP-0199 ping support.
  62. * @param jid the JID to be checked for ping support.
  63. * @param callback function with boolean argument which will be
  64. * <tt>true</tt> if XEP-0199 ping is supported by given <tt>jid</tt>
  65. */
  66. hasPingSupport(jid, callback) {
  67. this.xmpp.caps.getFeatures(jid).then(features =>
  68. callback(features.has('urn:xmpp:ping')), error => {
  69. const errmsg = 'Ping feature discovery error';
  70. GlobalOnErrorHandler.callErrorHandler(
  71. new Error(`${errmsg}: ${error}`));
  72. logger.error(errmsg, error);
  73. callback(false);
  74. });
  75. }
  76. /**
  77. * Starts to send ping in given interval to specified remote JID.
  78. * This plugin supports only one such task and <tt>stopInterval</tt>
  79. * must be called before starting a new one.
  80. * @param remoteJid remote JID to which ping requests will be sent to.
  81. * @param interval task interval in ms.
  82. */
  83. startInterval(remoteJid, interval = PING_INTERVAL) {
  84. if (this.intervalId) {
  85. const errmsg = 'Ping task scheduled already';
  86. GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
  87. logger.error(errmsg);
  88. return;
  89. }
  90. this.intervalId = window.setInterval(() => {
  91. this.ping(remoteJid, () => {
  92. this.failedPings = 0;
  93. }, error => {
  94. this.failedPings += 1;
  95. const errmsg = `Ping ${error ? 'error' : 'timeout'}`;
  96. if (this.failedPings >= PING_THRESHOLD) {
  97. GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
  98. logger.error(errmsg, error);
  99. // FIXME it doesn't help to disconnect when 3rd PING
  100. // times out, it only stops Strophe from retrying.
  101. // Not really sure what's the right thing to do in that
  102. // situation, but just closing the connection makes no
  103. // sense.
  104. // self.connection.disconnect();
  105. } else {
  106. logger.warn(errmsg, error);
  107. }
  108. }, PING_TIMEOUT);
  109. }, interval);
  110. logger.info(`XMPP pings will be sent every ${interval} ms`);
  111. }
  112. /**
  113. * Stops current "ping" interval task.
  114. */
  115. stopInterval() {
  116. if (this.intervalId) {
  117. window.clearInterval(this.intervalId);
  118. this.intervalId = null;
  119. this.failedPings = 0;
  120. logger.info('Ping interval cleared');
  121. }
  122. }
  123. }
  124. /**
  125. *
  126. * @param xmpp
  127. */
  128. export default function(xmpp) {
  129. Strophe.addConnectionPlugin('ping', new PingConnectionPlugin(xmpp));
  130. }