aboutsummaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2021-09-05 16:02:37 +0200
committerLinus Jahn <lnj@kaidan.im>2021-09-28 17:08:08 +0200
commit22be2464b5d253e840d4731fbc86e9633a394e8c (patch)
tree341eea345bd621cd4ef045a79aca57129075ee8d /src/base
parent21a198fd66e7c35622fce0b08c306553a4e4ff5a (diff)
downloadqxmpp-22be2464b5d253e840d4731fbc86e9633a394e8c.tar.gz
QXmppStream: Allow to use existing future interface
Diffstat (limited to 'src/base')
-rw-r--r--src/base/QXmppPacket.cpp26
-rw-r--r--src/base/QXmppPacket_p.h4
-rw-r--r--src/base/QXmppStream.cpp62
-rw-r--r--src/base/QXmppStream.h8
4 files changed, 84 insertions, 16 deletions
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 <QFuture>
#include <QXmlStreamWriter>
+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<QFutureInterface<QXmpp::SendResult>>(QFutureInterfaceBase::Started)),
- m_isXmppStanza(nonza.isXmppStanza())
+ : QXmppPacket(nonza, std::make_shared<QFutureInterface<QXmpp::SendResult>>())
{
- QXmlStreamWriter xmlStream(&m_data);
- nonza.toXml(&xmlStream);
+}
+
+QXmppPacket::QXmppPacket(const QXmppNonza &nonza, std::shared_ptr<QFutureInterface<QXmpp::SendResult>> interface)
+ : QXmppPacket(serialize(nonza), nonza.isXmppStanza(), std::move(interface))
+{
+}
+
+QXmppPacket::QXmppPacket(const QByteArray &data, bool isXmppStanza, std::shared_ptr<QFutureInterface<QXmpp::SendResult>> 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<QFutureInterface<QXmpp::SendResult>>);
+ QXmppPacket(const QByteArray &data, bool isXmppStanza, std::shared_ptr<QFutureInterface<QXmpp::SendResult>>);
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<QXmpp::SendResult> 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<QXmpp::SendResult> QXmppStream::send(QXmppPacket &&packet)
+{
+ bool success;
+ return send(std::move(packet), success);
}
-QFuture<QXmpp::SendResult> QXmppStream::send(QXmppNonza &&nonza, bool &writtenToSocket)
+QFuture<QXmpp::SendResult> 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::IqResult> 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::IqResult> QXmppStream::sendIq(QXmppPacket &&packet, const QString &id)
+{
+ using namespace QXmpp;
+
+ if (id.isEmpty() || d->runningIqs.contains(id)) {
+ return makeReadyFuture<IqResult>(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<SendError>(sendFuture.result())) {
// early exit (saves QFutureWatcher)
@@ -246,7 +278,7 @@ QFuture<QXmppStream::IqResult> QXmppStream::sendIq(QXmppIq &&iq)
}
IqState interface(IqState::Started);
- d->runningIqs.insert(iq.id(), interface);
+ d->runningIqs.insert(id, interface);
return interface.future();
}
@@ -268,6 +300,16 @@ void QXmppStream::cancelOngoingIqs()
}
///
+/// 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.
///
/// This can be done to prevent that packages from the last connection are being
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 <variant>
+#include <memory>
#include <QAbstractSocket>
#include <QObject>
@@ -36,6 +37,8 @@
class QDomElement;
template<typename T>
class QFuture;
+template<typename T>
+class QFutureInterface;
class QSslSocket;
class QXmppIq;
class QXmppNonza;
@@ -58,10 +61,13 @@ public:
bool sendPacket(const QXmppNonza &);
QFuture<QXmpp::SendResult> send(QXmppNonza &&);
+ QFuture<QXmpp::SendResult> send(QXmppPacket &&);
using IqResult = std::variant<QDomElement, QXmpp::SendError>;
QFuture<IqResult> sendIq(QXmppIq &&);
+ QFuture<IqResult> 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<QXmpp::SendResult> send(QXmppNonza &&, bool &);
+ QFuture<QXmpp::SendResult> send(QXmppPacket &&, bool &);
void processData(const QString &data);
bool handleIqResponse(const QDomElement &);