aboutsummaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2015-09-03 16:34:36 +0200
committerJeremy Lainé <jeremy.laine@m4x.org>2015-09-03 16:34:36 +0200
commitcb16b3abb805c02c103237155e2ee624325f5dd6 (patch)
tree4e52159289e6048f07b5d079ef2eaa70e2e2f73e /src/base
parentaa3e0a2d41f25b05aef08df3d8b8cf698e9045c8 (diff)
parenta159e4c4afc62628ec5b753829e1a023b6ae5dea (diff)
downloadqxmpp-cb16b3abb805c02c103237155e2ee624325f5dd6.tar.gz
Merge branch 'master' of github.com:qxmpp-project/qxmpp
Diffstat (limited to 'src/base')
-rw-r--r--src/base/QXmppCodec.cpp11
-rw-r--r--src/base/QXmppGlobal.h2
-rw-r--r--src/base/QXmppJingleIq.cpp486
-rw-r--r--src/base/QXmppJingleIq.h71
-rw-r--r--src/base/QXmppStun.cpp77
-rw-r--r--src/base/QXmppStun.h19
6 files changed, 483 insertions, 183 deletions
diff --git a/src/base/QXmppCodec.cpp b/src/base/QXmppCodec.cpp
index 328fd043..98b6934a 100644
--- a/src/base/QXmppCodec.cpp
+++ b/src/base/QXmppCodec.cpp
@@ -1218,11 +1218,11 @@ QList<QXmppVideoFrame> QXmppVpxDecoder::handlePacket(const QXmppRtpPacket &packe
if (frag_type == NoFragment) {
// unfragmented packet
if ((payload[1] & 0x1) == 0 // is key frame
- || packet.sequence == sequence) {
+ || packet.sequence() == sequence) {
if (d->decodeFrame(payload.mid(1), &frame))
frames << frame;
- sequence = packet.sequence + 1;
+ sequence = packet.sequence() + 1;
}
d->packetBuffer.resize(0);
@@ -1231,13 +1231,13 @@ QList<QXmppVideoFrame> QXmppVpxDecoder::handlePacket(const QXmppRtpPacket &packe
if (frag_type == StartFragment) {
// start fragment
if ((payload[1] & 0x1) == 0 // is key frame
- || packet.sequence == sequence) {
+ || packet.sequence() == sequence) {
d->packetBuffer = payload.mid(1);
- sequence = packet.sequence + 1;
+ sequence = packet.sequence() + 1;
}
} else {
// continuation or end fragment
- if (packet.sequence == sequence) {
+ if (packet.sequence() == sequence) {
const int packetPos = d->packetBuffer.size();
d->packetBuffer.resize(packetPos + packetLength);
stream.readRawData(d->packetBuffer.data() + packetPos, packetLength);
@@ -1260,6 +1260,7 @@ QList<QXmppVideoFrame> QXmppVpxDecoder::handlePacket(const QXmppRtpPacket &packe
bool QXmppVpxDecoder::setParameters(const QMap<QString, QString> &parameters)
{
+ Q_UNUSED(parameters);
return true;
}
diff --git a/src/base/QXmppGlobal.h b/src/base/QXmppGlobal.h
index 1d4047ba..01826e44 100644
--- a/src/base/QXmppGlobal.h
+++ b/src/base/QXmppGlobal.h
@@ -52,7 +52,7 @@
/// available.
///
-#define QXMPP_VERSION 0x000900
+#define QXMPP_VERSION 0x000902
QXMPP_EXPORT QString QXmppVersion();
diff --git a/src/base/QXmppJingleIq.cpp b/src/base/QXmppJingleIq.cpp
index 26799054..899509e7 100644
--- a/src/base/QXmppJingleIq.cpp
+++ b/src/base/QXmppJingleIq.cpp
@@ -175,16 +175,32 @@ QXmppJingleIqContentPrivate::QXmppJingleIqContentPrivate()
{
}
+/// Constructs an empty content.
+
QXmppJingleIq::Content::Content()
: d(new QXmppJingleIqContentPrivate())
{
}
+/// Constructs a copy of other.
+///
+/// \param other
+
QXmppJingleIq::Content::Content(const QXmppJingleIq::Content &other)
: d(other.d)
{
}
+/// Assigns the other content to this one.
+///
+/// \param other
+
+QXmppJingleIq::Content& QXmppJingleIq::Content::operator=(const QXmppJingleIq::Content& other)
+{
+ d = other.d;
+ return *this;
+}
+
QXmppJingleIq::Content::~Content()
{
}
@@ -267,6 +283,12 @@ QList<QXmppJingleCandidate> QXmppJingleIq::Content::transportCandidates() const
return d->transportCandidates;
}
+void QXmppJingleIq::Content::setTransportCandidates(const QList<QXmppJingleCandidate> &candidates)
+{
+ d->transportType = candidates.isEmpty() ? QString() : ns_jingle_ice_udp;
+ d->transportCandidates = candidates;
+}
+
QString QXmppJingleIq::Content::transportUser() const
{
return d->transportUser;
@@ -436,7 +458,10 @@ void QXmppJingleIq::Content::toXml(QXmlStreamWriter *writer) const
bool QXmppJingleIq::Content::parseSdp(const QString &sdp)
{
QList<QXmppJinglePayloadType> payloads;
- foreach (const QString &line, sdp.split("\r\n")) {
+ QString line;
+ foreach (line, sdp.split('\n')) {
+ if (line.endsWith('\r'))
+ line.resize(line.size() - 1);
if (line.startsWith("a=")) {
int idx = line.indexOf(':');
const QString attrName = idx != -1 ? line.mid(2, idx - 2) : line.mid(2);
@@ -537,12 +562,22 @@ bool QXmppJingleIq::Content::parseSdp(const QString &sdp)
return true;
}
+static bool candidateLessThan(const QXmppJingleCandidate &c1, const QXmppJingleCandidate &c2)
+{
+ if (c1.type() == c2.type())
+ return c1.priority() > c2.priority();
+ else
+ return c1.type() == QXmppJingleCandidate::ServerReflexiveType;
+}
+
QString QXmppJingleIq::Content::toSdp() const
{
// get default candidate
QHostAddress localRtpAddress = QHostAddress::Any;
quint16 localRtpPort = 0;
- foreach (const QXmppJingleCandidate &candidate, d->transportCandidates) {
+ QList<QXmppJingleCandidate> sortedCandidates = d->transportCandidates;
+ qSort(sortedCandidates.begin(), sortedCandidates.end(), candidateLessThan);
+ foreach (const QXmppJingleCandidate &candidate, sortedCandidates) {
if (candidate.component() == RTP_COMPONENT) {
localRtpAddress = candidate.host();
localRtpPort = candidate.port();
@@ -597,7 +632,6 @@ QString QXmppJingleIq::Content::toSdp() const
return sdp.join("\r\n") + "\r\n";
}
-
/// \endcond
QXmppJingleIq::Reason::Reason()
@@ -605,21 +639,29 @@ QXmppJingleIq::Reason::Reason()
{
}
+/// Returns the reason's textual description.
+
QString QXmppJingleIq::Reason::text() const
{
return m_text;
}
+/// Sets the reason's textual description.
+
void QXmppJingleIq::Reason::setText(const QString &text)
{
m_text = text;
}
+/// Gets the reason's type.
+
QXmppJingleIq::Reason::Type QXmppJingleIq::Reason::type() const
{
return m_type;
}
+/// Sets the reason's type.
+
void QXmppJingleIq::Reason::setType(QXmppJingleIq::Reason::Type type)
{
m_type = type;
@@ -652,18 +694,62 @@ void QXmppJingleIq::Reason::toXml(QXmlStreamWriter *writer) const
}
/// \endcond
+class QXmppJingleIqPrivate : public QSharedData
+{
+public:
+ QXmppJingleIqPrivate();
+
+ QXmppJingleIq::Action action;
+ QString initiator;
+ QString responder;
+ QString sid;
+
+ QList<QXmppJingleIq::Content> contents;
+ QXmppJingleIq::Reason reason;
+ bool ringing;
+};
+
+QXmppJingleIqPrivate::QXmppJingleIqPrivate()
+ : ringing(false)
+{
+}
+
/// Constructs a QXmppJingleIq.
QXmppJingleIq::QXmppJingleIq()
- : m_ringing(false)
+ : d(new QXmppJingleIqPrivate())
+{
+}
+
+/// Constructs a copy of other.
+///
+/// \param other
+
+QXmppJingleIq::QXmppJingleIq(const QXmppJingleIq &other)
+ : QXmppIq(other)
+ , d(other.d)
{
}
+QXmppJingleIq::~QXmppJingleIq()
+{
+}
+
+/// Assigns the other Jingle IQ to this one.
+///
+/// \param other
+
+QXmppJingleIq& QXmppJingleIq::operator=(const QXmppJingleIq& other)
+{
+ d = other.d;
+ return *this;
+}
+
/// Returns the Jingle IQ's action.
QXmppJingleIq::Action QXmppJingleIq::action() const
{
- return m_action;
+ return d->action;
}
/// Sets the Jingle IQ's action.
@@ -672,14 +758,35 @@ QXmppJingleIq::Action QXmppJingleIq::action() const
void QXmppJingleIq::setAction(QXmppJingleIq::Action action)
{
- m_action = action;
+ d->action = action;
+}
+
+/// Adds an element to the IQ's content elements.
+
+void QXmppJingleIq::addContent(const QXmppJingleIq::Content &content)
+{
+ d->contents << content;
+}
+
+/// Returns the IQ's content elements.
+
+QList<QXmppJingleIq::Content> QXmppJingleIq::contents() const
+{
+ return d->contents;
+}
+
+/// Sets the IQ's content elements.
+
+void QXmppJingleIq::setContents(const QList<QXmppJingleIq::Content> &contents)
+{
+ d->contents = contents;
}
/// Returns the session initiator.
QString QXmppJingleIq::initiator() const
{
- return m_initiator;
+ return d->initiator;
}
/// Sets the session initiator.
@@ -688,14 +795,28 @@ QString QXmppJingleIq::initiator() const
void QXmppJingleIq::setInitiator(const QString &initiator)
{
- m_initiator = initiator;
+ d->initiator = initiator;
+}
+
+/// Returns a reference to the IQ's reason element.
+
+QXmppJingleIq::Reason& QXmppJingleIq::reason()
+{
+ return d->reason;
+}
+
+/// Returns a const reference to the IQ's reason element.
+
+const QXmppJingleIq::Reason& QXmppJingleIq::reason() const
+{
+ return d->reason;
}
/// Returns the session responder.
QString QXmppJingleIq::responder() const
{
- return m_responder;
+ return d->responder;
}
/// Sets the session responder.
@@ -704,39 +825,39 @@ QString QXmppJingleIq::responder() const
void QXmppJingleIq::setResponder(const QString &responder)
{
- m_responder = responder;
+ d->responder = responder;
}
-/// Returns the session ID.
+/// Returns true if the call is ringing.
-QString QXmppJingleIq::sid() const
+bool QXmppJingleIq::ringing() const
{
- return m_sid;
+ return d->ringing;
}
-/// Sets the session ID.
+/// Set to true if the call is ringing.
///
-/// \param sid
+/// \param ringing
-void QXmppJingleIq::setSid(const QString &sid)
+void QXmppJingleIq::setRinging(bool ringing)
{
- m_sid = sid;
+ d->ringing = ringing;
}
-/// Returns true if the call is ringing.
+/// Returns the session ID.
-bool QXmppJingleIq::ringing() const
+QString QXmppJingleIq::sid() const
{
- return m_ringing;
+ return d->sid;
}
-/// Set to true if the call is ringing.
+/// Sets the session ID.
///
-/// \param ringing
+/// \param sid
-void QXmppJingleIq::setRinging(bool ringing)
+void QXmppJingleIq::setSid(const QString &sid)
{
- m_ringing = ringing;
+ d->sid = sid;
}
/// \cond
@@ -750,43 +871,47 @@ 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);
+ for (int i = ContentAccept; i <= TransportReplace; i++) {
+ if (action == jingle_actions[i]) {
+ d->action = static_cast<Action>(i);
break;
}
}
- m_initiator = jingleElement.attribute("initiator");
- m_responder = jingleElement.attribute("responder");
- m_sid = jingleElement.attribute("sid");
+ d->initiator = jingleElement.attribute("initiator");
+ d->responder = jingleElement.attribute("responder");
+ d->sid = jingleElement.attribute("sid");
// content
+ d->contents.clear();
QDomElement contentElement = jingleElement.firstChildElement("content");
- m_content.parse(contentElement);
+ while (!contentElement.isNull()) {
+ QXmppJingleIq::Content content;
+ content.parse(contentElement);
+ addContent(content);
+ contentElement = contentElement.nextSiblingElement("content");
+ }
QDomElement reasonElement = jingleElement.firstChildElement("reason");
- m_reason.parse(reasonElement);
+ d->reason.parse(reasonElement);
// ringing
QDomElement ringingElement = jingleElement.firstChildElement("ringing");
- m_ringing = (ringingElement.namespaceURI() == ns_jingle_rtp_info);
+ d->ringing = (ringingElement.namespaceURI() == ns_jingle_rtp_info);
}
void QXmppJingleIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
{
writer->writeStartElement("jingle");
writer->writeAttribute("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);
+ helperToXmlAddAttribute(writer, "action", jingle_actions[d->action]);
+ helperToXmlAddAttribute(writer, "initiator", d->initiator);
+ helperToXmlAddAttribute(writer, "responder", d->responder);
+ helperToXmlAddAttribute(writer, "sid", d->sid);
+ foreach (const QXmppJingleIq::Content &content, d->contents)
+ content.toXml(writer);
+ d->reason.toXml(writer);
// ringing
- if (m_ringing)
- {
+ if (d->ringing) {
writer->writeStartElement("ringing");
writer->writeAttribute("xmlns", ns_jingle_rtp_info);
writer->writeEndElement();
@@ -796,21 +921,68 @@ void QXmppJingleIq::toXmlElementFromChild(QXmlStreamWriter *writer) const
}
/// \endcond
+class QXmppJingleCandidatePrivate : public QSharedData
+{
+public:
+ QXmppJingleCandidatePrivate();
+
+ int component;
+ QString foundation;
+ int generation;
+ QHostAddress host;
+ QString id;
+ int network;
+ quint16 port;
+ QString protocol;
+ int priority;
+ QXmppJingleCandidate::Type type;
+};
+
+QXmppJingleCandidatePrivate::QXmppJingleCandidatePrivate()
+ : component(0)
+ , generation(0)
+ , network(0)
+ , port(0)
+ , priority(0)
+ , type(QXmppJingleCandidate::HostType)
+{
+}
+
+/// Constructs an empty candidate.
+
QXmppJingleCandidate::QXmppJingleCandidate()
- : m_component(0),
- m_generation(0),
- m_network(0),
- m_port(0),
- m_priority(0),
- m_type(HostType)
+ : d(new QXmppJingleCandidatePrivate())
+{
+}
+
+/// Constructs a copy of other.
+///
+/// \param other
+
+QXmppJingleCandidate::QXmppJingleCandidate(const QXmppJingleCandidate &other)
+ : d(other.d)
{
}
+QXmppJingleCandidate::~QXmppJingleCandidate()
+{
+}
+
+/// Assigns the other candidate to this one.
+///
+/// \param other
+
+QXmppJingleCandidate& QXmppJingleCandidate::operator=(const QXmppJingleCandidate& other)
+{
+ d = other.d;
+ return *this;
+}
+
/// Returns the candidate's component ID.
int QXmppJingleCandidate::component() const
{
- return m_component;
+ return d->component;
}
/// Sets the candidates's component ID.
@@ -819,14 +991,14 @@ int QXmppJingleCandidate::component() const
void QXmppJingleCandidate::setComponent(int component)
{
- m_component = component;
+ d->component = component;
}
/// Returns the candidate's foundation.
QString QXmppJingleCandidate::foundation() const
{
- return m_foundation;
+ return d->foundation;
}
/// Sets the candidate's foundation.
@@ -835,14 +1007,14 @@ QString QXmppJingleCandidate::foundation() const
void QXmppJingleCandidate::setFoundation(const QString &foundation)
{
- m_foundation = foundation;
+ d->foundation = foundation;
}
/// Returns the candidate's generation.
int QXmppJingleCandidate::generation() const
{
- return m_generation;
+ return d->generation;
}
/// Sets the candidate's generation.
@@ -851,7 +1023,7 @@ int QXmppJingleCandidate::generation() const
void QXmppJingleCandidate::setGeneration(int generation)
{
- m_generation = generation;
+ d->generation = generation;
}
/// Returns the candidate's host address.
@@ -859,7 +1031,7 @@ void QXmppJingleCandidate::setGeneration(int generation)
QHostAddress QXmppJingleCandidate::host() const
{
- return m_host;
+ return d->host;
}
/// Sets the candidate's host address.
@@ -868,7 +1040,7 @@ QHostAddress QXmppJingleCandidate::host() const
void QXmppJingleCandidate::setHost(const QHostAddress &host)
{
- m_host = host;
+ d->host = host;
}
/// Returns the candidate's unique identifier.
@@ -876,7 +1048,7 @@ void QXmppJingleCandidate::setHost(const QHostAddress &host)
QString QXmppJingleCandidate::id() const
{
- return m_id;
+ return d->id;
}
/// Sets the candidate's unique identifier.
@@ -885,7 +1057,7 @@ QString QXmppJingleCandidate::id() const
void QXmppJingleCandidate::setId(const QString &id)
{
- m_id = id;
+ d->id = id;
}
/// Returns the network index (starting at 0) the candidate is on.
@@ -893,7 +1065,7 @@ void QXmppJingleCandidate::setId(const QString &id)
int QXmppJingleCandidate::network() const
{
- return m_network;
+ return d->network;
}
/// Sets the network index (starting at 0) the candidate is on.
@@ -902,7 +1074,7 @@ int QXmppJingleCandidate::network() const
void QXmppJingleCandidate::setNetwork(int network)
{
- m_network = network;
+ d->network = network;
}
/// Returns the candidate's port number.
@@ -910,7 +1082,7 @@ void QXmppJingleCandidate::setNetwork(int network)
quint16 QXmppJingleCandidate::port() const
{
- return m_port;
+ return d->port;
}
/// Sets the candidate's port number.
@@ -919,7 +1091,7 @@ quint16 QXmppJingleCandidate::port() const
void QXmppJingleCandidate::setPort(quint16 port)
{
- m_port = port;
+ d->port = port;
}
/// Returns the candidate's priority.
@@ -927,7 +1099,7 @@ void QXmppJingleCandidate::setPort(quint16 port)
int QXmppJingleCandidate::priority() const
{
- return m_priority;
+ return d->priority;
}
/// Sets the candidate's priority.
@@ -936,7 +1108,7 @@ int QXmppJingleCandidate::priority() const
void QXmppJingleCandidate::setPriority(int priority)
{
- m_priority = priority;
+ d->priority = priority;
}
/// Returns the candidate's protocol (e.g. "udp").
@@ -944,7 +1116,7 @@ void QXmppJingleCandidate::setPriority(int priority)
QString QXmppJingleCandidate::protocol() const
{
- return m_protocol;
+ return d->protocol;
}
/// Sets the candidate's protocol (e.g. "udp").
@@ -953,7 +1125,7 @@ QString QXmppJingleCandidate::protocol() const
void QXmppJingleCandidate::setProtocol(const QString &protocol)
{
- m_protocol = protocol;
+ d->protocol = protocol;
}
/// Returns the candidate type (e.g. "host").
@@ -961,7 +1133,7 @@ void QXmppJingleCandidate::setProtocol(const QString &protocol)
QXmppJingleCandidate::Type QXmppJingleCandidate::type() const
{
- return m_type;
+ return d->type;
}
/// Sets the candidate type (e.g. "host").
@@ -970,7 +1142,7 @@ QXmppJingleCandidate::Type QXmppJingleCandidate::type() const
void QXmppJingleCandidate::setType(QXmppJingleCandidate::Type type)
{
- m_type = type;
+ d->type = type;
}
/// Returns true if the host address or port are empty.
@@ -978,37 +1150,37 @@ void QXmppJingleCandidate::setType(QXmppJingleCandidate::Type type)
bool QXmppJingleCandidate::isNull() const
{
- return m_host.isNull() || !m_port;
+ return d->host.isNull() || !d->port;
}
/// \cond
void QXmppJingleCandidate::parse(const QDomElement &element)
{
- m_component = element.attribute("component").toInt();
- m_foundation = element.attribute("foundation");
- 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 = typeFromString(element.attribute("type"));
+ d->component = element.attribute("component").toInt();
+ d->foundation = element.attribute("foundation");
+ d->generation = element.attribute("generation").toInt();
+ d->host = QHostAddress(element.attribute("ip"));
+ d->id = element.attribute("id");
+ d->network = element.attribute("network").toInt();
+ d->port = element.attribute("port").toInt();
+ d->priority = element.attribute("priority").toInt();
+ d->protocol = element.attribute("protocol");
+ d->type = typeFromString(element.attribute("type"));
}
void QXmppJingleCandidate::toXml(QXmlStreamWriter *writer) const
{
writer->writeStartElement("candidate");
- helperToXmlAddAttribute(writer, "component", QString::number(m_component));
- helperToXmlAddAttribute(writer, "foundation", 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", typeToString(m_type));
+ helperToXmlAddAttribute(writer, "component", QString::number(d->component));
+ helperToXmlAddAttribute(writer, "foundation", d->foundation);
+ helperToXmlAddAttribute(writer, "generation", QString::number(d->generation));
+ helperToXmlAddAttribute(writer, "id", d->id);
+ helperToXmlAddAttribute(writer, "ip", d->host.toString());
+ helperToXmlAddAttribute(writer, "network", QString::number(d->network));
+ helperToXmlAddAttribute(writer, "port", QString::number(d->port));
+ helperToXmlAddAttribute(writer, "priority", QString::number(d->priority));
+ helperToXmlAddAttribute(writer, "protocol", d->protocol);
+ helperToXmlAddAttribute(writer, "type", typeToString(d->type));
writer->writeEndElement();
}
@@ -1056,12 +1228,44 @@ QString QXmppJingleCandidate::typeToString(QXmppJingleCandidate::Type type)
}
/// \endcond
+class QXmppJinglePayloadTypePrivate : public QSharedData
+{
+public:
+ QXmppJinglePayloadTypePrivate();
+
+ unsigned char channels;
+ unsigned int clockrate;
+ unsigned char id;
+ unsigned int maxptime;
+ QString name;
+ QMap<QString, QString> parameters;
+ unsigned int ptime;
+};
+
+QXmppJinglePayloadTypePrivate::QXmppJinglePayloadTypePrivate()
+ : channels(1)
+ , clockrate(0)
+ , id(0)
+ , maxptime(0)
+ , ptime(0)
+{
+}
+
QXmppJinglePayloadType::QXmppJinglePayloadType()
- : m_channels(1),
- m_clockrate(0),
- m_id(0),
- m_maxptime(0),
- m_ptime(0)
+ : d(new QXmppJinglePayloadTypePrivate())
+{
+}
+
+/// Constructs a copy of other.
+///
+/// \param other
+
+QXmppJinglePayloadType::QXmppJinglePayloadType(const QXmppJinglePayloadType &other)
+ : d(other.d)
+{
+}
+
+QXmppJinglePayloadType::~QXmppJinglePayloadType()
{
}
@@ -1070,7 +1274,7 @@ QXmppJinglePayloadType::QXmppJinglePayloadType()
unsigned char QXmppJinglePayloadType::channels() const
{
- return m_channels;
+ return d->channels;
}
/// Sets the number of channels (e.g. 1 for mono, 2 for stereo).
@@ -1079,7 +1283,7 @@ unsigned char QXmppJinglePayloadType::channels() const
void QXmppJinglePayloadType::setChannels(unsigned char channels)
{
- m_channels = channels;
+ d->channels = channels;
}
/// Returns the clockrate in Hz, i.e. the number of samples per second.
@@ -1087,7 +1291,7 @@ void QXmppJinglePayloadType::setChannels(unsigned char channels)
unsigned int QXmppJinglePayloadType::clockrate() const
{
- return m_clockrate;
+ return d->clockrate;
}
/// Sets the clockrate in Hz, i.e. the number of samples per second.
@@ -1096,7 +1300,7 @@ unsigned int QXmppJinglePayloadType::clockrate() const
void QXmppJinglePayloadType::setClockrate(unsigned int clockrate)
{
- m_clockrate = clockrate;
+ d->clockrate = clockrate;
}
/// Returns the payload type identifier.
@@ -1104,7 +1308,7 @@ void QXmppJinglePayloadType::setClockrate(unsigned int clockrate)
unsigned char QXmppJinglePayloadType::id() const
{
- return m_id;
+ return d->id;
}
/// Sets the payload type identifier.
@@ -1113,7 +1317,7 @@ unsigned char QXmppJinglePayloadType::id() const
void QXmppJinglePayloadType::setId(unsigned char id)
{
Q_ASSERT(id <= 127);
- m_id = id;
+ d->id = id;
}
/// Returns the maximum packet time in milliseconds.
@@ -1121,7 +1325,7 @@ void QXmppJinglePayloadType::setId(unsigned char id)
unsigned int QXmppJinglePayloadType::maxptime() const
{
- return m_maxptime;
+ return d->maxptime;
}
/// Sets the maximum packet type in milliseconds.
@@ -1130,7 +1334,7 @@ unsigned int QXmppJinglePayloadType::maxptime() const
void QXmppJinglePayloadType::setMaxptime(unsigned int maxptime)
{
- m_maxptime = maxptime;
+ d->maxptime = maxptime;
}
/// Returns the payload type name.
@@ -1138,7 +1342,7 @@ void QXmppJinglePayloadType::setMaxptime(unsigned int maxptime)
QString QXmppJinglePayloadType::name() const
{
- return m_name;
+ return d->name;
}
/// Sets the payload type name.
@@ -1147,21 +1351,21 @@ QString QXmppJinglePayloadType::name() const
void QXmppJinglePayloadType::setName(const QString &name)
{
- m_name = name;
+ d->name = name;
}
/// Returns the payload parameters.
QMap<QString,QString> QXmppJinglePayloadType::parameters() const
{
- return m_parameters;
+ return d->parameters;
}
/// Sets the payload parameters.
void QXmppJinglePayloadType::setParameters(const QMap<QString, QString> &parameters)
{
- m_parameters = parameters;
+ d->parameters = parameters;
}
/// Returns the packet time in milliseconds (20 by default).
@@ -1169,7 +1373,7 @@ void QXmppJinglePayloadType::setParameters(const QMap<QString, QString> &paramet
unsigned int QXmppJinglePayloadType::ptime() const
{
- return m_ptime ? m_ptime : 20;
+ return d->ptime ? d->ptime : 20;
}
/// Sets the packet time in milliseconds (20 by default).
@@ -1178,24 +1382,24 @@ unsigned int QXmppJinglePayloadType::ptime() const
void QXmppJinglePayloadType::setPtime(unsigned int ptime)
{
- m_ptime = ptime;
+ d->ptime = ptime;
}
/// \cond
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();
+ d->id = element.attribute("id").toInt();
+ d->name = element.attribute("name");
+ d->channels = element.attribute("channels").toInt();
+ if (!d->channels)
+ d->channels = 1;
+ d->clockrate = element.attribute("clockrate").toInt();
+ d->maxptime = element.attribute("maxptime").toInt();
+ d->ptime = element.attribute("ptime").toInt();
QDomElement child = element.firstChildElement("parameter");
while (!child.isNull()) {
- m_parameters.insert(child.attribute("name"), child.attribute("value"));
+ d->parameters.insert(child.attribute("name"), child.attribute("value"));
child = child.nextSiblingElement("parameter");
}
}
@@ -1203,27 +1407,37 @@ void QXmppJinglePayloadType::parse(const QDomElement &element)
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));
-
- foreach (const QString &key, m_parameters.keys()) {
+ helperToXmlAddAttribute(writer, "id", QString::number(d->id));
+ helperToXmlAddAttribute(writer, "name", d->name);
+ if (d->channels > 1)
+ helperToXmlAddAttribute(writer, "channels", QString::number(d->channels));
+ if (d->clockrate > 0)
+ helperToXmlAddAttribute(writer, "clockrate", QString::number(d->clockrate));
+ if (d->maxptime > 0)
+ helperToXmlAddAttribute(writer, "maxptime", QString::number(d->maxptime));
+ if (d->ptime > 0)
+ helperToXmlAddAttribute(writer, "ptime", QString::number(d->ptime));
+
+ foreach (const QString &key, d->parameters.keys()) {
writer->writeStartElement("parameter");
writer->writeAttribute("name", key);
- writer->writeAttribute("value", m_parameters.value(key));
+ writer->writeAttribute("value", d->parameters.value(key));
writer->writeEndElement();
}
writer->writeEndElement();
}
/// \endcond
+/// Assigns the other payload type to this one.
+///
+/// \param other
+
+QXmppJinglePayloadType& QXmppJinglePayloadType::operator=(const QXmppJinglePayloadType& other)
+{
+ d = other.d;
+ return *this;
+}
+
/// Returns true if this QXmppJinglePayloadType and \a other refer to the same payload type.
///
/// \param other
@@ -1231,10 +1445,10 @@ void QXmppJinglePayloadType::toXml(QXmlStreamWriter *writer) const
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;
+ if (d->id <= 95)
+ return other.d->id == d->id && other.d->clockrate == d->clockrate;
else
- return other.m_channels == m_channels &&
- other.m_clockrate == m_clockrate &&
- other.m_name.toLower() == m_name.toLower();
+ return other.d->channels == d->channels &&
+ other.d->clockrate == d->clockrate &&
+ other.d->name.toLower() == d->name.toLower();
}
diff --git a/src/base/QXmppJingleIq.h b/src/base/QXmppJingleIq.h
index 046b7c96..ba41dc8f 100644
--- a/src/base/QXmppJingleIq.h
+++ b/src/base/QXmppJingleIq.h
@@ -28,7 +28,10 @@
#include "QXmppIq.h"
+class QXmppJingleCandidatePrivate;
class QXmppJingleIqContentPrivate;
+class QXmppJingleIqPrivate;
+class QXmppJinglePayloadTypePrivate;
/// \brief The QXmppJinglePayloadType class represents a payload type
/// as specified by XEP-0167: Jingle RTP Sessions and RFC 5245.
@@ -38,6 +41,8 @@ class QXMPP_EXPORT QXmppJinglePayloadType
{
public:
QXmppJinglePayloadType();
+ QXmppJinglePayloadType(const QXmppJinglePayloadType &other);
+ ~QXmppJinglePayloadType();
unsigned char channels() const;
void setChannels(unsigned char channels);
@@ -65,16 +70,11 @@ public:
void toXml(QXmlStreamWriter *writer) const;
/// \endcond
+ QXmppJinglePayloadType& operator=(const QXmppJinglePayloadType &other);
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;
- QMap<QString, QString> m_parameters;
- unsigned int m_ptime;
+ QSharedDataPointer<QXmppJinglePayloadTypePrivate> d;
};
/// \brief The QXmppJingleCandidate class represents a transport candidate
@@ -97,6 +97,10 @@ public:
};
QXmppJingleCandidate();
+ QXmppJingleCandidate(const QXmppJingleCandidate &other);
+ ~QXmppJingleCandidate();
+
+ QXmppJingleCandidate& operator=(const QXmppJingleCandidate &other);
int component() const;
void setComponent(int component);
@@ -139,16 +143,7 @@ public:
/// \endcond
private:
- int m_component;
- QString m_foundation;
- int m_generation;
- QHostAddress m_host;
- QString m_id;
- int m_network;
- quint16 m_port;
- QString m_protocol;
- int m_priority;
- QXmppJingleCandidate::Type m_type;
+ QSharedDataPointer<QXmppJingleCandidatePrivate> d;
};
/// \brief The QXmppJingleIq class represents an IQ used for initiating media
@@ -190,6 +185,8 @@ public:
Content(const QXmppJingleIq::Content &other);
~Content();
+ Content& operator=(const Content &other);
+
QString creator() const;
void setCreator(const QString &creator);
@@ -212,6 +209,7 @@ public:
void addTransportCandidate(const QXmppJingleCandidate &candidate);
QList<QXmppJingleCandidate> transportCandidates() const;
+ void setTransportCandidates(const QList<QXmppJingleCandidate> &candidates);
QString transportUser() const;
void setTransportUser(const QString &user);
@@ -249,6 +247,7 @@ public:
class QXMPP_EXPORT Reason
{
public:
+ /// This enum is used to describe a reason's type.
enum Type {
None,
AlternativeSession,
@@ -289,35 +288,34 @@ public:
};
QXmppJingleIq();
+ QXmppJingleIq(const QXmppJingleIq &other);
+ ~QXmppJingleIq();
+
+ QXmppJingleIq& operator=(const QXmppJingleIq &other);
Action action() const;
void setAction(Action action);
+ void addContent(const Content &content);
+ QList<Content> contents() const;
+ void setContents(const QList<Content> &contents);
+
QString initiator() const;
void setInitiator(const QString &initiator);
+ Reason& reason();
+ const Reason& reason() const;
+
QString responder() const;
void setResponder(const QString &responder);
- QString sid() const;
- void setSid(const QString &sid);
-
- /// Returns a reference to the IQ's content element.
- Content& content() { return m_content; };
-
- /// Returns a const reference to the IQ's content element.
- const Content& content() const { return m_content; };
-
- /// Returns a reference to the IQ's reason element.
- Reason& reason() { return m_reason; };
-
- /// Returns a const reference to the IQ's reason element.
- const Reason& reason() const { return m_reason; };
-
// XEP-0167: Jingle RTP Sessions
bool ringing() const;
void setRinging(bool ringing);
+ QString sid() const;
+ void setSid(const QString &sid);
+
/// \cond
static bool isJingleIq(const QDomElement &element);
/// \endcond
@@ -329,14 +327,7 @@ protected:
/// \endcond
private:
- Action m_action;
- QString m_initiator;
- QString m_responder;
- QString m_sid;
-
- Content m_content;
- Reason m_reason;
- bool m_ringing;
+ QSharedDataPointer<QXmppJingleIqPrivate> d;
};
#endif
diff --git a/src/base/QXmppStun.cpp b/src/base/QXmppStun.cpp
index 18a3342d..86d4004a 100644
--- a/src/base/QXmppStun.cpp
+++ b/src/base/QXmppStun.cpp
@@ -42,6 +42,12 @@ static const quint16 STUN_HEADER = 20;
static const quint8 STUN_IPV4 = 0x01;
static const quint8 STUN_IPV6 = 0x02;
+static const char* gathering_states[] = {
+ "new",
+ "gathering",
+ "complete"
+};
+
static const char* pair_states[] = {
"frozen",
"waiting",
@@ -1761,6 +1767,8 @@ public:
const QXmppIcePrivate* const config;
CandidatePair *fallbackPair;
+ QXmppIceConnection::GatheringState gatheringState;
+
QList<QXmppJingleCandidate> localCandidates;
quint32 peerReflexivePriority;
@@ -1786,6 +1794,7 @@ QXmppIceComponentPrivate::QXmppIceComponentPrivate(int component_, QXmppIcePriva
, component(component_)
, config(config_)
, fallbackPair(0)
+ , gatheringState(QXmppIceConnection::NewGatheringState)
, peerReflexivePriority(0)
, timer(0)
, turnAllocation(0)
@@ -1909,6 +1918,8 @@ void QXmppIceComponentPrivate::setSockets(QList<QUdpSocket*> sockets)
transports << turnAllocation;
turnAllocation->connectToHost();
}
+
+ q->updateGatheringState();
}
void QXmppIceComponentPrivate::setTurnServer(const QHostAddress &host, quint16 port)
@@ -1965,6 +1976,9 @@ QXmppIceComponent::QXmppIceComponent(int component, QXmppIcePrivate *config, QOb
check = connect(d->turnAllocation, SIGNAL(datagramReceived(QByteArray,QHostAddress,quint16)),
this, SLOT(handleDatagram(QByteArray,QHostAddress,quint16)));
Q_ASSERT(check);
+ check = connect(d->turnAllocation, SIGNAL(disconnected()),
+ this, SLOT(updateGatheringState()));
+ Q_ASSERT(check);
// calculate peer-reflexive candidate priority
// see RFC 5245 - 7.1.2.1. PRIORITY and USE-CANDIDATE
@@ -2313,6 +2327,7 @@ void QXmppIceComponent::transactionFinished()
transaction->response().errorPhrase));
}
d->stunTransactions.remove(transaction);
+ updateGatheringState();
return;
}
}
@@ -2328,6 +2343,7 @@ void QXmppIceComponent::turnConnected()
d->localCandidates << candidate;
emit localCandidatesChanged();
+ updateGatheringState();
}
static QList<QUdpSocket*> reservePort(const QList<QHostAddress> &addresses, quint16 port, QObject *parent)
@@ -2443,6 +2459,23 @@ qint64 QXmppIceComponent::sendDatagram(const QByteArray &datagram)
return pair->transport->writeDatagram(datagram, pair->remote.host(), pair->remote.port());
}
+void QXmppIceComponent::updateGatheringState()
+{
+ QXmppIceConnection::GatheringState newGatheringState;
+ if (d->transports.isEmpty())
+ newGatheringState = QXmppIceConnection::NewGatheringState;
+ else if (!d->stunTransactions.isEmpty()
+ || d->turnAllocation->state() == QXmppTurnAllocation::ConnectingState)
+ newGatheringState = QXmppIceConnection::BusyGatheringState;
+ else
+ newGatheringState = QXmppIceConnection::CompleteGatheringState;
+
+ if (newGatheringState != d->gatheringState) {
+ d->gatheringState = newGatheringState;
+ emit gatheringStateChanged();
+ }
+}
+
void QXmppIceComponent::writeStun(const QXmppStunMessage &message)
{
QXmppStunTransaction *transaction = qobject_cast<QXmppStunTransaction*>(sender());
@@ -2476,6 +2509,8 @@ public:
QMap<int, QXmppIceComponent*> components;
QTimer *connectTimer;
+ QXmppIceConnection::GatheringState gatheringState;
+
QHostAddress turnHost;
quint16 turnPort;
QString turnUser;
@@ -2483,7 +2518,8 @@ public:
};
QXmppIceConnectionPrivate::QXmppIceConnectionPrivate()
- : turnPort(0)
+ : gatheringState(QXmppIceConnection::NewGatheringState)
+ , turnPort(0)
{
}
@@ -2549,6 +2585,10 @@ void QXmppIceConnection::addComponent(int component)
this, SLOT(slotConnected()));
Q_ASSERT(check);
+ check = connect(socket, SIGNAL(gatheringStateChanged()),
+ this, SLOT(slotGatheringStateChanged()));
+ Q_ASSERT(check);
+
d->components[component] = socket;
}
@@ -2622,6 +2662,14 @@ bool QXmppIceConnection::isConnected() const
return true;
}
+/// Returns the ICE gathering state, that is the discovery of
+/// local candidates.
+
+QXmppIceConnection::GatheringState QXmppIceConnection::gatheringState() const
+{
+ return d->gatheringState;
+}
+
/// Sets whether the local party has the ICE controlling role.
///
/// \a note This must be called only once, immediately after creating
@@ -2740,6 +2788,33 @@ void QXmppIceConnection::slotConnected()
emit connected();
}
+void QXmppIceConnection::slotGatheringStateChanged()
+{
+ GatheringState newGatheringState;
+ bool allComplete = true;
+ bool allNew = true;
+ foreach (QXmppIceComponent *socket, d->components.values()) {
+ if (socket->d->gatheringState != CompleteGatheringState)
+ allComplete = false;
+ if (socket->d->gatheringState != NewGatheringState)
+ allNew = false;
+ }
+ if (allNew)
+ newGatheringState = NewGatheringState;
+ else if (allComplete)
+ newGatheringState = CompleteGatheringState;
+ else
+ newGatheringState = BusyGatheringState;
+
+ if (newGatheringState != d->gatheringState) {
+ info(QString("ICE gathering state changed from '%1' to '%2'").arg(
+ gathering_states[d->gatheringState],
+ gathering_states[newGatheringState]));
+ d->gatheringState = newGatheringState;
+ emit gatheringStateChanged();
+ }
+}
+
void QXmppIceConnection::slotTimeout()
{
warning(QString("ICE negotiation timed out"));
diff --git a/src/base/QXmppStun.h b/src/base/QXmppStun.h
index cc8b01c1..bd0868c0 100644
--- a/src/base/QXmppStun.h
+++ b/src/base/QXmppStun.h
@@ -186,6 +186,7 @@ private slots:
void handleDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port);
void turnConnected();
void transactionFinished();
+ void updateGatheringState();
void writeStun(const QXmppStunMessage &request);
signals:
@@ -195,6 +196,9 @@ signals:
/// \brief This signal is emitted when a data packet is received.
void datagramReceived(const QByteArray &datagram);
+ /// \internal This signal is emitted when the gathering state of local candidates changes.
+ void gatheringStateChanged();
+
/// \brief This signal is emitted when the list of local candidates changes.
void localCandidatesChanged();
@@ -237,8 +241,17 @@ private:
class QXMPP_EXPORT QXmppIceConnection : public QXmppLoggable
{
Q_OBJECT
+ Q_ENUMS(GatheringState)
+ Q_PROPERTY(QXmppIceConnection::GatheringState gatheringState READ gatheringState NOTIFY gatheringStateChanged)
public:
+ enum GatheringState
+ {
+ NewGatheringState,
+ BusyGatheringState,
+ CompleteGatheringState
+ };
+
QXmppIceConnection(QObject *parent = 0);
~QXmppIceConnection();
@@ -262,6 +275,8 @@ public:
bool bind(const QList<QHostAddress> &addresses);
bool isConnected() const;
+ GatheringState gatheringState() const;
+
signals:
/// \brief This signal is emitted once ICE negotiation succeeds.
void connected();
@@ -269,6 +284,9 @@ signals:
/// \brief This signal is emitted when ICE negotiation fails.
void disconnected();
+ /// \brief This signal is emitted when the gathering state of local candidates changes.
+ void gatheringStateChanged();
+
/// \brief This signal is emitted when the list of local candidates changes.
void localCandidatesChanged();
@@ -278,6 +296,7 @@ public slots:
private slots:
void slotConnected();
+ void slotGatheringStateChanged();
void slotTimeout();
private: