Permalink
Browse files

Implement XEP-0352: Client State Indication

This commit is based on a pull request by fbeutel (GitHub) (see #87) and
was rebased and slightly modified by me.
  • Loading branch information...
LNJ2 committed Oct 23, 2015
1 parent 3e2ca3c commit 5559ed29681d031f36e7a7d011e3ec4bec3635f5
@@ -124,3 +124,5 @@ const char* ns_forwarding = "urn:xmpp:forward:0";
const char* ns_mam = "urn:xmpp:mam:1";
// XEP-0333: Chat Markers
const char* ns_chat_markers = "urn:xmpp:chat-markers:0";
// XEP-0352: Client State Indication
const char* ns_csi = "urn:xmpp:csi:0";
@@ -136,5 +136,7 @@ extern const char* ns_forwarding;
extern const char* ns_mam;
// XEP-0333: Char Markers
extern const char* ns_chat_markers;
// XEP-0352: Client State Indication
extern const char* ns_csi;
#endif // QXMPPCONSTANTS_H
@@ -31,7 +31,8 @@ QXmppStreamFeatures::QXmppStreamFeatures()
m_sessionMode(Disabled),
m_nonSaslAuthMode(Disabled),
m_tlsMode(Disabled),
m_streamManagementMode(Disabled)
m_streamManagementMode(Disabled),
m_csiMode(Disabled)
{
}
@@ -105,6 +106,16 @@ void QXmppStreamFeatures::setStreamManagementMode(QXmppStreamFeatures::Mode mode
m_streamManagementMode = mode;
}
QXmppStreamFeatures::Mode QXmppStreamFeatures::clientStateIndicationMode() const
{
return m_csiMode;
}
void QXmppStreamFeatures::setClientStateIndicationMode(QXmppStreamFeatures::Mode mode)
{
m_csiMode = mode;
}
/// \cond
bool QXmppStreamFeatures::isStreamFeatures(const QDomElement &element)
{
@@ -136,6 +147,7 @@ void QXmppStreamFeatures::parse(const QDomElement &element)
m_nonSaslAuthMode = readFeature(element, "auth", ns_authFeature);
m_tlsMode = readFeature(element, "starttls", ns_tls);
m_streamManagementMode = readFeature(element, "sm", ns_stream_management);
m_csiMode = readFeature(element, "csi", ns_csi);
// parse advertised compression methods
QDomElement compression = element.firstChildElement("compression");
@@ -181,6 +193,7 @@ void QXmppStreamFeatures::toXml(QXmlStreamWriter *writer) const
writeFeature(writer, "auth", ns_authFeature, m_nonSaslAuthMode);
writeFeature(writer, "starttls", ns_tls, m_tlsMode);
writeFeature(writer, "sm", ns_stream_management, m_streamManagementMode);
writeFeature(writer, "csi", ns_csi, m_csiMode);
if (!m_compressionMethods.isEmpty())
{
@@ -65,6 +65,14 @@ class QXMPP_EXPORT QXmppStreamFeatures : public QXmppStanza
/// \pa mode The mode to set.
void setStreamManagementMode(Mode mode);
/// Returns the mode for XEP-0352: Client State Indication
Mode clientStateIndicationMode() const;
/// Sets the mode for XEP-0352: Client State Indication
///
/// \pa mode The mode to set.
void setClientStateIndicationMode(Mode mode);
/// \cond
void parse(const QDomElement &element);
void toXml(QXmlStreamWriter *writer) const;
@@ -78,6 +86,7 @@ class QXMPP_EXPORT QXmppStreamFeatures : public QXmppStanza
Mode m_nonSaslAuthMode;
Mode m_tlsMode;
Mode m_streamManagementMode;
Mode m_csiMode;
QStringList m_authMechanisms;
QStringList m_compressionMethods;
};
View
@@ -54,6 +54,9 @@ class QXmppClientPrivate
int reconnectionTries;
QTimer *reconnectionTimer;
// Client state indication
bool isActive;
void addProperCapability(QXmppPresence& presence);
int getNextReconnectTime() const;
@@ -68,6 +71,7 @@ QXmppClientPrivate::QXmppClientPrivate(QXmppClient *qq)
, receivedConflict(false)
, reconnectionTries(0)
, reconnectionTimer(0)
, isActive(true)
, q(qq)
{
}
@@ -320,6 +324,25 @@ bool QXmppClient::isConnected() const
return d->stream->isConnected();
}
/// Returns true if the current client state is "active", false if it is
/// "inactive". See XEP-0352 for details.
bool QXmppClient::isActive() const
{
return d->isActive;
}
/// Sets the client state as described in XEP-0352
void QXmppClient::setActive(bool active)
{
if (active != d->isActive && d->stream->isClientStateIndicationEnabled()) {
d->isActive = active;
QString packet = "<%1 xmlns='%2'/>";
d->stream->sendData(packet.arg(active ? "active" : "inactive", ns_csi).toUtf8());
}
}
/// Returns the reference to QXmppRosterManager object of the client.
/// \return Reference to the roster object of the connected client. Use this to
/// get the list of friends in the roster and their presence information.
View
@@ -140,6 +140,9 @@ class QXMPP_EXPORT QXmppClient : public QXmppLoggable
bool isAuthenticated() const;
bool isConnected() const;
bool isActive() const;
void setActive(bool active);
QXmppPresence clientPresence() const;
void setClientPresence(const QXmppPresence &presence);
@@ -106,6 +106,9 @@ class QXmppOutgoingClientPrivate
QString resumeHost;
quint16 resumePort;
// Client State Indication
bool clientStateIndicationEnabled;
// Timers
QTimer *pingTimer;
QTimer *timeoutTimer;
@@ -126,6 +129,7 @@ QXmppOutgoingClientPrivate::QXmppOutgoingClientPrivate(QXmppOutgoingClient *qq)
, canResume(false)
, isResuming(false)
, resumePort(0)
, clientStateIndicationEnabled(false)
, pingTimer(0)
, timeoutTimer(0)
, q(qq)
@@ -294,6 +298,13 @@ bool QXmppOutgoingClient::isConnected() const
return QXmppStream::isConnected() && d->sessionStarted;
}
/// Returns true if client state indication (xep-0352) is supported by the server
bool QXmppOutgoingClient::isClientStateIndicationEnabled() const
{
return d->clientStateIndicationEnabled;
}
void QXmppOutgoingClient::_q_socketDisconnected()
{
debug("Socket disconnected");
@@ -400,6 +411,9 @@ void QXmppOutgoingClient::handleStanza(const QDomElement &nodeRecv)
QXmppStreamFeatures features;
features.parse(nodeRecv);
if(features.clientStateIndicationMode() == QXmppStreamFeatures::Enabled)
d->clientStateIndicationEnabled = true;
if (!socket()->isEncrypted())
{
// determine TLS mode to use
@@ -55,6 +55,7 @@ class QXMPP_EXPORT QXmppOutgoingClient : public QXmppStream
void connectToHost();
bool isAuthenticated() const;
bool isConnected() const;
bool isClientStateIndicationEnabled() const;
QSslSocket *socket() const { return QXmppStream::socket(); };
QXmppStanza::Error::Condition xmppStreamError();
@@ -43,6 +43,7 @@ void tst_QXmppStreamFeatures::testEmpty()
QCOMPARE(features.sessionMode(), QXmppStreamFeatures::Disabled);
QCOMPARE(features.nonSaslAuthMode(), QXmppStreamFeatures::Disabled);
QCOMPARE(features.tlsMode(), QXmppStreamFeatures::Disabled);
QCOMPARE(features.clientStateIndicationMode(), QXmppStreamFeatures::Disabled);
QCOMPARE(features.authMechanisms(), QStringList());
QCOMPARE(features.compressionMethods(), QStringList());
serializePacket(features, xml);
@@ -55,6 +56,7 @@ void tst_QXmppStreamFeatures::testFull()
"<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
"<auth xmlns=\"http://jabber.org/features/iq-auth\"/>"
"<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"
"<csi xmlns=\"urn:xmpp:csi:0\"/>"
"<compression xmlns=\"http://jabber.org/features/compress\"><method>zlib</method></compression>"
"<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"><mechanism>PLAIN</mechanism></mechanisms>"
"</stream:features>");
@@ -65,6 +67,7 @@ void tst_QXmppStreamFeatures::testFull()
QCOMPARE(features.sessionMode(), QXmppStreamFeatures::Enabled);
QCOMPARE(features.nonSaslAuthMode(), QXmppStreamFeatures::Enabled);
QCOMPARE(features.tlsMode(), QXmppStreamFeatures::Enabled);
QCOMPARE(features.clientStateIndicationMode(), QXmppStreamFeatures::Enabled);
QCOMPARE(features.authMechanisms(), QStringList() << "PLAIN");
QCOMPARE(features.compressionMethods(), QStringList() << "zlib");
serializePacket(features, xml);

0 comments on commit 5559ed2

Please sign in to comment.