xmpp.chapril.org-conversejs/src/headless/converse-ping.js

122 lines
4.4 KiB
JavaScript

// Converse.js
// https://conversejs.org
//
// Copyright (c) 2013-2019, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2)
/**
* @module converse-ping
* @description
* Converse.js plugin which add support for application-level pings
* as specified in XEP-0199 XMPP Ping.
*/
import converse from "./converse-core";
const { Strophe, $iq, _ } = converse.env;
const u = converse.env.utils;
Strophe.addNamespace('PING', "urn:xmpp:ping");
converse.plugins.add('converse-ping', {
initialize () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this;
let lastStanzaDate;
_converse.api.settings.update({
ping_interval: 60 //in seconds
});
function pong (ping) {
lastStanzaDate = new Date();
const from = ping.getAttribute('from');
const id = ping.getAttribute('id');
const iq = $iq({type: 'result', to: from,id: id});
_converse.connection.sendIQ(iq);
return true;
}
function registerPongHandler () {
if (_converse.connection.disco !== undefined) {
_converse.api.disco.own.features.add(Strophe.NS.PING);
}
return _converse.connection.addHandler(pong, Strophe.NS.PING, "iq", "get");
}
function registerPingHandler () {
_converse.connection.addHandler(() => {
if (_converse.ping_interval > 0) {
// Handler on each stanza, saves the received date
// in order to ping only when needed.
lastStanzaDate = new Date();
return true;
}
});
}
setTimeout(() => {
if (_converse.ping_interval > 0) {
const now = new Date();
if (!lastStanzaDate) {
lastStanzaDate = now;
}
if ((now - lastStanzaDate)/1000 > _converse.ping_interval) {
return _converse.api.ping();
}
return true;
}
}, 1000);
const onConnected = function () {
// Wrapper so that we can spy on registerPingHandler in tests
registerPongHandler();
registerPingHandler();
};
_converse.api.listen.on('connected', onConnected);
_converse.api.listen.on('reconnected', onConnected);
/************************ BEGIN API ************************/
Object.assign(_converse.api, {
/**
* Pings the service represented by the passed in JID by sending an
* IQ stanza.
* @private
* @method _converse.api.ping
* @param { string } [jid] - The JID of the service to ping
*/
async ping (jid) {
// XXX: We could first check here if the server advertised that it supports PING.
// However, some servers don't advertise while still responding to pings
//
// const feature = _converse.disco_entities[_converse.domain].features.findWhere({'var': Strophe.NS.PING});
lastStanzaDate = new Date();
jid = jid || Strophe.getDomainFromJid(_converse.bare_jid);
if (_converse.connection) {
const iq = $iq({
'type': 'get',
'to': jid,
'id': _converse.connection.getUniqueId('ping')
}).c('ping', {'xmlns': Strophe.NS.PING});
const result = await _converse.api.sendIQ(iq, 10000, false);
if (result === null) {
_converse.log(`Timeout while pinging ${jid}`, Strophe.LogLevel.WARN);
if (jid === Strophe.getDomainFromJid(_converse.bare_jid)) {
_converse.api.connection.reconnect();
}
} else if (u.isErrorStanza(result)) {
_converse.log(`Error while pinging ${jid}`, Strophe.LogLevel.ERROR);
_converse.log(result, Strophe.LogLevel.ERROR);
}
return true;
}
return false;
}
});
}
});