diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2015-08-28 14:17:16 +0200 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2015-08-28 14:17:16 +0200 |
| commit | 721836a76a028982495ccab6758a2d34a149fff3 (patch) | |
| tree | b09f1ca850b3780b617c968f82e18846ef26baf6 /src/base | |
| parent | b447fb1a91b0e4e5c46700c123aa8d79ed711891 (diff) | |
| download | qxmpp-721836a76a028982495ccab6758a2d34a149fff3.tar.gz | |
parse DTLS-SRTP attributes according to XEP-0320
Diffstat (limited to 'src/base')
| -rw-r--r-- | src/base/QXmppJingleIq.cpp | 114 | ||||
| -rw-r--r-- | src/base/QXmppJingleIq.h | 10 |
2 files changed, 122 insertions, 2 deletions
diff --git a/src/base/QXmppJingleIq.cpp b/src/base/QXmppJingleIq.cpp index a9371661..26799054 100644 --- a/src/base/QXmppJingleIq.cpp +++ b/src/base/QXmppJingleIq.cpp @@ -33,6 +33,7 @@ static const int RTP_COMPONENT = 1; static const char* ns_jingle_rtp_info = "urn:xmpp:jingle:apps:rtp:info:1"; +static const char* ns_jingle_dtls = "urn:xmpp:jingle:apps:dtls:0"; static const char* jingle_actions[] = { "content-accept", @@ -73,6 +74,25 @@ static const char* jingle_reasons[] = { "unsupported-transports", }; +static QString formatFingerprint(const QByteArray &digest) +{ + QString fingerprint; + const QString hx = digest.toHex().toUpper(); + for (int i = 0; i < hx.size(); i+=2) { + if (!fingerprint.isEmpty()) + fingerprint += ':'; + fingerprint += hx.mid(i, 2); + } + return fingerprint; +} + +static QByteArray parseFingerprint(const QString &fingerprint) +{ + QString z = fingerprint; + z.replace(':', ""); + return QByteArray::fromHex(z.toUtf8()); +} + static QString addressToSdp(const QHostAddress &host) { return QString("IN %1 %2").arg( @@ -141,6 +161,11 @@ public: QString transportType; QString transportUser; QString transportPassword; + + QByteArray transportFingerprint; + QString transportFingerprintHash; + QString transportFingerprintSetup; + QList<QXmppJinglePayloadType> payloadTypes; QList<QXmppJingleCandidate> transportCandidates; }; @@ -262,6 +287,60 @@ void QXmppJingleIq::Content::setTransportPassword(const QString &password) d->transportPassword = password; } +/// Returns the fingerprint hash value for the transport key. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +QByteArray QXmppJingleIq::Content::transportFingerprint() const +{ + return d->transportFingerprint; +} + +/// Sets the fingerprint hash value for the transport key. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +void QXmppJingleIq::Content::setTransportFingerprint(const QByteArray &fingerprint) +{ + d->transportFingerprint = fingerprint; +} + +/// Returns the fingerprint hash algorithm for the transport key. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +QString QXmppJingleIq::Content::transportFingerprintHash() const +{ + return d->transportFingerprintHash; +} + +/// Sets the fingerprint hash algorithm for the transport key. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +void QXmppJingleIq::Content::setTransportFingerprintHash(const QString &hash) +{ + d->transportFingerprintHash = hash; +} + +/// Returns the setup role for the encrypted transport. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +QString QXmppJingleIq::Content::transportFingerprintSetup() const +{ + return d->transportFingerprintSetup; +} + +/// Sets the setup role for the encrypted transport. +/// +/// This is used for DTLS-SRTP as defined in XEP-0320. + +void QXmppJingleIq::Content::setTransportFingerprintSetup(const QString &setup) +{ + d->transportFingerprintSetup = setup; +} + /// \cond void QXmppJingleIq::Content::parse(const QDomElement &element) { @@ -290,13 +369,20 @@ void QXmppJingleIq::Content::parse(const QDomElement &element) d->transportUser = transportElement.attribute("ufrag"); d->transportPassword = transportElement.attribute("pwd"); child = transportElement.firstChildElement("candidate"); - while (!child.isNull()) - { + while (!child.isNull()) { QXmppJingleCandidate candidate; candidate.parse(child); d->transportCandidates << candidate; child = child.nextSiblingElement("candidate"); } + child = transportElement.firstChildElement("fingerprint"); + + /// XEP-0320 + if (!child.isNull()) { + d->transportFingerprint = parseFingerprint(child.text()); + d->transportFingerprintHash = child.attribute("hash"); + d->transportFingerprintSetup = child.attribute("setup"); + } } void QXmppJingleIq::Content::toXml(QXmlStreamWriter *writer) const @@ -332,6 +418,16 @@ void QXmppJingleIq::Content::toXml(QXmlStreamWriter *writer) const helperToXmlAddAttribute(writer, "pwd", d->transportPassword); foreach (const QXmppJingleCandidate &candidate, d->transportCandidates) candidate.toXml(writer); + + // XEP-0320 + if (!d->transportFingerprint.isEmpty() && !d->transportFingerprintHash.isEmpty()) { + writer->writeStartElement("fingerprint"); + writer->writeAttribute("xmlns", ns_jingle_dtls); + writer->writeAttribute("hash", d->transportFingerprintHash); + writer->writeAttribute("setup", d->transportFingerprintSetup); + writer->writeCharacters(formatFingerprint(d->transportFingerprint)); + writer->writeEndElement(); + } writer->writeEndElement(); } writer->writeEndElement(); @@ -353,6 +449,12 @@ bool QXmppJingleIq::Content::parseSdp(const QString &sdp) return false; } addTransportCandidate(candidate); + } else if (attrName == "fingerprint") { + const QStringList bits = attrValue.split(' '); + if (bits.size() > 1) { + d->transportFingerprintHash = bits[0]; + d->transportFingerprint = parseFingerprint(bits[1]); + } } else if (attrName == "fmtp") { int spIdx = attrValue.indexOf(' '); if (spIdx == -1) { @@ -400,6 +502,8 @@ bool QXmppJingleIq::Content::parseSdp(const QString &sdp) d->transportUser = attrValue; } else if (attrName == "ice-pwd") { d->transportPassword = attrValue; + } else if (attrName == "setup") { + d->transportFingerprintSetup = attrValue; } else if (attrName == "ssrc") { const QStringList bits = attrValue.split(' '); if (bits.isEmpty()) { @@ -483,6 +587,12 @@ QString QXmppJingleIq::Content::toSdp() const sdp << QString("a=ice-ufrag:%1").arg(d->transportUser); if (!d->transportPassword.isEmpty()) sdp << QString("a=ice-pwd:%1").arg(d->transportPassword); + if (!d->transportFingerprint.isEmpty() && !d->transportFingerprintHash.isEmpty()) + sdp << QString("a=fingerprint:%1 %2").arg( + d->transportFingerprintHash, + formatFingerprint(d->transportFingerprint)); + if (!d->transportFingerprintSetup.isEmpty()) + sdp << QString("a=setup:%1").arg(d->transportFingerprintSetup); return sdp.join("\r\n") + "\r\n"; } diff --git a/src/base/QXmppJingleIq.h b/src/base/QXmppJingleIq.h index 6ec8f7ec..046b7c96 100644 --- a/src/base/QXmppJingleIq.h +++ b/src/base/QXmppJingleIq.h @@ -219,6 +219,16 @@ public: QString transportPassword() const; void setTransportPassword(const QString &password); + // XEP-0320: Use of DTLS-SRTP in Jingle Sessions + QByteArray transportFingerprint() const; + void setTransportFingerprint(const QByteArray &fingerprint); + + QString transportFingerprintHash() const; + void setTransportFingerprintHash(const QString &hash); + + QString transportFingerprintSetup() const; + void setTransportFingerprintSetup(const QString &setup); + /// \cond void parse(const QDomElement &element); void toXml(QXmlStreamWriter *writer) const; |
