Move XMPP Ping code to a plugin.

This commit is contained in:
JC Brand 2016-02-19 11:38:29 +00:00
parent 16f8b14ea8
commit f371b62157
5 changed files with 156 additions and 67 deletions

View File

@ -8,9 +8,10 @@ define("converse", [
* --------------------
* Any of the following components may be removed if they're not needed.
*/
"converse-muc", // XEP-0045 Multi-user chat
"converse-otr", // Off-the-record encryption for one-on-one messages
"converse-register", // XEP-0077 In-band registration
"converse-muc", // XEP-0045 Multi-user chat
"converse-otr", // Off-the-record encryption for one-on-one messages
"converse-register",// XEP-0077 In-band registration
"converse-ping", // XEP-0199 XMPP Ping
/* End: Removable components */
"converse-core"

View File

@ -3,8 +3,8 @@
## 0.11.0 (Unreleased)
- Split converse.js into different modules.
The code for the OTR, MUC and registration features are now in separate
modules and these can be removed completely from the build. [jcbrand]
The code for the OTR, MUC, Ping and registration features are now written as
plugins in separate modules and they can be completely removed from the build. [jcbrand]
- Don't play sound notifications for OTR messages which are setting up an
encrypted session. [jcbrand]
- Removed the `account.logout` API, instead use `user.logout`. [jcbrand]

View File

@ -47,6 +47,7 @@ require.config({
"converse-core": "src/converse-core",
"converse-muc": "src/converse-muc",
"converse-otr": "src/converse-otr",
"converse-ping": "src/converse-ping",
"converse-register": "src/converse-register",
"converse-dependencies": "src/deps-full",
"converse-templates": "src/templates",

View File

@ -284,7 +284,6 @@
message_carbons: false, // Support for XEP-280
no_trimming: false, // Set to true for phantomjs tests (where browser apparently has no width)
password: undefined,
ping_interval: 180, //in seconds
play_sounds: false,
prebind: false, // XXX: Deprecated, use "authentication" instead.
prebind_url: null,
@ -741,71 +740,19 @@
}.bind(this), 200));
};
this.ping = function (jid, success, error, timeout) {
// XXX: We could first check here if the server advertised that it supports PING.
// However, some servers don't advertise while still keeping the
// connection option due to pings.
//
// var feature = converse.features.findWhere({'var': Strophe.NS.PING});
converse.lastStanzaDate = new Date();
if (typeof jid === 'undefined' || jid === null) {
jid = Strophe.getDomainFromJid(converse.bare_jid);
}
if (typeof timeout === 'undefined' ) { timeout = null; }
if (typeof success === 'undefined' ) { success = null; }
if (typeof error === 'undefined' ) { error = null; }
if (converse.connection) {
converse.connection.ping.ping(jid, success, error, timeout);
return true;
}
return false;
};
this.pong = function (ping) {
converse.lastStanzaDate = new Date();
converse.connection.ping.pong(ping);
return true;
};
this.registerPongHandler = function () {
converse.connection.disco.addFeature(Strophe.NS.PING);
converse.connection.ping.addPingHandler(this.pong);
};
this.registerPingHandler = function () {
this.registerPongHandler();
if (this.ping_interval > 0) {
this.connection.addHandler(function () {
/* Handler on each stanza, saves the received date
* in order to ping only when needed.
*/
this.lastStanzaDate = new Date();
return true;
}.bind(converse));
this.connection.addTimedHandler(1000, function () {
var now = new Date();
if (!this.lastStanzaDate) {
this.lastStanzaDate = now;
}
if ((now - this.lastStanzaDate)/1000 > this.ping_interval) {
return this.ping();
}
return true;
}.bind(converse));
}
};
this.onReconnected = function () {
// We need to re-register all the event handlers on the newly
// created connection.
var deferred = new $.Deferred();
this.initStatus(function () {
this.registerPingHandler();
this.rosterview.registerRosterXHandler();
this.rosterview.registerPresenceHandler();
this.chatboxes.registerMessageHandler();
this.xmppstatus.sendPresence();
this.giveFeedback(__('Contacts'));
deferred.resolve();
}.bind(this));
return deferred.promise();
};
this.enableCarbons = function () {
@ -832,10 +779,11 @@
this.connection.send(carbons_iq);
};
this.onConnected = function () {
this.onConnected = function (callback) {
// When reconnecting, there might be some open chat boxes. We don't
// know whether these boxes are of the same account or not, so we
// close them now.
var deferred = new $.Deferred();
this.chatboxviews.closeAllChatBoxes();
this.jid = this.connection.jid;
this.bare_jid = Strophe.getBareJidFromJid(this.connection.jid);
@ -845,11 +793,13 @@
this.features = new this.Features();
this.enableCarbons();
this.initStatus(function () {
this.registerPingHandler();
this.registerIntervalHandler();
this.chatboxes.onConnected();
this.giveFeedback(__('Contacts'));
if (this.callback) {
if (typeof this.callback === 'function') {
// A callback method may be passed in via the
// converse.initialize method.
// XXX: Can we use $.Deferred instead of this callback?
if (this.connection.service === 'jasmine tests') {
// XXX: Call back with the internal converse object. This
// object should never be exposed to production systems.
@ -860,8 +810,10 @@
this.callback();
}
}
deferred.resolve();
}.bind(this));
converse.emit('ready');
return deferred.promise();
};
this.Message = Backbone.Model.extend({
@ -4630,9 +4582,6 @@
'send': function (stanza) {
converse.connection.send(stanza);
},
'ping': function (jid) {
converse.ping(jid);
},
'plugins': {
'add': function (name, plugin) {
converse.plugins[name] = plugin;

138
src/converse-ping.js Normal file
View File

@ -0,0 +1,138 @@
// Converse.js (A browser based XMPP chat client)
// http://conversejs.org
//
// Copyright (c) 2012-2016, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
//
/*global converse, utils, define */
/* This is a Converse.js plugin which add support for application-level pings
* as specified in XEP-0199 XMPP Ping.
*/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD module loading
define("converse-ping", ["converse-core", "utils"], factory);
} else {
// When not using a module loader
// -------------------------------
// In this case, the dependencies need to be available already as
// global variables, and should be loaded separately via *script* tags.
// See the file **non_amd.html** for an example of this usecase.
factory(converse, utils);
}
}(this, function (converse_api, utils) {
"use strict";
// Strophe methods for building stanzas
var Strophe = converse_api.env.Strophe;
// Other necessary globals
var _ = converse_api.env._;
// Translation machinery
// ---------------------
// Just a placeholder for now, we need to bind the utils.__ method to the
// inner converse object, which we can't here, so we do it in the
// initialize method.
var __ = function () {};
converse_api.plugins.add('ping', {
overrides: {
// Overrides mentioned here will be picked up by converse.js's
// plugin architecture they will replace existing methods on the
// relevant objects or classes.
//
// New functions which don't exist yet can also be added.
onConnected: function () {
var converse = this._super.converse;
this._super.onConnected().done(converse.registerPingHandler);
},
onReconnected: function () {
// We need to re-register the ping event handler on the newly
// created connection.
var converse = this._super.converse;
this._super.onReconnected().done(converse.registerPingHandler);
}
},
initialize: function () {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
var converse = this.converse;
// For translations
__ = utils.__.bind(converse);
// Configuration values for this plugin
var settings = {
ping_interval: 180 //in seconds
};
_.extend(converse, settings);
_.extend(converse, _.pick(converse.user_settings, Object.keys(settings)));
converse.ping = function (jid, success, error, timeout) {
// XXX: We could first check here if the server advertised that
// it supports PING.
// However, some servers don't advertise while still keeping the
// connection option due to pings.
//
// var feature = converse.features.findWhere({'var': Strophe.NS.PING});
converse.lastStanzaDate = new Date();
if (typeof jid === 'undefined' || jid === null) {
jid = Strophe.getDomainFromJid(converse.bare_jid);
}
if (typeof timeout === 'undefined' ) { timeout = null; }
if (typeof success === 'undefined' ) { success = null; }
if (typeof error === 'undefined' ) { error = null; }
if (converse.connection) {
converse.connection.ping.ping(jid, success, error, timeout);
return true;
}
return false;
};
converse.pong = function (ping) {
converse.lastStanzaDate = new Date();
converse.connection.ping.pong(ping);
return true;
};
converse.registerPongHandler = function () {
converse.connection.disco.addFeature(Strophe.NS.PING);
converse.connection.ping.addPingHandler(this.pong);
};
converse.registerPingHandler = function () {
converse.registerPongHandler();
if (converse.ping_interval > 0) {
converse.connection.addHandler(function () {
/* Handler on each stanza, saves the received date
* in order to ping only when needed.
*/
converse.lastStanzaDate = new Date();
return true;
});
converse.connection.addTimedHandler(1000, function () {
var now = new Date();
if (!converse.lastStanzaDate) {
converse.lastStanzaDate = now;
}
if ((now - converse.lastStanzaDate)/1000 > this.ping_interval) {
return converse.ping();
}
return true;
});
}
};
_.extend(converse_api, {
/* We extend the default converse.js API to add a method specific
* to this plugin.
*/
'ping': function (jid) {
converse.ping(jid);
}
});
}
});
}));