diff options
| author | Tibor Csötönyi <work@taibsu.de> | 2023-05-03 15:33:35 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2023-05-14 23:58:00 +0200 |
| commit | 2fde987d39dc66f028ea3ff44929ebd6e2b37f90 (patch) | |
| tree | 14ce02a68b801caf984f74700ea28c0a85fc5b3b /src/base | |
| parent | 44e9657c4e1551697f496cc9415f3d458103ca5c (diff) | |
| download | qxmpp-2fde987d39dc66f028ea3ff44929ebd6e2b37f90.tar.gz | |
Add XEP-0353: Jingle Message Initiation data classes
Diffstat (limited to 'src/base')
| -rw-r--r-- | src/base/QXmppConstants.cpp | 2 | ||||
| -rw-r--r-- | src/base/QXmppConstants_p.h | 2 | ||||
| -rw-r--r-- | src/base/QXmppJingleIq.cpp | 275 | ||||
| -rw-r--r-- | src/base/QXmppJingleIq.h | 51 | ||||
| -rw-r--r-- | src/base/QXmppMessage.cpp | 35 | ||||
| -rw-r--r-- | src/base/QXmppMessage.h | 6 |
6 files changed, 370 insertions, 1 deletions
diff --git a/src/base/QXmppConstants.cpp b/src/base/QXmppConstants.cpp index be5b62c7..0ddd3db2 100644 --- a/src/base/QXmppConstants.cpp +++ b/src/base/QXmppConstants.cpp @@ -160,6 +160,8 @@ const char *ns_chat_markers = "urn:xmpp:chat-markers:0"; const char *ns_message_processing_hints = "urn:xmpp:hints"; // XEP-0352: Client State Indication const char *ns_csi = "urn:xmpp:csi:0"; +// XEP-0353: Jingle Message Initiation +const char *ns_jingle_message_initiation = "urn:xmpp:jingle-message:0"; // XEP-0357: Push Notifications const char *ns_push = "urn:xmpp:push:0"; // XEP-0359: Unique and Stable Stanza IDs diff --git a/src/base/QXmppConstants_p.h b/src/base/QXmppConstants_p.h index b90346b6..c859de96 100644 --- a/src/base/QXmppConstants_p.h +++ b/src/base/QXmppConstants_p.h @@ -172,6 +172,8 @@ extern const char *ns_chat_markers; extern const char *ns_message_processing_hints; // XEP-0352: Client State Indication extern const char *ns_csi; +// XEP-0353: Jingle Message Initiation +extern const char *ns_jingle_message_initiation; // XEP-0357: Push Notifications extern const char *ns_push; // XEP-0359: Unique and Stable Stanza IDs diff --git a/src/base/QXmppJingleIq.cpp b/src/base/QXmppJingleIq.cpp index d769e809..67883fc8 100644 --- a/src/base/QXmppJingleIq.cpp +++ b/src/base/QXmppJingleIq.cpp @@ -2930,3 +2930,278 @@ bool QXmppJingleRtpHeaderExtensionProperty::isJingleRtpHeaderExtensionProperty(c return element.tagName() == QStringLiteral("rtp-hdrext") && element.namespaceURI() == ns_jingle_rtp_header_extensions_negotiation; } + +class QXmppJingleMessageInitiationElementPrivate : public QSharedData +{ +public: + QXmppJingleMessageInitiationElementPrivate() = default; + + QXmppJingleMessageInitiationElement::Type type { QXmppJingleMessageInitiationElement::Type::None }; + QString id; + + std::optional<QXmppJingleDescription> description; + std::optional<QXmppJingleReason> reason; + QString migratedTo; + + bool containsTieBreak; +}; + +QXMPP_PRIVATE_DEFINE_RULE_OF_SIX(QXmppJingleReason) + +/// +/// \enum QXmppJingleMessageInitiationElement::Type +/// +/// Possible types of Jingle Message Initiation elements +/// + +/// +/// \class QXmppJingleMessageInitiationElement +/// +/// \brief The QXmppJingleMessageInitiationElement class represents a Jingle Message Initiation +/// element as specified by \xep{0353}: Jingle Message Initiation. +/// +/// \ingroup Stanzas +/// +/// \since QXmpp 1.6 +/// + +/// +/// \brief Constructs a Jingle Message Initiation element. +/// \param type The JMI element type +/// +QXmppJingleMessageInitiationElement::QXmppJingleMessageInitiationElement() + : d(new QXmppJingleMessageInitiationElementPrivate()) +{ +} + +/// +/// Returns the Jingle Message Initiation element type +/// +QXmppJingleMessageInitiationElement::Type QXmppJingleMessageInitiationElement::type() const +{ + return d->type; +} + +/// +/// Sets the Jingle Message Initiation element type. +/// +void QXmppJingleMessageInitiationElement::setType(Type type) +{ + d->type = type; +} + +/// +/// Returns the Jingle Message Initiation element id. +/// +QString QXmppJingleMessageInitiationElement::id() const +{ + return d->id; +} + +/// +/// Sets the Jingle Message Initiation element id. +/// +void QXmppJingleMessageInitiationElement::setId(const QString &id) +{ + d->id = id; +} + +/// +/// Returns the Jingle Message Initiation element description. +/// +std::optional<QXmppJingleDescription> QXmppJingleMessageInitiationElement::description() const +{ + return d->description; +} + +/// +/// Sets the Jingle Message Initiation element description. +/// +void QXmppJingleMessageInitiationElement::setDescription(std::optional<QXmppJingleDescription> description) +{ + d->description = description; +} + +/// +/// Returns the Jingle Message Initiation element reason. +/// +std::optional<QXmppJingleReason> QXmppJingleMessageInitiationElement::reason() const +{ + return d->reason; +} + +/// +/// Sets the Jingle Message Initiation element reason. +/// +void QXmppJingleMessageInitiationElement::setReason(std::optional<QXmppJingleReason> reason) +{ + d->reason = reason; + + if (d->reason) { + d->reason->setNamespaceUri(ns_jingle); + } +} + +/// +/// Returns true if the Jingle Message Initiation element contains a <tie-break/> tag. +/// +bool QXmppJingleMessageInitiationElement::containsTieBreak() const +{ + return d->containsTieBreak; +} + +/// +/// Sets if the Jingle Message Initiation element contains a <tie-break/> tag. +/// +void QXmppJingleMessageInitiationElement::setContainsTieBreak(bool containsTieBreak) +{ + d->containsTieBreak = containsTieBreak; +} + +/// +/// Returns the Jingle Message Initiation element ID migrated to if the Jingle is being migrated +/// to a different device. +/// +QString QXmppJingleMessageInitiationElement::migratedTo() const +{ + return d->migratedTo; +} + +/// +/// Sets the Jingle Message Initiation element ID migrated to if the Jingle is being migrated +/// to a different device. +/// +void QXmppJingleMessageInitiationElement::setMigratedTo(const QString &migratedTo) +{ + d->migratedTo = migratedTo; +} + +/// \cond +void QXmppJingleMessageInitiationElement::parse(const QDomElement &element) +{ + d->type = stringToJmiElementType(element.nodeName()); + + if (d->type == Type::None) { + return; + } + + d->id = element.attribute(QStringLiteral("id")); + + // Type::Proceed and Type::Ringing don't need any parsing aside of the id. + switch (d->type) { + case Type::Propose: { + if (const auto &descriptionElement = element.firstChildElement("description"); !descriptionElement.isNull()) { + d->description = QXmppJingleDescription(); + d->description->parse(descriptionElement); + } + + break; + } + case Type::Reject: + case Type::Retract: + d->containsTieBreak = !element.firstChildElement("tie-break").isNull(); + + if (const auto &reasonElement = element.firstChildElement("reason"); !reasonElement.isNull()) { + d->reason = QXmppJingleReason(); + d->reason->parse(reasonElement); + } + + break; + case Type::Finish: + if (const auto &reasonElement = element.firstChildElement("reason"); !reasonElement.isNull()) { + d->reason = QXmppJingleReason(); + d->reason->parse(reasonElement); + } + + if (const auto &migratedToElement = element.firstChildElement("migrated"); !migratedToElement.isNull()) { + d->migratedTo = migratedToElement.attribute("to"); + } + + break; + default: + break; + } +} + +void QXmppJingleMessageInitiationElement::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement(jmiElementTypeToString(d->type)); + writer->writeDefaultNamespace(ns_jingle_message_initiation); + + helperToXmlAddAttribute(writer, QStringLiteral("id"), d->id); + + if (d->description) { + d->description->toXml(writer); + } + + if (d->reason) { + d->reason->toXml(writer); + } + + if (d->containsTieBreak) { + writer->writeEmptyElement(QStringLiteral("tie-break")); + } + + if (!d->migratedTo.isEmpty()) { + writer->writeEmptyElement(QStringLiteral("migrated")); + helperToXmlAddAttribute(writer, QStringLiteral("to"), d->migratedTo); + } + + writer->writeEndElement(); +} +/// \endcond + +QXMPP_PRIVATE_DEFINE_RULE_OF_SIX(QXmppJingleMessageInitiationElement) + +/// +/// Returns true if passed QDomElement is a Jingle Message Initiation element +/// +bool QXmppJingleMessageInitiationElement::isJingleMessageInitiationElement(const QDomElement &element) +{ + return (element.nodeName() == QStringLiteral("propose") || element.nodeName() == QStringLiteral("ringing") || element.nodeName() == QStringLiteral("proceed") || element.nodeName() == QStringLiteral("retract") || element.nodeName() == QStringLiteral("reject") || element.nodeName() == QStringLiteral("finish")) && element.hasAttribute(QStringLiteral("id")) && element.namespaceURI() == ns_jingle_message_initiation; +} + +/// +/// Takes a Jingle Message Initiation element type and parses it to a string. +/// +QString QXmppJingleMessageInitiationElement::jmiElementTypeToString(Type type) const +{ + switch (type) { + case Type::Propose: + return "propose"; + case Type::Ringing: + return "ringing"; + case Type::Proceed: + return "proceed"; + case Type::Reject: + return "reject"; + case Type::Retract: + return "retract"; + case Type::Finish: + return "finish"; + default: + return {}; + } +} + +/// +/// Takes a string and parses it to a Jingle Message Initiation element type. +/// +QXmppJingleMessageInitiationElement::Type QXmppJingleMessageInitiationElement::stringToJmiElementType(const QString &typeStr) const +{ + if (typeStr == "propose") { + return Type::Propose; + } else if (typeStr == "ringing") { + return Type::Ringing; + } else if (typeStr == "proceed") { + return Type::Proceed; + } else if (typeStr == "reject") { + return Type::Reject; + } else if (typeStr == "retract") { + return Type::Retract; + } else if (typeStr == "finish") { + return Type::Finish; + } + + return Type::None; +} diff --git a/src/base/QXmppJingleIq.h b/src/base/QXmppJingleIq.h index 6589a5cb..1e425f4d 100644 --- a/src/base/QXmppJingleIq.h +++ b/src/base/QXmppJingleIq.h @@ -24,6 +24,7 @@ class QXmppJingleRtpEncryptionPrivate; class QXmppJingleRtpFeedbackPropertyPrivate; class QXmppJingleRtpHeaderExtensionPropertyPrivate; class QXmppSdpParameterPrivate; +class QXmppJingleMessageInitiationElementPrivate; class QXMPP_EXPORT QXmppSdpParameter { @@ -595,6 +596,54 @@ private: QSharedDataPointer<QXmppJingleIqPrivate> d; }; -Q_DECLARE_METATYPE(QXmppJingleIq::Reason::RtpErrorCondition) +class QXMPP_EXPORT QXmppJingleMessageInitiationElement +{ +public: + enum class Type { + None, + Propose, + Ringing, + Proceed, + Reject, + Retract, + Finish + }; + + QXmppJingleMessageInitiationElement(); + QXMPP_PRIVATE_DECLARE_RULE_OF_SIX(QXmppJingleMessageInitiationElement) + + Type type() const; + void setType(Type type); + + QString id() const; + void setId(const QString &id); + + std::optional<QXmppJingleDescription> description() const; + void setDescription(std::optional<QXmppJingleDescription> description); + + std::optional<QXmppJingleReason> reason() const; + void setReason(std::optional<QXmppJingleReason> reason); + + bool containsTieBreak() const; + void setContainsTieBreak(bool containsTieBreak); + + QString migratedTo() const; + void setMigratedTo(const QString &migratedTo); + + /// \cond + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *writer) const; + /// \endcond + + static bool isJingleMessageInitiationElement(const QDomElement &); + +private: + QString jmiElementTypeToString(Type type) const; + Type stringToJmiElementType(const QString &typeStr) const; + + QSharedDataPointer<QXmppJingleMessageInitiationElementPrivate> d; +}; + +Q_DECLARE_METATYPE(QXmppJingleReason::RtpErrorCondition) #endif diff --git a/src/base/QXmppMessage.cpp b/src/base/QXmppMessage.cpp index 9527f5ed..be6cd83e 100644 --- a/src/base/QXmppMessage.cpp +++ b/src/base/QXmppMessage.cpp @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: 2010 Jeremy Lainé <jeremy.laine@m4x.org> // SPDX-FileCopyrightText: 2018 Linus Jahn <lnj@kaidan.im> // SPDX-FileCopyrightText: 2021 Melvin Keskin <melvo@olomono.de> +// SPDX-FileCopyrightText: 2023 Tibor Csötönyi <work@taibsu.de> // // SPDX-License-Identifier: LGPL-2.1-or-later @@ -11,6 +12,7 @@ #include "QXmppConstants_p.h" #include "QXmppFileShare.h" #include "QXmppGlobal_p.h" +#include "QXmppJingleData.h" #include "QXmppMessageReaction.h" #include "QXmppMixInvitation.h" #ifdef BUILD_OMEMO @@ -123,6 +125,9 @@ public: // XEP-0334: Message Processing Hints quint8 hints; + // XEP-0353: Jingle Message Initiation + std::optional<QXmppJingleMessageInitiationElement> jingleMessageInitiationElement; + // XEP-0359: Unique and Stable Stanza IDs QString stanzaId; QString stanzaIdBy; @@ -872,6 +877,24 @@ void QXmppMessage::removeAllHints() } /// +/// Returns a Jingle Message Initiation element as defined in \xep{0353}: Jingle Message +/// Initiation. +/// +std::optional<QXmppJingleMessageInitiationElement> QXmppMessage::jingleMessageInitiationElement() const +{ + return d->jingleMessageInitiationElement; +} + +/// +/// Sets a Jingle Message Initiation element as defined in \xep{0353}: Jingle Message +/// Initiation. +/// +void QXmppMessage::setJingleMessageInitiationElement(const std::optional<QXmppJingleMessageInitiationElement> &jingleMessageInitiationElement) +{ + d->jingleMessageInitiationElement = jingleMessageInitiationElement; +} + +/// /// Returns the stanza ID of the message according to \xep{0359}: Unique and /// Stable Stanza IDs. /// @@ -1393,6 +1416,13 @@ bool QXmppMessage::parseExtension(const QDomElement &element, QXmpp::SceMode sce } return true; } + // XEP-0353: Jingle Message Initiation + if (QXmppJingleMessageInitiationElement::isJingleMessageInitiationElement(element)) { + QXmppJingleMessageInitiationElement jingleMessageInitiationElement; + jingleMessageInitiationElement.parse(element); + d->jingleMessageInitiationElement = jingleMessageInitiationElement; + return true; + } // XEP-0359: Unique and Stable Stanza IDs if (checkElement(element, QStringLiteral("stanza-id"), ns_sid)) { d->stanzaId = element.attribute(QStringLiteral("id")); @@ -1811,6 +1841,11 @@ void QXmppMessage::serializeExtensions(QXmlStreamWriter *writer, QXmpp::SceMode writer->writeEndElement(); } + // XEP-0353: Jingle Message Initiation + if (d->jingleMessageInitiationElement) { + d->jingleMessageInitiationElement->toXml(writer); + } + // XEP-0367: Message Attaching if (!d->attachId.isEmpty()) { writer->writeStartElement(QStringLiteral("attach-to")); diff --git a/src/base/QXmppMessage.h b/src/base/QXmppMessage.h index be9e9b96..cf6df18d 100644 --- a/src/base/QXmppMessage.h +++ b/src/base/QXmppMessage.h @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: 2010 Jeremy Lainé <jeremy.laine@m4x.org> // SPDX-FileCopyrightText: 2018 Linus Jahn <lnj@kaidan.im> // SPDX-FileCopyrightText: 2020 Melvin Keskin <melvo@olomono.de> +// SPDX-FileCopyrightText: 2023 Tibor Csötönyi <work@taibsu.de> // // SPDX-License-Identifier: LGPL-2.1-or-later @@ -18,6 +19,7 @@ class QXmppMessagePrivate; class QXmppBitsOfBinaryDataList; +class QXmppJingleMessageInitiationElement; class QXmppMessageReaction; class QXmppMixInvitation; #ifdef BUILD_OMEMO @@ -205,6 +207,10 @@ public: void removeHint(const Hint hint); void removeAllHints(); + // XEP-0353: Jingle Message Initiation + std::optional<QXmppJingleMessageInitiationElement> jingleMessageInitiationElement() const; + void setJingleMessageInitiationElement(const std::optional<QXmppJingleMessageInitiationElement> &jingleMessageInitiationElement); + // XEP-0359: Unique and Stable Stanza IDs QString stanzaId() const; void setStanzaId(const QString &id); |
