diff options
| author | Linus Jahn <lnj@kaidan.im> | 2020-07-26 20:33:07 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2021-01-09 14:37:47 +0100 |
| commit | 8570b4c56616547e5fa2530e6b9733fb37cf02a3 (patch) | |
| tree | dd25156ba0680c964eef13828cb1de0bdf7b48ee /src/base/QXmppStreamManagement.cpp | |
| parent | 9d181aa8e4d31612391586785144dfefa75356ff (diff) | |
| download | qxmpp-8570b4c56616547e5fa2530e6b9733fb37cf02a3.tar.gz | |
QXmppStream: Move stream management into separate class
Diffstat (limited to 'src/base/QXmppStreamManagement.cpp')
| -rw-r--r-- | src/base/QXmppStreamManagement.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/base/QXmppStreamManagement.cpp b/src/base/QXmppStreamManagement.cpp index 45f0b94c..e2fc621c 100644 --- a/src/base/QXmppStreamManagement.cpp +++ b/src/base/QXmppStreamManagement.cpp @@ -24,6 +24,7 @@ #include "QXmppConstants_p.h" #include "QXmppGlobal.h" #include "QXmppStanza_p.h" +#include "QXmppStream.h" #include "QXmppStreamManagement_p.h" QXmppStreamManagementEnable::QXmppStreamManagementEnable(const bool resume, const unsigned max) @@ -324,3 +325,132 @@ void QXmppStreamManagementReq::toXml(QXmlStreamWriter *writer) writer->writeDefaultNamespace(ns_stream_management); writer->writeEndElement(); } + +QXmppStreamManager::QXmppStreamManager(QXmppStream *stream) + : stream(stream) +{ +} + +unsigned int QXmppStreamManager::lastIncomingSequenceNumber() const +{ + return m_lastIncomingSequenceNumber; +} + +void QXmppStreamManager::handleDisconnect() +{ + m_enabled = false; +} + +void QXmppStreamManager::handleStart() +{ + m_enabled = false; +} + +void QXmppStreamManager::handlePacketSent(const QXmppStanza &packet, const QByteArray &data) +{ + if (m_enabled && packet.isXmppStanza()) { + m_unacknowledgedStanzas.insert(++m_lastOutgoingSequenceNumber, data); + sendAcknowledgementRequest(); + } +} + +bool QXmppStreamManager::handleStanza(const QDomElement &stanza) +{ + if (QXmppStreamManagementAck::isStreamManagementAck(stanza)) { + handleAcknowledgement(stanza); + return true; + } + if (QXmppStreamManagementReq::isStreamManagementReq(stanza)) { + sendAcknowledgement(); + return true; + } + + if (stanza.tagName() == QLatin1String("message") || + stanza.tagName() == QLatin1String("presence") || + stanza.tagName() == QLatin1String("iq")) { + m_lastIncomingSequenceNumber++; + } + return false; +} + +void QXmppStreamManager::enableStreamManagement(bool resetSequenceNumber) +{ + m_enabled = true; + + if (resetSequenceNumber) { + m_lastOutgoingSequenceNumber = 0; + m_lastIncomingSequenceNumber = 0; + + // resend unacked stanzas + if (!m_unacknowledgedStanzas.isEmpty()) { + const auto oldUnackedStanzas = m_unacknowledgedStanzas; + m_unacknowledgedStanzas.clear(); + + for (const auto &value : oldUnackedStanzas) { + m_unacknowledgedStanzas.insert(++m_lastOutgoingSequenceNumber, value); + stream->sendData(value); + } + + sendAcknowledgementRequest(); + } + } else { + // resend unacked stanzas + if (!m_unacknowledgedStanzas.isEmpty()) { + for (const auto &value : std::as_const(m_unacknowledgedStanzas)) { + stream->sendData(value); + } + + sendAcknowledgementRequest(); + } + } +} + +void QXmppStreamManager::setAcknowledgedSequenceNumber(unsigned int sequenceNumber) +{ + for (auto it = m_unacknowledgedStanzas.begin(); it != m_unacknowledgedStanzas.end();) { + if (it.key() <= sequenceNumber) { + it = m_unacknowledgedStanzas.erase(it); + } else { + break; + } + } +} + +void QXmppStreamManager::handleAcknowledgement(const QDomElement &element) +{ + if (!m_enabled) + return; + + QXmppStreamManagementAck ack; + ack.parse(element); + setAcknowledgedSequenceNumber(ack.seqNo()); +} + +void QXmppStreamManager::sendAcknowledgement() +{ + if (!m_enabled) + return; + + // prepare packet + QByteArray data; + QXmlStreamWriter xmlStream(&data); + QXmppStreamManagementAck ack(m_lastIncomingSequenceNumber); + ack.toXml(&xmlStream); + + // send packet + stream->sendData(data); +} + +void QXmppStreamManager::sendAcknowledgementRequest() +{ + if (!m_enabled) + return; + + // prepare packet + QByteArray data; + QXmlStreamWriter xmlStream(&data); + QXmppStreamManagementReq::toXml(&xmlStream); + + // send packet + stream->sendData(data); +} |
