diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-23 05:49:24 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-08-23 05:49:24 +0000 |
| commit | 6c462ee694b614f538cfbee894134f723ae58820 (patch) | |
| tree | 53e3398d261222ad0c8209fac35057dc3dd86050 /src | |
| parent | 12418dc2d452f372c19d129a1dacfbf4e7e00817 (diff) | |
| download | qxmpp-6c462ee694b614f538cfbee894134f723ae58820.tar.gz | |
- add support for incoming C2S connections
- add support for incoming S2S connections
- add support for outgoing S2S connections
Diffstat (limited to 'src')
| -rw-r--r-- | src/QXmppIncomingClient.cpp | 281 | ||||
| -rw-r--r-- | src/QXmppIncomingClient.h | 71 | ||||
| -rw-r--r-- | src/QXmppIncomingServer.cpp | 177 | ||||
| -rw-r--r-- | src/QXmppIncomingServer.h | 62 | ||||
| -rw-r--r-- | src/QXmppOutgoingServer.cpp | 177 | ||||
| -rw-r--r-- | src/QXmppOutgoingServer.h | 63 | ||||
| -rw-r--r-- | src/src.pro | 6 |
7 files changed, 837 insertions, 0 deletions
diff --git a/src/QXmppIncomingClient.cpp b/src/QXmppIncomingClient.cpp new file mode 100644 index 00000000..0e51958c --- /dev/null +++ b/src/QXmppIncomingClient.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include <QDomElement> +#include <QSslKey> +#include <QSslSocket> +#include <QTimer> + +#include "QXmppBind.h" +#include "QXmppConstants.h" +#include "QXmppMessage.h" +#include "QXmppSession.h" +#include "QXmppStreamFeatures.h" +#include "QXmppUtils.h" + +#include "QXmppIncomingClient.h" + +class QXmppIncomingClientPrivate +{ +public: + QTimer *idleTimer; + + QString domain; + QString username; + QString resource; + QXmppPasswordChecker *passwordChecker; + QByteArray saslNonce; +}; + +QXmppIncomingClient::QXmppIncomingClient(QSslSocket *socket, const QString &domain, QObject *parent) + : QXmppStream(parent), + d(new QXmppIncomingClientPrivate) +{ + d->passwordChecker = 0; + d->domain = domain; + + setObjectName("C2S"); + setSocket(socket); + + // create inactivity timer + d->idleTimer = new QTimer(this); + d->idleTimer->setInterval(70000); + d->idleTimer->setSingleShot(true); + bool check = connect(d->idleTimer, SIGNAL(timeout()), + this, SLOT(slotTimeout())); + Q_ASSERT(check); +} + +QXmppIncomingClient::~QXmppIncomingClient() +{ + delete d; +} + +bool QXmppIncomingClient::isConnected() const +{ + return !d->username.isEmpty(); +} + +QString QXmppIncomingClient::jid() const +{ + if (d->username.isEmpty()) + return QString(); + QString jid = d->username + "@" + d->domain; + if (!d->resource.isEmpty()) + jid += "/" + d->resource; + return jid; +} + +void QXmppIncomingClient::setPasswordChecker(QXmppPasswordChecker *checker) +{ + d->passwordChecker = checker; +} + +void QXmppIncomingClient::handleStream(const QDomElement &streamElement) +{ + Q_UNUSED(streamElement); + + d->idleTimer->start(); + + // start stream + const QByteArray sessionId = generateStanzaHash().toAscii(); + QString response = QString("<?xml version='1.0'?><stream:stream" + " xmlns=\"%1\" xmlns:stream=\"%2\"" + " id=\"%3\" from=\"%4\" version=\"1.0\" xml:lang=\"en\">").arg( + ns_client, + ns_stream, + sessionId, + d->domain.toAscii()); + sendData(response.toUtf8()); + + // send stream features + QXmppStreamFeatures features; + if (!socket()->isEncrypted() && !socket()->localCertificate().isNull() && !socket()->privateKey().isNull()) + features.setSecurityMode(QXmppConfiguration::TLSEnabled); + if (!d->username.isEmpty()) + { + features.setBindAvailable(true); + features.setSessionAvailable(true); + } + else + { + QList<QXmppConfiguration::SASLAuthMechanism> mechanisms; + mechanisms << QXmppConfiguration::SASLPlain; + mechanisms << QXmppConfiguration::SASLDigestMD5; + features.setAuthMechanisms(mechanisms); + } + sendPacket(features); +} + +void QXmppIncomingClient::handleStanza(const QDomElement &nodeRecv) +{ + const QString ns = nodeRecv.namespaceURI(); + + d->idleTimer->start(); + + if (ns == ns_tls && nodeRecv.tagName() == "starttls") + { + sendData("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); + socket()->flush(); + socket()->startServerEncryption(); + return; + } + else if (ns == ns_sasl) + { + if (nodeRecv.tagName() == "auth") + { + const QString mechanism = nodeRecv.attribute("mechanism"); + if (mechanism == "PLAIN") + { + QList<QByteArray> auth = QByteArray::fromBase64(nodeRecv.text().toAscii()).split('\0'); + if (auth.size() != 3) + { + sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); + disconnectFromHost(); + return; + } + + const QString username = QString::fromUtf8(auth[1]); + const QString password = QString::fromUtf8(auth[2]); + if (d->passwordChecker && d->passwordChecker->check(username, password)) + { + d->username = username; + sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); + } else { + sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>"); + disconnectFromHost(); + return; + } + } + else if (mechanism == "DIGEST-MD5") + { + // generate nonce + QByteArray nonce(32, 'm'); + for(int n = 0; n < nonce.size(); ++n) + nonce[n] = (char)(256.0*qrand()/(RAND_MAX+1.0)); + d->saslNonce = nonce.toBase64(); + + QMap<QByteArray, QByteArray> challenge; + challenge["nonce"] = d->saslNonce; + challenge["realm"] = d->domain.toUtf8(); + challenge["qop"] = "auth"; + challenge["charset"] = "utf-8"; + challenge["algorithm"] = "md5-sess"; + + const QByteArray data = serializeDigestMd5(challenge).toBase64(); + sendData("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" + data +"</challenge>"); + } + else + { + // unsupported method + sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'></failure>"); + disconnectFromHost(); + return; + } + } + else if (nodeRecv.tagName() == "response") + { + const QByteArray raw = QByteArray::fromBase64(nodeRecv.text().toAscii()); + QMap<QByteArray, QByteArray> response = parseDigestMd5(raw); + + // check credentials + const QString username = QString::fromUtf8(response.value("username")); + QString password; + if (!d->passwordChecker || !d->passwordChecker->get(username, password)) + { + sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>"); + disconnectFromHost(); + return; + } + const QByteArray a1 = username.toUtf8() + ':' + d->domain.toUtf8() + ':' + password.toUtf8(); + const QByteArray remote = QByteArray::fromHex(response["response"]); + if (remote != calculateDigestMd5(a1, + d->saslNonce, + response.value("nc"), + response.value("cnonce"), + response.value("digest-uri"), + QByteArray())) + { + sendData("<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><not-authorized/></failure>"); + disconnectFromHost(); + return; + } + + // authentication succeeded + d->username = username; + sendData("<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); + } + } + else if (ns == ns_client) + { + if (nodeRecv.tagName() == "iq") + { + const QString type = nodeRecv.attribute("type"); + if (QXmppBind::isBind(nodeRecv) && type == "set") + { + QXmppBind bindSet; + bindSet.parse(nodeRecv); + d->resource = bindSet.resource(); + + QXmppBind bindResult(QXmppIq::Result); + bindResult.setId(bindSet.id()); + bindResult.setJid(jid()); + sendPacket(bindResult); + + // bound + emit connected(); + } + else if (QXmppSession::isSession(nodeRecv) && type == "set") + { + QXmppSession sessionSet; + sessionSet.parse(nodeRecv); + + QXmppSession sessionResult(QXmppIq::Result); + sessionResult.setId(sessionSet.id()); + sendPacket(sessionResult); + } + else + { + QDomElement nodeFull(nodeRecv); + nodeFull.setAttribute("from", jid()); + bool handled = false; + emit elementReceived(nodeFull, handled); + } + } + else if (nodeRecv.tagName() == "message" || nodeRecv.tagName() == "presence") + { + QDomElement nodeFull(nodeRecv); + nodeFull.setAttribute("from", jid()); + bool handled = false; + emit elementReceived(nodeFull, handled); + } + } +} + +void QXmppIncomingClient::slotTimeout() +{ + warning(QString("Idle timeout for %1").arg(jid())); + disconnectFromHost(); +} + + diff --git a/src/QXmppIncomingClient.h b/src/QXmppIncomingClient.h new file mode 100644 index 00000000..a09fcf5f --- /dev/null +++ b/src/QXmppIncomingClient.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPINCOMINGCLIENT_H +#define QXMPPINCOMINGCLIENT_H + +#include "QXmppStream.h" + +class QXmppIncomingClientPrivate; + +/// Interface for password checkers. +/// +/// FIXME : make this an abstract class + +class QXmppPasswordChecker +{ +public: + virtual bool check(const QString &username, const QString &password) = 0; + virtual bool get(const QString &username, QString &password) = 0; +}; + +/// The QXmppIncomingClient class represents an incoming XMPP stream +/// from an XMPP client. +/// + +class QXmppIncomingClient : public QXmppStream +{ + Q_OBJECT + +public: + QXmppIncomingClient(QSslSocket *socket, const QString &domain, QObject *parent = 0); + ~QXmppIncomingClient(); + + bool isConnected() const; + QString jid() const; + + void setPasswordChecker(QXmppPasswordChecker *checker); + +protected: + void handleStream(const QDomElement &element); + void handleStanza(const QDomElement &element); + +private slots: + void slotTimeout(); + +private: + Q_DISABLE_COPY(QXmppIncomingClient) + QXmppIncomingClientPrivate* const d; +}; + +#endif diff --git a/src/QXmppIncomingServer.cpp b/src/QXmppIncomingServer.cpp new file mode 100644 index 00000000..24775360 --- /dev/null +++ b/src/QXmppIncomingServer.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include <QDomElement> +#include <QSslKey> +#include <QSslSocket> + +#include "QXmppConstants.h" +#include "QXmppDialback.h" +#include "QXmppIncomingServer.h" +#include "QXmppOutgoingServer.h" +#include "QXmppStreamFeatures.h" +#include "QXmppUtils.h" + +class QXmppIncomingServerPrivate +{ +public: + bool authenticated; + QString domain; + QString localStreamId; +}; + +QXmppIncomingServer::QXmppIncomingServer(QSslSocket *socket, const QString &domain, QObject *parent) + : QXmppStream(parent), + d(new QXmppIncomingServerPrivate) +{ + setObjectName("S2S-in"); + setSocket(socket); + d->authenticated = false; + d->domain = domain; +} + +QXmppIncomingServer::~QXmppIncomingServer() +{ + delete d; +} + +void QXmppIncomingServer::handleStream(const QDomElement &streamElement) +{ + if (!streamElement.attribute("from").isEmpty()) + setObjectName("S2S-in-" + streamElement.attribute("from")); + + // start stream + d->localStreamId = generateStanzaHash().toAscii(); + QString data = QString("<?xml version='1.0'?><stream:stream" + " xmlns='%1' xmlns:db='%2' xmlns:stream='%3'" + " id='%4' version=\"1.0\">").arg( + ns_server, + ns_server_dialback, + ns_stream, + d->localStreamId); + sendData(data.toUtf8()); + + // send stream features + QXmppStreamFeatures features; + if (!socket()->isEncrypted() && !socket()->localCertificate().isNull() && !socket()->privateKey().isNull()) + features.setSecurityMode(QXmppConfiguration::TLSEnabled); + sendPacket(features); +} + +void QXmppIncomingServer::handleStanza(const QDomElement &stanza) +{ + const QString ns = stanza.namespaceURI(); + + if (ns == ns_tls && stanza.tagName() == "starttls") + { + sendData("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"); + socket()->flush(); + socket()->startServerEncryption(); + return; + } + else if (QXmppDialback::isDialback(stanza)) + { + QXmppDialback request; + request.parse(stanza); + // check the request is valid + if (!request.type().isEmpty() || + request.from().isEmpty() || + request.to() != d->domain || + request.key().isEmpty()) + { + warning("Invalid dialback received"); + return; + } + + const QString domain = request.from(); + setObjectName("S2S-in-" + domain); + + if (request.command() == QXmppDialback::Result) + { + // etablish dialback connection + QXmppOutgoingServer *stream = new QXmppOutgoingServer(d->domain, this); + stream->setLogger(logger()); + stream->setObjectName("S2S-dialback-" + domain); + stream->configuration().setDomain(domain); + stream->configuration().setHost(domain); + stream->configuration().setPort(5269); + bool check = connect(stream, SIGNAL(dialbackResponseReceived(QXmppDialback)), + this, SLOT(slotDialbackResponseReceived(QXmppDialback))); + Q_ASSERT(check); + stream->setVerify(d->localStreamId, request.key()); + stream->connectToHost(); + } else { + emit dialbackRequestReceived(request); + } + + } else if (d->authenticated) { + // relay packets if the remote party is authenticated + bool handled = false; + emit elementReceived(stanza, handled); + } else { + warning("Received an element, but remote party is not authenticated"); + } +} + +QString QXmppIncomingServer::localStreamId() const +{ + return d->localStreamId; +} + +/// Handles a dialback response received from the authority server. +/// +/// \param response +/// + +void QXmppIncomingServer::slotDialbackResponseReceived(const QXmppDialback &dialback) +{ + QXmppOutgoingServer *stream = qobject_cast<QXmppOutgoingServer*>(sender()); + if (!stream || + dialback.command() != QXmppDialback::Verify || + dialback.id() != d->localStreamId) + return; + + // relay verify response + QXmppDialback response; + response.setCommand(QXmppDialback::Result); + response.setTo(dialback.from()); + response.setFrom(d->domain); + response.setType(dialback.type()); + sendPacket(response); + + // check for success + if (response.type() == "valid") + { + info("Incoming stream is ready"); + d->authenticated = true; + emit connected(); + } else { + disconnectFromHost(); + } + + // disconnect dialback + stream->disconnectFromHost(); + stream->deleteLater(); +} + + diff --git a/src/QXmppIncomingServer.h b/src/QXmppIncomingServer.h new file mode 100644 index 00000000..52372813 --- /dev/null +++ b/src/QXmppIncomingServer.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPINCOMINGSERVER_H +#define QXMPPINCOMINGSERVER_H + +#include "QXmppStream.h" + +class QXmppDialback; +class QXmppIncomingServerPrivate; +class QXmppOutgoingServer; + +/// The QXmppIncomingServer class represents an incoming XMPP stream +/// from an XMPP server. +/// + +class QXmppIncomingServer : public QXmppStream +{ + Q_OBJECT + +public: + QXmppIncomingServer(QSslSocket *socket, const QString &domain, QObject *parent); + ~QXmppIncomingServer(); + + QString localStreamId() const; + +signals: + void dialbackRequestReceived(const QXmppDialback &result); + +protected: + void handleStanza(const QDomElement &stanzaElement); + void handleStream(const QDomElement &streamElement); + +private slots: + void slotDialbackResponseReceived(const QXmppDialback &dialback); + +private: + Q_DISABLE_COPY(QXmppIncomingServer) + QXmppIncomingServerPrivate* const d; +}; + +#endif diff --git a/src/QXmppOutgoingServer.cpp b/src/QXmppOutgoingServer.cpp new file mode 100644 index 00000000..d5daa316 --- /dev/null +++ b/src/QXmppOutgoingServer.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#include <QDomElement> +#include <QSslKey> +#include <QSslSocket> + +#include "QXmppConstants.h" +#include "QXmppDialback.h" +#include "QXmppOutgoingServer.h" +#include "QXmppStreamFeatures.h" +#include "QXmppUtils.h" + +class QXmppOutgoingServerPrivate +{ +public: + QString domain; + QString incomingId; + QString incomingKey; + QString localStreamKey; + bool ready; +}; + +/// Constructs a new outgoing server-to-server stream. +/// +/// \param socket +/// \param domain the local domain +/// \param parent the parent object +/// + +QXmppOutgoingServer::QXmppOutgoingServer(const QString &domain, QObject *parent) + : QXmppOutgoingClient(parent), + d(new QXmppOutgoingServerPrivate) +{ + d->domain = domain; + d->ready = false; + configuration().setKeepAliveInterval(0); +} + +/// Destroys the stream. +/// + +QXmppOutgoingServer::~QXmppOutgoingServer() +{ + delete d; +} + +void QXmppOutgoingServer::handleStart() +{ + QString data = QString("<?xml version='1.0'?><stream:stream" + " xmlns='%1' xmlns:db='%2' xmlns:stream='%3' version='1.0'>").arg( + ns_server, + ns_server_dialback, + ns_stream); + sendData(data.toUtf8()); +} + +void QXmppOutgoingServer::handleStanza(const QDomElement &stanza) +{ + const QString ns = stanza.namespaceURI(); + + if(QXmppStreamFeatures::isStreamFeatures(stanza)) + { + QXmppStreamFeatures features; + features.parse(stanza); + if (features.securityMode() != QXmppConfiguration::TLSDisabled) + { + // let QXmppOutgoingClient handle TLS + QXmppOutgoingClient::handleStanza(stanza); + } + else if (!d->localStreamKey.isEmpty()) + { + // send dialback key + QXmppDialback dialback; + dialback.setCommand(QXmppDialback::Result); + dialback.setFrom(d->domain); + dialback.setTo(configuration().domain()); + dialback.setKey(d->localStreamKey); + sendPacket(dialback); + } + else if (!d->incomingId.isEmpty() && !d->incomingKey.isEmpty()) + { + // send dialback verify + QXmppDialback verify; + verify.setCommand(QXmppDialback::Verify); + verify.setId(d->incomingId); + verify.setTo(configuration().domain()); + verify.setFrom(d->domain); + verify.setKey(d->incomingKey); + sendPacket(verify); + } + } + else if (ns == ns_tls) + { + if (stanza.tagName() == "proceed") + { + debug("Starting encryption"); + socket()->startClientEncryption(); + return; + } + } + else if (QXmppDialback::isDialback(stanza)) + { + QXmppDialback response; + response.parse(stanza); + + // check the request is valid + if (response.from().isEmpty() || + response.to() != d->domain || + response.type().isEmpty()) + { + warning("Invalid dialback response received"); + return; + } + if (response.command() == QXmppDialback::Result) + { + if (response.type() == "valid") + { + info("Outgoing stream is ready"); + d->ready = true; + emit connected(); + } + } + else if (response.command() == QXmppDialback::Verify) + { + emit dialbackResponseReceived(response); + } + + } + else + { + bool handled = false; + emit elementReceived(stanza, handled); + } +} + +bool QXmppOutgoingServer::isConnected() const +{ + return d->ready; +} + +QString QXmppOutgoingServer::localStreamKey() const +{ + return d->localStreamKey; +} + +void QXmppOutgoingServer::setLocalStreamKey(const QString &key) +{ + d->localStreamKey = key; +} + +void QXmppOutgoingServer::setVerify(const QString &id, const QString &key) +{ + d->incomingId = id; + d->incomingKey = key; +} + diff --git a/src/QXmppOutgoingServer.h b/src/QXmppOutgoingServer.h new file mode 100644 index 00000000..5d3e67d4 --- /dev/null +++ b/src/QXmppOutgoingServer.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPOUTGOINGSERVER_H +#define QXMPPOUTGOINGSERVER_H + +#include "QXmppOutgoingClient.h" + +class QXmppDialback; +class QXmppOutgoingServer; +class QXmppOutgoingServerPrivate; + +/// The QXmppOutgoingServer class represents an outgoing XMPP stream +/// to another XMPP server. +/// + +class QXmppOutgoingServer : public QXmppOutgoingClient +{ + Q_OBJECT + +public: + QXmppOutgoingServer(const QString &domain, QObject *parent); + ~QXmppOutgoingServer(); + + bool isConnected() const; + + QString localStreamKey() const; + void setLocalStreamKey(const QString &key); + void setVerify(const QString &id, const QString &key); + +signals: + void dialbackResponseReceived(const QXmppDialback &response); + +protected: + void handleStart(); + void handleStanza(const QDomElement &stanzaElement); + +private: + Q_DISABLE_COPY(QXmppOutgoingServer) + QXmppOutgoingServerPrivate* const d; +}; + +#endif diff --git a/src/src.pro b/src/src.pro index 74e71c78..14d20884 100644 --- a/src/src.pro +++ b/src/src.pro @@ -33,6 +33,8 @@ HEADERS += QXmppUtils.h \ QXmppDiscoveryIq.h \ QXmppElement.h \ QXmppIbbIq.h \ + QXmppIncomingClient.h \ + QXmppIncomingServer.h \ QXmppInvokable.h \ QXmppIq.h \ QXmppJingleIq.h \ @@ -42,6 +44,7 @@ HEADERS += QXmppUtils.h \ QXmppMucManager.h \ QXmppNonSASLAuth.h \ QXmppOutgoingClient.h \ + QXmppOutgoingServer.h \ QXmppPacket.h \ QXmppPingIq.h \ QXmppPresence.h \ @@ -79,6 +82,8 @@ SOURCES += QXmppUtils.cpp \ QXmppDiscoveryIq.cpp \ QXmppElement.cpp \ QXmppIbbIq.cpp \ + QXmppIncomingClient.cpp \ + QXmppIncomingServer.cpp \ QXmppInvokable.cpp \ QXmppIq.cpp \ QXmppJingleIq.cpp \ @@ -88,6 +93,7 @@ SOURCES += QXmppUtils.cpp \ QXmppMucManager.cpp \ QXmppNonSASLAuth.cpp \ QXmppOutgoingClient.cpp \ + QXmppOutgoingServer.cpp \ QXmppPacket.cpp \ QXmppPingIq.cpp \ QXmppPresence.cpp \ |
