aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2010-07-16 08:53:13 +0000
committerJeremy Lainé <jeremy.laine@m4x.org>2010-07-16 08:53:13 +0000
commit1b596e06fac7e1ec96cc5f9f387b936836f2c601 (patch)
tree428311cd012409834d0f7fa0408bf47c68c8a737 /source
parent71ff1eec1fdc8e102d7b2b9732b5b576f7649f34 (diff)
downloadqxmpp-1b596e06fac7e1ec96cc5f9f387b936836f2c601.tar.gz
add support for parsing Jingle IQs
Diffstat (limited to 'source')
-rw-r--r--source/QXmppJingleIq.cpp631
-rw-r--r--source/QXmppJingleIq.h267
-rw-r--r--source/QXmppStream.cpp12
-rw-r--r--source/QXmppStream.h4
-rw-r--r--source/source.pro2
5 files changed, 916 insertions, 0 deletions
diff --git a/source/QXmppJingleIq.cpp b/source/QXmppJingleIq.cpp
new file mode 100644
index 00000000..7af47797
--- /dev/null
+++ b/source/QXmppJingleIq.cpp
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2010 Bolloré telecom
+ *
+ * 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 "QXmppConstants.h"
+#include "QXmppJingleIq.h"
+#include "QXmppUtils.h"
+
+static const char* ns_jingle_rtp_info = "urn:xmpp:jingle:apps:rtp:info:1";
+
+static const char* jingle_actions[] = {
+ "content-accept",
+ "content-add",
+ "content-modify",
+ "content-reject",
+ "content-remove",
+ "description-info",
+ "security-info",
+ "session-accept",
+ "session-info",
+ "session-initiate",
+ "session-terminate",
+ "transport-accept",
+ "transport-info",
+ "transport-reject",
+ "transport-replace",
+};
+
+static const char* jingle_reasons[] = {
+ "",
+ "alternative-session",
+ "busy",
+ "cancel",
+ "connectivity-error",
+ "decline",
+ "expired",
+ "failed-application",
+ "failed-transport",
+ "general-error",
+ "gone",
+ "incompatible-parameters",
+ "media-error",
+ "security-error",
+ "success",
+ "timeout",
+ "unsupported-applications",
+ "unsupported-transports",
+};
+
+QXmppJingleIq::Content::Content()
+{
+}
+
+QString QXmppJingleIq::Content::creator() const
+{
+ return m_creator;
+}
+
+void QXmppJingleIq::Content::setCreator(const QString &creator)
+{
+ m_creator = creator;
+}
+
+QString QXmppJingleIq::Content::name() const
+{
+ return m_name;
+}
+
+void QXmppJingleIq::Content::setName(const QString &name)
+{
+ m_name = name;
+}
+
+QString QXmppJingleIq::Content::senders() const
+{
+ return m_senders;
+}
+
+void QXmppJingleIq::Content::setSenders(const QString &senders)
+{
+ m_senders = senders;
+}
+
+QString QXmppJingleIq::Content::descriptionMedia() const
+{
+ return m_descriptionMedia;
+}
+
+void QXmppJingleIq::Content::setDescriptionMedia(const QString &media)
+{
+ m_descriptionMedia = media;
+}
+
+void QXmppJingleIq::Content::addPayloadType(const QXmppJinglePayloadType &payload)
+{
+ m_descriptionType = ns_jingle_rtp;
+ m_payloadTypes << payload;
+}
+
+QList<QXmppJinglePayloadType> QXmppJingleIq::Content::payloadTypes() const
+{
+ return m_payloadTypes;
+}
+
+void QXmppJingleIq::Content::setPayloadTypes(const QList<QXmppJinglePayloadType> &payloadTypes)
+{
+ m_descriptionType = payloadTypes.isEmpty() ? QString() : ns_jingle_rtp;
+ m_payloadTypes = payloadTypes;
+}
+
+void QXmppJingleIq::Content::addTransportCandidate(const QXmppJingleCandidate &candidate)
+{
+ m_transportType = ns_jingle_ice_udp;
+ m_transportCandidates << candidate;
+}
+
+QList<QXmppJingleCandidate> QXmppJingleIq::Content::transportCandidates() const
+{
+ return m_transportCandidates;
+}
+
+QString QXmppJingleIq::Content::transportUser() const
+{
+ return m_transportUser;
+}
+
+void QXmppJingleIq::Content::setTransportUser(const QString &user)
+{
+ m_transportUser = user;
+}
+
+QString QXmppJingleIq::Content::transportPassword() const
+{
+ return m_transportPassword;
+}
+
+void QXmppJingleIq::Content::setTransportPassword(const QString &password)
+{
+ m_transportPassword = password;
+}
+
+void QXmppJingleIq::Content::parse(const QDomElement &element)
+{
+ m_creator = element.attribute("creator");
+ m_disposition = element.attribute("disposition");
+ m_name = element.attribute("name");
+ m_senders = element.attribute("senders");
+
+ // description
+ QDomElement descriptionElement = element.firstChildElement("description");
+ m_descriptionType = descriptionElement.namespaceURI();
+ m_descriptionMedia = descriptionElement.attribute("media");
+ QDomElement child = descriptionElement.firstChildElement("payload-type");
+ while (!child.isNull())
+ {
+ QXmppJinglePayloadType payload;
+ payload.parse(child);
+ m_payloadTypes << payload;
+ child = child.nextSiblingElement("payload-type");
+ }
+
+ // transport
+ QDomElement transportElement = element.firstChildElement("transport");
+ m_transportType = transportElement.namespaceURI();
+ m_transportUser = transportElement.attribute("ufrag");
+ m_transportPassword = transportElement.attribute("pwd");
+ child = transportElement.firstChildElement("candidate");
+ while (!child.isNull())
+ {
+ QXmppJingleCandidate candidate;
+ candidate.parse(child);
+ m_transportCandidates << candidate;
+ child = child.nextSiblingElement("candidate");
+ }
+}
+
+void QXmppJingleIq::Content::toXml(QXmlStreamWriter *writer) const
+{
+ if (m_creator.isEmpty() || m_name.isEmpty())
+ return;
+
+ writer->writeStartElement("content");
+ helperToXmlAddAttribute(writer, "creator", m_creator);
+ helperToXmlAddAttribute(writer, "disposition", m_disposition);
+ helperToXmlAddAttribute(writer, "name", m_name);
+ helperToXmlAddAttribute(writer, "senders", m_senders);
+
+ // description
+ if (!m_descriptionType.isEmpty() || !m_payloadTypes.isEmpty())
+ {
+ writer->writeStartElement("description");
+ helperToXmlAddAttribute(writer, "xmlns", m_descriptionType);
+ helperToXmlAddAttribute(writer, "media", m_descriptionMedia);
+ foreach (const QXmppJinglePayloadType &payload, m_payloadTypes)
+ payload.toXml(writer);
+ writer->writeEndElement();
+ }
+
+ // transport
+ if (!m_transportType.isEmpty() || !m_transportCandidates.isEmpty())
+ {
+ writer->writeStartElement("transport");
+ helperToXmlAddAttribute(writer, "xmlns", m_transportType);
+ helperToXmlAddAttribute(writer, "ufrag", m_transportUser);
+ helperToXmlAddAttribute(writer, "pwd", m_transportPassword);
+ foreach (const QXmppJingleCandidate &candidate, m_transportCandidates)
+ candidate.toXml(writer);
+ writer->writeEndElement();
+ }
+ writer->writeEndElement();
+}
+
+QXmppJingleIq::Reason::Reason()
+ : m_type(None)
+{
+}
+
+QString QXmppJingleIq::Reason::text() const
+{
+ return m_text;
+}
+
+void QXmppJingleIq::Reason::setText(const QString &text)
+{
+ m_text = text;
+}
+
+QXmppJingleIq::Reason::Type QXmppJingleIq::Reason::type() const
+{
+ return m_type;
+}
+
+void QXmppJingleIq::Reason::setType(QXmppJingleIq::Reason::Type type)
+{
+ m_type = type;
+}
+
+void QXmppJingleIq::Reason::parse(const QDomElement &element)
+{
+ m_text = element.firstChildElement("text").text();
+ for (int i = AlternativeSession; i <= UnsupportedTransports; i++)
+ {
+ if (!element.firstChildElement(jingle_reasons[i]).isNull())
+ {
+ m_type = static_cast<Type>(i);
+ break;
+ }
+ }
+}
+
+void QXmppJingleIq::Reason::toXml(QXmlStreamWriter *writer) const
+{
+ if (m_type < AlternativeSession || m_type > UnsupportedTransports)
+ return;
+
+ writer->writeStartElement("reason");
+ if (!m_text.isEmpty())
+ helperToXmlAddTextElement(writer, "text", m_text);
+ writer->writeEmptyElement(jingle_reasons[m_type]);
+ writer->writeEndElement();
+}
+
+QXmppJingleIq::QXmppJingleIq()
+ : m_ringing(false)
+{
+}
+
+QXmppJingleIq::Action QXmppJingleIq::action() const
+{
+ return m_action;
+}
+
+void QXmppJingleIq::setAction(QXmppJingleIq::Action action)
+{
+ m_action = action;
+}
+
+QString QXmppJingleIq::initiator() const
+{
+ return m_initiator;
+}
+
+void QXmppJingleIq::setInitiator(const QString &initiator)
+{
+ m_initiator = initiator;
+}
+
+QString QXmppJingleIq::responder() const
+{
+ return m_responder;
+}
+
+void QXmppJingleIq::setResponder(const QString &responder)
+{
+ m_responder = responder;
+}
+
+QString QXmppJingleIq::sid() const
+{
+ return m_sid;
+}
+
+void QXmppJingleIq::setSid(const QString &sid)
+{
+ m_sid = sid;
+}
+
+bool QXmppJingleIq::isJingleIq(const QDomElement &element)
+{
+ QDomElement jingleElement = element.firstChildElement("jingle");
+ return (jingleElement.namespaceURI() == ns_jingle);
+}
+
+bool QXmppJingleIq::ringing() const
+{
+ return m_ringing;
+}
+
+void QXmppJingleIq::setRinging(bool ringing)
+{
+ m_ringing = ringing;
+}
+
+void QXmppJingleIq::parseElementFromChild(const QDomElement &element)
+{
+ QDomElement jingleElement = element.firstChildElement("jingle");
+ const QString action = jingleElement.attribute("action");
+ for (int i = ContentAccept; i <= TransportReplace; i++)
+ {
+ if (action == jingle_actions[i])
+ {
+ m_action = static_cast<Action>(i);
+ break;
+ }
+ }
+ m_initiator = jingleElement.attribute("initiator");
+ m_responder = jingleElement.attribute("responder");
+ m_sid = jingleElement.attribute("sid");
+
+ // content
+ QDomElement contentElement = jingleElement.firstChildElement("content");
+ m_content.parse(contentElement);
+ QDomElement reasonElement = jingleElement.firstChildElement("reason");
+ m_reason.parse(reasonElement);
+
+ // ringing
+ QDomElement ringingElement = jingleElement.firstChildElement("ringing");
+ m_ringing = (ringingElement.namespaceURI() == ns_jingle_rtp_info);
+}
+
+void QXmppJingleIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("jingle");
+ helperToXmlAddAttribute(writer, "xmlns", ns_jingle);
+ helperToXmlAddAttribute(writer, "action", jingle_actions[m_action]);
+ helperToXmlAddAttribute(writer, "initiator", m_initiator);
+ helperToXmlAddAttribute(writer, "responder", m_responder);
+ helperToXmlAddAttribute(writer, "sid", m_sid);
+ m_content.toXml(writer);
+ m_reason.toXml(writer);
+
+ // ringing
+ if (m_ringing)
+ {
+ writer->writeStartElement("ringing");
+ helperToXmlAddAttribute(writer, "xmlns", ns_jingle_rtp_info);
+ writer->writeEndElement();
+ }
+
+ writer->writeEndElement();
+}
+
+QXmppJingleCandidate::QXmppJingleCandidate()
+ : m_component(0),
+ m_foundation(0),
+ m_generation(0),
+ m_network(0),
+ m_port(0),
+ m_priority(0)
+{
+}
+
+int QXmppJingleCandidate::component() const
+{
+ return m_component;
+}
+
+void QXmppJingleCandidate::setComponent(int component)
+{
+ m_component = component;
+}
+
+int QXmppJingleCandidate::foundation() const
+{
+ return m_foundation;
+}
+
+void QXmppJingleCandidate::setFoundation(int foundation)
+{
+ m_foundation = foundation;
+}
+
+QHostAddress QXmppJingleCandidate::host() const
+{
+ return m_host;
+}
+
+void QXmppJingleCandidate::setHost(const QHostAddress &host)
+{
+ m_host = host;
+}
+
+QString QXmppJingleCandidate::id() const
+{
+ return m_id;
+}
+
+void QXmppJingleCandidate::setId(const QString &id)
+{
+ m_id = id;
+}
+
+int QXmppJingleCandidate::network() const
+{
+ return m_network;
+}
+
+void QXmppJingleCandidate::setNetwork(int network)
+{
+ m_network = network;
+}
+
+int QXmppJingleCandidate::priority() const
+{
+ return m_priority;
+}
+
+void QXmppJingleCandidate::setPriority(int priority)
+{
+ m_priority = priority;
+}
+
+QString QXmppJingleCandidate::protocol() const
+{
+ return m_protocol;
+}
+
+void QXmppJingleCandidate::setProtocol(const QString &protocol)
+{
+ m_protocol = protocol;
+}
+
+quint16 QXmppJingleCandidate::port() const
+{
+ return m_port;
+}
+
+void QXmppJingleCandidate::setPort(quint16 port)
+{
+ m_port = port;
+}
+
+QString QXmppJingleCandidate::type() const
+{
+ return m_type;
+}
+
+void QXmppJingleCandidate::setType(const QString &type)
+{
+ m_type = type;
+}
+
+void QXmppJingleCandidate::parse(const QDomElement &element)
+{
+ m_component = element.attribute("component").toInt();
+ m_foundation = element.attribute("foundation").toInt();
+ m_generation = element.attribute("generation").toInt();
+ m_host = QHostAddress(element.attribute("ip"));
+ m_id = element.attribute("id");
+ m_network = element.attribute("network").toInt();
+ m_port = element.attribute("port").toInt();
+ m_priority = element.attribute("priority").toInt();
+ m_protocol = element.attribute("protocol");
+ m_type = element.attribute("type");
+}
+
+void QXmppJingleCandidate::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("candidate");
+ helperToXmlAddAttribute(writer, "component", QString::number(m_component));
+ helperToXmlAddAttribute(writer, "foundation", QString::number(m_foundation));
+ helperToXmlAddAttribute(writer, "generation", QString::number(m_generation));
+ helperToXmlAddAttribute(writer, "id", m_id);
+ helperToXmlAddAttribute(writer, "ip", m_host.toString());
+ helperToXmlAddAttribute(writer, "network", QString::number(m_network));
+ helperToXmlAddAttribute(writer, "port", QString::number(m_port));
+ helperToXmlAddAttribute(writer, "priority", QString::number(m_priority));
+ helperToXmlAddAttribute(writer, "protocol", m_protocol);
+ helperToXmlAddAttribute(writer, "type", m_type);
+ writer->writeEndElement();
+}
+
+QXmppJinglePayloadType::QXmppJinglePayloadType()
+ : m_channels(1),
+ m_clockrate(0),
+ m_id(0),
+ m_maxptime(0),
+ m_ptime(0)
+{
+}
+
+unsigned char QXmppJinglePayloadType::channels() const
+{
+ return m_channels;
+}
+
+void QXmppJinglePayloadType::setChannels(unsigned char channels)
+{
+ m_channels = channels;
+}
+
+unsigned int QXmppJinglePayloadType::clockrate() const
+{
+ return m_clockrate;
+}
+
+void QXmppJinglePayloadType::setClockrate(unsigned int clockrate)
+{
+ m_clockrate = clockrate;
+}
+
+unsigned char QXmppJinglePayloadType::id() const
+{
+ return m_id;
+}
+
+void QXmppJinglePayloadType::setId(unsigned char id)
+{
+ Q_ASSERT(id <= 127);
+ m_id = id;
+}
+
+unsigned int QXmppJinglePayloadType::maxptime() const
+{
+ return m_maxptime;
+}
+
+void QXmppJinglePayloadType::setMaxptime(unsigned int maxptime)
+{
+ m_maxptime = maxptime;
+}
+
+QString QXmppJinglePayloadType::name() const
+{
+ return m_name;
+}
+
+void QXmppJinglePayloadType::setName(const QString &name)
+{
+ m_name = name;
+}
+
+unsigned int QXmppJinglePayloadType::ptime() const
+{
+ return m_ptime ? m_ptime : 20;
+}
+
+void QXmppJinglePayloadType::setPtime(unsigned int ptime)
+{
+ m_ptime = ptime;
+}
+
+void QXmppJinglePayloadType::parse(const QDomElement &element)
+{
+ m_id = element.attribute("id").toInt();
+ m_name = element.attribute("name");
+ m_channels = element.attribute("channels").toInt();
+ if (!m_channels)
+ m_channels = 1;
+ m_clockrate = element.attribute("clockrate").toInt();
+ m_maxptime = element.attribute("maxptime").toInt();
+ m_ptime = element.attribute("ptime").toInt();
+}
+
+void QXmppJinglePayloadType::toXml(QXmlStreamWriter *writer) const
+{
+ writer->writeStartElement("payload-type");
+ helperToXmlAddAttribute(writer, "id", QString::number(m_id));
+ helperToXmlAddAttribute(writer, "name", m_name);
+ if (m_channels > 1)
+ helperToXmlAddAttribute(writer, "channels", QString::number(m_channels));
+ if (m_clockrate > 0)
+ helperToXmlAddAttribute(writer, "clockrate", QString::number(m_clockrate));
+ if (m_maxptime > 0)
+ helperToXmlAddAttribute(writer, "maxptime", QString::number(m_maxptime));
+ if (m_ptime > 0)
+ helperToXmlAddAttribute(writer, "ptime", QString::number(m_ptime));
+ writer->writeEndElement();
+}
+
+bool QXmppJinglePayloadType::operator==(const QXmppJinglePayloadType &other) const
+{
+ // FIXME : what to do with m_ptime and m_maxptime?
+ if (m_id <= 95)
+ return other.m_id == m_id && other.m_clockrate == m_clockrate;
+ else
+ return other.m_channels == m_channels &&
+ other.m_clockrate == m_clockrate &&
+ other.m_name.toLower() == m_name.toLower();
+}
diff --git a/source/QXmppJingleIq.h b/source/QXmppJingleIq.h
new file mode 100644
index 00000000..566d5b75
--- /dev/null
+++ b/source/QXmppJingleIq.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2010 Bolloré telecom
+ *
+ * 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 QXMPPJINGLEIQ_H
+#define QXMPPJINGLEIQ_H
+
+#include <QHostAddress>
+
+#include "QXmppIq.h"
+
+class QXmppJinglePayloadType
+{
+public:
+ QXmppJinglePayloadType();
+
+ unsigned char channels() const;
+ void setChannels(unsigned char channels);
+
+ unsigned int clockrate() const;
+ void setClockrate(unsigned int clockrate);
+
+ unsigned char id() const;
+ void setId(unsigned char id);
+
+ unsigned int maxptime() const;
+ void setMaxptime(unsigned int maxptime);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ unsigned int ptime() const;
+ void setPtime(unsigned int ptime);
+
+ void parse(const QDomElement &element);
+ void toXml(QXmlStreamWriter *writer) const;
+
+ bool operator==(const QXmppJinglePayloadType &other) const;
+
+private:
+ unsigned char m_channels;
+ unsigned int m_clockrate;
+ unsigned char m_id;
+ unsigned int m_maxptime;
+ QString m_name;
+ unsigned int m_ptime;
+};
+
+class QXmppJingleCandidate
+{
+public:
+ QXmppJingleCandidate();
+
+ int component() const;
+ void setComponent(int component);
+
+ int foundation() const;
+ void setFoundation(int foundation);
+
+ QHostAddress host() const;
+ void setHost(const QHostAddress &host);
+
+ QString id() const;
+ void setId(const QString &id);
+
+ int network() const;
+ void setNetwork(int network);
+
+ quint16 port() const;
+ void setPort(quint16 port);
+
+ int priority() const;
+ void setPriority(int priority);
+
+ QString protocol() const;
+ void setProtocol(const QString &protocol);
+
+ QString type() const;
+ void setType(const QString &type);
+
+ void parse(const QDomElement &element);
+ void toXml(QXmlStreamWriter *writer) const;
+
+private:
+ int m_component;
+ int m_foundation;
+ int m_generation;
+ QHostAddress m_host;
+ QString m_id;
+ int m_network;
+ quint16 m_port;
+ QString m_protocol;
+ int m_priority;
+ QString m_type;
+};
+
+class QXmppJingleIq : public QXmppIq
+{
+public:
+ enum Action {
+ ContentAccept,
+ ContentAdd,
+ ContentModify,
+ ContentReject,
+ ContentRemove,
+ DescriptionInfo,
+ SecurityInfo,
+ SessionAccept,
+ SessionInfo,
+ SessionInitiate,
+ SessionTerminate,
+ TransportAccept,
+ TransportInfo,
+ TransportReject,
+ TransportReplace,
+ };
+
+ class Content
+ {
+ public:
+ Content();
+
+ QString creator() const;
+ void setCreator(const QString &creator);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString senders() const;
+ void setSenders(const QString &senders);
+
+ // XEP-0167: Jingle RTP Sessions
+ QString descriptionMedia() const;
+ void setDescriptionMedia(const QString &media);
+
+ void addPayloadType(const QXmppJinglePayloadType &payload);
+ QList<QXmppJinglePayloadType> payloadTypes() const;
+ void setPayloadTypes(const QList<QXmppJinglePayloadType> &payloadTypes);
+
+ void addTransportCandidate(const QXmppJingleCandidate &candidate);
+ QList<QXmppJingleCandidate> transportCandidates() const;
+
+ QString transportUser() const;
+ void setTransportUser(const QString &user);
+
+ QString transportPassword() const;
+ void setTransportPassword(const QString &password);
+
+ void parse(const QDomElement &element);
+ void toXml(QXmlStreamWriter *writer) const;
+
+ private:
+ QString m_creator;
+ QString m_disposition;
+ QString m_name;
+ QString m_senders;
+
+ QString m_descriptionMedia;
+ QString m_descriptionType;
+ QString m_transportType;
+ QString m_transportUser;
+ QString m_transportPassword;
+ QList<QXmppJinglePayloadType> m_payloadTypes;
+ QList<QXmppJingleCandidate> m_transportCandidates;
+ };
+
+ class Reason
+ {
+ public:
+ enum Type {
+ None,
+ AlternativeSession,
+ Busy,
+ Cancel,
+ ConnectivityError,
+ Decline,
+ Expired,
+ FailedApplication,
+ FailedTransport,
+ GeneralError,
+ Gone,
+ IncompatibleParameters,
+ MediaError,
+ SecurityError,
+ Success,
+ Timeout,
+ UnsupportedApplications,
+ UnsupportedTransports,
+ };
+
+ Reason();
+
+ QString text() const;
+ void setText(const QString &text);
+
+ Type type() const;
+ void setType(Type type);
+
+ void parse(const QDomElement &element);
+ void toXml(QXmlStreamWriter *writer) const;
+
+ private:
+ QString m_text;
+ Type m_type;
+ };
+
+ QXmppJingleIq();
+
+ Action action() const;
+ void setAction(Action action);
+
+ QString initiator() const;
+ void setInitiator(const QString &initiator);
+
+ QString responder() const;
+ void setResponder(const QString &responder);
+
+ QString sid() const;
+ void setSid(const QString &sid);
+
+ Content& content() { return m_content; };
+ const Content& content() const { return m_content; };
+
+ Reason& reason() { return m_reason; };
+ const Reason& reason() const { return m_reason; };
+
+ // XEP-0167: Jingle RTP Sessions
+ bool ringing() const;
+ void setRinging(bool ringing);
+
+ static bool isJingleIq(const QDomElement &element);
+
+protected:
+ void parseElementFromChild(const QDomElement &element);
+ void toXmlElementFromChild(QXmlStreamWriter *writer) const;
+
+private:
+ Action m_action;
+ QString m_initiator;
+ QString m_responder;
+ QString m_sid;
+
+ Content m_content;
+ Reason m_reason;
+ bool m_ringing;
+};
+
+#endif
diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp
index 5be25d5a..fc8f6f4e 100644
--- a/source/QXmppStream.cpp
+++ b/source/QXmppStream.cpp
@@ -39,6 +39,7 @@
#include "QXmppByteStreamIq.h"
#include "QXmppDiscoveryIq.h"
#include "QXmppIbbIq.h"
+#include "QXmppJingleIq.h"
#include "QXmppMucIq.h"
#include "QXmppPingIq.h"
#include "QXmppRpcIq.h"
@@ -674,6 +675,13 @@ void QXmppStream::parser(const QByteArray& data)
archiveIq.parse(nodeRecv);
emit archivePrefIqReceived(archiveIq);
}
+ // XEP-0166: Jingle
+ else if(QXmppJingleIq::isJingleIq(nodeRecv))
+ {
+ QXmppJingleIq jingleIq;
+ jingleIq.parse(nodeRecv);
+ emit jingleIqReceived(jingleIq);
+ }
// XEP-0199: XMPP Ping
else if(QXmppPingIq::isPingIq(nodeRecv))
{
@@ -1065,6 +1073,10 @@ QXmppDiscoveryIq QXmppStream::capabilities() const
<< ns_stream_initiation // XEP-0095: Stream Initiation
<< ns_stream_initiation_file_transfer // XEP-0096: SI File Transfer
<< ns_capabilities // XEP-0115 : Entity Capabilities
+ << ns_jingle // XEP-0166 : Jingle
+ << ns_jingle_rtp // XEP-0167 : Jingle RTP Sessions
+ << ns_jingle_rtp_audio
+ << ns_jingle_ice_udp // XEP-0176 : Jingle ICE-UDP Transport Method
<< ns_ping; // XEP-0199: XMPP Ping
iq.setFeatures(features);
diff --git a/source/QXmppStream.h b/source/QXmppStream.h
index acfcf1b4..419bcb1c 100644
--- a/source/QXmppStream.h
+++ b/source/QXmppStream.h
@@ -53,6 +53,7 @@ class QXmppDiscoveryIq;
class QXmppIbbCloseIq;
class QXmppIbbDataIq;
class QXmppIbbOpenIq;
+class QXmppJingleIq;
class QXmppMucAdminIq;
class QXmppMucOwnerIq;
class QXmppStreamInitiationIq;
@@ -126,6 +127,9 @@ signals:
void mucAdminIqReceived(const QXmppMucAdminIq&);
void mucOwnerIqReceived(const QXmppMucOwnerIq&);
+ // XEP-0166: Jingle
+ void jingleIqReceived(const QXmppJingleIq&);
+
private slots:
void socketHostFound();
void socketReadReady();
diff --git a/source/source.pro b/source/source.pro
index d792353d..31fc0431 100644
--- a/source/source.pro
+++ b/source/source.pro
@@ -31,6 +31,7 @@ HEADERS += QXmppUtils.h \
QXmppIbbIq.h \
QXmppInvokable.h \
QXmppIq.h \
+ QXmppJingleIq.h \
QXmppLogger.h \
QXmppMessage.h \
QXmppMucIq.h \
@@ -70,6 +71,7 @@ SOURCES += QXmppUtils.cpp \
QXmppIbbIq.cpp \
QXmppInvokable.cpp \
QXmppIq.cpp \
+ QXmppJingleIq.cpp \
QXmppLogger.cpp \
QXmppMessage.cpp \
QXmppMucIq.cpp \