aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2010-03-10 11:06:53 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2010-03-10 11:06:53 +0000
commitb4442cdcf163d96bbf0d893eddf59a5bee0c64b6 (patch)
tree1c29ca36d041ab3bcf3e49569bff696de4d6f4b8
parent617dd2f07a30203fd885a5bad041ada73f9f8db0 (diff)
downloadqxmpp-b4442cdcf163d96bbf0d893eddf59a5bee0c64b6.tar.gz
add support for keep alive
-rw-r--r--source/QXmppClient.h1
-rw-r--r--source/QXmppReconnectionManager.cpp5
-rw-r--r--source/QXmppStream.cpp63
-rw-r--r--source/QXmppStream.h8
4 files changed, 77 insertions, 0 deletions
diff --git a/source/QXmppClient.h b/source/QXmppClient.h
index 70f5297e..d2539c25 100644
--- a/source/QXmppClient.h
+++ b/source/QXmppClient.h
@@ -74,6 +74,7 @@ public:
enum Error
{
SocketError, ///< Error due to TCP socket
+ KeepAliveError, ///< Error due to no response to a keep alive
XmppStreamError, ///< Error due to XML stream
XmppStanzaError ///< Error due to stanza
};
diff --git a/source/QXmppReconnectionManager.cpp b/source/QXmppReconnectionManager.cpp
index 8c0fbaa8..65557811 100644
--- a/source/QXmppReconnectionManager.cpp
+++ b/source/QXmppReconnectionManager.cpp
@@ -62,6 +62,11 @@ void QXmppReconnectionManager::error(QXmppClient::Error error)
m_timer.start(time*1000);
emit reconnectingIn(time);
}
+ else if (m_client && error == QXmppClient::KeepAliveError)
+ {
+ // if we got a keepalive error, reconnect in one second
+ m_timer.start(1000);
+ }
}
int QXmppReconnectionManager::getNextReconnectingInTime()
diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp
index 0fa9c24b..bbe3e35c 100644
--- a/source/QXmppStream.cpp
+++ b/source/QXmppStream.cpp
@@ -54,6 +54,7 @@
#include <QRegExp>
#include <QHostAddress>
#include <QXmlStreamWriter>
+#include <QTimer>
static const QByteArray streamRootElementStart = "<?xml version=\"1.0\"?><stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" xmlns=\"jabber:client\" xml:lang=\"en\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\">\n";
static const QByteArray streamRootElementEnd = "</stream:stream>";
@@ -155,6 +156,22 @@ QXmppStream::QXmppStream(QXmppClient* client)
check = QObject::connect(this, SIGNAL(streamInitiationIqReceived(const QXmppStreamInitiationIq&)),
&m_transferManager, SLOT(streamInitiationIqReceived(const QXmppStreamInitiationIq&)));
Q_ASSERT(check);
+
+ // XEP-0199: XMPP Ping
+ m_pingTimer = new QTimer();
+ check = QObject::connect(m_pingTimer, SIGNAL(timeout()), this, SLOT(pingSend()));
+ Q_ASSERT(check);
+
+ m_timeoutTimer = new QTimer();
+ m_timeoutTimer->setSingleShot(true);
+ check = QObject::connect(m_timeoutTimer, SIGNAL(timeout()), this, SLOT(pingTimeout()));
+ Q_ASSERT(check);
+
+ check = QObject::connect(this, SIGNAL(xmppConnected()), this, SLOT(pingStart()));
+ Q_ASSERT(check);
+
+ check = QObject::connect(this, SIGNAL(disconnected()), this, SLOT(pingStop()));
+ Q_ASSERT(check);
}
QXmppStream::~QXmppStream()
@@ -307,6 +324,10 @@ void QXmppStream::parser(const QByteArray& data)
QString ns = nodeRecv.namespaceURI();
debug("Namespace: " + ns + " Tag: " + nodeRecv.tagName() );
+
+ // if we receive any kind of data, stop the timeout timer
+ m_timeoutTimer->stop();
+
if(m_client->handleStreamElement(nodeRecv))
{
// already handled by client, do nothing
@@ -1115,6 +1136,48 @@ void QXmppStream::processRosterIq(const QXmppRosterIq& rosterIq)
}
}
+void QXmppStream::pingStart()
+{
+ const int interval = getConfiguration().keepAliveInterval();
+ // start ping timer
+ if (interval > 0)
+ {
+ m_pingTimer->setInterval(interval * 1000);
+ m_pingTimer->start();
+ }
+}
+
+void QXmppStream::pingStop()
+{
+ // stop all timers
+ m_pingTimer->stop();
+ m_timeoutTimer->stop();
+}
+
+void QXmppStream::pingSend()
+{
+ // send ping packet
+ QXmppPingIq ping;
+ ping.setFrom(getConfiguration().jid());
+ ping.setTo(getConfiguration().domain());
+ sendPacket(ping);
+
+ // start timeout timer
+ const int timeout = getConfiguration().keepAliveTimeout();
+ if (timeout > 0)
+ {
+ m_timeoutTimer->setInterval(timeout * 1000);
+ m_timeoutTimer->start();
+ }
+}
+
+void QXmppStream::pingTimeout()
+{
+ warning("Ping timeout");
+ disconnect();
+ emit error(QXmppClient::KeepAliveError);
+}
+
QAbstractSocket::SocketError QXmppStream::getSocketError()
{
return m_socketError;
diff --git a/source/QXmppStream.h b/source/QXmppStream.h
index f3e90e45..493553b2 100644
--- a/source/QXmppStream.h
+++ b/source/QXmppStream.h
@@ -35,6 +35,7 @@
#include "QXmppTransferManager.h"
class QDomElement;
+class QTimer;
class QXmppRoster;
class QXmppClient;
@@ -121,6 +122,11 @@ private slots:
void socketError(QAbstractSocket::SocketError);
void socketSslErrors(const QList<QSslError>&);
+ void pingStart();
+ void pingStop();
+ void pingSend();
+ void pingTimeout();
+
private:
QXmppClient* m_client; // reverse pointer
QXmppRoster m_roster;
@@ -135,6 +141,8 @@ private:
QString m_nonSASLAuthId;
QString m_XMPPVersion;
QXmppClient::StreamError m_xmppStreamError;
+ QTimer *m_pingTimer;
+ QTimer *m_timeoutTimer;
// m_xmppStanzaError;
QXmppArchiveManager m_archiveManager;