From 22be2464b5d253e840d4731fbc86e9633a394e8c Mon Sep 17 00:00:00 2001 From: Linus Jahn Date: Sun, 5 Sep 2021 16:02:37 +0200 Subject: QXmppStream: Allow to use existing future interface --- src/base/QXmppPacket.cpp | 26 ++++++++++++++++---- src/base/QXmppPacket_p.h | 4 +++- src/base/QXmppStream.cpp | 62 ++++++++++++++++++++++++++++++++++++++++-------- src/base/QXmppStream.h | 8 ++++++- 4 files changed, 84 insertions(+), 16 deletions(-) (limited to 'src/base') diff --git a/src/base/QXmppPacket.cpp b/src/base/QXmppPacket.cpp index 3676c269..3269369c 100644 --- a/src/base/QXmppPacket.cpp +++ b/src/base/QXmppPacket.cpp @@ -27,13 +27,31 @@ #include #include +inline QByteArray serialize(const QXmppNonza &nonza) +{ + QByteArray out; + QXmlStreamWriter xmlStream(&out); + nonza.toXml(&xmlStream); + return out; +} + /// \cond QXmppPacket::QXmppPacket(const QXmppNonza &nonza) - : m_interface(std::make_shared>(QFutureInterfaceBase::Started)), - m_isXmppStanza(nonza.isXmppStanza()) + : QXmppPacket(nonza, std::make_shared>()) { - QXmlStreamWriter xmlStream(&m_data); - nonza.toXml(&xmlStream); +} + +QXmppPacket::QXmppPacket(const QXmppNonza &nonza, std::shared_ptr> interface) + : QXmppPacket(serialize(nonza), nonza.isXmppStanza(), std::move(interface)) +{ +} + +QXmppPacket::QXmppPacket(const QByteArray &data, bool isXmppStanza, std::shared_ptr> interface) + : m_interface(std::move(interface)), + m_data(data), + m_isXmppStanza(isXmppStanza) +{ + m_interface->reportStarted(); } QByteArray QXmppPacket::data() const diff --git a/src/base/QXmppPacket_p.h b/src/base/QXmppPacket_p.h index a99752bb..0ce80760 100644 --- a/src/base/QXmppPacket_p.h +++ b/src/base/QXmppPacket_p.h @@ -36,7 +36,9 @@ class QXmppNonza; class QXmppPacket { public: - QXmppPacket(const QXmppNonza &); + QXmppPacket(const QXmppNonza &nonza); + QXmppPacket(const QXmppNonza &nonza, std::shared_ptr>); + QXmppPacket(const QByteArray &data, bool isXmppStanza, std::shared_ptr>); QByteArray data() const; bool isXmppStanza() const; diff --git a/src/base/QXmppStream.cpp b/src/base/QXmppStream.cpp index 1cac8740..895705a8 100644 --- a/src/base/QXmppStream.cpp +++ b/src/base/QXmppStream.cpp @@ -172,13 +172,13 @@ bool QXmppStream::sendData(const QByteArray &data) /// /// Sends an XMPP packet to the peer. /// -/// \param stanza +/// \param nonza /// -bool QXmppStream::sendPacket(const QXmppNonza &stanza) +bool QXmppStream::sendPacket(const QXmppNonza &nonza) { bool success; -// send(stanza, success); - return false; + send(nonza, success); + return success; } /// @@ -189,12 +189,24 @@ bool QXmppStream::sendPacket(const QXmppNonza &stanza) QFuture QXmppStream::send(QXmppNonza &&nonza) { bool success; - return send(std::move(nonza), success); + return send(QXmppPacket(nonza), success); +} + +/// +/// Sends an XMPP packet to the peer. +/// +/// \since QXmpp 1.5 +/// +QFuture QXmppStream::send(QXmppPacket &&packet) +{ + bool success; + return send(std::move(packet), success); } -QFuture QXmppStream::send(QXmppNonza &&nonza, bool &writtenToSocket) +QFuture QXmppStream::send(QXmppPacket &&packet, bool &writtenToSocket) { - QXmppPacket packet(nonza); + // the writtenToSocket parameter is just for backwards compat (see + // QXmppStream::sendPacket()) writtenToSocket = sendData(packet.data()); // handle stream management @@ -225,8 +237,28 @@ QFuture QXmppStream::sendIq(QXmppIq &&iq) iq.setId(QXmppUtils::generateStanzaUuid()); } - const auto id = iq.id(); - auto sendFuture = send(std::move(iq)); + return sendIq(QXmppPacket(iq), iq.id()); +} + +/// +/// Sends an IQ packet and returns the response asynchronously. +/// +/// \warning THIS API IS NOT FINALIZED YET! +/// +/// \since QXmpp 1.5 +/// +QFuture QXmppStream::sendIq(QXmppPacket &&packet, const QString &id) +{ + using namespace QXmpp; + + if (id.isEmpty() || d->runningIqs.contains(id)) { + return makeReadyFuture(QXmpp::SendError { + QStringLiteral("Invalid IQ id: empty or in use."), + SendError::Disconnected + }); + } + + auto sendFuture = send(std::move(packet)); if (sendFuture.isFinished()) { if (std::holds_alternative(sendFuture.result())) { // early exit (saves QFutureWatcher) @@ -246,7 +278,7 @@ QFuture QXmppStream::sendIq(QXmppIq &&iq) } IqState interface(IqState::Started); - d->runningIqs.insert(iq.id(), interface); + d->runningIqs.insert(id, interface); return interface.future(); } @@ -267,6 +299,16 @@ void QXmppStream::cancelOngoingIqs() d->runningIqs.clear(); } +/// +/// Returns whether the IQ ID is currently in use. +/// +/// \since QXmpp 1.5 +/// +bool QXmppStream::hasIqId(const QString &id) const +{ + return d->runningIqs.contains(id); +} + /// /// Resets the stream management packages cache. /// diff --git a/src/base/QXmppStream.h b/src/base/QXmppStream.h index e1fd31ac..3c321921 100644 --- a/src/base/QXmppStream.h +++ b/src/base/QXmppStream.h @@ -29,6 +29,7 @@ #include "QXmppSendResult.h" #include +#include #include #include @@ -36,6 +37,8 @@ class QDomElement; template class QFuture; +template +class QFutureInterface; class QSslSocket; class QXmppIq; class QXmppNonza; @@ -58,10 +61,13 @@ public: bool sendPacket(const QXmppNonza &); QFuture send(QXmppNonza &&); + QFuture send(QXmppPacket &&); using IqResult = std::variant; QFuture sendIq(QXmppIq &&); + QFuture sendIq(QXmppPacket &&, const QString &id); void cancelOngoingIqs(); + bool hasIqId(const QString &id) const; void resetPacketCache(); @@ -110,7 +116,7 @@ private: friend class tst_QXmppStream; friend class TestClient; - QFuture send(QXmppNonza &&, bool &); + QFuture send(QXmppPacket &&, bool &); void processData(const QString &data); bool handleIqResponse(const QDomElement &); -- cgit v1.2.3