From e932840bdd1e511f6b6849166757d216863196c3 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 22 Apr 2019 00:29:57 +0300 Subject: [PATCH 001/383] jingle-s5b progress --- src/xmpp/xmpp-im/jingle-s5b.cpp | 133 ++++++++++++++++++++++---------- 1 file changed, 94 insertions(+), 39 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index c895022d..73347990 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -221,7 +221,7 @@ class Transport::Private : public QSharedData { bool signalNegotiated = false; bool remoteReportedCandidateError = false; bool localReportedCandidateError = false; - bool proxyDiscoveryInProgress = false; + bool proxyDiscoveryInProgress = false; // if we have valid proxy requests quint16 pendingActions; int proxiesInDiscoCount = 0; quint32 minimalPriority = 0; @@ -229,8 +229,8 @@ class Transport::Private : public QSharedData { QMap localCandidates; // cid to candidate mapping QMap remoteCandidates; QSet> signalingCandidates; // origin here is session role. so for remote it's != session->role - Candidate localUsedCandidate; // we received "candidate-used" for this candidate - Candidate remoteUsedCandidate; + Candidate localUsedCandidate; // we received "candidate-used" for this candidate from localCandidates list + Candidate remoteUsedCandidate; // we sent "candidate-used" for this candidate from remoteCandidates list QString dstaddr; QString sid; Transport::Mode mode = Transport::Tcp; @@ -333,6 +333,48 @@ class Transport::Private : public QSharedData { } // TODO start connecting to the candidate here } + + bool hasUnaknowledgedLocalCandidates() const + { + // now ensure all local were sent to remote and no hope left + if (proxyDiscoveryInProgress) { + return true; + } + // Note: When upnp support is added we have one more check here + + // now local candidates + for (const auto &c: localCandidates) { + auto s = c.state(); + if (s == Candidate::Probing || s == Candidate::New || s == Candidate::Unacked) { + return true; + } + } + + return false; + } + + void checkAndSendLocalCandidatesExhausted() + { + // so the situation: we discarded all remote candidates (failed to connect) + // but we have some local candidates which are still in Probing state (upnp for example) + // if we send candidate-error while we have unsent candidates this may trigger transport failure. + // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more + // local candidates are expected to be discovered + for (const auto &c: remoteCandidates) { + if (c.state() != Candidate::Discarded) { + // we have other cadidates to handle. so we don't need candidate-error to be sent to remote yet + return; + } + } + if (hasUnaknowledgedLocalCandidates()) { + return; + } + + // so no pending local candidates discovery and all discovered candidates were already sent to remote. + // since all remote candidates are failed as well, we can't do anything here. time to accept the failure. + pendingActions |= Private::CandidateError; + emit q->updated(); + } }; Transport::Transport(const TransportManagerPad::Ptr &pad) : @@ -408,9 +450,8 @@ void Transport::prepare() ServerInfoManager::SQ_CheckAllOnNoMatch, [this](const QList &items) { - if (d->minimalPriority >= (Candidate::TunnelPreference << 16)) { + if (!d->proxyDiscoveryInProgress) { // check if new results are ever/still expected // seems like we have successful connection via higher priority channel. so nobody cares about proxy - d->proxyDiscoveryInProgress = false; return; } auto m = static_cast(d->pad->manager()); @@ -421,15 +462,23 @@ void Transport::prepare() d->proxiesInDiscoCount++; auto query = new JT_S5B(d->pad->session()->manager()->client()->rootTask()); connect(query, &JT_S5B::finished, this, [this,query,cid](){ + if (!d->proxyDiscoveryInProgress) { + return; + } bool candidateUpdated = false; - if (query->success()) { - auto sh = query->proxyInfo(); - auto c = d->localCandidates.value(cid); - if (c && c.state() == Candidate::Probing) { // it can discarded by this moment. so we have to check. + auto c = d->localCandidates.value(cid); + if (c && c.state() == Candidate::Probing) { + if (query->success()) { + auto sh = query->proxyInfo(); + // it can be discarded by this moment (e.g. got success on a higher priority candidate). + // so we have to check. c.setHost(sh.host()); c.setPort(sh.port()); c.setState(Candidate::New); candidateUpdated = true; + d->pendingActions |= Private::NewCandidate; + } else { + c.setState(Candidate::Discarded); } } d->proxiesInDiscoCount--; @@ -437,8 +486,10 @@ void Transport::prepare() d->proxyDiscoveryInProgress = false; } if (candidateUpdated) { - d->pendingActions |= Private::NewCandidate; emit updated(); + } else if (!d->proxiesInDiscoCount) { + // it's possible it was our last hope and probaby we have to send candidate-error now. + d->checkAndSendLocalCandidatesExhausted(); } }); query->requestProxyInfo(j); @@ -464,26 +515,7 @@ void Transport::prepare() } else if (items.count() == 0) { // seems like we don't have any proxy d->proxyDiscoveryInProgress = false; - // but it's possible it was our last hope and probaby we have to send candidate-error now. - // so the situation: we discarded all remote candidates (failed to connect) - // and all our candidates were already sent to remote - // if we send candidate-error while we have unsent candidates this may trigger transport failure. - // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more - // local candidates are expected to be discovered - for (const auto &c: d->remoteCandidates) { - if (c.state() != Candidate::Discarded) { - // we have other cadidates to handle. so we don't need candidate-error to be sent to remote yet - return; - } - } - // now ensure all local were sent to remote and no hope left - for (const auto &c: d->localCandidates) { - auto s = c.state(); - if (s == Candidate::Probing || s == Candidate::New) { - return; - } - } - d->pendingActions |= Private::CandidateError; + d->checkAndSendLocalCandidatesExhausted(); } }); @@ -502,8 +534,10 @@ void Transport::start() bool Transport::update(const QDomElement &transportEl) { + // we can just on type of elements in transport-info + // so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info QString contentTag(QStringLiteral("candidate")); - bool candidatesAdded = false;; + int candidatesAdded = 0; for(QDomElement ce = transportEl.firstChildElement(contentTag); !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) { Candidate c(ce); @@ -511,7 +545,7 @@ bool Transport::update(const QDomElement &transportEl) return false; } d->remoteCandidates.insert(c.cid(), c); // TODO check for collisions! - candidatesAdded = true; + candidatesAdded++; } if (candidatesAdded) { d->localReportedCandidateError = false; @@ -529,37 +563,58 @@ bool Transport::update(const QDomElement &transportEl) } cUsed.setState(Candidate::Accepted); d->localUsedCandidate = cUsed; - cUsed.setState(Candidate::Accepted); + for (auto &c: d->localCandidates) { + if (c.priority() < cUsed.priority() && c.state() != Candidate::Discarded) { + c.setState(Candidate::Discarded); + } + } + quint32 prio = cUsed.priority() >> 16; + if (d->proxyDiscoveryInProgress && prio > Candidate::ProxyPreference) { + // all proxies do no make sense anymore. we have successful higher priority candidate + d->proxyDiscoveryInProgress = false; + } + // TODO check upnp too when implemented + d->checkAndSendLocalCandidatesExhausted(); + // TODO here we can emit connected() if did send candidate-error or candidate-used before QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + return true; } el = transportEl.firstChildElement(QStringLiteral("candidate-error")); if (!el.isNull()) { d->remoteReportedCandidateError = true; - QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + for (auto &c: d->localCandidates) { + if (c.state() == Candidate::Pending) { + c.setState(Candidate::Discarded); + } + } + d->checkAndSendLocalCandidatesExhausted(); + return true; } el = transportEl.firstChildElement(QStringLiteral("activated")); if (!el.isNull()) { auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!c) { + if (!(c && c.type() == Candidate::Proxy && c.state() == Candidate::Accepted && c == d->localUsedCandidate)) { return false; } c.setState(Candidate::Active); - QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + QTimer::singleShot(0, this, [this](){ emit connected(); }); + return true; } el = transportEl.firstChildElement(QStringLiteral("proxy-error")); if (!el.isNull()) { auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!c) { + if (!c || c.state() != Candidate::Accepted) { return false; } c.setState(Candidate::Discarded); - QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + d->checkAndSendLocalCandidatesExhausted(); + return true; } - return true; + return false; } Action Transport::outgoingUpdateType() const From 0c123ab22c20e0513475a0839878e9f7f60a5e1b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 22 Apr 2019 07:54:40 +0300 Subject: [PATCH 002/383] jingle-s5b: updte minimal priority in separate function --- src/xmpp/xmpp-im/jingle-s5b.cpp | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 73347990..3ad35d2e 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -375,6 +375,33 @@ class Transport::Private : public QSharedData { pendingActions |= Private::CandidateError; emit q->updated(); } + + void updateMinimalPriority() { + quint32 prio = 0; + if (localUsedCandidate && minimalPriority < localUsedCandidate.priority() && localUsedCandidate.state() != Candidate::Discarded) { + prio = localUsedCandidate.priority(); + } else if (remoteUsedCandidate && minimalPriority < remoteUsedCandidate.priority() && remoteUsedCandidate.state() != Candidate::Discarded) { + prio = remoteUsedCandidate.priority(); + } + if (prio < minimalPriority) { + return; + } + for (auto &c: localCandidates) { + if (c.priority() < prio && c.state() != Candidate::Discarded) { + c.setState(Candidate::Discarded); + } + } + for (auto &c: remoteCandidates) { + if (c.priority() < prio && c.state() != Candidate::Discarded) { + c.setState(Candidate::Discarded); + } + } + prio >>= 16; + if (proxyDiscoveryInProgress && prio > Candidate::ProxyPreference) { + // all proxies do no make sense anymore. we have successful higher priority candidate + proxyDiscoveryInProgress = false; + } + } }; Transport::Transport(const TransportManagerPad::Ptr &pad) : @@ -563,16 +590,7 @@ bool Transport::update(const QDomElement &transportEl) } cUsed.setState(Candidate::Accepted); d->localUsedCandidate = cUsed; - for (auto &c: d->localCandidates) { - if (c.priority() < cUsed.priority() && c.state() != Candidate::Discarded) { - c.setState(Candidate::Discarded); - } - } - quint32 prio = cUsed.priority() >> 16; - if (d->proxyDiscoveryInProgress && prio > Candidate::ProxyPreference) { - // all proxies do no make sense anymore. we have successful higher priority candidate - d->proxyDiscoveryInProgress = false; - } + d->updateMinimalPriority(); // TODO check upnp too when implemented d->checkAndSendLocalCandidatesExhausted(); // TODO here we can emit connected() if did send candidate-error or candidate-used before From d558c745410355cd042e225f6a7a07c52c5d274f Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 22 Apr 2019 10:54:38 +0300 Subject: [PATCH 003/383] jingle-s5b: more states magic --- src/xmpp/xmpp-im/jingle-s5b.cpp | 47 +++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 3ad35d2e..f01ef3b5 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -313,6 +313,8 @@ class Transport::Private : public QSharedData { // seems like we don't have better candidates, // so we are going to use the d->localUsedCandidate signalNegotiated = true; + + // TODO emit connected() if ready } void tryConnectToRemoteCandidate() @@ -360,6 +362,12 @@ class Transport::Private : public QSharedData { // if we send candidate-error while we have unsent candidates this may trigger transport failure. // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more // local candidates are expected to be discovered + + // if we already sent candidate-error or candidate-used then just silently exit + if (remoteUsedCandidate || localReportedCandidateError || (pendingActions & Private::CandidateError)) { + return; + } + for (const auto &c: remoteCandidates) { if (c.state() != Candidate::Discarded) { // we have other cadidates to handle. so we don't need candidate-error to be sent to remote yet @@ -401,6 +409,13 @@ class Transport::Private : public QSharedData { // all proxies do no make sense anymore. we have successful higher priority candidate proxyDiscoveryInProgress = false; } + // if we discarded "used" candidates then reset them to invalid + if (localUsedCandidate && localUsedCandidate.state() == Candidate::Discarded) { + localUsedCandidate = Candidate(); + } + if (remoteUsedCandidate && remoteUsedCandidate.state() == Candidate::Discarded) { + remoteUsedCandidate = Candidate(); + } } }; @@ -593,7 +608,6 @@ bool Transport::update(const QDomElement &transportEl) d->updateMinimalPriority(); // TODO check upnp too when implemented d->checkAndSendLocalCandidatesExhausted(); - // TODO here we can emit connected() if did send candidate-error or candidate-used before QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); return true; } @@ -607,15 +621,20 @@ bool Transport::update(const QDomElement &transportEl) } } d->checkAndSendLocalCandidatesExhausted(); + QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); return true; } el = transportEl.firstChildElement(QStringLiteral("activated")); if (!el.isNull()) { auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!(c && c.type() == Candidate::Proxy && c.state() == Candidate::Accepted && c == d->localUsedCandidate)) { + if (!c) { return false; } + if (!(c.type() == Candidate::Proxy && c.state() == Candidate::Accepted && c == d->localUsedCandidate)) { + qDebug("Received on a candidate in an inappropriate state. Ignored."); + return true; + } c.setState(Candidate::Active); QTimer::singleShot(0, this, [this](){ emit connected(); }); return true; @@ -624,11 +643,29 @@ bool Transport::update(const QDomElement &transportEl) el = transportEl.firstChildElement(QStringLiteral("proxy-error")); if (!el.isNull()) { auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!c || c.state() != Candidate::Accepted) { + if (!c) { return false; } - c.setState(Candidate::Discarded); - d->checkAndSendLocalCandidatesExhausted(); + if (c != d->localUsedCandidate || c.state() != Candidate::Accepted) { + qDebug("Received on a candidate in an inappropriate state. Ignored."); + return true; + } + + // if we got proxy-error then the transport has to be considered failed according to spec + // so never send proxy-error while we have unaknowledged local non-proxy candidates, + // but we have to follow the standard. + + // Discard everything + for (auto &c: d->localCandidates) { + c.setState(Candidate::Discarded); + } + for (auto &c: d->remoteCandidates) { + c.setState(Candidate::Discarded); + } + d->proxyDiscoveryInProgress = false; + // TODO do the same for upnp when implemented + + QTimer::singleShot(0, this, [this](){ emit failed(); }); return true; } From 2f895d8596f52ce764682a4f7980cdc320f97b98 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 28 Apr 2019 00:10:15 +0300 Subject: [PATCH 004/383] jingle-s5b: check connection negotiation complete --- src/xmpp/xmpp-im/jingle-s5b.cpp | 177 +++++++++++++++++++------------- src/xmpp/xmpp-im/jingle-s5b.h | 1 + 2 files changed, 108 insertions(+), 70 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index f01ef3b5..619fc4cb 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1,4 +1,4 @@ -/* +/* * jignle-s5b.cpp - Jingle SOCKS5 transport * Copyright (C) 2019 Sergey Ilinykh * @@ -87,6 +87,12 @@ Candidate::Candidate(const QDomElement &el) return; } + if ((candidateType == Proxy && !jid.isValid()) || + (candidateType != Proxy && (host.isEmpty() || !port))) + { + return; + } + auto d = new Private; d->cid = cid; d->host = host; @@ -205,20 +211,26 @@ QDomElement Candidate::toXml(QDomDocument *doc) const return e; } +void Candidate::connectToHost(std::function callback) +{ + // TODO negotiate socks5 connection to host and port + Q_UNUSED(callback) +} + class Transport::Private : public QSharedData { public: enum PendingActions { - NewCandidate, - CandidateUsed, - CandidateError, - Activated, - ProxyError + NewCandidate = 1, + CandidateUsed = 2, + CandidateError = 4, + Activated = 8, + ProxyError = 16 }; Transport *q = NULL; Pad::Ptr pad; + bool waitingAck = true; bool aborted = false; - bool signalNegotiated = false; bool remoteReportedCandidateError = false; bool localReportedCandidateError = false; bool proxyDiscoveryInProgress = false; // if we have valid proxy requests @@ -273,50 +285,6 @@ class Transport::Private : public QSharedData { return false; } - void updateSelfState() - { - // TODO code below is from handler of "candidate-used". it has to be updated - bool hasMoreCandidates = false; - for (auto &c: localCandidates) { - auto s = c.state(); - if (s < Candidate::Pending && c.priority() > localUsedCandidate.priority()) { - hasMoreCandidates = true; - continue; // we have more high priority candidates to be handled by remote - } - c.setState(Candidate::Discarded); - } - - if (hasMoreCandidates) { - return; - } - - // let's check remote candidates too before we decide to use this local candidate - for (auto &c: remoteCandidates) { - auto s = c.state(); - if (c.priority() > localUsedCandidate.priority() && (s == Candidate::Pending || - s == Candidate::Probing || - s == Candidate::New)) { - hasMoreCandidates = true; - continue; // we have more high priority candidates to be handled by remote - } else if (c.priority() == localUsedCandidate.priority() && s == Candidate::Unacked && - pad->session()->role() == Origin::Initiator) { - hasMoreCandidates = true; - continue; // see 2.4 Completing the Negotiation (p.4) - } - c.setState(Candidate::Discarded); // TODO stop any probing as well - } - - if (hasMoreCandidates) { - return; - } - - // seems like we don't have better candidates, - // so we are going to use the d->localUsedCandidate - signalNegotiated = true; - - // TODO emit connected() if ready - } - void tryConnectToRemoteCandidate() { if (application->state() != State::Connecting) { @@ -355,35 +323,96 @@ class Transport::Private : public QSharedData { return false; } - void checkAndSendLocalCandidatesExhausted() + void checkAndFinishNegotiation() { + // Why we can't send candidate-used/error right when this happens: // so the situation: we discarded all remote candidates (failed to connect) // but we have some local candidates which are still in Probing state (upnp for example) // if we send candidate-error while we have unsent candidates this may trigger transport failure. // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more // local candidates are expected to be discovered - // if we already sent candidate-error or candidate-used then just silently exit - if (remoteUsedCandidate || localReportedCandidateError || (pendingActions & Private::CandidateError)) { + if (application->state() != State::Connecting) { + return; // we can't finish anything in this state. Only Connecting is acceptable + } + + // sort out already handled states or states which will bring us here a little later + if (waitingAck || pendingActions || hasUnaknowledgedLocalCandidates()) + { + // waitingAck some query waits for ack and in the callback this func will be called again + // pendingActions means we reported to app we have data to send but the app didn't take this data yet, + // but as soon as it's taken it will switch to waitingAck. + // And with unacknowledged local candidates we can't send used/error as well as report connected()/failure() + // until tried them all return; } + // if we already sent used/error. In other words if we already have finished local part of negotiation + if (localReportedCandidateError || remoteUsedCandidate) { + // maybe it's time to report connected()/failure() + if (remoteReportedCandidateError || localUsedCandidate) { + // so remote seems to be finished too. + // tell application about it and it has to change its state immediatelly + if (localUsedCandidate || remoteUsedCandidate) { + auto c = localUsedCandidate? localUsedCandidate : remoteUsedCandidate; + if (c.type() == Candidate::Proxy) { + // If it's proxy, first it has to be activated + if (localUsedCandidate) { + // it's our side who proposed proxy. so we have to connect to it and activate + c.connectToHost([this](bool success){ + if (success) { + pendingActions |= Private::Activated; + } else { + pendingActions |= Private::ProxyError; + } + emit q->updated(); + }); + } else { + return; // let's just wait for from remote + } + } else { + c.setState(Candidate::Active); + emit q->connected(); + } + } else { + emit q->failed(); + } + } // else we have to wait till remote reports its status + return; + } + + // if we are here then neither candidate-used nor candidate-error was sent to remote, + // but we can send it now. + // first let's check if we can send candidate-used + bool allRemoteDiscarded = true; + bool hasConnectedRemoteCandidate = false; for (const auto &c: remoteCandidates) { - if (c.state() != Candidate::Discarded) { - // we have other cadidates to handle. so we don't need candidate-error to be sent to remote yet - return; + auto s = c.state(); + if (s != Candidate::Discarded) { + allRemoteDiscarded = false; + } + if (s == Candidate::Pending) { // connected but not yet sent + hasConnectedRemoteCandidate = true; } } - if (hasUnaknowledgedLocalCandidates()) { + + // if we have connection to remote candidate it's time to send it + if (hasConnectedRemoteCandidate) { + pendingActions |= Private::CandidateUsed; + emit q->updated(); return; } - // so no pending local candidates discovery and all discovered candidates were already sent to remote. - // since all remote candidates are failed as well, we can't do anything here. time to accept the failure. - pendingActions |= Private::CandidateError; - emit q->updated(); + if (allRemoteDiscarded) { + pendingActions |= Private::CandidateError; + emit q->updated(); + return; + } + + // apparently we haven't connected anywhere but there are more remote candidates to try } + // take used-candidate with highest priority and discard all with lower. also update used candidates themselves void updateMinimalPriority() { quint32 prio = 0; if (localUsedCandidate && minimalPriority < localUsedCandidate.priority() && localUsedCandidate.state() != Candidate::Discarded) { @@ -416,6 +445,16 @@ class Transport::Private : public QSharedData { if (remoteUsedCandidate && remoteUsedCandidate.state() == Candidate::Discarded) { remoteUsedCandidate = Candidate(); } + if (localUsedCandidate && remoteUsedCandidate) { + if (application->creator() == pad->session()->role()) { + // i'm initiator. see 2.4.4 + localUsedCandidate.setState(Candidate::Discarded); + localUsedCandidate = Candidate(); + } else { + remoteUsedCandidate.setState(Candidate::Discarded); + remoteUsedCandidate = Candidate(); + } + } } }; @@ -531,7 +570,7 @@ void Transport::prepare() emit updated(); } else if (!d->proxiesInDiscoCount) { // it's possible it was our last hope and probaby we have to send candidate-error now. - d->checkAndSendLocalCandidatesExhausted(); + d->checkAndFinishNegotiation(); } }); query->requestProxyInfo(j); @@ -557,7 +596,7 @@ void Transport::prepare() } else if (items.count() == 0) { // seems like we don't have any proxy d->proxyDiscoveryInProgress = false; - d->checkAndSendLocalCandidatesExhausted(); + d->checkAndFinishNegotiation(); } }); @@ -590,6 +629,7 @@ bool Transport::update(const QDomElement &transportEl) candidatesAdded++; } if (candidatesAdded) { + d->pendingActions &= ~Private::CandidateError; d->localReportedCandidateError = false; QTimer::singleShot(0, this, [this](){ d->tryConnectToRemoteCandidate(); @@ -606,9 +646,7 @@ bool Transport::update(const QDomElement &transportEl) cUsed.setState(Candidate::Accepted); d->localUsedCandidate = cUsed; d->updateMinimalPriority(); - // TODO check upnp too when implemented - d->checkAndSendLocalCandidatesExhausted(); - QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); return true; } @@ -620,8 +658,7 @@ bool Transport::update(const QDomElement &transportEl) c.setState(Candidate::Discarded); } } - d->checkAndSendLocalCandidatesExhausted(); - QTimer::singleShot(0, this, [this](){ d->updateSelfState(); }); + QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); return true; } @@ -674,7 +711,7 @@ bool Transport::update(const QDomElement &transportEl) Action Transport::outgoingUpdateType() const { - if (isValid() && d->application) { + if (isValid() && d->application && d->pendingActions) { // if we are preparing local offer and have at least one candidate, we have to sent it. // otherwise it's not first update to remote from this transport, so we have to send just signalling candidates if ((d->application->state() == State::PrepareLocalOffer && d->localCandidates.size()) || diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 6275a892..320c21bb 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -110,6 +110,7 @@ class Candidate { QDomElement toXml(QDomDocument *doc) const; + void connectToHost(std::function callback); private: class Private; QExplicitlySharedDataPointer d; From feb3e7a2ecc4d1056712f25c68f1eb415c13791a Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 28 Apr 2019 13:30:22 +0300 Subject: [PATCH 005/383] jingle-s5b: actually send local events --- src/xmpp/xmpp-im/jingle-s5b.cpp | 156 ++++++++++++++++++++++++-------- 1 file changed, 116 insertions(+), 40 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 619fc4cb..78126cbe 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -240,7 +240,6 @@ class Transport::Private : public QSharedData { Application *application = nullptr; QMap localCandidates; // cid to candidate mapping QMap remoteCandidates; - QSet> signalingCandidates; // origin here is session role. so for remote it's != session->role Candidate localUsedCandidate; // we received "candidate-used" for this candidate from localCandidates list Candidate remoteUsedCandidate; // we sent "candidate-used" for this candidate from remoteCandidates list QString dstaddr; @@ -261,6 +260,11 @@ class Transport::Private : public QSharedData { return senders == Origin::Both || senders == negateOrigin(application->creator()); } + bool amICreator() const + { + return application->creator() == pad->session()->role(); + } + inline Jid remoteJid() const { return pad->session()->peer(); @@ -355,26 +359,28 @@ class Transport::Private : public QSharedData { // tell application about it and it has to change its state immediatelly if (localUsedCandidate || remoteUsedCandidate) { auto c = localUsedCandidate? localUsedCandidate : remoteUsedCandidate; - if (c.type() == Candidate::Proxy) { - // If it's proxy, first it has to be activated - if (localUsedCandidate) { - // it's our side who proposed proxy. so we have to connect to it and activate - c.connectToHost([this](bool success){ - if (success) { - pendingActions |= Private::Activated; - } else { - pendingActions |= Private::ProxyError; - } - emit q->updated(); - }); + if (c.state() != Candidate::Active) { + if (c.type() == Candidate::Proxy) { + // If it's proxy, first it has to be activated + if (localUsedCandidate) { + // it's our side who proposed proxy. so we have to connect to it and activate + c.connectToHost([this](bool success){ + if (success) { + pendingActions |= Private::Activated; + } else { + pendingActions |= Private::ProxyError; + } + emit q->updated(); + }); + } // else so it's remote proxy. let's just wait for from remote } else { - return; // let's just wait for from remote + c.setState(Candidate::Active); } - } else { - c.setState(Candidate::Active); + } + if (c.state() == Candidate::Active) { emit q->connected(); } - } else { + } else { // both sides reported candidate error emit q->failed(); } } // else we have to wait till remote reports its status @@ -446,7 +452,7 @@ class Transport::Private : public QSharedData { remoteUsedCandidate = Candidate(); } if (localUsedCandidate && remoteUsedCandidate) { - if (application->creator() == pad->session()->role()) { + if (amICreator()) { // i'm initiator. see 2.4.4 localUsedCandidate.setState(Candidate::Discarded); localUsedCandidate = Candidate(); @@ -549,8 +555,8 @@ void Transport::prepare() bool candidateUpdated = false; auto c = d->localCandidates.value(cid); if (c && c.state() == Candidate::Probing) { - if (query->success()) { - auto sh = query->proxyInfo(); + auto sh = query->proxyInfo(); + if (query->success() && !sh.host().isEmpty() && sh.port()) { // it can be discarded by this moment (e.g. got success on a higher priority candidate). // so we have to check. c.setHost(sh.host()); @@ -600,10 +606,6 @@ void Transport::prepare() } }); - for (auto const &c: d->localCandidates) { - d->signalingCandidates.insert(QPair{c.cid(),d->pad->session()->role()}); - } - // TODO nat-assisted candidates.. emit updated(); } @@ -715,8 +717,7 @@ Action Transport::outgoingUpdateType() const // if we are preparing local offer and have at least one candidate, we have to sent it. // otherwise it's not first update to remote from this transport, so we have to send just signalling candidates if ((d->application->state() == State::PrepareLocalOffer && d->localCandidates.size()) || - (d->application->state() > State::PrepareLocalOffer && d->application->state() < State::Finished && - !d->signalingCandidates.isEmpty())) + (d->application->state() > State::PrepareLocalOffer && d->application->state() < State::Finished)) { return Action::TransportInfo; } @@ -732,26 +733,27 @@ OutgoingUpdate Transport::takeOutgoingUpdate() return upd; } - auto sessRole = d->pad->session()->role(); auto doc = d->pad->session()->manager()->client()->doc(); - if (appState == State::PrepareLocalOffer && !d->localCandidates.isEmpty()) { - QDomElement tel = doc->createElementNS(NS, "transport"); - tel.setAttribute(QStringLiteral("sid"), d->sid); - if (d->mode != Tcp) { - tel.setAttribute(QStringLiteral("mode"), "udp"); - } + QDomElement tel = doc->createElementNS(NS, "transport"); + tel.setAttribute(QStringLiteral("sid"), d->sid); + if (d->amICreator() && d->mode != Tcp) { + tel.setAttribute(QStringLiteral("mode"), "udp"); + } + + if (d->pendingActions & Private::NewCandidate) { + d->pendingActions &= ~Private::NewCandidate; bool useProxy = false; QList candidatesToSend; for (auto &c: d->localCandidates) { + if (c.state() != Candidate::New) { + continue; + } if (c.type() == Candidate::Proxy) { useProxy = true; } - if (!c.host().isEmpty()) { - tel.appendChild(c.toXml(doc)); - } + tel.appendChild(c.toXml(doc)); candidatesToSend.append(c); - d->signalingCandidates.remove(QPair{c.cid(),sessRole}); c.setState(Candidate::Unacked); } if (useProxy) { @@ -761,12 +763,86 @@ OutgoingUpdate Transport::takeOutgoingUpdate() QCryptographicHash::Sha1); tel.setAttribute(QStringLiteral("dstaddr"), dstaddr); } - OutgoingUpdate{tel, [this, candidatesToSend]() mutable { + if (!candidatesToSend.isEmpty()) { + d->waitingAck = true; + upd = OutgoingUpdate{tel, [this, candidatesToSend]() mutable { + d->waitingAck = false; for (auto &c: candidatesToSend) { - c.setState(Candidate::Pending); + if (c.state() == Candidate::Unacked) { + c.setState(Candidate::Pending); + } + } + d->checkAndFinishNegotiation(); + }}; + } + } else if (d->pendingActions & Private::CandidateUsed) { + d->pendingActions &= ~Private::NewCandidate; + // we should have the only remote candidate in Pending state + for (auto &c: d->remoteCandidates) { + if (c.state() != Candidate::Pending) { + continue; + } + auto el = tel.appendChild(doc->createElement(QStringLiteral("candidate-used"))).toElement(); + el.setAttribute(QStringLiteral("cid"), c.cid()); + c.setState(Candidate::Unacked); + + d->waitingAck = true; + upd = OutgoingUpdate{tel, [this, c]() mutable { + d->waitingAck = false; + if (c.state() == Candidate::Unacked) { + c.setState(Candidate::Accepted); + d->remoteUsedCandidate = c; + } + d->checkAndFinishNegotiation(); + }}; + + break; + } + } else if (d->pendingActions & Private::CandidateError) { + d->pendingActions &= ~Private::CandidateError; + // we are here because all remote are already in Discardd state + tel.appendChild(doc->createElement(QStringLiteral("candidate-error"))); + d->waitingAck = true; + upd = OutgoingUpdate{tel, [this]() mutable { + d->waitingAck = false; + d->localReportedCandidateError = true; + d->checkAndFinishNegotiation(); + }}; + } else if (d->pendingActions & Private::Activated) { + d->pendingActions &= ~Private::Activated; + if (d->localUsedCandidate) { + auto cand = d->localUsedCandidate; + auto el = tel.appendChild(doc->createElement(QStringLiteral("activated"))).toElement(); + el.setAttribute(QStringLiteral("cid"), cand.cid()); + d->waitingAck = true; + upd = OutgoingUpdate{tel, [this, cand]() mutable { + d->waitingAck = false; + if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { + return; // seems like state was changed while we was waiting for an ack } - }}; // FIXME we should update candidates status here + cand.setState(Candidate::Active); + d->checkAndFinishNegotiation(); + }}; + } + } else if (d->pendingActions & Private::ProxyError) { + // we send proxy error only for local proxy + d->pendingActions &= ~Private::ProxyError; + if (d->localUsedCandidate) { + auto cand = d->localUsedCandidate; + tel.appendChild(doc->createElement(QStringLiteral("proxy-error"))); + d->waitingAck = true; + upd = OutgoingUpdate{tel, [this, cand]() mutable { + d->waitingAck = false; + if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { + return; // seems like state was changed while we was waiting for an ack + } + cand.setState(Candidate::Discarded); + d->localUsedCandidate = Candidate(); + emit failed(); + }}; + } } + return upd; // TODO } From 2b51a42277c0153af95066a330571e0591ff67b8 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 30 Apr 2019 15:42:07 +0300 Subject: [PATCH 006/383] jingle: commont code from session-initiate content-add moved to separate function --- src/xmpp/xmpp-im/jingle.cpp | 220 +++++++++++++++++------------------- src/xmpp/xmpp-im/jingle.h | 1 + 2 files changed, 106 insertions(+), 115 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index cefa1059..412b2021 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -577,8 +577,6 @@ class Session::Private Origin role = Origin::Initiator; // my role in the session XMPP::Stanza::Error lastError; Reason terminateReason; - Action outgoingUpdateType = Action::NoAction; - QDomElement outgoingUpdate; QMap> applicationPads; QMap> transportPads; //QMap myContent; // content::creator=(role == Session::Role::Initiator?initiator:responder) @@ -793,7 +791,7 @@ class Session::Private Unsupported }; - std::tuple addContent(const QDomElement &ce) + std::tuple parseContent(const QDomElement &ce) { QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); @@ -835,6 +833,62 @@ class Session::Private return result{Unparsed, Reason::Success, nullptr}; } + + + typedef std::tuple, QList> ParseContentListResult; + + ParseContentListResult parseContentList(const QDomElement &jingleEl) + { + QMap addSet; + QMap> rejectSet; + + QString contentTag(QStringLiteral("content")); + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + + Private::AddContentError err; + Reason::Condition cond; + Application *app; + + std::tie(err, cond, app) = parseContent(ce); + if (err == Private::AddContentError::Unparsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + qDeleteAll(addSet); + return ParseContentListResult(Unparsed, cond, QList(), QList()); + } + + auto contentName = app->contentName(); + auto it = addSet.find(contentName); + if (err != Private::AddContentError::Ok) { + // can't continue as well + if (app) { // we are going to reject it completely so delete + delete app; + } + + if (it == addSet.end()) { + rejectSet.insert(contentName, std::make_pair(ce, cond)); + } + continue; + } + + rejectSet.remove(contentName); + if (it == addSet.end() || (*it)->wantBetterTransport(app->transport())) { // probably not wantBetterTransport but wantBetterApplication + delete *it; // unpreferred app + *it = app; + } + } + + if (rejectSet.size()) { + QList rejectList; + for (auto const &i: rejectSet) { + rejectList.append(i.first); + } + return ParseContentListResult(Unsupported, rejectSet.first().second, addSet.values(), rejectList); + } + + return ParseContentListResult(Ok, Reason::Success, addSet.values(), QList()); + } }; Session::Session(Manager *manager, const Jid &peer) : @@ -1029,142 +1083,78 @@ bool Session::incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl if (jingle.initiator().isValid() && !jingle.initiator().compare(d->origFrom)) { d->otherParty = jingle.initiator(); } - //auto key = qMakePair(from, jingle.sid()); - - QMap> addSet; // application to supported - - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) { - Private::AddContentError err; - Reason::Condition cond; - Application *app; - auto r = d->addContent(ce); - std::tie(err, cond, app) = r; - if (err == Private::AddContentError::Unparsed) { - for (auto const &i: addSet) { - delete std::get<1>(i); - } - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - if (err == Private::AddContentError::Unsupported) { - if (cond == Reason::Condition::UnsupportedTransports) { - } - // can't continue as well - for (auto const &i: addSet) { - delete std::get<1>(i); - } - d->outgoingUpdateType = Action::SessionTerminate; - Reason r(cond); - d->outgoingUpdate = r.toXml(d->manager->client()->doc()); - return true; - } - QString contentName = ce.attribute(QStringLiteral("name")); - if (err == Private::AddContentError::Ok) { - auto et = addSet.value(contentName); - auto eapp = std::get<1>(et); - if (!eapp || eapp->wantBetterTransport(app->transport())) { - addSet.insert(contentName, std::make_tuple(cond,app)); - } - } else if (!std::get<1>(addSet.value(contentName))) { - // something unsupported. but lets parse all items. maybe it will get replaced - addSet.insert(contentName, std::make_tuple(cond,app)); - } - - // TODO at this point if all addSet items have application it's success, - // otherwise we have to think what to do with this. for example replace transport if it's unsupported. + Private::AddContentError err; + Reason::Condition cond; + QList apps; + QList rejects; - for (auto const &i: addSet) { - Reason::Condition cond; - Application *app; - std::tie(cond, app) = i; - if (!app) { - // TODO - return false; // FIXME. memory release - } + std::tie(err, cond, apps, rejects) = d->parseContentList(jingleEl); + switch (err) { + case Private::AddContentError::Unparsed: + return false; + case Private::AddContentError::Unsupported: + QTimer::singleShot(0, this, [this, cond](){ + d->sendJingle(Action::SessionTerminate, QList() << Reason(cond).toXml(d->manager->client()->doc())); + d->state = State::Finished; + emit terminated(); + }); + return true; + case Private::AddContentError::Ok: + for (auto app: apps) { d->contentList.insert(ContentKey{app->contentName(), Origin::Initiator}, app); } + d->planStep(); + return true; } - d->planStep(); - return true; + + return false; } bool Session::updateFromXml(Action action, const QDomElement &jingleEl) { - if (action == Action::SessionInfo) { - - } - - if (action != Action::ContentAdd) { + if (d->state == State::Finished) { + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); // TODO OutOfOrder return false; } - QMap addSet; // application to supported - bool parsed = true; - int unsupported = 0; - Reason::Condition rejectCond = Reason::Condition::Success; + if (action == Action::SessionInfo) { - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) { + } + + if (action == Action::ContentAdd) { Private::AddContentError err; Reason::Condition cond; - Application *app; - QString contentName = ce.attribute(QStringLiteral("name")); - if (!contentName.size()) { - parsed = false; + QList apps; + QList rejects; + + std::tie(err, cond, apps, rejects) = d->parseContentList(jingleEl); + switch (err) { + case Private::AddContentError::Unparsed: + return false; + case Private::AddContentError::Unsupported: + QTimer::singleShot(0, this, [this, cond, rejects]() mutable { + rejects += Reason(cond).toXml(d->manager->client()->doc()); + d->sendJingle(Action::ContentReject, rejects); + }); + break; + case Private::AddContentError::Ok: break; } - std::tie(err, cond, app) = d->addContent(ce); - bool alreadyAdded = addSet.contains(contentName); - if (err != Private::AddContentError::Ok) { - // can't continue as well - if (app) { // we are going to reject it completely so delete - delete app; - } - if (err == Private::AddContentError::Unsupported) { - rejectCond = cond; + if (apps.size()) { + Origin remoteRole = negateOrigin(d->role); + for (auto app: apps) { + d->contentList.insert(ContentKey{app->contentName(), remoteRole}, app); // TODO check conflicts } - if (!alreadyAdded) { - unsupported++; - addSet.insert(contentName, nullptr); - } // else just ignore this unsupported content. we aready have one - continue; + QTimer::singleShot(0, this, [this](){ emit newContentReceived(); }); } - auto eapp = addSet.value(contentName); - if (alreadyAdded && !eapp) { - unsupported--; // we are going to overwrite previous with successful - } - if (!eapp || eapp->wantBetterTransport(app->transport())) { - addSet.insert(contentName, app); - } - } - - if (unsupported && rejectCond == Reason::Condition::Success) { - parsed = false; // the only way it's possible - } - if (!parsed) { - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - qDeleteAll(addSet); - return false; - } else if (unsupported) { - d->outgoingUpdateType = Action::ContentReject; - Reason r(rejectCond); - d->outgoingUpdate = r.toXml(d->manager->client()->doc()); - qDeleteAll(addSet); return true; } - Origin remoteRole = negateOrigin(d->role); - for (auto const &app: addSet) { - d->contentList.insert(ContentKey{app->contentName(), remoteRole}, app); // TODO check conflicts - } - - return true; + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); + return false; } diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 43a294d3..c5e6f77c 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -391,6 +391,7 @@ class Session : public QObject void managerPadAdded(const QString &ns); void activated(); void terminated(); + void newContentReceived(); private: friend class Manager; From cad08f63603c828101436e815dcfad015996004d Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 3 May 2019 21:37:03 +0300 Subject: [PATCH 007/383] jingle: handle content add/accept --- src/xmpp/xmpp-im/jingle-ft.cpp | 47 ++-- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle-s5b.cpp | 75 ++----- src/xmpp/xmpp-im/jingle-s5b.h | 5 +- src/xmpp/xmpp-im/jingle.cpp | 375 ++++++++++++++++++++++++++------ src/xmpp/xmpp-im/jingle.h | 35 ++- 6 files changed, 389 insertions(+), 149 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index db291459..f5def76c 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -463,7 +463,6 @@ bool Application::setTransport(const QSharedPointer &transport) } d->availableTransports.removeAt(nsIndex); d->transport = transport; - d->transport->setApplication(this); d->state = State::Pending; return true; } @@ -481,14 +480,17 @@ Action Application::outgoingUpdateType() const case State::Created: break; case State::PrepareLocalOffer: - if (!d->transport && !d->availableTransports.size()) { - break; // not yet ready + if (d->transport->hasUpdates()) { + return d->creator == d->pad->session()->role()? Action::ContentAdd : Action::ContentAccept; } - return Action::ContentAdd; + break; case State::Connecting: case State::Active: - return d->transport->outgoingUpdateType(); case State::Pending: + if (d->transport->hasUpdates()) { + return Action::TransportInfo; + } + break; default: break; } @@ -500,17 +502,14 @@ OutgoingUpdate Application::takeOutgoingUpdate() if (!isValid() || d->state == State::Created) { return OutgoingUpdate(); } - if (d->state == State::Connecting || d->state == State::Active) { - return d->transport->takeOutgoingUpdate(); - } + + auto client = d->pad->session()->manager()->client(); + auto doc = client->doc(); if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content - if (!d->transport && d->availableTransports.size()) { - selectNextTransport(); - } - if (!d->transport || d->transport->outgoingUpdateType() == Action::NoAction) { // failed to select next transport. can't continue + if (!d->transport->hasUpdates()) { // failed to select next transport. can't continue return OutgoingUpdate(); } - auto client = d->pad->session()->manager()->client(); + if (d->file.thumbnail().data.size()) { auto thumb = d->file.thumbnail(); auto bm = client->bobManager(); @@ -518,7 +517,6 @@ OutgoingUpdate Application::takeOutgoingUpdate() thumb.uri = QLatin1String("cid:") + data.cid(); d->file.setThumbnail(thumb); } - auto doc = client->doc(); ContentBase cb(d->pad->session()->role(), d->contentName); cb.senders = d->senders; auto cel = cb.toXml(doc, "content"); @@ -529,13 +527,25 @@ OutgoingUpdate Application::takeOutgoingUpdate() cel.appendChild(tel); d->state = State::Unacked; - return OutgoingUpdate{cel, [this, trCallback](){ + return OutgoingUpdate{QList()<state = d->pad->session()->role() == Origin::Initiator? State::Pending : State::Active; }}; } + if (d->state == State::Connecting || d->state == State::Active || d->state == State::Pending) { + if (d->transport->hasUpdates()) { // failed to select next transport. can't continue + ContentBase cb(d->pad->session()->role(), d->contentName); + cb.senders = d->senders; + auto cel = cb.toXml(doc, "content"); + QDomElement tel; + OutgoingUpdateCB trCallback; + std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); + cel.appendChild(tel); + return OutgoingUpdate{QList()<availableTransports.size()) { QString ns = d->availableTransports.takeFirst(); d->transport = d->pad->session()->newOutgoingTransport(ns); - d->transport->setApplication(this); return true; } return false; @@ -576,6 +585,12 @@ void Application::start() // TODO we nedd QIODevice somewhere here } +bool Application::accept(const QDomElement &el) +{ + Q_UNUSED(el); + return true; // TODO!!! +} + bool Application::isValid() const { return d->file.isValid() && d->transport && d->contentName.size() > 0 && diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 0a23a00a..e2c2171c 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -135,6 +135,7 @@ class Application : public XMPP::Jingle::Application bool selectNextTransport() override; void prepare() override; void start() override; + bool accept(const QDomElement &el) override; bool isValid() const; diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 78126cbe..15b6295c 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -229,6 +229,8 @@ class Transport::Private : public QSharedData { Transport *q = NULL; Pad::Ptr pad; + bool meCreator = true; // content.content is local side + bool connectionStarted = false; // where start() was called bool waitingAck = true; bool aborted = false; bool remoteReportedCandidateError = false; @@ -246,25 +248,6 @@ class Transport::Private : public QSharedData { QString sid; Transport::Mode mode = Transport::Tcp; - bool amISender() const - { - Q_ASSERT(application); - auto senders = application->senders(); - return senders == Origin::Both || senders == application->creator(); - } - - bool amIReceiver() const - { - Q_ASSERT(application); - auto senders = application->senders(); - return senders == Origin::Both || senders == negateOrigin(application->creator()); - } - - bool amICreator() const - { - return application->creator() == pad->session()->role(); - } - inline Jid remoteJid() const { return pad->session()->peer(); @@ -291,7 +274,7 @@ class Transport::Private : public QSharedData { void tryConnectToRemoteCandidate() { - if (application->state() != State::Connecting) { + if (!connectionStarted) { return; // will come back later } quint64 priority = 0; @@ -336,7 +319,7 @@ class Transport::Private : public QSharedData { // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more // local candidates are expected to be discovered - if (application->state() != State::Connecting) { + if (!connectionStarted) { return; // we can't finish anything in this state. Only Connecting is acceptable } @@ -452,7 +435,7 @@ class Transport::Private : public QSharedData { remoteUsedCandidate = Candidate(); } if (localUsedCandidate && remoteUsedCandidate) { - if (amICreator()) { + if (meCreator) { // i'm initiator. see 2.4.4 localUsedCandidate.setState(Candidate::Discarded); localUsedCandidate = Candidate(); @@ -478,6 +461,7 @@ Transport::Transport(const TransportManagerPad::Ptr &pad) : Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : Transport::Transport(pad) { + d->meCreator = false; d->dstaddr = transportEl.attribute(QStringLiteral("dstaddr")); d->sid = transportEl.attribute(QStringLiteral("sid")); if (d->sid.isEmpty() || !update(transportEl)) { @@ -496,18 +480,13 @@ TransportManagerPad::Ptr Transport::pad() const return d->pad.staticCast(); } -void Transport::setApplication(Application *app) +void Transport::prepare() { - d->application = app; - if (app->creator() == d->pad->session()->role()) { // I'm a creator + auto m = static_cast(d->pad->manager()); + if (d->meCreator) { d->sid = d->pad->generateSid(); } d->pad->registerSid(d->sid); -} - -void Transport::prepare() -{ - auto m = static_cast(d->pad->manager()); auto serv = m->socksServ(); if (serv) { @@ -610,9 +589,11 @@ void Transport::prepare() emit updated(); } +// we got content acceptance from any side and not can connect void Transport::start() { - // TODO start connecting to remote candidates + d->connectionStarted = true; + d->tryConnectToRemoteCandidate(); } bool Transport::update(const QDomElement &transportEl) @@ -711,25 +692,15 @@ bool Transport::update(const QDomElement &transportEl) return false; } -Action Transport::outgoingUpdateType() const +bool Transport::hasUpdates() const { - if (isValid() && d->application && d->pendingActions) { - // if we are preparing local offer and have at least one candidate, we have to sent it. - // otherwise it's not first update to remote from this transport, so we have to send just signalling candidates - if ((d->application->state() == State::PrepareLocalOffer && d->localCandidates.size()) || - (d->application->state() > State::PrepareLocalOffer && d->application->state() < State::Finished)) - { - return Action::TransportInfo; - } - } - return Action::NoAction; // TODO + return isValid() && d->pendingActions; } -OutgoingUpdate Transport::takeOutgoingUpdate() +OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() { - OutgoingUpdate upd; - State appState; - if (!isValid() || !d->application || (appState = d->application->state()) == State::Finished) { + OutgoingTransportInfoUpdate upd; + if (!isValid()) { return upd; } @@ -737,7 +708,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() QDomElement tel = doc->createElementNS(NS, "transport"); tel.setAttribute(QStringLiteral("sid"), d->sid); - if (d->amICreator() && d->mode != Tcp) { + if (d->meCreator && d->mode != Tcp) { tel.setAttribute(QStringLiteral("mode"), "udp"); } @@ -765,7 +736,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() } if (!candidatesToSend.isEmpty()) { d->waitingAck = true; - upd = OutgoingUpdate{tel, [this, candidatesToSend]() mutable { + upd = OutgoingTransportInfoUpdate{tel, [this, candidatesToSend]() mutable { d->waitingAck = false; for (auto &c: candidatesToSend) { if (c.state() == Candidate::Unacked) { @@ -787,7 +758,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() c.setState(Candidate::Unacked); d->waitingAck = true; - upd = OutgoingUpdate{tel, [this, c]() mutable { + upd = OutgoingTransportInfoUpdate{tel, [this, c]() mutable { d->waitingAck = false; if (c.state() == Candidate::Unacked) { c.setState(Candidate::Accepted); @@ -803,7 +774,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() // we are here because all remote are already in Discardd state tel.appendChild(doc->createElement(QStringLiteral("candidate-error"))); d->waitingAck = true; - upd = OutgoingUpdate{tel, [this]() mutable { + upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { d->waitingAck = false; d->localReportedCandidateError = true; d->checkAndFinishNegotiation(); @@ -815,7 +786,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() auto el = tel.appendChild(doc->createElement(QStringLiteral("activated"))).toElement(); el.setAttribute(QStringLiteral("cid"), cand.cid()); d->waitingAck = true; - upd = OutgoingUpdate{tel, [this, cand]() mutable { + upd = OutgoingTransportInfoUpdate{tel, [this, cand]() mutable { d->waitingAck = false; if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { return; // seems like state was changed while we was waiting for an ack @@ -831,7 +802,7 @@ OutgoingUpdate Transport::takeOutgoingUpdate() auto cand = d->localUsedCandidate; tel.appendChild(doc->createElement(QStringLiteral("proxy-error"))); d->waitingAck = true; - upd = OutgoingUpdate{tel, [this, cand]() mutable { + upd = OutgoingTransportInfoUpdate{tel, [this, cand]() mutable { d->waitingAck = false; if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { return; // seems like state was changed while we was waiting for an ack diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 320c21bb..e4edb4c1 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -131,13 +131,12 @@ class Transport : public XMPP::Jingle::Transport ~Transport(); TransportManagerPad::Ptr pad() const override; - void setApplication(Application *app) override; void prepare() override; void start() override; bool update(const QDomElement &transportEl) override; - Action outgoingUpdateType() const override; - OutgoingUpdate takeOutgoingUpdate() override; + bool hasUpdates() const override; + OutgoingTransportInfoUpdate takeOutgoingUpdate() override; bool isValid() const override; Features features() const override; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 412b2021..8c0ef35d 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace XMPP { namespace Jingle { @@ -583,12 +584,26 @@ class Session::Private //QMap remoteContent; // content::creator=(role == Session::Role::Responder?initiator:responder) QMap contentList; QSet signalingContent; + QHash outgoingUpdates; // session level updates. session-info for example or some rejected apps QString sid; Jid origFrom; // "from" attr of IQ. Jid otherParty; // either "from" or initiator/responder. it's where to send all requests. Jid localParty; // that one will be set as initiator/responder if provided bool waitingAck = false; + void setSessionFinished() + { + state = State::Finished; + emit q->terminated(); + signalingContent.clear(); + auto vals = contentList.values(); + contentList.clear(); + while (vals.size()) { + vals.takeLast()->deleteLater(); + } + q->deleteLater(); + } + void sendJingle(Action action, QList update, std::function successCB = std::function()) { QDomDocument &doc = *manager->client()->doc(); @@ -616,10 +631,8 @@ class Session::Private planStep(); } } else { - state = State::Finished; lastError = jt->error(); - emit q->terminated(); - q->deleteLater(); + setSessionFinished(); } }); waitingAck = true; @@ -644,14 +657,29 @@ class Session::Private if (state != State::Created || role == Origin::Responder) { sendJingle(Action::SessionTerminate, QList() << terminateReason.toXml(manager->client()->doc())); } - state = State::Finished; - q->deleteLater(); - emit q->terminated(); + setSessionFinished(); return; } if (state == State::Created || state == State::Finished) { return; // we will start doing something when initiate() is called } + + if (outgoingUpdates.size()) { + auto it = outgoingUpdates.begin(); + auto action = it.key(); + auto updates = it.value(); + auto elements = std::get<0>(updates); + auto cb = std::get<1>(updates); + outgoingUpdates.erase(it); + sendJingle(action, elements, [this, cb](){ + if (cb) { + cb(); + } + planStep(); + }); + return; + } + typedef std::tuple,OutgoingUpdateCB> AckHndl; // will be used from callback on iq ack if (state == State::PrepareLocalOffer) { // we are going to send session-initiate/accept (already accepted by the user but not sent yet) /* @@ -671,9 +699,7 @@ class Session::Private auto out = c->outgoingUpdateType(); if (out == Action::ContentReject) { // yeah we are rejecting local content. invalid? lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - state = State::Finished; - q->deleteLater(); - emit q->terminated(); + setSessionFinished(); return; } if (out != expectedContentAction) { @@ -695,10 +721,10 @@ class Session::Private if (p->creator() != role) { continue; // we care only about local content for now. } - QDomElement xml; + QList xml; OutgoingUpdateCB callback; std::tie(xml, callback) = p->takeOutgoingUpdate(); - contents.append(xml); + contents += xml; //p->setState(State::Unacked); if (callback) { acceptApps.append(AckHndl{p, callback}); @@ -739,7 +765,7 @@ class Session::Private QMultiMap updates; - for (auto app : contentList) { + for (auto app : signalingContent) { Action updateType = app->outgoingUpdateType(); if (updateType != Action::NoAction) { updates.insert(updateType, app); @@ -748,13 +774,13 @@ class Session::Private QList acceptApps; if (updates.size()) { - Action action = updates.begin().key(); + Action action = updates.begin().key(); // NOTE maybe some actions have more priority than another auto apps = updates.values(action); for (auto app: apps) { - QDomElement xml; + QList xml; OutgoingUpdateCB callback; std::tie(xml, callback) = app->takeOutgoingUpdate(); - updateXml.append(xml); + updateXml += xml; if (callback) { acceptApps.append(AckHndl{app, callback}); } @@ -785,13 +811,37 @@ class Session::Private return reason; } + void addAndInitContent(Origin creator, Application *content) + { + contentList.insert(ContentKey{content->contentName(), creator}, content); + if (state != State::Created && content->outgoingUpdateType() != Action::NoAction) { + signalingContent.insert(content); + } + QObject::connect(content, &Application::updated, q, [this, content](){ + signalingContent.insert(content); + if (!waitingAck && !stepTimer.isActive()) { + stepTimer.start(); + } + }); + QObject::connect(content, &Application::destroyed, q, [this, content](){ + signalingContent.remove(content); + for (auto it = contentList.begin(); it != contentList.end(); ++it) { // optimize for large lists? + if (it.value() == content) { + contentList.erase(it); + break; + } + } + }); + } + enum AddContentError { Ok, Unparsed, + Unexpected, Unsupported }; - std::tuple parseContent(const QDomElement &ce) + std::tuple parseContentAdd(const QDomElement &ce) { QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); @@ -837,7 +887,7 @@ class Session::Private typedef std::tuple, QList> ParseContentListResult; - ParseContentListResult parseContentList(const QDomElement &jingleEl) + ParseContentListResult parseContentAddList(const QDomElement &jingleEl) { QMap addSet; QMap> rejectSet; @@ -851,7 +901,7 @@ class Session::Private Reason::Condition cond; Application *app; - std::tie(err, cond, app) = parseContent(ce); + std::tie(err, cond, app) = parseContentAdd(ce); if (err == Private::AddContentError::Unparsed) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); qDeleteAll(addSet); @@ -875,7 +925,11 @@ class Session::Private rejectSet.remove(contentName); if (it == addSet.end() || (*it)->wantBetterTransport(app->transport())) { // probably not wantBetterTransport but wantBetterApplication delete *it; // unpreferred app - *it = app; + if (it == addSet.end()) { + addSet.insert(contentName, app); + } else { + *it = app; + } } } @@ -889,6 +943,197 @@ class Session::Private return ParseContentListResult(Ok, Reason::Success, addSet.values(), QList()); } + + std::tuple parseContentAccept(const QDomElement &ce) + { + QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); + QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); + QString descriptionNS = descriptionEl.attribute(QStringLiteral("xmlns")); + QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + typedef std::tuple result; + + ContentBase c(ce); + if (!c.isValid() || role != c.creator || descriptionEl.isNull() || transportEl.isNull() || + descriptionNS.isEmpty() || transportNS.isEmpty()) + { + return result{Unparsed, Reason::NoReason, nullptr}; + } + + auto app = q->content(c.name, role); + if (!(app && app->state() == State::Pending)) { // reaccept is possible + return result{AddContentError::Unexpected, Reason::NoReason, app}; + } + + if (app->pad()->ns() != descriptionNS || app->transport()->pad()->ns() != transportNS) { + // well it's more than unexpected. let's send unparsed + return result{AddContentError::Unparsed, Reason::NoReason, app}; + } + + if (!app->transport()->update(transportEl) || !app->accept(descriptionEl)) { + // clearly unparsed. otherwise the app will generate failure event with a Reason. + return result{AddContentError::Unparsed, Reason::NoReason, app}; + } + + if (app->state() != State::Accepted) { // parsed but was not accepted. so it's somehow incompatible + return result{AddContentError::Unsupported, Reason::IncompatibleParameters, app}; + } + + return result{AddContentError::Ok, Reason::Success, app}; + } + + std::tuple> parseContentAcceptList(const QDomElement &jingleEl) + { + QMap acceptSet; + QMap> rejectSet; + + QString contentTag(QStringLiteral("content")); + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + + Private::AddContentError err; + Reason::Condition cond; + Application *app; + + std::tie(err, cond, app) = parseContentAccept(ce); + if (err == Private::AddContentError::Unparsed || err == Private::AddContentError::Unexpected) { + for (auto &a: acceptSet) { + a->setState(State::Pending); // reset state to pending for already passed validation before passing error back + } + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, err == Private::AddContentError::Unexpected? + XMPP::Stanza::Error::UnexpectedRequest : XMPP::Stanza::Error::BadRequest); + return std::tuple>(false, QList()); + } + + auto contentName = app->contentName(); + auto it = acceptSet.find(contentName); + auto rit = rejectSet.find(contentName); + if (it != acceptSet.end() || rit != rejectSet.end()) { + // duplicates are not allowed in accept request + for (auto &a: acceptSet) { + a->setState(State::Pending); // reset state to pending for already passed validation before passing error back + } + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return std::tuple>(false, QList()); + } + + if (err != Private::AddContentError::Ok) { + app->setState(State::Finished); // we can't keep working with this content for whatever reason. if "accept" failed there is no fallback + rejectSet.insert(contentName, std::make_pair(ce, cond)); // NOTE, probably instead of ce we have to generate original description + continue; + } + acceptSet.insert(contentName, app); + } + + if (rejectSet.size()) { + QTimer::singleShot(0, q, [this, rejectSet]() mutable { + auto cond = rejectSet.first().second; + QList rejects; + for (auto const &i: rejectSet) { + rejects.append(i.first); + } + rejects += Reason(cond).toXml(manager->client()->doc()); + outgoingUpdates.insert( + Action::ContentRemove, + OutgoingUpdate{ + rejects, + [this, rejects]() { + for (auto &r: rejects) { + ContentBase c(r); + delete contentList.take(ContentKey{c.name, role}); + } + if (contentList.isEmpty()) { + // the other party has to generate session-terminate but we do not care already + setSessionFinished(); + } + } + }); + }); + } + return std::tuple>(true, acceptSet.values()); + } + + + bool handleIncomingContentAdd(const QDomElement &jingleEl) + { + Private::AddContentError err; + Reason::Condition cond; + QList apps; + QList rejects; + + std::tie(err, cond, apps, rejects) = parseContentAddList(jingleEl); + switch (err) { + case Private::AddContentError::Unparsed: + case Private::AddContentError::Unexpected: + return false; + case Private::AddContentError::Unsupported: + rejects += Reason(cond).toXml(manager->client()->doc()); + outgoingUpdates.insert(Action::ContentReject, OutgoingUpdate{rejects, OutgoingUpdateCB()}); + break; + case Private::AddContentError::Ok: + break; + } + + if (apps.size()) { + Origin remoteRole = negateOrigin(role); + for (auto app: apps) { + addAndInitContent(remoteRole, app); // TODO check conflicts + } + QTimer::singleShot(0, q, [this](){ emit q->newContentReceived(); }); + } + planStep(); + + return true; + } + + bool handleIncomingSessionTerminate(const QDomElement &jingleEl) + { + terminateReason = Reason(jingleEl.firstChildElement(QString::fromLatin1("reason"))); + setSessionFinished(); + return true; + } + + bool handleIncomingSessionAccept(const QDomElement &jingleEl) + { + bool parsed; + QList apps; + + std::tie(parsed, apps) = parseContentAcceptList(jingleEl); + if (!parsed) { + return false; + } + + state = State::Connecting; + if (apps.size()) { + for (auto app: apps) { + app->start(); + } + } + QTimer::singleShot(0, q, [this](){ emit q->activated(); }); + planStep(); + + return true; + } + + bool handleIncomingContentAccept(const QDomElement &jingleEl) + { + bool parsed; + QList apps; + + std::tie(parsed, apps) = parseContentAcceptList(jingleEl); // marks valid apps as accepted + if (!parsed) { + return false; + } + + if (apps.size() && state >= State::Active) { + for (auto app: apps) { + app->start(); // start accepted app. connection establishing and data transfer are inside + } + } + planStep(); + + return true; + } }; Session::Session(Manager *manager, const Jid &peer) : @@ -964,16 +1209,7 @@ Application *Session::content(const QString &contentName, Origin creator) void Session::addContent(Application *content) { - d->contentList.insert(ContentKey{content->contentName(), d->role}, content); - if (d->state != State::Created && content->outgoingUpdateType() != Action::NoAction) { - d->signalingContent.insert(content); - } - connect(content, &Application::updated, this, [this](){ - d->signalingContent.insert(static_cast(sender())); - if (!d->waitingAck && !d->stepTimer.isActive()) { - d->stepTimer.start(); - } - }); + d->addAndInitContent(d->role, content); } const QMap &Session::contentList() const @@ -1089,20 +1325,18 @@ bool Session::incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl QList apps; QList rejects; - std::tie(err, cond, apps, rejects) = d->parseContentList(jingleEl); + std::tie(err, cond, apps, rejects) = d->parseContentAddList(jingleEl); switch (err) { case Private::AddContentError::Unparsed: + case Private::AddContentError::Unexpected: return false; case Private::AddContentError::Unsupported: - QTimer::singleShot(0, this, [this, cond](){ - d->sendJingle(Action::SessionTerminate, QList() << Reason(cond).toXml(d->manager->client()->doc())); - d->state = State::Finished; - emit terminated(); - }); + d->terminateReason = Reason(cond); + d->planStep(); return true; case Private::AddContentError::Ok: for (auto app: apps) { - d->contentList.insert(ContentKey{app->contentName(), Origin::Initiator}, app); + d->addAndInitContent(Origin::Initiator, app); } d->planStep(); return true; @@ -1118,42 +1352,43 @@ bool Session::updateFromXml(Action action, const QDomElement &jingleEl) return false; } - if (action == Action::SessionInfo) { - - } - - if (action == Action::ContentAdd) { - Private::AddContentError err; - Reason::Condition cond; - QList apps; - QList rejects; - - std::tie(err, cond, apps, rejects) = d->parseContentList(jingleEl); - switch (err) { - case Private::AddContentError::Unparsed: - return false; - case Private::AddContentError::Unsupported: - QTimer::singleShot(0, this, [this, cond, rejects]() mutable { - rejects += Reason(cond).toXml(d->manager->client()->doc()); - d->sendJingle(Action::ContentReject, rejects); - }); - break; - case Private::AddContentError::Ok: - break; - } - - if (apps.size()) { - Origin remoteRole = negateOrigin(d->role); - for (auto app: apps) { - d->contentList.insert(ContentKey{app->contentName(), remoteRole}, app); // TODO check conflicts - } - QTimer::singleShot(0, this, [this](){ emit newContentReceived(); }); - } - - return true; + switch (action) { + case Action::ContentAccept: + return d->handleIncomingContentAccept(jingleEl); + case Action::ContentAdd: + return d->handleIncomingContentAdd(jingleEl); + case Action::ContentModify: + break; + case Action::ContentReject: + break; + case Action::ContentRemove: + break; + case Action::DescriptionInfo: + break; + case Action::SecurityInfo: + break; + case Action::SessionAccept: + return d->handleIncomingSessionAccept(jingleEl); + case Action::SessionInfo: + break; + case Action::SessionInitiate: // impossible case. but let compiler be happy + break; + case Action::SessionTerminate: + return d->handleIncomingSessionTerminate(jingleEl); + case Action::TransportAccept: + break; + case Action::TransportInfo: + break; + case Action::TransportReject: + break; + case Action::TransportReplace: + break; + case Action::NoAction: + default: + break; } - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::FeatureNotImplemented); return false; } diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index c5e6f77c..fb32c9b2 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -51,15 +51,28 @@ inline uint qHash(const XMPP::Jingle::Origin &o, uint seed = 0) return ::qHash(int(o), seed); } +/* + Session states: + * Created - new session + * PrepareLocalOffer - user accepted session but it's not yet ready for session-initiate/accept message + * Unacked - session-initiate/accept was sent. wait for IQ ack + * Pending - session-initiate was acknowledged. awaits session-accept. + * Active - session was accepted and now active. + * Finihed - session-terminate was sent/received + + Locally initiated session passes all the above and remotely initiated skips Pending. +*/ enum class State { Created, // just after constructor PrepareLocalOffer, // content accepted by local user but we are not ready yet to send content-accept or session-accept. // same for content-add/session-initiate, where user already already sent/added in ui and it's network turn. - Unacked, // local conten offer is sent to remote but no IQ ack yet + Unacked, // local content offer is sent to remote but no IQ ack yet Pending, // waits for session-accept or content-accept from remote - Connecting, // s5b/ice probes etc (particular application state. can be omited for other entities) - Active, // active transfer. transport is connected - Finished // transfering is finished for whatever reason + Accepted, // app only: local: "accept" received, waits for start(). remote: "accept" sent and acknowledged, waits for start() + Connecting, // app only: s5b/ice probes etc (particular application state. can be omited for other entities) + Active, // active transfer. transport is connected. For session it means it was accepted + Finishing, // app only: basically it's finished but has some pending operations. like sending content-reject/remove to remote + Finished // transfering is finished for whatever reason. no more signals/state changes etc. can be deleted }; enum class Action { @@ -81,9 +94,15 @@ enum class Action { TransportReplace }; +inline uint qHash(const XMPP::Jingle::Action &o, uint seed = 0) +{ + return ::qHash(int(o), seed); +} + typedef QPair ContentKey; typedef std::function OutgoingUpdateCB; -typedef std::tuple OutgoingUpdate; +typedef std::tuple, OutgoingUpdateCB> OutgoingUpdate; // list of elements to b inserted to and success callback +typedef std::tuple OutgoingTransportInfoUpdate; // transport element and success callback class Jingle { @@ -286,12 +305,11 @@ class Transport : public QObject { // for remote transport try to connect to all proposed hosts in order their priority. // in-band transport may just emit updated() here virtual bool update(const QDomElement &el) = 0; // accepts transport element on incoming transport-info - virtual Action outgoingUpdateType() const = 0; - virtual OutgoingUpdate takeOutgoingUpdate() = 0; + virtual bool hasUpdates() const = 0; + virtual OutgoingTransportInfoUpdate takeOutgoingUpdate() = 0; virtual bool isValid() const = 0; virtual Features features() const = 0; virtual TransportManagerPad::Ptr pad() const = 0; - virtual void setApplication(Application *) = 0; signals: void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler. // if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent. @@ -336,6 +354,7 @@ class Application : public QObject * When ready, the application first set update type to ContentAdd and then emit updated() */ virtual void prepare() = 0; + virtual bool accept(const QDomElement &el) = 0; // remote accepted our content virtual void start() = 0; signals: From 46b55f6b3f75be43f3e882f7d0b16338b1541d40 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 11 May 2019 11:01:34 +0300 Subject: [PATCH 008/383] jingle-s5b: socks5 connection establishment --- src/irisnet/noncore/cutestuff/socks.cpp | 10 +- src/xmpp/xmpp-im/jingle-ft.cpp | 66 +++++- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle-s5b.cpp | 265 ++++++++++++++++++++---- src/xmpp/xmpp-im/jingle-s5b.h | 18 +- src/xmpp/xmpp-im/jingle.cpp | 10 + src/xmpp/xmpp-im/jingle.h | 53 ++++- src/xmpp/xmpp-im/s5b.cpp | 12 +- src/xmpp/xmpp-im/s5b.h | 2 + 9 files changed, 379 insertions(+), 58 deletions(-) diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index 7dd8f4f6..8162ca65 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -1126,12 +1126,14 @@ void SocksServer::connectionError() void SocksServer::sd_activated() { while (d->sd->hasPendingDatagrams()) { - QByteArray datagram; + QByteArray datagram(d->sd->pendingDatagramSize(), Qt::Uninitialized); QHostAddress sender; quint16 senderPort; - datagram.resize(d->sd->pendingDatagramSize()); - d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); - incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram); + auto sz = d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + if (sz >= 0) { + datagram.truncate(sz); + incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram); + } } } diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index f5def76c..ab4363ee 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -380,7 +380,7 @@ QStringList Manager::availableTransports() const class Application::Private { public: - + Application *q = nullptr; State state = State::Created; QSharedPointer pad; QString contentName; @@ -389,11 +389,19 @@ class Application::Private Origin senders; QSharedPointer transport; QStringList availableTransports; + bool transportFailed = false; + + void setState(State s) + { + state = s; + emit q->stateChanged(s); + } }; Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : d(new Private) { + d->q = this; d->pad = pad; d->contentName = contentName; d->creator = creator; @@ -456,6 +464,9 @@ File Application::file() const // incoming one? or we have to check real direction bool Application::setTransport(const QSharedPointer &transport) { + if (d->transport) { + d->transport->disconnect(this); + } if (transport->features() & Transport::Reliable) { int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); if (nsIndex == -1) { @@ -463,7 +474,18 @@ bool Application::setTransport(const QSharedPointer &transport) } d->availableTransports.removeAt(nsIndex); d->transport = transport; - d->state = State::Pending; + d->setState(State::Pending); + connect(transport.data(), &Transport::updated, this, &Application::updated); + connect(transport.data(), &Transport::connected, this, [this](){ + + }); + connect(transport.data(), &Transport::failed, this, [this](){ + if (d->availableTransports.size()) { // we can do transport-replace here + // TODO + } + d->transportFailed = true; + d->setState(State::Finishing); + }); return true; } return false; @@ -491,6 +513,11 @@ Action Application::outgoingUpdateType() const return Action::TransportInfo; } break; + case State::Finishing: + if (d->transportFailed) { + return Action::ContentRemove; + } + return Action::SecurityInfo; default: break; } @@ -526,7 +553,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); cel.appendChild(tel); - d->state = State::Unacked; + d->setState(State::Unacked); return OutgoingUpdate{QList()<()<state == State::Finishing) { + if (d->transportFailed) { + ContentBase cb(d->pad->session()->role(), d->contentName); + QList updates; + updates << cb.toXml(doc, "content"); + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); + return OutgoingUpdate{updates, [this](){ + d->setState(State::Finished); + } + }; + } + // else send + ContentBase cb(d->pad->session()->role(), d->contentName); + return OutgoingUpdate{QList() << cb.toXml(doc, "received"), [this](){ + d->setState(State::Finished); + } + }; + } return OutgoingUpdate(); // TODO } @@ -558,9 +603,7 @@ bool Application::wantBetterTransport(const QSharedPointer &t) const bool Application::selectNextTransport() { if (d->availableTransports.size()) { - QString ns = d->availableTransports.takeFirst(); - d->transport = d->pad->session()->newOutgoingTransport(ns); - return true; + return setTransport(d->pad->session()->newOutgoingTransport(d->availableTransports.first())); } return false; } @@ -582,13 +625,18 @@ void Application::start() d->state = State::Active; d->transport->start(); } - // TODO we nedd QIODevice somewhere here + // TODO we need QIODevice somewhere here } bool Application::accept(const QDomElement &el) { - Q_UNUSED(el); - return true; // TODO!!! + File f(el.firstChildElement("file")); + if (!f.isValid()) { + return false; + } + // TODO validate if accept file matches to the offer + setState(State::Accepted); + return true; } bool Application::isValid() const diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index e2c2171c..20f23098 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -21,6 +21,7 @@ #define JINGLEFT_H #include "jingle.h" +#include "xmpp_hash.h" namespace XMPP { diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 15b6295c..718d0b0d 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -22,7 +22,9 @@ #include "xmpp/jid/jid.h" #include "xmpp_client.h" #include "xmpp_serverinfomanager.h" +#include "socks.h" +#include #include namespace XMPP { @@ -31,15 +33,51 @@ namespace S5B { const QString NS(QStringLiteral("urn:xmpp:jingle:transports:s5b:1")); +static QString makeKey(const QString &sid, const Jid &j1, const Jid &j2) +{ + return QString::fromLatin1(QCryptographicHash::hash((sid + + j1.full() + + j2.full()).toUtf8(), + QCryptographicHash::Sha1)); +} + +class Connection : public XMPP::Jingle::Connection +{ + Q_OBJECT + + QList datagrams; +public: + bool hasPendingDatagrams() const + { + return datagrams.size() > 0; + } + + NetworkDatagram receiveDatagram(qint64 maxSize = -1) + { + Q_UNUSED(maxSize); // TODO or not? + return datagrams.size()? datagrams.takeFirst(): NetworkDatagram(); + } +protected: + friend class Transport; + void enqueueIncomingUDP(const QByteArray &data) + { + datagrams.append(NetworkDatagram{data}); + emit readyRead(); + } +}; + class Candidate::Private : public QSharedData { public: QString cid; QString host; Jid jid; - quint16 port; - quint32 priority; + quint16 port = 0; + quint32 priority = 0; Candidate::Type type = Candidate::Direct; Candidate::State state = Candidate::New; + + quint16 localPort = 0; // where Psi actually listens. e.g. with NAT-assited candidats it may be different from just port + SocksClient *socksClient = nullptr; }; Candidate::Candidate() @@ -133,12 +171,15 @@ Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type } else { d->priority = 0; } + if (type == Direct) { + d->localPort = port; + } d->state = New; } Candidate::~Candidate() { - + delete d->socksClient; } Candidate::Type Candidate::type() const @@ -176,6 +217,16 @@ void Candidate::setPort(quint16 port) d->port = port; } +quint16 Candidate::localPort() const +{ + return d->localPort; +} + +void Candidate::setLocalPort(quint16 port) +{ + d->localPort = port; +} + Candidate::State Candidate::state() const { return d->state; @@ -211,10 +262,30 @@ QDomElement Candidate::toXml(QDomDocument *doc) const return e; } -void Candidate::connectToHost(std::function callback) +void Candidate::connectToHost(const QString &key, std::function callback, bool isUdp) { // TODO negotiate socks5 connection to host and port - Q_UNUSED(callback) + d->socksClient = new SocksClient; + + QObject::connect(d->socksClient, &SocksClient::connected, [this, callback](){ + callback(true); + }); + QObject::connect(d->socksClient, &SocksClient::error, [this, callback](int error){ + Q_UNUSED(error); + callback(false); + }); + //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); + + d->socksClient->connectToHost(d->host, d->port, key, 0, isUdp); +} + +bool Candidate::incomingConnection(SocksClient *sc) +{ + if (d->socksClient) { + return false; + } + d->socksClient = sc; + return false; } class Transport::Private : public QSharedData { @@ -244,9 +315,20 @@ class Transport::Private : public QSharedData { QMap remoteCandidates; Candidate localUsedCandidate; // we received "candidate-used" for this candidate from localCandidates list Candidate remoteUsedCandidate; // we sent "candidate-used" for this candidate from remoteCandidates list - QString dstaddr; + QString dstaddr; // an address for xmpp proxy as it comes from remote. each side calculates it like sha1(sid + local jid + remote jid) + QString directAddr; // like dstaddr but for direct connection. Basically it's sha1(sid + initiator jid + responder jid) QString sid; Transport::Mode mode = Transport::Tcp; + QTimer probingTimer; + QElapsedTimer lastConnectionStart; + + QSharedPointer connection; + + // udp stuff + bool udpInitialized; + quint16 udpPort; + QHostAddress udpAddress; + inline Jid remoteJid() const { @@ -277,18 +359,63 @@ class Transport::Private : public QSharedData { if (!connectionStarted) { return; // will come back later } - quint64 priority = 0; - Candidate candidate; + quint64 maxProbingPrio = 0; + quint64 maxNewPrio = 0; + Candidate maxProbing; + Candidate maxNew; + + /* + We have to find highest-priority already connecting candidate and highest-priority new candidate. + If already-connecting is not found then start connecting to new if it's found. + If both already-connecting and new are found then + if new candidate has higher priority or the same priority then start connecting + else ensure the new candidate starts connecting in 200ms after previous connection attempt + (if it's in future then reschedule this call for future) + In all the other cases just return and wait for events. + */ + for (auto &c: remoteCandidates) { - if ((c.state() == Candidate::New || c.state() == Candidate::Probing) && c.priority() > priority) { - candidate = c; - priority = c.priority(); + if (c.state() == Candidate::New && c.priority() > maxNewPrio) { + maxNew = c; + maxNewPrio = c.priority(); + } + if (c.state() == Candidate::Probing && c.priority() > maxProbingPrio) { + maxProbing = c; + maxProbingPrio = c.priority(); } } - if (candidate && candidate.state() == Candidate::Probing) { - return; // already trying connection + if (!maxNew) { + return; // nowhere to connect + } + + if (maxProbing) { + if (maxNew.priority() < maxProbing.priority()) { + if (probingTimer.isActive()) { + return; // we will come back here soon + } + qint64 msToFuture = 200 - lastConnectionStart.elapsed(); + if (msToFuture > 0) { // seems like we have to rescheduler for future + probingTimer.start(int(msToFuture)); + return; + } + } } - // TODO start connecting to the candidate here + + // now we have to connect to maxNew candidate + lastConnectionStart.start(); + QString key = maxNew.type() == Candidate::Proxy? dstaddr : directAddr; + maxNew.connectToHost(key, [this, maxNew](bool success) { + // candidate's status had to be changed by connectToHost, so we don't set it again + // if our candidate has higher priority than any of local or remoteUsedCandidate then set it as "used" + if (success && (!remoteUsedCandidate || remoteUsedCandidate.priority() < maxNew.priority()) && + ((!localUsedCandidate || localUsedCandidate.priority() < maxNew.priority()))) + { + remoteUsedCandidate = maxNew; + localUsedCandidate = Candidate(); + updateMinimalPriority(); + } + checkAndFinishNegotiation(); + }, mode == Transport::Udp); } bool hasUnaknowledgedLocalCandidates() const @@ -347,14 +474,15 @@ class Transport::Private : public QSharedData { // If it's proxy, first it has to be activated if (localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate - c.connectToHost([this](bool success){ + auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); + c.connectToHost(key, [this](bool success){ if (success) { pendingActions |= Private::Activated; } else { pendingActions |= Private::ProxyError; } emit q->updated(); - }); + }, mode == Transport::Udp); } // else so it's remote proxy. let's just wait for from remote } else { c.setState(Candidate::Active); @@ -452,6 +580,8 @@ Transport::Transport(const TransportManagerPad::Ptr &pad) : { d->q = this; d->pad = pad.staticCast(); + d->probingTimer.setSingleShot(true); + d->probingTimer.callOnTimeout([this](){ d->tryConnectToRemoteCandidate(); }); connect(pad->manager(), &TransportManager::abortAllRequested, this, [this](){ d->aborted = true; emit failed(); @@ -472,7 +602,7 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::~Transport() { - + static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); } TransportManagerPad::Ptr Transport::pad() const @@ -487,6 +617,9 @@ void Transport::prepare() d->sid = d->pad->generateSid(); } d->pad->registerSid(d->sid); + d->directAddr = makeKey(d->sid, d->pad->session()->initiator(), d->pad->session()->responder()); + m->addKeyMapping(d->directAddr, this); + auto serv = m->socksServ(); if (serv) { @@ -728,10 +861,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() c.setState(Candidate::Unacked); } if (useProxy) { - QString dstaddr = QCryptographicHash::hash((d->sid + - d->pad->session()->me().full() + - d->pad->session()->peer().full()).toUtf8(), - QCryptographicHash::Sha1); + QString dstaddr = makeKey(d->sid, d->pad->session()->me(), d->pad->session()->peer()); tel.setAttribute(QStringLiteral("dstaddr"), dstaddr); } if (!candidatesToSend.isEmpty()) { @@ -832,25 +962,60 @@ QString Transport::sid() const return d->sid; } -bool Transport::incomingConnection(SocksClient *sc, const QString &key) +bool Transport::incomingConnection(SocksClient *sc) { - // incoming direct connection -#if 0 - if(!d->allowIncoming) { - sc->requestDeny(); - sc->deleteLater(); - return; + if (!d->connection) { + for (auto &c: d->localCandidates) { + auto s = sc->abstractSocket(); + if (s->localPort() == c.localPort() && c.state() == Candidate::Pending) { + if(d->mode == Transport::Udp) + sc->grantUDPAssociate("", 0); + else + sc->grantConnect(); + // we can also remember the server it comes from. static_cast(sender()) + return c.incomingConnection(sc); + } + } } - if(d->mode == Transport::Udp) - sc->grantUDPAssociate("", 0); - else - sc->grantConnect(); - e->relatedServer = static_cast(sender()); - e->i->setIncomingClient(sc); -#endif + + sc->requestDeny(); + sc->deleteLater(); return false; } +bool Transport::incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data) +{ + if (d->mode != Transport::Mode::Udp) { + return false; + } + + if(init) { + // TODO probably we could create a Connection here and put all the params inside + if(d->udpInitialized) + return false; // only init once + + // lock on to this sender + d->udpAddress = addr; + d->udpPort = port; + d->udpInitialized = true; + + // reply that initialization was successful + d->pad->session()->manager()->client()->s5bManager()->jtPush()->sendUDPSuccess(d->pad->session()->peer(), key); // TODO fix ->->-> + return true; + } + + // not initialized yet? something went wrong + if(!d->udpInitialized) + return false; + + // must come from same source as when initialized + if(addr != d->udpAddress || port != d->udpPort) + return false; + + d->connection->enqueueIncomingUDP(data); // man_udpReady + return true; +} + //---------------------------------------------------------------- // Manager //---------------------------------------------------------------- @@ -919,6 +1084,15 @@ void Manager::setServer(S5BServer *serv) if(d->serv) { d->serv->unlink(this); d->serv = nullptr; + + auto jt = d->jingleManager->client()->s5bManager()->jtPush(); + connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { + Q_UNUSED(from); + auto t = d->key2transport.value(dstaddr); + if (t) { + // TODO return t->incomingUDPSuccess(from); + } + }, Qt::UniqueConnection); } if(serv) { @@ -927,11 +1101,30 @@ void Manager::setServer(S5BServer *serv) } } +void Manager::addKeyMapping(const QString &key, Transport *transport) +{ + d->key2transport.insert(key, transport); +} + +void Manager::removeKeyMapping(const QString &key) +{ + d->key2transport.remove(key); +} + bool Manager::incomingConnection(SocksClient *client, const QString &key) { auto t = d->key2transport.value(key); if (t) { - return t->incomingConnection(client, key); + return t->incomingConnection(client); + } + return false; +} + +bool Manager::incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data) +{ + auto t = d->key2transport.value(key); + if (t) { + return t->incomingUDP(init, addr, port, key, data); } return false; } diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index e4edb4c1..01cc7978 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -31,6 +31,7 @@ #include "jingle.h" +class QHostAddress; class SocksClient; namespace XMPP { @@ -104,13 +105,16 @@ class Candidate { void setHost(const QString &host); quint16 port() const; void setPort(quint16 port); + quint16 localPort() const; + void setLocalPort(quint16 port); State state() const; void setState(State s); quint32 priority() const; QDomElement toXml(QDomDocument *doc) const; - void connectToHost(std::function callback); + void connectToHost(const QString &key, std::function callback, bool isUdp = false); + bool incomingConnection(SocksClient *sc); private: class Private; QExplicitlySharedDataPointer d; @@ -140,11 +144,12 @@ class Transport : public XMPP::Jingle::Transport bool isValid() const override; Features features() const override; - QString sid() const; - - bool incomingConnection(SocksClient *sc, const QString &key); - + QString sid() const; private: + friend class S5BServer; + bool incomingConnection(SocksClient *sc); + bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); + friend class Manager; static QSharedPointer createOutgoing(const TransportManagerPad::Ptr &pad); static QSharedPointer createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); @@ -188,12 +193,15 @@ class Manager : public TransportManager { void setServer(S5BServer *serv); bool incomingConnection(SocksClient *client, const QString &key); // returns false if key is unknown + bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); QString generateSid(const Jid &remote); void registerSid(const Jid &remote, const QString &sid); S5BServer* socksServ() const; Jid userProxy() const; + void addKeyMapping(const QString &key, Transport *transport); + void removeKeyMapping(const QString &key); private: class Private; QScopedPointer d; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 8c0ef35d..107bac98 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1588,6 +1588,16 @@ Origin negateOrigin(Origin o) return Origin::None; } +bool Connection::hasPendingDatagrams() const +{ + return false; +} + +NetworkDatagram Connection::receiveDatagram(qint64 maxSize) +{ + return NetworkDatagram(); +} + } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index fb32c9b2..e2c06657 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -20,11 +20,16 @@ #ifndef JINGLE_H #define JINGLE_H -#include "xmpp_hash.h" +#include "bytestream.h" #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(5,8,0) +# include +#endif + +#include "xmpp_stanza.h" class QDomElement; class QDomDocument; @@ -249,6 +254,47 @@ class ApplicationManagerPad : public SessionManagerPad virtual QString generateContentName(Origin senders) = 0; }; +#if QT_VERSION < QT_VERSION_CHECK(5,8,0) +// stub implementation +class NetworkDatagram +{ +public: + bool _valid = false; + QByteArray _data; + inline NetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress = QHostAddress(), quint16 port = 0) : + _valid(true), + _data(data) + { + Q_UNUSED(destinationAddress); + Q_UNUSED(port) + } + inline NetworkDatagram(){} + + inline bool isValid() const { return _valid; } + inline QByteArray data() const { return _data; } +} +#else +typedef QNetworkDatagram NetworkDatagram; +#endif + +class Connection : public ByteStream +{ + Q_OBJECT + + QList datagrams; +public: + virtual bool hasPendingDatagrams() const; + virtual NetworkDatagram receiveDatagram(qint64 maxSize = -1); + +protected: + friend class Transport; + void enqueueIncomingUDP(const QByteArray &data) + { + datagrams.append(data); + emit readyRead(); + } +}; + class Application; class Transport : public QObject { Q_OBJECT @@ -330,7 +376,7 @@ class Application : public QObject virtual ApplicationManagerPad::Ptr pad() const = 0; virtual State state() const = 0; - virtual void setState(State state) = 0; // likely just remember the state + virtual void setState(State state) = 0; // likely just remember the state and not generate any signals virtual Origin creator() const = 0; virtual Origin senders() const = 0; @@ -358,7 +404,8 @@ class Application : public QObject virtual void start() = 0; signals: - void updated(); + void updated(); // signal for session it has to send updates to remote. so it will follow with takeOutgoingUpdate() eventually + void stateChanged(State); }; class Session : public QObject diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index 2839ac39..884445cd 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -632,6 +632,11 @@ void S5BManager::setServer(S5BServer *serv) } } +JT_PushS5B* S5BManager::jtPush() const +{ + return d->ps; +} + BSConnection *S5BManager::createConnection() { return new S5BConnection(this); @@ -2102,7 +2107,12 @@ void S5BServer::ss_incomingUDP(const QString &host, int port, const QHostAddress if(port != 0 && port != 1) return; - // TODO check jingle managers too + for (Jingle::S5B::Manager *m: d->jingleManagerList) { + if (m->incomingUDP(port == 1 ? true : false, addr, sourcePort, host, data)) { + return; + } + } + foreach(S5BManager* m, d->manList) { if(m->srv_ownsHash(host)) { m->srv_incomingUDP(port == 1 ? true : false, addr, sourcePort, host, data); diff --git a/src/xmpp/xmpp-im/s5b.h b/src/xmpp/xmpp-im/s5b.h index 1cd62515..2fca6c6d 100644 --- a/src/xmpp/xmpp-im/s5b.h +++ b/src/xmpp/xmpp-im/s5b.h @@ -46,6 +46,7 @@ namespace XMPP class S5BConnection; class S5BManager; class S5BServer; + class JT_PushS5B; struct S5BRequest; typedef QList StreamHostList; typedef QList S5BConnectionList; @@ -152,6 +153,7 @@ namespace XMPP Client *client() const; S5BServer *server() const; void setServer(S5BServer *s); + JT_PushS5B *jtPush() const; bool isAcceptableSID(const Jid &peer, const QString &sid) const; From 1428cdd356f8b9de83a3e719433a8a2fd2444341 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 00:25:32 +0300 Subject: [PATCH 009/383] jignle-ft/s5b: more connection handling stuff --- src/xmpp/xmpp-im/jingle-ft.cpp | 7 ++- src/xmpp/xmpp-im/jingle-s5b.cpp | 86 ++++++++++++++++++++++++++++++--- src/xmpp/xmpp-im/jingle-s5b.h | 8 ++- src/xmpp/xmpp-im/jingle.h | 12 +---- 4 files changed, 93 insertions(+), 20 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index ab4363ee..187d722d 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -388,6 +388,7 @@ class Application::Private Origin creator; Origin senders; QSharedPointer transport; + Connection::Ptr connection; QStringList availableTransports; bool transportFailed = false; @@ -477,7 +478,11 @@ bool Application::setTransport(const QSharedPointer &transport) d->setState(State::Pending); connect(transport.data(), &Transport::updated, this, &Application::updated); connect(transport.data(), &Transport::connected, this, [this](){ - + d->connection = d->transport->connection(); + connect(d->connection.data(), &Connection::readyRead, this, [this](){ + // TODO read data + }); + d->setState(State::Active); }); connect(transport.data(), &Transport::failed, this, [this](){ if (d->availableTransports.size()) { // we can do transport-replace here diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 718d0b0d..de9872ad 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -46,7 +46,21 @@ class Connection : public XMPP::Jingle::Connection Q_OBJECT QList datagrams; + SocksClient *client; + Transport::Mode mode; public: + Connection(SocksClient *client, Transport::Mode mode) : + client(client), + mode(mode) + { + connect(client, &SocksClient::readyRead, this, &Connection::readyRead); + if (client->isOpen()) { + setOpenMode(client->openMode()); + } else { + qWarning("Creating S5B Transport connection on closed SockClient connection"); + } + } + bool hasPendingDatagrams() const { return datagrams.size() > 0; @@ -57,7 +71,39 @@ class Connection : public XMPP::Jingle::Connection Q_UNUSED(maxSize); // TODO or not? return datagrams.size()? datagrams.takeFirst(): NetworkDatagram(); } + + qint64 bytesAvailable() const + { + if(client) + return client->bytesAvailable(); + else + return 0; + } + + qint64 bytesToWrite() const + { + return client->bytesToWrite(); + } + protected: + qint64 writeData(const char *data, qint64 maxSize) + { + if(mode == Transport::Tcp) + return client->write(data, maxSize); + return 0; + } + + qint64 readData(char *data, qint64 maxSize) + { + if(client) + return client->read(data, maxSize); + else + return 0; + } + + + +private: friend class Transport; void enqueueIncomingUDP(const QByteArray &data) { @@ -66,7 +112,8 @@ class Connection : public XMPP::Jingle::Connection } }; -class Candidate::Private : public QSharedData { +class Candidate::Private : public QObject, public QSharedData { + Q_OBJECT public: QString cid; QString host; @@ -262,16 +309,17 @@ QDomElement Candidate::toXml(QDomDocument *doc) const return e; } -void Candidate::connectToHost(const QString &key, std::function callback, bool isUdp) +void Candidate::connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { - // TODO negotiate socks5 connection to host and port d->socksClient = new SocksClient; - QObject::connect(d->socksClient, &SocksClient::connected, [this, callback](){ + QObject::connect(d->socksClient, &SocksClient::connected, [this, callback, successState](){ + d->state = successState; callback(true); }); QObject::connect(d->socksClient, &SocksClient::error, [this, callback](int error){ Q_UNUSED(error); + d->state = Candidate::Discarded; callback(false); }); //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); @@ -285,9 +333,24 @@ bool Candidate::incomingConnection(SocksClient *sc) return false; } d->socksClient = sc; + QObject::connect(d->socksClient, &SocksClient::error, [this](int error){ + Q_UNUSED(error); + d->state = Candidate::Discarded; + }); return false; } +SocksClient *Candidate::takeSocksClient() +{ + if (!d->socksClient) { + return nullptr; + } + auto c = d->socksClient; + d->socksClient = nullptr; + d->disconnect(c); + return c; +} + class Transport::Private : public QSharedData { public: enum PendingActions { @@ -404,7 +467,7 @@ class Transport::Private : public QSharedData { // now we have to connect to maxNew candidate lastConnectionStart.start(); QString key = maxNew.type() == Candidate::Proxy? dstaddr : directAddr; - maxNew.connectToHost(key, [this, maxNew](bool success) { + maxNew.connectToHost(key, Candidate::Pending, [this, maxNew](bool success) { // candidate's status had to be changed by connectToHost, so we don't set it again // if our candidate has higher priority than any of local or remoteUsedCandidate then set it as "used" if (success && (!remoteUsedCandidate || remoteUsedCandidate.priority() < maxNew.priority()) && @@ -475,7 +538,7 @@ class Transport::Private : public QSharedData { if (localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); - c.connectToHost(key, [this](bool success){ + c.connectToHost(key, Candidate::Active, [this](bool success){ if (success) { pendingActions |= Private::Activated; } else { @@ -489,6 +552,7 @@ class Transport::Private : public QSharedData { } } if (c.state() == Candidate::Active) { + connection.reset(new Connection(c.takeSocksClient(), mode)); emit q->connected(); } } else { // both sides reported candidate error @@ -581,7 +645,7 @@ Transport::Transport(const TransportManagerPad::Ptr &pad) : d->q = this; d->pad = pad.staticCast(); d->probingTimer.setSingleShot(true); - d->probingTimer.callOnTimeout([this](){ d->tryConnectToRemoteCandidate(); }); + connect(&d->probingTimer, &QTimer::timeout, [this](){ d->tryConnectToRemoteCandidate(); }); connect(pad->manager(), &TransportManager::abortAllRequested, this, [this](){ d->aborted = true; emit failed(); @@ -789,6 +853,7 @@ bool Transport::update(const QDomElement &transportEl) return true; } c.setState(Candidate::Active); + d->connection.reset(new Connection(c.takeSocksClient(), d->mode)); QTimer::singleShot(0, this, [this](){ emit connected(); }); return true; } @@ -962,6 +1027,11 @@ QString Transport::sid() const return d->sid; } +Connection::Ptr Transport::connection() const +{ + return d->connection.staticCast(); +} + bool Transport::incomingConnection(SocksClient *sc) { if (!d->connection) { @@ -1193,3 +1263,5 @@ void Pad::registerSid(const QString &sid) } // namespace S5B } // namespace Jingle } // namespace XMPP + +#include "jingle-s5b.moc" diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 01cc7978..f403bf11 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -44,6 +44,7 @@ namespace S5B { extern const QString NS; +class Transport; class Candidate { public: enum Type { @@ -113,10 +114,12 @@ class Candidate { QDomElement toXml(QDomDocument *doc) const; - void connectToHost(const QString &key, std::function callback, bool isUdp = false); + void connectToHost(const QString &key, State successState, std::function callback, bool isUdp = false); bool incomingConnection(SocksClient *sc); + SocksClient* takeSocksClient(); private: class Private; + friend class Transport; QExplicitlySharedDataPointer d; }; @@ -144,7 +147,8 @@ class Transport : public XMPP::Jingle::Transport bool isValid() const override; Features features() const override; - QString sid() const; + QString sid() const; + Connection::Ptr connection() const; private: friend class S5BServer; bool incomingConnection(SocksClient *sc); diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index e2c06657..4ea281e3 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -280,19 +280,10 @@ typedef QNetworkDatagram NetworkDatagram; class Connection : public ByteStream { Q_OBJECT - - QList datagrams; public: + using Ptr = QSharedPointer; // will be shared between transport and application virtual bool hasPendingDatagrams() const; virtual NetworkDatagram receiveDatagram(qint64 maxSize = -1); - -protected: - friend class Transport; - void enqueueIncomingUDP(const QByteArray &data) - { - datagrams.append(data); - emit readyRead(); - } }; class Application; @@ -356,6 +347,7 @@ class Transport : public QObject { virtual bool isValid() const = 0; virtual Features features() const = 0; virtual TransportManagerPad::Ptr pad() const = 0; + virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection signals: void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler. // if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent. From f723c867e8b974eab2ff6d76e76fe8d7bc89c93b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 08:03:23 +0300 Subject: [PATCH 010/383] applied 0001-temporary-iris-fix.diff --- src/xmpp/CMakeLists.txt | 4 ++-- src/xmpp/xmpp-im/jingle-s5b.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/xmpp/CMakeLists.txt b/src/xmpp/CMakeLists.txt index 593b5dc1..3d72b436 100644 --- a/src/xmpp/CMakeLists.txt +++ b/src/xmpp/CMakeLists.txt @@ -123,8 +123,9 @@ set(SOURCES xmpp-im/xmpp_vcard.cpp xmpp-im/xmpp_xdata.cpp xmpp-im/xmpp_xmlcommon.cpp - xmpp-im/jingle-s5b.cpp + xmpp-im/jingle.cpp xmpp-im/jingle-ft.cpp + xmpp-im/jingle-s5b.cpp base/randomnumbergenerator.cpp base/timezone.cpp @@ -150,7 +151,6 @@ set(SOURCES xmpp-im/s5b.cpp xmpp-im/xmpp_features.cpp - xmpp-im/jingle.cpp ) add_library(iris diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index de9872ad..e13ded99 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -16,7 +16,6 @@ * along with this library. If not, see . * */ - #include "jingle-s5b.h" #include "s5b.h" #include "xmpp/jid/jid.h" From 0ef610398bdfb902a6e3a7550573df936e8deaaf Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 10:20:40 +0300 Subject: [PATCH 011/383] Fixed crash on s5b destruction --- src/xmpp/xmpp-im/jingle-s5b.cpp | 25 ++++++++++++++++--------- src/xmpp/xmpp-im/jingle.cpp | 6 +++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index e13ded99..46cccde7 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1106,11 +1106,25 @@ Manager::Manager(QObject *parent) : TransportManager(parent), d(new Private) { + // ensure S5BManager is initialized + QTimer::singleShot(0, [this](){ + auto jt = d->jingleManager->client()->s5bManager()->jtPush(); + connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { + Q_UNUSED(from); + auto t = d->key2transport.value(dstaddr); + if (t) { + // TODO return t->incomingUDPSuccess(from); + } + }); + }); } Manager::~Manager() { d->jingleManager->unregisterTransport(NS); + if (d->serv) { + d->serv->unlink(this); + } } Transport::Features Manager::features() const @@ -1153,20 +1167,13 @@ void Manager::setServer(S5BServer *serv) if(d->serv) { d->serv->unlink(this); d->serv = nullptr; - - auto jt = d->jingleManager->client()->s5bManager()->jtPush(); - connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { - Q_UNUSED(from); - auto t = d->key2transport.value(dstaddr); - if (t) { - // TODO return t->incomingUDPSuccess(from); - } - }, Qt::UniqueConnection); } if(serv) { d->serv = serv; d->serv->link(this); + } else { + d->serv = nullptr; } } diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 107bac98..b1d48a9d 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1239,7 +1239,10 @@ QSharedPointer Session::newOutgoingTransport(const QString &ns) QString Session::preferredApplication() const { // TODO some heuristics to detect preferred application - return d->applicationPads.keys().value(0); + if (d->applicationPads.size()) { + return d->applicationPads.constBegin().key(); + } + return QString(); } QStringList Session::allApplicationTypes() const @@ -1595,6 +1598,7 @@ bool Connection::hasPendingDatagrams() const NetworkDatagram Connection::receiveDatagram(qint64 maxSize) { + Q_UNUSED(maxSize) return NetworkDatagram(); } From b07d12076885ca56117070e2ada6e8a1c956a595 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 12:12:32 +0300 Subject: [PATCH 012/383] jingle: fixed a few bugs after Gajim interoperability tests --- src/xmpp/xmpp-im/jingle-s5b.cpp | 11 +++++++---- src/xmpp/xmpp-im/jingle-s5b.h | 12 ++++++++++++ src/xmpp/xmpp-im/jingle.cpp | 18 +++++++++++------- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 46cccde7..4cd95fb1 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -37,7 +37,8 @@ static QString makeKey(const QString &sid, const Jid &j1, const Jid &j2) return QString::fromLatin1(QCryptographicHash::hash((sid + j1.full() + j2.full()).toUtf8(), - QCryptographicHash::Sha1)); + QCryptographicHash::Sha1) + .toHex()); } class Connection : public XMPP::Jingle::Connection @@ -225,7 +226,9 @@ Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type Candidate::~Candidate() { - delete d->socksClient; + if (d) { // if it's valid candidate + delete d->socksClient; + } } Candidate::Type Candidate::type() const @@ -360,7 +363,7 @@ class Transport::Private : public QSharedData { ProxyError = 16 }; - Transport *q = NULL; + Transport *q = nullptr; Pad::Ptr pad; bool meCreator = true; // content.content is local side bool connectionStarted = false; // where start() was called @@ -369,7 +372,7 @@ class Transport::Private : public QSharedData { bool remoteReportedCandidateError = false; bool localReportedCandidateError = false; bool proxyDiscoveryInProgress = false; // if we have valid proxy requests - quint16 pendingActions; + quint16 pendingActions = 0; int proxiesInDiscoCount = 0; quint32 minimalPriority = 0; Application *application = nullptr; diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index f403bf11..ccce07d3 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -203,7 +203,19 @@ class Manager : public TransportManager { void registerSid(const Jid &remote, const QString &sid); S5BServer* socksServ() const; + + /** + * @brief userProxy returns custom (set by user) SOCKS proxy JID + * @return + */ Jid userProxy() const; + + /** + * @brief addKeyMapping sets mapping between key/socks hostname used for direct connection and transport. + * The key is sha1(sid, initiator full jid, responder full jid) + * @param key + * @param transport + */ void addKeyMapping(const QString &key, Transport *transport); void removeKeyMapping(const QString &key); private: diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index b1d48a9d..3770a9f7 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -488,8 +488,9 @@ class JTPush : public Task } } else { auto session = client()->jingleManager()->session(from, jingle.sid()); - if (session) { - respondError(iq, Stanza::Error::Cancel, Stanza::Error::Conflict); + if (!session) { + auto el = client()->doc()->createElementNS(QString::fromLatin1("urn:xmpp:jingle:errors:1"), QStringLiteral("unknown-session")); + respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); return true; } if (!session->updateFromXml(jingle.action(), jingleEl)) { @@ -503,11 +504,16 @@ class JTPush : public Task return true; } - void respondError(const QDomElement &iq, Stanza::Error::ErrorType errType, Stanza::Error::ErrorCond errCond, const QString &text = QString()) + void respondError(const QDomElement &iq, Stanza::Error::ErrorType errType, Stanza::Error::ErrorCond errCond, + const QString &text = QString(), const QDomElement &jingleErr = QDomElement()) { auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), iq.attribute(QStringLiteral("id"))); Stanza::Error error(errType, errCond, text); - resp.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); + auto errEl = error.toXml(*client()->doc(), client()->stream().baseNS()); + if (!jingleErr.isNull()) { + errEl.appendChild(jingleErr); + } + resp.appendChild(errEl); client()->send(resp); } @@ -819,9 +825,7 @@ class Session::Private } QObject::connect(content, &Application::updated, q, [this, content](){ signalingContent.insert(content); - if (!waitingAck && !stepTimer.isActive()) { - stepTimer.start(); - } + planStep(); }); QObject::connect(content, &Application::destroyed, q, [this, content](){ signalingContent.remove(content); From e01348f497c16877fe320b5a5ce6ce241082938b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 16:38:35 +0300 Subject: [PATCH 013/383] Fixed compilation error with qt<5.8.0 --- src/xmpp/xmpp-im/jingle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 4ea281e3..58809481 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -27,6 +27,8 @@ #include #if QT_VERSION >= QT_VERSION_CHECK(5,8,0) # include +#else +# include #endif #include "xmpp_stanza.h" From 47c39652d791b963d25df65aac0d2eb975011b26 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 18:30:52 +0300 Subject: [PATCH 014/383] Added missed semicolon --- src/xmpp/xmpp-im/jingle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 58809481..ff45adc0 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -274,7 +274,7 @@ class NetworkDatagram inline bool isValid() const { return _valid; } inline QByteArray data() const { return _data; } -} +}; #else typedef QNetworkDatagram NetworkDatagram; #endif From 1bd45f7f4bb00979d3ed433e2f186760ac04fdaa Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 21:08:37 +0300 Subject: [PATCH 015/383] jingle: fixed a few more bugs after tests with Gajim --- src/xmpp/xmpp-im/jingle-s5b.cpp | 59 ++++++++++++++++++++------------- src/xmpp/xmpp-im/jingle.cpp | 50 +++++++++++++++++++++++++--- src/xmpp/xmpp-im/jingle.h | 4 ++- 3 files changed, 84 insertions(+), 29 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 4cd95fb1..05213fad 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -115,6 +115,11 @@ class Connection : public XMPP::Jingle::Connection class Candidate::Private : public QObject, public QSharedData { Q_OBJECT public: + ~Private() + { + delete socksClient; + } + QString cid; QString host; Jid jid; @@ -125,6 +130,32 @@ class Candidate::Private : public QObject, public QSharedData { quint16 localPort = 0; // where Psi actually listens. e.g. with NAT-assited candidats it may be different from just port SocksClient *socksClient = nullptr; + + void connectToHost(const QString &key, State successState, std::function callback, bool isUdp) + { + socksClient = new SocksClient; + + connect(socksClient, &SocksClient::connected, [this, callback, successState](){ + state = successState; + callback(true); + }); + connect(socksClient, &SocksClient::error, [this, callback](int error){ + Q_UNUSED(error); + state = Candidate::Discarded; + callback(false); + }); + //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); + + socksClient->connectToHost(host, port, key, 0, isUdp); + } + + void setupIncomingSocksClient() + { + connect(socksClient, &SocksClient::error, [this](int error){ + Q_UNUSED(error); + state = Candidate::Discarded; + }); + } }; Candidate::Candidate() @@ -226,9 +257,6 @@ Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type Candidate::~Candidate() { - if (d) { // if it's valid candidate - delete d->socksClient; - } } Candidate::Type Candidate::type() const @@ -313,20 +341,7 @@ QDomElement Candidate::toXml(QDomDocument *doc) const void Candidate::connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { - d->socksClient = new SocksClient; - - QObject::connect(d->socksClient, &SocksClient::connected, [this, callback, successState](){ - d->state = successState; - callback(true); - }); - QObject::connect(d->socksClient, &SocksClient::error, [this, callback](int error){ - Q_UNUSED(error); - d->state = Candidate::Discarded; - callback(false); - }); - //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); - - d->socksClient->connectToHost(d->host, d->port, key, 0, isUdp); + d->connectToHost(key, successState, callback, isUdp); } bool Candidate::incomingConnection(SocksClient *sc) @@ -335,11 +350,8 @@ bool Candidate::incomingConnection(SocksClient *sc) return false; } d->socksClient = sc; - QObject::connect(d->socksClient, &SocksClient::error, [this](int error){ - Q_UNUSED(error); - d->state = Candidate::Discarded; - }); - return false; + d->setupIncomingSocksClient(); + return true; } SocksClient *Candidate::takeSocksClient() @@ -353,7 +365,8 @@ SocksClient *Candidate::takeSocksClient() return c; } -class Transport::Private : public QSharedData { +class Transport::Private +{ public: enum PendingActions { NewCandidate = 1, diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 3770a9f7..e5772785 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -716,7 +716,7 @@ class Session::Private State finalState = State::Active; // so all contents is ready for session-initiate. let's do it if (role == Origin::Initiator) { - sid = manager->generateSessionId(otherParty); + sid = manager->registerSession(q); actionToSend = Action::SessionInitiate; finalState = State::Pending; } @@ -1138,6 +1138,34 @@ class Session::Private return true; } + + bool handleIncomingTransportInfo(const QDomElement &jingleEl) + { + QString contentTag(QStringLiteral("content")); + QList,QDomElement>> updates; + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + Application *app; + ContentBase cb(ce); + if (!cb.isValid() || !(app = q->content(cb.name, role)) || app->state() >= State::Finishing || !app->transport()) { + return false; + } + auto tel = ce.firstChildElement(QStringLiteral("transport")); + if (tel.isNull() || tel.attribute(QStringLiteral("xmlns")) != app->transport()->pad()->ns()) { + return false; + } + updates.append(qMakePair(app->transport(), tel)); + } + + for (auto &u: updates) { + if (!u.first->update(u.second)) { + return false; // yes this may lead to half updated content, but what choice do we have? + } + } + + return true; + } }; Session::Session(Manager *manager, const Jid &peer) : @@ -1187,6 +1215,11 @@ Jid Session::responder() const return d->role == Origin::Responder? d->manager->client()->jid() : d->otherParty; } +QString Session::sid() const +{ + return d->sid; +} + Origin Session::role() const { return d->role; @@ -1273,6 +1306,7 @@ void Session::accept() void Session::initiate() { + emit initiated(); if (d->role == Origin::Initiator && d->state == State::Created) { d->state = State::PrepareLocalOffer; for (auto &c: d->contentList) { @@ -1385,7 +1419,7 @@ bool Session::updateFromXml(Action action, const QDomElement &jingleEl) case Action::TransportAccept: break; case Action::TransportInfo: - break; + return d->handleIncomingTransportInfo(jingleEl); case Action::TransportReject: break; case Action::TransportReplace: @@ -1572,15 +1606,21 @@ XMPP::Stanza::Error Manager::lastError() const Session *Manager::newSession(const Jid &j) { - return new Session(this, j); + auto s = new Session(this, j); + connect(s, &Session::terminated, this, [this, s](){ + d->sessions.remove(qMakePair(s->peer(), s->sid())); + }); + return s; } -QString Manager::generateSessionId(const Jid &peer) +QString Manager::registerSession(Session *session) { QString id; + auto peer = session->peer(); do { id = QString("%1").arg(quint32(qrand()), 6, 32, QChar('0')); - } while (d->sessions.contains(QPair(peer,id))); + } while (d->sessions.contains(qMakePair(peer,id))); + d->sessions.insert(qMakePair(peer, id), session); return id; } diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index ff45adc0..be31c82e 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -419,6 +419,7 @@ class Session : public QObject Jid peer() const; Jid initiator() const; Jid responder() const; + QString sid() const; Origin role() const; // my role in session: initiator or responder XMPP::Stanza::Error lastError() const; @@ -449,6 +450,7 @@ class Session : public QObject TransportManagerPad::Ptr transportPadFactory(const QString &ns); signals: void managerPadAdded(const QString &ns); + void initiated(); void activated(); void terminated(); void newContentReceived(); @@ -533,7 +535,7 @@ class Manager : public QObject Session* session(const Jid &remoteJid, const QString &sid); Session* newSession(const Jid &j); - QString generateSessionId(const Jid &peer); + QString registerSession(Session *session); XMPP::Stanza::Error lastError() const; signals: From 5e594d279746aa18f42a54f7eb368c391897a5ab Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 21:31:45 +0300 Subject: [PATCH 016/383] jignle-s5b: incomplete changes to candidate selection algo --- src/xmpp/xmpp-im/jingle-s5b.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 05213fad..0cd24753 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -387,7 +387,6 @@ class Transport::Private bool proxyDiscoveryInProgress = false; // if we have valid proxy requests quint16 pendingActions = 0; int proxiesInDiscoCount = 0; - quint32 minimalPriority = 0; Application *application = nullptr; QMap localCandidates; // cid to candidate mapping QMap remoteCandidates; @@ -611,14 +610,13 @@ class Transport::Private // take used-candidate with highest priority and discard all with lower. also update used candidates themselves void updateMinimalPriority() { quint32 prio = 0; - if (localUsedCandidate && minimalPriority < localUsedCandidate.priority() && localUsedCandidate.state() != Candidate::Discarded) { + if (localUsedCandidate && localUsedCandidate.state() != Candidate::Discarded) { prio = localUsedCandidate.priority(); - } else if (remoteUsedCandidate && minimalPriority < remoteUsedCandidate.priority() && remoteUsedCandidate.state() != Candidate::Discarded) { - prio = remoteUsedCandidate.priority(); } - if (prio < minimalPriority) { - return; + if (remoteUsedCandidate && prio < remoteUsedCandidate.priority() && remoteUsedCandidate.state() != Candidate::Discarded) { + prio = remoteUsedCandidate.priority(); } + for (auto &c: localCandidates) { if (c.priority() < prio && c.state() != Candidate::Discarded) { c.setState(Candidate::Discarded); @@ -646,9 +644,11 @@ class Transport::Private // i'm initiator. see 2.4.4 localUsedCandidate.setState(Candidate::Discarded); localUsedCandidate = Candidate(); + remoteReportedCandidateError = true; // as a sign of completeness even if not true } else { remoteUsedCandidate.setState(Candidate::Discarded); remoteUsedCandidate = Candidate(); + //localReportedCandidateError = true; // as a sign of completeness even if not true } } } @@ -812,10 +812,10 @@ bool Transport::update(const QDomElement &transportEl) { // we can just on type of elements in transport-info // so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info - QString contentTag(QStringLiteral("candidate")); + QString candidateTag(QStringLiteral("candidate")); int candidatesAdded = 0; - for(QDomElement ce = transportEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) { + for(QDomElement ce = transportEl.firstChildElement(candidateTag); + !ce.isNull(); ce = ce.nextSiblingElement(candidateTag)) { Candidate c(ce); if (!c) { return false; From 1e5d9abb4e53b56f1c81dcfb6d8a982b7bcea48a Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 13 May 2019 22:27:15 +0300 Subject: [PATCH 017/383] jingle-s5b: cleanup unused candidates --- src/xmpp/xmpp-im/jingle-s5b.cpp | 37 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 0cd24753..83f36358 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -233,7 +233,7 @@ Candidate::Candidate(const Jid &proxy, const QString &cid, quint16 localPreferen d->jid = proxy; d->priority = (ProxyPreference << 16) + localPreference; d->type = Proxy; - d->state = Probing; + d->state = Probing; // FIXME? } Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type type, quint16 localPreference) : @@ -311,6 +311,7 @@ Candidate::State Candidate::state() const void Candidate::setState(Candidate::State s) { + // don't close sockets here since pending events may change state machine or remote side and closed socket may break it d->state = s; } @@ -378,7 +379,7 @@ class Transport::Private Transport *q = nullptr; Pad::Ptr pad; - bool meCreator = true; // content.content is local side + bool meCreator = true; // content created on local side bool connectionStarted = false; // where start() was called bool waitingAck = true; bool aborted = false; @@ -481,14 +482,17 @@ class Transport::Private // now we have to connect to maxNew candidate lastConnectionStart.start(); QString key = maxNew.type() == Candidate::Proxy? dstaddr : directAddr; + maxNew.setState(Candidate::Probing); maxNew.connectToHost(key, Candidate::Pending, [this, maxNew](bool success) { // candidate's status had to be changed by connectToHost, so we don't set it again - // if our candidate has higher priority than any of local or remoteUsedCandidate then set it as "used" - if (success && (!remoteUsedCandidate || remoteUsedCandidate.priority() < maxNew.priority()) && - ((!localUsedCandidate || localUsedCandidate.priority() < maxNew.priority()))) - { - remoteUsedCandidate = maxNew; - localUsedCandidate = Candidate(); + if (success) { + // discard all current in-progress connections with <= priority + for (auto &c: remoteCandidates) { + if (c != maxNew && c.state() == Candidate::Probing && c.priority() <= maxNew.priority()) { + c.setState(Candidate::Discarded); + } + } + updateMinimalPriority(); } checkAndFinishNegotiation(); @@ -567,6 +571,8 @@ class Transport::Private } if (c.state() == Candidate::Active) { connection.reset(new Connection(c.takeSocksClient(), mode)); + localCandidates.clear(); + remoteCandidates.clear(); emit q->connected(); } } else { // both sides reported candidate error @@ -640,7 +646,7 @@ class Transport::Private remoteUsedCandidate = Candidate(); } if (localUsedCandidate && remoteUsedCandidate) { - if (meCreator) { + if (pad->session()->role() == Origin::Initiator) { // i'm initiator. see 2.4.4 localUsedCandidate.setState(Candidate::Discarded); localUsedCandidate = Candidate(); @@ -648,7 +654,7 @@ class Transport::Private } else { remoteUsedCandidate.setState(Candidate::Discarded); remoteUsedCandidate = Candidate(); - //localReportedCandidateError = true; // as a sign of completeness even if not true + localReportedCandidateError = true; // as a sign of completeness even if not true } } } @@ -869,7 +875,11 @@ bool Transport::update(const QDomElement &transportEl) } c.setState(Candidate::Active); d->connection.reset(new Connection(c.takeSocksClient(), d->mode)); - QTimer::singleShot(0, this, [this](){ emit connected(); }); + QTimer::singleShot(0, this, [this](){ + d->localCandidates.clear(); + d->remoteCandidates.clear(); + emit connected(); + }); return true; } @@ -957,8 +967,9 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() }}; } } else if (d->pendingActions & Private::CandidateUsed) { - d->pendingActions &= ~Private::NewCandidate; - // we should have the only remote candidate in Pending state + d->pendingActions &= ~Private::CandidateUsed; + // we should have the only remote candidate in Pending state. + // all other has to be discarded by priority check for (auto &c: d->remoteCandidates) { if (c.state() != Candidate::Pending) { continue; From ce4c3613043aeeec9c999c84e4884eeb4b209790 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 14 May 2019 01:15:28 +0300 Subject: [PATCH 018/383] jingle-s5b: fixed crash on double negotiation finish --- src/xmpp/xmpp-im/jingle-s5b.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 83f36358..2ac39193 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -233,7 +233,7 @@ Candidate::Candidate(const Jid &proxy, const QString &cid, quint16 localPreferen d->jid = proxy; d->priority = (ProxyPreference << 16) + localPreference; d->type = Proxy; - d->state = Probing; // FIXME? + d->state = Probing; // it's probing because it's a local side proxy and host and port are unknown } Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type type, quint16 localPreference) : @@ -342,11 +342,13 @@ QDomElement Candidate::toXml(QDomDocument *doc) const void Candidate::connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { + qDebug() << "connect to host with " << d->cid << "candidate"; d->connectToHost(key, successState, callback, isUdp); } bool Candidate::incomingConnection(SocksClient *sc) { + qDebug() << "incoming connection on" << d->cid << "candidate"; if (d->socksClient) { return false; } @@ -357,6 +359,7 @@ bool Candidate::incomingConnection(SocksClient *sc) SocksClient *Candidate::takeSocksClient() { + qDebug() << "taking socket from " << d->cid << "candidate"; if (!d->socksClient) { return nullptr; } @@ -527,8 +530,8 @@ class Transport::Private // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more // local candidates are expected to be discovered - if (!connectionStarted) { - return; // we can't finish anything in this state. Only Connecting is acceptable + if (!connectionStarted || connection) { // if not started or already finished + return; } // sort out already handled states or states which will bring us here a little later @@ -712,6 +715,7 @@ void Transport::prepare() Candidate c(h, serv->port(), d->generateCid(), Candidate::Direct); if (!d->isDup(c)) { d->localCandidates.insert(c.cid(), c); + d->pendingActions |= Private::NewCandidate; } } } @@ -1061,8 +1065,8 @@ Connection::Ptr Transport::connection() const bool Transport::incomingConnection(SocksClient *sc) { if (!d->connection) { + auto s = sc->abstractSocket(); for (auto &c: d->localCandidates) { - auto s = sc->abstractSocket(); if (s->localPort() == c.localPort() && c.state() == Candidate::Pending) { if(d->mode == Transport::Udp) sc->grantUDPAssociate("", 0); From 93c239ae92e2ef4b438fb927818d42acc7ecce6e Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 14 May 2019 11:53:10 +0300 Subject: [PATCH 019/383] jingle-s5b: reject lower-priority candidates if we have connected higher priority --- src/irisnet/noncore/cutestuff/socks.cpp | 1 + src/xmpp/xmpp-im/jingle-s5b.cpp | 33 ++++++++++++++++--------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index 8162ca65..41f645d6 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -886,6 +886,7 @@ void SocksClient::continueIncoming() else d->rhost = s.addr.toString(); d->rport = s.port; + QIODevice::open(QIODevice::ReadWrite); incomingConnectRequest(d->rhost, d->rport); } else if(s.cmd == REQ_UDPASSOCIATE) { diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 2ac39193..61485cc5 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -57,7 +57,7 @@ class Connection : public XMPP::Jingle::Connection if (client->isOpen()) { setOpenMode(client->openMode()); } else { - qWarning("Creating S5B Transport connection on closed SockClient connection"); + qWarning("Creating S5B Transport connection on closed SockClient connection %p", client); } } @@ -134,14 +134,17 @@ class Candidate::Private : public QObject, public QSharedData { void connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { socksClient = new SocksClient; + qDebug() << "connect to host with " << cid << "candidate and socks client" << socksClient; connect(socksClient, &SocksClient::connected, [this, callback, successState](){ state = successState; + qDebug() << "socks client" << socksClient << "is connected"; callback(true); }); connect(socksClient, &SocksClient::error, [this, callback](int error){ Q_UNUSED(error); state = Candidate::Discarded; + qDebug() << "socks client" << socksClient << "failed to connect"; callback(false); }); //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); @@ -342,13 +345,12 @@ QDomElement Candidate::toXml(QDomDocument *doc) const void Candidate::connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { - qDebug() << "connect to host with " << d->cid << "candidate"; d->connectToHost(key, successState, callback, isUdp); } bool Candidate::incomingConnection(SocksClient *sc) { - qDebug() << "incoming connection on" << d->cid << "candidate"; + qDebug() << "incoming connection on" << d->cid << "candidate with socks client" << sc; if (d->socksClient) { return false; } @@ -359,7 +361,7 @@ bool Candidate::incomingConnection(SocksClient *sc) SocksClient *Candidate::takeSocksClient() { - qDebug() << "taking socket from " << d->cid << "candidate"; + qDebug() << "taking socks client" << d->socksClient << "from " << d->cid << "candidate"; if (!d->socksClient) { return nullptr; } @@ -489,13 +491,16 @@ class Transport::Private maxNew.connectToHost(key, Candidate::Pending, [this, maxNew](bool success) { // candidate's status had to be changed by connectToHost, so we don't set it again if (success) { - // discard all current in-progress connections with <= priority + // let's reject candidates which are meaningless to try for (auto &c: remoteCandidates) { - if (c != maxNew && c.state() == Candidate::Probing && c.priority() <= maxNew.priority()) { + if (c.state() == Candidate::New && c.priority() <= maxNew.priority()) { c.setState(Candidate::Discarded); } } - + if (proxyDiscoveryInProgress && (maxNew.priority() >> 16) > Candidate::ProxyPreference) { + proxyDiscoveryInProgress = false; // doesn't make sense anymore + } + // TODO do the same for upnp updateMinimalPriority(); } checkAndFinishNegotiation(); @@ -848,10 +853,16 @@ bool Transport::update(const QDomElement &transportEl) if (!cUsed) { return false; } - cUsed.setState(Candidate::Accepted); - d->localUsedCandidate = cUsed; - d->updateMinimalPriority(); - QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); + if (cUsed.state() == Candidate::Pending) { + cUsed.setState(Candidate::Accepted); + d->localUsedCandidate = cUsed; + d->updateMinimalPriority(); + QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); + } else { + //seems like we already rejected the candidate and either remote side already know about it or will soon + d->localUsedCandidate = Candidate(); + d->remoteReportedCandidateError = true; // as a sign remote has finished + } return true; } From 9bfd3a18db884d23db0e740ba0af76f598d3dcf0 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 07:43:23 +0300 Subject: [PATCH 020/383] jingle-s5b: select proper candidate on finish --- src/xmpp/xmpp-im/jingle-s5b.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 61485cc5..9234e005 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -526,6 +526,24 @@ class Transport::Private return false; } + Candidate preferredCandidate() const + { + if (localUsedCandidate) { + if (remoteUsedCandidate) { + if (localUsedCandidate.priority() == remoteUsedCandidate.priority()) { + if (pad->session()->role() == Origin::Initiator) { + return remoteUsedCandidate; + } + return localUsedCandidate; + } + return localUsedCandidate.priority() > remoteUsedCandidate.priority()? + localUsedCandidate : remoteUsedCandidate; + } + return localUsedCandidate; + } + return remoteUsedCandidate; + } + void checkAndFinishNegotiation() { // Why we can't send candidate-used/error right when this happens: @@ -556,10 +574,10 @@ class Transport::Private if (remoteReportedCandidateError || localUsedCandidate) { // so remote seems to be finished too. // tell application about it and it has to change its state immediatelly - if (localUsedCandidate || remoteUsedCandidate) { - auto c = localUsedCandidate? localUsedCandidate : remoteUsedCandidate; + auto c = preferredCandidate(); + if (c) { if (c.state() != Candidate::Active) { - if (c.type() == Candidate::Proxy) { + if (c.type() == Candidate::Proxy && c == localUsedCandidate) { // local proxy // If it's proxy, first it has to be activated if (localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate From f3408e42711a4c7e8315101a0fc8a2185f4d8e4b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 08:17:37 +0300 Subject: [PATCH 021/383] jingle-ft: started work on actual transfer over open connection --- src/xmpp/xmpp-im/jingle-ft.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 187d722d..417853f2 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -482,8 +482,15 @@ bool Application::setTransport(const QSharedPointer &transport) connect(d->connection.data(), &Connection::readyRead, this, [this](){ // TODO read data }); + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ + if (d->pad->session()->role() == d->senders) { + // write next port of data + + } + }); d->setState(State::Active); }); + connect(transport.data(), &Transport::failed, this, [this](){ if (d->availableTransports.size()) { // we can do transport-replace here // TODO From 3df933f19d5e4b108bf663d1c88668b5fb2e7ab9 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 11:57:34 +0300 Subject: [PATCH 022/383] jingle-ft: Make file sending working --- src/xmpp/xmpp-im/jingle-ft.cpp | 64 ++++++++++++++++++++++++++++++--- src/xmpp/xmpp-im/jingle-ft.h | 4 +++ src/xmpp/xmpp-im/jingle-s5b.cpp | 16 +++++++++ src/xmpp/xmpp-im/jingle-s5b.h | 1 + src/xmpp/xmpp-im/jingle.h | 1 + 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 417853f2..e660f310 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -385,18 +385,51 @@ class Application::Private QSharedPointer pad; QString contentName; File file; + File acceptFile; // as it comes with "accept" response Origin creator; Origin senders; QSharedPointer transport; Connection::Ptr connection; QStringList availableTransports; bool transportFailed = false; + QIODevice *device = nullptr; + quint64 bytesLeft = 0; void setState(State s) { state = s; emit q->stateChanged(s); } + + void writeNextBlockToTransport() + { + if (!bytesLeft) { + return; // everything is written + } + auto sz = transport->blockSize(); + sz = sz? sz : 8192; + if (sz > bytesLeft) { + sz = bytesLeft; + } + QByteArray data = device->read(sz); + if (data.isEmpty()) { + // TODO d->lastError = Condition::FailedApplication + connection.reset(); + setState(State::Finished); + return; + } + if (connection->write(data) == -1) { + // TODO d->lastError = Condition::FailedApplication + connection.reset(); + setState(State::Finished); + return; + } + } + + void readNextBlockFromTransport() + { + // TODO + } }; Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : @@ -479,13 +512,25 @@ bool Application::setTransport(const QSharedPointer &transport) connect(transport.data(), &Transport::updated, this, &Application::updated); connect(transport.data(), &Transport::connected, this, [this](){ d->connection = d->transport->connection(); + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + } else { + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); + } connect(d->connection.data(), &Connection::readyRead, this, [this](){ - // TODO read data + if (!d->device) { + return; + } + if (d->pad->session()->role() != d->senders) { + d->readNextBlockFromTransport(); + } }); connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ - if (d->pad->session()->role() == d->senders) { - // write next port of data - + Q_UNUSED(bytes) + if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { + d->writeNextBlockToTransport(); } }); d->setState(State::Active); @@ -646,6 +691,7 @@ bool Application::accept(const QDomElement &el) if (!f.isValid()) { return false; } + d->acceptFile = f; // TODO validate if accept file matches to the offer setState(State::Accepted); return true; @@ -657,6 +703,16 @@ bool Application::isValid() const (d->senders == Origin::Initiator || d->senders == Origin::Responder); } +void Application::setDevice(QIODevice *dev) +{ + d->device = dev; + if (d->senders == d->pad->session()->role()) { + d->writeNextBlockToTransport(); + } else { + d->readNextBlockFromTransport(); + } +} + Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 20f23098..582542cf 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -140,6 +140,10 @@ class Application : public XMPP::Jingle::Application bool isValid() const; + void setDevice(QIODevice *dev); + +signals: + void deviceRequested(quint64 offset, quint64 size); private: class Private; diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 9234e005..661cef74 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -54,6 +54,8 @@ class Connection : public XMPP::Jingle::Connection mode(mode) { connect(client, &SocksClient::readyRead, this, &Connection::readyRead); + connect(client, &SocksClient::bytesWritten, this, &Connection::bytesWritten); + connect(client, &SocksClient::aboutToClose, this, &Connection::aboutToClose); if (client->isOpen()) { setOpenMode(client->openMode()); } else { @@ -404,6 +406,7 @@ class Transport::Private Transport::Mode mode = Transport::Tcp; QTimer probingTimer; QElapsedTimer lastConnectionStart; + size_t blockSize = 8129; QSharedPointer connection; @@ -845,6 +848,13 @@ bool Transport::update(const QDomElement &transportEl) { // we can just on type of elements in transport-info // so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info + auto bs = transportEl.attribute(QString::fromLatin1("block-size")); + if (!bs.isEmpty()) { + size_t bsn = bs.toULongLong(); + if (bsn && bsn <= d->blockSize) { + d->blockSize = bsn; + } + } QString candidateTag(QStringLiteral("candidate")); int candidatesAdded = 0; for(QDomElement ce = transportEl.firstChildElement(candidateTag); @@ -967,6 +977,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() if (d->meCreator && d->mode != Tcp) { tel.setAttribute(QStringLiteral("mode"), "udp"); } + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); if (d->pendingActions & Private::NewCandidate) { d->pendingActions &= ~Private::NewCandidate; @@ -1091,6 +1102,11 @@ Connection::Ptr Transport::connection() const return d->connection.staticCast(); } +size_t Transport::blockSize() const +{ + return d->blockSize; +} + bool Transport::incomingConnection(SocksClient *sc) { if (!d->connection) { diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index ccce07d3..f25138a9 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -149,6 +149,7 @@ class Transport : public XMPP::Jingle::Transport QString sid() const; Connection::Ptr connection() const; + size_t blockSize() const; private: friend class S5BServer; bool incomingConnection(SocksClient *sc); diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index be31c82e..ff6f4b80 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -350,6 +350,7 @@ class Transport : public QObject { virtual Features features() const = 0; virtual TransportManagerPad::Ptr pad() const = 0; virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection + virtual size_t blockSize() const = 0; signals: void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler. // if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent. From a2754d275750492ac5c6cb9910bee648190db88b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 15:30:35 +0300 Subject: [PATCH 023/383] jingle-ft: close file-like device on finish --- src/xmpp/xmpp-im/jingle-ft.cpp | 7 ++++++- src/xmpp/xmpp-im/jingle-ft.h | 2 +- src/xmpp/xmpp-im/jingle.cpp | 7 ++++--- src/xmpp/xmpp-im/jingle.h | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index e660f310..dbeb7508 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -392,12 +392,16 @@ class Application::Private Connection::Ptr connection; QStringList availableTransports; bool transportFailed = false; + bool closeDeviceOnFinish = true; QIODevice *device = nullptr; quint64 bytesLeft = 0; void setState(State s) { state = s; + if (s == State::Finished && device && closeDeviceOnFinish) { + device->close(); + } emit q->stateChanged(s); } @@ -703,9 +707,10 @@ bool Application::isValid() const (d->senders == Origin::Initiator || d->senders == Origin::Responder); } -void Application::setDevice(QIODevice *dev) +void Application::setDevice(QIODevice *dev, bool closeOnFinish) { d->device = dev; + d->closeDeviceOnFinish = closeOnFinish; if (d->senders == d->pad->session()->role()) { d->writeNextBlockToTransport(); } else { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 582542cf..72cd9598 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -140,7 +140,7 @@ class Application : public XMPP::Jingle::Application bool isValid() const; - void setDevice(QIODevice *dev); + void setDevice(QIODevice *dev, bool closeOnFinish = true); signals: void deviceRequested(quint64 offset, quint64 size); diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index e5772785..c6766a11 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -928,10 +928,10 @@ class Session::Private rejectSet.remove(contentName); if (it == addSet.end() || (*it)->wantBetterTransport(app->transport())) { // probably not wantBetterTransport but wantBetterApplication - delete *it; // unpreferred app if (it == addSet.end()) { addSet.insert(contentName, app); } else { + delete *it; // unpreferred app *it = app; } } @@ -1168,10 +1168,11 @@ class Session::Private } }; -Session::Session(Manager *manager, const Jid &peer) : +Session::Session(Manager *manager, const Jid &peer, Origin role) : d(new Private) { d->q = this; + d->role = role; d->manager = manager; d->otherParty = peer; d->stepTimer.setSingleShot(true); @@ -1586,7 +1587,7 @@ Session* Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, return NULL; } auto key = qMakePair(from, jingle.sid()); - auto s = new Session(this, from); + auto s = new Session(this, from, Origin::Responder); if (s->incomingInitiate(jingle, jingleEl)) { // if parsed well d->sessions.insert(key, s); // emit incomingSession makes sense when there are no unsolved conflicts in content descriptions / transports diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index ff6f4b80..3d3622b4 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -410,7 +410,7 @@ class Session : public QObject // Note incoming session are not registered in Jingle Manager until validated. // and then either rejected or registered in Pending state. - Session(Manager *manager, const Jid &peer); + Session(Manager *manager, const Jid &peer, Origin role = Origin::Initiator); ~Session(); Manager* manager() const; From a2326a596a2b77c801cd1f0a798026899e3f43b2 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 20:48:53 +0300 Subject: [PATCH 024/383] jingle: properly accept incoming content --- src/xmpp/xmpp-im/jingle-ft.cpp | 8 ++++---- src/xmpp/xmpp-im/jingle-s5b.cpp | 2 +- src/xmpp/xmpp-im/jingle.cpp | 6 ------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index dbeb7508..8622be85 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -605,7 +605,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() thumb.uri = QLatin1String("cid:") + data.cid(); d->file.setThumbnail(thumb); } - ContentBase cb(d->pad->session()->role(), d->contentName); + ContentBase cb(d->creator, d->contentName); cb.senders = d->senders; auto cel = cb.toXml(doc, "content"); cel.appendChild(doc->createElementNS(NS, "description")).appendChild(d->file.toXml(doc)); @@ -624,8 +624,8 @@ OutgoingUpdate Application::takeOutgoingUpdate() } if (d->state == State::Connecting || d->state == State::Active || d->state == State::Pending) { if (d->transport->hasUpdates()) { // failed to select next transport. can't continue - ContentBase cb(d->pad->session()->role(), d->contentName); - cb.senders = d->senders; + ContentBase cb(d->creator, d->contentName); + //cb.senders = d->senders; auto cel = cb.toXml(doc, "content"); QDomElement tel; OutgoingUpdateCB trCallback; @@ -636,7 +636,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() } if (d->state == State::Finishing) { if (d->transportFailed) { - ContentBase cb(d->pad->session()->role(), d->contentName); + ContentBase cb(d->creator, d->contentName); QList updates; updates << cb.toXml(doc, "content"); updates << Reason(Reason::Condition::FailedTransport).toXml(doc); diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 661cef74..2a4f55ff 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -406,7 +406,7 @@ class Transport::Private Transport::Mode mode = Transport::Tcp; QTimer probingTimer; QElapsedTimer lastConnectionStart; - size_t blockSize = 8129; + size_t blockSize = 8192; QSharedPointer connection; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index c6766a11..ed385f9d 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -699,9 +699,6 @@ class Session::Private */ Action expectedContentAction = role == Origin::Initiator? Action::ContentAdd : Action::ContentAccept; for (const auto &c: contentList) { - if (c->creator() != role) { - continue; // we care only about local content for now. - } auto out = c->outgoingUpdateType(); if (out == Action::ContentReject) { // yeah we are rejecting local content. invalid? lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); @@ -724,9 +721,6 @@ class Session::Private QList contents; QList acceptApps; for (const auto &p: contentList) { - if (p->creator() != role) { - continue; // we care only about local content for now. - } QList xml; OutgoingUpdateCB callback; std::tie(xml, callback) = p->takeOutgoingUpdate(); From 863045f2c907765c11b61ae2ff737a4c5b343c0c Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 15 May 2019 21:37:59 +0300 Subject: [PATCH 025/383] jingle: don't forget to start transfers when our accept is acknowledged --- src/xmpp/xmpp-im/jingle-s5b.cpp | 2 ++ src/xmpp/xmpp-im/jingle.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 2a4f55ff..90282327 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -842,6 +842,8 @@ void Transport::start() { d->connectionStarted = true; d->tryConnectToRemoteCandidate(); + // if there is no higher priority candidates than ours but they are already connected then + d->checkAndFinishNegotiation(); } bool Transport::update(const QDomElement &transportEl) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index ed385f9d..426ed4bf 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -738,6 +738,9 @@ class Session::Private auto callback = std::get<1>(h); if (app) { callback(); + if (role == Origin::Responder) { + app->start(); + } } } if (finalState == State::Active) { @@ -1142,7 +1145,7 @@ class Session::Private { Application *app; ContentBase cb(ce); - if (!cb.isValid() || !(app = q->content(cb.name, role)) || app->state() >= State::Finishing || !app->transport()) { + if (!cb.isValid() || !(app = q->content(cb.name, cb.creator)) || app->state() >= State::Finishing || !app->transport()) { return false; } auto tel = ce.firstChildElement(QStringLiteral("transport")); From 3296abe95dc7868bfef08c072ecd579632f8667c Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 00:43:20 +0300 Subject: [PATCH 026/383] jingle-ft: implemented transport read procedure --- src/xmpp/xmpp-im/jingle-ft.cpp | 42 ++++++++++++++++++++++++++++------ src/xmpp/xmpp-im/jingle-ft.h | 1 + 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 8622be85..dae20772 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -405,6 +405,13 @@ class Application::Private emit q->stateChanged(s); } + void handleStreamFail() + { + // TODO d->lastError = Condition::FailedApplication + connection.reset(); + setState(State::Finished); + } + void writeNextBlockToTransport() { if (!bytesLeft) { @@ -417,22 +424,40 @@ class Application::Private } QByteArray data = device->read(sz); if (data.isEmpty()) { - // TODO d->lastError = Condition::FailedApplication - connection.reset(); - setState(State::Finished); + handleStreamFail(); return; } if (connection->write(data) == -1) { - // TODO d->lastError = Condition::FailedApplication - connection.reset(); - setState(State::Finished); + handleStreamFail(); return; } + emit q->progress(device->pos()); } void readNextBlockFromTransport() { - // TODO + quint64 bytesAvail = connection->bytesAvailable(); + if (!bytesLeft || !bytesAvail) { + return; // nothing to read + } + quint64 sz = transport->blockSize(); + sz = sz? sz : 8192; + if (sz > bytesLeft) { + sz = bytesLeft; + } + if (sz > bytesAvail) { + sz = bytesAvail; + } + QByteArray data = connection->read(sz); + if (data.isEmpty()) { + handleStreamFail(); + return; + } + if (device->write(data) == -1) { + handleStreamFail(); + return; + } + emit q->progress(device->pos()); } }; @@ -538,6 +563,9 @@ bool Application::setTransport(const QSharedPointer &transport) } }); d->setState(State::Active); + if (d->pad->session()->role() != d->senders && d->connection->bytesAvailable()) { + d->readNextBlockFromTransport(); + } }); connect(transport.data(), &Transport::failed, this, [this](){ diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 72cd9598..b50ff33a 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -144,6 +144,7 @@ class Application : public XMPP::Jingle::Application signals: void deviceRequested(quint64 offset, quint64 size); + void progress(quint64 offset); private: class Private; From 18be2101b759e54fedd99dcd0e12c92477b07f39 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 11:28:02 +0300 Subject: [PATCH 027/383] jingle: make file receive working --- src/xmpp/xmpp-im/jingle-ft.cpp | 52 +++++++------ src/xmpp/xmpp-im/jingle-s5b.cpp | 126 +++++++++++++++++++++++--------- src/xmpp/xmpp-im/jingle-s5b.h | 4 + src/xmpp/xmpp-im/jingle.cpp | 6 ++ 4 files changed, 128 insertions(+), 60 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index dae20772..1eba2dbf 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -436,28 +436,29 @@ class Application::Private void readNextBlockFromTransport() { - quint64 bytesAvail = connection->bytesAvailable(); - if (!bytesLeft || !bytesAvail) { - return; // nothing to read - } - quint64 sz = transport->blockSize(); - sz = sz? sz : 8192; - if (sz > bytesLeft) { - sz = bytesLeft; - } - if (sz > bytesAvail) { - sz = bytesAvail; - } - QByteArray data = connection->read(sz); - if (data.isEmpty()) { - handleStreamFail(); - return; - } - if (device->write(data) == -1) { - handleStreamFail(); - return; + while (quint64 bytesAvail = connection->bytesAvailable()) { + qDebug("bytes available %llu", bytesAvail); + if (!bytesLeft || !bytesAvail) { + return; // nothing to read + } + quint64 sz = 65536; // should be respect transport->blockSize() ? + if (sz > bytesLeft) { + sz = bytesLeft; + } + if (sz > bytesAvail) { + sz = bytesAvail; + } + QByteArray data = connection->read(sz); + if (data.isEmpty()) { + handleStreamFail(); + return; + } + if (device->write(data) == -1) { + handleStreamFail(); + return; + } + emit q->progress(device->pos()); } - emit q->progress(device->pos()); } }; @@ -652,12 +653,15 @@ OutgoingUpdate Application::takeOutgoingUpdate() } if (d->state == State::Connecting || d->state == State::Active || d->state == State::Pending) { if (d->transport->hasUpdates()) { // failed to select next transport. can't continue - ContentBase cb(d->creator, d->contentName); - //cb.senders = d->senders; - auto cel = cb.toXml(doc, "content"); QDomElement tel; OutgoingUpdateCB trCallback; std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); + if (tel.isNull()) { + qWarning("transport for content=%s reported it had updates but got null update", qPrintable(d->contentName)); + return OutgoingUpdate(); + } + ContentBase cb(d->creator, d->contentName); + auto cel = cb.toXml(doc, "content"); cel.appendChild(tel); return OutgoingUpdate{QList()<socksClient->disconnect(); + delete d->socksClient; + d->socksClient = nullptr; +} + +bool Candidate::operator==(const Candidate &other) const +{ + return d.data() == other.d.data(); +} + class Transport::Private { public: @@ -448,7 +460,7 @@ class Transport::Private quint64 maxProbingPrio = 0; quint64 maxNewPrio = 0; Candidate maxProbing; - Candidate maxNew; + QList maxNew; /* We have to find highest-priority already connecting candidate and highest-priority new candidate. @@ -461,21 +473,26 @@ class Transport::Private */ for (auto &c: remoteCandidates) { - if (c.state() == Candidate::New && c.priority() > maxNewPrio) { - maxNew = c; - maxNewPrio = c.priority(); + if (c.state() == Candidate::New) { + if (c.priority() > maxNewPrio) { + maxNew = QList(); + maxNew.append(c); + maxNewPrio = c.priority(); + } else if (c.priority() == maxNewPrio) { + maxNew.append(c); + } } if (c.state() == Candidate::Probing && c.priority() > maxProbingPrio) { maxProbing = c; maxProbingPrio = c.priority(); } } - if (!maxNew) { + if (maxNew.isEmpty()) { return; // nowhere to connect } if (maxProbing) { - if (maxNew.priority() < maxProbing.priority()) { + if (maxNewPrio < maxProbing.priority()) { if (probingTimer.isActive()) { return; // we will come back here soon } @@ -487,27 +504,37 @@ class Transport::Private } } - // now we have to connect to maxNew candidate - lastConnectionStart.start(); - QString key = maxNew.type() == Candidate::Proxy? dstaddr : directAddr; - maxNew.setState(Candidate::Probing); - maxNew.connectToHost(key, Candidate::Pending, [this, maxNew](bool success) { - // candidate's status had to be changed by connectToHost, so we don't set it again - if (success) { - // let's reject candidates which are meaningless to try - for (auto &c: remoteCandidates) { - if (c.state() == Candidate::New && c.priority() <= maxNew.priority()) { - c.setState(Candidate::Discarded); + // now we have to connect to maxNew candidates + for (auto &mnc: maxNew) { + lastConnectionStart.start(); + QString key = mnc.type() == Candidate::Proxy? dstaddr : directAddr; + mnc.setState(Candidate::Probing); + mnc.connectToHost(key, Candidate::Pending, [this, mnc](bool success) { + // candidate's status had to be changed by connectToHost, so we don't set it again + if (success) { + // let's reject candidates which are meaningless to try + bool hasUnckeckedNew = false; + for (auto &c: remoteCandidates) { + if (c.state() == Candidate::New) { + if (c.priority() <= mnc.priority()) { + c.setState(Candidate::Discarded); + } else { + hasUnckeckedNew = true; + } + } } + if (!hasUnckeckedNew) { + pendingActions &= ~Private::NewCandidate; // just if we had it for example after proxy discovery + } + if (proxyDiscoveryInProgress && (mnc.priority() >> 16) > Candidate::ProxyPreference) { + proxyDiscoveryInProgress = false; // doesn't make sense anymore + } + // TODO do the same for upnp + updateMinimalPriority(); } - if (proxyDiscoveryInProgress && (maxNew.priority() >> 16) > Candidate::ProxyPreference) { - proxyDiscoveryInProgress = false; // doesn't make sense anymore - } - // TODO do the same for upnp - updateMinimalPriority(); - } - checkAndFinishNegotiation(); - }, mode == Transport::Udp); + checkAndFinishNegotiation(); + }, mode == Transport::Udp); + } } bool hasUnaknowledgedLocalCandidates() const @@ -599,10 +626,7 @@ class Transport::Private } } if (c.state() == Candidate::Active) { - connection.reset(new Connection(c.takeSocksClient(), mode)); - localCandidates.clear(); - remoteCandidates.clear(); - emit q->connected(); + handleConnected(c); } } else { // both sides reported candidate error emit q->failed(); @@ -686,6 +710,34 @@ class Transport::Private localReportedCandidateError = true; // as a sign of completeness even if not true } } + + // now check and reset NewCandidate pending action + bool haveNewCandidates = false; + for (auto &c: remoteCandidates) { + if (c.state() == Candidate::New) { + haveNewCandidates = true; + break; + } + } + if (!haveNewCandidates) { + pendingActions &= ~Private::NewCandidate; + } + } + + void handleConnected(Candidate &connCand) + { + connection.reset(new Connection(connCand.takeSocksClient(), mode)); + probingTimer.stop(); + for (auto &rc: remoteCandidates) { + if (rc != connCand && rc.state() == Candidate::Probing) { + rc.deleteSocksClient(); + } + } + QTimer::singleShot(0, q, [this](){ + localCandidates.clear(); + remoteCandidates.clear(); + emit q->connected(); + }); } }; @@ -919,12 +971,7 @@ bool Transport::update(const QDomElement &transportEl) return true; } c.setState(Candidate::Active); - d->connection.reset(new Connection(c.takeSocksClient(), d->mode)); - QTimer::singleShot(0, this, [this](){ - d->localCandidates.clear(); - d->remoteCandidates.clear(); - emit connected(); - }); + d->handleConnected(c); return true; } @@ -1011,6 +1058,8 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() } d->checkAndFinishNegotiation(); }}; + } else { + qWarning("Got NewCandidate pending action but no candidate to send"); } } else if (d->pendingActions & Private::CandidateUsed) { d->pendingActions &= ~Private::CandidateUsed; @@ -1036,6 +1085,9 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() break; } + if (std::get<0>(upd).isNull()) { + qWarning("Got CandidateUsed pending action but no pending candidates"); + } } else if (d->pendingActions & Private::CandidateError) { d->pendingActions &= ~Private::CandidateError; // we are here because all remote are already in Discardd state @@ -1078,6 +1130,8 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() d->localUsedCandidate = Candidate(); emit failed(); }}; + } else { + qWarning("Got ProxyError pending action but no local used candidate is not set"); } } @@ -1114,7 +1168,7 @@ bool Transport::incomingConnection(SocksClient *sc) if (!d->connection) { auto s = sc->abstractSocket(); for (auto &c: d->localCandidates) { - if (s->localPort() == c.localPort() && c.state() == Candidate::Pending) { + if (s->localPort() == c.localPort() && (c.state() == Candidate::Pending || c.state() == Candidate::Unacked)) { if(d->mode == Transport::Udp) sc->grantUDPAssociate("", 0); else diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index f25138a9..88d754be 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -117,6 +117,10 @@ class Candidate { void connectToHost(const QString &key, State successState, std::function callback, bool isUdp = false); bool incomingConnection(SocksClient *sc); SocksClient* takeSocksClient(); + void deleteSocksClient(); + + bool operator==(const Candidate &other) const; + inline bool operator!=(const Candidate &other) const { return !(*this == other); } private: class Private; friend class Transport; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 426ed4bf..c1535233 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1066,6 +1066,7 @@ class Session::Private switch (err) { case Private::AddContentError::Unparsed: case Private::AddContentError::Unexpected: + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; case Private::AddContentError::Unsupported: rejects += Reason(cond).toXml(manager->client()->doc()); @@ -1101,6 +1102,7 @@ class Session::Private std::tie(parsed, apps) = parseContentAcceptList(jingleEl); if (!parsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } @@ -1123,6 +1125,7 @@ class Session::Private std::tie(parsed, apps) = parseContentAcceptList(jingleEl); // marks valid apps as accepted if (!parsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } @@ -1146,10 +1149,12 @@ class Session::Private Application *app; ContentBase cb(ce); if (!cb.isValid() || !(app = q->content(cb.name, cb.creator)) || app->state() >= State::Finishing || !app->transport()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } auto tel = ce.firstChildElement(QStringLiteral("transport")); if (tel.isNull() || tel.attribute(QStringLiteral("xmlns")) != app->transport()->pad()->ns()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } updates.append(qMakePair(app->transport(), tel)); @@ -1157,6 +1162,7 @@ class Session::Private for (auto &u: updates) { if (!u.first->update(u.second)) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; // yes this may lead to half updated content, but what choice do we have? } } From 70d2c562c3ba206ba4b7b528f14d7b6f7a7bb9d5 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 19:31:26 +0300 Subject: [PATCH 028/383] jingle: prepare content being added to an initiated session --- src/xmpp/xmpp-im/jingle.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index c1535233..a51c3e4e 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1250,7 +1250,13 @@ Application *Session::content(const QString &contentName, Origin creator) void Session::addContent(Application *content) { + Q_ASSERT(d->state < State::Finishing); d->addAndInitContent(d->role, content); + if (d->state >= State::PrepareLocalOffer) { + // If we add content to already initiated session then we are gonna + // send it immediatelly. So start prepare + content->prepare(); + } } const QMap &Session::contentList() const From e3f1200dadd89552658e54dee8c9c021f62823cc Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 21:04:54 +0300 Subject: [PATCH 029/383] Fixed crash on destruction of invalid Jingle s5b transport --- src/xmpp/xmpp-im/jingle-s5b.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 794e2d43..da0f9c84 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -768,7 +768,9 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::~Transport() { - static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); + if (d) { + static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); + } } TransportManagerPad::Ptr Transport::pad() const From 271fc3580cb66ff4dde0a272394a2783ed212cde Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 21:16:33 +0300 Subject: [PATCH 030/383] Validate host/port as it comes from S5BServer --- src/xmpp/xmpp-im/jingle-s5b.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index da0f9c84..2ce50077 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -792,6 +792,9 @@ void Transport::prepare() auto serv = m->socksServ(); if (serv) { for(auto const &h: serv->hostList()) { + if (!serv->port() || h.isEmpty()) { + continue; + } Candidate c(h, serv->port(), d->generateCid(), Candidate::Direct); if (!d->isDup(c)) { d->localCandidates.insert(c.cid(), c); From 70d1883f3ab3701535980bd450e579e991b49b74 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 16 May 2019 23:54:00 +0300 Subject: [PATCH 031/383] Fixed 0-length jingle downloads --- src/xmpp/xmpp-im/jingle-ft.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 1eba2dbf..7dc30b78 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -432,6 +432,13 @@ class Application::Private return; } emit q->progress(device->pos()); + bytesLeft -= sz; + if (!bytesLeft) { + if (closeDeviceOnFinish) { + device->close(); + } + setState(State::Finished); + } } void readNextBlockFromTransport() @@ -458,6 +465,14 @@ class Application::Private return; } emit q->progress(device->pos()); + bytesLeft -= sz; + } + if (!bytesLeft) { + if (closeDeviceOnFinish) { + device->close(); + } + // TODO send + setState(State::Finished); } } }; From 784850281668211f109646ede6bc92a3d1e0afea Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 17 May 2019 00:17:38 +0300 Subject: [PATCH 032/383] jingle-ft reorder progress and stateChange events --- src/xmpp/xmpp-im/jingle-ft.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 7dc30b78..b658d3c0 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -443,11 +443,8 @@ class Application::Private void readNextBlockFromTransport() { - while (quint64 bytesAvail = connection->bytesAvailable()) { - qDebug("bytes available %llu", bytesAvail); - if (!bytesLeft || !bytesAvail) { - return; // nothing to read - } + quint64 bytesAvail; + while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { quint64 sz = 65536; // should be respect transport->blockSize() ? if (sz > bytesLeft) { sz = bytesLeft; @@ -557,13 +554,6 @@ bool Application::setTransport(const QSharedPointer &transport) connect(transport.data(), &Transport::updated, this, &Application::updated); connect(transport.data(), &Transport::connected, this, [this](){ d->connection = d->transport->connection(); - if (d->acceptFile.range().isValid()) { - d->bytesLeft = d->acceptFile.range().length; - emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); - } else { - d->bytesLeft = d->file.size(); - emit deviceRequested(0, d->bytesLeft); - } connect(d->connection.data(), &Connection::readyRead, this, [this](){ if (!d->device) { return; @@ -579,8 +569,12 @@ bool Application::setTransport(const QSharedPointer &transport) } }); d->setState(State::Active); - if (d->pad->session()->role() != d->senders && d->connection->bytesAvailable()) { - d->readNextBlockFromTransport(); + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + } else { + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); } }); From 457e1c4a1fbd01a7d385221ccc249f86255af931 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 17 May 2019 12:00:52 +0300 Subject: [PATCH 033/383] return accepted file so we can know accepted offset/length --- src/xmpp/xmpp-im/jingle-ft.cpp | 5 +++++ src/xmpp/xmpp-im/jingle-ft.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index b658d3c0..bf6b2e66 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -537,6 +537,11 @@ File Application::file() const return d->file; } +File Application::acceptFile() const +{ + return d->acceptFile; +} + // incoming one? or we have to check real direction bool Application::setTransport(const QSharedPointer &transport) { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index b50ff33a..476d05e9 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -127,6 +127,7 @@ class Application : public XMPP::Jingle::Application SetDescError setDescription(const QDomElement &description) override; void setFile(const File &file); File file() const; + File acceptFile() const; bool setTransport(const QSharedPointer &transport) override; QSharedPointer transport() const override; From a26f7d8dba2e8be2f05fc622a487c6619eadee65 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 17 May 2019 22:09:43 +0300 Subject: [PATCH 034/383] State Finishing when user calls session->terminate --- src/xmpp/xmpp-im/jingle.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index a51c3e4e..7d74f3a7 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1328,6 +1328,7 @@ void Session::initiate() void Session::terminate(Reason::Condition cond, const QString &comment) { + d->state = State::Finishing; d->terminateReason = Reason(cond, comment); } From a2d258622acdc59a47a04b5f05f277ad1296f84f Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 18 May 2019 23:47:10 +0300 Subject: [PATCH 035/383] Fixed possible race condition in incoming socks connection initialization --- src/xmpp/xmpp-im/jingle-s5b.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 2ce50077..11face03 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1173,13 +1173,17 @@ bool Transport::incomingConnection(SocksClient *sc) if (!d->connection) { auto s = sc->abstractSocket(); for (auto &c: d->localCandidates) { - if (s->localPort() == c.localPort() && (c.state() == Candidate::Pending || c.state() == Candidate::Unacked)) { + if (s->localPort() == c.localPort() && + (c.state() == Candidate::Pending || c.state() == Candidate::Unacked) && + c.incomingConnection(sc)) + { + if(d->mode == Transport::Udp) sc->grantUDPAssociate("", 0); else sc->grantConnect(); // we can also remember the server it comes from. static_cast(sender()) - return c.incomingConnection(sc); + return true; } } } From c67e999f47fc8c4712d229ddd2a91c0cf97c50ea Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 19 May 2019 10:07:18 +0300 Subject: [PATCH 036/383] Always clsoe socks connection on Finished state --- src/xmpp/xmpp-im/jingle-ft.cpp | 16 +++++++--------- src/xmpp/xmpp-im/jingle-s5b.cpp | 10 ++++++++++ src/xmpp/xmpp-im/jingle.cpp | 5 +++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index bf6b2e66..994e1b21 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -399,8 +399,13 @@ class Application::Private void setState(State s) { state = s; - if (s == State::Finished && device && closeDeviceOnFinish) { - device->close(); + if (s == State::Finished) { + if (device && closeDeviceOnFinish) { + device->close(); + } + if (connection) { + connection->close(); + } } emit q->stateChanged(s); } @@ -408,7 +413,6 @@ class Application::Private void handleStreamFail() { // TODO d->lastError = Condition::FailedApplication - connection.reset(); setState(State::Finished); } @@ -434,9 +438,6 @@ class Application::Private emit q->progress(device->pos()); bytesLeft -= sz; if (!bytesLeft) { - if (closeDeviceOnFinish) { - device->close(); - } setState(State::Finished); } } @@ -465,9 +466,6 @@ class Application::Private bytesLeft -= sz; } if (!bytesLeft) { - if (closeDeviceOnFinish) { - device->close(); - } // TODO send setState(State::Finished); } diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 11face03..187fdbe9 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -87,6 +87,16 @@ class Connection : public XMPP::Jingle::Connection return client->bytesToWrite(); } + void close() + { + if (client) { + client->disconnect(this); + } + XMPP::Jingle::Connection::close(); + client->deleteLater(); + client = nullptr; + } + protected: qint64 writeData(const char *data, qint64 maxSize) { diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 7d74f3a7..e57d3b37 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -602,6 +602,11 @@ class Session::Private state = State::Finished; emit q->terminated(); signalingContent.clear(); + for (auto &c: contentList) { + if (c->state() != State::Finished) { + c->setState(State::Finished); + } + } auto vals = contentList.values(); contentList.clear(); while (vals.size()) { From e4047959965d49477e9fca7c4ae50b3c958e1765 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 19 May 2019 13:36:37 +0300 Subject: [PATCH 037/383] Close socks socket only when when all data realy written --- src/xmpp/xmpp-im/jingle-ft.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 994e1b21..9d82ad9a 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -419,6 +419,7 @@ class Application::Private void writeNextBlockToTransport() { if (!bytesLeft) { + setState(State::Finished); return; // everything is written } auto sz = transport->blockSize(); @@ -437,9 +438,6 @@ class Application::Private } emit q->progress(device->pos()); bytesLeft -= sz; - if (!bytesLeft) { - setState(State::Finished); - } } void readNextBlockFromTransport() From 913f7e7f4c94ed230f21d4490aa66db8add8e991 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 19 May 2019 15:10:04 +0300 Subject: [PATCH 038/383] Fixed crah in Jingle task callback + fixed Session::terminate --- src/xmpp/xmpp-im/jingle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index e57d3b37..d1a20a09 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -633,7 +633,7 @@ class Session::Private auto jt = new JT(manager->client()->rootTask()); jt->request(otherParty, xml); - QObject::connect(jt, &JT::finished, manager, [jt, jingle, successCB, this](){ + QObject::connect(jt, &JT::finished, q, [jt, jingle, successCB, this](){ waitingAck = false; if (jt->success()) { if (successCB) { @@ -1335,6 +1335,7 @@ void Session::terminate(Reason::Condition cond, const QString &comment) { d->state = State::Finishing; d->terminateReason = Reason(cond, comment); + d->planStep(); } TransportManagerPad::Ptr Session::transportPadFactory(const QString &ns) From a3c07caf6ee8d9dc34f31261bb8c23a7d1a5d1cd Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 19 May 2019 15:36:01 +0300 Subject: [PATCH 039/383] Remove session from internal sessions list on terminate for any type of session --- src/xmpp/xmpp-im/jingle.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index d1a20a09..ae0908a1 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1479,6 +1479,13 @@ class Manager::Private XMPP::Stanza::Error lastError; QHash,Session*> sessions; int maxSessions = -1; // no limit + + void setupSession(Session *s) + { + QObject::connect(s, &Session::terminated, manager, [this, s](){ + sessions.remove(qMakePair(s->peer(), s->sid())); + }); + } }; Manager::Manager(Client *client) : @@ -1606,6 +1613,7 @@ Session* Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, auto s = new Session(this, from, Origin::Responder); if (s->incomingInitiate(jingle, jingleEl)) { // if parsed well d->sessions.insert(key, s); + d->setupSession(s); // emit incomingSession makes sense when there are no unsolved conflicts in content descriptions / transports //QTimer::singleShot(0,[s, this](){ emit incomingSession(s); }); QMetaObject::invokeMethod(this, "incomingSession", Qt::QueuedConnection, Q_ARG(Session*, s)); @@ -1624,9 +1632,7 @@ XMPP::Stanza::Error Manager::lastError() const Session *Manager::newSession(const Jid &j) { auto s = new Session(this, j); - connect(s, &Session::terminated, this, [this, s](){ - d->sessions.remove(qMakePair(s->peer(), s->sid())); - }); + d->setupSession(s); return s; } From b2873f138eb6827659b7264d971757c3866bda89 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 23 May 2019 08:13:37 +0300 Subject: [PATCH 040/383] Started implementation of tcp port reserver --- src/irisnet/noncore/noncore.pri | 6 +- src/irisnet/noncore/tcpportreserver.cpp | 96 +++++++++++++++++++++++++ src/irisnet/noncore/tcpportreserver.h | 52 ++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 src/irisnet/noncore/tcpportreserver.cpp create mode 100644 src/irisnet/noncore/tcpportreserver.h diff --git a/src/irisnet/noncore/noncore.pri b/src/irisnet/noncore/noncore.pri index 559ed568..c4b0e005 100644 --- a/src/irisnet/noncore/noncore.pri +++ b/src/irisnet/noncore/noncore.pri @@ -27,7 +27,8 @@ HEADERS += \ $$PWD/icelocaltransport.h \ $$PWD/iceturntransport.h \ $$PWD/icecomponent.h \ - $$PWD/ice176.h + $$PWD/ice176.h \ + $$PWD/tcpportreserver.h SOURCES += \ $$PWD/processquit.cpp \ @@ -43,7 +44,8 @@ SOURCES += \ $$PWD/icelocaltransport.cpp \ $$PWD/iceturntransport.cpp \ $$PWD/icecomponent.cpp \ - $$PWD/ice176.cpp + $$PWD/ice176.cpp \ + $$PWD/tcpportreserver.cpp INCLUDEPATH += $$PWD/legacy include(legacy/legacy.pri) diff --git a/src/irisnet/noncore/tcpportreserver.cpp b/src/irisnet/noncore/tcpportreserver.cpp new file mode 100644 index 00000000..fd140504 --- /dev/null +++ b/src/irisnet/noncore/tcpportreserver.cpp @@ -0,0 +1,96 @@ +/* + * tcpportreserver.cpp - dialog for handling tabbed chats + * Copyright (C) 2019 Sergey Ilinykh + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include + +#include "tcpportreserver.h" +#include "ice176.h" + +namespace XMPP { + +struct StaticForwarding +{ + QString extHost; + quint16 extPort; + QHostAddress localIp; + quint16 localPort; +}; + +struct TcpPortReserver::Private +{ + QMap staticForwarding; +}; + +TcpPortReserver::TcpPortReserver(QObject *parent) : QObject(parent), + d(new Private) +{ + +} + +TcpPortReserver::~TcpPortReserver() +{ + +} + +QList TcpPortReserver::borrow(const QString &scopeId, const QString &intanceId) +{ + QList listenAddrs; + foreach(const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) + { + if (!(ni.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning))) { + continue; + } + if (ni.flags() & QNetworkInterface::IsLoopBack) { + continue; + } + QList entries = ni.addressEntries(); + foreach(const QNetworkAddressEntry &na, entries) + { + QHostAddress h = na.ip(); + if (h.isLoopback()) { + continue; + } + + // don't put the same address in twice. + // this also means that if there are + // two link-local ipv6 interfaces + // with the exact same address, we + // only use the first one + if(listenAddrs.contains(h)) + continue; +#if QT_VERSION >= QT_VERSION_CHECK(5,11,0) + if(h.protocol() == QAbstractSocket::IPv6Protocol && h.isLinkLocal()) +#else + if(h.protocol() == QAbstractSocket::IPv6Protocol && XMPP::Ice176::isIPv6LinkLocalAddress(h)) +#endif + h.setScopeId(ni.name()); + listenAddrs += h; + } + } + + return QList(); // FIXME +} + + +void TcpPortReserver::setExternalHost(const QString &scopeId, const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort) +{ + d->staticForwarding.insert(scopeId, StaticForwarding{extHost, extPort, localIp, localPort}); +} + +} // namespace XMPP diff --git a/src/irisnet/noncore/tcpportreserver.h b/src/irisnet/noncore/tcpportreserver.h new file mode 100644 index 00000000..94a68b66 --- /dev/null +++ b/src/irisnet/noncore/tcpportreserver.h @@ -0,0 +1,52 @@ +/* + * tcpportreserver.cpp - dialog for handling tabbed chats + * Copyright (C) 2019 Sergey Ilinykh + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef TCPPORTRESERVER_H +#define TCPPORTRESERVER_H + +#include + +class QTcpServer; +class QHostAddress; + +namespace XMPP { + +class TcpPortReserver : public QObject +{ + Q_OBJECT +public: + explicit TcpPortReserver(QObject *parent = nullptr); + ~TcpPortReserver(); + + // port withing instanceId are uique but can be the same withing the same scopeId + // scopes never intersect + QList borrow(const QString &scopeId, const QString &intanceId); + void setExternalHost(const QString &scopeId, const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort); + +signals: + +public slots: +private: + class Private; + QScopedPointer d; +}; + +} // namespace XMPP + +#endif // TCPPORTRESERVER_H From d95407de6cea2d09e6f7b2a072053102929c12eb Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 1 Jun 2019 19:38:32 +0300 Subject: [PATCH 041/383] Tcp port reserver for file transfer (#60) Implemented a util creating servers servers on all interfaces and deleting them when not used anymore. --- include/iris/tcpportreserver.h | 1 + src/irisnet/CMakeLists.txt | 2 + src/irisnet/noncore/cutestuff/socks.cpp | 42 +- src/irisnet/noncore/cutestuff/socks.h | 2 + src/irisnet/noncore/tcpportreserver.cpp | 194 ++++++++- src/irisnet/noncore/tcpportreserver.h | 136 +++++- src/xmpp/xmpp-im/client.cpp | 12 + src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle-s5b.cpp | 556 ++++++++++++++++-------- src/xmpp/xmpp-im/jingle-s5b.h | 22 +- src/xmpp/xmpp-im/jingle.cpp | 43 +- src/xmpp/xmpp-im/jingle.h | 1 + src/xmpp/xmpp-im/s5b.cpp | 475 ++++++++------------ src/xmpp/xmpp-im/s5b.h | 50 +-- src/xmpp/xmpp-im/xmpp_client.h | 3 + src/xmpp/xmpp-im/xmpp_liverosteritem.h | 1 + src/xmpp/xmpp-im/xmpp_rosteritem.h | 1 + 17 files changed, 986 insertions(+), 556 deletions(-) create mode 100644 include/iris/tcpportreserver.h diff --git a/include/iris/tcpportreserver.h b/include/iris/tcpportreserver.h new file mode 100644 index 00000000..ed0f9a46 --- /dev/null +++ b/include/iris/tcpportreserver.h @@ -0,0 +1 @@ +#include "../../src/irisnet/noncore/tcpportreserver.h" diff --git a/src/irisnet/CMakeLists.txt b/src/irisnet/CMakeLists.txt index 662c8541..3141406e 100644 --- a/src/irisnet/CMakeLists.txt +++ b/src/irisnet/CMakeLists.txt @@ -48,6 +48,7 @@ set(SOURCES noncore/stuntransaction.cpp noncore/turnclient.cpp noncore/udpportreserver.cpp + noncore/tcpportreserver.cpp noncore/cutestuff/bsocket.cpp ) @@ -89,6 +90,7 @@ set(HEADERS noncore/stuntransaction.h noncore/turnclient.h noncore/udpportreserver.h + noncore/tcpportreserver.h noncore/cutestuff/bsocket.h noncore/cutestuff/bytestream.h diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index 41f645d6..2dbc8272 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -1019,22 +1019,15 @@ SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddre class SocksServer::Private { public: - Private(SocksServer *_q) : - serv(_q) - { - } - - QTcpServer serv; + QTcpServer *serv = nullptr; QList incomingConns; - QUdpSocket *sd; + QUdpSocket *sd = nullptr; }; SocksServer::SocksServer(QObject *parent) :QObject(parent) { - d = new Private(this); - d->sd = 0; - connect(&d->serv, SIGNAL(newConnection()), SLOT(newConnection())); + d = new Private; } SocksServer::~SocksServer() @@ -1046,22 +1039,32 @@ SocksServer::~SocksServer() delete d; } +void SocksServer::setServerSocket(QTcpServer *server) +{ + d->serv = server; + connect(d->serv, SIGNAL(newConnection()), SLOT(newConnection())); +} + bool SocksServer::isActive() const { - return d->serv.isListening(); + return d->serv->isListening(); } bool SocksServer::listen(quint16 port, bool udp) { stop(); - if(!d->serv.listen(QHostAddress::Any, port)) + if (!d->serv) { + setServerSocket(new QTcpServer(this)); + } + if(!d->serv->listen(QHostAddress::Any, port)) return false; if(udp) { d->sd = new QUdpSocket(this); if(!d->sd->bind(QHostAddress::LocalHost, port)) { delete d->sd; - d->sd = 0; - d->serv.close(); + d->sd = nullptr; + delete d->serv; + d->serv = nullptr; return false; } connect(d->sd, SIGNAL(readyRead()), SLOT(sd_activated())); @@ -1072,18 +1075,19 @@ bool SocksServer::listen(quint16 port, bool udp) void SocksServer::stop() { delete d->sd; - d->sd = 0; - d->serv.close(); + d->sd = nullptr; + delete d->serv; + d->serv = nullptr; } int SocksServer::port() const { - return d->serv.serverPort(); + return d->serv? d->serv->serverPort(): 0; } QHostAddress SocksServer::address() const { - return d->serv.serverAddress(); + return d->serv? d->serv->serverAddress(): QHostAddress(); } SocksClient *SocksServer::takeIncoming() @@ -1111,7 +1115,7 @@ void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray void SocksServer::newConnection() { - SocksClient *c = new SocksClient(d->serv.nextPendingConnection(), this); + SocksClient *c = new SocksClient(d->serv->nextPendingConnection(), this); connect(c, SIGNAL(error(int)), this, SLOT(connectionError())); d->incomingConns.append(c); incomingReady(); diff --git a/src/irisnet/noncore/cutestuff/socks.h b/src/irisnet/noncore/cutestuff/socks.h index 6ca5efd6..eb3811db 100644 --- a/src/irisnet/noncore/cutestuff/socks.h +++ b/src/irisnet/noncore/cutestuff/socks.h @@ -26,6 +26,7 @@ class QHostAddress; class QTcpSocket; +class QTcpServer; class SocksClient; class SocksServer; @@ -135,6 +136,7 @@ class SocksServer : public QObject SocksServer(QObject *parent=0); ~SocksServer(); + void setServerSocket(QTcpServer *server); bool isActive() const; bool listen(quint16 port, bool udp=false); void stop(); diff --git a/src/irisnet/noncore/tcpportreserver.cpp b/src/irisnet/noncore/tcpportreserver.cpp index fd140504..e1ad089c 100644 --- a/src/irisnet/noncore/tcpportreserver.cpp +++ b/src/irisnet/noncore/tcpportreserver.cpp @@ -1,5 +1,5 @@ /* - * tcpportreserver.cpp - dialog for handling tabbed chats + * tcpportreserver.cpp - a utility to bind local tcp server sockets * Copyright (C) 2019 Sergey Ilinykh * * This program is free software; you can redistribute it and/or @@ -18,37 +18,64 @@ */ #include +#include +#include #include "tcpportreserver.h" #include "ice176.h" namespace XMPP { -struct StaticForwarding +TcpPortDiscoverer::TcpPortDiscoverer(TcpPortScope *scope) : + QObject(scope), + scope(scope) { - QString extHost; - quint16 extPort; - QHostAddress localIp; - quint16 localPort; -}; -struct TcpPortReserver::Private +} + +bool TcpPortDiscoverer::setExternalHost(const QString &extHost, quint16 extPort, const QHostAddress &localAddr, quint16 localPort) { - QMap staticForwarding; -}; + if (!(typeMask & TcpPortServer::NatAssited)) { + return false; // seems like we don't need nat-assited + } + auto server = scope->bind(localAddr, localPort); + if (!server) { + return false; + } + TcpPortServer::Port p; + p.portType = TcpPortServer::NatAssited; + p.publishHost = extHost; + p.publishPort = extPort; + server->setPortInfo(p); + servers.append(server); + emit portAvailable(); + return true; +} -TcpPortReserver::TcpPortReserver(QObject *parent) : QObject(parent), - d(new Private) +TcpPortServer::PortTypes TcpPortDiscoverer::inProgressPortTypes() const { + return 0; // same as for stop() +} +bool TcpPortDiscoverer::isDepleted() const +{ + return servers.size() == 0; // TODO and no active subdiscoveries } -TcpPortReserver::~TcpPortReserver() +TcpPortServer::PortTypes TcpPortDiscoverer::setTypeMask(TcpPortServer::PortTypes mask) { + this->typeMask = mask; + // drop ready ports if any + std::remove_if(servers.begin(), servers.end(), [mask](auto &s){ return !(s->portType() & mask); }); + + TcpPortServer::PortTypes pendingTypes; + for (auto &s: servers) pendingTypes |= s->portType(); + // TODO drop pending subdiscoveries too and update pendingType when implemented + return pendingTypes; } -QList TcpPortReserver::borrow(const QString &scopeId, const QString &intanceId) +void TcpPortDiscoverer::start() { QList listenAddrs; foreach(const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) @@ -84,13 +111,146 @@ QList TcpPortReserver::borrow(const QString &scopeId, const QStrin } } - return QList(); // FIXME + for (auto &h: listenAddrs) { + auto server = scope->bind(h, 0); + if (!server) { + continue; + } + TcpPortServer::Port p; + p.portType = TcpPortServer::Direct; + QHostAddress addr = server->serverAddress(); + addr.setScopeId(QString()); + p.publishHost = addr.toString(); + p.publishPort = server->serverPort(); + server->setPortInfo(p); + servers.append(server); + } + + if (listenAddrs.size()) { + emit portAvailable(); + } +} + +void TcpPortDiscoverer::stop() +{ + // nothing really to do here. but if we invent extension interface it can call stop on subdisco +} + +QList TcpPortDiscoverer::takeServers() +{ + auto ret = servers; + servers.clear(); + for (auto &p: ret) { + p->disconnect(this); + } + return ret; +} + +// -------------------------------------------------------------------------- +// TcpPortScope +// -------------------------------------------------------------------------- +struct TcpPortScope::Private +{ + QHash, QWeakPointer> servers; +}; + + +TcpPortScope::TcpPortScope() : + d(new Private) +{ +} + +TcpPortScope::~TcpPortScope() +{ + +} + +TcpPortDiscoverer *TcpPortScope::disco() +{ + auto discoverer = new TcpPortDiscoverer(this); + QMetaObject::invokeMethod(parent(), "newDiscoverer", Q_ARG(TcpPortDiscoverer*, discoverer)); + QMetaObject::invokeMethod(discoverer, "start"); + return discoverer; +} + +QList TcpPortScope::allServers() const +{ + QList ret; + for (auto &s: d->servers) { + auto sl = s.lock(); + if (sl) { + ret.append(sl); + } + } + return ret; +} + +void TcpPortScope::destroyServer(TcpPortServer *server) +{ + delete server; } +TcpPortServer::Ptr TcpPortScope::bind(const QHostAddress &addr, quint16 port) +{ + if (port) { + auto srv = d->servers.value(qMakePair(addr,port)).toStrongRef(); + if (srv) { + return srv; + } + } + auto socket = new QTcpServer(this); + if (!socket->listen(addr, port)) { + delete socket; + return TcpPortServer::Ptr(); + } + auto server = makeServer(socket); + + TcpPortServer::Ptr shared(server, [](TcpPortServer *s){ + auto scope = qobject_cast(s->parent()); + if (scope) { + scope->d->servers.remove(qMakePair(s->serverAddress(),s->serverPort())); + scope->destroyServer(s); + } else { + delete s; + } + }); + d->servers.insert(qMakePair(socket->serverAddress(), socket->serverPort()), shared.toWeakRef()); + + return shared; +} -void TcpPortReserver::setExternalHost(const QString &scopeId, const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort) + +// -------------------------------------------------------------------------- +// TcpPortScope +// -------------------------------------------------------------------------- +TcpPortReserver::TcpPortReserver(QObject *parent) : QObject(parent) { - d->staticForwarding.insert(scopeId, StaticForwarding{extHost, extPort, localIp, localPort}); + +} + +TcpPortReserver::~TcpPortReserver() +{ + +} + +TcpPortScope *TcpPortReserver::scope(const QString &id) +{ + return findChild(id, Qt::FindDirectChildrenOnly); +} + +void TcpPortReserver::registerScope(const QString &id, TcpPortScope *scope) +{ + scope->setObjectName(id); + scope->setParent(this); +} + +TcpPortScope *TcpPortReserver::unregisterScope(const QString &id) +{ + auto s = scope(id); + if (s) { + s->setParent(nullptr); + } + return s; } } // namespace XMPP diff --git a/src/irisnet/noncore/tcpportreserver.h b/src/irisnet/noncore/tcpportreserver.h index 94a68b66..97017e27 100644 --- a/src/irisnet/noncore/tcpportreserver.h +++ b/src/irisnet/noncore/tcpportreserver.h @@ -1,5 +1,5 @@ /* - * tcpportreserver.cpp - dialog for handling tabbed chats + * tcpportreserver.cpp - a utility to bind local tcp server sockets * Copyright (C) 2019 Sergey Ilinykh * * This program is free software; you can redistribute it and/or @@ -21,12 +21,121 @@ #define TCPPORTRESERVER_H #include - -class QTcpServer; -class QHostAddress; +#include +#include +#include namespace XMPP { +class TcpPortServer : public QObject +{ + Q_OBJECT +public: + using Ptr = QSharedPointer; + + enum PortType { + NoType = 0x0, + Direct = 0x1, + NatAssited = 0x2, + Tunneled = 0x4 + }; + Q_DECLARE_FLAGS(PortTypes, PortType) + + struct Port + { + PortType portType = NoType; + QString publishHost; + quint16 publishPort = 0; + QVariant meta; + }; + + inline TcpPortServer(QTcpServer *serverSocket) : serverSocket(serverSocket) {} + inline void setPortInfo(const Port &port) { this->port = port; } + inline QHostAddress serverAddress() const { return serverSocket->serverAddress(); } + inline quint16 serverPort() const { return serverSocket->serverPort(); } + inline const QString &publishHost() const { return port.publishHost; } + inline quint16 publishPort() const { return port.publishPort; } + inline PortType portType() const { return port.portType; } + inline const QVariant &meta() const { return port.meta; } + +protected: + QTcpServer *serverSocket = nullptr; + Port port; +}; + +class TcpPortScope; +/** + * @brief The TcpPortDiscoverer class + * + * Discovers / starts listening on a set of unique tcp ports. + */ +class TcpPortDiscoverer : public QObject +{ + Q_OBJECT +public: + + TcpPortDiscoverer(TcpPortScope *scope); + bool setExternalHost(const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort); + + TcpPortServer::PortTypes inProgressPortTypes() const; + bool isDepleted() const; + + /** + * @brief setTypeMask sets expected port types mask and frees unnecessary resources + * @param mask + * @return remaining port types + */ + XMPP::TcpPortServer::PortTypes setTypeMask(TcpPortServer::PortTypes mask); + + /** + * @brief takeServers takes all discovered servers + * @return + */ + QList takeServers(); +public slots: + void start(); // it's autocalled after outside world is notified about this new discoverer + void stop(); +signals: + void portAvailable(); +private: + TcpPortServer::PortTypes typeMask = TcpPortServer::PortTypes(TcpPortServer::Direct | TcpPortServer::NatAssited | TcpPortServer::Tunneled); + TcpPortScope *scope = nullptr; + QList servers; +}; + +class TcpPortReserver; +/** + * @brief The TcpPortScope class + * + * Handles scopes of ports. For example just S5B dedicated ports. + * There only on scope instance per scope id + */ +class TcpPortScope: public QObject +{ + Q_OBJECT +public: + TcpPortScope(); + ~TcpPortScope(); + TcpPortDiscoverer* disco(); + QList allServers() const; +protected: + virtual TcpPortServer* makeServer(QTcpServer *socket) = 0; + virtual void destroyServer(TcpPortServer *server); + +private: + friend class TcpPortDiscoverer; + TcpPortServer::Ptr bind(const QHostAddress &addr, quint16 port); + +private: + class Private; + QScopedPointer d; +}; + + +/** + * @brief The TcpPortReserver class + * This class should have the only instance per application + */ class TcpPortReserver : public QObject { Q_OBJECT @@ -34,19 +143,24 @@ class TcpPortReserver : public QObject explicit TcpPortReserver(QObject *parent = nullptr); ~TcpPortReserver(); - // port withing instanceId are uique but can be the same withing the same scopeId - // scopes never intersect - QList borrow(const QString &scopeId, const QString &intanceId); - void setExternalHost(const QString &scopeId, const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort); + /** + * @brief scope returns a registered scope corresponding to scope id + * @param id + * @return scope + * @note Do not reparent the object + */ + TcpPortScope *scope(const QString &id); + void registerScope(const QString &id, TcpPortScope *scope); + TcpPortScope *unregisterScope(const QString &id); signals: + void newDiscoverer(TcpPortDiscoverer *discoverer); public slots: -private: - class Private; - QScopedPointer d; }; } // namespace XMPP +Q_DECLARE_OPERATORS_FOR_FLAGS(XMPP::TcpPortServer::PortTypes) + #endif // TCPPORTRESERVER_H diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index d8573bfa..7396bac5 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -87,6 +87,7 @@ #include "jingle.h" #include "jingle-ft.h" #include "jingle-s5b.h" +#include "tcpportreserver.h" #ifdef Q_OS_WIN #define vsnprintf _vsnprintf @@ -132,6 +133,7 @@ class Client::ClientPrivate LiveRoster roster; ResourceList resourceList; CapsManager *capsman = nullptr; + TcpPortReserver *tcpPortReserver = nullptr; S5BManager *s5bman = nullptr; Jingle::S5B::Manager *jingleS5BManager = nullptr; IBBManager *ibbman = nullptr; @@ -237,6 +239,16 @@ void Client::start(const QString &host, const QString &user, const QString &pass d->active = true; } +void Client::setTcpPortReserver(TcpPortReserver *portReserver) +{ + d->tcpPortReserver = portReserver; +} + +TcpPortReserver * Client::tcpPortReserver() const +{ + return d->tcpPortReserver; +} + void Client::setFileTransferEnabled(bool b) { if(b) { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 476d05e9..327dfbb3 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -50,6 +50,7 @@ class File File(const File &other); File(const QDomElement &file); ~File(); + File& operator=(const File& other) = default; inline bool isValid() const { return d != nullptr; } QDomElement toXml(QDomDocument *doc) const; diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 187fdbe9..afbd4145 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -24,6 +24,7 @@ #include "socks.h" #include +#include #include namespace XMPP { @@ -124,14 +125,95 @@ class Connection : public XMPP::Jingle::Connection } }; +class V6LinkLocalSocksConnector : public QObject +{ + Q_OBJECT + + QMap clients; + SocksClient *client = nullptr; +public: + using QObject::QObject; + + void connectToHost(const QHostAddress &proxyHost, int proxyPort, const QString &host, bool udpMode) + { + foreach(const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) + { + if (!(ni.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning))) { + continue; + } + if (ni.flags() & QNetworkInterface::IsLoopBack) { + continue; + } + QList entries = ni.addressEntries(); + foreach(const QNetworkAddressEntry &na, entries) + { + QHostAddress ha = na.ip(); + if (ha.protocol() == QAbstractSocket::IPv6Protocol && + #if QT_VERSION >= QT_VERSION_CHECK(5,11,0) + ha.isLinkLocal() + #else + XMPP::Ice176::isIPv6LinkLocalAddress(ha) + #endif + ) // && proxyHost.isInSubnet(ha, na.prefixLength()) + { + auto client = new SocksClient(this); + clients.insert(ni.name(), client); + break; + } + } + } + + if (!clients.size()) { + emit ready(); + return; + } + + QHostAddress ph(proxyHost); + for (auto it = clients.begin(); it != clients.end(); ++it) { + QString name = it.key(); + SocksClient *client = it.value(); + connect(client, &SocksClient::connected, this, [this, name, client](){ + this->client = client; + clients.remove(name); + qDeleteAll(clients); + emit ready(); + }); + connect(client, &SocksClient::error, this, [this, name, client](int error){ + Q_UNUSED(error); + clients.remove(name); + delete client; + if (clients.isEmpty()) { + emit ready(); + } + }, Qt::QueuedConnection); + ph.setScopeId(name); + client->connectToHost(ph.toString(), proxyPort, host, 0, udpMode); + } + } + + SocksClient* takeClient() + { + auto c = client; + client = nullptr; + return c; + } + +signals: + void ready(); +}; + class Candidate::Private : public QObject, public QSharedData { Q_OBJECT public: ~Private() { + if (server) { + server->unregisterKey(transport->directAddr()); + } delete socksClient; } + Transport *transport; QString cid; QString host; Jid jid; @@ -140,28 +222,60 @@ class Candidate::Private : public QObject, public QSharedData { Candidate::Type type = Candidate::Direct; Candidate::State state = Candidate::New; - quint16 localPort = 0; // where Psi actually listens. e.g. with NAT-assited candidats it may be different from just port + QSharedPointer server; SocksClient *socksClient = nullptr; void connectToHost(const QString &key, State successState, std::function callback, bool isUdp) { - socksClient = new SocksClient; - qDebug() << "connect to host with " << cid << "candidate and socks client" << socksClient; + QHostAddress ha(host); + if (!ha.isNull() && ha.protocol() == QAbstractSocket::IPv6Protocol && ha.scopeId().isEmpty() && + #if QT_VERSION >= QT_VERSION_CHECK(5,11,0) + ha.isLinkLocal() + #else + XMPP::Ice176::isIPv6LinkLocalAddress(ha) + #endif + ) + { + qDebug() << "connect to host with " << cid << "candidate using V6LinkLocalSocksConnector"; + // we have link local address without scope. We have to enumerate all possible scopes. + auto v6llConnector = new V6LinkLocalSocksConnector(this); + connect(v6llConnector, &V6LinkLocalSocksConnector::ready, this, [this, v6llConnector, callback, successState]() { + socksClient = v6llConnector->takeClient(); + socksClient->setParent(nullptr); + delete v6llConnector; + if (state == Candidate::Discarded) { + return; + } - connect(socksClient, &SocksClient::connected, [this, callback, successState](){ - state = successState; - qDebug() << "socks client" << socksClient << "is connected"; - callback(true); - }); - connect(socksClient, &SocksClient::error, [this, callback](int error){ - Q_UNUSED(error); - state = Candidate::Discarded; - qDebug() << "socks client" << socksClient << "failed to connect"; - callback(false); - }); - //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); + if (socksClient) { + state = successState; + qDebug() << "socks client" << socksClient << "is connected"; + callback(true); + return; + } + state = Candidate::Discarded; + qDebug() << "socks client" << socksClient << "failed to connect"; + callback(false); + }); + v6llConnector->connectToHost(ha, port, key, isUdp); + } else { + socksClient = new SocksClient; + qDebug() << "connect to host with " << cid << "candidate and socks client" << socksClient; + connect(socksClient, &SocksClient::connected, [this, callback, successState](){ + state = successState; + qDebug() << "socks client" << socksClient << "is connected"; + callback(true); + }); + connect(socksClient, &SocksClient::error, [this, callback](int error){ + Q_UNUSED(error); + state = Candidate::Discarded; + qDebug() << "socks client" << socksClient << "failed to connect"; + callback(false); + }); + //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); - socksClient->connectToHost(host, port, key, 0, isUdp); + socksClient->connectToHost(host, port, key, 0, isUdp); + } } void setupIncomingSocksClient() @@ -178,7 +292,7 @@ Candidate::Candidate() } -Candidate::Candidate(const QDomElement &el) +Candidate::Candidate(Transport *transport, const QDomElement &el) { bool ok; QString host(el.attribute(QStringLiteral("host"))); @@ -225,6 +339,7 @@ Candidate::Candidate(const QDomElement &el) } auto d = new Private; + d->transport = transport; d->cid = cid; d->host = host; d->jid = jid; @@ -241,9 +356,10 @@ Candidate::Candidate(const Candidate &other) : } -Candidate::Candidate(const Jid &proxy, const QString &cid, quint16 localPreference) : +Candidate::Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference) : d(new Private) { + d->transport = transport; d->cid = cid; d->jid = proxy; d->priority = (ProxyPreference << 16) + localPreference; @@ -251,12 +367,35 @@ Candidate::Candidate(const Jid &proxy, const QString &cid, quint16 localPreferen d->state = Probing; // it's probing because it's a local side proxy and host and port are unknown } -Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type type, quint16 localPreference) : +Candidate::Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, quint16 localPreference) : d(new Private) { + Type type = None; + switch (server->portType()) { + case TcpPortServer::Direct: + type = Candidate::Direct; + break; + case TcpPortServer::NatAssited: + type = Candidate::Assisted; + break; + case TcpPortServer::Tunneled: + type = Candidate::Tunnel; + break; + case TcpPortServer::NoType: + default: + type = None; + } + + if (type == None) { + d.reset(); + return; + } + + d->transport = transport; + d->server = server.staticCast(); d->cid = cid; - d->host = host; - d->port = port; + d->host = server->publishHost(); + d->port = server->publishPort(); d->type = type; static const int priorities[] = {0, ProxyPreference, TunnelPreference, AssistedPreference, DirectPreference}; if (type >= Type(0) && type <= Direct) { @@ -264,9 +403,7 @@ Candidate::Candidate(const QString &host, quint16 port, const QString &cid, Type } else { d->priority = 0; } - if (type == Direct) { - d->localPort = port; - } + d->state = New; } @@ -311,12 +448,12 @@ void Candidate::setPort(quint16 port) quint16 Candidate::localPort() const { - return d->localPort; + return d->server ? d->server->serverPort() : 0; } -void Candidate::setLocalPort(quint16 port) +QHostAddress Candidate::localAddress() const { - d->localPort = port; + return d->server ? d->server->serverAddress() : QHostAddress(); } Candidate::State Candidate::state() const @@ -330,6 +467,20 @@ void Candidate::setState(Candidate::State s) d->state = s; } +const char *Candidate::stateText(Candidate::State s) +{ + switch (s) { + case New: return "New"; + case Probing: return "Probing"; + case Pending: return "Pending"; + case Unacked: return "Unacked"; + case Accepted: return "Accepted"; + case Active: return "Active"; + case Discarded: return "Discarded"; + } + return nullptr; +} + quint32 Candidate::priority() const { return d->priority; @@ -390,6 +541,11 @@ void Candidate::deleteSocksClient() d->socksClient = nullptr; } +TcpPortServer::Ptr Candidate::server() const +{ + return d->server.staticCast(); +} + bool Candidate::operator==(const Candidate &other) const { return d.data() == other.d.data(); @@ -409,7 +565,7 @@ class Transport::Private Transport *q = nullptr; Pad::Ptr pad; bool meCreator = true; // content created on local side - bool connectionStarted = false; // where start() was called + bool transportStarted = false; // where start() was called bool waitingAck = true; bool aborted = false; bool remoteReportedCandidateError = false; @@ -429,6 +585,7 @@ class Transport::Private QTimer probingTimer; QElapsedTimer lastConnectionStart; size_t blockSize = 8192; + TcpPortDiscoverer *disco = nullptr; QSharedPointer connection; @@ -462,15 +619,106 @@ class Transport::Private return false; } + void discoS5BProxy() + { + auto m = static_cast(pad->manager()); + Jid proxy = m->userProxy(); + if (proxy.isValid()) { + Candidate c(q, proxy, generateCid()); + if (!isDup(c)) { + localCandidates.insert(c.cid(), c); + } + } + + proxyDiscoveryInProgress = true; + QList> featureOptions = {{"http://jabber.org/protocol/bytestreams"}}; + pad->session()->manager()->client()->serverInfoManager()-> + queryServiceInfo(QStringLiteral("proxy"), + QStringLiteral("bytestreams"), + featureOptions, + QRegExp("proxy.*|socks.*|stream.*|s5b.*"), + ServerInfoManager::SQ_CheckAllOnNoMatch, + [this](const QList &items) + { + if (!proxyDiscoveryInProgress) { // check if new results are ever/still expected + // seems like we have successful connection via higher priority channel. so nobody cares about proxy + return; + } + auto m = static_cast(pad->manager()); + Jid userProxy = m->userProxy(); + + // queries proxy's host/port and sends the candidate to remote + auto queryProxy = [this](const Jid &j, const QString &cid) { + proxiesInDiscoCount++; + auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); + connect(query, &JT_S5B::finished, q, [this,query,cid](){ + if (!proxyDiscoveryInProgress) { + return; + } + bool candidateUpdated = false; + auto c = localCandidates.value(cid); + if (c && c.state() == Candidate::Probing) { + auto sh = query->proxyInfo(); + if (query->success() && !sh.host().isEmpty() && sh.port()) { + // it can be discarded by this moment (e.g. got success on a higher priority candidate). + // so we have to check. + c.setHost(sh.host()); + c.setPort(sh.port()); + c.setState(Candidate::New); + candidateUpdated = true; + pendingActions |= Private::NewCandidate; + } else { + c.setState(Candidate::Discarded); + } + } + proxiesInDiscoCount--; + if (!proxiesInDiscoCount) { + proxyDiscoveryInProgress = false; + } + if (candidateUpdated) { + emit q->updated(); + } else if (!proxiesInDiscoCount) { + // it's possible it was our last hope and probaby we have to send candidate-error now. + checkAndFinishNegotiation(); + } + }); + query->requestProxyInfo(j); + query->go(true); + }; + + bool userProxyFound = !userProxy.isValid(); + for (const auto i: items) { + int localPref = 0; + if (!userProxyFound && i.jid() == userProxy) { + localPref = 1; + userProxyFound = true; + } + Candidate c(q, i.jid(), generateCid(), localPref); + localCandidates.insert(c.cid(), c); + + queryProxy(i.jid(), c.cid()); + } + if (!userProxyFound) { + Candidate c(q, userProxy, generateCid(), 1); + localCandidates.insert(c.cid(), c); + queryProxy(userProxy, c.cid()); + } else if (items.count() == 0) { + // seems like we don't have any proxy + proxyDiscoveryInProgress = false; + checkAndFinishNegotiation(); + } + }); + } + void tryConnectToRemoteCandidate() { - if (!connectionStarted) { + if (!transportStarted) { return; // will come back later } quint64 maxProbingPrio = 0; quint64 maxNewPrio = 0; Candidate maxProbing; - QList maxNew; + QList maxNew; // keeps highest (same) priority New candidates /* We have to find highest-priority already connecting candidate and highest-priority new candidate. @@ -482,6 +730,7 @@ class Transport::Private In all the other cases just return and wait for events. */ + qDebug("tryConnectToRemoteCandidate()"); for (auto &c: remoteCandidates) { if (c.state() == Candidate::New) { if (c.priority() > maxNewPrio) { @@ -498,21 +747,26 @@ class Transport::Private } } if (maxNew.isEmpty()) { + qDebug(" tryConnectToRemoteCandidate() no maxNew candidates"); return; // nowhere to connect } + // check if we have to hang on for a little if a higher priority candidate is Probing if (maxProbing) { if (maxNewPrio < maxProbing.priority()) { if (probingTimer.isActive()) { + qDebug(" tryConnectToRemoteCandidate() timer is already active. let's wait"); return; // we will come back here soon } qint64 msToFuture = 200 - lastConnectionStart.elapsed(); if (msToFuture > 0) { // seems like we have to rescheduler for future probingTimer.start(int(msToFuture)); + qDebug(" tryConnectToRemoteCandidate() too early. timer started. let's wait"); return; } } } + probingTimer.start(200); // for the next candidate if any // now we have to connect to maxNew candidates for (auto &mnc: maxNew) { @@ -536,10 +790,7 @@ class Transport::Private if (!hasUnckeckedNew) { pendingActions &= ~Private::NewCandidate; // just if we had it for example after proxy discovery } - if (proxyDiscoveryInProgress && (mnc.priority() >> 16) > Candidate::ProxyPreference) { - proxyDiscoveryInProgress = false; // doesn't make sense anymore - } - // TODO do the same for upnp + setLocalProbingMinimalPreference(mnc.priority() >> 16); updateMinimalPriority(); } checkAndFinishNegotiation(); @@ -547,13 +798,40 @@ class Transport::Private } } + /** + * @brief limitTcpDiscoByMinimalPreference take upper part of candidate preference (type preference) + * and drops lower priority pending local servers disco + * @param preference + */ + void setLocalProbingMinimalPreference(quint32 preference) + { + if (proxyDiscoveryInProgress && preference > Candidate::ProxyPreference) { + proxyDiscoveryInProgress = false; // doesn't make sense anymore + } + + // and now local ports discoverer.. + if (!disco) { + return; + } + TcpPortServer::PortTypes types = TcpPortServer::Direct; + if (preference >= Candidate::AssistedPreference) { + types |= TcpPortServer::NatAssited; + } + if (preference >= Candidate::TunnelPreference) { + types |= TcpPortServer::Tunneled; + } + if (!disco->setTypeMask(types)) { + delete disco; + disco = nullptr; + } + } + bool hasUnaknowledgedLocalCandidates() const { // now ensure all local were sent to remote and no hope left - if (proxyDiscoveryInProgress) { + if (proxyDiscoveryInProgress || (disco && !disco->isDepleted())) { return true; } - // Note: When upnp support is added we have one more check here // now local candidates for (const auto &c: localCandidates) { @@ -566,7 +844,7 @@ class Transport::Private return false; } - Candidate preferredCandidate() const + Candidate preferredUsedCandidate() const { if (localUsedCandidate) { if (remoteUsedCandidate) { @@ -593,7 +871,8 @@ class Transport::Private // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more // local candidates are expected to be discovered - if (!connectionStarted || connection) { // if not started or already finished + if (!transportStarted || connection) { // if not started or already finished + qDebug("checkAndFinishNegotiation not finished: !connectionStarted || connection"); return; } @@ -605,6 +884,7 @@ class Transport::Private // but as soon as it's taken it will switch to waitingAck. // And with unacknowledged local candidates we can't send used/error as well as report connected()/failure() // until tried them all + qDebug("checkAndFinishNegotiation not finished: waitingAck || pendingActions || hasUnaknowledgedLocalCandidates()"); return; } @@ -614,7 +894,7 @@ class Transport::Private if (remoteReportedCandidateError || localUsedCandidate) { // so remote seems to be finished too. // tell application about it and it has to change its state immediatelly - auto c = preferredCandidate(); + auto c = preferredUsedCandidate(); if (c) { if (c.state() != Candidate::Active) { if (c.type() == Candidate::Proxy && c == localUsedCandidate) { // local proxy @@ -638,13 +918,16 @@ class Transport::Private if (c.state() == Candidate::Active) { handleConnected(c); } + else qDebug("checkAndFinishNegotiation not finished: preferred is not Active"); } else { // both sides reported candidate error emit q->failed(); } } // else we have to wait till remote reports its status + else qDebug("checkAndFinishNegotiation not finished: remote didn't reported yet"); return; } + qDebug("checkAndFinishNegotiation not finished: trying to send condidate-used/error if any"); // if we are here then neither candidate-used nor candidate-error was sent to remote, // but we can send it now. // first let's check if we can send candidate-used @@ -652,6 +935,7 @@ class Transport::Private bool hasConnectedRemoteCandidate = false; for (const auto &c: remoteCandidates) { auto s = c.state(); + qDebug() << " candidate " << c.cid() << " is " << Candidate::stateText(s); if (s != Candidate::Discarded) { allRemoteDiscarded = false; } @@ -663,16 +947,19 @@ class Transport::Private // if we have connection to remote candidate it's time to send it if (hasConnectedRemoteCandidate) { pendingActions |= Private::CandidateUsed; + qDebug("checkAndFinishNegotiation: used"); emit q->updated(); return; } if (allRemoteDiscarded) { pendingActions |= Private::CandidateError; + qDebug("checkAndFinishNegotiation: error"); emit q->updated(); return; } + qDebug("checkAndFinishNegotiation not finished: there are more remote candidates to try"); // apparently we haven't connected anywhere but there are more remote candidates to try } @@ -697,10 +984,7 @@ class Transport::Private } } prio >>= 16; - if (proxyDiscoveryInProgress && prio > Candidate::ProxyPreference) { - // all proxies do no make sense anymore. we have successful higher priority candidate - proxyDiscoveryInProgress = false; - } + setLocalProbingMinimalPreference(prio); // if we discarded "used" candidates then reset them to invalid if (localUsedCandidate && localUsedCandidate.state() == Candidate::Discarded) { localUsedCandidate = Candidate(); @@ -730,7 +1014,34 @@ class Transport::Private } } if (!haveNewCandidates) { - pendingActions &= ~Private::NewCandidate; + pendingActions &= ~NewCandidate; + } + } + + void onLocalServerDiscovered() + { + for (auto serv: disco->takeServers()) { + auto s5bserv = serv.staticCast(); + s5bserv->registerKey(directAddr); + Candidate c(q, serv, generateCid()); + if (c.isValid() && !isDup(c) && c.priority()) { + QObject::connect(s5bserv.data(), &S5BServer::incomingConnection, q, [this, c](SocksClient *sc, const QString &key) mutable { + if (!connection && key == directAddr && (c.state() == Candidate::Pending || c.state() == Candidate::Unacked)) { + c.incomingConnection(sc); + c.server().data()->disconnect(q); // drop this connection. + if(mode == Transport::Udp) + sc->grantUDPAssociate("", 0); + else + sc->grantConnect(); + return; + } + + sc->requestDeny(); + sc->deleteLater(); + }); + localCandidates.insert(c.cid(), c); + pendingActions |= NewCandidate; + } } } @@ -798,116 +1109,22 @@ void Transport::prepare() d->directAddr = makeKey(d->sid, d->pad->session()->initiator(), d->pad->session()->responder()); m->addKeyMapping(d->directAddr, this); + auto scope = d->pad->discoScope(); + d->disco = scope->disco(); // FIXME store and handle signale. delete when not needed - auto serv = m->socksServ(); - if (serv) { - for(auto const &h: serv->hostList()) { - if (!serv->port() || h.isEmpty()) { - continue; - } - Candidate c(h, serv->port(), d->generateCid(), Candidate::Direct); - if (!d->isDup(c)) { - d->localCandidates.insert(c.cid(), c); - d->pendingActions |= Private::NewCandidate; - } - } - } - - Jid proxy = m->userProxy(); - if (proxy.isValid()) { - Candidate c(proxy, d->generateCid()); - if (!d->isDup(c)) { - d->localCandidates.insert(c.cid(), c); - } - } - - d->proxyDiscoveryInProgress = true; - QList> featureOptions = {{"http://jabber.org/protocol/bytestreams"}}; - d->pad->session()->manager()->client()->serverInfoManager()-> - queryServiceInfo(QStringLiteral("proxy"), - QStringLiteral("bytestreams"), - featureOptions, - QRegExp("proxy.*|socks.*|stream.*|s5b.*"), - ServerInfoManager::SQ_CheckAllOnNoMatch, - [this](const QList &items) - { - if (!d->proxyDiscoveryInProgress) { // check if new results are ever/still expected - // seems like we have successful connection via higher priority channel. so nobody cares about proxy - return; - } - auto m = static_cast(d->pad->manager()); - Jid userProxy = m->userProxy(); - - // queries proxy's host/port and sends the candidate to remote - auto queryProxy = [this](const Jid &j, const QString &cid) { - d->proxiesInDiscoCount++; - auto query = new JT_S5B(d->pad->session()->manager()->client()->rootTask()); - connect(query, &JT_S5B::finished, this, [this,query,cid](){ - if (!d->proxyDiscoveryInProgress) { - return; - } - bool candidateUpdated = false; - auto c = d->localCandidates.value(cid); - if (c && c.state() == Candidate::Probing) { - auto sh = query->proxyInfo(); - if (query->success() && !sh.host().isEmpty() && sh.port()) { - // it can be discarded by this moment (e.g. got success on a higher priority candidate). - // so we have to check. - c.setHost(sh.host()); - c.setPort(sh.port()); - c.setState(Candidate::New); - candidateUpdated = true; - d->pendingActions |= Private::NewCandidate; - } else { - c.setState(Candidate::Discarded); - } - } - d->proxiesInDiscoCount--; - if (!d->proxiesInDiscoCount) { - d->proxyDiscoveryInProgress = false; - } - if (candidateUpdated) { - emit updated(); - } else if (!d->proxiesInDiscoCount) { - // it's possible it was our last hope and probaby we have to send candidate-error now. - d->checkAndFinishNegotiation(); - } - }); - query->requestProxyInfo(j); - query->go(true); - }; - - bool userProxyFound = !userProxy.isValid(); - for (const auto i: items) { - int localPref = 0; - if (!userProxyFound && i.jid() == userProxy) { - localPref = 1; - userProxyFound = true; - } - Candidate c(i.jid(), d->generateCid(), localPref); - d->localCandidates.insert(c.cid(), c); - - queryProxy(i.jid(), c.cid()); - } - if (!userProxyFound) { - Candidate c(userProxy, d->generateCid(), 1); - d->localCandidates.insert(c.cid(), c); - queryProxy(userProxy, c.cid()); - } else if (items.count() == 0) { - // seems like we don't have any proxy - d->proxyDiscoveryInProgress = false; - d->checkAndFinishNegotiation(); - } + connect(d->disco, &TcpPortDiscoverer::portAvailable, this, [this](){ + d->onLocalServerDiscovered(); }); + d->onLocalServerDiscovered(); + d->discoS5BProxy(); - // TODO nat-assisted candidates.. emit updated(); } // we got content acceptance from any side and not can connect void Transport::start() { - d->connectionStarted = true; + d->transportStarted = true; d->tryConnectToRemoteCandidate(); // if there is no higher priority candidates than ours but they are already connected then d->checkAndFinishNegotiation(); @@ -928,7 +1145,7 @@ bool Transport::update(const QDomElement &transportEl) int candidatesAdded = 0; for(QDomElement ce = transportEl.firstChildElement(candidateTag); !ce.isNull(); ce = ce.nextSiblingElement(candidateTag)) { - Candidate c(ce); + Candidate c(this, ce); if (!c) { return false; } @@ -971,6 +1188,7 @@ bool Transport::update(const QDomElement &transportEl) c.setState(Candidate::Discarded); } } + qDebug("recv candidate-error: all local pending candidates were discarded"); QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); return true; } @@ -1013,7 +1231,7 @@ bool Transport::update(const QDomElement &transportEl) c.setState(Candidate::Discarded); } d->proxyDiscoveryInProgress = false; - // TODO do the same for upnp when implemented + delete d->disco; QTimer::singleShot(0, this, [this](){ emit failed(); }); return true; @@ -1168,6 +1386,11 @@ QString Transport::sid() const return d->sid; } +QString Transport::directAddr() const +{ + return d->directAddr; +} + Connection::Ptr Transport::connection() const { return d->connection.staticCast(); @@ -1244,7 +1467,6 @@ class Manager::Private { public: XMPP::Jingle::Manager *jingleManager = nullptr; - S5BServer *serv = nullptr; // FIMME it's reuiqred to split transports by direction otherwise we gonna hit conflicts. // jid,transport-sid -> transport mapping @@ -1273,9 +1495,6 @@ Manager::Manager(QObject *parent) : Manager::~Manager() { d->jingleManager->unregisterTransport(NS); - if (d->serv) { - d->serv->unlink(this); - } } Transport::Features Manager::features() const @@ -1313,21 +1532,6 @@ void Manager::closeAll() emit abortAllRequested(); } -void Manager::setServer(S5BServer *serv) -{ - if(d->serv) { - d->serv->unlink(this); - d->serv = nullptr; - } - - if(serv) { - d->serv = serv; - d->serv->link(this); - } else { - d->serv = nullptr; - } -} - void Manager::addKeyMapping(const QString &key, Transport *transport) { d->key2transport.insert(key, transport); @@ -1358,12 +1562,22 @@ bool Manager::incomingUDP(bool init, const QHostAddress &addr, int port, const Q QString Manager::generateSid(const Jid &remote) { + auto servers = d->jingleManager->client()->tcpPortReserver()-> + scope(QString::fromLatin1("s5b"))->allServers(); QString sid; QPair key; + QString key1; + QString key2; + auto servChecker = [&](const TcpPortServer::Ptr &s){ + return s.staticCast()->hasKey(key1) || s.staticCast()->hasKey(key2); + }; + do { sid = QString("s5b_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); key = qMakePair(remote, sid); - } while (d->sids.contains(key)); + key1 = makeKey(sid, remote, d->jingleManager->client()->jid()); + key2 = makeKey(sid, d->jingleManager->client()->jid(), remote); + } while (d->sids.contains(key) || std::find_if(servers.begin(), servers.end(), servChecker) != servers.end()); return sid; } @@ -1372,11 +1586,6 @@ void Manager::registerSid(const Jid &remote, const QString &sid) d->sids.insert(qMakePair(remote, sid)); } -S5BServer *Manager::socksServ() const -{ - return d->serv; -} - Jid Manager::userProxy() const { return d->proxy; @@ -1389,7 +1598,8 @@ Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) { - + auto reserver = _session->manager()->client()->tcpPortReserver(); + _discoScope = reserver->scope(QString::fromLatin1("s5b")); } QString Pad::ns() const diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 88d754be..de08a26e 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -30,6 +30,7 @@ #define JINGLE_S5B_H #include "jingle.h" +#include "tcpportreserver.h" class QHostAddress; class SocksClient; @@ -37,7 +38,6 @@ class SocksClient; namespace XMPP { class Client; -class S5BServer; namespace Jingle { namespace S5B { @@ -92,11 +92,12 @@ class Candidate { }; Candidate(); - Candidate(const QDomElement &el); + Candidate(Transport *transport, const QDomElement &el); Candidate(const Candidate &other); - Candidate(const Jid &proxy, const QString &cid, quint16 localPreference = 0); - Candidate(const QString &host, quint16 port, const QString &cid, Type type, quint16 localPreference = 0); + Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference = 0); + Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, quint16 localPreference = 0); ~Candidate(); + Candidate& operator=(const Candidate& other) = default; inline bool isValid() const { return d != nullptr; } inline operator bool() const { return isValid(); } Type type() const; @@ -107,9 +108,10 @@ class Candidate { quint16 port() const; void setPort(quint16 port); quint16 localPort() const; - void setLocalPort(quint16 port); + QHostAddress localAddress() const; State state() const; void setState(State s); + static const char *stateText(State s); quint32 priority() const; QDomElement toXml(QDomDocument *doc) const; @@ -118,6 +120,7 @@ class Candidate { bool incomingConnection(SocksClient *sc); SocksClient* takeSocksClient(); void deleteSocksClient(); + TcpPortServer::Ptr server() const; bool operator==(const Candidate &other) const; inline bool operator!=(const Candidate &other) const { return !(*this == other); } @@ -152,10 +155,11 @@ class Transport : public XMPP::Jingle::Transport Features features() const override; QString sid() const; + QString directAddr() const; Connection::Ptr connection() const; size_t blockSize() const; private: - friend class S5BServer; + friend class S5BServersManager; bool incomingConnection(SocksClient *sc); bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); @@ -181,9 +185,12 @@ class Pad : public TransportManagerPad QString generateSid() const; void registerSid(const QString &sid); + + inline TcpPortScope *discoScope() const { return _discoScope; } private: Manager *_manager; Session *_session; + TcpPortScope *_discoScope; }; class Manager : public TransportManager { @@ -200,15 +207,12 @@ class Manager : public TransportManager { void closeAll() override; - void setServer(S5BServer *serv); bool incomingConnection(SocksClient *client, const QString &key); // returns false if key is unknown bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); QString generateSid(const Jid &remote); void registerSid(const Jid &remote, const QString &sid); - S5BServer* socksServ() const; - /** * @brief userProxy returns custom (set by user) SOCKS proxy JID * @return diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index ae0908a1..e5ba24f1 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -489,8 +489,13 @@ class JTPush : public Task } else { auto session = client()->jingleManager()->session(from, jingle.sid()); if (!session) { - auto el = client()->doc()->createElementNS(QString::fromLatin1("urn:xmpp:jingle:errors:1"), QStringLiteral("unknown-session")); - respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); + if (jingle.action() == Action::SessionTerminate) { + auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); + client()->send(resp); + } else { + auto el = client()->doc()->createElementNS(QString::fromLatin1("urn:xmpp:jingle:errors:1"), QStringLiteral("unknown-session")); + respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); + } return true; } if (!session->updateFromXml(jingle.action(), jingleEl)) { @@ -1093,6 +1098,38 @@ class Session::Private return true; } + bool handleIncomingContentRemove(const QDomElement &jingleEl) + { + QSet toRemove; + QString contentTag(QStringLiteral("content")); + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + ContentBase cb(ce); + if (!cb.isValid()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + Application *app = contentList.value(ContentKey{cb.name, cb.creator}); + if (app) { + toRemove.insert(app); + } + } + + for (auto app: toRemove) { + contentList.remove(ContentKey{app->contentName(), app->creator()}); + delete app; + } + + if (contentList.isEmpty()) { + auto reasonEl = jingleEl.firstChildElement(QString::fromLatin1("reason")); + terminateReason = reasonEl.isNull()? Reason(Reason::Success) : Reason(reasonEl); + } + + planStep(); + return true; + } + bool handleIncomingSessionTerminate(const QDomElement &jingleEl) { terminateReason = Reason(jingleEl.firstChildElement(QString::fromLatin1("reason"))); @@ -1420,7 +1457,7 @@ bool Session::updateFromXml(Action action, const QDomElement &jingleEl) case Action::ContentReject: break; case Action::ContentRemove: - break; + return d->handleIncomingContentRemove(jingleEl); case Action::DescriptionInfo: break; case Action::SecurityInfo: diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 3d3622b4..b9458f08 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -164,6 +164,7 @@ class Reason { Reason(Condition cond, const QString &text = QString()); Reason(const QDomElement &el); Reason(const Reason &other); + Reason& operator=(const Reason &)=default; inline bool isValid() const { return d != nullptr; } Condition condition() const; void setCondition(Condition cond); diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index 884445cd..0f6fb71b 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -29,6 +29,7 @@ #include "im.h" #include "jingle-s5b.h" #include "socks.h" +#include "tcpportreserver.h" #ifdef Q_OS_WIN # include @@ -62,6 +63,7 @@ static bool haveHost(const StreamHostList &list, const Jid &j) return false; } + class S5BManager::Item : public QObject { Q_OBJECT @@ -78,12 +80,14 @@ class S5BManager::Item : public QObject StreamHostList in_hosts; JT_S5B *task = nullptr; JT_S5B *proxy_task = nullptr; + QSharedPointer relatedServer; SocksClient *client = nullptr; SocksClient *client_out = nullptr; SocksUDP *client_udp = nullptr; SocksUDP *client_out_udp = nullptr; S5BConnector *conn = nullptr; S5BConnector *proxy_conn = nullptr; + //S5BServersManager::S5BLocalServers *localServ = nullptr; bool wantFast = false; StreamHost proxy; int targetMode = 0; // requester sets this once it figures it out @@ -560,7 +564,6 @@ class S5BManager::Entry QString sid; JT_S5B *query = nullptr; StreamHost proxyInfo; - QPointer relatedServer; bool udp_init = false; QHostAddress udp_addr; @@ -571,7 +574,6 @@ class S5BManager::Private { public: Client *client; - S5BServer *serv; QList activeList; S5BConnectionList incomingConns; JT_PushS5B *ps; @@ -586,7 +588,6 @@ S5BManager::S5BManager(Client *parent) d = new Private; d->client = parent; - d->serv = 0; d->ps = new JT_PushS5B(d->client->rootTask()); connect(d->ps, SIGNAL(incoming(S5BRequest)), SLOT(ps_incoming(S5BRequest))); @@ -596,7 +597,6 @@ S5BManager::S5BManager(Client *parent) S5BManager::~S5BManager() { - setServer(0); while (!d->incomingConns.isEmpty()) { delete d->incomingConns.takeFirst(); } @@ -614,24 +614,6 @@ Client *S5BManager::client() const return d->client; } -S5BServer *S5BManager::server() const -{ - return d->serv; -} - -void S5BManager::setServer(S5BServer *serv) -{ - if(d->serv) { - d->serv->unlink(this); - d->serv = 0; - } - - if(serv) { - d->serv = serv; - d->serv->link(this); - } -} - JT_PushS5B* S5BManager::jtPush() const { return d->ps; @@ -747,15 +729,15 @@ bool S5BManager::isAcceptableSID(const Jid &peer, const QString &sid) const QString key = makeKey(sid, d->client->jid(), peer); QString key_out = makeKey(sid, peer, d->client->jid()); //not valid in muc via proxy - // if we have a server, then check through it - if(d->serv) { - if(findServerEntryByHash(key) || findServerEntryByHash(key_out)) - return false; - } - else { - if(findEntryByHash(key) || findEntryByHash(key_out)) - return false; + foreach(Entry *e, d->activeList) { + if(e->i) { + if (e->i->key == key || e->i->key == key_out) + return false; + else if (e->i->relatedServer && (e->i->relatedServer->hasKey(key) || e->i->relatedServer->hasKey(key_out))) + return false; + } } + return true; } @@ -809,17 +791,6 @@ S5BManager::Entry *S5BManager::findEntryBySID(const Jid &peer, const QString &si return 0; } -S5BManager::Entry *S5BManager::findServerEntryByHash(const QString &key) const -{ - const QList &manList = d->serv->managerList(); - foreach(S5BManager *m, manList) { - Entry *e = m->findEntryByHash(key); - if(e) - return e; - } - return 0; -} - bool S5BManager::srv_ownsHash(const QString &key) const { if(findEntryByHash(key)) @@ -832,14 +803,12 @@ void S5BManager::srv_incomingReady(SocksClient *sc, const QString &key) Entry *e = findEntryByHash(key); if(!e->i->allowIncoming) { sc->requestDeny(); - sc->deleteLater(); return; } if(e->c->d->mode == S5BConnection::Datagram) sc->grantUDPAssociate("", 0); else sc->grantConnect(); - e->relatedServer = static_cast(sender()); e->i->setIncomingClient(sc); } @@ -874,11 +843,6 @@ void S5BManager::srv_incomingUDP(bool init, const QHostAddress &addr, int port, e->c->man_udpReady(data); } -void S5BManager::srv_unlink() -{ - d->serv = 0; -} - void S5BManager::con_connect(S5BConnection *c) { if(findEntry(c)) @@ -939,8 +903,8 @@ void S5BManager::con_sendUDP(S5BConnection *c, const QByteArray &buf) if(!e->udp_init) return; - if(e->relatedServer) - e->relatedServer->writeUDP(e->udp_addr, e->udp_port, buf); + if(e->i->relatedServer) + e->i->relatedServer->writeUDP(e->udp_addr, e->udp_port, buf); } void S5BManager::item_accepted() @@ -1109,6 +1073,11 @@ S5BManager::Item::~Item() void S5BManager::Item::resetConnection() { + if (relatedServer) { + relatedServer->unregisterKey(key); + relatedServer.reset(); + } + delete task; task = nullptr; @@ -1210,17 +1179,29 @@ void S5BManager::Item::handleFast(const StreamHostList &hosts, const QString &iq void S5BManager::Item::doOutgoing() { StreamHostList hosts; - S5BServer *serv = m->server(); - if(serv && serv->isActive() && !haveHost(in_hosts, self)) { - QStringList hostList = serv->hostList(); - foreach (const QString & it, hostList) { + auto disco = m->client()->tcpPortReserver()->scope(QString::fromLatin1("s5b"))->disco(); + if(!haveHost(in_hosts, self)) { + foreach (auto &c, disco->takeServers()) { + relatedServer = c.staticCast(); + relatedServer->registerKey(key); + connect(relatedServer.data(), &S5BServer::incomingConnection, this, [this](SocksClient *c, const QString &key) { + if (key == this->key) { + m->srv_incomingReady(c, key); + } + }); + connect(relatedServer.data(), &S5BServer::incomingUdp, this, [this](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data) { + if (key == this->key) { + m->srv_incomingUDP(isInit, addr, sourcePort, key, data); + } + }); StreamHost h; h.setJid(self); - h.setHost(it); - h.setPort(serv->port()); + h.setHost(c->publishHost()); + h.setPort(c->publishPort()); hosts += h; } } + delete disco; // FIXME we could start listening for signals instead. it may send us upnp candidate // if the proxy is valid, then it's ok to add (the manager already ensured that it doesn't conflict) if(proxy.jid().isValid()) @@ -1967,244 +1948,6 @@ void S5BConnector::man_udpSuccess(const Jid &streamHost) } } -//---------------------------------------------------------------------------- -// S5BServer -//---------------------------------------------------------------------------- -class S5BServer::Item : public QObject -{ - Q_OBJECT -public: - SocksClient *client; - QString host; - QTimer expire; - - Item(SocksClient *c) : QObject(0) - { - client = c; - connect(client, SIGNAL(incomingMethods(int)), SLOT(sc_incomingMethods(int))); - connect(client, SIGNAL(incomingConnectRequest(QString,int)), SLOT(sc_incomingConnectRequest(QString,int))); - connect(client, SIGNAL(error(int)), SLOT(sc_error(int))); - - connect(&expire, SIGNAL(timeout()), SLOT(doError())); - resetExpiration(); - } - - ~Item() - { - delete client; - } - - void resetExpiration() - { - expire.start(30000); - } - -signals: - void result(bool); - -private slots: - void doError() - { - expire.stop(); - delete client; - client = 0; - result(false); - } - - void sc_incomingMethods(int m) - { - if(m & SocksClient::AuthNone) - client->chooseMethod(SocksClient::AuthNone); - else - doError(); - } - - void sc_incomingConnectRequest(const QString &_host, int port) - { - if(port == 0) { - host = _host; - client->disconnect(this); - emit result(true); - } - else - doError(); - } - - void sc_error(int) - { - doError(); - } -}; - -class S5BServer::Private -{ -public: - SocksServer serv; - QStringList hostList; - QList manList; - QList jingleManagerList; - QList itemList; -}; - -S5BServer::S5BServer(QObject *parent) -:QObject(parent) -{ - d = new Private; - connect(&d->serv, SIGNAL(incomingReady()), SLOT(ss_incomingReady())); - connect(&d->serv, SIGNAL(incomingUDP(QString,int,QHostAddress,int,QByteArray)), SLOT(ss_incomingUDP(QString,int,QHostAddress,int,QByteArray))); -} - -S5BServer::~S5BServer() -{ - unlinkAll(); - delete d; -} - -bool S5BServer::isActive() const -{ - return d->serv.isActive(); -} - -bool S5BServer::start(int port) -{ - d->serv.stop(); - //return d->serv.listen(port, true); - return d->serv.listen(port); -} - -void S5BServer::stop() -{ - d->serv.stop(); -} - -void S5BServer::setHostList(const QStringList &list) -{ - d->hostList = list; -} - -QStringList S5BServer::hostList() const -{ - return d->hostList; -} - -int S5BServer::port() const -{ - return d->serv.port(); -} - -void S5BServer::ss_incomingReady() -{ - Item *i = new Item(d->serv.takeIncoming()); -#ifdef S5B_DEBUG - qDebug("S5BServer: incoming connection from %s:%d\n", qPrintable(i->client->peerAddress().toString()), i->client->peerPort()); -#endif - connect(i, SIGNAL(result(bool)), SLOT(item_result(bool))); - d->itemList.append(i); -} - -void S5BServer::ss_incomingUDP(const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data) -{ - if(port != 0 && port != 1) - return; - - for (Jingle::S5B::Manager *m: d->jingleManagerList) { - if (m->incomingUDP(port == 1 ? true : false, addr, sourcePort, host, data)) { - return; - } - } - - foreach(S5BManager* m, d->manList) { - if(m->srv_ownsHash(host)) { - m->srv_incomingUDP(port == 1 ? true : false, addr, sourcePort, host, data); - return; - } - } -} - -void S5BServer::item_result(bool b) -{ - Item *i = static_cast(sender()); -#ifdef S5B_DEBUG - qDebug("S5BServer item result: %d\n", b); -#endif - if(!b) { - d->itemList.removeAll(i); - delete i; - return; - } - - SocksClient *c = i->client; - i->client = 0; - QString key = i->host; - d->itemList.removeAll(i); - delete i; - - - for (Jingle::S5B::Manager *m: d->jingleManagerList) { - if (m->incomingConnection(c, key)) { - return; - } - } - - // find the appropriate manager for this incoming connection - foreach(S5BManager *m, d->manList) { - if(m->srv_ownsHash(key)) { - m->srv_incomingReady(c, key); - return; - } - } - -#ifdef S5B_DEBUG - qDebug("S5BServer item result: unknown hash [%s]\n", qPrintable(key)); -#endif - - // throw it away - delete c; -} - -void S5BServer::link(S5BManager *m) -{ - d->manList.append(m); -} - -void S5BServer::unlink(S5BManager *m) -{ - d->manList.removeAll(m); -} - -void S5BServer::link(Jingle::S5B::Manager *m) -{ - d->jingleManagerList.append(m); -} - -void S5BServer::unlink(Jingle::S5B::Manager *m) -{ - d->jingleManagerList.removeAll(m); -} - -void S5BServer::unlinkAll() -{ - auto jl = d->jingleManagerList; - d->jingleManagerList.clear(); // clear early for setServer optimization - for(Jingle::S5B::Manager *m : jl) { - m->setServer(nullptr); - } - - foreach(S5BManager *m, d->manList) { - m->srv_unlink(); - } - d->manList.clear(); -} - -const QList & S5BServer::managerList() const -{ - return d->manList; -} - -void S5BServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data) -{ - d->serv.writeUDP(addr, port, data); -} //---------------------------------------------------------------------------- // JT_S5B @@ -2568,6 +2311,150 @@ void StreamHost::setIsProxy(bool b) proxy = b; } +//---------------------------------------------------------------------------- +// S5BServersProducer +//---------------------------------------------------------------------------- +TcpPortServer *S5BServersProducer::makeServer(QTcpServer *socket) +{ + return new S5BServer(socket); +} + +//---------------------------------------------------------------------------- +// S5BIncomingConnection +//---------------------------------------------------------------------------- +class S5BIncomingConnection : public QObject +{ + Q_OBJECT +public: + SocksClient *client; + QString host; + QTimer expire; + + S5BIncomingConnection(SocksClient *c) : QObject(0) + { + client = c; + connect(client, &SocksClient::incomingMethods, [this](int methods){ + if(methods & SocksClient::AuthNone) + client->chooseMethod(SocksClient::AuthNone); + else + doError(); + }); + connect(client, &SocksClient::incomingConnectRequest, [this](const QString &_host, int port) + { + if(port == 0) { + host = _host; + client->disconnect(this); + expire.stop(); + emit result(true); + } + else + doError(); + }); + connect(client, &SocksClient::error, [this](){ doError(); }); + connect(&expire, SIGNAL(timeout()), SLOT(doError())); + resetExpiration(); + } + + ~S5BIncomingConnection() + { + delete client; + } + + void resetExpiration() + { + expire.start(30000); + } + +signals: + void result(bool); + +private slots: + void doError() + { + expire.stop(); + delete client; + client = 0; + result(false); + } +}; + +//---------------------------------------------------------------------------- +// S5BServer +//---------------------------------------------------------------------------- +struct S5BServer::Private +{ + SocksServer serv; + QSet keys; +}; + +S5BServer::S5BServer(QTcpServer *serverSocket) : + TcpPortServer(serverSocket), + d(new Private) +{ + d->serv.setServerSocket(serverSocket); + connect(&d->serv, &SocksServer::incomingReady, this, [this]() { + S5BIncomingConnection *inConn = new S5BIncomingConnection(d->serv.takeIncoming()); +#ifdef S5B_DEBUG + qDebug("S5BServer: incoming connection from %s:%d\n", qPrintable(i->client->peerAddress().toString()), i->client->peerPort()); +#endif + connect(inConn, &S5BIncomingConnection::result, this, [this, inConn](bool success){ +#ifdef S5B_DEBUG + qDebug("S5BServer item result: %d\n", success); +#endif + if(!success) { + delete inConn; + return; + } + + SocksClient *c = inConn->client; + inConn->client = 0; + QString key = inConn->host; + delete inConn; + + emit incomingConnection(c, key); + if (!c->isOpen()) { + delete c; + } + }); + }); + connect(&d->serv, &SocksServer::incomingUDP, this, [this](const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data){ + if(port != 0 && port != 1) + return; + bool isInit = port == 1; + emit incomingUdp(isInit, addr, sourcePort, host, data); + }); +} + +S5BServer::~S5BServer() +{ + // basically to make QScopedPointer happy +} + +void S5BServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data) +{ + d->serv.writeUDP(addr, port, data); +} + +bool S5BServer::isActive() const +{ + return d->serv.isActive(); +} + +bool S5BServer::hasKey(const QString &key) +{ + return d->keys.contains(key); +} + +void S5BServer::registerKey(const QString &key) +{ + d->keys.insert(key); +} + +void S5BServer::unregisterKey(const QString &key) +{ + d->keys.remove(key); +} + } #include "s5b.moc" diff --git a/src/xmpp/xmpp-im/s5b.h b/src/xmpp/xmpp-im/s5b.h index 2fca6c6d..4f0d9863 100644 --- a/src/xmpp/xmpp-im/s5b.h +++ b/src/xmpp/xmpp-im/s5b.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "bytestream.h" #include "xmpp_bytestream.h" @@ -43,9 +44,9 @@ namespace XMPP class StreamHost; class Client; + class TcpPortReserver; class S5BConnection; class S5BManager; - class S5BServer; class JT_PushS5B; struct S5BRequest; typedef QList StreamHostList; @@ -151,8 +152,6 @@ namespace XMPP static const char* ns(); Client *client() const; - S5BServer *server() const; - void setServer(S5BServer *s); JT_PushS5B *jtPush() const; bool isAcceptableSID(const Jid &peer, const QString &sid) const; @@ -187,7 +186,6 @@ namespace XMPP Entry *findEntry(Item *) const; Entry *findEntryByHash(const QString &key) const; Entry *findEntryBySID(const Jid &peer, const QString &sid) const; - Entry *findServerEntryByHash(const QString &key) const; void entryContinue(Entry *e); void queryProxy(Entry *e); @@ -204,7 +202,6 @@ namespace XMPP bool srv_ownsHash(const QString &key) const; void srv_incomingReady(SocksClient *sc, const QString &key); void srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); - void srv_unlink(); friend class Item; void doSuccess(const Jid &peer, const QString &id, const Jid &streamHost); @@ -242,41 +239,34 @@ namespace XMPP void man_udpSuccess(const Jid &streamHost); }; - // listens on a port for serving - class S5BServer : public QObject + + class S5BServersProducer : public TcpPortScope + { + protected: + TcpPortServer* makeServer(QTcpServer *socket); // in fact returns S5BServer + }; + + class S5BServer : public TcpPortServer { Q_OBJECT + public: - S5BServer(QObject *par=0); + S5BServer(QTcpServer *serverSocket); ~S5BServer(); + void writeUDP(const QHostAddress &addr, int port, const QByteArray &data); bool isActive() const; - bool start(int port); - void stop(); - int port() const; - void setHostList(const QStringList &); - QStringList hostList() const; + bool hasKey(const QString &key); + void registerKey(const QString &key); + void unregisterKey(const QString &key); - class Item; - - private slots: - void ss_incomingReady(); - void ss_incomingUDP(const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data); - void item_result(bool); + signals: + void incomingConnection(SocksClient *c, const QString &key); + void incomingUdp(bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data); private: class Private; - Private *d; - - friend class S5BManager; - friend class Jingle::S5B::Manager; - void link(S5BManager *); - void unlink(S5BManager *); - void link(Jingle::S5B::Manager *m); - void unlink(Jingle::S5B::Manager *m); - void unlinkAll(); - const QList & managerList() const; - void writeUDP(const QHostAddress &addr, int port, const QByteArray &data); + QScopedPointer d; }; class JT_S5B : public Task diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index 897d31cf..695b6a96 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -53,6 +53,7 @@ namespace XMPP { class EncryptionHandler; class ServerInfoManager; class HttpFileUploadManager; + class TcpPortReserver; namespace Jingle { class Manager; @@ -133,6 +134,8 @@ namespace XMPP const Features& features() const; DiscoItem makeDiscoResult(const QString &node = QString::null) const; + void setTcpPortReserver(TcpPortReserver *portReserver); + TcpPortReserver *tcpPortReserver() const; S5BManager *s5bManager() const; IBBManager *ibbManager() const; BoBManager *bobManager() const; diff --git a/src/xmpp/xmpp-im/xmpp_liverosteritem.h b/src/xmpp/xmpp-im/xmpp_liverosteritem.h index b46d0664..08bfbb44 100644 --- a/src/xmpp/xmpp-im/xmpp_liverosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_liverosteritem.h @@ -31,6 +31,7 @@ namespace XMPP LiveRosterItem(const Jid &j=""); LiveRosterItem(const RosterItem &); ~LiveRosterItem(); + LiveRosterItem& operator=(const LiveRosterItem& other) = default; void setRosterItem(const RosterItem &); diff --git a/src/xmpp/xmpp-im/xmpp_rosteritem.h b/src/xmpp/xmpp-im/xmpp_rosteritem.h index 5ed23f6f..acb31e95 100644 --- a/src/xmpp/xmpp-im/xmpp_rosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_rosteritem.h @@ -48,6 +48,7 @@ namespace XMPP RosterItem(const Jid &jid=""); RosterItem(const RosterItem &item); virtual ~RosterItem(); + RosterItem& operator=(const RosterItem& other) = default; const Jid & jid() const; const QString & name() const; From 488bca08868282e8d338354c302e7cedb9cbde30 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 1 Jun 2019 22:27:15 +0300 Subject: [PATCH 042/383] A few fixes to s5b mediated transfer --- src/xmpp/xmpp-im/jingle-s5b.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index afbd4145..0a6758a6 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -22,6 +22,7 @@ #include "xmpp_client.h" #include "xmpp_serverinfomanager.h" #include "socks.h" +#include "ice176.h" #include #include @@ -897,9 +898,9 @@ class Transport::Private auto c = preferredUsedCandidate(); if (c) { if (c.state() != Candidate::Active) { - if (c.type() == Candidate::Proxy && c == localUsedCandidate) { // local proxy + if (c.type() == Candidate::Proxy) { // local proxy // If it's proxy, first it has to be activated - if (localUsedCandidate) { + if (c == localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); c.connectToHost(key, Candidate::Active, [this](bool success){ @@ -909,6 +910,7 @@ class Transport::Private pendingActions |= Private::ProxyError; } emit q->updated(); + handleConnected(localUsedCandidate); }, mode == Transport::Udp); } // else so it's remote proxy. let's just wait for from remote } else { @@ -1079,7 +1081,6 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::Transport(pad) { d->meCreator = false; - d->dstaddr = transportEl.attribute(QStringLiteral("dstaddr")); d->sid = transportEl.attribute(QStringLiteral("sid")); if (d->sid.isEmpty() || !update(transportEl)) { d.reset(); @@ -1141,6 +1142,10 @@ bool Transport::update(const QDomElement &transportEl) d->blockSize = bsn; } } + auto dstaddr = transportEl.attribute(QStringLiteral("dstaddr")); + if (!dstaddr.isEmpty()) { + d->dstaddr = dstaddr; + } QString candidateTag(QStringLiteral("candidate")); int candidatesAdded = 0; for(QDomElement ce = transportEl.firstChildElement(candidateTag); @@ -1195,11 +1200,12 @@ bool Transport::update(const QDomElement &transportEl) el = transportEl.firstChildElement(QStringLiteral("activated")); if (!el.isNull()) { - auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!c) { + QString cid = el.attribute(QStringLiteral("cid")); + if (cid.isEmpty()) { return false; } - if (!(c.type() == Candidate::Proxy && c.state() == Candidate::Accepted && c == d->localUsedCandidate)) { + auto c = d->remoteUsedCandidate; + if (!(c.cid() == cid && c.type() == Candidate::Proxy && c.state() == Candidate::Accepted)) { qDebug("Received on a candidate in an inappropriate state. Ignored."); return true; } @@ -1340,11 +1346,6 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() d->waitingAck = true; upd = OutgoingTransportInfoUpdate{tel, [this, cand]() mutable { d->waitingAck = false; - if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { - return; // seems like state was changed while we was waiting for an ack - } - cand.setState(Candidate::Active); - d->checkAndFinishNegotiation(); }}; } } else if (d->pendingActions & Private::ProxyError) { From 0955d007860a96aebf129ddc36eb1c7f8a564e55 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 2 Jun 2019 00:13:52 +0300 Subject: [PATCH 043/383] Added forgotten s5b proxy activation --- src/xmpp/xmpp-im/jingle-s5b.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 0a6758a6..c1af5b21 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -237,7 +237,7 @@ class Candidate::Private : public QObject, public QSharedData { #endif ) { - qDebug() << "connect to host with " << cid << "candidate using V6LinkLocalSocksConnector"; + qDebug() << "connect to host with cid=" << cid << "and key=" << key << "candidate using V6LinkLocalSocksConnector"; // we have link local address without scope. We have to enumerate all possible scopes. auto v6llConnector = new V6LinkLocalSocksConnector(this); connect(v6llConnector, &V6LinkLocalSocksConnector::ready, this, [this, v6llConnector, callback, successState]() { @@ -261,7 +261,7 @@ class Candidate::Private : public QObject, public QSharedData { v6llConnector->connectToHost(ha, port, key, isUdp); } else { socksClient = new SocksClient; - qDebug() << "connect to host with " << cid << "candidate and socks client" << socksClient; + qDebug() << "connect to host with cid=" << cid << ", key=" << key << " and socks client" << socksClient; connect(socksClient, &SocksClient::connected, [this, callback, successState](){ state = successState; qDebug() << "socks client" << socksClient << "is connected"; @@ -903,14 +903,28 @@ class Transport::Private if (c == localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); - c.connectToHost(key, Candidate::Active, [this](bool success){ - if (success) { - pendingActions |= Private::Activated; - } else { + c.connectToHost(key, Candidate::Accepted, [this](bool success){ + if (!success) { pendingActions |= Private::ProxyError; + emit q->updated(); + return; } - emit q->updated(); - handleConnected(localUsedCandidate); + + auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); + connect(query, &JT_S5B::finished, q, [this,query]() { + Q_ASSERT(localUsedCandidate.state() == Candidate::Accepted); + if (!query->success()) { + pendingActions |= Private::ProxyError; + emit q->updated(); + return; + } + pendingActions |= Private::Activated; + localUsedCandidate.setState(Candidate::Active); + emit q->updated(); + handleConnected(localUsedCandidate); + }); + query->requestActivation(localUsedCandidate.jid(), sid, pad->session()->peer()); + query->go(true); }, mode == Transport::Udp); } // else so it's remote proxy. let's just wait for from remote } else { @@ -1117,6 +1131,7 @@ void Transport::prepare() d->onLocalServerDiscovered(); }); d->onLocalServerDiscovered(); + d->discoS5BProxy(); emit updated(); From 4b0aabf441a6fd6976659c87d74dafe6d34f50b6 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 2 Jun 2019 10:49:08 +0300 Subject: [PATCH 044/383] Fixed regression/crash in legacy s5b --- src/xmpp/xmpp-im/jingle-s5b.cpp | 2 +- src/xmpp/xmpp-im/s5b.cpp | 31 +++++++++++++++++++------------ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index c1af5b21..fc86e441 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -195,6 +195,7 @@ class V6LinkLocalSocksConnector : public QObject SocksClient* takeClient() { auto c = client; + c->setParent(nullptr); client = nullptr; return c; } @@ -242,7 +243,6 @@ class Candidate::Private : public QObject, public QSharedData { auto v6llConnector = new V6LinkLocalSocksConnector(this); connect(v6llConnector, &V6LinkLocalSocksConnector::ready, this, [this, v6llConnector, callback, successState]() { socksClient = v6llConnector->takeClient(); - socksClient->setParent(nullptr); delete v6llConnector; if (state == Candidate::Discarded) { return; diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index 0f6fb71b..a9597d3c 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -80,7 +80,7 @@ class S5BManager::Item : public QObject StreamHostList in_hosts; JT_S5B *task = nullptr; JT_S5B *proxy_task = nullptr; - QSharedPointer relatedServer; + QList> relatedServers; SocksClient *client = nullptr; SocksClient *client_out = nullptr; SocksUDP *client_udp = nullptr; @@ -733,8 +733,13 @@ bool S5BManager::isAcceptableSID(const Jid &peer, const QString &sid) const if(e->i) { if (e->i->key == key || e->i->key == key_out) return false; - else if (e->i->relatedServer && (e->i->relatedServer->hasKey(key) || e->i->relatedServer->hasKey(key_out))) - return false; + else { + for (auto &s: e->i->relatedServers) { + if (s->hasKey(key) || s->hasKey(key_out)) { + return false; + } + } + } } } @@ -903,8 +908,8 @@ void S5BManager::con_sendUDP(S5BConnection *c, const QByteArray &buf) if(!e->udp_init) return; - if(e->i->relatedServer) - e->i->relatedServer->writeUDP(e->udp_addr, e->udp_port, buf); + if(e->i->relatedServers.size()) // FIXME in fact we shoule keep eact related server in Connection + e->i->relatedServers[0]->writeUDP(e->udp_addr, e->udp_port, buf); } void S5BManager::item_accepted() @@ -1073,9 +1078,9 @@ S5BManager::Item::~Item() void S5BManager::Item::resetConnection() { - if (relatedServer) { - relatedServer->unregisterKey(key); - relatedServer.reset(); + for (auto &s: relatedServers) { + s->unregisterKey(key); + s.reset(); } delete task; @@ -1182,14 +1187,15 @@ void S5BManager::Item::doOutgoing() auto disco = m->client()->tcpPortReserver()->scope(QString::fromLatin1("s5b"))->disco(); if(!haveHost(in_hosts, self)) { foreach (auto &c, disco->takeServers()) { - relatedServer = c.staticCast(); - relatedServer->registerKey(key); - connect(relatedServer.data(), &S5BServer::incomingConnection, this, [this](SocksClient *c, const QString &key) { + auto server = c.staticCast(); + server->registerKey(key); + relatedServers.append(server); + connect(server.data(), &S5BServer::incomingConnection, this, [this](SocksClient *c, const QString &key) { if (key == this->key) { m->srv_incomingReady(c, key); } }); - connect(relatedServer.data(), &S5BServer::incomingUdp, this, [this](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data) { + connect(server.data(), &S5BServer::incomingUdp, this, [this](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data) { if (key == this->key) { m->srv_incomingUDP(isInit, addr, sourcePort, key, data); } @@ -1282,6 +1288,7 @@ void S5BManager::Item::setIncomingClient(SocksClient *sc) connect(sc, SIGNAL(bytesWritten(qint64)), SLOT(sc_bytesWritten(qint64))); connect(sc, SIGNAL(error(int)), SLOT(sc_error(int))); + sc->setParent(nullptr); // avoid deleting it by SocksServer destructor client = sc; allowIncoming = false; } From 7c885d6a746792fd05cd3cc963a9b6e830786949 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 2 Jun 2019 11:55:59 +0300 Subject: [PATCH 045/383] Started implementation of Jingle IBB transport --- src/xmpp/xmpp-im/jingle-ibb.cpp | 143 ++++++++++++++++++++++++++++++++ src/xmpp/xmpp-im/jingle-ibb.h | 108 ++++++++++++++++++++++++ src/xmpp/xmpp-im/jingle-s5b.cpp | 106 +++++++---------------- src/xmpp/xmpp-im/jingle-s5b.h | 14 ---- src/xmpp/xmpp.pri | 6 +- 5 files changed, 286 insertions(+), 91 deletions(-) create mode 100644 src/xmpp/xmpp-im/jingle-ibb.cpp create mode 100644 src/xmpp/xmpp-im/jingle-ibb.h diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp new file mode 100644 index 00000000..ba451ee5 --- /dev/null +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -0,0 +1,143 @@ +/* + * jignle-ibb.cpp - Jingle In-Band Bytestream transport + * Copyright (C) 2019 Sergey Ilinykh + * + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#include "jingle-ibb.h" + +namespace XMPP { +namespace Jingle { +namespace IBB { + +struct Transport::Private +{ + TransportManagerPad::Ptr pad; +}; + +Transport::Transport(const TransportManagerPad::Ptr &pad) +{ + +} + +Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) +{ + +} + +Transport::~Transport() +{ + +} + +TransportManagerPad::Ptr Transport::pad() const +{ + return d->pad; +} + +void Transport::prepare() +{ + +} + +void Transport::start() +{ + +} + +bool Transport::update(const QDomElement &transportEl) +{ + +} + +bool Transport::hasUpdates() const +{ + +} + +OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() +{ + +} + +bool Transport::isValid() const +{ + return true; +} + +Transport::Features Transport::features() const +{ + +} + +QString Transport::sid() const +{ + +} + +Connection::Ptr Transport::connection() const +{ + +} + +size_t Transport::blockSize() const +{ + +} + +QSharedPointer Transport::createOutgoing(const TransportManagerPad::Ptr &pad) +{ + return QSharedPointer(); +} + +QSharedPointer Transport::createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) +{ + return QSharedPointer(); +} + +Pad::Pad(Manager *manager, Session *session) +{ + +} + +QString Pad::ns() const +{ + return NS; +} + +Session *Pad::session() const +{ + +} + +TransportManager *Pad::manager() const +{ + +} + +QString Pad::generateSid() const +{ + +} + +void Pad::registerSid(const QString &sid) +{ + +} + +} // namespace IBB +} // namespace Jingle +} // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h new file mode 100644 index 00000000..8bc81239 --- /dev/null +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -0,0 +1,108 @@ +/* + * jignle-ibb.h - Jingle In-Band Bytestream transport + * Copyright (C) 2019 Sergey Ilinykh + * + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#ifndef JINGLEIBB_H +#define JINGLEIBB_H + +#include "jingle.h" + +namespace XMPP { +namespace Jingle { +namespace IBB { + +extern const QString NS; + +class Transport : public XMPP::Jingle::Transport +{ + Q_OBJECT +public: + Transport(const TransportManagerPad::Ptr &pad); + Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); + ~Transport(); + + TransportManagerPad::Ptr pad() const override; + + void prepare() override; + void start() override; + bool update(const QDomElement &transportEl) override; + bool hasUpdates() const override; + OutgoingTransportInfoUpdate takeOutgoingUpdate() override; + bool isValid() const override; + Features features() const override; + + QString sid() const; + Connection::Ptr connection() const; + size_t blockSize() const; +private: + friend class S5BServersManager; + + friend class Manager; + static QSharedPointer createOutgoing(const TransportManagerPad::Ptr &pad); + static QSharedPointer createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); + + class Private; + QScopedPointer d; +}; + +class Manager; +class Pad : public TransportManagerPad +{ + Q_OBJECT + // TODO +public: + typedef QSharedPointer Ptr; + + Pad(Manager *manager, Session *session); + QString ns() const override; + Session *session() const override; + TransportManager *manager() const override; + + QString generateSid() const; + void registerSid(const QString &sid); +private: + Manager *_manager; + Session *_session; +}; + +class Manager : public TransportManager { + Q_OBJECT +public: + Manager(QObject *parent = nullptr); + ~Manager(); + + XMPP::Jingle::Transport::Features features() const override; + void setJingleManager(XMPP::Jingle::Manager *jm) override; + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) override; // outgoing. one have to call Transport::start to collect candidates + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) override; // incoming + TransportManagerPad* pad(Session *session) override; + + void closeAll() override; + + QString generateSid(const Jid &remote); + void registerSid(const Jid &remote, const QString &sid); +private: + class Private; + QScopedPointer d; +}; + +} // namespace IBB +} // namespace Jingle +} // namespace XMPP + +#endif // JINGLEIBB_H diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index fc86e441..1739423d 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1055,6 +1055,37 @@ class Transport::Private sc->requestDeny(); sc->deleteLater(); }); + QObject::connect(s5bserv.data(), &S5BServer::incomingUdp, q, [this, c](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data){ + if (mode != Transport::Mode::Udp || !connection) { + return false; + } + + if(isInit) { + // TODO probably we could create a Connection here and put all the params inside + if(udpInitialized) + return false; // only init once + + // lock on to this sender + udpAddress = addr; + udpPort = sourcePort; + udpInitialized = true; + + // reply that initialization was successful + pad->session()->manager()->client()->s5bManager()->jtPush()->sendUDPSuccess(pad->session()->peer(), key); // TODO fix ->->-> + return true; + } + + // not initialized yet? something went wrong + if(!udpInitialized) + return false; + + // must come from same source as when initialized + if(addr != udpAddress || sourcePort != udpPort) + return false; + + connection->enqueueIncomingUDP(data); // man_udpReady + return true; + }); localCandidates.insert(c.cid(), c); pendingActions |= NewCandidate; } @@ -1417,63 +1448,6 @@ size_t Transport::blockSize() const return d->blockSize; } -bool Transport::incomingConnection(SocksClient *sc) -{ - if (!d->connection) { - auto s = sc->abstractSocket(); - for (auto &c: d->localCandidates) { - if (s->localPort() == c.localPort() && - (c.state() == Candidate::Pending || c.state() == Candidate::Unacked) && - c.incomingConnection(sc)) - { - - if(d->mode == Transport::Udp) - sc->grantUDPAssociate("", 0); - else - sc->grantConnect(); - // we can also remember the server it comes from. static_cast(sender()) - return true; - } - } - } - - sc->requestDeny(); - sc->deleteLater(); - return false; -} - -bool Transport::incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data) -{ - if (d->mode != Transport::Mode::Udp) { - return false; - } - - if(init) { - // TODO probably we could create a Connection here and put all the params inside - if(d->udpInitialized) - return false; // only init once - - // lock on to this sender - d->udpAddress = addr; - d->udpPort = port; - d->udpInitialized = true; - - // reply that initialization was successful - d->pad->session()->manager()->client()->s5bManager()->jtPush()->sendUDPSuccess(d->pad->session()->peer(), key); // TODO fix ->->-> - return true; - } - - // not initialized yet? something went wrong - if(!d->udpInitialized) - return false; - - // must come from same source as when initialized - if(addr != d->udpAddress || port != d->udpPort) - return false; - - d->connection->enqueueIncomingUDP(data); // man_udpReady - return true; -} //---------------------------------------------------------------- // Manager @@ -1558,24 +1532,6 @@ void Manager::removeKeyMapping(const QString &key) d->key2transport.remove(key); } -bool Manager::incomingConnection(SocksClient *client, const QString &key) -{ - auto t = d->key2transport.value(key); - if (t) { - return t->incomingConnection(client); - } - return false; -} - -bool Manager::incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data) -{ - auto t = d->key2transport.value(key); - if (t) { - return t->incomingUDP(init, addr, port, key, data); - } - return false; -} - QString Manager::generateSid(const Jid &remote) { auto servers = d->jingleManager->client()->tcpPortReserver()-> diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index de08a26e..71f6883f 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -17,15 +17,6 @@ * */ -/* - * In s5b.cpp we have - * S5BManager -> Jingle::S5B::Manager - * S5BManager::Item -> Jingle::S5B::Transport - * S5BManager::Entry -> ??? - * - */ - - #ifndef JINGLE_S5B_H #define JINGLE_S5B_H @@ -160,8 +151,6 @@ class Transport : public XMPP::Jingle::Transport size_t blockSize() const; private: friend class S5BServersManager; - bool incomingConnection(SocksClient *sc); - bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); friend class Manager; static QSharedPointer createOutgoing(const TransportManagerPad::Ptr &pad); @@ -207,9 +196,6 @@ class Manager : public TransportManager { void closeAll() override; - bool incomingConnection(SocksClient *client, const QString &key); // returns false if key is unknown - bool incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); - QString generateSid(const Jid &remote); void registerSid(const Jid &remote, const QString &sid); diff --git a/src/xmpp/xmpp.pri b/src/xmpp/xmpp.pri index 8dd342d8..8e9fd795 100644 --- a/src/xmpp/xmpp.pri +++ b/src/xmpp/xmpp.pri @@ -80,7 +80,8 @@ HEADERS += \ $$PWD/xmpp-im/xmpp_serverinfomanager.h \ $$PWD/xmpp-im/jingle.h \ $$PWD/xmpp-im/jingle-ft.h \ - $$PWD/xmpp-im/jingle-s5b.h + $$PWD/xmpp-im/jingle-s5b.h \ + $$PWD/xmpp-im/jingle-ibb.h SOURCES += \ $$PWD/xmpp-core/connector.cpp \ @@ -115,5 +116,6 @@ SOURCES += \ $$PWD/xmpp-im/xmpp_serverinfomanager.cpp \ $$PWD/xmpp-im/jingle.cpp \ $$PWD/xmpp-im/jingle-ft.cpp \ - $$PWD/xmpp-im/jingle-s5b.cpp + $$PWD/xmpp-im/jingle-s5b.cpp \ + $$PWD/xmpp-im/jingle-ibb.cpp From 3292b40388fd7c9cff289bfd04d02183a4284d19 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 3 Jun 2019 08:27:32 +0300 Subject: [PATCH 046/383] a little progress with jingle IBB --- src/xmpp/xmpp-im/jingle-ibb.cpp | 67 +++++++++++++++++++++------------ src/xmpp/xmpp-im/jingle-ibb.h | 4 -- src/xmpp/xmpp-im/jingle-s5b.h | 4 -- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index ba451ee5..dafa859c 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -18,24 +18,47 @@ */ #include "jingle-ibb.h" +#include "xmpp/jid/jid.h" namespace XMPP { namespace Jingle { namespace IBB { +class Connection : public XMPP::Jingle::Connection +{ + Q_OBJECT + + Jid peer; + QString sid; + size_t blockSize; +public: + Connection(const Jid &jid, const QString &sid, size_t blockSize) : + peer(jid), + sid(sid), + blockSize(blockSize) + { + + } +}; + struct Transport::Private { TransportManagerPad::Ptr pad; + QString sid; + QSharedPointer connection; + size_t blockSize = 4096; }; -Transport::Transport(const TransportManagerPad::Ptr &pad) +Transport::Transport(const TransportManagerPad::Ptr &pad) : + d(new Private) { - + d->pad = pad; } -Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) +Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : + d(new Private) { - + d->pad = pad; } Transport::~Transport() @@ -50,17 +73,23 @@ TransportManagerPad::Ptr Transport::pad() const void Transport::prepare() { - + emit updated(); } void Transport::start() { - + d->connection.reset(new Connection(d->pad->session()->peer(), d->sid, d->blockSize)); } bool Transport::update(const QDomElement &transportEl) { - + auto bs = transportEl.attribute(QString::fromLatin1("block-size")); + if (!bs.isEmpty()) { + size_t bsn = bs.toULongLong(); + if (bsn && bsn <= d->blockSize) { + d->blockSize = bsn; + } + } } bool Transport::hasUpdates() const @@ -80,32 +109,22 @@ bool Transport::isValid() const Transport::Features Transport::features() const { - + return AlwaysConnect | Reliable | Slow; } QString Transport::sid() const { - + return d->sid; } Connection::Ptr Transport::connection() const { - + return d->connection.staticCast(); } size_t Transport::blockSize() const { - -} - -QSharedPointer Transport::createOutgoing(const TransportManagerPad::Ptr &pad) -{ - return QSharedPointer(); -} - -QSharedPointer Transport::createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) -{ - return QSharedPointer(); + return d->blockSize; } Pad::Pad(Manager *manager, Session *session) @@ -120,17 +139,17 @@ QString Pad::ns() const Session *Pad::session() const { - + return nullptr; } TransportManager *Pad::manager() const { - + return nullptr; } QString Pad::generateSid() const { - + return QString(); } void Pad::registerSid(const QString &sid) diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 8bc81239..5ede921d 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -50,11 +50,7 @@ class Transport : public XMPP::Jingle::Transport Connection::Ptr connection() const; size_t blockSize() const; private: - friend class S5BServersManager; - friend class Manager; - static QSharedPointer createOutgoing(const TransportManagerPad::Ptr &pad); - static QSharedPointer createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); class Private; QScopedPointer d; diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 71f6883f..fc80ccc4 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -150,11 +150,7 @@ class Transport : public XMPP::Jingle::Transport Connection::Ptr connection() const; size_t blockSize() const; private: - friend class S5BServersManager; - friend class Manager; - static QSharedPointer createOutgoing(const TransportManagerPad::Ptr &pad); - static QSharedPointer createIncoming(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); class Private; QScopedPointer d; From de24d3dc19266e890c0d7ad03cf041a17a57ab88 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 3 Jun 2019 10:55:56 +0300 Subject: [PATCH 047/383] Fixed crash on socks connection failure in jingle --- src/xmpp/xmpp-im/jingle-ibb.cpp | 5 +++++ src/xmpp/xmpp-im/jingle-s5b.cpp | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index dafa859c..32558593 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -59,6 +59,11 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra d(new Private) { d->pad = pad; + update(transportEl); + if (d->sid.isEmpty()) { + d.reset(); + return; + } } Transport::~Transport() diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 1739423d..caf2c86f 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -195,8 +195,10 @@ class V6LinkLocalSocksConnector : public QObject SocksClient* takeClient() { auto c = client; - c->setParent(nullptr); - client = nullptr; + if (c) { + c->setParent(nullptr); + client = nullptr; + } return c; } From 6731058c533c17fc8b16f888ca7f9b67faba8276 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 3 Jun 2019 11:40:52 +0300 Subject: [PATCH 048/383] close any in progress s5b connections on transport destroy --- src/xmpp/xmpp-im/jingle-s5b.cpp | 17 ++++++++++++++--- src/xmpp/xmpp-im/jingle-s5b.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index caf2c86f..7e4e6032 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -539,9 +539,11 @@ SocksClient *Candidate::takeSocksClient() void Candidate::deleteSocksClient() { - d->socksClient->disconnect(); - delete d->socksClient; - d->socksClient = nullptr; + if (d->socksClient) { + d->socksClient->disconnect(); + delete d->socksClient; + d->socksClient = nullptr; + } } TcpPortServer::Ptr Candidate::server() const @@ -1138,7 +1140,11 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::~Transport() { if (d) { + // TODO unregister sid too static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); + for (auto &c: d->remoteCandidates) { + c.deleteSocksClient(); + } } } @@ -1565,6 +1571,11 @@ Jid Manager::userProxy() const return d->proxy; } +void Manager::setUserProxy(const Jid &jid) +{ + d->proxy = jid; +} + //---------------------------------------------------------------- // Pad //---------------------------------------------------------------- diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index fc80ccc4..b6aa13af 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -200,6 +200,7 @@ class Manager : public TransportManager { * @return */ Jid userProxy() const; + void setUserProxy(const Jid &jid); /** * @brief addKeyMapping sets mapping between key/socks hostname used for direct connection and transport. From 0d4d838b84db1e02cdfe20a96890b4a91408338b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 3 Jun 2019 15:17:16 +0300 Subject: [PATCH 049/383] Emit updated when new s5b local servers are discovered --- src/xmpp/xmpp-im/jingle-s5b.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 7e4e6032..8e9da075 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -889,7 +889,8 @@ class Transport::Private // but as soon as it's taken it will switch to waitingAck. // And with unacknowledged local candidates we can't send used/error as well as report connected()/failure() // until tried them all - qDebug("checkAndFinishNegotiation not finished: waitingAck || pendingActions || hasUnaknowledgedLocalCandidates()"); + qDebug("checkAndFinishNegotiation not finished: waitingAck=%d || pendingActions=%x || hasUnaknowledgedLocalCandidates()=%d", + int(waitingAck), int(pendingActions), int(hasUnaknowledgedLocalCandidates())); return; } @@ -1040,6 +1041,7 @@ class Transport::Private void onLocalServerDiscovered() { + bool hasNewCandidates = false; for (auto serv: disco->takeServers()) { auto s5bserv = serv.staticCast(); s5bserv->registerKey(directAddr); @@ -1092,8 +1094,12 @@ class Transport::Private }); localCandidates.insert(c.cid(), c); pendingActions |= NewCandidate; + hasNewCandidates = true; } } + if (hasNewCandidates) { + emit q->updated(); + } } void handleConnected(Candidate &connCand) From f4658de77e4116591aa16346bf03c726b52c351a Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 4 Jun 2019 10:15:40 +0300 Subject: [PATCH 050/383] External Jingle manager support Not it's possible to have more thn one jingle manager where the first one will ignore sessions dedicated for other managers --- src/xmpp/xmpp-im/jingle-ibb.cpp | 30 ++++++++++++++++++++++--- src/xmpp/xmpp-im/jingle.cpp | 39 ++++++++++++++++++++++++++++++++- src/xmpp/xmpp-im/jingle.h | 5 +++++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 32558593..0045f3c8 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -19,6 +19,7 @@ #include "jingle-ibb.h" #include "xmpp/jid/jid.h" +#include "xmpp_client.h" namespace XMPP { namespace Jingle { @@ -39,6 +40,11 @@ class Connection : public XMPP::Jingle::Connection { } + + void open() + { + // TODO + } }; struct Transport::Private @@ -47,6 +53,7 @@ struct Transport::Private QString sid; QSharedPointer connection; size_t blockSize = 4096; + bool waitingAck = false; }; Transport::Transport(const TransportManagerPad::Ptr &pad) : @@ -95,16 +102,32 @@ bool Transport::update(const QDomElement &transportEl) d->blockSize = bsn; } } + return true; } bool Transport::hasUpdates() const { - + return !d->connection; } OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() { + OutgoingTransportInfoUpdate upd; + if (!isValid()) { + return upd; + } + auto doc = d->pad->session()->manager()->client()->doc(); + + QDomElement tel = doc->createElementNS(NS, "transport"); + tel.setAttribute(QStringLiteral("sid"), d->sid); + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); + + d->connection.reset(new Connection(d->pad->session()->peer(), d->sid, d->blockSize)); + upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { + d->connection->open(); + }}; + return upd; } bool Transport::isValid() const @@ -134,7 +157,8 @@ size_t Transport::blockSize() const Pad::Pad(Manager *manager, Session *session) { - + _manager = manager; + _session = session; } QString Pad::ns() const @@ -159,7 +183,7 @@ QString Pad::generateSid() const void Pad::registerSid(const QString &sid) { - + Q_UNUSED(sid); } } // namespace IBB diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index e5ba24f1..56000fc9 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -431,11 +431,14 @@ TransportManager::TransportManager(QObject *parent) : } //---------------------------------------------------------------------------- -// JT - Jingle Task +// JTPush - Jingle Task //---------------------------------------------------------------------------- class JTPush : public Task { Q_OBJECT + + QList externalManagers; + QList externalSessions; public: JTPush(Task *parent) : Task(parent) @@ -445,6 +448,10 @@ class JTPush : public Task ~JTPush(){} + inline void addExternalManager(const QString &ns) { externalManagers.append(ns); } + inline void forgetExternalSession(const QString &sid) { externalSessions.removeOne(sid); } + + bool take(const QDomElement &iq) { if (iq.tagName() != QLatin1String("iq") || iq.attribute(QLatin1String("type")) != QLatin1String("set")) { @@ -454,12 +461,32 @@ class JTPush : public Task if (jingleEl.isNull() || jingleEl.attribute(QStringLiteral("xmlns")) != ::XMPP::Jingle::NS) { return false; } + Jingle jingle(jingleEl); if (!jingle.isValid()) { respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); return true; } + if (externalManagers.size()) { + if (jingle.action() == Action::SessionInitiate) { + auto cname = QString::fromLatin1("content"); + auto dname = QString::fromLatin1("description"); + for (auto n = jingleEl.firstChildElement(cname); !n.isNull(); n = n.nextSiblingElement(cname)) { + auto del = n.firstChildElement(dname); + if (!del.isNull() && externalManagers.contains(del.attribute(QStringLiteral("xmlns")))) { + externalSessions.append(jingle.sid()); + return false; + } + } + } else if (externalSessions.contains(jingle.sid())) { + if (jingle.action() == Action::SessionTerminate) { + externalSessions.removeOne(jingle.sid()); + } + return false; + } + } + QString fromStr(iq.attribute(QStringLiteral("from"))); Jid from(fromStr); if (jingle.action() == Action::SessionInitiate) { @@ -1542,6 +1569,16 @@ Client *Manager::client() const return d->client; } +void Manager::addExternalManager(const QString &ns) +{ + d->pushTask->addExternalManager(ns); +} + +void Manager::forgetExternalSession(const QString &sid) +{ + d->pushTask->forgetExternalSession(sid); +} + void Manager::setRedirection(const Jid &to) { d->redirectionJid = to; diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index b9458f08..cccfd145 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -513,6 +513,11 @@ class Manager : public QObject XMPP::Client* client() const; + // if we have another jingle manager we can add its contents' namespaces here. + void addExternalManager(const QString &ns); + // on outgoing session destroy an external manager should call this function. + void forgetExternalSession(const QString &sid); + void setRedirection(const Jid &to); const Jid &redirectionJid() const; From 5ba75fbaf4ed8503708982fa0cc900b0e067559b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 4 Jun 2019 19:41:22 +0300 Subject: [PATCH 051/383] Jingle IBB in progress --- src/xmpp/xmpp-im/jingle-ibb.cpp | 167 ++++++++++++++++++++++++++------ src/xmpp/xmpp-im/jingle-ibb.h | 7 +- 2 files changed, 139 insertions(+), 35 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 0045f3c8..73418726 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -28,11 +28,14 @@ namespace IBB { class Connection : public XMPP::Jingle::Connection { Q_OBJECT - +public: Jid peer; QString sid; size_t blockSize; -public: + + bool offerSent = false; + bool offerReceived = false; + Connection(const Jid &jid, const QString &sid, size_t blockSize) : peer(jid), sid(sid), @@ -41,7 +44,7 @@ class Connection : public XMPP::Jingle::Connection } - void open() + void checkAndStartConnection() { // TODO } @@ -49,25 +52,34 @@ class Connection : public XMPP::Jingle::Connection struct Transport::Private { - TransportManagerPad::Ptr pad; - QString sid; - QSharedPointer connection; - size_t blockSize = 4096; - bool waitingAck = false; + Transport *q = nullptr; + Pad::Ptr pad; + QMap> connections; + QList> readyConnections; + size_t defaultBlockSize = 4096; + bool started = false; + + QSharedPointer makeConnection(const Jid &jid, const QString &sid, size_t blockSize) + { + // TODO connect some signals + return QSharedPointer::create(jid, sid, blockSize); + } }; Transport::Transport(const TransportManagerPad::Ptr &pad) : d(new Private) { - d->pad = pad; + d->q = this; + d->pad = pad.staticCast(); } Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : d(new Private) { - d->pad = pad; + d->q = this; + d->pad = pad.staticCast(); update(transportEl); - if (d->sid.isEmpty()) { + if (d->connections.isEmpty()) { d.reset(); return; } @@ -85,29 +97,66 @@ TransportManagerPad::Ptr Transport::pad() const void Transport::prepare() { + if (d->connections.isEmpty()) { // seems like outgoing + QString sid = d->pad->generateSid(); + auto conn = d->makeConnection(d->pad->session()->peer(), sid, d->defaultBlockSize); + d->connections.insert(sid, conn); + } emit updated(); } void Transport::start() { - d->connection.reset(new Connection(d->pad->session()->peer(), d->sid, d->blockSize)); + d->started = true; + + for (auto &c: d->connections) { + c->checkAndStartConnection(); + } } bool Transport::update(const QDomElement &transportEl) { + QString sid = transportEl.attribute(QString::fromLatin1("sid")); + if (sid.isEmpty()) { + return false; + } + + size_t bs_final = d->defaultBlockSize; auto bs = transportEl.attribute(QString::fromLatin1("block-size")); if (!bs.isEmpty()) { size_t bsn = bs.toULongLong(); - if (bsn && bsn <= d->blockSize) { - d->blockSize = bsn; + if (bsn && bsn <= bs_final) { + bs_final = bsn; } } + + auto it = d->connections.find(sid); + if (it == d->connections.end()) { + if (!d->pad->registerSid(sid)) { + return false; // TODO we need last error somewhere + } + it = d->connections.insert(sid, d->makeConnection(d->pad->session()->peer(), sid, bs_final)); + } else { + if (bs_final < (*it)->blockSize) { + (*it)->blockSize = bs_final; + } + } + + (*it)->offerReceived = true; + if (d->started) { + (*it)->checkAndStartConnection(); + } return true; } bool Transport::hasUpdates() const { - return !d->connection; + for (auto &c: d->connections) { + if (!c->offerSent) { + return true; + } + } + return false; } OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() @@ -117,16 +166,29 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() return upd; } + QSharedPointer connection; + for (auto &c: d->connections) { + if (!c->offerSent) { + connection = c; + break; + } + } + if (!connection) { + return upd; + } + auto doc = d->pad->session()->manager()->client()->doc(); QDomElement tel = doc->createElementNS(NS, "transport"); - tel.setAttribute(QStringLiteral("sid"), d->sid); - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); + tel.setAttribute(QStringLiteral("sid"), connection->sid); + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->blockSize)); - d->connection.reset(new Connection(d->pad->session()->peer(), d->sid, d->blockSize)); - upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { - d->connection->open(); + upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { + if (d->started) + connection->checkAndStartConnection(); }}; + + connection->offerSent = true; return upd; } @@ -140,19 +202,14 @@ Transport::Features Transport::features() const return AlwaysConnect | Reliable | Slow; } -QString Transport::sid() const -{ - return d->sid; -} - Connection::Ptr Transport::connection() const { - return d->connection.staticCast(); + return d->readyConnections.takeLast(); } size_t Transport::blockSize() const { - return d->blockSize; + return d->defaultBlockSize; } Pad::Pad(Manager *manager, Session *session) @@ -168,22 +225,68 @@ QString Pad::ns() const Session *Pad::session() const { - return nullptr; + return _session; } TransportManager *Pad::manager() const { - return nullptr; + return _manager; } QString Pad::generateSid() const { - return QString(); + return _manager->generateSid(_session->peer()); +} + +bool Pad::registerSid(const QString &sid) +{ + return _manager->registerSid(_session->peer(), sid); +} + +void Pad::forgetSid(const QString &sid) +{ + _manager->forgetSid(_session->peer(), sid); +} + +struct Manager::Private +{ + QSet> sids; +}; + +Manager::Manager(QObject *parent) : + TransportManager(parent), + d(new Private) +{ + +} + +QString Manager::generateSid(const Jid &remote) +{ + QString sid; + QPair key; + do { + sid = QString("ibb_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + key = qMakePair(remote, sid); + } while (d->sids.contains(key)); + + d->sids.insert(key); + return sid; +} + +bool Manager::registerSid(const Jid &remote, const QString &sid) +{ + QPair key = qMakePair(remote, sid); + if (d->sids.contains(key)) { + return false; + } + d->sids.insert(key); + return true; } -void Pad::registerSid(const QString &sid) +void Manager::forgetSid(const Jid &remote, const QString &sid) { - Q_UNUSED(sid); + QPair key = qMakePair(remote, sid); + d->sids.remove(key); } } // namespace IBB diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 5ede921d..5746ffff 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -46,7 +46,6 @@ class Transport : public XMPP::Jingle::Transport bool isValid() const override; Features features() const override; - QString sid() const; Connection::Ptr connection() const; size_t blockSize() const; private: @@ -70,7 +69,8 @@ class Pad : public TransportManagerPad TransportManager *manager() const override; QString generateSid() const; - void registerSid(const QString &sid); + bool registerSid(const QString &sid); + void forgetSid(const QString &sid); private: Manager *_manager; Session *_session; @@ -91,7 +91,8 @@ class Manager : public TransportManager { void closeAll() override; QString generateSid(const Jid &remote); - void registerSid(const Jid &remote, const QString &sid); + bool registerSid(const Jid &remote, const QString &sid); + void forgetSid(const Jid &remote, const QString &sid); private: class Private; QScopedPointer d; From b403d635ec06a00738facbfd99034e57ca767a60 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 5 Jun 2019 08:19:12 +0300 Subject: [PATCH 052/383] Jingle IBB in progress --- src/xmpp/xmpp-im/jingle-ibb.cpp | 13 ++++++++++--- src/xmpp/xmpp-im/xmpp_ibb.cpp | 16 ++++++++++------ src/xmpp/xmpp-im/xmpp_ibb.h | 5 ++++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 73418726..8e4753d4 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -20,6 +20,7 @@ #include "jingle-ibb.h" #include "xmpp/jid/jid.h" #include "xmpp_client.h" +#include "xmpp_ibb.h" namespace XMPP { namespace Jingle { @@ -29,14 +30,17 @@ class Connection : public XMPP::Jingle::Connection { Q_OBJECT public: + Client *client; Jid peer; QString sid; size_t blockSize; + BSConnection *connection = nullptr; bool offerSent = false; bool offerReceived = false; - Connection(const Jid &jid, const QString &sid, size_t blockSize) : + Connection(Client *client, const Jid &jid, const QString &sid, size_t blockSize) : + client(client), peer(jid), sid(sid), blockSize(blockSize) @@ -46,7 +50,10 @@ class Connection : public XMPP::Jingle::Connection void checkAndStartConnection() { - // TODO + if (offerReceived && offerSent) { + connection = client->ibbManager()->createConnection(); + //connection->setP + } } }; @@ -62,7 +69,7 @@ struct Transport::Private QSharedPointer makeConnection(const Jid &jid, const QString &sid, size_t blockSize) { // TODO connect some signals - return QSharedPointer::create(jid, sid, blockSize); + return QSharedPointer::create(pad->session()->manager()->client(), jid, sid, blockSize); } }; diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index cf37f7f2..482781d4 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -25,7 +25,6 @@ #include -#define IBB_PACKET_SIZE 4096 #define IBB_PACKET_DELAY 0 using namespace XMPP; @@ -51,7 +50,7 @@ class IBBConnection::Private QString iq_id; QString stanza; - int blockSize = 0; + int blockSize = IBBConnection::PacketSize; //QByteArray recvBuf, sendBuf; bool closePending, closing; @@ -64,7 +63,7 @@ IBBConnection::IBBConnection(IBBManager *m) d = new Private; d->m = m; d->j = 0; - d->blockSize = IBB_PACKET_SIZE; + d->blockSize = PacketSize; resetConnection(); ++num_conn; @@ -104,6 +103,11 @@ IBBConnection::~IBBConnection() delete d; } +void IBBConnection::setPacketSize(int blockSize) +{ + d->blockSize = blockSize; +} + void IBBConnection::connectToJid(const Jid &peer, const QString &sid) { close(); @@ -119,7 +123,7 @@ void IBBConnection::connectToJid(const Jid &peer, const QString &sid) d->j = new JT_IBB(d->m->client()->rootTask()); connect(d->j, SIGNAL(finished()), SLOT(ibb_finished())); - d->j->request(d->peer, d->sid); + d->j->request(d->peer, d->sid, d->blockSize); d->j->go(true); } @@ -519,7 +523,7 @@ JT_IBB::~JT_IBB() delete d; } -void JT_IBB::request(const Jid &to, const QString &sid) +void JT_IBB::request(const Jid &to, const QString &sid, int blockSize) { d->mode = ModeRequest; QDomElement iq; @@ -529,7 +533,7 @@ void JT_IBB::request(const Jid &to, const QString &sid) //genUniqueKey query.setAttribute("xmlns", IBB_NS); query.setAttribute("sid", sid); - query.setAttribute("block-size", IBB_PACKET_SIZE); + query.setAttribute("block-size", blockSize); query.setAttribute("stanza", "iq"); iq.appendChild(query); d->iq = iq; diff --git a/src/xmpp/xmpp-im/xmpp_ibb.h b/src/xmpp/xmpp-im/xmpp_ibb.h index 0b70723d..8784a4f6 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.h +++ b/src/xmpp/xmpp-im/xmpp_ibb.h @@ -57,11 +57,14 @@ namespace XMPP { Q_OBJECT public: + static const int PacketSize = 4096; + enum { ErrRequest, ErrData }; enum { Idle, Requesting, WaitingForAccept, Active }; IBBConnection(IBBManager *); ~IBBConnection(); + void setPacketSize(int blockSize = IBBConnection::PacketSize); void connectToJid(const Jid &peer, const QString &sid); void accept(); void close(); @@ -147,7 +150,7 @@ namespace XMPP JT_IBB(Task *, bool serve=false); ~JT_IBB(); - void request(const Jid &, const QString &sid); + void request(const Jid &, const QString &sid, int blockSize = IBBConnection::PacketSize); void sendData(const Jid &, const IBBData &ibbData); void close(const Jid &, const QString &sid); void respondError(const Jid &, const QString &id, From 7af0fdf477729cef9fbf8dd561e4d1de31eaaf97 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 9 Jun 2019 00:48:35 +0300 Subject: [PATCH 053/383] jingle-ibb almost finished --- src/xmpp/xmpp-im/client.cpp | 17 ++- src/xmpp/xmpp-im/jingle-ibb.cpp | 247 +++++++++++++++++++++++++------- src/xmpp/xmpp-im/jingle-ibb.h | 11 +- src/xmpp/xmpp-im/xmpp_client.h | 4 + src/xmpp/xmpp-im/xmpp_ibb.cpp | 2 +- 5 files changed, 224 insertions(+), 57 deletions(-) diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index 7396bac5..a95164a2 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -88,6 +88,7 @@ #include "jingle-ft.h" #include "jingle-s5b.h" #include "tcpportreserver.h" +#include "jingle-ibb.h" #ifdef Q_OS_WIN #define vsnprintf _vsnprintf @@ -136,6 +137,7 @@ class Client::ClientPrivate TcpPortReserver *tcpPortReserver = nullptr; S5BManager *s5bman = nullptr; Jingle::S5B::Manager *jingleS5BManager = nullptr; + Jingle::IBB::Manager *jingleIBBManager = nullptr; IBBManager *ibbman = nullptr; BoBManager *bobman = nullptr; FileTransferManager *ftman = nullptr; @@ -177,7 +179,9 @@ Client::Client(QObject *par) auto ft = new Jingle::FileTransfer::Manager(this); d->jingleManager->registerApp(Jingle::FileTransfer::NS, ft); d->jingleS5BManager = new Jingle::S5B::Manager(d->jingleManager); + d->jingleIBBManager = new Jingle::IBB::Manager(d->jingleManager); d->jingleManager->registerTransport(Jingle::S5B::NS, d->jingleS5BManager); + d->jingleManager->registerTransport(Jingle::IBB::NS, d->jingleIBBManager); } Client::~Client() @@ -278,6 +282,11 @@ Jingle::S5B::Manager *Client::jingleS5BManager() const return d->jingleS5BManager; } +Jingle::IBB::Manager *Client::jingleIBBManager() const +{ + return d->jingleIBBManager; +} + IBBManager *Client::ibbManager() const { return d->ibbman; @@ -1318,7 +1327,13 @@ void Client::s5b_incomingReady() void Client::ibb_incomingReady() { - handleIncoming(d->ibbman->takeIncoming()); + auto c = d->ibbman->takeIncoming(); + if (!c) + return; + + if (d->jingleIBBManager && d->jingleIBBManager->handleIncoming(c)) + return; + handleIncoming(c); } void Client::handleIncoming(BSConnection *c) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 8e4753d4..4579d157 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -22,22 +22,28 @@ #include "xmpp_client.h" #include "xmpp_ibb.h" +#include + namespace XMPP { namespace Jingle { namespace IBB { +const QString NS(QStringLiteral("urn:xmpp:jingle:transports:ibb:1")); + class Connection : public XMPP::Jingle::Connection { Q_OBJECT + public: Client *client; Jid peer; QString sid; size_t blockSize; - BSConnection *connection = nullptr; + IBBConnection *connection = nullptr; bool offerSent = false; bool offerReceived = false; + bool closing = false; Connection(Client *client, const Jid &jid, const QString &sid, size_t blockSize) : client(client), @@ -48,12 +54,74 @@ class Connection : public XMPP::Jingle::Connection } - void checkAndStartConnection() + void setConnection(IBBConnection *c) + { + connection = c; + connect(c, &IBBConnection::readyRead, this, &Connection::readyRead); + connect(c, &IBBConnection::bytesWritten, this, &Connection::bytesWritten); + connect(c, &IBBConnection::connectionClosed, this, &Connection::handleIBBClosed); + connect(c, &IBBConnection::delayedCloseFinished, this, &Connection::handleIBBClosed); + connect(c, &IBBConnection::aboutToClose, this, &Connection::aboutToClose); + connect(c, &IBBConnection::connected, this, [this](){ setOpenMode(connection->openMode()); emit connected(); }); + } + + qint64 bytesAvailable() const + { + return XMPP::Jingle::Connection::bytesAvailable() + (connection? connection->bytesAvailable() : 0); + } + + qint64 bytesToWrite() const + { + return XMPP::Jingle::Connection::bytesToWrite() + (connection? connection->bytesToWrite() : 0); + } + + void close() + { + if (connection) { + connection->close(); + setOpenMode(connection->openMode()); + } else { + XMPP::Jingle::Connection::close(); + emit connectionClosed(); + } + } + +signals: + void connected(); + +protected: + qint64 writeData(const char *data, qint64 maxSize) + { + return connection->write(data, maxSize); + } + + qint64 readData(char *data, qint64 maxSize) { - if (offerReceived && offerSent) { - connection = client->ibbManager()->createConnection(); - //connection->setP + quint64 ret = connection->read(data, maxSize); + if (closing && !bytesAvailable()) { + postCloseAllDataRead(); } + return ret; + } + +private: + + void handleIBBClosed() + { + closing = true; + if (bytesAvailable()) + setOpenMode(QIODevice::ReadOnly); + else + postCloseAllDataRead(); + emit connectionClosed(); + } + + void postCloseAllDataRead() + { + closing = false; + connection->deleteLater(); + connection = nullptr; + setOpenMode(QIODevice::NotOpen); } }; @@ -66,10 +134,23 @@ struct Transport::Private size_t defaultBlockSize = 4096; bool started = false; - QSharedPointer makeConnection(const Jid &jid, const QString &sid, size_t blockSize) + void checkAndStartConnection(QSharedPointer &c) + { + if (!c->connection && c->offerReceived && c->offerSent && pad->session()->role() == Origin::Initiator) { + auto con = pad->session()->manager()->client()->ibbManager()->createConnection(); + auto ibbcon = static_cast(con); + ibbcon->setPacketSize(defaultBlockSize); + c->setConnection(ibbcon); + ibbcon->connectToJid(pad->session()->peer(), c->sid); + } + } + + void handleConnected(const QSharedPointer &c) { - // TODO connect some signals - return QSharedPointer::create(pad->session()->manager()->client(), jid, sid, blockSize); + if (c) { + readyConnections.append(c); + emit q->connected(); + } } }; @@ -78,6 +159,13 @@ Transport::Transport(const TransportManagerPad::Ptr &pad) : { d->q = this; d->pad = pad.staticCast(); + connect(pad->manager(), &TransportManager::abortAllRequested, this, [this](){ + for(auto &c: d->connections) { + c->close(); + } + //d->aborted = true; + emit failed(); + }); } Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : @@ -105,9 +193,26 @@ TransportManagerPad::Ptr Transport::pad() const void Transport::prepare() { if (d->connections.isEmpty()) { // seems like outgoing - QString sid = d->pad->generateSid(); - auto conn = d->makeConnection(d->pad->session()->peer(), sid, d->defaultBlockSize); - d->connections.insert(sid, conn); + auto conn = d->pad->makeConnection(QString(), d->defaultBlockSize); + auto ibbConn = conn.staticCast(); + connect(ibbConn.data(), &Connection::connected, this, [this](){ + auto c = static_cast(sender()); + d->handleConnected(d->connections.value(c->sid)); + }); + d->connections.insert(ibbConn->sid, ibbConn); + + connect(ibbConn.data(), &Connection::connectionClosed, this, [this](){ + Connection *c = static_cast(sender()); + d->connections.remove(c->sid); + QMutableListIterator> it(d->readyConnections); + while (it.hasNext()) { + auto &p = it.next(); + if (p.data() == c) { + it.remove(); + break; + } + } + }); } emit updated(); } @@ -117,7 +222,7 @@ void Transport::start() d->started = true; for (auto &c: d->connections) { - c->checkAndStartConnection(); + d->checkAndStartConnection(c); } } @@ -139,10 +244,15 @@ bool Transport::update(const QDomElement &transportEl) auto it = d->connections.find(sid); if (it == d->connections.end()) { - if (!d->pad->registerSid(sid)) { - return false; // TODO we need last error somewhere + auto c = d->pad->makeConnection(sid, bs_final); + if (c) { + auto ibbc = c.staticCast(); + it = d->connections.insert(ibbc->sid, ibbc); + connect(ibbc.data(), &Connection::connected, this, [this](){ + auto c = static_cast(sender()); + d->handleConnected(d->connections.value(c->sid)); + }); } - it = d->connections.insert(sid, d->makeConnection(d->pad->session()->peer(), sid, bs_final)); } else { if (bs_final < (*it)->blockSize) { (*it)->blockSize = bs_final; @@ -151,7 +261,7 @@ bool Transport::update(const QDomElement &transportEl) (*it)->offerReceived = true; if (d->started) { - (*it)->checkAndStartConnection(); + d->checkAndStartConnection(it.value()); } return true; } @@ -192,7 +302,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { if (d->started) - connection->checkAndStartConnection(); + d->checkAndStartConnection(connection); }}; connection->offerSent = true; @@ -211,7 +321,7 @@ Transport::Features Transport::features() const Connection::Ptr Transport::connection() const { - return d->readyConnections.takeLast(); + return d->readyConnections.isEmpty()? Connection::Ptr() : d->readyConnections.takeFirst().staticCast(); } size_t Transport::blockSize() const @@ -240,62 +350,101 @@ TransportManager *Pad::manager() const return _manager; } -QString Pad::generateSid() const +Connection::Ptr Pad::makeConnection(const QString &sid, size_t blockSize) { - return _manager->generateSid(_session->peer()); + return _manager->makeConnection(_session->peer(), sid, blockSize); } -bool Pad::registerSid(const QString &sid) +struct Manager::Private +{ + QHash,QSharedPointer> connections; + XMPP::Jingle::Manager *jingleManager = nullptr; +}; + +Manager::Manager(QObject *parent) : + TransportManager(parent), + d(new Private) { - return _manager->registerSid(_session->peer(), sid); + } -void Pad::forgetSid(const QString &sid) +Manager::~Manager() { - _manager->forgetSid(_session->peer(), sid); + } -struct Manager::Private +Transport::Features Manager::features() const { - QSet> sids; -}; + return Transport::AlwaysConnect | Transport::Reliable | Transport::Slow; +} -Manager::Manager(QObject *parent) : - TransportManager(parent), - d(new Private) +void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { + d->jingleManager = jm; +} +QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) +{ + return QSharedPointer(new Transport(pad)); } -QString Manager::generateSid(const Jid &remote) +QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) { - QString sid; - QPair key; - do { - sid = QString("ibb_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - key = qMakePair(remote, sid); - } while (d->sids.contains(key)); - - d->sids.insert(key); - return sid; + auto t = new Transport(pad, transportEl); + QSharedPointer ret(t); + if (t->isValid()) { + return ret; + } + return QSharedPointer(); } -bool Manager::registerSid(const Jid &remote, const QString &sid) +TransportManagerPad* Manager::pad(Session *session) { - QPair key = qMakePair(remote, sid); - if (d->sids.contains(key)) { - return false; + return new Pad(this, session); +} + +void Manager::closeAll() +{ + emit abortAllRequested(); +} + +XMPP::Jingle::Connection::Ptr Manager::makeConnection(const Jid &peer, const QString &sid, size_t blockSize) +{ + if (!sid.isEmpty() && d->connections.contains(qMakePair(peer, sid))) { + qWarning("sid %s was already registered for %s", qPrintable(sid), qPrintable(peer.full())); + return Connection::Ptr(); } - d->sids.insert(key); - return true; + QString s(sid); + if (s.isEmpty()) { + QPair key; + do { + s = QString("ibb_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + key = qMakePair(peer, s); + } while (d->connections.contains(key)); + } + auto conn = QSharedPointer::create(d->jingleManager->client(), peer, sid, blockSize); + d->connections.insert(qMakePair(peer, sid), conn); + connect(conn.data(), &Connection::connectionClosed, this, [this](){ + Connection *c = static_cast(sender()); + d->connections.remove(qMakePair(c->peer, c->sid)); + }); + + return conn.staticCast(); } -void Manager::forgetSid(const Jid &remote, const QString &sid) +bool Manager::handleIncoming(IBBConnection *c) { - QPair key = qMakePair(remote, sid); - d->sids.remove(key); + auto conn = d->connections.value(qMakePair(c->peer(), c->sid())); + if (conn) { + conn->setConnection(c); + QTimer::singleShot(0, c, &IBBConnection::accept); + return true; + } + return false; } } // namespace IBB } // namespace Jingle } // namespace XMPP + +#include "jingle-ibb.moc" diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 5746ffff..95ad5ef1 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -23,6 +23,8 @@ #include "jingle.h" namespace XMPP { + class IBBConnection; + namespace Jingle { namespace IBB { @@ -68,9 +70,7 @@ class Pad : public TransportManagerPad Session *session() const override; TransportManager *manager() const override; - QString generateSid() const; - bool registerSid(const QString &sid); - void forgetSid(const QString &sid); + Connection::Ptr makeConnection(const QString &sid, size_t blockSize); private: Manager *_manager; Session *_session; @@ -90,9 +90,8 @@ class Manager : public TransportManager { void closeAll() override; - QString generateSid(const Jid &remote); - bool registerSid(const Jid &remote, const QString &sid); - void forgetSid(const Jid &remote, const QString &sid); + Connection::Ptr makeConnection(const Jid &peer, const QString &sid, size_t blockSize); + bool handleIncoming(IBBConnection *c); private: class Private; QScopedPointer d; diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index 695b6a96..b250bf59 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -60,6 +60,9 @@ namespace XMPP { namespace S5B { class Manager; } + namespace IBB { + class Manager; + } } } @@ -145,6 +148,7 @@ namespace XMPP HttpFileUploadManager *httpFileUploadManager() const; Jingle::Manager* jingleManager() const; Jingle::S5B::Manager *jingleS5BManager() const; + Jingle::IBB::Manager *jingleIBBManager() const; void setFileTransferEnabled(bool b); FileTransferManager *fileTransferManager() const; diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index 482781d4..bb719b27 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -409,7 +409,7 @@ BSConnection *IBBManager::createConnection() IBBConnection *IBBManager::takeIncoming() { - return d->incomingConns.isEmpty()? 0 : d->incomingConns.takeFirst(); + return d->incomingConns.isEmpty()? nullptr : d->incomingConns.takeFirst(); } void IBBManager::ibb_incomingRequest(const Jid &from, const QString &id, From c90f592999e0fcb87f02badfbd3311ec4a630403 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 9 Jun 2019 09:24:07 +0300 Subject: [PATCH 054/383] Make jingle-ibb working --- src/xmpp/xmpp-im/jingle-ibb.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 4579d157..7303d3e8 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -44,6 +44,7 @@ class Connection : public XMPP::Jingle::Connection bool offerSent = false; bool offerReceived = false; bool closing = false; + bool finished = false; Connection(Client *client, const Jid &jid, const QString &sid, size_t blockSize) : client(client), @@ -113,15 +114,16 @@ class Connection : public XMPP::Jingle::Connection setOpenMode(QIODevice::ReadOnly); else postCloseAllDataRead(); - emit connectionClosed(); } void postCloseAllDataRead() { closing = false; + finished = true; connection->deleteLater(); connection = nullptr; setOpenMode(QIODevice::NotOpen); + emit connectionClosed(); } }; @@ -136,7 +138,7 @@ struct Transport::Private void checkAndStartConnection(QSharedPointer &c) { - if (!c->connection && c->offerReceived && c->offerSent && pad->session()->role() == Origin::Initiator) { + if (!c->connection && !c->finished && c->offerReceived && c->offerSent && pad->session()->role() == Origin::Initiator) { auto con = pad->session()->manager()->client()->ibbManager()->createConnection(); auto ibbcon = static_cast(con); ibbcon->setPacketSize(defaultBlockSize); @@ -182,7 +184,10 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::~Transport() { - + // we have to mark all of them as finished just in case they are captured somewhere else + for (auto &c: d->connections) { + c->finished = true; + } } TransportManagerPad::Ptr Transport::pad() const @@ -261,7 +266,8 @@ bool Transport::update(const QDomElement &transportEl) (*it)->offerReceived = true; if (d->started) { - d->checkAndStartConnection(it.value()); + auto c = it.value(); + QTimer::singleShot(0, this, [this,c]() mutable { d->checkAndStartConnection(c); }); } return true; } @@ -311,7 +317,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() bool Transport::isValid() const { - return true; + return d; } Transport::Features Transport::features() const @@ -422,8 +428,8 @@ XMPP::Jingle::Connection::Ptr Manager::makeConnection(const Jid &peer, const QSt key = qMakePair(peer, s); } while (d->connections.contains(key)); } - auto conn = QSharedPointer::create(d->jingleManager->client(), peer, sid, blockSize); - d->connections.insert(qMakePair(peer, sid), conn); + auto conn = QSharedPointer::create(d->jingleManager->client(), peer, s, blockSize); + d->connections.insert(qMakePair(peer, s), conn); connect(conn.data(), &Connection::connectionClosed, this, [this](){ Connection *c = static_cast(sender()); d->connections.remove(qMakePair(c->peer, c->sid)); From 1bf2bc3c78e4e8bf41fa14af9f844511887791a7 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 9 Jun 2019 14:27:37 +0300 Subject: [PATCH 055/383] Wait with ibb connection reset till iq ack for close --- src/xmpp/xmpp-im/client.cpp | 2 ++ src/xmpp/xmpp-im/jingle-ft.cpp | 4 ++-- src/xmpp/xmpp-im/jingle-ibb.cpp | 20 ++++++++++---------- src/xmpp/xmpp-im/jingle-ibb.h | 2 +- src/xmpp/xmpp-im/jingle-s5b.cpp | 6 ------ src/xmpp/xmpp-im/jingle-s5b.h | 2 +- src/xmpp/xmpp-im/jingle.cpp | 5 +++++ src/xmpp/xmpp-im/jingle.h | 2 +- src/xmpp/xmpp-im/xmpp_ibb.cpp | 2 +- 9 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index a95164a2..d1d7d786 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -1267,7 +1267,9 @@ DiscoItem Client::makeDiscoResult(const QString &node) const features.addFeature("urn:xmpp:time"); features.addFeature("urn:xmpp:message-correct:0"); features.addFeature("urn:xmpp:jingle:1"); + // TODO rather do foreach for all registered jingle apps and transports features.addFeature("urn:xmpp:jingle:transports:s5b:1"); + features.addFeature("urn:xmpp:jingle:transports:ibb:1"); features.addFeature("urn:xmpp:jingle:apps:file-transfer:5"); // TODO: since it depends on UI it needs a way to be disabled Hash::populateFeatures(features); diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 9d82ad9a..fc38e42f 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -422,7 +422,7 @@ class Application::Private setState(State::Finished); return; // everything is written } - auto sz = transport->blockSize(); + auto sz = connection->blockSize(); sz = sz? sz : 8192; if (sz > bytesLeft) { sz = bytesLeft; @@ -444,7 +444,7 @@ class Application::Private { quint64 bytesAvail; while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { - quint64 sz = 65536; // should be respect transport->blockSize() ? + quint64 sz = 65536; // shall we respect transport->blockSize() ? if (sz > bytesLeft) { sz = bytesLeft; } diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 7303d3e8..fce8e769 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -38,7 +38,7 @@ class Connection : public XMPP::Jingle::Connection Client *client; Jid peer; QString sid; - size_t blockSize; + size_t _blockSize; IBBConnection *connection = nullptr; bool offerSent = false; @@ -50,7 +50,7 @@ class Connection : public XMPP::Jingle::Connection client(client), peer(jid), sid(sid), - blockSize(blockSize) + _blockSize(blockSize) { } @@ -66,6 +66,11 @@ class Connection : public XMPP::Jingle::Connection connect(c, &IBBConnection::connected, this, [this](){ setOpenMode(connection->openMode()); emit connected(); }); } + size_t blockSize() const + { + return _blockSize; + } + qint64 bytesAvailable() const { return XMPP::Jingle::Connection::bytesAvailable() + (connection? connection->bytesAvailable() : 0); @@ -259,8 +264,8 @@ bool Transport::update(const QDomElement &transportEl) }); } } else { - if (bs_final < (*it)->blockSize) { - (*it)->blockSize = bs_final; + if (bs_final < (*it)->_blockSize) { + (*it)->_blockSize = bs_final; } } @@ -304,7 +309,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() QDomElement tel = doc->createElementNS(NS, "transport"); tel.setAttribute(QStringLiteral("sid"), connection->sid); - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->blockSize)); + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->_blockSize)); upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { if (d->started) @@ -330,11 +335,6 @@ Connection::Ptr Transport::connection() const return d->readyConnections.isEmpty()? Connection::Ptr() : d->readyConnections.takeFirst().staticCast(); } -size_t Transport::blockSize() const -{ - return d->defaultBlockSize; -} - Pad::Pad(Manager *manager, Session *session) { _manager = manager; diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 95ad5ef1..7486f476 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -49,7 +49,7 @@ class Transport : public XMPP::Jingle::Transport Features features() const override; Connection::Ptr connection() const; - size_t blockSize() const; + private: friend class Manager; diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 8e9da075..5e303f7a 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1457,12 +1457,6 @@ Connection::Ptr Transport::connection() const return d->connection.staticCast(); } -size_t Transport::blockSize() const -{ - return d->blockSize; -} - - //---------------------------------------------------------------- // Manager //---------------------------------------------------------------- diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index b6aa13af..8ecf0056 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -148,7 +148,7 @@ class Transport : public XMPP::Jingle::Transport QString sid() const; QString directAddr() const; Connection::Ptr connection() const; - size_t blockSize() const; + private: friend class Manager; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 56000fc9..baf076b8 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1743,6 +1743,11 @@ NetworkDatagram Connection::receiveDatagram(qint64 maxSize) return NetworkDatagram(); } +size_t Connection::blockSize() const +{ + return 0; // means "block" is not applicable for this kind of connection +} + } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index cccfd145..d423c47b 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -287,6 +287,7 @@ class Connection : public ByteStream using Ptr = QSharedPointer; // will be shared between transport and application virtual bool hasPendingDatagrams() const; virtual NetworkDatagram receiveDatagram(qint64 maxSize = -1); + virtual size_t blockSize() const; }; class Application; @@ -351,7 +352,6 @@ class Transport : public QObject { virtual Features features() const = 0; virtual TransportManagerPad::Ptr pad() const = 0; virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection - virtual size_t blockSize() const = 0; signals: void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler. // if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent. diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index bb719b27..475af303 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -165,7 +165,7 @@ void IBBConnection::close() trySend(); // if there is data pending to be written, then pend the closing - if(bytesToWrite() > 0) { + if(bytesToWrite() > 0 || d->closing) { return; } } From def42726e4ae12f264f22bfec9b9dec90f3964e6 Mon Sep 17 00:00:00 2001 From: Vitaly Tonkacheyev Date: Sun, 9 Jun 2019 16:48:23 +0300 Subject: [PATCH 056/383] Update CMakeLists.txt Added lost xmpp-im/jingle-ibb files --- src/xmpp/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xmpp/CMakeLists.txt b/src/xmpp/CMakeLists.txt index 3d72b436..1fbbc606 100644 --- a/src/xmpp/CMakeLists.txt +++ b/src/xmpp/CMakeLists.txt @@ -90,6 +90,7 @@ set(HEADERS xmpp-im/jingle.h xmpp-im/jingle-ft.h xmpp-im/jingle-s5b.h + xmpp-im/jingle-ibb.h zlib/zlibcompressor.h zlib/zlibdecompressor.h @@ -126,6 +127,7 @@ set(SOURCES xmpp-im/jingle.cpp xmpp-im/jingle-ft.cpp xmpp-im/jingle-s5b.cpp + xmpp-im/jingle-ibb.cpp base/randomnumbergenerator.cpp base/timezone.cpp From b24d0d602a3b65a3e624eb7a49a8562e594c7913 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 10 Jun 2019 00:31:36 +0300 Subject: [PATCH 057/383] Jingle transport fallback in progress --- src/xmpp/xmpp-im/jingle-ft.cpp | 165 +++++++++++++++++++++++---------- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle.h | 1 + 3 files changed, 117 insertions(+), 50 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index fc38e42f..d8da40b4 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -393,6 +393,7 @@ class Application::Private QStringList availableTransports; bool transportFailed = false; bool closeDeviceOnFinish = true; + bool waitTransportAccept = false; QIODevice *device = nullptr; quint64 bytesLeft = 0; @@ -498,7 +499,7 @@ State Application::state() const void Application::setState(State state) { - d->state = state; + d->setState(state); } QString Application::contentName() const @@ -513,7 +514,7 @@ Origin Application::creator() const Origin Application::senders() const { - return d->senders; + return d->senders; } Application::SetDescError Application::setDescription(const QDomElement &description) @@ -543,52 +544,64 @@ bool Application::setTransport(const QSharedPointer &transport) { if (d->transport) { d->transport->disconnect(this); + d->transport.reset(); } - if (transport->features() & Transport::Reliable) { - int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); - if (nsIndex == -1) { - return false; - } - d->availableTransports.removeAt(nsIndex); - d->transport = transport; - d->setState(State::Pending); - connect(transport.data(), &Transport::updated, this, &Application::updated); - connect(transport.data(), &Transport::connected, this, [this](){ - d->connection = d->transport->connection(); - connect(d->connection.data(), &Connection::readyRead, this, [this](){ - if (!d->device) { - return; - } - if (d->pad->session()->role() != d->senders) { - d->readNextBlockFromTransport(); - } - }); - connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ - Q_UNUSED(bytes) - if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { - d->writeNextBlockToTransport(); - } - }); - d->setState(State::Active); - if (d->acceptFile.range().isValid()) { - d->bytesLeft = d->acceptFile.range().length; - emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); - } else { - d->bytesLeft = d->file.size(); - emit deviceRequested(0, d->bytesLeft); + if (!(transport->features() & Transport::Reliable)) + return false; + + int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); + if (nsIndex == -1) { + return false; + } + + d->availableTransports.removeAt(nsIndex); + d->transport = transport; + connect(transport.data(), &Transport::updated, this, &Application::updated); + connect(transport.data(), &Transport::connected, this, [this](){ + d->transportFailed = false; + d->connection = d->transport->connection(); + connect(d->connection.data(), &Connection::readyRead, this, [this](){ + if (!d->device) { + return; + } + if (d->pad->session()->role() != d->senders) { + d->readNextBlockFromTransport(); } }); - - connect(transport.data(), &Transport::failed, this, [this](){ - if (d->availableTransports.size()) { // we can do transport-replace here - // TODO + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ + Q_UNUSED(bytes) + if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { + d->writeNextBlockToTransport(); } - d->transportFailed = true; - d->setState(State::Finishing); }); - return true; + d->setState(State::Active); + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + } else { + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); + } + }); + + connect(transport.data(), &Transport::failed, this, [this](){ + d->transportFailed = true; + d->waitTransportAccept = false; + if (!selectNextTransport()) { // we can do transport-replace here + if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { + // we were unable to send even initial offer + d->setState(State::Finished); + } else { + d->setState(State::Finishing); // we have to notify our peer about problems + } + } + }); + + if (d->state >= State::Unacked) { + // seems like we are in transport failure recovery. d->transportFailed may confirm this + d->transport->prepare(); } - return false; + return true; } QSharedPointer Application::transport() const @@ -598,18 +611,30 @@ QSharedPointer Application::transport() const Action Application::outgoingUpdateType() const { + if (d->waitTransportAccept && d->state < State::Finishing) + return Action::NoAction; // let's first finish waiting. and after we will do content-accept + switch (d->state) { case State::Created: break; case State::PrepareLocalOffer: - if (d->transport->hasUpdates()) { - return d->creator == d->pad->session()->role()? Action::ContentAdd : Action::ContentAccept; - } + if (d->transportFailed && !d->transport) + return Action::ContentReject; // case me=initiator was already handled by this momemnt + + if (d->transport->hasUpdates()) + return d->creator == d->pad->session()->role()? Action::ContentAdd : + (d->transportFailed? Action::ContentAccept : Action::TransportReplace); break; case State::Connecting: case State::Active: case State::Pending: + if (d->transportFailed && (d->state == State::Active || !d->transport)) + return Action::ContentRemove; + if (d->transport->hasUpdates()) { + if (d->transportFailed) { + return Action::TransportReplace; + } return Action::TransportInfo; } break; @@ -633,6 +658,17 @@ OutgoingUpdate Application::takeOutgoingUpdate() auto client = d->pad->session()->manager()->client(); auto doc = client->doc(); if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content + if (d->transportFailed && !d->transport) { + ContentBase cb(d->creator, d->contentName); + QList updates; + updates << cb.toXml(doc, "content"); + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); + + return OutgoingUpdate{updates, [this](){ + d->setState(State::Finished); + }}; + } + if (!d->transport->hasUpdates()) { // failed to select next transport. can't continue return OutgoingUpdate(); } @@ -653,15 +689,31 @@ OutgoingUpdate Application::takeOutgoingUpdate() std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); cel.appendChild(tel); + if (d->transportFailed) { + d->waitTransportAccept = true; + return OutgoingUpdate{QList()<setState(State::Unacked); return OutgoingUpdate{QList()<state = d->pad->session()->role() == Origin::Initiator? State::Pending : State::Active; + d->setState(d->pad->session()->role() == Origin::Initiator? State::Pending : State::Connecting); }}; } if (d->state == State::Connecting || d->state == State::Active || d->state == State::Pending) { + if (d->transportFailed && (d->state == State::Active || !d->transport)) { + ContentBase cb(d->creator, d->contentName); + QList updates; + updates << cb.toXml(doc, "content"); + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); + return OutgoingUpdate{updates, [this](){ + d->setState(State::Finished); + } + }; + } + if (d->transport->hasUpdates()) { // failed to select next transport. can't continue QDomElement tel; OutgoingUpdateCB trCallback; @@ -673,6 +725,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() ContentBase cb(d->creator, d->contentName); auto cel = cb.toXml(doc, "content"); cel.appendChild(tel); + d->waitTransportAccept = true; return OutgoingUpdate{QList()< &t) const bool Application::selectNextTransport() { - if (d->availableTransports.size()) { - return setTransport(d->pad->session()->newOutgoingTransport(d->availableTransports.first())); + while (d->availableTransports.size()) { + auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.first()); + if (t && setTransport(t)) { + return true; + } else { + d->availableTransports.removeFirst(); + } } return false; } @@ -717,7 +775,7 @@ void Application::prepare() selectNextTransport(); } if (d->transport) { - d->state = State::PrepareLocalOffer; + d->setState(State::PrepareLocalOffer); d->transport->prepare(); } } @@ -725,7 +783,7 @@ void Application::prepare() void Application::start() { if (d->transport) { - d->state = State::Active; + d->setState(State::Active); d->transport->start(); } // TODO we need QIODevice somewhere here @@ -743,6 +801,13 @@ bool Application::accept(const QDomElement &el) return true; } +void Application::setTransportAccepted() +{ + d->waitTransportAccept = false; + d->transportFailed = false; + emit updated(); +} + bool Application::isValid() const { return d->file.isValid() && d->transport && d->contentName.size() > 0 && diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 327dfbb3..24fb5760 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -139,6 +139,7 @@ class Application : public XMPP::Jingle::Application void prepare() override; void start() override; bool accept(const QDomElement &el) override; + void setTransportAccepted() override; bool isValid() const; diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index d423c47b..3053a669 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -390,6 +390,7 @@ class Application : public QObject virtual OutgoingUpdate takeOutgoingUpdate() = 0; // this may return something only when outgoingUpdateType() != NoAction virtual bool wantBetterTransport(const QSharedPointer &) const = 0; virtual bool selectNextTransport() = 0; + virtual void setTransportAccepted() = 0; /** * @brief prepare to send content-add/session-initiate From 89b32927d7a46cabe71dfff6294a126797785072 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 10 Jun 2019 08:24:58 +0300 Subject: [PATCH 058/383] a little more progress with jingle transport fallback --- src/xmpp/xmpp-im/jingle-ft.cpp | 49 +++++++++++----------------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index d8da40b4..c89b2170 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -391,6 +391,7 @@ class Application::Private QSharedPointer transport; Connection::Ptr connection; QStringList availableTransports; + bool transportReady = false; // when prepare local offer finished for the transport bool transportFailed = false; bool closeDeviceOnFinish = true; bool waitTransportAccept = false; @@ -621,9 +622,11 @@ Action Application::outgoingUpdateType() const if (d->transportFailed && !d->transport) return Action::ContentReject; // case me=initiator was already handled by this momemnt - if (d->transport->hasUpdates()) + if (d->transport->hasUpdates() || d->transportReady) { + d->transportReady = true; return d->creator == d->pad->session()->role()? Action::ContentAdd : (d->transportFailed? Action::ContentAccept : Action::TransportReplace); + } break; case State::Connecting: case State::Active: @@ -657,18 +660,20 @@ OutgoingUpdate Application::takeOutgoingUpdate() auto client = d->pad->session()->manager()->client(); auto doc = client->doc(); - if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content - if (d->transportFailed && !d->transport) { - ContentBase cb(d->creator, d->contentName); - QList updates; - updates << cb.toXml(doc, "content"); - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); - return OutgoingUpdate{updates, [this](){ - d->setState(State::Finished); - }}; - } + // content-remove or content-reject + if (d->transportFailed && (d->state >= State::Active || !d->transport)) { + ContentBase cb(d->creator, d->contentName); + QList updates; + updates << cb.toXml(doc, "content"); + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); + return OutgoingUpdate{updates, [this](){ + d->setState(State::Finished); + } + }; + } + if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content if (!d->transport->hasUpdates()) { // failed to select next transport. can't continue return OutgoingUpdate(); } @@ -703,17 +708,6 @@ OutgoingUpdate Application::takeOutgoingUpdate() }}; } if (d->state == State::Connecting || d->state == State::Active || d->state == State::Pending) { - if (d->transportFailed && (d->state == State::Active || !d->transport)) { - ContentBase cb(d->creator, d->contentName); - QList updates; - updates << cb.toXml(doc, "content"); - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); - return OutgoingUpdate{updates, [this](){ - d->setState(State::Finished); - } - }; - } - if (d->transport->hasUpdates()) { // failed to select next transport. can't continue QDomElement tel; OutgoingUpdateCB trCallback; @@ -730,17 +724,6 @@ OutgoingUpdate Application::takeOutgoingUpdate() } } if (d->state == State::Finishing) { - if (d->transportFailed) { - ContentBase cb(d->creator, d->contentName); - QList updates; - updates << cb.toXml(doc, "content"); - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); - return OutgoingUpdate{updates, [this](){ - d->setState(State::Finished); - } - }; - } - // else send ContentBase cb(d->pad->session()->role(), d->contentName); return OutgoingUpdate{QList() << cb.toXml(doc, "received"), [this](){ d->setState(State::Finished); From 57885217329554a4d716d5df3ead0d5ac4b1183f Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 11 Jun 2019 00:39:54 +0300 Subject: [PATCH 059/383] transport replace generic handlers --- src/xmpp/xmpp-im/jingle.cpp | 73 ++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index baf076b8..38c69197 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1208,6 +1208,75 @@ class Session::Private return true; } + bool handleIncomingTransportReplace(const QDomElement &jingleEl) + { + QList>> apps; + QList> toReject; + QString contentTag(QStringLiteral("content")); + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + ContentBase cb(ce); + auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); + QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + Application *app = contentList.value(ContentKey{cb.name, cb.creator}); + if (!app) continue; //wtf? + + auto trPad = q->transportPadFactory(transportNS); + if (!trPad) { + toReject.append(qMakePair(app, transportEl)); + continue; + } + + auto transport = trPad->manager()->newTransport(trPad, transportEl); + if (!transport) { + toReject.append(qMakePair(app, transportEl)); + continue; + } + + apps.append(qMakePair(app, transport)); + } + + for (auto &v: apps) { + if (!v.first->setTransport(v.second)) { + // TODO + } + } + + planStep(); + return true; + } + + bool handleIncomingTransportAccept(const QDomElement &jingleEl) + { + QSet apps; + QString contentTag(QStringLiteral("content")); + for(QDomElement ce = jingleEl.firstChildElement(contentTag); + !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) + { + ContentBase cb(ce); + if (!cb.isValid()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + Application *app = contentList.value(ContentKey{cb.name, cb.creator}); + if (app) { + apps.insert(app); + } + } + + for (auto app: apps) { + app->setTransportAccepted(); + } + + planStep(); + return true; + } + bool handleIncomingTransportInfo(const QDomElement &jingleEl) { QString contentTag(QStringLiteral("content")); @@ -1498,13 +1567,13 @@ bool Session::updateFromXml(Action action, const QDomElement &jingleEl) case Action::SessionTerminate: return d->handleIncomingSessionTerminate(jingleEl); case Action::TransportAccept: - break; + return d->handleIncomingTransportAccept(jingleEl); case Action::TransportInfo: return d->handleIncomingTransportInfo(jingleEl); case Action::TransportReject: break; case Action::TransportReplace: - break; + return d->handleIncomingTransportReplace(jingleEl); case Action::NoAction: default: break; From 33eb278ac8a975fbbcf6b485eba27c2352b4ed52 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 11 Jun 2019 19:53:57 +0300 Subject: [PATCH 060/383] jingle transport-replace in progress --- src/xmpp/xmpp-im/jingle-ft.cpp | 77 ++++++++++++++++++++++++---------- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle.cpp | 29 +++++++++---- src/xmpp/xmpp-im/jingle.h | 3 ++ 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index c89b2170..3074146e 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -388,11 +388,11 @@ class Application::Private File acceptFile; // as it comes with "accept" response Origin creator; Origin senders; + Origin transportFailedOrigin = Origin::None; QSharedPointer transport; Connection::Ptr connection; QStringList availableTransports; bool transportReady = false; // when prepare local offer finished for the transport - bool transportFailed = false; bool closeDeviceOnFinish = true; bool waitTransportAccept = false; QIODevice *device = nullptr; @@ -543,10 +543,6 @@ File Application::acceptFile() const // incoming one? or we have to check real direction bool Application::setTransport(const QSharedPointer &transport) { - if (d->transport) { - d->transport->disconnect(this); - d->transport.reset(); - } if (!(transport->features() & Transport::Reliable)) return false; @@ -555,11 +551,17 @@ bool Application::setTransport(const QSharedPointer &transport) return false; } + // in case we automatically select a new transport on our own we definitely will come up to this point + if (d->transport) { + d->transport->disconnect(this); + d->transport.reset(); + } + d->availableTransports.removeAt(nsIndex); d->transport = transport; connect(transport.data(), &Transport::updated, this, &Application::updated); connect(transport.data(), &Transport::connected, this, [this](){ - d->transportFailed = false; + d->transportFailedOrigin = Origin::None; d->connection = d->transport->connection(); connect(d->connection.data(), &Connection::readyRead, this, [this](){ if (!d->device) { @@ -586,16 +588,21 @@ bool Application::setTransport(const QSharedPointer &transport) }); connect(transport.data(), &Transport::failed, this, [this](){ - d->transportFailed = true; + d->transportFailedOrigin = d->pad->session()->role(); d->waitTransportAccept = false; + if (d->state >= State::Active) { + emit updated(); // late failure are unhandled. just notify the remote + return; + } + // we can try to replace the transport if (!selectNextTransport()) { // we can do transport-replace here if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { // we were unable to send even initial offer d->setState(State::Finished); } else { - d->setState(State::Finishing); // we have to notify our peer about problems + emit updated(); // we have to notify our peer about failure } - } + } // else transport will notify when ready }); if (d->state >= State::Unacked) { @@ -605,6 +612,26 @@ bool Application::setTransport(const QSharedPointer &transport) return true; } +bool Application::replaceTransport(const QSharedPointer &transport) +{ + // remote party called transport-replace + auto peerRole = d->pad->session()->peerRole(); + // if transport recovery is in progress and I as an inititiator started it then forbid remote transport-replace + if (d->transportFailedOrigin != Origin::None && d->transportFailedOrigin != peerRole && d->pad->session()->role() == Origin::Initiator) { + // TODO tie-break + return false; + } + auto prev = d->transportFailedOrigin; + d->transportFailedOrigin = peerRole; + auto ret = setTransport(transport); + if (ret) + d->waitTransportAccept = false; + else + d->transportFailedOrigin = prev; + + return ret; +} + QSharedPointer Application::transport() const { return d->transport; @@ -613,36 +640,39 @@ QSharedPointer Application::transport() const Action Application::outgoingUpdateType() const { if (d->waitTransportAccept && d->state < State::Finishing) - return Action::NoAction; // let's first finish waiting. and after we will do content-accept + return Action::NoAction; switch (d->state) { case State::Created: break; case State::PrepareLocalOffer: - if (d->transportFailed && !d->transport) - return Action::ContentReject; // case me=initiator was already handled by this momemnt + if (d->transportFailedOrigin != Origin::None && !d->transport) + return Action::ContentReject; // case me=creator was already handled by this momemnt. see Transport::failed connectio above if (d->transport->hasUpdates() || d->transportReady) { d->transportReady = true; - return d->creator == d->pad->session()->role()? Action::ContentAdd : - (d->transportFailed? Action::ContentAccept : Action::TransportReplace); + auto myRole = d->pad->session()->role(); + if (d->creator == myRole) { + return Action::ContentAdd; + } + return d->transportFailedOrigin == myRole? Action::TransportReplace : Action::ContentAccept; } break; case State::Connecting: case State::Active: case State::Pending: - if (d->transportFailed && (d->state == State::Active || !d->transport)) + if (d->transportFailedOrigin != Origin::None && (d->state == State::Active || !d->transport)) return Action::ContentRemove; if (d->transport->hasUpdates()) { - if (d->transportFailed) { + if (d->transportFailedOrigin != Origin::None) { return Action::TransportReplace; } return Action::TransportInfo; } break; case State::Finishing: - if (d->transportFailed) { + if (d->transportFailedOrigin != Origin::None) { return Action::ContentRemove; } return Action::SecurityInfo; @@ -658,11 +688,14 @@ OutgoingUpdate Application::takeOutgoingUpdate() return OutgoingUpdate(); } + if (d->waitTransportAccept && d->state < State::Finishing) + return OutgoingUpdate(); + auto client = d->pad->session()->manager()->client(); auto doc = client->doc(); // content-remove or content-reject - if (d->transportFailed && (d->state >= State::Active || !d->transport)) { + if (d->transportFailedOrigin != Origin::None && (d->state >= State::Active || !d->transport)) { ContentBase cb(d->creator, d->contentName); QList updates; updates << cb.toXml(doc, "content"); @@ -694,7 +727,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); cel.appendChild(tel); - if (d->transportFailed) { + if (d->transportFailedOrigin == d->pad->session()->role()) { d->waitTransportAccept = true; return OutgoingUpdate{QList()<creator, d->contentName); auto cel = cb.toXml(doc, "content"); cel.appendChild(tel); - d->waitTransportAccept = true; + if (d->transportFailedOrigin != Origin::None) { + d->waitTransportAccept = true; + } return OutgoingUpdate{QList()<waitTransportAccept = false; - d->transportFailed = false; + d->transportFailedOrigin = Origin::None; emit updated(); } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 24fb5760..7cd8fb04 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -139,6 +139,7 @@ class Application : public XMPP::Jingle::Application void prepare() override; void start() override; bool accept(const QDomElement &el) override; + bool replaceTransport(const QSharedPointer &transport) override; void setTransportAccepted() override; bool isValid() const; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 38c69197..9c61c812 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1210,8 +1210,8 @@ class Session::Private bool handleIncomingTransportReplace(const QDomElement &jingleEl) { - QList>> apps; - QList> toReject; + QList,QDomElement>> passed; + QList toReject; QString contentTag(QStringLiteral("content")); for(QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) @@ -1228,25 +1228,33 @@ class Session::Private auto trPad = q->transportPadFactory(transportNS); if (!trPad) { - toReject.append(qMakePair(app, transportEl)); + toReject.append(ce); continue; } auto transport = trPad->manager()->newTransport(trPad, transportEl); if (!transport) { - toReject.append(qMakePair(app, transportEl)); + toReject.append(ce); continue; } - apps.append(qMakePair(app, transport)); + passed.append(std::make_tuple(app, transport, ce)); } - for (auto &v: apps) { - if (!v.first->setTransport(v.second)) { - // TODO + for (auto &v: passed) { + Application *app; + QSharedPointer transport; + QDomElement ce; + std::tie(app,transport,ce) = v; + if (!app->replaceTransport(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet + toReject.append(ce); } } + if (toReject.size()) { + outgoingUpdates.insert(Action::TransportReject, OutgoingUpdate{toReject,OutgoingUpdateCB()}); + } + planStep(); return true; } @@ -1367,6 +1375,11 @@ Origin Session::role() const return d->role; } +Origin Session::peerRole() const +{ + return negateOrigin(d->role); +} + XMPP::Stanza::Error Session::lastError() const { return d->lastError; diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 3053a669..d9d6e90f 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -390,6 +390,7 @@ class Application : public QObject virtual OutgoingUpdate takeOutgoingUpdate() = 0; // this may return something only when outgoingUpdateType() != NoAction virtual bool wantBetterTransport(const QSharedPointer &) const = 0; virtual bool selectNextTransport() = 0; + virtual bool replaceTransport(const QSharedPointer &transport) = 0; virtual void setTransportAccepted() = 0; /** @@ -425,6 +426,8 @@ class Session : public QObject QString sid() const; Origin role() const; // my role in session: initiator or responder + Origin peerRole() const; + XMPP::Stanza::Error lastError() const; // make new local content but do not add it to session yet From c4fe3cbeaaa366645b51075d42f464bb5fe6ed63 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 12 Jun 2019 09:30:45 +0300 Subject: [PATCH 061/383] Jingle errors handling --- src/xmpp/xmpp-im/jingle.cpp | 60 ++++++++++++++++++++++++++++++++++--- src/xmpp/xmpp-im/jingle.h | 20 +++++++++++++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 9c61c812..6ee11381 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -39,6 +39,7 @@ namespace XMPP { namespace Jingle { const QString NS(QStringLiteral("urn:xmpp:jingle:1")); +const QString ERROR_NS(QStringLiteral("urn:xmpp:jingle:errors:1")); //---------------------------------------------------------------------------- @@ -504,8 +505,12 @@ class JTPush : public Task auto session = client()->jingleManager()->session(from, jingle.sid()); if (session) { - // FIXME what if not yet acknowledged. xep-0166 has a solution for that - respondError(iq, Stanza::Error::Cancel, Stanza::Error::Conflict); + if (session->role() == Origin::Initiator) { // + respondTieBreak(iq); + } else { + // second session from this peer with the same sid. + respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); + } return true; } session = client()->jingleManager()->incomingSessionInitiate(from, jingle, jingleEl); @@ -520,7 +525,7 @@ class JTPush : public Task auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); client()->send(resp); } else { - auto el = client()->doc()->createElementNS(QString::fromLatin1("urn:xmpp:jingle:errors:1"), QStringLiteral("unknown-session")); + auto el = client()->doc()->createElementNS(ERROR_NS, QStringLiteral("unknown-session")); respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); } return true; @@ -549,6 +554,13 @@ class JTPush : public Task client()->send(resp); } + void respondTieBreak(const QDomElement &iq) + { + Stanza::Error error(Stanza::Error::Cancel, Stanza::Error::Conflict); + ErrorUtil::fill(*client()->doc(), error, ErrorUtil::TieBreak); + respondError(iq, error); + } + void respondError(const QDomElement &iq, const Stanza::Error &error) { auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), iq.attribute(QStringLiteral("id"))); @@ -1040,6 +1052,9 @@ class Session::Private } lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, err == Private::AddContentError::Unexpected? XMPP::Stanza::Error::UnexpectedRequest : XMPP::Stanza::Error::BadRequest); + if (err == Private::AddContentError::Unexpected) { + ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); + } return std::tuple>(false, QList()); } @@ -1104,6 +1119,9 @@ class Session::Private case Private::AddContentError::Unparsed: case Private::AddContentError::Unexpected: lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + if (err == Private::AddContentError::Unexpected) { + ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); + } return false; case Private::AddContentError::Unsupported: rejects += Reason(cond).toXml(manager->client()->doc()); @@ -1552,7 +1570,8 @@ bool Session::incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl bool Session::updateFromXml(Action action, const QDomElement &jingleEl) { if (d->state == State::Finished) { - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); // TODO OutOfOrder + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); + ErrorUtil::fill(jingleEl.ownerDocument(), d->lastError, ErrorUtil::OutOfOrder); return false; } @@ -1734,6 +1753,12 @@ Session *Manager::session(const Jid &remoteJid, const QString &sid) return d->sessions.value(qMakePair(remoteJid, sid)); } +void Manager::detachSession(Session *s) +{ + s->disconnect(this); + d->sessions.remove(qMakePair(s->peer(), s->sid())); +} + void Manager::setRemoteJidChecker(std::function checker) { d->remoteJidCecker = checker; @@ -1830,6 +1855,33 @@ size_t Connection::blockSize() const return 0; // means "block" is not applicable for this kind of connection } +const char* ErrorUtil::names[ErrorUtil::Last] = {"out-of-order","tie-break", "unknown-session", "unsupported-info"}; + +Stanza::Error ErrorUtil::make(QDomDocument &doc, int jingleCond, int type, int condition, const QString &text) +{ + auto el = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond])); + return Stanza::Error(type, condition, text, el); +} + +void ErrorUtil::fill(QDomDocument doc, Stanza::Error &error, int jingleCond) +{ + error.appSpec = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond])); +} + +int ErrorUtil::jingleCondition(const Stanza::Error &error) +{ + if (error.appSpec.attribute(QString::fromLatin1("xmlns")) != ERROR_NS) { + return UnknownError; + } + QString tagName = error.appSpec.tagName(); + for (int i = 0; i < int(sizeof(names) / sizeof(names[0])); ++i) { + if (tagName == names[i]) { + return i; + } + } + return UnknownError; +} + } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index d9d6e90f..619189bc 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -111,6 +111,25 @@ typedef std::function OutgoingUpdateCB; typedef std::tuple, OutgoingUpdateCB> OutgoingUpdate; // list of elements to b inserted to and success callback typedef std::tuple OutgoingTransportInfoUpdate; // transport element and success callback +class ErrorUtil +{ +public: + enum { + UnknownError, // unparsed/unknown error + OutOfOrder, + TieBreak, + UnknownSession, + UnsupportedInfo, + Last + }; + + static const char* names[Last]; + + static XMPP::Stanza::Error make(QDomDocument &doc, int jingleCond, int type=XMPP::Stanza::Error::Cancel, int condition=XMPP::Stanza::Error::UndefinedCondition, const QString &text=QString()); + static void fill(QDomDocument doc, XMPP::Stanza::Error &error, int jingleCond); + static int jingleCondition(const XMPP::Stanza::Error &error); +}; + class Jingle { public: @@ -549,6 +568,7 @@ class Manager : public QObject QString registerSession(Session *session); XMPP::Stanza::Error lastError() const; + void detachSession(Session *s); // disconnect the session from manager signals: void incomingSession(Session *); From de26fe25ca5d7f89150f3301bc98b41cf10ab75c Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 12 Jun 2019 15:55:34 +0300 Subject: [PATCH 062/383] handle tie-break case on jingle transport-replace --- src/xmpp/xmpp-core/xmpp_stanza.cpp | 10 ++++++++++ src/xmpp/xmpp-core/xmpp_stanza.h | 2 ++ src/xmpp/xmpp-im/jingle-ft.cpp | 24 +++++++++++++++--------- src/xmpp/xmpp-im/jingle-ft.h | 2 ++ src/xmpp/xmpp-im/jingle.cpp | 12 ++++++++++++ src/xmpp/xmpp-im/jingle.h | 3 +++ 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index fb6e74d6..fd74c0cc 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -81,6 +81,16 @@ Stanza::Error::Error(int _type, int _condition, const QString &_text, const QDom originalCode = 0; } +void Stanza::Error::reset() +{ + type = 0; + condition = UndefinedCondition; + text.clear(); + by.clear(); + appSpec = QDomElement(); + originalCode = 0; +} + class Stanza::Error::Private { diff --git a/src/xmpp/xmpp-core/xmpp_stanza.h b/src/xmpp/xmpp-core/xmpp_stanza.h index 34558ea0..f9be5d62 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.h +++ b/src/xmpp/xmpp-core/xmpp_stanza.h @@ -79,6 +79,8 @@ namespace XMPP QString by; QDomElement appSpec; + void reset(); + int code() const; bool fromCode(int code); diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 3074146e..7d08fa2f 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -389,6 +389,7 @@ class Application::Private Origin creator; Origin senders; Origin transportFailedOrigin = Origin::None; + XMPP::Stanza::Error lastError; QSharedPointer transport; Connection::Ptr connection; QStringList availableTransports; @@ -503,6 +504,11 @@ void Application::setState(State state) d->setState(state); } +Stanza::Error Application::lastError() const +{ + return d->lastError; +} + QString Application::contentName() const { return d->contentName; @@ -612,22 +618,22 @@ bool Application::setTransport(const QSharedPointer &transport) return true; } +Origin Application::transportReplaceOrigin() const +{ + return d->transportFailedOrigin; +} + bool Application::replaceTransport(const QSharedPointer &transport) { - // remote party called transport-replace - auto peerRole = d->pad->session()->peerRole(); - // if transport recovery is in progress and I as an inititiator started it then forbid remote transport-replace - if (d->transportFailedOrigin != Origin::None && d->transportFailedOrigin != peerRole && d->pad->session()->role() == Origin::Initiator) { - // TODO tie-break - return false; - } auto prev = d->transportFailedOrigin; - d->transportFailedOrigin = peerRole; + d->transportFailedOrigin = d->pad->session()->peerRole(); auto ret = setTransport(transport); if (ret) d->waitTransportAccept = false; - else + else { d->transportFailedOrigin = prev; + d->lastError.reset(); + } return ret; } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 7cd8fb04..495efe88 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -121,10 +121,12 @@ class Application : public XMPP::Jingle::Application ApplicationManagerPad::Ptr pad() const override; State state() const override; void setState(State state) override; + XMPP::Stanza::Error lastError() const; QString contentName() const override; Origin creator() const override; Origin senders() const override; + Origin transportReplaceOrigin() const; SetDescError setDescription(const QDomElement &description) override; void setFile(const File &file); File file() const; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 6ee11381..f3c1c58e 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1256,6 +1256,13 @@ class Session::Private continue; } + auto tfo = app->transportReplaceOrigin(); + // if transport recovery is in progress and I as an inititiator started it then forbid remote transport-replace + if (tfo != Origin::None && tfo != q->peerRole() && role == Origin::Initiator) { + lastError = ErrorUtil::makeTieBreak(*manager->client()->doc()); + return false; + } + passed.append(std::make_tuple(app, transport, ce)); } @@ -1882,6 +1889,11 @@ int ErrorUtil::jingleCondition(const Stanza::Error &error) return UnknownError; } +Stanza::Error ErrorUtil::makeTieBreak(QDomDocument &doc) +{ + return make(doc, TieBreak, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::Conflict); +} + } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 619189bc..c03175a0 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -126,6 +126,7 @@ class ErrorUtil static const char* names[Last]; static XMPP::Stanza::Error make(QDomDocument &doc, int jingleCond, int type=XMPP::Stanza::Error::Cancel, int condition=XMPP::Stanza::Error::UndefinedCondition, const QString &text=QString()); + static XMPP::Stanza::Error makeTieBreak(QDomDocument &doc); static void fill(QDomDocument doc, XMPP::Stanza::Error &error, int jingleCond); static int jingleCondition(const XMPP::Stanza::Error &error); }; @@ -392,10 +393,12 @@ class Application : public QObject virtual ApplicationManagerPad::Ptr pad() const = 0; virtual State state() const = 0; virtual void setState(State state) = 0; // likely just remember the state and not generate any signals + virtual XMPP::Stanza::Error lastError() const = 0; virtual Origin creator() const = 0; virtual Origin senders() const = 0; virtual QString contentName() const = 0; + virtual Origin transportReplaceOrigin() const = 0; // returns Origin::None if no transport-replace in progress or the side triggered the replace. virtual SetDescError setDescription(const QDomElement &description) = 0; /** From 798897507305e6257e6aae4c9bdc5115ee00edb2 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 13 Jun 2019 01:22:17 +0300 Subject: [PATCH 063/383] transport fallback fixes --- src/xmpp/xmpp-im/jingle-ft.cpp | 8 ++++---- src/xmpp/xmpp-im/jingle.cpp | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 7d08fa2f..47ce1d99 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -713,7 +713,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() } if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content - if (!d->transport->hasUpdates()) { // failed to select next transport. can't continue + if (!d->transport->hasUpdates() && !d->transportReady) { // failed to select next transport. can't continue return OutgoingUpdate(); } @@ -783,11 +783,11 @@ bool Application::wantBetterTransport(const QSharedPointer &t) const bool Application::selectNextTransport() { while (d->availableTransports.size()) { - auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.first()); + auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.last()); if (t && setTransport(t)) { return true; } else { - d->availableTransports.removeFirst(); + d->availableTransports.removeLast(); } } return false; @@ -807,7 +807,7 @@ void Application::prepare() void Application::start() { if (d->transport) { - d->setState(State::Active); + d->setState(State::Connecting); d->transport->start(); } // TODO we need QIODevice somewhere here diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index f3c1c58e..5f6a657a 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1357,6 +1357,7 @@ Session::Session(Manager *manager, const Jid &peer, Origin role) : Session::~Session() { + qDeleteAll(d->contentList); qDebug("session %s destroyed", qPrintable(d->sid)); } From 95691650abfd4d80843cd78280663caa9c979689 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 13 Jun 2019 08:22:18 +0300 Subject: [PATCH 064/383] More jingle fallback fixes --- src/xmpp/xmpp-core/xmpp_stanza.cpp | 43 +++++++++--------------------- src/xmpp/xmpp-im/jingle.cpp | 10 ++++--- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index fd74c0cc..ca2f39c6 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -327,23 +327,22 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS) // type type = Private::stringToErrorType(e.attribute("type")); by = e.attribute(QLatin1String("by")); - - // condition - QDomNodeList nl = e.childNodes(); - QDomElement t; condition = -1; - int n; - for(n = 0; n < nl.count(); ++n) { - QDomNode i = nl.item(n); - t = i.toElement(); - if(!t.isNull()) { - // FIX-ME: this shouldn't be needed - if(t.namespaceURI() == NS_STANZAS || t.attribute("xmlns") == NS_STANZAS) { + + QString textTag(QString::fromLatin1("text")); + for (auto t = e.firstChildElement(); !t.isNull(); t = t.nextSiblingElement()) { + if(t.namespaceURI() == NS_STANZAS || t.attribute(QString::fromLatin1("xmlns")) == NS_STANZAS) { + if (t.tagName() == textTag) { + text = t.text().trimmed(); + } else { condition = Private::stringToErrorCond(t.tagName()); - if (condition != -1) - break; } + } else { + appSpec = t; } + + if (condition != -1 && !appSpec.isNull() && !text.isEmpty()) + break; } // code @@ -361,24 +360,6 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS) condition = guess.second != -1 ? guess.second : UndefinedCondition; } - // text - t = e.elementsByTagNameNS(NS_STANZAS, "text").item(0).toElement(); - if(!t.isNull()) - text = t.text().trimmed(); - else - text = e.text().trimmed(); - - // appspec: find first non-standard namespaced element - appSpec = QDomElement(); - nl = e.childNodes(); - for(n = 0; n < nl.count(); ++n) { - QDomNode i = nl.item(n); - if(i.isElement() && i.namespaceURI() != NS_STANZAS) { - appSpec = i.toElement(); - break; - } - } - return true; } diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 5f6a657a..0a5d82a5 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -687,7 +687,8 @@ class Session::Private } } else { lastError = jt->error(); - setSessionFinished(); + if (ErrorUtil::jingleCondition(lastError) != ErrorUtil::TieBreak) + setSessionFinished(); } }); waitingAck = true; @@ -1867,24 +1868,25 @@ const char* ErrorUtil::names[ErrorUtil::Last] = {"out-of-order","tie-break", "un Stanza::Error ErrorUtil::make(QDomDocument &doc, int jingleCond, int type, int condition, const QString &text) { - auto el = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond])); + auto el = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); return Stanza::Error(type, condition, text, el); } void ErrorUtil::fill(QDomDocument doc, Stanza::Error &error, int jingleCond) { - error.appSpec = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond])); + error.appSpec = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); } int ErrorUtil::jingleCondition(const Stanza::Error &error) { + //qDebug() << "tag" << error.appSpec.tagName() << "xmlns" << error.appSpec.attribute(QString::fromLatin1("xmlns")) << "ns" << error.appSpec.namespaceURI(); if (error.appSpec.attribute(QString::fromLatin1("xmlns")) != ERROR_NS) { return UnknownError; } QString tagName = error.appSpec.tagName(); for (int i = 0; i < int(sizeof(names) / sizeof(names[0])); ++i) { if (tagName == names[i]) { - return i; + return i + 1; } } return UnknownError; From b60d36853743b9ef73f709f3d8f7beea04a7bb59 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 13 Jun 2019 19:02:07 +0300 Subject: [PATCH 065/383] Another jingle transport fallback fix --- src/xmpp/xmpp-im/jingle-ft.cpp | 6 +++++- src/xmpp/xmpp-im/jingle-ibb.cpp | 9 +++++++-- src/xmpp/xmpp-im/jingle-s5b.cpp | 10 ++++++++-- src/xmpp/xmpp-im/jingle.cpp | 2 ++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 47ce1d99..342f74d6 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -626,6 +626,10 @@ Origin Application::transportReplaceOrigin() const bool Application::replaceTransport(const QSharedPointer &transport) { auto prev = d->transportFailedOrigin; + if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { + // if I'm a responder and tried to send transport-replace too, then push ns back + d->availableTransports.append(d->transport->pad()->ns()); + } d->transportFailedOrigin = d->pad->session()->peerRole(); auto ret = setTransport(transport); if (ret) @@ -665,8 +669,8 @@ Action Application::outgoingUpdateType() const } break; case State::Connecting: - case State::Active: case State::Pending: + case State::Active: if (d->transportFailedOrigin != Origin::None && (d->state == State::Active || !d->transport)) return Action::ContentRemove; diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index fce8e769..0ef725d4 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -190,8 +190,10 @@ Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &tra Transport::~Transport() { // we have to mark all of them as finished just in case they are captured somewhere else - for (auto &c: d->connections) { - c->finished = true; + if (d) { + for (auto &c: d->connections) { + c->finished = true; + } } } @@ -262,6 +264,9 @@ bool Transport::update(const QDomElement &transportEl) auto c = static_cast(sender()); d->handleConnected(d->connections.value(c->sid)); }); + } else { + qWarning("failed to create IBB connection"); + return false; } } else { if (bs_final < (*it)->_blockSize) { diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 5e303f7a..8cd76da8 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -211,13 +211,13 @@ class Candidate::Private : public QObject, public QSharedData { public: ~Private() { - if (server) { + if (server && transport) { server->unregisterKey(transport->directAddr()); } delete socksClient; } - Transport *transport; + QPointer transport; QString cid; QString host; Jid jid; @@ -1151,6 +1151,12 @@ Transport::~Transport() for (auto &c: d->remoteCandidates) { c.deleteSocksClient(); } + for (auto &c: d->remoteCandidates) { + auto srv = c.server(); + if (srv) { + srv.staticCast()->unregisterKey(d->directAddr); + } + } } } diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 0a5d82a5..1ce723d1 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -689,6 +689,8 @@ class Session::Private lastError = jt->error(); if (ErrorUtil::jingleCondition(lastError) != ErrorUtil::TieBreak) setSessionFinished(); + else + planStep(); } }); waitingAck = true; From 5bfaa569f2903e3604c1925e6931f7e940ae14fc Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 13 Jun 2019 20:38:57 +0300 Subject: [PATCH 066/383] valgrind fixes --- src/xmpp/xmpp-im/httpfileupload.cpp | 5 +++++ src/xmpp/xmpp-im/httpfileupload.h | 1 + src/xmpp/xmpp-im/jingle-ibb.h | 4 ++-- src/xmpp/xmpp-im/jingle-s5b.cpp | 14 +++++++------- src/xmpp/xmpp-im/jingle-s5b.h | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 67d93fc0..77a53620 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -427,6 +427,11 @@ HttpFileUploadManager::HttpFileUploadManager(Client *parent) : d->client = parent; } +HttpFileUploadManager::~HttpFileUploadManager() +{ + delete d; +} + void HttpFileUploadManager::setNetworkAccessManager(QNetworkAccessManager *qnam) { d->externalQnam = true; diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index 43298393..935ed0c6 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -149,6 +149,7 @@ class HttpFileUploadManager : public QObject typedef std::function Callback; // params: success, detail. where detail could be a "get" url HttpFileUploadManager(Client *parent); + ~HttpFileUploadManager(); /** * @brief setNetworkAccessManager sets network access manager to do http requests. diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 7486f476..e1383ecb 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -72,8 +72,8 @@ class Pad : public TransportManagerPad Connection::Ptr makeConnection(const QString &sid, size_t blockSize); private: - Manager *_manager; - Session *_session; + Manager *_manager = nullptr; + Session *_session = nullptr; }; class Manager : public TransportManager { diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 8cd76da8..6d3b505c 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -229,7 +229,7 @@ class Candidate::Private : public QObject, public QSharedData { QSharedPointer server; SocksClient *socksClient = nullptr; - void connectToHost(const QString &key, State successState, std::function callback, bool isUdp) + void connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp) { QHostAddress ha(host); if (!ha.isNull() && ha.protocol() == QAbstractSocket::IPv6Protocol && ha.scopeId().isEmpty() && @@ -264,12 +264,12 @@ class Candidate::Private : public QObject, public QSharedData { } else { socksClient = new SocksClient; qDebug() << "connect to host with cid=" << cid << ", key=" << key << " and socks client" << socksClient; - connect(socksClient, &SocksClient::connected, [this, callback, successState](){ + connect(socksClient, &SocksClient::connected, callbackContext, [this, callback, successState](){ state = successState; qDebug() << "socks client" << socksClient << "is connected"; callback(true); }); - connect(socksClient, &SocksClient::error, [this, callback](int error){ + connect(socksClient, &SocksClient::error, callbackContext, [this, callback](int error){ Q_UNUSED(error); state = Candidate::Discarded; qDebug() << "socks client" << socksClient << "failed to connect"; @@ -509,9 +509,9 @@ QDomElement Candidate::toXml(QDomDocument *doc) const return e; } -void Candidate::connectToHost(const QString &key, State successState, std::function callback, bool isUdp) +void Candidate::connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp) { - d->connectToHost(key, successState, callback, isUdp); + d->connectToHost(key, successState, callbackContext, callback, isUdp); } bool Candidate::incomingConnection(SocksClient *sc) @@ -778,7 +778,7 @@ class Transport::Private lastConnectionStart.start(); QString key = mnc.type() == Candidate::Proxy? dstaddr : directAddr; mnc.setState(Candidate::Probing); - mnc.connectToHost(key, Candidate::Pending, [this, mnc](bool success) { + mnc.connectToHost(key, Candidate::Pending, q, [this, mnc](bool success) { // candidate's status had to be changed by connectToHost, so we don't set it again if (success) { // let's reject candidates which are meaningless to try @@ -908,7 +908,7 @@ class Transport::Private if (c == localUsedCandidate) { // it's our side who proposed proxy. so we have to connect to it and activate auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); - c.connectToHost(key, Candidate::Accepted, [this](bool success){ + c.connectToHost(key, Candidate::Accepted, q, [this](bool success){ if (!success) { pendingActions |= Private::ProxyError; emit q->updated(); diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 8ecf0056..4c1b344c 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -107,7 +107,7 @@ class Candidate { QDomElement toXml(QDomDocument *doc) const; - void connectToHost(const QString &key, State successState, std::function callback, bool isUdp = false); + void connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp = false); bool incomingConnection(SocksClient *sc); SocksClient* takeSocksClient(); void deleteSocksClient(); From e8125a6f601103fa56b472251c79e6f3d7665301 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 14 Jun 2019 08:25:14 +0300 Subject: [PATCH 067/383] Started refactoring jingle transport updates api --- src/xmpp/xmpp-im/jingle-ft.cpp | 149 +++++++++++++++++++------------- src/xmpp/xmpp-im/jingle-ft.h | 8 +- src/xmpp/xmpp-im/jingle-ibb.cpp | 58 +++++++++---- src/xmpp/xmpp-im/jingle-ibb.h | 2 + src/xmpp/xmpp-im/jingle-s5b.cpp | 29 +++++-- src/xmpp/xmpp-im/jingle-s5b.h | 2 + src/xmpp/xmpp-im/jingle.cpp | 53 +++++++++--- src/xmpp/xmpp-im/jingle.h | 35 +++++++- 8 files changed, 236 insertions(+), 100 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 342f74d6..faf817df 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -382,6 +382,7 @@ class Application::Private public: Application *q = nullptr; State state = State::Created; + Action updateToSend = Action::NoAction; QSharedPointer pad; QString contentName; File file; @@ -623,7 +624,7 @@ Origin Application::transportReplaceOrigin() const return d->transportFailedOrigin; } -bool Application::replaceTransport(const QSharedPointer &transport) +bool Application::incomingTransportReplace(const QSharedPointer &transport) { auto prev = d->transportFailedOrigin; if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { @@ -647,80 +648,96 @@ QSharedPointer Application::transport() const return d->transport; } -Action Application::outgoingUpdateType() const +Action Application::evaluateOutgoingUpdate() { - if (d->waitTransportAccept && d->state < State::Finishing) - return Action::NoAction; + d->updateToSend = Action::NoAction; + if (!isValid() || d->state == State::Created || d->state == State::Finished || (d->waitTransportAccept && d->state < State::Finishing)) { + return d->updateToSend; + } switch (d->state) { case State::Created: break; case State::PrepareLocalOffer: if (d->transportFailedOrigin != Origin::None && !d->transport) - return Action::ContentReject; // case me=creator was already handled by this momemnt. see Transport::failed connectio above + d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt. see Transport::failed connectio above - if (d->transport->hasUpdates() || d->transportReady) { + else if (d->transport->hasUpdates() || d->transportReady) { d->transportReady = true; auto myRole = d->pad->session()->role(); - if (d->creator == myRole) { - return Action::ContentAdd; - } - return d->transportFailedOrigin == myRole? Action::TransportReplace : Action::ContentAccept; + if (d->creator == myRole) + d->updateToSend = Action::ContentAdd; + else + d->updateToSend = d->transportFailedOrigin == myRole? Action::TransportReplace : Action::ContentAccept; } break; case State::Connecting: case State::Pending: case State::Active: if (d->transportFailedOrigin != Origin::None && (d->state == State::Active || !d->transport)) - return Action::ContentRemove; + d->updateToSend = Action::ContentRemove; - if (d->transport->hasUpdates()) { - if (d->transportFailedOrigin != Origin::None) { - return Action::TransportReplace; - } - return Action::TransportInfo; + else if (d->transport->hasUpdates()) { + if (d->transportFailedOrigin != Origin::None) + d->updateToSend = d->transportFailedOrigin == d->pad->session()->role()? Action::TransportReplace : Action::TransportAccept; + else + d->updateToSend = Action::TransportInfo; } break; case State::Finishing: if (d->transportFailedOrigin != Origin::None) { - return Action::ContentRemove; + d->updateToSend = Action::ContentRemove; + } else { + d->updateToSend = Action::SessionInfo; } - return Action::SecurityInfo; + break; default: break; } - return Action::NoAction; // TODO + return d->updateToSend; // TODO } OutgoingUpdate Application::takeOutgoingUpdate() { - if (!isValid() || d->state == State::Created) { + if (d->updateToSend == Action::NoAction) { return OutgoingUpdate(); } - if (d->waitTransportAccept && d->state < State::Finishing) - return OutgoingUpdate(); - auto client = d->pad->session()->manager()->client(); auto doc = client->doc(); - // content-remove or content-reject - if (d->transportFailedOrigin != Origin::None && (d->state >= State::Active || !d->transport)) { - ContentBase cb(d->creator, d->contentName); - QList updates; - updates << cb.toXml(doc, "content"); - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); - return OutgoingUpdate{updates, [this](){ + if (d->updateToSend == Action::SessionInfo) { + if (d->state != State::Finishing) { + // TODO implement + return OutgoingUpdate(); + } + ContentBase cb(d->pad->session()->role(), d->contentName); + return OutgoingUpdate{QList() << cb.toXml(doc, "received"), [this](){ d->setState(State::Finished); } }; } - if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content - if (!d->transport->hasUpdates() && !d->transportReady) { // failed to select next transport. can't continue - return OutgoingUpdate(); - } + QDomElement transportEl; + OutgoingUpdateCB transportCB; + ContentBase cb(d->creator, d->contentName); + if (d->state == State::PrepareLocalOffer) + cb.senders = d->senders; + QList updates; + auto contentEl = cb.toXml(doc, "content"); + updates << contentEl; + + switch (d->updateToSend) { + case Action::ContentReject: + case Action::ContentRemove: + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); // do we have other reasons? + return OutgoingUpdate{updates, [this](){ + d->setState(State::Finished); + } + }; + case Action::ContentAdd: + case Action::ContentAccept: if (d->file.thumbnail().data.size()) { auto thumb = d->file.thumbnail(); auto bm = client->bobManager(); @@ -728,27 +745,41 @@ OutgoingUpdate Application::takeOutgoingUpdate() thumb.uri = QLatin1String("cid:") + data.cid(); d->file.setThumbnail(thumb); } - ContentBase cb(d->creator, d->contentName); - cb.senders = d->senders; - auto cel = cb.toXml(doc, "content"); - cel.appendChild(doc->createElementNS(NS, "description")).appendChild(d->file.toXml(doc)); - QDomElement tel; - OutgoingUpdateCB trCallback; - std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); - cel.appendChild(tel); - - if (d->transportFailedOrigin == d->pad->session()->role()) { - d->waitTransportAccept = true; - return OutgoingUpdate{QList()<createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); + if (d->transport->hasUpdates()) { + std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + } else { + transportEl = doc->createElementNS(d->transport->pad()->ns(), QString::fromLatin1("transport")); } + contentEl.appendChild(transportEl); d->setState(State::Unacked); - return OutgoingUpdate{QList()<setState(d->pad->session()->role() == Origin::Initiator? State::Pending : State::Connecting); }}; + case Action::TransportInfo: + Q_ASSERT(d->transport->hasUpdates()); + std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + contentEl.appendChild(transportEl); + return OutgoingUpdate{updates, transportCB}; + case Action::TransportReplace: + Q_ASSERT(d->transport->hasUpdates()); + std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + contentEl.appendChild(transportEl); + return OutgoingUpdate{updates, transportCB}; + } + + + if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content + + if (d->transportFailedOrigin == d->pad->session()->role()) { + d->waitTransportAccept = true; + return OutgoingUpdate{QList()<state == State::Connecting || d->state == State::Active || d->state == State::Pending) { if (d->transport->hasUpdates()) { // failed to select next transport. can't continue @@ -769,11 +800,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() } } if (d->state == State::Finishing) { - ContentBase cb(d->pad->session()->role(), d->contentName); - return OutgoingUpdate{QList() << cb.toXml(doc, "received"), [this](){ - d->setState(State::Finished); - } - }; + } return OutgoingUpdate(); // TODO } @@ -829,16 +856,20 @@ bool Application::accept(const QDomElement &el) return true; } -void Application::setTransportAccepted() +bool Application::incomingTransportAccept(const QSharedPointer &transport) { - d->waitTransportAccept = false; - d->transportFailedOrigin = Origin::None; - emit updated(); + if (d->transport->update(transport)) { + d->waitTransportAccept = false; + d->transportFailedOrigin = Origin::None; + emit updated(); + return true; + } + return false; } bool Application::isValid() const { - return d->file.isValid() && d->transport && d->contentName.size() > 0 && + return d->file.isValid() && d->contentName.size() > 0 && (d->senders == Origin::Initiator || d->senders == Origin::Responder); } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 495efe88..e21c417e 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -134,20 +134,22 @@ class Application : public XMPP::Jingle::Application bool setTransport(const QSharedPointer &transport) override; QSharedPointer transport() const override; - Action outgoingUpdateType() const override; + Action evaluateOutgoingUpdate() override; OutgoingUpdate takeOutgoingUpdate() override; bool wantBetterTransport(const QSharedPointer &) const override; bool selectNextTransport() override; void prepare() override; void start() override; bool accept(const QDomElement &el) override; - bool replaceTransport(const QSharedPointer &transport) override; - void setTransportAccepted() override; bool isValid() const; void setDevice(QIODevice *dev, bool closeOnFinish = true); +protected: + bool incomingTransportReplace(const QSharedPointer &transport) override; + bool incomingTransportAccept(const QSharedPointer &transport) override; + signals: void deviceRequested(quint64 offset, quint64 size); void progress(quint64 offset); diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 0ef725d4..012468ae 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -138,8 +138,10 @@ struct Transport::Private Pad::Ptr pad; QMap> connections; QList> readyConnections; + QSharedPointer lastOfferedConnection; size_t defaultBlockSize = 4096; bool started = false; + bool initialOfferSent = false; // if we ever sent anything void checkAndStartConnection(QSharedPointer &c) { @@ -159,6 +161,29 @@ struct Transport::Private emit q->connected(); } } + + OutgoingTransportInfoUpdate makeOffer(const QSharedPointer &connection) + { + OutgoingTransportInfoUpdate upd; + if (!connection) { + return upd; + } + + auto doc = pad->session()->manager()->client()->doc(); + + QDomElement tel = doc->createElementNS(NS, "transport"); + tel.setAttribute(QStringLiteral("sid"), connection->sid); + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->_blockSize)); + + upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { + if (started) + checkAndStartConnection(connection); + }}; + + lastOfferedConnection = connection; + connection->offerSent = true; + return upd; + } }; Transport::Transport(const TransportManagerPad::Ptr &pad) : @@ -282,6 +307,21 @@ bool Transport::update(const QDomElement &transportEl) return true; } + +bool Transport::isInitialOfferReady() const +{ + return isValid() && (hasUpdates() || d->initialOfferSent); +} + +OutgoingTransportInfoUpdate Transport::takeInitialOffer() +{ + auto upd = takeOutgoingUpdate(); + if (std::get<0>(upd).isNull() && d->lastOfferedConnection) { + return d->makeOffer(d->lastOfferedConnection); + } + return upd; +} + bool Transport::hasUpdates() const { for (auto &c: d->connections) { @@ -306,23 +346,7 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() break; } } - if (!connection) { - return upd; - } - - auto doc = d->pad->session()->manager()->client()->doc(); - - QDomElement tel = doc->createElementNS(NS, "transport"); - tel.setAttribute(QStringLiteral("sid"), connection->sid); - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->_blockSize)); - - upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { - if (d->started) - d->checkAndStartConnection(connection); - }}; - - connection->offerSent = true; - return upd; + return d->makeOffer(connection); } bool Transport::isValid() const diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index e1383ecb..7b2011df 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -42,6 +42,8 @@ class Transport : public XMPP::Jingle::Transport void prepare() override; void start() override; + bool isInitialOfferReady() const override; + OutgoingTransportInfoUpdate takeInitialOffer() override; bool update(const QDomElement &transportEl) override; bool hasUpdates() const override; OutgoingTransportInfoUpdate takeOutgoingUpdate() override; diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 6d3b505c..49cbe9a8 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -397,7 +397,7 @@ Candidate::Candidate(Transport *transport, const TcpPortServer::Ptr &server, con d->transport = transport; d->server = server.staticCast(); d->cid = cid; - d->host = server->publishHost(); + d->host = "192.168.0.44";//server->publishHost(); d->port = server->publishPort(); d->type = type; static const int priorities[] = {0, ProxyPreference, TunnelPreference, AssistedPreference, DirectPreference}; @@ -571,6 +571,7 @@ class Transport::Private Pad::Ptr pad; bool meCreator = true; // content created on local side bool transportStarted = false; // where start() was called + bool offerSent = false; bool waitingAck = true; bool aborted = false; bool remoteReportedCandidateError = false; @@ -1183,7 +1184,7 @@ void Transport::prepare() }); d->onLocalServerDiscovered(); - d->discoS5BProxy(); + //d->discoS5BProxy(); emit updated(); } @@ -1312,6 +1313,25 @@ bool Transport::update(const QDomElement &transportEl) return false; } + +bool Transport::isInitialOfferReady() const +{ + return isValid() && (d->pendingActions || d->offerSent); +} + +OutgoingTransportInfoUpdate Transport::takeInitialOffer() +{ + d->offerSent = true; + auto upd = takeOutgoingUpdate(); + auto tel = std::get<0>(upd); + if (d->meCreator && d->mode != Tcp) { + tel.setAttribute(QStringLiteral("mode"), "udp"); + } + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); + + return upd; +} + bool Transport::hasUpdates() const { return isValid() && d->pendingActions; @@ -1328,10 +1348,6 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() QDomElement tel = doc->createElementNS(NS, "transport"); tel.setAttribute(QStringLiteral("sid"), d->sid); - if (d->meCreator && d->mode != Tcp) { - tel.setAttribute(QStringLiteral("mode"), "udp"); - } - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); if (d->pendingActions & Private::NewCandidate) { d->pendingActions &= ~Private::NewCandidate; @@ -1623,3 +1639,4 @@ void Pad::registerSid(const QString &sid) } // namespace XMPP #include "jingle-s5b.moc" + diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 4c1b344c..80bfa28c 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -140,6 +140,8 @@ class Transport : public XMPP::Jingle::Transport void prepare() override; void start() override; bool update(const QDomElement &transportEl) override; + bool isInitialOfferReady() const override; + OutgoingTransportInfoUpdate takeInitialOffer() override; bool hasUpdates() const override; OutgoingTransportInfoUpdate takeOutgoingUpdate() override; bool isValid() const override; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 1ce723d1..f87a115e 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -751,7 +751,7 @@ class Session::Private */ Action expectedContentAction = role == Origin::Initiator? Action::ContentAdd : Action::ContentAccept; for (const auto &c: contentList) { - auto out = c->outgoingUpdateType(); + auto out = c->evaluateOutgoingUpdate(); if (out == Action::ContentReject) { // yeah we are rejecting local content. invalid? lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); setSessionFinished(); @@ -821,7 +821,7 @@ class Session::Private QMultiMap updates; for (auto app : signalingContent) { - Action updateType = app->outgoingUpdateType(); + Action updateType = app->evaluateOutgoingUpdate(); if (updateType != Action::NoAction) { updates.insert(updateType, app); } @@ -869,7 +869,7 @@ class Session::Private void addAndInitContent(Origin creator, Application *content) { contentList.insert(ContentKey{content->contentName(), creator}, content); - if (state != State::Created && content->outgoingUpdateType() != Action::NoAction) { + if (state != State::Created && content->evaluateOutgoingUpdate() != Action::NoAction) { signalingContent.insert(content); } QObject::connect(content, &Application::updated, q, [this, content](){ @@ -1245,7 +1245,10 @@ class Session::Private return false; } Application *app = contentList.value(ContentKey{cb.name, cb.creator}); - if (!app) continue; //wtf? + if (!app) { + toReject.append(ce); + continue; + } auto trPad = q->transportPadFactory(transportNS); if (!trPad) { @@ -1274,7 +1277,7 @@ class Session::Private QSharedPointer transport; QDomElement ce; std::tie(app,transport,ce) = v; - if (!app->replaceTransport(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet + if (!app->incomingTransportReplace(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet toReject.append(ce); } } @@ -1289,24 +1292,52 @@ class Session::Private bool handleIncomingTransportAccept(const QDomElement &jingleEl) { - QSet apps; + QList,QDomElement>> passed; + QList toReject; QString contentTag(QStringLiteral("content")); for(QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) { ContentBase cb(ce); - if (!cb.isValid()) { + auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); + QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } Application *app = contentList.value(ContentKey{cb.name, cb.creator}); - if (app) { - apps.insert(app); + if (!app || !app->transport() || app->transport()->pad()->ns() != transportNS || !app->incomingTransportAccept(transportEl)) { + toReject.append(ce); + continue; + } + + auto trPad = q->transportPadFactory(transportNS); + if (!trPad) { + toReject.append(ce); + continue; + } + + auto transport = trPad->manager()->newTransport(trPad, transportEl); + if (!transport) { + toReject.append(ce); + continue; } + + passed.append(std::make_tuple(app, transport, ce)); } - for (auto app: apps) { - app->setTransportAccepted(); + for (auto &v: passed) { + Application *app; + QSharedPointer transport; + QDomElement ce; + std::tie(app,transport,ce) = v; + if (!app->incomingTransportAccept(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet + toReject.append(ce); + } + } + + if (toReject.size()) { + outgoingUpdates.insert(Action::TransportReject, OutgoingUpdate{toReject,OutgoingUpdateCB()}); } planStep(); diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index c03175a0..3b78048f 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -366,7 +366,9 @@ class Transport : public QObject { // for remote transport try to connect to all proposed hosts in order their priority. // in-band transport may just emit updated() here virtual bool update(const QDomElement &el) = 0; // accepts transport element on incoming transport-info + virtual bool isInitialOfferReady() const = 0; virtual bool hasUpdates() const = 0; + virtual OutgoingTransportInfoUpdate takeInitialOffer() = 0; virtual OutgoingTransportInfoUpdate takeOutgoingUpdate() = 0; virtual bool isValid() const = 0; virtual Features features() const = 0; @@ -408,12 +410,28 @@ class Application : public QObject */ virtual bool setTransport(const QSharedPointer &transport) = 0; virtual QSharedPointer transport() const = 0; - virtual Action outgoingUpdateType() const = 0; - virtual OutgoingUpdate takeOutgoingUpdate() = 0; // this may return something only when outgoingUpdateType() != NoAction + + /** + * @brief evaluateOutgoingUpdate computes and prepares next update which will be taken with takeOutgoingUpdate + * The updated will be taked immediately if considered to be most preferred among other updates types of + * other applications. + * @return update type + */ + virtual Action evaluateOutgoingUpdate() = 0; + virtual OutgoingUpdate takeOutgoingUpdate() = 0; // this may return something only when evaluateOutgoingUpdate() != NoAction + + /** + * @brief wantBetterTransport checks if the transport is a better match for the application + * @return + */ virtual bool wantBetterTransport(const QSharedPointer &) const = 0; + + /** + * @brief selectNextTransport selects next transport from compatible transports list. + * The list is usually store in the application + * @return + */ virtual bool selectNextTransport() = 0; - virtual bool replaceTransport(const QSharedPointer &transport) = 0; - virtual void setTransportAccepted() = 0; /** * @brief prepare to send content-add/session-initiate @@ -423,6 +441,15 @@ class Application : public QObject virtual bool accept(const QDomElement &el) = 0; // remote accepted our content virtual void start() = 0; +protected: + /** + * @brief incomingTransportReplace it's jingle transport-replace + * @param transport + * @return + */ + virtual bool incomingTransportReplace(const QSharedPointer &transport) = 0; + virtual bool incomingTransportAccept(const QSharedPointer &transport) = 0; + signals: void updated(); // signal for session it has to send updates to remote. so it will follow with takeOutgoingUpdate() eventually void stateChanged(State); From 31d5194559ba7281b3938da54226dff1b84dfd38 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 14 Jun 2019 20:50:39 +0300 Subject: [PATCH 068/383] Continue jingle updates refactoring --- src/xmpp/xmpp-im/jingle-ft.cpp | 132 +++++++++++++++----------------- src/xmpp/xmpp-im/jingle-ft.h | 2 +- src/xmpp/xmpp-im/jingle-ibb.cpp | 2 +- src/xmpp/xmpp-im/jingle-s5b.cpp | 4 +- src/xmpp/xmpp-im/jingle.cpp | 38 ++------- src/xmpp/xmpp-im/jingle.h | 3 +- 6 files changed, 74 insertions(+), 107 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index faf817df..0a8ba1f6 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -382,6 +382,7 @@ class Application::Private public: Application *q = nullptr; State state = State::Created; + State transportReplaceState = State::Finished; Action updateToSend = Action::NoAction; QSharedPointer pad; QString contentName; @@ -389,14 +390,12 @@ class Application::Private File acceptFile; // as it comes with "accept" response Origin creator; Origin senders; - Origin transportFailedOrigin = Origin::None; + Origin transportReplaceOrigin = Origin::None; XMPP::Stanza::Error lastError; QSharedPointer transport; Connection::Ptr connection; QStringList availableTransports; - bool transportReady = false; // when prepare local offer finished for the transport bool closeDeviceOnFinish = true; - bool waitTransportAccept = false; QIODevice *device = nullptr; quint64 bytesLeft = 0; @@ -568,7 +567,8 @@ bool Application::setTransport(const QSharedPointer &transport) d->transport = transport; connect(transport.data(), &Transport::updated, this, &Application::updated); connect(transport.data(), &Transport::connected, this, [this](){ - d->transportFailedOrigin = Origin::None; + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; // not needed here probably d->connection = d->transport->connection(); connect(d->connection.data(), &Connection::readyRead, this, [this](){ if (!d->device) { @@ -595,8 +595,7 @@ bool Application::setTransport(const QSharedPointer &transport) }); connect(transport.data(), &Transport::failed, this, [this](){ - d->transportFailedOrigin = d->pad->session()->role(); - d->waitTransportAccept = false; + d->transportReplaceOrigin = d->pad->session()->role(); if (d->state >= State::Active) { emit updated(); // late failure are unhandled. just notify the remote return; @@ -609,7 +608,9 @@ bool Application::setTransport(const QSharedPointer &transport) } else { emit updated(); // we have to notify our peer about failure } - } // else transport will notify when ready + } else { + d->transportReplaceState = State::PrepareLocalOffer; + } }); if (d->state >= State::Unacked) { @@ -621,23 +622,24 @@ bool Application::setTransport(const QSharedPointer &transport) Origin Application::transportReplaceOrigin() const { - return d->transportFailedOrigin; + return d->transportReplaceOrigin; } bool Application::incomingTransportReplace(const QSharedPointer &transport) { - auto prev = d->transportFailedOrigin; + auto prev = d->transportReplaceOrigin; if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { // if I'm a responder and tried to send transport-replace too, then push ns back d->availableTransports.append(d->transport->pad()->ns()); } - d->transportFailedOrigin = d->pad->session()->peerRole(); + d->transportReplaceOrigin = d->pad->session()->peerRole(); auto ret = setTransport(transport); if (ret) - d->waitTransportAccept = false; + d->transportReplaceState = State::PrepareLocalOffer; else { - d->transportFailedOrigin = prev; + d->transportReplaceOrigin = prev; d->lastError.reset(); + // REVIEW We have to fail application here on tie-break or propose another transport } return ret; @@ -651,41 +653,53 @@ QSharedPointer Application::transport() const Action Application::evaluateOutgoingUpdate() { d->updateToSend = Action::NoAction; - if (!isValid() || d->state == State::Created || d->state == State::Finished || (d->waitTransportAccept && d->state < State::Finishing)) { + if (!isValid() || d->state == State::Created || d->state == State::Finished) { return d->updateToSend; } + auto evaluateTransportReplaceAction = [this]() { + if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) + return Action::NoAction; + + return d->transportReplaceOrigin == d->pad->session()->role()? Action::TransportReplace : Action::TransportAccept; + }; + switch (d->state) { case State::Created: break; case State::PrepareLocalOffer: - if (d->transportFailedOrigin != Origin::None && !d->transport) - d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt. see Transport::failed connectio above - - else if (d->transport->hasUpdates() || d->transportReady) { - d->transportReady = true; - auto myRole = d->pad->session()->role(); - if (d->creator == myRole) - d->updateToSend = Action::ContentAdd; - else - d->updateToSend = d->transportFailedOrigin == myRole? Action::TransportReplace : Action::ContentAccept; + if (d->transportReplaceOrigin != Origin::None) { + if (!d->transport) { + d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt in case of app.PrepareLocalOffer. see Transport::failed above + } + d->updateToSend = evaluateTransportReplaceAction(); + if (d->updateToSend == Action::TransportAccept) { + d->updateToSend = Action::ContentAccept; + } + return d->updateToSend; } + + if (d->transport->isInitialOfferReady()) + d->updateToSend = d->creator == d->pad->session()->role()? Action::ContentAdd : Action::ContentAccept; + break; case State::Connecting: case State::Pending: case State::Active: - if (d->transportFailedOrigin != Origin::None && (d->state == State::Active || !d->transport)) - d->updateToSend = Action::ContentRemove; - - else if (d->transport->hasUpdates()) { - if (d->transportFailedOrigin != Origin::None) - d->updateToSend = d->transportFailedOrigin == d->pad->session()->role()? Action::TransportReplace : Action::TransportAccept; + if (d->transportReplaceOrigin != Origin::None) { + if (d->state == State::Active || !d->transport) + d->updateToSend = Action::ContentRemove; else - d->updateToSend = Action::TransportInfo; + d->updateToSend = evaluateTransportReplaceAction(); + return d->updateToSend; } + + if (d->transport->hasUpdates()) + d->updateToSend = Action::TransportInfo; + break; case State::Finishing: - if (d->transportFailedOrigin != Origin::None) { + if (d->transportReplaceOrigin != Origin::None) { d->updateToSend = Action::ContentRemove; } else { d->updateToSend = Action::SessionInfo; @@ -731,13 +745,15 @@ OutgoingUpdate Application::takeOutgoingUpdate() switch (d->updateToSend) { case Action::ContentReject: case Action::ContentRemove: - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); // do we have other reasons? + if (d->transportReplaceOrigin != Origin::None) + updates << Reason(Reason::Condition::FailedTransport).toXml(doc); return OutgoingUpdate{updates, [this](){ d->setState(State::Finished); } }; case Action::ContentAdd: case Action::ContentAccept: + Q_ASSERT(d->transport->isInitialOfferReady()); if (d->file.thumbnail().data.size()) { auto thumb = d->file.thumbnail(); auto bm = client->bobManager(); @@ -766,42 +782,20 @@ OutgoingUpdate Application::takeOutgoingUpdate() contentEl.appendChild(transportEl); return OutgoingUpdate{updates, transportCB}; case Action::TransportReplace: - Q_ASSERT(d->transport->hasUpdates()); - std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + case Action::TransportAccept: + Q_ASSERT(d->transport->isInitialOfferReady()); + d->transportReplaceState = State::Unacked; + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); contentEl.appendChild(transportEl); - return OutgoingUpdate{updates, transportCB}; - } - - - if (d->state == State::PrepareLocalOffer) { // basically when we come to this function Created is possible only for outgoing content - - if (d->transportFailedOrigin == d->pad->session()->role()) { - d->waitTransportAccept = true; - return OutgoingUpdate{QList()<state == State::Connecting || d->state == State::Active || d->state == State::Pending) { - if (d->transport->hasUpdates()) { // failed to select next transport. can't continue - QDomElement tel; - OutgoingUpdateCB trCallback; - std::tie(tel, trCallback) = d->transport->takeOutgoingUpdate(); - if (tel.isNull()) { - qWarning("transport for content=%s reported it had updates but got null update", qPrintable(d->contentName)); - return OutgoingUpdate(); - } - ContentBase cb(d->creator, d->contentName); - auto cel = cb.toXml(doc, "content"); - cel.appendChild(tel); - if (d->transportFailedOrigin != Origin::None) { - d->waitTransportAccept = true; - } - return OutgoingUpdate{QList()<updateToSend; + return OutgoingUpdate{updates, [this,transportCB,action](){ + if (transportCB) { + transportCB(); + } + d->transportReplaceState = action == Action::TransportReplace? State::Pending : State::Finished; + }}; } - if (d->state == State::Finishing) { - } return OutgoingUpdate(); // TODO } @@ -856,11 +850,11 @@ bool Application::accept(const QDomElement &el) return true; } -bool Application::incomingTransportAccept(const QSharedPointer &transport) +bool Application::incomingTransportAccept(const QDomElement &transportEl) { - if (d->transport->update(transport)) { - d->waitTransportAccept = false; - d->transportFailedOrigin = Origin::None; + if (d->transport->update(transportEl)) { + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; emit updated(); return true; } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index e21c417e..32aa629a 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -148,7 +148,7 @@ class Application : public XMPP::Jingle::Application protected: bool incomingTransportReplace(const QSharedPointer &transport) override; - bool incomingTransportAccept(const QSharedPointer &transport) override; + bool incomingTransportAccept(const QDomElement &transportEl) override; signals: void deviceRequested(quint64 offset, quint64 size); diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 012468ae..3bf7d437 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -143,7 +143,7 @@ struct Transport::Private bool started = false; bool initialOfferSent = false; // if we ever sent anything - void checkAndStartConnection(QSharedPointer &c) + void checkAndStartConnection(const QSharedPointer &c) { if (!c->connection && !c->finished && c->offerReceived && c->offerSent && pad->session()->role() == Origin::Initiator) { auto con = pad->session()->manager()->client()->ibbManager()->createConnection(); diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 49cbe9a8..7c71aa16 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -397,7 +397,7 @@ Candidate::Candidate(Transport *transport, const TcpPortServer::Ptr &server, con d->transport = transport; d->server = server.staticCast(); d->cid = cid; - d->host = "192.168.0.44";//server->publishHost(); + d->host = server->publishHost(); d->port = server->publishPort(); d->type = type; static const int priorities[] = {0, ProxyPreference, TunnelPreference, AssistedPreference, DirectPreference}; @@ -1184,7 +1184,7 @@ void Transport::prepare() }); d->onLocalServerDiscovered(); - //d->discoS5BProxy(); + d->discoS5BProxy(); emit updated(); } diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index f87a115e..6a0d2d25 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1292,8 +1292,6 @@ class Session::Private bool handleIncomingTransportAccept(const QDomElement &jingleEl) { - QList,QDomElement>> passed; - QList toReject; QString contentTag(QStringLiteral("content")); for(QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) @@ -1307,39 +1305,11 @@ class Session::Private } Application *app = contentList.value(ContentKey{cb.name, cb.creator}); if (!app || !app->transport() || app->transport()->pad()->ns() != transportNS || !app->incomingTransportAccept(transportEl)) { - toReject.append(ce); - continue; - } - - auto trPad = q->transportPadFactory(transportNS); - if (!trPad) { - toReject.append(ce); - continue; - } - - auto transport = trPad->manager()->newTransport(trPad, transportEl); - if (!transport) { - toReject.append(ce); - continue; - } - - passed.append(std::make_tuple(app, transport, ce)); - } - - for (auto &v: passed) { - Application *app; - QSharedPointer transport; - QDomElement ce; - std::tie(app,transport,ce) = v; - if (!app->incomingTransportAccept(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet - toReject.append(ce); + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; } } - if (toReject.size()) { - outgoingUpdates.insert(Action::TransportReject, OutgoingUpdate{toReject,OutgoingUpdateCB()}); - } - planStep(); return true; } @@ -1539,6 +1509,10 @@ void Session::initiate() void Session::terminate(Reason::Condition cond, const QString &comment) { + if (d->role == Origin::Initiator && d->state == State::PrepareLocalOffer) { + d->setSessionFinished(); + return; + } d->state = State::Finishing; d->terminateReason = Reason(cond, comment); d->planStep(); diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 3b78048f..e8cbbd5f 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -441,14 +441,13 @@ class Application : public QObject virtual bool accept(const QDomElement &el) = 0; // remote accepted our content virtual void start() = 0; -protected: /** * @brief incomingTransportReplace it's jingle transport-replace * @param transport * @return */ virtual bool incomingTransportReplace(const QSharedPointer &transport) = 0; - virtual bool incomingTransportAccept(const QSharedPointer &transport) = 0; + virtual bool incomingTransportAccept(const QDomElement &transportEl) = 0; signals: void updated(); // signal for session it has to send updates to remote. so it will follow with takeOutgoingUpdate() eventually From 0a2e88fca09b531044a52d787e9840d6cb45d956 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 15 Jun 2019 11:36:01 +0300 Subject: [PATCH 069/383] Fixed jingle transport fallback --- src/xmpp/xmpp-im/client.cpp | 1 + src/xmpp/xmpp-im/jingle-ft.cpp | 23 ++++++++++++++---- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle-ibb.cpp | 3 ++- src/xmpp/xmpp-im/jingle-s5b.cpp | 41 ++++++++++++++++++++++----------- src/xmpp/xmpp-im/jingle.cpp | 17 ++++++++++++++ src/xmpp/xmpp-im/jingle.h | 4 ++++ src/xmpp/xmpp-im/xmpp_caps.cpp | 1 + 8 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index d1d7d786..4c9dd8a5 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -194,6 +194,7 @@ Client::~Client() delete d->ftman; delete d->ibbman; delete d->s5bman; + delete d->jingleManager; delete d->root; delete d; //fprintf(stderr, "\tClient::~Client\n"); diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 0a8ba1f6..00b0be66 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -337,6 +337,12 @@ Manager::Manager(QObject *parent): } +Manager::~Manager() +{ + if (jingleManager) + jingleManager->unregisterApp(NS); +} + void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { jingleManager = jm; @@ -762,11 +768,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() d->file.setThumbnail(thumb); } contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); - if (d->transport->hasUpdates()) { - std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); - } else { - transportEl = doc->createElementNS(d->transport->pad()->ns(), QString::fromLatin1("transport")); - } + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); contentEl.appendChild(transportEl); d->setState(State::Unacked); @@ -783,6 +785,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() return OutgoingUpdate{updates, transportCB}; case Action::TransportReplace: case Action::TransportAccept: + { Q_ASSERT(d->transport->isInitialOfferReady()); d->transportReplaceState = State::Unacked; std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); @@ -795,6 +798,9 @@ OutgoingUpdate Application::takeOutgoingUpdate() d->transportReplaceState = action == Action::TransportReplace? State::Pending : State::Finished; }}; } + default: + break; + } return OutgoingUpdate(); // TODO } @@ -852,9 +858,16 @@ bool Application::accept(const QDomElement &el) bool Application::incomingTransportAccept(const QDomElement &transportEl) { + if (d->transportReplaceOrigin != d->pad->session()->role()) { + d->lastError = ErrorUtil::makeOutOfOrder(*d->pad->doc()); + return false; + } if (d->transport->update(transportEl)) { d->transportReplaceOrigin = Origin::None; d->transportReplaceState = State::Finished; + if (d->state >= State::Connecting) { + d->transport->start(); + } emit updated(); return true; } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 32aa629a..246f10d2 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -164,6 +164,7 @@ class Manager : public XMPP::Jingle::ApplicationManager Q_OBJECT public: Manager(QObject *parent = nullptr); + ~Manager(); void setJingleManager(XMPP::Jingle::Manager *jm); Application *startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders); ApplicationManagerPad *pad(Session *session); // pad factory diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 3bf7d437..3383938d 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -405,7 +405,8 @@ Manager::Manager(QObject *parent) : Manager::~Manager() { - + if (d->jingleManager) + d->jingleManager->unregisterTransport(NS); } Transport::Features Manager::features() const diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 7c71aa16..897d8271 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1310,13 +1310,18 @@ bool Transport::update(const QDomElement &transportEl) return true; } - return false; + // Seems like we got an empty transport. It's still valid though. + QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); + + return true; } bool Transport::isInitialOfferReady() const { - return isValid() && (d->pendingActions || d->offerSent); + return isValid() && (d->pendingActions || d->offerSent || + (d->localCandidates.isEmpty() && !d->proxyDiscoveryInProgress && + !(d->disco && d->disco->inProgressPortTypes()))); } OutgoingTransportInfoUpdate Transport::takeInitialOffer() @@ -1324,6 +1329,7 @@ OutgoingTransportInfoUpdate Transport::takeInitialOffer() d->offerSent = true; auto upd = takeOutgoingUpdate(); auto tel = std::get<0>(upd); + if (d->meCreator && d->mode != Tcp) { tel.setAttribute(QStringLiteral("mode"), "udp"); } @@ -1449,6 +1455,11 @@ OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() } else { qWarning("Got ProxyError pending action but no local used candidate is not set"); } + } else { + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { + d->waitingAck = false; + }}; } return upd; // TODO @@ -1499,22 +1510,13 @@ Manager::Manager(QObject *parent) : TransportManager(parent), d(new Private) { - // ensure S5BManager is initialized - QTimer::singleShot(0, [this](){ - auto jt = d->jingleManager->client()->s5bManager()->jtPush(); - connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { - Q_UNUSED(from); - auto t = d->key2transport.value(dstaddr); - if (t) { - // TODO return t->incomingUDPSuccess(from); - } - }); - }); + } Manager::~Manager() { - d->jingleManager->unregisterTransport(NS); + if (d->jingleManager) + d->jingleManager->unregisterTransport(NS); } Transport::Features Manager::features() const @@ -1525,6 +1527,17 @@ Transport::Features Manager::features() const void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { d->jingleManager = jm; + // ensure S5BManager is initialized + QTimer::singleShot(0, [this](){ + auto jt = d->jingleManager->client()->s5bManager()->jtPush(); + connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { + Q_UNUSED(from); + auto t = d->key2transport.value(dstaddr); + if (t) { + // TODO return t->incomingUDPSuccess(from); + } + }); + }); } QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 6a0d2d25..a9c6c5a8 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1640,6 +1640,11 @@ QDomElement SessionManagerPad::takeOutgoingSessionInfoUpdate() return QDomElement(); } +QDomDocument *SessionManagerPad::doc() const +{ + return session()->manager()->client()->doc(); +} + //---------------------------------------------------------------------------- // Manager //---------------------------------------------------------------------------- @@ -1670,6 +1675,7 @@ class Manager::Private }; Manager::Manager(Client *client) : + QObject(client), d(new Private()) { d->client = client; @@ -1679,6 +1685,12 @@ Manager::Manager(Client *client) : Manager::~Manager() { + for (auto &m: d->transportManagers) { + m->setJingleManager(nullptr); + } + for (auto &m: d->applicationManagers) { + m->setJingleManager(nullptr); + } } Client *Manager::client() const @@ -1904,6 +1916,11 @@ Stanza::Error ErrorUtil::makeTieBreak(QDomDocument &doc) return make(doc, TieBreak, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::Conflict); } +Stanza::Error ErrorUtil::makeOutOfOrder(QDomDocument &doc) +{ + return make(doc, OutOfOrder, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); +} + } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index e8cbbd5f..907cc426 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -126,7 +126,10 @@ class ErrorUtil static const char* names[Last]; static XMPP::Stanza::Error make(QDomDocument &doc, int jingleCond, int type=XMPP::Stanza::Error::Cancel, int condition=XMPP::Stanza::Error::UndefinedCondition, const QString &text=QString()); + static XMPP::Stanza::Error makeTieBreak(QDomDocument &doc); + static XMPP::Stanza::Error makeOutOfOrder(QDomDocument &doc); + static void fill(QDomDocument doc, XMPP::Stanza::Error &error, int jingleCond); static int jingleCondition(const XMPP::Stanza::Error &error); }; @@ -246,6 +249,7 @@ class SessionManagerPad : public QObject virtual QDomElement takeOutgoingSessionInfoUpdate(); virtual QString ns() const = 0; virtual Session *session() const = 0; + QDomDocument* doc() const; }; class TransportManager; diff --git a/src/xmpp/xmpp-im/xmpp_caps.cpp b/src/xmpp/xmpp-im/xmpp_caps.cpp index 000ce489..324aea3b 100644 --- a/src/xmpp/xmpp-im/xmpp_caps.cpp +++ b/src/xmpp/xmpp-im/xmpp_caps.cpp @@ -220,6 +220,7 @@ DiscoItem CapsRegistry::disco(const QString &spec) const * \brief Default constructor. */ CapsManager::CapsManager(Client *client) : + QObject(client), client_(client), isEnabled_(true) {} From 75139f786b3eb76eed1eb9d1b2371e8ff7501c17 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 17 Jun 2019 01:02:15 +0300 Subject: [PATCH 070/383] Return empty mime or unrecognized images --- src/xmpp/xmpp-im/xmpp_vcard.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/xmpp_vcard.cpp b/src/xmpp/xmpp-im/xmpp_vcard.cpp index 19851e2c..07dcbadc 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.cpp +++ b/src/xmpp/xmpp-im/xmpp_vcard.cpp @@ -57,10 +57,7 @@ QString openedImage2type(QIODevice *dev) if ( format == QLatin1String("SVG") ) return QLatin1String("image/svg+xml"); - - qWarning() << QString("WARNING! VCard::image2type: unknown format = '%1'").arg(format.isNull() ? QString("UNKNOWN") : format); - - return QLatin1String("image/unknown"); + return QString(); } QString image2type(const QByteArray &ba) From a139986124b0f4a5a5140aad9098a4618afb9969 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 17 Jun 2019 08:28:08 +0300 Subject: [PATCH 071/383] Added httpupload progress signal --- src/xmpp/xmpp-im/httpfileupload.cpp | 1 + src/xmpp/xmpp-im/httpfileupload.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 77a53620..eec47938 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -210,6 +210,7 @@ void HttpFileUpload::tryNextServer() req.setRawHeader(h.name.toLatin1(), h.value.toLatin1()); } auto reply = d->qnam->put(req, d->sourceDevice); + connect(reply, &QNetworkReply::downloadProgress, this, &HttpFileUpload::progress); connect(reply, &QNetworkReply::finished, this, [this, reply](){ if (reply->error() == QNetworkReply::NoError) { done(State::Success); diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index 935ed0c6..53f6feeb 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -103,6 +103,7 @@ public slots: signals: void stateChanged(); void finished(); + void progress(qint64 bytesReceived, qint64 bytesTotal); private: enum State { None, GettingSlot, HttpRequest, Success, Error }; From 9953da16bb99d7e00f1315d00734ec1b751c05d9 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 17 Jun 2019 16:02:21 +0300 Subject: [PATCH 072/383] Return empty mime early if image data is empty --- src/xmpp/xmpp-im/xmpp_vcard.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xmpp/xmpp-im/xmpp_vcard.cpp b/src/xmpp/xmpp-im/xmpp_vcard.cpp index 07dcbadc..e1aaef7b 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.cpp +++ b/src/xmpp/xmpp-im/xmpp_vcard.cpp @@ -62,6 +62,8 @@ QString openedImage2type(QIODevice *dev) QString image2type(const QByteArray &ba) { + if (ba.isEmpty()) + return QString(); QBuffer buf; buf.setData(ba); buf.open(QIODevice::ReadOnly); From c79e360bed6de83bfa1f4d88f99f7fb1af6835bd Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 18 Jun 2019 12:56:46 +0300 Subject: [PATCH 073/383] drop timer on jingle manager removal --- src/xmpp/xmpp-im/jingle-s5b.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index 897d8271..e8a72f02 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -1527,8 +1527,12 @@ Transport::Features Manager::features() const void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { d->jingleManager = jm; + if (!jm) + return; // ensure S5BManager is initialized - QTimer::singleShot(0, [this](){ + QTimer::singleShot(0, this, [this](){ + if (!d->jingleManager) // unregistered that early? + return; auto jt = d->jingleManager->client()->s5bManager()->jtPush(); connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { Q_UNUSED(from); From 092f318b7c650d848eea71c11ad1dcaa1c0e5cb7 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 19 Jun 2019 08:12:46 +0300 Subject: [PATCH 074/383] Added SIMS classes --- src/xmpp/CMakeLists.txt | 2 + src/xmpp/xmpp-im/jingle-ft.cpp | 6 + src/xmpp/xmpp-im/jingle-ft.h | 2 +- src/xmpp/xmpp-im/types.cpp | 12 ++ src/xmpp/xmpp-im/xmpp_message.h | 5 + src/xmpp/xmpp-im/xmpp_reference.cpp | 183 ++++++++++++++++++++++++++++ src/xmpp/xmpp-im/xmpp_reference.h | 78 ++++++++++++ src/xmpp/xmpp.pri | 2 + 8 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 src/xmpp/xmpp-im/xmpp_reference.cpp create mode 100644 src/xmpp/xmpp-im/xmpp_reference.h diff --git a/src/xmpp/CMakeLists.txt b/src/xmpp/CMakeLists.txt index 1fbbc606..ef01da35 100644 --- a/src/xmpp/CMakeLists.txt +++ b/src/xmpp/CMakeLists.txt @@ -35,6 +35,7 @@ set(HEADERS xmpp-im/xmpp_liverosteritem.h xmpp-im/xmpp_message.h xmpp-im/xmpp_muc.h + xmpp-im/xmpp_reference.h xmpp-im/xmpp_pubsubitem.h xmpp-im/xmpp_pubsubretraction.h xmpp-im/xmpp_receipts.h @@ -117,6 +118,7 @@ set(SOURCES xmpp-im/xmpp_discoinfotask.cpp xmpp-im/xmpp_discoitem.cpp xmpp-im/xmpp_ibb.cpp + xmpp-im/xmpp_reference.cpp xmpp-im/xmpp_serverinfomanager.cpp xmpp-im/xmpp_subsets.cpp xmpp-im/xmpp_task.cpp diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 00b0be66..57f25880 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -74,6 +74,12 @@ File::~File() } +File &File::operator=(const File &other) +{ + d = other.d; + return *this; +} + File::File(const File &other) : d(other.d) { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 246f10d2..246a07f4 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -50,7 +50,7 @@ class File File(const File &other); File(const QDomElement &file); ~File(); - File& operator=(const File& other) = default; + File& operator=(const File& other); inline bool isValid() const { return d != nullptr; } QDomElement toXml(QDomDocument *doc) const; diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index ff1a972f..cdb2d072 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -25,6 +25,7 @@ #include "xmpp_xmlcommon.h" #include "xmpp_bitsofbinary.h" #include "xmpp_ibb.h" +#include "xmpp_reference.h" #include "xmpp_captcha.h" #include "protocol.h" #include "xmpp/blake2/blake2qt.h" @@ -1073,6 +1074,7 @@ class Message::Private : public QSharedData QString replaceId; QString originId; // XEP-0359 Message::StanzaId stanzaId; // XEP-0359 + Reference reference; // XEP-0732 }; #define MessageD() (d? d : (d = new Private)) @@ -1559,6 +1561,16 @@ void Message::setOriginId(const QString &id) MessageD()->originId = id; } +Reference Message::reference() const +{ + return d? d->reference: Reference(); +} + +void Message::setReference(const Reference &r) +{ + MessageD()->reference = r; +} + QString Message::invite() const { return d? d->invite: QString(); diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index 58fc7201..a933760b 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -26,6 +26,7 @@ #include "xmpp_address.h" #include "xmpp_rosterx.h" #include "xmpp_muc.h" +#include "xmpp_reference.h" #include @@ -213,6 +214,10 @@ namespace XMPP { QString originId() const; void setOriginId(const QString &id); + // XEP-0732 + Reference reference() const; + void setReference(const Reference &r); + // Obsolete invitation QString invite() const; void setInvite(const QString &s); diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp new file mode 100644 index 00000000..bcaf34d0 --- /dev/null +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -0,0 +1,183 @@ +/* + * xmpp_reference.h - XMPP References / XEP-0372 + * Copyright (C) 2019 Sergey Ilinykh + * + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#include "xmpp_reference.h" + +using namespace XMPP; + +#define D() (d? d:(d=new Private)) + +const QString XMPP::MEDIASHARING_NS(QStringLiteral("urn:xmpp:sims:1")); +const QString XMPP::REFERENCE_NS(QStringLiteral("urn:xmpp:reference:0")); + +class Reference::Private : public QSharedData +{ +public: + Reference::Type type; + QString uri; + QString anchor; + int begin = 0; + int end = 0; + MediaSharing mediaSharing; +}; + +Reference::Reference() +{ + +} + +Reference::Reference(Type type, const QString &uri) : + d(new Private) +{ + d->type = type; + d->uri = uri; +} + +Reference::~Reference() +{ + +} + +Reference::Reference(const Reference &other) : + d(other.d) +{ + +} + +Reference &Reference::operator=(const Reference &other) +{ + d = other.d; + return *this; +} + +Reference::Type Reference::type() const +{ + return d->type; +} + +const QString &Reference::uri() const +{ + return d->uri; +} + +void Reference::setRange(int begin, int end) +{ + D()->begin = begin; + d->end = end; +} + +int Reference::start() const +{ + return d->begin; +} + +int Reference::end() const +{ + return d->end; +} + +const QString &Reference::anchor() const +{ + return d->anchor; +} + +void Reference::setAnchor(const QString &anchor) +{ + D()->anchor = anchor; +} + +void Reference::setMediaSharing(const MediaSharing &ms) +{ + D()->mediaSharing = ms; +} + +const MediaSharing &Reference::mediaSharing() const +{ + return d->mediaSharing; +} + +bool Reference::fromXml(const QDomElement &e) +{ + QString type = e.attribute(QString::fromLatin1("type")); + QString uri = e.attribute(QString::fromLatin1("uri")); + QString begin = e.attribute(QString::fromLatin1("begin")); + QString end = e.attribute(QString::fromLatin1("end")); + QString anchor = e.attribute(QString::fromLatin1("anchor")); + + if (type.isEmpty() || uri.isEmpty()) { + return false; + } + + Type t; + if (type == QString::fromLatin1("data")) + t = Data; + else if (type == QString::fromLatin1("mention")) + t = Mention; + else + return false; + + int beginN, endN; + bool ok; + if (!begin.isEmpty() && !(beginN = begin.toInt(&ok),ok)) { + return false; + } + if (!end.isEmpty() && !(endN = end.toInt(&ok),ok)) { + return false; + } + + auto msEl = e.firstChildElement("media-sharing"); + MediaSharing ms; + if (msEl.attribute(QString::fromLatin1("xmlns")) == MEDIASHARING_NS) { + auto fileEl = msEl.firstChildElement("file"); + auto sourcesEl = msEl.firstChildElement("file"); + if (sourcesEl.isNull() || fileEl.isNull() || fileEl.attribute(QString::fromLatin1("xmlns")) != XMPP::Jingle::FileTransfer::NS) + return false; + + ms.file = XMPP::Jingle::FileTransfer::File(fileEl); + if (!ms.file.isValid()) + return false; + + + auto srcName = QString::fromLatin1("reference"); + for (auto el = msEl.firstChildElement(srcName); !el.isNull(); el = el.nextSiblingElement(srcName)) { + if (el.attribute(QString::fromLatin1("xmlns")) == REFERENCE_NS) { + Reference ref; + if (!ref.fromXml(el)) { + return false; + } + ms.sources.append(ref.uri()); + } + } + } + + D()->type = t; + d->uri = uri; + d->begin = beginN; + d->end = endN; + d->anchor = anchor; + d->mediaSharing = ms; + + return true; +} + +QDomElement Reference::toXml(QDomDocument *) const +{ + return QDomElement(); +} + diff --git a/src/xmpp/xmpp-im/xmpp_reference.h b/src/xmpp/xmpp-im/xmpp_reference.h new file mode 100644 index 00000000..bb1681d6 --- /dev/null +++ b/src/xmpp/xmpp-im/xmpp_reference.h @@ -0,0 +1,78 @@ +/* + * xmpp_reference.h - XMPP References / XEP-0372 + * Copyright (C) 2019 Sergey Ilinykh + * + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + * + */ + +#ifndef XMPPREFERENCE_H +#define XMPPREFERENCE_H + +#include +#include + +#include "jingle-ft.h" + +namespace XMPP +{ + extern const QString MEDIASHARING_NS; + extern const QString REFERENCE_NS; + + class MediaSharing + { + public: + Jingle::FileTransfer::File file; + QStringList sources; + }; + + class Reference + { + public: + enum Type : char { + + Mention, + Data + }; + + Reference(); + Reference(Type type, const QString &uri); + ~Reference(); + Reference(const Reference &other); + Reference &operator=(const Reference &other); + + bool isValid() const { return d != nullptr; } + Type type() const; + const QString &uri() const; + + void setRange(int start, int end); + int start() const; + int end() const; + + const QString &anchor() const; + void setAnchor(const QString &anchor); + + void setMediaSharing(const MediaSharing &); + const MediaSharing &mediaSharing() const; + + bool fromXml(const QDomElement &e); + QDomElement toXml(QDomDocument *) const; + + private: + class Private; + QSharedDataPointer d; + }; +} + +#endif diff --git a/src/xmpp/xmpp.pri b/src/xmpp/xmpp.pri index 8e9fd795..0ce51bf1 100644 --- a/src/xmpp/xmpp.pri +++ b/src/xmpp/xmpp.pri @@ -56,6 +56,7 @@ HEADERS += \ $$PWD/xmpp-im/xmpp_thumbs.h \ $$PWD/xmpp-im/xmpp_htmlelement.h \ $$PWD/xmpp-im/xmpp_muc.h \ + $$PWD/xmpp-im/xmpp_reference.h \ $$PWD/xmpp-im/xmpp_message.h \ $$PWD/xmpp-im/xmpp_pubsubitem.h \ $$PWD/xmpp-im/xmpp_resource.h \ @@ -109,6 +110,7 @@ SOURCES += \ $$PWD/xmpp-im/xmpp_bytestream.cpp \ $$PWD/xmpp-im/s5b.cpp \ $$PWD/xmpp-im/xmpp_ibb.cpp \ + $$PWD/xmpp-im/xmpp_reference.cpp \ $$PWD/xmpp-im/filetransfer.cpp \ $$PWD/xmpp-im/httpfileupload.cpp \ $$PWD/xmpp-im/xmpp_bitsofbinary.cpp \ From 70ee78248b1e8b3e703a9fc1691cc562dcbf0cf2 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 19 Jun 2019 08:30:22 +0300 Subject: [PATCH 075/383] Implement Reference::toXml --- src/xmpp/xmpp-im/xmpp_reference.cpp | 31 ++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp index bcaf34d0..cce8a09d 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.cpp +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -132,7 +132,7 @@ bool Reference::fromXml(const QDomElement &e) else return false; - int beginN, endN; + int beginN = -1, endN = -1; bool ok; if (!begin.isEmpty() && !(beginN = begin.toInt(&ok),ok)) { return false; @@ -176,8 +176,33 @@ bool Reference::fromXml(const QDomElement &e) return true; } -QDomElement Reference::toXml(QDomDocument *) const +QDomElement Reference::toXml(QDomDocument *doc) const { - return QDomElement(); + auto root = doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference")); + root.setAttribute(QString::fromLatin1("uri"), d->uri); + root.setAttribute(QString::fromLatin1("type"), QString(d->type == Reference::Mention? "mention": "data")); + + if (d->mediaSharing.file.isValid() && d->mediaSharing.sources.count()) { + auto msEl = doc->createElementNS(MEDIASHARING_NS, QString::fromLatin1("media-sharing")); + root.appendChild(msEl); + msEl.appendChild(d->mediaSharing.file.toXml(doc)); + auto sourcesEl = msEl.appendChild(doc->createElement(QString::fromLatin1("sources"))).toElement(); + for (auto const &s: d->mediaSharing.sources) { + auto sEl = sourcesEl.appendChild(doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference"))).toElement(); + sEl.setAttribute(QString::fromLatin1("uri"), s); + sEl.setAttribute(QString::fromLatin1("type"), QString::fromLatin1("data")); + } + } + + if (d->begin != -1) + root.setAttribute(QString::fromLatin1("begin"), d->begin); + + if (d->end != -1) + root.setAttribute(QString::fromLatin1("end"), d->end); + + if (!d->anchor.isEmpty()) + root.setAttribute(QString::fromLatin1("anchor"), d->anchor); + + return root; } From b73f4b5f2e4732425006b66c48fb477f414241df Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 19 Jun 2019 14:48:58 +0300 Subject: [PATCH 076/383] Send and parser references in message stanzas --- include/iris/xmpp_reference.h | 1 + src/xmpp/xmpp-im/types.cpp | 15 ++++++++++++++- src/xmpp/xmpp-im/xmpp_message.h | 2 +- src/xmpp/xmpp-im/xmpp_reference.cpp | 7 +++++-- 4 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 include/iris/xmpp_reference.h diff --git a/include/iris/xmpp_reference.h b/include/iris/xmpp_reference.h new file mode 100644 index 00000000..0dee0eae --- /dev/null +++ b/include/iris/xmpp_reference.h @@ -0,0 +1 @@ +#include "../../src/xmpp/xmpp-im/xmpp_reference.h" diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index cdb2d072..608be91d 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -29,6 +29,7 @@ #include "xmpp_captcha.h" #include "protocol.h" #include "xmpp/blake2/blake2qt.h" +#include "xmpp_reference.h" #define NS_XML "http://www.w3.org/XML/1998/namespace" namespace XMPP @@ -1074,7 +1075,7 @@ class Message::Private : public QSharedData QString replaceId; QString originId; // XEP-0359 Message::StanzaId stanzaId; // XEP-0359 - Reference reference; // XEP-0732 + Reference reference; // XEP-0385 and XEP-0372 }; #define MessageD() (d? d : (d = new Private)) @@ -1974,6 +1975,11 @@ Stanza Message::toStanza(Stream *stream) const s.appendChild(e); } + // XEP-0372 and XEP-0385 + if (d->reference.isValid()) { + s.appendChild(d->reference.toXml(&s.doc())); + } + return s; } @@ -2320,6 +2326,13 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf if (!t.isNull()) { d->replaceId = t.attribute("id"); } + + // XEP-0385 SIMS and XEP-0372 Reference + t = childElementsByTagNameNS(root, REFERENCE_NS, QString::fromLatin1("reference")).item(0).toElement(); + if (!t.isNull()) { + d->reference.fromXml(t); + } + return true; } diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index a933760b..29b44b9f 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -214,7 +214,7 @@ namespace XMPP { QString originId() const; void setOriginId(const QString &id); - // XEP-0732 + // XEP-0385 and XEP-0372 Reference reference() const; void setReference(const Reference &r); diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp index cce8a09d..e5e9a398 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.cpp +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -32,8 +32,8 @@ class Reference::Private : public QSharedData Reference::Type type; QString uri; QString anchor; - int begin = 0; - int end = 0; + int begin = -1; + int end = -1; MediaSharing mediaSharing; }; @@ -178,6 +178,9 @@ bool Reference::fromXml(const QDomElement &e) QDomElement Reference::toXml(QDomDocument *doc) const { + if (!d) { + return QDomElement(); + } auto root = doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference")); root.setAttribute(QString::fromLatin1("uri"), d->uri); root.setAttribute(QString::fromLatin1("type"), QString(d->type == Reference::Mention? "mention": "data")); From 9ace8411104f18b748b9f4deba50ed116937b7ec Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 19 Jun 2019 22:07:14 +0300 Subject: [PATCH 077/383] Create jingle file with namespace --- src/xmpp/xmpp-im/jingle-ft.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 57f25880..7535fe68 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -186,7 +186,7 @@ QDomElement File::toXml(QDomDocument *doc) const if (!isValid()) { return QDomElement(); } - QDomElement el = doc->createElement(QStringLiteral("file")); + QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); if (d->date.isValid()) { el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("date"), d->date.toString(Qt::ISODate))); } From 5b1e0ea9a445c11ab2abe35fdb31685425755d1c Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 20 Jun 2019 08:19:45 +0300 Subject: [PATCH 078/383] Allow multiple references in one message --- src/xmpp/xmpp-im/types.cpp | 28 ++++++++++++++++++---------- src/xmpp/xmpp-im/xmpp_message.h | 5 +++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index 608be91d..4e4f1bcc 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -1075,7 +1075,7 @@ class Message::Private : public QSharedData QString replaceId; QString originId; // XEP-0359 Message::StanzaId stanzaId; // XEP-0359 - Reference reference; // XEP-0385 and XEP-0372 + QList references; // XEP-0385 and XEP-0372 }; #define MessageD() (d? d : (d = new Private)) @@ -1562,14 +1562,19 @@ void Message::setOriginId(const QString &id) MessageD()->originId = id; } -Reference Message::reference() const +QList Message::references() const { - return d? d->reference: Reference(); + return d? d->references: QList(); } -void Message::setReference(const Reference &r) +void Message::addReference(const Reference &r) { - MessageD()->reference = r; + MessageD()->references.append(r); +} + +void Message::setReferences(const QList &r) +{ + MessageD()->references = r; } QString Message::invite() const @@ -1976,8 +1981,8 @@ Stanza Message::toStanza(Stream *stream) const } // XEP-0372 and XEP-0385 - if (d->reference.isValid()) { - s.appendChild(d->reference.toXml(&s.doc())); + for (auto const &r: d->references) { + s.appendChild(r.toXml(&s.doc())); } return s; @@ -2328,9 +2333,12 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf } // XEP-0385 SIMS and XEP-0372 Reference - t = childElementsByTagNameNS(root, REFERENCE_NS, QString::fromLatin1("reference")).item(0).toElement(); - if (!t.isNull()) { - d->reference.fromXml(t); + auto references = childElementsByTagNameNS(root, REFERENCE_NS, QString::fromLatin1("reference")); + for (int i = 0; i < references.size(); i++) { + Reference r; + if (r.fromXml(references.at(i).toElement())) { + d->references.append(r); + } } return true; diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index 29b44b9f..1c40fa5a 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -215,8 +215,9 @@ namespace XMPP { void setOriginId(const QString &id); // XEP-0385 and XEP-0372 - Reference reference() const; - void setReference(const Reference &r); + QList references() const; + void addReference(const Reference &r); + void setReferences(const QList &r); // Obsolete invitation QString invite() const; From a81e5fa07673daf6e57d4fb5ec8a50ca33839db1 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 23 Jun 2019 23:21:39 +0300 Subject: [PATCH 079/383] Added audio spectrum element to jingle file --- src/xmpp/xmpp-im/jingle-ft.cpp | 109 ++++++++++++++++++++++------ src/xmpp/xmpp-im/jingle-ft.h | 26 +++++-- src/xmpp/xmpp-im/xmpp_reference.cpp | 15 ++-- src/xmpp/xmpp-im/xmpp_reference.h | 6 +- 4 files changed, 120 insertions(+), 36 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 7535fe68..607dc350 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -29,7 +29,7 @@ namespace Jingle { namespace FileTransfer { const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); - +const QString SPECTRUM_NS = QStringLiteral("iris.psi-im.org/spectrum"); QDomElement Range::toXml(QDomDocument *doc) const { @@ -60,8 +60,9 @@ class File::Private : public QSharedData quint64 size = 0; Range range; bool rangeSupported = false; - Hash hash; + QList hashes; Thumbnail thumbnail; + File::Spectrum audioSpectrum; }; File::File() @@ -88,15 +89,16 @@ File::File(const File &other) : File::File(const QDomElement &file) { - QDateTime date; - QString mediaType; - QString name; - QString desc; - size_t size = 0; - bool rangeSupported = false; - Range range; - Hash hash; - Thumbnail thumbnail; + QDateTime date; + QString mediaType; + QString name; + QString desc; + size_t size = 0; + bool rangeSupported = false; + Range range; + QList hashes; + Thumbnail thumbnail; + Spectrum spectrum; bool ok; @@ -148,22 +150,43 @@ File::File(const QDomElement &file) } else if (ce.tagName() == QLatin1String("hash")) { if (ce.attribute(QStringLiteral("xmlns")) == QLatin1String(XMPP_HASH_NS)) { - hash = Hash(ce); - if (hash.type() == Hash::Type::Unknown) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { return; } + hashes.append(h); } } else if (ce.tagName() == QLatin1String("hash-used")) { if (ce.attribute(QStringLiteral("xmlns")) == QLatin1String(XMPP_HASH_NS)) { - hash = Hash(ce); - if (hash.type() == Hash::Type::Unknown) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { return; } + hashes.append(h); } } else if (ce.tagName() == QLatin1String("thumbnail")) { thumbnail = Thumbnail(ce); + } else if (ce.tagName() == QLatin1String("spectrum") && ce.attribute(QStringLiteral("xmlns")) == SPECTRUM_NS) { + QStringList spv = ce.text().split(','); + spectrum.bars.reserve(spv.count()); + std::transform(spv.begin(), spv.end(), std::back_inserter(spectrum.bars), [](const QString &v){ return v.toUInt(); }); + auto c = ce.attribute(QStringLiteral("coding")).toLatin1(); + if (c == "u8") + spectrum.coding = File::Spectrum::Coding::U8; + else if (c == "s8") + spectrum.coding = File::Spectrum::Coding::S8; + else if (c == "u16") + spectrum.coding = File::Spectrum::Coding::U16; + else if (c == "s16") + spectrum.coding = File::Spectrum::Coding::S16; + else if (c == "u32") + spectrum.coding = File::Spectrum::Coding::U32; + else if (c == "s32") + spectrum.coding = File::Spectrum::Coding::S32; + else + spectrum.bars.clear(); // drop invalid spectrum } } @@ -175,15 +198,16 @@ File::File(const QDomElement &file) p->size = size; p->rangeSupported = rangeSupported; p->range = range; - p->hash = hash; + p->hashes = hashes; p->thumbnail = thumbnail; + p->audioSpectrum = spectrum; d = p; } QDomElement File::toXml(QDomDocument *doc) const { - if (!isValid()) { + if (!isValid() || d->hashes.isEmpty()) { return QDomElement(); } QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); @@ -193,8 +217,8 @@ QDomElement File::toXml(QDomDocument *doc) const if (d->desc.size()) { el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("desc"), d->desc)); } - if (d->hash.isValid()) { - el.appendChild(d->hash.toXml(doc)); + for (const auto &h: d->hashes) { + el.appendChild(h.toXml(doc)); } if (d->mediaType.size()) { el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("media-type"), d->mediaType)); @@ -211,9 +235,34 @@ QDomElement File::toXml(QDomDocument *doc) const if (d->thumbnail.isValid()) { el.appendChild(d->thumbnail.toXml(doc)); } + if (d->audioSpectrum.bars.count()) { + auto sel = el.appendChild(doc->createElementNS(SPECTRUM_NS, QString::fromLatin1("spectrum"))).toElement(); + const char* s[] = {"u8","s8","u16","s16","u32","s32"}; + sel.setAttribute(QString::fromLatin1("coding"), QString::fromLatin1(s[d->audioSpectrum.coding])); + QStringList sl; + std::transform(d->audioSpectrum.bars.begin(), d->audioSpectrum.bars.end(), std::back_inserter(sl), + [](quint32 v){ return QString::number(v); }); + sel.appendChild(doc->createTextNode(sl.join(','))); + } return el; } +bool File::merge(const File &other) +{ + if (!d->thumbnail.isValid()) { + d->thumbnail = other.thumbnail(); + } + for (auto const &h: other.d->hashes) { + auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v){ return h.type() == v.type(); }); + if (it == d->hashes.constEnd()) { + d->hashes.append(h); + } else if (h.data() != it->data()) { + return false; // hashes are different + } + } + return true; +} + QDateTime File::date() const { return d? d->date : QDateTime(); @@ -224,9 +273,18 @@ QString File::description() const return d? d->desc : QString(); } -Hash File::hash() const +Hash File::hash(Hash::Type t) const { - return d? d->hash : Hash(); + if (d && d->hashes.count()) { + if (t == Hash::Unknown) + return d->hashes.at(0); + for (auto const &h: d->hashes) { + if (h.type() == t) { + return h; + } + } + } + return Hash(); } QString File::mediaType() const @@ -254,6 +312,11 @@ Thumbnail File::thumbnail() const return d? d->thumbnail: Thumbnail(); } +File::Spectrum File::audioSpectrum() const +{ + return d? d->audioSpectrum: Spectrum(); +} + void File::setDate(const QDateTime &date) { ensureD()->date = date; @@ -264,9 +327,9 @@ void File::setDescription(const QString &desc) ensureD()->desc = desc; } -void File::setHash(const Hash &hash) +void File::addHash(const Hash &hash) { - ensureD()->hash = hash; + ensureD()->hashes.append(hash); } void File::setMediaType(const QString &mediaType) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 246a07f4..4f056320 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -46,6 +46,18 @@ struct Range { class File { public: + struct Spectrum + { + enum Coding { + U8, S8, + U16, S16, + U32, S32 + }; + + Coding coding; + QList bars; + }; + File(); File(const File &other); File(const QDomElement &file); @@ -53,19 +65,21 @@ class File File& operator=(const File& other); inline bool isValid() const { return d != nullptr; } QDomElement toXml(QDomDocument *doc) const; + bool merge(const File &other); QDateTime date() const; - QString description() const; - Hash hash() const; - QString mediaType() const; - QString name() const; - quint64 size() const; + QString description() const; + Hash hash(Hash::Type t = Hash::Unknown) const; + QString mediaType() const; + QString name() const; + quint64 size() const; Range range() const; Thumbnail thumbnail() const; + Spectrum audioSpectrum() const; void setDate(const QDateTime &date); void setDescription(const QString &desc); - void setHash(const Hash &hash); + void addHash(const Hash &hash); void setMediaType(const QString &mediaType); void setName(const QString &name); void setSize(quint64 size); diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp index e5e9a398..3194a4f2 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.cpp +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -82,7 +82,7 @@ void Reference::setRange(int begin, int end) d->end = end; } -int Reference::start() const +int Reference::begin() const { return d->begin; } @@ -134,12 +134,17 @@ bool Reference::fromXml(const QDomElement &e) int beginN = -1, endN = -1; bool ok; - if (!begin.isEmpty() && !(beginN = begin.toInt(&ok),ok)) { + if (!begin.isEmpty() && !(beginN = begin.toInt(&ok),ok)) return false; - } - if (!end.isEmpty() && !(endN = end.toInt(&ok),ok)) { + + if (!end.isEmpty() && !(endN = end.toInt(&ok),ok)) + return false; + + if (beginN >= 0 && endN >= 0 && endN < beginN) + return false; + + if ((endN >= 0 && beginN == -1) || (endN == -1 && beginN >= 0)) return false; - } auto msEl = e.firstChildElement("media-sharing"); MediaSharing ms; diff --git a/src/xmpp/xmpp-im/xmpp_reference.h b/src/xmpp/xmpp-im/xmpp_reference.h index bb1681d6..d19b5316 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.h +++ b/src/xmpp/xmpp-im/xmpp_reference.h @@ -35,6 +35,8 @@ namespace XMPP public: Jingle::FileTransfer::File file; QStringList sources; + + inline bool isValid() const { return file.isValid(); } }; class Reference @@ -56,8 +58,8 @@ namespace XMPP Type type() const; const QString &uri() const; - void setRange(int start, int end); - int start() const; + void setRange(int begin, int end); + int begin() const; int end() const; const QString &anchor() const; From 6af64e550011f8d3f6a9fb5446de23f85d893b1e Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 25 Jun 2019 08:14:34 +0300 Subject: [PATCH 080/383] Consider coding while converting spectrum to xml --- src/xmpp/xmpp-im/jingle-ft.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 607dc350..c0b266e7 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -241,7 +241,17 @@ QDomElement File::toXml(QDomDocument *doc) const sel.setAttribute(QString::fromLatin1("coding"), QString::fromLatin1(s[d->audioSpectrum.coding])); QStringList sl; std::transform(d->audioSpectrum.bars.begin(), d->audioSpectrum.bars.end(), std::back_inserter(sl), - [](quint32 v){ return QString::number(v); }); + [this](quint32 v){ + switch (d->audioSpectrum.coding) { + case Spectrum::U8: return QString::number(quint8(v)); + case Spectrum::S8: return QString::number(qint8(v)); + case Spectrum::U16: return QString::number(quint16(v)); + case Spectrum::S16: return QString::number(qint16(v)); + case Spectrum::U32: return QString::number(quint32(v)); + case Spectrum::S32: return QString::number(qint32(v)); + } + return QString(); + }); sel.appendChild(doc->createTextNode(sl.join(','))); } return el; From 48b10763a4eeb191e18bde397c25d8318bc92a3b Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 27 Jun 2019 11:39:43 +0300 Subject: [PATCH 081/383] SIMS related fixes --- src/xmpp/xmpp-im/jingle-ft.cpp | 19 +++++++++++++++---- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/types.cpp | 6 ++++-- src/xmpp/xmpp-im/xmpp_hash.h | 3 ++- src/xmpp/xmpp-im/xmpp_reference.cpp | 15 ++++++++------- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index c0b266e7..5a41f13c 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -137,7 +137,7 @@ File::File(const QDomElement &file) } } QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); - if (hashEl.attribute(QStringLiteral("xmlns")) == QLatin1String("urn:xmpp:hashes:2")) { + if (hashEl.attribute(QStringLiteral("xmlns")) == HASH_NS || hashEl.namespaceURI() == HASH_NS) { range.hash = Hash(hashEl); if (range.hash.type() == Hash::Type::Unknown) { return; @@ -149,7 +149,7 @@ File::File(const QDomElement &file) desc = ce.text(); } else if (ce.tagName() == QLatin1String("hash")) { - if (ce.attribute(QStringLiteral("xmlns")) == QLatin1String(XMPP_HASH_NS)) { + if (ce.attribute(QStringLiteral("xmlns")) == HASH_NS || ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -158,7 +158,7 @@ File::File(const QDomElement &file) } } else if (ce.tagName() == QLatin1String("hash-used")) { - if (ce.attribute(QStringLiteral("xmlns")) == QLatin1String(XMPP_HASH_NS)) { + if (ce.attribute(QStringLiteral("xmlns")) == HASH_NS || ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -168,7 +168,7 @@ File::File(const QDomElement &file) } else if (ce.tagName() == QLatin1String("thumbnail")) { thumbnail = Thumbnail(ce); - } else if (ce.tagName() == QLatin1String("spectrum") && ce.attribute(QStringLiteral("xmlns")) == SPECTRUM_NS) { + } else if (ce.tagName() == QLatin1String("spectrum") && (ce.attribute(QStringLiteral("xmlns")) == SPECTRUM_NS || ce.namespaceURI() == SPECTRUM_NS)) { QStringList spv = ce.text().split(','); spectrum.bars.reserve(spv.count()); std::transform(spv.begin(), spv.end(), std::back_inserter(spectrum.bars), [](const QString &v){ return v.toUInt(); }); @@ -273,6 +273,17 @@ bool File::merge(const File &other) return true; } +bool File::hasComputedHashes() const +{ + if (!d) + return false; + for (auto const &h: d->hashes) { + if (h.data().size()) + return true; + } + return false; +} + QDateTime File::date() const { return d? d->date : QDateTime(); diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 4f056320..0619a594 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -66,6 +66,7 @@ class File inline bool isValid() const { return d != nullptr; } QDomElement toXml(QDomDocument *doc) const; bool merge(const File &other); + bool hasComputedHashes() const; QDateTime date() const; QString description() const; diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index 4e4f1bcc..1eb677f5 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -35,6 +35,7 @@ namespace XMPP { +QString HASH_NS = QStringLiteral("urn:xmpp:hashes:2"); //---------------------------------------------------------------------------- // Url //---------------------------------------------------------------------------- @@ -391,7 +392,7 @@ QDomElement Hash::toXml(QDomDocument *doc) const if (v_type != Type::Unknown) { for(size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { if(v_type == hashTypes[n].hashType) { - auto el = doc->createElementNS(XMPP_HASH_NS, QLatin1String(v_data.isEmpty()? "hash-used": "hash")); + auto el = doc->createElementNS(HASH_NS, QLatin1String(v_data.isEmpty()? "hash-used": "hash")); el.setAttribute(QLatin1String("algo"), QLatin1String(hashTypes[n].text)); if (!v_data.isEmpty()) { XMLHelper::setTagText(el, v_data.toBase64()); @@ -3740,7 +3741,8 @@ const Jid &CaptchaChallenge::arbiter() const Thumbnail::Thumbnail(const QDomElement &el) { - if(el.attribute("xmlns") == QLatin1String(XMPP_THUMBS_NS)) { + QString ns(QLatin1String(XMPP_THUMBS_NS)); + if(el.attribute("xmlns") == ns || el.namespaceURI() == ns) { uri = QUrl(el.attribute("uri"), QUrl::StrictMode); mimeType = el.attribute("mime-type"); width = el.attribute("width").toUInt(); diff --git a/src/xmpp/xmpp-im/xmpp_hash.h b/src/xmpp/xmpp-im/xmpp_hash.h index df6ddfb4..e61d7ed2 100644 --- a/src/xmpp/xmpp-im/xmpp_hash.h +++ b/src/xmpp/xmpp-im/xmpp_hash.h @@ -23,17 +23,18 @@ #include #include -#define XMPP_HASH_NS "urn:xmpp:hashes:2" // TODO make nsdb.cpp/h with static declarations of all ns class QDomElement; namespace XMPP { + extern QString HASH_NS; class Features; class Hash { public: + enum Type { // XEP-0300 Version 0.5.3 (2018-02-14) Unknown, // not standard, just a default Sha1, // SHOULD NOT diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp index 3194a4f2..d610b8b3 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.cpp +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -148,20 +148,19 @@ bool Reference::fromXml(const QDomElement &e) auto msEl = e.firstChildElement("media-sharing"); MediaSharing ms; - if (msEl.attribute(QString::fromLatin1("xmlns")) == MEDIASHARING_NS) { + if (msEl.namespaceURI() == MEDIASHARING_NS) { auto fileEl = msEl.firstChildElement("file"); - auto sourcesEl = msEl.firstChildElement("file"); - if (sourcesEl.isNull() || fileEl.isNull() || fileEl.attribute(QString::fromLatin1("xmlns")) != XMPP::Jingle::FileTransfer::NS) + auto sourcesEl = msEl.firstChildElement("sources"); + if (sourcesEl.isNull() || fileEl.isNull() || fileEl.namespaceURI() != XMPP::Jingle::FileTransfer::NS) return false; ms.file = XMPP::Jingle::FileTransfer::File(fileEl); - if (!ms.file.isValid()) + if (!ms.file.isValid() || !ms.file.hasComputedHashes()) return false; - auto srcName = QString::fromLatin1("reference"); - for (auto el = msEl.firstChildElement(srcName); !el.isNull(); el = el.nextSiblingElement(srcName)) { - if (el.attribute(QString::fromLatin1("xmlns")) == REFERENCE_NS) { + for (auto el = sourcesEl.firstChildElement(srcName); !el.isNull(); el = el.nextSiblingElement(srcName)) { + if (el.namespaceURI() == REFERENCE_NS) { Reference ref; if (!ref.fromXml(el)) { return false; @@ -169,6 +168,8 @@ bool Reference::fromXml(const QDomElement &e) ms.sources.append(ref.uri()); } } + if (ms.sources.isEmpty()) + return false; } D()->type = t; From 6dd3c8906c17ec1a2e57137869d681a72897b718 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 28 Jun 2019 08:05:42 +0300 Subject: [PATCH 082/383] Drop xmlns attribute usage in favor of namespaceURI --- src/xmpp/xmpp-core/protocol.cpp | 14 +-- src/xmpp/xmpp-core/stream.cpp | 3 +- src/xmpp/xmpp-core/xmpp_stanza.cpp | 6 +- src/xmpp/xmpp-im/client.cpp | 6 +- src/xmpp/xmpp-im/filetransfer.cpp | 32 +++--- src/xmpp/xmpp-im/httpfileupload.cpp | 18 +++- src/xmpp/xmpp-im/jingle-ft.cpp | 8 +- src/xmpp/xmpp-im/jingle.cpp | 26 +++-- src/xmpp/xmpp-im/s5b.cpp | 32 +++--- src/xmpp/xmpp-im/types.cpp | 6 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 3 +- src/xmpp/xmpp-im/xmpp_discoinfotask.cpp | 3 +- src/xmpp/xmpp-im/xmpp_discoitem.cpp | 2 +- src/xmpp/xmpp-im/xmpp_ibb.cpp | 15 ++- src/xmpp/xmpp-im/xmpp_subsets.cpp | 7 +- src/xmpp/xmpp-im/xmpp_tasks.cpp | 132 +++++++++--------------- src/xmpp/xmpp-im/xmpp_vcard.cpp | 3 +- src/xmpp/xmpp-im/xmpp_xdata.cpp | 5 +- src/xmpp/xmpp-im/xmpp_xmlcommon.cpp | 20 +++- src/xmpp/xmpp-im/xmpp_xmlcommon.h | 1 + 20 files changed, 151 insertions(+), 191 deletions(-) diff --git a/src/xmpp/xmpp-core/protocol.cpp b/src/xmpp/xmpp-core/protocol.cpp index 42553ec1..c98b595e 100644 --- a/src/xmpp/xmpp-core/protocol.cpp +++ b/src/xmpp/xmpp-core/protocol.cpp @@ -426,24 +426,24 @@ QDomElement BasicProtocol::docElement() // HACK: using attributes seems to be the only way to get additional namespaces in here if(!defns.isEmpty()) - e.setAttribute("xmlns", defns); + e.setAttribute(QString::fromLatin1("xmlns"), defns); for(QStringList::ConstIterator it = list.begin(); it != list.end();) { QString prefix = *(it++); QString uri = *(it++); - e.setAttribute(QString("xmlns:") + prefix, uri); + e.setAttribute(QString::fromLatin1("xmlns:") + prefix, uri); } // additional attributes if(!isIncoming() && !to.isEmpty()) - e.setAttribute("to", to); + e.setAttribute(QString::fromLatin1("to"), to); if(isIncoming() && !from.isEmpty()) - e.setAttribute("from", from); + e.setAttribute(QString::fromLatin1("from"), from); if(!id.isEmpty()) - e.setAttribute("id", id); + e.setAttribute(QString::fromLatin1("id"), id); if(!lang.isEmpty()) - e.setAttributeNS(NS_XML, "xml:lang", lang); + e.setAttributeNS(QString::fromLatin1(NS_XML), QString::fromLatin1("xml:lang"), lang); if(version.major > 0 || version.minor > 0) - e.setAttribute("version", QString::number(version.major) + '.' + QString::number(version.minor)); + e.setAttribute(QString::fromLatin1("version"), QString::number(version.major) + '.' + QString::number(version.minor)); return e; } diff --git a/src/xmpp/xmpp-core/stream.cpp b/src/xmpp/xmpp-core/stream.cpp index 8285055b..bec855e2 100644 --- a/src/xmpp/xmpp-core/stream.cpp +++ b/src/xmpp/xmpp-core/stream.cpp @@ -430,8 +430,7 @@ void ClientStream::continueAfterParams() d->sasl->continueAfterParams(); } } else if (d->state == AuthAbort) { - auto e = doc().createElement("abort"); // FIXME it's kind of wrong to forge xml here - e.setAttribute("xmlns", NS_SASL); + auto e = doc().createElementNS(NS_SASL, "abort"); d->client.sendStanza(e); processNext(); } diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index ca2f39c6..d283541c 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -331,7 +331,7 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS) QString textTag(QString::fromLatin1("text")); for (auto t = e.firstChildElement(); !t.isNull(); t = t.nextSiblingElement()) { - if(t.namespaceURI() == NS_STANZAS || t.attribute(QString::fromLatin1("xmlns")) == NS_STANZAS) { + if(t.namespaceURI() == NS_STANZAS) { if (t.tagName() == textTag) { text = t.text().trimmed(); } else { @@ -389,7 +389,7 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const errElem.setAttribute("by", by); } errElem.appendChild(t = doc.createElementNS(NS_STANZAS, scond)); - t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed + //t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed // old code int scode = code(); @@ -399,7 +399,7 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const // text if(!text.isEmpty()) { t = doc.createElementNS(NS_STANZAS, "text"); - t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed + //t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed t.appendChild(doc.createTextNode(text)); errElem.appendChild(t); } diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index 4c9dd8a5..6033a505 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -580,7 +580,7 @@ void Client::streamReadyRead() debug(QString("Client: incoming: [\n%1]\n").arg(out)); emit xmlIncoming(out); - QDomElement x = oldStyleNS(s.element()); + QDomElement x = s.element();//oldStyleNS(s.element()); distribute(x); } } @@ -664,8 +664,8 @@ void Client::distribute(const QDomElement &x) error.setAttribute("type","cancel"); reply.appendChild(error); - QDomElement error_type = doc()->createElement("feature-not-implemented"); - error_type.setAttribute("xmlns","urn:ietf:params:xml:ns:xmpp-stanzas"); + QDomElement error_type = doc()->createElementNS(QLatin1String("urn:ietf:params:xml:ns:xmpp-stanzas"), + QLatin1String("feature-not-implemented")); error.appendChild(error_type); send(reply); diff --git a/src/xmpp/xmpp-im/filetransfer.cpp b/src/xmpp/xmpp-im/filetransfer.cpp index 78d0ae5e..493b4175 100644 --- a/src/xmpp/xmpp-im/filetransfer.cpp +++ b/src/xmpp/xmpp-im/filetransfer.cpp @@ -565,13 +565,11 @@ void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, QDomElement iq; d->to = to; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement si = doc()->createElement("si"); - si.setAttribute("xmlns", "http://jabber.org/protocol/si"); + QDomElement si = doc()->createElementNS("http://jabber.org/protocol/si", "si"); si.setAttribute("id", _id); si.setAttribute("profile", "http://jabber.org/protocol/si/profile/file-transfer"); - QDomElement file = doc()->createElement("file"); - file.setAttribute("xmlns", "http://jabber.org/protocol/si/profile/file-transfer"); + QDomElement file = doc()->createElementNS("http://jabber.org/protocol/si/profile/file-transfer", "file"); file.setAttribute("name", fname); file.setAttribute("size", QString::number(size)); if(!desc.isEmpty()) { @@ -590,10 +588,8 @@ void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, si.appendChild(file); - QDomElement feature = doc()->createElement("feature"); - feature.setAttribute("xmlns", "http://jabber.org/protocol/feature-neg"); - QDomElement x = doc()->createElement("x"); - x.setAttribute("xmlns", "jabber:x:data"); + QDomElement feature = doc()->createElementNS("http://jabber.org/protocol/feature-neg", "feature"); + QDomElement x = doc()->createElementNS("jabber:x:data", "x"); x.setAttribute("type", "form"); QDomElement field = doc()->createElement("field"); @@ -645,7 +641,7 @@ bool JT_FT::take(const QDomElement &x) if(x.attribute("type") == "result") { QDomElement si = firstChildElement(x); - if(si.attribute("xmlns") != "http://jabber.org/protocol/si" || si.tagName() != "si") { + if(si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") { setError(900, ""); return true; } @@ -687,7 +683,7 @@ bool JT_FT::take(const QDomElement &x) QString streamtype; QDomElement feature = si.elementsByTagName("feature").item(0).toElement(); - if(!feature.isNull() && feature.attribute("xmlns") == "http://jabber.org/protocol/feature-neg") { + if(!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { QDomElement x = feature.elementsByTagName("x").item(0).toElement(); if(!x.isNull() && x.attribute("type") == "submit") { QDomElement field = x.elementsByTagName("field").item(0).toElement(); @@ -731,12 +727,10 @@ JT_PushFT::~JT_PushFT() void JT_PushFT::respondSuccess(const Jid &to, const QString &id, qlonglong rangeOffset, qlonglong rangeLength, const QString &streamType) { QDomElement iq = createIQ(doc(), "result", to.full(), id); - QDomElement si = doc()->createElement("si"); - si.setAttribute("xmlns", "http://jabber.org/protocol/si"); + QDomElement si = doc()->createElementNS("http://jabber.org/protocol/si", "si"); if(rangeOffset != 0 || rangeLength != 0) { - QDomElement file = doc()->createElement("file"); - file.setAttribute("xmlns", "http://jabber.org/protocol/si/profile/file-transfer"); + QDomElement file = doc()->createElementNS("http://jabber.org/protocol/si/profile/file-transfer", "file"); QDomElement range = doc()->createElement("range"); if(rangeOffset > 0) range.setAttribute("offset", QString::number(rangeOffset)); @@ -746,10 +740,8 @@ void JT_PushFT::respondSuccess(const Jid &to, const QString &id, qlonglong range si.appendChild(file); } - QDomElement feature = doc()->createElement("feature"); - feature.setAttribute("xmlns", "http://jabber.org/protocol/feature-neg"); - QDomElement x = doc()->createElement("x"); - x.setAttribute("xmlns", "jabber:x:data"); + QDomElement feature = doc()->createElementNS("http://jabber.org/protocol/feature-neg", "feature"); + QDomElement x = doc()->createElementNS("jabber:x:data", "x"); x.setAttribute("type", "submit"); QDomElement field = doc()->createElement("field"); @@ -784,7 +776,7 @@ bool JT_PushFT::take(const QDomElement &e) return false; QDomElement si = firstChildElement(e); - if(si.attribute("xmlns") != "http://jabber.org/protocol/si" || si.tagName() != "si") + if(si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") return false; if(si.attribute("profile") != "http://jabber.org/protocol/si/profile/file-transfer") return false; @@ -827,7 +819,7 @@ bool JT_PushFT::take(const QDomElement &e) QStringList streamTypes; QDomElement feature = si.elementsByTagName("feature").item(0).toElement(); - if(!feature.isNull() && feature.attribute("xmlns") == "http://jabber.org/protocol/feature-neg") { + if(!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { QDomElement x = feature.elementsByTagName("x").item(0).toElement(); if(!x.isNull() /*&& x.attribute("type") == "form"*/) { QDomElement field = x.elementsByTagName("field").item(0).toElement(); diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index eec47938..8e5efedf 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -302,14 +302,22 @@ JT_HTTPFileUpload::~JT_HTTPFileUpload() void JT_HTTPFileUpload::request(const Jid &to, const QString &fname, quint64 fsize, const QString &ftype, XEP0363::version ver) { + QString ns; + switch (ver) + { + case XEP0363::v0_2_5: ns = xmlns_v0_2_5; break; + case XEP0363::v0_3_1: ns = xmlns_v0_3_1; break; + default: return; + } + d->to = to; d->ver = ver; d->iq = createIQ(doc(), "get", to.full(), id()); - QDomElement req = doc()->createElement("request"); + QDomElement req = doc()->createElementNS(ns, "request"); switch (ver) { case XEP0363::v0_2_5: - req.setAttribute("xmlns", xmlns_v0_2_5); + ns = xmlns_v0_2_5; req.appendChild(textTag(doc(), "filename", fname)); req.appendChild(textTag(doc(), "size", QString::number(fsize))); if (!ftype.isEmpty()) { @@ -317,7 +325,7 @@ void JT_HTTPFileUpload::request(const Jid &to, const QString &fname, } break; case XEP0363::v0_3_1: - req.setAttribute("xmlns", xmlns_v0_3_1); + ns = xmlns_v0_3_1; req.setAttribute("filename", fname); req.setAttribute("size", fsize); if (!ftype.isEmpty()) @@ -366,12 +374,12 @@ bool JT_HTTPFileUpload::take(const QDomElement &e) switch (d->ver) { case XEP0363::v0_2_5: - correct_xmlns = slot.attribute("xmlns") == xmlns_v0_2_5; + correct_xmlns = slot.namespaceURI() == xmlns_v0_2_5; getUrl = tagContent(get); putUrl = tagContent(put); break; case XEP0363::v0_3_1: - correct_xmlns = slot.attribute("xmlns") == xmlns_v0_3_1; + correct_xmlns = slot.namespaceURI() == xmlns_v0_3_1; getUrl = get.attribute("url"); if (!put.isNull()) { putUrl = put.attribute("url"); diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 5a41f13c..d9507c1e 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -137,7 +137,7 @@ File::File(const QDomElement &file) } } QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); - if (hashEl.attribute(QStringLiteral("xmlns")) == HASH_NS || hashEl.namespaceURI() == HASH_NS) { + if (hashEl.namespaceURI() == HASH_NS || hashEl.namespaceURI() == HASH_NS) { range.hash = Hash(hashEl); if (range.hash.type() == Hash::Type::Unknown) { return; @@ -149,7 +149,7 @@ File::File(const QDomElement &file) desc = ce.text(); } else if (ce.tagName() == QLatin1String("hash")) { - if (ce.attribute(QStringLiteral("xmlns")) == HASH_NS || ce.namespaceURI() == HASH_NS) { + if (ce.namespaceURI() == HASH_NS || ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -158,7 +158,7 @@ File::File(const QDomElement &file) } } else if (ce.tagName() == QLatin1String("hash-used")) { - if (ce.attribute(QStringLiteral("xmlns")) == HASH_NS || ce.namespaceURI() == HASH_NS) { + if (ce.namespaceURI() == HASH_NS || ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -168,7 +168,7 @@ File::File(const QDomElement &file) } else if (ce.tagName() == QLatin1String("thumbnail")) { thumbnail = Thumbnail(ce); - } else if (ce.tagName() == QLatin1String("spectrum") && (ce.attribute(QStringLiteral("xmlns")) == SPECTRUM_NS || ce.namespaceURI() == SPECTRUM_NS)) { + } else if (ce.tagName() == QLatin1String("spectrum") && (ce.namespaceURI() == SPECTRUM_NS || ce.namespaceURI() == SPECTRUM_NS)) { QStringList spv = ce.text().split(','); spectrum.bars.reserve(spv.count()); std::transform(spv.begin(), spv.end(), std::back_inserter(spectrum.bars), [](const QString &v){ return v.toUInt(); }); diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index a9c6c5a8..cea49046 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -155,7 +155,6 @@ QDomElement Jingle::toXml(QDomDocument *doc) const } QDomElement query = doc->createElementNS(NS, QLatin1String("jingle")); - //query.setAttribute("xmlns", JINGLE_NS); for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { if (jingleActions[i].action == d->action) { query.setAttribute(QLatin1String("action"), QLatin1String(jingleActions[i].text)); @@ -256,13 +255,13 @@ Reason::Reason(const QDomElement &e) Condition condition = NoReason; QString text; - QString rns = e.attribute(QStringLiteral("xmlns")); + QString rns = e.namespaceURI(); for (QDomElement c = e.firstChildElement(); !c.isNull(); c = c.nextSiblingElement()) { if (c.tagName() == QLatin1String("text")) { text = c.text(); } - else if (c.attribute(QStringLiteral("xmlns")) != rns) { + else if (c.namespaceURI() != rns) { // TODO add here all the extensions to reason. } else { @@ -459,7 +458,7 @@ class JTPush : public Task return false; } auto jingleEl = iq.firstChildElement(QStringLiteral("jingle")); - if (jingleEl.isNull() || jingleEl.attribute(QStringLiteral("xmlns")) != ::XMPP::Jingle::NS) { + if (jingleEl.isNull() || jingleEl.namespaceURI() != ::XMPP::Jingle::NS) { return false; } @@ -475,7 +474,7 @@ class JTPush : public Task auto dname = QString::fromLatin1("description"); for (auto n = jingleEl.firstChildElement(cname); !n.isNull(); n = n.nextSiblingElement(cname)) { auto del = n.firstChildElement(dname); - if (!del.isNull() && externalManagers.contains(del.attribute(QStringLiteral("xmlns")))) { + if (!del.isNull() && externalManagers.contains(del.namespaceURI())) { externalSessions.append(jingle.sid()); return false; } @@ -898,8 +897,8 @@ class Session::Private { QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); - QString descriptionNS = descriptionEl.attribute(QStringLiteral("xmlns")); - QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + QString descriptionNS = descriptionEl.namespaceURI(); + QString transportNS = transportEl.namespaceURI(); typedef std::tuple result; ContentBase c(ce); @@ -1001,8 +1000,8 @@ class Session::Private { QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); - QString descriptionNS = descriptionEl.attribute(QStringLiteral("xmlns")); - QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + QString descriptionNS = descriptionEl.namespaceURI(); + QString transportNS = transportEl.namespaceURI(); typedef std::tuple result; ContentBase c(ce); @@ -1239,7 +1238,7 @@ class Session::Private { ContentBase cb(ce); auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); - QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + QString transportNS = transportEl.namespaceURI(); if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; @@ -1298,7 +1297,7 @@ class Session::Private { ContentBase cb(ce); auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); - QString transportNS = transportEl.attribute(QStringLiteral("xmlns")); + QString transportNS = transportEl.namespaceURI(); if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; @@ -1328,7 +1327,7 @@ class Session::Private return false; } auto tel = ce.firstChildElement(QStringLiteral("transport")); - if (tel.isNull() || tel.attribute(QStringLiteral("xmlns")) != app->transport()->pad()->ns()) { + if (tel.isNull() || tel.namespaceURI() != app->transport()->pad()->ns()) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); return false; } @@ -1898,8 +1897,7 @@ void ErrorUtil::fill(QDomDocument doc, Stanza::Error &error, int jingleCond) int ErrorUtil::jingleCondition(const Stanza::Error &error) { - //qDebug() << "tag" << error.appSpec.tagName() << "xmlns" << error.appSpec.attribute(QString::fromLatin1("xmlns")) << "ns" << error.appSpec.namespaceURI(); - if (error.appSpec.attribute(QString::fromLatin1("xmlns")) != ERROR_NS) { + if (error.appSpec.namespaceURI() != ERROR_NS) { return UnknownError; } QString tagName = error.appSpec.tagName(); diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index a9597d3c..5cdea38d 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -1991,8 +1991,7 @@ void JT_S5B::request(const Jid &to, const QString &sid, const QString &dstaddr, QDomElement iq; d->to = to; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", S5B_NS); + QDomElement query = doc()->createElementNS(S5B_NS, "query"); query.setAttribute("sid", sid); if (!client()->groupChatNick(to.domain(), to.node()).isEmpty()) { query.setAttribute("dstaddr", dstaddr); // special case for muc as in xep-0065rc3 @@ -2005,15 +2004,13 @@ void JT_S5B::request(const Jid &to, const QString &sid, const QString &dstaddr, shost.setAttribute("host", (*it).host()); shost.setAttribute("port", QString::number((*it).port())); if((*it).isProxy()) { - QDomElement p = doc()->createElement("proxy"); - p.setAttribute("xmlns", "http://affinix.com/jabber/stream"); + QDomElement p = doc()->createElementNS("http://affinix.com/jabber/stream", "proxy"); shost.appendChild(p); } query.appendChild(shost); } if(fast) { - QDomElement e = doc()->createElement("fast"); - e.setAttribute("xmlns", "http://affinix.com/jabber/stream"); + QDomElement e = doc()->createElementNS("http://affinix.com/jabber/stream", "fast"); query.appendChild(e); } d->iq = iq; @@ -2026,8 +2023,7 @@ void JT_S5B::requestProxyInfo(const Jid &to) QDomElement iq; d->to = to; iq = createIQ(doc(), "get", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", S5B_NS); + QDomElement query = doc()->createElementNS(S5B_NS, "query"); iq.appendChild(query); d->iq = iq; } @@ -2039,8 +2035,7 @@ void JT_S5B::requestActivation(const Jid &to, const QString &sid, const Jid &tar QDomElement iq; d->to = to; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", S5B_NS); + QDomElement query = doc()->createElementNS(S5B_NS, "query"); query.setAttribute("sid", sid); iq.appendChild(query); QDomElement act = doc()->createElement("activate"); @@ -2156,12 +2151,12 @@ bool JT_PushS5B::take(const QDomElement &e) // look for udpsuccess if(e.tagName() == "message") { QDomElement x = e.elementsByTagName("udpsuccess").item(0).toElement(); - if(!x.isNull() && x.attribute("xmlns") == S5B_NS) { + if(!x.isNull() && x.namespaceURI() == S5B_NS) { incomingUDPSuccess(Jid(x.attribute("from")), x.attribute("dstaddr")); return true; } x = e.elementsByTagName("activate").item(0).toElement(); - if(!x.isNull() && x.attribute("xmlns") == "http://affinix.com/jabber/stream") { + if(!x.isNull() && x.namespaceURI() == "http://affinix.com/jabber/stream") { incomingActivate(Jid(x.attribute("from")), x.attribute("sid"), Jid(x.attribute("jid"))); return true; } @@ -2194,7 +2189,7 @@ bool JT_PushS5B::take(const QDomElement &e) int port = shost.attribute("port").toInt(); QDomElement p = shost.elementsByTagName("proxy").item(0).toElement(); bool isProxy = false; - if(!p.isNull() && p.attribute("xmlns") == "http://affinix.com/jabber/stream") + if(!p.isNull() && p.namespaceURI() == "http://affinix.com/jabber/stream") isProxy = true; StreamHost h; @@ -2209,7 +2204,7 @@ bool JT_PushS5B::take(const QDomElement &e) bool fast = false; QDomElement t; t = q.elementsByTagName("fast").item(0).toElement(); - if(!t.isNull() && t.attribute("xmlns") == "http://affinix.com/jabber/stream") + if(!t.isNull() && t.namespaceURI() == "http://affinix.com/jabber/stream") fast = true; S5BRequest r; @@ -2228,8 +2223,7 @@ bool JT_PushS5B::take(const QDomElement &e) void JT_PushS5B::respondSuccess(const Jid &to, const QString &id, const Jid &streamHost) { QDomElement iq = createIQ(doc(), "result", to.full(), id); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", S5B_NS); + QDomElement query = doc()->createElementNS(S5B_NS, "query"); iq.appendChild(query); QDomElement shost = doc()->createElement("streamhost-used"); shost.setAttribute("jid", streamHost.full()); @@ -2250,8 +2244,7 @@ void JT_PushS5B::sendUDPSuccess(const Jid &to, const QString &dstaddr) { QDomElement m = doc()->createElement("message"); m.setAttribute("to", to.full()); - QDomElement u = doc()->createElement("udpsuccess"); - u.setAttribute("xmlns", S5B_NS); + QDomElement u = doc()->createElementNS(S5B_NS, "udpsuccess"); u.setAttribute("dstaddr", dstaddr); m.appendChild(u); send(m); @@ -2261,8 +2254,7 @@ void JT_PushS5B::sendActivate(const Jid &to, const QString &sid, const Jid &stre { QDomElement m = doc()->createElement("message"); m.setAttribute("to", to.full()); - QDomElement act = doc()->createElement("activate"); - act.setAttribute("xmlns", "http://affinix.com/jabber/stream"); + QDomElement act = doc()->createElementNS("http://affinix.com/jabber/stream", "activate"); act.setAttribute("sid", sid); act.setAttribute("jid", streamHost.full()); m.appendChild(act); diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index 1eb677f5..b13863ca 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -2449,7 +2449,6 @@ QDomElement HttpAuthRequest::toXml(QDomDocument &doc) const return e; e = doc.createElementNS("http://jabber.org/protocol/http-auth", "confirm"); - e.setAttribute("xmlns", "http://jabber.org/protocol/http-auth"); if(hasId_) e.setAttribute("id", id_); @@ -2590,8 +2589,7 @@ QCryptographicHash::Algorithm CapsSpec::hashAlgorithm() const QDomElement CapsSpec::toXml(QDomDocument *doc) const { - QDomElement c = doc->createElement("c"); - c.setAttribute("xmlns", NS_CAPS); + QDomElement c = doc->createElementNS(NS_CAPS, "c"); QString algo = cryptoMap().key(hashAlgo_); c.setAttribute("hash",algo); c.setAttribute("node",node_); @@ -3742,7 +3740,7 @@ const Jid &CaptchaChallenge::arbiter() const Thumbnail::Thumbnail(const QDomElement &el) { QString ns(QLatin1String(XMPP_THUMBS_NS)); - if(el.attribute("xmlns") == ns || el.namespaceURI() == ns) { + if(el.namespaceURI() == ns) { uri = QUrl(el.attribute("uri"), QUrl::StrictMode); mimeType = el.attribute("mime-type"); width = el.attribute("width").toUInt(); diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index a431568c..de7ee799 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -121,8 +121,7 @@ void BoBData::fromXml(const QDomElement &data) QDomElement BoBData::toXml(QDomDocument *doc) const { - QDomElement data = doc->createElement("data"); - data.setAttribute("xmlns", "urn:xmpp:bob"); + QDomElement data = doc->createElementNS("urn:xmpp:bob", "data"); data.setAttribute("cid", d->cid); data.setAttribute("max-age", d->maxAge); data.setAttribute("type", d->type); diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp index 1bf0252c..24d7f17a 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp @@ -110,8 +110,7 @@ void DiscoInfoTask::onGo () } QDomElement iq = createIQ(doc(), "get", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "http://jabber.org/protocol/disco#info"); + QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#info", "query"); if ( !d->node.isEmpty() ) query.setAttribute("node", d->node); diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.cpp b/src/xmpp/xmpp-im/xmpp_discoitem.cpp index 6a1f3243..75738ef1 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoitem.cpp @@ -189,7 +189,7 @@ DiscoItem DiscoItem::fromDiscoInfoResult(const QDomElement &q) identities.append( id ); } - else if (e.tagName() == QLatin1String("x") && e.attribute("xmlns") == QLatin1String("jabber:x:data")) { + else if (e.tagName() == QLatin1String("x") && e.namespaceURI() == QLatin1String("jabber:x:data")) { XData form; form.fromXml(e); extList.append(form); diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index 475af303..9089ecce 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -345,8 +345,7 @@ IBBData& IBBData::fromXml(const QDomElement &e) QDomElement IBBData::toXml(QDomDocument *doc) const { - QDomElement query = textTag(doc, "data", QString::fromLatin1(data.toBase64())).toElement(); - query.setAttribute("xmlns", IBB_NS); + QDomElement query = textTagNS(doc, IBB_NS, "data", QString::fromLatin1(data.toBase64())).toElement(); query.setAttribute("seq", QString::number(seq)); query.setAttribute("sid", sid); return query; @@ -529,9 +528,8 @@ void JT_IBB::request(const Jid &to, const QString &sid, int blockSize) QDomElement iq; d->to = to; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("open"); + QDomElement query = doc()->createElementNS(IBB_NS, "open"); //genUniqueKey - query.setAttribute("xmlns", IBB_NS); query.setAttribute("sid", sid); query.setAttribute("block-size", blockSize); query.setAttribute("stanza", "iq"); @@ -556,8 +554,7 @@ void JT_IBB::close(const Jid &to, const QString &sid) QDomElement iq; d->to = to; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = iq.appendChild(doc()->createElement("close")).toElement(); - query.setAttribute("xmlns", IBB_NS); + QDomElement query = iq.appendChild(doc()->createElementNS(IBB_NS, "close")).toElement(); query.setAttribute("sid", sid); d->iq = iq; @@ -592,7 +589,7 @@ bool JT_IBB::take(const QDomElement &e) QString id = e.attribute("id"); QString from = e.attribute("from"); QDomElement openEl = e.firstChildElement("open"); - if (!openEl.isNull() && openEl.attribute("xmlns") == IBB_NS) { + if (!openEl.isNull() && openEl.namespaceURI() == IBB_NS) { emit incomingRequest(Jid(from), id, openEl.attribute("sid"), openEl.attribute("block-size").toInt(), @@ -600,13 +597,13 @@ bool JT_IBB::take(const QDomElement &e) return true; } QDomElement dataEl = e.firstChildElement("data"); - if (!dataEl.isNull() && dataEl.attribute("xmlns") == IBB_NS) { + if (!dataEl.isNull() && dataEl.namespaceURI() == IBB_NS) { IBBData data; emit incomingData(Jid(from), id, data.fromXml(dataEl), Stanza::IQ); return true; } QDomElement closeEl = e.firstChildElement("close"); - if (!closeEl.isNull() && closeEl.attribute("xmlns") == IBB_NS) { + if (!closeEl.isNull() && closeEl.namespaceURI() == IBB_NS) { emit closeRequest(Jid(from), id, closeEl.attribute("sid")); return true; } diff --git a/src/xmpp/xmpp-im/xmpp_subsets.cpp b/src/xmpp/xmpp-im/xmpp_subsets.cpp index 014ddccc..ef306639 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.cpp +++ b/src/xmpp/xmpp-im/xmpp_subsets.cpp @@ -56,8 +56,7 @@ class SubsetsClientManager::Private QDomElement mainElement(QDomDocument *doc) { - QDomElement e = doc->createElement(QStringLiteral("set")); - e.setAttribute(QStringLiteral("xmlns"), xmlns_ns_rsm); + QDomElement e = doc->createElementNS(xmlns_ns_rsm, QStringLiteral("set")); return e; } @@ -189,13 +188,13 @@ void SubsetsClientManager::setMax(int max) QDomElement SubsetsClientManager::findElement(const QDomElement &el, bool child) { - if (el.tagName() == QLatin1String("set") && el.attribute(QLatin1String("xmlns")) == xmlns_ns_rsm) + if (el.tagName() == QLatin1String("set") && el.namespaceURI() == xmlns_ns_rsm) return el; if (child) { QDomElement e = el.firstChildElement(QLatin1String("set")); while (!e.isNull()) { - if (e.attribute(QLatin1String("xmlns")) == xmlns_ns_rsm) { + if (e.namespaceURI() == xmlns_ns_rsm) { return e; } e = e.nextSiblingElement(QLatin1String("set")); diff --git a/src/xmpp/xmpp-im/xmpp_tasks.cpp b/src/xmpp/xmpp-im/xmpp_tasks.cpp index aa569a6d..7a627a3c 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.cpp +++ b/src/xmpp/xmpp-im/xmpp_tasks.cpp @@ -101,8 +101,7 @@ JT_Session::JT_Session(Task *parent) : Task(parent) void JT_Session::onGo() { QDomElement iq = createIQ(doc(), "set", "", id()); - QDomElement session = doc()->createElement("session"); - session.setAttribute("xmlns",NS_SESSION); + QDomElement session = doc()->createElementNS(NS_SESSION, "session"); iq.appendChild(session); send(iq); } @@ -161,8 +160,7 @@ void JT_Register::reg(const QString &user, const QString &pass) d->type = 0; to = client()->host(); iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "username", user)); query.appendChild(textTag(doc(), "password", pass)); @@ -173,8 +171,7 @@ void JT_Register::changepw(const QString &pass) d->type = 1; to = client()->host(); iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "username", client()->user())); query.appendChild(textTag(doc(), "password", pass)); @@ -185,8 +182,7 @@ void JT_Register::unreg(const Jid &j) d->type = 2; to = j.isEmpty() ? client()->host() : j.full(); iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); // this may be useful @@ -201,8 +197,7 @@ void JT_Register::getForm(const Jid &j) d->type = 3; to = j; iq = createIQ(doc(), "get", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); } @@ -211,8 +206,7 @@ void JT_Register::setForm(const Form &form) d->type = 4; to = form.jid(); iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); // key? @@ -230,8 +224,7 @@ void JT_Register::setForm(const Jid& to, const XData& xdata) { d->type = 4; iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:register"); + QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(xdata.toXml(doc(), true)); } @@ -284,11 +277,11 @@ bool JT_Register::take(const QDomElement &x) d->form.setKey(tagContent(i)); else if (i.tagName() == QLatin1String("registered")) d->registered = true; - else if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:data") { + else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; } - else if(i.tagName() == "data" && i.attribute("xmlns") == "urn:xmpp:bob") { + else if(i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { client()->bobManager()->append(BoBData(i)); // xep-0231 } else { @@ -401,8 +394,7 @@ void JT_Roster::get() type = 0; //to = client()->host(); iq = createIQ(doc(), "get", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:roster"); + QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); } @@ -436,8 +428,7 @@ void JT_Roster::onGo() else if(type == 1) { //to = client()->host(); iq = createIQ(doc(), "set", to.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:roster"); + QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); foreach (const QDomElement& it, d->itemList) query.appendChild(it); @@ -583,13 +574,11 @@ void JT_Presence::pres(const Status &s) tag.appendChild( textTag(doc(), "priority", QString("%1").arg(s.priority()) ) ); if(!s.keyID().isEmpty()) { - QDomElement x = textTag(doc(), "x", s.keyID()); - x.setAttribute("xmlns", "http://jabber.org/protocol/e2e"); + QDomElement x = textTagNS(doc(), "http://jabber.org/protocol/e2e", "x", s.keyID()); tag.appendChild(x); } if(!s.xsigned().isEmpty()) { - QDomElement x = textTag(doc(), "x", s.xsigned()); - x.setAttribute("xmlns", "jabber:x:signed"); + QDomElement x = textTagNS(doc(), "jabber:x:signed", "x", s.xsigned()); tag.appendChild(x); } @@ -601,8 +590,7 @@ void JT_Presence::pres(const Status &s) } if(s.isMUC()) { - QDomElement m = doc()->createElement("x"); - m.setAttribute("xmlns","http://jabber.org/protocol/muc"); + QDomElement m = doc()->createElementNS("http://jabber.org/protocol/muc", "x"); if (!s.mucPassword().isEmpty()) { m.appendChild(textTag(doc(),"password",s.mucPassword())); } @@ -622,8 +610,7 @@ void JT_Presence::pres(const Status &s) } if(s.hasPhotoHash()) { - QDomElement m = doc()->createElement("x"); - m.setAttribute("xmlns", "vcard-temp:x:update"); + QDomElement m = doc()->createElementNS("vcard-temp:x:update","x"); m.appendChild(textTag(doc(), "photo", s.photoHash())); tag.appendChild(m); } @@ -651,8 +638,7 @@ void JT_Presence::sub(const Jid &to, const QString &subType, const QString& nick if (!nick.isEmpty() && (subType == QLatin1String("subscribe") || subType == QLatin1String("subscribed") || subType == QLatin1String("unsubscribe") || subType == QLatin1String("unsubscribed"))) { - QDomElement nick_tag = textTag(doc(),"nick",nick); - nick_tag.setAttribute("xmlns","http://jabber.org/protocol/nick"); + QDomElement nick_tag = textTagNS(doc(),"http://jabber.org/protocol/nick","nick",nick); tag.appendChild(nick_tag); } } @@ -708,7 +694,7 @@ bool JT_PushPresence::take(const QDomElement &e) type == QLatin1String("unsubscribe") || type == QLatin1String("unsubscribed")) { QString nick; QDomElement tag = e.firstChildElement("nick"); - if (!tag.isNull() && tag.attribute("xmlns") == "http://jabber.org/protocol/nick") { + if (!tag.isNull() && tag.namespaceURI() == "http://jabber.org/protocol/nick") { nick = tagContent(tag); } subscription(j, type, nick); @@ -735,17 +721,17 @@ bool JT_PushPresence::take(const QDomElement &e) if(i.isNull()) continue; - if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:delay") { + if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:delay") { if(i.hasAttribute("stamp") && !stamp.isValid()) { stamp = stamp2TS(i.attribute("stamp")); } } - else if(i.tagName() == "delay" && i.attribute("xmlns") == "urn:xmpp:delay") { + else if(i.tagName() == "delay" && i.namespaceURI() == "urn:xmpp:delay") { if(i.hasAttribute("stamp") && !stamp.isValid()) { stamp = QDateTime::fromString(i.attribute("stamp").left(19), Qt::ISODate); } } - else if(i.tagName() == "x" && i.attribute("xmlns") == "gabber:x:music:info") { + else if(i.tagName() == "x" && i.namespaceURI() == "gabber:x:music:info") { QDomElement t; QString title, state; @@ -759,26 +745,26 @@ bool JT_PushPresence::take(const QDomElement &e) if(!title.isEmpty() && state == "playing") p.setSongTitle(title); } - else if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:signed") { + else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:signed") { p.setXSigned(tagContent(i)); } - else if(i.tagName() == "x" && i.attribute("xmlns") == "http://jabber.org/protocol/e2e") { + else if(i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/e2e") { p.setKeyID(tagContent(i)); } - else if(i.tagName() == "c" && i.attribute("xmlns") == NS_CAPS) { + else if(i.tagName() == "c" && i.namespaceURI() == NS_CAPS) { p.setCaps(CapsSpec::fromXml(i)); if(!e.hasAttribute("type") && p.caps().isValid()) { client()->capsManager()->updateCaps(j, p.caps()); } } - else if(i.tagName() == "x" && i.attribute("xmlns") == "vcard-temp:x:update") { + else if(i.tagName() == "x" && i.namespaceURI() == "vcard-temp:x:update") { QDomElement t; t = i.firstChildElement("photo"); if (!t.isNull()) p.setPhotoHash(tagContent(t).toLower()); // if hash is empty this may mean photo removal // else vcard.hasPhotoHash() returns false and that's mean user is not yet ready to advertise his image } - else if(i.tagName() == "x" && i.attribute("xmlns") == "http://jabber.org/protocol/muc#user") { + else if(i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/muc#user") { for(QDomNode muc_n = i.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { QDomElement muc_e = muc_n.toElement(); if(muc_e.isNull()) @@ -792,7 +778,7 @@ bool JT_PushPresence::take(const QDomElement &e) p.setMUCDestroy(MUCDestroy(muc_e)); } } - else if (i.tagName() == "data" && i.attribute("xmlns") == "urn:xmpp:bob") { + else if (i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { BoBData bd(i); client()->bobManager()->append(bd); p.addBoBData(bd); @@ -872,7 +858,7 @@ void JT_Message::onGo() { Stanza s = m.toStanza(&(client()->stream())); - QDomElement e = oldStyleNS(s.element()); + QDomElement e = s.element();//oldStyleNS(s.element()); auto encryptionHandler = client()->encryptionHandler(); bool wasEncrypted = encryptionHandler && encryptionHandler->encryptMessageElement(e); @@ -928,12 +914,12 @@ bool JT_PushMessage::take(const QDomElement &e) for (int i = 0; i < list.size(); ++i) { QDomElement el = list.at(i).toElement(); - if (el.attribute("xmlns") == QLatin1String("urn:xmpp:carbons:2") + if (el.namespaceURI() == QLatin1String("urn:xmpp:carbons:2") && (el.tagName() == QLatin1String("received") || el.tagName() == QLatin1String("sent")) && fromJid.compare(Jid(e1.attribute(QLatin1String("to"))), false)) { QDomElement el1 = el.firstChildElement(); if (el1.tagName() == QLatin1String("forwarded") - && el1.attribute(QLatin1String("xmlns")) == QLatin1String("urn:xmpp:forward:0")) { + && el1.namespaceURI() == QLatin1String("urn:xmpp:forward:0")) { QDomElement el2 = el1.firstChildElement(QLatin1String("message")); if (!el2.isNull()) { forward = el2; @@ -943,7 +929,7 @@ bool JT_PushMessage::take(const QDomElement &e) } } else if (el.tagName() == QLatin1String("forwarded") - && el.attribute(QLatin1String("xmlns")) == QLatin1String("urn:xmpp:forward:0")) { + && el.namespaceURI() == QLatin1String("urn:xmpp:forward:0")) { forward = el.firstChildElement(QLatin1String("message")); // currently only messages are supportted // TODO element support if (!forward.isNull()) { @@ -1003,8 +989,7 @@ void JT_VCard::get(const Jid &_jid) type = 0; d->jid = _jid; d->iq = createIQ(doc(), "get", type == 1 ? Jid().full() : d->jid.full(), id()); - QDomElement v = doc()->createElement("vCard"); - v.setAttribute("xmlns", "vcard-temp"); + QDomElement v = doc()->createElementNS("vcard-temp", "vCard"); d->iq.appendChild(v); } @@ -1116,8 +1101,7 @@ void JT_Search::get(const Jid &jid) d->hasXData = false; d->xdata = XData(); iq = createIQ(doc(), "get", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:search"); + QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); } @@ -1128,8 +1112,7 @@ void JT_Search::set(const Form &form) d->hasXData = false; d->xdata = XData(); iq = createIQ(doc(), "set", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:search"); + QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); // key? @@ -1150,8 +1133,7 @@ void JT_Search::set(const Jid &jid, const XData &form) d->hasXData = false; d->xdata = XData(); iq = createIQ(doc(), "set", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:search"); + QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); query.appendChild(form.toXml(doc(), true)); } @@ -1202,7 +1184,7 @@ bool JT_Search::take(const QDomElement &x) d->form.setInstructions(tagContent(i)); else if(i.tagName() == "key") d->form.setKey(tagContent(i)); - else if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:data") { + else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; } @@ -1244,7 +1226,7 @@ bool JT_Search::take(const QDomElement &x) d->resultList += r; } - else if(i.tagName() == "x" && i.attribute("xmlns") == "jabber:x:data") { + else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; } @@ -1272,8 +1254,7 @@ void JT_ClientVersion::get(const Jid &jid) { j = jid; iq = createIQ(doc(), "get", j.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:version"); + QDomElement query = doc()->createElementNS("jabber:iq:version", "query"); iq.appendChild(query); } @@ -1352,8 +1333,7 @@ void JT_EntityTime::get(const Jid &jid) { j = jid; iq = createIQ(doc(), "get", jid.full(), id()); - QDomElement time = doc()->createElement("time"); - time.setAttribute("xmlns", "urn:xmpp:time"); + QDomElement time = doc()->createElementNS("urn:xmpp:time", "time"); iq.appendChild(time); } @@ -1428,8 +1408,7 @@ bool JT_ServInfo::take(const QDomElement &e) QString ns = queryNS(e); if(ns == "jabber:iq:version") { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:version"); + QDomElement query = doc()->createElementNS("jabber:iq:version", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "name", client()->clientName())); query.appendChild(textTag(doc(), "version", client()->clientVersion())); @@ -1464,8 +1443,7 @@ bool JT_ServInfo::take(const QDomElement &e) QDomElement error = doc()->createElement("error"); error.setAttribute("type","cancel"); error_reply.appendChild(error); - QDomElement error_type = doc()->createElement("item-not-found"); - error_type.setAttribute("xmlns","urn:ietf:params:xml:ns:xmpp-stanzas"); + QDomElement error_type = doc()->createElementNS("urn:ietf:params:xml:ns:xmpp-stanzas", "item-not-found"); error.appendChild(error_type); send(error_reply); } @@ -1475,11 +1453,10 @@ bool JT_ServInfo::take(const QDomElement &e) return false; } - ns = e.firstChildElement("time").attribute("xmlns"); + ns = e.firstChildElement("time").namespaceURI(); if (ns == "urn:xmpp:time") { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); - QDomElement time = doc()->createElement("time"); - time.setAttribute("xmlns", ns); + QDomElement time = doc()->createElementNS(ns, "time"); iq.appendChild(time); QDateTime local = QDateTime::currentDateTime(); @@ -1515,8 +1492,7 @@ void JT_Gateway::get(const Jid &jid) type = 0; v_jid = jid; iq = createIQ(doc(), "get", v_jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:gateway"); + QDomElement query = doc()->createElementNS("jabber:iq:gateway", "query"); iq.appendChild(query); } @@ -1526,8 +1502,7 @@ void JT_Gateway::set(const Jid &jid, const QString &prompt) v_jid = jid; v_prompt = prompt; iq = createIQ(doc(), "set", v_jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "jabber:iq:gateway"); + QDomElement query = doc()->createElementNS("jabber:iq:gateway", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "prompt", v_prompt)); } @@ -1635,8 +1610,7 @@ void JT_DiscoItems::get (const Jid &j, const QString &node) d->jid = j; d->iq = createIQ(doc(), "get", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); + QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#items", "query"); if ( !node.isEmpty() ) query.setAttribute("node", node); @@ -1736,8 +1710,7 @@ void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) d->jid = j; d->iq = createIQ(doc(), "set", d->jid.full(), id()); - QDomElement query = doc()->createElement("query"); - query.setAttribute("xmlns", "http://jabber.org/protocol/disco#items"); + QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#items", "query"); // FIXME: unsure about this //if ( !node.isEmpty() ) @@ -1796,7 +1769,7 @@ bool JT_BoBServer::take(const QDomElement &e) return false; QDomElement data = e.firstChildElement("data"); - if (data.attribute("xmlns") == "urn:xmpp:bob") { + if (data.namespaceURI() == "urn:xmpp:bob") { QDomElement iq; BoBData bd = client()->bobManager()->bobData(data.attribute("cid")); if (bd.isNull()) { @@ -1850,8 +1823,7 @@ void JT_BitsOfBinary::get(const Jid &j, const QString &cid) d->data = client()->bobManager()->bobData(cid); if (d->data.isNull()) { d->iq = createIQ(doc(), "get", d->jid.full(), id()); - QDomElement data = doc()->createElement("data"); - data.setAttribute("xmlns", "urn:xmpp:bob"); + QDomElement data = doc()->createElementNS("urn:xmpp:bob", "data"); data.setAttribute("cid", cid); d->iq.appendChild(data); } @@ -1915,7 +1887,7 @@ bool JT_PongServer::take(const QDomElement &e) return false; QDomElement ping = e.firstChildElement("ping"); - if (!e.isNull() && ping.attribute("xmlns") == "urn:xmpp:ping") { + if (!e.isNull() && ping.namespaceURI() == "urn:xmpp:ping") { QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); send(iq); return true; @@ -2075,8 +2047,7 @@ void JT_MessageCarbons::enable() { _iq = createIQ(doc(), "set", "", id()); - QDomElement enable = doc()->createElement("enable"); - enable.setAttribute("xmlns", "urn:xmpp:carbons:2"); + QDomElement enable = doc()->createElementNS("urn:xmpp:carbons:2", "enable"); _iq.appendChild(enable); } @@ -2085,8 +2056,7 @@ void JT_MessageCarbons::disable() { _iq = createIQ(doc(), "set", "", id()); - QDomElement disable = doc()->createElement("disable"); - disable.setAttribute("xmlns", "urn:xmpp:carbons:2"); + QDomElement disable = doc()->createElementNS("urn:xmpp:carbons:2", "disable"); _iq.appendChild(disable); } diff --git a/src/xmpp/xmpp-im/xmpp_vcard.cpp b/src/xmpp/xmpp-im/xmpp_vcard.cpp index e1aaef7b..fa74112b 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.cpp +++ b/src/xmpp/xmpp-im/xmpp_vcard.cpp @@ -210,8 +210,7 @@ VCard::~VCard() QDomElement VCard::toXml(QDomDocument *doc) const { - QDomElement v = doc->createElement("vCard"); - v.setAttribute("xmlns", "vcard-temp"); + QDomElement v = doc->createElementNS("vcard-temp", "vCard"); if ( !d->version.isEmpty() ) v.appendChild( textTag(doc, "VERSION", d->version) ); diff --git a/src/xmpp/xmpp-im/xmpp_xdata.cpp b/src/xmpp/xmpp-im/xmpp_xdata.cpp index 128557cb..a481db8d 100644 --- a/src/xmpp/xmpp-im/xmpp_xdata.cpp +++ b/src/xmpp/xmpp-im/xmpp_xdata.cpp @@ -220,7 +220,7 @@ void XData::Field::fromXml(const QDomElement &e) _value.append(i.text()); } else if (tag == "media" && (i.namespaceURI() == "urn:xmpp:media-element" - || i.attribute("xmlns") == "urn:xmpp:media-element")) { // allow only one media element + || i.namespaceURI() == "urn:xmpp:media-element")) { // allow only one media element QSize s; if (i.hasAttribute("width")) { s.setWidth(i.attribute("width").toInt()); @@ -457,7 +457,7 @@ void XData::setFields(const FieldList &fl) void XData::fromXml(const QDomElement &e) { - if ( (e.attribute("xmlns") != "jabber:x:data") && (e.namespaceURI() != "jabber:x:data") ) + if (e.namespaceURI() != "jabber:x:data") return; QString type = e.attribute("type"); @@ -526,7 +526,6 @@ void XData::fromXml(const QDomElement &e) QDomElement XData::toXml(QDomDocument *doc, bool submitForm) const { QDomElement x = doc->createElementNS("jabber:x:data", "x"); - x.setAttribute("xmlns", "jabber:x:data"); QString type = "form"; if ( d->type == Data_Result ) diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp index 8440ff13..fd0c8653 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp @@ -143,6 +143,15 @@ QDomElement textTag(QDomDocument *doc, const QString &name, const QString &conte return tag; } +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content) +{ + QDomElement tag = doc->createElementNS(ns, name); + QDomText text = doc->createTextNode(content); + tag.appendChild(text); + + return tag; +} + QString tagContent(const QDomElement &e) { // look for some tag content @@ -211,7 +220,7 @@ QDomElement queryTag(const QDomElement &e) QString queryNS(const QDomElement &e) { - return e.firstChildElement("query").attribute("xmlns"); + return e.firstChildElement("query").namespaceURI(); } /** @@ -262,17 +271,18 @@ QDomElement addCorrectNS(const QDomElement &e) // find from this to parent closest node with xmlns/namespaceURI QDomNode n = e; - while(!n.isNull() && !n.toElement().hasAttribute("xmlns") && n.toElement().namespaceURI().isEmpty()) + static QString xmlns = QStringLiteral("xmlns"); + while(!n.isNull() && !n.toElement().hasAttribute(xmlns) && n.toElement().namespaceURI().isEmpty()) n = n.parentNode(); QString ns; - if(n.isNull() || !n.toElement().hasAttribute("xmlns")) { // if not found or it's namespaceURI + if(n.isNull() || !n.toElement().hasAttribute(xmlns)) { // if not found or it's namespaceURI if (n.toElement().namespaceURI().isEmpty()) { // if nothing found, then use default jabber:client namespace ns = "jabber:client"; } else { ns = n.toElement().namespaceURI(); } } else { // if found node with xmlns - ns = n.toElement().attribute("xmlns"); + ns = n.toElement().attribute(xmlns); } // at this point `ns` is either detected namespace of `e` or jabber:client // make a new node @@ -282,7 +292,7 @@ QDomElement addCorrectNS(const QDomElement &e) QDomNamedNodeMap al = e.attributes(); for(x = 0; x < al.count(); ++x) { QDomAttr a = al.item(x).toAttr(); - if(a.name() != "xmlns") + if(a.name() != xmlns) i.setAttributeNodeNS(a.cloneNode().toAttr()); } diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.h b/src/xmpp/xmpp-im/xmpp_xmlcommon.h index 42eba997..e3df0a06 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.h +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.h @@ -62,6 +62,7 @@ QDateTime stamp2TS(const QString &ts); bool stamp2TS(const QString &ts, QDateTime *d); QString TS2stamp(const QDateTime &d); QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content); +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content); QString tagContent(const QDomElement &e); XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI, const QString &localName); QDomElement createIQ(QDomDocument *doc, const QString &type, const QString &to, const QString &id); From 64367bbdb6d93d59a1b43a0501c5960b2bfee5cd Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 29 Jun 2019 15:59:22 +0300 Subject: [PATCH 083/383] Added Jingle application termination reasons --- src/xmpp/xmpp-im/jingle-ft.cpp | 52 +++++++++++++++++--------- src/xmpp/xmpp-im/jingle-ft.h | 1 + src/xmpp/xmpp-im/jingle.cpp | 6 +++ src/xmpp/xmpp-im/jingle.h | 3 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 8 ++-- 5 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index d9507c1e..1096da2a 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -476,24 +476,25 @@ QStringList Manager::availableTransports() const class Application::Private { public: - Application *q = nullptr; - State state = State::Created; - State transportReplaceState = State::Finished; - Action updateToSend = Action::NoAction; + Application *q = nullptr; + State state = State::Created; + State transportReplaceState = State::Finished; + Action updateToSend = Action::NoAction; QSharedPointer pad; - QString contentName; - File file; - File acceptFile; // as it comes with "accept" response - Origin creator; - Origin senders; - Origin transportReplaceOrigin = Origin::None; + QString contentName; + File file; + File acceptFile; // as it comes with "accept" response + Origin creator; + Origin senders; + Origin transportReplaceOrigin = Origin::None; XMPP::Stanza::Error lastError; + Reason terminationReason; QSharedPointer transport; Connection::Ptr connection; - QStringList availableTransports; - bool closeDeviceOnFinish = true; - QIODevice *device = nullptr; - quint64 bytesLeft = 0; + QStringList availableTransports; + bool closeDeviceOnFinish = true; + QIODevice *device = nullptr; + quint64 bytesLeft = 0; void setState(State s) { @@ -511,13 +512,14 @@ class Application::Private void handleStreamFail() { - // TODO d->lastError = Condition::FailedApplication + terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("stream failed")); setState(State::Finished); } void writeNextBlockToTransport() { if (!bytesLeft) { + terminationReason = Reason(Reason::Condition::Success); setState(State::Finished); return; // everything is written } @@ -564,6 +566,7 @@ class Application::Private } if (!bytesLeft) { // TODO send + terminationReason = Reason(Reason::Condition::Success); setState(State::Finished); } } @@ -605,6 +608,11 @@ Stanza::Error Application::lastError() const return d->lastError; } +Reason Application::terminationReason() const +{ + return d->terminationReason; +} + QString Application::contentName() const { return d->contentName; @@ -790,7 +798,10 @@ Action Application::evaluateOutgoingUpdate() return d->updateToSend; } - if (d->transport->hasUpdates()) + if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { + d->updateToSend = Action::ContentRemove; + } + else if (d->transport->hasUpdates()) d->updateToSend = Action::TransportInfo; break; @@ -842,7 +853,9 @@ OutgoingUpdate Application::takeOutgoingUpdate() case Action::ContentReject: case Action::ContentRemove: if (d->transportReplaceOrigin != Origin::None) - updates << Reason(Reason::Condition::FailedTransport).toXml(doc); + d->terminationReason = Reason(Reason::Condition::FailedTransport); + if (d->terminationReason.isValid()) + updates << d->terminationReason.toXml(doc); return OutgoingUpdate{updates, [this](){ d->setState(State::Finished); } @@ -972,6 +985,11 @@ bool Application::isValid() const void Application::setDevice(QIODevice *dev, bool closeOnFinish) { + if (!dev) { // failed to provide proper device + d->terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("No destination device")); + emit updated(); + return; + } d->device = dev; d->closeDeviceOnFinish = closeOnFinish; if (d->senders == d->pad->session()->role()) { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 0619a594..c08dd682 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -137,6 +137,7 @@ class Application : public XMPP::Jingle::Application State state() const override; void setState(State state) override; XMPP::Stanza::Error lastError() const; + Reason terminationReason() const; QString contentName() const override; Origin creator() const override; diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index cea49046..0b486959 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -282,6 +282,12 @@ Reason::Reason(const Reason &other) : } +Reason &Reason::operator=(const Reason &other) +{ + d = other.d; + return *this; +} + Reason::Condition Reason::condition() const { if (d) return d->cond; diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 907cc426..9a13b26f 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -187,7 +187,7 @@ class Reason { Reason(Condition cond, const QString &text = QString()); Reason(const QDomElement &el); Reason(const Reason &other); - Reason& operator=(const Reason &)=default; + Reason& operator=(const Reason &); inline bool isValid() const { return d != nullptr; } Condition condition() const; void setCondition(Condition cond); @@ -400,6 +400,7 @@ class Application : public QObject virtual State state() const = 0; virtual void setState(State state) = 0; // likely just remember the state and not generate any signals virtual XMPP::Stanza::Error lastError() const = 0; + virtual Reason terminationReason() const = 0; virtual Origin creator() const = 0; virtual Origin senders() const = 0; diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index de7ee799..a988230a 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -29,10 +29,10 @@ using namespace XMPP; class BoBData::Private : public QSharedData { public: - QByteArray data; - QString type; - QString cid; - unsigned int maxAge; + QByteArray data; // file data itself + QString type; // mime type. e.g. image/png + QString cid; // content identifier without "cid:" + unsigned int maxAge; // seconds to live }; BoBData::BoBData() From 0b635ccd8d171da5859c1dfe5744cfbe5d814ded Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 29 Jun 2019 21:10:07 +0300 Subject: [PATCH 084/383] fixed compilation warnings --- src/xmpp/xmpp-im/jingle-ft.h | 6 +++--- src/xmpp/xmpp-im/jingle-ibb.h | 2 +- src/xmpp/xmpp-im/jingle-s5b.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index c08dd682..f92dca04 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -136,13 +136,13 @@ class Application : public XMPP::Jingle::Application ApplicationManagerPad::Ptr pad() const override; State state() const override; void setState(State state) override; - XMPP::Stanza::Error lastError() const; - Reason terminationReason() const; + XMPP::Stanza::Error lastError() const override; + Reason terminationReason() const override; QString contentName() const override; Origin creator() const override; Origin senders() const override; - Origin transportReplaceOrigin() const; + Origin transportReplaceOrigin() const override; SetDescError setDescription(const QDomElement &description) override; void setFile(const File &file); File file() const; diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 7b2011df..9768edb7 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -50,7 +50,7 @@ class Transport : public XMPP::Jingle::Transport bool isValid() const override; Features features() const override; - Connection::Ptr connection() const; + Connection::Ptr connection() const override; private: friend class Manager; diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index 80bfa28c..cd277c0d 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -149,7 +149,7 @@ class Transport : public XMPP::Jingle::Transport QString sid() const; QString directAddr() const; - Connection::Ptr connection() const; + Connection::Ptr connection() const override; private: friend class Manager; From 7981a8417f43f8596eed317421f18dc5bc43a59c Mon Sep 17 00:00:00 2001 From: Vitaly Tonkacheyev Date: Tue, 2 Jul 2019 07:59:21 +0300 Subject: [PATCH 085/383] Modernize iris code (#61) --- src/irisnet/corelib/addressresolver.cpp | 2 +- src/irisnet/corelib/addressresolver.h | 2 +- src/irisnet/corelib/irisnetglobal.cpp | 14 ++-- src/irisnet/corelib/irisnetplugin.cpp | 12 +-- src/irisnet/corelib/irisnetplugin.h | 10 +-- src/irisnet/corelib/netavailability.h | 2 +- src/irisnet/corelib/netinterface.cpp | 14 ++-- src/irisnet/corelib/netinterface.h | 2 +- src/irisnet/corelib/netinterface_qtname.cpp | 2 +- src/irisnet/corelib/netinterface_unix.cpp | 4 +- src/irisnet/corelib/netnames.cpp | 24 +++--- src/irisnet/corelib/netnames.h | 8 +- src/irisnet/corelib/objectsession.cpp | 6 +- src/irisnet/corelib/objectsession.h | 2 +- src/irisnet/noncore/cutestuff/bsocket.cpp | 4 +- src/irisnet/noncore/cutestuff/bsocket.h | 2 +- src/irisnet/noncore/cutestuff/httpconnect.h | 2 +- src/irisnet/noncore/cutestuff/httppoll.cpp | 6 +- src/irisnet/noncore/cutestuff/httppoll.h | 6 +- src/irisnet/noncore/cutestuff/socks.cpp | 2 +- src/irisnet/noncore/cutestuff/socks.h | 6 +- src/irisnet/noncore/ice176.cpp | 12 +-- src/irisnet/noncore/ice176.h | 2 +- src/irisnet/noncore/icecomponent.cpp | 22 +++--- src/irisnet/noncore/icecomponent.h | 4 +- src/irisnet/noncore/icelocaltransport.cpp | 40 +++++----- src/irisnet/noncore/icelocaltransport.h | 2 +- src/irisnet/noncore/icetransport.h | 2 +- src/irisnet/noncore/iceturntransport.h | 2 +- src/irisnet/noncore/legacy/ndns.h | 2 +- src/irisnet/noncore/legacy/srvresolver.h | 2 +- src/irisnet/noncore/processquit.cpp | 16 ++-- src/irisnet/noncore/stunallocate.cpp | 24 +++--- src/irisnet/noncore/stunallocate.h | 4 +- src/irisnet/noncore/stunbinding.cpp | 8 +- src/irisnet/noncore/stunmessage.cpp | 4 +- src/irisnet/noncore/stunmessage.h | 2 +- src/irisnet/noncore/stuntransaction.cpp | 4 +- src/irisnet/noncore/stuntransaction.h | 6 +- src/irisnet/noncore/stuntypes.cpp | 4 +- src/irisnet/noncore/tcpportreserver.cpp | 2 +- src/irisnet/noncore/turnclient.cpp | 26 +++---- src/irisnet/noncore/turnclient.h | 2 +- src/irisnet/noncore/udpportreserver.cpp | 2 +- src/irisnet/noncore/udpportreserver.h | 4 +- src/xmpp/jid/jid.cpp | 2 +- src/xmpp/xmpp-core/connector.cpp | 6 +- src/xmpp/xmpp-core/parser.cpp | 28 +++---- src/xmpp/xmpp-core/protocol.cpp | 4 +- src/xmpp/xmpp-core/securestream.cpp | 2 +- src/xmpp/xmpp-core/simplesasl.cpp | 2 +- src/xmpp/xmpp-core/sm.h | 2 +- src/xmpp/xmpp-core/stream.cpp | 18 ++--- src/xmpp/xmpp-core/xmpp.h | 6 +- src/xmpp/xmpp-core/xmpp_clientstream.h | 4 +- src/xmpp/xmpp-core/xmpp_stanza.cpp | 12 +-- src/xmpp/xmpp-core/xmpp_stream.h | 2 +- src/xmpp/xmpp-im/client.cpp | 4 +- src/xmpp/xmpp-im/filetransfer.cpp | 16 ++-- src/xmpp/xmpp-im/filetransfer.h | 2 +- src/xmpp/xmpp-im/jingle.cpp | 8 +- src/xmpp/xmpp-im/jingle.h | 2 +- src/xmpp/xmpp-im/s5b.cpp | 86 ++++++++++----------- src/xmpp/xmpp-im/s5b.h | 4 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 2 +- src/xmpp/xmpp-im/xmpp_bytestream.h | 2 +- src/xmpp/xmpp-im/xmpp_client.h | 2 +- src/xmpp/xmpp-im/xmpp_features.cpp | 2 +- src/xmpp/xmpp-im/xmpp_ibb.cpp | 10 +-- src/xmpp/xmpp-im/xmpp_tasks.cpp | 6 +- src/xmpp/zlib/common.h | 8 +- 71 files changed, 286 insertions(+), 286 deletions(-) diff --git a/src/irisnet/corelib/addressresolver.cpp b/src/irisnet/corelib/addressresolver.cpp index 33a54578..cc2e1b1c 100644 --- a/src/irisnet/corelib/addressresolver.cpp +++ b/src/irisnet/corelib/addressresolver.cpp @@ -66,7 +66,7 @@ class AddressResolver::Private : public QObject ~Private() { opTimer->disconnect(this); - opTimer->setParent(0); + opTimer->setParent(nullptr); opTimer->deleteLater(); } diff --git a/src/irisnet/corelib/addressresolver.h b/src/irisnet/corelib/addressresolver.h index c4186b79..8d419820 100644 --- a/src/irisnet/corelib/addressresolver.h +++ b/src/irisnet/corelib/addressresolver.h @@ -35,7 +35,7 @@ class AddressResolver : public QObject ErrorGeneric }; - AddressResolver(QObject *parent = 0); + AddressResolver(QObject *parent = nullptr); ~AddressResolver(); void start(const QByteArray &hostName); diff --git a/src/irisnet/corelib/irisnetglobal.cpp b/src/irisnet/corelib/irisnetglobal.cpp index baee4c95..bc10deb8 100644 --- a/src/irisnet/corelib/irisnetglobal.cpp +++ b/src/irisnet/corelib/irisnetglobal.cpp @@ -57,14 +57,14 @@ class PluginInstance if(!loader->load()) { delete loader; - return 0; + return nullptr; } QObject *obj = loader->instance(); if(!obj) { loader->unload(); delete loader; - return 0; + return nullptr; } PluginInstance *i = new PluginInstance; i->_loader = loader; @@ -76,7 +76,7 @@ class PluginInstance static PluginInstance *fromStatic(QObject *obj) { PluginInstance *i = new PluginInstance; - i->_loader = 0; + i->_loader = nullptr; i->_instance = obj; i->_ownInstance = false; return i; @@ -85,7 +85,7 @@ class PluginInstance static PluginInstance *fromInstance(QObject *obj) { PluginInstance *i = new PluginInstance; - i->_loader = 0; + i->_loader = nullptr; i->_instance = obj; i->_ownInstance = true; return i; @@ -108,7 +108,7 @@ class PluginInstance if(_loader) _loader->moveToThread(0); if(_ownInstance) - _instance->moveToThread(0); + _instance->moveToThread(nullptr); } QObject *instance() @@ -244,7 +244,7 @@ class IrisNetGlobal }; Q_GLOBAL_STATIC(QMutex, global_mutex) -static IrisNetGlobal *global = 0; +static IrisNetGlobal *global = nullptr; static void deinit(); @@ -267,7 +267,7 @@ void deinit() (global->cleanupList.takeFirst())(); delete global; - global = 0; + global = nullptr; } //---------------------------------------------------------------------------- diff --git a/src/irisnet/corelib/irisnetplugin.cpp b/src/irisnet/corelib/irisnetplugin.cpp index fb7b8754..ead49f5e 100644 --- a/src/irisnet/corelib/irisnetplugin.cpp +++ b/src/irisnet/corelib/irisnetplugin.cpp @@ -25,32 +25,32 @@ namespace XMPP { //---------------------------------------------------------------------------- NetInterfaceProvider *IrisNetProvider::createNetInterfaceProvider() { - return 0; + return nullptr; } NetGatewayProvider *IrisNetProvider::createNetGatewayProvider() { - return 0; + return nullptr; } NetAvailabilityProvider *IrisNetProvider::createNetAvailabilityProvider() { - return 0; + return nullptr; } NameProvider *IrisNetProvider::createNameProviderInternet() { - return 0; + return nullptr; } NameProvider *IrisNetProvider::createNameProviderLocal() { - return 0; + return nullptr; } ServiceProvider *IrisNetProvider::createServiceProvider() { - return 0; + return nullptr; } //---------------------------------------------------------------------------- diff --git a/src/irisnet/corelib/irisnetplugin.h b/src/irisnet/corelib/irisnetplugin.h index 88fad7f1..97274c21 100644 --- a/src/irisnet/corelib/irisnetplugin.h +++ b/src/irisnet/corelib/irisnetplugin.h @@ -58,7 +58,7 @@ class IRISNET_EXPORT NetInterfaceProvider : public QObject QList addresses; }; - NetInterfaceProvider(QObject *parent = 0) : + NetInterfaceProvider(QObject *parent = nullptr) : QObject(parent) { } @@ -84,7 +84,7 @@ class IRISNET_EXPORT NetGatewayProvider : public QObject QHostAddress gateway; }; - NetGatewayProvider(QObject *parent = 0) : + NetGatewayProvider(QObject *parent = nullptr) : QObject(parent) { } @@ -103,7 +103,7 @@ class IRISNET_EXPORT NetAvailabilityProvider : public QObject Q_OBJECT public: - NetAvailabilityProvider(QObject *parent = 0) : + NetAvailabilityProvider(QObject *parent = nullptr) : QObject(parent) { } @@ -122,7 +122,7 @@ class IRISNET_EXPORT NameProvider : public QObject Q_OBJECT public: - NameProvider(QObject *parent = 0) : + NameProvider(QObject *parent = nullptr) : QObject(parent) { } @@ -160,7 +160,7 @@ class IRISNET_EXPORT ServiceProvider : public QObject QByteArray hostName; // optional }; - ServiceProvider(QObject *parent = 0) : + ServiceProvider(QObject *parent = nullptr) : QObject(parent) { } diff --git a/src/irisnet/corelib/netavailability.h b/src/irisnet/corelib/netavailability.h index a53c45bf..ad4e2b6e 100644 --- a/src/irisnet/corelib/netavailability.h +++ b/src/irisnet/corelib/netavailability.h @@ -28,7 +28,7 @@ class NetAvailability : public QObject Q_OBJECT public: - NetAvailability(QObject *parent = 0); + NetAvailability(QObject *parent = nullptr); ~NetAvailability(); bool isAvailable() const; diff --git a/src/irisnet/corelib/netinterface.cpp b/src/irisnet/corelib/netinterface.cpp index a4459c50..79dc04f2 100644 --- a/src/irisnet/corelib/netinterface.cpp +++ b/src/irisnet/corelib/netinterface.cpp @@ -42,7 +42,7 @@ class NetTracker : public QObject { NetTracker() { QList list = irisNetProviders(); - c = 0; + c = nullptr; foreach(IrisNetProvider* p, list) { c = p->createNetInterfaceProvider(); if(c) break; @@ -123,7 +123,7 @@ class NetTrackerThread : public QThread { exit(0); wait(); delete this; - self = 0; + self = nullptr; } } @@ -151,7 +151,7 @@ class NetTrackerThread : public QThread { startCond.wait(startMutex); // wait for thread startup finished } delete startMutex; - startMutex = 0; + startMutex = nullptr; } void run() { @@ -165,7 +165,7 @@ class NetTrackerThread : public QThread { } exec(); delete nettracker; - nettracker = 0; + nettracker = nullptr; } private: @@ -177,7 +177,7 @@ class NetTrackerThread : public QThread { NetTracker *nettracker; }; -NetTrackerThread *NetTrackerThread::self = 0; +NetTrackerThread *NetTrackerThread::self = nullptr; //---------------------------------------------------------------------------- @@ -277,7 +277,7 @@ class NetInterfaceManagerPrivate : public QObject ~NetInterfaceManagerPrivate() { tracker->releaseRef(); - tracker = 0; + tracker = nullptr; } static int lookup(const QList &list, const QString &id) @@ -401,7 +401,7 @@ void *NetInterfaceManager::reg(const QString &id, NetInterface *i) return new NetInterfaceProvider::Info(d->info[n]); } } - return 0; + return nullptr; } void NetInterfaceManager::unreg(NetInterface *i) diff --git a/src/irisnet/corelib/netinterface.h b/src/irisnet/corelib/netinterface.h index a384c2dc..05fa8eb1 100644 --- a/src/irisnet/corelib/netinterface.h +++ b/src/irisnet/corelib/netinterface.h @@ -148,7 +148,7 @@ class IRISNET_EXPORT NetInterfaceManager : public QObject /** \brief Constructs a new manager object with the given \a parent */ - NetInterfaceManager(QObject *parent = 0); + NetInterfaceManager(QObject *parent = nullptr); /** \brief Destroys the manager object diff --git a/src/irisnet/corelib/netinterface_qtname.cpp b/src/irisnet/corelib/netinterface_qtname.cpp index e9a57a99..f217aef8 100644 --- a/src/irisnet/corelib/netinterface_qtname.cpp +++ b/src/irisnet/corelib/netinterface_qtname.cpp @@ -37,7 +37,7 @@ class IrisQtName : public NameProvider QHash hostInfo; // we need all these tricks with double mapping because we still support Qt 5.5.1. (5.12 is way better) public: - IrisQtName(QObject *parent = 0) : + IrisQtName(QObject *parent = nullptr) : NameProvider(parent), currentId(0) { diff --git a/src/irisnet/corelib/netinterface_unix.cpp b/src/irisnet/corelib/netinterface_unix.cpp index 3459d152..706d6d30 100644 --- a/src/irisnet/corelib/netinterface_unix.cpp +++ b/src/irisnet/corelib/netinterface_unix.cpp @@ -119,7 +119,7 @@ static QList get_linux_gateways() if(addr.isNull()) continue; - int iflags = parts[3].toInt(0, 16); + int iflags = parts[3].toInt(nullptr, 16); if(!(iflags & RTF_UP)) continue; @@ -144,7 +144,7 @@ static QList get_linux_gateways() if(addr.isNull()) continue; - int iflags = parts[8].toInt(0, 16); + int iflags = parts[8].toInt(nullptr, 16); if(!(iflags & RTF_UP)) continue; diff --git a/src/irisnet/corelib/netnames.cpp b/src/irisnet/corelib/netnames.cpp index 3e1e5a8b..97fbd20f 100644 --- a/src/irisnet/corelib/netnames.cpp +++ b/src/irisnet/corelib/netnames.cpp @@ -444,7 +444,7 @@ QByteArray ServiceInstance::name() const class NameManager; Q_GLOBAL_STATIC(QMutex, nman_mutex) -static NameManager *g_nman = 0; +static NameManager *g_nman = nullptr; class NameResolver::Private { @@ -706,10 +706,10 @@ class NameManager : public QObject QHash sres_instances; QHash slp_instances; - NameManager(QObject *parent = 0) : QObject(parent) + NameManager(QObject *parent = nullptr) : QObject(parent) { - p_net = 0; - p_local = 0; + p_net = nullptr; + p_local = nullptr; p_serv = 0; } @@ -734,7 +734,7 @@ class NameManager : public QObject static void cleanup() { delete g_nman; - g_nman = 0; + g_nman = nullptr; } void resolve_start(NameResolver::Private *np, const QByteArray &name, int qType, bool longLived) @@ -802,7 +802,7 @@ class NameManager : public QObject res_instances.remove(np->id); NameResolver *q = np->q; delete q->d; - q->d = 0; + q->d = nullptr; } void browse_start(ServiceBrowser::Private *np, const QString &type, const QString &domain) @@ -811,7 +811,7 @@ class NameManager : public QObject if(!p_serv) { - ServiceProvider *c = 0; + ServiceProvider *c = nullptr; QList list = irisNetProviders(); for(int n = 0; n < list.count(); ++n) { @@ -845,7 +845,7 @@ class NameManager : public QObject if(!p_serv) { - ServiceProvider *c = 0; + ServiceProvider *c = nullptr; QList list = irisNetProviders(); for(int n = 0; n < list.count(); ++n) { @@ -875,7 +875,7 @@ class NameManager : public QObject if(!p_serv) { - ServiceProvider *c = 0; + ServiceProvider *c = nullptr; QList list = irisNetProviders(); for(int n = 0; n < list.count(); ++n) { @@ -944,7 +944,7 @@ private slots: // transfer to local if(!p_local) { - NameProvider *c = 0; + NameProvider *c = nullptr; QList list = irisNetProviders(); for(int n = 0; n < list.count(); ++n) { @@ -1064,7 +1064,7 @@ static int recordType2Rtype(NameRecord::Type type) NameResolver::NameResolver(QObject *parent) :QObject(parent) { - d = 0; + d = nullptr; } NameResolver::~NameResolver() @@ -1088,7 +1088,7 @@ void NameResolver::stop() { NameManager::instance()->resolve_stop(d); delete d; - d = 0; + d = nullptr; } } diff --git a/src/irisnet/corelib/netnames.h b/src/irisnet/corelib/netnames.h index ee5ee350..76f8bffd 100644 --- a/src/irisnet/corelib/netnames.h +++ b/src/irisnet/corelib/netnames.h @@ -421,7 +421,7 @@ class IRISNET_EXPORT NameResolver : public QObject /** \brief Constructs a new resolver object with the given \a parent */ - NameResolver(QObject *parent = 0); + NameResolver(QObject *parent = nullptr); /** \brief Destroys the resolver object @@ -523,7 +523,7 @@ class IRISNET_EXPORT ServiceBrowser : public QObject ErrorNoWide }; - ServiceBrowser(QObject *parent = 0); + ServiceBrowser(QObject *parent = nullptr); ~ServiceBrowser(); void start(const QString &type, const QString &domain = "local"); @@ -589,7 +589,7 @@ class IRISNET_EXPORT ServiceResolver : public QObject * Create a new ServiceResolver. * This resolver can be used for multiple lookups in a row, but not concurrently! */ - ServiceResolver(QObject *parent = 0); + ServiceResolver(QObject *parent = nullptr); ~ServiceResolver(); Protocol protocol() const; //!< IP protocol to use, defaults to IPv6_IPv4 @@ -675,7 +675,7 @@ class IRISNET_EXPORT ServiceLocalPublisher : public QObject ErrorNoLocal // unable to setup multicast dns }; - ServiceLocalPublisher(QObject *parent = 0); + ServiceLocalPublisher(QObject *parent = nullptr); ~ServiceLocalPublisher(); void publish(const QString &instance, const QString &type, int port, const QMap &attributes); diff --git a/src/irisnet/corelib/objectsession.cpp b/src/irisnet/corelib/objectsession.cpp index e3218e4e..ab8030d1 100644 --- a/src/irisnet/corelib/objectsession.cpp +++ b/src/irisnet/corelib/objectsession.cpp @@ -102,7 +102,7 @@ class ObjectSessionPrivate : public QObject for(int n = 0; n < 10; ++n) { - if(arg_name[n] == 0) + if(arg_name[n] == nullptr) break; Argument arg; @@ -141,7 +141,7 @@ class ObjectSessionPrivate : public QObject invalidateWatchers(); callTrigger->disconnect(this); - callTrigger->setParent(0); + callTrigger->setParent(nullptr); callTrigger->deleteLater(); qDeleteAll(pendingCalls); pendingCalls.clear(); @@ -167,7 +167,7 @@ class ObjectSessionPrivate : public QObject void invalidateWatchers() { for(int n = 0; n < watchers.count(); ++n) - watchers[n]->sess = 0; + watchers[n]->sess = nullptr; watchers.clear(); } diff --git a/src/irisnet/corelib/objectsession.h b/src/irisnet/corelib/objectsession.h index bcae574b..04a13b2e 100644 --- a/src/irisnet/corelib/objectsession.h +++ b/src/irisnet/corelib/objectsession.h @@ -31,7 +31,7 @@ class ObjectSession : public QObject Q_OBJECT public: - ObjectSession(QObject *parent = 0); + ObjectSession(QObject *parent = nullptr); ~ObjectSession(); // clear all deferred requests, invalidate watchers diff --git a/src/irisnet/noncore/cutestuff/bsocket.cpp b/src/irisnet/noncore/cutestuff/bsocket.cpp index d3a366ce..12254aa6 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.cpp +++ b/src/irisnet/noncore/cutestuff/bsocket.cpp @@ -41,7 +41,7 @@ class QTcpSocketSignalRelay : public QObject { Q_OBJECT public: - QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = 0) + QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = nullptr) :QObject(parent) { qRegisterMetaType("QAbstractSocket::SocketError"); @@ -143,7 +143,7 @@ class HappyEyeballsConnector : public QObject sd.sock->setProxy(QNetworkProxy::NoProxy); sd.sock->setReadBufferSize(READBUFSIZE); sd.relay = new QTcpSocketSignalRelay(sd.sock, this); - sd.resolver = 0; + sd.resolver = nullptr; connect(sd.relay, SIGNAL(connected()), SLOT(qs_connected())); connect(sd.relay, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(qs_error(QAbstractSocket::SocketError))); sockets.append(sd); diff --git a/src/irisnet/noncore/cutestuff/bsocket.h b/src/irisnet/noncore/cutestuff/bsocket.h index 1a5d08ad..21b41895 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.h +++ b/src/irisnet/noncore/cutestuff/bsocket.h @@ -43,7 +43,7 @@ class BSocket : public ByteStream public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound }; enum State { Idle, HostLookup, Connecting, Connected, Closing }; - BSocket(QObject *parent=0); + BSocket(QObject *parent=nullptr); ~BSocket(); /*! Connect to an already resolved host */ diff --git a/src/irisnet/noncore/cutestuff/httpconnect.h b/src/irisnet/noncore/cutestuff/httpconnect.h index e3285322..297a58c7 100644 --- a/src/irisnet/noncore/cutestuff/httpconnect.h +++ b/src/irisnet/noncore/cutestuff/httpconnect.h @@ -29,7 +29,7 @@ class HttpConnect : public ByteStream Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpConnect(QObject *parent=0); + HttpConnect(QObject *parent=nullptr); ~HttpConnect(); void setAuth(const QString &user, const QString &pass=""); diff --git a/src/irisnet/noncore/cutestuff/httppoll.cpp b/src/irisnet/noncore/cutestuff/httppoll.cpp index 133f40d4..6d88a97d 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.cpp +++ b/src/irisnet/noncore/cutestuff/httppoll.cpp @@ -443,7 +443,7 @@ class HttpProxyPost::Private public: Private(HttpProxyPost *_q) : sock(_q), - tls(0) + tls(nullptr) { } @@ -774,7 +774,7 @@ HttpProxyGetStream::HttpProxyGetStream(QObject *parent) :QObject(parent) { d = new Private(this); - d->tls = 0; + d->tls = nullptr; connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected())); connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed())); connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead())); @@ -792,7 +792,7 @@ void HttpProxyGetStream::resetConnection(bool /*clear*/) { if(d->tls) { delete d->tls; - d->tls = 0; + d->tls = nullptr; } if(d->sock.state() != BSocket::Idle) d->sock.close(); diff --git a/src/irisnet/noncore/cutestuff/httppoll.h b/src/irisnet/noncore/cutestuff/httppoll.h index 82bf1f06..53c45d1a 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.h +++ b/src/irisnet/noncore/cutestuff/httppoll.h @@ -31,7 +31,7 @@ class HttpPoll : public ByteStream Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpPoll(QObject *parent=0); + HttpPoll(QObject *parent=nullptr); ~HttpPoll(); virtual QAbstractSocket* abstractSocket() const; @@ -75,7 +75,7 @@ class HttpProxyPost : public QObject Q_OBJECT public: enum Error { ErrConnectionRefused, ErrHostNotFound, ErrSocket, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpProxyPost(QObject *parent=0); + HttpProxyPost(QObject *parent=nullptr); ~HttpProxyPost(); QAbstractSocket* abstractSocket() const; @@ -114,7 +114,7 @@ class HttpProxyGetStream : public QObject Q_OBJECT public: enum Error { ErrConnectionRefused, ErrHostNotFound, ErrSocket, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpProxyGetStream(QObject *parent=0); + HttpProxyGetStream(QObject *parent=nullptr); ~HttpProxyGetStream(); void setAuth(const QString &user, const QString &pass=""); diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index 2dbc8272..faef4509 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -1093,7 +1093,7 @@ QHostAddress SocksServer::address() const SocksClient *SocksServer::takeIncoming() { if(d->incomingConns.isEmpty()) - return 0; + return nullptr; SocksClient *c = d->incomingConns.takeFirst(); diff --git a/src/irisnet/noncore/cutestuff/socks.h b/src/irisnet/noncore/cutestuff/socks.h index eb3811db..d07d6c4a 100644 --- a/src/irisnet/noncore/cutestuff/socks.h +++ b/src/irisnet/noncore/cutestuff/socks.h @@ -60,8 +60,8 @@ class SocksClient : public ByteStream enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; enum Method { AuthNone=0x0001, AuthUsername=0x0002 }; enum Request { ReqConnect, ReqUDPAssociate }; - SocksClient(QObject *parent=0); - SocksClient(QTcpSocket *, QObject *parent=0); + SocksClient(QObject *parent=nullptr); + SocksClient(QTcpSocket *, QObject *parent=nullptr); ~SocksClient(); virtual QAbstractSocket* abstractSocket() const; @@ -133,7 +133,7 @@ class SocksServer : public QObject { Q_OBJECT public: - SocksServer(QObject *parent=0); + SocksServer(QObject *parent=nullptr); ~SocksServer(); void setServerSocket(QTcpServer *server); diff --git a/src/irisnet/noncore/ice176.cpp b/src/irisnet/noncore/ice176.cpp index fb417602..a4cbe59f 100644 --- a/src/irisnet/noncore/ice176.cpp +++ b/src/irisnet/noncore/ice176.cpp @@ -158,8 +158,8 @@ class Ice176::Private : public QObject StunTransactionPool *pool; CandidatePair() : - binding(0), - pool(0) + binding(nullptr), + pool(nullptr) { } }; @@ -224,14 +224,14 @@ class Ice176::Private : public QObject QObject(_q), q(_q), state(Stopped), - portReserver(0), + portReserver(nullptr), componentCount(0), useLocal(true), useStunBind(true), useStunRelayUdp(true), useStunRelayTcp(true), useTrickle(false), - collectTimer(0) + collectTimer(nullptr) { } @@ -792,7 +792,7 @@ private slots: if(pool) { pool->disconnect(this); - pool->setParent(0); + pool->setParent(nullptr); pool->deleteLater(); } @@ -910,7 +910,7 @@ private slots: { collectTimer->disconnect(this); collectTimer->deleteLater(); - collectTimer = 0; + collectTimer = nullptr; QList list; foreach(const IceComponent::Candidate &cc, localCandidates) diff --git a/src/irisnet/noncore/ice176.h b/src/irisnet/noncore/ice176.h index ac120af8..159f908e 100644 --- a/src/irisnet/noncore/ice176.h +++ b/src/irisnet/noncore/ice176.h @@ -105,7 +105,7 @@ class Ice176 : public QObject } }; - Ice176(QObject *parent = 0); + Ice176(QObject *parent = nullptr); ~Ice176(); void reset(); diff --git a/src/irisnet/noncore/icecomponent.cpp b/src/irisnet/noncore/icecomponent.cpp index b27c7006..cbd873d4 100644 --- a/src/irisnet/noncore/icecomponent.cpp +++ b/src/irisnet/noncore/icecomponent.cpp @@ -81,9 +81,9 @@ class IceComponent::Private : public QObject bool ext_finished; LocalTransport() : - qsock(0), + qsock(nullptr), borrowedSocket(false), - sock(0), + sock(nullptr), network(-1), isVpn(false), started(false), @@ -120,9 +120,9 @@ class IceComponent::Private : public QObject QObject(_q), q(_q), sess(this), - portReserver(0), + portReserver(nullptr), stopping(false), - tt(0), + tt(nullptr), useLocal(true), useStunBind(true), useStunRelayUdp(true), @@ -180,7 +180,7 @@ class IceComponent::Private : public QObject continue; } - QUdpSocket *qsock = 0; + QUdpSocket *qsock = nullptr; if(socketList) qsock = takeFromSocketList(socketList, la.addr, this); @@ -444,7 +444,7 @@ class IceComponent::Private : public QObject return calc_priority(typePref, localPref, componentId); } - static QUdpSocket *takeFromSocketList(QList *socketList, const QHostAddress &addr, QObject *parent = 0) + static QUdpSocket *takeFromSocketList(QList *socketList, const QHostAddress &addr, QObject *parent = nullptr) { for(int n = 0; n < socketList->count(); ++n) { @@ -456,7 +456,7 @@ class IceComponent::Private : public QObject } } - return 0; + return nullptr; } int getId() const @@ -727,7 +727,7 @@ private slots: return; delete lt->sock; - lt->sock = 0; + lt->sock = nullptr; if(isLocalLeap) { @@ -857,7 +857,7 @@ private slots: return; delete lt->sock; - lt->sock = 0; + lt->sock = nullptr; if(isLocalLeap) { @@ -915,7 +915,7 @@ private slots: return; delete tt; - tt = 0; + tt = nullptr; tryStopped(); } @@ -931,7 +931,7 @@ private slots: return; delete tt; - tt = 0; + tt = nullptr; } void tt_debugLine(const QString &line) diff --git a/src/irisnet/noncore/icecomponent.h b/src/irisnet/noncore/icecomponent.h index 94320ce1..215cc478 100644 --- a/src/irisnet/noncore/icecomponent.h +++ b/src/irisnet/noncore/icecomponent.h @@ -113,7 +113,7 @@ class IceComponent : public QObject DL_Packet }; - IceComponent(int id, QObject *parent = 0); + IceComponent(int id, QObject *parent = nullptr); ~IceComponent(); int id() const; @@ -143,7 +143,7 @@ class IceComponent : public QObject void setUseStunRelayTcp(bool enabled); // if socketList is not null then port reserver must be set - void update(QList *socketList = 0); + void update(QList *socketList = nullptr); void stop(); // prflx priority to use when replying from this transport/path diff --git a/src/irisnet/noncore/icelocaltransport.cpp b/src/irisnet/noncore/icelocaltransport.cpp index f9229f4e..28ff5e3f 100644 --- a/src/irisnet/noncore/icelocaltransport.cpp +++ b/src/irisnet/noncore/icelocaltransport.cpp @@ -53,7 +53,7 @@ class SafeUdpSocket : public QObject int writtenCount; public: - SafeUdpSocket(QUdpSocket *_sock, QObject *parent = 0) : + SafeUdpSocket(QUdpSocket *_sock, QObject *parent = nullptr) : QObject(parent), sess(this), sock(_sock) @@ -77,9 +77,9 @@ class SafeUdpSocket : public QObject QUdpSocket *release() { sock->disconnect(this); - sock->setParent(0); + sock->setParent(nullptr); QUdpSocket *out = sock; - sock = 0; + sock = nullptr; return out; } @@ -98,7 +98,7 @@ class SafeUdpSocket : public QObject return sock->hasPendingDatagrams(); } - QByteArray readDatagram(QHostAddress *address = 0, quint16 *port = 0) + QByteArray readDatagram(QHostAddress *address = nullptr, quint16 *port = nullptr) { if(!sock->hasPendingDatagrams()) return QByteArray(); @@ -212,11 +212,11 @@ class IceLocalTransport::Private : public QObject QObject(_q), q(_q), sess(this), - extSock(0), - sock(0), - pool(0), - stunBinding(0), - turn(0), + extSock(nullptr), + sock(nullptr), + pool(nullptr), + stunBinding(nullptr), + turn(nullptr), turnActivated(false), port(-1), refPort(-1), @@ -237,10 +237,10 @@ class IceLocalTransport::Private : public QObject sess.reset(); delete stunBinding; - stunBinding = 0; + stunBinding = nullptr; delete turn; - turn = 0; + turn = nullptr; turnActivated = false; if(sock) @@ -248,11 +248,11 @@ class IceLocalTransport::Private : public QObject if(extSock) { sock->release(); - extSock = 0; + extSock = nullptr; } delete sock; - sock = 0; + sock = nullptr; } addr = QHostAddress(); @@ -350,7 +350,7 @@ class IceLocalTransport::Private : public QObject { delete qsock; emit q->error(IceLocalTransport::ErrorBind); - return 0; + return nullptr; } return qsock; @@ -379,7 +379,7 @@ class IceLocalTransport::Private : public QObject emit q->debugLine("retrying..."); delete sock; - sock = 0; + sock = nullptr; // to receive this error, it is a Relay, so change // the mode @@ -619,7 +619,7 @@ private slots: refPort = stunBinding->reflexivePort(); delete stunBinding; - stunBinding = 0; + stunBinding = nullptr; emit q->addressesChanged(); } @@ -629,7 +629,7 @@ private slots: Q_UNUSED(e); delete stunBinding; - stunBinding = 0; + stunBinding = nullptr; // don't report any error //if(stunType == IceLocalTransport::Basic || (stunType == IceLocalTransport::Auto && !turn)) @@ -654,7 +654,7 @@ private slots: emit q->debugLine("turn_closed"); delete turn; - turn = 0; + turn = nullptr; turnActivated = false; postStop(); @@ -696,7 +696,7 @@ private slots: emit q->debugLine(QString("turn_error: ") + turn->errorString()); delete turn; - turn = 0; + turn = nullptr; bool wasActivated = turnActivated; turnActivated = false; @@ -833,7 +833,7 @@ bool IceLocalTransport::hasPendingDatagrams(int path) const QByteArray IceLocalTransport::readDatagram(int path, QHostAddress *addr, int *port) { - QList *in = 0; + QList *in = nullptr; if(path == Direct) in = &d->in; else if(path == Relayed) diff --git a/src/irisnet/noncore/icelocaltransport.h b/src/irisnet/noncore/icelocaltransport.h index e413c095..0e571bf9 100644 --- a/src/irisnet/noncore/icelocaltransport.h +++ b/src/irisnet/noncore/icelocaltransport.h @@ -46,7 +46,7 @@ class IceLocalTransport : public IceTransport ErrorBind = ErrorCustom }; - IceLocalTransport(QObject *parent = 0); + IceLocalTransport(QObject *parent = nullptr); ~IceLocalTransport(); void setClientSoftwareNameAndVersion(const QString &str); diff --git a/src/irisnet/noncore/icetransport.h b/src/irisnet/noncore/icetransport.h index 82776069..be673e95 100644 --- a/src/irisnet/noncore/icetransport.h +++ b/src/irisnet/noncore/icetransport.h @@ -44,7 +44,7 @@ class IceTransport : public QObject DL_Packet }; - IceTransport(QObject *parent = 0); + IceTransport(QObject *parent = nullptr); ~IceTransport(); virtual void stop() = 0; diff --git a/src/irisnet/noncore/iceturntransport.h b/src/irisnet/noncore/iceturntransport.h index 46677a08..32f344d8 100644 --- a/src/irisnet/noncore/iceturntransport.h +++ b/src/irisnet/noncore/iceturntransport.h @@ -39,7 +39,7 @@ class IceTurnTransport : public IceTransport ErrorTurn = ErrorCustom }; - IceTurnTransport(QObject *parent = 0); + IceTurnTransport(QObject *parent = nullptr); ~IceTurnTransport(); void setClientSoftwareNameAndVersion(const QString &str); diff --git a/src/irisnet/noncore/legacy/ndns.h b/src/irisnet/noncore/legacy/ndns.h index 8b74b8eb..46561faa 100644 --- a/src/irisnet/noncore/legacy/ndns.h +++ b/src/irisnet/noncore/legacy/ndns.h @@ -30,7 +30,7 @@ class NDns : public QObject { Q_OBJECT public: - NDns(QObject *parent=0); + NDns(QObject *parent=nullptr); ~NDns(); void resolve(const QString &); diff --git a/src/irisnet/noncore/legacy/srvresolver.h b/src/irisnet/noncore/legacy/srvresolver.h index 07dca3df..f350677b 100644 --- a/src/irisnet/noncore/legacy/srvresolver.h +++ b/src/irisnet/noncore/legacy/srvresolver.h @@ -46,7 +46,7 @@ class SrvResolver : public QObject { Q_OBJECT public: - SrvResolver(QObject *parent=0); + SrvResolver(QObject *parent=nullptr); ~SrvResolver(); void resolve(const QString &server, const QString &type, const QString &proto); diff --git a/src/irisnet/noncore/processquit.cpp b/src/irisnet/noncore/processquit.cpp index cc6935c8..8560b503 100644 --- a/src/irisnet/noncore/processquit.cpp +++ b/src/irisnet/noncore/processquit.cpp @@ -42,7 +42,7 @@ namespace { void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); - obj->setParent(0); + obj->setParent(nullptr); obj->deleteLater(); } @@ -51,7 +51,7 @@ class SafeSocketNotifier : public QObject Q_OBJECT public: SafeSocketNotifier(int socket, QSocketNotifier::Type type, - QObject *parent = 0) : + QObject *parent = nullptr) : QObject(parent) { sn = new QSocketNotifier(socket, type, this); @@ -85,7 +85,7 @@ namespace XMPP { #endif Q_GLOBAL_STATIC(QMutex, pq_mutex) -static ProcessQuit *g_pq = 0; +static ProcessQuit *g_pq = nullptr; inline bool is_gui_app() { @@ -174,7 +174,7 @@ class ProcessQuit::Private : public QObject void unixWatchAdd(int sig) { struct sigaction sa; - sigaction(sig, NULL, &sa); + sigaction(sig, nullptr, &sa); // if the signal is ignored, don't take it over. this is // recommended by the glibc manual if(sa.sa_handler == SIG_IGN) @@ -182,13 +182,13 @@ class ProcessQuit::Private : public QObject sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; sa.sa_handler = unixHandler; - sigaction(sig, &sa, 0); + sigaction(sig, &sa, nullptr); } void unixWatchRemove(int sig) { struct sigaction sa; - sigaction(sig, NULL, &sa); + sigaction(sig, nullptr, &sa); // ignored means we skipped it earlier, so we should // skip it again if(sa.sa_handler == SIG_IGN) @@ -196,7 +196,7 @@ class ProcessQuit::Private : public QObject sigemptyset(&(sa.sa_mask)); sa.sa_flags = 0; sa.sa_handler = SIG_DFL; - sigaction(sig, &sa, 0); + sigaction(sig, &sa, nullptr); } #endif @@ -269,7 +269,7 @@ void ProcessQuit::reset() void ProcessQuit::cleanup() { delete g_pq; - g_pq = 0; + g_pq = nullptr; } #ifndef NO_IRISNET diff --git a/src/irisnet/noncore/stunallocate.cpp b/src/irisnet/noncore/stunallocate.cpp index ef027a0f..91ff75c4 100644 --- a/src/irisnet/noncore/stunallocate.cpp +++ b/src/irisnet/noncore/stunallocate.cpp @@ -39,7 +39,7 @@ namespace XMPP { void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); - obj->setParent(0); + obj->setParent(nullptr); obj->deleteLater(); } @@ -96,7 +96,7 @@ class StunAllocatePermission : public QObject StunAllocatePermission(StunTransactionPool *_pool, const QHostAddress &_addr) : QObject(_pool), pool(_pool), - trans(0), + trans(nullptr), addr(_addr), active(false) { @@ -149,7 +149,7 @@ class StunAllocatePermission : public QObject void cleanup() { delete trans; - trans = 0; + trans = nullptr; timer->stop(); @@ -200,7 +200,7 @@ private slots: void trans_finished(const XMPP::StunMessage &response) { delete trans; - trans = 0; + trans = nullptr; bool err = false; int code; @@ -284,7 +284,7 @@ class StunAllocateChannel : public QObject StunAllocateChannel(StunTransactionPool *_pool, int _channelId, const QHostAddress &_addr, int _port) : QObject(_pool), pool(_pool), - trans(0), + trans(nullptr), channelId(_channelId), addr(_addr), port(_port), @@ -339,7 +339,7 @@ class StunAllocateChannel : public QObject void cleanup() { delete trans; - trans = 0; + trans = nullptr; timer->stop(); @@ -394,7 +394,7 @@ private slots: void trans_finished(const XMPP::StunMessage &response) { delete trans; - trans = 0; + trans = nullptr; bool err = false; int code; @@ -498,8 +498,8 @@ class StunAllocate::Private : public QObject QObject(_q), q(_q), sess(this), - pool(0), - trans(0), + pool(nullptr), + trans(nullptr), state(Stopped), dfState(DF_Unknown), erroringCode(-1) @@ -797,7 +797,7 @@ class StunAllocate::Private : public QObject void cleanupTasks() { delete trans; - trans = 0; + trans = nullptr; allocateRefreshTimer->stop(); @@ -956,7 +956,7 @@ private slots: void trans_finished(const XMPP::StunMessage &response) { delete trans; - trans = 0; + trans = nullptr; bool error = false; int code; @@ -1206,7 +1206,7 @@ private slots: void trans_error(XMPP::StunTransaction::Error e) { delete trans; - trans = 0; + trans = nullptr; cleanup(); diff --git a/src/irisnet/noncore/stunallocate.h b/src/irisnet/noncore/stunallocate.h index 9653184b..2c18011d 100644 --- a/src/irisnet/noncore/stunallocate.h +++ b/src/irisnet/noncore/stunallocate.h @@ -98,8 +98,8 @@ class StunAllocate : public QObject int packetHeaderOverhead(const QHostAddress &addr, int port) const; QByteArray encode(const QByteArray &datagram, const QHostAddress &addr, int port); - QByteArray decode(const QByteArray &encoded, QHostAddress *addr = 0, int *port = 0); - QByteArray decode(const StunMessage &encoded, QHostAddress *addr = 0, int *port = 0); + QByteArray decode(const QByteArray &encoded, QHostAddress *addr = nullptr, int *port = nullptr); + QByteArray decode(const StunMessage &encoded, QHostAddress *addr = nullptr, int *port = nullptr); QString errorString() const; diff --git a/src/irisnet/noncore/stunbinding.cpp b/src/irisnet/noncore/stunbinding.cpp index dd1fcc8f..897e1e1d 100644 --- a/src/irisnet/noncore/stunbinding.cpp +++ b/src/irisnet/noncore/stunbinding.cpp @@ -48,8 +48,8 @@ class StunBinding::Private : public QObject Private(StunBinding *_q) : QObject(_q), q(_q), - pool(0), - trans(0), + pool(nullptr), + trans(nullptr), use_extPriority(false), use_extIceControlling(false), use_extIceControlled(false), @@ -134,7 +134,7 @@ private slots: void trans_finished(const XMPP::StunMessage &response) { delete trans; - trans = 0; + trans = nullptr; bool error = false; int code; @@ -203,7 +203,7 @@ private slots: void trans_error(XMPP::StunTransaction::Error e) { delete trans; - trans = 0; + trans = nullptr; if(e == StunTransaction::ErrorTimeout) { diff --git a/src/irisnet/noncore/stunmessage.cpp b/src/irisnet/noncore/stunmessage.cpp index c60f1ffc..a6a5feec 100644 --- a/src/irisnet/noncore/stunmessage.cpp +++ b/src/irisnet/noncore/stunmessage.cpp @@ -228,7 +228,7 @@ static int get_attribute_props(const QByteArray &buf, int offset, quint16 *type, // len = take attribute value length (value is at offset + 4) // next = take offset of next attribute // returns offset of found attribute, -1 if not found -static int find_attribute(const QByteArray &buf, quint16 type, int *len, int *next = 0) +static int find_attribute(const QByteArray &buf, quint16 type, int *len, int *next = nullptr) { int at = ATTRIBUTE_AREA_START; quint16 _type; @@ -386,7 +386,7 @@ class StunMessage::Private : public QSharedData }; StunMessage::StunMessage() : - d(0) + d(nullptr) { } diff --git a/src/irisnet/noncore/stunmessage.h b/src/irisnet/noncore/stunmessage.h index 5c2369bd..dbc15fa4 100644 --- a/src/irisnet/noncore/stunmessage.h +++ b/src/irisnet/noncore/stunmessage.h @@ -82,7 +82,7 @@ class StunMessage void setAttributes(const QList &attribs); QByteArray toBinary(int validationFlags = 0, const QByteArray &key = QByteArray()) const; - static StunMessage fromBinary(const QByteArray &a, ConvertResult *result = 0, int validationFlags = 0, const QByteArray &key = QByteArray()); + static StunMessage fromBinary(const QByteArray &a, ConvertResult *result = nullptr, int validationFlags = 0, const QByteArray &key = QByteArray()); // minimal 3-field check static bool isProbablyStun(const QByteArray &a); diff --git a/src/irisnet/noncore/stuntransaction.cpp b/src/irisnet/noncore/stuntransaction.cpp index 3927cf9e..3132fccf 100644 --- a/src/irisnet/noncore/stuntransaction.cpp +++ b/src/irisnet/noncore/stuntransaction.cpp @@ -156,7 +156,7 @@ class StunTransactionPrivate : public QObject StunTransactionPrivate(StunTransaction *_q) : QObject(_q), q(_q), - pool(0), + pool(nullptr), fpRequired(false) { qRegisterMetaType(); @@ -180,7 +180,7 @@ class StunTransactionPrivate : public QObject pool->d->remove(q); t->disconnect(this); - t->setParent(0); + t->setParent(nullptr); t->deleteLater(); } diff --git a/src/irisnet/noncore/stuntransaction.h b/src/irisnet/noncore/stuntransaction.h index badcd512..e07dd45c 100644 --- a/src/irisnet/noncore/stuntransaction.h +++ b/src/irisnet/noncore/stuntransaction.h @@ -76,7 +76,7 @@ class StunTransaction : public QObject ErrorTimeout }; - StunTransaction(QObject *parent = 0); + StunTransaction(QObject *parent = nullptr); ~StunTransaction(); // toAddress/toPort are optional, to associate this request to a @@ -140,7 +140,7 @@ class StunTransactionPool : public QObject DL_Packet }; - StunTransactionPool(StunTransaction::Mode mode, QObject *parent = 0); + StunTransactionPool(StunTransaction::Mode mode, QObject *parent = nullptr); ~StunTransactionPool(); StunTransaction::Mode mode() const; @@ -157,7 +157,7 @@ class StunTransactionPool : public QObject // not be a STUN message. *notStun will be set to true if the packet // is surely not STUN, or set to false if it is unclear whether the // packet is STUN or not. - bool writeIncomingMessage(const QByteArray &packet, bool *notStun = 0, const QHostAddress &addr = QHostAddress(), int port = -1); + bool writeIncomingMessage(const QByteArray &packet, bool *notStun = nullptr, const QHostAddress &addr = QHostAddress(), int port = -1); void setLongTermAuthEnabled(bool enabled); diff --git a/src/irisnet/noncore/stuntypes.cpp b/src/irisnet/noncore/stuntypes.cpp index 0e730d4c..48487f1c 100644 --- a/src/irisnet/noncore/stuntypes.cpp +++ b/src/irisnet/noncore/stuntypes.cpp @@ -430,7 +430,7 @@ struct MethodEntry METHOD_ENTRY(Data), METHOD_ENTRY(CreatePermission), METHOD_ENTRY(ChannelBind), - { (Method)-1, 0 } + { (Method)-1, nullptr } }; QString methodToString(int method) @@ -477,7 +477,7 @@ struct AttribEntry ATTRIB_ENTRY(FINGERPRINT), ATTRIB_ENTRY(ICE_CONTROLLED), ATTRIB_ENTRY(ICE_CONTROLLING), - { (Attribute)-1, 0 } + { (Attribute)-1, nullptr } }; QString attributeTypeToString(int type) diff --git a/src/irisnet/noncore/tcpportreserver.cpp b/src/irisnet/noncore/tcpportreserver.cpp index e1ad089c..e69a9b18 100644 --- a/src/irisnet/noncore/tcpportreserver.cpp +++ b/src/irisnet/noncore/tcpportreserver.cpp @@ -54,7 +54,7 @@ bool TcpPortDiscoverer::setExternalHost(const QString &extHost, quint16 extPort, TcpPortServer::PortTypes TcpPortDiscoverer::inProgressPortTypes() const { - return 0; // same as for stop() + return nullptr; // same as for stop() } bool TcpPortDiscoverer::isDepleted() const diff --git a/src/irisnet/noncore/turnclient.cpp b/src/irisnet/noncore/turnclient.cpp index 61bf9769..31221eb7 100644 --- a/src/irisnet/noncore/turnclient.cpp +++ b/src/irisnet/noncore/turnclient.cpp @@ -187,11 +187,11 @@ class TurnClient::Private : public QObject QObject(_q), q(_q), sess(this), - bs(0), + bs(nullptr), tls(0), udp(false), - pool(0), - allocate(0), + pool(nullptr), + allocate(nullptr), retryCount(0), debugLevel(TurnClient::DL_None), writtenBytes(0), @@ -208,15 +208,15 @@ class TurnClient::Private : public QObject void cleanup() { delete allocate; - allocate = 0; + allocate = nullptr; // in udp mode, we don't own the pool if(!udp) delete pool; - pool = 0; + pool = nullptr; delete tls; - tls = 0; + tls = nullptr; delete bs; bs = 0; @@ -293,12 +293,12 @@ class TurnClient::Private : public QObject else { delete allocate; - allocate = 0; + allocate = nullptr; // in udp mode, we don't own the pool if(!udp) delete pool; - pool = 0; + pool = nullptr; if(udp) sess.defer(q, "closed"); @@ -316,7 +316,7 @@ class TurnClient::Private : public QObject else { delete tls; - tls = 0; + tls = nullptr; do_sock_close(); } @@ -697,7 +697,7 @@ class TurnClient::Private : public QObject int tmp_retryCount = retryCount; StunTransactionPool *tmp_pool = pool; - pool = 0; + pool = nullptr; cleanup(); @@ -887,7 +887,7 @@ private slots: void tls_closed() { delete tls; - tls = 0; + tls = nullptr; do_sock_close(); } @@ -935,12 +935,12 @@ private slots: void allocate_stopped() { delete allocate; - allocate = 0; + allocate = nullptr; // in udp mode, we don't own the pool if(!udp) delete pool; - pool = 0; + pool = nullptr; if(udp) emit q->closed(); diff --git a/src/irisnet/noncore/turnclient.h b/src/irisnet/noncore/turnclient.h index 80a07e90..18af00cb 100644 --- a/src/irisnet/noncore/turnclient.h +++ b/src/irisnet/noncore/turnclient.h @@ -111,7 +111,7 @@ class TurnClient : public QObject QString v_user, v_pass; }; - TurnClient(QObject *parent = 0); + TurnClient(QObject *parent = nullptr); ~TurnClient(); void setProxy(const Proxy &proxy); diff --git a/src/irisnet/noncore/udpportreserver.cpp b/src/irisnet/noncore/udpportreserver.cpp index f7e48ba4..650e2132 100644 --- a/src/irisnet/noncore/udpportreserver.cpp +++ b/src/irisnet/noncore/udpportreserver.cpp @@ -255,7 +255,7 @@ private slots: // eat all packets while(sock->hasPendingDatagrams()) - sock->readDatagram(0, 0); + sock->readDatagram(nullptr, 0); } private: diff --git a/src/irisnet/noncore/udpportreserver.h b/src/irisnet/noncore/udpportreserver.h index 57eed035..5650a489 100644 --- a/src/irisnet/noncore/udpportreserver.h +++ b/src/irisnet/noncore/udpportreserver.h @@ -37,7 +37,7 @@ class UdpPortReserver : public QObject Q_OBJECT public: - UdpPortReserver(QObject *parent = 0); + UdpPortReserver(QObject *parent = nullptr); ~UdpPortReserver(); void setAddresses(const QList &addrs); @@ -58,7 +58,7 @@ class UdpPortReserver : public QObject // able to bind to a port for it to be considered reserved, this // function always returns a list with a size that is a multiple of // the number of addresses. - QList borrowSockets(int portCount, QObject *parent = 0); + QList borrowSockets(int portCount, QObject *parent = nullptr); void returnSockets(const QList &sockList); diff --git a/src/xmpp/jid/jid.cpp b/src/xmpp/jid/jid.cpp index 93c08e16..4aa7c967 100644 --- a/src/xmpp/jid/jid.cpp +++ b/src/xmpp/jid/jid.cpp @@ -161,7 +161,7 @@ using namespace XMPP; void StringPrepCache::cleanup() { - _instance.reset(0); + _instance.reset(nullptr); } StringPrepCache *StringPrepCache::instance() diff --git a/src/xmpp/xmpp-core/connector.cpp b/src/xmpp/xmpp-core/connector.cpp index 6bbce914..6aa01c2f 100644 --- a/src/xmpp/xmpp-core/connector.cpp +++ b/src/xmpp/xmpp-core/connector.cpp @@ -215,7 +215,7 @@ AdvancedConnector::AdvancedConnector(QObject *parent) :Connector(parent) { d = new Private; - d->bs = 0; + d->bs = nullptr; d->opt_ssl = Never; cleanup(); d->errorCode = 0; @@ -233,7 +233,7 @@ void AdvancedConnector::cleanup() // destroy the bytestream, if there is one delete d->bs; - d->bs = 0; + d->bs = nullptr; setUseSSL(false); setPeerAddressNone(); @@ -403,7 +403,7 @@ ByteStream *AdvancedConnector::stream() const if(d->mode == Connected) return d->bs; else - return 0; + return nullptr; } void AdvancedConnector::done() diff --git a/src/xmpp/xmpp-core/parser.cpp b/src/xmpp/xmpp-core/parser.cpp index 9706afa4..bb53d345 100644 --- a/src/xmpp/xmpp-core/parser.cpp +++ b/src/xmpp/xmpp-core/parser.cpp @@ -64,7 +64,7 @@ class StreamInput : public QXmlInputSource public: StreamInput() { - dec = 0; + dec = nullptr; reset(); } @@ -76,7 +76,7 @@ class StreamInput : public QXmlInputSource void reset() { delete dec; - dec = 0; + dec = nullptr; in.resize(0); out = ""; at = 0; @@ -197,7 +197,7 @@ class StreamInput : public QXmlInputSource printf("processing. size=%d, at=%d\n", in.size(), at); #endif if(!dec) { - QTextCodec *codec = 0; + QTextCodec *codec = nullptr; uchar *p = (uchar *)in.data() + at; int size = in.size() - at; @@ -239,7 +239,7 @@ class StreamInput : public QXmlInputSource ++n2; QString h = out.mid(n, n2-n); QString enc = processXmlHeader(h); - QTextCodec *codec = 0; + QTextCodec *codec = nullptr; if(!enc.isEmpty()) codec = QTextCodec::codecForName(enc.toLatin1()); @@ -528,9 +528,9 @@ namespace XMPP Parser::Event *takeEvent() { if(needMore) - return 0; + return nullptr; if(eventList.isEmpty()) - return 0; + return nullptr; Parser::Event *e = eventList.takeFirst(); in->pause(false); @@ -564,12 +564,12 @@ class Parser::Event::Private Parser::Event::Event() { - d = 0; + d = nullptr; } Parser::Event::Event(const Event &from) { - d = 0; + d = nullptr; *this = from; } @@ -579,7 +579,7 @@ Parser::Event & Parser::Event::operator=(const Event &from) return *this; delete d; - d = 0; + d = nullptr; if(from.d) d = new Private(*from.d); return *this; @@ -695,9 +695,9 @@ class Parser::Private public: Private() { - doc = 0; + doc = nullptr; in = 0; - handler = 0; + handler = nullptr; reader = 0; reset(); } @@ -726,9 +726,9 @@ class Parser::Private reader->parse(in, true); in->pause(false); } else { - reader = 0; - handler = 0; - in = 0; + reader = nullptr; + handler = nullptr; + in = nullptr; doc = 0; } } diff --git a/src/xmpp/xmpp-core/protocol.cpp b/src/xmpp/xmpp-core/protocol.cpp index c98b595e..d6bdc297 100644 --- a/src/xmpp/xmpp-core/protocol.cpp +++ b/src/xmpp/xmpp-core/protocol.cpp @@ -107,7 +107,7 @@ BasicProtocol::SASLCondEntry BasicProtocol::saslCondTable[] = { "mechanism-too-weak", MechTooWeak }, { "not-authorized", NotAuthorized }, { "temporary-auth-failure", TemporaryAuthFailure }, - { 0, 0 }, + { nullptr, 0 }, }; BasicProtocol::StreamCondEntry BasicProtocol::streamCondTable[] = @@ -136,7 +136,7 @@ BasicProtocol::StreamCondEntry BasicProtocol::streamCondTable[] = { "unsupported-encoding", UnsupportedEncoding }, { "unsupported-stanza-type", UnsupportedStanzaType }, { "unsupported-version", UnsupportedVersion }, - { 0, 0 }, + { nullptr, 0 }, }; BasicProtocol::BasicProtocol() diff --git a/src/xmpp/xmpp-core/securestream.cpp b/src/xmpp/xmpp-core/securestream.cpp index ca192722..f1934d37 100644 --- a/src/xmpp/xmpp-core/securestream.cpp +++ b/src/xmpp/xmpp-core/securestream.cpp @@ -390,7 +390,7 @@ class SecureStream::Private }; SecureStream::SecureStream(ByteStream *s) -:ByteStream(0) +:ByteStream(nullptr) { d = new Private; diff --git a/src/xmpp/xmpp-core/simplesasl.cpp b/src/xmpp/xmpp-core/simplesasl.cpp index db72cd04..4480a673 100644 --- a/src/xmpp/xmpp-core/simplesasl.cpp +++ b/src/xmpp/xmpp-core/simplesasl.cpp @@ -448,7 +448,7 @@ class QCASimpleSASL : public QCA::Provider { if(cap == "sasl") return new SimpleSASLContext(this); - return 0; + return nullptr; } int qcaVersion() const { diff --git a/src/xmpp/xmpp-core/sm.h b/src/xmpp/xmpp-core/sm.h index cbcd94c5..e16d3c14 100644 --- a/src/xmpp/xmpp-core/sm.h +++ b/src/xmpp/xmpp-core/sm.h @@ -57,7 +57,7 @@ namespace XMPP class StreamManagement : QObject { public: - StreamManagement(QObject *parent = 0); + StreamManagement(QObject *parent = nullptr); XMPP::SMState &state() { return state_; } const XMPP::SMState &state() const { return state_; } bool isActive() const { return sm_started || sm_resumed; } diff --git a/src/xmpp/xmpp-core/stream.cpp b/src/xmpp/xmpp-core/stream.cpp index bec855e2..b0c7e49c 100644 --- a/src/xmpp/xmpp-core/stream.cpp +++ b/src/xmpp/xmpp-core/stream.cpp @@ -71,7 +71,7 @@ using namespace XMPP; -static Debug *debug_ptr = 0; +static Debug *debug_ptr = nullptr; void XMPP::setDebug(Debug *p) { debug_ptr = p; @@ -98,7 +98,7 @@ static QString genId() //---------------------------------------------------------------------------- // Stream //---------------------------------------------------------------------------- -static XmlProtocol *foo = 0; +static XmlProtocol *foo = nullptr; Stream::Stream(QObject *parent) :QObject(parent) { @@ -133,7 +133,7 @@ QString Stream::xmlToString(const QDomElement &e, bool clip) void Stream::cleanup() { delete foo; - foo = 0; + foo = nullptr; } //---------------------------------------------------------------------------- @@ -290,11 +290,11 @@ void ClientStream::reset(bool all) // delete securestream delete d->ss; - d->ss = 0; + d->ss = nullptr; // reset sasl delete d->sasl; - d->sasl = 0; + d->sasl = nullptr; if(all) { while (!d->in.isEmpty()) { @@ -317,7 +317,7 @@ void ClientStream::reset(bool all) // reset connector if(d->bs) { d->bs->close(); - d->bs = 0; + d->bs = nullptr; } d->conn->done(); @@ -331,7 +331,7 @@ void ClientStream::reset(bool all) if(d->bs) { d->bs->close(); - d->bs = 0; + d->bs = nullptr; } d->srv.reset(); @@ -459,7 +459,7 @@ QCA::Provider::Context *ClientStream::currentSASLContext() const if (d->sasl) { return d->sasl->context(); } - return 0; + return nullptr; } void ClientStream::setSCRAMStoredSaltedHash(const QString &s) { @@ -1281,7 +1281,7 @@ bool ClientStream::handleNeed() } } - d->sasl = new QCA::SASL(0, saslProvider); + d->sasl = new QCA::SASL(nullptr, saslProvider); connect(d->sasl, SIGNAL(clientStarted(bool,QByteArray)), SLOT(sasl_clientFirstStep(bool,QByteArray))); connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray))); connect(d->sasl, SIGNAL(needParams(QCA::SASL::Params)), SLOT(sasl_needParams(QCA::SASL::Params))); diff --git a/src/xmpp/xmpp-core/xmpp.h b/src/xmpp/xmpp-core/xmpp.h index 61617a02..76443b05 100644 --- a/src/xmpp/xmpp-core/xmpp.h +++ b/src/xmpp/xmpp-core/xmpp.h @@ -71,7 +71,7 @@ namespace XMPP { Q_OBJECT public: - Connector(QObject *parent=0); + Connector(QObject *parent=nullptr); virtual ~Connector(); virtual void setOptHostPort(const QString &host, quint16 port)=0; @@ -107,7 +107,7 @@ namespace XMPP Q_OBJECT public: enum Error { ErrConnectionRefused, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth, ErrStream }; - AdvancedConnector(QObject *parent=0); + AdvancedConnector(QObject *parent=nullptr); virtual ~AdvancedConnector(); class Proxy @@ -180,7 +180,7 @@ namespace XMPP { Q_OBJECT public: - TLSHandler(QObject *parent=0); + TLSHandler(QObject *parent=nullptr); virtual ~TLSHandler(); virtual void reset()=0; diff --git a/src/xmpp/xmpp-core/xmpp_clientstream.h b/src/xmpp/xmpp-core/xmpp_clientstream.h index 4bc5b6a4..d33bf834 100644 --- a/src/xmpp/xmpp-core/xmpp_clientstream.h +++ b/src/xmpp/xmpp-core/xmpp_clientstream.h @@ -99,8 +99,8 @@ namespace XMPP AllowPlainOverTLS }; - ClientStream(Connector *conn, TLSHandler *tlsHandler=0, QObject *parent=0); - ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls=0, QObject *parent=0); // server + ClientStream(Connector *conn, TLSHandler *tlsHandler=nullptr, QObject *parent=nullptr); + ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls=nullptr, QObject *parent=nullptr); // server ~ClientStream(); Jid jid() const; diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index d283541c..25fe145c 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -199,7 +199,7 @@ Stanza::Error::Private::ErrorTypeEntry Stanza::Error::Private::errorTypeTable[] { "modify", Modify }, { "auth", Auth }, { "wait", Wait }, - { 0, 0 }, + { nullptr, 0 }, }; Stanza::Error::Private::ErrorCondEntry Stanza::Error::Private::errorCondTable[] = @@ -225,7 +225,7 @@ Stanza::Error::Private::ErrorCondEntry Stanza::Error::Private::errorCondTable[] { "subscription-required", SubscriptionRequired }, { "undefined-condition", UndefinedCondition }, { "unexpected-request", UnexpectedRequest }, - { 0, 0 }, + { nullptr, 0 }, }; Stanza::Error::Private::ErrorCodeEntry Stanza::Error::Private::errorCodeTable[] = @@ -467,7 +467,7 @@ class Stanza::Private Stanza::Stanza() { - d = 0; + d = nullptr; } Stanza::Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QString &id) @@ -495,7 +495,7 @@ Stanza::Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QStr Stanza::Stanza(Stream *s, const QDomElement &e) { Q_ASSERT(s); - d = 0; + d = nullptr; if(e.namespaceURI() != s->baseNS()) return; int x = Private::stringToKind(e.tagName()); @@ -508,7 +508,7 @@ Stanza::Stanza(Stream *s, const QDomElement &e) Stanza::Stanza(const Stanza &from) { - d = 0; + d = nullptr; *this = from; } @@ -518,7 +518,7 @@ Stanza & Stanza::operator=(const Stanza &from) return *this; delete d; - d = 0; + d = nullptr; if(from.d) d = new Private(*from.d); return *this; diff --git a/src/xmpp/xmpp-core/xmpp_stream.h b/src/xmpp/xmpp-core/xmpp_stream.h index 916a9807..06dd3ae3 100644 --- a/src/xmpp/xmpp-core/xmpp_stream.h +++ b/src/xmpp/xmpp-core/xmpp_stream.h @@ -48,7 +48,7 @@ namespace XMPP StreamReset }; - Stream(QObject *parent=0); + Stream(QObject *parent=nullptr); virtual ~Stream(); virtual QDomDocument & doc() const=0; diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index 6033a505..f4ecc8c4 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -263,7 +263,7 @@ void Client::setFileTransferEnabled(bool b) else { if(d->ftman) { delete d->ftman; - d->ftman = 0; + d->ftman = nullptr; } } } @@ -482,7 +482,7 @@ void Client::close(bool) if(d->stream) { d->stream->disconnect(this); d->stream->close(); - d->stream = 0; + d->stream = nullptr; } disconnected(); cleanup(); diff --git a/src/xmpp/xmpp-im/filetransfer.cpp b/src/xmpp/xmpp-im/filetransfer.cpp index 493b4175..1290b9d3 100644 --- a/src/xmpp/xmpp-im/filetransfer.cpp +++ b/src/xmpp/xmpp-im/filetransfer.cpp @@ -74,8 +74,8 @@ FileTransfer::FileTransfer(FileTransferManager *m, QObject *parent) { d = new Private; d->m = m; - d->ft = 0; - d->c = 0; + d->ft = nullptr; + d->c = nullptr; reset(); } @@ -85,7 +85,7 @@ FileTransfer::FileTransfer(const FileTransfer& other) d = new Private; *d = *other.d; d->m = other.d->m; - d->ft = 0; + d->ft = nullptr; d->c = 0; reset(); @@ -109,13 +109,13 @@ void FileTransfer::reset() d->m->unlink(this); delete d->ft; - d->ft = 0; + d->ft = nullptr; if (d->c) { d->c->disconnect(this); d->c->manager()->deleteConnection(d->c, d->state == Active && !d->sender ? 3000 : 0); - d->c = 0; + d->c = nullptr; } d->state = Idle; @@ -247,7 +247,7 @@ BSConnection *FileTransfer::bsConnection() const void FileTransfer::ft_finished() { JT_FT *ft = d->ft; - d->ft = 0; + d->ft = nullptr; if(ft->success()) { d->state = Connecting; @@ -420,7 +420,7 @@ FileTransfer *FileTransferManager::createTransfer() FileTransfer *FileTransferManager::takeIncoming() { if(d->incoming.isEmpty()) - return 0; + return nullptr; FileTransfer *ft = d->incoming.takeFirst(); @@ -472,7 +472,7 @@ void FileTransferManager::pft_incoming(const FTRequest &req) BytestreamManager* FileTransferManager::streamManager(const QString &ns) const { if (d->disabledStreamTypes.contains(ns)) { - return 0; + return nullptr; } return d->streamMap.value(ns); } diff --git a/src/xmpp/xmpp-im/filetransfer.h b/src/xmpp/xmpp-im/filetransfer.h index bdb24f8a..8d436089 100644 --- a/src/xmpp/xmpp-im/filetransfer.h +++ b/src/xmpp/xmpp-im/filetransfer.h @@ -95,7 +95,7 @@ namespace XMPP Private *d; friend class FileTransferManager; - FileTransfer(FileTransferManager *, QObject *parent=0); + FileTransfer(FileTransferManager *, QObject *parent=nullptr); FileTransfer(const FileTransfer& other); void man_waitForAccept(const FTRequest &req, const QString &streamType); void takeConnection(BSConnection *c); diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 0b486959..1066e592 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -1747,7 +1747,7 @@ ApplicationManagerPad *Manager::applicationPad(Session *session, const QString & { auto am = d->applicationManagers.value(ns); if (!am) { - return NULL; + return nullptr; } return am->pad(session); } @@ -1801,7 +1801,7 @@ TransportManagerPad* Manager::transportPad(Session *session, const QString &ns) { auto transportManager = d->transportManagers.value(ns); if (!transportManager) { - return NULL; + return nullptr; } return transportManager->pad(session); } @@ -1821,7 +1821,7 @@ Session* Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, { if (d->maxSessions > 0 && d->sessions.size() == d->maxSessions) { d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Wait, XMPP::Stanza::Error::ResourceConstraint); - return NULL; + return nullptr; } auto key = qMakePair(from, jingle.sid()); auto s = new Session(this, from, Origin::Responder); @@ -1835,7 +1835,7 @@ Session* Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, } d->lastError = s->lastError(); delete s; - return NULL; + return nullptr; } XMPP::Stanza::Error Manager::lastError() const diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 9a13b26f..cda4d5b1 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -565,7 +565,7 @@ class Manager : public QObject Q_OBJECT public: - explicit Manager(XMPP::Client *client = 0); + explicit Manager(XMPP::Client *client = nullptr); ~Manager(); XMPP::Client* client() const; diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index 5cdea38d..596c7f8b 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -200,8 +200,8 @@ S5BConnection::S5BConnection(S5BManager *m, QObject *parent) { d = new Private; d->m = m; - d->sc = 0; - d->su = 0; + d->sc = nullptr; + d->su = nullptr; ++num_conn; d->id = id_conn++; @@ -229,10 +229,10 @@ void S5BConnection::resetConnection(bool clear) d->m->con_unlink(this); if(clear && d->sc) { delete d->sc; - d->sc = 0; + d->sc = nullptr; } delete d->su; - d->su = 0; + d->su = nullptr; if(clear) { while (!d->dglist.isEmpty()) { delete d->dglist.takeFirst(); @@ -627,7 +627,7 @@ BSConnection *S5BManager::createConnection() S5BConnection *S5BManager::takeIncoming() { if(d->incomingConns.isEmpty()) - return 0; + return nullptr; S5BConnection *c = d->incomingConns.takeFirst(); @@ -757,7 +757,7 @@ S5BConnection *S5BManager::findIncoming(const Jid &from, const QString &sid) con if(c->d->peer.compare(from) && c->d->sid == sid) return c; } - return 0; + return nullptr; } S5BManager::Entry *S5BManager::findEntry(S5BConnection *c) const @@ -766,7 +766,7 @@ S5BManager::Entry *S5BManager::findEntry(S5BConnection *c) const if(e->c == c) return e; } - return 0; + return nullptr; } S5BManager::Entry *S5BManager::findEntry(Item *i) const @@ -775,7 +775,7 @@ S5BManager::Entry *S5BManager::findEntry(Item *i) const if(e->i == i) return e; } - return 0; + return nullptr; } S5BManager::Entry *S5BManager::findEntryByHash(const QString &key) const @@ -784,7 +784,7 @@ S5BManager::Entry *S5BManager::findEntryByHash(const QString &key) const if(e->i && e->i->key == key) return e; } - return 0; + return nullptr; } S5BManager::Entry *S5BManager::findEntryBySID(const Jid &peer, const QString &sid) const @@ -793,7 +793,7 @@ S5BManager::Entry *S5BManager::findEntryBySID(const Jid &peer, const QString &si if(e->i && e->i->peer.compare(peer) && e->sid == sid) return e; } - return 0; + return nullptr; } bool S5BManager::srv_ownsHash(const QString &key) const @@ -951,9 +951,9 @@ void S5BManager::item_connected() // grab the client SocksClient *client = i->client; - i->client = 0; + i->client = nullptr; SocksUDP *client_udp = i->client_udp; - i->client_udp = 0; + i->client_udp = nullptr; // give it to the connection e->c->man_clientReady(client, client_udp); @@ -1008,7 +1008,7 @@ void S5BManager::queryProxy(Entry *e) void S5BManager::query_finished() { JT_S5B *query = static_cast(sender()); - Entry* e = 0; + Entry* e = nullptr; foreach(Entry* i, d->activeList) { if(i->query == query) { e = i; @@ -1017,7 +1017,7 @@ void S5BManager::query_finished() } if(!e) return; - e->query = 0; + e->query = nullptr; #ifdef S5B_DEBUG qDebug("query finished: "); @@ -1304,7 +1304,7 @@ void S5BManager::Item::incomingActivate(const Jid &streamHost) void S5BManager::Item::jt_finished() { JT_S5B *j = task; - task = 0; + task = nullptr; #ifdef S5B_DEBUG qDebug("jt_finished: state=%s, %s\n", state == Requester ? "requester" : "target", j->success() ? "ok" : "fail"); @@ -1330,7 +1330,7 @@ void S5BManager::Item::jt_finished() // stop connecting out if(conn || lateProxy) { delete conn; - conn = 0; + conn = nullptr; doConnectError(); } @@ -1357,7 +1357,7 @@ void S5BManager::Item::jt_finished() else if(streamHost.compare(proxy.jid())) { // toss out any direct incoming, since it won't be used delete client; - client = 0; + client = nullptr; allowIncoming = false; #ifdef S5B_DEBUG @@ -1412,7 +1412,7 @@ void S5BManager::Item::conn_result(bool b) SocksUDP *sc_udp = conn->takeUDP(); StreamHost h = conn->streamHostUsed(); delete conn; - conn = 0; + conn = nullptr; connSuccess = true; #ifdef S5B_DEBUG @@ -1448,7 +1448,7 @@ void S5BManager::Item::conn_result(bool b) } else { delete conn; - conn = 0; + conn = nullptr; // if we delayed the proxies for later, try now if(lateProxy) { @@ -1469,7 +1469,7 @@ void S5BManager::Item::proxy_result(bool b) SocksClient *sc = proxy_conn->takeClient(); SocksUDP *sc_udp = proxy_conn->takeUDP(); delete proxy_conn; - proxy_conn = 0; + proxy_conn = nullptr; connect(sc, SIGNAL(readyRead()), SLOT(sc_readyRead())); connect(sc, SIGNAL(bytesWritten(qint64)), SLOT(sc_bytesWritten(qint64))); @@ -1489,7 +1489,7 @@ void S5BManager::Item::proxy_result(bool b) } else { delete proxy_conn; - proxy_conn = 0; + proxy_conn = nullptr; resetConnection(); error(ErrProxy); } @@ -1498,7 +1498,7 @@ void S5BManager::Item::proxy_result(bool b) void S5BManager::Item::proxy_finished() { JT_S5B *j = proxy_task; - proxy_task = 0; + proxy_task = nullptr; if(j->success()) { #ifdef S5B_DEBUG @@ -1575,7 +1575,7 @@ void S5BManager::Item::tryActivation() else if(targetMode == Fast) { // with fast mode, we don't wait for the iq reply, so delete the task (if any) delete task; - task = 0; + task = nullptr; activated = true; @@ -1628,15 +1628,15 @@ void S5BManager::Item::checkForActivation() } if(ok) { - SocksUDP *sc_udp = 0; + SocksUDP *sc_udp = nullptr; if(sc == client) { delete client_out_udp; - client_out_udp = 0; + client_out_udp = nullptr; sc_udp = client_udp; } else if(sc == client_out) { delete client_udp; - client_udp = 0; + client_udp = nullptr; sc_udp = client_out_udp; } @@ -1645,7 +1645,7 @@ void S5BManager::Item::checkForActivation() delete clientList.takeFirst(); } client = sc; - client_out = 0; + client_out = nullptr; client_udp = sc_udp; activated = true; #ifdef S5B_DEBUG @@ -1664,7 +1664,7 @@ void S5BManager::Item::checkForActivation() delete clientList.takeFirst(); } client = sc; - client_out = 0; + client_out = nullptr; activated = true; break; } @@ -1738,9 +1738,9 @@ class S5BConnector::Item : public QObject Jid jid; Item(const Jid &self, const StreamHost &_host, const QString &_key, bool _udp) - : QObject(0) + : QObject(nullptr) , client(new SocksClient) - , client_udp(0) + , client_udp(nullptr) , host(_host) , key(_key) , udp(_udp) @@ -1816,9 +1816,9 @@ private slots: void cleanup() { delete client_udp; - client_udp = 0; + client_udp = nullptr; delete client; - client = 0; + client = nullptr; } void success() @@ -1846,8 +1846,8 @@ S5BConnector::S5BConnector(QObject *parent) :QObject(parent) { d = new Private; - d->active = 0; - d->active_udp = 0; + d->active = nullptr; + d->active_udp = nullptr; connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout())); } @@ -1861,9 +1861,9 @@ void S5BConnector::resetConnection() { d->t.stop(); delete d->active_udp; - d->active_udp = 0; + d->active_udp = nullptr; delete d->active; - d->active = 0; + d->active = nullptr; while (!d->itemList.empty()) { delete d->itemList.takeFirst(); } @@ -1888,14 +1888,14 @@ void S5BConnector::start(const Jid &self, const StreamHostList &hosts, const QSt SocksClient *S5BConnector::takeClient() { SocksClient *c = d->active; - d->active = 0; + d->active = nullptr; return c; } SocksUDP *S5BConnector::takeUDP() { SocksUDP *c = d->active_udp; - d->active_udp = 0; + d->active_udp = nullptr; return c; } @@ -1909,9 +1909,9 @@ void S5BConnector::item_result(bool b) Item *i = static_cast(sender()); if(b) { d->active = i->client; - i->client = 0; + i->client = nullptr; d->active_udp = i->client_udp; - i->client_udp = 0; + i->client_udp = nullptr; d->activeHost = i->host; while (!d->itemList.isEmpty()) { delete d->itemList.takeFirst(); @@ -2329,7 +2329,7 @@ class S5BIncomingConnection : public QObject QString host; QTimer expire; - S5BIncomingConnection(SocksClient *c) : QObject(0) + S5BIncomingConnection(SocksClient *c) : QObject(nullptr) { client = c; connect(client, &SocksClient::incomingMethods, [this](int methods){ @@ -2372,7 +2372,7 @@ private slots: { expire.stop(); delete client; - client = 0; + client = nullptr; result(false); } }; @@ -2406,7 +2406,7 @@ S5BServer::S5BServer(QTcpServer *serverSocket) : } SocksClient *c = inConn->client; - inConn->client = 0; + inConn->client = nullptr; QString key = inConn->host; delete inConn; diff --git a/src/xmpp/xmpp-im/s5b.h b/src/xmpp/xmpp-im/s5b.h index 4f0d9863..951076f8 100644 --- a/src/xmpp/xmpp-im/s5b.h +++ b/src/xmpp/xmpp-im/s5b.h @@ -140,7 +140,7 @@ namespace XMPP void man_clientReady(SocksClient *, SocksUDP *); void man_udpReady(const QByteArray &buf); void man_failed(int); - S5BConnection(S5BManager *, QObject *parent=0); + S5BConnection(S5BManager *, QObject *parent=nullptr); }; class S5BManager : public BytestreamManager @@ -213,7 +213,7 @@ namespace XMPP { Q_OBJECT public: - S5BConnector(QObject *parent=0); + S5BConnector(QObject *parent=nullptr); ~S5BConnector(); void resetConnection(); diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index a988230a..f3db19b7 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -146,7 +146,7 @@ BoBCache::BoBCache(QObject *parent) //------------------------------------------------------------------------------ BoBManager::BoBManager(Client *client) : QObject(client) - , _cache(0) + , _cache(nullptr) { new JT_BoBServer(client->rootTask()); } diff --git a/src/xmpp/xmpp-im/xmpp_bytestream.h b/src/xmpp/xmpp-im/xmpp_bytestream.h index 7da4d0c3..9f3a88b6 100644 --- a/src/xmpp/xmpp-im/xmpp_bytestream.h +++ b/src/xmpp/xmpp-im/xmpp_bytestream.h @@ -35,7 +35,7 @@ namespace XMPP enum Error { ErrRefused = ErrCustom, ErrConnect, ErrProxy, ErrSocket }; enum State { Idle, Requesting, Connecting, WaitingForAccept, Active }; - BSConnection(QObject *parent = 0) : ByteStream(parent) {} + BSConnection(QObject *parent = nullptr) : ByteStream(parent) {} virtual void connectToJid(const Jid &peer, const QString &sid) = 0; virtual void accept() = 0; diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index b250bf59..4cfb935f 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -73,7 +73,7 @@ namespace XMPP Q_OBJECT public: - Client(QObject *parent=0); + Client(QObject *parent=nullptr); ~Client(); bool isActive() const; diff --git a/src/xmpp/xmpp-im/xmpp_features.cpp b/src/xmpp/xmpp-im/xmpp_features.cpp index 0190e67b..378f0556 100644 --- a/src/xmpp/xmpp-im/xmpp_features.cpp +++ b/src/xmpp/xmpp-im/xmpp_features.cpp @@ -253,7 +253,7 @@ class Features::FeatureName : public QObject QMap id2f; }; -static Features::FeatureName *featureName = 0; +static Features::FeatureName *featureName = nullptr; long Features::id() const { diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index 9089ecce..0c716760 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -62,7 +62,7 @@ IBBConnection::IBBConnection(IBBManager *m) { d = new Private; d->m = m; - d->j = 0; + d->j = nullptr; d->blockSize = PacketSize; resetConnection(); @@ -82,7 +82,7 @@ void IBBConnection::resetConnection(bool clear) d->seq = 0; delete d->j; - d->j = 0; + d->j = nullptr; clearWriteBuffer(); if(clear) @@ -254,7 +254,7 @@ void IBBConnection::setRemoteClosed() void IBBConnection::ibb_finished() { JT_IBB *j = d->j; - d->j = 0; + d->j = nullptr; if(j->success()) { if(j->mode() == JT_IBB::ModeRequest) { @@ -455,7 +455,7 @@ void IBBManager::ibb_closeRequest(const Jid &from, const QString &id, bool IBBManager::isAcceptableSID(const XMPP::Jid &jid, const QString&sid) const { - return findConnection(sid, jid) == NULL; + return findConnection(sid, jid) == nullptr; } const char* IBBManager::sidPrefix() const @@ -479,7 +479,7 @@ IBBConnection *IBBManager::findConnection(const QString &sid, const Jid &peer) c if(c->sid() == sid && (peer.isEmpty() || c->peer().compare(peer)) ) return c; } - return 0; + return nullptr; } void IBBManager::doAccept(IBBConnection *c, const QString &id) diff --git a/src/xmpp/xmpp-im/xmpp_tasks.cpp b/src/xmpp/xmpp-im/xmpp_tasks.cpp index 7a627a3c..cfa6bc3f 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.cpp +++ b/src/xmpp/xmpp-im/xmpp_tasks.cpp @@ -318,7 +318,7 @@ JT_UnRegister::JT_UnRegister(Task *parent) : Task(parent) { d = new Private; - d->jt_reg = 0; + d->jt_reg = nullptr; } JT_UnRegister::~JT_UnRegister() @@ -344,7 +344,7 @@ void JT_UnRegister::onGo() void JT_UnRegister::getFormFinished() { - disconnect(d->jt_reg, 0, this, 0); + disconnect(d->jt_reg, nullptr, this, nullptr); if (d->jt_reg->isRegistered()) { d->jt_reg->unreg(d->j); connect(d->jt_reg, SIGNAL(finished()), SLOT(unregFinished())); @@ -362,7 +362,7 @@ void JT_UnRegister::unregFinished() setError(d->jt_reg->statusCode(), d->jt_reg->statusString()); delete d->jt_reg; - d->jt_reg = 0; + d->jt_reg = nullptr; } //---------------------------------------------------------------------------- diff --git a/src/xmpp/zlib/common.h b/src/xmpp/zlib/common.h index da3fe842..bf243c0d 100644 --- a/src/xmpp/zlib/common.h +++ b/src/xmpp/zlib/common.h @@ -5,14 +5,14 @@ static void initZStream(z_stream* z) { - z->next_in = NULL; + z->next_in = nullptr; z->avail_in = 0; z->total_in = 0; - z->next_out = NULL; + z->next_out = nullptr; z->avail_out = 0; z->total_out = 0; - z->msg = NULL; - z->state = NULL; + z->msg = nullptr; + z->state = nullptr; z->zalloc = Z_NULL; z->zfree = Z_NULL; z->opaque = Z_NULL; From 28452af5bc8ab433cca0924640642f6849bbab51 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 2 Jul 2019 08:13:03 +0300 Subject: [PATCH 086/383] Fixed more compilation warnings --- src/irisnet/noncore/udpportreserver.cpp | 2 +- src/xmpp/jid/jid.cpp | 8 ++++---- src/xmpp/xmpp-core/parser.cpp | 2 +- src/xmpp/xmpp-core/parser.h | 2 +- src/xmpp/xmpp-im/httpfileupload.h | 8 ++++---- src/xmpp/xmpp-im/xmpp_client.h | 2 +- src/xmpp/xmpp-im/xmpp_discoinfotask.h | 2 +- src/xmpp/xmpp-im/xmpp_discoitem.cpp | 8 ++++---- src/xmpp/xmpp-im/xmpp_discoitem.h | 2 +- src/xmpp/xmpp-im/xmpp_message.h | 2 +- src/xmpp/xmpp-im/xmpp_status.h | 2 +- src/xmpp/xmpp-im/xmpp_subsets.cpp | 6 +++--- src/xmpp/xmpp-im/xmpp_tasks.h | 2 +- src/xmpp/xmpp-im/xmpp_xdata.cpp | 2 +- src/xmpp/xmpp-im/xmpp_xmlcommon.cpp | 2 +- 15 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/irisnet/noncore/udpportreserver.cpp b/src/irisnet/noncore/udpportreserver.cpp index 650e2132..54adc0b4 100644 --- a/src/irisnet/noncore/udpportreserver.cpp +++ b/src/irisnet/noncore/udpportreserver.cpp @@ -125,7 +125,7 @@ class UdpPortReserver::Private : public QObject ports = newPorts; // keep ports in sorted order - qSort(ports); + std::sort(ports.begin(), ports.end()); foreach(int x, added) { diff --git a/src/xmpp/jid/jid.cpp b/src/xmpp/jid/jid.cpp index 4aa7c967..e7e35bc5 100644 --- a/src/xmpp/jid/jid.cpp +++ b/src/xmpp/jid/jid.cpp @@ -56,7 +56,7 @@ using namespace XMPP; cs.resize(maxbytes); if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0) { - that->nameprep_table.insert(in, QString::null); + that->nameprep_table.insert(in, QString()); return false; } @@ -87,7 +87,7 @@ using namespace XMPP; QByteArray cs = in.toUtf8(); cs.resize(maxbytes); if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0) { - that->nodeprep_table.insert(in, QString::null); + that->nodeprep_table.insert(in, QString()); return false; } @@ -118,7 +118,7 @@ using namespace XMPP; QByteArray cs = in.toUtf8(); cs.resize(maxbytes); if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0) { - that->resourceprep_table.insert(in, QString::null); + that->resourceprep_table.insert(in, QString()); return false; } @@ -149,7 +149,7 @@ using namespace XMPP; QByteArray cs = in.toUtf8(); cs.resize(maxbytes); if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_saslprep) != 0) { - that->saslprep_table.insert(in, QString::null); + that->saslprep_table.insert(in, QString()); return false; } diff --git a/src/xmpp/xmpp-core/parser.cpp b/src/xmpp/xmpp-core/parser.cpp index bb53d345..4eb601d8 100644 --- a/src/xmpp/xmpp-core/parser.cpp +++ b/src/xmpp/xmpp-core/parser.cpp @@ -611,7 +611,7 @@ QString Parser::Event::nsprefix(const QString &s) const return (*it2); ++it2; } - return QString::null; + return QString(); } QString Parser::Event::namespaceURI() const diff --git a/src/xmpp/xmpp-core/parser.h b/src/xmpp/xmpp-core/parser.h index b31841e7..72fa9b57 100644 --- a/src/xmpp/xmpp-core/parser.h +++ b/src/xmpp/xmpp-core/parser.h @@ -44,7 +44,7 @@ namespace XMPP int type() const; // for document open - QString nsprefix(const QString &s=QString::null) const; + QString nsprefix(const QString &s=QString()) const; // for document open / close QString namespaceURI() const; diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index 53f6feeb..e5666adf 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -78,7 +78,7 @@ class HttpFileUpload : public QObject }; HttpFileUpload(Client *client, QIODevice *source, size_t fsize, const QString &dstFilename, - const QString &mType = QString::null); + const QString &mType = QString()); HttpFileUpload(const HttpFileUpload &) = delete; ~HttpFileUpload(); @@ -172,8 +172,8 @@ class HttpFileUploadManager : public QObject * @param mType meta type. image/png for example * @return returns a handler object which will signal "finished" when ready */ - HttpFileUpload* upload(const QString &srcFilename, const QString &dstFilename = QString::null, - const QString &mType = QString::null); + HttpFileUpload* upload(const QString &srcFilename, const QString &dstFilename = QString(), + const QString &mType = QString()); /** * @brief uploads data of given size from the given to remote server @@ -184,7 +184,7 @@ class HttpFileUploadManager : public QObject * @return returns a handler object which will signal "finished" when ready */ HttpFileUpload* upload(QIODevice *source, size_t fsize, const QString &dstFilename, - const QString &mType = QString::null); + const QString &mType = QString()); private: class Private; diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index 4cfb935f..aa995f62 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -135,7 +135,7 @@ namespace XMPP void setFeatures(const Features& f); const Features& features() const; - DiscoItem makeDiscoResult(const QString &node = QString::null) const; + DiscoItem makeDiscoResult(const QString &node = QString()) const; void setTcpPortReserver(TcpPortReserver *portReserver); TcpPortReserver *tcpPortReserver() const; diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.h b/src/xmpp/xmpp-im/xmpp_discoinfotask.h index 47c561bc..77cafc0e 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.h +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.h @@ -40,7 +40,7 @@ namespace XMPP // Allow retreive result from cache and update cache on finish with new data void setAllowCache(bool allow = true); - void get(const Jid &, const QString &node = QString::null, const DiscoItem::Identity = DiscoItem::Identity()); + void get(const Jid &, const QString &node = QString(), const DiscoItem::Identity = DiscoItem::Identity()); void get(const DiscoItem &); const DiscoItem &item() const; diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.cpp b/src/xmpp/xmpp-im/xmpp_discoitem.cpp index 75738ef1..ddb9bdb1 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoitem.cpp @@ -111,14 +111,14 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const { QStringList prep; DiscoItem::Identities idents = d->identities; - qSort(idents); + std::sort(idents.begin(), idents.end()); foreach (const DiscoItem::Identity &id, idents) { prep << QString("%1/%2/%3/%4").arg(id.category, id.type, id.lang, id.name); } QStringList fl = d->features.list(); - qSort(fl); + std::sort(fl.begin(), fl.end()); prep += fl; QMap forms; @@ -145,7 +145,7 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const if (v.isEmpty()) { continue; // maybe it's media-element but xep-115 (1.5) and xep-232 (0.3) are not clear about that. } - qSort(v); + std::sort(v.begin(), v.end()); values[f.var()] = v; } QMap ::ConstIterator it = values.constBegin(); @@ -338,7 +338,7 @@ QString DiscoItem::action2string(const Action a) else if ( a == Remove ) s = "remove"; else - s = QString::null; + s = QString(); return s; } diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.h b/src/xmpp/xmpp-im/xmpp_discoitem.h index a6b06145..b2f990ff 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.h +++ b/src/xmpp/xmpp-im/xmpp_discoitem.h @@ -66,7 +66,7 @@ namespace XMPP { inline Identity() {} inline Identity(const QString &categoty, const QString &type, - const QString &lang = QString::null, const QString &name = QString::null) : + const QString &lang = QString(), const QString &name = QString()) : category(categoty), type(type), lang(lang), name(name) {} bool operator==(const Identity &other) const; }; diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index 1c40fa5a..f1378c4b 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -84,7 +84,7 @@ namespace XMPP { QString id() const; QString type() const; QString lang() const; - QString subject(const QString &lang=QString::null) const; + QString subject(const QString &lang=QString()) const; QString subject(const QLocale &lang) const; StringMap subjectMap() const; QString body(const QString &lang="") const; diff --git a/src/xmpp/xmpp-im/xmpp_status.h b/src/xmpp/xmpp-im/xmpp_status.h index e78af9ab..a43f9577 100644 --- a/src/xmpp/xmpp-im/xmpp_status.h +++ b/src/xmpp/xmpp-im/xmpp_status.h @@ -39,7 +39,7 @@ namespace XMPP static const QCryptographicHash::Algorithm invalidAlgo = (QCryptographicHash::Algorithm)255; CapsSpec(); - CapsSpec(const QString& node, QCryptographicHash::Algorithm hashAlgo, const QString& ver = QString::null); + CapsSpec(const QString& node, QCryptographicHash::Algorithm hashAlgo, const QString& ver = QString()); CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlgo = QCryptographicHash::Sha1); bool isValid() const; diff --git a/src/xmpp/xmpp-im/xmpp_subsets.cpp b/src/xmpp/xmpp-im/xmpp_subsets.cpp index ef306639..f5835304 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.cpp +++ b/src/xmpp/xmpp-im/xmpp_subsets.cpp @@ -156,8 +156,8 @@ void SubsetsClientManager::reset() d->query.type = Private::None; d->query.max = 50; d->query.index = -1; - d->result.firstId = QString::null; - d->result.lastId = QString::null; + d->result.firstId = QString(); + d->result.lastId = QString(); d->resetResult(); } @@ -259,7 +259,7 @@ QDomElement SubsetsClientManager::makeQueryElement(QDomDocument *doc) const d->insertMaxElement(doc, &e, 0); break; case Private::Last: - d->insertBeforeElement(doc, &e, QString::null); + d->insertBeforeElement(doc, &e, QString()); break; case Private::Next: d->insertAfterElement(doc, &e, d->result.lastId); diff --git a/src/xmpp/xmpp-im/xmpp_tasks.h b/src/xmpp/xmpp-im/xmpp_tasks.h index 01e4e568..11c401f0 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.h +++ b/src/xmpp/xmpp-im/xmpp_tasks.h @@ -352,7 +352,7 @@ namespace XMPP JT_DiscoItems(Task *); ~JT_DiscoItems(); - void get(const Jid &, const QString &node = QString::null); + void get(const Jid &, const QString &node = QString()); void get(const DiscoItem &); const DiscoList &items() const; diff --git a/src/xmpp/xmpp-im/xmpp_xdata.cpp b/src/xmpp/xmpp-im/xmpp_xdata.cpp index a481db8d..e2bf37d4 100644 --- a/src/xmpp/xmpp-im/xmpp_xdata.cpp +++ b/src/xmpp/xmpp-im/xmpp_xdata.cpp @@ -195,7 +195,7 @@ void XData::Field::fromXml(const QDomElement &e) _type = Field_TextSingle; _required = false; - _desc = QString::null; + _desc = QString(); _options.clear(); _value.clear(); diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp index fd0c8653..b4e86c93 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp @@ -333,7 +333,7 @@ QString subTagText(const QDomElement &e, const QString &name) QDomElement i = e.firstChildElement(name); if ( !i.isNull() ) return i.text(); - return QString::null; + return QString(); } QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content) From 3e3597298b587f870b111efa499baea7771a48fe Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 3 Jul 2019 09:44:56 +0300 Subject: [PATCH 087/383] minor formatting fix --- src/xmpp/xmpp-im/xmpp_features.cpp | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/xmpp/xmpp-im/xmpp_features.cpp b/src/xmpp/xmpp-im/xmpp_features.cpp index 378f0556..11e3eef0 100644 --- a/src/xmpp/xmpp-im/xmpp_features.cpp +++ b/src/xmpp/xmpp-im/xmpp_features.cpp @@ -214,16 +214,16 @@ class Features::FeatureName : public QObject FeatureName() : QObject(QCoreApplication::instance()) { - id2s[FID_Invalid] = tr("ERROR: Incorrect usage of Features class"); - id2s[FID_None] = tr("None"); - id2s[FID_Register] = tr("Register"); + id2s[FID_Invalid] = tr("ERROR: Incorrect usage of Features class"); + id2s[FID_None] = tr("None"); + id2s[FID_Register] = tr("Register"); id2s[FID_Search] = tr("Search"); - id2s[FID_Groupchat] = tr("Groupchat"); - id2s[FID_Gateway] = tr("Gateway"); - id2s[FID_Disco] = tr("Service Discovery"); - id2s[FID_VCard] = tr("VCard"); - id2s[FID_AHCommand] = tr("Execute command"); - id2s[FID_QueryVersion] = tr("Query version"); + id2s[FID_Groupchat] = tr("Groupchat"); + id2s[FID_Gateway] = tr("Gateway"); + id2s[FID_Disco] = tr("Service Discovery"); + id2s[FID_VCard] = tr("VCard"); + id2s[FID_AHCommand] = tr("Execute command"); + id2s[FID_QueryVersion] = tr("Query version"); id2s[FID_MessageCarbons]= tr("Message Carbons"); // custom Psi actions @@ -234,18 +234,18 @@ class Features::FeatureName : public QObject //for ( ; it != id2s.end(); ++it) // s2id[it.data()] = it.key(); - id2f[FID_Register] = FID_REGISTER; + id2f[FID_Register] = FID_REGISTER; id2f[FID_Search] = FID_SEARCH; - id2f[FID_Groupchat] = FID_GROUPCHAT; - id2f[FID_Gateway] = FID_GATEWAY; - id2f[FID_Disco] = FID_DISCO; - id2f[FID_VCard] = FID_VCARD; - id2f[FID_AHCommand] = FID_AHCOMMAND; - id2f[FID_QueryVersion] = FID_QUERYVERSION; + id2f[FID_Groupchat] = FID_GROUPCHAT; + id2f[FID_Gateway] = FID_GATEWAY; + id2f[FID_Disco] = FID_DISCO; + id2f[FID_VCard] = FID_VCARD; + id2f[FID_AHCommand] = FID_AHCOMMAND; + id2f[FID_QueryVersion] = FID_QUERYVERSION; id2f[FID_MessageCarbons]= FID_MESSAGECARBONS; // custom Psi actions - id2f[FID_Add] = FID_ADD; + id2f[FID_Add] = FID_ADD; } //QMap s2id; From 2784fb7c51d754fe389cab7abffc5deacd586430 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 9 Jul 2019 01:12:32 +0300 Subject: [PATCH 088/383] A couple of constructors for jingle-ft ranges --- src/xmpp/xmpp-im/jingle-ft.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index f92dca04..cd6e9754 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -39,6 +39,8 @@ struct Range { quint64 length = 0; Hash hash; + inline Range() {} + inline Range(quint64 offset, quint64 length) : offset(offset), length(length) {} inline bool isValid() const { return hash.isValid() || offset || length; } QDomElement toXml(QDomDocument *doc) const; }; From 764defd80103541a0b66915d040f96cac91ee4a9 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 10 Jul 2019 09:52:14 +0300 Subject: [PATCH 089/383] ranged file transfers fixes --- src/xmpp/xmpp-im/jingle-ft.cpp | 4 ++-- src/xmpp/xmpp-im/jingle-ft.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 1096da2a..0525e54f 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -131,8 +131,8 @@ File::File(const QDomElement &file) } } if (ce.hasAttribute(QLatin1String("length"))) { - range.offset = ce.attribute(QLatin1String("length")).toULongLong(&ok); - if (!ok) { + range.length = ce.attribute(QLatin1String("length")).toULongLong(&ok); + if (!ok || !range.length) { // length should absent if we need to read till end of file. 0-length is nonsense return; } } diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index cd6e9754..8053bf5b 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -36,7 +36,7 @@ class Manager; struct Range { quint64 offset = 0; - quint64 length = 0; + quint64 length = 0; // 0 - from offset to the end of the file Hash hash; inline Range() {} @@ -169,7 +169,7 @@ class Application : public XMPP::Jingle::Application bool incomingTransportAccept(const QDomElement &transportEl) override; signals: - void deviceRequested(quint64 offset, quint64 size); + void deviceRequested(quint64 offset, quint64 size); // if size = 0 then it's reamaining part of the file void progress(quint64 offset); private: From 2e08a83dc5450f0505ac8acb49eb159762646025 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 11 Jul 2019 09:05:05 +0300 Subject: [PATCH 090/383] s/downloadProgress/uploadProgress/ --- src/xmpp/xmpp-im/httpfileupload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 8e5efedf..9bc78ef6 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -210,7 +210,7 @@ void HttpFileUpload::tryNextServer() req.setRawHeader(h.name.toLatin1(), h.value.toLatin1()); } auto reply = d->qnam->put(req, d->sourceDevice); - connect(reply, &QNetworkReply::downloadProgress, this, &HttpFileUpload::progress); + connect(reply, &QNetworkReply::uploadProgress, this, &HttpFileUpload::progress); connect(reply, &QNetworkReply::finished, this, [this, reply](){ if (reply->error() == QNetworkReply::NoError) { done(State::Success); From fb63f3eb40e601791c0b8eae22fc8e9da061bf20 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 11 Jul 2019 11:54:54 +0300 Subject: [PATCH 091/383] Added jingle-ft:file:size presence flag --- src/xmpp/xmpp-im/jingle-ft.cpp | 10 ++++++++++ src/xmpp/xmpp-im/jingle-ft.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 0525e54f..af63dac6 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -60,6 +60,7 @@ class File::Private : public QSharedData quint64 size = 0; Range range; bool rangeSupported = false; + bool hasSize = false; QList hashes; Thumbnail thumbnail; File::Spectrum audioSpectrum; @@ -95,6 +96,7 @@ File::File(const QDomElement &file) QString desc; size_t size = 0; bool rangeSupported = false; + bool hasSize = false; Range range; QList hashes; Thumbnail thumbnail; @@ -122,6 +124,7 @@ File::File(const QDomElement &file) if (!ok) { return; } + hasSize = true; } else if (ce.tagName() == QLatin1String("range")) { if (ce.hasAttribute(QLatin1String("offset"))) { @@ -197,6 +200,7 @@ File::File(const QDomElement &file) p->desc = desc; p->size = size; p->rangeSupported = rangeSupported; + p->hasSize = hasSize; p->range = range; p->hashes = hashes; p->thumbnail = thumbnail; @@ -284,6 +288,11 @@ bool File::hasComputedHashes() const return false; } +bool File::hasSize() const +{ + return d->hasSize; +} + QDateTime File::date() const { return d? d->date : QDateTime(); @@ -366,6 +375,7 @@ void File::setName(const QString &name) void File::setSize(quint64 size) { ensureD()->size = size; + d->hasSize = true; } void File::setRange(const Range &range) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 8053bf5b..f717de91 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -69,6 +69,7 @@ class File QDomElement toXml(QDomDocument *doc) const; bool merge(const File &other); bool hasComputedHashes() const; + bool hasSize() const; QDateTime date() const; QString description() const; From bf63af4ec4b6feea0cbbf2a9db7b7b14e26e931e Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 15 Jul 2019 01:22:18 +0300 Subject: [PATCH 092/383] Added streamed mode for jingle-ft --- src/xmpp/xmpp-im/jingle-ft.cpp | 81 +++++++++++++++++++++++++--------- src/xmpp/xmpp-im/jingle-ft.h | 17 ++++++- src/xmpp/xmpp-im/jingle.h | 1 + 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index af63dac6..db15c8ce 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -503,6 +503,7 @@ class Application::Private Connection::Ptr connection; QStringList availableTransports; bool closeDeviceOnFinish = true; + bool streamigMode = false; QIODevice *device = nullptr; quint64 bytesLeft = 0; @@ -684,27 +685,33 @@ bool Application::setTransport(const QSharedPointer &transport) d->transportReplaceOrigin = Origin::None; d->transportReplaceState = State::Finished; // not needed here probably d->connection = d->transport->connection(); - connect(d->connection.data(), &Connection::readyRead, this, [this](){ - if (!d->device) { - return; - } - if (d->pad->session()->role() != d->senders) { - d->readNextBlockFromTransport(); - } - }); - connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ - Q_UNUSED(bytes) - if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { - d->writeNextBlockToTransport(); - } - }); + if (d->streamigMode) { + connect(d->connection.data(), &Connection::readyRead, this, [this](){ + if (!d->device) { + return; + } + if (d->pad->session()->role() != d->senders) { + d->readNextBlockFromTransport(); + } + }); + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ + Q_UNUSED(bytes) + if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { + d->writeNextBlockToTransport(); + } + }); + } d->setState(State::Active); - if (d->acceptFile.range().isValid()) { - d->bytesLeft = d->acceptFile.range().length; - emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + if (d->streamigMode) { + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + } else { + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); + } } else { - d->bytesLeft = d->file.size(); - emit deviceRequested(0, d->bytesLeft); + emit connectionReady(); } }); @@ -764,6 +771,13 @@ QSharedPointer Application::transport() const return d->transport; } +void Application::setStreamingMode(bool mode) +{ + if (d->state <= State::Connecting) { + d->streamigMode = mode; + } +} + Action Application::evaluateOutgoingUpdate() { d->updateToSend = Action::NoAction; @@ -816,10 +830,10 @@ Action Application::evaluateOutgoingUpdate() break; case State::Finishing: - if (d->transportReplaceOrigin != Origin::None) { + if (d->transportReplaceOrigin != Origin::None || d->terminationReason.isValid()) { d->updateToSend = Action::ContentRemove; } else { - d->updateToSend = Action::SessionInfo; + d->updateToSend = Action::SessionInfo; // to send checksum } break; default: @@ -969,6 +983,26 @@ bool Application::accept(const QDomElement &el) return true; } +void Application::remove(Reason::Condition cond, const QString &comment) +{ + if (d->state >= State::Finishing) + return; + + d->terminationReason = Reason(cond, comment); + d->transportReplaceOrigin = Origin::None; // just in case + d->transport->disconnect(this); + d->transport.reset(); + + if (d->creator == d->pad->session()->role() && d->state <= State::PrepareLocalOffer) { + // local content, not yet sent to remote + setState(State::Finished); + return; + } + + setState(State::Finishing); + emit updated(); +} + bool Application::incomingTransportAccept(const QDomElement &transportEl) { if (d->transportReplaceOrigin != d->pad->session()->role()) { @@ -1009,6 +1043,11 @@ void Application::setDevice(QIODevice *dev, bool closeOnFinish) } } +Connection::Ptr Application::connection() const +{ + return d->connection.staticCast(); +} + Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index f717de91..7891227f 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -153,6 +153,18 @@ class Application : public XMPP::Jingle::Application bool setTransport(const QSharedPointer &transport) override; QSharedPointer transport() const override; + /** + * @brief setStreamingMode enables external download control. + * So Jingle-FT won't request output device but instead underlying established + * connection will be emitted (see connectionReady() signal). + * The connection is an XMPP::Jingle::Connection::Ptr instance. + * When the connection is not needed anymore, one can just destroy jingle + * session or remove the Application from the session. + * Make sure to set the mode before connection is established. + * @param mode + */ + void setStreamingMode(bool mode = true); + Action evaluateOutgoingUpdate() override; OutgoingUpdate takeOutgoingUpdate() override; bool wantBetterTransport(const QSharedPointer &) const override; @@ -160,17 +172,20 @@ class Application : public XMPP::Jingle::Application void prepare() override; void start() override; bool accept(const QDomElement &el) override; + void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) override; bool isValid() const; void setDevice(QIODevice *dev, bool closeOnFinish = true); + Connection::Ptr connection() const; protected: bool incomingTransportReplace(const QSharedPointer &transport) override; bool incomingTransportAccept(const QDomElement &transportEl) override; signals: - void deviceRequested(quint64 offset, quint64 size); // if size = 0 then it's reamaining part of the file + void connectionReady(); // streaming mode only + void deviceRequested(quint64 offset, quint64 size); // if size = 0 then it's reamaining part of the file (non-streaming mode only) void progress(quint64 offset); private: diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index cda4d5b1..c5ab81d1 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -445,6 +445,7 @@ class Application : public QObject virtual void prepare() = 0; virtual bool accept(const QDomElement &el) = 0; // remote accepted our content virtual void start() = 0; + virtual void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) = 0; /** * @brief incomingTransportReplace it's jingle transport-replace From 0badd8669c9b0b813b15a68f42790b272a8cef0e Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 16 Jul 2019 10:53:20 +0300 Subject: [PATCH 093/383] Cache http hosts --- src/xmpp/xmpp-im/httpfileupload.cpp | 33 +++++++++++++++++++++++++++++ src/xmpp/xmpp-im/httpfileupload.h | 12 +++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 9bc78ef6..08d68a7b 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -88,6 +88,21 @@ void HttpFileUpload::start() setState(State::GettingSlot); d->result.statusCode = HttpFileUpload::ErrorCode::NoError; + + auto mgr = d->client->httpFileUploadManager(); + if (mgr->discoveryStatus() == HttpFileUploadManager::DiscoNotFound) { + d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; + d->result.statusString = "No suitable http upload services were found"; + done(State::Error); + return; + } + + if (mgr->discoveryStatus() == HttpFileUploadManager::DiscoFound) { + d->httpHosts = mgr->discoHosts(); + tryNextServer(); + return; + } + static QList> featureOptions; if (featureOptions.isEmpty()) { featureOptions << (QSet() << xmlns_v0_2_5) << (QSet() << xmlns_v0_3_1); @@ -145,6 +160,7 @@ void HttpFileUpload::start() } } //d->currentHost = d->httpHosts.begin(); + d->client->httpFileUploadManager()->setDiscoHosts(d->httpHosts); if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; d->result.statusString = "No suitable http upload services were found"; @@ -423,6 +439,8 @@ class HttpFileUploadManager::Private { public: Client *client = nullptr; QPointer qnam; + int discoStatus = 0; + QList discoHosts; bool externalQnam = false; QLinkedList hosts; }; @@ -441,6 +459,11 @@ HttpFileUploadManager::~HttpFileUploadManager() delete d; } +int HttpFileUploadManager::discoveryStatus() const +{ + return d->discoStatus; +} + void HttpFileUploadManager::setNetworkAccessManager(QNetworkAccessManager *qnam) { d->externalQnam = true; @@ -464,3 +487,13 @@ HttpFileUpload* HttpFileUploadManager::upload(QIODevice *source, size_t fsize, c QMetaObject::invokeMethod(hfu, "start", Qt::QueuedConnection); return hfu; } + +const QList &HttpFileUploadManager::discoHosts() const +{ + return d->discoHosts; +} + +void HttpFileUploadManager::setDiscoHosts(const QList &hosts) +{ + d->discoStatus = hosts.size()? DiscoFound : DiscoNotFound; +} diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index e5666adf..5d3b78da 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -147,11 +147,19 @@ class HttpFileUploadManager : public QObject { Q_OBJECT public: + enum { + DiscoNone = 0x0, + DiscoNotFound = 0x1, + DiscoFound = 0x2 + }; + typedef std::function Callback; // params: success, detail. where detail could be a "get" url HttpFileUploadManager(Client *parent); ~HttpFileUploadManager(); + int discoveryStatus() const; + /** * @brief setNetworkAccessManager sets network access manager to do http requests. * @param qnam network access manager instance @@ -187,6 +195,10 @@ class HttpFileUploadManager : public QObject const QString &mType = QString()); private: + friend class HttpFileUpload; + const QList &discoHosts() const; + void setDiscoHosts(const QList &hosts); + class Private; Private *d; }; From 7b0e025ebd42830fdc5e2c5977c943e25b7a599c Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 17 Jul 2019 11:01:07 +0300 Subject: [PATCH 094/383] audio histogram improvements --- src/xmpp/xmpp-im/jingle-ft.cpp | 59 ++++++++++++++++++---------------- src/xmpp/xmpp-im/jingle-ft.h | 23 +++++++++++-- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index db15c8ce..454e6f19 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -29,7 +29,7 @@ namespace Jingle { namespace FileTransfer { const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); -const QString SPECTRUM_NS = QStringLiteral("iris.psi-im.org/spectrum"); +const QString HISTOGRAM_NS = QStringLiteral("urn:audio:histogram"); QDomElement Range::toXml(QDomDocument *doc) const { @@ -63,7 +63,7 @@ class File::Private : public QSharedData bool hasSize = false; QList hashes; Thumbnail thumbnail; - File::Spectrum audioSpectrum; + File::Histogram audioHistogram; }; File::File() @@ -100,7 +100,7 @@ File::File(const QDomElement &file) Range range; QList hashes; Thumbnail thumbnail; - Spectrum spectrum; + Histogram histogram; bool ok; @@ -171,25 +171,25 @@ File::File(const QDomElement &file) } else if (ce.tagName() == QLatin1String("thumbnail")) { thumbnail = Thumbnail(ce); - } else if (ce.tagName() == QLatin1String("spectrum") && (ce.namespaceURI() == SPECTRUM_NS || ce.namespaceURI() == SPECTRUM_NS)) { + } else if (ce.tagName() == QLatin1String("histogram") && (ce.namespaceURI() == HISTOGRAM_NS || ce.namespaceURI() == HISTOGRAM_NS)) { QStringList spv = ce.text().split(','); - spectrum.bars.reserve(spv.count()); - std::transform(spv.begin(), spv.end(), std::back_inserter(spectrum.bars), [](const QString &v){ return v.toUInt(); }); + histogram.bars.reserve(spv.count()); + std::transform(spv.begin(), spv.end(), std::back_inserter(histogram.bars), [](const QString &v){ return v.toUInt(); }); auto c = ce.attribute(QStringLiteral("coding")).toLatin1(); if (c == "u8") - spectrum.coding = File::Spectrum::Coding::U8; + histogram.coding = File::Histogram::Coding::U8; else if (c == "s8") - spectrum.coding = File::Spectrum::Coding::S8; + histogram.coding = File::Histogram::Coding::S8; else if (c == "u16") - spectrum.coding = File::Spectrum::Coding::U16; + histogram.coding = File::Histogram::Coding::U16; else if (c == "s16") - spectrum.coding = File::Spectrum::Coding::S16; + histogram.coding = File::Histogram::Coding::S16; else if (c == "u32") - spectrum.coding = File::Spectrum::Coding::U32; + histogram.coding = File::Histogram::Coding::U32; else if (c == "s32") - spectrum.coding = File::Spectrum::Coding::S32; + histogram.coding = File::Histogram::Coding::S32; else - spectrum.bars.clear(); // drop invalid spectrum + histogram.bars.clear(); // drop invalid histogram } } @@ -204,7 +204,7 @@ File::File(const QDomElement &file) p->range = range; p->hashes = hashes; p->thumbnail = thumbnail; - p->audioSpectrum = spectrum; + p->audioHistogram = histogram; d = p; } @@ -239,20 +239,20 @@ QDomElement File::toXml(QDomDocument *doc) const if (d->thumbnail.isValid()) { el.appendChild(d->thumbnail.toXml(doc)); } - if (d->audioSpectrum.bars.count()) { - auto sel = el.appendChild(doc->createElementNS(SPECTRUM_NS, QString::fromLatin1("spectrum"))).toElement(); + if (d->audioHistogram.bars.count()) { + auto sel = el.appendChild(doc->createElementNS(HISTOGRAM_NS, QString::fromLatin1("histogram"))).toElement(); const char* s[] = {"u8","s8","u16","s16","u32","s32"}; - sel.setAttribute(QString::fromLatin1("coding"), QString::fromLatin1(s[d->audioSpectrum.coding])); + sel.setAttribute(QString::fromLatin1("coding"), QString::fromLatin1(s[d->audioHistogram.coding])); QStringList sl; - std::transform(d->audioSpectrum.bars.begin(), d->audioSpectrum.bars.end(), std::back_inserter(sl), + std::transform(d->audioHistogram.bars.begin(), d->audioHistogram.bars.end(), std::back_inserter(sl), [this](quint32 v){ - switch (d->audioSpectrum.coding) { - case Spectrum::U8: return QString::number(quint8(v)); - case Spectrum::S8: return QString::number(qint8(v)); - case Spectrum::U16: return QString::number(quint16(v)); - case Spectrum::S16: return QString::number(qint16(v)); - case Spectrum::U32: return QString::number(quint32(v)); - case Spectrum::S32: return QString::number(qint32(v)); + switch (d->audioHistogram.coding) { + case Histogram::U8: return QString::number(quint8(v)); + case Histogram::S8: return QString::number(qint8(v)); + case Histogram::U16: return QString::number(quint16(v)); + case Histogram::S16: return QString::number(qint16(v)); + case Histogram::U32: return QString::number(quint32(v)); + case Histogram::S32: return QString::number(qint32(v)); } return QString(); }); @@ -342,9 +342,9 @@ Thumbnail File::thumbnail() const return d? d->thumbnail: Thumbnail(); } -File::Spectrum File::audioSpectrum() const +File::Histogram File::audioHistogram() const { - return d? d->audioSpectrum: Spectrum(); + return d? d->audioHistogram: Histogram(); } void File::setDate(const QDateTime &date) @@ -389,6 +389,11 @@ void File::setThumbnail(const Thumbnail &thumb) ensureD()->thumbnail = thumb; } +void File::setAudioHistogram(const File::Histogram &histogram) +{ + d->audioHistogram = histogram; +} + File::Private *File::ensureD() { if (!d) { diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 7891227f..bafab2df 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -48,7 +48,7 @@ struct Range { class File { public: - struct Spectrum + struct Histogram { enum Coding { U8, S8, @@ -79,7 +79,25 @@ class File quint64 size() const; Range range() const; Thumbnail thumbnail() const; - Spectrum audioSpectrum() const; + Histogram audioHistogram() const; + template + QList audioHistogram() const + { + QList ret; + auto hg = audioHistogram(); + std::function normalizer; + switch (hg.coding) { + case Histogram::U8: normalizer = [](quint32 v){ return v/T(255); }; break; + case Histogram::S8: normalizer = [](quint32 v){ return std::abs(v/T(128)); }; break; + case Histogram::U16: normalizer = [](quint32 v){ return v/T(2<<16); }; break; + case Histogram::S16: normalizer = [](quint32 v){ return std::abs(v/T(2<<15)); }; break; + case Histogram::U32: normalizer = [](quint32 v){ return quint64(v)/T(2L<<32); }; break; + case Histogram::S32: normalizer = [](quint32 v){ return std::abs(qint64(v)/T(2L<<31)); }; break; + } + if (normalizer) + std::transform(hg.bars.begin(), hg.bars.end(), std::back_inserter(ret), normalizer); + return ret; + } void setDate(const QDateTime &date); void setDescription(const QString &desc); @@ -89,6 +107,7 @@ class File void setSize(quint64 size); void setRange(const Range &range = Range()); // default empty just to indicate it's supported void setThumbnail(const Thumbnail &thumb); + void setAudioHistogram(const Histogram &histogram); private: class Private; Private *ensureD(); From bb267f2c990b1d535868a55bf91408a8d2f585cd Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 17 Jul 2019 21:37:51 +0300 Subject: [PATCH 095/383] Remove buggy audioHistogram templated function --- src/xmpp/xmpp-im/jingle-ft.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index bafab2df..91504a8d 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -80,24 +80,6 @@ class File Range range() const; Thumbnail thumbnail() const; Histogram audioHistogram() const; - template - QList audioHistogram() const - { - QList ret; - auto hg = audioHistogram(); - std::function normalizer; - switch (hg.coding) { - case Histogram::U8: normalizer = [](quint32 v){ return v/T(255); }; break; - case Histogram::S8: normalizer = [](quint32 v){ return std::abs(v/T(128)); }; break; - case Histogram::U16: normalizer = [](quint32 v){ return v/T(2<<16); }; break; - case Histogram::S16: normalizer = [](quint32 v){ return std::abs(v/T(2<<15)); }; break; - case Histogram::U32: normalizer = [](quint32 v){ return quint64(v)/T(2L<<32); }; break; - case Histogram::S32: normalizer = [](quint32 v){ return std::abs(qint64(v)/T(2L<<31)); }; break; - } - if (normalizer) - std::transform(hg.bars.begin(), hg.bars.end(), std::back_inserter(ret), normalizer); - return ret; - } void setDate(const QDateTime &date); void setDescription(const QString &desc); From 42f5e399a1f4b24731d1bd0f7ed834398b963912 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Wed, 17 Jul 2019 22:31:18 +0300 Subject: [PATCH 096/383] Fixed http host queries optimization --- src/xmpp/xmpp-im/httpfileupload.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 08d68a7b..89695f63 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -174,8 +174,10 @@ void HttpFileUpload::start() void HttpFileUpload::tryNextServer() { if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services - d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; - d->result.statusString = "All http services are either non compliant or returned errors"; + if (d->result.statusCode == HttpFileUpload::ErrorCode::NoError) { + d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; + d->result.statusString = "All http services are either non compliant or returned errors"; + } done(State::Error); return; } @@ -233,6 +235,7 @@ void HttpFileUpload::tryNextServer() } else { d->result.statusCode = ErrorCode::HttpFailed; d->result.statusString = reply->errorString(); + qDebug("http upload failed: %s", qPrintable(d->result.statusString)); if (d->httpHosts.isEmpty()) done(State::Error); else @@ -496,4 +499,5 @@ const QList &HttpFileUploadManager::discoHosts() const void HttpFileUploadManager::setDiscoHosts(const QList &hosts) { d->discoStatus = hosts.size()? DiscoFound : DiscoNotFound; + d->discoHosts = hosts; } From c4ea8721cd94f7456a6b90508c078d15f2fd7489 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Tue, 30 Jul 2019 00:04:14 +0300 Subject: [PATCH 097/383] Allow register external jingle manager sessions in advance --- src/xmpp/xmpp-im/jingle.cpp | 6 ++++++ src/xmpp/xmpp-im/jingle.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 1066e592..128643f3 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -456,6 +456,7 @@ class JTPush : public Task inline void addExternalManager(const QString &ns) { externalManagers.append(ns); } inline void forgetExternalSession(const QString &sid) { externalSessions.removeOne(sid); } + inline void registerExternalSession(const QString &sid) { externalSessions.append(sid); } bool take(const QDomElement &iq) @@ -1708,6 +1709,11 @@ void Manager::addExternalManager(const QString &ns) d->pushTask->addExternalManager(ns); } +void Manager::registerExternalSession(const QString &sid) +{ + d->pushTask->registerExternalSession(sid); +} + void Manager::forgetExternalSession(const QString &sid) { d->pushTask->forgetExternalSession(sid); diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index c5ab81d1..8765cea1 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -574,6 +574,7 @@ class Manager : public QObject // if we have another jingle manager we can add its contents' namespaces here. void addExternalManager(const QString &ns); // on outgoing session destroy an external manager should call this function. + void registerExternalSession(const QString &sid); void forgetExternalSession(const QString &sid); void setRedirection(const Jid &to); From 103086126c245782b056731d7c0ded1faa30a738 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Mon, 26 Aug 2019 01:31:48 +0300 Subject: [PATCH 098/383] Added method to return voice histogram in float format --- src/xmpp/xmpp-im/jingle-ft.cpp | 27 +++++++++++++++++++++++++++ src/xmpp/xmpp-im/jingle-ft.h | 1 + 2 files changed, 28 insertions(+) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 454e6f19..54059868 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -23,6 +23,9 @@ #include "xmpp_hash.h" #include "xmpp_xmlcommon.h" +#include +#include + namespace XMPP { namespace Jingle { @@ -347,6 +350,30 @@ File::Histogram File::audioHistogram() const return d? d->audioHistogram: Histogram(); } +QList File::audioFloatHistogram() const +{ + QList ret; + if (!d->audioHistogram.bars.count()) + return ret; + + std::function normalizer; + switch (d->audioHistogram.coding) { + case Histogram::U8: normalizer = [](quint32 v){ return quint8(v) / 255.0f; }; break; + case Histogram::S8: normalizer = [](quint32 v){ return std::fabs(qint8(v) / 128.0f); }; break; + case Histogram::U16: normalizer = [](quint32 v){ return quint16(v) / float(1 << 16); }; break; + case Histogram::S16: normalizer = [](quint32 v){ return std::fabs(qint16(v) / float(1 << 15)); }; break; + case Histogram::U32: normalizer = [](quint32 v){ return quint32(v) / float(quint64(1) << 32); }; break; + case Histogram::S32: normalizer = [](quint32 v){ return std::fabs(qint32(v) / float(quint64(1) << 31)); }; break; + } + + if (normalizer) { + ret.reserve(d->audioHistogram.bars.count()); + std::transform(d->audioHistogram.bars.begin(), d->audioHistogram.bars.end(), std::back_inserter(ret), normalizer); + } + + return ret; +} + void File::setDate(const QDateTime &date) { ensureD()->date = date; diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 91504a8d..a905bc66 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -80,6 +80,7 @@ class File Range range() const; Thumbnail thumbnail() const; Histogram audioHistogram() const; + QList audioFloatHistogram() const; void setDate(const QDateTime &date); void setDescription(const QString &desc); From 51805e9f6eccbeddba7f5fd68f153e0dcb95ecdd Mon Sep 17 00:00:00 2001 From: Neustradamus <104737+Neustradamus@users.noreply.github.com> Date: Sat, 31 Aug 2019 06:33:43 +0200 Subject: [PATCH 099/383] beautify some code parts (#62) sort headers etc --- COPYING | 2 - cmake/modules/FindIDN.cmake | 2 +- cmake/modules/FindQJDns.cmake | 2 +- cmake/modules/FindQca.cmake | 2 +- configure | 5 +- src/irisnet/appledns/appledns.cpp | 9 ++-- src/irisnet/appledns/qdnssd.cpp | 14 ++---- src/irisnet/appledns/qdnssd.h | 4 +- src/irisnet/appledns/sdtest.cpp | 7 ++- src/irisnet/corelib/addressresolver.cpp | 5 +- src/irisnet/corelib/addressresolver.h | 8 ++-- src/irisnet/corelib/irisnetexport.h | 2 +- src/irisnet/corelib/irisnetglobal.cpp | 4 +- src/irisnet/corelib/irisnetglobal.h | 10 ++-- src/irisnet/corelib/irisnetglobal_p.h | 6 +-- src/irisnet/corelib/irisnetplugin.cpp | 3 +- src/irisnet/corelib/irisnetplugin.h | 16 +++---- src/irisnet/corelib/netavailability.cpp | 3 +- src/irisnet/corelib/netavailability.h | 6 +-- src/irisnet/corelib/netinterface.cpp | 17 ++----- src/irisnet/corelib/netinterface.h | 8 ++-- src/irisnet/corelib/netinterface_qtname.cpp | 4 +- src/irisnet/corelib/netinterface_qtnet.cpp | 4 +- src/irisnet/corelib/netinterface_unix.cpp | 20 ++++---- src/irisnet/corelib/netnames.cpp | 21 ++------- src/irisnet/corelib/netnames.h | 18 ++------ src/irisnet/corelib/netnames_jdns.cpp | 7 +-- src/irisnet/corelib/objectsession.cpp | 9 ++-- src/irisnet/corelib/objectsession.h | 6 +-- src/irisnet/noncore/cutestuff/bsocket.cpp | 13 ++---- src/irisnet/noncore/cutestuff/bsocket.h | 18 +++----- src/irisnet/noncore/cutestuff/bytestream.cpp | 1 + src/irisnet/noncore/cutestuff/bytestream.h | 7 ++- src/irisnet/noncore/cutestuff/httpconnect.cpp | 8 ++-- src/irisnet/noncore/cutestuff/httpconnect.h | 3 +- src/irisnet/noncore/cutestuff/httppoll.cpp | 16 +++---- src/irisnet/noncore/cutestuff/httppoll.h | 3 +- src/irisnet/noncore/cutestuff/socks.cpp | 30 ++++++------ src/irisnet/noncore/cutestuff/socks.h | 5 +- src/irisnet/noncore/ice176.cpp | 20 ++++---- src/irisnet/noncore/ice176.h | 13 +++--- src/irisnet/noncore/icecomponent.cpp | 14 +++--- src/irisnet/noncore/icecomponent.h | 11 ++--- src/irisnet/noncore/icelocaltransport.cpp | 16 +++---- src/irisnet/noncore/icelocaltransport.h | 13 +++--- src/irisnet/noncore/icetransport.cpp | 3 +- src/irisnet/noncore/icetransport.h | 8 ++-- src/irisnet/noncore/iceturntransport.cpp | 6 +-- src/irisnet/noncore/iceturntransport.h | 14 +++--- src/irisnet/noncore/legacy/ndns.cpp | 2 +- src/irisnet/noncore/legacy/ndns.h | 8 ++-- src/irisnet/noncore/legacy/srvresolver.cpp | 1 - src/irisnet/noncore/legacy/srvresolver.h | 6 +-- src/irisnet/noncore/processquit.cpp | 15 ++---- src/irisnet/noncore/processquit.h | 2 +- src/irisnet/noncore/stunallocate.cpp | 17 ++++--- src/irisnet/noncore/stunallocate.h | 10 ++-- src/irisnet/noncore/stunbinding.cpp | 9 ++-- src/irisnet/noncore/stunbinding.h | 6 +-- src/irisnet/noncore/stunmessage.cpp | 7 ++- src/irisnet/noncore/stunmessage.h | 6 +-- src/irisnet/noncore/stuntransaction.cpp | 12 ++--- src/irisnet/noncore/stuntransaction.h | 11 ++--- src/irisnet/noncore/stuntypes.cpp | 14 ++---- src/irisnet/noncore/stuntypes.h | 16 +++---- src/irisnet/noncore/stunutil.cpp | 8 +--- src/irisnet/noncore/stunutil.h | 9 ++-- src/irisnet/noncore/tcpportreserver.cpp | 11 ++--- src/irisnet/noncore/tcpportreserver.h | 5 +- src/irisnet/noncore/turnclient.cpp | 19 ++++---- src/irisnet/noncore/turnclient.h | 12 ++--- src/irisnet/noncore/udpportreserver.cpp | 6 +-- src/irisnet/noncore/udpportreserver.h | 8 ++-- src/jdns/CMakeLists.txt | 2 - src/jdns/include/jdns/jdns.h | 4 +- src/jdns/include/jdns/jdns_export.h | 2 +- src/jdns/include/jdns/qjdns.h | 5 +- src/jdns/include/jdns/qjdnsshared.h | 6 +-- src/jdns/src/jdns/CMakeLists.txt | 1 - src/jdns/src/jdns/jdns.c | 5 +- src/jdns/src/jdns/jdns_mdnsd.c | 3 +- src/jdns/src/jdns/jdns_mdnsd.h | 5 +- src/jdns/src/jdns/jdns_p.h | 20 ++++---- src/jdns/src/jdns/jdns_packet.h | 2 +- src/jdns/src/jdns/jdns_sys.c | 11 ++--- src/jdns/src/jdns/jdns_util.c | 1 - src/jdns/src/qjdns/qjdns.cpp | 6 +-- src/jdns/src/qjdns/qjdns_p.h | 9 ++-- src/jdns/src/qjdns/qjdns_sock.cpp | 24 +++++----- src/jdns/src/qjdns/qjdns_sock.h | 4 +- src/jdns/src/qjdns/qjdnsshared.cpp | 3 +- src/jdns/src/qjdns/qjdnsshared_p.h | 15 +++--- src/jdns/tools/jdns/main.cpp | 5 +- src/jdns/tools/jdns/main.h | 1 + src/xmpp/base/randomnumbergenerator.cpp | 4 +- src/xmpp/base/randomnumbergenerator.h | 4 +- src/xmpp/base/randrandomnumbergenerator.h | 4 +- src/xmpp/base/timezone.cpp | 23 +++++----- .../incrementingrandomnumbergenerator.h | 8 ++-- .../unittest/randomnumbergeneratortest.cpp | 6 +-- .../randrandomnumbergeneratortest.cpp | 6 +-- src/xmpp/blake2/blake2-impl.h | 2 +- src/xmpp/blake2/blake2.h | 3 +- src/xmpp/blake2/blake2b-ref.c | 14 ++---- src/xmpp/blake2/blake2qt.cpp | 3 +- src/xmpp/blake2/blake2qt.h | 5 +- src/xmpp/blake2/blake2s-ref.c | 11 ++--- src/xmpp/jid/jid.cpp | 9 ++-- src/xmpp/jid/jid.h | 11 ++--- src/xmpp/jid/unittest/jidtest.cpp | 6 +-- .../qttestutil/example/myfirstclasstest.cpp | 4 +- .../qttestutil/example/mysecondclasstest.cpp | 4 +- src/xmpp/qa/qttestutil/qttestutil.h | 2 +- src/xmpp/qa/qttestutil/simplechecker.cpp | 4 +- src/xmpp/qa/qttestutil/testregistration.h | 6 +-- src/xmpp/qa/qttestutil/testregistry.cpp | 4 +- src/xmpp/qa/qttestutil/testregistry.h | 5 +- src/xmpp/qa/unittest.pri | 1 - src/xmpp/qa/unittest.template/myclasstest.cpp | 4 +- src/xmpp/sasl/digestmd5proplist.cpp | 3 +- src/xmpp/sasl/digestmd5proplist.h | 6 +-- src/xmpp/sasl/digestmd5response.cpp | 10 ++-- src/xmpp/sasl/digestmd5response.h | 4 +- src/xmpp/sasl/plainmessage.cpp | 3 +- src/xmpp/sasl/plainmessage.h | 4 +- src/xmpp/sasl/scramsha1message.cpp | 12 ++--- src/xmpp/sasl/scramsha1message.h | 8 ++-- src/xmpp/sasl/scramsha1response.cpp | 11 ++--- src/xmpp/sasl/scramsha1response.h | 4 +- src/xmpp/sasl/scramsha1signature.cpp | 10 ++-- src/xmpp/sasl/scramsha1signature.h | 4 +- .../sasl/unittest/digestmd5responsetest.cpp | 10 ++-- src/xmpp/sasl/unittest/plainmessagetest.cpp | 6 +-- .../sasl/unittest/scramsha1messagetest.cpp | 8 ++-- .../sasl/unittest/scramsha1responsetest.cpp | 10 ++-- src/xmpp/xmpp-core/compressionhandler.cpp | 6 +-- src/xmpp/xmpp-core/compressionhandler.h | 4 +- src/xmpp/xmpp-core/connector.cpp | 17 +++---- src/xmpp/xmpp-core/parser.cpp | 7 +-- src/xmpp/xmpp-core/parser.h | 7 ++- src/xmpp/xmpp-core/protocol.cpp | 10 ++-- src/xmpp/xmpp-core/protocol.h | 17 ++++--- src/xmpp/xmpp-core/securestream.cpp | 10 ++-- src/xmpp/xmpp-core/securestream.h | 9 ++-- src/xmpp/xmpp-core/simplesasl.cpp | 27 ++++++----- src/xmpp/xmpp-core/simplesasl.h | 5 +- src/xmpp/xmpp-core/sm.cpp | 6 +-- src/xmpp/xmpp-core/sm.h | 11 ++--- src/xmpp/xmpp-core/stream.cpp | 35 ++++++-------- src/xmpp/xmpp-core/td.h | 3 +- src/xmpp/xmpp-core/tlshandler.cpp | 7 +-- src/xmpp/xmpp-core/xmlprotocol.cpp | 11 ++--- src/xmpp/xmpp-core/xmlprotocol.h | 12 ++--- src/xmpp/xmpp-core/xmpp.h | 34 ++++++-------- src/xmpp/xmpp-core/xmpp_clientstream.h | 19 ++++---- src/xmpp/xmpp-core/xmpp_stanza.cpp | 9 ++-- src/xmpp/xmpp-core/xmpp_stanza.h | 11 ++--- src/xmpp/xmpp-core/xmpp_stream.h | 13 +++--- src/xmpp/xmpp-im/client.cpp | 42 ++++++++--------- src/xmpp/xmpp-im/filetransfer.cpp | 11 +++-- src/xmpp/xmpp-im/filetransfer.h | 8 ++-- src/xmpp/xmpp-im/httpfileupload.cpp | 14 +++--- src/xmpp/xmpp-im/httpfileupload.h | 25 +++++----- src/xmpp/xmpp-im/im.h | 46 +++++++++---------- src/xmpp/xmpp-im/jingle-ft.cpp | 8 +--- src/xmpp/xmpp-im/jingle-ft.h | 2 - src/xmpp/xmpp-im/jingle-ibb.cpp | 4 +- src/xmpp/xmpp-im/jingle-ibb.h | 2 - src/xmpp/xmpp-im/jingle-s5b.cpp | 13 ++---- src/xmpp/xmpp-im/jingle-s5b.h | 4 +- src/xmpp/xmpp-im/jingle.cpp | 22 ++------- src/xmpp/xmpp-im/jingle.h | 7 +-- src/xmpp/xmpp-im/s5b.cpp | 19 +++----- src/xmpp/xmpp-im/s5b.h | 28 ++++++----- src/xmpp/xmpp-im/types.cpp | 46 +++++-------------- src/xmpp/xmpp-im/xmpp_address.h | 11 ++--- src/xmpp/xmpp-im/xmpp_agentitem.h | 9 ++-- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 14 +++--- src/xmpp/xmpp-im/xmpp_bitsofbinary.h | 22 ++++----- src/xmpp/xmpp-im/xmpp_bytestream.cpp | 12 ++--- src/xmpp/xmpp-im/xmpp_bytestream.h | 16 +++---- src/xmpp/xmpp-im/xmpp_caps.cpp | 26 ++++------- src/xmpp/xmpp-im/xmpp_caps.h | 13 ++---- src/xmpp/xmpp-im/xmpp_captcha.h | 15 +++--- src/xmpp/xmpp-im/xmpp_chatstate.h | 4 +- src/xmpp/xmpp-im/xmpp_client.h | 35 +++++++------- src/xmpp/xmpp-im/xmpp_discoinfotask.cpp | 20 ++++---- src/xmpp/xmpp-im/xmpp_discoinfotask.h | 18 ++++---- src/xmpp/xmpp-im/xmpp_discoitem.cpp | 6 +-- src/xmpp/xmpp-im/xmpp_discoitem.h | 12 ++--- src/xmpp/xmpp-im/xmpp_encryptionhandler.h | 5 +- src/xmpp/xmpp-im/xmpp_features.cpp | 12 ++--- src/xmpp/xmpp-im/xmpp_features.h | 9 ++-- src/xmpp/xmpp-im/xmpp_hash.h | 9 ++-- src/xmpp/xmpp-im/xmpp_htmlelement.h | 7 ++- src/xmpp/xmpp-im/xmpp_httpauthrequest.h | 9 ++-- src/xmpp/xmpp-im/xmpp_ibb.cpp | 10 ++-- src/xmpp/xmpp-im/xmpp_ibb.h | 23 +++++----- src/xmpp/xmpp-im/xmpp_liveroster.h | 11 ++--- src/xmpp/xmpp-im/xmpp_liverosteritem.h | 9 ++-- src/xmpp/xmpp-im/xmpp_message.h | 25 +++++----- src/xmpp/xmpp-im/xmpp_muc.h | 12 ++--- src/xmpp/xmpp-im/xmpp_pubsubitem.h | 9 ++-- src/xmpp/xmpp-im/xmpp_pubsubretraction.h | 10 ++-- src/xmpp/xmpp-im/xmpp_receipts.h | 4 +- src/xmpp/xmpp-im/xmpp_reference.h | 11 ++--- src/xmpp/xmpp-im/xmpp_resource.h | 11 ++--- src/xmpp/xmpp-im/xmpp_resourcelist.h | 11 ++--- src/xmpp/xmpp-im/xmpp_roster.h | 12 ++--- src/xmpp/xmpp-im/xmpp_rosteritem.h | 11 ++--- src/xmpp/xmpp-im/xmpp_rosterx.h | 11 ++--- src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp | 7 ++- src/xmpp/xmpp-im/xmpp_serverinfomanager.h | 8 +--- src/xmpp/xmpp-im/xmpp_status.h | 22 ++++----- src/xmpp/xmpp-im/xmpp_subsets.cpp | 1 + src/xmpp/xmpp-im/xmpp_subsets.h | 7 ++- src/xmpp/xmpp-im/xmpp_task.cpp | 9 ++-- src/xmpp/xmpp-im/xmpp_task.h | 4 +- src/xmpp/xmpp-im/xmpp_tasks.cpp | 34 ++++---------- src/xmpp/xmpp-im/xmpp_tasks.h | 29 ++++++------ src/xmpp/xmpp-im/xmpp_thumbs.h | 9 ++-- src/xmpp/xmpp-im/xmpp_url.h | 7 ++- src/xmpp/xmpp-im/xmpp_vcard.cpp | 10 ++-- src/xmpp/xmpp-im/xmpp_vcard.h | 33 +++---------- src/xmpp/xmpp-im/xmpp_xdata.cpp | 11 ++--- src/xmpp/xmpp-im/xmpp_xdata.h | 20 ++++---- src/xmpp/xmpp-im/xmpp_xmlcommon.cpp | 24 ++++------ src/xmpp/xmpp-im/xmpp_xmlcommon.h | 15 +++--- src/xmpp/zlib/common.h | 2 +- src/xmpp/zlib/zlibcompressor.cpp | 8 ++-- src/xmpp/zlib/zlibcompressor.h | 6 +-- src/xmpp/zlib/zlibdecompressor.cpp | 8 ++-- src/xmpp/zlib/zlibdecompressor.h | 6 +-- tools/nettool/main.cpp | 14 +++--- tools/xmpptest/xmpptest.cpp | 32 ++++++------- 235 files changed, 1018 insertions(+), 1429 deletions(-) diff --git a/COPYING b/COPYING index 5ab7695a..732811e4 100644 --- a/COPYING +++ b/COPYING @@ -500,5 +500,3 @@ necessary. Here is a sample; alter the names: Ty Coon, President of Vice That's all there is to it! - - diff --git a/cmake/modules/FindIDN.cmake b/cmake/modules/FindIDN.cmake index ea3a9133..5fbe937a 100644 --- a/cmake/modules/FindIDN.cmake +++ b/cmake/modules/FindIDN.cmake @@ -1,5 +1,5 @@ #============================================================================= -# Copyright 2016-2017 Psi+ Project, Vitaly Tonkacheyev +# Copyright (C) 2016-2017 Psi+ Project, Vitaly Tonkacheyev # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/cmake/modules/FindQJDns.cmake b/cmake/modules/FindQJDns.cmake index 1b2359fd..77568649 100644 --- a/cmake/modules/FindQJDns.cmake +++ b/cmake/modules/FindQJDns.cmake @@ -1,5 +1,5 @@ #============================================================================= -# Copyright 2016-2017 Psi+ Project +# Copyright (C) 2016-2017 Psi+ Project # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/cmake/modules/FindQca.cmake b/cmake/modules/FindQca.cmake index a82ada09..17e5a14a 100644 --- a/cmake/modules/FindQca.cmake +++ b/cmake/modules/FindQca.cmake @@ -1,5 +1,5 @@ #============================================================================= -# Copyright 2016-2017 Psi+ Project, Vitaly Tonkacheyev +# Copyright (C) 2016-2017 Psi+ Project, Vitaly Tonkacheyev # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/configure b/configure index af0fcd87..d76a9b55 100755 --- a/configure +++ b/configure @@ -257,7 +257,6 @@ while [ $# -gt 0 ]; do esac done - echo "Configuring Iris ..." if [ "$QC_VERBOSE" = "Y" ]; then @@ -1384,9 +1383,9 @@ preserved. #include "conf4.h" +#include #include #include -#include #ifndef PATH_MAX # ifdef Q_OS_WIN # define PATH_MAX 260 @@ -1658,7 +1657,6 @@ QString qc_escapeArg(const QString &str) return out; } - QString qc_trim_char(const QString &s, const QChar &ch) { if (s.startsWith(ch) && s.endsWith(ch)) { @@ -2495,7 +2493,6 @@ DESTDIR = \$\$PWD HEADERS += conf4.h SOURCES += conf4.cpp - DEFINES += HAVE_MODULES greaterThan(QT_MAJOR_VERSION, 4):CONFIG += c++11 diff --git a/src/irisnet/appledns/appledns.cpp b/src/irisnet/appledns/appledns.cpp index f0f054ba..e08d8e66 100644 --- a/src/irisnet/appledns/appledns.cpp +++ b/src/irisnet/appledns/appledns.cpp @@ -17,13 +17,11 @@ */ #include "irisnetplugin.h" +#include "qdnssd.h" #include #include -#include "qdnssd.h" - -// for ntohl -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN // for ntohl # include #else # include @@ -152,7 +150,6 @@ static XMPP::NameRecord importQDnsSdRecord(const QDnsSd::Record &in) } namespace { - class QDnsSdDelegate { public: @@ -227,7 +224,7 @@ class IdManager } }; -} +} // namespace //---------------------------------------------------------------------------- // AppleProvider diff --git a/src/irisnet/appledns/qdnssd.cpp b/src/irisnet/appledns/qdnssd.cpp index 9be138e2..75a0d39f 100644 --- a/src/irisnet/appledns/qdnssd.cpp +++ b/src/irisnet/appledns/qdnssd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007,2008 Justin Karneges + * Copyright (C) 2007-2008 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,22 +18,18 @@ #include "qdnssd.h" +#include "dns_sd.h" + #include #include - -// for ntohs -#ifdef Q_OS_WIN +#ifdef Q_OS_WIN // for ntohs # include #else # include #endif -#include "dns_sd.h" - namespace { - // safeobj stuff, from qca - void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); @@ -210,7 +206,7 @@ class IdManager } }; -} +} // namespace //---------------------------------------------------------------------------- // QDnsSd diff --git a/src/irisnet/appledns/qdnssd.h b/src/irisnet/appledns/qdnssd.h index 6edb3bd6..7996cd51 100644 --- a/src/irisnet/appledns/qdnssd.h +++ b/src/irisnet/appledns/qdnssd.h @@ -19,9 +19,9 @@ #ifndef QDNSSD_H #define QDNSSD_H -#include #include #include +#include // DOR-compliant class QDnsSd : public QObject @@ -156,4 +156,4 @@ class QDnsSd : public QObject Private *d; }; -#endif +#endif // QDNSSD_H diff --git a/src/irisnet/appledns/sdtest.cpp b/src/irisnet/appledns/sdtest.cpp index 5a69fe02..b60c6223 100644 --- a/src/irisnet/appledns/sdtest.cpp +++ b/src/irisnet/appledns/sdtest.cpp @@ -16,12 +16,11 @@ * */ -#include -#include #include "qdnssd.h" -// for ntohl -#ifdef Q_OS_WIN +#include +#include +#ifdef Q_OS_WIN // for ntohl # include #else # include diff --git a/src/irisnet/corelib/addressresolver.cpp b/src/irisnet/corelib/addressresolver.cpp index cc2e1b1c..d43f1dd4 100644 --- a/src/irisnet/corelib/addressresolver.cpp +++ b/src/irisnet/corelib/addressresolver.cpp @@ -18,11 +18,10 @@ #include "addressresolver.h" -#include "objectsession.h" #include "netnames.h" +#include "objectsession.h" namespace XMPP { - class AddressResolver::Private : public QObject { Q_OBJECT @@ -207,6 +206,6 @@ void AddressResolver::stop() d->stop(); } -} +} // namespace XMPP #include "addressresolver.moc" diff --git a/src/irisnet/corelib/addressresolver.h b/src/irisnet/corelib/addressresolver.h index 8d419820..39d1bee9 100644 --- a/src/irisnet/corelib/addressresolver.h +++ b/src/irisnet/corelib/addressresolver.h @@ -19,11 +19,10 @@ #ifndef ADDRESSRESOLVER_H #define ADDRESSRESOLVER_H -#include #include +#include namespace XMPP { - // resolve both AAAA and A for a hostname class AddressResolver : public QObject { @@ -50,7 +49,6 @@ class AddressResolver : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // ADDRESSRESOLVER_H diff --git a/src/irisnet/corelib/irisnetexport.h b/src/irisnet/corelib/irisnetexport.h index 55f2226b..3eaf4970 100644 --- a/src/irisnet/corelib/irisnetexport.h +++ b/src/irisnet/corelib/irisnetexport.h @@ -31,4 +31,4 @@ # endif #endif -#endif +#endif // IRISNETEXPORT_H diff --git a/src/irisnet/corelib/irisnetglobal.cpp b/src/irisnet/corelib/irisnetglobal.cpp index bc10deb8..848b262d 100644 --- a/src/irisnet/corelib/irisnetglobal.cpp +++ b/src/irisnet/corelib/irisnetglobal.cpp @@ -17,11 +17,9 @@ */ #include "irisnetglobal_p.h" - #include "irisnetplugin.h" namespace XMPP { - // built-in providers extern IrisNetProvider *irisnet_createQtNetProvider(); #ifdef Q_OS_UNIX @@ -304,4 +302,4 @@ QList irisNetProviders() return global->pluginManager.providers; } -} +} // namespace XMPP diff --git a/src/irisnet/corelib/irisnetglobal.h b/src/irisnet/corelib/irisnetglobal.h index 9aae0198..8d62337e 100644 --- a/src/irisnet/corelib/irisnetglobal.h +++ b/src/irisnet/corelib/irisnetglobal.h @@ -19,19 +19,17 @@ #ifndef IRISNETGLOBAL_H #define IRISNETGLOBAL_H +#include "irisnetexport.h" + #include #include -#include "irisnetexport.h" namespace XMPP { - // set the directories for plugins. call before doing anything else. IRISNET_EXPORT void irisNetSetPluginPaths(const QStringList &paths); - // free any shared data and plugins. // note: this is automatically called when qapp shuts down. IRISNET_EXPORT void irisNetCleanup(); +} // namespace XMPP -} - -#endif +#endif // IRISNETGLOBAL_H diff --git a/src/irisnet/corelib/irisnetglobal_p.h b/src/irisnet/corelib/irisnetglobal_p.h index 4b9d070e..2864627e 100644 --- a/src/irisnet/corelib/irisnetglobal_p.h +++ b/src/irisnet/corelib/irisnetglobal_p.h @@ -23,12 +23,10 @@ #include "irisnetplugin.h" namespace XMPP { - typedef void (*IrisNetCleanUpFunction)(); IRISNET_EXPORT void irisNetAddPostRoutine(IrisNetCleanUpFunction func); IRISNET_EXPORT QList irisNetProviders(); +} // namespace XMPP -} - -#endif +#endif // IRISNETGLOBAL_P_H diff --git a/src/irisnet/corelib/irisnetplugin.cpp b/src/irisnet/corelib/irisnetplugin.cpp index ead49f5e..6e1faaae 100644 --- a/src/irisnet/corelib/irisnetplugin.cpp +++ b/src/irisnet/corelib/irisnetplugin.cpp @@ -19,7 +19,6 @@ #include "irisnetplugin.h" namespace XMPP { - //---------------------------------------------------------------------------- // IrisNetProvider //---------------------------------------------------------------------------- @@ -84,4 +83,4 @@ void NameProvider::resolve_localError(int id, XMPP::NameResolver::Error e) Q_UNUSED(e); } -} +} // namespace XMPP diff --git a/src/irisnet/corelib/irisnetplugin.h b/src/irisnet/corelib/irisnetplugin.h index 97274c21..5005129c 100644 --- a/src/irisnet/corelib/irisnetplugin.h +++ b/src/irisnet/corelib/irisnetplugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006,2008 Justin Karneges + * Copyright (C) 2006-2008 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,16 +20,15 @@ #define IRISNETPLUGIN_H #include "irisnetglobal.h" -#include "netinterface.h" #include "netavailability.h" +#include "netinterface.h" #include "netnames.h" namespace XMPP { - -class NetInterfaceProvider; -class NetGatewayProvider; -class NetAvailabilityProvider; class NameProvider; +class NetAvailabilityProvider; +class NetGatewayProvider; +class NetInterfaceProvider; class ServiceProvider; class IRISNET_EXPORT IrisNetProvider : public QObject @@ -191,8 +190,7 @@ class IRISNET_EXPORT ServiceProvider : public QObject void publish_extra_published(int id); void publish_extra_error(int id, XMPP::ServiceLocalPublisher::Error e); }; - -} +} // namespace XMPP Q_DECLARE_INTERFACE(XMPP::NetGatewayProvider, "com.affinix.irisnet.IrisGatewayProvider/1.0") Q_DECLARE_INTERFACE(XMPP::IrisNetProvider, "com.affinix.irisnet.IrisNetProvider/1.0") @@ -200,4 +198,4 @@ Q_DECLARE_INTERFACE(XMPP::NetInterfaceProvider, "com.affinix.irisnet.NetInterfac Q_DECLARE_INTERFACE(XMPP::NameProvider, "com.affinix.irisnet.NameProvider/1.0") Q_DECLARE_INTERFACE(XMPP::ServiceProvider, "com.affinix.irisnet.ServiceProvider/1.0") -#endif +#endif // IRISNETPLUGIN_H diff --git a/src/irisnet/corelib/netavailability.cpp b/src/irisnet/corelib/netavailability.cpp index 7c5db6ed..782e3c68 100644 --- a/src/irisnet/corelib/netavailability.cpp +++ b/src/irisnet/corelib/netavailability.cpp @@ -19,7 +19,6 @@ #include "netavailability.h" namespace XMPP { - class NetAvailability::Private : public QObject { Q_OBJECT @@ -51,6 +50,6 @@ bool NetAvailability::isAvailable() const return true; } -} +} // namespace XMPP #include "netavailability.moc" diff --git a/src/irisnet/corelib/netavailability.h b/src/irisnet/corelib/netavailability.h index ad4e2b6e..884957a6 100644 --- a/src/irisnet/corelib/netavailability.h +++ b/src/irisnet/corelib/netavailability.h @@ -22,7 +22,6 @@ #include "irisnetglobal.h" namespace XMPP { - class NetAvailability : public QObject { Q_OBJECT @@ -41,7 +40,6 @@ class NetAvailability : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // NETAVAILABILITY_H diff --git a/src/irisnet/corelib/netinterface.cpp b/src/irisnet/corelib/netinterface.cpp index 79dc04f2..17564818 100644 --- a/src/irisnet/corelib/netinterface.cpp +++ b/src/irisnet/corelib/netinterface.cpp @@ -18,15 +18,14 @@ #include "netinterface.h" -#include "irisnetplugin.h" #include "irisnetglobal_p.h" +#include "irisnetplugin.h" -#include -#include #include +#include +#include namespace XMPP { - //---------------------------------------------------------------------------- // NetTracker //---------------------------------------------------------------------------- @@ -59,12 +58,10 @@ class NetTracker : public QObject { delete c; } - signals: void updated(); private: - static QList filterList(const QList &in) { QList out; for(int n = 0; n < in.count(); ++n) @@ -83,7 +80,6 @@ private slots: emit updated(); } - private: // this are all protected by m NetInterfaceProvider *c; @@ -92,7 +88,6 @@ private slots: }; - // Global because static getRef needs this too. Q_GLOBAL_STATIC(QMutex, nettracker_mutex) @@ -131,12 +126,10 @@ class NetTrackerThread : public QThread { return nettracker->getInterfaces(); } - ~NetTrackerThread() { // locked from caller } - signals: void updated(); private: @@ -179,7 +172,6 @@ class NetTrackerThread : public QThread { NetTrackerThread *NetTrackerThread::self = nullptr; - //---------------------------------------------------------------------------- // NetInterface //---------------------------------------------------------------------------- @@ -408,7 +400,6 @@ void NetInterfaceManager::unreg(NetInterface *i) { d->listeners.removeAll(i); } - -} +} // namespace XMPP #include "netinterface.moc" diff --git a/src/irisnet/corelib/netinterface.h b/src/irisnet/corelib/netinterface.h index 05fa8eb1..1d1e7b4a 100644 --- a/src/irisnet/corelib/netinterface.h +++ b/src/irisnet/corelib/netinterface.h @@ -22,10 +22,9 @@ #include "irisnetglobal.h" namespace XMPP { - class NetInterfaceManager; -class NetInterfacePrivate; class NetInterfaceManagerPrivate; +class NetInterfacePrivate; /** \brief Provides information about a network interface @@ -196,7 +195,6 @@ QString iface = NetInterfaceManager::interfaceForAddress(tcpSocket->localAddress void *reg(const QString &id, NetInterface *i); void unreg(NetInterface *i); }; +} // namespace XMPP -} - -#endif +#endif // NETINTERFACE_H diff --git a/src/irisnet/corelib/netinterface_qtname.cpp b/src/irisnet/corelib/netinterface_qtname.cpp index f217aef8..ddfcc931 100644 --- a/src/irisnet/corelib/netinterface_qtname.cpp +++ b/src/irisnet/corelib/netinterface_qtname.cpp @@ -21,7 +21,6 @@ #include namespace XMPP { - class IrisQtName : public NameProvider { Q_OBJECT @@ -231,7 +230,6 @@ IrisNetProvider *irisnet_createQtNameProvider() { return new IrisQtNameProvider; } - -} +} // namespace XMPP #include "netinterface_qtname.moc" diff --git a/src/irisnet/corelib/netinterface_qtnet.cpp b/src/irisnet/corelib/netinterface_qtnet.cpp index dc3730da..f33079a4 100644 --- a/src/irisnet/corelib/netinterface_qtnet.cpp +++ b/src/irisnet/corelib/netinterface_qtnet.cpp @@ -21,7 +21,6 @@ #include namespace XMPP { - class IrisQtNet : public NetInterfaceProvider { Q_OBJECT @@ -88,7 +87,6 @@ IrisNetProvider *irisnet_createQtNetProvider() { return new IrisQtNetProvider; } - -} +} // namespace XMPP #include "netinterface_qtnet.moc" diff --git a/src/irisnet/corelib/netinterface_unix.cpp b/src/irisnet/corelib/netinterface_unix.cpp index 706d6d30..8cb5765a 100644 --- a/src/irisnet/corelib/netinterface_unix.cpp +++ b/src/irisnet/corelib/netinterface_unix.cpp @@ -24,19 +24,17 @@ #include "irisnetplugin.h" -#include -#include -#include +#include #include #include #include -#include -#include - -// for solaris -#ifndef SIOCGIFCONF -# include +#include +#include +#ifndef SIOCGIFCONF // for solaris +# include #endif +#include +#include #ifdef Q_OS_LINUX static QStringList read_proc_as_lines(const char *procfile) @@ -172,7 +170,6 @@ static QList get_unix_gateways() } namespace XMPP { - class UnixGateway : public NetGatewayProvider { Q_OBJECT @@ -226,7 +223,6 @@ IrisNetProvider *irisnet_createUnixNetProvider() { return new UnixNetProvider; } - -} +} // namespace XMPP #include "netinterface_unix.moc" diff --git a/src/irisnet/corelib/netnames.cpp b/src/irisnet/corelib/netnames.cpp index 97fbd20f..c44da895 100644 --- a/src/irisnet/corelib/netnames.cpp +++ b/src/irisnet/corelib/netnames.cpp @@ -19,23 +19,19 @@ #include "netnames.h" -#include - -//#include -#include "irisnetplugin.h" -#include "irisnetglobal_p.h" #include "addressresolver.h" +#include "irisnetglobal_p.h" +#include "irisnetplugin.h" +//#include +#include //#define NETNAMES_DEBUG - #ifdef NETNAMES_DEBUG # define NNDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif - namespace XMPP { - //---------------------------------------------------------------------------- // NameRecord //---------------------------------------------------------------------------- @@ -501,7 +497,6 @@ class ServiceResolver::Private : public QObject }; - WeightedNameRecordList::WeightedNameRecordList() : currentPriorityGroup(priorityGroups.end()) /* void current state */ {} @@ -661,7 +656,6 @@ XMPP::WeightedNameRecordList& WeightedNameRecordList::operator<<(const XMPP::Nam return *this; } - QDebug operator<<(QDebug dbg, const XMPP::WeightedNameRecordList &list) { dbg.nospace() << "XMPP::WeightedNameRecordList(\n"; @@ -680,7 +674,6 @@ QDebug operator<<(QDebug dbg, const XMPP::WeightedNameRecordList &list) { return dbg; } - class ServiceLocalPublisher::Private { public: @@ -1118,7 +1111,6 @@ QDebug operator<<(QDebug dbg, XMPP::NameResolver::Error e) return dbg; } - //---------------------------------------------------------------------------- // ServiceBrowser //---------------------------------------------------------------------------- @@ -1142,7 +1134,6 @@ void ServiceBrowser::stop() { } - //---------------------------------------------------------------------------- // ServiceResolver //---------------------------------------------------------------------------- @@ -1457,7 +1448,6 @@ ServiceResolver::ProtoSplit ServiceResolver::happySplit() return s; } - //---------------------------------------------------------------------------- // ServiceLocalPublisher //---------------------------------------------------------------------------- @@ -1532,7 +1522,6 @@ QByteArray NetNames::unescapeDomain(const QByteArray &in) Q_UNUSED(in); return QByteArray(); } - -} +} // namespace XMPP #include "netnames.moc" diff --git a/src/irisnet/corelib/netnames.h b/src/irisnet/corelib/netnames.h index 76f8bffd..f5989875 100644 --- a/src/irisnet/corelib/netnames.h +++ b/src/irisnet/corelib/netnames.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006,2008 Justin Karneges + * Copyright (C) 2006-2008 Justin Karneges * Copyright (C) 2009-2010 Dennis Schridde * * This library is free software; you can redistribute it and/or @@ -20,20 +20,18 @@ #ifndef NETNAMES_H #define NETNAMES_H +#include "irisnetglobal.h" + #include #include - #include -#include "irisnetglobal.h" - // it seems visual studio defines it somewhere #ifdef max # undef max #endif namespace XMPP { - class NameManager; class IRISNET_EXPORT NetNames @@ -308,7 +306,6 @@ class IRISNET_EXPORT NameRecord IRISNET_EXPORT QDebug operator<<(QDebug, XMPP::NameRecord::Type); IRISNET_EXPORT QDebug operator<<(QDebug, const XMPP::NameRecord &); - class IRISNET_EXPORT ServiceInstance { public: @@ -477,7 +474,6 @@ class IRISNET_EXPORT NameResolver : public QObject IRISNET_EXPORT QDebug operator<<(QDebug, XMPP::NameResolver::Error); - class IRISNET_EXPORT WeightedNameRecordList { friend QDebug operator<<(QDebug, const WeightedNameRecordList&); @@ -511,7 +507,6 @@ class IRISNET_EXPORT WeightedNameRecordList QDebug operator<<(QDebug, const XMPP::WeightedNameRecordList&); - class IRISNET_EXPORT ServiceBrowser : public QObject { Q_OBJECT @@ -542,7 +537,6 @@ class IRISNET_EXPORT ServiceBrowser : public QObject friend class NameManager; }; - /*! DNS resolver with DNS-SD/mDNS and recursive lookup support */ /* Flow: @@ -695,10 +689,8 @@ class IRISNET_EXPORT ServiceLocalPublisher : public QObject friend class NameManager; }; -} - +} // namespace XMPP Q_DECLARE_METATYPE(XMPP::NameResolver::Error) - -#endif +#endif // NETNAMES_H diff --git a/src/irisnet/corelib/netnames_jdns.cpp b/src/irisnet/corelib/netnames_jdns.cpp index e1ee1a68..008eddcc 100644 --- a/src/irisnet/corelib/netnames_jdns.cpp +++ b/src/irisnet/corelib/netnames_jdns.cpp @@ -17,10 +17,9 @@ */ #include "irisnetplugin.h" - +#include "netinterface.h" #include "objectsession.h" #include "qjdnsshared.h" -#include "netinterface.h" //#define JDNS_DEBUG @@ -31,7 +30,6 @@ Q_DECLARE_METATYPE(XMPP::ServiceResolver::Error) Q_DECLARE_METATYPE(XMPP::ServiceLocalPublisher::Error) namespace XMPP { - static NameRecord importJDNSRecord(const QJDns::Record &in) { NameRecord out; @@ -2716,7 +2714,6 @@ IrisNetProvider *irisnet_createJDnsProvider() { return new JDnsProvider; } - -} +} // namespace XMPP #include "netnames_jdns.moc" diff --git a/src/irisnet/corelib/objectsession.cpp b/src/irisnet/corelib/objectsession.cpp index ab8030d1..ad12b7e7 100644 --- a/src/irisnet/corelib/objectsession.cpp +++ b/src/irisnet/corelib/objectsession.cpp @@ -18,15 +18,14 @@ #include "objectsession.h" -#include -#include #include +#include #include #include #include +#include namespace XMPP { - class ObjectSessionWatcherPrivate { public: @@ -220,7 +219,6 @@ bool ObjectSessionWatcher::isValid() const return false; } - ObjectSession::ObjectSession(QObject *parent) : QObject(parent) { @@ -300,7 +298,6 @@ void ObjectSession::resume() if(!d->pendingCalls.isEmpty()) d->callTrigger->start(); } - -} +} // namespace XMPP #include "objectsession.moc" diff --git a/src/irisnet/corelib/objectsession.h b/src/irisnet/corelib/objectsession.h index 04a13b2e..427d949e 100644 --- a/src/irisnet/corelib/objectsession.h +++ b/src/irisnet/corelib/objectsession.h @@ -22,7 +22,6 @@ #include namespace XMPP { - class ObjectSessionPrivate; class ObjectSessionWatcherPrivate; @@ -81,7 +80,6 @@ class ObjectSessionWatcher friend class ObjectSessionPrivate; ObjectSessionWatcherPrivate *d; }; +} // namespace XMPP -} - -#endif +#endif // OBJECTSESSION_H diff --git a/src/irisnet/noncore/cutestuff/bsocket.cpp b/src/irisnet/noncore/cutestuff/bsocket.cpp index 12254aa6..cc3a2d99 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.cpp +++ b/src/irisnet/noncore/cutestuff/bsocket.cpp @@ -18,25 +18,21 @@ * */ -#include +#include "bsocket.h" + #include #include - +#include #include -#include "bsocket.h" - //#define BS_DEBUG - #ifdef BS_DEBUG # define BSDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif - #define READBUFSIZE 65536 // CS_NAMESPACE_BEGIN - class QTcpSocketSignalRelay : public QObject { Q_OBJECT @@ -93,7 +89,6 @@ public slots: } }; - class HappyEyeballsConnector : public QObject { Q_OBJECT @@ -158,7 +153,6 @@ class HappyEyeballsConnector : public QObject fallbackTimer.stop(); } - void connectToHost(const QHostAddress &address, quint16 port) { #ifdef BS_DEBUG @@ -429,7 +423,6 @@ BSocket::~BSocket() delete d; } - void BSocket::resetConnection(bool clear) { #ifdef BS_DEBUG diff --git a/src/irisnet/noncore/cutestuff/bsocket.h b/src/irisnet/noncore/cutestuff/bsocket.h index 21b41895..e0f59416 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.h +++ b/src/irisnet/noncore/cutestuff/bsocket.h @@ -21,19 +21,17 @@ #ifndef CS_BSOCKET_H #define CS_BSOCKET_H -#include -#include - #include "bytestream.h" #include "netnames.h" -class QString; -class QObject; +#include +#include + class QByteArray; +class QObject; +class QString; // CS_NAMESPACE_BEGIN - - /*! Socket with automatic hostname lookups, using SRV, AAAA and A DNS queries. */ @@ -98,8 +96,6 @@ private slots: void dns_srv_try_next(); bool connect_host_try_next(); void qs_connected_step2(bool signalConnected = true); -}; - -// CS_NAMESPACE_END +}; // CS_NAMESPACE_END -#endif +#endif // CS_BSOCKET_H diff --git a/src/irisnet/noncore/cutestuff/bytestream.cpp b/src/irisnet/noncore/cutestuff/bytestream.cpp index 8602214e..b352435f 100644 --- a/src/irisnet/noncore/cutestuff/bytestream.cpp +++ b/src/irisnet/noncore/cutestuff/bytestream.cpp @@ -18,6 +18,7 @@ */ #include "bytestream.h" + #include // CS_NAMESPACE_BEGIN diff --git a/src/irisnet/noncore/cutestuff/bytestream.h b/src/irisnet/noncore/cutestuff/bytestream.h index 382dfe6b..2b88b429 100644 --- a/src/irisnet/noncore/cutestuff/bytestream.h +++ b/src/irisnet/noncore/cutestuff/bytestream.h @@ -20,13 +20,13 @@ #ifndef CS_BYTESTREAM_H #define CS_BYTESTREAM_H -#include #include #include +#include class QAbstractSocket; -// CS_NAMESPACE_BEGIN +// CS_NAMESPACE_BEGIN // CS_EXPORT_BEGIN class ByteStream : public QIODevice { @@ -74,7 +74,6 @@ class ByteStream : public QIODevice //! \endif }; // CS_EXPORT_END - // CS_NAMESPACE_END -#endif +#endif // CS_BYTESTREAM_H diff --git a/src/irisnet/noncore/cutestuff/httpconnect.cpp b/src/irisnet/noncore/cutestuff/httpconnect.cpp index de8f02ea..0bd8a8cd 100644 --- a/src/irisnet/noncore/cutestuff/httpconnect.cpp +++ b/src/irisnet/noncore/cutestuff/httpconnect.cpp @@ -19,20 +19,18 @@ #include "httpconnect.h" -#include +#include "bsocket.h" + #include +#include #include -#include "bsocket.h" - //#define PROX_DEBUG - #ifdef PROX_DEBUG #include #endif // CS_NAMESPACE_BEGIN - #ifdef PROX_DEBUG QString escapeOutput(const QByteArray &in) { diff --git a/src/irisnet/noncore/cutestuff/httpconnect.h b/src/irisnet/noncore/cutestuff/httpconnect.h index 297a58c7..4039b61f 100644 --- a/src/irisnet/noncore/cutestuff/httpconnect.h +++ b/src/irisnet/noncore/cutestuff/httpconnect.h @@ -23,7 +23,6 @@ #include "bytestream.h" // CS_NAMESPACE_BEGIN - class HttpConnect : public ByteStream { Q_OBJECT @@ -61,4 +60,4 @@ private slots: // CS_NAMESPACE_END -#endif +#endif // CS_HTTPCONNECT_H diff --git a/src/irisnet/noncore/cutestuff/httppoll.cpp b/src/irisnet/noncore/cutestuff/httppoll.cpp index 6d88a97d..572e6bfa 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.cpp +++ b/src/irisnet/noncore/cutestuff/httppoll.cpp @@ -19,23 +19,22 @@ #include "httppoll.h" +#include "bsocket.h" + +#include #include +#include +#include #include #include -#include -#include -#include -#include -#include "bsocket.h" - #ifdef PROX_DEBUG -#include +# include #endif +#include #define POLL_KEYS 64 // CS_NAMESPACE_BEGIN - static QByteArray randomArray(int size) { QByteArray a; @@ -389,7 +388,6 @@ const QString & HttpPoll::getKey(bool *last) return d->key[d->key_n]; } - //---------------------------------------------------------------------------- // HttpProxyPost //---------------------------------------------------------------------------- diff --git a/src/irisnet/noncore/cutestuff/httppoll.h b/src/irisnet/noncore/cutestuff/httppoll.h index 53c45d1a..db10005c 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.h +++ b/src/irisnet/noncore/cutestuff/httppoll.h @@ -25,7 +25,6 @@ class QUrl; // CS_NAMESPACE_BEGIN - class HttpPoll : public ByteStream { Q_OBJECT @@ -150,4 +149,4 @@ private slots: // CS_NAMESPACE_END -#endif +#endif // CS_HTTPPOLL_H diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index faef4509..41ad6b33 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -19,33 +19,29 @@ #include "socks.h" +#include "bsocket.h" + +#include #include -#include -#include #include #include -#include - -#ifdef Q_OS_UNIX -#include -#include -#endif +#include +#include -#ifdef Q_OS_WIN32 -#include +//#define PROX_DEBUG +#ifdef PROX_DEBUG +#include #endif #ifdef Q_OS_UNIX -#include #include +#include +#include +#include #endif -#include "bsocket.h" - -//#define PROX_DEBUG - -#ifdef PROX_DEBUG -#include +#ifdef Q_OS_WIN32 +#include #endif // CS_NAMESPACE_BEGIN diff --git a/src/irisnet/noncore/cutestuff/socks.h b/src/irisnet/noncore/cutestuff/socks.h index d07d6c4a..8605e7fd 100644 --- a/src/irisnet/noncore/cutestuff/socks.h +++ b/src/irisnet/noncore/cutestuff/socks.h @@ -23,10 +23,9 @@ #include "bytestream.h" // CS_NAMESPACE_BEGIN - class QHostAddress; -class QTcpSocket; class QTcpServer; +class QTcpSocket; class SocksClient; class SocksServer; @@ -162,4 +161,4 @@ private slots: // CS_NAMESPACE_END -#endif +#endif // CS_SOCKS_H diff --git a/src/irisnet/noncore/ice176.cpp b/src/irisnet/noncore/ice176.cpp index a4cbe59f..079eb239 100644 --- a/src/irisnet/noncore/ice176.cpp +++ b/src/irisnet/noncore/ice176.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009,2010 Barracuda Networks, Inc. + * Copyright (C) 2009-2010 Barracuda Networks, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,20 +18,20 @@ #include "ice176.h" +#include "icecomponent.h" +#include "icelocaltransport.h" +#include "iceturntransport.h" +#include "stunbinding.h" +#include "stunmessage.h" +#include "stuntransaction.h" +#include "udpportreserver.h" + #include #include #include #include -#include "stuntransaction.h" -#include "stunbinding.h" -#include "stunmessage.h" -#include "udpportreserver.h" -#include "icelocaltransport.h" -#include "iceturntransport.h" -#include "icecomponent.h" namespace XMPP { - enum { Direct, @@ -1339,6 +1339,6 @@ bool Ice176::isIPv6LinkLocalAddress(const QHostAddress &addr) return false; } -} +} // namespace XMPP #include "ice176.moc" diff --git a/src/irisnet/noncore/ice176.h b/src/irisnet/noncore/ice176.h index 159f908e..4a9c5ef7 100644 --- a/src/irisnet/noncore/ice176.h +++ b/src/irisnet/noncore/ice176.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009,2010 Barracuda Networks, Inc. + * Copyright (C) 2009-2010 Barracuda Networks, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,17 +19,17 @@ #ifndef ICE176_H #define ICE176_H +#include "turnclient.h" + +#include #include #include -#include -#include "turnclient.h" namespace QCA { class SecureArray; } namespace XMPP { - class UdpPortReserver; class Ice176 : public QObject @@ -181,7 +181,6 @@ class Ice176 : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // ICE176_H diff --git a/src/irisnet/noncore/icecomponent.cpp b/src/irisnet/noncore/icecomponent.cpp index cbd873d4..b8aa609b 100644 --- a/src/irisnet/noncore/icecomponent.cpp +++ b/src/irisnet/noncore/icecomponent.cpp @@ -18,16 +18,16 @@ #include "icecomponent.h" -#include -#include -#include -#include "objectsession.h" -#include "udpportreserver.h" #include "icelocaltransport.h" #include "iceturntransport.h" +#include "objectsession.h" +#include "udpportreserver.h" -namespace XMPP { +#include +#include +#include +namespace XMPP { static int calc_priority(int typePref, int localPref, int componentId) { Q_ASSERT(typePref >= 0 && typePref <= 126); @@ -1055,6 +1055,6 @@ void IceComponent::setDebugLevel(DebugLevel level) d->tt->setDebugLevel((IceTransport::DebugLevel)level); } -} +} // namespace XMPP #include "icecomponent.moc" diff --git a/src/irisnet/noncore/icecomponent.h b/src/irisnet/noncore/icecomponent.h index 215cc478..b31b58b7 100644 --- a/src/irisnet/noncore/icecomponent.h +++ b/src/irisnet/noncore/icecomponent.h @@ -19,15 +19,15 @@ #ifndef ICECOMPONENT_H #define ICECOMPONENT_H -#include -#include "turnclient.h" -#include "icetransport.h" #include "ice176.h" +#include "icetransport.h" +#include "turnclient.h" + +#include class QUdpSocket; namespace XMPP { - class UdpPortReserver; class IceComponent : public QObject @@ -180,7 +180,6 @@ inline uint qHash(const XMPP::IceComponent::TransportAddress &key, uint seed = 0 { return ::qHash(key.addr, seed) ^ ::qHash(key.port, seed); } - } //namespace XMPP -#endif +#endif // ICECOMPONENT_H diff --git a/src/irisnet/noncore/icelocaltransport.cpp b/src/irisnet/noncore/icelocaltransport.cpp index 28ff5e3f..53e009c4 100644 --- a/src/irisnet/noncore/icelocaltransport.cpp +++ b/src/irisnet/noncore/icelocaltransport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009,2010 Barracuda Networks, Inc. + * Copyright (C) 2009-2010 Barracuda Networks, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,21 +18,21 @@ #include "icelocaltransport.h" -#include -#include -#include #include "objectsession.h" +#include "stunallocate.h" +#include "stunbinding.h" #include "stunmessage.h" #include "stuntransaction.h" -#include "stunbinding.h" -#include "stunallocate.h" #include "turnclient.h" +#include +#include +#include + // don't queue more incoming packets than this per transmit path #define MAX_PACKET_QUEUE 64 namespace XMPP { - enum { Direct, @@ -881,6 +881,6 @@ void IceLocalTransport::setDebugLevel(DebugLevel level) d->turn->setDebugLevel((TurnClient::DebugLevel)level); } -} +} // namespace XMPP #include "icelocaltransport.moc" diff --git a/src/irisnet/noncore/icelocaltransport.h b/src/irisnet/noncore/icelocaltransport.h index 0e571bf9..05738c40 100644 --- a/src/irisnet/noncore/icelocaltransport.h +++ b/src/irisnet/noncore/icelocaltransport.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009,2010 Barracuda Networks, Inc. + * Copyright (C) 2009-2010 Barracuda Networks, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,11 @@ #ifndef ICELOCALTRANSPORT_H #define ICELOCALTRANSPORT_H -#include -#include #include "icetransport.h" +#include +#include + class QHostAddress; class QUdpSocket; @@ -31,7 +32,6 @@ namespace QCA { } namespace XMPP { - // this class manages a single port on a single interface, including the // relationship with an associated STUN/TURN server. if TURN is used, this // class offers two paths (0=direct and 1=relayed), otherwise it offers @@ -95,7 +95,6 @@ class IceLocalTransport : public IceTransport friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // ICELOCALTRANSPORT_H diff --git a/src/irisnet/noncore/icetransport.cpp b/src/irisnet/noncore/icetransport.cpp index 1a512d73..4c7825ee 100644 --- a/src/irisnet/noncore/icetransport.cpp +++ b/src/irisnet/noncore/icetransport.cpp @@ -19,7 +19,6 @@ #include "icetransport.h" namespace XMPP { - IceTransport::IceTransport(QObject *parent) : QObject(parent) { @@ -29,4 +28,4 @@ IceTransport::~IceTransport() { } -} +} // namespace XMPP diff --git a/src/irisnet/noncore/icetransport.h b/src/irisnet/noncore/icetransport.h index be673e95..97dfe6de 100644 --- a/src/irisnet/noncore/icetransport.h +++ b/src/irisnet/noncore/icetransport.h @@ -19,13 +19,12 @@ #ifndef ICETRANSPORT_H #define ICETRANSPORT_H -#include #include +#include class QHostAddress; namespace XMPP { - class IceTransport : public QObject { Q_OBJECT @@ -67,7 +66,6 @@ class IceTransport : public QObject // not DOR-SS/DS safe void debugLine(const QString &str); }; +} // namespace XMPP -} - -#endif +#endif // ICETRANSPORT_H diff --git a/src/irisnet/noncore/iceturntransport.cpp b/src/irisnet/noncore/iceturntransport.cpp index 37c1027e..e46f5467 100644 --- a/src/irisnet/noncore/iceturntransport.cpp +++ b/src/irisnet/noncore/iceturntransport.cpp @@ -18,11 +18,11 @@ #include "iceturntransport.h" -#include #include "stunallocate.h" -namespace XMPP { +#include +namespace XMPP { class IceTurnTransport::Private : public QObject { Q_OBJECT @@ -244,6 +244,6 @@ void IceTurnTransport::setDebugLevel(DebugLevel level) d->turn.setDebugLevel((TurnClient::DebugLevel)level); } -} +} // namespace XMPP #include "iceturntransport.moc" diff --git a/src/irisnet/noncore/iceturntransport.h b/src/irisnet/noncore/iceturntransport.h index 32f344d8..98604cb1 100644 --- a/src/irisnet/noncore/iceturntransport.h +++ b/src/irisnet/noncore/iceturntransport.h @@ -19,16 +19,15 @@ #ifndef ICETURNTRANSPORT_H #define ICETURNTRANSPORT_H -#include +#include "icetransport.h" +#include "turnclient.h" + #include #include -#include "turnclient.h" -#include "icetransport.h" +#include namespace XMPP { - // for the turn transport, only path 0 is used - class IceTurnTransport : public IceTransport { Q_OBJECT @@ -70,7 +69,6 @@ class IceTurnTransport : public IceTransport friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // ICETURNTRANSPORT_H diff --git a/src/irisnet/noncore/legacy/ndns.cpp b/src/irisnet/noncore/legacy/ndns.cpp index 5a68a8c4..7ae585bc 100644 --- a/src/irisnet/noncore/legacy/ndns.cpp +++ b/src/irisnet/noncore/legacy/ndns.cpp @@ -1,6 +1,6 @@ /* * ndns.cpp - native DNS resolution - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/irisnet/noncore/legacy/ndns.h b/src/irisnet/noncore/legacy/ndns.h index 46561faa..2b8a3d86 100644 --- a/src/irisnet/noncore/legacy/ndns.h +++ b/src/irisnet/noncore/legacy/ndns.h @@ -1,6 +1,6 @@ /* * ndns.h - native DNS resolution - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,12 +20,12 @@ #ifndef CS_NDNS_H #define CS_NDNS_H +#include "netnames.h" + #include #include -#include "netnames.h" // CS_NAMESPACE_BEGIN - class NDns : public QObject { Q_OBJECT @@ -55,4 +55,4 @@ private slots: // CS_NAMESPACE_END -#endif +#endif // CS_NDNS_H diff --git a/src/irisnet/noncore/legacy/srvresolver.cpp b/src/irisnet/noncore/legacy/srvresolver.cpp index f3d747df..16ae25bd 100644 --- a/src/irisnet/noncore/legacy/srvresolver.cpp +++ b/src/irisnet/noncore/legacy/srvresolver.cpp @@ -24,7 +24,6 @@ #endif // CS_NAMESPACE_BEGIN - static void sortSRVList(QList &list) { QList tmp = list; diff --git a/src/irisnet/noncore/legacy/srvresolver.h b/src/irisnet/noncore/legacy/srvresolver.h index f350677b..ecca77e5 100644 --- a/src/irisnet/noncore/legacy/srvresolver.h +++ b/src/irisnet/noncore/legacy/srvresolver.h @@ -20,12 +20,12 @@ #ifndef CS_SRVRESOLVER_H #define CS_SRVRESOLVER_H +#include "netnames.h" + #include #include -#include "netnames.h" // CS_NAMESPACE_BEGIN - class Q3Dns { public: @@ -79,4 +79,4 @@ private slots: // CS_NAMESPACE_END -#endif +#endif // CS_SRVRESOLVER_H diff --git a/src/irisnet/noncore/processquit.cpp b/src/irisnet/noncore/processquit.cpp index 8560b503..6c05f2ba 100644 --- a/src/irisnet/noncore/processquit.cpp +++ b/src/irisnet/noncore/processquit.cpp @@ -25,20 +25,16 @@ #ifdef QT_GUI_LIB # include #endif - -#ifdef Q_OS_WIN -# include -#endif - #ifdef Q_OS_UNIX # include # include #endif +#ifdef Q_OS_WIN +# include +#endif namespace { - // safeobj stuff, from qca - void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); @@ -77,8 +73,7 @@ public slots: private: QSocketNotifier *sn; }; - -} +} // namespace #ifndef NO_IRISNET namespace XMPP { @@ -274,6 +269,6 @@ void ProcessQuit::cleanup() #ifndef NO_IRISNET } -#endif +#endif // NO_IRISNET #include "processquit.moc" diff --git a/src/irisnet/noncore/processquit.h b/src/irisnet/noncore/processquit.h index d9e3b552..363088ca 100644 --- a/src/irisnet/noncore/processquit.h +++ b/src/irisnet/noncore/processquit.h @@ -113,4 +113,4 @@ class IRISNET_EXPORT ProcessQuit : public QObject } #endif -#endif +#endif // PROCESSQUIT_H diff --git a/src/irisnet/noncore/stunallocate.cpp b/src/irisnet/noncore/stunallocate.cpp index 91ff75c4..96ee4ea4 100644 --- a/src/irisnet/noncore/stunallocate.cpp +++ b/src/irisnet/noncore/stunallocate.cpp @@ -18,15 +18,16 @@ #include "stunallocate.h" -#include -#include -#include -#include #include "objectsession.h" -#include "stunutil.h" #include "stunmessage.h" -#include "stuntypes.h" #include "stuntransaction.h" +#include "stuntypes.h" +#include "stunutil.h" + +#include +#include +#include +#include // permissions last 5 minutes, update them every 4 minutes #define PERM_INTERVAL (4 * 60 * 1000) @@ -35,7 +36,6 @@ #define CHAN_INTERVAL (9 * 60 * 1000) namespace XMPP { - void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); @@ -1447,7 +1447,6 @@ QByteArray StunAllocate::readChannelData(const quint8 *data, int size) else return QByteArray(); } - -} +} // namespace XMPP #include "stunallocate.moc" diff --git a/src/irisnet/noncore/stunallocate.h b/src/irisnet/noncore/stunallocate.h index 2c18011d..e802ddef 100644 --- a/src/irisnet/noncore/stunallocate.h +++ b/src/irisnet/noncore/stunallocate.h @@ -19,14 +19,13 @@ #ifndef STUNALLOCATE_H #define STUNALLOCATE_H -#include -#include #include +#include +#include class QByteArray; namespace XMPP { - class StunMessage; class StunTransactionPool; @@ -127,7 +126,6 @@ class StunAllocate : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // STUNALLOCATE_H diff --git a/src/irisnet/noncore/stunbinding.cpp b/src/irisnet/noncore/stunbinding.cpp index 897e1e1d..524097b2 100644 --- a/src/irisnet/noncore/stunbinding.cpp +++ b/src/irisnet/noncore/stunbinding.cpp @@ -18,13 +18,13 @@ #include "stunbinding.h" -#include #include "stunmessage.h" -#include "stuntypes.h" #include "stuntransaction.h" +#include "stuntypes.h" -namespace XMPP { +#include +namespace XMPP { class StunBinding::Private : public QObject { Q_OBJECT @@ -292,7 +292,6 @@ QString StunBinding::errorString() const { return d->errorString; } - -} +} // namespace XMPP #include "stunbinding.moc" diff --git a/src/irisnet/noncore/stunbinding.h b/src/irisnet/noncore/stunbinding.h index 9bec8ae2..963e5fd2 100644 --- a/src/irisnet/noncore/stunbinding.h +++ b/src/irisnet/noncore/stunbinding.h @@ -24,7 +24,6 @@ class QHostAddress; namespace XMPP { - class StunTransactionPool; class StunBinding : public QObject @@ -75,7 +74,6 @@ class StunBinding : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // STUNBINDING_H diff --git a/src/irisnet/noncore/stunmessage.cpp b/src/irisnet/noncore/stunmessage.cpp index a6a5feec..87e6a6ec 100644 --- a/src/irisnet/noncore/stunmessage.cpp +++ b/src/irisnet/noncore/stunmessage.cpp @@ -18,14 +18,14 @@ #include "stunmessage.h" +#include "stunutil.h" + #include #include -#include "stunutil.h" #define ENSURE_D { if(!d) d = new Private; } namespace XMPP { - using namespace StunUtil; // some attribute types we need to explicitly support @@ -727,5 +727,4 @@ QByteArray StunMessage::readStun(const quint8 *data, int size) else return QByteArray(); } - -} +} // namespace XMPP diff --git a/src/irisnet/noncore/stunmessage.h b/src/irisnet/noncore/stunmessage.h index dbc15fa4..8563712e 100644 --- a/src/irisnet/noncore/stunmessage.h +++ b/src/irisnet/noncore/stunmessage.h @@ -24,7 +24,6 @@ #include namespace XMPP { - class StunMessage { public: @@ -103,7 +102,6 @@ class StunMessage class Private; QSharedDataPointer d; }; +} // namespace XMPP -} - -#endif +#endif // STUNMESSAGE_H diff --git a/src/irisnet/noncore/stuntransaction.cpp b/src/irisnet/noncore/stuntransaction.cpp index 3132fccf..70a13c75 100644 --- a/src/irisnet/noncore/stuntransaction.cpp +++ b/src/irisnet/noncore/stuntransaction.cpp @@ -18,20 +18,20 @@ #include "stuntransaction.h" +#include "stunbinding.h" +#include "stunmessage.h" +#include "stuntypes.h" +#include "stunutil.h" + #include #include #include #include #include -#include "stunutil.h" -#include "stunmessage.h" -#include "stuntypes.h" -#include "stunbinding.h" Q_DECLARE_METATYPE(XMPP::StunTransaction::Error) namespace XMPP { - // parse a stun message, optionally performing validity checks. the // StunMessage class itself provides parsing with validity or parsing // without validity, but it does not provide a way to do both together, @@ -740,6 +740,6 @@ void StunTransactionPool::setDebugLevel(DebugLevel level) d->debugLevel = level; } -} +} // namespace XMPP #include "stuntransaction.moc" diff --git a/src/irisnet/noncore/stuntransaction.h b/src/irisnet/noncore/stuntransaction.h index e07dd45c..6d924b3b 100644 --- a/src/irisnet/noncore/stuntransaction.h +++ b/src/irisnet/noncore/stuntransaction.h @@ -19,21 +19,19 @@ #ifndef STUNTRANSACTION_H #define STUNTRANSACTION_H -#include #include #include +#include namespace QCA { class SecureArray; } namespace XMPP { - class StunMessage; - -class StunTransactionPrivate; class StunTransactionPool; class StunTransactionPoolPrivate; +class StunTransactionPrivate; // Notes: // @@ -199,7 +197,6 @@ class StunTransactionPool : public QObject friend class StunTransactionPoolPrivate; StunTransactionPoolPrivate *d; }; +} // namespace XMPP -} - -#endif +#endif // STUNTRANSACTION_H diff --git a/src/irisnet/noncore/stuntypes.cpp b/src/irisnet/noncore/stuntypes.cpp index 48487f1c..9cc72ff8 100644 --- a/src/irisnet/noncore/stuntypes.cpp +++ b/src/irisnet/noncore/stuntypes.cpp @@ -18,19 +18,17 @@ #include "stuntypes.h" -#include -#include #include "stunutil.h" +#include +#include + #define STRING_MAX_CHARS 127 #define STRING_MAX_BYTES 763 namespace XMPP { - using namespace StunUtil; - namespace StunTypes { - static void xorIPv4(QByteArray *in, const quint8 *magic) { quint8 *p = (quint8 *)in->data(); @@ -730,7 +728,5 @@ void print_packet(const StunMessage &message) { printf("%s\n", qPrintable(print_packet_str(message))); } - -} - -} +} // namespace StunTypes +} // namespace XMPP diff --git a/src/irisnet/noncore/stuntypes.h b/src/irisnet/noncore/stuntypes.h index e0179910..c09da16b 100644 --- a/src/irisnet/noncore/stuntypes.h +++ b/src/irisnet/noncore/stuntypes.h @@ -19,16 +19,15 @@ #ifndef STUNTYPES_H #define STUNTYPES_H -#include +#include "stunmessage.h" + #include -#include #include -#include "stunmessage.h" +#include +#include namespace XMPP { - namespace StunTypes { - enum Method { Binding = 0x001, @@ -137,8 +136,7 @@ QString attributeValueToString(int type, const QByteArray &val, const quint8 *ma QString print_packet_str(const StunMessage &message); void print_packet(const StunMessage &message); -} - -} +} // namespace StunTypes +} // namespace XMPP -#endif +#endif // STUNTYPES_H diff --git a/src/irisnet/noncore/stunutil.cpp b/src/irisnet/noncore/stunutil.cpp index 0dac62ea..46afe447 100644 --- a/src/irisnet/noncore/stunutil.cpp +++ b/src/irisnet/noncore/stunutil.cpp @@ -19,9 +19,7 @@ #include "stunutil.h" namespace XMPP { - namespace StunUtil { - quint16 read16(const quint8 *in) { quint16 out = in[0]; @@ -93,7 +91,5 @@ QCA::SecureArray saslPrep(const QCA::SecureArray &in) // TODO return in; } - -} - -} +} // namespace StunUtil +} // namespace XMPP diff --git a/src/irisnet/noncore/stunutil.h b/src/irisnet/noncore/stunutil.h index fac82f00..ca71f011 100644 --- a/src/irisnet/noncore/stunutil.h +++ b/src/irisnet/noncore/stunutil.h @@ -22,9 +22,7 @@ #include namespace XMPP { - namespace StunUtil { - quint16 read16(const quint8 *in); quint32 read32(const quint8 *in); quint64 read64(const quint8 *in); @@ -35,8 +33,7 @@ void write64(quint8 *out, quint64 i); QCA::SecureArray saslPrep(const QCA::SecureArray &in); -} - -} +} // namespace StunUtil +} // namespace XMPP -#endif +#endif // STUNUTIL_H diff --git a/src/irisnet/noncore/tcpportreserver.cpp b/src/irisnet/noncore/tcpportreserver.cpp index e69a9b18..32039e91 100644 --- a/src/irisnet/noncore/tcpportreserver.cpp +++ b/src/irisnet/noncore/tcpportreserver.cpp @@ -17,15 +17,15 @@ * */ +#include "tcpportreserver.h" + +#include "ice176.h" + #include #include #include -#include "tcpportreserver.h" -#include "ice176.h" - namespace XMPP { - TcpPortDiscoverer::TcpPortDiscoverer(TcpPortScope *scope) : QObject(scope), scope(scope) @@ -154,7 +154,6 @@ struct TcpPortScope::Private QHash, QWeakPointer> servers; }; - TcpPortScope::TcpPortScope() : d(new Private) { @@ -219,7 +218,6 @@ TcpPortServer::Ptr TcpPortScope::bind(const QHostAddress &addr, quint16 port) return shared; } - // -------------------------------------------------------------------------- // TcpPortScope // -------------------------------------------------------------------------- @@ -252,5 +250,4 @@ TcpPortScope *TcpPortReserver::unregisterScope(const QString &id) } return s; } - } // namespace XMPP diff --git a/src/irisnet/noncore/tcpportreserver.h b/src/irisnet/noncore/tcpportreserver.h index 97017e27..a4068bc4 100644 --- a/src/irisnet/noncore/tcpportreserver.h +++ b/src/irisnet/noncore/tcpportreserver.h @@ -22,11 +22,10 @@ #include #include -#include #include +#include namespace XMPP { - class TcpPortServer : public QObject { Q_OBJECT @@ -131,7 +130,6 @@ class TcpPortScope: public QObject QScopedPointer d; }; - /** * @brief The TcpPortReserver class * This class should have the only instance per application @@ -158,7 +156,6 @@ class TcpPortReserver : public QObject public slots: }; - } // namespace XMPP Q_DECLARE_OPERATORS_FOR_FLAGS(XMPP::TcpPortServer::PortTypes) diff --git a/src/irisnet/noncore/turnclient.cpp b/src/irisnet/noncore/turnclient.cpp index 31221eb7..fd1ea2e9 100644 --- a/src/irisnet/noncore/turnclient.cpp +++ b/src/irisnet/noncore/turnclient.cpp @@ -18,19 +18,19 @@ #include "turnclient.h" -#include -#include "stuntypes.h" -#include "stunmessage.h" -#include "stuntransaction.h" -#include "stunallocate.h" -#include "objectsession.h" -#include "bytestream.h" #include "bsocket.h" +#include "bytestream.h" #include "httpconnect.h" +#include "objectsession.h" #include "socks.h" +#include "stunallocate.h" +#include "stunmessage.h" +#include "stuntransaction.h" +#include "stuntypes.h" -namespace XMPP { +#include +namespace XMPP { //---------------------------------------------------------------------------- // TurnClient::Proxy //---------------------------------------------------------------------------- @@ -1139,7 +1139,6 @@ void TurnClient::setDebugLevel(DebugLevel level) if(d->pool) d->pool->setDebugLevel((StunTransactionPool::DebugLevel)level); } - -} +} // namespace XMPP #include "turnclient.moc" diff --git a/src/irisnet/noncore/turnclient.h b/src/irisnet/noncore/turnclient.h index 18af00cb..74e7b6a7 100644 --- a/src/irisnet/noncore/turnclient.h +++ b/src/irisnet/noncore/turnclient.h @@ -19,19 +19,18 @@ #ifndef TURNCLIENT_H #define TURNCLIENT_H -#include #include -#include #include +#include +#include namespace QCA { class SecureArray; } namespace XMPP { - -class StunTransactionPool; class StunAllocate; +class StunTransactionPool; class TurnClient : public QObject { @@ -186,7 +185,6 @@ class TurnClient : public QObject friend class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // TURNCLIENT_H diff --git a/src/irisnet/noncore/udpportreserver.cpp b/src/irisnet/noncore/udpportreserver.cpp index 54adc0b4..94ded097 100644 --- a/src/irisnet/noncore/udpportreserver.cpp +++ b/src/irisnet/noncore/udpportreserver.cpp @@ -18,11 +18,10 @@ #include "udpportreserver.h" -#include #include +#include namespace XMPP { - class UdpPortReserver::Private : public QObject { Q_OBJECT @@ -433,7 +432,6 @@ void UdpPortReserver::returnSockets(const QList &sockList) { d->returnSockets(sockList); } - -} +} // namespace XMPP #include "udpportreserver.moc" diff --git a/src/irisnet/noncore/udpportreserver.h b/src/irisnet/noncore/udpportreserver.h index 5650a489..8604b38b 100644 --- a/src/irisnet/noncore/udpportreserver.h +++ b/src/irisnet/noncore/udpportreserver.h @@ -19,14 +19,13 @@ #ifndef UDPPORTRESERVER_H #define UDPPORTRESERVER_H -#include #include +#include class QHostAddress; class QUdpSocket; namespace XMPP { - // call both setAddresses() and setPorts() at least once for socket // reservations to occur. at any time you can update the list of addresses // (interfaces) and ports to reserve. note that the port must be available @@ -66,7 +65,6 @@ class UdpPortReserver : public QObject class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // UDPPORTRESERVER_H diff --git a/src/jdns/CMakeLists.txt b/src/jdns/CMakeLists.txt index 43b99914..13789762 100644 --- a/src/jdns/CMakeLists.txt +++ b/src/jdns/CMakeLists.txt @@ -74,7 +74,6 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) set(JDNS_INCLUDEDIR "${CMAKE_CURRENT_SOURCE_DIR}/include/jdns" ) - #add extra search paths for libraries and includes set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE STRING "Directory where binary will install") @@ -104,7 +103,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" ) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" ) - # pkg-config if(NOT WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/jdns.pc.in diff --git a/src/jdns/include/jdns/jdns.h b/src/jdns/include/jdns/jdns.h index defcbab8..f1bc5c86 100644 --- a/src/jdns/include/jdns/jdns.h +++ b/src/jdns/include/jdns/jdns.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -505,4 +505,4 @@ JDNS_EXPORT void jdns_set_hold_ids_enabled(jdns_session_t *s, int enabled); } #endif -#endif +#endif // JDNS_H diff --git a/src/jdns/include/jdns/jdns_export.h b/src/jdns/include/jdns/jdns_export.h index 7a9ee396..c5d79a13 100644 --- a/src/jdns/include/jdns/jdns_export.h +++ b/src/jdns/include/jdns/jdns_export.h @@ -49,4 +49,4 @@ # define JDNS_EXPORT #endif -#endif +#endif // JDNS_EXPORT_H diff --git a/src/jdns/include/jdns/qjdns.h b/src/jdns/include/jdns/qjdns.h index b8c3cf92..13a26261 100644 --- a/src/jdns/include/jdns/qjdns.h +++ b/src/jdns/include/jdns/qjdns.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,6 +27,7 @@ #define QJDNS_H #include "jdns_export.h" + #include #include @@ -156,4 +157,4 @@ class JDNS_EXPORT QJDns : public QObject Private *d; }; -#endif +#endif // QJDNS_H diff --git a/src/jdns/include/jdns/qjdnsshared.h b/src/jdns/include/jdns/qjdnsshared.h index e1e67a7a..335d91bb 100644 --- a/src/jdns/include/jdns/qjdnsshared.h +++ b/src/jdns/include/jdns/qjdnsshared.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006,2007 Justin Karneges + * Copyright (C) 2006-2007 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,9 +27,9 @@ #include "qjdns.h" class QJDnsShared; +class QJDnsSharedDebugPrivate; class QJDnsSharedPrivate; class QJDnsSharedRequestPrivate; -class QJDnsSharedDebugPrivate; /** \brief Collects debugging information from QJDnsShared @@ -511,4 +511,4 @@ QStringList finalDebugLines = jdnsSharedDebug.readDebugLines(); QJDnsSharedPrivate *d; }; -#endif +#endif // QJDNSSHARED_H diff --git a/src/jdns/src/jdns/CMakeLists.txt b/src/jdns/src/jdns/CMakeLists.txt index 3a68f930..7bf91584 100644 --- a/src/jdns/src/jdns/CMakeLists.txt +++ b/src/jdns/src/jdns/CMakeLists.txt @@ -6,7 +6,6 @@ set(jdns_SRCS jdns_util.c ) - set(jdns_PUBLIC_HEADERS "${JDNS_INCLUDEDIR}/jdns.h" "${JDNS_INCLUDEDIR}/jdns_export.h" diff --git a/src/jdns/src/jdns/jdns.c b/src/jdns/src/jdns/jdns.c index 52f223a4..3da4c25c 100644 --- a/src/jdns/src/jdns/jdns.c +++ b/src/jdns/src/jdns/jdns.c @@ -21,13 +21,12 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "jdns_mdnsd.h" #include "jdns_p.h" +#include "jdns_packet.h" #include -#include "jdns_packet.h" -#include "jdns_mdnsd.h" - #define JDNS_UDP_UNI_OUT_MAX 512 #define JDNS_UDP_UNI_IN_MAX 16384 #define JDNS_UDP_MUL_OUT_MAX 9000 diff --git a/src/jdns/src/jdns/jdns_mdnsd.c b/src/jdns/src/jdns/jdns_mdnsd.c index 3dd581d0..e818d5dd 100644 --- a/src/jdns/src/jdns/jdns_mdnsd.c +++ b/src/jdns/src/jdns/jdns_mdnsd.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2005 Jeremie Miller - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -638,7 +638,6 @@ int _r_out(mdnsd d, jdns_packet_t *m, mdnsdr *list) return ret; } - mdnsd mdnsd_new(int class, int frame, int port, int (*time_now)(mdnsd d, void *arg), int (*rand_int)(mdnsd d, void *arg), void *arg) { //int i; diff --git a/src/jdns/src/jdns/jdns_mdnsd.h b/src/jdns/src/jdns/jdns_mdnsd.h index 2870dc70..d311c405 100644 --- a/src/jdns/src/jdns/jdns_mdnsd.h +++ b/src/jdns/src/jdns/jdns_mdnsd.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2005 Jeremie Miller - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -116,5 +116,4 @@ void mdnsd_set_srv(mdnsd d, mdnsdr r, int priority, int weight, int port, char * // /////////// - -#endif +#endif // JDNS_MDNSD_H diff --git a/src/jdns/src/jdns/jdns_p.h b/src/jdns/src/jdns/jdns_p.h index 0ae7e948..ef2ac093 100644 --- a/src/jdns/src/jdns/jdns_p.h +++ b/src/jdns/src/jdns/jdns_p.h @@ -24,11 +24,14 @@ #ifndef JDNS_P_H #define JDNS_P_H +#include "jdns.h" +#include "jdns_packet.h" + +#include +#include #include #include #include -#include -#include #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) # define JDNS_OS_WIN @@ -50,17 +53,14 @@ # define JDNS_OS_MAC #endif -#ifdef JDNS_OS_WIN -# include -#endif - #ifdef JDNS_OS_UNIX -# include # include +# include #endif -#include "jdns.h" -#include "jdns_packet.h" +#ifdef JDNS_OS_WIN +# include +#endif // jdns_util.c void *jdns_alloc(int size); @@ -96,4 +96,4 @@ void jdns_response_remove_answer(jdns_response_t *r, int pos); #define _ustrlen(str) strlen((const char *)str) #define _ustrcmp(a, b) strcmp((const char *)a, (const char *)b) -#endif +#endif // JDNS_P_H diff --git a/src/jdns/src/jdns/jdns_packet.h b/src/jdns/src/jdns/jdns_packet.h index 113c55eb..23eb059a 100644 --- a/src/jdns/src/jdns/jdns_packet.h +++ b/src/jdns/src/jdns/jdns_packet.h @@ -113,4 +113,4 @@ void jdns_packet_delete(jdns_packet_t *a); int jdns_packet_import(jdns_packet_t **a, const unsigned char *data, int size); // 0 on fail int jdns_packet_export(jdns_packet_t *a, int maxsize); // 0 on fail -#endif +#endif // JDNS_PACKET_H diff --git a/src/jdns/src/jdns/jdns_sys.c b/src/jdns/src/jdns/jdns_sys.c index d755c1c4..bf345819 100644 --- a/src/jdns/src/jdns/jdns_sys.c +++ b/src/jdns/src/jdns/jdns_sys.c @@ -113,15 +113,14 @@ read /etc/hosts manually: #include "jdns_p.h" -#ifdef JDNS_OS_WIN -# include -#endif - #ifdef JDNS_OS_UNIX -# include # include -# include # include +# include +# include +#endif +#ifdef JDNS_OS_WIN +# include #endif #define string_indexOf jdns_string_indexOf diff --git a/src/jdns/src/jdns/jdns_util.c b/src/jdns/src/jdns/jdns_util.c index af8cd09a..701cd126 100644 --- a/src/jdns/src/jdns/jdns_util.c +++ b/src/jdns/src/jdns/jdns_util.c @@ -22,7 +22,6 @@ */ #include "jdns_p.h" - #include "jdns_packet.h" //---------------------------------------------------------------------------- diff --git a/src/jdns/src/qjdns/qjdns.cpp b/src/jdns/src/qjdns/qjdns.cpp index a6e61d15..4f7572ef 100644 --- a/src/jdns/src/qjdns/qjdns.cpp +++ b/src/jdns/src/qjdns/qjdns.cpp @@ -22,12 +22,10 @@ */ #include "qjdns_p.h" - -#include #include "qjdns_sock.h" -// for fprintf -#include +#include // for fprintf +#include // safeobj stuff, from qca diff --git a/src/jdns/src/qjdns/qjdns_p.h b/src/jdns/src/qjdns/qjdns_p.h index 0cdaa73f..94669c85 100644 --- a/src/jdns/src/qjdns/qjdns_p.h +++ b/src/jdns/src/qjdns/qjdns_p.h @@ -26,13 +26,14 @@ #include "jdns.h" #include "qjdns.h" + +#include #include -#include #include -#include +#include -class QUdpSocket; class QTimer; +class QUdpSocket; class SafeTimer : public QObject { @@ -131,4 +132,4 @@ private slots: static int cb_udp_write(jdns_session_t *, void *app, int handle, const jdns_address_t *addr, int port, unsigned char *buf, int bufsize); }; -#endif +#endif // QJDNS_P_H diff --git a/src/jdns/src/qjdns/qjdns_sock.cpp b/src/jdns/src/qjdns/qjdns_sock.cpp index 8c2991f3..09cd96a8 100644 --- a/src/jdns/src/qjdns/qjdns_sock.cpp +++ b/src/jdns/src/qjdns/qjdns_sock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,21 +27,19 @@ #include #include #include - -#ifdef Q_OS_WIN -# include -# include -#endif - #ifdef Q_OS_UNIX -# include -# include -# include -# include -# include +# include # include +# include +# include # include -# include +# include +# include +# include +#endif +#ifdef Q_OS_WIN +# include +# include #endif #ifdef Q_OS_HAIKU diff --git a/src/jdns/src/qjdns/qjdns_sock.h b/src/jdns/src/qjdns/qjdns_sock.h index 13d388d6..dcbf9b74 100644 --- a/src/jdns/src/qjdns/qjdns_sock.h +++ b/src/jdns/src/qjdns/qjdns_sock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005,2006 Justin Karneges + * Copyright (C) 2005-2006 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -30,4 +30,4 @@ bool qjdns_sock_setTTL4(int s, int ttl); bool qjdns_sock_setTTL6(int s, int ttl); bool qjdns_sock_setIPv6Only(int s); -#endif +#endif // QJDNS_SOCK_H diff --git a/src/jdns/src/qjdns/qjdnsshared.cpp b/src/jdns/src/qjdns/qjdnsshared.cpp index 8c9ed3ca..6d8f35a1 100644 --- a/src/jdns/src/qjdns/qjdnsshared.cpp +++ b/src/jdns/src/qjdns/qjdnsshared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Justin Karneges + * Copyright (C) 2006-2008 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -159,7 +159,6 @@ static inline uint qHash(const Handle &key) return ((h1 << 16) | (h1 >> 16)) ^ h2; } - //---------------------------------------------------------------------------- // JDnsShutdown //---------------------------------------------------------------------------- diff --git a/src/jdns/src/qjdns/qjdnsshared_p.h b/src/jdns/src/qjdns/qjdnsshared_p.h index 7cf2e729..98024460 100644 --- a/src/jdns/src/qjdns/qjdnsshared_p.h +++ b/src/jdns/src/qjdns/qjdnsshared_p.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Justin Karneges + * Copyright (C) 2006-2008 Justin Karneges * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,13 +27,14 @@ // SafeTimer #include "qjdns_p.h" #include "qjdnsshared.h" -#include -#include -#include + +#include #include -#include +#include #include -#include +#include +#include +#include class JDnsShutdownAgent : public QObject { @@ -230,4 +231,4 @@ private slots: void lateTimer_timeout(); }; -#endif +#endif // QJDNSSHARED_P_H diff --git a/src/jdns/tools/jdns/main.cpp b/src/jdns/tools/jdns/main.cpp index 5259f5f0..5bd3bdb2 100644 --- a/src/jdns/tools/jdns/main.cpp +++ b/src/jdns/tools/jdns/main.cpp @@ -22,9 +22,11 @@ */ #include "main.h" + +#include "qjdns.h" + #include #include -#include "qjdns.h" QString dataToString(const QByteArray &buf) { @@ -216,7 +218,6 @@ void App::start() QTimer::singleShot(quit_time * 1000, this, SLOT(doShutdown())); } - void App::jdns_resultsReady(int id, const QJDns::Response &results) { printf("[%d] Results\n", id); diff --git a/src/jdns/tools/jdns/main.h b/src/jdns/tools/jdns/main.h index 018965e9..e208fe94 100644 --- a/src/jdns/tools/jdns/main.h +++ b/src/jdns/tools/jdns/main.h @@ -25,6 +25,7 @@ #define MAIN_H #include "qjdns.h" + #include #include diff --git a/src/xmpp/base/randomnumbergenerator.cpp b/src/xmpp/base/randomnumbergenerator.cpp index 4ac131b0..672c0611 100644 --- a/src/xmpp/base/randomnumbergenerator.cpp +++ b/src/xmpp/base/randomnumbergenerator.cpp @@ -21,7 +21,6 @@ #include namespace XMPP { - RandomNumberGenerator::~RandomNumberGenerator() { } @@ -31,5 +30,4 @@ double RandomNumberGenerator::generateNumberBetween(double a, double b) const assert(b > a); return a + (generateNumber()/getMaximumGeneratedNumber())*(b-a); } - -} +} // namespace XMPP diff --git a/src/xmpp/base/randomnumbergenerator.h b/src/xmpp/base/randomnumbergenerator.h index 5d3fb337..abadb9a9 100644 --- a/src/xmpp/base/randomnumbergenerator.h +++ b/src/xmpp/base/randomnumbergenerator.h @@ -31,6 +31,6 @@ namespace XMPP { virtual double generateNumber() const = 0; virtual double getMaximumGeneratedNumber() const = 0; }; -} +} // namespace XMPP -#endif +#endif // RANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/randrandomnumbergenerator.h b/src/xmpp/base/randrandomnumbergenerator.h index 6306e1ae..1d1c45ee 100644 --- a/src/xmpp/base/randrandomnumbergenerator.h +++ b/src/xmpp/base/randrandomnumbergenerator.h @@ -35,6 +35,6 @@ namespace XMPP { return RAND_MAX; } }; -} +} // namespace XMPP -#endif +#endif // RANDRANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/timezone.cpp b/src/xmpp/base/timezone.cpp index fb705254..4e7e5d20 100644 --- a/src/xmpp/base/timezone.cpp +++ b/src/xmpp/base/timezone.cpp @@ -16,22 +16,21 @@ * */ -#include +#include "timezone.h" #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) -#include -#include -#ifdef Q_OS_UNIX -#include -#endif -#ifdef Q_OS_WIN -#include -#endif +# include +# include +# ifdef Q_OS_UNIX +# include +# endif +# ifdef Q_OS_WIN +# include +# endif #else -#include +# include #endif - -#include "timezone.h" +#include #if QT_VERSION < QT_VERSION_CHECK(5,2,0) static bool inited = false; diff --git a/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h b/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h index 6141481f..132ea8b8 100644 --- a/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h +++ b/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h @@ -19,10 +19,10 @@ #ifndef INCREMENTINGRANDOMNUMBERGENERATOR_H #define INCREMENTINGRANDOMNUMBERGENERATOR_H -#include - #include "xmpp/base/randomnumbergenerator.h" +#include + namespace XMPP { class IncrementingRandomNumberGenerator : public RandomNumberGenerator { @@ -42,6 +42,6 @@ namespace XMPP { int maximumNumber_; mutable int currentNumber_; }; -} +} // namespace XMPP -#endif +#endif // INCREMENTINGRANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/unittest/randomnumbergeneratortest.cpp b/src/xmpp/base/unittest/randomnumbergeneratortest.cpp index d904e26e..d2b01c59 100644 --- a/src/xmpp/base/unittest/randomnumbergeneratortest.cpp +++ b/src/xmpp/base/unittest/randomnumbergeneratortest.cpp @@ -16,12 +16,12 @@ * */ -#include -#include - #include "qttestutil/qttestutil.h" #include "xmpp/base/randomnumbergenerator.h" +#include +#include + using namespace XMPP; class RandomNumberGeneratorTest : public QObject diff --git a/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp b/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp index 9a784683..a7255dd6 100644 --- a/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp +++ b/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp @@ -16,12 +16,12 @@ * */ -#include -#include - #include "qttestutil/qttestutil.h" #include "xmpp/base/randrandomnumbergenerator.h" +#include +#include + using namespace XMPP; class RandRandomNumberGeneratorTest : public QObject diff --git a/src/xmpp/blake2/blake2-impl.h b/src/xmpp/blake2/blake2-impl.h index c1df82e0..6369ac76 100644 --- a/src/xmpp/blake2/blake2-impl.h +++ b/src/xmpp/blake2/blake2-impl.h @@ -157,4 +157,4 @@ static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) memset_v(v, 0, n); } -#endif +#endif // BLAKE2_IMPL_H diff --git a/src/xmpp/blake2/blake2.h b/src/xmpp/blake2/blake2.h index ad62f260..e547afb9 100644 --- a/src/xmpp/blake2/blake2.h +++ b/src/xmpp/blake2/blake2.h @@ -86,7 +86,6 @@ extern "C" { size_t outlen; } blake2bp_state; - BLAKE2_PACKED(struct blake2s_param__ { uint8_t digest_length; /* 1 */ @@ -192,4 +191,4 @@ extern "C" { } #endif -#endif +#endif // BLAKE2_H diff --git a/src/xmpp/blake2/blake2b-ref.c b/src/xmpp/blake2/blake2b-ref.c index cd38b1ba..ab5fbde8 100644 --- a/src/xmpp/blake2/blake2b-ref.c +++ b/src/xmpp/blake2/blake2b-ref.c @@ -13,12 +13,12 @@ https://blake2.net. */ +#include "blake2-impl.h" +#include "blake2.h" + #include -#include #include - -#include "blake2.h" -#include "blake2-impl.h" +#include static const uint64_t blake2b_IV[8] = { @@ -44,7 +44,6 @@ static const uint8_t blake2b_sigma[12][16] = { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } }; - static void blake2b_set_lastnode( blake2b_state *S ) { S->f[1] = (uint64_t)-1; @@ -93,8 +92,6 @@ int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) return 0; } - - int blake2b_init( blake2b_state *S, size_t outlen ) { blake2b_param P[1]; @@ -116,7 +113,6 @@ int blake2b_init( blake2b_state *S, size_t outlen ) return blake2b_init_param( S, P ); } - int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) { blake2b_param P[1]; @@ -311,8 +307,8 @@ int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen #endif #if defined(BLAKE2B_SELFTEST) -#include #include "blake2-kat.h" +#include int main( void ) { uint8_t key[BLAKE2B_KEYBYTES]; diff --git a/src/xmpp/blake2/blake2qt.cpp b/src/xmpp/blake2/blake2qt.cpp index b90c7f6d..381d5b58 100644 --- a/src/xmpp/blake2/blake2qt.cpp +++ b/src/xmpp/blake2/blake2qt.cpp @@ -1,10 +1,10 @@ #include "blake2qt.h" + #include "blake2.h" #include namespace XMPP { - QByteArray computeBlake2Hash(const QByteArray &ba, Blake2DigestSize digestSize) { QByteArray ret; @@ -101,5 +101,4 @@ QByteArray computeBlake2Hash(QIODevice *dev, Blake2DigestSize digestSize) return computeBlake2Hash512(dev); } } - } //namespace XMPP diff --git a/src/xmpp/blake2/blake2qt.h b/src/xmpp/blake2/blake2qt.h index 8240afbd..78f08481 100644 --- a/src/xmpp/blake2/blake2qt.h +++ b/src/xmpp/blake2/blake2qt.h @@ -6,7 +6,6 @@ class QIODevice; namespace XMPP { - enum Blake2DigestSize { Blake2Digest256, Blake2Digest512 @@ -14,6 +13,6 @@ enum Blake2DigestSize { QByteArray computeBlake2Hash(const QByteArray &ba, Blake2DigestSize digestSize); QByteArray computeBlake2Hash(QIODevice *dev, Blake2DigestSize digestSize); +} // namespace XMPP -} -#endif +#endif // BLAKE2QT_H diff --git a/src/xmpp/blake2/blake2s-ref.c b/src/xmpp/blake2/blake2s-ref.c index c8b035f6..f4e09dfc 100644 --- a/src/xmpp/blake2/blake2s-ref.c +++ b/src/xmpp/blake2/blake2s-ref.c @@ -13,12 +13,12 @@ https://blake2.net. */ +#include "blake2-impl.h" +#include "blake2.h" + #include -#include #include - -#include "blake2.h" -#include "blake2-impl.h" +#include static const uint32_t blake2s_IV[8] = { @@ -88,7 +88,6 @@ int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) return 0; } - /* Sequential blake2s initialization */ int blake2s_init( blake2s_state *S, size_t outlen ) { @@ -299,8 +298,8 @@ int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen #endif #if defined(BLAKE2S_SELFTEST) -#include #include "blake2-kat.h" +#include int main( void ) { uint8_t key[BLAKE2S_KEYBYTES]; diff --git a/src/xmpp/jid/jid.cpp b/src/xmpp/jid/jid.cpp index e7e35bc5..e33b8682 100644 --- a/src/xmpp/jid/jid.cpp +++ b/src/xmpp/jid/jid.cpp @@ -19,15 +19,14 @@ #include "xmpp/jid/jid.h" -#include -#include - #ifndef NO_IRISNET -#include "irisnetglobal_p.h" +# include "irisnetglobal_p.h" #endif -using namespace XMPP; +#include +#include +using namespace XMPP; //---------------------------------------------------------------------------- // StringPrepCache diff --git a/src/xmpp/jid/jid.h b/src/xmpp/jid/jid.h index 92ee5d84..b334150b 100644 --- a/src/xmpp/jid/jid.h +++ b/src/xmpp/jid/jid.h @@ -20,13 +20,12 @@ #ifndef XMPP_JID_H #define XMPP_JID_H -#include -#include #include #include +#include +#include -namespace XMPP -{ +namespace XMPP { class StringPrepCache { public: @@ -98,6 +97,6 @@ namespace XMPP { return qHash(key.full(), seed); } -} +} // namespace XMPP -#endif +#endif // XMPP_JID_H diff --git a/src/xmpp/jid/unittest/jidtest.cpp b/src/xmpp/jid/unittest/jidtest.cpp index fa4dc602..b3c417e5 100644 --- a/src/xmpp/jid/unittest/jidtest.cpp +++ b/src/xmpp/jid/unittest/jidtest.cpp @@ -18,12 +18,12 @@ // FIXME: Complete this -#include -#include - #include "qttestutil/qttestutil.h" #include "xmpp/jid/jid.h" +#include +#include + using namespace XMPP; class JidTest : public QObject diff --git a/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp b/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp index 122742a7..a62835b7 100644 --- a/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp +++ b/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp @@ -1,8 +1,8 @@ +#include "qttestutil/qttestutil.h" + #include #include -#include "qttestutil/qttestutil.h" - class MyFirstClassTest : public QObject { Q_OBJECT diff --git a/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp b/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp index 80be96d5..c2b57159 100644 --- a/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp +++ b/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp @@ -1,8 +1,8 @@ +#include "qttestutil/qttestutil.h" + #include #include -#include "qttestutil/qttestutil.h" - class MySecondClassTest : public QObject { Q_OBJECT diff --git a/src/xmpp/qa/qttestutil/qttestutil.h b/src/xmpp/qa/qttestutil/qttestutil.h index 69729aff..d53a8363 100644 --- a/src/xmpp/qa/qttestutil/qttestutil.h +++ b/src/xmpp/qa/qttestutil/qttestutil.h @@ -38,4 +38,4 @@ #define QTTESTUTIL_REGISTER_TEST(TestClass) \ static QtTestUtil::TestRegistration TestClass##Registration -#endif +#endif // QTTESTUTIL_H diff --git a/src/xmpp/qa/qttestutil/simplechecker.cpp b/src/xmpp/qa/qttestutil/simplechecker.cpp index 1ac56714..50a6f11e 100644 --- a/src/xmpp/qa/qttestutil/simplechecker.cpp +++ b/src/xmpp/qa/qttestutil/simplechecker.cpp @@ -16,10 +16,10 @@ * */ -#include - #include "qttestutil/testregistry.h" +#include + /** * Runs all tests registered with the QtTestUtil registry. */ diff --git a/src/xmpp/qa/qttestutil/testregistration.h b/src/xmpp/qa/qttestutil/testregistration.h index 7754c735..0378ea05 100644 --- a/src/xmpp/qa/qttestutil/testregistration.h +++ b/src/xmpp/qa/qttestutil/testregistration.h @@ -22,7 +22,6 @@ #include "qttestutil/testregistry.h" namespace QtTestUtil { - /** * A wrapper class around a test to manage registration and static * creation of an instance of the test class. @@ -45,7 +44,6 @@ namespace QtTestUtil { private: TestClass* test_; }; +} // namespace QtTestUtil -} - -#endif +#endif // QTTESTUTIL_TESTREGISTRATION_H diff --git a/src/xmpp/qa/qttestutil/testregistry.cpp b/src/xmpp/qa/qttestutil/testregistry.cpp index 9afaf083..29d58d8d 100644 --- a/src/xmpp/qa/qttestutil/testregistry.cpp +++ b/src/xmpp/qa/qttestutil/testregistry.cpp @@ -21,7 +21,6 @@ #include namespace QtTestUtil { - TestRegistry* TestRegistry::getInstance() { static TestRegistry registry; @@ -41,5 +40,4 @@ int TestRegistry::runTests(int argc, char* argv[]) } return result; } - -} +} // namespace QtTestUtil diff --git a/src/xmpp/qa/qttestutil/testregistry.h b/src/xmpp/qa/qttestutil/testregistry.h index 332b8013..95d7502c 100644 --- a/src/xmpp/qa/qttestutil/testregistry.h +++ b/src/xmpp/qa/qttestutil/testregistry.h @@ -24,7 +24,6 @@ class QObject; namespace QtTestUtil { - /** * A registry of QtTest test classes. * All test classes registered with QTTESTUTIL_REGISTER_TEST add @@ -57,6 +56,6 @@ namespace QtTestUtil { private: QList tests_; }; -} +} // namespace QtTestUtil -#endif +#endif // QTTESTUTIL_TESTREGISTRY_H diff --git a/src/xmpp/qa/unittest.pri b/src/xmpp/qa/unittest.pri index 116b7096..85267535 100644 --- a/src/xmpp/qa/unittest.pri +++ b/src/xmpp/qa/unittest.pri @@ -5,7 +5,6 @@ # standalone checker for the module. # - CONFIG += crypto include($$PWD/qttestutil/qttestutil.pri) diff --git a/src/xmpp/qa/unittest.template/myclasstest.cpp b/src/xmpp/qa/unittest.template/myclasstest.cpp index d665feba..05218989 100644 --- a/src/xmpp/qa/unittest.template/myclasstest.cpp +++ b/src/xmpp/qa/unittest.template/myclasstest.cpp @@ -16,11 +16,11 @@ * */ +#include "qttestutil/qttestutil.h" + #include #include -#include "qttestutil/qttestutil.h" - class MyClassTest : public QObject { Q_OBJECT diff --git a/src/xmpp/sasl/digestmd5proplist.cpp b/src/xmpp/sasl/digestmd5proplist.cpp index f5e0bfe0..59c682e4 100644 --- a/src/xmpp/sasl/digestmd5proplist.cpp +++ b/src/xmpp/sasl/digestmd5proplist.cpp @@ -19,7 +19,6 @@ #include "xmpp/sasl/digestmd5proplist.h" namespace XMPP { - DIGESTMD5PropList::DIGESTMD5PropList() : QList() { } @@ -129,4 +128,4 @@ int DIGESTMD5PropList::varCount(const QByteArray &var) const return n; } -} +} // namespace XMPP diff --git a/src/xmpp/sasl/digestmd5proplist.h b/src/xmpp/sasl/digestmd5proplist.h index f6c9f4db..f94d36d4 100644 --- a/src/xmpp/sasl/digestmd5proplist.h +++ b/src/xmpp/sasl/digestmd5proplist.h @@ -19,8 +19,8 @@ #ifndef DIGESTMD5PROPLIST_H #define DIGESTMD5PROPLIST_H -#include #include +#include namespace XMPP { struct DIGESTMD5Prop @@ -41,6 +41,6 @@ namespace XMPP { private: int varCount(const QByteArray &var) const; }; -} +} // namespace XMPP -#endif +#endif // DIGESTMD5PROPLIST_H diff --git a/src/xmpp/sasl/digestmd5response.cpp b/src/xmpp/sasl/digestmd5response.cpp index 02f625a2..2cd4e9b9 100644 --- a/src/xmpp/sasl/digestmd5response.cpp +++ b/src/xmpp/sasl/digestmd5response.cpp @@ -18,15 +18,14 @@ #include "xmpp/sasl/digestmd5response.h" +#include "xmpp/base/randomnumbergenerator.h" +#include "xmpp/sasl/digestmd5proplist.h" + #include #include #include -#include "xmpp/sasl/digestmd5proplist.h" -#include "xmpp/base/randomnumbergenerator.h" - namespace XMPP { - DIGESTMD5Response::DIGESTMD5Response(const QByteArray& challenge, const QString& service, const QString& host, const QString& arealm, const QString& user, const QString& authz, const QByteArray& password, const RandomNumberGenerator& rand) : isValid_(true) { QString realm = arealm; @@ -93,5 +92,4 @@ DIGESTMD5Response::DIGESTMD5Response(const QByteArray& challenge, const QString& out.set("authzid", authz.toUtf8()); value_ = out.toString(); } - -} +} // namespace XMPP diff --git a/src/xmpp/sasl/digestmd5response.h b/src/xmpp/sasl/digestmd5response.h index 403b3948..60969974 100644 --- a/src/xmpp/sasl/digestmd5response.h +++ b/src/xmpp/sasl/digestmd5response.h @@ -50,6 +50,6 @@ namespace XMPP { bool isValid_; QByteArray value_; }; -} +} // namespace XMPP -#endif +#endif // DIGESTMD5RESPONSE_H diff --git a/src/xmpp/sasl/plainmessage.cpp b/src/xmpp/sasl/plainmessage.cpp index b067859a..3585065a 100644 --- a/src/xmpp/sasl/plainmessage.cpp +++ b/src/xmpp/sasl/plainmessage.cpp @@ -19,10 +19,9 @@ #include "xmpp/sasl/plainmessage.h" namespace XMPP { - PLAINMessage::PLAINMessage(const QString& authzid, const QString& authcid, const QByteArray& password) { value_ = authzid.toUtf8() + '\0' + authcid.toUtf8() + '\0' + password; } -} +} // namespace XMPP diff --git a/src/xmpp/sasl/plainmessage.h b/src/xmpp/sasl/plainmessage.h index 127613b9..a41c0b57 100644 --- a/src/xmpp/sasl/plainmessage.h +++ b/src/xmpp/sasl/plainmessage.h @@ -35,6 +35,6 @@ namespace XMPP { private: QByteArray value_; }; -} +} // namespace XMPP -#endif +#endif // PLAINMESSAGE_H diff --git a/src/xmpp/sasl/scramsha1message.cpp b/src/xmpp/sasl/scramsha1message.cpp index 12559b73..eac93f5c 100644 --- a/src/xmpp/sasl/scramsha1message.cpp +++ b/src/xmpp/sasl/scramsha1message.cpp @@ -18,16 +18,15 @@ #include "xmpp/sasl/scramsha1message.h" +#include "xmpp/base/randomnumbergenerator.h" +#include "xmpp/jid/jid.h" + +#include #include #include #include -#include - -#include "xmpp/base/randomnumbergenerator.h" -#include "xmpp/jid/jid.h" namespace XMPP { - bool Normalize(const QString &username_in, QString &username_out ) { // SASLprep if (StringPrepCache::saslprep(username_in, 1024, username_out)) { @@ -68,5 +67,4 @@ SCRAMSHA1Message::SCRAMSHA1Message(const QString& authzid, const QString& authci QTextStream(&result) << ",n=" << username << ",r=" << clientnonce; value_ = result.toUtf8(); } - -} +} // namespace XMPP diff --git a/src/xmpp/sasl/scramsha1message.h b/src/xmpp/sasl/scramsha1message.h index cad4f790..24fae6fb 100644 --- a/src/xmpp/sasl/scramsha1message.h +++ b/src/xmpp/sasl/scramsha1message.h @@ -19,11 +19,11 @@ #ifndef SCRAMSHA1MESSAGE_H #define SCRAMSHA1MESSAGE_H +#include "xmpp/base/randomnumbergenerator.h" + #include #include -#include "xmpp/base/randomnumbergenerator.h" - namespace XMPP { class SCRAMSHA1Message { @@ -42,6 +42,6 @@ namespace XMPP { QByteArray value_; bool isValid_; }; -} +} // namespace XMPP -#endif +#endif // SCRAMSHA1MESSAGE_H diff --git a/src/xmpp/sasl/scramsha1response.cpp b/src/xmpp/sasl/scramsha1response.cpp index 210ae63b..960327e8 100644 --- a/src/xmpp/sasl/scramsha1response.cpp +++ b/src/xmpp/sasl/scramsha1response.cpp @@ -18,15 +18,15 @@ #include "xmpp/sasl/scramsha1response.h" +#include "xmpp/base/randomnumbergenerator.h" +#include "xmpp/jid/jid.h" + #include +#include #include #include #include #include -#include - -#include "xmpp/base/randomnumbergenerator.h" -#include "xmpp/jid/jid.h" namespace XMPP { QCA::SecureArray HMAC_SHA_1(const QCA::SecureArray &key, const QCA::SecureArray &str) { @@ -130,5 +130,4 @@ namespace XMPP { const QString SCRAMSHA1Response::getSaltedPassword() { return QCA::Base64().arrayToString(salted_password_); } - -} +} // namespace XMPP diff --git a/src/xmpp/sasl/scramsha1response.h b/src/xmpp/sasl/scramsha1response.h index 93a141cc..9d00dee8 100644 --- a/src/xmpp/sasl/scramsha1response.h +++ b/src/xmpp/sasl/scramsha1response.h @@ -56,6 +56,6 @@ namespace XMPP { QCA::SecureArray server_signature_; QCA::SymmetricKey salted_password_; }; -} +} // namespace XMPP -#endif +#endif // SCRAMSHA1RESPONSE_H diff --git a/src/xmpp/sasl/scramsha1signature.cpp b/src/xmpp/sasl/scramsha1signature.cpp index 70240c23..60b101ba 100644 --- a/src/xmpp/sasl/scramsha1signature.cpp +++ b/src/xmpp/sasl/scramsha1signature.cpp @@ -18,17 +18,16 @@ #include "xmpp/sasl/scramsha1signature.h" +#include "xmpp/base/randomnumbergenerator.h" + #include +#include #include #include #include #include -#include - -#include "xmpp/base/randomnumbergenerator.h" namespace XMPP { - SCRAMSHA1Signature::SCRAMSHA1Signature(const QByteArray &server_final_message, const QCA::SecureArray &server_signature_should) { QRegExp pattern("v=([^,]*)"); @@ -43,5 +42,4 @@ namespace XMPP { isValid_ = false; } } - -} +} // namespace XMPP diff --git a/src/xmpp/sasl/scramsha1signature.h b/src/xmpp/sasl/scramsha1signature.h index 81969ca1..5b4125d1 100644 --- a/src/xmpp/sasl/scramsha1signature.h +++ b/src/xmpp/sasl/scramsha1signature.h @@ -36,6 +36,6 @@ namespace XMPP { private: bool isValid_; }; -} +} // namespace XMPP -#endif +#endif // SCRAMSHA1SIGNATURE_H diff --git a/src/xmpp/sasl/unittest/digestmd5responsetest.cpp b/src/xmpp/sasl/unittest/digestmd5responsetest.cpp index 825b21d9..6cf2d790 100644 --- a/src/xmpp/sasl/unittest/digestmd5responsetest.cpp +++ b/src/xmpp/sasl/unittest/digestmd5responsetest.cpp @@ -16,13 +16,13 @@ * */ -#include -#include -#include - #include "qttestutil/qttestutil.h" -#include "xmpp/sasl/digestmd5response.h" #include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" +#include "xmpp/sasl/digestmd5response.h" + +#include +#include +#include using namespace XMPP; diff --git a/src/xmpp/sasl/unittest/plainmessagetest.cpp b/src/xmpp/sasl/unittest/plainmessagetest.cpp index ec2a66c1..7bb1dc29 100644 --- a/src/xmpp/sasl/unittest/plainmessagetest.cpp +++ b/src/xmpp/sasl/unittest/plainmessagetest.cpp @@ -16,12 +16,12 @@ * */ +#include "qttestutil/qttestutil.h" +#include "xmpp/sasl/plainmessage.h" + #include #include -#include "xmpp/sasl/plainmessage.h" -#include "qttestutil/qttestutil.h" - using namespace XMPP; class PlainMessageTest : public QObject diff --git a/src/xmpp/sasl/unittest/scramsha1messagetest.cpp b/src/xmpp/sasl/unittest/scramsha1messagetest.cpp index 24d3a36a..0cf9121d 100644 --- a/src/xmpp/sasl/unittest/scramsha1messagetest.cpp +++ b/src/xmpp/sasl/unittest/scramsha1messagetest.cpp @@ -16,14 +16,14 @@ * */ -#include -#include -#include - #include "qttestutil/qttestutil.h" #include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" #include "xmpp/sasl/scramsha1message.h" +#include +#include +#include + using namespace XMPP; class SCRAMSHA1MessageTest : public QObject diff --git a/src/xmpp/sasl/unittest/scramsha1responsetest.cpp b/src/xmpp/sasl/unittest/scramsha1responsetest.cpp index 132302aa..6e0260fb 100644 --- a/src/xmpp/sasl/unittest/scramsha1responsetest.cpp +++ b/src/xmpp/sasl/unittest/scramsha1responsetest.cpp @@ -16,14 +16,14 @@ * */ -#include -#include -#include - #include "qttestutil/qttestutil.h" +#include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" #include "xmpp/sasl/scramsha1response.h" #include "xmpp/sasl/scramsha1signature.h" -#include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" + +#include +#include +#include using namespace XMPP; diff --git a/src/xmpp/xmpp-core/compressionhandler.cpp b/src/xmpp/xmpp-core/compressionhandler.cpp index 89fd9f1d..6d051ca8 100644 --- a/src/xmpp/xmpp-core/compressionhandler.cpp +++ b/src/xmpp/xmpp-core/compressionhandler.cpp @@ -1,10 +1,10 @@ -#include -#include - #include "compressionhandler.h" #include "xmpp/zlib/zlibcompressor.h" #include "xmpp/zlib/zlibdecompressor.h" +#include +#include + CompressionHandler::CompressionHandler() : errorCode_(0) { diff --git a/src/xmpp/xmpp-core/compressionhandler.h b/src/xmpp/xmpp-core/compressionhandler.h index d336af47..13b2808d 100644 --- a/src/xmpp/xmpp-core/compressionhandler.h +++ b/src/xmpp/xmpp-core/compressionhandler.h @@ -1,8 +1,8 @@ #ifndef COMPRESSIONHANDLER_H #define COMPRESSIONHANDLER_H -#include #include +#include class ZLibCompressor; class ZLibDecompressor; @@ -32,4 +32,4 @@ class CompressionHandler : public QObject int errorCode_; }; -#endif +#endif // COMPRESSIONHANDLER_H diff --git a/src/xmpp/xmpp-core/connector.cpp b/src/xmpp/xmpp-core/connector.cpp index 6aa01c2f..b8617787 100644 --- a/src/xmpp/xmpp-core/connector.cpp +++ b/src/xmpp/xmpp-core/connector.cpp @@ -28,21 +28,19 @@ greatly simplify this class. - Sep 3rd, 2003. */ +#include "bsocket.h" +#include "httpconnect.h" +#include "httppoll.h" +#include "socks.h" #include "xmpp.h" -#include #include -#include +#include #include +#include #include -#include "bsocket.h" -#include "httpconnect.h" -#include "httppoll.h" -#include "socks.h" - //#define XMPP_DEBUG - #ifdef XMPP_DEBUG # define XDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif @@ -54,7 +52,6 @@ static const int XMPP_LEGACY_PORT = 5223; static const char* XMPP_CLIENT_SRV = "xmpp-client"; static const char* XMPP_CLIENT_TRANSPORT = "tcp"; - //---------------------------------------------------------------------------- // Connector //---------------------------------------------------------------------------- @@ -113,7 +110,6 @@ QString Connector::host() const return QString(); } - //---------------------------------------------------------------------------- // AdvancedConnector::Proxy //---------------------------------------------------------------------------- @@ -186,7 +182,6 @@ void AdvancedConnector::Proxy::setPollInterval(int secs) v_poll = secs; } - //---------------------------------------------------------------------------- // AdvancedConnector //---------------------------------------------------------------------------- diff --git a/src/xmpp/xmpp-core/parser.cpp b/src/xmpp/xmpp-core/parser.cpp index 4eb601d8..282839db 100644 --- a/src/xmpp/xmpp-core/parser.cpp +++ b/src/xmpp/xmpp-core/parser.cpp @@ -347,12 +347,10 @@ class StreamInput : public QXmlInputSource } }; - //---------------------------------------------------------------------------- // ParserHandler //---------------------------------------------------------------------------- -namespace XMPP -{ +namespace XMPP { class ParserHandler : public QXmlDefaultHandler { public: @@ -545,8 +543,7 @@ namespace XMPP QList eventList; bool needMore = false; }; -}; - +}; // namespace XMPP //---------------------------------------------------------------------------- // Event diff --git a/src/xmpp/xmpp-core/parser.h b/src/xmpp/xmpp-core/parser.h index 72fa9b57..3b7a9f63 100644 --- a/src/xmpp/xmpp-core/parser.h +++ b/src/xmpp/xmpp-core/parser.h @@ -23,8 +23,7 @@ #include #include -namespace XMPP -{ +namespace XMPP { class Parser { public: @@ -80,6 +79,6 @@ namespace XMPP class Private; Private *d; }; -} +} // namespace XMPP -#endif +#endif // PARSER_H diff --git a/src/xmpp/xmpp-core/protocol.cpp b/src/xmpp/xmpp-core/protocol.cpp index d6bdc297..7ba0845a 100644 --- a/src/xmpp/xmpp-core/protocol.cpp +++ b/src/xmpp/xmpp-core/protocol.cpp @@ -23,15 +23,15 @@ #include "protocol.h" -#include -#include -#include -#include - #ifdef XMPP_TEST #include "td.h" #endif +#include +#include +#include +#include + using namespace XMPP; // printArray diff --git a/src/xmpp/xmpp-core/protocol.h b/src/xmpp/xmpp-core/protocol.h index 764be73b..13cb6531 100644 --- a/src/xmpp/xmpp-core/protocol.h +++ b/src/xmpp/xmpp-core/protocol.h @@ -20,15 +20,15 @@ #ifndef PROTOCOL_H #define PROTOCOL_H -#include +#include "sm.h" +#include "xmlprotocol.h" +#include "xmpp.h" + #include +#include #include #include -#include "xmlprotocol.h" -#include "xmpp.h" -#include "sm.h" - #define NS_ETHERX "http://etherx.jabber.org/streams" #define NS_CLIENT "jabber:client" #define NS_SERVER "jabber:server" @@ -44,8 +44,7 @@ #define NS_COMPRESS_PROTOCOL "http://jabber.org/protocol/compress" #define NS_HOSTS "http://barracuda.com/xmppextensions/hosts" -namespace XMPP -{ +namespace XMPP { class Version { public: @@ -383,6 +382,6 @@ namespace XMPP void elementSend(const QDomElement &e); void elementRecv(const QDomElement &e); }; -} +} // namespace XMPP -#endif +#endif // PROTOCOL_H diff --git a/src/xmpp/xmpp-core/securestream.cpp b/src/xmpp/xmpp-core/securestream.cpp index f1934d37..74cf9238 100644 --- a/src/xmpp/xmpp-core/securestream.cpp +++ b/src/xmpp/xmpp-core/securestream.cpp @@ -27,14 +27,14 @@ #include "securestream.h" -#include -#include -#include - +#include "compressionhandler.h" #ifdef USE_TLSHANDLER #include "xmpp.h" #endif -#include "compressionhandler.h" + +#include +#include +#include //---------------------------------------------------------------------------- // LayerTracker diff --git a/src/xmpp/xmpp-core/securestream.h b/src/xmpp/xmpp-core/securestream.h index 5607c959..6abc2ca6 100644 --- a/src/xmpp/xmpp-core/securestream.h +++ b/src/xmpp/xmpp-core/securestream.h @@ -20,14 +20,13 @@ #ifndef SECURESTREAM_H #define SECURESTREAM_H -#include #include "bytestream.h" -#define USE_TLSHANDLER +#include +#define USE_TLSHANDLER #ifdef USE_TLSHANDLER -namespace XMPP -{ +namespace XMPP { class TLSHandler; } #endif @@ -83,4 +82,4 @@ private slots: Private *d; }; -#endif +#endif // SECURESTREAM_H diff --git a/src/xmpp/xmpp-core/simplesasl.cpp b/src/xmpp/xmpp-core/simplesasl.cpp index 4480a673..c17930c8 100644 --- a/src/xmpp/xmpp-core/simplesasl.cpp +++ b/src/xmpp/xmpp-core/simplesasl.cpp @@ -19,22 +19,22 @@ #include "simplesasl.h" +#include "xmpp/base/randrandomnumbergenerator.h" +#include "xmpp/sasl/digestmd5response.h" +#include "xmpp/sasl/plainmessage.h" +#include "xmpp/sasl/scramsha1message.h" +#include "xmpp/sasl/scramsha1response.h" +#include "xmpp/sasl/scramsha1signature.h" + +#include +#include +#include #include +#include +#include #include #include -#include -#include -#include #include -#include -#include - -#include "xmpp/sasl/plainmessage.h" -#include "xmpp/sasl/digestmd5response.h" -#include "xmpp/sasl/scramsha1response.h" -#include "xmpp/sasl/scramsha1message.h" -#include "xmpp/sasl/scramsha1signature.h" -#include "xmpp/base/randrandomnumbergenerator.h" namespace XMPP { class SimpleSASLContext : public QCA::SASLContext @@ -460,7 +460,6 @@ QCA::Provider *createProviderSimpleSASL() { return (new QCASimpleSASL); } - -} +} // namespace XMPP #include "simplesasl.moc" diff --git a/src/xmpp/xmpp-core/simplesasl.h b/src/xmpp/xmpp-core/simplesasl.h index c6d1769d..fb880cf0 100644 --- a/src/xmpp/xmpp-core/simplesasl.h +++ b/src/xmpp/xmpp-core/simplesasl.h @@ -24,9 +24,8 @@ namespace QCA { class Provider; } -namespace XMPP -{ +namespace XMPP { QCA::Provider* createProviderSimpleSASL(); } -#endif +#endif // SIMPLESASL_H diff --git a/src/xmpp/xmpp-core/sm.cpp b/src/xmpp/xmpp-core/sm.cpp index 0c508b77..7ed53e3e 100644 --- a/src/xmpp/xmpp-core/sm.cpp +++ b/src/xmpp/xmpp-core/sm.cpp @@ -17,13 +17,12 @@ * */ +#include "sm.h" + #ifdef IRIS_SM_DEBUG #include #endif - -#include "sm.h" - using namespace XMPP; SMState::SMState() @@ -42,7 +41,6 @@ void SMState::resetCounters() send_queue.clear(); } - StreamManagement::StreamManagement(QObject *parent) : QObject(parent) , sm_started(false) diff --git a/src/xmpp/xmpp-core/sm.h b/src/xmpp/xmpp-core/sm.h index e16d3c14..0be89a4f 100644 --- a/src/xmpp/xmpp-core/sm.h +++ b/src/xmpp/xmpp-core/sm.h @@ -20,18 +20,17 @@ #ifndef XMPP_SM_H #define XMPP_SM_H -#include -#include #include #include +#include +#include #define NS_STREAM_MANAGEMENT "urn:xmpp:sm:3" #define SM_TIMER_INTERVAL_SECS 40 //#define IRIS_SM_DEBUG -namespace XMPP -{ +namespace XMPP { class SMState { public: @@ -87,6 +86,6 @@ namespace XMPP bool waiting_answer = false; } sm_timeout_data; }; -} +} // namespace XMPP -#endif //XMPP_SM_H +#endif // XMPP_SM_H diff --git a/src/xmpp/xmpp-core/stream.cpp b/src/xmpp/xmpp-core/stream.cpp index b0c7e49c..5e468d80 100644 --- a/src/xmpp/xmpp-core/stream.cpp +++ b/src/xmpp/xmpp-core/stream.cpp @@ -41,31 +41,26 @@ - sasl anonymous */ -#include "xmpp.h" - -#include -#include -#include -#include -#include -#include -#include -//#include -#include - #include "bytestream.h" -#include "simplesasl.h" -#include "securestream.h" -#include "protocol.h" - #ifndef NO_IRISNET -#include "irisnetglobal_p.h" +# include "irisnetglobal_p.h" #endif - +#include "protocol.h" +#include "securestream.h" +#include "simplesasl.h" #ifdef XMPP_TEST -#include "td.h" +# include "td.h" #endif +#include +#include +#include +#include +#include +#include +#include +//#include +#include //#define XMPP_DEBUG @@ -538,7 +533,6 @@ QString ClientStream::errorText() const return d->errText; } - QHash ClientStream::errorLangText() const { return d->errLangText; @@ -1562,7 +1556,6 @@ QList ClientStream::unhandledFeatures() const return d->client.unhandledFeatures; } - //---------------------------------------------------------------------------- // Debug //---------------------------------------------------------------------------- diff --git a/src/xmpp/xmpp-core/td.h b/src/xmpp/xmpp-core/td.h index f20dbe6c..192dc01b 100644 --- a/src/xmpp/xmpp-core/td.h +++ b/src/xmpp/xmpp-core/td.h @@ -16,5 +16,4 @@ class TD static void incomingXml(const QDomElement &); }; -#endif - +#endif // TESTDEBUG_H diff --git a/src/xmpp/xmpp-core/tlshandler.cpp b/src/xmpp/xmpp-core/tlshandler.cpp index e129e1fa..2a5fe27c 100644 --- a/src/xmpp/xmpp-core/tlshandler.cpp +++ b/src/xmpp/xmpp-core/tlshandler.cpp @@ -17,16 +17,15 @@ * */ +#include "qca.h" #include "xmpp.h" #include -#include "qca.h" +#include using namespace XMPP; - // FIXME: remove this code once qca cert host checking works ... using namespace QCA; -#include // ip address string to binary (msb), adapted from jdns (adapted from qt) // return: size 4 = ipv4, size 16 = ipv6, size 0 = error @@ -312,7 +311,6 @@ TLSHandler::~TLSHandler() { } - //---------------------------------------------------------------------------- // QCATLSHandler //---------------------------------------------------------------------------- @@ -371,7 +369,6 @@ bool QCATLSHandler::certMatchesHostname() return false; } - QCA::TLS *QCATLSHandler::tls() const { return d->tls; diff --git a/src/xmpp/xmpp-core/xmlprotocol.cpp b/src/xmpp/xmpp-core/xmlprotocol.cpp index e3774c23..32e6aa85 100644 --- a/src/xmpp/xmpp-core/xmlprotocol.cpp +++ b/src/xmpp/xmpp-core/xmlprotocol.cpp @@ -17,13 +17,14 @@ * */ -#include -#include -#include - #include "xmlprotocol.h" + #include "bytestream.h" +#include +#include +#include + using namespace XMPP; // stripExtraNS @@ -171,7 +172,6 @@ static inline bool highSurrogate(const quint32 ch) return ch >= 0xD800 && ch <= 0xDBFF; } - // force encoding of '>'. this function is needed for XMPP-Core, which // requires the '>' character to be encoded as ">" even though this is // not required by the XML spec. @@ -243,7 +243,6 @@ static QString sanitizeForStream(const QString &in) return out; } - //---------------------------------------------------------------------------- // Protocol //---------------------------------------------------------------------------- diff --git a/src/xmpp/xmpp-core/xmlprotocol.h b/src/xmpp/xmpp-core/xmlprotocol.h index cc63e707..2f02a75a 100644 --- a/src/xmpp/xmpp-core/xmlprotocol.h +++ b/src/xmpp/xmpp-core/xmlprotocol.h @@ -20,15 +20,15 @@ #ifndef XMLPROTOCOL_H #define XMLPROTOCOL_H -#include +#include "parser.h" + #include #include -#include "parser.h" +#include #define NS_XML "http://www.w3.org/XML/1998/namespace" -namespace XMPP -{ +namespace XMPP { class XmlProtocol : public QObject { public: @@ -147,6 +147,6 @@ namespace XMPP void sendTagClose(); bool baseStep(const Parser::Event &pe); }; -} +} // namespace XMPP -#endif +#endif // XMLPROTOCOL_H diff --git a/src/xmpp/xmpp-core/xmpp.h b/src/xmpp/xmpp-core/xmpp.h index 76443b05..2bb59c63 100644 --- a/src/xmpp/xmpp-core/xmpp.h +++ b/src/xmpp/xmpp-core/xmpp.h @@ -20,33 +20,29 @@ #ifndef XMPP_H #define XMPP_H -#include -#include -#include -#include -#include -#include -#include - #include "addressresolver.h" #include "xmpp/jid/jid.h" +#include "xmpp_clientstream.h" #include "xmpp_stanza.h" #include "xmpp_stream.h" -#include "xmpp_clientstream.h" -namespace QCA -{ - class TLS; -}; +#include +#include +#include +#include +#include +#include +#include // For QCA::SASL::Params #ifndef CS_XMPP -class ByteStream; + class ByteStream; #endif -#include // For QCA::SASL::Params +namespace QCA { + class TLS; +}; -namespace XMPP -{ +namespace XMPP { // CS_IMPORT_BEGIN cutestuff/bytestream.h #ifdef CS_XMPP class ByteStream; @@ -232,6 +228,6 @@ namespace XMPP class Private; Private *d; }; -}; +}; // namespace XMPP -#endif +#endif // XMPP_H diff --git a/src/xmpp/xmpp-core/xmpp_clientstream.h b/src/xmpp/xmpp-core/xmpp_clientstream.h index d33bf834..f06d1e39 100644 --- a/src/xmpp/xmpp-core/xmpp_clientstream.h +++ b/src/xmpp/xmpp-core/xmpp_clientstream.h @@ -19,23 +19,22 @@ #ifndef XMPP_CLIENTSTREAM_H #define XMPP_CLIENTSTREAM_H -#include - #include "xmpp_stream.h" +#include + +class ByteStream; class QByteArray; -class QString; class QDomDocument; class QDomElement; -class QObject; -class ByteStream; class QHostAddress; +class QObject; +class QString; -namespace XMPP -{ - class TLSHandler; +namespace XMPP { class Connector; class StreamFeatures; + class TLSHandler; class ClientStream : public Stream { @@ -226,6 +225,6 @@ namespace XMPP void srvProcessNext(); void setTimer(int secs); }; -} +} // namespace XMPP -#endif +#endif // XMPP_CLIENTSTREAM_H diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index 25fe145c..6dfea235 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -18,16 +18,16 @@ #include "xmpp_stanza.h" -#include #include "xmpp/jid/jid.h" -#include "xmpp_stream.h" #include "xmpp_clientstream.h" +#include "xmpp_stream.h" +#include #include using namespace XMPP; -#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" +#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" #define NS_XML "http://www.w3.org/XML/1998/namespace" //---------------------------------------------------------------------------- @@ -91,7 +91,6 @@ void Stanza::Error::reset() originalCode = 0; } - class Stanza::Error::Private { public: @@ -125,7 +124,6 @@ class Stanza::Error::Private }; static ErrorDescEntry errorDescriptions[]; - static int stringToErrorType(const QString &s) { for(int n = 0; errorTypeTable[n].str; ++n) { @@ -676,4 +674,3 @@ QSharedPointer Stanza::unboundDocument(QSharedPointersharedDoc = sd; return d->sharedDoc; } - diff --git a/src/xmpp/xmpp-core/xmpp_stanza.h b/src/xmpp/xmpp-core/xmpp_stanza.h index f9be5d62..c2fd7ae4 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.h +++ b/src/xmpp/xmpp-core/xmpp_stanza.h @@ -19,15 +19,14 @@ #ifndef XMPP_STANZA_H #define XMPP_STANZA_H -#include -#include #include +#include #include +#include class QDomDocument; -namespace XMPP -{ +namespace XMPP { class Jid; class Stream; @@ -139,6 +138,6 @@ namespace XMPP class Private; Private *d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_STANZA_H diff --git a/src/xmpp/xmpp-core/xmpp_stream.h b/src/xmpp/xmpp-core/xmpp_stream.h index 06dd3ae3..cb0d4cdb 100644 --- a/src/xmpp/xmpp-core/xmpp_stream.h +++ b/src/xmpp/xmpp-core/xmpp_stream.h @@ -20,16 +20,15 @@ #ifndef XMPP_STREAM_H #define XMPP_STREAM_H +#include "xmpp/jid/jid.h" +#include "xmpp_stanza.h" + #include #include -#include "xmpp_stanza.h" -#include "xmpp/jid/jid.h" - class QDomDocument; -namespace XMPP -{ +namespace XMPP { class Stream : public QObject { Q_OBJECT @@ -79,6 +78,6 @@ namespace XMPP void stanzaWritten(); void error(int); }; -} +} // namespace XMPP -#endif +#endif // XMPP_STREAM_H diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index f4ecc8c4..681645f8 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -65,38 +65,35 @@ //! } //! \endcode -#include -#include -#include -#include -#include - +#include "filetransfer.h" +#include "httpfileupload.h" #include "im.h" -#include "xmpp_tasks.h" -#include "xmpp_xmlcommon.h" +#include "jingle-ft.h" +#include "jingle-ibb.h" +#include "jingle-s5b.h" +#include "jingle.h" +#include "protocol.h" #include "s5b.h" -#include "xmpp_ibb.h" +#include "tcpportreserver.h" #include "xmpp_bitsofbinary.h" -#include "filetransfer.h" #include "xmpp_caps.h" #include "xmpp_hash.h" +#include "xmpp_ibb.h" #include "xmpp_serverinfomanager.h" -#include "protocol.h" -#include "xmpp_serverinfomanager.h" -#include "httpfileupload.h" -#include "jingle.h" -#include "jingle-ft.h" -#include "jingle-s5b.h" -#include "tcpportreserver.h" -#include "jingle-ibb.h" +#include "xmpp_tasks.h" +#include "xmpp_xmlcommon.h" + +#include +#include +#include +#include +#include #ifdef Q_OS_WIN #define vsnprintf _vsnprintf #endif -namespace XMPP -{ - +namespace XMPP { //---------------------------------------------------------------------------- // Client //---------------------------------------------------------------------------- @@ -148,7 +145,6 @@ class Client::ClientPrivate EncryptionHandler *encryptionHandler = nullptr; }; - Client::Client(QObject *par) :QObject(par) { @@ -519,7 +515,7 @@ void Client::streamError(int) disconnected(); cleanup(); //} -} +} // namespace XMPP /*void Client::streamSSLCertificateReady(const QSSLCert &cert) { diff --git a/src/xmpp/xmpp-im/filetransfer.cpp b/src/xmpp/xmpp-im/filetransfer.cpp index 1290b9d3..2a66c8b1 100644 --- a/src/xmpp/xmpp-im/filetransfer.cpp +++ b/src/xmpp/xmpp-im/filetransfer.cpp @@ -19,14 +19,15 @@ #include "filetransfer.h" +#include "s5b.h" +#include "xmpp_ibb.h" +#include "xmpp_xmlcommon.h" + +#include #include -#include #include -#include #include -#include "xmpp_xmlcommon.h" -#include "s5b.h" -#include "xmpp_ibb.h" +#include #define SENDBUFSIZE 65536 diff --git a/src/xmpp/xmpp-im/filetransfer.h b/src/xmpp/xmpp-im/filetransfer.h index 8d436089..9f2de709 100644 --- a/src/xmpp/xmpp-im/filetransfer.h +++ b/src/xmpp/xmpp-im/filetransfer.h @@ -22,9 +22,7 @@ #include "im.h" -namespace XMPP -{ - //class BSConnection; +namespace XMPP { class BSConnection; class BytestreamManager; struct FTRequest; @@ -186,6 +184,6 @@ namespace XMPP signals: void incoming(const FTRequest &req); }; -} +} // namespace XMPP -#endif +#endif // XMPP_FILETRANSFER_H diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 89695f63..2bf96890 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -17,17 +17,18 @@ * */ +#include "httpfileupload.h" + +#include "xmpp_serverinfomanager.h" +#include "xmpp_tasks.h" +#include "xmpp_xmlcommon.h" + #include #include #include #include #include -#include "httpfileupload.h" -#include "xmpp_tasks.h" -#include "xmpp_xmlcommon.h" -#include "xmpp_serverinfomanager.h" - using namespace XMPP; static QLatin1String xmlns_v0_2_5("urn:xmpp:http:upload"); @@ -437,7 +438,6 @@ bool JT_HTTPFileUpload::take(const QDomElement &e) return true; } - class HttpFileUploadManager::Private { public: Client *client = nullptr; @@ -448,8 +448,6 @@ class HttpFileUploadManager::Private { QLinkedList hosts; }; - - HttpFileUploadManager::HttpFileUploadManager(Client *parent) : QObject(parent), d(new Private) diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index 5d3b78da..3d923bba 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -20,21 +20,19 @@ #ifndef XMPP_HTTPFILEUPLOAD_H #define XMPP_HTTPFILEUPLOAD_H -#include +#include "im.h" + #include +#include class QNetworkAccessManager; -#include "im.h" - -namespace XMPP -{ - -namespace XEP0363 { -enum version { vUnknown, v0_2_5, v0_3_1 }; -struct HttpHeader { QString name; QString value; }; -typedef QList HttpHeaders; -} +namespace XMPP { + namespace XEP0363 { + enum version { vUnknown, v0_2_5, v0_3_1 }; + struct HttpHeader { QString name; QString value; }; + typedef QList HttpHeaders; + } class HttpFileUpload : public QObject { @@ -202,7 +200,6 @@ class HttpFileUploadManager : public QObject class Private; Private *d; }; +} // namespace XMPP -} - -#endif +#endif // XMPP_HTTPFILEUPLOAD_H diff --git a/src/xmpp/xmpp-im/im.h b/src/xmpp/xmpp-im/im.h index 78d336c8..2842e30a 100644 --- a/src/xmpp/xmpp-im/im.h +++ b/src/xmpp/xmpp-im/im.h @@ -20,40 +20,38 @@ #ifndef XMPP_IM_H #define XMPP_IM_H -#include -//Added by qt3to4: -#include - #include "xmpp.h" #include "xmpp/jid/jid.h" -#include "xmpp_muc.h" -#include "xmpp_message.h" +#include "xmpp_address.h" +#include "xmpp_agentitem.h" #include "xmpp_chatstate.h" -#include "xmpp_status.h" -#include "xmpp_htmlelement.h" +#include "xmpp_client.h" +#include "xmpp_discoitem.h" #include "xmpp_features.h" +#include "xmpp_hash.h" +#include "xmpp_htmlelement.h" #include "xmpp_httpauthrequest.h" -#include "xmpp_url.h" -#include "xmpp_task.h" +#include "xmpp_liveroster.h" +#include "xmpp_liverosteritem.h" +#include "xmpp_message.h" +#include "xmpp_muc.h" +#include "xmpp_pubsubitem.h" +#include "xmpp_pubsubretraction.h" #include "xmpp_resource.h" #include "xmpp_resourcelist.h" #include "xmpp_roster.h" #include "xmpp_rosteritem.h" -#include "xmpp_liverosteritem.h" -#include "xmpp_liveroster.h" #include "xmpp_rosterx.h" -#include "xmpp_xdata.h" -#include "xmpp_discoitem.h" -#include "xmpp_agentitem.h" -#include "xmpp_client.h" -#include "xmpp_address.h" -#include "xmpp_hash.h" +#include "xmpp_status.h" +#include "xmpp_task.h" #include "xmpp_thumbs.h" -#include "xmpp_pubsubitem.h" -#include "xmpp_pubsubretraction.h" +#include "xmpp_url.h" +#include "xmpp_xdata.h" + +#include +#include -namespace XMPP -{ +namespace XMPP { typedef QList AgentList; typedef QList DiscoList; @@ -127,6 +125,6 @@ namespace XMPP Jid v_jid; QString v_nick, v_first, v_last, v_email; }; -} +} // namespace XMPP -#endif +#endif // XMPP_IM_H diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 54059868..60c2ef2b 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -18,9 +18,10 @@ */ #include "jingle-ft.h" + #include "xmpp_client.h" -#include "xmpp_thumbs.h" #include "xmpp_hash.h" +#include "xmpp_thumbs.h" #include "xmpp_xmlcommon.h" #include @@ -28,9 +29,7 @@ namespace XMPP { namespace Jingle { - namespace FileTransfer { - const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); const QString HISTOGRAM_NS = QStringLiteral("urn:audio:histogram"); @@ -1123,9 +1122,6 @@ void Pad::addOutgoingOffer(const File &file) auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); app->setFile(file); } - - - } // namespace FileTransfer } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index a905bc66..4e9ac92c 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -24,7 +24,6 @@ #include "xmpp_hash.h" namespace XMPP { - class Client; class Thumbnail; @@ -211,7 +210,6 @@ class Manager : public XMPP::Jingle::ApplicationManager private: XMPP::Jingle::Manager *jingleManager = nullptr; }; - } // namespace FileTransfer } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 3383938d..8721ad43 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -18,6 +18,7 @@ */ #include "jingle-ibb.h" + #include "xmpp/jid/jid.h" #include "xmpp_client.h" #include "xmpp_ibb.h" @@ -27,7 +28,6 @@ namespace XMPP { namespace Jingle { namespace IBB { - const QString NS(QStringLiteral("urn:xmpp:jingle:transports:ibb:1")); class Connection : public XMPP::Jingle::Connection @@ -307,7 +307,6 @@ bool Transport::update(const QDomElement &transportEl) return true; } - bool Transport::isInitialOfferReady() const { return isValid() && (hasUpdates() || d->initialOfferSent); @@ -478,7 +477,6 @@ bool Manager::handleIncoming(IBBConnection *c) } return false; } - } // namespace IBB } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index 9768edb7..acfd516c 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -27,7 +27,6 @@ namespace XMPP { namespace Jingle { namespace IBB { - extern const QString NS; class Transport : public XMPP::Jingle::Transport @@ -98,7 +97,6 @@ class Manager : public TransportManager { class Private; QScopedPointer d; }; - } // namespace IBB } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index e8a72f02..c0e394e6 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -16,13 +16,15 @@ * along with this library. If not, see . * */ + #include "jingle-s5b.h" + +#include "ice176.h" #include "s5b.h" +#include "socks.h" #include "xmpp/jid/jid.h" #include "xmpp_client.h" #include "xmpp_serverinfomanager.h" -#include "socks.h" -#include "ice176.h" #include #include @@ -31,7 +33,6 @@ namespace XMPP { namespace Jingle { namespace S5B { - const QString NS(QStringLiteral("urn:xmpp:jingle:transports:s5b:1")); static QString makeKey(const QString &sid, const Jid &j1, const Jid &j2) @@ -115,8 +116,6 @@ class Connection : public XMPP::Jingle::Connection return 0; } - - private: friend class Transport; void enqueueIncomingUDP(const QByteArray &data) @@ -600,7 +599,6 @@ class Transport::Private quint16 udpPort; QHostAddress udpAddress; - inline Jid remoteJid() const { return pad->session()->peer(); @@ -1316,7 +1314,6 @@ bool Transport::update(const QDomElement &transportEl) return true; } - bool Transport::isInitialOfferReady() const { return isValid() && (d->pendingActions || d->offerSent || @@ -1650,10 +1647,8 @@ void Pad::registerSid(const QString &sid) { return _manager->registerSid(_session->peer(), sid); } - } // namespace S5B } // namespace Jingle } // namespace XMPP #include "jingle-s5b.moc" - diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index cd277c0d..dffed154 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -27,15 +27,14 @@ class QHostAddress; class SocksClient; namespace XMPP { - class Client; namespace Jingle { namespace S5B { - extern const QString NS; class Transport; + class Candidate { public: enum Type { @@ -216,7 +215,6 @@ class Manager : public TransportManager { class Private; QScopedPointer d; }; - } // namespace S5B } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index 128643f3..e1b48aff 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -18,30 +18,27 @@ */ #include "jingle.h" -#include "xmpp_xmlcommon.h" -#include "xmpp/jid/jid.h" + #include "xmpp-im/xmpp_hash.h" +#include "xmpp/jid/jid.h" #include "xmpp_client.h" -#include "xmpp_task.h" #include "xmpp_stream.h" +#include "xmpp_task.h" +#include "xmpp_xmlcommon.h" #include +#include #include #include -#include #include #include #include -#include -#include namespace XMPP { namespace Jingle { - const QString NS(QStringLiteral("urn:xmpp:jingle:1")); const QString ERROR_NS(QStringLiteral("urn:xmpp:jingle:errors:1")); - //---------------------------------------------------------------------------- // Jingle //---------------------------------------------------------------------------- @@ -95,7 +92,6 @@ Jingle::Jingle(const QDomElement &e) Jid initiator; Jid responder; - bool found = false; for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { if (actionStr == jingleActions[i].text) { @@ -201,7 +197,6 @@ void Jingle::setResponder(const Jid &jid) d->responder = jid; } - //---------------------------------------------------------------------------- // Reason //---------------------------------------------------------------------------- @@ -394,7 +389,6 @@ QDomElement ContentBase::toXml(QDomDocument *doc, const char *tagName) const return el; } - Origin ContentBase::creatorAttr(const QDomElement &el) { auto creatorStr = el.attribute(QLatin1String("creator")); @@ -458,7 +452,6 @@ class JTPush : public Task inline void forgetExternalSession(const QString &sid) { externalSessions.removeOne(sid); } inline void registerExternalSession(const QString &sid) { externalSessions.append(sid); } - bool take(const QDomElement &iq) { if (iq.tagName() != QLatin1String("iq") || iq.attribute(QLatin1String("type")) != QLatin1String("set")) { @@ -620,7 +613,6 @@ class JT : public Task } }; - //---------------------------------------------------------------------------- // Session //---------------------------------------------------------------------------- @@ -943,7 +935,6 @@ class Session::Private return result{Unparsed, Reason::Success, nullptr}; } - typedef std::tuple, QList> ParseContentListResult; ParseContentListResult parseContentAddList(const QDomElement &jingleEl) @@ -1115,7 +1106,6 @@ class Session::Private return std::tuple>(true, acceptSet.values()); } - bool handleIncomingContentAdd(const QDomElement &jingleEl) { Private::AddContentError err; @@ -1637,7 +1627,6 @@ bool Session::updateFromXml(Action action, const QDomElement &jingleEl) return false; } - //---------------------------------------------------------------------------- // SessionManagerPad - handle event related to a type of app/transport but not specific instance //---------------------------------------------------------------------------- @@ -1931,7 +1920,6 @@ Stanza::Error ErrorUtil::makeOutOfOrder(QDomDocument &doc) return make(doc, OutOfOrder, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); } - } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 8765cea1..6d166a81 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -21,6 +21,7 @@ #define JINGLE_H #include "bytestream.h" +#include "xmpp_stanza.h" #include #include @@ -31,16 +32,13 @@ # include #endif -#include "xmpp_stanza.h" - -class QDomElement; class QDomDocument; +class QDomElement; namespace XMPP { class Client; namespace Jingle { - extern const QString NS; class Manager; @@ -349,7 +347,6 @@ class Transport : public QObject { }; Q_DECLARE_FLAGS(Features, Feature) - using QObject::QObject; enum Direction { // incoming or outgoing file/data transfer. diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index 596c7f8b..d100d97c 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -19,18 +19,17 @@ #include "s5b.h" -#include -#include -#include -#include -#include - -#include "xmpp_xmlcommon.h" #include "im.h" #include "jingle-s5b.h" #include "socks.h" #include "tcpportreserver.h" +#include "xmpp_xmlcommon.h" +#include +#include +#include +#include +#include #ifdef Q_OS_WIN # include #else @@ -42,7 +41,6 @@ static const char *S5B_NS = "http://jabber.org/protocol/bytestreams"; namespace XMPP { - static QString makeKey(const QString &sid, const Jid &requester, const Jid &target) { #ifdef S5B_DEBUG @@ -63,7 +61,6 @@ static bool haveHost(const StreamHostList &list, const Jid &j) return false; } - class S5BManager::Item : public QObject { Q_OBJECT @@ -1955,7 +1952,6 @@ void S5BConnector::man_udpSuccess(const Jid &streamHost) } } - //---------------------------------------------------------------------------- // JT_S5B //---------------------------------------------------------------------------- @@ -2453,7 +2449,6 @@ void S5BServer::unregisterKey(const QString &key) { d->keys.remove(key); } - -} +} // namespace XMPP #include "s5b.moc" diff --git a/src/xmpp/xmpp-im/s5b.h b/src/xmpp/xmpp-im/s5b.h index 951076f8..86cd2d4a 100644 --- a/src/xmpp/xmpp-im/s5b.h +++ b/src/xmpp/xmpp-im/s5b.h @@ -20,34 +20,33 @@ #ifndef XMPP_S5B_H #define XMPP_S5B_H -#include -#include -#include -#include - #include "bytestream.h" -#include "xmpp_bytestream.h" #include "xmpp/jid/jid.h" -#include "xmpp_task.h" +#include "xmpp_bytestream.h" #include "xmpp_stanza.h" +#include "xmpp_task.h" + +#include +#include +#include +#include class SocksClient; class SocksUDP; -namespace XMPP -{ +namespace XMPP { namespace Jingle { namespace S5B { class Manager; } } - class StreamHost; class Client; - class TcpPortReserver; + class JT_PushS5B; class S5BConnection; class S5BManager; - class JT_PushS5B; + class StreamHost; + class TcpPortReserver; struct S5BRequest; typedef QList StreamHostList; typedef QList S5BConnectionList; @@ -239,7 +238,6 @@ namespace XMPP void man_udpSuccess(const Jid &streamHost); }; - class S5BServersProducer : public TcpPortScope { protected: @@ -347,6 +345,6 @@ namespace XMPP int v_port; bool proxy; }; -} +} // namespace XMPP -#endif +#endif // XMPP_S5B_H diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index b13863ca..d68a46cd 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -17,24 +17,22 @@ * */ -#include -#include - #include "im.h" -#include "xmpp_features.h" -#include "xmpp_xmlcommon.h" -#include "xmpp_bitsofbinary.h" -#include "xmpp_ibb.h" -#include "xmpp_reference.h" -#include "xmpp_captcha.h" #include "protocol.h" #include "xmpp/blake2/blake2qt.h" +#include "xmpp_bitsofbinary.h" +#include "xmpp_captcha.h" +#include "xmpp_features.h" +#include "xmpp_ibb.h" #include "xmpp_reference.h" -#define NS_XML "http://www.w3.org/XML/1998/namespace" +#include "xmpp_xmlcommon.h" -namespace XMPP -{ +#include +#include + +#define NS_XML "http://www.w3.org/XML/1998/namespace" +namespace XMPP { QString HASH_NS = QStringLiteral("urn:xmpp:hashes:2"); //---------------------------------------------------------------------------- // Url @@ -312,7 +310,6 @@ void Address::setType(Type type) v_type = type; } - //---------------------------------------------------------------------------- // Hash //---------------------------------------------------------------------------- @@ -330,7 +327,6 @@ static const struct { { "blake2b-512", Hash::Type::Blake2b512 } }; - Hash::Hash(const QDomElement &el) { QString algo = el.attribute(QLatin1String("algo")); @@ -515,7 +511,6 @@ void RosterExchangeItem::fromXml(const QDomElement& e) } } - //---------------------------------------------------------------------------- // MUCItem //---------------------------------------------------------------------------- @@ -1022,7 +1017,6 @@ void HTMLElement::filterOutUnwantedRecursive(QDomElement &el, bool strict) } } - //---------------------------------------------------------------------------- // Message //---------------------------------------------------------------------------- @@ -2524,7 +2518,6 @@ bool Subscription::fromString(const QString &s) return true; } - //--------------------------------------------------------------------------- // Status //--------------------------------------------------------------------------- @@ -2536,7 +2529,6 @@ CapsSpec::CapsSpec() : { } - /** * \brief Basic constructor. * @param node the node @@ -2564,7 +2556,6 @@ bool CapsSpec::isValid() const return !node_.isEmpty() && !ver_.isEmpty() && (hashAlgo_ != CapsSpec::invalidAlgo); } - /** * \brief Returns the node of the capabilities specification. */ @@ -2573,7 +2564,6 @@ const QString& CapsSpec::node() const return node_; } - /** * \brief Returns the version of the capabilities specification. */ @@ -2674,7 +2664,6 @@ bool CapsSpec::operator<(const CapsSpec& s) const hashAlgorithm() < s.hashAlgorithm())); } - class StatusPrivate : public QSharedData { public: @@ -2711,7 +2700,6 @@ class StatusPrivate : public QSharedData QString estr; }; - Status::Status(const QString &show, const QString &status, int priority, bool available) : d(new StatusPrivate) { @@ -2877,7 +2865,6 @@ void Status::setMUCHistory(int maxchars, int maxstanzas, int seconds, const QDat d->mucHistorySince = since; } - const QString& Status::photoHash() const { return d->photoHash; @@ -3077,7 +3064,6 @@ const QString & Status::errorString() const return d->estr; } - //--------------------------------------------------------------------------- // Resource //--------------------------------------------------------------------------- @@ -3112,7 +3098,6 @@ void Resource::setStatus(const Status & _status) v_status = _status; } - //--------------------------------------------------------------------------- // ResourceList //--------------------------------------------------------------------------- @@ -3169,7 +3154,6 @@ ResourceList::ConstIterator ResourceList::priority() const return highest; } - //--------------------------------------------------------------------------- // RosterItem //--------------------------------------------------------------------------- @@ -3331,7 +3315,6 @@ bool RosterItem::fromXml(const QDomElement &item) return true; } - //--------------------------------------------------------------------------- // Roster //--------------------------------------------------------------------------- @@ -3364,7 +3347,6 @@ Roster::ConstIterator Roster::find(const Jid &j) const return end(); } - //--------------------------------------------------------------------------- // FormField //--------------------------------------------------------------------------- @@ -3488,7 +3470,6 @@ QString FormField::typeToTagName(int type) const }; } - //--------------------------------------------------------------------------- // Form //--------------------------------------------------------------------------- @@ -3531,7 +3512,6 @@ void Form::setKey(const QString &s) v_key = s; } - //--------------------------------------------------------------------------- // SearchResult //--------------------------------------------------------------------------- @@ -3612,7 +3592,6 @@ const QDomElement& PubSubItem::payload() const return payload_; } - PubSubRetraction::PubSubRetraction() { } @@ -3626,8 +3605,6 @@ const QString& PubSubRetraction::id() const return id_; } - - // ========================================= // CaptchaChallenge // ========================================= @@ -3759,5 +3736,4 @@ QDomElement Thumbnail::toXml(QDomDocument *doc) const } return el; } - -} +} // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_address.h b/src/xmpp/xmpp-im/xmpp_address.h index 8af4bab4..108c6614 100644 --- a/src/xmpp/xmpp-im/xmpp_address.h +++ b/src/xmpp/xmpp-im/xmpp_address.h @@ -19,14 +19,13 @@ #ifndef XMPP_ADDRESS_H #define XMPP_ADDRESS_H -#include - #include "xmpp/jid/jid.h" +#include + class QDomElement; -namespace XMPP -{ +namespace XMPP { class Address { public: @@ -60,6 +59,6 @@ namespace XMPP }; typedef QList
AddressList; -} +} // namespace XMPP -#endif +#endif // XMPP_ADDRESS_H diff --git a/src/xmpp/xmpp-im/xmpp_agentitem.h b/src/xmpp/xmpp-im/xmpp_agentitem.h index 85107c13..f9570424 100644 --- a/src/xmpp/xmpp-im/xmpp_agentitem.h +++ b/src/xmpp/xmpp-im/xmpp_agentitem.h @@ -20,11 +20,11 @@ #ifndef XMPP_AGENTITEM #define XMPP_AGENTITEM -#include - #include "xmpp/jid/jid.h" #include "xmpp_features.h" +#include + namespace XMPP { class AgentItem { @@ -48,7 +48,6 @@ namespace XMPP { QString v_name, v_category, v_type; Features v_features; }; -} - -#endif +} // namespace XMPP +#endif // XMPP_AGENTITEM diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index f3db19b7..688d2e94 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Rion + * Copyright (C) 2010 Sergey Ilinykh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -16,13 +16,14 @@ * */ -#include -#include - #include "xmpp_bitsofbinary.h" -#include "xmpp_xmlcommon.h" + #include "xmpp_client.h" #include "xmpp_tasks.h" +#include "xmpp_xmlcommon.h" + +#include +#include using namespace XMPP; @@ -129,8 +130,6 @@ QDomElement BoBData::toXml(QDomDocument *doc) const return data; } - - // --------------------------------------------------------- // BoBCache // --------------------------------------------------------- @@ -140,7 +139,6 @@ BoBCache::BoBCache(QObject *parent) } - //------------------------------------------------------------------------------ // BoBManager //------------------------------------------------------------------------------ diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h index 0399730e..7a856478 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Rion + * Copyright (C) 2010 Sergey Ilinykh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -19,18 +19,17 @@ #ifndef XMPP_BITSOFBINARY_H #define XMPP_BITSOFBINARY_H +#include "xmpp/jid/jid.h" + #include -#include +#include #include +#include #include -#include - -#include "xmpp/jid/jid.h" -namespace XMPP -{ - class JT_BitsOfBinary; +namespace XMPP { class Client; + class JT_BitsOfBinary; class BoBData { @@ -63,8 +62,6 @@ namespace XMPP QSharedDataPointer d; }; - - class BoBCache : public QObject { Q_OBJECT @@ -75,8 +72,6 @@ namespace XMPP virtual BoBData get(const QString &) = 0; }; - - class BoBManager : public QObject { Q_OBJECT @@ -97,7 +92,6 @@ namespace XMPP BoBCache *_cache; QHash > _localFiles; //cid => (filename, mime) }; - -} +} // namespace XMPP #endif // XMPP_BITSOFBINARY_H diff --git a/src/xmpp/xmpp-im/xmpp_bytestream.cpp b/src/xmpp/xmpp-im/xmpp_bytestream.cpp index 92dac0d8..71863929 100644 --- a/src/xmpp/xmpp-im/xmpp_bytestream.cpp +++ b/src/xmpp/xmpp-im/xmpp_bytestream.cpp @@ -1,6 +1,6 @@ /* * bytestream_manager.cpp - base class for bytestreams over xmpp - * Copyright (C) 2003 Justin Karneges, Rion + * Copyright (C) 2003 Justin Karneges, Sergey Ilinykh * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,14 +17,13 @@ * */ -#include - #include "xmpp_bytestream.h" + #include "xmpp_client.h" -namespace XMPP -{ +#include +namespace XMPP { BytestreamManager::BytestreamManager(Client *parent) : QObject(parent) { @@ -59,5 +58,4 @@ void BytestreamManager::deleteConnection(BSConnection *c, int msec) delete c; } } - -} +} // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_bytestream.h b/src/xmpp/xmpp-im/xmpp_bytestream.h index 9f3a88b6..5933ff2e 100644 --- a/src/xmpp/xmpp-im/xmpp_bytestream.h +++ b/src/xmpp/xmpp-im/xmpp_bytestream.h @@ -1,6 +1,6 @@ /* * bytestream_manager.h - base class for bytestreams over xmpp - * Copyright (C) 2003 Justin Karneges, Rion + * Copyright (C) 2003 Justin Karneges, Sergey Ilinykh * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,14 +20,14 @@ #ifndef BYTESTREAM_MANAGER_H #define BYTESTREAM_MANAGER_H -#include -#include "xmpp/jid/jid.h" #include "bytestream.h" +#include "xmpp/jid/jid.h" -namespace XMPP -{ - class Client; +#include + +namespace XMPP { class BytestreamManager; + class Client; class BSConnection : public ByteStream { @@ -64,6 +64,6 @@ namespace XMPP signals: void incomingReady(); }; -} +} // namespace XMPP -#endif +#endif // BYTESTREAM_MANAGER_H diff --git a/src/xmpp/xmpp-im/xmpp_caps.cpp b/src/xmpp/xmpp-im/xmpp_caps.cpp index 324aea3b..2637bd84 100644 --- a/src/xmpp/xmpp-im/xmpp_caps.cpp +++ b/src/xmpp/xmpp-im/xmpp_caps.cpp @@ -1,6 +1,6 @@ /* * capsregistry.cpp - * Copyright (C) 2006-2016 Remko Troncon, Rion + * Copyright (C) 2006-2016 Remko Troncon, Sergey Ilinykh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -24,21 +24,20 @@ * goes to CapsSpec. */ -#include -#include -#include -#include -#include - -#include "xmpp_features.h" #include "xmpp_caps.h" -#include "xmpp_discoinfotask.h" + #include "xmpp_client.h" +#include "xmpp_discoinfotask.h" +#include "xmpp_features.h" #include "xmpp_xmlcommon.h" -namespace XMPP { - +#include +#include +#include +#include +#include +namespace XMPP { QDomElement CapsInfo::toXml(QDomDocument *doc) const { QDomElement caps = doc->createElement("info"); @@ -57,7 +56,6 @@ CapsInfo CapsInfo::fromXml(const QDomElement &caps) return CapsInfo(item, lastSeen); } - // ----------------------------------------------------------------------------- /** @@ -197,7 +195,6 @@ DiscoItem CapsRegistry::disco(const QString &spec) const return ci.disco(); } - /*-------------------------------------------------------------- _____ __ __ / ____| | \/ | @@ -228,7 +225,6 @@ CapsManager::CapsManager(Client *client) : CapsManager::~CapsManager() {} - /** * \brief Checks whether the caps manager is enabled (and does lookups). */ @@ -362,7 +358,6 @@ bool CapsManager::capsEnabled(const Jid& jid) const return capsSpecs_.contains(jid.full()); } - /** * \brief Requests the list of features of a given JID. */ @@ -480,5 +475,4 @@ CapsSpec CapsManager::capsSpec(const Jid &jid) const { return capsSpecs_.value(jid.full()); } - } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_caps.h b/src/xmpp/xmpp-im/xmpp_caps.h index d11a3e7d..929c6f64 100644 --- a/src/xmpp/xmpp-im/xmpp_caps.h +++ b/src/xmpp/xmpp-im/xmpp_caps.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Remko Troncon, Rion + * Copyright (C) 2016 Remko Troncon, Sergey Ilinykh * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,15 +19,13 @@ #ifndef XMPP_CAPS_H #define XMPP_CAPS_H -#include - -#include "xmpp_features.h" #include "xmpp_discoitem.h" +#include "xmpp_features.h" #include "xmpp_status.h" +#include namespace XMPP { - class CapsInfo { public: @@ -46,7 +44,6 @@ class CapsInfo XMPP::DiscoItem _disco; }; - class CapsRegistry : public QObject { Q_OBJECT @@ -77,7 +74,6 @@ public slots: QHash capsInfo_; }; - class CapsManager : public QObject { Q_OBJECT @@ -118,7 +114,6 @@ protected slots: QMap capsSpecs_; QMap > capsJids_; }; - } // namespace XMPP -#endif // CAPS_H +#endif // XMPP_CAPS_H diff --git a/src/xmpp/xmpp-im/xmpp_captcha.h b/src/xmpp/xmpp-im/xmpp_captcha.h index d3d36930..27b76e85 100644 --- a/src/xmpp/xmpp-im/xmpp_captcha.h +++ b/src/xmpp/xmpp-im/xmpp_captcha.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Rion + * Copyright (C) 2016 Sergey Ilinykh * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,17 +19,16 @@ #ifndef XMPP_CAPTCHA_H #define XMPP_CAPTCHA_H -#include - #include "xmpp/jid/jid.h" #include "xmpp_url.h" -namespace XMPP -{ +#include + +namespace XMPP { + class CaptchaChallengePrivate; class Message; class XData; - class CaptchaChallengePrivate; class CaptchaChallenge { public: @@ -68,6 +67,6 @@ namespace XMPP friend class CaptchaChallengePrivate; QSharedDataPointer d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_CAPTCHA_H diff --git a/src/xmpp/xmpp-im/xmpp_chatstate.h b/src/xmpp/xmpp-im/xmpp_chatstate.h index ef4faf94..5596147d 100644 --- a/src/xmpp/xmpp-im/xmpp_chatstate.h +++ b/src/xmpp/xmpp-im/xmpp_chatstate.h @@ -28,6 +28,6 @@ namespace XMPP { StateInactive, StateGone } ChatState; -} +} // namespace XMPP -#endif +#endif // XMPP_CHATSTATE diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index aa995f62..2bd4528e 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -19,23 +19,28 @@ #ifndef XMPP_CLIENT_H #define XMPP_CLIENT_H -#include -#include -#include - #include "xmpp/jid/jid.h" -#include "xmpp_status.h" #include "xmpp_discoitem.h" +#include "xmpp_status.h" + +#include +#include +#include -class QString; -class QDomElement; -class QDomDocument; class ByteStream; +class QDomDocument; +class QDomElement; class QNetworkAccessManager; +class QString; + namespace XMPP { + class BSConnection; + class CapsManager; class ClientStream; + class EncryptionHandler; class Features; class FileTransferManager; + class HttpFileUploadManager; class IBBManager; class JidLinkManager; class LiveRoster; @@ -46,15 +51,10 @@ namespace XMPP { class Roster; class RosterItem; class S5BManager; - class BSConnection; + class ServerInfoManager; class Stream; class Task; - class CapsManager; - class EncryptionHandler; - class ServerInfoManager; - class HttpFileUploadManager; class TcpPortReserver; - namespace Jingle { class Manager; namespace S5B { @@ -66,8 +66,7 @@ namespace XMPP { } } -namespace XMPP -{ +namespace XMPP { class Client : public QObject { Q_OBJECT @@ -230,6 +229,6 @@ namespace XMPP class ClientPrivate; ClientPrivate *d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_CLIENT_H diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp index 24d7f17a..4694152c 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,17 +16,18 @@ * */ -#include -#include -#include +#include "xmpp_discoinfotask.h" -#include "xmpp_task.h" #include "xmpp/jid/jid.h" +#include "xmpp_caps.h" +#include "xmpp_client.h" #include "xmpp_discoitem.h" -#include "xmpp_discoinfotask.h" +#include "xmpp_task.h" #include "xmpp_xmlcommon.h" -#include "xmpp_client.h" -#include "xmpp_caps.h" + +#include +#include +#include using namespace XMPP; @@ -73,7 +74,6 @@ void DiscoInfoTask::get (const Jid &j, const QString &node, DiscoItem::Identity d->ident = ident; } - /** * Original requested jid. * Is here because sometimes the responder does not include this information @@ -157,5 +157,3 @@ bool DiscoInfoTask::take(const QDomElement &x) return true; } - - diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.h b/src/xmpp/xmpp-im/xmpp_discoinfotask.h index 77cafc0e..03aa8885 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.h +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,17 +19,15 @@ #ifndef XMPP_DISCOINFOTASK_H #define XMPP_DISCOINFOTASK_H -#include "xmpp_task.h" #include "xmpp_discoitem.h" +#include "xmpp_task.h" + +class QDomElement; +class QString; namespace XMPP { class Jid; -} -class QString; -class QDomElement; -namespace XMPP -{ class DiscoInfoTask : public Task { Q_OBJECT @@ -57,8 +55,8 @@ namespace XMPP class Private; Private *d; }; - // Deprecated name typedef DiscoInfoTask JT_DiscoInfo; -} -#endif +} // namespace XMPP + +#endif // XMPP_DISCOINFOTASK_H diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.cpp b/src/xmpp/xmpp-im/xmpp_discoitem.cpp index ddb9bdb1..3006c91f 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoitem.cpp @@ -17,10 +17,10 @@ * */ -#include - #include "xmpp_discoitem.h" +#include + using namespace XMPP; class XMPP::DiscoItemPrivate : public QSharedData @@ -343,8 +343,6 @@ QString DiscoItem::action2string(const Action a) return s; } - - bool XMPP::operator<(const DiscoItem::Identity &a, const DiscoItem::Identity &b) { int r = a.category.compare(b.category); diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.h b/src/xmpp/xmpp-im/xmpp_discoitem.h index b2f990ff..051f6833 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.h +++ b/src/xmpp/xmpp-im/xmpp_discoitem.h @@ -20,13 +20,13 @@ #ifndef XMPP_DISCOITEM #define XMPP_DISCOITEM -#include -#include - #include "xmpp/jid/jid.h" +#include "xmpp_agentitem.h" #include "xmpp_features.h" #include "xmpp_xdata.h" -#include "xmpp_agentitem.h" + +#include +#include namespace XMPP { class DiscoItemPrivate; @@ -102,6 +102,6 @@ namespace XMPP { }; bool operator<(const DiscoItem::Identity &a, const DiscoItem::Identity &b); -} +} // namespace XMPP -#endif +#endif // XMPP_DISCOITEM diff --git a/src/xmpp/xmpp-im/xmpp_encryptionhandler.h b/src/xmpp/xmpp-im/xmpp_encryptionhandler.h index 9e106287..89691f34 100644 --- a/src/xmpp/xmpp-im/xmpp_encryptionhandler.h +++ b/src/xmpp/xmpp-im/xmpp_encryptionhandler.h @@ -22,14 +22,13 @@ class QDomElement; -namespace XMPP -{ +namespace XMPP { class EncryptionHandler { public: virtual bool decryptMessageElement(QDomElement &) = 0; virtual bool encryptMessageElement(QDomElement &) = 0; }; -} +} // namespace XMPP #endif //PSI_XMPP_ENCRYPTIONHANDLER_H diff --git a/src/xmpp/xmpp-im/xmpp_features.cpp b/src/xmpp/xmpp-im/xmpp_features.cpp index 11e3eef0..81af7ed8 100644 --- a/src/xmpp/xmpp-im/xmpp_features.cpp +++ b/src/xmpp/xmpp-im/xmpp_features.cpp @@ -17,15 +17,15 @@ * */ -#include -#include -#include -#include - #include "xmpp_features.h" -#include "jingle.h" #include "jingle-ft.h" +#include "jingle.h" + +#include +#include +#include +#include using namespace XMPP; diff --git a/src/xmpp/xmpp-im/xmpp_features.h b/src/xmpp/xmpp-im/xmpp_features.h index d3117675..df628a14 100644 --- a/src/xmpp/xmpp-im/xmpp_features.h +++ b/src/xmpp/xmpp-im/xmpp_features.h @@ -20,13 +20,12 @@ #ifndef XMPP_FEATURES_H #define XMPP_FEATURES_H -#include #include +#include class QString; -namespace XMPP -{ +namespace XMPP { class Features { public: @@ -108,6 +107,6 @@ namespace XMPP private: QSet _list; }; -} +} // namespace XMPP -#endif +#endif // XMPP_FEATURES_H diff --git a/src/xmpp/xmpp-im/xmpp_hash.h b/src/xmpp/xmpp-im/xmpp_hash.h index e61d7ed2..5b2a0852 100644 --- a/src/xmpp/xmpp-im/xmpp_hash.h +++ b/src/xmpp/xmpp-im/xmpp_hash.h @@ -21,13 +21,12 @@ #include "xmpp_stanza.h" -#include #include +#include class QDomElement; -namespace XMPP -{ +namespace XMPP { extern QString HASH_NS; class Features; @@ -67,6 +66,6 @@ namespace XMPP Type v_type = Type::Unknown; QByteArray v_data; }; -} +} // namespace XMPP -#endif +#endif // XMPP_HASH_H diff --git a/src/xmpp/xmpp-im/xmpp_htmlelement.h b/src/xmpp/xmpp-im/xmpp_htmlelement.h index 57ca1d66..4fc42dfb 100644 --- a/src/xmpp/xmpp-im/xmpp_htmlelement.h +++ b/src/xmpp/xmpp-im/xmpp_htmlelement.h @@ -23,8 +23,7 @@ class QString; -namespace XMPP -{ +namespace XMPP { class HTMLElement { public: @@ -43,6 +42,6 @@ namespace XMPP QDomDocument doc_; QDomElement body_; }; -} +} // namespace XMPP -#endif +#endif // XMPP_HTMLELEMENT_H diff --git a/src/xmpp/xmpp-im/xmpp_httpauthrequest.h b/src/xmpp/xmpp-im/xmpp_httpauthrequest.h index 4702dee6..3c9d429a 100644 --- a/src/xmpp/xmpp-im/xmpp_httpauthrequest.h +++ b/src/xmpp/xmpp-im/xmpp_httpauthrequest.h @@ -21,11 +21,10 @@ #include -class QDomElement; class QDomDocument; +class QDomElement; -namespace XMPP -{ +namespace XMPP { class HttpAuthRequest { public: @@ -51,6 +50,6 @@ namespace XMPP QString method_, url_, id_; bool hasId_; }; -} +} // namespace XMPP -#endif +#endif // XMPP_AUTHREQUEST_H diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index 0c716760..067da527 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -1,6 +1,6 @@ /* * ibb.cpp - Inband bytestream - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ #include "xmpp_ibb.h" -#include #include "xmpp_xmlcommon.h" -#include +#include +#include #include #define IBB_PACKET_DELAY 0 @@ -330,8 +330,6 @@ void IBBConnection::trySend() d->j->go(true); } - - //---------------------------------------------------------------------------- // IBBData //---------------------------------------------------------------------------- @@ -493,7 +491,6 @@ void IBBManager::doReject(IBBConnection *c, const QString &id, d->ibb->respondError(c->peer(), id, cond, str); } - //---------------------------------------------------------------------------- // JT_IBB //---------------------------------------------------------------------------- @@ -639,4 +636,3 @@ int JT_IBB::bytesWritten() const { return d->bytesWritten; } - diff --git a/src/xmpp/xmpp-im/xmpp_ibb.h b/src/xmpp/xmpp-im/xmpp_ibb.h index 8784a4f6..e12df7cc 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.h +++ b/src/xmpp/xmpp-im/xmpp_ibb.h @@ -1,6 +1,6 @@ /* * ibb.h - Inband bytestream - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,20 +17,19 @@ * */ -#ifndef JABBER_IBB_H -#define JABBER_IBB_H - -#include -#include -#include +#ifndef XMPP_IBB_H +#define XMPP_IBB_H #include "bytestream.h" -#include "xmpp_bytestream.h" #include "im.h" +#include "xmpp_bytestream.h" #include "xmpp_task.h" -namespace XMPP -{ +#include +#include +#include + +namespace XMPP { class Client; class IBBManager; @@ -176,6 +175,6 @@ namespace XMPP class Private; Private *d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_IBB_H diff --git a/src/xmpp/xmpp-im/xmpp_liveroster.h b/src/xmpp/xmpp-im/xmpp_liveroster.h index a4339b63..5cbfb1a8 100644 --- a/src/xmpp/xmpp-im/xmpp_liveroster.h +++ b/src/xmpp/xmpp-im/xmpp_liveroster.h @@ -19,12 +19,11 @@ #ifndef XMPP_LIVEROSTER_H #define XMPP_LIVEROSTER_H -#include - #include "xmpp_liverosteritem.h" -namespace XMPP -{ +#include + +namespace XMPP { class Jid; class LiveRoster : public QList @@ -37,6 +36,6 @@ namespace XMPP LiveRoster::Iterator find(const Jid &, bool compareRes=true); LiveRoster::ConstIterator find(const Jid &, bool compareRes=true) const; }; -} +} // namespace XMPP -#endif +#endif // XMPP_LIVEROSTER_H diff --git a/src/xmpp/xmpp-im/xmpp_liverosteritem.h b/src/xmpp/xmpp-im/xmpp_liverosteritem.h index 08bfbb44..a9c71091 100644 --- a/src/xmpp/xmpp-im/xmpp_liverosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_liverosteritem.h @@ -19,12 +19,11 @@ #ifndef XMPP_LIVEROSTERITEM_H #define XMPP_LIVEROSTERITEM_H -#include "xmpp_status.h" #include "xmpp_resourcelist.h" #include "xmpp_rosteritem.h" +#include "xmpp_status.h" -namespace XMPP -{ +namespace XMPP { class LiveRosterItem : public RosterItem { public: @@ -53,6 +52,6 @@ namespace XMPP Status v_lastUnavailableStatus; bool v_flagForDelete; }; -} +} // namespace XMPP -#endif +#endif // XMPP_LIVEROSTERITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index f1378c4b..bc0d407b 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -19,29 +19,29 @@ #ifndef XMPP_MESSAGE_H #define XMPP_MESSAGE_H -#include "xmpp_stanza.h" -#include "xmpp_url.h" -#include "xmpp_chatstate.h" -#include "xmpp_receipts.h" #include "xmpp_address.h" -#include "xmpp_rosterx.h" +#include "xmpp_chatstate.h" #include "xmpp_muc.h" +#include "xmpp_receipts.h" #include "xmpp_reference.h" +#include "xmpp_rosterx.h" +#include "xmpp_stanza.h" +#include "xmpp_url.h" #include -class QString; class QDateTime; +class QString; namespace XMPP { + class BoBData; + class HTMLElement; + class HttpAuthRequest; + class IBBData; class Jid; class PubSubItem; class PubSubRetraction; - class HTMLElement; - class HttpAuthRequest; class XData; - class BoBData; - class IBBData; typedef QMap StringMap; @@ -238,9 +238,8 @@ namespace XMPP { class Private; QExplicitlySharedDataPointer d; }; -} +} // namespace XMPP Q_DECLARE_OPERATORS_FOR_FLAGS(XMPP::Message::ProcessingHints) - -#endif +#endif // XMPP_MESSAGE_H diff --git a/src/xmpp/xmpp-im/xmpp_muc.h b/src/xmpp/xmpp-im/xmpp_muc.h index 17b3657e..7b4cfd54 100644 --- a/src/xmpp/xmpp-im/xmpp_muc.h +++ b/src/xmpp/xmpp-im/xmpp_muc.h @@ -20,13 +20,12 @@ #ifndef XMPP_MUC_H #define XMPP_MUC_H +#include "xmpp/jid/jid.h" + #include #include -#include "xmpp/jid/jid.h" - -namespace XMPP -{ +namespace XMPP { class MUCItem { public: @@ -79,7 +78,6 @@ namespace XMPP bool cont() const; void setCont(bool); - void fromXml(const QDomElement&); QDomElement toXml(QDomDocument&) const; bool isNull() const; @@ -131,6 +129,6 @@ namespace XMPP Jid jid_; QString reason_; }; -} +} // namespace XMPP -#endif +#endif // XMPP_MUC_H diff --git a/src/xmpp/xmpp-im/xmpp_pubsubitem.h b/src/xmpp/xmpp-im/xmpp_pubsubitem.h index 2820c36e..3d2a6853 100644 --- a/src/xmpp/xmpp-im/xmpp_pubsubitem.h +++ b/src/xmpp/xmpp-im/xmpp_pubsubitem.h @@ -19,11 +19,10 @@ #ifndef XMPP_PUBSUBITEM_H #define XMPP_PUBSUBITEM_H -#include #include +#include -namespace XMPP -{ +namespace XMPP { class PubSubItem { public: @@ -36,6 +35,6 @@ namespace XMPP QString id_; QDomElement payload_; }; -} +} // namespace XMPP -#endif +#endif // XMPP_PUBSUBITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_pubsubretraction.h b/src/xmpp/xmpp-im/xmpp_pubsubretraction.h index 2ece653e..8a0c463e 100644 --- a/src/xmpp/xmpp-im/xmpp_pubsubretraction.h +++ b/src/xmpp/xmpp-im/xmpp_pubsubretraction.h @@ -19,12 +19,10 @@ #ifndef XMPP_PUBSUBRETRACTION_H #define XMPP_PUBSUBRETRACTION_H -#include #include +#include -namespace XMPP -{ - +namespace XMPP { class PubSubRetraction { public: @@ -35,6 +33,6 @@ namespace XMPP private: QString id_; }; -} +} // namespace XMPP -#endif +#endif // XMPP_PUBSUBRETRACTION_H diff --git a/src/xmpp/xmpp-im/xmpp_receipts.h b/src/xmpp/xmpp-im/xmpp_receipts.h index 8468837b..1554eb72 100644 --- a/src/xmpp/xmpp-im/xmpp_receipts.h +++ b/src/xmpp/xmpp-im/xmpp_receipts.h @@ -26,6 +26,6 @@ namespace XMPP { ReceiptRequest, ReceiptReceived } MessageReceipt; -} +} // namespace XMPP -#endif +#endif // XMPP_RECEIPTS_H diff --git a/src/xmpp/xmpp-im/xmpp_reference.h b/src/xmpp/xmpp-im/xmpp_reference.h index d19b5316..9cf3e5ac 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.h +++ b/src/xmpp/xmpp-im/xmpp_reference.h @@ -20,13 +20,12 @@ #ifndef XMPPREFERENCE_H #define XMPPREFERENCE_H +#include "jingle-ft.h" + #include #include -#include "jingle-ft.h" - -namespace XMPP -{ +namespace XMPP { extern const QString MEDIASHARING_NS; extern const QString REFERENCE_NS; @@ -75,6 +74,6 @@ namespace XMPP class Private; QSharedDataPointer d; }; -} +} // namespace XMPP -#endif +#endif // XMPPREFERENCE_H diff --git a/src/xmpp/xmpp-im/xmpp_resource.h b/src/xmpp/xmpp-im/xmpp_resource.h index 1c9f0b6e..7fd1b6b1 100644 --- a/src/xmpp/xmpp-im/xmpp_resource.h +++ b/src/xmpp/xmpp-im/xmpp_resource.h @@ -19,12 +19,11 @@ #ifndef XMPP_RESOURCE_H #define XMPP_RESOURCE_H -#include - #include "xmpp_status.h" -namespace XMPP -{ +#include + +namespace XMPP { class Resource { public: @@ -41,6 +40,6 @@ namespace XMPP QString v_name; Status v_status; }; -} +} // namespace XMPP -#endif +#endif // XMPP_RESOURCE_H diff --git a/src/xmpp/xmpp-im/xmpp_resourcelist.h b/src/xmpp/xmpp-im/xmpp_resourcelist.h index 75c4c4a3..ae41bad2 100644 --- a/src/xmpp/xmpp-im/xmpp_resourcelist.h +++ b/src/xmpp/xmpp-im/xmpp_resourcelist.h @@ -19,14 +19,13 @@ #ifndef XMPP_RESOURCELIST_H #define XMPP_RESOURCELIST_H -#include - #include "xmpp_resource.h" +#include + class QString; -namespace XMPP -{ +namespace XMPP { class ResourceList : public QList { public: @@ -39,6 +38,6 @@ namespace XMPP ResourceList::ConstIterator find(const QString &) const; ResourceList::ConstIterator priority() const; }; -} +} // namespace XMPP -#endif +#endif // XMPP_RESOURCELIST_H diff --git a/src/xmpp/xmpp-im/xmpp_roster.h b/src/xmpp/xmpp-im/xmpp_roster.h index 2e134686..9572e580 100644 --- a/src/xmpp/xmpp-im/xmpp_roster.h +++ b/src/xmpp/xmpp-im/xmpp_roster.h @@ -19,16 +19,16 @@ #ifndef XMPP_ROSTER_H #define XMPP_ROSTER_H -#include - #include "xmpp_rosteritem.h" +#include + class QDomDocument; class QDomElement; -namespace XMPP -{ +namespace XMPP { class Jid; + class Roster : public QList { public: @@ -42,6 +42,6 @@ namespace XMPP class RosterPrivate; RosterPrivate *d = nullptr; }; -} +} // namespace XMPP -#endif +#endif // XMPP_ROSTER_H diff --git a/src/xmpp/xmpp-im/xmpp_rosteritem.h b/src/xmpp/xmpp-im/xmpp_rosteritem.h index acb31e95..3fe1e486 100644 --- a/src/xmpp/xmpp-im/xmpp_rosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_rosteritem.h @@ -19,13 +19,12 @@ #ifndef XMPP_ROSTERITEM_H #define XMPP_ROSTERITEM_H +#include "xmpp/jid/jid.h" + #include #include -#include "xmpp/jid/jid.h" - -namespace XMPP -{ +namespace XMPP { class Subscription { public: @@ -78,6 +77,6 @@ namespace XMPP QString v_ask; bool v_push; }; -} +} // namespace XMPP -#endif +#endif // XMPP_ROSTERITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_rosterx.h b/src/xmpp/xmpp-im/xmpp_rosterx.h index b4d52d15..70a3f9de 100644 --- a/src/xmpp/xmpp-im/xmpp_rosterx.h +++ b/src/xmpp/xmpp-im/xmpp_rosterx.h @@ -20,15 +20,14 @@ #ifndef XMPP_ROSTERX_H #define XMPP_ROSTERX_H +#include "xmpp/jid/jid.h" + #include #include -#include "xmpp/jid/jid.h" - class QDomElement; -namespace XMPP -{ +namespace XMPP { class Stanza; class RosterExchangeItem @@ -60,6 +59,6 @@ namespace XMPP Action action_; }; typedef QList RosterExchangeItems; -} +} // namespace XMPP -#endif +#endif // XMPP_ROSTERX_H diff --git a/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp b/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp index f942beda..72e5ee83 100644 --- a/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp +++ b/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp @@ -1,6 +1,6 @@ /* * xmpp_serverinfomanager.cpp - * Copyright (C) 2006,2019 Remko Troncon, Sergey Ilinykh + * Copyright (C) 2006-2019 Remko Troncon, Sergey Ilinykh * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,11 +18,11 @@ */ #include "xmpp_serverinfomanager.h" -#include "xmpp_tasks.h" + #include "xmpp_caps.h" +#include "xmpp_tasks.h" namespace XMPP { - ServerInfoManager::ServerInfoManager(Client* client): QObject(client), _client(client), @@ -293,5 +293,4 @@ void ServerInfoManager::disco_finished() emit featuresChanged(); } } - } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_serverinfomanager.h b/src/xmpp/xmpp-im/xmpp_serverinfomanager.h index b5957c14..ebbaeeef 100644 --- a/src/xmpp/xmpp-im/xmpp_serverinfomanager.h +++ b/src/xmpp/xmpp-im/xmpp_serverinfomanager.h @@ -23,15 +23,13 @@ #include "xmpp_caps.h" #include "xmpp_discoitem.h" +#include #include #include -#include #include - #include namespace XMPP { - class Client; class Features; class Jid; @@ -84,7 +82,6 @@ class ServerInfoManager : public QObject QMap meta; }; - public: ServerInfoManager(XMPP::Client* client); @@ -148,7 +145,6 @@ private slots: bool _hasPEP; bool _canMessageCarbons; }; - } // namespace XMPP -#endif +#endif // SERVERINFOMANAGER_H diff --git a/src/xmpp/xmpp-im/xmpp_status.h b/src/xmpp/xmpp-im/xmpp_status.h index a43f9577..a37f5988 100644 --- a/src/xmpp/xmpp-im/xmpp_status.h +++ b/src/xmpp/xmpp-im/xmpp_status.h @@ -20,18 +20,19 @@ #ifndef XMPP_STATUS_H #define XMPP_STATUS_H +#include "xmpp_bitsofbinary.h" +#include "xmpp_muc.h" + +#include +#include #include #include #include -#include -#include -#include "xmpp_muc.h" -#include "xmpp_bitsofbinary.h" - -namespace XMPP -{ +namespace XMPP { class DiscoItem; + class StatusPrivate; + class CapsSpec { public: @@ -66,8 +67,6 @@ namespace XMPP QStringList ext_; }; - class StatusPrivate; - class Status { public: @@ -146,9 +145,8 @@ namespace XMPP private: QSharedDataPointer d; }; - -} +} // namespace XMPP Q_DECLARE_METATYPE(XMPP::Status) -#endif +#endif // XMPP_STATUS_H diff --git a/src/xmpp/xmpp-im/xmpp_subsets.cpp b/src/xmpp/xmpp-im/xmpp_subsets.cpp index f5835304..5bdf0831 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.cpp +++ b/src/xmpp/xmpp-im/xmpp_subsets.cpp @@ -18,6 +18,7 @@ */ #include "xmpp_subsets.h" + #include "xmpp_xmlcommon.h" using namespace XMPP; diff --git a/src/xmpp/xmpp-im/xmpp_subsets.h b/src/xmpp/xmpp-im/xmpp_subsets.h index 51b75387..d1f9b8e5 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.h +++ b/src/xmpp/xmpp-im/xmpp_subsets.h @@ -22,8 +22,7 @@ #include -namespace XMPP -{ +namespace XMPP { class SubsetsClientManager { public: @@ -52,6 +51,6 @@ namespace XMPP class Private; Private *d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_SUBSETS_H diff --git a/src/xmpp/xmpp-im/xmpp_task.cpp b/src/xmpp/xmpp-im/xmpp_task.cpp index d72cc875..8b65987d 100644 --- a/src/xmpp/xmpp-im/xmpp_task.cpp +++ b/src/xmpp/xmpp-im/xmpp_task.cpp @@ -16,12 +16,13 @@ * */ -#include - #include "xmpp_task.h" + #include "xmpp_client.h" -#include "xmpp_xmlcommon.h" #include "xmpp_stanza.h" +#include "xmpp_xmlcommon.h" + +#include #define DEFAULT_TIMEOUT 120 @@ -291,7 +292,6 @@ void Task::debug(const QString &str) client()->debug(QString("%1: ").arg(metaObject()->className()) + str); } - /** * \brief verifiys a stanza is a IQ reply for this task * @@ -345,4 +345,3 @@ bool Task::iqVerify(const QDomElement &x, const Jid &to, const QString &id, cons return true; } - diff --git a/src/xmpp/xmpp-im/xmpp_task.h b/src/xmpp/xmpp-im/xmpp_task.h index 91daae14..fcdb9533 100644 --- a/src/xmpp/xmpp-im/xmpp_task.h +++ b/src/xmpp/xmpp-im/xmpp_task.h @@ -84,6 +84,6 @@ namespace XMPP { class TaskPrivate; TaskPrivate *d; }; -} +} // namespace XMPP -#endif +#endif // XMPP_TASK_H diff --git a/src/xmpp/xmpp-im/xmpp_tasks.cpp b/src/xmpp/xmpp-im/xmpp_tasks.cpp index cfa6bc3f..c47e87c2 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.cpp +++ b/src/xmpp/xmpp-im/xmpp_tasks.cpp @@ -1,6 +1,6 @@ /* * tasks.cpp - basic tasks - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,20 +17,20 @@ * */ -#include -#include -#include - #include "xmpp_tasks.h" -#include "xmpp_xmlcommon.h" -#include "xmpp_vcard.h" -#include "xmpp_bitsofbinary.h" -#include "xmpp_captcha.h" + #include "xmpp/base/timezone.h" +#include "xmpp_bitsofbinary.h" #include "xmpp_caps.h" +#include "xmpp_captcha.h" +#include "xmpp_vcard.h" +#include "xmpp_xmlcommon.h" -using namespace XMPP; +#include +#include +#include +using namespace XMPP; static QString lineEncode(QString str) { @@ -513,7 +513,6 @@ bool JT_Roster::take(const QDomElement &x) return false; } - //---------------------------------------------------------------------------- // JT_PushRoster //---------------------------------------------------------------------------- @@ -540,7 +539,6 @@ bool JT_PushRoster::take(const QDomElement &e) return true; } - //---------------------------------------------------------------------------- // JT_Presence //---------------------------------------------------------------------------- @@ -658,7 +656,6 @@ void JT_Presence::onGo() setSuccess(); } - //---------------------------------------------------------------------------- // JT_PushPresence //---------------------------------------------------------------------------- @@ -785,7 +782,6 @@ bool JT_PushPresence::take(const QDomElement &e) } } - if (stamp.isValid()) { if (client()->manualTimeZoneOffset()) { stamp = stamp.addSecs(client()->timeZoneOffset() * 3600); @@ -801,7 +797,6 @@ bool JT_PushPresence::take(const QDomElement &e) return true; } - //---------------------------------------------------------------------------- // JT_Message //---------------------------------------------------------------------------- @@ -871,7 +866,6 @@ void JT_Message::onGo() setSuccess(); } - //---------------------------------------------------------------------------- // JT_PushMessage //---------------------------------------------------------------------------- @@ -1066,7 +1060,6 @@ bool JT_VCard::take(const QDomElement &x) return true; } - //---------------------------------------------------------------------------- // JT_Search //---------------------------------------------------------------------------- @@ -1241,7 +1234,6 @@ bool JT_Search::take(const QDomElement &x) return true; } - //---------------------------------------------------------------------------- // JT_ClientVersion //---------------------------------------------------------------------------- @@ -1310,7 +1302,6 @@ const QString & JT_ClientVersion::os() const return v_os; } - //---------------------------------------------------------------------------- // JT_EntityTime //---------------------------------------------------------------------------- @@ -1387,7 +1378,6 @@ int JT_EntityTime::timezoneOffset() const return tzo; } - //---------------------------------------------------------------------------- // JT_ServInfo //---------------------------------------------------------------------------- @@ -1477,7 +1467,6 @@ bool JT_ServInfo::take(const QDomElement &e) return false; } - //---------------------------------------------------------------------------- // JT_Gateway //---------------------------------------------------------------------------- @@ -1753,7 +1742,6 @@ bool JT_DiscoPublish::take(const QDomElement &x) return true; } - // --------------------------------------------------------- // JT_BoBServer // --------------------------------------------------------- @@ -1789,7 +1777,6 @@ bool JT_BoBServer::take(const QDomElement &e) return false; } - //---------------------------------------------------------------------------- // JT_BitsOfBinary //---------------------------------------------------------------------------- @@ -1996,7 +1983,6 @@ bool JT_CaptchaChallenger::take(const QDomElement &x) return true; } - //--------------------------------------------------------------------------- // JT_CaptchaSender //--------------------------------------------------------------------------- diff --git a/src/xmpp/xmpp-im/xmpp_tasks.h b/src/xmpp/xmpp-im/xmpp_tasks.h index 11c401f0..d183ff42 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.h +++ b/src/xmpp/xmpp-im/xmpp_tasks.h @@ -1,6 +1,6 @@ /* * tasks.h - basic tasks - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,25 +17,24 @@ * */ -#ifndef JABBER_TASKS_H -#define JABBER_TASKS_H - -#include -#include -#include +#ifndef XMPP_TASKS_H +#define XMPP_TASKS_H #include "im.h" -#include "xmpp_vcard.h" #include "xmpp_discoinfotask.h" -#include "xmpp_subsets.h" #include "xmpp_encryptionhandler.h" +#include "xmpp_subsets.h" +#include "xmpp_vcard.h" -namespace XMPP -{ - class Roster; - class Status; +#include +#include +#include + +namespace XMPP { class BoBData; class CaptchaChallenge; + class Roster; + class Status; class JT_Register : public Task { @@ -470,6 +469,6 @@ namespace XMPP Jid to; QDomElement iq; }; -} +} // namespace XMPP -#endif +#endif // XMPP_TASKS_H diff --git a/src/xmpp/xmpp-im/xmpp_thumbs.h b/src/xmpp/xmpp-im/xmpp_thumbs.h index 268c414d..bf913c01 100644 --- a/src/xmpp/xmpp-im/xmpp_thumbs.h +++ b/src/xmpp/xmpp-im/xmpp_thumbs.h @@ -19,14 +19,13 @@ #ifndef XMPP_THUMBS_H #define XMPP_THUMBS_H +#include #include #include -#include #define XMPP_THUMBS_NS "urn:xmpp:thumbs:1" // TODO make nsdb.cpp/h with static declarations of all ns -namespace XMPP -{ +namespace XMPP { class Thumbnail { public: @@ -48,6 +47,6 @@ namespace XMPP quint32 width; quint32 height; }; -} +} // namespace XMPP -#endif +#endif // XMPP_THUMBS_H diff --git a/src/xmpp/xmpp-im/xmpp_url.h b/src/xmpp/xmpp-im/xmpp_url.h index 315e6d28..0f90b421 100644 --- a/src/xmpp/xmpp-im/xmpp_url.h +++ b/src/xmpp/xmpp-im/xmpp_url.h @@ -21,8 +21,7 @@ class QString; -namespace XMPP -{ +namespace XMPP { class Url { public: @@ -43,6 +42,6 @@ namespace XMPP }; typedef QList UrlList; -} +} // namespace XMPP -#endif +#endif // XMPP_URL diff --git a/src/xmpp/xmpp-im/xmpp_vcard.cpp b/src/xmpp/xmpp-im/xmpp_vcard.cpp index fa74112b..d28a4c7a 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.cpp +++ b/src/xmpp/xmpp-im/xmpp_vcard.cpp @@ -19,16 +19,16 @@ #include "xmpp_vcard.h" -#include +#include "xmpp_xmlcommon.h" + +#include #include #include // needed for image format recognition -#include #include #include #include #include - -#include "xmpp_xmlcommon.h" +#include using namespace XMLHelper; @@ -71,7 +71,6 @@ QString image2type(const QByteArray &ba) } namespace XMPP { - // Long lines of encoded binary data SHOULD BE folded to 75 characters using the folding method defined in [MIME-DIR]. static QString foldString(const QString &s) { @@ -1193,5 +1192,4 @@ void VCard::setKey(const QByteArray &k) { d->key = k; } - } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_vcard.h b/src/xmpp/xmpp-im/xmpp_vcard.h index 145c492f..8dda52d3 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.h +++ b/src/xmpp/xmpp-im/xmpp_vcard.h @@ -17,21 +17,20 @@ * */ -#ifndef JABBER_VCARD_H -#define JABBER_VCARD_H +#ifndef XMPP_VCARD_H +#define XMPP_VCARD_H +#include #include #include #include - -#include #include class QDate; -namespace XMPP -{ +namespace XMPP { class VCardPrivate; + class VCard { public: @@ -54,7 +53,6 @@ namespace XMPP const QString &fullName() const; void setFullName(const QString &); - const QString &familyName() const; void setFamilyName(const QString &); @@ -70,25 +68,21 @@ namespace XMPP const QString &suffixName() const; void setSuffixName(const QString &); - const QString &nickName() const; void setNickName(const QString &); - const QByteArray &photo() const; void setPhoto(const QByteArray &); const QString &photoURI() const; void setPhotoURI(const QString &); - const QDate bday() const; void setBday(const QDate &); const QString &bdayStr() const; void setBdayStr(const QString &); - class Address { public: Address(); @@ -135,7 +129,6 @@ namespace XMPP const LabelList &labelList() const; void setLabelList(const LabelList &); - class Phone { public: Phone(); @@ -160,7 +153,6 @@ namespace XMPP const PhoneList &phoneList() const; void setPhoneList(const PhoneList &); - class Email { public: Email(); @@ -176,7 +168,6 @@ namespace XMPP const EmailList &emailList() const; void setEmailList(const EmailList &); - const QString &jid() const; void setJid(const QString &); @@ -186,7 +177,6 @@ namespace XMPP const QString &timezone() const; void setTimezone(const QString &); - class Geo { public: Geo(); @@ -197,28 +187,24 @@ namespace XMPP const Geo &geo() const; void setGeo(const Geo &); - const QString &title() const; void setTitle(const QString &); const QString &role() const; void setRole(const QString &); - const QByteArray &logo() const; void setLogo(const QByteArray &); const QString &logoURI() const; void setLogoURI(const QString &); - VCard agent() const; void setAgent(const VCard &); const QString agentURI() const; void setAgentURI(const QString &); - class Org { public: Org(); @@ -229,7 +215,6 @@ namespace XMPP const Org &org() const; void setOrg(const Org &); - const QStringList &categories() const; void setCategories(const QStringList &); @@ -245,7 +230,6 @@ namespace XMPP const QString &sortString() const; void setSortString(const QString &); - const QByteArray &sound() const; void setSound(const QByteArray &); @@ -255,7 +239,6 @@ namespace XMPP const QString &soundPhonetic() const; void setSoundPhonetic(const QString &); - const QString &uid() const; void setUid(const QString &); @@ -265,7 +248,6 @@ namespace XMPP const QString &desc() const; void setDesc(const QString &); - enum PrivacyClass { pcNone = 0, pcPublic = 1, @@ -275,16 +257,15 @@ namespace XMPP const PrivacyClass &privacyClass() const; void setPrivacyClass(const PrivacyClass &); - const QByteArray &key() const; void setKey(const QByteArray &); private: QSharedDataPointer d; }; -} +} // namespace XMPP QString openedImage2type(QIODevice *dev); QString image2type(const QByteArray &ba); -#endif +#endif // XMPP_VCARD_H diff --git a/src/xmpp/xmpp-im/xmpp_xdata.cpp b/src/xmpp/xmpp-im/xmpp_xdata.cpp index e2bf37d4..2d4264c6 100644 --- a/src/xmpp/xmpp-im/xmpp_xdata.cpp +++ b/src/xmpp/xmpp-im/xmpp_xdata.cpp @@ -18,14 +18,15 @@ */ #include "xmpp_xdata.h" -#include "xmpp_xmlcommon.h" + #include "xmpp/jid/jid.h" +#include "xmpp_xmlcommon.h" #include #include -using namespace XMPP; using namespace XMLHelper; +using namespace XMPP; // TODO: report, item @@ -329,9 +330,6 @@ QDomElement XData::Field::toXml(QDomDocument *doc, bool submitForm) const return f; } - - - //---------------------------------------------------------------------------- // MediaElement //---------------------------------------------------------------------------- @@ -369,9 +367,6 @@ bool XData::Field::MediaElement::checkSupport(const QStringList &wildcards) return false; } - - - //---------------------------------------------------------------------------- // XData //---------------------------------------------------------------------------- diff --git a/src/xmpp/xmpp-im/xmpp_xdata.h b/src/xmpp/xmpp-im/xmpp_xdata.h index 621890e3..de1f5e87 100644 --- a/src/xmpp/xmpp-im/xmpp_xdata.h +++ b/src/xmpp/xmpp-im/xmpp_xdata.h @@ -17,22 +17,21 @@ * */ -#ifndef XMPPXDATA_H -#define XMPPXDATA_H +#ifndef XMPP_XDATA_H +#define XMPP_XDATA_H -#include -#include +#include #include +#include #include -#include #include -#include +#include +#include -class QDomElement; class QDomDocument; +class QDomElement; namespace XMPP { - class XData { public: @@ -178,7 +177,6 @@ namespace XMPP { }; QSharedDataPointer d; }; +}; // namespace XMPP -}; - -#endif +#endif // XMPP_XDATA_H diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp index b4e86c93..927e3c01 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp @@ -1,6 +1,6 @@ /* * xmlcommon.cpp - helper functions for dealing with XML - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,16 +17,17 @@ * */ -#include +#include "xmpp_xmlcommon.h" + +#include "xmpp_stanza.h" + +#include #include -#include +#include #include +#include +#include #include -#include -#include - -#include "xmpp_xmlcommon.h" -#include "xmpp_stanza.h" //---------------------------------------------------------------------------- // XDomNodeList @@ -165,7 +166,6 @@ QString tagContent(const QDomElement &e) return ""; } - /** * \brief obtain direct child elements of a certain kind. unlike * elementsByTagNameNS, this function does not descend beyond the first @@ -188,7 +188,6 @@ XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI return out; } - /** * \brief create a new IQ stanza * \param doc @@ -313,9 +312,7 @@ QDomElement addCorrectNS(const QDomElement &e) //---------------------------------------------------------------------------- // XMLHelper //---------------------------------------------------------------------------- - namespace XMLHelper { - QDomElement emptyTag(QDomDocument *doc, const QString &name) { QDomElement tag = doc->createElement(name); @@ -537,5 +534,4 @@ void setTagText(QDomElement &e, const QString &text) { e.appendChild(e.ownerDocument().createTextNode(text)); } - -} +} // namespace XMLHelper diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.h b/src/xmpp/xmpp-im/xmpp_xmlcommon.h index e3df0a06..d3ac151d 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.h +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.h @@ -1,6 +1,6 @@ /* * xmlcommon.h - helper functions for dealing with XML - * Copyright (C) 2001, 2002 Justin Karneges + * Copyright (C) 2001-2002 Justin Karneges * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,20 +17,19 @@ * */ -#ifndef JABBER_XMLCOMMON_H -#define JABBER_XMLCOMMON_H +#ifndef XMPP_XMLCOMMON_H +#define XMPP_XMLCOMMON_H #include #include +class QColor; class QDateTime; class QRect; class QSize; -class QColor; class QStringList; -class XDomNodeList -{ +class XDomNodeList { public: XDomNodeList(); XDomNodeList(const XDomNodeList &from); @@ -100,6 +99,6 @@ namespace XMLHelper { //QString tagContent(const QDomElement &e); // obsolete; QString sanitizedLang(const QString &lang); -} +} // namespace XMLHelper -#endif +#endif // XMPP_XMLCOMMON_H diff --git a/src/xmpp/zlib/common.h b/src/xmpp/zlib/common.h index bf243c0d..d738379e 100644 --- a/src/xmpp/zlib/common.h +++ b/src/xmpp/zlib/common.h @@ -21,4 +21,4 @@ static void initZStream(z_stream* z) z->reserved = 0; } -#endif +#endif // ZLIB_COMMON_H diff --git a/src/xmpp/zlib/zlibcompressor.cpp b/src/xmpp/zlib/zlibcompressor.cpp index e1d08f8f..bbf43256 100644 --- a/src/xmpp/zlib/zlibcompressor.cpp +++ b/src/xmpp/zlib/zlibcompressor.cpp @@ -1,11 +1,11 @@ #include "xmpp/zlib/zlibcompressor.h" -#include -#include -#include +#include "common.h" #include "zlib.h" -#include "common.h" +#include +#include +#include ZLibCompressor::ZLibCompressor(QIODevice* device, int compression) : device_(device) { diff --git a/src/xmpp/zlib/zlibcompressor.h b/src/xmpp/zlib/zlibcompressor.h index 7e3783a5..92d1f113 100644 --- a/src/xmpp/zlib/zlibcompressor.h +++ b/src/xmpp/zlib/zlibcompressor.h @@ -1,10 +1,10 @@ #ifndef ZLIBCOMPRESSOR_H #define ZLIBCOMPRESSOR_H -#include - #include "zlib.h" +#include + class QIODevice; class ZLibCompressor : public QObject @@ -29,4 +29,4 @@ protected slots: bool flushed_; }; -#endif +#endif // ZLIBCOMPRESSOR_H diff --git a/src/xmpp/zlib/zlibdecompressor.cpp b/src/xmpp/zlib/zlibdecompressor.cpp index 0f04eba6..0f0aafaf 100644 --- a/src/xmpp/zlib/zlibdecompressor.cpp +++ b/src/xmpp/zlib/zlibdecompressor.cpp @@ -1,11 +1,11 @@ #include "xmpp/zlib/zlibdecompressor.h" -#include -#include -#include +#include "xmpp/zlib/common.h" #include "zlib.h" -#include "xmpp/zlib/common.h" +#include +#include +#include ZLibDecompressor::ZLibDecompressor(QIODevice* device) : device_(device) { diff --git a/src/xmpp/zlib/zlibdecompressor.h b/src/xmpp/zlib/zlibdecompressor.h index f0bac6e6..898d8c7d 100644 --- a/src/xmpp/zlib/zlibdecompressor.h +++ b/src/xmpp/zlib/zlibdecompressor.h @@ -1,10 +1,10 @@ #ifndef ZLIBDECOMPRESSOR_H #define ZLIBDECOMPRESSOR_H -#include - #include "zlib.h" +#include + class QIODevice; class ZLibDecompressor : public QObject @@ -29,4 +29,4 @@ protected slots: bool flushed_; }; -#endif +#endif // ZLIBDECOMPRESSOR_H diff --git a/tools/nettool/main.cpp b/tools/nettool/main.cpp index 6e03d5e4..d52bd627 100644 --- a/tools/nettool/main.cpp +++ b/tools/nettool/main.cpp @@ -16,18 +16,18 @@ * */ -#include -#include -#include +#include +#include #include +#include #include -#include +#include +#include +#include #include #include -#include -#include #include -#include +#include using namespace XMPP; diff --git a/tools/xmpptest/xmpptest.cpp b/tools/xmpptest/xmpptest.cpp index 497ab6a3..4753d760 100644 --- a/tools/xmpptest/xmpptest.cpp +++ b/tools/xmpptest/xmpptest.cpp @@ -16,33 +16,31 @@ * */ +#include "im.h" +#include "ui_test.h" +#include "xmpp.h" + #include +#include #include -#include -#include -#include +#include #include #include -#include -#include +#include #include -#include -#include -#include +#include +#include #include +#include +#include +#include +#include #include -#include -#include -#include "xmpp.h" -#include "im.h" - +#include +#include #include #include -#include "ui_test.h" - -#include - #define AppName "xmpptest" static QString plain2rich(const QString &plain) From 1144eb23c993825f9b9c25795af77ac2fd7933ad Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sat, 31 Aug 2019 08:22:04 +0300 Subject: [PATCH 100/383] fixed compilation --- src/xmpp/base/randrandomnumbergenerator.h | 2 ++ src/xmpp/xmpp-im/xmpp_address.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/xmpp/base/randrandomnumbergenerator.h b/src/xmpp/base/randrandomnumbergenerator.h index 1d1c45ee..985786cf 100644 --- a/src/xmpp/base/randrandomnumbergenerator.h +++ b/src/xmpp/base/randrandomnumbergenerator.h @@ -21,6 +21,8 @@ #include "xmpp/base/randomnumbergenerator.h" +#include + namespace XMPP { class RandRandomNumberGenerator : public RandomNumberGenerator { diff --git a/src/xmpp/xmpp-im/xmpp_address.h b/src/xmpp/xmpp-im/xmpp_address.h index 108c6614..9343c888 100644 --- a/src/xmpp/xmpp-im/xmpp_address.h +++ b/src/xmpp/xmpp-im/xmpp_address.h @@ -20,6 +20,7 @@ #define XMPP_ADDRESS_H #include "xmpp/jid/jid.h" +#include "xmpp_stanza.h" #include From 5999922802f5bac118f91486021dbf6e71886246 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Thu, 10 Oct 2019 10:16:34 +0300 Subject: [PATCH 101/383] improved xmpp::hash and jingle file Al the remaining changes - automatic reformatting --- src/xmpp/xmpp-im/jingle-ft.cpp | 390 +++---- src/xmpp/xmpp-im/jingle-ft.h | 145 ++- src/xmpp/xmpp-im/types.cpp | 1453 +++++++++++++----------- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 108 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.h | 132 +-- src/xmpp/xmpp-im/xmpp_hash.h | 97 +- src/xmpp/xmpp-im/xmpp_status.h | 234 ++-- src/xmpp/xmpp-im/xmpp_tasks.cpp | 828 +++++++------- src/xmpp/xmpp-im/xmpp_xmlcommon.cpp | 149 +-- src/xmpp/xmpp-im/xmpp_xmlcommon.h | 92 +- 10 files changed, 1853 insertions(+), 1775 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 60c2ef2b..3d559e86 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -30,21 +30,34 @@ namespace XMPP { namespace Jingle { namespace FileTransfer { -const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); -const QString HISTOGRAM_NS = QStringLiteral("urn:audio:histogram"); +const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); +const QString AMPLITUDES_NS = QStringLiteral("urn:audio:amplitudes"); + +// tags +static const QString AMPLITUDES_TAG = QStringLiteral("amplitudes"); +static const QString FILETAG = QStringLiteral("file"); +static const QString DATE_TAG = QStringLiteral("date"); +static const QString DESC_TAG = QStringLiteral("desc"); +static const QString MEDIA_TYPE_TAG = QStringLiteral("media-type"); +static const QString NAME_TAG = QStringLiteral("name"); +static const QString SIZE_TAG = QStringLiteral("size"); +static const QString RANGE_TAG = QStringLiteral("range"); +static const QString THUMBNAIL_TAG = QStringLiteral("thumbnail"); QDomElement Range::toXml(QDomDocument *doc) const { - auto r = doc->createElement(QStringLiteral("range")); + auto r = doc->createElement(RANGE_TAG); if (length) { r.setAttribute(QStringLiteral("length"), QString::number(length)); } if (offset) { - r.setAttribute(QStringLiteral("length"), QString::number(length)); + r.setAttribute(QStringLiteral("offset"), QString::number(offset)); } - auto h = hash.toXml(doc); - if (!h.isNull()) { - r.appendChild(h); + for (auto const &h : hashes) { + auto hel = h.toXml(doc); + if (!hel.isNull()) { + r.appendChild(hel); + } } return r; } @@ -52,30 +65,27 @@ QDomElement Range::toXml(QDomDocument *doc) const //---------------------------------------------------------------------------- // File //---------------------------------------------------------------------------- -class File::Private : public QSharedData -{ +class File::Private : public QSharedData { public: - QDateTime date; - QString mediaType; - QString name; - QString desc; - quint64 size = 0; - Range range; - bool rangeSupported = false; - bool hasSize = false; + QDateTime date; + QString mediaType; + QString name; + QString desc; + qint64 size = 0; + Range range; + bool rangeSupported = false; + bool hasSize = false; QList hashes; - Thumbnail thumbnail; - File::Histogram audioHistogram; + Thumbnail thumbnail; + QByteArray amplitudes; }; File::File() { - } File::~File() { - } File &File::operator=(const File &other) @@ -87,7 +97,6 @@ File &File::operator=(const File &other) File::File(const File &other) : d(other.d) { - } File::File(const QDomElement &file) @@ -96,39 +105,39 @@ File::File(const QDomElement &file) QString mediaType; QString name; QString desc; - size_t size = 0; + size_t size = 0; bool rangeSupported = false; - bool hasSize = false; + bool hasSize = false; Range range; QList hashes; Thumbnail thumbnail; - Histogram histogram; + QByteArray amplitudes; bool ok; - for(QDomElement ce = file.firstChildElement(); - !ce.isNull(); ce = ce.nextSiblingElement()) { + for (QDomElement ce = file.firstChildElement(); + !ce.isNull(); ce = ce.nextSiblingElement()) { - if (ce.tagName() == QLatin1String("date")) { + if (ce.tagName() == DATE_TAG) { date = QDateTime::fromString(ce.text().left(19), Qt::ISODate); if (!date.isValid()) { return; } - } else if (ce.tagName() == QLatin1String("media-type")) { + } else if (ce.tagName() == MEDIA_TYPE_TAG) { mediaType = ce.text(); - } else if (ce.tagName() == QLatin1String("name")) { + } else if (ce.tagName() == NAME_TAG) { name = ce.text(); - } else if (ce.tagName() == QLatin1String("size")) { + } else if (ce.tagName() == SIZE_TAG) { size = ce.text().toULongLong(&ok); if (!ok) { return; } hasSize = true; - } else if (ce.tagName() == QLatin1String("range")) { + } else if (ce.tagName() == RANGE_TAG) { if (ce.hasAttribute(QLatin1String("offset"))) { range.offset = ce.attribute(QLatin1String("offset")).toULongLong(&ok); if (!ok) { @@ -142,19 +151,22 @@ File::File(const QDomElement &file) } } QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); - if (hashEl.namespaceURI() == HASH_NS || hashEl.namespaceURI() == HASH_NS) { - range.hash = Hash(hashEl); - if (range.hash.type() == Hash::Type::Unknown) { - return; + for (; !hashEl.isNull(); hashEl = hashEl.nextSiblingElement(QLatin1String("hash"))) { + if (hashEl.namespaceURI() == HASH_NS) { + auto hash = Hash(hashEl); + if (hash.type() == Hash::Type::Unknown) { + continue; + } + range.hashes.append(hash); } } rangeSupported = true; - } else if (ce.tagName() == QLatin1String("desc")) { + } else if (ce.tagName() == DESC_TAG) { desc = ce.text(); } else if (ce.tagName() == QLatin1String("hash")) { - if (ce.namespaceURI() == HASH_NS || ce.namespaceURI() == HASH_NS) { + if (ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -163,7 +175,7 @@ File::File(const QDomElement &file) } } else if (ce.tagName() == QLatin1String("hash-used")) { - if (ce.namespaceURI() == HASH_NS || ce.namespaceURI() == HASH_NS) { + if (ce.namespaceURI() == HASH_NS) { Hash h(ce); if (h.type() == Hash::Type::Unknown) { return; @@ -171,42 +183,25 @@ File::File(const QDomElement &file) hashes.append(h); } - } else if (ce.tagName() == QLatin1String("thumbnail")) { + } else if (ce.tagName() == THUMBNAIL_TAG) { thumbnail = Thumbnail(ce); - } else if (ce.tagName() == QLatin1String("histogram") && (ce.namespaceURI() == HISTOGRAM_NS || ce.namespaceURI() == HISTOGRAM_NS)) { - QStringList spv = ce.text().split(','); - histogram.bars.reserve(spv.count()); - std::transform(spv.begin(), spv.end(), std::back_inserter(histogram.bars), [](const QString &v){ return v.toUInt(); }); - auto c = ce.attribute(QStringLiteral("coding")).toLatin1(); - if (c == "u8") - histogram.coding = File::Histogram::Coding::U8; - else if (c == "s8") - histogram.coding = File::Histogram::Coding::S8; - else if (c == "u16") - histogram.coding = File::Histogram::Coding::U16; - else if (c == "s16") - histogram.coding = File::Histogram::Coding::S16; - else if (c == "u32") - histogram.coding = File::Histogram::Coding::U32; - else if (c == "s32") - histogram.coding = File::Histogram::Coding::S32; - else - histogram.bars.clear(); // drop invalid histogram + } else if (ce.tagName() == AMPLITUDES_TAG && ce.namespaceURI() == AMPLITUDES_NS) { + amplitudes = QByteArray::fromBase64(ce.text().toLatin1()); } } - auto p = new Private; - p->date = date; - p->mediaType = mediaType; - p->name = name; - p->desc = desc; - p->size = size; + auto p = new Private; + p->date = date; + p->mediaType = mediaType; + p->name = name; + p->desc = desc; + p->size = size; p->rangeSupported = rangeSupported; - p->hasSize = hasSize; - p->range = range; - p->hashes = hashes; - p->thumbnail = thumbnail; - p->audioHistogram = histogram; + p->hasSize = hasSize; + p->range = range; + p->hashes = hashes; + p->thumbnail = thumbnail; + p->amplitudes = amplitudes; d = p; } @@ -218,22 +213,22 @@ QDomElement File::toXml(QDomDocument *doc) const } QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); if (d->date.isValid()) { - el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("date"), d->date.toString(Qt::ISODate))); + el.appendChild(XMLHelper::textTag(*doc, DATE_TAG, d->date.toString(Qt::ISODate))); } if (d->desc.size()) { - el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("desc"), d->desc)); + el.appendChild(XMLHelper::textTag(*doc, DESC_TAG, d->desc)); } - for (const auto &h: d->hashes) { + for (const auto &h : d->hashes) { el.appendChild(h.toXml(doc)); } if (d->mediaType.size()) { - el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("media-type"), d->mediaType)); + el.appendChild(XMLHelper::textTag(*doc, MEDIA_TYPE_TAG, d->mediaType)); } if (d->name.size()) { - el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("name"), d->name)); + el.appendChild(XMLHelper::textTag(*doc, NAME_TAG, d->name)); } if (d->size) { - el.appendChild(XMLHelper::textTag(*doc, QStringLiteral("size"), QString::number(d->size))); + el.appendChild(XMLHelper::textTag(*doc, SIZE_TAG, d->size)); } if (d->rangeSupported || d->range.isValid()) { el.appendChild(d->range.toXml(doc)); @@ -241,24 +236,8 @@ QDomElement File::toXml(QDomDocument *doc) const if (d->thumbnail.isValid()) { el.appendChild(d->thumbnail.toXml(doc)); } - if (d->audioHistogram.bars.count()) { - auto sel = el.appendChild(doc->createElementNS(HISTOGRAM_NS, QString::fromLatin1("histogram"))).toElement(); - const char* s[] = {"u8","s8","u16","s16","u32","s32"}; - sel.setAttribute(QString::fromLatin1("coding"), QString::fromLatin1(s[d->audioHistogram.coding])); - QStringList sl; - std::transform(d->audioHistogram.bars.begin(), d->audioHistogram.bars.end(), std::back_inserter(sl), - [this](quint32 v){ - switch (d->audioHistogram.coding) { - case Histogram::U8: return QString::number(quint8(v)); - case Histogram::S8: return QString::number(qint8(v)); - case Histogram::U16: return QString::number(quint16(v)); - case Histogram::S16: return QString::number(qint16(v)); - case Histogram::U32: return QString::number(quint32(v)); - case Histogram::S32: return QString::number(qint32(v)); - } - return QString(); - }); - sel.appendChild(doc->createTextNode(sl.join(','))); + if (d->amplitudes.size()) { + el.appendChild(XMLHelper::textTagNS(doc, AMPLITUDES_NS, AMPLITUDES_TAG, d->amplitudes)); } return el; } @@ -268,8 +247,8 @@ bool File::merge(const File &other) if (!d->thumbnail.isValid()) { d->thumbnail = other.thumbnail(); } - for (auto const &h: other.d->hashes) { - auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v){ return h.type() == v.type(); }); + for (auto const &h : other.d->hashes) { + auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v) { return h.type() == v.type(); }); if (it == d->hashes.constEnd()) { d->hashes.append(h); } else if (h.data() != it->data()) { @@ -283,7 +262,7 @@ bool File::hasComputedHashes() const { if (!d) return false; - for (auto const &h: d->hashes) { + for (auto const &h : d->hashes) { if (h.data().size()) return true; } @@ -297,12 +276,17 @@ bool File::hasSize() const QDateTime File::date() const { - return d? d->date : QDateTime(); + return d ? d->date : QDateTime(); } QString File::description() const { - return d? d->desc : QString(); + return d ? d->desc : QString(); +} + +QList File::hashes() const +{ + return d ? d->hashes : QList(); } Hash File::hash(Hash::Type t) const @@ -310,7 +294,7 @@ Hash File::hash(Hash::Type t) const if (d && d->hashes.count()) { if (t == Hash::Unknown) return d->hashes.at(0); - for (auto const &h: d->hashes) { + for (auto const &h : d->hashes) { if (h.type() == t) { return h; } @@ -321,56 +305,32 @@ Hash File::hash(Hash::Type t) const QString File::mediaType() const { - return d? d->mediaType : QString(); + return d ? d->mediaType : QString(); } QString File::name() const { - return d? d->name : QString(); + return d ? d->name : QString(); } quint64 File::size() const { - return d? d->size : 0; + return d ? d->size : 0; } Range File::range() const { - return d? d->range : Range(); + return d ? d->range : Range(); } Thumbnail File::thumbnail() const { - return d? d->thumbnail: Thumbnail(); + return d ? d->thumbnail : Thumbnail(); } -File::Histogram File::audioHistogram() const +QByteArray File::amplitudes() const { - return d? d->audioHistogram: Histogram(); -} - -QList File::audioFloatHistogram() const -{ - QList ret; - if (!d->audioHistogram.bars.count()) - return ret; - - std::function normalizer; - switch (d->audioHistogram.coding) { - case Histogram::U8: normalizer = [](quint32 v){ return quint8(v) / 255.0f; }; break; - case Histogram::S8: normalizer = [](quint32 v){ return std::fabs(qint8(v) / 128.0f); }; break; - case Histogram::U16: normalizer = [](quint32 v){ return quint16(v) / float(1 << 16); }; break; - case Histogram::S16: normalizer = [](quint32 v){ return std::fabs(qint16(v) / float(1 << 15)); }; break; - case Histogram::U32: normalizer = [](quint32 v){ return quint32(v) / float(quint64(1) << 32); }; break; - case Histogram::S32: normalizer = [](quint32 v){ return std::fabs(qint32(v) / float(quint64(1) << 31)); }; break; - } - - if (normalizer) { - ret.reserve(d->audioHistogram.bars.count()); - std::transform(d->audioHistogram.bars.begin(), d->audioHistogram.bars.end(), std::back_inserter(ret), normalizer); - } - - return ret; + return d ? d->amplitudes : QByteArray(); } void File::setDate(const QDateTime &date) @@ -401,12 +361,12 @@ void File::setName(const QString &name) void File::setSize(quint64 size) { ensureD()->size = size; - d->hasSize = true; + d->hasSize = true; } void File::setRange(const Range &range) { - ensureD()->range = range; + ensureD()->range = range; d->rangeSupported = true; } @@ -415,9 +375,9 @@ void File::setThumbnail(const Thumbnail &thumb) ensureD()->thumbnail = thumb; } -void File::setAudioHistogram(const File::Histogram &histogram) +void File::setAmplitudes(const QByteArray &litudes) { - d->audioHistogram = histogram; + d->amplitudes = amplitudes; } File::Private *File::ensureD() @@ -462,10 +422,9 @@ QDomElement Received::toXml(QDomDocument *doc) const //---------------------------------------------------------------------------- // ApplicationManager //---------------------------------------------------------------------------- -Manager::Manager(QObject *parent): +Manager::Manager(QObject *parent) : XMPP::Jingle::ApplicationManager(parent) { - } Manager::~Manager() @@ -479,7 +438,7 @@ void Manager::setJingleManager(XMPP::Jingle::Manager *jm) jingleManager = jm; } -Application* Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) +Application *Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) { if (!(contentName.size() > 0 && (senders == Origin::Initiator || senders == Origin::Responder))) { qDebug("Invalid Jignle FT App start parameters"); @@ -488,14 +447,13 @@ Application* Manager::startApplication(const ApplicationManagerPad::Ptr &pad, co return new Application(pad.staticCast(), contentName, creator, senders); // ContentOrigin::Remote } -ApplicationManagerPad* Manager::pad(Session *session) +ApplicationManagerPad *Manager::pad(Session *session) { return new Pad(this, session); } void Manager::closeAll() { - } Client *Manager::client() @@ -514,29 +472,28 @@ QStringList Manager::availableTransports() const //---------------------------------------------------------------------------- // Application //---------------------------------------------------------------------------- -class Application::Private -{ +class Application::Private { public: - Application *q = nullptr; - State state = State::Created; - State transportReplaceState = State::Finished; - Action updateToSend = Action::NoAction; - QSharedPointer pad; - QString contentName; - File file; - File acceptFile; // as it comes with "accept" response - Origin creator; - Origin senders; - Origin transportReplaceOrigin = Origin::None; - XMPP::Stanza::Error lastError; - Reason terminationReason; + Application * q = nullptr; + State state = State::Created; + State transportReplaceState = State::Finished; + Action updateToSend = Action::NoAction; + QSharedPointer pad; + QString contentName; + File file; + File acceptFile; // as it comes with "accept" response + Origin creator; + Origin senders; + Origin transportReplaceOrigin = Origin::None; + XMPP::Stanza::Error lastError; + Reason terminationReason; QSharedPointer transport; - Connection::Ptr connection; - QStringList availableTransports; - bool closeDeviceOnFinish = true; - bool streamigMode = false; - QIODevice *device = nullptr; - quint64 bytesLeft = 0; + Connection::Ptr connection; + QStringList availableTransports; + bool closeDeviceOnFinish = true; + bool streamigMode = false; + QIODevice * device = nullptr; + quint64 bytesLeft = 0; void setState(State s) { @@ -566,7 +523,7 @@ class Application::Private return; // everything is written } auto sz = connection->blockSize(); - sz = sz? sz : 8192; + sz = sz ? sz : 8192; if (sz > bytesLeft) { sz = bytesLeft; } @@ -617,17 +574,16 @@ class Application::Private Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : d(new Private) { - d->q = this; - d->pad = pad; - d->contentName = contentName; - d->creator = creator; - d->senders = senders; - d->availableTransports = static_cast(pad->manager())->availableTransports(); + d->q = this; + d->pad = pad; + d->contentName = contentName; + d->creator = creator; + d->senders = senders; + d->availableTransports = static_cast(pad->manager())->availableTransports(); } Application::~Application() { - } ApplicationManagerPad::Ptr Application::pad() const @@ -674,7 +630,7 @@ Application::SetDescError Application::setDescription(const QDomElement &descrip { d->file = File(description.firstChildElement("file")); //d->state = State::Pending; // basically it's incomming content. so if we parsed it it's pending. if not parsed if will rejected anyway. - return d->file.isValid()? Ok: Unparsed; + return d->file.isValid() ? Ok : Unparsed; } void Application::setFile(const File &file) @@ -712,12 +668,12 @@ bool Application::setTransport(const QSharedPointer &transport) d->availableTransports.removeAt(nsIndex); d->transport = transport; connect(transport.data(), &Transport::updated, this, &Application::updated); - connect(transport.data(), &Transport::connected, this, [this](){ + connect(transport.data(), &Transport::connected, this, [this]() { d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; // not needed here probably - d->connection = d->transport->connection(); + d->transportReplaceState = State::Finished; // not needed here probably + d->connection = d->transport->connection(); if (d->streamigMode) { - connect(d->connection.data(), &Connection::readyRead, this, [this](){ + connect(d->connection.data(), &Connection::readyRead, this, [this]() { if (!d->device) { return; } @@ -725,7 +681,7 @@ bool Application::setTransport(const QSharedPointer &transport) d->readNextBlockFromTransport(); } }); - connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes){ + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes) { Q_UNUSED(bytes) if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { d->writeNextBlockToTransport(); @@ -746,7 +702,7 @@ bool Application::setTransport(const QSharedPointer &transport) } }); - connect(transport.data(), &Transport::failed, this, [this](){ + connect(transport.data(), &Transport::failed, this, [this]() { d->transportReplaceOrigin = d->pad->session()->role(); if (d->state >= State::Active) { emit updated(); // late failure are unhandled. just notify the remote @@ -785,7 +741,7 @@ bool Application::incomingTransportReplace(const QSharedPointer &tran d->availableTransports.append(d->transport->pad()->ns()); } d->transportReplaceOrigin = d->pad->session()->peerRole(); - auto ret = setTransport(transport); + auto ret = setTransport(transport); if (ret) d->transportReplaceState = State::PrepareLocalOffer; else { @@ -820,7 +776,7 @@ Action Application::evaluateOutgoingUpdate() if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) return Action::NoAction; - return d->transportReplaceOrigin == d->pad->session()->role()? Action::TransportReplace : Action::TransportAccept; + return d->transportReplaceOrigin == d->pad->session()->role() ? Action::TransportReplace : Action::TransportAccept; }; switch (d->state) { @@ -839,7 +795,7 @@ Action Application::evaluateOutgoingUpdate() } if (d->transport->isInitialOfferReady()) - d->updateToSend = d->creator == d->pad->session()->role()? Action::ContentAdd : Action::ContentAccept; + d->updateToSend = d->creator == d->pad->session()->role() ? Action::ContentAdd : Action::ContentAccept; break; case State::Connecting: @@ -855,8 +811,7 @@ Action Application::evaluateOutgoingUpdate() if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { d->updateToSend = Action::ContentRemove; - } - else if (d->transport->hasUpdates()) + } else if (d->transport->hasUpdates()) d->updateToSend = Action::TransportInfo; break; @@ -880,7 +835,7 @@ OutgoingUpdate Application::takeOutgoingUpdate() } auto client = d->pad->session()->manager()->client(); - auto doc = client->doc(); + auto doc = client->doc(); if (d->updateToSend == Action::SessionInfo) { if (d->state != State::Finishing) { @@ -888,20 +843,19 @@ OutgoingUpdate Application::takeOutgoingUpdate() return OutgoingUpdate(); } ContentBase cb(d->pad->session()->role(), d->contentName); - return OutgoingUpdate{QList() << cb.toXml(doc, "received"), [this](){ - d->setState(State::Finished); - } - }; + return OutgoingUpdate { QList() << cb.toXml(doc, "received"), [this]() { + d->setState(State::Finished); + } }; } - QDomElement transportEl; + QDomElement transportEl; OutgoingUpdateCB transportCB; ContentBase cb(d->creator, d->contentName); if (d->state == State::PrepareLocalOffer) cb.senders = d->senders; QList updates; - auto contentEl = cb.toXml(doc, "content"); + auto contentEl = cb.toXml(doc, "content"); updates << contentEl; switch (d->updateToSend) { @@ -911,18 +865,17 @@ OutgoingUpdate Application::takeOutgoingUpdate() d->terminationReason = Reason(Reason::Condition::FailedTransport); if (d->terminationReason.isValid()) updates << d->terminationReason.toXml(doc); - return OutgoingUpdate{updates, [this](){ - d->setState(State::Finished); - } - }; + return OutgoingUpdate { updates, [this]() { + d->setState(State::Finished); + } }; case Action::ContentAdd: case Action::ContentAccept: Q_ASSERT(d->transport->isInitialOfferReady()); if (d->file.thumbnail().data.size()) { - auto thumb = d->file.thumbnail(); - auto bm = client->bobManager(); - BoBData data = bm->append(thumb.data, thumb.mimeType); - thumb.uri = QLatin1String("cid:") + data.cid(); + auto thumb = d->file.thumbnail(); + auto bm = client->bobManager(); + BoBData data = bm->append(thumb.data, thumb.mimeType); + thumb.uri = QLatin1String("cid:") + data.cid(); d->file.setThumbnail(thumb); } contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); @@ -930,31 +883,30 @@ OutgoingUpdate Application::takeOutgoingUpdate() contentEl.appendChild(transportEl); d->setState(State::Unacked); - return OutgoingUpdate{updates, [this, transportCB](){ - if (transportCB) { - transportCB(); - } - d->setState(d->pad->session()->role() == Origin::Initiator? State::Pending : State::Connecting); - }}; + return OutgoingUpdate { updates, [this, transportCB]() { + if (transportCB) { + transportCB(); + } + d->setState(d->pad->session()->role() == Origin::Initiator ? State::Pending : State::Connecting); + } }; case Action::TransportInfo: Q_ASSERT(d->transport->hasUpdates()); std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); contentEl.appendChild(transportEl); - return OutgoingUpdate{updates, transportCB}; + return OutgoingUpdate { updates, transportCB }; case Action::TransportReplace: - case Action::TransportAccept: - { + case Action::TransportAccept: { Q_ASSERT(d->transport->isInitialOfferReady()); - d->transportReplaceState = State::Unacked; + d->transportReplaceState = State::Unacked; std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); contentEl.appendChild(transportEl); auto action = d->updateToSend; - return OutgoingUpdate{updates, [this,transportCB,action](){ - if (transportCB) { - transportCB(); - } - d->transportReplaceState = action == Action::TransportReplace? State::Pending : State::Finished; - }}; + return OutgoingUpdate { updates, [this, transportCB, action]() { + if (transportCB) { + transportCB(); + } + d->transportReplaceState = action == Action::TransportReplace ? State::Pending : State::Finished; + } }; } default: break; @@ -1019,7 +971,7 @@ void Application::remove(Reason::Condition cond, const QString &comment) if (d->state >= State::Finishing) return; - d->terminationReason = Reason(cond, comment); + d->terminationReason = Reason(cond, comment); d->transportReplaceOrigin = Origin::None; // just in case d->transport->disconnect(this); d->transport.reset(); @@ -1042,7 +994,7 @@ bool Application::incomingTransportAccept(const QDomElement &transportEl) } if (d->transport->update(transportEl)) { d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; + d->transportReplaceState = State::Finished; if (d->state >= State::Connecting) { d->transport->start(); } @@ -1054,8 +1006,7 @@ bool Application::incomingTransportAccept(const QDomElement &transportEl) bool Application::isValid() const { - return d->file.isValid() && d->contentName.size() > 0 && - (d->senders == Origin::Initiator || d->senders == Origin::Responder); + return d->file.isValid() && d->contentName.size() > 0 && (d->senders == Origin::Initiator || d->senders == Origin::Responder); } void Application::setDevice(QIODevice *dev, bool closeOnFinish) @@ -1065,7 +1016,7 @@ void Application::setDevice(QIODevice *dev, bool closeOnFinish) emit updated(); return; } - d->device = dev; + d->device = dev; d->closeDeviceOnFinish = closeOnFinish; if (d->senders == d->pad->session()->role()) { d->writeNextBlockToTransport(); @@ -1083,7 +1034,6 @@ Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) { - } QDomElement Pad::takeOutgoingSessionInfoUpdate() @@ -1108,7 +1058,7 @@ ApplicationManager *Pad::manager() const QString Pad::generateContentName(Origin senders) { - QString prefix = senders == _session->role()? "fileoffer" : "filereq"; + QString prefix = senders == _session->role() ? "fileoffer" : "filereq"; QString name; do { name = prefix + QString("_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); @@ -1119,7 +1069,7 @@ QString Pad::generateContentName(Origin senders) void Pad::addOutgoingOffer(const File &file) { auto selfp = _session->applicationPad(NS); - auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); + auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); app->setFile(file); } } // namespace FileTransfer diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 4e9ac92c..3b62d085 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -34,52 +34,40 @@ extern const QString NS; class Manager; struct Range { - quint64 offset = 0; - quint64 length = 0; // 0 - from offset to the end of the file - Hash hash; + quint64 offset = 0; + quint64 length = 0; // 0 - from offset to the end of the file + QList hashes; inline Range() {} - inline Range(quint64 offset, quint64 length) : offset(offset), length(length) {} - inline bool isValid() const { return hash.isValid() || offset || length; } + inline Range(quint64 offset, quint64 length) : + offset(offset), length(length) {} + inline bool isValid() const { return hashes.size() || offset || length; } QDomElement toXml(QDomDocument *doc) const; }; -class File -{ +class File { public: - struct Histogram - { - enum Coding { - U8, S8, - U16, S16, - U32, S32 - }; - - Coding coding; - QList bars; - }; - File(); File(const File &other); File(const QDomElement &file); ~File(); - File& operator=(const File& other); + File & operator=(const File &other); inline bool isValid() const { return d != nullptr; } QDomElement toXml(QDomDocument *doc) const; - bool merge(const File &other); - bool hasComputedHashes() const; - bool hasSize() const; - - QDateTime date() const; - QString description() const; - Hash hash(Hash::Type t = Hash::Unknown) const; - QString mediaType() const; - QString name() const; - quint64 size() const; - Range range() const; - Thumbnail thumbnail() const; - Histogram audioHistogram() const; - QList audioFloatHistogram() const; + bool merge(const File &other); + bool hasComputedHashes() const; + bool hasSize() const; + + QDateTime date() const; + QString description() const; + QList hashes() const; + Hash hash(Hash::Type t = Hash::Unknown) const; + QString mediaType() const; + QString name() const; + quint64 size() const; + Range range() const; + Thumbnail thumbnail() const; + QByteArray amplitudes() const; void setDate(const QDateTime &date); void setDescription(const QString &desc); @@ -89,69 +77,68 @@ class File void setSize(quint64 size); void setRange(const Range &range = Range()); // default empty just to indicate it's supported void setThumbnail(const Thumbnail &thumb); - void setAudioHistogram(const Histogram &histogram); + void setAmplitudes(const QByteArray &litudes); + private: class Private; - Private *ensureD(); + Private * ensureD(); QSharedDataPointer d; }; -class Checksum : public ContentBase -{ - inline Checksum(){} +class Checksum : public ContentBase { + inline Checksum() {} Checksum(const QDomElement &file); - bool isValid() const; + bool isValid() const; QDomElement toXml(QDomDocument *doc) const; + private: File file; }; -class Received : public ContentBase -{ +class Received : public ContentBase { using ContentBase::ContentBase; QDomElement toXml(QDomDocument *doc) const; }; -class Pad : public ApplicationManagerPad -{ +class Pad : public ApplicationManagerPad { Q_OBJECT // TODO public: Pad(Manager *manager, Session *session); - QDomElement takeOutgoingSessionInfoUpdate() override; - QString ns() const override; - Session *session() const override; + QDomElement takeOutgoingSessionInfoUpdate() override; + QString ns() const override; + Session * session() const override; ApplicationManager *manager() const override; - QString generateContentName(Origin senders) override; + QString generateContentName(Origin senders) override; void addOutgoingOffer(const File &file); + private: Manager *_manager; Session *_session; }; -class Application : public XMPP::Jingle::Application -{ +class Application : public XMPP::Jingle::Application { Q_OBJECT public: Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders); ~Application(); ApplicationManagerPad::Ptr pad() const override; - State state() const override; - void setState(State state) override; - XMPP::Stanza::Error lastError() const override; - Reason terminationReason() const override; - - QString contentName() const override; - Origin creator() const override; - Origin senders() const override; - Origin transportReplaceOrigin() const override; - SetDescError setDescription(const QDomElement &description) override; - void setFile(const File &file); - File file() const; - File acceptFile() const; - bool setTransport(const QSharedPointer &transport) override; + State state() const override; + void setState(State state) override; + XMPP::Stanza::Error lastError() const override; + Reason terminationReason() const override; + + QString contentName() const override; + Origin creator() const override; + Origin senders() const override; + Origin transportReplaceOrigin() const override; + SetDescError setDescription(const QDomElement &description) override; + void setFile(const File &file); + File file() const; + File acceptFile() const; + bool setTransport(const QSharedPointer &transport) override; QSharedPointer transport() const override; /** @@ -166,18 +153,18 @@ class Application : public XMPP::Jingle::Application */ void setStreamingMode(bool mode = true); - Action evaluateOutgoingUpdate() override; + Action evaluateOutgoingUpdate() override; OutgoingUpdate takeOutgoingUpdate() override; - bool wantBetterTransport(const QSharedPointer &) const override; - bool selectNextTransport() override; - void prepare() override; - void start() override; - bool accept(const QDomElement &el) override; - void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) override; + bool wantBetterTransport(const QSharedPointer &) const override; + bool selectNextTransport() override; + void prepare() override; + void start() override; + bool accept(const QDomElement &el) override; + void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) override; bool isValid() const; - void setDevice(QIODevice *dev, bool closeOnFinish = true); + void setDevice(QIODevice *dev, bool closeOnFinish = true); Connection::Ptr connection() const; protected: @@ -185,7 +172,7 @@ class Application : public XMPP::Jingle::Application bool incomingTransportAccept(const QDomElement &transportEl) override; signals: - void connectionReady(); // streaming mode only + void connectionReady(); // streaming mode only void deviceRequested(quint64 offset, quint64 size); // if size = 0 then it's reamaining part of the file (non-streaming mode only) void progress(quint64 offset); @@ -194,19 +181,19 @@ class Application : public XMPP::Jingle::Application QScopedPointer d; }; -class Manager : public XMPP::Jingle::ApplicationManager -{ +class Manager : public XMPP::Jingle::ApplicationManager { Q_OBJECT public: Manager(QObject *parent = nullptr); ~Manager(); - void setJingleManager(XMPP::Jingle::Manager *jm); - Application *startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders); + void setJingleManager(XMPP::Jingle::Manager *jm); + Application * startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders); ApplicationManagerPad *pad(Session *session); // pad factory - void closeAll(); - Client* client(); + void closeAll(); + Client * client(); QStringList availableTransports() const; + private: XMPP::Jingle::Manager *jingleManager = nullptr; }; diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index d68a46cd..6082b215 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -29,6 +29,7 @@ #include #include +#include #define NS_XML "http://www.w3.org/XML/1998/namespace" @@ -37,8 +38,7 @@ QString HASH_NS = QStringLiteral("urn:xmpp:hashes:2"); //---------------------------------------------------------------------------- // Url //---------------------------------------------------------------------------- -class Url::Private -{ +class Url::Private { public: QString url; QString desc; @@ -52,8 +52,8 @@ class Url::Private //! \sa setUrl() setDesc() Url::Url(const QString &url, const QString &desc) { - d = new Private; - d->url = url; + d = new Private; + d->url = url; d->desc = desc; } @@ -63,12 +63,12 @@ Url::Url(const QString &url, const QString &desc) //! \param Url - Url Object Url::Url(const Url &from) { - d = new Private; + d = new Private; *this = from; } //! \brief operator overloader needed for d pointer (Internel). -Url & Url::operator=(const Url &from) +Url &Url::operator=(const Url &from) { *d = *from.d; return *this; @@ -124,20 +124,18 @@ void Url::setDesc(const QString &desc) //! \param Type - type (default: Unknown) //! \param Jid - specify address (default: empty string) //! \sa setType() setJid() -Address::Address(Type type, const Jid & jid) - : v_jid(jid) - , v_delivered(false) - , v_type(type) +Address::Address(Type type, const Jid &jid) : + v_jid(jid), v_delivered(false), v_type(type) { } -Address::Address(const QDomElement& e) - : v_delivered(false) +Address::Address(const QDomElement &e) : + v_delivered(false) { fromXml(e); } -void Address::fromXml(const QDomElement& t) +void Address::fromXml(const QDomElement &t) { setJid(t.attribute("jid")); setUri(t.attribute("uri")); @@ -163,18 +161,18 @@ void Address::fromXml(const QDomElement& t) setType(OriginalTo); } -QDomElement Address::toXml(Stanza& s) const +QDomElement Address::toXml(Stanza &s) const { QDomElement e = s.createElement("http://jabber.org/protocol/address", "address"); - if(!jid().isEmpty()) + if (!jid().isEmpty()) e.setAttribute("jid", jid().full()); - if(!uri().isEmpty()) + if (!uri().isEmpty()) e.setAttribute("uri", uri()); - if(!node().isEmpty()) + if (!node().isEmpty()) e.setAttribute("node", node()); - if(!desc().isEmpty()) + if (!desc().isEmpty()) e.setAttribute("desc", desc()); - if(delivered()) + if (delivered()) e.setAttribute("delivered", "true"); switch (type()) { case To: @@ -211,7 +209,7 @@ QDomElement Address::toXml(Stanza& s) const //! \brief Get Jid information. //! //! Returns jid information. -const Jid& Address::jid() const +const Jid &Address::jid() const { return v_jid; } @@ -219,7 +217,7 @@ const Jid& Address::jid() const //! \brief Get Uri information. //! //! Returns desction of the Address. -const QString& Address::uri() const +const QString &Address::uri() const { return v_uri; } @@ -227,7 +225,7 @@ const QString& Address::uri() const //! \brief Get Node information. //! //! Returns node of the Address. -const QString& Address::node() const +const QString &Address::node() const { return v_node; } @@ -235,7 +233,7 @@ const QString& Address::node() const //! \brief Get Description information. //! //! Returns desction of the Address. -const QString& Address::desc() const +const QString &Address::desc() const { return v_desc; } @@ -313,50 +311,77 @@ void Address::setType(Type type) //---------------------------------------------------------------------------- // Hash //---------------------------------------------------------------------------- +// NOTE: keep this in sync with enum. same order! static const struct { const char *text; - Hash::Type hashType; -} hashTypes[] = -{ -{ "sha-1", Hash::Type::Sha1 }, -{ "sha-256", Hash::Type::Sha256 }, -{ "sha-512", Hash::Type::Sha512 }, -{ "sha3-256", Hash::Type::Sha3_256 }, -{ "sha3-512", Hash::Type::Sha3_512 }, -{ "blake2b-256", Hash::Type::Blake2b256 }, -{ "blake2b-512", Hash::Type::Blake2b512 } + Hash::Type hashType; +} hashTypes[] = { + { "sha-1", Hash::Type::Sha1 }, + { "sha-256", Hash::Type::Sha256 }, + { "sha-512", Hash::Type::Sha512 }, + { "sha3-256", Hash::Type::Sha3_256 }, + { "sha3-512", Hash::Type::Sha3_512 }, + { "blake2b-256", Hash::Type::Blake2b256 }, + { "blake2b-512", Hash::Type::Blake2b512 } }; Hash::Hash(const QDomElement &el) { QString algo = el.attribute(QLatin1String("algo")); + v_type = parseType(QStringRef(&algo)); + if (v_type != Unknown && el.tagName() == QLatin1String("hash")) { + v_data = QByteArray::fromBase64(el.text().toLatin1()); + if (v_data.isEmpty()) { + v_type = Type::Unknown; + } + } +} + +QString Hash::stringType() const +{ + if (!v_type) + return QString(); + static_assert(LastType == (sizeof(hashTypes) / sizeof(hashTypes[0])), "hashType and enum are not in sync"); + return QLatin1String(hashTypes[int(v_type) - 1].text); +} + +Hash::Type Hash::parseType(const QStringRef &algo) +{ if (!algo.isEmpty()) { - for(size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { - if(algo == QLatin1String(hashTypes[n].text)) { - v_type = hashTypes[n].hashType; - if (el.tagName() == QLatin1String("hash")) { - v_data = QByteArray::fromBase64(el.text().toLatin1()); - if (v_data.isEmpty()) { - v_type = Type::Unknown; - } - } // else hash-used - break; + for (size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { + if (algo == QLatin1String(hashTypes[n].text)) { + return hashTypes[n].hashType; } } } + return Unknown; } -bool Hash::computeFromData(const QByteArray &ba) +bool Hash::compute(const QByteArray &ba) { v_data.clear(); switch (v_type) { - case Type::Sha1: v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha1); break; - case Type::Sha256: v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha256); break; - case Type::Sha512: v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha512); break; - case Type::Sha3_256: v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha3_256); break; - case Type::Sha3_512: v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha3_512); break; - case Type::Blake2b256: v_data = computeBlake2Hash(ba, Blake2Digest256); break; - case Type::Blake2b512: v_data = computeBlake2Hash(ba, Blake2Digest512); break; + case Type::Sha1: + v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha1); + break; + case Type::Sha256: + v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha256); + break; + case Type::Sha512: + v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha512); + break; + case Type::Sha3_256: + v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha3_256); + break; + case Type::Sha3_512: + v_data = QCryptographicHash::hash(ba, QCryptographicHash::Sha3_512); + break; + case Type::Blake2b256: + v_data = computeBlake2Hash(ba, Blake2Digest256); + break; + case Type::Blake2b512: + v_data = computeBlake2Hash(ba, Blake2Digest512); + break; case Type::Unknown: default: qDebug("invalid hash type"); @@ -365,16 +390,45 @@ bool Hash::computeFromData(const QByteArray &ba) return !v_data.isEmpty(); } -bool Hash::computeFromDevice(QIODevice *dev) +bool Hash::compute(QIODevice *dev) { switch (v_type) { - case Type::Sha1: { QCryptographicHash h(QCryptographicHash::Sha1); h.addData(dev); v_data = h.result(); break; } - case Type::Sha256: { QCryptographicHash h(QCryptographicHash::Sha256); h.addData(dev); v_data = h.result(); break; } - case Type::Sha512: { QCryptographicHash h(QCryptographicHash::Sha512); h.addData(dev); v_data = h.result(); break; } - case Type::Sha3_256: { QCryptographicHash h(QCryptographicHash::Sha3_256); h.addData(dev); v_data = h.result(); break; } - case Type::Sha3_512: { QCryptographicHash h(QCryptographicHash::Sha3_512); h.addData(dev); v_data = h.result(); break; } - case Type::Blake2b256: v_data = computeBlake2Hash(dev, Blake2Digest256); break; - case Type::Blake2b512: v_data = computeBlake2Hash(dev, Blake2Digest512); break; + case Type::Sha1: { + QCryptographicHash h(QCryptographicHash::Sha1); + h.addData(dev); + v_data = h.result(); + break; + } + case Type::Sha256: { + QCryptographicHash h(QCryptographicHash::Sha256); + h.addData(dev); + v_data = h.result(); + break; + } + case Type::Sha512: { + QCryptographicHash h(QCryptographicHash::Sha512); + h.addData(dev); + v_data = h.result(); + break; + } + case Type::Sha3_256: { + QCryptographicHash h(QCryptographicHash::Sha3_256); + h.addData(dev); + v_data = h.result(); + break; + } + case Type::Sha3_512: { + QCryptographicHash h(QCryptographicHash::Sha3_512); + h.addData(dev); + v_data = h.result(); + break; + } + case Type::Blake2b256: + v_data = computeBlake2Hash(dev, Blake2Digest256); + break; + case Type::Blake2b512: + v_data = computeBlake2Hash(dev, Blake2Digest512); + break; case Type::Unknown: default: qDebug("invalid hash type"); @@ -386,9 +440,9 @@ bool Hash::computeFromDevice(QIODevice *dev) QDomElement Hash::toXml(QDomDocument *doc) const { if (v_type != Type::Unknown) { - for(size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { - if(v_type == hashTypes[n].hashType) { - auto el = doc->createElementNS(HASH_NS, QLatin1String(v_data.isEmpty()? "hash-used": "hash")); + for (size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { + if (v_type == hashTypes[n].hashType) { + auto el = doc->createElementNS(HASH_NS, QLatin1String(v_data.isEmpty() ? "hash-used" : "hash")); el.setAttribute(QLatin1String("algo"), QLatin1String(hashTypes[n].text)); if (!v_data.isEmpty()) { XMLHelper::setTagText(el, v_data.toBase64()); @@ -402,26 +456,59 @@ QDomElement Hash::toXml(QDomDocument *doc) const void Hash::populateFeatures(Features &features) { - for(size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { - features.addFeature(QLatin1String("urn:xmpp:hash-function-text-names:") + - QLatin1String(hashTypes[n].text)); + for (size_t n = 0; n < sizeof(hashTypes) / sizeof(hashTypes[0]); ++n) { + features.addFeature(QLatin1String("urn:xmpp:hash-function-text-names:") + QLatin1String(hashTypes[n].text)); + } +} + +Hash Hash::from(XMPP::Hash::Type t, const QByteArray &fileData) +{ + Hash h(t); + if (!h.compute(fileData)) + h.setType(Unknown); + return h; +} + +Hash Hash::from(XMPP::Hash::Type t, QIODevice *dev) +{ + Hash h(t); + if (!h.compute(dev)) + h.setType(Unknown); + return h; +} + +Hash Hash::from(const QStringRef &str) +{ + auto ind = str.indexOf('+'); + if (ind <= 0) + return Hash(); + Hash hash(str.left(ind)); + if (hash.isValid()) { + auto data = QByteArray::fromHex(str.mid(ind + 1).toLatin1()); + if (data.size()) + hash.setData(data); + else + hash = Hash(); } + return hash; } //---------------------------------------------------------------------------- // RosterExchangeItem //---------------------------------------------------------------------------- -RosterExchangeItem::RosterExchangeItem(const Jid& jid, const QString& name, const QStringList& groups, Action action) : jid_(jid), name_(name), groups_(groups), action_(action) +RosterExchangeItem::RosterExchangeItem(const Jid &jid, const QString &name, const QStringList &groups, Action action) : + jid_(jid), name_(name), groups_(groups), action_(action) { } -RosterExchangeItem::RosterExchangeItem(const QDomElement& el) : action_(Add) +RosterExchangeItem::RosterExchangeItem(const QDomElement &el) : + action_(Add) { fromXml(el); } -const Jid& RosterExchangeItem::jid() const +const Jid &RosterExchangeItem::jid() const { return jid_; } @@ -431,12 +518,12 @@ RosterExchangeItem::Action RosterExchangeItem::action() const return action_; } -const QString& RosterExchangeItem::name() const +const QString &RosterExchangeItem::name() const { return name_; } -const QStringList& RosterExchangeItem::groups() const +const QStringList &RosterExchangeItem::groups() const { return groups_; } @@ -446,7 +533,7 @@ bool RosterExchangeItem::isNull() const return jid_.isEmpty(); } -void RosterExchangeItem::setJid(const Jid& jid) +void RosterExchangeItem::setJid(const Jid &jid) { jid_ = jid; } @@ -456,54 +543,52 @@ void RosterExchangeItem::setAction(Action action) action_ = action; } -void RosterExchangeItem::setName(const QString& name) +void RosterExchangeItem::setName(const QString &name) { name_ = name; } -void RosterExchangeItem::setGroups(const QStringList& groups) +void RosterExchangeItem::setGroups(const QStringList &groups) { groups_ = groups; } -QDomElement RosterExchangeItem::toXml(Stanza& s) const +QDomElement RosterExchangeItem::toXml(Stanza &s) const { QDomElement e = s.createElement("http://jabber.org/protocol/rosterx", "item"); e.setAttribute("jid", jid().full()); if (!name().isEmpty()) e.setAttribute("name", name()); - switch(action()) { + switch (action()) { case Add: - e.setAttribute("action","add"); + e.setAttribute("action", "add"); break; case Delete: - e.setAttribute("action","delete"); + e.setAttribute("action", "delete"); break; case Modify: - e.setAttribute("action","modify"); + e.setAttribute("action", "modify"); break; } - foreach(QString group, groups_) { - e.appendChild(s.createTextElement("http://jabber.org/protocol/rosterx", "group",group)); + foreach (QString group, groups_) { + e.appendChild(s.createTextElement("http://jabber.org/protocol/rosterx", "group", group)); } return e; } -void RosterExchangeItem::fromXml(const QDomElement& e) +void RosterExchangeItem::fromXml(const QDomElement &e) { setJid(e.attribute("jid")); setName(e.attribute("name")); if (e.attribute("action") == "delete") { setAction(Delete); - } - else if (e.attribute("action") == "modify") { + } else if (e.attribute("action") == "modify") { setAction(Modify); - } - else { + } else { setAction(Add); } QDomNodeList nl = e.childNodes(); - for(int n = 0; n < nl.count(); ++n) { + for (int n = 0; n < nl.count(); ++n) { QDomElement g = nl.item(n).toElement(); if (!g.isNull() && g.tagName() == "group") { groups_ += g.text(); @@ -514,21 +599,23 @@ void RosterExchangeItem::fromXml(const QDomElement& e) //---------------------------------------------------------------------------- // MUCItem //---------------------------------------------------------------------------- -MUCItem::MUCItem(Role r, Affiliation a) : affiliation_(a), role_(r) +MUCItem::MUCItem(Role r, Affiliation a) : + affiliation_(a), role_(r) { } -MUCItem::MUCItem(const QDomElement& el) : affiliation_(UnknownAffiliation), role_(UnknownRole) +MUCItem::MUCItem(const QDomElement &el) : + affiliation_(UnknownAffiliation), role_(UnknownRole) { fromXml(el); } -void MUCItem::setNick(const QString& n) +void MUCItem::setNick(const QString &n) { nick_ = n; } -void MUCItem::setJid(const Jid& j) +void MUCItem::setJid(const Jid &j) { jid_ = j; } @@ -543,22 +630,22 @@ void MUCItem::setRole(Role r) role_ = r; } -void MUCItem::setActor(const Jid& a) +void MUCItem::setActor(const Jid &a) { actor_ = a; } -void MUCItem::setReason(const QString& r) +void MUCItem::setReason(const QString &r) { reason_ = r; } -const QString& MUCItem::nick() const +const QString &MUCItem::nick() const { return nick_; } -const Jid& MUCItem::jid() const +const Jid &MUCItem::jid() const { return jid_; } @@ -573,58 +660,51 @@ MUCItem::Role MUCItem::role() const return role_; } -const Jid& MUCItem::actor() const +const Jid &MUCItem::actor() const { return actor_; } -const QString& MUCItem::reason() const +const QString &MUCItem::reason() const { return reason_; } -void MUCItem::fromXml(const QDomElement& e) +void MUCItem::fromXml(const QDomElement &e) { if (e.tagName() != QLatin1String("item")) return; - jid_ = Jid(e.attribute("jid")); + jid_ = Jid(e.attribute("jid")); nick_ = e.attribute(QLatin1String("nick")); // Affiliation if (e.attribute(QLatin1String("affiliation")) == QLatin1String("owner")) { affiliation_ = Owner; - } - else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("admin")) { + } else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("admin")) { affiliation_ = Admin; - } - else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("member")) { + } else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("member")) { affiliation_ = Member; - } - else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("outcast")) { + } else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("outcast")) { affiliation_ = Outcast; - } - else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("none")) { + } else if (e.attribute(QLatin1String("affiliation")) == QLatin1String("none")) { affiliation_ = NoAffiliation; } // Role if (e.attribute(QLatin1String("role")) == QLatin1String("moderator")) { role_ = Moderator; - } - else if (e.attribute(QLatin1String("role")) == QLatin1String("participant")) { + } else if (e.attribute(QLatin1String("role")) == QLatin1String("participant")) { role_ = Participant; - } - else if (e.attribute(QLatin1String("role")) == QLatin1String("visitor")) { + } else if (e.attribute(QLatin1String("role")) == QLatin1String("visitor")) { role_ = Visitor; - } - else if (e.attribute(QLatin1String("role")) == QLatin1String("none")) { + } else if (e.attribute(QLatin1String("role")) == QLatin1String("none")) { role_ = NoRole; } - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; if (i.tagName() == QLatin1String("actor")) @@ -634,50 +714,50 @@ void MUCItem::fromXml(const QDomElement& e) } } -QDomElement MUCItem::toXml(QDomDocument& d) +QDomElement MUCItem::toXml(QDomDocument &d) { QDomElement e = d.createElement("item"); if (!nick_.isEmpty()) - e.setAttribute("nick",nick_); + e.setAttribute("nick", nick_); if (!jid_.isEmpty()) - e.setAttribute("jid",jid_.full()); + e.setAttribute("jid", jid_.full()); if (!reason_.isEmpty()) - e.appendChild(textTag(&d,"reason",reason_)); + e.appendChild(textTag(&d, "reason", reason_)); switch (affiliation_) { case NoAffiliation: - e.setAttribute("affiliation","none"); + e.setAttribute("affiliation", "none"); break; case Owner: - e.setAttribute("affiliation","owner"); + e.setAttribute("affiliation", "owner"); break; case Admin: - e.setAttribute("affiliation","admin"); + e.setAttribute("affiliation", "admin"); break; case Member: - e.setAttribute("affiliation","member"); + e.setAttribute("affiliation", "member"); break; case Outcast: - e.setAttribute("affiliation","outcast"); + e.setAttribute("affiliation", "outcast"); break; default: break; } switch (role_) { case NoRole: - e.setAttribute("role","none"); + e.setAttribute("role", "none"); break; case Moderator: - e.setAttribute("role","moderator"); + e.setAttribute("role", "moderator"); break; case Participant: - e.setAttribute("role","participant"); + e.setAttribute("role", "participant"); break; case Visitor: - e.setAttribute("role","visitor"); + e.setAttribute("role", "visitor"); break; default: break; @@ -686,54 +766,57 @@ QDomElement MUCItem::toXml(QDomDocument& d) return e; } -bool MUCItem::operator==(const MUCItem& o) +bool MUCItem::operator==(const MUCItem &o) { - return !nick_.compare(o.nick_) && ((!jid_.isValid() && !o.jid_.isValid()) || jid_.compare(o.jid_,true)) && ((!actor_.isValid() && !o.actor_.isValid()) || actor_.compare(o.actor_,true)) && affiliation_ == o.affiliation_ && role_ == o.role_ && !reason_.compare(o.reason_); + return !nick_.compare(o.nick_) && ((!jid_.isValid() && !o.jid_.isValid()) || jid_.compare(o.jid_, true)) && ((!actor_.isValid() && !o.actor_.isValid()) || actor_.compare(o.actor_, true)) && affiliation_ == o.affiliation_ && role_ == o.role_ && !reason_.compare(o.reason_); } //---------------------------------------------------------------------------- // MUCInvite //---------------------------------------------------------------------------- -MUCInvite::MUCInvite() : cont_(false) +MUCInvite::MUCInvite() : + cont_(false) { } -MUCInvite::MUCInvite(const Jid& to, const QString& reason) : to_(to), reason_(reason), cont_(false) +MUCInvite::MUCInvite(const Jid &to, const QString &reason) : + to_(to), reason_(reason), cont_(false) { } -MUCInvite::MUCInvite(const QDomElement& e) : cont_(false) +MUCInvite::MUCInvite(const QDomElement &e) : + cont_(false) { fromXml(e); } -const Jid& MUCInvite::from() const +const Jid &MUCInvite::from() const { return from_; } -void MUCInvite::setFrom(const Jid& j) +void MUCInvite::setFrom(const Jid &j) { from_ = j; } -const Jid& MUCInvite::to() const +const Jid &MUCInvite::to() const { return to_; } -void MUCInvite::setTo(const Jid& j) +void MUCInvite::setTo(const Jid &j) { to_ = j; } -const QString& MUCInvite::reason() const +const QString &MUCInvite::reason() const { return reason_; } -void MUCInvite::setReason(const QString& r) +void MUCInvite::setReason(const QString &r) { reason_ = r; } @@ -748,16 +831,16 @@ void MUCInvite::setCont(bool b) cont_ = b; } -void MUCInvite::fromXml(const QDomElement& e) +void MUCInvite::fromXml(const QDomElement &e) { if (e.tagName() != "invite") return; from_ = e.attribute("from"); - to_ = e.attribute("to"); - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + to_ = e.attribute("to"); + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; if (i.tagName() == "continue") @@ -767,14 +850,14 @@ void MUCInvite::fromXml(const QDomElement& e) } } -QDomElement MUCInvite::toXml(QDomDocument& d) const +QDomElement MUCInvite::toXml(QDomDocument &d) const { QDomElement invite = d.createElement("invite"); if (!to_.isEmpty()) { - invite.setAttribute("to",to_.full()); + invite.setAttribute("to", to_.full()); } if (!from_.isEmpty()) { - invite.setAttribute("from",from_.full()); + invite.setAttribute("from", from_.full()); } if (!reason_.isEmpty()) { invite.appendChild(textTag(&d, "reason", reason_)); @@ -798,51 +881,51 @@ MUCDecline::MUCDecline() { } -MUCDecline::MUCDecline(const QDomElement& e) +MUCDecline::MUCDecline(const QDomElement &e) { fromXml(e); } -const Jid& MUCDecline::from() const +const Jid &MUCDecline::from() const { return from_; } -void MUCDecline::setFrom(const Jid& j) +void MUCDecline::setFrom(const Jid &j) { from_ = j; } -const Jid& MUCDecline::to() const +const Jid &MUCDecline::to() const { return to_; } -void MUCDecline::setTo(const Jid& j) +void MUCDecline::setTo(const Jid &j) { to_ = j; } -const QString& MUCDecline::reason() const +const QString &MUCDecline::reason() const { return reason_; } -void MUCDecline::setReason(const QString& r) +void MUCDecline::setReason(const QString &r) { reason_ = r; } -void MUCDecline::fromXml(const QDomElement& e) +void MUCDecline::fromXml(const QDomElement &e) { if (e.tagName() != "decline") return; from_ = e.attribute("from"); - to_ = e.attribute("to"); - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + to_ = e.attribute("to"); + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; if (i.tagName() == "reason") @@ -850,14 +933,14 @@ void MUCDecline::fromXml(const QDomElement& e) } } -QDomElement MUCDecline::toXml(QDomDocument& d) const +QDomElement MUCDecline::toXml(QDomDocument &d) const { QDomElement decline = d.createElement("decline"); if (!to_.isEmpty()) { - decline.setAttribute("to",to_.full()); + decline.setAttribute("to", to_.full()); } if (!from_.isEmpty()) { - decline.setAttribute("from",from_.full()); + decline.setAttribute("from", from_.full()); } if (!reason_.isEmpty()) { decline.appendChild(textTag(&d, "reason", reason_)); @@ -878,40 +961,40 @@ MUCDestroy::MUCDestroy() { } -MUCDestroy::MUCDestroy(const QDomElement& e) +MUCDestroy::MUCDestroy(const QDomElement &e) { fromXml(e); } -const Jid& MUCDestroy::jid() const +const Jid &MUCDestroy::jid() const { return jid_; } -void MUCDestroy::setJid(const Jid& j) +void MUCDestroy::setJid(const Jid &j) { jid_ = j; } -const QString& MUCDestroy::reason() const +const QString &MUCDestroy::reason() const { return reason_; } -void MUCDestroy::setReason(const QString& r) +void MUCDestroy::setReason(const QString &r) { reason_ = r; } -void MUCDestroy::fromXml(const QDomElement& e) +void MUCDestroy::fromXml(const QDomElement &e) { if (e.tagName() != "destroy") return; jid_ = e.attribute("jid"); - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; if (i.tagName() == "reason") @@ -919,11 +1002,11 @@ void MUCDestroy::fromXml(const QDomElement& e) } } -QDomElement MUCDestroy::toXml(QDomDocument& d) const +QDomElement MUCDestroy::toXml(QDomDocument &d) const { QDomElement destroy = d.createElement("destroy"); if (!jid_.isEmpty()) { - destroy.setAttribute("jid",jid_.full()); + destroy.setAttribute("jid", jid_.full()); } if (!reason_.isEmpty()) { destroy.appendChild(textTag(&d, "reason", reason_)); @@ -945,7 +1028,7 @@ void HTMLElement::setBody(const QDomElement &body) body_ = doc_.importNode(body, true).toElement(); } -const QDomElement& HTMLElement::body() const +const QDomElement &HTMLElement::body() const { return body_; } @@ -970,7 +1053,7 @@ QString HTMLElement::toString(const QString &rootTagName) const // msg.appendChild(e); // return msg.toString(); // call Stream::xmlToString, to remove unwanted namespace attributes - return(Stream::xmlToString(e)); + return (Stream::xmlToString(e)); } QString HTMLElement::text() const @@ -988,7 +1071,8 @@ void HTMLElement::filterOutUnwantedRecursive(QDomElement &el, bool strict) { Q_UNUSED(strict) //TODO filter out not xhtml-im elements - static QSet unwanted = QSet()<<"script"<<"iframe"; + static QSet unwanted = QSet() << "script" + << "iframe"; QDomNode child = el.firstChild(); while (!child.isNull()) { QDomNode sibling = child.nextSibling(); @@ -996,18 +1080,17 @@ void HTMLElement::filterOutUnwantedRecursive(QDomElement &el, bool strict) QDomElement childEl = child.toElement(); if (unwanted.contains(childEl.tagName())) { child.parentNode().removeChild(child); - } - else { + } else { QDomNamedNodeMap domAttrs = childEl.attributes(); - int acnt = domAttrs.count(); - QStringList attrs; //attributes for removing - for (int i=0; i pubsubItems; - QList pubsubRetractions; - QList eventList; - ChatState chatState = StateNone; - MessageReceipt messageReceipt = ReceiptNone; - HttpAuthRequest httpAuthRequest; - XData xdata; - IBBData ibbData; - QMap htmlElements; - QDomElement sxe; - QList bobDataList; - Jid forwardedFrom; - - QList mucStatuses; + QDateTime timeStamp; // local time + bool timeStampSend = false; + UrlList urlList; + AddressList addressList; + RosterExchangeItems rosterExchangeItems; + QString messageReceiptId; + QString nick; + QString eventId; + QString xsigned, xencrypted, invite; + QString pubsubNode; + QList pubsubItems; + QList pubsubRetractions; + QList eventList; + ChatState chatState = StateNone; + MessageReceipt messageReceipt = ReceiptNone; + HttpAuthRequest httpAuthRequest; + XData xdata; + IBBData ibbData; + QMap htmlElements; + QDomElement sxe; + QList bobDataList; + Jid forwardedFrom; + + QList mucStatuses; QList mucInvites; - MUCDecline mucDecline; - QString mucPassword; - bool hasMUCUser = false; + MUCDecline mucDecline; + QString mucPassword; + bool hasMUCUser = false; bool spooled = false, wasEncrypted = false; //XEP-0280 Message Carbons - bool isDisabledCarbons = false; - Message::CarbonDir carbonDir = Message::NoCarbon; // it's a forwarded message + bool isDisabledCarbons = false; + Message::CarbonDir carbonDir = Message::NoCarbon; // it's a forwarded message Message::ProcessingHints processingHints; - QString replaceId; - QString originId; // XEP-0359 - Message::StanzaId stanzaId; // XEP-0359 - QList references; // XEP-0385 and XEP-0372 + QString replaceId; + QString originId; // XEP-0359 + Message::StanzaId stanzaId; // XEP-0359 + QList references; // XEP-0385 and XEP-0372 }; -#define MessageD() (d? d : (d = new Private)) +#define MessageD() (d ? d : (d = new Private)) //! \brief Constructs Message with given Jid information. //! //! This function will construct a Message container. //! \param to - specify receiver (default: empty string) Message::Message() { - } -Message::Message(const Jid &to) - : d(new Private) +Message::Message(const Jid &to) : + d(new Private) { d->to = to; } @@ -1100,7 +1181,7 @@ Message::Message(const Message &from) : } //! \brief Required for internel use. -Message & Message::operator=(const Message &from) +Message &Message::operator=(const Message &from) { d = from.d; return *this; @@ -1120,46 +1201,46 @@ bool Message::operator==(const Message &from) const //! \brief Return receiver's Jid information. Jid Message::to() const { - return d? d->to: Jid(); + return d ? d->to : Jid(); } //! \brief Return sender's Jid information. Jid Message::from() const { - return d? d->from: Jid(); + return d ? d->from : Jid(); } QString Message::id() const { - return d? d->id: QString(); + return d ? d->id : QString(); } //! \brief Return type information QString Message::type() const { - return d? d->type: QString(); + return d ? d->type : QString(); } QString Message::lang() const { - return d? d->lang: QString(); + return d ? d->lang : QString(); } //! \brief Return subject information. QString Message::subject(const QString &lang) const { - return d? d->subject.value(lang): QString(); + return d ? d->subject.value(lang) : QString(); } //! \brief Return subject information. QString Message::subject(const QLocale &lang) const { - return d? d->subject.value(lang.bcp47Name()): QString(); + return d ? d->subject.value(lang.bcp47Name()) : QString(); } StringMap Message::subjectMap() const { - return d? d->subject: StringMap(); + return d ? d->subject : StringMap(); } //! \brief Return body information. @@ -1200,13 +1281,12 @@ QString Message::body(const QLocale &lang) const //! \note The return string is in xhtml HTMLElement Message::html(const QString &lang) const { - if(containsHTML()) { + if (containsHTML()) { if (d->htmlElements.contains(lang)) return d->htmlElements[lang]; else return d->htmlElements.begin().value(); - } - else + } else return HTMLElement(); } @@ -1221,12 +1301,12 @@ bool Message::containsHTML() const QString Message::thread() const { - return d? d->thread: QString(); + return d ? d->thread : QString(); } Stanza::Error Message::error() const { - return d? d->error: Stanza::Error(); + return d ? d->error : Stanza::Error(); } //! \brief Set receivers information @@ -1296,7 +1376,7 @@ void Message::setHTML(const HTMLElement &e, const QString &lang) void Message::setThread(const QString &s, bool send) { MessageD()->threadSend = send; - d->thread = s; + d->thread = s; } void Message::setError(const Stanza::Error &err) @@ -1306,34 +1386,34 @@ void Message::setError(const Stanza::Error &err) QString Message::pubsubNode() const { - return d? d->pubsubNode: QString(); + return d ? d->pubsubNode : QString(); } QList Message::pubsubItems() const { - return d? d->pubsubItems: QList(); + return d ? d->pubsubItems : QList(); } QList Message::pubsubRetractions() const { - return d? d->pubsubRetractions: QList(); + return d ? d->pubsubRetractions : QList(); } QDateTime Message::timeStamp() const { - return d? d->timeStamp: QDateTime(); + return d ? d->timeStamp : QDateTime(); } void Message::setTimeStamp(const QDateTime &ts, bool send) { MessageD()->timeStampSend = send; - d->timeStamp = ts; + d->timeStamp = ts; } //! \brief Return list of urls attached to message. UrlList Message::urlList() const { - return d? d->urlList: UrlList(); + return d ? d->urlList : UrlList(); } //! \brief Add Url to the url list. @@ -1363,7 +1443,7 @@ void Message::setUrlList(const UrlList &list) //! \brief Return list of addresses attached to message. AddressList Message::addresses() const { - return d? d->addressList : AddressList(); + return d ? d->addressList : AddressList(); } //! \brief Add Address to the address list. @@ -1388,7 +1468,7 @@ AddressList Message::findAddresses(Address::Type t) const return AddressList(); } AddressList matches; - foreach(Address a, d->addressList) { + foreach (Address a, d->addressList) { if (a.type() == t) matches.append(a); } @@ -1405,20 +1485,20 @@ void Message::setAddresses(const AddressList &list) RosterExchangeItems Message::rosterExchangeItems() const { - return d? d->rosterExchangeItems : RosterExchangeItems(); + return d ? d->rosterExchangeItems : RosterExchangeItems(); } -void Message::setRosterExchangeItems(const RosterExchangeItems& items) +void Message::setRosterExchangeItems(const RosterExchangeItems &items) { MessageD()->rosterExchangeItems = items; } QString Message::eventId() const { - return d? d->eventId: QString(); + return d ? d->eventId : QString(); } -void Message::setEventId(const QString& id) +void Message::setEventId(const QString &id) { MessageD()->eventId = id; } @@ -1444,7 +1524,7 @@ void Message::addEvent(MsgEvent e) ChatState Message::chatState() const { - return d? d->chatState : StateNone; + return d ? d->chatState : StateNone; } void Message::setChatState(ChatState state) @@ -1454,7 +1534,7 @@ void Message::setChatState(ChatState state) MessageReceipt Message::messageReceipt() const { - return d? d->messageReceipt: ReceiptNone; + return d ? d->messageReceipt : ReceiptNone; } void Message::setMessageReceipt(MessageReceipt messageReceipt) @@ -1464,7 +1544,7 @@ void Message::setMessageReceipt(MessageReceipt messageReceipt) QString Message::messageReceiptId() const { - return d? d->messageReceiptId: QString(); + return d ? d->messageReceiptId : QString(); } void Message::setMessageReceiptId(const QString &s) @@ -1474,7 +1554,7 @@ void Message::setMessageReceiptId(const QString &s) QString Message::xsigned() const { - return d? d->xsigned: QString(); + return d ? d->xsigned : QString(); } void Message::setXSigned(const QString &s) @@ -1484,7 +1564,7 @@ void Message::setXSigned(const QString &s) QString Message::xencrypted() const { - return d? d->xencrypted: QString(); + return d ? d->xencrypted : QString(); } void Message::setXEncrypted(const QString &s) @@ -1494,7 +1574,7 @@ void Message::setXEncrypted(const QString &s) QList Message::getMUCStatuses() const { - return d? d->mucStatuses: QList(); + return d ? d->mucStatuses : QList(); } void Message::addMUCStatus(int i) @@ -1502,32 +1582,32 @@ void Message::addMUCStatus(int i) MessageD()->mucStatuses += i; } -void Message::addMUCInvite(const MUCInvite& i) +void Message::addMUCInvite(const MUCInvite &i) { MessageD()->mucInvites += i; } QList Message::mucInvites() const { - return d? d->mucInvites: QList(); + return d ? d->mucInvites : QList(); } -void Message::setMUCDecline(const MUCDecline& de) +void Message::setMUCDecline(const MUCDecline &de) { MessageD()->mucDecline = de; } MUCDecline Message::mucDecline() const { - return d? d->mucDecline: MUCDecline(); + return d ? d->mucDecline : MUCDecline(); } QString Message::mucPassword() const { - return d? d->mucPassword: QString(); + return d ? d->mucPassword : QString(); } -void Message::setMUCPassword(const QString& p) +void Message::setMUCPassword(const QString &p) { MessageD()->mucPassword = p; } @@ -1539,7 +1619,7 @@ bool Message::hasMUCUser() const Message::StanzaId Message::stanzaId() const { - return d? d->stanzaId: StanzaId(); + return d ? d->stanzaId : StanzaId(); } void Message::setStanzaId(const Message::StanzaId &id) @@ -1549,7 +1629,7 @@ void Message::setStanzaId(const Message::StanzaId &id) QString Message::originId() const { - return d? d->originId: QString(); + return d ? d->originId : QString(); } void Message::setOriginId(const QString &id) @@ -1559,7 +1639,7 @@ void Message::setOriginId(const QString &id) QList Message::references() const { - return d? d->references: QList(); + return d ? d->references : QList(); } void Message::addReference(const Reference &r) @@ -1574,7 +1654,7 @@ void Message::setReferences(const QList &r) QString Message::invite() const { - return d? d->invite: QString(); + return d ? d->invite : QString(); } void Message::setInvite(const QString &s) @@ -1584,10 +1664,10 @@ void Message::setInvite(const QString &s) QString Message::nick() const { - return d? d->nick: QString(); + return d ? d->nick : QString(); } -void Message::setNick(const QString& n) +void Message::setNick(const QString &n) { MessageD()->nick = n; } @@ -1599,7 +1679,7 @@ void Message::setHttpAuthRequest(const HttpAuthRequest &req) HttpAuthRequest Message::httpAuthRequest() const { - return d? d->httpAuthRequest: HttpAuthRequest(); + return d ? d->httpAuthRequest : HttpAuthRequest(); } void Message::setForm(const XData &form) @@ -1609,15 +1689,15 @@ void Message::setForm(const XData &form) XData Message::getForm() const { - return d? d->xdata: XData(); + return d ? d->xdata : XData(); } QDomElement Message::sxe() const { - return d? d->sxe: QDomElement(); + return d ? d->sxe : QDomElement(); } -void Message::setSxe(const QDomElement& e) +void Message::setSxe(const QDomElement &e) { MessageD()->sxe = e; } @@ -1629,12 +1709,12 @@ void Message::addBoBData(const BoBData &bob) QList Message::bobDataList() const { - return d? d->bobDataList: QList(); + return d ? d->bobDataList : QList(); } IBBData Message::ibbData() const { - return d? d->ibbData: IBBData(); + return d ? d->ibbData : IBBData(); } void Message::setDisabledCarbons(bool disabled) @@ -1654,7 +1734,7 @@ void Message::setCarbonDirection(Message::CarbonDir cd) Message::CarbonDir Message::carbonDirection() const { - return d? d->carbonDir: NoCarbon; + return d ? d->carbonDir : NoCarbon; } void Message::setForwardedFrom(const Jid &jid) @@ -1664,7 +1744,7 @@ void Message::setForwardedFrom(const Jid &jid) Jid Message::forwardedFrom() const { - return d? d->forwardedFrom: Jid(); + return d ? d->forwardedFrom : Jid(); } bool Message::spooled() const @@ -1687,11 +1767,12 @@ void Message::setWasEncrypted(bool b) MessageD()->wasEncrypted = b; } -QString Message::replaceId() const { - return d? d->replaceId: QString(); +QString Message::replaceId() const +{ + return d ? d->replaceId : QString(); } -void Message::setReplaceId(const QString& id) +void Message::setReplaceId(const QString &id) { MessageD()->replaceId = id; } @@ -1703,7 +1784,7 @@ void Message::setProcessingHints(const ProcessingHints &hints) Message::ProcessingHints Message::processingHints() const { - return d? d->processingHints: ProcessingHints(); + return d ? d->processingHints : ProcessingHints(); } Stanza Message::toStanza(Stream *stream) const @@ -1712,28 +1793,28 @@ Stanza Message::toStanza(Stream *stream) const return Stanza(); } Stanza s = stream->createStanza(Stanza::Message, d->to, d->type); - if(!d->from.isEmpty()) + if (!d->from.isEmpty()) s.setFrom(d->from); - if(!d->id.isEmpty()) + if (!d->id.isEmpty()) s.setId(d->id); - if(!d->lang.isEmpty()) + if (!d->lang.isEmpty()) s.setLang(d->lang); StringMap::ConstIterator it; for (it = d->subject.constBegin(); it != d->subject.constEnd(); ++it) { const QString &str = (*it); - if(!str.isNull()) { + if (!str.isNull()) { QDomElement e = s.createTextElement(s.baseNS(), "subject", str); - if(!it.key().isEmpty()) + if (!it.key().isEmpty()) e.setAttributeNS(NS_XML, "xml:lang", it.key()); s.appendChild(e); } } for (it = d->body.constBegin(); it != d->body.constEnd(); ++it) { const QString &str = (*it); - if(!str.isEmpty()) { + if (!str.isEmpty()) { QDomElement e = s.createTextElement(s.baseNS(), "body", str); - if(!it.key().isEmpty()) + if (!it.key().isEmpty()) e.setAttributeNS(NS_XML, "xml:lang", it.key()); s.appendChild(e); } @@ -1747,17 +1828,17 @@ Stanza Message::toStanza(Stream *stream) const } } - if(d->type == "error") + if (d->type == "error") s.setError(d->error); // thread - if(d->threadSend && !d->thread.isEmpty()) { + if (d->threadSend && !d->thread.isEmpty()) { QDomElement e = s.createTextElement(s.baseNS(), "thread", d->thread); s.appendChild(e); } // timestamp - if(d->timeStampSend && !d->timeStamp.isNull()) { + if (d->timeStampSend && !d->timeStamp.isNull()) { QDomElement e = s.createElement("urn:xmpp:delay", "delay"); e.setAttribute("stamp", d->timeStamp.toUTC().toString(Qt::ISODate) + "Z"); s.appendChild(e); @@ -1768,7 +1849,7 @@ Stanza Message::toStanza(Stream *stream) const } // urls - foreach (const Url& uit, d->urlList) { + foreach (const Url &uit, d->urlList) { QDomElement x = s.createElement("jabber:x:oob", "x"); x.appendChild(s.createTextElement("jabber:x:oob", "url", uit.url())); if (!uit.desc().isEmpty()) @@ -1782,12 +1863,12 @@ Stanza Message::toStanza(Stream *stream) const if (d->body.isEmpty()) { if (d->eventId.isEmpty()) - x.appendChild(s.createElement("jabber:x:event","id")); + x.appendChild(s.createElement("jabber:x:event", "id")); else - x.appendChild(s.createTextElement("jabber:x:event","id",d->eventId)); + x.appendChild(s.createTextElement("jabber:x:event", "id", d->eventId)); } - foreach (const MsgEvent& ev, d->eventList) { + foreach (const MsgEvent &ev, d->eventList) { switch (ev) { case OfflineEvent: x.appendChild(s.createElement("jabber:x:event", "offline")); @@ -1812,7 +1893,7 @@ Stanza Message::toStanza(Stream *stream) const // chat state QString chatStateNS = "http://jabber.org/protocol/chatstates"; if (d->chatState != StateNone) { - switch(d->chatState) { + switch (d->chatState) { case StateActive: s.appendChild(s.createElement(chatStateNS, "active")); break; @@ -1836,36 +1917,34 @@ Stanza Message::toStanza(Stream *stream) const // message receipt QString messageReceiptNS = "urn:xmpp:receipts"; if (d->messageReceipt != ReceiptNone) { - switch(d->messageReceipt) { + switch (d->messageReceipt) { case ReceiptRequest: s.appendChild(s.createElement(messageReceiptNS, "request")); break; - case ReceiptReceived: - { + case ReceiptReceived: { QDomElement elem = s.createElement(messageReceiptNS, "received"); if (!d->messageReceiptId.isEmpty()) { elem.setAttribute("id", d->messageReceiptId); } s.appendChild(elem); - } - break; + } break; default: break; } } // xsigned - if(!d->xsigned.isEmpty()) + if (!d->xsigned.isEmpty()) s.appendChild(s.createTextElement("jabber:x:signed", "x", d->xsigned)); // xencrypted - if(!d->xencrypted.isEmpty()) + if (!d->xencrypted.isEmpty()) s.appendChild(s.createTextElement("jabber:x:encrypted", "x", d->xencrypted)); // addresses if (!d->addressList.isEmpty()) { - QDomElement as = s.createElement("http://jabber.org/protocol/address","addresses"); - foreach(Address a, d->addressList) { + QDomElement as = s.createElement("http://jabber.org/protocol/address", "addresses"); + foreach (Address a, d->addressList) { as.appendChild(a.toXml(s)); } s.appendChild(as); @@ -1873,56 +1952,55 @@ Stanza Message::toStanza(Stream *stream) const // roster item exchange if (!d->rosterExchangeItems.isEmpty()) { - QDomElement rx = s.createElement("http://jabber.org/protocol/rosterx","x"); - foreach(RosterExchangeItem r, d->rosterExchangeItems) { + QDomElement rx = s.createElement("http://jabber.org/protocol/rosterx", "x"); + foreach (RosterExchangeItem r, d->rosterExchangeItems) { rx.appendChild(r.toXml(s)); } s.appendChild(rx); } // invite - if(!d->invite.isEmpty()) { + if (!d->invite.isEmpty()) { QDomElement e = s.createElement("jabber:x:conference", "x"); e.setAttribute("jid", d->invite); s.appendChild(e); } // nick - if(!d->nick.isEmpty()) { + if (!d->nick.isEmpty()) { s.appendChild(s.createTextElement("http://jabber.org/protocol/nick", "nick", d->nick)); } // sxe - if(!d->sxe.isNull()) { + if (!d->sxe.isNull()) { s.appendChild(d->sxe); } // muc - if(!d->mucInvites.isEmpty()) { - QDomElement e = s.createElement("http://jabber.org/protocol/muc#user","x"); - foreach(MUCInvite i, d->mucInvites) { + if (!d->mucInvites.isEmpty()) { + QDomElement e = s.createElement("http://jabber.org/protocol/muc#user", "x"); + foreach (MUCInvite i, d->mucInvites) { e.appendChild(i.toXml(s.doc())); } if (!d->mucPassword.isEmpty()) { - e.appendChild(s.createTextElement("http://jabber.org/protocol/muc#user","password",d->mucPassword)); + e.appendChild(s.createTextElement("http://jabber.org/protocol/muc#user", "password", d->mucPassword)); } s.appendChild(e); - } - else if(!d->mucDecline.isNull()) { - QDomElement e = s.createElement("http://jabber.org/protocol/muc#user","x"); + } else if (!d->mucDecline.isNull()) { + QDomElement e = s.createElement("http://jabber.org/protocol/muc#user", "x"); e.appendChild(d->mucDecline.toXml(s.doc())); s.appendChild(e); } // http auth - if(!d->httpAuthRequest.isEmpty()) { + if (!d->httpAuthRequest.isEmpty()) { s.appendChild(d->httpAuthRequest.toXml(s.doc())); } // data form - if(!d->xdata.fields().empty() || (d->xdata.type() == XData::Data_Cancel)) { - bool submit = (d->xdata.type() == XData::Data_Submit) || (d->xdata.type() == XData::Data_Cancel); - QDomElement dr = s.element(); + if (!d->xdata.fields().empty() || (d->xdata.type() == XData::Data_Cancel)) { + bool submit = (d->xdata.type() == XData::Data_Submit) || (d->xdata.type() == XData::Data_Cancel); + QDomElement dr = s.element(); if (d->xdata.registrarType() == "urn:xmpp:captcha") { dr = dr.appendChild(s.createElement("urn:xmpp:captcha", "captcha")).toElement(); } @@ -1930,13 +2008,13 @@ Stanza Message::toStanza(Stream *stream) const } // bits of binary - foreach(const BoBData &bd, d->bobDataList) { + foreach (const BoBData &bd, d->bobDataList) { s.appendChild(bd.toXml(&s.doc())); } // Avoiding Carbons if (isDisabledCarbons() || wasEncrypted()) { - QDomElement e = s.createElement("urn:xmpp:carbons:2","private"); + QDomElement e = s.createElement("urn:xmpp:carbons:2", "private"); s.appendChild(e); } if (!d->replaceId.isEmpty()) { @@ -1976,7 +2054,7 @@ Stanza Message::toStanza(Stream *stream) const } // XEP-0372 and XEP-0385 - for (auto const &r: d->references) { + for (auto const &r : d->references) { s.appendChild(r.toXml(&s.doc())); } @@ -2009,7 +2087,7 @@ bool Message::fromStanza(const Stanza &s) */ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOffset) { - if(s.kind() != Stanza::Message) + if (s.kind() != Stanza::Message) return false; d = new Private; @@ -2027,39 +2105,36 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf QDomElement root = s.element(); XDomNodeList nl = root.childNodes(); - int n; - for(n = 0; n < nl.count(); ++n) { + int n; + for (n = 0; n < nl.count(); ++n) { QDomNode i = nl.item(n); - if(i.isElement()) { + if (i.isElement()) { QDomElement e = i.toElement(); - if(e.namespaceURI() == s.baseNS()) { - if(e.tagName() == QLatin1String("subject")) { + if (e.namespaceURI() == s.baseNS()) { + if (e.tagName() == QLatin1String("subject")) { QString lang = e.attributeNS(NS_XML, "lang", ""); if (lang.isEmpty() || !(lang = XMLHelper::sanitizedLang(lang)).isEmpty()) { d->subject[lang] = e.text(); } - } - else if(e.tagName() == QLatin1String("body")) { + } else if (e.tagName() == QLatin1String("body")) { QString lang = e.attributeNS(NS_XML, "lang", ""); if (lang.isEmpty() || !(lang = XMLHelper::sanitizedLang(lang)).isEmpty()) { d->body[lang] = e.text(); } - } - else if(e.tagName() == QLatin1String("thread")) + } else if (e.tagName() == QLatin1String("thread")) d->thread = e.text(); - } - else if(e.tagName() == QLatin1String("event") && e.namespaceURI() == QLatin1String("http://jabber.org/protocol/pubsub#event")) { - for(QDomNode enode = e.firstChild(); !enode.isNull(); enode = enode.nextSibling()) { + } else if (e.tagName() == QLatin1String("event") && e.namespaceURI() == QLatin1String("http://jabber.org/protocol/pubsub#event")) { + for (QDomNode enode = e.firstChild(); !enode.isNull(); enode = enode.nextSibling()) { QDomElement eel = enode.toElement(); if (eel.tagName() == QLatin1String("items")) { d->pubsubNode = eel.attribute("node"); - for(QDomNode inode = eel.firstChild(); !inode.isNull(); inode = inode.nextSibling()) { + for (QDomNode inode = eel.firstChild(); !inode.isNull(); inode = inode.nextSibling()) { QDomElement o = inode.toElement(); if (o.tagName() == QLatin1String("item")) { - for(QDomNode j = o.firstChild(); !j.isNull(); j = j.nextSibling()) { + for (QDomNode j = o.firstChild(); !j.isNull(); j = j.nextSibling()) { QDomElement item = j.toElement(); if (!item.isNull()) { - d->pubsubItems += PubSubItem(o.attribute("id"),item); + d->pubsubItems += PubSubItem(o.attribute("id"), item); } } } @@ -2069,23 +2144,17 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf } } } - } - else if (e.tagName() == QLatin1String("no-permanent-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("no-permanent-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoPermanentStore; - } - else if (e.tagName() == QLatin1String("no-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("no-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoStore; - } - else if (e.tagName() == QLatin1String("no-copy") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("no-copy") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoCopy; - } - else if (e.tagName() == QLatin1String("store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= Store; - } - else if (e.tagName() == QLatin1String("origin-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { + } else if (e.tagName() == QLatin1String("origin-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { d->originId = e.attribute(QStringLiteral("id")); - } - else if (e.tagName() == QLatin1String("stanza-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { + } else if (e.tagName() == QLatin1String("stanza-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { d->stanzaId.id = e.attribute(QStringLiteral("id")); d->stanzaId.by = Jid(e.attribute(QStringLiteral("by"))); } @@ -2096,12 +2165,12 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf } } - if(s.type() == "error") + if (s.type() == "error") d->error = s.error(); // Bits of Binary XEP-0231 nl = childElementsByTagNameNS(root, "urn:xmpp:bob", "data"); - for(n = 0; n < nl.count(); ++n) { + for (n = 0; n < nl.count(); ++n) { addBoBData(BoBData(nl.item(n).toElement())); } @@ -2109,7 +2178,7 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/xhtml-im", "html"); if (nl.count()) { nl = nl.item(0).childNodes(); - for(n = 0; n < nl.count(); ++n) { + for (n = 0; n < nl.count(); ++n) { QDomElement e = nl.item(n).toElement(); if (e.tagName() == "body" && e.namespaceURI() == "http://www.w3.org/1999/xhtml") { QString lang = e.attributeNS(NS_XML, "lang", ""); @@ -2123,7 +2192,7 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf // timestamp QDomElement t = childElementsByTagNameNS(root, "urn:xmpp:delay", "delay").item(0).toElement(); - QDateTime stamp; + QDateTime stamp; if (!t.isNull()) { stamp = QDateTime::fromString(t.attribute("stamp").left(19), Qt::ISODate); } else { @@ -2140,20 +2209,19 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf d->timeStamp = stamp.toLocalTime(); } d->timeStampSend = true; - d->spooled = true; - } - else { - d->timeStamp = QDateTime::currentDateTime(); + d->spooled = true; + } else { + d->timeStamp = QDateTime::currentDateTime(); d->timeStampSend = false; - d->spooled = false; + d->spooled = false; } // urls d->urlList.clear(); nl = childElementsByTagNameNS(root, "jabber:x:oob", "x"); - for(n = 0; n < nl.count(); ++n) { + for (n = 0; n < nl.count(); ++n) { QDomElement t = nl.item(n).toElement(); - Url u; + Url u; u.setUrl(t.elementsByTagName("url").item(0).toElement().text()); u.setDesc(t.elementsByTagName("desc").item(0).toElement().text()); d->urlList += u; @@ -2164,12 +2232,11 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf nl = childElementsByTagNameNS(root, "jabber:x:event", "x"); if (nl.count()) { nl = nl.item(0).childNodes(); - for(n = 0; n < nl.count(); ++n) { + for (n = 0; n < nl.count(); ++n) { QString evtag = nl.item(n).toElement().tagName(); if (evtag == "id") { - d->eventId = nl.item(n).toElement().text(); - } - else if (evtag == "displayed") + d->eventId = nl.item(n).toElement().text(); + } else if (evtag == "displayed") d->eventList += DisplayedEvent; else if (evtag == "composing") d->eventList += ComposingEvent; @@ -2182,32 +2249,32 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf // Chat states QString chatStateNS = "http://jabber.org/protocol/chatstates"; - t = childElementsByTagNameNS(root, chatStateNS, "active").item(0).toElement(); - if(!t.isNull()) + t = childElementsByTagNameNS(root, chatStateNS, "active").item(0).toElement(); + if (!t.isNull()) d->chatState = StateActive; t = childElementsByTagNameNS(root, chatStateNS, "composing").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->chatState = StateComposing; t = childElementsByTagNameNS(root, chatStateNS, "paused").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->chatState = StatePaused; t = childElementsByTagNameNS(root, chatStateNS, "inactive").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->chatState = StateInactive; t = childElementsByTagNameNS(root, chatStateNS, "gone").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->chatState = StateGone; // message receipts QString messageReceiptNS = "urn:xmpp:receipts"; - t = childElementsByTagNameNS(root, messageReceiptNS, "request").item(0).toElement(); - if(!t.isNull()) { + t = childElementsByTagNameNS(root, messageReceiptNS, "request").item(0).toElement(); + if (!t.isNull()) { d->messageReceipt = ReceiptRequest; d->messageReceiptId.clear(); } t = childElementsByTagNameNS(root, messageReceiptNS, "received").item(0).toElement(); - if(!t.isNull()) { - d->messageReceipt = ReceiptReceived; + if (!t.isNull()) { + d->messageReceipt = ReceiptReceived; d->messageReceiptId = t.attribute("id"); if (d->messageReceiptId.isEmpty()) d->messageReceiptId = id(); @@ -2215,14 +2282,14 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf // xsigned t = childElementsByTagNameNS(root, "jabber:x:signed", "x").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->xsigned = t.text(); else d->xsigned = QString(); // xencrypted t = childElementsByTagNameNS(root, "jabber:x:encrypted", "x").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->xencrypted = t.text(); else d->xencrypted = QString(); @@ -2232,8 +2299,8 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/address", "addresses"); if (nl.count()) { QDomElement t = nl.item(0).toElement(); - nl = t.elementsByTagName("address"); - for(n = 0; n < nl.count(); ++n) { + nl = t.elementsByTagName("address"); + for (n = 0; n < nl.count(); ++n) { d->addressList += Address(nl.item(n).toElement()); } } @@ -2243,8 +2310,8 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf nl = childElementsByTagNameNS(root, "http://jabber.org/protocol/rosterx", "x"); if (nl.count()) { QDomElement t = nl.item(0).toElement(); - nl = t.elementsByTagName("item"); - for(n = 0; n < nl.count(); ++n) { + nl = t.elementsByTagName("item"); + for (n = 0; n < nl.count(); ++n) { RosterExchangeItem it = RosterExchangeItem(nl.item(n).toElement()); if (!it.isNull()) d->rosterExchangeItems += it; @@ -2253,44 +2320,41 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf // invite t = childElementsByTagNameNS(root, "jabber:x:conference", "x").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->invite = t.attribute("jid"); else d->invite = QString(); // nick t = childElementsByTagNameNS(root, "http://jabber.org/protocol/nick", "nick").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->nick = t.text(); else d->nick = QString(); // sxe t = childElementsByTagNameNS(root, "http://jabber.org/protocol/sxe", "sxe").item(0).toElement(); - if(!t.isNull()) + if (!t.isNull()) d->sxe = t; else d->sxe = QDomElement(); t = childElementsByTagNameNS(root, "http://jabber.org/protocol/muc#user", "x").item(0).toElement(); - if(!t.isNull()) { + if (!t.isNull()) { d->hasMUCUser = true; - for(QDomNode muc_n = t.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { + for (QDomNode muc_n = t.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { QDomElement muc_e = muc_n.toElement(); - if(muc_e.isNull()) + if (muc_e.isNull()) continue; if (muc_e.tagName() == "status") { addMUCStatus(muc_e.attribute("code").toInt()); - } - else if (muc_e.tagName() == "invite") { + } else if (muc_e.tagName() == "invite") { MUCInvite inv(muc_e); if (!inv.isNull()) addMUCInvite(inv); - } - else if (muc_e.tagName() == "decline") { + } else if (muc_e.tagName() == "decline") { setMUCDecline(MUCDecline(muc_e)); - } - else if (muc_e.tagName() == "password") { + } else if (muc_e.tagName() == "password") { setMUCPassword(muc_e.text()); } } @@ -2298,15 +2362,16 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf // http auth t = childElementsByTagNameNS(root, "http://jabber.org/protocol/http-auth", "confirm").item(0).toElement(); - if(!t.isNull()){ + if (!t.isNull()) { d->httpAuthRequest = HttpAuthRequest(t); - } - else { + } else { d->httpAuthRequest = HttpAuthRequest(); } QDomElement captcha = childElementsByTagNameNS(root, "urn:xmpp:captcha", - "captcha").item(0).toElement(); + "captcha") + .item(0) + .toElement(); QDomElement xdataRoot = root; if (!captcha.isNull()) { xdataRoot = captcha; @@ -2347,14 +2412,16 @@ Stanza::Error HttpAuthRequest::denyError(Stanza::Error::Auth, Stanza::Error::Not /*! Constructs request of resource URL \a u, made by method \a m, with transaction id \a i. */ -HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u, const QString &i) : method_(m), url_(u), id_(i), hasId_(true) +HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u, const QString &i) : + method_(m), url_(u), id_(i), hasId_(true) { } /*! Constructs request of resource URL \a u, made by method \a m, without transaction id. */ -HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u) : method_(m), url_(u), hasId_(false) +HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u) : + method_(m), url_(u), hasId_(false) { } @@ -2377,7 +2444,7 @@ bool HttpAuthRequest::isEmpty() const /*! Sets request method. */ -void HttpAuthRequest::setMethod(const QString& m) +void HttpAuthRequest::setMethod(const QString &m) { method_ = m; } @@ -2385,7 +2452,7 @@ void HttpAuthRequest::setMethod(const QString& m) /*! Sets requested URL. */ -void HttpAuthRequest::setUrl(const QString& u) +void HttpAuthRequest::setUrl(const QString &u) { url_ = u; } @@ -2393,9 +2460,9 @@ void HttpAuthRequest::setUrl(const QString& u) /*! Sets transaction identifier. */ -void HttpAuthRequest::setId(const QString& i) +void HttpAuthRequest::setId(const QString &i) { - id_ = i; + id_ = i; hasId_ = true; } @@ -2439,12 +2506,12 @@ bool HttpAuthRequest::hasId() const QDomElement HttpAuthRequest::toXml(QDomDocument &doc) const { QDomElement e; - if(isEmpty()) + if (isEmpty()) return e; e = doc.createElementNS("http://jabber.org/protocol/http-auth", "confirm"); - if(hasId_) + if (hasId_) e.setAttribute("id", id_); e.setAttribute("method", method_); e.setAttribute("url", url_); @@ -2457,15 +2524,15 @@ QDomElement HttpAuthRequest::toXml(QDomDocument &doc) const */ bool HttpAuthRequest::fromXml(const QDomElement &e) { - if(e.tagName() != "confirm") + if (e.tagName() != "confirm") return false; hasId_ = e.hasAttribute("id"); - if(hasId_) + if (hasId_) id_ = e.attribute("id"); method_ = e.attribute("method"); - url_ = e.attribute("url"); + url_ = e.attribute("url"); return true; } @@ -2485,7 +2552,7 @@ int Subscription::type() const QString Subscription::toString() const { - switch(value) { + switch (value) { case Remove: return "remove"; case Both: @@ -2502,15 +2569,15 @@ QString Subscription::toString() const bool Subscription::fromString(const QString &s) { - if(s == QLatin1String("remove")) + if (s == QLatin1String("remove")) value = Remove; - else if(s == QLatin1String("both")) + else if (s == QLatin1String("both")) value = Both; - else if(s == QLatin1String("from")) + else if (s == QLatin1String("from")) value = From; - else if(s == QLatin1String("to")) + else if (s == QLatin1String("to")) value = To; - else if(s.isEmpty() || s == QLatin1String("none")) + else if (s.isEmpty() || s == QLatin1String("none")) value = None; else return false; @@ -2535,17 +2602,17 @@ CapsSpec::CapsSpec() : * @param ven the version * @param ext the list of extensions (separated by spaces) */ -CapsSpec::CapsSpec(const QString& node, QCryptographicHash::Algorithm hashAlgo, const QString& ver) - : node_(node) - , ver_(ver) - , hashAlgo_(hashAlgo) -{} +CapsSpec::CapsSpec(const QString &node, QCryptographicHash::Algorithm hashAlgo, const QString &ver) : + node_(node), ver_(ver), hashAlgo_(hashAlgo) +{ +} CapsSpec::CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlgo) : node_(disco.node().section('#', 0, 0)), ver_(disco.capsHash(hashAlgo)), hashAlgo_(hashAlgo) -{} +{ +} /** * @brief Checks for validity @@ -2559,7 +2626,7 @@ bool CapsSpec::isValid() const /** * \brief Returns the node of the capabilities specification. */ -const QString& CapsSpec::node() const +const QString &CapsSpec::node() const { return node_; } @@ -2567,7 +2634,7 @@ const QString& CapsSpec::node() const /** * \brief Returns the version of the capabilities specification. */ -const QString& CapsSpec::version() const +const QString &CapsSpec::version() const { return ver_; } @@ -2579,25 +2646,25 @@ QCryptographicHash::Algorithm CapsSpec::hashAlgorithm() const QDomElement CapsSpec::toXml(QDomDocument *doc) const { - QDomElement c = doc->createElementNS(NS_CAPS, "c"); - QString algo = cryptoMap().key(hashAlgo_); - c.setAttribute("hash",algo); - c.setAttribute("node",node_); - c.setAttribute("ver",ver_); + QDomElement c = doc->createElementNS(NS_CAPS, "c"); + QString algo = cryptoMap().key(hashAlgo_); + c.setAttribute("hash", algo); + c.setAttribute("node", node_); + c.setAttribute("ver", ver_); return c; } CapsSpec CapsSpec::fromXml(const QDomElement &e) { - QString node = e.attribute("node"); - QString ver = e.attribute("ver"); - QString hashAlgo = e.attribute("hash"); - QString ext = e.attribute("ext"); // deprecated. let it be here till 2018 - CryptoMap &cm = cryptoMap(); - CapsSpec cs; + QString node = e.attribute("node"); + QString ver = e.attribute("ver"); + QString hashAlgo = e.attribute("hash"); + QString ext = e.attribute("ext"); // deprecated. let it be here till 2018 + CryptoMap &cm = cryptoMap(); + CapsSpec cs; if (!node.isEmpty() && !ver.isEmpty()) { QCryptographicHash::Algorithm algo = CapsSpec::invalidAlgo; - CryptoMap::ConstIterator it; + CryptoMap::ConstIterator it; if (!hashAlgo.isEmpty() && (it = cm.constFind(hashAlgo)) != cm.constEnd()) { algo = it.value(); } @@ -2613,8 +2680,8 @@ CapsSpec::CryptoMap &CapsSpec::cryptoMap() { static CryptoMap cm; if (cm.isEmpty()) { - cm.insert("md5", QCryptographicHash::Md5); - cm.insert("sha-1", QCryptographicHash::Sha1); + cm.insert("md5", QCryptographicHash::Md5); + cm.insert("sha-1", QCryptographicHash::Sha1); cm.insert("sha-224", QCryptographicHash::Sha224); cm.insert("sha-256", QCryptographicHash::Sha256); cm.insert("sha-384", QCryptographicHash::Sha384); @@ -2647,75 +2714,72 @@ void CapsSpec::resetVersion() ver_.clear(); } -bool CapsSpec::operator==(const CapsSpec& s) const +bool CapsSpec::operator==(const CapsSpec &s) const { return (node() == s.node() && version() == s.version() && hashAlgorithm() == s.hashAlgorithm()); } -bool CapsSpec::operator!=(const CapsSpec& s) const +bool CapsSpec::operator!=(const CapsSpec &s) const { return !((*this) == s); } -bool CapsSpec::operator<(const CapsSpec& s) const +bool CapsSpec::operator<(const CapsSpec &s) const { - return (node() != s.node() ? node() < s.node() : - (version() != s.version() ? version() < s.version() : - hashAlgorithm() < s.hashAlgorithm())); + return (node() != s.node() ? node() < s.node() : (version() != s.version() ? version() < s.version() : hashAlgorithm() < s.hashAlgorithm())); } -class StatusPrivate : public QSharedData -{ +class StatusPrivate : public QSharedData { public: StatusPrivate() = default; - int priority = 0; - QString show, status, key; - QDateTime timeStamp; - bool isAvailable = false; - bool isInvisible = false; - QString photoHash; - bool hasPhotoHash = false; + int priority = 0; + QString show, status, key; + QDateTime timeStamp; + bool isAvailable = false; + bool isInvisible = false; + QByteArray photoHash; + bool hasPhotoHash = false; QString xsigned; // gabber song extension - QString songTitle; - CapsSpec caps; + QString songTitle; + CapsSpec caps; QList bobDataList; // MUC - bool isMUC = false; - bool hasMUCItem = false; - bool hasMUCDestroy = false; - MUCItem mucItem; + bool isMUC = false; + bool hasMUCItem = false; + bool hasMUCDestroy = false; + MUCItem mucItem; MUCDestroy mucDestroy; QList mucStatuses; - QString mucPassword; - int mucHistoryMaxChars = -1; - int mucHistoryMaxStanzas = -1; - int mucHistorySeconds = -1; - QDateTime mucHistorySince; + QString mucPassword; + int mucHistoryMaxChars = -1; + int mucHistoryMaxStanzas = -1; + int mucHistorySeconds = -1; + QDateTime mucHistorySince; - int ecode = -1; + int ecode = -1; QString estr; }; -Status::Status(const QString &show, const QString &status, int priority, bool available) - : d(new StatusPrivate) +Status::Status(const QString &show, const QString &status, int priority, bool available) : + d(new StatusPrivate) { d->isAvailable = available; - d->show = show; - d->status = status; - d->priority = priority; - d->timeStamp = QDateTime::currentDateTime(); + d->show = show; + d->status = status; + d->priority = priority; + d->timeStamp = QDateTime::currentDateTime(); d->isInvisible = false; } -Status::Status(Type type, const QString& status, int priority) - : d(new StatusPrivate) +Status::Status(Type type, const QString &status, int priority) : + d(new StatusPrivate) { - d->status = status; - d->priority = priority; + d->status = status; + d->priority = priority; d->timeStamp = QDateTime::currentDateTime(); setType(type); } @@ -2743,7 +2807,7 @@ bool Status::hasError() const void Status::setError(int code, const QString &str) { d->ecode = code; - d->estr = str; + d->estr = str; } void Status::setIsAvailable(bool available) @@ -2763,24 +2827,37 @@ void Status::setPriority(int x) void Status::setType(Status::Type _type) { - bool available = true; - bool invisible = false; + bool available = true; + bool invisible = false; QString show; - switch(_type) { - case Away: show = "away"; break; - case FFC: show = "chat"; break; - case XA: show = "xa"; break; - case DND: show = "dnd"; break; - case Offline: available = false; break; - case Invisible: invisible = true; break; - default: break; + switch (_type) { + case Away: + show = "away"; + break; + case FFC: + show = "chat"; + break; + case XA: + show = "xa"; + break; + case DND: + show = "dnd"; + break; + case Offline: + available = false; + break; + case Invisible: + invisible = true; + break; + default: + break; } setShow(show); setIsAvailable(available); setIsInvisible(invisible); } -Status::Type Status::txt2type(const QString& stat) +Status::Type Status::txt2type(const QString &stat) { if (stat == "offline") return XMPP::Status::Offline; @@ -2805,17 +2882,17 @@ void Status::setType(const QString &stat) setType(txt2type(stat)); } -void Status::setShow(const QString & _show) +void Status::setShow(const QString &_show) { d->show = _show; } -void Status::setStatus(const QString & _status) +void Status::setStatus(const QString &_status) { d->status = _status; } -void Status::setTimeStamp(const QDateTime & _timestamp) +void Status::setTimeStamp(const QDateTime &_timestamp) { d->timeStamp = _timestamp; } @@ -2830,12 +2907,12 @@ void Status::setXSigned(const QString &s) d->xsigned = s; } -void Status::setSongTitle(const QString & _songtitle) +void Status::setSongTitle(const QString &_songtitle) { d->songTitle = _songtitle; } -void Status::setCaps(const CapsSpec & caps) +void Status::setCaps(const CapsSpec &caps) { d->caps = caps; } @@ -2845,34 +2922,34 @@ void Status::setMUC() d->isMUC = true; } -void Status::setMUCItem(const MUCItem& i) +void Status::setMUCItem(const MUCItem &i) { d->hasMUCItem = true; - d->mucItem = i; + d->mucItem = i; } -void Status::setMUCDestroy(const MUCDestroy& i) +void Status::setMUCDestroy(const MUCDestroy &i) { d->hasMUCDestroy = true; - d->mucDestroy = i; + d->mucDestroy = i; } void Status::setMUCHistory(int maxchars, int maxstanzas, int seconds, const QDateTime &since) { - d->mucHistoryMaxChars = maxchars; + d->mucHistoryMaxChars = maxchars; d->mucHistoryMaxStanzas = maxstanzas; - d->mucHistorySeconds = seconds; - d->mucHistorySince = since; + d->mucHistorySeconds = seconds; + d->mucHistorySince = since; } -const QString& Status::photoHash() const +const QByteArray &Status::photoHash() const { return d->photoHash; } -void Status::setPhotoHash(const QString& h) +void Status::setPhotoHash(const QByteArray &h) { - d->photoHash = h; + d->photoHash = h; d->hasPhotoHash = true; } @@ -2916,11 +2993,9 @@ Status::Type Status::type() const Status::Type type = Status::Online; if (!isAvailable()) { type = Status::Offline; - } - else if (isInvisible()) { + } else if (isInvisible()) { type = Status::Invisible; - } - else { + } else { QString s = show(); if (s == "away") type = Status::Away; @@ -2937,24 +3012,39 @@ Status::Type Status::type() const QString Status::typeString() const { QString stat; - switch(type()) { - case XMPP::Status::Offline: stat = "offline"; break; - case XMPP::Status::Online: stat = "online"; break; - case XMPP::Status::Away: stat = "away"; break; - case XMPP::Status::XA: stat = "xa"; break; - case XMPP::Status::DND: stat = "dnd"; break; - case XMPP::Status::Invisible: stat = "invisible"; break; - case XMPP::Status::FFC: stat = "chat"; break; - default: stat = "away"; + switch (type()) { + case XMPP::Status::Offline: + stat = "offline"; + break; + case XMPP::Status::Online: + stat = "online"; + break; + case XMPP::Status::Away: + stat = "away"; + break; + case XMPP::Status::XA: + stat = "xa"; + break; + case XMPP::Status::DND: + stat = "dnd"; + break; + case XMPP::Status::Invisible: + stat = "invisible"; + break; + case XMPP::Status::FFC: + stat = "chat"; + break; + default: + stat = "away"; } return stat; } -const QString & Status::show() const +const QString &Status::show() const { return d->show; } -const QString & Status::status() const +const QString &Status::status() const { return d->status; } @@ -2964,22 +3054,22 @@ QDateTime Status::timeStamp() const return d->timeStamp; } -const QString & Status::keyID() const +const QString &Status::keyID() const { return d->key; } -const QString & Status::xsigned() const +const QString &Status::xsigned() const { return d->xsigned; } -const QString & Status::songTitle() const +const QString &Status::songTitle() const { return d->songTitle; } -const CapsSpec & Status::caps() const +const CapsSpec &Status::caps() const { return d->caps; } @@ -2994,7 +3084,7 @@ bool Status::hasMUCItem() const return d->hasMUCItem; } -const MUCItem& Status::mucItem() const +const MUCItem &Status::mucItem() const { return d->mucItem; } @@ -3004,12 +3094,12 @@ bool Status::hasMUCDestroy() const return d->hasMUCDestroy; } -const MUCDestroy& Status::mucDestroy() const +const MUCDestroy &Status::mucDestroy() const { return d->mucDestroy; } -const QList& Status::getMUCStatuses() const +const QList &Status::getMUCStatuses() const { return d->mucStatuses; } @@ -3019,7 +3109,7 @@ void Status::addMUCStatus(int i) d->mucStatuses += i; } -const QString& Status::mucPassword() const +const QString &Status::mucPassword() const { return d->mucPassword; } @@ -3044,12 +3134,12 @@ int Status::mucHistorySeconds() const return d->mucHistorySeconds; } -const QDateTime & Status::mucHistorySince() const +const QDateTime &Status::mucHistorySince() const { return d->mucHistorySince; } -void Status::setMUCPassword(const QString& i) +void Status::setMUCPassword(const QString &i) { d->mucPassword = i; } @@ -3059,7 +3149,7 @@ int Status::errorCode() const return d->ecode; } -const QString & Status::errorString() const +const QString &Status::errorString() const { return d->estr; } @@ -3067,13 +3157,12 @@ const QString & Status::errorString() const //--------------------------------------------------------------------------- // Resource //--------------------------------------------------------------------------- -Resource::Resource(const QString &name, const Status &stat) - : v_name(name) - , v_status(stat) +Resource::Resource(const QString &name, const Status &stat) : + v_name(name), v_status(stat) { } -const QString & Resource::name() const +const QString &Resource::name() const { return v_name; } @@ -3083,17 +3172,17 @@ int Resource::priority() const return v_status.priority(); } -const Status & Resource::status() const +const Status &Resource::status() const { return v_status; } -void Resource::setName(const QString & _name) +void Resource::setName(const QString &_name) { v_name = _name; } -void Resource::setStatus(const Status & _status) +void Resource::setStatus(const Status &_status) { v_status = _status; } @@ -3101,8 +3190,8 @@ void Resource::setStatus(const Status & _status) //--------------------------------------------------------------------------- // ResourceList //--------------------------------------------------------------------------- -ResourceList::ResourceList() - :QList() +ResourceList::ResourceList() : + QList() { } @@ -3110,10 +3199,10 @@ ResourceList::~ResourceList() { } -ResourceList::Iterator ResourceList::find(const QString & _find) +ResourceList::Iterator ResourceList::find(const QString &_find) { - for(ResourceList::Iterator it = begin(); it != end(); ++it) { - if((*it).name() == _find) + for (ResourceList::Iterator it = begin(); it != end(); ++it) { + if ((*it).name() == _find) return it; } @@ -3124,18 +3213,18 @@ ResourceList::Iterator ResourceList::priority() { ResourceList::Iterator highest = end(); - for(ResourceList::Iterator it = begin(); it != end(); ++it) { - if(highest == end() || (*it).priority() > (*highest).priority()) + for (ResourceList::Iterator it = begin(); it != end(); ++it) { + if (highest == end() || (*it).priority() > (*highest).priority()) highest = it; } return highest; } -ResourceList::ConstIterator ResourceList::find(const QString & _find) const +ResourceList::ConstIterator ResourceList::find(const QString &_find) const { - for(ResourceList::ConstIterator it = begin(); it != end(); ++it) { - if((*it).name() == _find) + for (ResourceList::ConstIterator it = begin(); it != end(); ++it) { + if ((*it).name() == _find) return it; } @@ -3146,8 +3235,8 @@ ResourceList::ConstIterator ResourceList::priority() const { ResourceList::ConstIterator highest = end(); - for(ResourceList::ConstIterator it = begin(); it != end(); ++it) { - if(highest == end() || (*it).priority() > (*highest).priority()) + for (ResourceList::ConstIterator it = begin(); it != end(); ++it) { + if (highest == end() || (*it).priority() > (*highest).priority()) highest = it; } @@ -3177,27 +3266,27 @@ RosterItem::~RosterItem() { } -const Jid & RosterItem::jid() const +const Jid &RosterItem::jid() const { return v_jid; } -const QString & RosterItem::name() const +const QString &RosterItem::name() const { return v_name; } -const QStringList & RosterItem::groups() const +const QStringList &RosterItem::groups() const { return v_groups; } -const Subscription & RosterItem::subscription() const +const Subscription &RosterItem::subscription() const { return v_subscription; } -const QString & RosterItem::ask() const +const QString &RosterItem::ask() const { return v_ask; } @@ -3209,8 +3298,8 @@ bool RosterItem::isPush() const bool RosterItem::inGroup(const QString &g) const { - for(QStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it) { - if(*it == g) + for (QStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it) { + if (*it == g) return true; } return false; @@ -3248,7 +3337,7 @@ void RosterItem::setIsPush(bool b) bool RosterItem::addGroup(const QString &g) { - if(inGroup(g)) + if (inGroup(g)) return false; v_groups += g; @@ -3257,8 +3346,8 @@ bool RosterItem::addGroup(const QString &g) bool RosterItem::removeGroup(const QString &g) { - for(QStringList::Iterator it = v_groups.begin(); it != v_groups.end(); ++it) { - if(*it == g) { + for (QStringList::Iterator it = v_groups.begin(); it != v_groups.end(); ++it) { + if (*it == g) { v_groups.erase(it); return true; } @@ -3273,9 +3362,9 @@ QDomElement RosterItem::toXml(QDomDocument *doc) const item.setAttribute("jid", v_jid.full()); item.setAttribute("name", v_name); item.setAttribute("subscription", v_subscription.toString()); - if(!v_ask.isEmpty()) + if (!v_ask.isEmpty()) item.setAttribute("ask", v_ask); - for(QStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it) + for (QStringList::ConstIterator it = v_groups.begin(); it != v_groups.end(); ++it) item.appendChild(textTag(doc, "group", *it)); return item; @@ -3283,34 +3372,34 @@ QDomElement RosterItem::toXml(QDomDocument *doc) const bool RosterItem::fromXml(const QDomElement &item) { - if(item.tagName() != "item") + if (item.tagName() != "item") return false; Jid j(item.attribute("jid")); - if(!j.isValid()) + if (!j.isValid()) return false; QString na = item.attribute("name"); Subscription s; - if(!s.fromString(item.attribute("subscription")) ) + if (!s.fromString(item.attribute("subscription"))) return false; QStringList g; - for(QDomNode n = item.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = item.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "group") + if (i.tagName() == "group") g += tagContent(i); } QString a = item.attribute("ask"); - v_jid = j; - v_name = na; + v_jid = j; + v_name = na; v_subscription = s; - v_groups = g; - v_ask = a; + v_groups = g; + v_ask = a; return true; } @@ -3318,8 +3407,8 @@ bool RosterItem::fromXml(const QDomElement &item) //--------------------------------------------------------------------------- // Roster //--------------------------------------------------------------------------- -Roster::Roster() - : QList() +Roster::Roster() : + QList() { } @@ -3329,8 +3418,8 @@ Roster::~Roster() Roster::Iterator Roster::find(const Jid &j) { - for(Roster::Iterator it = begin(); it != end(); ++it) { - if((*it).jid().compare(j)) + for (Roster::Iterator it = begin(); it != end(); ++it) { + if ((*it).jid().compare(j)) return it; } @@ -3339,8 +3428,8 @@ Roster::Iterator Roster::find(const Jid &j) Roster::ConstIterator Roster::find(const Jid &j) const { - for(Roster::ConstIterator it = begin(); it != end(); ++it) { - if((*it).jid().compare(j)) + for (Roster::ConstIterator it = begin(); it != end(); ++it) { + if ((*it).jid().compare(j)) return it; } @@ -3353,9 +3442,9 @@ Roster::ConstIterator Roster::find(const Jid &j) const FormField::FormField(const QString &type, const QString &value) { v_type = misc; - if(!type.isEmpty()) { + if (!type.isEmpty()) { int x = tagNameToType(type); - if(x != -1) + if (x != -1) v_type = x; } v_value = value; @@ -3377,23 +3466,39 @@ QString FormField::realName() const QString FormField::fieldName() const { - switch(v_type) { - case username: return QObject::tr("Username"); - case nick: return QObject::tr("Nickname"); - case password: return QObject::tr("Password"); - case name: return QObject::tr("Name"); - case first: return QObject::tr("First Name"); - case last: return QObject::tr("Last Name"); - case email: return QObject::tr("E-mail"); - case address: return QObject::tr("Address"); - case city: return QObject::tr("City"); - case state: return QObject::tr("State"); - case zip: return QObject::tr("Zipcode"); - case phone: return QObject::tr("Phone"); - case url: return QObject::tr("URL"); - case date: return QObject::tr("Date"); - case misc: return QObject::tr("Misc"); - default: return ""; + switch (v_type) { + case username: + return QObject::tr("Username"); + case nick: + return QObject::tr("Nickname"); + case password: + return QObject::tr("Password"); + case name: + return QObject::tr("Name"); + case first: + return QObject::tr("First Name"); + case last: + return QObject::tr("Last Name"); + case email: + return QObject::tr("E-mail"); + case address: + return QObject::tr("Address"); + case city: + return QObject::tr("City"); + case state: + return QObject::tr("State"); + case zip: + return QObject::tr("Zipcode"); + case phone: + return QObject::tr("Phone"); + case url: + return QObject::tr("URL"); + case date: + return QObject::tr("Date"); + case misc: + return QObject::tr("Misc"); + default: + return ""; }; } @@ -3402,7 +3507,7 @@ bool FormField::isSecret() const return (type() == password); } -const QString & FormField::value() const +const QString &FormField::value() const { return v_value; } @@ -3415,7 +3520,7 @@ void FormField::setType(int x) bool FormField::setType(const QString &in) { int x = tagNameToType(in); - if(x == -1) + if (x == -1) return false; v_type = x; @@ -3429,51 +3534,83 @@ void FormField::setValue(const QString &in) int FormField::tagNameToType(const QString &in) const { - if(!in.compare("username")) return username; - if(!in.compare("nick")) return nick; - if(!in.compare("password")) return password; - if(!in.compare("name")) return name; - if(!in.compare("first")) return first; - if(!in.compare("last")) return last; - if(!in.compare("email")) return email; - if(!in.compare("address")) return address; - if(!in.compare("city")) return city; - if(!in.compare("state")) return state; - if(!in.compare("zip")) return zip; - if(!in.compare("phone")) return phone; - if(!in.compare("url")) return url; - if(!in.compare("date")) return date; - if(!in.compare("misc")) return misc; + if (!in.compare("username")) + return username; + if (!in.compare("nick")) + return nick; + if (!in.compare("password")) + return password; + if (!in.compare("name")) + return name; + if (!in.compare("first")) + return first; + if (!in.compare("last")) + return last; + if (!in.compare("email")) + return email; + if (!in.compare("address")) + return address; + if (!in.compare("city")) + return city; + if (!in.compare("state")) + return state; + if (!in.compare("zip")) + return zip; + if (!in.compare("phone")) + return phone; + if (!in.compare("url")) + return url; + if (!in.compare("date")) + return date; + if (!in.compare("misc")) + return misc; return -1; } QString FormField::typeToTagName(int type) const { - switch(type) { - case username: return "username"; - case nick: return "nick"; - case password: return "password"; - case name: return "name"; - case first: return "first"; - case last: return "last"; - case email: return "email"; - case address: return "address"; - case city: return "city"; - case state: return "state"; - case zip: return "zipcode"; - case phone: return "phone"; - case url: return "url"; - case date: return "date"; - case misc: return "misc"; - default: return ""; + switch (type) { + case username: + return "username"; + case nick: + return "nick"; + case password: + return "password"; + case name: + return "name"; + case first: + return "first"; + case last: + return "last"; + case email: + return "email"; + case address: + return "address"; + case city: + return "city"; + case state: + return "state"; + case zip: + return "zipcode"; + case phone: + return "phone"; + case url: + return "url"; + case date: + return "date"; + case misc: + return "misc"; + default: + return ""; }; } //--------------------------------------------------------------------------- // Form //--------------------------------------------------------------------------- -Form::Form(const Jid &j) : QList() +Form::Form(const Jid &j) : + QList() { setJid(j); } @@ -3524,27 +3661,27 @@ SearchResult::~SearchResult() { } -const Jid & SearchResult::jid() const +const Jid &SearchResult::jid() const { return v_jid; } -const QString & SearchResult::nick() const +const QString &SearchResult::nick() const { return v_nick; } -const QString & SearchResult::first() const +const QString &SearchResult::first() const { return v_first; } -const QString & SearchResult::last() const +const QString &SearchResult::last() const { return v_last; } -const QString & SearchResult::email() const +const QString &SearchResult::email() const { return v_email; } @@ -3578,16 +3715,17 @@ PubSubItem::PubSubItem() { } -PubSubItem::PubSubItem(const QString& id, const QDomElement& payload) : id_(id), payload_(payload) +PubSubItem::PubSubItem(const QString &id, const QDomElement &payload) : + id_(id), payload_(payload) { } -const QString& PubSubItem::id() const +const QString &PubSubItem::id() const { return id_; } -const QDomElement& PubSubItem::payload() const +const QDomElement &PubSubItem::payload() const { return payload_; } @@ -3596,11 +3734,12 @@ PubSubRetraction::PubSubRetraction() { } -PubSubRetraction::PubSubRetraction(const QString& id) : id_(id) +PubSubRetraction::PubSubRetraction(const QString &id) : + id_(id) { } -const QString& PubSubRetraction::id() const +const QString &PubSubRetraction::id() const { return id_; } @@ -3608,28 +3747,29 @@ const QString& PubSubRetraction::id() const // ========================================= // CaptchaChallenge // ========================================= -class CaptchaChallengePrivate : public QSharedData -{ +class CaptchaChallengePrivate : public QSharedData { public: CaptchaChallengePrivate() : state(CaptchaChallenge::New) {} CaptchaChallenge::State state; - Jid arbiter; - Jid offendedJid; - XData form; - QDateTime dt; - QString explanation; - UrlList urls; + Jid arbiter; + Jid offendedJid; + XData form; + QDateTime dt; + QString explanation; + UrlList urls; }; CaptchaChallenge::CaptchaChallenge() : d(new CaptchaChallengePrivate) -{} +{ +} CaptchaChallenge::CaptchaChallenge(const CaptchaChallenge &other) : d(other.d) -{} +{ +} CaptchaChallenge::CaptchaChallenge(const Message &m) : d(new CaptchaChallengePrivate) @@ -3646,22 +3786,21 @@ CaptchaChallenge::CaptchaChallenge(const Message &m) : if (m.getForm().registrarType() != "urn:xmpp:captcha" || m.getForm().type() != XData::Data_Form) return; - if (m.id().isEmpty() || m.getForm().getField("challenge").value().value(0) !=m.id()) + if (m.id().isEmpty() || m.getForm().getField("challenge").value().value(0) != m.id()) return; if (m.getForm().getField("from").value().value(0).isEmpty()) return; - d->form = m.getForm(); + d->form = m.getForm(); d->explanation = m.body(); - d->urls = m.urlList(); - d->arbiter = m.from(); + d->urls = m.urlList(); + d->arbiter = m.from(); d->offendedJid = Jid(m.getForm().getField("from").value().value(0)); } CaptchaChallenge::~CaptchaChallenge() { - } CaptchaChallenge &CaptchaChallenge::operator=(const CaptchaChallenge &from) @@ -3699,9 +3838,7 @@ CaptchaChallenge::Result CaptchaChallenge::validateResponse(const XData &xd) bool CaptchaChallenge::isValid() const { - return d->dt.isValid() && - d->dt.secsTo(QDateTime::currentDateTime()) < Timeout && - d->form.fields().count() > 0; + return d->dt.isValid() && d->dt.secsTo(QDateTime::currentDateTime()) < Timeout && d->form.fields().count() > 0; } const Jid &CaptchaChallenge::offendedJid() const @@ -3717,11 +3854,11 @@ const Jid &CaptchaChallenge::arbiter() const Thumbnail::Thumbnail(const QDomElement &el) { QString ns(QLatin1String(XMPP_THUMBS_NS)); - if(el.namespaceURI() == ns) { - uri = QUrl(el.attribute("uri"), QUrl::StrictMode); + if (el.namespaceURI() == ns) { + uri = QUrl(el.attribute("uri"), QUrl::StrictMode); mimeType = el.attribute("mime-type"); - width = el.attribute("width").toUInt(); - height = el.attribute("height").toUInt(); + width = el.attribute("width").toUInt(); + height = el.attribute("height").toUInt(); } } diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index 688d2e94..9b6ee453 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -19,6 +19,7 @@ #include "xmpp_bitsofbinary.h" #include "xmpp_client.h" +#include "xmpp_hash.h" #include "xmpp_tasks.h" #include "xmpp_xmlcommon.h" @@ -27,58 +28,75 @@ using namespace XMPP; -class BoBData::Private : public QSharedData -{ +class BoBData::Private : public QSharedData { public: - QByteArray data; // file data itself - QString type; // mime type. e.g. image/png - QString cid; // content identifier without "cid:" + QByteArray data; // file data itself + QString type; // mime type. e.g. image/png + //QString cid; // content identifier without "cid:" + Hash hash; unsigned int maxAge; // seconds to live }; -BoBData::BoBData() - : d(new Private) +BoBData::BoBData() : + d(new Private) { - } -BoBData::BoBData(const BoBData &other) - : d(other.d) +BoBData::BoBData(const BoBData &other) : + d(other.d) { - } -BoBData::BoBData(const QDomElement &e) - : d(new Private) +BoBData::BoBData(const QDomElement &e) : + d(new Private) { fromXml(e); } BoBData::~BoBData() { - } -BoBData & BoBData::operator=(const BoBData &other) +BoBData &BoBData::operator=(const BoBData &other) { - if (this==&other) return *this; //Protect against self-assignment + if (this == &other) + return *this; //Protect against self-assignment d = other.d; return *this; } bool BoBData::isNull() const { - return d->cid.isEmpty() || d->data.isNull(); + return !d->hash.isValid() || d->data.isNull(); +} + +Hash BoBData::cidToHash(const QString &cid) +{ + if (!cid.endsWith(QLatin1String("@bob.xmpp.org"))) + return Hash(); + return Hash::from(cid.leftRef(cid.size() - sizeof("@bob.xmpp.org") + 1)); } QString BoBData::cid() const { - return d->cid; + if (!isNull()) + return QString(); + return QString("%1+%2@bob.xmpp.org").arg(d->hash.stringType(), QString::fromLatin1(d->hash.data().toHex())); } void BoBData::setCid(const QString &cid) { - d->cid = cid; + d->hash = cidToHash(cid); +} + +const Hash &BoBData::hash() const +{ + return d->hash; +} + +void BoBData::setHash(const Hash &hash) +{ + d->hash = hash; } QByteArray BoBData::data() const @@ -113,17 +131,16 @@ void BoBData::setMaxAge(unsigned int maxAge) void BoBData::fromXml(const QDomElement &data) { - d->cid = data.attribute("cid"); + setCid(data.attribute("cid")); d->maxAge = data.attribute("max-age").toInt(); - d->type = data.attribute("type"); - d->data = QCA::Base64().stringToArray(data.text().replace("\n","")) - .toByteArray(); + d->type = data.attribute("type"); + d->data = QCA::Base64().stringToArray(data.text().replace("\n", "")).toByteArray(); } QDomElement BoBData::toXml(QDomDocument *doc) const { QDomElement data = doc->createElementNS("urn:xmpp:bob", "data"); - data.setAttribute("cid", d->cid); + data.setAttribute("cid", cid()); data.setAttribute("max-age", d->maxAge); data.setAttribute("type", d->type); data.appendChild(doc->createTextNode(QCA::Base64().arrayToString(d->data))); @@ -133,18 +150,16 @@ QDomElement BoBData::toXml(QDomDocument *doc) const // --------------------------------------------------------- // BoBCache // --------------------------------------------------------- -BoBCache::BoBCache(QObject *parent) - : QObject(parent) +BoBCache::BoBCache(QObject *parent) : + QObject(parent) { - } //------------------------------------------------------------------------------ // BoBManager //------------------------------------------------------------------------------ -BoBManager::BoBManager(Client *client) - : QObject(client) - , _cache(nullptr) +BoBManager::BoBManager(Client *client) : + QObject(client), _cache(nullptr) { new JT_BoBServer(client->rootTask()); } @@ -157,14 +172,18 @@ void BoBManager::setCache(BoBCache *cache) BoBData BoBManager::bobData(const QString &cid) { BoBData bd; + Hash h = BoBData::cidToHash(cid); if (_cache) { - bd = _cache->get(cid); + bd = _cache->get(h); } - if (bd.isNull() && _localFiles.contains(cid)) { - QPair fileData = _localFiles.value(cid); - QFile file(fileData.first); + if (!bd.isNull()) + return bd; + auto it = _localFiles.find(h); + if (it != _localFiles.end()) { + QPair fileData = it.value(); + QFile file(fileData.first); if (file.open(QIODevice::ReadOnly)) { - bd.setCid(cid); + bd.setHash(h); bd.setData(file.readAll()); bd.setMaxAge(0); bd.setType(fileData.second); @@ -174,11 +193,10 @@ BoBData BoBManager::bobData(const QString &cid) } BoBData BoBManager::append(const QByteArray &data, const QString &type, - unsigned int maxAge) + unsigned int maxAge) { BoBData b; - b.setCid(QString("sha1+%1@bob.xmpp.org").arg(QString( - QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex()))); + b.setHash(Hash::from(Hash::Sha1, data)); b.setData(data); b.setMaxAge(maxAge); b.setType(type); @@ -188,20 +206,20 @@ BoBData BoBManager::append(const QByteArray &data, const QString &type, return b; } -QString BoBManager::append(QFile &file, const QString &type) +XMPP::Hash BoBManager::append(QFile &file, const QString &type) { bool isOpen = file.isOpen(); if (isOpen || file.open(QIODevice::ReadOnly)) { - QString cid = QString("sha1+%1@bob.xmpp.org").arg( - QString(QCryptographicHash::hash(file.readAll(), - QCryptographicHash::Sha1).toHex())); - _localFiles[cid] = QPair(file.fileName(), type); + Hash h = Hash::from(Hash::Sha1, &file); + if (h.isValid()) { + _localFiles[h] = QPair(file.fileName(), type); + } if (!isOpen) { file.close(); } - return cid; + return h; } - return QString(); + return XMPP::Hash(); } void BoBManager::append(const BoBData &data) diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h index 7a856478..c8f2de3a 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h @@ -20,6 +20,7 @@ #define XMPP_BITSOFBINARY_H #include "xmpp/jid/jid.h" +#include "xmpp_hash.h" #include #include @@ -28,70 +29,73 @@ #include namespace XMPP { - class Client; - class JT_BitsOfBinary; - - class BoBData - { - class Private; - public: - BoBData(); - BoBData(const BoBData &other); - BoBData(const QDomElement &); - ~BoBData(); - BoBData &operator=(const BoBData &other); - - bool isNull() const; - - QString cid() const; - void setCid(const QString &); - - QByteArray data() const; - void setData(const QByteArray &); - - QString type() const; - void setType(const QString &); - - unsigned int maxAge() const; - void setMaxAge(unsigned int); - - void fromXml(const QDomElement &); - QDomElement toXml(QDomDocument *doc) const; - - private: - QSharedDataPointer d; - }; - - class BoBCache : public QObject - { - Q_OBJECT - - public: - BoBCache(QObject *parent); - virtual void put(const BoBData &) = 0; - virtual BoBData get(const QString &) = 0; - }; - - class BoBManager : public QObject - { - Q_OBJECT - - public: - BoBManager(Client *); - void setCache(BoBCache*); - - BoBData bobData(const QString &); - // file data, mime type, max age in seconds - BoBData append(const QByteArray &data, const QString &type, - unsigned int maxAge = 0); - QString append(QFile &file, - const QString &type = "application/octet-stream"); - void append(const BoBData &); - - private: - BoBCache *_cache; - QHash > _localFiles; //cid => (filename, mime) - }; +class Client; +class JT_BitsOfBinary; + +class BoBData { + class Private; + +public: + BoBData(); + BoBData(const BoBData &other); + BoBData(const QDomElement &); + ~BoBData(); + BoBData &operator=(const BoBData &other); + + bool isNull() const; + + static Hash cidToHash(const QString &cid); + + QString cid() const; + void setCid(const QString &); + + const Hash &hash() const; + void setHash(const Hash &hash); + + QByteArray data() const; + void setData(const QByteArray &); + + QString type() const; + void setType(const QString &); + + unsigned int maxAge() const; + void setMaxAge(unsigned int); + + void fromXml(const QDomElement &); + QDomElement toXml(QDomDocument *doc) const; + +private: + QSharedDataPointer d; +}; + +class BoBCache : public QObject { + Q_OBJECT + +public: + BoBCache(QObject *parent); + virtual void put(const BoBData &) = 0; + virtual BoBData get(const Hash &) = 0; +}; + +class BoBManager : public QObject { + Q_OBJECT + +public: + BoBManager(Client *); + void setCache(BoBCache *); + + BoBData bobData(const QString &); + // file data, mime type, max age in seconds + BoBData append(const QByteArray &data, const QString &type, + unsigned int maxAge = 0); + Hash append(QFile & file, + const QString &type = "application/octet-stream"); // this method adds just to runtime cache + void append(const BoBData &); + +private: + BoBCache * _cache; + QHash> _localFiles; //cid => (filename, mime) +}; } // namespace XMPP #endif // XMPP_BITSOFBINARY_H diff --git a/src/xmpp/xmpp-im/xmpp_hash.h b/src/xmpp/xmpp-im/xmpp_hash.h index 5b2a0852..72b17a36 100644 --- a/src/xmpp/xmpp-im/xmpp_hash.h +++ b/src/xmpp/xmpp-im/xmpp_hash.h @@ -21,51 +21,70 @@ #include "xmpp_stanza.h" -#include #include class QDomElement; namespace XMPP { - extern QString HASH_NS; - class Features; - - class Hash - { - public: - - enum Type { // XEP-0300 Version 0.5.3 (2018-02-14) - Unknown, // not standard, just a default - Sha1, // SHOULD NOT - Sha256, // MUST - Sha512, // SHOULD - Sha3_256, // MUST - Sha3_512, // SHOULD - Blake2b256, // MUST - Blake2b512, // SHOULD - LastType = Blake2b512 - }; - - inline Hash(Type type = Type::Unknown) : v_type(type) {} - Hash(const QDomElement&); - - inline bool isValid() const { return v_type > Unknown && v_type <= LastType; } - - inline Type type() const { return v_type; } - inline void setType(Type t) { v_type = t; } - - inline QByteArray data() const { return v_data; } - inline void setData(const QByteArray &d) { v_data = d; } // sets already computed hash - bool computeFromData(const QByteArray &); // computes hash from passed data - bool computeFromDevice(QIODevice *dev); - - QDomElement toXml(QDomDocument *doc) const; - static void populateFeatures(XMPP::Features &); - - private: - Type v_type = Type::Unknown; - QByteArray v_data; + +extern QString HASH_NS; +class Features; + +class Hash { +public: + enum Type { // XEP-0300 Version 0.5.3 (2018-02-14) + Unknown, // not standard, just a default + Sha1, // SHOULD NOT + Sha256, // MUST + Sha512, // SHOULD + Sha3_256, // MUST + Sha3_512, // SHOULD + Blake2b256, // MUST + Blake2b512, // SHOULD + LastType = Blake2b512 }; + + inline Hash(Type type = Type::Unknown) : + v_type(type) {} + inline Hash(Type type, const QByteArray &data) : + v_type(type), v_data(data) {} + inline Hash(const QStringRef &algo) : + v_type(parseType(algo)) {} + Hash(const QDomElement &); + + inline bool operator==(const Hash &other) const { return v_type == other.v_type && v_data == other.v_data; } + + inline bool isValid() const { return v_type > Unknown && v_type <= LastType; } + + inline Type type() const { return v_type; } + inline void setType(Type t) { v_type = t; } + QString stringType() const; + static Type parseType(const QStringRef &algo); + + inline QByteArray data() const { return v_data; } + inline void setData(const QByteArray &d) { v_data = d; } // sets already computed hash + inline QByteArray toHex() const { return v_data.toHex(); } + inline QByteArray toBase64() const { return v_data.toBase64(); } + inline QString toString() const { return QString("%1+%2").arg(stringType(), QString::fromLatin1(v_data.toHex())); } + bool compute(const QByteArray &); // computes hash from passed data + bool compute(QIODevice *dev); + + QDomElement toXml(QDomDocument *doc) const; + static void populateFeatures(XMPP::Features &); + static Hash from(Type t, const QByteArray &fileData); + static Hash from(XMPP::Hash::Type t, QIODevice *dev); + static Hash from(const QStringRef &str); // e.g. sha1+aabccddeeffaabbcc232387539465923645 + +private: + Type v_type = Type::Unknown; + QByteArray v_data; +}; + +Q_DECL_PURE_FUNCTION inline uint qHash(const Hash &hash, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(hash.data(), seed); +} + } // namespace XMPP #endif // XMPP_HASH_H diff --git a/src/xmpp/xmpp-im/xmpp_status.h b/src/xmpp/xmpp-im/xmpp_status.h index a37f5988..f3caa4a8 100644 --- a/src/xmpp/xmpp-im/xmpp_status.h +++ b/src/xmpp/xmpp-im/xmpp_status.h @@ -30,121 +30,125 @@ #include namespace XMPP { - class DiscoItem; - class StatusPrivate; - - class CapsSpec - { - public: - typedef QMap CryptoMap; - static const QCryptographicHash::Algorithm invalidAlgo = (QCryptographicHash::Algorithm)255; - - CapsSpec(); - CapsSpec(const QString& node, QCryptographicHash::Algorithm hashAlgo, const QString& ver = QString()); - CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlgo = QCryptographicHash::Sha1); - - bool isValid() const; - const QString& node() const; - const QString& version() const; - QCryptographicHash::Algorithm hashAlgorithm() const; - inline const QStringList &ext() const { return ext_; } - QString flatten() const; - - void resetVersion(); - - bool operator==(const CapsSpec&) const; - bool operator!=(const CapsSpec&) const; - bool operator<(const CapsSpec&) const; - - QDomElement toXml(QDomDocument *doc) const; - static CapsSpec fromXml(const QDomElement &e); - - static CryptoMap &cryptoMap(); - - private: - QString node_, ver_; - QCryptographicHash::Algorithm hashAlgo_; - QStringList ext_; - }; - - class Status - { - public: - enum Type { Offline, Online, Away, XA, DND, Invisible, FFC }; - - Status(const QString &show=QString(), const QString &status=QString(), int priority=0, bool available=true); - Status(Type type, const QString& status=QString(), int priority=0); - Status(const Status &); - Status &operator=(const Status &); - ~Status(); - - int priority() const; - Type type() const; - QString typeString() const; - const QString & show() const; - const QString & status() const; - QDateTime timeStamp() const; - const QString & keyID() const; - bool isAvailable() const; - bool isAway() const; - bool isInvisible() const; - bool hasError() const; - int errorCode() const; - const QString & errorString() const; - - const QString & xsigned() const; - const QString & songTitle() const; - const CapsSpec & caps() const; - - bool isMUC() const; - bool hasMUCItem() const; - const MUCItem & mucItem() const; - bool hasMUCDestroy() const; - const MUCDestroy & mucDestroy() const; - const QList& getMUCStatuses() const; - const QString& mucPassword() const; - bool hasMUCHistory() const; - int mucHistoryMaxChars() const; - int mucHistoryMaxStanzas() const; - int mucHistorySeconds() const; - const QDateTime & mucHistorySince() const; - - static Type txt2type(const QString& stat); - - void setPriority(int); - void setType(Type); - void setType(const QString &); - void setShow(const QString &); - void setStatus(const QString &); - void setTimeStamp(const QDateTime &); - void setKeyID(const QString &); - void setIsAvailable(bool); - void setIsInvisible(bool); - void setError(int, const QString &); - void setCaps(const CapsSpec&); - - void setMUC(); - void setMUCItem(const MUCItem&); - void setMUCDestroy(const MUCDestroy&); - void addMUCStatus(int); - void setMUCPassword(const QString&); - void setMUCHistory(int maxchars, int maxstanzas, int seconds, const QDateTime &since); - - void setXSigned(const QString &); - void setSongTitle(const QString &); - - // XEP-153: VCard-based Avatars - const QString& photoHash() const; - void setPhotoHash(const QString&); - bool hasPhotoHash() const; - - // XEP-0231 bits of binary - void addBoBData(const BoBData &); - QList bobDataList() const; - - private: - QSharedDataPointer d; - }; +class DiscoItem; +class StatusPrivate; + +class CapsSpec { +public: + typedef QMap CryptoMap; + static const QCryptographicHash::Algorithm invalidAlgo = (QCryptographicHash::Algorithm)255; + + CapsSpec(); + CapsSpec(const QString &node, QCryptographicHash::Algorithm hashAlgo, const QString &ver = QString()); + CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlgo = QCryptographicHash::Sha1); + + bool isValid() const; + const QString & node() const; + const QString & version() const; + QCryptographicHash::Algorithm hashAlgorithm() const; + inline const QStringList & ext() const { return ext_; } + QString flatten() const; + + void resetVersion(); + + bool operator==(const CapsSpec &) const; + bool operator!=(const CapsSpec &) const; + bool operator<(const CapsSpec &) const; + + QDomElement toXml(QDomDocument *doc) const; + static CapsSpec fromXml(const QDomElement &e); + + static CryptoMap &cryptoMap(); + +private: + QString node_, ver_; + QCryptographicHash::Algorithm hashAlgo_; + QStringList ext_; +}; + +class Status { +public: + enum Type { Offline, + Online, + Away, + XA, + DND, + Invisible, + FFC }; + + Status(const QString &show = QString(), const QString &status = QString(), int priority = 0, bool available = true); + Status(Type type, const QString &status = QString(), int priority = 0); + Status(const Status &); + Status &operator=(const Status &); + ~Status(); + + int priority() const; + Type type() const; + QString typeString() const; + const QString &show() const; + const QString &status() const; + QDateTime timeStamp() const; + const QString &keyID() const; + bool isAvailable() const; + bool isAway() const; + bool isInvisible() const; + bool hasError() const; + int errorCode() const; + const QString &errorString() const; + + const QString & xsigned() const; + const QString & songTitle() const; + const CapsSpec &caps() const; + + bool isMUC() const; + bool hasMUCItem() const; + const MUCItem & mucItem() const; + bool hasMUCDestroy() const; + const MUCDestroy &mucDestroy() const; + const QList &getMUCStatuses() const; + const QString & mucPassword() const; + bool hasMUCHistory() const; + int mucHistoryMaxChars() const; + int mucHistoryMaxStanzas() const; + int mucHistorySeconds() const; + const QDateTime & mucHistorySince() const; + + static Type txt2type(const QString &stat); + + void setPriority(int); + void setType(Type); + void setType(const QString &); + void setShow(const QString &); + void setStatus(const QString &); + void setTimeStamp(const QDateTime &); + void setKeyID(const QString &); + void setIsAvailable(bool); + void setIsInvisible(bool); + void setError(int, const QString &); + void setCaps(const CapsSpec &); + + void setMUC(); + void setMUCItem(const MUCItem &); + void setMUCDestroy(const MUCDestroy &); + void addMUCStatus(int); + void setMUCPassword(const QString &); + void setMUCHistory(int maxchars, int maxstanzas, int seconds, const QDateTime &since); + + void setXSigned(const QString &); + void setSongTitle(const QString &); + + // XEP-153: VCard-based Avatars + const QByteArray &photoHash() const; + void setPhotoHash(const QByteArray &); + bool hasPhotoHash() const; + + // XEP-0231 bits of binary + void addBoBData(const BoBData &); + QList bobDataList() const; + +private: + QSharedDataPointer d; +}; } // namespace XMPP Q_DECLARE_METATYPE(XMPP::Status) diff --git a/src/xmpp/xmpp-im/xmpp_tasks.cpp b/src/xmpp/xmpp-im/xmpp_tasks.cpp index c47e87c2..104a0de5 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.cpp +++ b/src/xmpp/xmpp-im/xmpp_tasks.cpp @@ -34,9 +34,9 @@ using namespace XMPP; static QString lineEncode(QString str) { - str.replace(QRegExp("\\\\"), "\\\\"); // backslash to double-backslash - str.replace(QRegExp("\\|"), "\\p"); // pipe to \p - str.replace(QRegExp("\n"), "\\n"); // newline to \n + str.replace(QRegExp("\\\\"), "\\\\"); // backslash to double-backslash + str.replace(QRegExp("\\|"), "\\p"); // pipe to \p + str.replace(QRegExp("\n"), "\\n"); // newline to \n return str; } @@ -44,20 +44,19 @@ static QString lineDecode(const QString &str) { QString ret; - for(int n = 0; n < str.length(); ++n) { - if(str.at(n) == '\\') { + for (int n = 0; n < str.length(); ++n) { + if (str.at(n) == '\\') { ++n; - if(n >= str.length()) + if (n >= str.length()) break; - if(str.at(n) == 'n') + if (str.at(n) == 'n') ret.append('\n'); - if(str.at(n) == 'p') + if (str.at(n) == 'p') ret.append('|'); - if(str.at(n) == '\\') + if (str.at(n) == '\\') ret.append('\\'); - } - else { + } else { ret.append(str.at(n)); } } @@ -69,16 +68,16 @@ static Roster xmlReadRoster(const QDomElement &q, bool push) { Roster r; - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "item") { + if (i.tagName() == "item") { RosterItem item; item.fromXml(i); - if(push) + if (push) item.setIsPush(true); r += item; @@ -94,32 +93,32 @@ static Roster xmlReadRoster(const QDomElement &q, bool push) // #include "protocol.h" -JT_Session::JT_Session(Task *parent) : Task(parent) +JT_Session::JT_Session(Task *parent) : + Task(parent) { } void JT_Session::onGo() { - QDomElement iq = createIQ(doc(), "set", "", id()); + QDomElement iq = createIQ(doc(), "set", "", id()); QDomElement session = doc()->createElementNS(NS_SESSION, "session"); iq.appendChild(session); send(iq); } -bool JT_Session::take(const QDomElement& x) +bool JT_Session::take(const QDomElement &x) { QString from = x.attribute("from"); if (!from.endsWith("chat.facebook.com")) { // remove this code when chat.facebook.com is disabled completely from.clear(); } - if(!iqVerify(x, from, id())) + if (!iqVerify(x, from, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { setSuccess(); - } - else { + } else { setError(x); } return true; @@ -128,25 +127,24 @@ bool JT_Session::take(const QDomElement& x) //---------------------------------------------------------------------------- // JT_Register //---------------------------------------------------------------------------- -class JT_Register::Private -{ +class JT_Register::Private { public: Private() = default; - Form form; + Form form; XData xdata; - bool hasXData; - bool registered; - Jid jid; - int type; + bool hasXData; + bool registered; + Jid jid; + int type; }; -JT_Register::JT_Register(Task *parent) -:Task(parent) +JT_Register::JT_Register(Task *parent) : + Task(parent) { - d = new Private; - d->type = -1; - d->hasXData = false; + d = new Private; + d->type = -1; + d->hasXData = false; d->registered = false; } @@ -157,9 +155,9 @@ JT_Register::~JT_Register() void JT_Register::reg(const QString &user, const QString &pass) { - d->type = 0; - to = client()->host(); - iq = createIQ(doc(), "set", to.full(), id()); + d->type = 0; + to = client()->host(); + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "username", user)); @@ -168,9 +166,9 @@ void JT_Register::reg(const QString &user, const QString &pass) void JT_Register::changepw(const QString &pass) { - d->type = 1; - to = client()->host(); - iq = createIQ(doc(), "set", to.full(), id()); + d->type = 1; + to = client()->host(); + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "username", client()->user())); @@ -179,14 +177,14 @@ void JT_Register::changepw(const QString &pass) void JT_Register::unreg(const Jid &j) { - d->type = 2; - to = j.isEmpty() ? client()->host() : j.full(); - iq = createIQ(doc(), "set", to.full(), id()); + d->type = 2; + to = j.isEmpty() ? client()->host() : j.full(); + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); // this may be useful - if(!d->form.key().isEmpty()) + if (!d->form.key().isEmpty()) query.appendChild(textTag(doc(), "key", d->form.key())); query.appendChild(doc()->createElement("remove")); @@ -194,42 +192,42 @@ void JT_Register::unreg(const Jid &j) void JT_Register::getForm(const Jid &j) { - d->type = 3; - to = j; - iq = createIQ(doc(), "get", to.full(), id()); + d->type = 3; + to = j; + iq = createIQ(doc(), "get", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); } void JT_Register::setForm(const Form &form) { - d->type = 4; - to = form.jid(); - iq = createIQ(doc(), "set", to.full(), id()); + d->type = 4; + to = form.jid(); + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); // key? - if(!form.key().isEmpty()) + if (!form.key().isEmpty()) query.appendChild(textTag(doc(), "key", form.key())); // fields - for(Form::ConstIterator it = form.begin(); it != form.end(); ++it) { + for (Form::ConstIterator it = form.begin(); it != form.end(); ++it) { const FormField &f = *it; query.appendChild(textTag(doc(), f.realName(), f.value())); } } -void JT_Register::setForm(const Jid& to, const XData& xdata) +void JT_Register::setForm(const Jid &to, const XData &xdata) { - d->type = 4; - iq = createIQ(doc(), "set", to.full(), id()); + d->type = 4; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:register", "query"); iq.appendChild(query); query.appendChild(xdata.toXml(doc(), true)); } -const Form & JT_Register::form() const +const Form &JT_Register::form() const { return d->form; } @@ -239,7 +237,7 @@ bool JT_Register::hasXData() const return d->hasXData; } -const XData& JT_Register::xdata() const +const XData &JT_Register::xdata() const { return d->xdata; } @@ -256,37 +254,35 @@ void JT_Register::onGo() bool JT_Register::take(const QDomElement &x) { - if(!iqVerify(x, to, id())) + if (!iqVerify(x, to, id())) return false; Jid from(x.attribute("from")); - if(x.attribute("type") == "result") { - if(d->type == 3) { + if (x.attribute("type") == "result") { + if (d->type == 3) { d->form.clear(); d->form.setJid(from); QDomElement q = queryTag(x); - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "instructions") + if (i.tagName() == "instructions") d->form.setInstructions(tagContent(i)); - else if(i.tagName() == "key") + else if (i.tagName() == "key") d->form.setKey(tagContent(i)); else if (i.tagName() == QLatin1String("registered")) d->registered = true; - else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { + else if (i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; - } - else if(i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { + } else if (i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { client()->bobManager()->append(BoBData(i)); // xep-0231 - } - else { + } else { FormField f; - if(f.setType(i.tagName())) { + if (f.setType(i.tagName())) { f.setValue(tagContent(i)); d->form += f; } @@ -295,8 +291,7 @@ bool JT_Register::take(const QDomElement &x) } setSuccess(); - } - else + } else setError(x); return true; @@ -305,19 +300,18 @@ bool JT_Register::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_UnRegister //---------------------------------------------------------------------------- -class JT_UnRegister::Private -{ +class JT_UnRegister::Private { public: Private() = default; - Jid j; + Jid j; JT_Register *jt_reg = nullptr; }; -JT_UnRegister::JT_UnRegister(Task *parent) -: Task(parent) +JT_UnRegister::JT_UnRegister(Task *parent) : + Task(parent) { - d = new Private; + d = new Private; d->jt_reg = nullptr; } @@ -356,7 +350,7 @@ void JT_UnRegister::getFormFinished() void JT_UnRegister::unregFinished() { - if ( d->jt_reg->success() ) + if (d->jt_reg->success()) setSuccess(); else setError(d->jt_reg->statusCode(), d->jt_reg->statusString()); @@ -368,20 +362,19 @@ void JT_UnRegister::unregFinished() //---------------------------------------------------------------------------- // JT_Roster //---------------------------------------------------------------------------- -class JT_Roster::Private -{ +class JT_Roster::Private { public: Private() = default; - Roster roster; + Roster roster; QList itemList; }; -JT_Roster::JT_Roster(Task *parent) -:Task(parent) +JT_Roster::JT_Roster(Task *parent) : + Task(parent) { type = -1; - d = new Private; + d = new Private; } JT_Roster::~JT_Roster() @@ -393,7 +386,7 @@ void JT_Roster::get() { type = 0; //to = client()->host(); - iq = createIQ(doc(), "get", to.full(), id()); + iq = createIQ(doc(), "get", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); } @@ -404,9 +397,9 @@ void JT_Roster::set(const Jid &jid, const QString &name, const QStringList &grou //to = client()->host(); QDomElement item = doc()->createElement("item"); item.setAttribute("jid", jid.full()); - if(!name.isEmpty()) + if (!name.isEmpty()) item.setAttribute("name", name); - for(QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it) + for (QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it) item.appendChild(textTag(doc(), "group", *it)); d->itemList += item; } @@ -423,32 +416,32 @@ void JT_Roster::remove(const Jid &jid) void JT_Roster::onGo() { - if(type == 0) + if (type == 0) send(iq); - else if(type == 1) { + else if (type == 1) { //to = client()->host(); - iq = createIQ(doc(), "set", to.full(), id()); + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); - foreach (const QDomElement& it, d->itemList) + foreach (const QDomElement &it, d->itemList) query.appendChild(it); send(iq); } } -const Roster & JT_Roster::roster() const +const Roster &JT_Roster::roster() const { return d->roster; } QString JT_Roster::toString() const { - if(type != 1) + if (type != 1) return ""; QDomElement i = doc()->createElement("request"); i.setAttribute("type", "JT_Roster"); - foreach (const QDomElement& it, d->itemList) + foreach (const QDomElement &it, d->itemList) i.appendChild(it); return lineEncode(Stream::xmlToString(i)); return ""; @@ -457,19 +450,19 @@ QString JT_Roster::toString() const bool JT_Roster::fromString(const QString &str) { QDomDocument *dd = new QDomDocument; - if(!dd->setContent(lineDecode(str).toUtf8())) + if (!dd->setContent(lineDecode(str).toUtf8())) return false; QDomElement e = doc()->importNode(dd->documentElement(), true).toElement(); delete dd; - if(e.tagName() != "request" || e.attribute("type") != "JT_Roster") + if (e.tagName() != "request" || e.attribute("type") != "JT_Roster") return false; type = 1; d->itemList.clear(); - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; d->itemList += i; } @@ -479,25 +472,24 @@ bool JT_Roster::fromString(const QString &str) bool JT_Roster::take(const QDomElement &x) { - if(!iqVerify(x, client()->host(), id())) + if (!iqVerify(x, client()->host(), id())) return false; // get - if(type == 0) { - if(x.attribute("type") == "result") { + if (type == 0) { + if (x.attribute("type") == "result") { QDomElement q = queryTag(x); - d->roster = xmlReadRoster(q, false); + d->roster = xmlReadRoster(q, false); setSuccess(); - } - else { + } else { setError(x); } return true; } // set - else if(type == 1) { - if(x.attribute("type") == "result") + else if (type == 1) { + if (x.attribute("type") == "result") setSuccess(); else setError(x); @@ -505,7 +497,7 @@ bool JT_Roster::take(const QDomElement &x) return true; } // remove - else if(type == 2) { + else if (type == 2) { setSuccess(); return true; } @@ -516,7 +508,8 @@ bool JT_Roster::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_PushRoster //---------------------------------------------------------------------------- -JT_PushRoster::JT_PushRoster(Task *parent) : Task(parent) +JT_PushRoster::JT_PushRoster(Task *parent) : + Task(parent) { } @@ -527,10 +520,10 @@ JT_PushRoster::~JT_PushRoster() bool JT_PushRoster::take(const QDomElement &e) { // must be an iq-set tag - if(e.tagName() != "iq" || e.attribute("type") != "set") + if (e.tagName() != "iq" || e.attribute("type") != "set") return false; - if(!iqVerify(e, client()->host(), "", "jabber:iq:roster")) + if (!iqVerify(e, client()->host(), "", "jabber:iq:roster")) return false; roster(xmlReadRoster(queryTag(e), true)); @@ -542,7 +535,8 @@ bool JT_PushRoster::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_Presence //---------------------------------------------------------------------------- -JT_Presence::JT_Presence(Task *parent) : Task(parent) +JT_Presence::JT_Presence(Task *parent) : + Task(parent) { } @@ -555,27 +549,26 @@ void JT_Presence::pres(const Status &s) type = 0; tag = doc()->createElement("presence"); - if(!s.isAvailable()) { + if (!s.isAvailable()) { tag.setAttribute("type", "unavailable"); - if(!s.status().isEmpty()) + if (!s.status().isEmpty()) tag.appendChild(textTag(doc(), "status", s.status())); - } - else { - if(s.isInvisible()) + } else { + if (s.isInvisible()) tag.setAttribute("type", "invisible"); - if(!s.show().isEmpty()) + if (!s.show().isEmpty()) tag.appendChild(textTag(doc(), "show", s.show())); - if(!s.status().isEmpty()) + if (!s.status().isEmpty()) tag.appendChild(textTag(doc(), "status", s.status())); - tag.appendChild( textTag(doc(), "priority", QString("%1").arg(s.priority()) ) ); + tag.appendChild(textTag(doc(), "priority", QString("%1").arg(s.priority()))); - if(!s.keyID().isEmpty()) { + if (!s.keyID().isEmpty()) { QDomElement x = textTagNS(doc(), "http://jabber.org/protocol/e2e", "x", s.keyID()); tag.appendChild(x); } - if(!s.xsigned().isEmpty()) { + if (!s.xsigned().isEmpty()) { QDomElement x = textTagNS(doc(), "jabber:x:signed", "x", s.xsigned()); tag.appendChild(x); } @@ -587,19 +580,19 @@ void JT_Presence::pres(const Status &s) } } - if(s.isMUC()) { + if (s.isMUC()) { QDomElement m = doc()->createElementNS("http://jabber.org/protocol/muc", "x"); if (!s.mucPassword().isEmpty()) { - m.appendChild(textTag(doc(),"password",s.mucPassword())); + m.appendChild(textTag(doc(), "password", s.mucPassword())); } if (s.hasMUCHistory()) { QDomElement h = doc()->createElement("history"); if (s.mucHistoryMaxChars() >= 0) - h.setAttribute("maxchars",s.mucHistoryMaxChars()); + h.setAttribute("maxchars", s.mucHistoryMaxChars()); if (s.mucHistoryMaxStanzas() >= 0) - h.setAttribute("maxstanzas",s.mucHistoryMaxStanzas()); + h.setAttribute("maxstanzas", s.mucHistoryMaxStanzas()); if (s.mucHistorySeconds() >= 0) - h.setAttribute("seconds",s.mucHistorySeconds()); + h.setAttribute("seconds", s.mucHistorySeconds()); if (!s.mucHistorySince().isNull()) h.setAttribute("since", s.mucHistorySince().toUTC().addSecs(1).toString(Qt::ISODate)); m.appendChild(h); @@ -607,14 +600,14 @@ void JT_Presence::pres(const Status &s) tag.appendChild(m); } - if(s.hasPhotoHash()) { - QDomElement m = doc()->createElementNS("vcard-temp:x:update","x"); - m.appendChild(textTag(doc(), "photo", s.photoHash())); + if (s.hasPhotoHash()) { + QDomElement m = doc()->createElementNS("vcard-temp:x:update", "x"); + m.appendChild(textTag(doc(), "photo", QString::fromLatin1(s.photoHash().toHex()))); tag.appendChild(m); } // bits of binary - foreach(const BoBData &bd, s.bobDataList()) { + foreach (const BoBData &bd, s.bobDataList()) { tag.appendChild(bd.toXml(doc())); } } @@ -626,17 +619,15 @@ void JT_Presence::pres(const Jid &to, const Status &s) tag.setAttribute("to", to.full()); } -void JT_Presence::sub(const Jid &to, const QString &subType, const QString& nick) +void JT_Presence::sub(const Jid &to, const QString &subType, const QString &nick) { type = 1; tag = doc()->createElement("presence"); tag.setAttribute("to", to.full()); tag.setAttribute("type", subType); - if (!nick.isEmpty() && (subType == QLatin1String("subscribe") || subType == QLatin1String("subscribed") || - subType == QLatin1String("unsubscribe") || subType == QLatin1String("unsubscribed"))) - { - QDomElement nick_tag = textTagNS(doc(),"http://jabber.org/protocol/nick","nick",nick); + if (!nick.isEmpty() && (subType == QLatin1String("subscribe") || subType == QLatin1String("subscribed") || subType == QLatin1String("unsubscribe") || subType == QLatin1String("unsubscribed"))) { + QDomElement nick_tag = textTagNS(doc(), "http://jabber.org/protocol/nick", "nick", nick); tag.appendChild(nick_tag); } } @@ -659,8 +650,8 @@ void JT_Presence::onGo() //---------------------------------------------------------------------------- // JT_PushPresence //---------------------------------------------------------------------------- -JT_PushPresence::JT_PushPresence(Task *parent) - : Task(parent) +JT_PushPresence::JT_PushPresence(Task *parent) : + Task(parent) { } @@ -670,26 +661,23 @@ JT_PushPresence::~JT_PushPresence() bool JT_PushPresence::take(const QDomElement &e) { - if(e.tagName() != "presence") + if (e.tagName() != "presence") return false; - Jid j(e.attribute("from")); + Jid j(e.attribute("from")); Status p; - if(e.hasAttribute("type")) { + if (e.hasAttribute("type")) { QString type = e.attribute("type"); - if(type == "unavailable") { + if (type == "unavailable") { p.setIsAvailable(false); - } - else if(type == "error") { - QString str = ""; - int code = 0; + } else if (type == "error") { + QString str = ""; + int code = 0; getErrorFromElement(e, client()->stream().baseNS(), &code, &str); p.setError(code, str); - } - else if(type == QLatin1String("subscribe") || type == QLatin1String("subscribed") || - type == QLatin1String("unsubscribe") || type == QLatin1String("unsubscribed")) { - QString nick; + } else if (type == QLatin1String("subscribe") || type == QLatin1String("subscribed") || type == QLatin1String("unsubscribe") || type == QLatin1String("unsubscribed")) { + QString nick; QDomElement tag = e.firstChildElement("nick"); if (!tag.isNull() && tag.namespaceURI() == "http://jabber.org/protocol/nick") { nick = tagContent(tag); @@ -702,69 +690,62 @@ bool JT_PushPresence::take(const QDomElement &e) QDomElement tag; tag = e.firstChildElement("status"); - if(!tag.isNull()) + if (!tag.isNull()) p.setStatus(tagContent(tag)); tag = e.firstChildElement("show"); - if(!tag.isNull()) + if (!tag.isNull()) p.setShow(tagContent(tag)); tag = e.firstChildElement("priority"); - if(!tag.isNull()) + if (!tag.isNull()) p.setPriority(tagContent(tag).toInt()); QDateTime stamp; - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:delay") { - if(i.hasAttribute("stamp") && !stamp.isValid()) { + if (i.tagName() == "x" && i.namespaceURI() == "jabber:x:delay") { + if (i.hasAttribute("stamp") && !stamp.isValid()) { stamp = stamp2TS(i.attribute("stamp")); } - } - else if(i.tagName() == "delay" && i.namespaceURI() == "urn:xmpp:delay") { - if(i.hasAttribute("stamp") && !stamp.isValid()) { + } else if (i.tagName() == "delay" && i.namespaceURI() == "urn:xmpp:delay") { + if (i.hasAttribute("stamp") && !stamp.isValid()) { stamp = QDateTime::fromString(i.attribute("stamp").left(19), Qt::ISODate); } - } - else if(i.tagName() == "x" && i.namespaceURI() == "gabber:x:music:info") { + } else if (i.tagName() == "x" && i.namespaceURI() == "gabber:x:music:info") { QDomElement t; - QString title, state; + QString title, state; t = i.firstChildElement("title"); - if(!t.isNull()) + if (!t.isNull()) title = tagContent(t); t = i.firstChildElement("state"); - if(!t.isNull()) + if (!t.isNull()) state = tagContent(t); - if(!title.isEmpty() && state == "playing") + if (!title.isEmpty() && state == "playing") p.setSongTitle(title); - } - else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:signed") { + } else if (i.tagName() == "x" && i.namespaceURI() == "jabber:x:signed") { p.setXSigned(tagContent(i)); - } - else if(i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/e2e") { + } else if (i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/e2e") { p.setKeyID(tagContent(i)); - } - else if(i.tagName() == "c" && i.namespaceURI() == NS_CAPS) { + } else if (i.tagName() == "c" && i.namespaceURI() == NS_CAPS) { p.setCaps(CapsSpec::fromXml(i)); - if(!e.hasAttribute("type") && p.caps().isValid()) { + if (!e.hasAttribute("type") && p.caps().isValid()) { client()->capsManager()->updateCaps(j, p.caps()); } - } - else if(i.tagName() == "x" && i.namespaceURI() == "vcard-temp:x:update") { + } else if (i.tagName() == "x" && i.namespaceURI() == "vcard-temp:x:update") { QDomElement t; t = i.firstChildElement("photo"); if (!t.isNull()) - p.setPhotoHash(tagContent(t).toLower()); // if hash is empty this may mean photo removal + p.setPhotoHash(QByteArray::fromHex(tagContent(t).toLatin1())); // if hash is empty this may mean photo removal // else vcard.hasPhotoHash() returns false and that's mean user is not yet ready to advertise his image - } - else if(i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/muc#user") { - for(QDomNode muc_n = i.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { + } else if (i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/muc#user") { + for (QDomNode muc_n = i.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { QDomElement muc_e = muc_n.toElement(); - if(muc_e.isNull()) + if (muc_e.isNull()) continue; if (muc_e.tagName() == "item") @@ -774,8 +755,7 @@ bool JT_PushPresence::take(const QDomElement &e) else if (muc_e.tagName() == "destroy") p.setMUCDestroy(MUCDestroy(muc_e)); } - } - else if (i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { + } else if (i.tagName() == "data" && i.namespaceURI() == "urn:xmpp:bob") { BoBData bd(i); client()->bobManager()->append(bd); p.addBoBData(bd); @@ -804,32 +784,32 @@ static QDomElement oldStyleNS(const QDomElement &e) { // find closest parent with a namespace QDomNode par = e.parentNode(); - while(!par.isNull() && par.namespaceURI().isNull()) + while (!par.isNull() && par.namespaceURI().isNull()) par = par.parentNode(); bool noShowNS = false; - if(!par.isNull() && par.namespaceURI() == e.namespaceURI()) + if (!par.isNull() && par.namespaceURI() == e.namespaceURI()) noShowNS = true; QDomElement i; - int x; + int x; //if(noShowNS) - i = e.ownerDocument().createElement(e.tagName()); + i = e.ownerDocument().createElement(e.tagName()); //else // i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName()); // copy attributes QDomNamedNodeMap al = e.attributes(); - for(x = 0; x < al.count(); ++x) + for (x = 0; x < al.count(); ++x) i.setAttributeNode(al.item(x).cloneNode().toAttr()); - if(!noShowNS) + if (!noShowNS) i.setAttribute("xmlns", e.namespaceURI()); // copy children QDomNodeList nl = e.childNodes(); - for(x = 0; x < nl.count(); ++x) { + for (x = 0; x < nl.count(); ++x) { QDomNode n = nl.item(x); - if(n.isElement()) + if (n.isElement()) i.appendChild(oldStyleNS(n.toElement())); else i.appendChild(n.cloneNode()); @@ -837,9 +817,8 @@ static QDomElement oldStyleNS(const QDomElement &e) return i; } -JT_Message::JT_Message(Task *parent, Message &msg) - : Task(parent) - , m(msg) +JT_Message::JT_Message(Task *parent, Message &msg) : + Task(parent), m(msg) { if (msg.id().isEmpty()) msg.setId(id()); @@ -852,11 +831,11 @@ JT_Message::~JT_Message() void JT_Message::onGo() { - Stanza s = m.toStanza(&(client()->stream())); - QDomElement e = s.element();//oldStyleNS(s.element()); + Stanza s = m.toStanza(&(client()->stream())); + QDomElement e = s.element(); //oldStyleNS(s.element()); auto encryptionHandler = client()->encryptionHandler(); - bool wasEncrypted = encryptionHandler && encryptionHandler->encryptMessageElement(e); + bool wasEncrypted = encryptionHandler && encryptionHandler->encryptMessageElement(e); m.setWasEncrypted(wasEncrypted); // if the element is null, then the encryption is happening asynchronously @@ -874,10 +853,10 @@ class JT_PushMessage::Private { EncryptionHandler *m_encryptionHandler; }; -JT_PushMessage::JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler) -:Task(parent) +JT_PushMessage::JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler) : + Task(parent) { - d = new Private; + d = new Private; d->m_encryptionHandler = encryptionHandler; } @@ -888,7 +867,7 @@ JT_PushMessage::~JT_PushMessage() bool JT_PushMessage::take(const QDomElement &e) { - if(e.tagName() != "message") + if (e.tagName() != "message") return false; QDomElement e1 = e; @@ -899,7 +878,7 @@ bool JT_PushMessage::take(const QDomElement &e) return true; } - QDomElement forward; + QDomElement forward; Message::CarbonDir cd = Message::NoCarbon; Jid fromJid = Jid(e1.attribute(QLatin1String("from"))); @@ -917,13 +896,12 @@ bool JT_PushMessage::take(const QDomElement &e) QDomElement el2 = el1.firstChildElement(QLatin1String("message")); if (!el2.isNull()) { forward = el2; - cd = el.tagName() == QLatin1String("received")? Message::Received : Message::Sent; + cd = el.tagName() == QLatin1String("received") ? Message::Received : Message::Sent; break; } } - } - else if (el.tagName() == QLatin1String("forwarded") - && el.namespaceURI() == QLatin1String("urn:xmpp:forward:0")) { + } else if (el.tagName() == QLatin1String("forwarded") + && el.namespaceURI() == QLatin1String("urn:xmpp:forward:0")) { forward = el.firstChildElement(QLatin1String("message")); // currently only messages are supportted // TODO element support if (!forward.isNull()) { @@ -932,14 +910,14 @@ bool JT_PushMessage::take(const QDomElement &e) } } - Stanza s = client()->stream().createStanza(addCorrectNS(forward.isNull()? e1 : forward)); - if(s.isNull()) { + Stanza s = client()->stream().createStanza(addCorrectNS(forward.isNull() ? e1 : forward)); + if (s.isNull()) { //printf("take: bad stanza??\n"); return false; } Message m; - if(!m.fromStanza(s, client()->manualTimeZoneOffset(), client()->timeZoneOffset())) { + if (!m.fromStanza(s, client()->manualTimeZoneOffset(), client()->timeZoneOffset())) { //printf("bad message\n"); return false; } @@ -956,21 +934,20 @@ bool JT_PushMessage::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_VCard //---------------------------------------------------------------------------- -class JT_VCard::Private -{ +class JT_VCard::Private { public: Private() = default; QDomElement iq; - Jid jid; - VCard vcard; + Jid jid; + VCard vcard; }; -JT_VCard::JT_VCard(Task *parent) -:Task(parent) +JT_VCard::JT_VCard(Task *parent) : + Task(parent) { type = -1; - d = new Private; + d = new Private; } JT_VCard::~JT_VCard() @@ -980,40 +957,40 @@ JT_VCard::~JT_VCard() void JT_VCard::get(const Jid &_jid) { - type = 0; - d->jid = _jid; - d->iq = createIQ(doc(), "get", type == 1 ? Jid().full() : d->jid.full(), id()); + type = 0; + d->jid = _jid; + d->iq = createIQ(doc(), "get", type == 1 ? Jid().full() : d->jid.full(), id()); QDomElement v = doc()->createElementNS("vcard-temp", "vCard"); d->iq.appendChild(v); } -const Jid & JT_VCard::jid() const +const Jid &JT_VCard::jid() const { return d->jid; } -const VCard & JT_VCard::vcard() const +const VCard &JT_VCard::vcard() const { return d->vcard; } void JT_VCard::set(const VCard &card) { - type = 1; + type = 1; d->vcard = card; - d->jid = ""; - d->iq = createIQ(doc(), "set", d->jid.full(), id()); - d->iq.appendChild(card.toXml(doc()) ); + d->jid = ""; + d->iq = createIQ(doc(), "set", d->jid.full(), id()); + d->iq.appendChild(card.toXml(doc())); } // isTarget is when we setting target's vcard. for example in case of muc own vcard void JT_VCard::set(const Jid &j, const VCard &card, bool isTarget) { - type = 1; + type = 1; d->vcard = card; - d->jid = j; - d->iq = createIQ(doc(), "set", isTarget? j.full() : "", id()); - d->iq.appendChild(card.toXml(doc()) ); + d->jid = j; + d->iq = createIQ(doc(), "set", isTarget ? j.full() : "", id()); + d->iq.appendChild(card.toXml(doc())); } void JT_VCard::onGo() @@ -1026,19 +1003,19 @@ bool JT_VCard::take(const QDomElement &x) Jid to = d->jid; if (to.bare() == client()->jid().bare()) to = client()->host(); - if(!iqVerify(x, to, id())) + if (!iqVerify(x, to, id())) return false; - if(x.attribute("type") == "result") { - if(type == 0) { - for(QDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) { + if (x.attribute("type") == "result") { + if (type == 0) { + for (QDomNode n = x.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement q = n.toElement(); - if(q.isNull()) + if (q.isNull()) continue; - if(q.tagName().toUpper() == "VCARD") { + if (q.tagName().toUpper() == "VCARD") { d->vcard = VCard::fromXml(q); - if(d->vcard) { + if (d->vcard) { setSuccess(); return true; } @@ -1047,13 +1024,11 @@ bool JT_VCard::take(const QDomElement &x) setError(ErrDisc + 1, tr("No VCard available")); return true; - } - else { + } else { setSuccess(); return true; } - } - else { + } else { setError(x); } @@ -1063,22 +1038,21 @@ bool JT_VCard::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_Search //---------------------------------------------------------------------------- -class JT_Search::Private -{ +class JT_Search::Private { public: Private() = default; - Jid jid; - Form form; - bool hasXData = false; - XData xdata; + Jid jid; + Form form; + bool hasXData = false; + XData xdata; QList resultList; }; -JT_Search::JT_Search(Task *parent) -:Task(parent) +JT_Search::JT_Search(Task *parent) : + Task(parent) { - d = new Private; + d = new Private; type = -1; } @@ -1089,31 +1063,31 @@ JT_Search::~JT_Search() void JT_Search::get(const Jid &jid) { - type = 0; - d->jid = jid; - d->hasXData = false; - d->xdata = XData(); - iq = createIQ(doc(), "get", d->jid.full(), id()); + type = 0; + d->jid = jid; + d->hasXData = false; + d->xdata = XData(); + iq = createIQ(doc(), "get", d->jid.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); } void JT_Search::set(const Form &form) { - type = 1; - d->jid = form.jid(); - d->hasXData = false; - d->xdata = XData(); - iq = createIQ(doc(), "set", d->jid.full(), id()); + type = 1; + d->jid = form.jid(); + d->hasXData = false; + d->xdata = XData(); + iq = createIQ(doc(), "set", d->jid.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); // key? - if(!form.key().isEmpty()) + if (!form.key().isEmpty()) query.appendChild(textTag(doc(), "key", form.key())); // fields - for(Form::ConstIterator it = form.begin(); it != form.end(); ++it) { + for (Form::ConstIterator it = form.begin(); it != form.end(); ++it) { const FormField &f = *it; query.appendChild(textTag(doc(), f.realName(), f.value())); } @@ -1121,22 +1095,22 @@ void JT_Search::set(const Form &form) void JT_Search::set(const Jid &jid, const XData &form) { - type = 1; - d->jid = jid; - d->hasXData = false; - d->xdata = XData(); - iq = createIQ(doc(), "set", d->jid.full(), id()); + type = 1; + d->jid = jid; + d->hasXData = false; + d->xdata = XData(); + iq = createIQ(doc(), "set", d->jid.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:search", "query"); iq.appendChild(query); query.appendChild(form.toXml(doc(), true)); } -const Form & JT_Search::form() const +const Form &JT_Search::form() const { return d->form; } -const QList & JT_Search::results() const +const QList &JT_Search::results() const { return d->resultList; } @@ -1146,7 +1120,7 @@ bool JT_Search::hasXData() const return d->hasXData; } -const XData & JT_Search::xdata() const +const XData &JT_Search::xdata() const { return d->xdata; } @@ -1158,76 +1132,72 @@ void JT_Search::onGo() bool JT_Search::take(const QDomElement &x) { - if(!iqVerify(x, d->jid, id())) + if (!iqVerify(x, d->jid, id())) return false; Jid from(x.attribute("from")); - if(x.attribute("type") == "result") { - if(type == 0) { + if (x.attribute("type") == "result") { + if (type == 0) { d->form.clear(); d->form.setJid(from); QDomElement q = queryTag(x); - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "instructions") + if (i.tagName() == "instructions") d->form.setInstructions(tagContent(i)); - else if(i.tagName() == "key") + else if (i.tagName() == "key") d->form.setKey(tagContent(i)); - else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { + else if (i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; - } - else { + } else { FormField f; - if(f.setType(i.tagName())) { + if (f.setType(i.tagName())) { f.setValue(tagContent(i)); d->form += f; } } } - } - else { + } else { d->resultList.clear(); QDomElement q = queryTag(x); - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "item") { + if (i.tagName() == "item") { SearchResult r(Jid(i.attribute("jid"))); QDomElement tag; tag = i.firstChildElement("nick"); - if(!tag.isNull()) + if (!tag.isNull()) r.setNick(tagContent(tag)); tag = i.firstChildElement("first"); - if(!tag.isNull()) + if (!tag.isNull()) r.setFirst(tagContent(tag)); tag = i.firstChildElement("last"); - if(!tag.isNull()) + if (!tag.isNull()) r.setLast(tagContent(tag)); tag = i.firstChildElement("email"); - if(!tag.isNull()) + if (!tag.isNull()) r.setEmail(tagContent(tag)); d->resultList += r; - } - else if(i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { + } else if (i.tagName() == "x" && i.namespaceURI() == "jabber:x:data") { d->xdata.fromXml(i); d->hasXData = true; } } } setSuccess(); - } - else { + } else { setError(x); } @@ -1237,15 +1207,15 @@ bool JT_Search::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_ClientVersion //---------------------------------------------------------------------------- -JT_ClientVersion::JT_ClientVersion(Task *parent) -:Task(parent) +JT_ClientVersion::JT_ClientVersion(Task *parent) : + Task(parent) { } void JT_ClientVersion::get(const Jid &jid) { - j = jid; - iq = createIQ(doc(), "get", j.full(), id()); + j = jid; + iq = createIQ(doc(), "get", j.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:version", "query"); iq.appendChild(query); } @@ -1257,47 +1227,46 @@ void JT_ClientVersion::onGo() bool JT_ClientVersion::take(const QDomElement &x) { - if(!iqVerify(x, j, id())) + if (!iqVerify(x, j, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { QDomElement q = queryTag(x); QDomElement tag; tag = q.firstChildElement("name"); - if(!tag.isNull()) + if (!tag.isNull()) v_name = tagContent(tag); tag = q.firstChildElement("version"); - if(!tag.isNull()) + if (!tag.isNull()) v_ver = tagContent(tag); tag = q.firstChildElement("os"); - if(!tag.isNull()) + if (!tag.isNull()) v_os = tagContent(tag); setSuccess(); - } - else { + } else { setError(x); } return true; } -const Jid & JT_ClientVersion::jid() const +const Jid &JT_ClientVersion::jid() const { return j; } -const QString & JT_ClientVersion::name() const +const QString &JT_ClientVersion::name() const { return v_name; } -const QString & JT_ClientVersion::version() const +const QString &JT_ClientVersion::version() const { return v_ver; } -const QString & JT_ClientVersion::os() const +const QString &JT_ClientVersion::os() const { return v_os; } @@ -1305,14 +1274,15 @@ const QString & JT_ClientVersion::os() const //---------------------------------------------------------------------------- // JT_EntityTime //---------------------------------------------------------------------------- -JT_EntityTime::JT_EntityTime(Task* parent) : Task(parent) +JT_EntityTime::JT_EntityTime(Task *parent) : + Task(parent) { } /** * \brief Queried entity's JID. */ -const Jid & JT_EntityTime::jid() const +const Jid &JT_EntityTime::jid() const { return j; } @@ -1322,8 +1292,8 @@ const Jid & JT_EntityTime::jid() const */ void JT_EntityTime::get(const Jid &jid) { - j = jid; - iq = createIQ(doc(), "get", jid.full(), id()); + j = jid; + iq = createIQ(doc(), "get", jid.full(), id()); QDomElement time = doc()->createElementNS("urn:xmpp:time", "time"); iq.appendChild(time); } @@ -1357,18 +1327,16 @@ bool JT_EntityTime::take(const QDomElement &x) } setSuccess(); return true; - } - while (false); + } while (false); setError(406); - } - else { + } else { setError(x); } return true; } -const QDateTime & JT_EntityTime::dateTime() const +const QDateTime &JT_EntityTime::dateTime() const { return utc; } @@ -1381,8 +1349,8 @@ int JT_EntityTime::timezoneOffset() const //---------------------------------------------------------------------------- // JT_ServInfo //---------------------------------------------------------------------------- -JT_ServInfo::JT_ServInfo(Task *parent) -:Task(parent) +JT_ServInfo::JT_ServInfo(Task *parent) : + Task(parent) { } @@ -1392,12 +1360,12 @@ JT_ServInfo::~JT_ServInfo() bool JT_ServInfo::take(const QDomElement &e) { - if(e.tagName() != "iq" || e.attribute("type") != "get") + if (e.tagName() != "iq" || e.attribute("type") != "get") return false; QString ns = queryNS(e); - if(ns == "jabber:iq:version") { - QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); + if (ns == "jabber:iq:version") { + QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); QDomElement query = doc()->createElementNS("jabber:iq:version", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "name", client()->clientName())); @@ -1405,22 +1373,20 @@ bool JT_ServInfo::take(const QDomElement &e) query.appendChild(textTag(doc(), "os", client()->OSName() + ' ' + client()->OSVersion())); send(iq); return true; - } - else if(ns == "http://jabber.org/protocol/disco#info") { + } else if (ns == "http://jabber.org/protocol/disco#info") { // Find out the node - QString node; + QString node; QDomElement q = e.firstChildElement("query"); - if(!q.isNull()) // NOTE: Should always be true, since a NS was found above + if (!q.isNull()) // NOTE: Should always be true, since a NS was found above node = q.attribute("node"); if (node.isEmpty() || node == client()->caps().flatten()) { - QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); - DiscoItem item = client()->makeDiscoResult(node); + QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); + DiscoItem item = client()->makeDiscoResult(node); iq.appendChild(item.toDiscoInfoResult(doc())); send(iq); - } - else { + } else { // Create error reply QDomElement error_reply = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); @@ -1431,7 +1397,7 @@ bool JT_ServInfo::take(const QDomElement &e) // Add error QDomElement error = doc()->createElement("error"); - error.setAttribute("type","cancel"); + error.setAttribute("type", "cancel"); error_reply.appendChild(error); QDomElement error_type = doc()->createElementNS("urn:ietf:params:xml:ns:xmpp-stanzas", "item-not-found"); error.appendChild(error_type); @@ -1445,14 +1411,14 @@ bool JT_ServInfo::take(const QDomElement &e) ns = e.firstChildElement("time").namespaceURI(); if (ns == "urn:xmpp:time") { - QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); + QDomElement iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); QDomElement time = doc()->createElementNS(ns, "time"); iq.appendChild(time); QDateTime local = QDateTime::currentDateTime(); - int off = TimeZone::offsetFromUtc(); - QTime t = QTime(0, 0).addSecs(qAbs(off)*60); + int off = TimeZone::offsetFromUtc(); + QTime t = QTime(0, 0).addSecs(qAbs(off) * 60); QString tzo = (off < 0 ? "-" : "+") + t.toString("HH:mm"); time.appendChild(textTag(doc(), "tzo", tzo)); QString localTimeStr = local.toUTC().toString(Qt::ISODate); @@ -1470,27 +1436,27 @@ bool JT_ServInfo::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_Gateway //---------------------------------------------------------------------------- -JT_Gateway::JT_Gateway(Task *parent) -:Task(parent) +JT_Gateway::JT_Gateway(Task *parent) : + Task(parent) { type = -1; } void JT_Gateway::get(const Jid &jid) { - type = 0; - v_jid = jid; - iq = createIQ(doc(), "get", v_jid.full(), id()); + type = 0; + v_jid = jid; + iq = createIQ(doc(), "get", v_jid.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:gateway", "query"); iq.appendChild(query); } void JT_Gateway::set(const Jid &jid, const QString &prompt) { - type = 1; - v_jid = jid; - v_prompt = prompt; - iq = createIQ(doc(), "set", v_jid.full(), id()); + type = 1; + v_jid = jid; + v_prompt = prompt; + iq = createIQ(doc(), "set", v_jid.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:gateway", "query"); iq.appendChild(query); query.appendChild(textTag(doc(), "prompt", v_prompt)); @@ -1523,11 +1489,11 @@ Jid JT_Gateway::translatedJid() const bool JT_Gateway::take(const QDomElement &x) { - if(!iqVerify(x, v_jid, id())) + if (!iqVerify(x, v_jid, id())) return false; - if(x.attribute("type") == "result") { - if(type == 0) { + if (x.attribute("type") == "result") { + if (type == 0) { QDomElement query = queryTag(x); QDomElement tag; tag = query.firstChildElement("desc"); @@ -1538,8 +1504,7 @@ bool JT_Gateway::take(const QDomElement &x) if (!tag.isNull()) { v_prompt = tagContent(tag); } - } - else { + } else { QDomElement query = queryTag(x); QDomElement tag; tag = query.firstChildElement("jid"); @@ -1555,8 +1520,7 @@ bool JT_Gateway::take(const QDomElement &x) } setSuccess(); - } - else { + } else { setError(x); } @@ -1566,19 +1530,18 @@ bool JT_Gateway::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_DiscoItems //---------------------------------------------------------------------------- -class JT_DiscoItems::Private -{ +class JT_DiscoItems::Private { public: - Private() { } + Private() {} QDomElement iq; - Jid jid; - DiscoList items; + Jid jid; + DiscoList items; QDomElement subsetsEl; }; -JT_DiscoItems::JT_DiscoItems(Task *parent) -: Task(parent) +JT_DiscoItems::JT_DiscoItems(Task *parent) : + Task(parent) { d = new Private; } @@ -1593,15 +1556,15 @@ void JT_DiscoItems::get(const DiscoItem &item) get(item.jid(), item.node()); } -void JT_DiscoItems::get (const Jid &j, const QString &node) +void JT_DiscoItems::get(const Jid &j, const QString &node) { d->items.clear(); - d->jid = j; - d->iq = createIQ(doc(), "get", d->jid.full(), id()); + d->jid = j; + d->iq = createIQ(doc(), "get", d->jid.full(), id()); QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#items", "query"); - if ( !node.isEmpty() ) + if (!node.isEmpty()) query.setAttribute("node", node); if (!d->subsetsEl.isNull()) { @@ -1619,7 +1582,7 @@ const DiscoList &JT_DiscoItems::items() const void JT_DiscoItems::includeSubsetQuery(const SubsetsClientManager &subsets) { - d->subsetsEl = subsets.makeQueryElement(doc()); + d->subsetsEl = subsets.makeQueryElement(doc()); } bool JT_DiscoItems::extractSubsetInfo(SubsetsClientManager &subsets) @@ -1627,42 +1590,40 @@ bool JT_DiscoItems::extractSubsetInfo(SubsetsClientManager &subsets) return d->subsetsEl.isNull() ? false : subsets.updateFromElement(d->subsetsEl, d->items.count()); } -void JT_DiscoItems::onGo () +void JT_DiscoItems::onGo() { send(d->iq); } bool JT_DiscoItems::take(const QDomElement &x) { - if(!iqVerify(x, d->jid, id())) + if (!iqVerify(x, d->jid, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { QDomElement q = queryTag(x); - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement e = n.toElement(); - if( e.isNull() ) + if (e.isNull()) continue; - if ( e.tagName() == "item" ) { + if (e.tagName() == "item") { DiscoItem item; - item.setJid ( e.attribute("jid") ); - item.setName( e.attribute("name") ); - item.setNode( e.attribute("node") ); - item.setAction( DiscoItem::string2action(e.attribute("action")) ); + item.setJid(e.attribute("jid")); + item.setName(e.attribute("name")); + item.setNode(e.attribute("node")); + item.setAction(DiscoItem::string2action(e.attribute("action"))); - d->items.append( item ); - } - else if (d->subsetsEl.isNull()) { + d->items.append(item); + } else if (d->subsetsEl.isNull()) { d->subsetsEl = SubsetsClientManager::findElement(e, false); } } setSuccess(); - } - else { + } else { setError(x); } @@ -1672,18 +1633,17 @@ bool JT_DiscoItems::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_DiscoPublish //---------------------------------------------------------------------------- -class JT_DiscoPublish::Private -{ +class JT_DiscoPublish::Private { public: - Private() { } + Private() {} QDomElement iq; - Jid jid; - DiscoList list; + Jid jid; + DiscoList list; }; -JT_DiscoPublish::JT_DiscoPublish(Task *parent) -: Task(parent) +JT_DiscoPublish::JT_DiscoPublish(Task *parent) : + Task(parent) { d = new Private; } @@ -1696,9 +1656,9 @@ JT_DiscoPublish::~JT_DiscoPublish() void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) { d->list = list; - d->jid = j; + d->jid = j; - d->iq = createIQ(doc(), "set", d->jid.full(), id()); + d->iq = createIQ(doc(), "set", d->jid.full(), id()); QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#items", "query"); // FIXME: unsure about this @@ -1706,36 +1666,35 @@ void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) // query.setAttribute("node", node); DiscoList::ConstIterator it = list.begin(); - for ( ; it != list.end(); ++it) { + for (; it != list.end(); ++it) { QDomElement w = doc()->createElement("item"); w.setAttribute("jid", (*it).jid().full()); - if ( !(*it).name().isEmpty() ) + if (!(*it).name().isEmpty()) w.setAttribute("name", (*it).name()); - if ( !(*it).node().isEmpty() ) - w.setAttribute("node", (*it).node()); + if (!(*it).node().isEmpty()) + w.setAttribute("node", (*it).node()); w.setAttribute("action", DiscoItem::action2string((*it).action())); - query.appendChild( w ); + query.appendChild(w); } d->iq.appendChild(query); } -void JT_DiscoPublish::onGo () +void JT_DiscoPublish::onGo() { send(d->iq); } bool JT_DiscoPublish::take(const QDomElement &x) { - if(!iqVerify(x, d->jid, id())) + if (!iqVerify(x, d->jid, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { setSuccess(); - } - else { + } else { setError(x); } @@ -1745,10 +1704,9 @@ bool JT_DiscoPublish::take(const QDomElement &x) // --------------------------------------------------------- // JT_BoBServer // --------------------------------------------------------- -JT_BoBServer::JT_BoBServer(Task *parent) - : Task(parent) +JT_BoBServer::JT_BoBServer(Task *parent) : + Task(parent) { - } bool JT_BoBServer::take(const QDomElement &e) @@ -1759,15 +1717,14 @@ bool JT_BoBServer::take(const QDomElement &e) QDomElement data = e.firstChildElement("data"); if (data.namespaceURI() == "urn:xmpp:bob") { QDomElement iq; - BoBData bd = client()->bobManager()->bobData(data.attribute("cid")); + BoBData bd = client()->bobManager()->bobData(data.attribute("cid")); if (bd.isNull()) { iq = createIQ(client()->doc(), "error", e.attribute("from"), e.attribute("id")); Stanza::Error error(Stanza::Error::Cancel, Stanza::Error::ItemNotFound); iq.appendChild(error.toXml(*doc(), client()->stream().baseNS())); - } - else { + } else { iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); iq.appendChild(bd.toXml(doc())); } @@ -1780,19 +1737,18 @@ bool JT_BoBServer::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_BitsOfBinary //---------------------------------------------------------------------------- -class JT_BitsOfBinary::Private -{ +class JT_BitsOfBinary::Private { public: - Private() { } + Private() {} QDomElement iq; - Jid jid; - QString cid; - BoBData data; + Jid jid; + QString cid; + BoBData data; }; -JT_BitsOfBinary::JT_BitsOfBinary(Task *parent) -: Task(parent) +JT_BitsOfBinary::JT_BitsOfBinary(Task *parent) : + Task(parent) { d = new Private; } @@ -1809,7 +1765,7 @@ void JT_BitsOfBinary::get(const Jid &j, const QString &cid) d->data = client()->bobManager()->bobData(cid); if (d->data.isNull()) { - d->iq = createIQ(doc(), "get", d->jid.full(), id()); + d->iq = createIQ(doc(), "get", d->jid.full(), id()); QDomElement data = doc()->createElementNS("urn:xmpp:bob", "data"); data.setAttribute("cid", cid); d->iq.appendChild(data); @@ -1820,8 +1776,7 @@ void JT_BitsOfBinary::onGo() { if (d->data.isNull()) { send(d->iq); - } - else { + } else { setSuccess(); } } @@ -1841,8 +1796,7 @@ bool JT_BitsOfBinary::take(const QDomElement &x) } setSuccess(); - } - else { + } else { setError(x); } @@ -1862,10 +1816,9 @@ BoBData &JT_BitsOfBinary::data() * \brief Answers XMPP Pings */ -JT_PongServer::JT_PongServer(Task *parent) -:Task(parent) +JT_PongServer::JT_PongServer(Task *parent) : + Task(parent) { - } bool JT_PongServer::take(const QDomElement &e) @@ -1885,10 +1838,9 @@ bool JT_PongServer::take(const QDomElement &e) //--------------------------------------------------------------------------- // JT_CaptchaChallenger //--------------------------------------------------------------------------- -class JT_CaptchaChallenger::Private -{ +class JT_CaptchaChallenger::Private { public: - Jid j; + Jid j; CaptchaChallenge challenge; }; @@ -1905,7 +1857,7 @@ JT_CaptchaChallenger::~JT_CaptchaChallenger() void JT_CaptchaChallenger::set(const Jid &j, const CaptchaChallenge &c) { - d->j = j; + d->j = j; d->challenge = c; } @@ -1918,8 +1870,8 @@ void JT_CaptchaChallenger::onGo() m.setBody(d->challenge.explanation()); m.setUrlList(d->challenge.urls()); - XData form = d->challenge.form(); - XData::FieldList fl = form.fields(); + XData form = d->challenge.form(); + XData::FieldList fl = form.fields(); XData::FieldList::Iterator it; for (it = fl.begin(); it < fl.end(); ++it) { if (it->var() == "challenge" && it->type() == XData::Field::Field_Hidden) { @@ -1942,27 +1894,20 @@ void JT_CaptchaChallenger::onGo() bool JT_CaptchaChallenger::take(const QDomElement &x) { - if(x.tagName() == "message" && x.attribute("id") == id() && - Jid(x.attribute("from")) == d->j && !x.firstChildElement("error").isNull()) - { + if (x.tagName() == "message" && x.attribute("id") == id() && Jid(x.attribute("from")) == d->j && !x.firstChildElement("error").isNull()) { setError(x); return true; } XDomNodeList nl; - XData xd; - QString rid = x.attribute("id"); - if (rid.isEmpty() || x.tagName() != "iq" || - Jid(x.attribute("from")) != d->j || x.attribute("type") != "set" || - (nl = childElementsByTagNameNS(x, "urn:xmpp:captcha", "captcha")).isEmpty() || - (nl = childElementsByTagNameNS(nl.item(0).toElement(), "jabber:x:data", "x")).isEmpty() || - (xd.fromXml(nl.item(0).toElement()), xd.getField("challenge").value().value(0) != id())) - { + XData xd; + QString rid = x.attribute("id"); + if (rid.isEmpty() || x.tagName() != "iq" || Jid(x.attribute("from")) != d->j || x.attribute("type") != "set" || (nl = childElementsByTagNameNS(x, "urn:xmpp:captcha", "captcha")).isEmpty() || (nl = childElementsByTagNameNS(nl.item(0).toElement(), "jabber:x:data", "x")).isEmpty() || (xd.fromXml(nl.item(0).toElement()), xd.getField("challenge").value().value(0) != id())) { return false; } CaptchaChallenge::Result r = d->challenge.validateResponse(xd); - QDomElement iq; + QDomElement iq; if (r == CaptchaChallenge::Passed) { iq = createIQ(doc(), "result", d->j.full(), rid); } else { @@ -1988,7 +1933,8 @@ bool JT_CaptchaChallenger::take(const QDomElement &x) //--------------------------------------------------------------------------- JT_CaptchaSender::JT_CaptchaSender(Task *parent) : Task(parent) -{} +{ +} void JT_CaptchaSender::set(const Jid &j, const XData &xd) { @@ -1996,7 +1942,7 @@ void JT_CaptchaSender::set(const Jid &j, const XData &xd) iq = createIQ(doc(), "set", to.full(), id()); iq.appendChild(doc()->createElementNS("urn:xmpp:captcha", "captcha")) - .appendChild(xd.toXml(doc(), true)); + .appendChild(xd.toXml(doc(), true)); } void JT_CaptchaSender::onGo() @@ -2012,8 +1958,7 @@ bool JT_CaptchaSender::take(const QDomElement &x) if (x.attribute("type") == "result") { setSuccess(); - } - else { + } else { setError(x); } @@ -2023,10 +1968,9 @@ bool JT_CaptchaSender::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_MessageCarbons //---------------------------------------------------------------------------- -JT_MessageCarbons::JT_MessageCarbons(Task *parent) - : Task(parent) +JT_MessageCarbons::JT_MessageCarbons(Task *parent) : + Task(parent) { - } void JT_MessageCarbons::enable() diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp index 927e3c01..bba61fe5 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp @@ -43,7 +43,7 @@ XDomNodeList::XDomNodeList(const XDomNodeList &from) : XDomNodeList::XDomNodeList(const QDomNodeList &from) { - for(int n = 0; n < from.count(); ++n) + for (int n = 0; n < from.count(); ++n) list += from.item(n); } @@ -51,7 +51,7 @@ XDomNodeList::~XDomNodeList() { } -XDomNodeList & XDomNodeList::operator=(const XDomNodeList &from) +XDomNodeList &XDomNodeList::operator=(const XDomNodeList &from) { list = from.list; return *this; @@ -85,25 +85,25 @@ void XDomNodeList::append(const QDomNode &i) // YYYYMMDDThh:mm:ss QDateTime stamp2TS(const QString &ts) { - if(ts.length() != 17) + if (ts.length() != 17) return QDateTime(); - int year = ts.mid(0,4).toInt(); - int month = ts.mid(4,2).toInt(); - int day = ts.mid(6,2).toInt(); + int year = ts.mid(0, 4).toInt(); + int month = ts.mid(4, 2).toInt(); + int day = ts.mid(6, 2).toInt(); - int hour = ts.mid(9,2).toInt(); - int min = ts.mid(12,2).toInt(); - int sec = ts.mid(15,2).toInt(); + int hour = ts.mid(9, 2).toInt(); + int min = ts.mid(12, 2).toInt(); + int sec = ts.mid(15, 2).toInt(); QDate xd; xd.setDate(year, month, day); - if(!xd.isValid()) + if (!xd.isValid()) return QDateTime(); QTime xt; xt.setHMS(hour, min, sec); - if(!xt.isValid()) + if (!xt.isValid()) return QDateTime(); return QDateTime(xd, xt); @@ -125,20 +125,20 @@ QString TS2stamp(const QDateTime &d) QString str; str.sprintf("%04d%02d%02dT%02d:%02d:%02d", - d.date().year(), - d.date().month(), - d.date().day(), - d.time().hour(), - d.time().minute(), - d.time().second()); + d.date().year(), + d.date().month(), + d.date().day(), + d.time().hour(), + d.time().minute(), + d.time().second()); return str; } QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content) { - QDomElement tag = doc->createElement(name); - QDomText text = doc->createTextNode(content); + QDomElement tag = doc->createElement(name); + QDomText text = doc->createTextNode(content); tag.appendChild(text); return tag; @@ -146,8 +146,8 @@ QDomElement textTag(QDomDocument *doc, const QString &name, const QString &conte QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content) { - QDomElement tag = doc->createElementNS(ns, name); - QDomText text = doc->createTextNode(content); + QDomElement tag = doc->createElementNS(ns, name); + QDomText text = doc->createTextNode(content); tag.appendChild(text); return tag; @@ -156,9 +156,9 @@ QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, QString tagContent(const QDomElement &e) { // look for some tag content - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomText i = n.toText(); - if(i.isNull()) + if (i.isNull()) continue; return i.data(); } @@ -178,11 +178,11 @@ QString tagContent(const QDomElement &e) XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI, const QString &localName) { XDomNodeList out; - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { - if(!n.isElement()) + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + if (!n.isElement()) continue; QDomElement i = n.toElement(); - if(i.namespaceURI() == nsURI && i.localName() == localName) + if (i.namespaceURI() == nsURI && i.localName() == localName) out.append(i); } return out; @@ -199,11 +199,11 @@ XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI QDomElement createIQ(QDomDocument *doc, const QString &type, const QString &to, const QString &id) { QDomElement iq = doc->createElement("iq"); - if(!type.isEmpty()) + if (!type.isEmpty()) iq.setAttribute("type", type); - if(!to.isEmpty()) + if (!to.isEmpty()) iq.setAttribute("to", to); - if(!id.isEmpty()) + if (!id.isEmpty()) iq.setAttribute("id", id); return iq; @@ -246,15 +246,15 @@ QString queryNS(const QDomElement &e) void getErrorFromElement(const QDomElement &e, const QString &baseNS, int *code, QString *str) { QDomElement tag = e.firstChildElement("error"); - if(tag.isNull()) + if (tag.isNull()) return; XMPP::Stanza::Error err; err.fromXml(tag, baseNS); - if(code) + if (code) *code = err.code(); - if(str) + if (str) *str = err.toString(); } @@ -269,13 +269,13 @@ QDomElement addCorrectNS(const QDomElement &e) frag.appendChild(nl.item(x).cloneNode());*/ // find from this to parent closest node with xmlns/namespaceURI - QDomNode n = e; + QDomNode n = e; static QString xmlns = QStringLiteral("xmlns"); - while(!n.isNull() && !n.toElement().hasAttribute(xmlns) && n.toElement().namespaceURI().isEmpty()) + while (!n.isNull() && !n.toElement().hasAttribute(xmlns) && n.toElement().namespaceURI().isEmpty()) n = n.parentNode(); QString ns; - if(n.isNull() || !n.toElement().hasAttribute(xmlns)) { // if not found or it's namespaceURI - if (n.toElement().namespaceURI().isEmpty()) { // if nothing found, then use default jabber:client namespace + if (n.isNull() || !n.toElement().hasAttribute(xmlns)) { // if not found or it's namespaceURI + if (n.toElement().namespaceURI().isEmpty()) { // if nothing found, then use default jabber:client namespace ns = "jabber:client"; } else { ns = n.toElement().namespaceURI(); @@ -289,17 +289,17 @@ QDomElement addCorrectNS(const QDomElement &e) // copy attributes QDomNamedNodeMap al = e.attributes(); - for(x = 0; x < al.count(); ++x) { + for (x = 0; x < al.count(); ++x) { QDomAttr a = al.item(x).toAttr(); - if(a.name() != xmlns) + if (a.name() != xmlns) i.setAttributeNodeNS(a.cloneNode().toAttr()); } // copy children QDomNodeList nl = e.childNodes(); - for(x = 0; x < nl.count(); ++x) { + for (x = 0; x < nl.count(); ++x) { QDomNode n = nl.item(x); - if(n.isElement()) + if (n.isElement()) i.appendChild(addCorrectNS(n.toElement())); else i.appendChild(n.cloneNode()); @@ -328,24 +328,24 @@ bool hasSubTag(const QDomElement &e, const QString &name) QString subTagText(const QDomElement &e, const QString &name) { QDomElement i = e.firstChildElement(name); - if ( !i.isNull() ) + if (!i.isNull()) return i.text(); return QString(); } QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content) { - QDomElement tag = doc.createElement(name); - QDomText text = doc.createTextNode(content); + QDomElement tag = doc.createElement(name); + QDomText text = doc.createTextNode(content); tag.appendChild(text); return tag; } -QDomElement textTag(QDomDocument &doc, const QString &name, int content) +QDomElement textTag(QDomDocument &doc, const QString &name, qint64 content) { - QDomElement tag = doc.createElement(name); - QDomText text = doc.createTextNode(QString::number(content)); + QDomElement tag = doc.createElement(name); + QDomText text = doc.createTextNode(QString::number(content)); tag.appendChild(text); return tag; @@ -353,8 +353,8 @@ QDomElement textTag(QDomDocument &doc, const QString &name, int content) QDomElement textTag(QDomDocument &doc, const QString &name, bool content) { - QDomElement tag = doc.createElement(name); - QDomText text = doc.createTextNode(content ? "true" : "false"); + QDomElement tag = doc.createElement(name); + QDomText text = doc.createTextNode(content ? "true" : "false"); tag.appendChild(text); return tag; @@ -365,8 +365,8 @@ QDomElement textTag(QDomDocument &doc, const QString &name, QSize &s) QString str; str.sprintf("%d,%d", s.width(), s.height()); - QDomElement tag = doc.createElement(name); - QDomText text = doc.createTextNode(str); + QDomElement tag = doc.createElement(name); + QDomText text = doc.createTextNode(str); tag.appendChild(text); return tag; @@ -377,8 +377,8 @@ QDomElement textTag(QDomDocument &doc, const QString &name, QRect &r) QString str; str.sprintf("%d,%d,%d,%d", r.x(), r.y(), r.width(), r.height()); - QDomElement tag = doc.createElement(name); - QDomText text = doc.createTextNode(str); + QDomElement tag = doc.createElement(name); + QDomText text = doc.createTextNode(str); tag.appendChild(text); return tag; @@ -387,7 +387,7 @@ QDomElement textTag(QDomDocument &doc, const QString &name, QRect &r) QDomElement stringListToXml(QDomDocument &doc, const QString &name, const QStringList &l) { QDomElement tag = doc.createElement(name); - for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) + for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) tag.appendChild(textTag(doc, "item", *it)); return tag; @@ -429,7 +429,7 @@ QDomElement stringListToXml(QDomDocument &doc, const QString &name, const QStrin void readEntry(const QDomElement &e, const QString &name, QString *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; *v = tagContent(tag); } @@ -437,7 +437,7 @@ void readEntry(const QDomElement &e, const QString &name, QString *v) void readNumEntry(const QDomElement &e, const QString &name, int *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; *v = tagContent(tag).toInt(); } @@ -445,18 +445,18 @@ void readNumEntry(const QDomElement &e, const QString &name, int *v) void readBoolEntry(const QDomElement &e, const QString &name, bool *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; - *v = (tagContent(tag) == "true") ? true: false; + *v = (tagContent(tag) == "true") ? true : false; } void readSizeEntry(const QDomElement &e, const QString &name, QSize *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; QStringList list = tagContent(tag).split(','); - if(list.count() != 2) + if (list.count() != 2) return; QSize s; s.setWidth(list[0].toInt()); @@ -467,10 +467,10 @@ void readSizeEntry(const QDomElement &e, const QString &name, QSize *v) void readRectEntry(const QDomElement &e, const QString &name, QRect *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; QStringList list = tagContent(tag).split(','); - if(list.count() != 4) + if (list.count() != 4) return; QRect r; r.setX(list[0].toInt()); @@ -483,25 +483,25 @@ void readRectEntry(const QDomElement &e, const QString &name, QRect *v) void readColorEntry(const QDomElement &e, const QString &name, QColor *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; QColor c; c.setNamedColor(tagContent(tag)); - if(c.isValid()) + if (c.isValid()) *v = c; } void xmlToStringList(const QDomElement &e, const QString &name, QStringList *v) { QDomElement tag = e.firstChildElement(name); - if(tag.isNull()) + if (tag.isNull()) return; QStringList list; - for(QDomNode n = tag.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = tag.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) + if (i.isNull()) continue; - if(i.tagName() == "item") + if (i.tagName() == "item") list += tagContent(i); } *v = list; @@ -514,9 +514,9 @@ void setBoolAttribute(QDomElement e, const QString &name, bool b) void readBoolAttribute(QDomElement e, const QString &name, bool *v) { - if(e.hasAttribute(name)) { + if (e.hasAttribute(name)) { QString s = e.attribute(name); - *v = (s == "true") ? true: false; + *v = (s == "true") ? true : false; } } @@ -534,4 +534,15 @@ void setTagText(QDomElement &e, const QString &text) { e.appendChild(e.ownerDocument().createTextNode(text)); } + +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content) +{ + return ::textTagNS(doc, ns, name, content); +} + +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QByteArray &content) +{ + return ::textTagNS(doc, ns, name, QString::fromLatin1(content.toBase64())); +} + } // namespace XMLHelper diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.h b/src/xmpp/xmpp-im/xmpp_xmlcommon.h index d3ac151d..027ac610 100644 --- a/src/xmpp/xmpp-im/xmpp_xmlcommon.h +++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.h @@ -35,14 +35,14 @@ class XDomNodeList { XDomNodeList(const XDomNodeList &from); XDomNodeList(const QDomNodeList &from); ~XDomNodeList(); - XDomNodeList & operator=(const XDomNodeList &from); + XDomNodeList &operator=(const XDomNodeList &from); QDomNode at(int index) const { return item(index); } - int count() const { return (int)length(); } - bool isEmpty() const; + int count() const { return (int)length(); } + bool isEmpty() const; QDomNode item(int index) const; - uint length() const; - int size() const { return (int)length(); } + uint length() const; + int size() const { return (int)length(); } void append(const QDomNode &i); @@ -57,48 +57,52 @@ class XDomNodeList { QList list; }; -QDateTime stamp2TS(const QString &ts); -bool stamp2TS(const QString &ts, QDateTime *d); -QString TS2stamp(const QDateTime &d); -QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content); -QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content); -QString tagContent(const QDomElement &e); +QDateTime stamp2TS(const QString &ts); +bool stamp2TS(const QString &ts, QDateTime *d); +QString TS2stamp(const QDateTime &d); +QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content); +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content); +QString tagContent(const QDomElement &e); XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI, const QString &localName); -QDomElement createIQ(QDomDocument *doc, const QString &type, const QString &to, const QString &id); -QDomElement queryTag(const QDomElement &e); -QString queryNS(const QDomElement &e); -void getErrorFromElement(const QDomElement &e, const QString &baseNS, int *code, QString *str); -QDomElement addCorrectNS(const QDomElement &e); +QDomElement createIQ(QDomDocument *doc, const QString &type, const QString &to, const QString &id); +QDomElement queryTag(const QDomElement &e); +QString queryNS(const QDomElement &e); +void getErrorFromElement(const QDomElement &e, const QString &baseNS, int *code, QString *str); +QDomElement addCorrectNS(const QDomElement &e); namespace XMLHelper { - //QDomElement findSubTag(const QDomElement &e, const QString &name, bool *found); - bool hasSubTag(const QDomElement &e, const QString &name); - - QDomElement emptyTag(QDomDocument *doc, const QString &name); - QString subTagText(const QDomElement &e, const QString &name); - - QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content); - QDomElement textTag(QDomDocument &doc, const QString &name, int content); - QDomElement textTag(QDomDocument &doc, const QString &name, bool content); - QDomElement textTag(QDomDocument &doc, const QString &name, QSize &s); - QDomElement textTag(QDomDocument &doc, const QString &name, QRect &r); - void setTagText(QDomElement &e, const QString &text); - QDomElement stringListToXml(QDomDocument &doc, const QString &name, const QStringList &l); - - void readEntry(const QDomElement &e, const QString &name, QString *v); - void readNumEntry(const QDomElement &e, const QString &name, int *v); - void readBoolEntry(const QDomElement &e, const QString &name, bool *v); - void readSizeEntry(const QDomElement &e, const QString &name, QSize *v); - void readRectEntry(const QDomElement &e, const QString &name, QRect *v); - void readColorEntry(const QDomElement &e, const QString &name, QColor *v); - - void xmlToStringList(const QDomElement &e, const QString &name, QStringList *v); - - void setBoolAttribute(QDomElement e, const QString &name, bool b); - void readBoolAttribute(QDomElement e, const QString &name, bool *v); - - //QString tagContent(const QDomElement &e); // obsolete; - QString sanitizedLang(const QString &lang); + +//QDomElement findSubTag(const QDomElement &e, const QString &name, bool *found); +bool hasSubTag(const QDomElement &e, const QString &name); + +QDomElement emptyTag(QDomDocument *doc, const QString &name); +QString subTagText(const QDomElement &e, const QString &name); + +QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content); +QDomElement textTag(QDomDocument &doc, const QString &name, qint64 content); +QDomElement textTag(QDomDocument &doc, const QString &name, bool content); +QDomElement textTag(QDomDocument &doc, const QString &name, QSize &s); +QDomElement textTag(QDomDocument &doc, const QString &name, QRect &r); +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QString &content); +QDomElement textTagNS(QDomDocument *doc, const QString &ns, const QString &name, const QByteArray &content); +void setTagText(QDomElement &e, const QString &text); +QDomElement stringListToXml(QDomDocument &doc, const QString &name, const QStringList &l); + +void readEntry(const QDomElement &e, const QString &name, QString *v); +void readNumEntry(const QDomElement &e, const QString &name, int *v); +void readBoolEntry(const QDomElement &e, const QString &name, bool *v); +void readSizeEntry(const QDomElement &e, const QString &name, QSize *v); +void readRectEntry(const QDomElement &e, const QString &name, QRect *v); +void readColorEntry(const QDomElement &e, const QString &name, QColor *v); + +void xmlToStringList(const QDomElement &e, const QString &name, QStringList *v); + +void setBoolAttribute(QDomElement e, const QString &name, bool b); +void readBoolAttribute(QDomElement e, const QString &name, bool *v); + +//QString tagContent(const QDomElement &e); // obsolete; +QString sanitizedLang(const QString &lang); + } // namespace XMLHelper #endif // XMPP_XMLCOMMON_H From cd6c90a052377e3bfbe91b495d4421ba02f5300d Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Fri, 11 Oct 2019 12:02:09 +0300 Subject: [PATCH 102/383] Only set jingle file size when we have it --- src/xmpp/xmpp-im/jingle-ft.cpp | 2008 ++++++++++++++++---------------- 1 file changed, 1004 insertions(+), 1004 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 3d559e86..3c6690d8 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -29,1049 +29,1049 @@ namespace XMPP { namespace Jingle { -namespace FileTransfer { -const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); -const QString AMPLITUDES_NS = QStringLiteral("urn:audio:amplitudes"); - -// tags -static const QString AMPLITUDES_TAG = QStringLiteral("amplitudes"); -static const QString FILETAG = QStringLiteral("file"); -static const QString DATE_TAG = QStringLiteral("date"); -static const QString DESC_TAG = QStringLiteral("desc"); -static const QString MEDIA_TYPE_TAG = QStringLiteral("media-type"); -static const QString NAME_TAG = QStringLiteral("name"); -static const QString SIZE_TAG = QStringLiteral("size"); -static const QString RANGE_TAG = QStringLiteral("range"); -static const QString THUMBNAIL_TAG = QStringLiteral("thumbnail"); - -QDomElement Range::toXml(QDomDocument *doc) const -{ - auto r = doc->createElement(RANGE_TAG); - if (length) { - r.setAttribute(QStringLiteral("length"), QString::number(length)); - } - if (offset) { - r.setAttribute(QStringLiteral("offset"), QString::number(offset)); - } - for (auto const &h : hashes) { - auto hel = h.toXml(doc); - if (!hel.isNull()) { - r.appendChild(hel); - } - } - return r; -} - -//---------------------------------------------------------------------------- -// File -//---------------------------------------------------------------------------- -class File::Private : public QSharedData { -public: - QDateTime date; - QString mediaType; - QString name; - QString desc; - qint64 size = 0; - Range range; - bool rangeSupported = false; - bool hasSize = false; - QList hashes; - Thumbnail thumbnail; - QByteArray amplitudes; -}; - -File::File() -{ -} - -File::~File() -{ -} - -File &File::operator=(const File &other) -{ - d = other.d; - return *this; -} - -File::File(const File &other) : - d(other.d) -{ -} - -File::File(const QDomElement &file) -{ - QDateTime date; - QString mediaType; - QString name; - QString desc; - size_t size = 0; - bool rangeSupported = false; - bool hasSize = false; - Range range; - QList hashes; - Thumbnail thumbnail; - QByteArray amplitudes; - - bool ok; - - for (QDomElement ce = file.firstChildElement(); - !ce.isNull(); ce = ce.nextSiblingElement()) { - - if (ce.tagName() == DATE_TAG) { - date = QDateTime::fromString(ce.text().left(19), Qt::ISODate); - if (!date.isValid()) { - return; + namespace FileTransfer { + const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); + const QString AMPLITUDES_NS = QStringLiteral("urn:audio:amplitudes"); + + // tags + static const QString AMPLITUDES_TAG = QStringLiteral("amplitudes"); + static const QString FILETAG = QStringLiteral("file"); + static const QString DATE_TAG = QStringLiteral("date"); + static const QString DESC_TAG = QStringLiteral("desc"); + static const QString MEDIA_TYPE_TAG = QStringLiteral("media-type"); + static const QString NAME_TAG = QStringLiteral("name"); + static const QString SIZE_TAG = QStringLiteral("size"); + static const QString RANGE_TAG = QStringLiteral("range"); + static const QString THUMBNAIL_TAG = QStringLiteral("thumbnail"); + + QDomElement Range::toXml(QDomDocument *doc) const + { + auto r = doc->createElement(RANGE_TAG); + if (length) { + r.setAttribute(QStringLiteral("length"), QString::number(length)); + } + if (offset) { + r.setAttribute(QStringLiteral("offset"), QString::number(offset)); } + for (auto const &h : hashes) { + auto hel = h.toXml(doc); + if (!hel.isNull()) { + r.appendChild(hel); + } + } + return r; + } - } else if (ce.tagName() == MEDIA_TYPE_TAG) { - mediaType = ce.text(); + //---------------------------------------------------------------------------- + // File + //---------------------------------------------------------------------------- + class File::Private : public QSharedData { + public: + QDateTime date; + QString mediaType; + QString name; + QString desc; + qint64 size = 0; + Range range; + bool rangeSupported = false; + bool hasSize = false; + QList hashes; + Thumbnail thumbnail; + QByteArray amplitudes; + }; + + File::File() + { + } - } else if (ce.tagName() == NAME_TAG) { - name = ce.text(); + File::~File() + { + } - } else if (ce.tagName() == SIZE_TAG) { - size = ce.text().toULongLong(&ok); - if (!ok) { - return; - } - hasSize = true; + File &File::operator=(const File &other) + { + d = other.d; + return *this; + } - } else if (ce.tagName() == RANGE_TAG) { - if (ce.hasAttribute(QLatin1String("offset"))) { - range.offset = ce.attribute(QLatin1String("offset")).toULongLong(&ok); - if (!ok) { - return; + File::File(const File &other) : + d(other.d) + { + } + + File::File(const QDomElement &file) + { + QDateTime date; + QString mediaType; + QString name; + QString desc; + size_t size = 0; + bool rangeSupported = false; + bool hasSize = false; + Range range; + QList hashes; + Thumbnail thumbnail; + QByteArray amplitudes; + + bool ok; + + for (QDomElement ce = file.firstChildElement(); + !ce.isNull(); ce = ce.nextSiblingElement()) { + + if (ce.tagName() == DATE_TAG) { + date = QDateTime::fromString(ce.text().left(19), Qt::ISODate); + if (!date.isValid()) { + return; + } + + } else if (ce.tagName() == MEDIA_TYPE_TAG) { + mediaType = ce.text(); + + } else if (ce.tagName() == NAME_TAG) { + name = ce.text(); + + } else if (ce.tagName() == SIZE_TAG) { + size = ce.text().toULongLong(&ok); + if (!ok) { + return; + } + hasSize = true; + + } else if (ce.tagName() == RANGE_TAG) { + if (ce.hasAttribute(QLatin1String("offset"))) { + range.offset = ce.attribute(QLatin1String("offset")).toULongLong(&ok); + if (!ok) { + return; + } + } + if (ce.hasAttribute(QLatin1String("length"))) { + range.length = ce.attribute(QLatin1String("length")).toULongLong(&ok); + if (!ok || !range.length) { // length should absent if we need to read till end of file. 0-length is nonsense + return; + } + } + QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); + for (; !hashEl.isNull(); hashEl = hashEl.nextSiblingElement(QLatin1String("hash"))) { + if (hashEl.namespaceURI() == HASH_NS) { + auto hash = Hash(hashEl); + if (hash.type() == Hash::Type::Unknown) { + continue; + } + range.hashes.append(hash); + } + } + rangeSupported = true; + + } else if (ce.tagName() == DESC_TAG) { + desc = ce.text(); + + } else if (ce.tagName() == QLatin1String("hash")) { + if (ce.namespaceURI() == HASH_NS) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { + return; + } + hashes.append(h); + } + + } else if (ce.tagName() == QLatin1String("hash-used")) { + if (ce.namespaceURI() == HASH_NS) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { + return; + } + hashes.append(h); + } + + } else if (ce.tagName() == THUMBNAIL_TAG) { + thumbnail = Thumbnail(ce); + } else if (ce.tagName() == AMPLITUDES_TAG && ce.namespaceURI() == AMPLITUDES_NS) { + amplitudes = QByteArray::fromBase64(ce.text().toLatin1()); } } - if (ce.hasAttribute(QLatin1String("length"))) { - range.length = ce.attribute(QLatin1String("length")).toULongLong(&ok); - if (!ok || !range.length) { // length should absent if we need to read till end of file. 0-length is nonsense - return; + + auto p = new Private; + p->date = date; + p->mediaType = mediaType; + p->name = name; + p->desc = desc; + p->size = size; + p->rangeSupported = rangeSupported; + p->hasSize = hasSize; + p->range = range; + p->hashes = hashes; + p->thumbnail = thumbnail; + p->amplitudes = amplitudes; + + d = p; + } + + QDomElement File::toXml(QDomDocument *doc) const + { + if (!isValid() || d->hashes.isEmpty()) { + return QDomElement(); + } + QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); + if (d->date.isValid()) { + el.appendChild(XMLHelper::textTag(*doc, DATE_TAG, d->date.toString(Qt::ISODate))); + } + if (d->desc.size()) { + el.appendChild(XMLHelper::textTag(*doc, DESC_TAG, d->desc)); + } + for (const auto &h : d->hashes) { + el.appendChild(h.toXml(doc)); + } + if (d->mediaType.size()) { + el.appendChild(XMLHelper::textTag(*doc, MEDIA_TYPE_TAG, d->mediaType)); + } + if (d->name.size()) { + el.appendChild(XMLHelper::textTag(*doc, NAME_TAG, d->name)); + } + if (d->hasSize) { + el.appendChild(XMLHelper::textTag(*doc, SIZE_TAG, d->size)); + } + if (d->rangeSupported || d->range.isValid()) { + el.appendChild(d->range.toXml(doc)); + } + if (d->thumbnail.isValid()) { + el.appendChild(d->thumbnail.toXml(doc)); + } + if (d->amplitudes.size()) { + el.appendChild(XMLHelper::textTagNS(doc, AMPLITUDES_NS, AMPLITUDES_TAG, d->amplitudes)); + } + return el; + } + + bool File::merge(const File &other) + { + if (!d->thumbnail.isValid()) { + d->thumbnail = other.thumbnail(); + } + for (auto const &h : other.d->hashes) { + auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v) { return h.type() == v.type(); }); + if (it == d->hashes.constEnd()) { + d->hashes.append(h); + } else if (h.data() != it->data()) { + return false; // hashes are different } } - QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); - for (; !hashEl.isNull(); hashEl = hashEl.nextSiblingElement(QLatin1String("hash"))) { - if (hashEl.namespaceURI() == HASH_NS) { - auto hash = Hash(hashEl); - if (hash.type() == Hash::Type::Unknown) { - continue; + return true; + } + + bool File::hasComputedHashes() const + { + if (!d) + return false; + for (auto const &h : d->hashes) { + if (h.data().size()) + return true; + } + return false; + } + + bool File::hasSize() const + { + return d->hasSize; + } + + QDateTime File::date() const + { + return d ? d->date : QDateTime(); + } + + QString File::description() const + { + return d ? d->desc : QString(); + } + + QList File::hashes() const + { + return d ? d->hashes : QList(); + } + + Hash File::hash(Hash::Type t) const + { + if (d && d->hashes.count()) { + if (t == Hash::Unknown) + return d->hashes.at(0); + for (auto const &h : d->hashes) { + if (h.type() == t) { + return h; } - range.hashes.append(hash); } } - rangeSupported = true; + return Hash(); + } + + QString File::mediaType() const + { + return d ? d->mediaType : QString(); + } - } else if (ce.tagName() == DESC_TAG) { - desc = ce.text(); + QString File::name() const + { + return d ? d->name : QString(); + } - } else if (ce.tagName() == QLatin1String("hash")) { - if (ce.namespaceURI() == HASH_NS) { - Hash h(ce); - if (h.type() == Hash::Type::Unknown) { - return; + quint64 File::size() const + { + return d ? d->size : 0; + } + + Range File::range() const + { + return d ? d->range : Range(); + } + + Thumbnail File::thumbnail() const + { + return d ? d->thumbnail : Thumbnail(); + } + + QByteArray File::amplitudes() const + { + return d ? d->amplitudes : QByteArray(); + } + + void File::setDate(const QDateTime &date) + { + ensureD()->date = date; + } + + void File::setDescription(const QString &desc) + { + ensureD()->desc = desc; + } + + void File::addHash(const Hash &hash) + { + ensureD()->hashes.append(hash); + } + + void File::setMediaType(const QString &mediaType) + { + ensureD()->mediaType = mediaType; + } + + void File::setName(const QString &name) + { + ensureD()->name = name; + } + + void File::setSize(quint64 size) + { + ensureD()->size = size; + d->hasSize = true; + } + + void File::setRange(const Range &range) + { + ensureD()->range = range; + d->rangeSupported = true; + } + + void File::setThumbnail(const Thumbnail &thumb) + { + ensureD()->thumbnail = thumb; + } + + void File::setAmplitudes(const QByteArray &litudes) + { + d->amplitudes = amplitudes; + } + + File::Private *File::ensureD() + { + if (!d) { + d = new Private; + } + return d.data(); + } + + //---------------------------------------------------------------------------- + // Checksum + //---------------------------------------------------------------------------- + Checksum::Checksum(const QDomElement &cs) : + ContentBase(cs) + { + file = File(cs.firstChildElement(QLatin1String("file"))); + } + + bool Checksum::isValid() const + { + return ContentBase::isValid() && file.isValid(); + } + + QDomElement Checksum::toXml(QDomDocument *doc) const + { + auto el = ContentBase::toXml(doc, "checksum"); + if (!el.isNull()) { + el.appendChild(file.toXml(doc)); + } + return el; + } + + //---------------------------------------------------------------------------- + // Received + //---------------------------------------------------------------------------- + QDomElement Received::toXml(QDomDocument *doc) const + { + return ContentBase::toXml(doc, "received"); + } + + //---------------------------------------------------------------------------- + // ApplicationManager + //---------------------------------------------------------------------------- + Manager::Manager(QObject *parent) : + XMPP::Jingle::ApplicationManager(parent) + { + } + + Manager::~Manager() + { + if (jingleManager) + jingleManager->unregisterApp(NS); + } + + void Manager::setJingleManager(XMPP::Jingle::Manager *jm) + { + jingleManager = jm; + } + + Application *Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) + { + if (!(contentName.size() > 0 && (senders == Origin::Initiator || senders == Origin::Responder))) { + qDebug("Invalid Jignle FT App start parameters"); + return nullptr; + } + return new Application(pad.staticCast(), contentName, creator, senders); // ContentOrigin::Remote + } + + ApplicationManagerPad *Manager::pad(Session *session) + { + return new Pad(this, session); + } + + void Manager::closeAll() + { + } + + Client *Manager::client() + { + if (jingleManager) { + return jingleManager->client(); + } + return nullptr; + } + + QStringList Manager::availableTransports() const + { + return jingleManager->availableTransports(Transport::Reliable); + } + + //---------------------------------------------------------------------------- + // Application + //---------------------------------------------------------------------------- + class Application::Private { + public: + Application * q = nullptr; + State state = State::Created; + State transportReplaceState = State::Finished; + Action updateToSend = Action::NoAction; + QSharedPointer pad; + QString contentName; + File file; + File acceptFile; // as it comes with "accept" response + Origin creator; + Origin senders; + Origin transportReplaceOrigin = Origin::None; + XMPP::Stanza::Error lastError; + Reason terminationReason; + QSharedPointer transport; + Connection::Ptr connection; + QStringList availableTransports; + bool closeDeviceOnFinish = true; + bool streamigMode = false; + QIODevice * device = nullptr; + quint64 bytesLeft = 0; + + void setState(State s) + { + state = s; + if (s == State::Finished) { + if (device && closeDeviceOnFinish) { + device->close(); + } + if (connection) { + connection->close(); + } } - hashes.append(h); + emit q->stateChanged(s); } - } else if (ce.tagName() == QLatin1String("hash-used")) { - if (ce.namespaceURI() == HASH_NS) { - Hash h(ce); - if (h.type() == Hash::Type::Unknown) { + void handleStreamFail() + { + terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("stream failed")); + setState(State::Finished); + } + + void writeNextBlockToTransport() + { + if (!bytesLeft) { + terminationReason = Reason(Reason::Condition::Success); + setState(State::Finished); + return; // everything is written + } + auto sz = connection->blockSize(); + sz = sz ? sz : 8192; + if (sz > bytesLeft) { + sz = bytesLeft; + } + QByteArray data = device->read(sz); + if (data.isEmpty()) { + handleStreamFail(); return; } - hashes.append(h); + if (connection->write(data) == -1) { + handleStreamFail(); + return; + } + emit q->progress(device->pos()); + bytesLeft -= sz; } - } else if (ce.tagName() == THUMBNAIL_TAG) { - thumbnail = Thumbnail(ce); - } else if (ce.tagName() == AMPLITUDES_TAG && ce.namespaceURI() == AMPLITUDES_NS) { - amplitudes = QByteArray::fromBase64(ce.text().toLatin1()); - } - } - - auto p = new Private; - p->date = date; - p->mediaType = mediaType; - p->name = name; - p->desc = desc; - p->size = size; - p->rangeSupported = rangeSupported; - p->hasSize = hasSize; - p->range = range; - p->hashes = hashes; - p->thumbnail = thumbnail; - p->amplitudes = amplitudes; - - d = p; -} - -QDomElement File::toXml(QDomDocument *doc) const -{ - if (!isValid() || d->hashes.isEmpty()) { - return QDomElement(); - } - QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); - if (d->date.isValid()) { - el.appendChild(XMLHelper::textTag(*doc, DATE_TAG, d->date.toString(Qt::ISODate))); - } - if (d->desc.size()) { - el.appendChild(XMLHelper::textTag(*doc, DESC_TAG, d->desc)); - } - for (const auto &h : d->hashes) { - el.appendChild(h.toXml(doc)); - } - if (d->mediaType.size()) { - el.appendChild(XMLHelper::textTag(*doc, MEDIA_TYPE_TAG, d->mediaType)); - } - if (d->name.size()) { - el.appendChild(XMLHelper::textTag(*doc, NAME_TAG, d->name)); - } - if (d->size) { - el.appendChild(XMLHelper::textTag(*doc, SIZE_TAG, d->size)); - } - if (d->rangeSupported || d->range.isValid()) { - el.appendChild(d->range.toXml(doc)); - } - if (d->thumbnail.isValid()) { - el.appendChild(d->thumbnail.toXml(doc)); - } - if (d->amplitudes.size()) { - el.appendChild(XMLHelper::textTagNS(doc, AMPLITUDES_NS, AMPLITUDES_TAG, d->amplitudes)); - } - return el; -} - -bool File::merge(const File &other) -{ - if (!d->thumbnail.isValid()) { - d->thumbnail = other.thumbnail(); - } - for (auto const &h : other.d->hashes) { - auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v) { return h.type() == v.type(); }); - if (it == d->hashes.constEnd()) { - d->hashes.append(h); - } else if (h.data() != it->data()) { - return false; // hashes are different - } - } - return true; -} - -bool File::hasComputedHashes() const -{ - if (!d) - return false; - for (auto const &h : d->hashes) { - if (h.data().size()) - return true; - } - return false; -} - -bool File::hasSize() const -{ - return d->hasSize; -} - -QDateTime File::date() const -{ - return d ? d->date : QDateTime(); -} - -QString File::description() const -{ - return d ? d->desc : QString(); -} - -QList File::hashes() const -{ - return d ? d->hashes : QList(); -} - -Hash File::hash(Hash::Type t) const -{ - if (d && d->hashes.count()) { - if (t == Hash::Unknown) - return d->hashes.at(0); - for (auto const &h : d->hashes) { - if (h.type() == t) { - return h; + void readNextBlockFromTransport() + { + quint64 bytesAvail; + while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { + quint64 sz = 65536; // shall we respect transport->blockSize() ? + if (sz > bytesLeft) { + sz = bytesLeft; + } + if (sz > bytesAvail) { + sz = bytesAvail; + } + QByteArray data = connection->read(sz); + if (data.isEmpty()) { + handleStreamFail(); + return; + } + if (device->write(data) == -1) { + handleStreamFail(); + return; + } + emit q->progress(device->pos()); + bytesLeft -= sz; + } + if (!bytesLeft) { + // TODO send + terminationReason = Reason(Reason::Condition::Success); + setState(State::Finished); + } } + }; + + Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : + d(new Private) + { + d->q = this; + d->pad = pad; + d->contentName = contentName; + d->creator = creator; + d->senders = senders; + d->availableTransports = static_cast(pad->manager())->availableTransports(); + } + + Application::~Application() + { + } + + ApplicationManagerPad::Ptr Application::pad() const + { + return d->pad.staticCast(); + } + + State Application::state() const + { + return d->state; + } + + void Application::setState(State state) + { + d->setState(state); + } + + Stanza::Error Application::lastError() const + { + return d->lastError; + } + + Reason Application::terminationReason() const + { + return d->terminationReason; + } + + QString Application::contentName() const + { + return d->contentName; + } + + Origin Application::creator() const + { + return d->creator; } - } - return Hash(); -} - -QString File::mediaType() const -{ - return d ? d->mediaType : QString(); -} - -QString File::name() const -{ - return d ? d->name : QString(); -} - -quint64 File::size() const -{ - return d ? d->size : 0; -} - -Range File::range() const -{ - return d ? d->range : Range(); -} - -Thumbnail File::thumbnail() const -{ - return d ? d->thumbnail : Thumbnail(); -} - -QByteArray File::amplitudes() const -{ - return d ? d->amplitudes : QByteArray(); -} - -void File::setDate(const QDateTime &date) -{ - ensureD()->date = date; -} - -void File::setDescription(const QString &desc) -{ - ensureD()->desc = desc; -} - -void File::addHash(const Hash &hash) -{ - ensureD()->hashes.append(hash); -} - -void File::setMediaType(const QString &mediaType) -{ - ensureD()->mediaType = mediaType; -} - -void File::setName(const QString &name) -{ - ensureD()->name = name; -} - -void File::setSize(quint64 size) -{ - ensureD()->size = size; - d->hasSize = true; -} - -void File::setRange(const Range &range) -{ - ensureD()->range = range; - d->rangeSupported = true; -} - -void File::setThumbnail(const Thumbnail &thumb) -{ - ensureD()->thumbnail = thumb; -} - -void File::setAmplitudes(const QByteArray &litudes) -{ - d->amplitudes = amplitudes; -} - -File::Private *File::ensureD() -{ - if (!d) { - d = new Private; - } - return d.data(); -} - -//---------------------------------------------------------------------------- -// Checksum -//---------------------------------------------------------------------------- -Checksum::Checksum(const QDomElement &cs) : - ContentBase(cs) -{ - file = File(cs.firstChildElement(QLatin1String("file"))); -} - -bool Checksum::isValid() const -{ - return ContentBase::isValid() && file.isValid(); -} - -QDomElement Checksum::toXml(QDomDocument *doc) const -{ - auto el = ContentBase::toXml(doc, "checksum"); - if (!el.isNull()) { - el.appendChild(file.toXml(doc)); - } - return el; -} - -//---------------------------------------------------------------------------- -// Received -//---------------------------------------------------------------------------- -QDomElement Received::toXml(QDomDocument *doc) const -{ - return ContentBase::toXml(doc, "received"); -} - -//---------------------------------------------------------------------------- -// ApplicationManager -//---------------------------------------------------------------------------- -Manager::Manager(QObject *parent) : - XMPP::Jingle::ApplicationManager(parent) -{ -} - -Manager::~Manager() -{ - if (jingleManager) - jingleManager->unregisterApp(NS); -} - -void Manager::setJingleManager(XMPP::Jingle::Manager *jm) -{ - jingleManager = jm; -} - -Application *Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) -{ - if (!(contentName.size() > 0 && (senders == Origin::Initiator || senders == Origin::Responder))) { - qDebug("Invalid Jignle FT App start parameters"); - return nullptr; - } - return new Application(pad.staticCast(), contentName, creator, senders); // ContentOrigin::Remote -} - -ApplicationManagerPad *Manager::pad(Session *session) -{ - return new Pad(this, session); -} - -void Manager::closeAll() -{ -} - -Client *Manager::client() -{ - if (jingleManager) { - return jingleManager->client(); - } - return nullptr; -} - -QStringList Manager::availableTransports() const -{ - return jingleManager->availableTransports(Transport::Reliable); -} - -//---------------------------------------------------------------------------- -// Application -//---------------------------------------------------------------------------- -class Application::Private { -public: - Application * q = nullptr; - State state = State::Created; - State transportReplaceState = State::Finished; - Action updateToSend = Action::NoAction; - QSharedPointer pad; - QString contentName; - File file; - File acceptFile; // as it comes with "accept" response - Origin creator; - Origin senders; - Origin transportReplaceOrigin = Origin::None; - XMPP::Stanza::Error lastError; - Reason terminationReason; - QSharedPointer transport; - Connection::Ptr connection; - QStringList availableTransports; - bool closeDeviceOnFinish = true; - bool streamigMode = false; - QIODevice * device = nullptr; - quint64 bytesLeft = 0; - - void setState(State s) - { - state = s; - if (s == State::Finished) { - if (device && closeDeviceOnFinish) { - device->close(); + + Origin Application::senders() const + { + return d->senders; + } + + Application::SetDescError Application::setDescription(const QDomElement &description) + { + d->file = File(description.firstChildElement("file")); + //d->state = State::Pending; // basically it's incomming content. so if we parsed it it's pending. if not parsed if will rejected anyway. + return d->file.isValid() ? Ok : Unparsed; + } + + void Application::setFile(const File &file) + { + d->file = file; + } + + File Application::file() const + { + return d->file; + } + + File Application::acceptFile() const + { + return d->acceptFile; + } + + // incoming one? or we have to check real direction + bool Application::setTransport(const QSharedPointer &transport) + { + if (!(transport->features() & Transport::Reliable)) + return false; + + int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); + if (nsIndex == -1) { + return false; } - if (connection) { - connection->close(); + + // in case we automatically select a new transport on our own we definitely will come up to this point + if (d->transport) { + d->transport->disconnect(this); + d->transport.reset(); } + + d->availableTransports.removeAt(nsIndex); + d->transport = transport; + connect(transport.data(), &Transport::updated, this, &Application::updated); + connect(transport.data(), &Transport::connected, this, [this]() { + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; // not needed here probably + d->connection = d->transport->connection(); + if (d->streamigMode) { + connect(d->connection.data(), &Connection::readyRead, this, [this]() { + if (!d->device) { + return; + } + if (d->pad->session()->role() != d->senders) { + d->readNextBlockFromTransport(); + } + }); + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes) { + Q_UNUSED(bytes) + if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { + d->writeNextBlockToTransport(); + } + }); + } + d->setState(State::Active); + if (d->streamigMode) { + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); + } else { + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); + } + } else { + emit connectionReady(); + } + }); + + connect(transport.data(), &Transport::failed, this, [this]() { + d->transportReplaceOrigin = d->pad->session()->role(); + if (d->state >= State::Active) { + emit updated(); // late failure are unhandled. just notify the remote + return; + } + // we can try to replace the transport + if (!selectNextTransport()) { // we can do transport-replace here + if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { + // we were unable to send even initial offer + d->setState(State::Finished); + } else { + emit updated(); // we have to notify our peer about failure + } + } else { + d->transportReplaceState = State::PrepareLocalOffer; + } + }); + + if (d->state >= State::Unacked) { + // seems like we are in transport failure recovery. d->transportFailed may confirm this + d->transport->prepare(); + } + return true; + } + + Origin Application::transportReplaceOrigin() const + { + return d->transportReplaceOrigin; } - emit q->stateChanged(s); - } - - void handleStreamFail() - { - terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("stream failed")); - setState(State::Finished); - } - - void writeNextBlockToTransport() - { - if (!bytesLeft) { - terminationReason = Reason(Reason::Condition::Success); - setState(State::Finished); - return; // everything is written - } - auto sz = connection->blockSize(); - sz = sz ? sz : 8192; - if (sz > bytesLeft) { - sz = bytesLeft; - } - QByteArray data = device->read(sz); - if (data.isEmpty()) { - handleStreamFail(); - return; - } - if (connection->write(data) == -1) { - handleStreamFail(); - return; - } - emit q->progress(device->pos()); - bytesLeft -= sz; - } - - void readNextBlockFromTransport() - { - quint64 bytesAvail; - while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { - quint64 sz = 65536; // shall we respect transport->blockSize() ? - if (sz > bytesLeft) { - sz = bytesLeft; + + bool Application::incomingTransportReplace(const QSharedPointer &transport) + { + auto prev = d->transportReplaceOrigin; + if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { + // if I'm a responder and tried to send transport-replace too, then push ns back + d->availableTransports.append(d->transport->pad()->ns()); } - if (sz > bytesAvail) { - sz = bytesAvail; + d->transportReplaceOrigin = d->pad->session()->peerRole(); + auto ret = setTransport(transport); + if (ret) + d->transportReplaceState = State::PrepareLocalOffer; + else { + d->transportReplaceOrigin = prev; + d->lastError.reset(); + // REVIEW We have to fail application here on tie-break or propose another transport } - QByteArray data = connection->read(sz); - if (data.isEmpty()) { - handleStreamFail(); - return; + + return ret; + } + + QSharedPointer Application::transport() const + { + return d->transport; + } + + void Application::setStreamingMode(bool mode) + { + if (d->state <= State::Connecting) { + d->streamigMode = mode; } - if (device->write(data) == -1) { - handleStreamFail(); - return; + } + + Action Application::evaluateOutgoingUpdate() + { + d->updateToSend = Action::NoAction; + if (!isValid() || d->state == State::Created || d->state == State::Finished) { + return d->updateToSend; } - emit q->progress(device->pos()); - bytesLeft -= sz; - } - if (!bytesLeft) { - // TODO send - terminationReason = Reason(Reason::Condition::Success); - setState(State::Finished); - } - } -}; - -Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : - d(new Private) -{ - d->q = this; - d->pad = pad; - d->contentName = contentName; - d->creator = creator; - d->senders = senders; - d->availableTransports = static_cast(pad->manager())->availableTransports(); -} - -Application::~Application() -{ -} - -ApplicationManagerPad::Ptr Application::pad() const -{ - return d->pad.staticCast(); -} - -State Application::state() const -{ - return d->state; -} - -void Application::setState(State state) -{ - d->setState(state); -} - -Stanza::Error Application::lastError() const -{ - return d->lastError; -} - -Reason Application::terminationReason() const -{ - return d->terminationReason; -} - -QString Application::contentName() const -{ - return d->contentName; -} - -Origin Application::creator() const -{ - return d->creator; -} - -Origin Application::senders() const -{ - return d->senders; -} - -Application::SetDescError Application::setDescription(const QDomElement &description) -{ - d->file = File(description.firstChildElement("file")); - //d->state = State::Pending; // basically it's incomming content. so if we parsed it it's pending. if not parsed if will rejected anyway. - return d->file.isValid() ? Ok : Unparsed; -} - -void Application::setFile(const File &file) -{ - d->file = file; -} - -File Application::file() const -{ - return d->file; -} - -File Application::acceptFile() const -{ - return d->acceptFile; -} - -// incoming one? or we have to check real direction -bool Application::setTransport(const QSharedPointer &transport) -{ - if (!(transport->features() & Transport::Reliable)) - return false; - - int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); - if (nsIndex == -1) { - return false; - } - - // in case we automatically select a new transport on our own we definitely will come up to this point - if (d->transport) { - d->transport->disconnect(this); - d->transport.reset(); - } - - d->availableTransports.removeAt(nsIndex); - d->transport = transport; - connect(transport.data(), &Transport::updated, this, &Application::updated); - connect(transport.data(), &Transport::connected, this, [this]() { - d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; // not needed here probably - d->connection = d->transport->connection(); - if (d->streamigMode) { - connect(d->connection.data(), &Connection::readyRead, this, [this]() { - if (!d->device) { - return; + + auto evaluateTransportReplaceAction = [this]() { + if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) + return Action::NoAction; + + return d->transportReplaceOrigin == d->pad->session()->role() ? Action::TransportReplace : Action::TransportAccept; + }; + + switch (d->state) { + case State::Created: + break; + case State::PrepareLocalOffer: + if (d->transportReplaceOrigin != Origin::None) { + if (!d->transport) { + d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt in case of app.PrepareLocalOffer. see Transport::failed above + } + d->updateToSend = evaluateTransportReplaceAction(); + if (d->updateToSend == Action::TransportAccept) { + d->updateToSend = Action::ContentAccept; + } + return d->updateToSend; } - if (d->pad->session()->role() != d->senders) { - d->readNextBlockFromTransport(); + + if (d->transport->isInitialOfferReady()) + d->updateToSend = d->creator == d->pad->session()->role() ? Action::ContentAdd : Action::ContentAccept; + + break; + case State::Connecting: + case State::Pending: + case State::Active: + if (d->transportReplaceOrigin != Origin::None) { + if (d->state == State::Active || !d->transport) + d->updateToSend = Action::ContentRemove; + else + d->updateToSend = evaluateTransportReplaceAction(); + return d->updateToSend; } - }); - connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes) { - Q_UNUSED(bytes) - if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { - d->writeNextBlockToTransport(); + + if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { + d->updateToSend = Action::ContentRemove; + } else if (d->transport->hasUpdates()) + d->updateToSend = Action::TransportInfo; + + break; + case State::Finishing: + if (d->transportReplaceOrigin != Origin::None || d->terminationReason.isValid()) { + d->updateToSend = Action::ContentRemove; + } else { + d->updateToSend = Action::SessionInfo; // to send checksum } - }); + break; + default: + break; + } + return d->updateToSend; // TODO } - d->setState(State::Active); - if (d->streamigMode) { - if (d->acceptFile.range().isValid()) { - d->bytesLeft = d->acceptFile.range().length; - emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); - } else { - d->bytesLeft = d->file.size(); - emit deviceRequested(0, d->bytesLeft); + + OutgoingUpdate Application::takeOutgoingUpdate() + { + if (d->updateToSend == Action::NoAction) { + return OutgoingUpdate(); } - } else { - emit connectionReady(); - } - }); - - connect(transport.data(), &Transport::failed, this, [this]() { - d->transportReplaceOrigin = d->pad->session()->role(); - if (d->state >= State::Active) { - emit updated(); // late failure are unhandled. just notify the remote - return; - } - // we can try to replace the transport - if (!selectNextTransport()) { // we can do transport-replace here - if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { - // we were unable to send even initial offer - d->setState(State::Finished); - } else { - emit updated(); // we have to notify our peer about failure + + auto client = d->pad->session()->manager()->client(); + auto doc = client->doc(); + + if (d->updateToSend == Action::SessionInfo) { + if (d->state != State::Finishing) { + // TODO implement + return OutgoingUpdate(); + } + ContentBase cb(d->pad->session()->role(), d->contentName); + return OutgoingUpdate { QList() << cb.toXml(doc, "received"), [this]() { + d->setState(State::Finished); + } }; } - } else { - d->transportReplaceState = State::PrepareLocalOffer; - } - }); - - if (d->state >= State::Unacked) { - // seems like we are in transport failure recovery. d->transportFailed may confirm this - d->transport->prepare(); - } - return true; -} - -Origin Application::transportReplaceOrigin() const -{ - return d->transportReplaceOrigin; -} - -bool Application::incomingTransportReplace(const QSharedPointer &transport) -{ - auto prev = d->transportReplaceOrigin; - if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { - // if I'm a responder and tried to send transport-replace too, then push ns back - d->availableTransports.append(d->transport->pad()->ns()); - } - d->transportReplaceOrigin = d->pad->session()->peerRole(); - auto ret = setTransport(transport); - if (ret) - d->transportReplaceState = State::PrepareLocalOffer; - else { - d->transportReplaceOrigin = prev; - d->lastError.reset(); - // REVIEW We have to fail application here on tie-break or propose another transport - } - - return ret; -} - -QSharedPointer Application::transport() const -{ - return d->transport; -} - -void Application::setStreamingMode(bool mode) -{ - if (d->state <= State::Connecting) { - d->streamigMode = mode; - } -} - -Action Application::evaluateOutgoingUpdate() -{ - d->updateToSend = Action::NoAction; - if (!isValid() || d->state == State::Created || d->state == State::Finished) { - return d->updateToSend; - } - - auto evaluateTransportReplaceAction = [this]() { - if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) - return Action::NoAction; - - return d->transportReplaceOrigin == d->pad->session()->role() ? Action::TransportReplace : Action::TransportAccept; - }; - - switch (d->state) { - case State::Created: - break; - case State::PrepareLocalOffer: - if (d->transportReplaceOrigin != Origin::None) { + + QDomElement transportEl; + OutgoingUpdateCB transportCB; + + ContentBase cb(d->creator, d->contentName); + if (d->state == State::PrepareLocalOffer) + cb.senders = d->senders; + QList updates; + auto contentEl = cb.toXml(doc, "content"); + updates << contentEl; + + switch (d->updateToSend) { + case Action::ContentReject: + case Action::ContentRemove: + if (d->transportReplaceOrigin != Origin::None) + d->terminationReason = Reason(Reason::Condition::FailedTransport); + if (d->terminationReason.isValid()) + updates << d->terminationReason.toXml(doc); + return OutgoingUpdate { updates, [this]() { + d->setState(State::Finished); + } }; + case Action::ContentAdd: + case Action::ContentAccept: + Q_ASSERT(d->transport->isInitialOfferReady()); + if (d->file.thumbnail().data.size()) { + auto thumb = d->file.thumbnail(); + auto bm = client->bobManager(); + BoBData data = bm->append(thumb.data, thumb.mimeType); + thumb.uri = QLatin1String("cid:") + data.cid(); + d->file.setThumbnail(thumb); + } + contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); + contentEl.appendChild(transportEl); + + d->setState(State::Unacked); + return OutgoingUpdate { updates, [this, transportCB]() { + if (transportCB) { + transportCB(); + } + d->setState(d->pad->session()->role() == Origin::Initiator ? State::Pending : State::Connecting); + } }; + case Action::TransportInfo: + Q_ASSERT(d->transport->hasUpdates()); + std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + contentEl.appendChild(transportEl); + return OutgoingUpdate { updates, transportCB }; + case Action::TransportReplace: + case Action::TransportAccept: { + Q_ASSERT(d->transport->isInitialOfferReady()); + d->transportReplaceState = State::Unacked; + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); + contentEl.appendChild(transportEl); + auto action = d->updateToSend; + return OutgoingUpdate { updates, [this, transportCB, action]() { + if (transportCB) { + transportCB(); + } + d->transportReplaceState = action == Action::TransportReplace ? State::Pending : State::Finished; + } }; + } + default: + break; + } + + return OutgoingUpdate(); // TODO + } + + bool Application::wantBetterTransport(const QSharedPointer &t) const + { + Q_UNUSED(t) + return true; // TODO check + } + + bool Application::selectNextTransport() + { + while (d->availableTransports.size()) { + auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.last()); + if (t && setTransport(t)) { + return true; + } else { + d->availableTransports.removeLast(); + } + } + return false; + } + + void Application::prepare() + { if (!d->transport) { - d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt in case of app.PrepareLocalOffer. see Transport::failed above + selectNextTransport(); + } + if (d->transport) { + d->setState(State::PrepareLocalOffer); + d->transport->prepare(); + } + } + + void Application::start() + { + if (d->transport) { + d->setState(State::Connecting); + d->transport->start(); } - d->updateToSend = evaluateTransportReplaceAction(); - if (d->updateToSend == Action::TransportAccept) { - d->updateToSend = Action::ContentAccept; + // TODO we need QIODevice somewhere here + } + + bool Application::accept(const QDomElement &el) + { + File f(el.firstChildElement("file")); + if (!f.isValid()) { + return false; } - return d->updateToSend; - } - - if (d->transport->isInitialOfferReady()) - d->updateToSend = d->creator == d->pad->session()->role() ? Action::ContentAdd : Action::ContentAccept; - - break; - case State::Connecting: - case State::Pending: - case State::Active: - if (d->transportReplaceOrigin != Origin::None) { - if (d->state == State::Active || !d->transport) - d->updateToSend = Action::ContentRemove; - else - d->updateToSend = evaluateTransportReplaceAction(); - return d->updateToSend; - } - - if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { - d->updateToSend = Action::ContentRemove; - } else if (d->transport->hasUpdates()) - d->updateToSend = Action::TransportInfo; - - break; - case State::Finishing: - if (d->transportReplaceOrigin != Origin::None || d->terminationReason.isValid()) { - d->updateToSend = Action::ContentRemove; - } else { - d->updateToSend = Action::SessionInfo; // to send checksum - } - break; - default: - break; - } - return d->updateToSend; // TODO -} - -OutgoingUpdate Application::takeOutgoingUpdate() -{ - if (d->updateToSend == Action::NoAction) { - return OutgoingUpdate(); - } - - auto client = d->pad->session()->manager()->client(); - auto doc = client->doc(); - - if (d->updateToSend == Action::SessionInfo) { - if (d->state != State::Finishing) { - // TODO implement - return OutgoingUpdate(); - } - ContentBase cb(d->pad->session()->role(), d->contentName); - return OutgoingUpdate { QList() << cb.toXml(doc, "received"), [this]() { - d->setState(State::Finished); - } }; - } - - QDomElement transportEl; - OutgoingUpdateCB transportCB; - - ContentBase cb(d->creator, d->contentName); - if (d->state == State::PrepareLocalOffer) - cb.senders = d->senders; - QList updates; - auto contentEl = cb.toXml(doc, "content"); - updates << contentEl; - - switch (d->updateToSend) { - case Action::ContentReject: - case Action::ContentRemove: - if (d->transportReplaceOrigin != Origin::None) - d->terminationReason = Reason(Reason::Condition::FailedTransport); - if (d->terminationReason.isValid()) - updates << d->terminationReason.toXml(doc); - return OutgoingUpdate { updates, [this]() { - d->setState(State::Finished); - } }; - case Action::ContentAdd: - case Action::ContentAccept: - Q_ASSERT(d->transport->isInitialOfferReady()); - if (d->file.thumbnail().data.size()) { - auto thumb = d->file.thumbnail(); - auto bm = client->bobManager(); - BoBData data = bm->append(thumb.data, thumb.mimeType); - thumb.uri = QLatin1String("cid:") + data.cid(); - d->file.setThumbnail(thumb); - } - contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); - std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); - contentEl.appendChild(transportEl); - - d->setState(State::Unacked); - return OutgoingUpdate { updates, [this, transportCB]() { - if (transportCB) { - transportCB(); - } - d->setState(d->pad->session()->role() == Origin::Initiator ? State::Pending : State::Connecting); - } }; - case Action::TransportInfo: - Q_ASSERT(d->transport->hasUpdates()); - std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); - contentEl.appendChild(transportEl); - return OutgoingUpdate { updates, transportCB }; - case Action::TransportReplace: - case Action::TransportAccept: { - Q_ASSERT(d->transport->isInitialOfferReady()); - d->transportReplaceState = State::Unacked; - std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); - contentEl.appendChild(transportEl); - auto action = d->updateToSend; - return OutgoingUpdate { updates, [this, transportCB, action]() { - if (transportCB) { - transportCB(); - } - d->transportReplaceState = action == Action::TransportReplace ? State::Pending : State::Finished; - } }; - } - default: - break; - } - - return OutgoingUpdate(); // TODO -} - -bool Application::wantBetterTransport(const QSharedPointer &t) const -{ - Q_UNUSED(t) - return true; // TODO check -} - -bool Application::selectNextTransport() -{ - while (d->availableTransports.size()) { - auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.last()); - if (t && setTransport(t)) { + d->acceptFile = f; + // TODO validate if accept file matches to the offer + setState(State::Accepted); return true; - } else { - d->availableTransports.removeLast(); - } - } - return false; -} - -void Application::prepare() -{ - if (!d->transport) { - selectNextTransport(); - } - if (d->transport) { - d->setState(State::PrepareLocalOffer); - d->transport->prepare(); - } -} - -void Application::start() -{ - if (d->transport) { - d->setState(State::Connecting); - d->transport->start(); - } - // TODO we need QIODevice somewhere here -} - -bool Application::accept(const QDomElement &el) -{ - File f(el.firstChildElement("file")); - if (!f.isValid()) { - return false; - } - d->acceptFile = f; - // TODO validate if accept file matches to the offer - setState(State::Accepted); - return true; -} - -void Application::remove(Reason::Condition cond, const QString &comment) -{ - if (d->state >= State::Finishing) - return; - - d->terminationReason = Reason(cond, comment); - d->transportReplaceOrigin = Origin::None; // just in case - d->transport->disconnect(this); - d->transport.reset(); - - if (d->creator == d->pad->session()->role() && d->state <= State::PrepareLocalOffer) { - // local content, not yet sent to remote - setState(State::Finished); - return; - } - - setState(State::Finishing); - emit updated(); -} - -bool Application::incomingTransportAccept(const QDomElement &transportEl) -{ - if (d->transportReplaceOrigin != d->pad->session()->role()) { - d->lastError = ErrorUtil::makeOutOfOrder(*d->pad->doc()); - return false; - } - if (d->transport->update(transportEl)) { - d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; - if (d->state >= State::Connecting) { - d->transport->start(); - } - emit updated(); - return true; - } - return false; -} - -bool Application::isValid() const -{ - return d->file.isValid() && d->contentName.size() > 0 && (d->senders == Origin::Initiator || d->senders == Origin::Responder); -} - -void Application::setDevice(QIODevice *dev, bool closeOnFinish) -{ - if (!dev) { // failed to provide proper device - d->terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("No destination device")); - emit updated(); - return; - } - d->device = dev; - d->closeDeviceOnFinish = closeOnFinish; - if (d->senders == d->pad->session()->role()) { - d->writeNextBlockToTransport(); - } else { - d->readNextBlockFromTransport(); - } -} - -Connection::Ptr Application::connection() const -{ - return d->connection.staticCast(); -} - -Pad::Pad(Manager *manager, Session *session) : - _manager(manager), - _session(session) -{ -} - -QDomElement Pad::takeOutgoingSessionInfoUpdate() -{ - return QDomElement(); // TODO -} - -QString Pad::ns() const -{ - return NS; -} - -Session *Pad::session() const -{ - return _session; -} - -ApplicationManager *Pad::manager() const -{ - return _manager; -} - -QString Pad::generateContentName(Origin senders) -{ - QString prefix = senders == _session->role() ? "fileoffer" : "filereq"; - QString name; - do { - name = prefix + QString("_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - } while (_session->content(name, _session->role())); - return name; -} - -void Pad::addOutgoingOffer(const File &file) -{ - auto selfp = _session->applicationPad(NS); - auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); - app->setFile(file); -} -} // namespace FileTransfer + } + + void Application::remove(Reason::Condition cond, const QString &comment) + { + if (d->state >= State::Finishing) + return; + + d->terminationReason = Reason(cond, comment); + d->transportReplaceOrigin = Origin::None; // just in case + d->transport->disconnect(this); + d->transport.reset(); + + if (d->creator == d->pad->session()->role() && d->state <= State::PrepareLocalOffer) { + // local content, not yet sent to remote + setState(State::Finished); + return; + } + + setState(State::Finishing); + emit updated(); + } + + bool Application::incomingTransportAccept(const QDomElement &transportEl) + { + if (d->transportReplaceOrigin != d->pad->session()->role()) { + d->lastError = ErrorUtil::makeOutOfOrder(*d->pad->doc()); + return false; + } + if (d->transport->update(transportEl)) { + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; + if (d->state >= State::Connecting) { + d->transport->start(); + } + emit updated(); + return true; + } + return false; + } + + bool Application::isValid() const + { + return d->file.isValid() && d->contentName.size() > 0 && (d->senders == Origin::Initiator || d->senders == Origin::Responder); + } + + void Application::setDevice(QIODevice *dev, bool closeOnFinish) + { + if (!dev) { // failed to provide proper device + d->terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("No destination device")); + emit updated(); + return; + } + d->device = dev; + d->closeDeviceOnFinish = closeOnFinish; + if (d->senders == d->pad->session()->role()) { + d->writeNextBlockToTransport(); + } else { + d->readNextBlockFromTransport(); + } + } + + Connection::Ptr Application::connection() const + { + return d->connection.staticCast(); + } + + Pad::Pad(Manager *manager, Session *session) : + _manager(manager), + _session(session) + { + } + + QDomElement Pad::takeOutgoingSessionInfoUpdate() + { + return QDomElement(); // TODO + } + + QString Pad::ns() const + { + return NS; + } + + Session *Pad::session() const + { + return _session; + } + + ApplicationManager *Pad::manager() const + { + return _manager; + } + + QString Pad::generateContentName(Origin senders) + { + QString prefix = senders == _session->role() ? "fileoffer" : "filereq"; + QString name; + do { + name = prefix + QString("_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + } while (_session->content(name, _session->role())); + return name; + } + + void Pad::addOutgoingOffer(const File &file) + { + auto selfp = _session->applicationPad(NS); + auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); + app->setFile(file); + } + } // namespace FileTransfer } // namespace Jingle } // namespace XMPP From f1c08fa8e0f684d5b440eb0ce1c18d8a59d5ec11 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 13 Oct 2019 11:17:57 +0300 Subject: [PATCH 103/383] reformat with compact namespaces --- src/xmpp/xmpp-im/jingle-ft.h | 343 ++++++++++++++++++----------------- 1 file changed, 173 insertions(+), 170 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle-ft.h b/src/xmpp/xmpp-im/jingle-ft.h index 3b62d085..536a4727 100644 --- a/src/xmpp/xmpp-im/jingle-ft.h +++ b/src/xmpp/xmpp-im/jingle-ft.h @@ -26,177 +26,180 @@ namespace XMPP { class Client; class Thumbnail; +} + +namespace XMPP { namespace Jingle { namespace FileTransfer { + + extern const QString NS; + class Manager; + + struct Range { + qint64 offset = 0; + qint64 length = 0; // 0 - from offset to the end of the file + QList hashes; + + inline Range() {} + inline Range(qint64 offset, qint64 length) : offset(offset), length(length) {} + inline bool isValid() const { return hashes.size() || offset || length; } + QDomElement toXml(QDomDocument *doc) const; + }; + + class File { + public: + File(); + File(const File &other); + File(const QDomElement &file); + ~File(); + File & operator=(const File &other); + inline bool isValid() const { return d != nullptr; } + QDomElement toXml(QDomDocument *doc) const; + bool merge(const File &other); + bool hasComputedHashes() const; + bool hasSize() const; + + QDateTime date() const; + QString description() const; + QList hashes() const; + Hash hash(Hash::Type t = Hash::Unknown) const; + QString mediaType() const; + QString name() const; + quint64 size() const; + Range range() const; + Thumbnail thumbnail() const; + QByteArray amplitudes() const; + + void setDate(const QDateTime &date); + void setDescription(const QString &desc); + void addHash(const Hash &hash); + void setMediaType(const QString &mediaType); + void setName(const QString &name); + void setSize(quint64 size); + void setRange(const Range &range = Range()); // default empty just to indicate it's supported + void setThumbnail(const Thumbnail &thumb); + void setAmplitudes(const QByteArray &litudes); + + private: + class Private; + Private * ensureD(); + QSharedDataPointer d; + }; + + class Checksum : public ContentBase { + inline Checksum() {} + Checksum(const QDomElement &file); + bool isValid() const; + QDomElement toXml(QDomDocument *doc) const; + + private: + File file; + }; + + class Received : public ContentBase { + using ContentBase::ContentBase; + QDomElement toXml(QDomDocument *doc) const; + }; + + class Pad : public ApplicationManagerPad { + Q_OBJECT + // TODO + public: + Pad(Manager *manager, Session *session); + QDomElement takeOutgoingSessionInfoUpdate() override; + QString ns() const override; + Session * session() const override; + ApplicationManager *manager() const override; + QString generateContentName(Origin senders) override; + + void addOutgoingOffer(const File &file); + + private: + Manager *_manager; + Session *_session; + }; + + class Application : public XMPP::Jingle::Application { + Q_OBJECT + public: + Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders); + ~Application(); + + ApplicationManagerPad::Ptr pad() const override; + State state() const override; + void setState(State state) override; + XMPP::Stanza::Error lastError() const override; + Reason terminationReason() const override; + + QString contentName() const override; + Origin creator() const override; + Origin senders() const override; + Origin transportReplaceOrigin() const override; + SetDescError setDescription(const QDomElement &description) override; + void setFile(const File &file); + File file() const; + File acceptFile() const; + bool setTransport(const QSharedPointer &transport) override; + QSharedPointer transport() const override; + + /** + * @brief setStreamingMode enables external download control. + * So Jingle-FT won't request output device but instead underlying established + * connection will be emitted (see connectionReady() signal). + * The connection is an XMPP::Jingle::Connection::Ptr instance. + * When the connection is not needed anymore, one can just destroy jingle + * session or remove the Application from the session. + * Make sure to set the mode before connection is established. + * @param mode + */ + void setStreamingMode(bool mode = true); + + Action evaluateOutgoingUpdate() override; + OutgoingUpdate takeOutgoingUpdate() override; + bool wantBetterTransport(const QSharedPointer &) const override; + bool selectNextTransport() override; + void prepare() override; + void start() override; + bool accept(const QDomElement &el) override; + void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) override; + + bool isValid() const; + + void setDevice(QIODevice *dev, bool closeOnFinish = true); + Connection::Ptr connection() const; + + protected: + bool incomingTransportReplace(const QSharedPointer &transport) override; + bool incomingTransportAccept(const QDomElement &transportEl) override; + + signals: + void connectionReady(); // streaming mode only + void + deviceRequested(quint64 offset, + quint64 size); // if size = 0 then it's reamaining part of the file (non-streaming mode only) + void progress(quint64 offset); + + private: + class Private; + QScopedPointer d; + }; + + class Manager : public XMPP::Jingle::ApplicationManager { + Q_OBJECT + public: + Manager(QObject *parent = nullptr); + ~Manager(); + void setJingleManager(XMPP::Jingle::Manager *jm); + Application *startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, + Origin senders); + ApplicationManagerPad *pad(Session *session); // pad factory + void closeAll(); + Client * client(); + + QStringList availableTransports() const; + + private: + XMPP::Jingle::Manager *jingleManager = nullptr; + }; -namespace Jingle { -namespace FileTransfer { - -extern const QString NS; -class Manager; - -struct Range { - quint64 offset = 0; - quint64 length = 0; // 0 - from offset to the end of the file - QList hashes; - - inline Range() {} - inline Range(quint64 offset, quint64 length) : - offset(offset), length(length) {} - inline bool isValid() const { return hashes.size() || offset || length; } - QDomElement toXml(QDomDocument *doc) const; -}; - -class File { -public: - File(); - File(const File &other); - File(const QDomElement &file); - ~File(); - File & operator=(const File &other); - inline bool isValid() const { return d != nullptr; } - QDomElement toXml(QDomDocument *doc) const; - bool merge(const File &other); - bool hasComputedHashes() const; - bool hasSize() const; - - QDateTime date() const; - QString description() const; - QList hashes() const; - Hash hash(Hash::Type t = Hash::Unknown) const; - QString mediaType() const; - QString name() const; - quint64 size() const; - Range range() const; - Thumbnail thumbnail() const; - QByteArray amplitudes() const; - - void setDate(const QDateTime &date); - void setDescription(const QString &desc); - void addHash(const Hash &hash); - void setMediaType(const QString &mediaType); - void setName(const QString &name); - void setSize(quint64 size); - void setRange(const Range &range = Range()); // default empty just to indicate it's supported - void setThumbnail(const Thumbnail &thumb); - void setAmplitudes(const QByteArray &litudes); - -private: - class Private; - Private * ensureD(); - QSharedDataPointer d; -}; - -class Checksum : public ContentBase { - inline Checksum() {} - Checksum(const QDomElement &file); - bool isValid() const; - QDomElement toXml(QDomDocument *doc) const; - -private: - File file; -}; - -class Received : public ContentBase { - using ContentBase::ContentBase; - QDomElement toXml(QDomDocument *doc) const; -}; - -class Pad : public ApplicationManagerPad { - Q_OBJECT - // TODO -public: - Pad(Manager *manager, Session *session); - QDomElement takeOutgoingSessionInfoUpdate() override; - QString ns() const override; - Session * session() const override; - ApplicationManager *manager() const override; - QString generateContentName(Origin senders) override; - - void addOutgoingOffer(const File &file); - -private: - Manager *_manager; - Session *_session; -}; - -class Application : public XMPP::Jingle::Application { - Q_OBJECT -public: - Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders); - ~Application(); - - ApplicationManagerPad::Ptr pad() const override; - State state() const override; - void setState(State state) override; - XMPP::Stanza::Error lastError() const override; - Reason terminationReason() const override; - - QString contentName() const override; - Origin creator() const override; - Origin senders() const override; - Origin transportReplaceOrigin() const override; - SetDescError setDescription(const QDomElement &description) override; - void setFile(const File &file); - File file() const; - File acceptFile() const; - bool setTransport(const QSharedPointer &transport) override; - QSharedPointer transport() const override; - - /** - * @brief setStreamingMode enables external download control. - * So Jingle-FT won't request output device but instead underlying established - * connection will be emitted (see connectionReady() signal). - * The connection is an XMPP::Jingle::Connection::Ptr instance. - * When the connection is not needed anymore, one can just destroy jingle - * session or remove the Application from the session. - * Make sure to set the mode before connection is established. - * @param mode - */ - void setStreamingMode(bool mode = true); - - Action evaluateOutgoingUpdate() override; - OutgoingUpdate takeOutgoingUpdate() override; - bool wantBetterTransport(const QSharedPointer &) const override; - bool selectNextTransport() override; - void prepare() override; - void start() override; - bool accept(const QDomElement &el) override; - void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) override; - - bool isValid() const; - - void setDevice(QIODevice *dev, bool closeOnFinish = true); - Connection::Ptr connection() const; - -protected: - bool incomingTransportReplace(const QSharedPointer &transport) override; - bool incomingTransportAccept(const QDomElement &transportEl) override; - -signals: - void connectionReady(); // streaming mode only - void deviceRequested(quint64 offset, quint64 size); // if size = 0 then it's reamaining part of the file (non-streaming mode only) - void progress(quint64 offset); - -private: - class Private; - QScopedPointer d; -}; - -class Manager : public XMPP::Jingle::ApplicationManager { - Q_OBJECT -public: - Manager(QObject *parent = nullptr); - ~Manager(); - void setJingleManager(XMPP::Jingle::Manager *jm); - Application * startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders); - ApplicationManagerPad *pad(Session *session); // pad factory - void closeAll(); - Client * client(); - - QStringList availableTransports() const; - -private: - XMPP::Jingle::Manager *jingleManager = nullptr; -}; } // namespace FileTransfer } // namespace Jingle } // namespace XMPP From d1af87befa75cad006103ba1fb4aeed36f525a72 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 13 Oct 2019 12:32:41 +0300 Subject: [PATCH 104/383] fixed senders attr parser --- src/xmpp/xmpp-im/jingle.cpp | 3148 +++++++++++++++++------------------ 1 file changed, 1506 insertions(+), 1642 deletions(-) diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp index e1b48aff..efcf2531 100644 --- a/src/xmpp/xmpp-im/jingle.cpp +++ b/src/xmpp/xmpp-im/jingle.cpp @@ -34,1891 +34,1755 @@ #include #include -namespace XMPP { -namespace Jingle { -const QString NS(QStringLiteral("urn:xmpp:jingle:1")); -const QString ERROR_NS(QStringLiteral("urn:xmpp:jingle:errors:1")); - -//---------------------------------------------------------------------------- -// Jingle -//---------------------------------------------------------------------------- -static const struct { - const char *text; - Action action; -} jingleActions[] = { -{ "content-accept", Action::ContentAccept }, -{ "content-add", Action::ContentAdd }, -{ "content-modify", Action::ContentModify }, -{ "content-reject", Action::ContentReject }, -{ "content-remove", Action::ContentRemove }, -{ "description-info", Action::DescriptionInfo }, -{ "security-info", Action::SecurityInfo }, -{ "session-accept", Action::SessionAccept }, -{ "session-info", Action::SessionInfo }, -{ "session-initiate", Action::SessionInitiate }, -{ "session-terminate", Action::SessionTerminate }, -{ "transport-accept", Action::TransportAccept }, -{ "transport-info", Action::TransportInfo }, -{ "transport-reject", Action::TransportReject }, -{ "transport-replace", Action::TransportReplace } -}; - -class Jingle::Private : public QSharedData -{ -public: - Action action; - QString sid; - Jid initiator; - Jid responder; -}; - -Jingle::Jingle() -{ - -} - -Jingle::Jingle(Action action, const QString &sid) : - d(new Private) -{ - d->action = action; - d->sid = sid; -} - -Jingle::Jingle(const QDomElement &e) -{ - QString actionStr = e.attribute(QLatin1String("action")); - Action action; - QString sid = e.attribute(QLatin1String("sid")); - Jid initiator; - Jid responder; - - bool found = false; - for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { - if (actionStr == jingleActions[i].text) { - found = true; - action = jingleActions[i].action; - break; - } - } - if (!found || sid.isEmpty()) { - return; +namespace XMPP { namespace Jingle { + const QString NS(QStringLiteral("urn:xmpp:jingle:1")); + const QString ERROR_NS(QStringLiteral("urn:xmpp:jingle:errors:1")); + + //---------------------------------------------------------------------------- + // Jingle + //---------------------------------------------------------------------------- + static const struct { + const char *text; + Action action; + } jingleActions[] + = { { "content-accept", Action::ContentAccept }, { "content-add", Action::ContentAdd }, + { "content-modify", Action::ContentModify }, { "content-reject", Action::ContentReject }, + { "content-remove", Action::ContentRemove }, { "description-info", Action::DescriptionInfo }, + { "security-info", Action::SecurityInfo }, { "session-accept", Action::SessionAccept }, + { "session-info", Action::SessionInfo }, { "session-initiate", Action::SessionInitiate }, + { "session-terminate", Action::SessionTerminate }, { "transport-accept", Action::TransportAccept }, + { "transport-info", Action::TransportInfo }, { "transport-reject", Action::TransportReject }, + { "transport-replace", Action::TransportReplace } }; + + class Jingle::Private : public QSharedData { + public: + Action action; + QString sid; + Jid initiator; + Jid responder; + }; + + Jingle::Jingle() {} + + Jingle::Jingle(Action action, const QString &sid) : d(new Private) + { + d->action = action; + d->sid = sid; } - if (!e.attribute(QLatin1String("initiator")).isEmpty()) { - initiator = Jid(e.attribute(QLatin1String("initiator"))); - if (initiator.isNull()) { - qDebug("malformed initiator jid"); - return; + Jingle::Jingle(const QDomElement &e) + { + QString actionStr = e.attribute(QLatin1String("action")); + Action action; + QString sid = e.attribute(QLatin1String("sid")); + Jid initiator; + Jid responder; + + bool found = false; + for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { + if (actionStr == jingleActions[i].text) { + found = true; + action = jingleActions[i].action; + break; + } } - } - if (!e.attribute(QLatin1String("responder")).isEmpty()) { - responder = Jid(e.attribute(QLatin1String("responder"))); - if (responder.isNull()) { - qDebug("malformed responder jid"); + if (!found || sid.isEmpty()) { return; } - } - - d = new Private; - d->action = action; - d->sid = sid; - d->responder = responder; -} -Jingle::Jingle(const Jingle &other) : - d(other.d) -{ - -} + if (!e.attribute(QLatin1String("initiator")).isEmpty()) { + initiator = Jid(e.attribute(QLatin1String("initiator"))); + if (initiator.isNull()) { + qDebug("malformed initiator jid"); + return; + } + } + if (!e.attribute(QLatin1String("responder")).isEmpty()) { + responder = Jid(e.attribute(QLatin1String("responder"))); + if (responder.isNull()) { + qDebug("malformed responder jid"); + return; + } + } -Jingle::~Jingle() -{ + d = new Private; + d->action = action; + d->sid = sid; + d->responder = responder; + } -} + Jingle::Jingle(const Jingle &other) : d(other.d) {} -Jingle::Private* Jingle::ensureD() -{ - if (!d) { - d = new Private; - } - return d.data(); -} + Jingle::~Jingle() {} -QDomElement Jingle::toXml(QDomDocument *doc) const -{ - if (!d || d->sid.isEmpty() || d->action == Action::NoAction) { - return QDomElement(); + Jingle::Private *Jingle::ensureD() + { + if (!d) { + d = new Private; + } + return d.data(); } - QDomElement query = doc->createElementNS(NS, QLatin1String("jingle")); - for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { - if (jingleActions[i].action == d->action) { - query.setAttribute(QLatin1String("action"), QLatin1String(jingleActions[i].text)); - break; + QDomElement Jingle::toXml(QDomDocument *doc) const + { + if (!d || d->sid.isEmpty() || d->action == Action::NoAction) { + return QDomElement(); } - } - if(!d->initiator.isNull()) - query.setAttribute(QLatin1String("initiator"), d->initiator.full()); - if(!d->responder.isNull()) - query.setAttribute(QLatin1String("responder"), d->responder.full()); - query.setAttribute(QLatin1String("sid"), d->sid); - - return query; -} - -Action Jingle::action() const -{ - return d->action; -} - -const QString &Jingle::sid() const -{ - return d->sid; -} - -const Jid &Jingle::initiator() const -{ - return d->initiator; -} - -void Jingle::setInitiator(const Jid &jid) -{ - d->initiator = jid; -} - -const Jid &Jingle::responder() const -{ - return d->responder; -} - -void Jingle::setResponder(const Jid &jid) -{ - d->responder = jid; -} - -//---------------------------------------------------------------------------- -// Reason -//---------------------------------------------------------------------------- -static const QMap reasonConditions = { - { QStringLiteral("alternative-session"), Reason::AlternativeSession }, - { QStringLiteral("busy"), Reason::Busy }, - { QStringLiteral("cancel"), Reason::Cancel }, - { QStringLiteral("connectivity-error"), Reason::ConnectivityError }, - { QStringLiteral("decline"), Reason::Decline }, - { QStringLiteral("expired"), Reason::Expired }, - { QStringLiteral("failed-application"), Reason::FailedApplication }, - { QStringLiteral("failed-transport"), Reason::FailedTransport }, - { QStringLiteral("general-error"), Reason::GeneralError }, - { QStringLiteral("gone"), Reason::Gone }, - { QStringLiteral("incompatible-parameters"), Reason::IncompatibleParameters }, - { QStringLiteral("media-error"), Reason::MediaError }, - { QStringLiteral("security-error"), Reason::SecurityError }, - { QStringLiteral("success"), Reason::Success }, - { QStringLiteral("timeout"), Reason::Timeout }, - { QStringLiteral("unsupported-applications"), Reason::UnsupportedApplications }, - { QStringLiteral("unsupported-transports"), Reason::UnsupportedTransports }, -}; - -class Reason::Private :public QSharedData { -public: - Reason::Condition cond; - QString text; -}; - -Reason::Reason() -{ - -} - -Reason::~Reason() -{ - -} - -Reason::Reason(Reason::Condition cond, const QString &text) : - d(new Private) -{ - d->cond = cond; - d->text = text; -} - -Reason::Reason(const QDomElement &e) -{ - if(e.tagName() != QLatin1String("reason")) - return; - - Condition condition = NoReason; - QString text; - QString rns = e.namespaceURI(); - - for (QDomElement c = e.firstChildElement(); !c.isNull(); c = c.nextSiblingElement()) { - if (c.tagName() == QLatin1String("text")) { - text = c.text(); - } - else if (c.namespaceURI() != rns) { - // TODO add here all the extensions to reason. - } - else { - condition = reasonConditions.value(c.tagName()); + QDomElement query = doc->createElementNS(NS, QLatin1String("jingle")); + for (unsigned int i = 0; i < sizeof(jingleActions) / sizeof(jingleActions[0]); i++) { + if (jingleActions[i].action == d->action) { + query.setAttribute(QLatin1String("action"), QLatin1String(jingleActions[i].text)); + break; + } } + + if (!d->initiator.isNull()) + query.setAttribute(QLatin1String("initiator"), d->initiator.full()); + if (!d->responder.isNull()) + query.setAttribute(QLatin1String("responder"), d->responder.full()); + query.setAttribute(QLatin1String("sid"), d->sid); + + return query; } - if (condition != NoReason) { - d = new Private; - d->cond = condition; + Action Jingle::action() const { return d->action; } + + const QString &Jingle::sid() const { return d->sid; } + + const Jid &Jingle::initiator() const { return d->initiator; } + + void Jingle::setInitiator(const Jid &jid) { d->initiator = jid; } + + const Jid &Jingle::responder() const { return d->responder; } + + void Jingle::setResponder(const Jid &jid) { d->responder = jid; } + + //---------------------------------------------------------------------------- + // Reason + //---------------------------------------------------------------------------- + static const QMap reasonConditions = { + { QStringLiteral("alternative-session"), Reason::AlternativeSession }, + { QStringLiteral("busy"), Reason::Busy }, + { QStringLiteral("cancel"), Reason::Cancel }, + { QStringLiteral("connectivity-error"), Reason::ConnectivityError }, + { QStringLiteral("decline"), Reason::Decline }, + { QStringLiteral("expired"), Reason::Expired }, + { QStringLiteral("failed-application"), Reason::FailedApplication }, + { QStringLiteral("failed-transport"), Reason::FailedTransport }, + { QStringLiteral("general-error"), Reason::GeneralError }, + { QStringLiteral("gone"), Reason::Gone }, + { QStringLiteral("incompatible-parameters"), Reason::IncompatibleParameters }, + { QStringLiteral("media-error"), Reason::MediaError }, + { QStringLiteral("security-error"), Reason::SecurityError }, + { QStringLiteral("success"), Reason::Success }, + { QStringLiteral("timeout"), Reason::Timeout }, + { QStringLiteral("unsupported-applications"), Reason::UnsupportedApplications }, + { QStringLiteral("unsupported-transports"), Reason::UnsupportedTransports }, + }; + + class Reason::Private : public QSharedData { + public: + Reason::Condition cond; + QString text; + }; + + Reason::Reason() {} + + Reason::~Reason() {} + + Reason::Reason(Reason::Condition cond, const QString &text) : d(new Private) + { + d->cond = cond; d->text = text; } -} - -Reason::Reason(const Reason &other) : - d(other.d) -{ - -} - -Reason &Reason::operator=(const Reason &other) -{ - d = other.d; - return *this; -} - -Reason::Condition Reason::condition() const -{ - if (d) return d->cond; - return NoReason; -} - -void Reason::setCondition(Condition cond) -{ - ensureD()->cond = cond; -} - -QString Reason::text() const -{ - if (d) return d->text; - return QString(); -} - -void Reason::setText(const QString &text) -{ - ensureD()->text = text; -} - -QDomElement Reason::toXml(QDomDocument *doc) const -{ - if (d && d->cond != NoReason) { - for (auto r = reasonConditions.cbegin(); r != reasonConditions.cend(); ++r) { - if (r.value() == d->cond) { - QDomElement e = doc->createElement(QLatin1String("reason")); - e.appendChild(doc->createElement(r.key())); - if (!d->text.isEmpty()) { - e.appendChild(textTag(doc, QLatin1String("text"), d->text)); - } - return e; + + Reason::Reason(const QDomElement &e) + { + if (e.tagName() != QLatin1String("reason")) + return; + + Condition condition = NoReason; + QString text; + QString rns = e.namespaceURI(); + + for (QDomElement c = e.firstChildElement(); !c.isNull(); c = c.nextSiblingElement()) { + if (c.tagName() == QLatin1String("text")) { + text = c.text(); + } else if (c.namespaceURI() != rns) { + // TODO add here all the extensions to reason. + } else { + condition = reasonConditions.value(c.tagName()); } } - } - return QDomElement(); -} -Reason::Private* Reason::ensureD() -{ - if (!d) { - d = new Private; - } - return d.data(); -} - -//---------------------------------------------------------------------------- -// ContentBase -//---------------------------------------------------------------------------- -ContentBase::ContentBase(Origin creator, const QString &name) : - creator(creator), name(name) -{ -} - -ContentBase::ContentBase(const QDomElement &el) -{ - static QMap sendersMap({ - {QStringLiteral("initiator"), Origin::Initiator}, - {QStringLiteral("none"), Origin::Initiator}, - {QStringLiteral("responder"), Origin::Initiator} - }); - creator = creatorAttr(el); - name = el.attribute(QLatin1String("name")); - senders = sendersMap.value(el.attribute(QLatin1String("senders"))); - disposition = el.attribute(QLatin1String("disposition")); // if empty, it's "session" -} - -QDomElement ContentBase::toXml(QDomDocument *doc, const char *tagName) const -{ - if (!isValid()) { - return QDomElement(); + if (condition != NoReason) { + d = new Private; + d->cond = condition; + d->text = text; + } } - auto el = doc->createElement(QLatin1String(tagName)); - setCreatorAttr(el, creator); - el.setAttribute(QLatin1String("name"), name); - - QString sendersStr; - switch (senders) { - case Origin::None: - sendersStr = QLatin1String("none"); - break; - - case Origin::Initiator: - sendersStr = QLatin1String("initiator"); - break; - - case Origin::Responder: - sendersStr = QLatin1String("responder"); - break; - - case Origin::Both: - default: - break; + + Reason::Reason(const Reason &other) : d(other.d) {} + + Reason &Reason::operator=(const Reason &other) + { + d = other.d; + return *this; } - if (!disposition.isEmpty() && disposition != QLatin1String("session")) { - el.setAttribute(QLatin1String("disposition"), disposition); // NOTE review how we can parse it some generic way + Reason::Condition Reason::condition() const + { + if (d) + return d->cond; + return NoReason; } - if (!sendersStr.isEmpty()) { - el.setAttribute(QLatin1String("senders"), sendersStr); + + void Reason::setCondition(Condition cond) { ensureD()->cond = cond; } + + QString Reason::text() const + { + if (d) + return d->text; + return QString(); } - return el; -} + void Reason::setText(const QString &text) { ensureD()->text = text; } -Origin ContentBase::creatorAttr(const QDomElement &el) -{ - auto creatorStr = el.attribute(QLatin1String("creator")); - if (creatorStr == QLatin1String("initiator")) { - return Origin::Initiator; + QDomElement Reason::toXml(QDomDocument *doc) const + { + if (d && d->cond != NoReason) { + for (auto r = reasonConditions.cbegin(); r != reasonConditions.cend(); ++r) { + if (r.value() == d->cond) { + QDomElement e = doc->createElement(QLatin1String("reason")); + e.appendChild(doc->createElement(r.key())); + if (!d->text.isEmpty()) { + e.appendChild(textTag(doc, QLatin1String("text"), d->text)); + } + return e; + } + } + } + return QDomElement(); } - if (creatorStr == QLatin1String("responder")) { - return Origin::Responder; + + Reason::Private *Reason::ensureD() + { + if (!d) { + d = new Private; + } + return d.data(); } - return Origin::None; -} - -bool ContentBase::setCreatorAttr(QDomElement &el, Origin creator) -{ - if (creator == Origin::Initiator) { - el.setAttribute(QLatin1String("creator"), QLatin1String("initiator")); - } else if (creator == Origin::Responder) { - el.setAttribute(QLatin1String("creator"), QLatin1String("responder")); - } else { - return false; + + //---------------------------------------------------------------------------- + // ContentBase + //---------------------------------------------------------------------------- + ContentBase::ContentBase(Origin creator, const QString &name) : creator(creator), name(name) {} + + ContentBase::ContentBase(const QDomElement &el) + { + static QMap sendersMap({ { QStringLiteral("initiator"), Origin::Initiator }, + { QStringLiteral("none"), Origin::Both }, + { QStringLiteral("responder"), Origin::Responder } }); + creator = creatorAttr(el); + name = el.attribute(QLatin1String("name")); + senders = sendersMap.value(el.attribute(QLatin1String("senders"))); + disposition = el.attribute(QLatin1String("disposition")); // if empty, it's "session" } - return true; -} - -//---------------------------------------------------------------------------- -// Application -//---------------------------------------------------------------------------- -ApplicationManager::ApplicationManager(QObject *parent) : - QObject(parent) -{ -} - -//---------------------------------------------------------------------------- -// TransportManager -//---------------------------------------------------------------------------- -TransportManager::TransportManager(QObject *parent) : - QObject(parent) -{ - -} - -//---------------------------------------------------------------------------- -// JTPush - Jingle Task -//---------------------------------------------------------------------------- -class JTPush : public Task -{ - Q_OBJECT - - QList externalManagers; - QList externalSessions; -public: - JTPush(Task *parent) : - Task(parent) + + QDomElement ContentBase::toXml(QDomDocument *doc, const char *tagName) const { + if (!isValid()) { + return QDomElement(); + } + auto el = doc->createElement(QLatin1String(tagName)); + setCreatorAttr(el, creator); + el.setAttribute(QLatin1String("name"), name); - } + QString sendersStr; + switch (senders) { + case Origin::None: + sendersStr = QLatin1String("none"); + break; + + case Origin::Initiator: + sendersStr = QLatin1String("initiator"); + break; + + case Origin::Responder: + sendersStr = QLatin1String("responder"); + break; + + case Origin::Both: + default: + break; + } - ~JTPush(){} + if (!disposition.isEmpty() && disposition != QLatin1String("session")) { + el.setAttribute(QLatin1String("disposition"), + disposition); // NOTE review how we can parse it some generic way + } + if (!sendersStr.isEmpty()) { + el.setAttribute(QLatin1String("senders"), sendersStr); + } - inline void addExternalManager(const QString &ns) { externalManagers.append(ns); } - inline void forgetExternalSession(const QString &sid) { externalSessions.removeOne(sid); } - inline void registerExternalSession(const QString &sid) { externalSessions.append(sid); } + return el; + } - bool take(const QDomElement &iq) + Origin ContentBase::creatorAttr(const QDomElement &el) { - if (iq.tagName() != QLatin1String("iq") || iq.attribute(QLatin1String("type")) != QLatin1String("set")) { - return false; + auto creatorStr = el.attribute(QLatin1String("creator")); + if (creatorStr == QLatin1String("initiator")) { + return Origin::Initiator; } - auto jingleEl = iq.firstChildElement(QStringLiteral("jingle")); - if (jingleEl.isNull() || jingleEl.namespaceURI() != ::XMPP::Jingle::NS) { - return false; + if (creatorStr == QLatin1String("responder")) { + return Origin::Responder; } + return Origin::None; + } - Jingle jingle(jingleEl); - if (!jingle.isValid()) { - respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); - return true; + bool ContentBase::setCreatorAttr(QDomElement &el, Origin creator) + { + if (creator == Origin::Initiator) { + el.setAttribute(QLatin1String("creator"), QLatin1String("initiator")); + } else if (creator == Origin::Responder) { + el.setAttribute(QLatin1String("creator"), QLatin1String("responder")); + } else { + return false; } + return true; + } + + //---------------------------------------------------------------------------- + // Application + //---------------------------------------------------------------------------- + ApplicationManager::ApplicationManager(QObject *parent) : QObject(parent) {} + + //---------------------------------------------------------------------------- + // TransportManager + //---------------------------------------------------------------------------- + TransportManager::TransportManager(QObject *parent) : QObject(parent) {} + + //---------------------------------------------------------------------------- + // JTPush - Jingle Task + //---------------------------------------------------------------------------- + class JTPush : public Task { + Q_OBJECT + + QList externalManagers; + QList externalSessions; + + public: + JTPush(Task *parent) : Task(parent) {} + + ~JTPush() {} + + inline void addExternalManager(const QString &ns) { externalManagers.append(ns); } + inline void forgetExternalSession(const QString &sid) { externalSessions.removeOne(sid); } + inline void registerExternalSession(const QString &sid) { externalSessions.append(sid); } + + bool take(const QDomElement &iq) + { + if (iq.tagName() != QLatin1String("iq") || iq.attribute(QLatin1String("type")) != QLatin1String("set")) { + return false; + } + auto jingleEl = iq.firstChildElement(QStringLiteral("jingle")); + if (jingleEl.isNull() || jingleEl.namespaceURI() != ::XMPP::Jingle::NS) { + return false; + } + + Jingle jingle(jingleEl); + if (!jingle.isValid()) { + respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); + return true; + } + + if (externalManagers.size()) { + if (jingle.action() == Action::SessionInitiate) { + auto cname = QString::fromLatin1("content"); + auto dname = QString::fromLatin1("description"); + for (auto n = jingleEl.firstChildElement(cname); !n.isNull(); n = n.nextSiblingElement(cname)) { + auto del = n.firstChildElement(dname); + if (!del.isNull() && externalManagers.contains(del.namespaceURI())) { + externalSessions.append(jingle.sid()); + return false; + } + } + } else if (externalSessions.contains(jingle.sid())) { + if (jingle.action() == Action::SessionTerminate) { + externalSessions.removeOne(jingle.sid()); + } + return false; + } + } - if (externalManagers.size()) { + QString fromStr(iq.attribute(QStringLiteral("from"))); + Jid from(fromStr); if (jingle.action() == Action::SessionInitiate) { - auto cname = QString::fromLatin1("content"); - auto dname = QString::fromLatin1("description"); - for (auto n = jingleEl.firstChildElement(cname); !n.isNull(); n = n.nextSiblingElement(cname)) { - auto del = n.firstChildElement(dname); - if (!del.isNull() && externalManagers.contains(del.namespaceURI())) { - externalSessions.append(jingle.sid()); - return false; + if (!client()->jingleManager()->isAllowedParty(from) + || (!jingle.initiator().isEmpty() + && !client()->jingleManager()->isAllowedParty(jingle.initiator()))) { + respondError(iq, Stanza::Error::Cancel, Stanza::Error::ServiceUnavailable); + return true; + } + + Jid redirection(client()->jingleManager()->redirectionJid()); + if (redirection.isValid()) { + respondError(iq, Stanza::Error::Modify, Stanza::Error::Redirect, + QStringLiteral("xmpp:") + redirection.full()); + return true; + } + + auto session = client()->jingleManager()->session(from, jingle.sid()); + if (session) { + if (session->role() == Origin::Initiator) { // + respondTieBreak(iq); + } else { + // second session from this peer with the same sid. + respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); } + return true; } - } else if (externalSessions.contains(jingle.sid())) { - if (jingle.action() == Action::SessionTerminate) { - externalSessions.removeOne(jingle.sid()); + session = client()->jingleManager()->incomingSessionInitiate(from, jingle, jingleEl); + if (!session) { + respondError(iq, client()->jingleManager()->lastError()); + return true; + } + } else { + auto session = client()->jingleManager()->session(from, jingle.sid()); + if (!session) { + if (jingle.action() == Action::SessionTerminate) { + auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); + client()->send(resp); + } else { + auto el = client()->doc()->createElementNS(ERROR_NS, QStringLiteral("unknown-session")); + respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); + } + return true; + } + if (!session->updateFromXml(jingle.action(), jingleEl)) { + respondError(iq, session->lastError()); + return true; } - return false; } + + auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); + client()->send(resp); + return true; } - QString fromStr(iq.attribute(QStringLiteral("from"))); - Jid from(fromStr); - if (jingle.action() == Action::SessionInitiate) { - if (!client()->jingleManager()->isAllowedParty(from) || - (!jingle.initiator().isEmpty() && !client()->jingleManager()->isAllowedParty(jingle.initiator()))) { - respondError(iq, Stanza::Error::Cancel, Stanza::Error::ServiceUnavailable); - return true; + void respondError(const QDomElement &iq, Stanza::Error::ErrorType errType, Stanza::Error::ErrorCond errCond, + const QString &text = QString(), const QDomElement &jingleErr = QDomElement()) + { + auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), + iq.attribute(QStringLiteral("id"))); + Stanza::Error error(errType, errCond, text); + auto errEl = error.toXml(*client()->doc(), client()->stream().baseNS()); + if (!jingleErr.isNull()) { + errEl.appendChild(jingleErr); } + resp.appendChild(errEl); + client()->send(resp); + } - Jid redirection(client()->jingleManager()->redirectionJid()); - if (redirection.isValid()) { - respondError(iq, Stanza::Error::Modify, Stanza::Error::Redirect, QStringLiteral("xmpp:")+redirection.full()); - return true; + void respondTieBreak(const QDomElement &iq) + { + Stanza::Error error(Stanza::Error::Cancel, Stanza::Error::Conflict); + ErrorUtil::fill(*client()->doc(), error, ErrorUtil::TieBreak); + respondError(iq, error); + } + + void respondError(const QDomElement &iq, const Stanza::Error &error) + { + auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), + iq.attribute(QStringLiteral("id"))); + resp.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); + client()->send(resp); + } + }; + + //---------------------------------------------------------------------------- + // JT - Jingle Task + //---------------------------------------------------------------------------- + class JT : public Task { + Q_OBJECT + + QDomElement iq_; + Jid to_; + + public: + JT(Task *parent) : Task(parent) {} + + ~JT() {} + + void request(const Jid &to, const QDomElement &jingleEl) + { + to_ = to; + iq_ = createIQ(doc(), "set", to.full(), id()); + iq_.appendChild(jingleEl); + } + + void onGo() { send(iq_); } + + bool take(const QDomElement &x) + { + if (!iqVerify(x, to_, id())) + return false; + + if (x.attribute("type") == "error") { + setError(x); + } else { + setSuccess(); } + return true; + } + }; - auto session = client()->jingleManager()->session(from, jingle.sid()); - if (session) { - if (session->role() == Origin::Initiator) { // - respondTieBreak(iq); - } else { - // second session from this peer with the same sid. - respondError(iq, Stanza::Error::Cancel, Stanza::Error::BadRequest); + //---------------------------------------------------------------------------- + // Session + //---------------------------------------------------------------------------- + class Session::Private { + public: + Session *q; + Manager *manager; + QTimer stepTimer; + State state = State::Created; // state of session on our side. if it's incoming we start from Created anyaway + // but Pending state is skipped + Origin role = Origin::Initiator; // my role in the session + XMPP::Stanza::Error lastError; + Reason terminateReason; + QMap> applicationPads; + QMap> transportPads; + // QMap myContent; // content::creator=(role == + // Session::Role::Initiator?initiator:responder) QMap remoteContent; // + // content::creator=(role == Session::Role::Responder?initiator:responder) + QMap contentList; + QSet signalingContent; + QHash + outgoingUpdates; // session level updates. session-info for example or some rejected apps + QString sid; + Jid origFrom; // "from" attr of IQ. + Jid otherParty; // either "from" or initiator/responder. it's where to send all requests. + Jid localParty; // that one will be set as initiator/responder if provided + bool waitingAck = false; + + void setSessionFinished() + { + state = State::Finished; + emit q->terminated(); + signalingContent.clear(); + for (auto &c : contentList) { + if (c->state() != State::Finished) { + c->setState(State::Finished); } - return true; } - session = client()->jingleManager()->incomingSessionInitiate(from, jingle, jingleEl); - if (!session) { - respondError(iq, client()->jingleManager()->lastError()); - return true; + auto vals = contentList.values(); + contentList.clear(); + while (vals.size()) { + vals.takeLast()->deleteLater(); } - } else { - auto session = client()->jingleManager()->session(from, jingle.sid()); - if (!session) { - if (jingle.action() == Action::SessionTerminate) { - auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); - client()->send(resp); + q->deleteLater(); + } + + void sendJingle(Action action, QList update, + std::function successCB = std::function()) + { + QDomDocument &doc = *manager->client()->doc(); + Jingle jingle(action, sid); + if (action == Action::SessionInitiate) { + jingle.setInitiator(manager->client()->jid()); + } + if (action == Action::SessionAccept) { + jingle.setResponder(manager->client()->jid()); + } + auto xml = jingle.toXml(&doc); + + for (const QDomElement &e : update) { + xml.appendChild(e); + } + + auto jt = new JT(manager->client()->rootTask()); + jt->request(otherParty, xml); + QObject::connect(jt, &JT::finished, q, [jt, jingle, successCB, this]() { + waitingAck = false; + if (jt->success()) { + if (successCB) { + successCB(); + } else { + planStep(); + } } else { - auto el = client()->doc()->createElementNS(ERROR_NS, QStringLiteral("unknown-session")); - respondError(iq, Stanza::Error::Cancel, Stanza::Error::ItemNotFound, QString(), el); + lastError = jt->error(); + if (ErrorUtil::jingleCondition(lastError) != ErrorUtil::TieBreak) + setSessionFinished(); + else + planStep(); } - return true; + }); + waitingAck = true; + jt->go(true); + } + + void planStep() + { + if (waitingAck) { + return; } - if (!session->updateFromXml(jingle.action(), jingleEl)) { - respondError(iq, session->lastError()); - return true; + lastError = Stanza::Error(0, 0); + if (!stepTimer.isActive()) { + stepTimer.start(); } } - auto resp = createIQ(client()->doc(), "result", fromStr, iq.attribute(QStringLiteral("id"))); - client()->send(resp); - return true; - } + void doStep() + { + if (waitingAck) { // we will return here when ack is received. Session::Unacked is possible also only with + // waitingAck + return; + } + if (terminateReason.condition() && state != State::Finished) { + if (state != State::Created || role == Origin::Responder) { + sendJingle(Action::SessionTerminate, + QList() << terminateReason.toXml(manager->client()->doc())); + } + setSessionFinished(); + return; + } + if (state == State::Created || state == State::Finished) { + return; // we will start doing something when initiate() is called + } - void respondError(const QDomElement &iq, Stanza::Error::ErrorType errType, Stanza::Error::ErrorCond errCond, - const QString &text = QString(), const QDomElement &jingleErr = QDomElement()) - { - auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), iq.attribute(QStringLiteral("id"))); - Stanza::Error error(errType, errCond, text); - auto errEl = error.toXml(*client()->doc(), client()->stream().baseNS()); - if (!jingleErr.isNull()) { - errEl.appendChild(jingleErr); - } - resp.appendChild(errEl); - client()->send(resp); - } + if (outgoingUpdates.size()) { + auto it = outgoingUpdates.begin(); + auto action = it.key(); + auto updates = it.value(); + auto elements = std::get<0>(updates); + auto cb = std::get<1>(updates); + outgoingUpdates.erase(it); + sendJingle(action, elements, [this, cb]() { + if (cb) { + cb(); + } + planStep(); + }); + return; + } - void respondTieBreak(const QDomElement &iq) - { - Stanza::Error error(Stanza::Error::Cancel, Stanza::Error::Conflict); - ErrorUtil::fill(*client()->doc(), error, ErrorUtil::TieBreak); - respondError(iq, error); - } + typedef std::tuple, OutgoingUpdateCB> AckHndl; // will be used from callback on iq ack + if (state == State::PrepareLocalOffer) { // we are going to send session-initiate/accept (already accepted + // by the user but not sent yet) + /* + * For session-initiate everything is prety much straightforward, just any content with + * Action::ContentAdd update type has to be added. But with session-accept things are more complicated + * 1. Local client could add its content. So we have to check content origin too. + * 2. Remote client could add more content before local session-accept. Then we have two options + * a) send content-accept and skip this content in session-accept later + * b) don't send content-accept and accept everything with session-accept + * We prefer option (b) in our implementation. + */ + Action expectedContentAction = role == Origin::Initiator ? Action::ContentAdd : Action::ContentAccept; + for (const auto &c : contentList) { + auto out = c->evaluateOutgoingUpdate(); + if (out == Action::ContentReject) { // yeah we are rejecting local content. invalid? + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + setSessionFinished(); + return; + } + if (out != expectedContentAction) { + return; // keep waiting. + } + } + Action actionToSend = Action::SessionAccept; + State finalState = State::Active; + // so all contents is ready for session-initiate. let's do it + if (role == Origin::Initiator) { + sid = manager->registerSession(q); + actionToSend = Action::SessionInitiate; + finalState = State::Pending; + } - void respondError(const QDomElement &iq, const Stanza::Error &error) - { - auto resp = createIQ(client()->doc(), "error", iq.attribute(QStringLiteral("from")), iq.attribute(QStringLiteral("id"))); - resp.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); - client()->send(resp); - } -}; + QList contents; + QList acceptApps; + for (const auto &p : contentList) { + QList xml; + OutgoingUpdateCB callback; + std::tie(xml, callback) = p->takeOutgoingUpdate(); + contents += xml; + // p->setState(State::Unacked); + if (callback) { + acceptApps.append(AckHndl { p, callback }); + } + } + state = State::Unacked; + sendJingle(actionToSend, contents, [this, acceptApps, finalState]() { + state = finalState; + for (const auto &h : acceptApps) { + auto app = std::get<0>(h); + auto callback = std::get<1>(h); + if (app) { + callback(); + if (role == Origin::Responder) { + app->start(); + } + } + } + if (finalState == State::Active) { + emit q->activated(); + } + planStep(); + }); -//---------------------------------------------------------------------------- -// JT - Jingle Task -//---------------------------------------------------------------------------- -class JT : public Task -{ - Q_OBJECT + return; + } - QDomElement iq_; - Jid to_; + // So session is either in State::Pending or State::Active here. + // State::Connecting status is skipped for session. + QList updateXml; + for (auto mp : applicationPads) { + auto p = mp.toStrongRef(); + QDomElement el = p->takeOutgoingSessionInfoUpdate(); + if (!el.isNull()) { + updateXml.append(el); + // we can send session-info for just one application. so stop processing + sendJingle(Action::SessionInfo, updateXml, [this]() { planStep(); }); + return; + } + } -public: - JT(Task *parent) : - Task(parent) - { + QMultiMap updates; - } + for (auto app : signalingContent) { + Action updateType = app->evaluateOutgoingUpdate(); + if (updateType != Action::NoAction) { + updates.insert(updateType, app); + } + } - ~JT(){} + QList acceptApps; + if (updates.size()) { + Action action = updates.begin().key(); // NOTE maybe some actions have more priority than another + auto apps = updates.values(action); + for (auto app : apps) { + QList xml; + OutgoingUpdateCB callback; + std::tie(xml, callback) = app->takeOutgoingUpdate(); + updateXml += xml; + if (callback) { + acceptApps.append(AckHndl { app, callback }); + } + } + sendJingle(action, updateXml, [this, acceptApps]() { + for (const auto &h : acceptApps) { + auto app = std::get<0>(h); + auto callback = std::get<1>(h); + if (app) { + callback(); + } + } + planStep(); + }); + } + } - void request(const Jid &to, const QDomElement &jingleEl) - { - to_ = to; - iq_ = createIQ(doc(), "set", to.full(), id()); - iq_.appendChild(jingleEl); - } + Reason reason(const QDomElement &jingleEl) + { + QDomElement re = jingleEl.firstChildElement(QLatin1String("reason")); + Reason reason; + if (!re.isNull()) { + reason = Reason(re); + if (!reason.isValid()) { + qDebug("invalid reason"); + } + } + return reason; + } - void onGo() - { - send(iq_); - } + void addAndInitContent(Origin creator, Application *content) + { + contentList.insert(ContentKey { content->contentName(), creator }, content); + if (state != State::Created && content->evaluateOutgoingUpdate() != Action::NoAction) { + signalingContent.insert(content); + } + QObject::connect(content, &Application::updated, q, [this, content]() { + signalingContent.insert(content); + planStep(); + }); + QObject::connect(content, &Application::destroyed, q, [this, content]() { + signalingContent.remove(content); + for (auto it = contentList.begin(); it != contentList.end(); ++it) { // optimize for large lists? + if (it.value() == content) { + contentList.erase(it); + break; + } + } + }); + } - bool take(const QDomElement &x) - { - if(!iqVerify(x, to_, id())) - return false; + enum AddContentError { Ok, Unparsed, Unexpected, Unsupported }; - if(x.attribute("type") == "error") { - setError(x); - } else { - setSuccess(); - } - return true; - } -}; - -//---------------------------------------------------------------------------- -// Session -//---------------------------------------------------------------------------- -class Session::Private -{ -public: - Session *q; - Manager *manager; - QTimer stepTimer; - State state = State::Created; // state of session on our side. if it's incoming we start from Created anyaway but Pending state is skipped - Origin role = Origin::Initiator; // my role in the session - XMPP::Stanza::Error lastError; - Reason terminateReason; - QMap> applicationPads; - QMap> transportPads; - //QMap myContent; // content::creator=(role == Session::Role::Initiator?initiator:responder) - //QMap remoteContent; // content::creator=(role == Session::Role::Responder?initiator:responder) - QMap contentList; - QSet signalingContent; - QHash outgoingUpdates; // session level updates. session-info for example or some rejected apps - QString sid; - Jid origFrom; // "from" attr of IQ. - Jid otherParty; // either "from" or initiator/responder. it's where to send all requests. - Jid localParty; // that one will be set as initiator/responder if provided - bool waitingAck = false; - - void setSessionFinished() - { - state = State::Finished; - emit q->terminated(); - signalingContent.clear(); - for (auto &c: contentList) { - if (c->state() != State::Finished) { - c->setState(State::Finished); + std::tuple parseContentAdd(const QDomElement &ce) + { + QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); + QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); + QString descriptionNS = descriptionEl.namespaceURI(); + QString transportNS = transportEl.namespaceURI(); + typedef std::tuple result; + + ContentBase c(ce); + if (!c.isValid() || descriptionEl.isNull() || transportEl.isNull() || descriptionNS.isEmpty() + || transportNS.isEmpty()) { + return result { Unparsed, Reason::Success, nullptr }; } - } - auto vals = contentList.values(); - contentList.clear(); - while (vals.size()) { - vals.takeLast()->deleteLater(); - } - q->deleteLater(); - } - void sendJingle(Action action, QList update, std::function successCB = std::function()) - { - QDomDocument &doc = *manager->client()->doc(); - Jingle jingle(action, sid); - if (action == Action::SessionInitiate) { - jingle.setInitiator(manager->client()->jid()); - } - if (action == Action::SessionAccept) { - jingle.setResponder(manager->client()->jid()); - } - auto xml = jingle.toXml(&doc); + auto appPad = q->applicationPadFactory(descriptionNS); + if (!appPad) { + return result { Unsupported, Reason::UnsupportedApplications, + nullptr }; // condition + } + QScopedPointer app(appPad->manager()->startApplication(appPad, c.name, c.creator, c.senders)); + auto descErr = app->setDescription(descriptionEl); + if (descErr == Application::IncompatibleParameters) { + return result { Unsupported, Reason::IncompatibleParameters, nullptr }; + } else if (descErr == Application::Unparsed) { + return result { Unparsed, Reason::Success, nullptr }; + } else { + // same for transport + auto trPad = q->transportPadFactory(transportNS); + if (!trPad) { + return result { + Unsupported, Reason::UnsupportedTransports, app.take() + }; // condition or we can try fallback and fail with + } + auto transport = trPad->manager()->newTransport(trPad, transportEl); + if (transport) { + if (app->setTransport(transport)) { + return result { Ok, Reason::Success, app.take() }; + } + return result { Unsupported, Reason::UnsupportedTransports, app.take() }; + } + } - for (const QDomElement &e: update) { - xml.appendChild(e); + return result { Unparsed, Reason::Success, nullptr }; } - auto jt = new JT(manager->client()->rootTask()); - jt->request(otherParty, xml); - QObject::connect(jt, &JT::finished, q, [jt, jingle, successCB, this](){ - waitingAck = false; - if (jt->success()) { - if (successCB) { - successCB(); - } else { - planStep(); + typedef std::tuple, QList> + ParseContentListResult; + + ParseContentListResult parseContentAddList(const QDomElement &jingleEl) + { + QMap addSet; + QMap> rejectSet; + + QString contentTag(QStringLiteral("content")); + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + + Private::AddContentError err; + Reason::Condition cond; + Application * app; + + std::tie(err, cond, app) = parseContentAdd(ce); + if (err == Private::AddContentError::Unparsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + qDeleteAll(addSet); + return ParseContentListResult(Unparsed, cond, QList(), QList()); + } + + auto contentName = app->contentName(); + auto it = addSet.find(contentName); + if (err != Private::AddContentError::Ok) { + // can't continue as well + if (app) { // we are going to reject it completely so delete + delete app; + } + + if (it == addSet.end()) { + rejectSet.insert(contentName, std::make_pair(ce, cond)); + } + continue; + } + + rejectSet.remove(contentName); + if (it == addSet.end() + || (*it)->wantBetterTransport( + app->transport())) { // probably not wantBetterTransport but wantBetterApplication + if (it == addSet.end()) { + addSet.insert(contentName, app); + } else { + delete *it; // unpreferred app + *it = app; + } } - } else { - lastError = jt->error(); - if (ErrorUtil::jingleCondition(lastError) != ErrorUtil::TieBreak) - setSessionFinished(); - else - planStep(); } - }); - waitingAck = true; - jt->go(true); - } - void planStep() { - if (waitingAck) { - return; - } - lastError = Stanza::Error(0, 0); - if (!stepTimer.isActive()) { - stepTimer.start(); - } - } + if (rejectSet.size()) { + QList rejectList; + for (auto const &i : rejectSet) { + rejectList.append(i.first); + } + return ParseContentListResult(Unsupported, rejectSet.first().second, addSet.values(), rejectList); + } - void doStep() { - if (waitingAck) { // we will return here when ack is received. Session::Unacked is possible also only with waitingAck - return; + return ParseContentListResult(Ok, Reason::Success, addSet.values(), QList()); } - if (terminateReason.condition() && state != State::Finished) { - if (state != State::Created || role == Origin::Responder) { - sendJingle(Action::SessionTerminate, QList() << terminateReason.toXml(manager->client()->doc())); + + std::tuple parseContentAccept(const QDomElement &ce) + { + QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); + QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); + QString descriptionNS = descriptionEl.namespaceURI(); + QString transportNS = transportEl.namespaceURI(); + typedef std::tuple result; + + ContentBase c(ce); + if (!c.isValid() || role != c.creator || descriptionEl.isNull() || transportEl.isNull() + || descriptionNS.isEmpty() || transportNS.isEmpty()) { + return result { Unparsed, Reason::NoReason, nullptr }; } - setSessionFinished(); - return; + + auto app = q->content(c.name, role); + if (!(app && app->state() == State::Pending)) { // reaccept is possible + return result { AddContentError::Unexpected, Reason::NoReason, app }; + } + + if (app->pad()->ns() != descriptionNS || app->transport()->pad()->ns() != transportNS) { + // well it's more than unexpected. let's send unparsed + return result { AddContentError::Unparsed, Reason::NoReason, app }; + } + + if (!app->transport()->update(transportEl) || !app->accept(descriptionEl)) { + // clearly unparsed. otherwise the app will generate failure event with a Reason. + return result { AddContentError::Unparsed, Reason::NoReason, app }; + } + + if (app->state() != State::Accepted) { // parsed but was not accepted. so it's somehow incompatible + return result { AddContentError::Unsupported, Reason::IncompatibleParameters, app }; + } + + return result { AddContentError::Ok, Reason::Success, app }; } - if (state == State::Created || state == State::Finished) { - return; // we will start doing something when initiate() is called + + std::tuple> parseContentAcceptList(const QDomElement &jingleEl) + { + QMap acceptSet; + QMap> rejectSet; + + QString contentTag(QStringLiteral("content")); + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + + Private::AddContentError err; + Reason::Condition cond; + Application * app; + + std::tie(err, cond, app) = parseContentAccept(ce); + if (err == Private::AddContentError::Unparsed || err == Private::AddContentError::Unexpected) { + for (auto &a : acceptSet) { + a->setState(State::Pending); // reset state to pending for already passed validation before + // passing error back + } + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, + err == Private::AddContentError::Unexpected + ? XMPP::Stanza::Error::UnexpectedRequest + : XMPP::Stanza::Error::BadRequest); + if (err == Private::AddContentError::Unexpected) { + ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); + } + return std::tuple>(false, QList()); + } + + auto contentName = app->contentName(); + auto it = acceptSet.find(contentName); + auto rit = rejectSet.find(contentName); + if (it != acceptSet.end() || rit != rejectSet.end()) { + // duplicates are not allowed in accept request + for (auto &a : acceptSet) { + a->setState(State::Pending); // reset state to pending for already passed validation before + // passing error back + } + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return std::tuple>(false, QList()); + } + + if (err != Private::AddContentError::Ok) { + app->setState(State::Finished); // we can't keep working with this content for whatever reason. if + // "accept" failed there is no fallback + rejectSet.insert( + contentName, + std::make_pair(ce, + cond)); // NOTE, probably instead of ce we have to generate original description + continue; + } + acceptSet.insert(contentName, app); + } + + if (rejectSet.size()) { + QTimer::singleShot(0, q, [this, rejectSet]() mutable { + auto cond = rejectSet.first().second; + QList rejects; + for (auto const &i : rejectSet) { + rejects.append(i.first); + } + rejects += Reason(cond).toXml(manager->client()->doc()); + outgoingUpdates.insert(Action::ContentRemove, + OutgoingUpdate { rejects, [this, rejects]() { + for (auto &r : rejects) { + ContentBase c(r); + delete contentList.take(ContentKey { c.name, role }); + } + if (contentList.isEmpty()) { + // the other party has to generate session-terminate + // but we do not care already + setSessionFinished(); + } + } }); + }); + } + return std::tuple>(true, acceptSet.values()); } - if (outgoingUpdates.size()) { - auto it = outgoingUpdates.begin(); - auto action = it.key(); - auto updates = it.value(); - auto elements = std::get<0>(updates); - auto cb = std::get<1>(updates); - outgoingUpdates.erase(it); - sendJingle(action, elements, [this, cb](){ - if (cb) { - cb(); + bool handleIncomingContentAdd(const QDomElement &jingleEl) + { + Private::AddContentError err; + Reason::Condition cond; + QList apps; + QList rejects; + + std::tie(err, cond, apps, rejects) = parseContentAddList(jingleEl); + switch (err) { + case Private::AddContentError::Unparsed: + case Private::AddContentError::Unexpected: + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + if (err == Private::AddContentError::Unexpected) { + ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); } - planStep(); - }); - return; + return false; + case Private::AddContentError::Unsupported: + rejects += Reason(cond).toXml(manager->client()->doc()); + outgoingUpdates.insert(Action::ContentReject, OutgoingUpdate { rejects, OutgoingUpdateCB() }); + break; + case Private::AddContentError::Ok: + break; + } + + if (apps.size()) { + Origin remoteRole = negateOrigin(role); + for (auto app : apps) { + addAndInitContent(remoteRole, app); // TODO check conflicts + } + QTimer::singleShot(0, q, [this]() { emit q->newContentReceived(); }); + } + planStep(); + + return true; } - typedef std::tuple,OutgoingUpdateCB> AckHndl; // will be used from callback on iq ack - if (state == State::PrepareLocalOffer) { // we are going to send session-initiate/accept (already accepted by the user but not sent yet) - /* - * For session-initiate everything is prety much straightforward, just any content with Action::ContentAdd - * update type has to be added. But with session-accept things are more complicated - * 1. Local client could add its content. So we have to check content origin too. - * 2. Remote client could add more content before local session-accept. Then we have two options - * a) send content-accept and skip this content in session-accept later - * b) don't send content-accept and accept everything with session-accept - * We prefer option (b) in our implementation. - */ - Action expectedContentAction = role == Origin::Initiator? Action::ContentAdd : Action::ContentAccept; - for (const auto &c: contentList) { - auto out = c->evaluateOutgoingUpdate(); - if (out == Action::ContentReject) { // yeah we are rejecting local content. invalid? + bool handleIncomingContentRemove(const QDomElement &jingleEl) + { + QSet toRemove; + QString contentTag(QStringLiteral("content")); + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + ContentBase cb(ce); + if (!cb.isValid()) { lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - setSessionFinished(); - return; + return false; } - if (out != expectedContentAction) { - return; // keep waiting. + Application *app = contentList.value(ContentKey { cb.name, cb.creator }); + if (app) { + toRemove.insert(app); } } - Action actionToSend = Action::SessionAccept; - State finalState = State::Active; - // so all contents is ready for session-initiate. let's do it - if (role == Origin::Initiator) { - sid = manager->registerSession(q); - actionToSend = Action::SessionInitiate; - finalState = State::Pending; + + for (auto app : toRemove) { + contentList.remove(ContentKey { app->contentName(), app->creator() }); + delete app; } - QList contents; - QList acceptApps; - for (const auto &p: contentList) { - QList xml; - OutgoingUpdateCB callback; - std::tie(xml, callback) = p->takeOutgoingUpdate(); - contents += xml; - //p->setState(State::Unacked); - if (callback) { - acceptApps.append(AckHndl{p, callback}); - } + if (contentList.isEmpty()) { + auto reasonEl = jingleEl.firstChildElement(QString::fromLatin1("reason")); + terminateReason = reasonEl.isNull() ? Reason(Reason::Success) : Reason(reasonEl); } - state = State::Unacked; - sendJingle(actionToSend, contents, [this, acceptApps, finalState](){ - state = finalState; - for (const auto &h: acceptApps) { - auto app = std::get<0>(h); - auto callback = std::get<1>(h); - if (app) { - callback(); - if (role == Origin::Responder) { - app->start(); - } - } + + planStep(); + return true; + } + + bool handleIncomingSessionTerminate(const QDomElement &jingleEl) + { + terminateReason = Reason(jingleEl.firstChildElement(QString::fromLatin1("reason"))); + setSessionFinished(); + return true; + } + + bool handleIncomingSessionAccept(const QDomElement &jingleEl) + { + bool parsed; + QList apps; + + std::tie(parsed, apps) = parseContentAcceptList(jingleEl); + if (!parsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + + state = State::Connecting; + if (apps.size()) { + for (auto app : apps) { + app->start(); } - if (finalState == State::Active) { - emit q->activated(); + } + QTimer::singleShot(0, q, [this]() { emit q->activated(); }); + planStep(); + + return true; + } + + bool handleIncomingContentAccept(const QDomElement &jingleEl) + { + bool parsed; + QList apps; + + std::tie(parsed, apps) = parseContentAcceptList(jingleEl); // marks valid apps as accepted + if (!parsed) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + + if (apps.size() && state >= State::Active) { + for (auto app : apps) { + app->start(); // start accepted app. connection establishing and data transfer are inside } - planStep(); - }); + } + planStep(); - return; + return true; } - // So session is either in State::Pending or State::Active here. - // State::Connecting status is skipped for session. - QList updateXml; - for (auto mp : applicationPads) { - auto p = mp.toStrongRef(); - QDomElement el = p->takeOutgoingSessionInfoUpdate(); - if (!el.isNull()) { - updateXml.append(el); - // we can send session-info for just one application. so stop processing - sendJingle(Action::SessionInfo, updateXml, [this](){planStep();}); - return; + bool handleIncomingTransportReplace(const QDomElement &jingleEl) + { + QList, QDomElement>> passed; + QList toReject; + QString contentTag(QStringLiteral("content")); + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + ContentBase cb(ce); + auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); + QString transportNS = transportEl.namespaceURI(); + if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + Application *app = contentList.value(ContentKey { cb.name, cb.creator }); + if (!app) { + toReject.append(ce); + continue; + } + + auto trPad = q->transportPadFactory(transportNS); + if (!trPad) { + toReject.append(ce); + continue; + } + + auto transport = trPad->manager()->newTransport(trPad, transportEl); + if (!transport) { + toReject.append(ce); + continue; + } + + auto tfo = app->transportReplaceOrigin(); + // if transport recovery is in progress and I as an inititiator started it then forbid remote + // transport-replace + if (tfo != Origin::None && tfo != q->peerRole() && role == Origin::Initiator) { + lastError = ErrorUtil::makeTieBreak(*manager->client()->doc()); + return false; + } + + passed.append(std::make_tuple(app, transport, ce)); } - } - QMultiMap updates; + for (auto &v : passed) { + Application * app; + QSharedPointer transport; + QDomElement ce; + std::tie(app, transport, ce) = v; + if (!app->incomingTransportReplace( + transport)) { // app should generate transport accept eventually. content-accept will work too + // if the content wasn't accepted yet + toReject.append(ce); + } + } - for (auto app : signalingContent) { - Action updateType = app->evaluateOutgoingUpdate(); - if (updateType != Action::NoAction) { - updates.insert(updateType, app); + if (toReject.size()) { + outgoingUpdates.insert(Action::TransportReject, OutgoingUpdate { toReject, OutgoingUpdateCB() }); } + + planStep(); + return true; } - QList acceptApps; - if (updates.size()) { - Action action = updates.begin().key(); // NOTE maybe some actions have more priority than another - auto apps = updates.values(action); - for (auto app: apps) { - QList xml; - OutgoingUpdateCB callback; - std::tie(xml, callback) = app->takeOutgoingUpdate(); - updateXml += xml; - if (callback) { - acceptApps.append(AckHndl{app, callback}); + bool handleIncomingTransportAccept(const QDomElement &jingleEl) + { + QString contentTag(QStringLiteral("content")); + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + ContentBase cb(ce); + auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); + QString transportNS = transportEl.namespaceURI(); + if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; } - } - sendJingle(action, updateXml, [this, acceptApps](){ - for (const auto &h: acceptApps) { - auto app = std::get<0>(h); - auto callback = std::get<1>(h); - if (app) { - callback(); - } + Application *app = contentList.value(ContentKey { cb.name, cb.creator }); + if (!app || !app->transport() || app->transport()->pad()->ns() != transportNS + || !app->incomingTransportAccept(transportEl)) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; } - planStep(); - }); + } + + planStep(); + return true; } - } - Reason reason(const QDomElement &jingleEl) - { - QDomElement re = jingleEl.firstChildElement(QLatin1String("reason")); - Reason reason; - if(!re.isNull()) { - reason = Reason(re); - if (!reason.isValid()) { - qDebug("invalid reason"); + bool handleIncomingTransportInfo(const QDomElement &jingleEl) + { + QString contentTag(QStringLiteral("content")); + QList, QDomElement>> updates; + for (QDomElement ce = jingleEl.firstChildElement(contentTag); !ce.isNull(); + ce = ce.nextSiblingElement(contentTag)) { + Application *app; + ContentBase cb(ce); + if (!cb.isValid() || !(app = q->content(cb.name, cb.creator)) || app->state() >= State::Finishing + || !app->transport()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + auto tel = ce.firstChildElement(QStringLiteral("transport")); + if (tel.isNull() || tel.namespaceURI() != app->transport()->pad()->ns()) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; + } + updates.append(qMakePair(app->transport(), tel)); } - } - return reason; - } - void addAndInitContent(Origin creator, Application *content) - { - contentList.insert(ContentKey{content->contentName(), creator}, content); - if (state != State::Created && content->evaluateOutgoingUpdate() != Action::NoAction) { - signalingContent.insert(content); - } - QObject::connect(content, &Application::updated, q, [this, content](){ - signalingContent.insert(content); - planStep(); - }); - QObject::connect(content, &Application::destroyed, q, [this, content](){ - signalingContent.remove(content); - for (auto it = contentList.begin(); it != contentList.end(); ++it) { // optimize for large lists? - if (it.value() == content) { - contentList.erase(it); - break; + for (auto &u : updates) { + if (!u.first->update(u.second)) { + lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); + return false; // yes this may lead to half updated content, but what choice do we have? } } - }); - } - enum AddContentError { - Ok, - Unparsed, - Unexpected, - Unsupported + return true; + } }; - std::tuple parseContentAdd(const QDomElement &ce) + Session::Session(Manager *manager, const Jid &peer, Origin role) : d(new Private) { - QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); - QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); - QString descriptionNS = descriptionEl.namespaceURI(); - QString transportNS = transportEl.namespaceURI(); - typedef std::tuple result; - - ContentBase c(ce); - if (!c.isValid() || descriptionEl.isNull() || transportEl.isNull() || descriptionNS.isEmpty() || transportNS.isEmpty()) { - return result{Unparsed, Reason::Success, nullptr}; - } - - auto appPad = q->applicationPadFactory(descriptionNS); - if (!appPad) { - return result{Unsupported, Reason::UnsupportedApplications, nullptr}; // condition - } - QScopedPointer app(appPad->manager()->startApplication(appPad, c.name, c.creator, c.senders)); - auto descErr = app->setDescription(descriptionEl); - if (descErr == Application::IncompatibleParameters) { - return result{Unsupported, Reason::IncompatibleParameters, nullptr}; - } else - if (descErr == Application::Unparsed) { - return result{Unparsed, Reason::Success, nullptr}; - } else - { - // same for transport - auto trPad = q->transportPadFactory(transportNS); - if (!trPad) { - return result{Unsupported, Reason::UnsupportedTransports, app.take()}; // condition or we can try fallback and fail with - } - auto transport = trPad->manager()->newTransport(trPad, transportEl); - if (transport) { - if (app->setTransport(transport)) { - return result{Ok, Reason::Success, app.take()}; - } - return result{Unsupported, Reason::UnsupportedTransports, app.take()}; - } - } + d->q = this; + d->role = role; + d->manager = manager; + d->otherParty = peer; + d->stepTimer.setSingleShot(true); + d->stepTimer.setInterval(0); + connect(&d->stepTimer, &QTimer::timeout, this, [this]() { d->doStep(); }); + } - return result{Unparsed, Reason::Success, nullptr}; + Session::~Session() + { + qDeleteAll(d->contentList); + qDebug("session %s destroyed", qPrintable(d->sid)); } - typedef std::tuple, QList> ParseContentListResult; + Manager *Session::manager() const { return d->manager; } - ParseContentListResult parseContentAddList(const QDomElement &jingleEl) - { - QMap addSet; - QMap> rejectSet; + State Session::state() const { return d->state; } - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { + Jid Session::me() const { return d->manager->client()->jid(); } - Private::AddContentError err; - Reason::Condition cond; - Application *app; + Jid Session::peer() const { return d->otherParty; } - std::tie(err, cond, app) = parseContentAdd(ce); - if (err == Private::AddContentError::Unparsed) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - qDeleteAll(addSet); - return ParseContentListResult(Unparsed, cond, QList(), QList()); - } + Jid Session::initiator() const + { + return d->role == Origin::Initiator ? d->manager->client()->jid() : d->otherParty; + } - auto contentName = app->contentName(); - auto it = addSet.find(contentName); - if (err != Private::AddContentError::Ok) { - // can't continue as well - if (app) { // we are going to reject it completely so delete - delete app; - } + Jid Session::responder() const + { + return d->role == Origin::Responder ? d->manager->client()->jid() : d->otherParty; + } - if (it == addSet.end()) { - rejectSet.insert(contentName, std::make_pair(ce, cond)); - } - continue; - } + QString Session::sid() const { return d->sid; } - rejectSet.remove(contentName); - if (it == addSet.end() || (*it)->wantBetterTransport(app->transport())) { // probably not wantBetterTransport but wantBetterApplication - if (it == addSet.end()) { - addSet.insert(contentName, app); - } else { - delete *it; // unpreferred app - *it = app; - } - } - } + Origin Session::role() const { return d->role; } - if (rejectSet.size()) { - QList rejectList; - for (auto const &i: rejectSet) { - rejectList.append(i.first); - } - return ParseContentListResult(Unsupported, rejectSet.first().second, addSet.values(), rejectList); + Origin Session::peerRole() const { return negateOrigin(d->role); } + + XMPP::Stanza::Error Session::lastError() const { return d->lastError; } + + Application *Session::newContent(const QString &ns, Origin senders) + { + auto pad = applicationPadFactory(ns); + if (pad) { + return pad->manager()->startApplication(pad, pad->generateContentName(senders), d->role, senders); } + return nullptr; + } - return ParseContentListResult(Ok, Reason::Success, addSet.values(), QList()); + Application *Session::content(const QString &contentName, Origin creator) + { + return d->contentList.value(ContentKey { contentName, creator }); } - std::tuple parseContentAccept(const QDomElement &ce) + void Session::addContent(Application *content) { - QDomElement descriptionEl = ce.firstChildElement(QLatin1String("description")); - QDomElement transportEl = ce.firstChildElement(QLatin1String("transport")); - QString descriptionNS = descriptionEl.namespaceURI(); - QString transportNS = transportEl.namespaceURI(); - typedef std::tuple result; - - ContentBase c(ce); - if (!c.isValid() || role != c.creator || descriptionEl.isNull() || transportEl.isNull() || - descriptionNS.isEmpty() || transportNS.isEmpty()) - { - return result{Unparsed, Reason::NoReason, nullptr}; + Q_ASSERT(d->state < State::Finishing); + d->addAndInitContent(d->role, content); + if (d->state >= State::PrepareLocalOffer) { + // If we add content to already initiated session then we are gonna + // send it immediatelly. So start prepare + content->prepare(); } + } - auto app = q->content(c.name, role); - if (!(app && app->state() == State::Pending)) { // reaccept is possible - return result{AddContentError::Unexpected, Reason::NoReason, app}; - } + const QMap &Session::contentList() const { return d->contentList; } - if (app->pad()->ns() != descriptionNS || app->transport()->pad()->ns() != transportNS) { - // well it's more than unexpected. let's send unparsed - return result{AddContentError::Unparsed, Reason::NoReason, app}; - } + ApplicationManagerPad::Ptr Session::applicationPad(const QString &ns) + { + return d->applicationPads.value(ns).toStrongRef(); + } - if (!app->transport()->update(transportEl) || !app->accept(descriptionEl)) { - // clearly unparsed. otherwise the app will generate failure event with a Reason. - return result{AddContentError::Unparsed, Reason::NoReason, app}; - } + TransportManagerPad::Ptr Session::transportPad(const QString &ns) + { + return d->transportPads.value(ns).toStrongRef(); + } - if (app->state() != State::Accepted) { // parsed but was not accepted. so it's somehow incompatible - return result{AddContentError::Unsupported, Reason::IncompatibleParameters, app}; + QSharedPointer Session::newOutgoingTransport(const QString &ns) + { + auto pad = transportPadFactory(ns); + if (pad) { + return pad->manager()->newTransport(pad); // pad on both side becaue we need shared pointer } - - return result{AddContentError::Ok, Reason::Success, app}; + return QSharedPointer(); } - std::tuple> parseContentAcceptList(const QDomElement &jingleEl) + QString Session::preferredApplication() const { - QMap acceptSet; - QMap> rejectSet; + // TODO some heuristics to detect preferred application + if (d->applicationPads.size()) { + return d->applicationPads.constBegin().key(); + } + return QString(); + } - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { + QStringList Session::allApplicationTypes() const { return d->applicationPads.keys(); } - Private::AddContentError err; - Reason::Condition cond; - Application *app; + void Session::setLocalJid(const Jid &jid) { d->localParty = jid; } - std::tie(err, cond, app) = parseContentAccept(ce); - if (err == Private::AddContentError::Unparsed || err == Private::AddContentError::Unexpected) { - for (auto &a: acceptSet) { - a->setState(State::Pending); // reset state to pending for already passed validation before passing error back - } - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, err == Private::AddContentError::Unexpected? - XMPP::Stanza::Error::UnexpectedRequest : XMPP::Stanza::Error::BadRequest); - if (err == Private::AddContentError::Unexpected) { - ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); - } - return std::tuple>(false, QList()); + void Session::accept() + { + // So we presented a user incoming session in UI, the user modified it somehow and finally accepted. + if (d->role == Origin::Responder && d->state == State::Created) { + d->state = State::PrepareLocalOffer; + for (auto &c : d->contentList) { + c->prepare(); } + d->planStep(); + } + } - auto contentName = app->contentName(); - auto it = acceptSet.find(contentName); - auto rit = rejectSet.find(contentName); - if (it != acceptSet.end() || rit != rejectSet.end()) { - // duplicates are not allowed in accept request - for (auto &a: acceptSet) { - a->setState(State::Pending); // reset state to pending for already passed validation before passing error back - } - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return std::tuple>(false, QList()); + void Session::initiate() + { + emit initiated(); + if (d->role == Origin::Initiator && d->state == State::Created) { + d->state = State::PrepareLocalOffer; + for (auto &c : d->contentList) { + c->prepare(); } + d->planStep(); + } + } + + void Session::terminate(Reason::Condition cond, const QString &comment) + { + if (d->role == Origin::Initiator && d->state == State::PrepareLocalOffer) { + d->setSessionFinished(); + return; + } + d->state = State::Finishing; + d->terminateReason = Reason(cond, comment); + d->planStep(); + } - if (err != Private::AddContentError::Ok) { - app->setState(State::Finished); // we can't keep working with this content for whatever reason. if "accept" failed there is no fallback - rejectSet.insert(contentName, std::make_pair(ce, cond)); // NOTE, probably instead of ce we have to generate original description - continue; + TransportManagerPad::Ptr Session::transportPadFactory(const QString &ns) + { + auto pad = d->transportPads.value(ns).toStrongRef(); + if (!pad) { + auto deleter = [ns, this](TransportManagerPad *pad) { + d->transportPads.remove(ns); + delete pad; + }; + pad = TransportManagerPad::Ptr(d->manager->transportPad(this, ns), deleter); + if (pad) { + d->transportPads.insert(ns, pad); } - acceptSet.insert(contentName, app); } + return pad; + } - if (rejectSet.size()) { - QTimer::singleShot(0, q, [this, rejectSet]() mutable { - auto cond = rejectSet.first().second; - QList rejects; - for (auto const &i: rejectSet) { - rejects.append(i.first); - } - rejects += Reason(cond).toXml(manager->client()->doc()); - outgoingUpdates.insert( - Action::ContentRemove, - OutgoingUpdate{ - rejects, - [this, rejects]() { - for (auto &r: rejects) { - ContentBase c(r); - delete contentList.take(ContentKey{c.name, role}); - } - if (contentList.isEmpty()) { - // the other party has to generate session-terminate but we do not care already - setSessionFinished(); - } - } - }); - }); + ApplicationManagerPad::Ptr Session::applicationPadFactory(const QString &ns) + { + auto pad = d->applicationPads.value(ns).toStrongRef(); + if (!pad) { + auto deleter = [ns, this](ApplicationManagerPad *pad) { + d->applicationPads.remove(ns); + delete pad; + }; + pad = ApplicationManagerPad::Ptr(d->manager->applicationPad(this, ns), deleter); + if (pad) { + d->applicationPads.insert(ns, pad); + } } - return std::tuple>(true, acceptSet.values()); + return pad; } - bool handleIncomingContentAdd(const QDomElement &jingleEl) + bool Session::incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl) { + d->sid = jingle.sid(); + d->origFrom = d->otherParty; + if (jingle.initiator().isValid() && !jingle.initiator().compare(d->origFrom)) { + d->otherParty = jingle.initiator(); + } + Private::AddContentError err; - Reason::Condition cond; - QList apps; - QList rejects; + Reason::Condition cond; + QList apps; + QList rejects; - std::tie(err, cond, apps, rejects) = parseContentAddList(jingleEl); + std::tie(err, cond, apps, rejects) = d->parseContentAddList(jingleEl); switch (err) { case Private::AddContentError::Unparsed: case Private::AddContentError::Unexpected: - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - if (err == Private::AddContentError::Unexpected) { - ErrorUtil::fill(jingleEl.ownerDocument(), lastError, ErrorUtil::OutOfOrder); - } return false; case Private::AddContentError::Unsupported: - rejects += Reason(cond).toXml(manager->client()->doc()); - outgoingUpdates.insert(Action::ContentReject, OutgoingUpdate{rejects, OutgoingUpdateCB()}); - break; + d->terminateReason = Reason(cond); + d->planStep(); + return true; case Private::AddContentError::Ok: - break; - } - - if (apps.size()) { - Origin remoteRole = negateOrigin(role); - for (auto app: apps) { - addAndInitContent(remoteRole, app); // TODO check conflicts + for (auto app : apps) { + d->addAndInitContent(Origin::Initiator, app); } - QTimer::singleShot(0, q, [this](){ emit q->newContentReceived(); }); + d->planStep(); + return true; } - planStep(); - return true; + return false; } - bool handleIncomingContentRemove(const QDomElement &jingleEl) + bool Session::updateFromXml(Action action, const QDomElement &jingleEl) { - QSet toRemove; - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { - ContentBase cb(ce); - if (!cb.isValid()) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - Application *app = contentList.value(ContentKey{cb.name, cb.creator}); - if (app) { - toRemove.insert(app); - } - } - - for (auto app: toRemove) { - contentList.remove(ContentKey{app->contentName(), app->creator()}); - delete app; + if (d->state == State::Finished) { + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); + ErrorUtil::fill(jingleEl.ownerDocument(), d->lastError, ErrorUtil::OutOfOrder); + return false; } - if (contentList.isEmpty()) { - auto reasonEl = jingleEl.firstChildElement(QString::fromLatin1("reason")); - terminateReason = reasonEl.isNull()? Reason(Reason::Success) : Reason(reasonEl); + switch (action) { + case Action::ContentAccept: + return d->handleIncomingContentAccept(jingleEl); + case Action::ContentAdd: + return d->handleIncomingContentAdd(jingleEl); + case Action::ContentModify: + break; + case Action::ContentReject: + break; + case Action::ContentRemove: + return d->handleIncomingContentRemove(jingleEl); + case Action::DescriptionInfo: + break; + case Action::SecurityInfo: + break; + case Action::SessionAccept: + return d->handleIncomingSessionAccept(jingleEl); + case Action::SessionInfo: + break; + case Action::SessionInitiate: // impossible case. but let compiler be happy + break; + case Action::SessionTerminate: + return d->handleIncomingSessionTerminate(jingleEl); + case Action::TransportAccept: + return d->handleIncomingTransportAccept(jingleEl); + case Action::TransportInfo: + return d->handleIncomingTransportInfo(jingleEl); + case Action::TransportReject: + break; + case Action::TransportReplace: + return d->handleIncomingTransportReplace(jingleEl); + case Action::NoAction: + default: + break; } - planStep(); - return true; + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::FeatureNotImplemented); + return false; } - bool handleIncomingSessionTerminate(const QDomElement &jingleEl) + //---------------------------------------------------------------------------- + // SessionManagerPad - handle event related to a type of app/transport but not specific instance + //---------------------------------------------------------------------------- + QDomElement SessionManagerPad::takeOutgoingSessionInfoUpdate() { return QDomElement(); } + + QDomDocument *SessionManagerPad::doc() const { return session()->manager()->client()->doc(); } + + //---------------------------------------------------------------------------- + // Manager + //---------------------------------------------------------------------------- + class Manager::Private { + public: + XMPP::Client * client; + Manager * manager; + QScopedPointer pushTask; + // ns -> application + QMap> applicationManagers; + // ns -> parser function + QMap> transportManagers; + std::function remoteJidCecker; + + // when set/valid any incoming session initiate will be replied with redirection error + Jid redirectionJid; + XMPP::Stanza::Error lastError; + QHash, Session *> sessions; + int maxSessions = -1; // no limit + + void setupSession(Session *s) + { + QObject::connect(s, &Session::terminated, manager, + [this, s]() { sessions.remove(qMakePair(s->peer(), s->sid())); }); + } + }; + + Manager::Manager(Client *client) : QObject(client), d(new Private()) { - terminateReason = Reason(jingleEl.firstChildElement(QString::fromLatin1("reason"))); - setSessionFinished(); - return true; + d->client = client; + d->manager = this; + d->pushTask.reset(new JTPush(client->rootTask())); } - bool handleIncomingSessionAccept(const QDomElement &jingleEl) + Manager::~Manager() { - bool parsed; - QList apps; - - std::tie(parsed, apps) = parseContentAcceptList(jingleEl); - if (!parsed) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; + for (auto &m : d->transportManagers) { + m->setJingleManager(nullptr); } - - state = State::Connecting; - if (apps.size()) { - for (auto app: apps) { - app->start(); - } + for (auto &m : d->applicationManagers) { + m->setJingleManager(nullptr); } - QTimer::singleShot(0, q, [this](){ emit q->activated(); }); - planStep(); - - return true; } - bool handleIncomingContentAccept(const QDomElement &jingleEl) - { - bool parsed; - QList apps; - - std::tie(parsed, apps) = parseContentAcceptList(jingleEl); // marks valid apps as accepted - if (!parsed) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } + Client *Manager::client() const { return d->client; } - if (apps.size() && state >= State::Active) { - for (auto app: apps) { - app->start(); // start accepted app. connection establishing and data transfer are inside - } - } - planStep(); + void Manager::addExternalManager(const QString &ns) { d->pushTask->addExternalManager(ns); } - return true; - } + void Manager::registerExternalSession(const QString &sid) { d->pushTask->registerExternalSession(sid); } - bool handleIncomingTransportReplace(const QDomElement &jingleEl) - { - QList,QDomElement>> passed; - QList toReject; - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { - ContentBase cb(ce); - auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); - QString transportNS = transportEl.namespaceURI(); - if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - Application *app = contentList.value(ContentKey{cb.name, cb.creator}); - if (!app) { - toReject.append(ce); - continue; - } + void Manager::forgetExternalSession(const QString &sid) { d->pushTask->forgetExternalSession(sid); } - auto trPad = q->transportPadFactory(transportNS); - if (!trPad) { - toReject.append(ce); - continue; - } + void Manager::setRedirection(const Jid &to) { d->redirectionJid = to; } - auto transport = trPad->manager()->newTransport(trPad, transportEl); - if (!transport) { - toReject.append(ce); - continue; - } + const Jid &Manager::redirectionJid() const { return d->redirectionJid; } - auto tfo = app->transportReplaceOrigin(); - // if transport recovery is in progress and I as an inititiator started it then forbid remote transport-replace - if (tfo != Origin::None && tfo != q->peerRole() && role == Origin::Initiator) { - lastError = ErrorUtil::makeTieBreak(*manager->client()->doc()); - return false; - } + void Manager::registerApp(const QString &ns, ApplicationManager *app) + { + d->applicationManagers.insert(ns, app); + app->setJingleManager(this); + } - passed.append(std::make_tuple(app, transport, ce)); + void Manager::unregisterApp(const QString &ns) + { + auto appManager = d->applicationManagers.value(ns); + if (appManager) { + appManager->closeAll(); + d->applicationManagers.remove(ns); } + } - for (auto &v: passed) { - Application *app; - QSharedPointer transport; - QDomElement ce; - std::tie(app,transport,ce) = v; - if (!app->incomingTransportReplace(transport)) { // app should generate transport accept eventually. content-accept will work too if the content wasn't accepted yet - toReject.append(ce); - } - } + bool Manager::isRegisteredApplication(const QString &ns) { return d->applicationManagers.contains(ns); } - if (toReject.size()) { - outgoingUpdates.insert(Action::TransportReject, OutgoingUpdate{toReject,OutgoingUpdateCB()}); + ApplicationManagerPad *Manager::applicationPad(Session *session, const QString &ns) + { + auto am = d->applicationManagers.value(ns); + if (!am) { + return nullptr; } - - planStep(); - return true; + return am->pad(session); } - bool handleIncomingTransportAccept(const QDomElement &jingleEl) + void Manager::registerTransport(const QString &ns, TransportManager *transport) { - QString contentTag(QStringLiteral("content")); - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { - ContentBase cb(ce); - auto transportEl = ce.firstChildElement(QString::fromLatin1("transport")); - QString transportNS = transportEl.namespaceURI(); - if (!cb.isValid() || transportEl.isNull() || transportNS.isEmpty()) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - Application *app = contentList.value(ContentKey{cb.name, cb.creator}); - if (!app || !app->transport() || app->transport()->pad()->ns() != transportNS || !app->incomingTransportAccept(transportEl)) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - } - - planStep(); - return true; + d->transportManagers.insert(ns, transport); + transport->setJingleManager(this); } - bool handleIncomingTransportInfo(const QDomElement &jingleEl) + void Manager::unregisterTransport(const QString &ns) { - QString contentTag(QStringLiteral("content")); - QList,QDomElement>> updates; - for(QDomElement ce = jingleEl.firstChildElement(contentTag); - !ce.isNull(); ce = ce.nextSiblingElement(contentTag)) - { - Application *app; - ContentBase cb(ce); - if (!cb.isValid() || !(app = q->content(cb.name, cb.creator)) || app->state() >= State::Finishing || !app->transport()) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - auto tel = ce.firstChildElement(QStringLiteral("transport")); - if (tel.isNull() || tel.namespaceURI() != app->transport()->pad()->ns()) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; - } - updates.append(qMakePair(app->transport(), tel)); + auto trManager = d->transportManagers.value(ns); + if (trManager) { + trManager->closeAll(); + d->transportManagers.remove(ns); } + } - for (auto &u: updates) { - if (!u.first->update(u.second)) { - lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::BadRequest); - return false; // yes this may lead to half updated content, but what choice do we have? - } - } + bool Manager::isRegisteredTransport(const QString &ns) { return d->transportManagers.contains(ns); } - return true; - } -}; - -Session::Session(Manager *manager, const Jid &peer, Origin role) : - d(new Private) -{ - d->q = this; - d->role = role; - d->manager = manager; - d->otherParty = peer; - d->stepTimer.setSingleShot(true); - d->stepTimer.setInterval(0); - connect(&d->stepTimer, &QTimer::timeout, this, [this](){ d->doStep();}); - -} - -Session::~Session() -{ - qDeleteAll(d->contentList); - qDebug("session %s destroyed", qPrintable(d->sid)); -} - -Manager *Session::manager() const -{ - return d->manager; -} - -State Session::state() const -{ - return d->state; -} - -Jid Session::me() const -{ - return d->manager->client()->jid(); -} - -Jid Session::peer() const -{ - return d->otherParty; -} - -Jid Session::initiator() const -{ - return d->role == Origin::Initiator? d->manager->client()->jid() : d->otherParty; -} - -Jid Session::responder() const -{ - return d->role == Origin::Responder? d->manager->client()->jid() : d->otherParty; -} - -QString Session::sid() const -{ - return d->sid; -} - -Origin Session::role() const -{ - return d->role; -} - -Origin Session::peerRole() const -{ - return negateOrigin(d->role); -} - -XMPP::Stanza::Error Session::lastError() const -{ - return d->lastError; -} - -Application *Session::newContent(const QString &ns, Origin senders) -{ - auto pad = applicationPadFactory(ns); - if (pad) { - return pad->manager()->startApplication(pad, pad->generateContentName(senders), d->role, senders); - } - return nullptr; -} - -Application *Session::content(const QString &contentName, Origin creator) -{ - return d->contentList.value(ContentKey{contentName, creator}); -} - -void Session::addContent(Application *content) -{ - Q_ASSERT(d->state < State::Finishing); - d->addAndInitContent(d->role, content); - if (d->state >= State::PrepareLocalOffer) { - // If we add content to already initiated session then we are gonna - // send it immediatelly. So start prepare - content->prepare(); - } -} - -const QMap &Session::contentList() const -{ - return d->contentList; -} - -ApplicationManagerPad::Ptr Session::applicationPad(const QString &ns) -{ - return d->applicationPads.value(ns).toStrongRef(); -} - -TransportManagerPad::Ptr Session::transportPad(const QString &ns) -{ - return d->transportPads.value(ns).toStrongRef(); -} - -QSharedPointer Session::newOutgoingTransport(const QString &ns) -{ - auto pad = transportPadFactory(ns); - if (pad) { - return pad->manager()->newTransport(pad); // pad on both side becaue we need shared pointer - } - return QSharedPointer(); -} - -QString Session::preferredApplication() const -{ - // TODO some heuristics to detect preferred application - if (d->applicationPads.size()) { - return d->applicationPads.constBegin().key(); - } - return QString(); -} - -QStringList Session::allApplicationTypes() const -{ - return d->applicationPads.keys(); -} - -void Session::setLocalJid(const Jid &jid) -{ - d->localParty = jid; -} - -void Session::accept() -{ - // So we presented a user incoming session in UI, the user modified it somehow and finally accepted. - if (d->role == Origin::Responder && d->state == State::Created) { - d->state = State::PrepareLocalOffer; - for (auto &c: d->contentList) { - c->prepare(); + bool Manager::isAllowedParty(const Jid &jid) const + { + if (d->remoteJidCecker) { + return d->remoteJidCecker(jid); } - d->planStep(); + // REVIEW probably we can check Client's internal roster when checker is not set. + return true; } -} -void Session::initiate() -{ - emit initiated(); - if (d->role == Origin::Initiator && d->state == State::Created) { - d->state = State::PrepareLocalOffer; - for (auto &c: d->contentList) { - c->prepare(); - } - d->planStep(); + Session *Manager::session(const Jid &remoteJid, const QString &sid) + { + return d->sessions.value(qMakePair(remoteJid, sid)); } -} -void Session::terminate(Reason::Condition cond, const QString &comment) -{ - if (d->role == Origin::Initiator && d->state == State::PrepareLocalOffer) { - d->setSessionFinished(); - return; + void Manager::detachSession(Session *s) + { + s->disconnect(this); + d->sessions.remove(qMakePair(s->peer(), s->sid())); } - d->state = State::Finishing; - d->terminateReason = Reason(cond, comment); - d->planStep(); -} - -TransportManagerPad::Ptr Session::transportPadFactory(const QString &ns) -{ - auto pad = d->transportPads.value(ns).toStrongRef(); - if (!pad) { - auto deleter = [ns, this](TransportManagerPad *pad){ - d->transportPads.remove(ns); - delete pad; - }; - pad = TransportManagerPad::Ptr(d->manager->transportPad(this, ns), deleter); - if (pad) { - d->transportPads.insert(ns, pad); + + void Manager::setRemoteJidChecker(std::function checker) { d->remoteJidCecker = checker; } + + TransportManagerPad *Manager::transportPad(Session *session, const QString &ns) + { + auto transportManager = d->transportManagers.value(ns); + if (!transportManager) { + return nullptr; } + return transportManager->pad(session); } - return pad; -} - -ApplicationManagerPad::Ptr Session::applicationPadFactory(const QString &ns) -{ - auto pad = d->applicationPads.value(ns).toStrongRef(); - if (!pad) { - auto deleter = [ns, this](ApplicationManagerPad *pad){ - d->applicationPads.remove(ns); - delete pad; - }; - pad = ApplicationManagerPad::Ptr(d->manager->applicationPad(this, ns), deleter); - if (pad) { - d->applicationPads.insert(ns, pad); + + QStringList Manager::availableTransports(const Transport::Features &features) const + { + QStringList ret; + for (auto it = d->transportManagers.cbegin(); it != d->transportManagers.cend(); ++it) { + if (((*it)->features() & features) == features) { + ret.append(it.key()); + } } + return ret; } - return pad; -} - -bool Session::incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl) -{ - d->sid = jingle.sid(); - d->origFrom = d->otherParty; - if (jingle.initiator().isValid() && !jingle.initiator().compare(d->origFrom)) { - d->otherParty = jingle.initiator(); - } - - Private::AddContentError err; - Reason::Condition cond; - QList apps; - QList rejects; - std::tie(err, cond, apps, rejects) = d->parseContentAddList(jingleEl); - switch (err) { - case Private::AddContentError::Unparsed: - case Private::AddContentError::Unexpected: - return false; - case Private::AddContentError::Unsupported: - d->terminateReason = Reason(cond); - d->planStep(); - return true; - case Private::AddContentError::Ok: - for (auto app: apps) { - d->addAndInitContent(Origin::Initiator, app); - } - d->planStep(); - return true; + Session *Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, const QDomElement &jingleEl) + { + if (d->maxSessions > 0 && d->sessions.size() == d->maxSessions) { + d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Wait, XMPP::Stanza::Error::ResourceConstraint); + return nullptr; + } + auto key = qMakePair(from, jingle.sid()); + auto s = new Session(this, from, Origin::Responder); + if (s->incomingInitiate(jingle, jingleEl)) { // if parsed well + d->sessions.insert(key, s); + d->setupSession(s); + // emit incomingSession makes sense when there are no unsolved conflicts in content descriptions / + // transports + // QTimer::singleShot(0,[s, this](){ emit incomingSession(s); }); + QMetaObject::invokeMethod(this, "incomingSession", Qt::QueuedConnection, Q_ARG(Session *, s)); + return s; + } + d->lastError = s->lastError(); + delete s; + return nullptr; } - return false; -} + XMPP::Stanza::Error Manager::lastError() const { return d->lastError; } -bool Session::updateFromXml(Action action, const QDomElement &jingleEl) -{ - if (d->state == State::Finished) { - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); - ErrorUtil::fill(jingleEl.ownerDocument(), d->lastError, ErrorUtil::OutOfOrder); - return false; + Session *Manager::newSession(const Jid &j) + { + auto s = new Session(this, j); + d->setupSession(s); + return s; } - switch (action) { - case Action::ContentAccept: - return d->handleIncomingContentAccept(jingleEl); - case Action::ContentAdd: - return d->handleIncomingContentAdd(jingleEl); - case Action::ContentModify: - break; - case Action::ContentReject: - break; - case Action::ContentRemove: - return d->handleIncomingContentRemove(jingleEl); - case Action::DescriptionInfo: - break; - case Action::SecurityInfo: - break; - case Action::SessionAccept: - return d->handleIncomingSessionAccept(jingleEl); - case Action::SessionInfo: - break; - case Action::SessionInitiate: // impossible case. but let compiler be happy - break; - case Action::SessionTerminate: - return d->handleIncomingSessionTerminate(jingleEl); - case Action::TransportAccept: - return d->handleIncomingTransportAccept(jingleEl); - case Action::TransportInfo: - return d->handleIncomingTransportInfo(jingleEl); - case Action::TransportReject: - break; - case Action::TransportReplace: - return d->handleIncomingTransportReplace(jingleEl); - case Action::NoAction: - default: - break; + QString Manager::registerSession(Session *session) + { + QString id; + auto peer = session->peer(); + do { + id = QString("%1").arg(quint32(qrand()), 6, 32, QChar('0')); + } while (d->sessions.contains(qMakePair(peer, id))); + d->sessions.insert(qMakePair(peer, id), session); + return id; } - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::FeatureNotImplemented); - return false; -} - -//---------------------------------------------------------------------------- -// SessionManagerPad - handle event related to a type of app/transport but not specific instance -//---------------------------------------------------------------------------- -QDomElement SessionManagerPad::takeOutgoingSessionInfoUpdate() -{ - return QDomElement(); -} - -QDomDocument *SessionManagerPad::doc() const -{ - return session()->manager()->client()->doc(); -} - -//---------------------------------------------------------------------------- -// Manager -//---------------------------------------------------------------------------- -class Manager::Private -{ -public: - XMPP::Client *client; - Manager *manager; - QScopedPointer pushTask; - // ns -> application - QMap> applicationManagers; - // ns -> parser function - QMap> transportManagers; - std::function remoteJidCecker; - - // when set/valid any incoming session initiate will be replied with redirection error - Jid redirectionJid; - XMPP::Stanza::Error lastError; - QHash,Session*> sessions; - int maxSessions = -1; // no limit - - void setupSession(Session *s) + Origin negateOrigin(Origin o) { - QObject::connect(s, &Session::terminated, manager, [this, s](){ - sessions.remove(qMakePair(s->peer(), s->sid())); - }); - } -}; - -Manager::Manager(Client *client) : - QObject(client), - d(new Private()) -{ - d->client = client; - d->manager = this; - d->pushTask.reset(new JTPush(client->rootTask())); -} - -Manager::~Manager() -{ - for (auto &m: d->transportManagers) { - m->setJingleManager(nullptr); - } - for (auto &m: d->applicationManagers) { - m->setJingleManager(nullptr); - } -} - -Client *Manager::client() const -{ - return d->client; -} - -void Manager::addExternalManager(const QString &ns) -{ - d->pushTask->addExternalManager(ns); -} - -void Manager::registerExternalSession(const QString &sid) -{ - d->pushTask->registerExternalSession(sid); -} - -void Manager::forgetExternalSession(const QString &sid) -{ - d->pushTask->forgetExternalSession(sid); -} - -void Manager::setRedirection(const Jid &to) -{ - d->redirectionJid = to; -} - -const Jid &Manager::redirectionJid() const -{ - return d->redirectionJid; -} - -void Manager::registerApp(const QString &ns, ApplicationManager *app) -{ - d->applicationManagers.insert(ns, app); - app->setJingleManager(this); -} - -void Manager::unregisterApp(const QString &ns) -{ - auto appManager = d->applicationManagers.value(ns); - if (appManager) { - appManager->closeAll(); - d->applicationManagers.remove(ns); + switch (o) { + case Origin::None: + return Origin::Both; + case Origin::Both: + return Origin::None; + case Origin::Initiator: + return Origin::Responder; + case Origin::Responder: + return Origin::Initiator; + } + return Origin::None; } -} -bool Manager::isRegisteredApplication(const QString &ns) -{ - return d->applicationManagers.contains(ns); -} + bool Connection::hasPendingDatagrams() const { return false; } -ApplicationManagerPad *Manager::applicationPad(Session *session, const QString &ns) -{ - auto am = d->applicationManagers.value(ns); - if (!am) { - return nullptr; + NetworkDatagram Connection::receiveDatagram(qint64 maxSize) + { + Q_UNUSED(maxSize) + return NetworkDatagram(); } - return am->pad(session); -} - -void Manager::registerTransport(const QString &ns, TransportManager *transport) -{ - d->transportManagers.insert(ns, transport); - transport->setJingleManager(this); -} - -void Manager::unregisterTransport(const QString &ns) -{ - auto trManager = d->transportManagers.value(ns); - if (trManager) { - trManager->closeAll(); - d->transportManagers.remove(ns); + + size_t Connection::blockSize() const + { + return 0; // means "block" is not applicable for this kind of connection } -} -bool Manager::isRegisteredTransport(const QString &ns) -{ - return d->transportManagers.contains(ns); -} + const char *ErrorUtil::names[ErrorUtil::Last] + = { "out-of-order", "tie-break", "unknown-session", "unsupported-info" }; -bool Manager::isAllowedParty(const Jid &jid) const -{ - if (d->remoteJidCecker) { - return d->remoteJidCecker(jid); + Stanza::Error ErrorUtil::make(QDomDocument &doc, int jingleCond, int type, int condition, const QString &text) + { + auto el = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); + return Stanza::Error(type, condition, text, el); } - // REVIEW probably we can check Client's internal roster when checker is not set. - return true; -} - -Session *Manager::session(const Jid &remoteJid, const QString &sid) -{ - return d->sessions.value(qMakePair(remoteJid, sid)); -} - -void Manager::detachSession(Session *s) -{ - s->disconnect(this); - d->sessions.remove(qMakePair(s->peer(), s->sid())); -} - -void Manager::setRemoteJidChecker(std::function checker) -{ - d->remoteJidCecker = checker; -} - -TransportManagerPad* Manager::transportPad(Session *session, const QString &ns) -{ - auto transportManager = d->transportManagers.value(ns); - if (!transportManager) { - return nullptr; + + void ErrorUtil::fill(QDomDocument doc, Stanza::Error &error, int jingleCond) + { + error.appSpec = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); } - return transportManager->pad(session); -} -QStringList Manager::availableTransports(const Transport::Features &features) const -{ - QStringList ret; - for (auto it = d->transportManagers.cbegin(); it != d->transportManagers.cend(); ++it) { - if (((*it)->features() & features) == features) { - ret.append(it.key()); + int ErrorUtil::jingleCondition(const Stanza::Error &error) + { + if (error.appSpec.namespaceURI() != ERROR_NS) { + return UnknownError; + } + QString tagName = error.appSpec.tagName(); + for (int i = 0; i < int(sizeof(names) / sizeof(names[0])); ++i) { + if (tagName == names[i]) { + return i + 1; + } } + return UnknownError; } - return ret; -} -Session* Manager::incomingSessionInitiate(const Jid &from, const Jingle &jingle, const QDomElement &jingleEl) -{ - if (d->maxSessions > 0 && d->sessions.size() == d->maxSessions) { - d->lastError = XMPP::Stanza::Error(XMPP::Stanza::Error::Wait, XMPP::Stanza::Error::ResourceConstraint); - return nullptr; - } - auto key = qMakePair(from, jingle.sid()); - auto s = new Session(this, from, Origin::Responder); - if (s->incomingInitiate(jingle, jingleEl)) { // if parsed well - d->sessions.insert(key, s); - d->setupSession(s); - // emit incomingSession makes sense when there are no unsolved conflicts in content descriptions / transports - //QTimer::singleShot(0,[s, this](){ emit incomingSession(s); }); - QMetaObject::invokeMethod(this, "incomingSession", Qt::QueuedConnection, Q_ARG(Session*, s)); - return s; - } - d->lastError = s->lastError(); - delete s; - return nullptr; -} - -XMPP::Stanza::Error Manager::lastError() const -{ - return d->lastError; -} - -Session *Manager::newSession(const Jid &j) -{ - auto s = new Session(this, j); - d->setupSession(s); - return s; -} - -QString Manager::registerSession(Session *session) -{ - QString id; - auto peer = session->peer(); - do { - id = QString("%1").arg(quint32(qrand()), 6, 32, QChar('0')); - } while (d->sessions.contains(qMakePair(peer,id))); - d->sessions.insert(qMakePair(peer, id), session); - return id; -} - -Origin negateOrigin(Origin o) -{ - switch (o) { - case Origin::None: return Origin::Both; - case Origin::Both: return Origin::None; - case Origin::Initiator: return Origin::Responder; - case Origin::Responder: return Origin::Initiator; - } - return Origin::None; -} - -bool Connection::hasPendingDatagrams() const -{ - return false; -} - -NetworkDatagram Connection::receiveDatagram(qint64 maxSize) -{ - Q_UNUSED(maxSize) - return NetworkDatagram(); -} - -size_t Connection::blockSize() const -{ - return 0; // means "block" is not applicable for this kind of connection -} - -const char* ErrorUtil::names[ErrorUtil::Last] = {"out-of-order","tie-break", "unknown-session", "unsupported-info"}; - -Stanza::Error ErrorUtil::make(QDomDocument &doc, int jingleCond, int type, int condition, const QString &text) -{ - auto el = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); - return Stanza::Error(type, condition, text, el); -} - -void ErrorUtil::fill(QDomDocument doc, Stanza::Error &error, int jingleCond) -{ - error.appSpec = doc.createElementNS(ERROR_NS, QString::fromLatin1(names[jingleCond - 1])); -} - -int ErrorUtil::jingleCondition(const Stanza::Error &error) -{ - if (error.appSpec.namespaceURI() != ERROR_NS) { - return UnknownError; + Stanza::Error ErrorUtil::makeTieBreak(QDomDocument &doc) + { + return make(doc, TieBreak, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::Conflict); } - QString tagName = error.appSpec.tagName(); - for (int i = 0; i < int(sizeof(names) / sizeof(names[0])); ++i) { - if (tagName == names[i]) { - return i + 1; - } + + Stanza::Error ErrorUtil::makeOutOfOrder(QDomDocument &doc) + { + return make(doc, OutOfOrder, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); } - return UnknownError; -} - -Stanza::Error ErrorUtil::makeTieBreak(QDomDocument &doc) -{ - return make(doc, TieBreak, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::Conflict); -} - -Stanza::Error ErrorUtil::makeOutOfOrder(QDomDocument &doc) -{ - return make(doc, OutOfOrder, XMPP::Stanza::Error::Cancel, XMPP::Stanza::Error::UnexpectedRequest); -} } // namespace Jingle } // namespace XMPP From 7805139e58d34368883f40b2dae3be69c4fc4a20 Mon Sep 17 00:00:00 2001 From: Sergey Ilinykh Date: Sun, 13 Oct 2019 14:27:03 +0300 Subject: [PATCH 105/383] reformat iris with clang-format --- src/irisnet/appledns/appledns.cpp | 495 ++- src/irisnet/appledns/qdnssd.cpp | 682 ++--- src/irisnet/appledns/qdnssd.h | 70 +- src/irisnet/appledns/sdtest.cpp | 282 +- src/irisnet/corelib/addressresolver.cpp | 89 +- src/irisnet/corelib/addressresolver.h | 8 +- src/irisnet/corelib/irisnetexport.h | 12 +- src/irisnet/corelib/irisnetglobal.cpp | 132 +- src/irisnet/corelib/irisnetglobal_p.h | 2 +- src/irisnet/corelib/irisnetplugin.cpp | 40 +- src/irisnet/corelib/irisnetplugin.h | 118 +- src/irisnet/corelib/netavailability.cpp | 20 +- src/irisnet/corelib/netavailability.h | 3 +- src/irisnet/corelib/netinterface.cpp | 177 +- src/irisnet/corelib/netinterface.h | 37 +- src/irisnet/corelib/netinterface_qtname.cpp | 112 +- src/irisnet/corelib/netinterface_qtnet.cpp | 36 +- src/irisnet/corelib/netinterface_unix.cpp | 97 +- src/irisnet/corelib/netnames.cpp | 859 +++--- src/irisnet/corelib/netnames.h | 208 +- src/irisnet/corelib/netnames_jdns.cpp | 1368 ++++----- src/irisnet/corelib/objectsession.cpp | 169 +- src/irisnet/corelib/objectsession.h | 40 +- src/irisnet/noncore/cutestuff/bsocket.cpp | 259 +- src/irisnet/noncore/cutestuff/bsocket.h | 25 +- src/irisnet/noncore/cutestuff/bytestream.cpp | 110 +- src/irisnet/noncore/cutestuff/bytestream.h | 37 +- src/irisnet/noncore/cutestuff/httpconnect.cpp | 152 +- src/irisnet/noncore/cutestuff/httpconnect.h | 12 +- src/irisnet/noncore/cutestuff/httppoll.cpp | 527 ++-- src/irisnet/noncore/cutestuff/httppoll.h | 51 +- src/irisnet/noncore/cutestuff/socks.cpp | 509 ++- src/irisnet/noncore/cutestuff/socks.h | 43 +- src/irisnet/noncore/ice176.cpp | 804 ++--- src/irisnet/noncore/ice176.h | 83 +- src/irisnet/noncore/icecomponent.cpp | 638 ++-- src/irisnet/noncore/icecomponent.h | 65 +- src/irisnet/noncore/icelocaltransport.cpp | 446 +-- src/irisnet/noncore/icelocaltransport.h | 26 +- src/irisnet/noncore/icetransport.cpp | 9 +- src/irisnet/noncore/icetransport.h | 24 +- src/irisnet/noncore/iceturntransport.cpp | 118 +- src/irisnet/noncore/iceturntransport.h | 20 +- src/irisnet/noncore/legacy/ndns.cpp | 24 +- src/irisnet/noncore/legacy/ndns.h | 11 +- src/irisnet/noncore/legacy/srvresolver.cpp | 137 +- src/irisnet/noncore/legacy/srvresolver.h | 21 +- src/irisnet/noncore/processquit.cpp | 68 +- src/irisnet/noncore/processquit.h | 24 +- src/irisnet/noncore/stunallocate.cpp | 702 ++--- src/irisnet/noncore/stunallocate.h | 42 +- src/irisnet/noncore/stunbinding.cpp | 171 +- src/irisnet/noncore/stunbinding.h | 14 +- src/irisnet/noncore/stunmessage.cpp | 340 +- src/irisnet/noncore/stunmessage.h | 49 +- src/irisnet/noncore/stuntransaction.cpp | 393 +-- src/irisnet/noncore/stuntransaction.h | 35 +- src/irisnet/noncore/stuntypes.cpp | 1027 +++---- src/irisnet/noncore/stuntypes.h | 217 +- src/irisnet/noncore/stunutil.cpp | 133 +- src/irisnet/noncore/stunutil.h | 17 +- src/irisnet/noncore/tcpportreserver.cpp | 81 +- src/irisnet/noncore/tcpportreserver.h | 44 +- src/irisnet/noncore/turnclient.cpp | 638 ++-- src/irisnet/noncore/turnclient.h | 45 +- src/irisnet/noncore/udpportreserver.cpp | 208 +- src/irisnet/noncore/udpportreserver.h | 7 +- src/xmpp/base/randomnumbergenerator.cpp | 6 +- src/xmpp/base/randomnumbergenerator.h | 17 +- src/xmpp/base/randrandomnumbergenerator.h | 17 +- src/xmpp/base/timezone.cpp | 53 +- src/xmpp/base/timezone.h | 7 +- .../incrementingrandomnumbergenerator.h | 35 +- .../unittest/randomnumbergeneratortest.cpp | 65 +- .../randrandomnumbergeneratortest.cpp | 24 +- src/xmpp/blake2/blake2-impl.h | 153 +- src/xmpp/blake2/blake2.h | 216 +- src/xmpp/blake2/blake2qt.cpp | 8 +- src/xmpp/blake2/blake2qt.h | 5 +- src/xmpp/jid/jid.cpp | 345 +-- src/xmpp/jid/jid.h | 140 +- src/xmpp/jid/unittest/jidtest.cpp | 22 +- .../qttestutil/example/myfirstclasstest.cpp | 20 +- .../qttestutil/example/mysecondclasstest.cpp | 20 +- src/xmpp/qa/qttestutil/qttestutil.h | 3 +- src/xmpp/qa/qttestutil/simplechecker.cpp | 2 +- src/xmpp/qa/qttestutil/testregistration.h | 35 +- src/xmpp/qa/qttestutil/testregistry.cpp | 13 +- src/xmpp/qa/qttestutil/testregistry.h | 59 +- src/xmpp/qa/unittest.template/myclasstest.cpp | 22 +- src/xmpp/sasl/digestmd5proplist.cpp | 66 +- src/xmpp/sasl/digestmd5proplist.h | 28 +- src/xmpp/sasl/digestmd5response.cpp | 43 +- src/xmpp/sasl/digestmd5response.h | 43 +- src/xmpp/sasl/plainmessage.cpp | 2 +- src/xmpp/sasl/plainmessage.h | 17 +- src/xmpp/sasl/scramsha1message.cpp | 18 +- src/xmpp/sasl/scramsha1message.h | 30 +- src/xmpp/sasl/scramsha1response.cpp | 39 +- src/xmpp/sasl/scramsha1response.h | 54 +- src/xmpp/sasl/scramsha1signature.cpp | 12 +- src/xmpp/sasl/scramsha1signature.h | 17 +- .../sasl/unittest/digestmd5responsetest.cpp | 83 +- src/xmpp/sasl/unittest/plainmessagetest.cpp | 43 +- .../sasl/unittest/scramsha1messagetest.cpp | 37 +- .../sasl/unittest/scramsha1responsetest.cpp | 48 +- src/xmpp/xmpp-core/compressionhandler.cpp | 26 +- src/xmpp/xmpp-core/compressionhandler.h | 19 +- src/xmpp/xmpp-core/connector.cpp | 273 +- src/xmpp/xmpp-core/parser.cpp | 660 ++-- src/xmpp/xmpp-core/parser.h | 85 +- src/xmpp/xmpp-core/protocol.cpp | 1075 +++---- src/xmpp/xmpp-core/protocol.h | 667 ++-- src/xmpp/xmpp-core/securestream.cpp | 270 +- src/xmpp/xmpp-core/securestream.h | 23 +- src/xmpp/xmpp-core/simplesasl.cpp | 318 +- src/xmpp/xmpp-core/simplesasl.h | 4 +- src/xmpp/xmpp-core/sm.cpp | 31 +- src/xmpp/xmpp-core/sm.h | 104 +- src/xmpp/xmpp-core/stream.cpp | 1344 ++++---- src/xmpp/xmpp-core/td.h | 3 +- src/xmpp/xmpp-core/tlshandler.cpp | 239 +- src/xmpp/xmpp-core/xmlprotocol.cpp | 334 +- src/xmpp/xmpp-core/xmlprotocol.h | 227 +- src/xmpp/xmpp-core/xmpp.h | 316 +- src/xmpp/xmpp-core/xmpp_clientstream.h | 377 ++- src/xmpp/xmpp-core/xmpp_stanza.cpp | 447 ++- src/xmpp/xmpp-core/xmpp_stanza.h | 192 +- src/xmpp/xmpp-core/xmpp_stream.h | 81 +- src/xmpp/xmpp-im/client.cpp | 782 ++--- src/xmpp/xmpp-im/filetransfer.cpp | 476 ++- src/xmpp/xmpp-im/filetransfer.h | 313 +- src/xmpp/xmpp-im/httpfileupload.cpp | 438 ++- src/xmpp/xmpp-im/httpfileupload.h | 64 +- src/xmpp/xmpp-im/im.h | 143 +- src/xmpp/xmpp-im/jingle-ft.cpp | 1635 +++++----- src/xmpp/xmpp-im/jingle-ibb.cpp | 733 +++-- src/xmpp/xmpp-im/jingle-ibb.h | 149 +- src/xmpp/xmpp-im/jingle-s5b.cpp | 2723 ++++++++--------- src/xmpp/xmpp-im/jingle-s5b.h | 354 ++- src/xmpp/xmpp-im/jingle.h | 1063 ++++--- src/xmpp/xmpp-im/s5b.cpp | 1245 ++++---- src/xmpp/xmpp-im/s5b.h | 605 ++-- src/xmpp/xmpp-im/types.cpp | 1558 ++-------- src/xmpp/xmpp-im/xmpp_address.h | 53 +- src/xmpp/xmpp-im/xmpp_agentitem.h | 43 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp | 93 +- src/xmpp/xmpp-im/xmpp_bitsofbinary.h | 5 +- src/xmpp/xmpp-im/xmpp_bytestream.cpp | 19 +- src/xmpp/xmpp-im/xmpp_bytestream.h | 56 +- src/xmpp/xmpp-im/xmpp_caps.cpp | 148 +- src/xmpp/xmpp-im/xmpp_caps.h | 74 +- src/xmpp/xmpp-im/xmpp_captcha.h | 59 +- src/xmpp/xmpp-im/xmpp_chatstate.h | 9 +- src/xmpp/xmpp-im/xmpp_client.h | 381 +-- src/xmpp/xmpp-im/xmpp_discoinfotask.cpp | 67 +- src/xmpp/xmpp-im/xmpp_discoinfotask.h | 47 +- src/xmpp/xmpp-im/xmpp_discoitem.cpp | 191 +- src/xmpp/xmpp-im/xmpp_discoitem.h | 107 +- src/xmpp/xmpp-im/xmpp_encryptionhandler.h | 13 +- src/xmpp/xmpp-im/xmpp_features.cpp | 133 +- src/xmpp/xmpp-im/xmpp_features.h | 158 +- src/xmpp/xmpp-im/xmpp_hash.h | 15 +- src/xmpp/xmpp-im/xmpp_htmlelement.h | 35 +- src/xmpp/xmpp-im/xmpp_httpauthrequest.h | 50 +- src/xmpp/xmpp-im/xmpp_ibb.cpp | 335 +- src/xmpp/xmpp-im/xmpp_ibb.h | 270 +- src/xmpp/xmpp-im/xmpp_liveroster.h | 19 +- src/xmpp/xmpp-im/xmpp_liverosteritem.h | 55 +- src/xmpp/xmpp-im/xmpp_message.h | 399 ++- src/xmpp/xmpp-im/xmpp_muc.h | 202 +- src/xmpp/xmpp-im/xmpp_pubsubitem.h | 21 +- src/xmpp/xmpp-im/xmpp_pubsubretraction.h | 17 +- src/xmpp/xmpp-im/xmpp_receipts.h | 6 +- src/xmpp/xmpp-im/xmpp_reference.cpp | 114 +- src/xmpp/xmpp-im/xmpp_reference.h | 72 +- src/xmpp/xmpp-im/xmpp_resource.h | 31 +- src/xmpp/xmpp-im/xmpp_resourcelist.h | 23 +- src/xmpp/xmpp-im/xmpp_roster.h | 23 +- src/xmpp/xmpp-im/xmpp_rosteritem.h | 84 +- src/xmpp/xmpp-im/xmpp_rosterx.h | 50 +- src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp | 109 +- src/xmpp/xmpp-im/xmpp_serverinfomanager.h | 86 +- src/xmpp/xmpp-im/xmpp_status.h | 8 +- src/xmpp/xmpp-im/xmpp_subsets.cpp | 81 +- src/xmpp/xmpp-im/xmpp_subsets.h | 55 +- src/xmpp/xmpp-im/xmpp_task.cpp | 194 +- src/xmpp/xmpp-im/xmpp_task.h | 109 +- src/xmpp/xmpp-im/xmpp_tasks.cpp | 396 +-- src/xmpp/xmpp-im/xmpp_tasks.h | 853 +++--- src/xmpp/xmpp-im/xmpp_thumbs.h | 36 +- src/xmpp/xmpp-im/xmpp_url.h | 39 +- src/xmpp/xmpp-im/xmpp_vcard.cpp | 1090 +++---- src/xmpp/xmpp-im/xmpp_vcard.h | 422 ++- src/xmpp/xmpp-im/xmpp_xdata.cpp | 361 +-- src/xmpp/xmpp-im/xmpp_xdata.h | 246 +- src/xmpp/xmpp-im/xmpp_xmlcommon.cpp | 80 +- src/xmpp/xmpp-im/xmpp_xmlcommon.h | 9 +- src/xmpp/zlib/common.h | 24 +- src/xmpp/zlib/zlibcompressor.cpp | 29 +- src/xmpp/zlib/zlibcompressor.h | 15 +- src/xmpp/zlib/zlibdecompressor.cpp | 34 +- src/xmpp/zlib/zlibdecompressor.h | 15 +- tools/icetunnel/main.cpp | 477 ++- tools/nettool/main.cpp | 668 ++-- tools/xmpptest/xmpptest.cpp | 556 ++-- 206 files changed, 18888 insertions(+), 25306 deletions(-) diff --git a/src/irisnet/appledns/appledns.cpp b/src/irisnet/appledns/appledns.cpp index e08d8e66..33fdd5e6 100644 --- a/src/irisnet/appledns/appledns.cpp +++ b/src/irisnet/appledns/appledns.cpp @@ -22,19 +22,18 @@ #include #include #ifdef Q_OS_WIN // for ntohl -# include +#include #else -# include +#include #endif static QByteArray nameToDottedString(const QByteArray &in) { QByteArray out; - int at = 0; - while(at < in.size()) - { + int at = 0; + while (at < in.size()) { int len = in[at++]; - if(len > 0) + if (len > 0) out += in.mid(at, len); out += '.'; at += len; @@ -42,21 +41,17 @@ static QByteArray nameToDottedString(const QByteArray &in) return out; } -static QMap textsToAttribs(const QList &texts) +static QMap textsToAttribs(const QList &texts) { - QMap out; - foreach(const QByteArray &a, texts) - { - QString key; + QMap out; + foreach (const QByteArray &a, texts) { + QString key; QByteArray value; - int x = a.indexOf('='); - if(x != -1) - { - key = QString::fromLatin1(a.mid(0, x)); + int x = a.indexOf('='); + if (x != -1) { + key = QString::fromLatin1(a.mid(0, x)); value = a.mid(x + 1); - } - else - { + } else { key = QString::fromLatin1(a); } @@ -65,12 +60,11 @@ static QMap textsToAttribs(const QList &texts) return out; } -static QByteArray attribsToTxtRecord(const QMap &attribs) +static QByteArray attribsToTxtRecord(const QMap &attribs) { - QList texts; - QMapIterator it(attribs); - while(it.hasNext()) - { + QList texts; + QMapIterator it(attribs); + while (it.hasNext()) { it.next(); QByteArray line = it.key().toLatin1() + '=' + it.value(); texts += line; @@ -82,14 +76,14 @@ static QByteArray attribsToTxtRecord(const QMap &attribs) static QList nameToInstanceParts(const QByteArray &name) { // FIXME: improve this parsing... (what about escaping??) - int at = name.indexOf('.'); + int at = name.indexOf('.'); QByteArray sname = name.mid(0, at); ++at; int next = name.indexOf('.', at); ++next; - next = name.indexOf('.', next); - QByteArray stype = name.mid(at, next - at); - at = next + 1; + next = name.indexOf('.', next); + QByteArray stype = name.mid(at, next - at); + at = next + 1; QByteArray sdomain = name.mid(at); QList out; @@ -102,46 +96,40 @@ static QList nameToInstanceParts(const QByteArray &name) static XMPP::NameRecord importQDnsSdRecord(const QDnsSd::Record &in) { XMPP::NameRecord out; - switch(in.rrtype) + switch (in.rrtype) { + case 1: // A { - case 1: // A - { - quint32 *p = (quint32 *)in.rdata.data(); - out.setAddress(QHostAddress(ntohl(*p))); - } - break; - - case 28: // AAAA - { - out.setAddress(QHostAddress((quint8 *)in.rdata.data())); - } - break; + quint32 *p = (quint32 *)in.rdata.data(); + out.setAddress(QHostAddress(ntohl(*p))); + } break; - case 12: // PTR - { - out.setPtr(nameToDottedString(in.rdata)); - } - break; + case 28: // AAAA + { + out.setAddress(QHostAddress((quint8 *)in.rdata.data())); + } break; - case 10: // NULL - { - out.setNull(in.rdata); - } - break; + case 12: // PTR + { + out.setPtr(nameToDottedString(in.rdata)); + } break; - case 16: // TXT - { - QList txtEntries = QDnsSd::parseTxtRecord(in.rdata); - if(txtEntries.isEmpty()) - return out; - out.setTxt(txtEntries); - } - break; + case 10: // NULL + { + out.setNull(in.rdata); + } break; - default: // unsupported - { + case 16: // TXT + { + QList txtEntries = QDnsSd::parseTxtRecord(in.rdata); + if (txtEntries.isEmpty()) return out; - } + out.setTxt(txtEntries); + } break; + + default: // unsupported + { + return out; + } } out.setOwner(in.name); @@ -150,12 +138,9 @@ static XMPP::NameRecord importQDnsSdRecord(const QDnsSd::Record &in) } namespace { -class QDnsSdDelegate -{ +class QDnsSdDelegate { public: - virtual ~QDnsSdDelegate() - { - } + virtual ~QDnsSdDelegate() {} virtual void dns_queryResult(int id, const QDnsSd::QueryResult &result) { @@ -182,32 +167,26 @@ class QDnsSdDelegate } }; -class IdManager -{ +class IdManager { private: QSet set; - int at; + int at; inline void bump_at() { - if(at == 0x7fffffff) + if (at == 0x7fffffff) at = 0; else ++at; } public: - IdManager() : - at(0) - { - } + IdManager() : at(0) {} int reserveId() { - while(1) - { - if(!set.contains(at)) - { + while (1) { + if (!set.contains(at)) { int id = at; set.insert(id); bump_at(); @@ -218,10 +197,7 @@ class IdManager } } - void releaseId(int id) - { - set.remove(id); - } + void releaseId(int id) { set.remove(id); } }; } // namespace @@ -229,51 +205,54 @@ class IdManager //---------------------------------------------------------------------------- // AppleProvider //---------------------------------------------------------------------------- -class AppleProvider : public XMPP::IrisNetProvider -{ +class AppleProvider : public XMPP::IrisNetProvider { Q_OBJECT Q_INTERFACES(XMPP::IrisNetProvider); + public: - QDnsSd dns; - QHash delegateById; + QDnsSd dns; + QHash delegateById; - AppleProvider() : - dns(this) + AppleProvider() : dns(this) { - connect(&dns, SIGNAL(queryResult(int,QDnsSd::QueryResult)), SLOT(dns_queryResult(int,QDnsSd::QueryResult))); - connect(&dns, SIGNAL(browseResult(int,QDnsSd::BrowseResult)), SLOT(dns_browseResult(int,QDnsSd::BrowseResult))); - connect(&dns, SIGNAL(resolveResult(int,QDnsSd::ResolveResult)), SLOT(dns_resolveResult(int,QDnsSd::ResolveResult))); - connect(&dns, SIGNAL(regResult(int,QDnsSd::RegResult)), SLOT(dns_regResult(int,QDnsSd::RegResult))); + connect(&dns, SIGNAL(queryResult(int, QDnsSd::QueryResult)), SLOT(dns_queryResult(int, QDnsSd::QueryResult))); + connect(&dns, SIGNAL(browseResult(int, QDnsSd::BrowseResult)), + SLOT(dns_browseResult(int, QDnsSd::BrowseResult))); + connect(&dns, SIGNAL(resolveResult(int, QDnsSd::ResolveResult)), + SLOT(dns_resolveResult(int, QDnsSd::ResolveResult))); + connect(&dns, SIGNAL(regResult(int, QDnsSd::RegResult)), SLOT(dns_regResult(int, QDnsSd::RegResult))); } - virtual XMPP::NameProvider *createNameProviderInternet(); - virtual XMPP::NameProvider *createNameProviderLocal(); + virtual XMPP::NameProvider * createNameProviderInternet(); + virtual XMPP::NameProvider * createNameProviderLocal(); virtual XMPP::ServiceProvider *createServiceProvider(); int query(QDnsSdDelegate *p, const QByteArray &name, int qType) { - int id = dns.query(name, qType); + int id = dns.query(name, qType); delegateById[id] = p; return id; } int browse(QDnsSdDelegate *p, const QByteArray &serviceType, const QByteArray &domain) { - int id = dns.browse(serviceType, domain); + int id = dns.browse(serviceType, domain); delegateById[id] = p; return id; } - int resolve(QDnsSdDelegate *p, const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain) + int resolve(QDnsSdDelegate *p, const QByteArray &serviceName, const QByteArray &serviceType, + const QByteArray &domain) { - int id = dns.resolve(serviceName, serviceType, domain); + int id = dns.resolve(serviceName, serviceType, domain); delegateById[id] = p; return id; } - int reg(QDnsSdDelegate *p, const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, const QByteArray &txtRecord) + int reg(QDnsSdDelegate *p, const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, + int port, const QByteArray &txtRecord) { - int id = dns.reg(serviceName, serviceType, domain, port, txtRecord); + int id = dns.reg(serviceName, serviceType, domain, port, txtRecord); delegateById[id] = p; return id; } @@ -286,23 +265,19 @@ class AppleProvider : public XMPP::IrisNetProvider void stop_all(QDnsSdDelegate *p) { - QList ids; - QHashIterator it(delegateById); - while(it.hasNext()) - { + QList ids; + QHashIterator it(delegateById); + while (it.hasNext()) { it.next(); - if(it.value() == p) + if (it.value() == p) ids += it.key(); } - foreach(int id, ids) + foreach (int id, ids) stop(id); } private slots: - void dns_queryResult(int id, const QDnsSd::QueryResult &result) - { - delegateById[id]->dns_queryResult(id, result); - } + void dns_queryResult(int id, const QDnsSd::QueryResult &result) { delegateById[id]->dns_queryResult(id, result); } void dns_browseResult(int id, const QDnsSd::BrowseResult &result) { @@ -314,10 +289,7 @@ private slots: delegateById[id]->dns_resolveResult(id, result); } - void dns_regResult(int id, const QDnsSd::RegResult &result) - { - delegateById[id]->dns_regResult(id, result); - } + void dns_regResult(int id, const QDnsSd::RegResult &result) { delegateById[id]->dns_regResult(id, result); } }; //---------------------------------------------------------------------------- @@ -325,27 +297,20 @@ private slots: //---------------------------------------------------------------------------- // only use this class for a single browse. if you want to browse again, // create a new object. -class AppleBrowse : public QObject, public QDnsSdDelegate -{ +class AppleBrowse : public QObject, public QDnsSdDelegate { Q_OBJECT public: - AppleProvider *global; - int browse_id; + AppleProvider * global; + int browse_id; QList instances; - QHash pendingByQueryId; // waiting for TXT + QHash pendingByQueryId; // waiting for TXT - AppleBrowse(AppleProvider *_global, QObject *parent = 0) : - QObject(parent), - global(_global), - browse_id(-1) + AppleBrowse(AppleProvider *_global, QObject *parent = 0) : QObject(parent), global(_global), browse_id(-1) { connect(this, SIGNAL(unavailable_p(XMPP::ServiceInstance)), SIGNAL(unavailable(XMPP::ServiceInstance))); } - ~AppleBrowse() - { - global->stop_all(this); - } + ~AppleBrowse() { global->stop_all(this); } void browse(const QString &type, const QString &domain) { @@ -365,30 +330,24 @@ class AppleBrowse : public QObject, public QDnsSdDelegate { Q_UNUSED(id); - if(!result.success) - { + if (!result.success) { emit error(); return; } - foreach(const QDnsSd::BrowseEntry &e, result.entries) - { - XMPP::ServiceInstance si(e.serviceName, e.serviceType, e.replyDomain, QMap()); + foreach (const QDnsSd::BrowseEntry &e, result.entries) { + XMPP::ServiceInstance si(e.serviceName, e.serviceType, e.replyDomain, QMap()); - if(e.added) - { - int query_id = global->query(this, si.name(), 16); // 16 == TXT + if (e.added) { + int query_id = global->query(this, si.name(), 16); // 16 == TXT pendingByQueryId[query_id] = si.name(); - } - else // removed + } else // removed { // emit these queued for SS. no worry of SR since // the browse operation is not cancellable. - for(int n = 0; n < instances.count(); ++n) - { + for (int n = 0; n < instances.count(); ++n) { const XMPP::ServiceInstance &i = instances[n]; - if(i.name() == si.name()) - { + if (i.name() == si.name()) { emit unavailable_p(i); instances.removeAt(n); --n; // adjust position @@ -400,8 +359,7 @@ class AppleBrowse : public QObject, public QDnsSdDelegate virtual void dns_queryResult(int id, const QDnsSd::QueryResult &result) { - if(!result.success) - { + if (!result.success) { // if we get here, then it means we received a browse // entry, but could not fetch its TXT record. if // that happens, cancel the query and drop the @@ -415,14 +373,13 @@ class AppleBrowse : public QObject, public QDnsSdDelegate Q_ASSERT(!result.records.isEmpty()); // only the first entry matters, and it must be an added TXT - if(!result.records[0].added || result.records[0].rrtype != 16) + if (!result.records[0].added || result.records[0].rrtype != 16) return; // we only care about one answer - QByteArray name = pendingByQueryId[id]; + QByteArray name = pendingByQueryId[id]; QList parts = nameToInstanceParts(name); - if(parts.isEmpty()) - { + if (parts.isEmpty()) { // TODO: error Q_ASSERT(0); } @@ -433,19 +390,18 @@ class AppleBrowse : public QObject, public QDnsSdDelegate XMPP::NameRecord rec = importQDnsSdRecord(result.records[0]); // bad answer? - if(rec.isNull()) + if (rec.isNull()) return; - QMap attribs = textsToAttribs(rec.texts()); + QMap attribs = textsToAttribs(rec.texts()); // FIXME: conversion/escaping? - XMPP::ServiceInstance si(QString::fromUtf8(parts[0]), QString::fromUtf8(parts[1]), QString::fromUtf8(parts[2]), attribs); + XMPP::ServiceInstance si(QString::fromUtf8(parts[0]), QString::fromUtf8(parts[1]), QString::fromUtf8(parts[2]), + attribs); // does qdnssd guarantee we won't receive dups? bool found = false; - foreach(const XMPP::ServiceInstance &i, instances) - { - if(i.name() == si.name()) - { + foreach (const XMPP::ServiceInstance &i, instances) { + if (i.name() == si.name()) { found = true; break; } @@ -462,50 +418,39 @@ class AppleBrowse : public QObject, public QDnsSdDelegate //---------------------------------------------------------------------------- // only use this class for a single lookup. if you want to lookup again, // create a new object. -class AppleBrowseLookup : public QObject, public QDnsSdDelegate -{ +class AppleBrowseLookup : public QObject, public QDnsSdDelegate { Q_OBJECT public: - AppleProvider *global; - int resolve_id; + AppleProvider * global; + int resolve_id; XMPP::NameResolver nameResolverAaaa; XMPP::NameResolver nameResolverA; - bool activeAaaa; - bool activeA; - QTimer waitTimer; - QByteArray host; - QHostAddress addr4; - QHostAddress addr6; - int port; + bool activeAaaa; + bool activeA; + QTimer waitTimer; + QByteArray host; + QHostAddress addr4; + QHostAddress addr6; + int port; AppleBrowseLookup(AppleProvider *_global, QObject *parent = 0) : - QObject(parent), - global(_global), - resolve_id(-1), - nameResolverAaaa(this), - nameResolverA(this), - activeAaaa(false), - activeA(false), - waitTimer(this) + QObject(parent), global(_global), resolve_id(-1), nameResolverAaaa(this), nameResolverA(this), + activeAaaa(false), activeA(false), waitTimer(this) { connect(&nameResolverAaaa, SIGNAL(resultsReady(QList)), - SLOT(nameAaaa_resultsReady(QList))); + SLOT(nameAaaa_resultsReady(QList))); connect(&nameResolverAaaa, SIGNAL(error(XMPP::NameResolver::Error)), - SLOT(nameAaaa_error(XMPP::NameResolver::Error))); + SLOT(nameAaaa_error(XMPP::NameResolver::Error))); connect(&nameResolverA, SIGNAL(resultsReady(QList)), - SLOT(nameA_resultsReady(QList))); - connect(&nameResolverA, SIGNAL(error(XMPP::NameResolver::Error)), - SLOT(nameA_error(XMPP::NameResolver::Error))); + SLOT(nameA_resultsReady(QList))); + connect(&nameResolverA, SIGNAL(error(XMPP::NameResolver::Error)), SLOT(nameA_error(XMPP::NameResolver::Error))); connect(&waitTimer, SIGNAL(timeout()), SLOT(waitTimer_timeout())); waitTimer.setSingleShot(true); } - ~AppleBrowseLookup() - { - global->stop_all(this); - } + ~AppleBrowseLookup() { global->stop_all(this); } void resolve(const QByteArray &instance, const QByteArray &type, const QByteArray &domain) { @@ -523,8 +468,7 @@ class AppleBrowseLookup : public QObject, public QDnsSdDelegate // there is only one response, so deregister global->stop(id); - if(!result.success) - { + if (!result.success) { emit error(); return; } @@ -533,7 +477,7 @@ class AppleBrowseLookup : public QObject, public QDnsSdDelegate port = result.port; activeAaaa = true; - activeA = true; + activeA = true; nameResolverAaaa.start(host, XMPP::NameRecord::Aaaa); nameResolverA.start(host, XMPP::NameRecord::A); waitTimer.start(500); // 500ms cut-off time, take what we have and run @@ -544,7 +488,7 @@ private slots: { // nameresolver guarantees at least one result, and we only // care about the first - addr6 = results[0].address(); + addr6 = results[0].address(); activeAaaa = false; tryDone(); } @@ -560,7 +504,7 @@ private slots: { // nameresolver guarantees at least one result, and we only // care about the first - addr4 = results[0].address(); + addr4 = results[0].address(); activeA = false; tryDone(); } @@ -572,10 +516,7 @@ private slots: tryDone(); } - void waitTimer_timeout() - { - tryDone(); - } + void waitTimer_timeout() { tryDone(); } private: void tryDone() @@ -584,8 +525,7 @@ private slots: // results, or if the wait timer ends and we have at least // one result - if(!activeAaaa && !activeA && addr6.isNull() && addr4.isNull()) - { + if (!activeAaaa && !activeA && addr6.isNull() && addr4.isNull()) { nameResolverAaaa.stop(); nameResolverA.stop(); waitTimer.stop(); @@ -594,15 +534,14 @@ private slots: return; } - if(!waitTimer.isActive() && (!addr6.isNull() || !addr4.isNull())) - { + if (!waitTimer.isActive() && (!addr6.isNull() || !addr4.isNull())) { nameResolverAaaa.stop(); nameResolverA.stop(); QList out; - if(!addr4.isNull()) + if (!addr4.isNull()) out += addr4; - if(!addr6.isNull()) + if (!addr6.isNull()) out += addr6; emit finished(out, port); } @@ -612,27 +551,16 @@ private slots: //---------------------------------------------------------------------------- // AppleNameProvider //---------------------------------------------------------------------------- -class AppleNameProvider : public XMPP::NameProvider, public QDnsSdDelegate -{ +class AppleNameProvider : public XMPP::NameProvider, public QDnsSdDelegate { Q_OBJECT public: AppleProvider *global; - AppleNameProvider(AppleProvider *parent) : - NameProvider(parent), - global(parent) - { - } + AppleNameProvider(AppleProvider *parent) : NameProvider(parent), global(parent) {} - ~AppleNameProvider() - { - global->stop_all(this); - } + ~AppleNameProvider() { global->stop_all(this); } - virtual bool supportsLongLived() const - { - return true; - } + virtual bool supportsLongLived() const { return true; } virtual bool supportsRecordType(int type) const { @@ -647,31 +575,26 @@ class AppleNameProvider : public XMPP::NameProvider, public QDnsSdDelegate return global->query(this, name, qType); } - virtual void resolve_stop(int id) - { - global->stop(id); - } + virtual void resolve_stop(int id) { global->stop(id); } protected: virtual void dns_queryResult(int id, const QDnsSd::QueryResult &result) { - if(!result.success) - { + if (!result.success) { emit resolve_error(id, XMPP::NameResolver::ErrorGeneric); return; } QList results; - foreach(const QDnsSd::Record &rec, result.records) - { + foreach (const QDnsSd::Record &rec, result.records) { XMPP::NameRecord nr = importQDnsSdRecord(rec); // unsupported type - if(nr.isNull()) + if (nr.isNull()) continue; // if removed, ensure ttl is 0 - if(!rec.added) + if (!rec.added) nr.setTtl(0); results += nr; @@ -684,23 +607,16 @@ class AppleNameProvider : public XMPP::NameProvider, public QDnsSdDelegate //---------------------------------------------------------------------------- // AppleServiceProvider //---------------------------------------------------------------------------- -class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate -{ +class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate { Q_OBJECT public: - class Browse - { + class Browse { public: AppleServiceProvider *parent; - int id; - AppleBrowse *browse; + int id; + AppleBrowse * browse; - Browse(AppleServiceProvider *_parent) : - parent(_parent), - id(-1), - browse(0) - { - } + Browse(AppleServiceProvider *_parent) : parent(_parent), id(-1), browse(0) {} ~Browse() { @@ -709,19 +625,13 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate } }; - class Resolve - { + class Resolve { public: AppleServiceProvider *parent; - int id; - AppleBrowseLookup *resolve; + int id; + AppleBrowseLookup * resolve; - Resolve(AppleServiceProvider *_parent) : - parent(_parent), - id(-1), - resolve(0) - { - } + Resolve(AppleServiceProvider *_parent) : parent(_parent), id(-1), resolve(0) {} ~Resolve() { @@ -730,16 +640,12 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate } }; - AppleProvider *global; - QList browseList; - QList resolveList; - IdManager idManager; + AppleProvider * global; + QList browseList; + QList resolveList; + IdManager idManager; - AppleServiceProvider(AppleProvider *parent) : - ServiceProvider(parent), - global(parent) - { - } + AppleServiceProvider(AppleProvider *parent) : ServiceProvider(parent), global(parent) {} ~AppleServiceProvider() { @@ -750,9 +656,8 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate int indexOfBrowseByBrowse(AppleBrowse *browse) const { - for(int n = 0; n < browseList.count(); ++n) - { - if(browseList[n]->browse == browse) + for (int n = 0; n < browseList.count(); ++n) { + if (browseList[n]->browse == browse) return n; } return -1; @@ -760,9 +665,8 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate int indexOfBrowseById(int id) const { - for(int n = 0; n < browseList.count(); ++n) - { - if(browseList[n]->id == id) + for (int n = 0; n < browseList.count(); ++n) { + if (browseList[n]->id == id) return n; } return -1; @@ -770,9 +674,8 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate int indexOfResolveByResolve(AppleBrowseLookup *resolve) const { - for(int n = 0; n < resolveList.count(); ++n) - { - if(resolveList[n]->resolve == resolve) + for (int n = 0; n < resolveList.count(); ++n) { + if (resolveList[n]->resolve == resolve) return n; } return -1; @@ -780,9 +683,8 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate int indexOfResolveById(int id) const { - for(int n = 0; n < resolveList.count(); ++n) - { - if(resolveList[n]->id == id) + for (int n = 0; n < resolveList.count(); ++n) { + if (resolveList[n]->id == id) return n; } return -1; @@ -791,7 +693,7 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate virtual int browse_start(const QString &type, const QString &domain) { Browse *b = new Browse(this); - b->id = idManager.reserveId(); + b->id = idManager.reserveId(); b->browse = new AppleBrowse(global, this); connect(b->browse, SIGNAL(available(XMPP::ServiceInstance)), SLOT(browse_available(XMPP::ServiceInstance))); connect(b->browse, SIGNAL(unavailable(XMPP::ServiceInstance)), SLOT(browse_unavailable(XMPP::ServiceInstance))); @@ -804,7 +706,7 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate virtual void browse_stop(int id) { int at = indexOfBrowseById(id); - if(at == -1) + if (at == -1) return; Browse *b = browseList[at]; @@ -815,14 +717,13 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate virtual int resolve_start(const QByteArray &name) { QList parts = nameToInstanceParts(name); - if(parts.isEmpty()) - { + if (parts.isEmpty()) { // TODO: signal error rather than die Q_ASSERT(0); } Resolve *r = new Resolve(this); - r->id = idManager.reserveId(); + r->id = idManager.reserveId(); r->resolve = new AppleBrowseLookup(global, this); connect(r->resolve, SIGNAL(finished(QList)), SLOT(resolve_finished(QList))); connect(r->resolve, SIGNAL(error()), SLOT(resolve_error())); @@ -834,7 +735,7 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate virtual void resolve_stop(int id) { int at = indexOfResolveById(id); - if(at == -1) + if (at == -1) return; Resolve *r = resolveList[at]; @@ -842,11 +743,11 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate delete r; } - virtual int publish_start(const QString &instance, const QString &type, int port, const QMap &attributes) + virtual int publish_start(const QString &instance, const QString &type, int port, + const QMap &attributes) { QByteArray txtRecord = attribsToTxtRecord(attributes); - if(txtRecord.isEmpty()) - { + if (txtRecord.isEmpty()) { // TODO: signal error rather than die Q_ASSERT(0); } @@ -857,37 +758,30 @@ class AppleServiceProvider : public XMPP::ServiceProvider, public QDnsSdDelegate return global->reg(this, instance.toUtf8(), type.toUtf8(), domain.toUtf8(), port, txtRecord); } - virtual void publish_update(int id, const QMap &attributes) + virtual void publish_update(int id, const QMap &attributes) { // TODO: verify 'id' is valid. if not valid, then assert/return (don't do anything or signal error) QByteArray txtRecord = attribsToTxtRecord(attributes); - if(txtRecord.isEmpty()) - { + if (txtRecord.isEmpty()) { // TODO: signal error rather than die Q_ASSERT(0); } - if(global->dns.recordUpdateTxt(id, txtRecord, 4500)) - { + if (global->dns.recordUpdateTxt(id, txtRecord, 4500)) { // FIXME: SR QMetaObject::invokeMethod(this, "publish_published", Qt::QueuedConnection, Q_ARG(int, id)); - } - else - { + } else { // TODO: unpublish // FIXME: register meta type, SR - QMetaObject::invokeMethod(this, "publish_error", Qt::QueuedConnection, - Q_ARG(int, id), + QMetaObject::invokeMethod( + this, "publish_error", Qt::QueuedConnection, Q_ARG(int, id), Q_ARG(XMPP::ServiceLocalPublisher::Error, XMPP::ServiceLocalPublisher::ErrorGeneric)); } } - virtual void publish_stop(int id) - { - global->stop(id); - } + virtual void publish_stop(int id) { global->stop(id); } virtual int publish_extra_start(int pub_id, const XMPP::NameRecord &name) { @@ -962,11 +856,10 @@ private slots: delete r; QList results; - foreach(const QHostAddress &addr, addrs) - { + foreach (const QHostAddress &addr, addrs) { ResolveResult r; r.address = addr; - r.port = port; + r.port = port; results += r; } @@ -990,26 +883,14 @@ private slots: }; // AppleProvider -XMPP::NameProvider *AppleProvider::createNameProviderInternet() -{ - return new AppleNameProvider(this); -} +XMPP::NameProvider *AppleProvider::createNameProviderInternet() { return new AppleNameProvider(this); } -XMPP::NameProvider *AppleProvider::createNameProviderLocal() -{ - return new AppleNameProvider(this); -} +XMPP::NameProvider *AppleProvider::createNameProviderLocal() { return new AppleNameProvider(this); } -XMPP::ServiceProvider *AppleProvider::createServiceProvider() -{ - return new AppleServiceProvider(this); -} +XMPP::ServiceProvider *AppleProvider::createServiceProvider() { return new AppleServiceProvider(this); } #ifdef APPLEDNS_STATIC -XMPP::IrisNetProvider *irisnet_createAppleProvider() -{ - return new AppleProvider; -} +XMPP::IrisNetProvider *irisnet_createAppleProvider() { return new AppleProvider; } #else Q_EXPORT_PLUGIN2(appledns, AppleProvider) #endif diff --git a/src/irisnet/appledns/qdnssd.cpp b/src/irisnet/appledns/qdnssd.cpp index 75a0d39f..dda1189c 100644 --- a/src/irisnet/appledns/qdnssd.cpp +++ b/src/irisnet/appledns/qdnssd.cpp @@ -23,9 +23,9 @@ #include #include #ifdef Q_OS_WIN // for ntohs -# include +#include #else -# include +#include #endif namespace { @@ -37,33 +37,28 @@ void releaseAndDeleteLater(QObject *owner, QObject *obj) obj->deleteLater(); } -class SafeTimer : public QObject -{ +class SafeTimer : public QObject { Q_OBJECT public: - SafeTimer(QObject *parent = 0) : - QObject(parent) + SafeTimer(QObject *parent = 0) : QObject(parent) { t = new QTimer(this); connect(t, SIGNAL(timeout()), SIGNAL(timeout())); } - ~SafeTimer() - { - releaseAndDeleteLater(this, t); - } + ~SafeTimer() { releaseAndDeleteLater(this, t); } - int interval() const { return t->interval(); } - bool isActive() const { return t->isActive(); } - bool isSingleShot() const { return t->isSingleShot(); } - void setInterval(int msec) { t->setInterval(msec); } + int interval() const { return t->interval(); } + bool isActive() const { return t->isActive(); } + bool isSingleShot() const { return t->isSingleShot(); } + void setInterval(int msec) { t->setInterval(msec); } void setSingleShot(bool singleShot) { t->setSingleShot(singleShot); } - int timerId() const { return t->timerId(); } + int timerId() const { return t->timerId(); } public slots: - void start(int msec) { t->start(msec); } - void start() { t->start(); } - void stop() { t->stop(); } + void start(int msec) { t->start(msec); } + void start() { t->start(); } + void stop() { t->stop(); } signals: void timeout(); @@ -72,13 +67,10 @@ public slots: QTimer *t; }; -class SafeSocketNotifier : public QObject -{ +class SafeSocketNotifier : public QObject { Q_OBJECT public: - SafeSocketNotifier(int socket, QSocketNotifier::Type type, - QObject *parent = 0) : - QObject(parent) + SafeSocketNotifier(int socket, QSocketNotifier::Type type, QObject *parent = 0) : QObject(parent) { sn = new QSocketNotifier(socket, type, this); connect(sn, SIGNAL(activated(int)), SIGNAL(activated(int))); @@ -90,12 +82,12 @@ class SafeSocketNotifier : public QObject releaseAndDeleteLater(this, sn); } - bool isEnabled() const { return sn->isEnabled(); } - int socket() const { return sn->socket(); } + bool isEnabled() const { return sn->isEnabled(); } + int socket() const { return sn->socket(); } QSocketNotifier::Type type() const { return sn->type(); } public slots: - void setEnabled(bool enable) { sn->setEnabled(enable); } + void setEnabled(bool enable) { sn->setEnabled(enable); } signals: void activated(int socket); @@ -111,85 +103,58 @@ public slots: // to maintain a pointer which /can/ be copied. Also, we'll keep // a flag to indicate whether the allocated DNSServiceRef has been // initialized yet. -class ServiceRef -{ +class ServiceRef { private: DNSServiceRef *_p; - bool _initialized; + bool _initialized; public: - ServiceRef() : - _initialized(false) - { - _p = (DNSServiceRef *)malloc(sizeof(DNSServiceRef)); - } + ServiceRef() : _initialized(false) { _p = (DNSServiceRef *)malloc(sizeof(DNSServiceRef)); } ~ServiceRef() { - if(_initialized) + if (_initialized) DNSServiceRefDeallocate(*_p); free(_p); } - DNSServiceRef *data() - { - return _p; - } + DNSServiceRef *data() { return _p; } - void setInitialized() - { - _initialized = true; - } + void setInitialized() { _initialized = true; } }; -class RecordRef -{ +class RecordRef { private: DNSRecordRef *_p; public: - RecordRef() - { - _p = (DNSRecordRef *)malloc(sizeof(DNSRecordRef)); - } + RecordRef() { _p = (DNSRecordRef *)malloc(sizeof(DNSRecordRef)); } - ~RecordRef() - { - free(_p); - } + ~RecordRef() { free(_p); } - DNSRecordRef *data() - { - return _p; - } + DNSRecordRef *data() { return _p; } }; -class IdManager -{ +class IdManager { private: QSet set; - int at; + int at; inline void bump_at() { - if(at == 0x7fffffff) + if (at == 0x7fffffff) at = 0; else ++at; } public: - IdManager() : - at(0) - { - } + IdManager() : at(0) {} int reserveId() { - while(1) - { - if(!set.contains(at)) - { + while (1) { + if (!set.contains(at)) { int id = at; set.insert(id); bump_at(); @@ -200,10 +165,7 @@ class IdManager } } - void releaseId(int id) - { - set.remove(id); - } + void releaseId(int id) { set.remove(id); } }; } // namespace @@ -211,26 +173,19 @@ class IdManager //---------------------------------------------------------------------------- // QDnsSd //---------------------------------------------------------------------------- -class QDnsSd::Private : public QObject -{ +class QDnsSd::Private : public QObject { Q_OBJECT public: - QDnsSd *q; + QDnsSd * q; IdManager idManager; - class SubRecord - { + class SubRecord { public: - Private *_self; - int _id; + Private * _self; + int _id; RecordRef *_sdref; - SubRecord(Private *self) : - _self(self), - _id(-1), - _sdref(0) - { - } + SubRecord(Private *self) : _self(self), _id(-1), _sdref(0) {} ~SubRecord() { @@ -239,46 +194,33 @@ class QDnsSd::Private : public QObject } }; - class Request - { + class Request { public: - enum Type - { - Query, - Browse, - Resolve, - Reg - }; - - Private *_self; - int _type; - int _id; - ServiceRef *_sdref; - int _sockfd; + enum Type { Query, Browse, Resolve, Reg }; + + Private * _self; + int _type; + int _id; + ServiceRef * _sdref; + int _sockfd; SafeSocketNotifier *_sn_read; - SafeTimer *_errorTrigger; + SafeTimer * _errorTrigger; - bool _doSignal; - LowLevelError _lowLevelError; - QList _queryRecords; + bool _doSignal; + LowLevelError _lowLevelError; + QList _queryRecords; QList _browseEntries; - QByteArray _resolveFullName; - QByteArray _resolveHost; - int _resolvePort; - QByteArray _resolveTxtRecord; - QByteArray _regDomain; - bool _regConflict; + QByteArray _resolveFullName; + QByteArray _resolveHost; + int _resolvePort; + QByteArray _resolveTxtRecord; + QByteArray _regDomain; + bool _regConflict; - QList _subRecords; + QList _subRecords; Request(Private *self) : - _self(self), - _id(-1), - _sdref(0), - _sockfd(-1), - _sn_read(0), - _errorTrigger(0), - _doSignal(false) + _self(self), _id(-1), _sdref(0), _sockfd(-1), _sn_read(0), _errorTrigger(0), _doSignal(false) { } @@ -294,30 +236,22 @@ class QDnsSd::Private : public QObject int subRecordIndexById(int rec_id) const { - for(int n = 0; n < _subRecords.count(); ++n) - { - if(_subRecords[n]->_id == rec_id) + for (int n = 0; n < _subRecords.count(); ++n) { + if (_subRecords[n]->_id == rec_id) return n; } return -1; } }; - QHash _requestsById; - QHash _requestsBySocket; - QHash _requestsByTimer; - QHash _requestsByRecId; + QHash _requestsById; + QHash _requestsBySocket; + QHash _requestsByTimer; + QHash _requestsByRecId; - Private(QDnsSd *_q) : - QObject(_q), - q(_q) - { - } + Private(QDnsSd *_q) : QObject(_q), q(_q) {} - ~Private() - { - qDeleteAll(_requestsById); - } + ~Private() { qDeleteAll(_requestsById); } void setDelayedError(Request *req, const LowLevelError &lowLevelError) { @@ -337,11 +271,11 @@ class QDnsSd::Private : public QObject void removeRequest(Request *req) { - foreach(const SubRecord *srec, req->_subRecords) + foreach (const SubRecord *srec, req->_subRecords) _requestsByRecId.remove(srec->_id); - if(req->_errorTrigger) + if (req->_errorTrigger) _requestsByTimer.remove(req->_errorTrigger); - if(req->_sn_read) + if (req->_sn_read) _requestsBySocket.remove(req->_sn_read); _requestsById.remove(req->_id); delete req; @@ -350,7 +284,7 @@ class QDnsSd::Private : public QObject int regIdForRecId(int rec_id) const { Request *req = _requestsByRecId.value(rec_id); - if(req) + if (req) return req->_id; return -1; } @@ -360,32 +294,27 @@ class QDnsSd::Private : public QObject int id = idManager.reserveId(); Request *req = new Request(this); - req->_type = Request::Query; - req->_id = id; - req->_sdref = new ServiceRef; - - DNSServiceErrorType err = DNSServiceQueryRecord( - req->_sdref->data(), kDNSServiceFlagsLongLivedQuery, - 0, name.constData(), qType, kDNSServiceClass_IN, - cb_queryRecordReply, req); - if(err != kDNSServiceErr_NoError) - { - setDelayedError(req, LowLevelError( - "DNSServiceQueryRecord", err)); + req->_type = Request::Query; + req->_id = id; + req->_sdref = new ServiceRef; + + DNSServiceErrorType err + = DNSServiceQueryRecord(req->_sdref->data(), kDNSServiceFlagsLongLivedQuery, 0, name.constData(), qType, + kDNSServiceClass_IN, cb_queryRecordReply, req); + if (err != kDNSServiceErr_NoError) { + setDelayedError(req, LowLevelError("DNSServiceQueryRecord", err)); return id; } req->_sdref->setInitialized(); int sockfd = DNSServiceRefSockFD(*(req->_sdref->data())); - if(sockfd == -1) - { - setDelayedError(req, LowLevelError( - "DNSServiceRefSockFD", -1)); + if (sockfd == -1) { + setDelayedError(req, LowLevelError("DNSServiceRefSockFD", -1)); return id; } - req->_sockfd = sockfd; + req->_sockfd = sockfd; req->_sn_read = new SafeSocketNotifier(sockfd, QSocketNotifier::Read, this); connect(req->_sn_read, SIGNAL(activated(int)), SLOT(sn_activated())); _requestsById.insert(id, req); @@ -399,32 +328,26 @@ class QDnsSd::Private : public QObject int id = idManager.reserveId(); Request *req = new Request(this); - req->_type = Request::Browse; - req->_id = id; - req->_sdref = new ServiceRef; - - DNSServiceErrorType err = DNSServiceBrowse( - req->_sdref->data(), 0, 0, serviceType.constData(), - !domain.isEmpty() ? domain.constData() : NULL, - cb_browseReply, req); - if(err != kDNSServiceErr_NoError) - { - setDelayedError(req, LowLevelError( - "DNSServiceBrowse", err)); + req->_type = Request::Browse; + req->_id = id; + req->_sdref = new ServiceRef; + + DNSServiceErrorType err = DNSServiceBrowse(req->_sdref->data(), 0, 0, serviceType.constData(), + !domain.isEmpty() ? domain.constData() : NULL, cb_browseReply, req); + if (err != kDNSServiceErr_NoError) { + setDelayedError(req, LowLevelError("DNSServiceBrowse", err)); return id; } req->_sdref->setInitialized(); int sockfd = DNSServiceRefSockFD(*(req->_sdref->data())); - if(sockfd == -1) - { - setDelayedError(req, LowLevelError( - "DNSServiceRefSockFD", -1)); + if (sockfd == -1) { + setDelayedError(req, LowLevelError("DNSServiceRefSockFD", -1)); return id; } - req->_sockfd = sockfd; + req->_sockfd = sockfd; req->_sn_read = new SafeSocketNotifier(sockfd, QSocketNotifier::Read, this); connect(req->_sn_read, SIGNAL(activated(int)), SLOT(sn_activated())); _requestsById.insert(id, req); @@ -438,32 +361,27 @@ class QDnsSd::Private : public QObject int id = idManager.reserveId(); Request *req = new Request(this); - req->_type = Request::Resolve; - req->_id = id; - req->_sdref = new ServiceRef; - - DNSServiceErrorType err = DNSServiceResolve( - req->_sdref->data(), 0, 0, serviceName.constData(), - serviceType.constData(), domain.constData(), - (DNSServiceResolveReply)cb_resolveReply, req); - if(err != kDNSServiceErr_NoError) - { - setDelayedError(req, LowLevelError( - "DNSServiceResolve", err)); + req->_type = Request::Resolve; + req->_id = id; + req->_sdref = new ServiceRef; + + DNSServiceErrorType err + = DNSServiceResolve(req->_sdref->data(), 0, 0, serviceName.constData(), serviceType.constData(), + domain.constData(), (DNSServiceResolveReply)cb_resolveReply, req); + if (err != kDNSServiceErr_NoError) { + setDelayedError(req, LowLevelError("DNSServiceResolve", err)); return id; } req->_sdref->setInitialized(); int sockfd = DNSServiceRefSockFD(*(req->_sdref->data())); - if(sockfd == -1) - { - setDelayedError(req, LowLevelError( - "DNSServiceRefSockFD", -1)); + if (sockfd == -1) { + setDelayedError(req, LowLevelError("DNSServiceRefSockFD", -1)); return id; } - req->_sockfd = sockfd; + req->_sockfd = sockfd; req->_sn_read = new SafeSocketNotifier(sockfd, QSocketNotifier::Read, this); connect(req->_sn_read, SIGNAL(activated(int)), SLOT(sn_activated())); _requestsById.insert(id, req); @@ -472,48 +390,42 @@ class QDnsSd::Private : public QObject return id; } - int reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, const QByteArray &txtRecord) + int reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, + const QByteArray &txtRecord) { int id = idManager.reserveId(); Request *req = new Request(this); - req->_type = Request::Reg; - req->_id = id; + req->_type = Request::Reg; + req->_id = id; - if(port < 1 || port > 0xffff) - { + if (port < 1 || port > 0xffff) { setDelayedError(req, LowLevelError()); return id; } uint16_t sport = port; - sport = htons(sport); + sport = htons(sport); req->_sdref = new ServiceRef; DNSServiceErrorType err = DNSServiceRegister( - req->_sdref->data(), kDNSServiceFlagsNoAutoRename, 0, - serviceName.constData(), serviceType.constData(), - domain.constData(), NULL, sport, txtRecord.size(), - txtRecord.data(), cb_regReply, req); - if(err != kDNSServiceErr_NoError) - { - setDelayedError(req, LowLevelError( - "DNSServiceRegister", err)); + req->_sdref->data(), kDNSServiceFlagsNoAutoRename, 0, serviceName.constData(), serviceType.constData(), + domain.constData(), NULL, sport, txtRecord.size(), txtRecord.data(), cb_regReply, req); + if (err != kDNSServiceErr_NoError) { + setDelayedError(req, LowLevelError("DNSServiceRegister", err)); return id; } req->_sdref->setInitialized(); int sockfd = DNSServiceRefSockFD(*(req->_sdref->data())); - if(sockfd == -1) - { - setDelayedError(req, LowLevelError( - "DNSServiceRefSockFD", -1)); + if (sockfd == -1) { + setDelayedError(req, LowLevelError("DNSServiceRefSockFD", -1)); return id; } - req->_sockfd = sockfd; + req->_sockfd = sockfd; req->_sn_read = new SafeSocketNotifier(sockfd, QSocketNotifier::Read, this); connect(req->_sn_read, SIGNAL(activated(int)), SLOT(sn_activated())); _requestsById.insert(id, req); @@ -525,31 +437,27 @@ class QDnsSd::Private : public QObject int recordAdd(int reg_id, const Record &rec, LowLevelError *lowLevelError) { Request *req = _requestsById.value(reg_id); - if(!req) - { - if(lowLevelError) + if (!req) { + if (lowLevelError) *lowLevelError = LowLevelError(); return -1; } RecordRef *recordRef = new RecordRef; - DNSServiceErrorType err = DNSServiceAddRecord( - *(req->_sdref->data()), recordRef->data(), 0, - rec.rrtype, rec.rdata.size(), rec.rdata.data(), - rec.ttl); - if(err != kDNSServiceErr_NoError) - { - if(lowLevelError) + DNSServiceErrorType err = DNSServiceAddRecord(*(req->_sdref->data()), recordRef->data(), 0, rec.rrtype, + rec.rdata.size(), rec.rdata.data(), rec.ttl); + if (err != kDNSServiceErr_NoError) { + if (lowLevelError) *lowLevelError = LowLevelError("DNSServiceAddRecord", err); delete recordRef; return -1; } - int id = idManager.reserveId(); + int id = idManager.reserveId(); SubRecord *srec = new SubRecord(this); - srec->_id = id; - srec->_sdref = recordRef; + srec->_id = id; + srec->_sdref = recordRef; req->_subRecords += srec; _requestsByRecId.insert(id, req); @@ -559,33 +467,27 @@ class QDnsSd::Private : public QObject bool recordUpdate(int reg_id, int rec_id, const Record &rec, LowLevelError *lowLevelError) { Request *req = _requestsById.value(reg_id); - if(!req) - { - if(lowLevelError) + if (!req) { + if (lowLevelError) *lowLevelError = LowLevelError(); return false; } SubRecord *srec = 0; - if(rec_id != -1) - { + if (rec_id != -1) { int at = req->subRecordIndexById(rec_id); - if(at == -1) - { - if(lowLevelError) + if (at == -1) { + if (lowLevelError) *lowLevelError = LowLevelError(); return false; } srec = req->_subRecords[at]; } - DNSServiceErrorType err = DNSServiceUpdateRecord( - *(req->_sdref->data()), - srec ? *(srec->_sdref->data()) : NULL, 0, - rec.rdata.size(), rec.rdata.data(), rec.ttl); - if(err != kDNSServiceErr_NoError) - { - if(lowLevelError) + DNSServiceErrorType err = DNSServiceUpdateRecord(*(req->_sdref->data()), srec ? *(srec->_sdref->data()) : NULL, + 0, rec.rdata.size(), rec.rdata.data(), rec.ttl); + if (err != kDNSServiceErr_NoError) { + if (lowLevelError) *lowLevelError = LowLevelError("DNSServiceUpdateRecord", err); return false; } @@ -596,7 +498,7 @@ class QDnsSd::Private : public QObject void recordRemove(int rec_id) { Request *req = _requestsByRecId.value(rec_id); - if(!req) + if (!req) return; // this can't fail @@ -612,7 +514,7 @@ class QDnsSd::Private : public QObject void stop(int id) { Request *req = _requestsById.value(id); - if(req) + if (req) removeRequest(req); } @@ -620,8 +522,8 @@ private slots: void sn_activated() { SafeSocketNotifier *sn_read = static_cast(sender()); - Request *req = _requestsBySocket.value(sn_read); - if(!req) + Request * req = _requestsBySocket.value(sn_read); + if (!req) return; int id = req->_id; @@ -630,47 +532,40 @@ private slots: // do error if the above function returns an error, or if we // collected an error during a callback - if(err != kDNSServiceErr_NoError || !req->_lowLevelError.func.isEmpty()) - { + if (err != kDNSServiceErr_NoError || !req->_lowLevelError.func.isEmpty()) { LowLevelError lowLevelError; - if(err != kDNSServiceErr_NoError) + if (err != kDNSServiceErr_NoError) lowLevelError = LowLevelError("DNSServiceProcessResult", err); else lowLevelError = req->_lowLevelError; // reg conflict indicated via callback bool regConflict = false; - if(req->_type == Request::Reg && !req->_lowLevelError.func.isEmpty()) + if (req->_type == Request::Reg && !req->_lowLevelError.func.isEmpty()) regConflict = req->_regConflict; removeRequest(req); - if(req->_type == Request::Query) - { + if (req->_type == Request::Query) { QDnsSd::QueryResult r; - r.success = false; + r.success = false; r.lowLevelError = lowLevelError; emit q->queryResult(id, r); - } - else if(req->_type == Request::Browse) - { + } else if (req->_type == Request::Browse) { QDnsSd::BrowseResult r; - r.success = false; + r.success = false; r.lowLevelError = lowLevelError; emit q->browseResult(id, r); - } - else if(req->_type == Request::Resolve) - { + } else if (req->_type == Request::Resolve) { QDnsSd::ResolveResult r; - r.success = false; + r.success = false; r.lowLevelError = lowLevelError; emit q->resolveResult(id, r); - } - else // Reg + } else // Reg { QDnsSd::RegResult r; r.success = false; - if(regConflict) + if (regConflict) r.errorCode = QDnsSd::RegResult::ErrorConflict; else r.errorCode = QDnsSd::RegResult::ErrorGeneric; @@ -683,10 +578,8 @@ private slots: // handle success - if(req->_type == Request::Query) - { - if(req->_doSignal) - { + if (req->_type == Request::Query) { + if (req->_doSignal) { QDnsSd::QueryResult r; r.success = true; r.records = req->_queryRecords; @@ -694,11 +587,8 @@ private slots: req->_doSignal = false; emit q->queryResult(id, r); } - } - else if(req->_type == Request::Browse) - { - if(req->_doSignal) - { + } else if (req->_type == Request::Browse) { + if (req->_doSignal) { QDnsSd::BrowseResult r; r.success = true; r.entries = req->_browseEntries; @@ -706,17 +596,14 @@ private slots: req->_doSignal = false; emit q->browseResult(id, r); } - } - else if(req->_type == Request::Resolve) - { - if(req->_doSignal) - { + } else if (req->_type == Request::Resolve) { + if (req->_doSignal) { QDnsSd::ResolveResult r; - r.success = true; - r.fullName = req->_resolveFullName; - r.hostTarget = req->_resolveHost; - r.port = req->_resolvePort; - r.txtRecord = req->_resolveTxtRecord; + r.success = true; + r.fullName = req->_resolveFullName; + r.hostTarget = req->_resolveHost; + r.port = req->_resolvePort; + r.txtRecord = req->_resolveTxtRecord; req->_doSignal = false; // there is only one response @@ -724,14 +611,12 @@ private slots: emit q->resolveResult(id, r); } - } - else // Reg + } else // Reg { - if(req->_doSignal) - { + if (req->_doSignal) { QDnsSd::RegResult r; - r.success = true; - r.domain = req->_regDomain; + r.success = true; + r.domain = req->_regDomain; req->_doSignal = false; emit q->regResult(id, r); @@ -741,180 +626,155 @@ private slots: void doError() { - SafeTimer *t = static_cast(sender()); - Request *req = _requestsByTimer.value(t); - if(!req) + SafeTimer *t = static_cast(sender()); + Request * req = _requestsByTimer.value(t); + if (!req) return; - int id = req->_id; + int id = req->_id; int type = req->_type; removeRequest(req); - if(type == Request::Query) - { + if (type == Request::Query) { QDnsSd::QueryResult r; - r.success = false; + r.success = false; r.lowLevelError = req->_lowLevelError; emit q->queryResult(id, r); - } - else if(type == Request::Browse) - { + } else if (type == Request::Browse) { QDnsSd::BrowseResult r; - r.success = false; + r.success = false; r.lowLevelError = req->_lowLevelError; emit q->browseResult(id, r); - } - else if(type == Request::Resolve) - { + } else if (type == Request::Resolve) { QDnsSd::ResolveResult r; - r.success = false; + r.success = false; r.lowLevelError = req->_lowLevelError; emit q->resolveResult(id, r); - } - else // Reg + } else // Reg { QDnsSd::RegResult r; - r.success = false; - r.errorCode = QDnsSd::RegResult::ErrorGeneric; + r.success = false; + r.errorCode = QDnsSd::RegResult::ErrorGeneric; r.lowLevelError = req->_lowLevelError; emit q->regResult(id, r); } } private: - static void cb_queryRecordReply(DNSServiceRef ref, - DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *fullname, - uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, - const void *rdata, uint32_t ttl, void *context) + static void cb_queryRecordReply(DNSServiceRef ref, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, + uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) { Q_UNUSED(ref); Q_UNUSED(interfaceIndex); Q_UNUSED(rrclass); Request *req = static_cast(context); - req->_self->handle_queryRecordReply(req, flags, errorCode, - fullname, rrtype, rdlen, (const char *)rdata, ttl); + req->_self->handle_queryRecordReply(req, flags, errorCode, fullname, rrtype, rdlen, (const char *)rdata, ttl); } - static void cb_browseReply(DNSServiceRef ref, - DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *serviceName, - const char *regtype, const char *replyDomain, void *context) + static void cb_browseReply(DNSServiceRef ref, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, + const char *replyDomain, void *context) { Q_UNUSED(ref); Q_UNUSED(interfaceIndex); Request *req = static_cast(context); - req->_self->handle_browseReply(req, flags, errorCode, - serviceName, regtype, replyDomain); + req->_self->handle_browseReply(req, flags, errorCode, serviceName, regtype, replyDomain); } - static void cb_resolveReply(DNSServiceRef ref, - DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *fullname, - const char *hosttarget, uint16_t port, uint16_t txtLen, - const unsigned char *txtRecord, void *context) + static void cb_resolveReply(DNSServiceRef ref, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, + uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) { Q_UNUSED(ref); Q_UNUSED(flags); Q_UNUSED(interfaceIndex); Request *req = static_cast(context); - req->_self->handle_resolveReply(req, errorCode, fullname, - hosttarget, port, txtLen, txtRecord); + req->_self->handle_resolveReply(req, errorCode, fullname, hosttarget, port, txtLen, txtRecord); } - static void cb_regReply(DNSServiceRef ref, - DNSServiceFlags flags, DNSServiceErrorType errorCode, - const char *name, const char *regtype, const char *domain, - void *context) + static void cb_regReply(DNSServiceRef ref, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, + const char *regtype, const char *domain, void *context) { Q_UNUSED(ref); Q_UNUSED(flags); Request *req = static_cast(context); - req->_self->handle_regReply(req, errorCode, name, regtype, - domain); + req->_self->handle_regReply(req, errorCode, name, regtype, domain); } - void handle_queryRecordReply(Request *req, DNSServiceFlags flags, - DNSServiceErrorType errorCode, const char *fullname, - uint16_t rrtype, uint16_t rdlen, const char *rdata, - uint16_t ttl) + void handle_queryRecordReply(Request *req, DNSServiceFlags flags, DNSServiceErrorType errorCode, + const char *fullname, uint16_t rrtype, uint16_t rdlen, const char *rdata, uint16_t ttl) { - if(errorCode != kDNSServiceErr_NoError) - { - req->_doSignal = true; + if (errorCode != kDNSServiceErr_NoError) { + req->_doSignal = true; req->_lowLevelError = LowLevelError("DNSServiceQueryRecordReply", errorCode); return; } QDnsSd::Record rec; - rec.added = (flags & kDNSServiceFlagsAdd) ? true: false; - rec.name = QByteArray(fullname); + rec.added = (flags & kDNSServiceFlagsAdd) ? true : false; + rec.name = QByteArray(fullname); rec.rrtype = rrtype; - rec.rdata = QByteArray(rdata, rdlen); - rec.ttl = ttl; + rec.rdata = QByteArray(rdata, rdlen); + rec.ttl = ttl; req->_queryRecords += rec; - if(!(flags & kDNSServiceFlagsMoreComing)) + if (!(flags & kDNSServiceFlagsMoreComing)) req->_doSignal = true; } - void handle_browseReply(Request *req, DNSServiceFlags flags, - DNSServiceErrorType errorCode, const char *serviceName, - const char *regtype, const char *replyDomain) + void handle_browseReply(Request *req, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *serviceName, + const char *regtype, const char *replyDomain) { - if(errorCode != kDNSServiceErr_NoError) - { - req->_doSignal = true; + if (errorCode != kDNSServiceErr_NoError) { + req->_doSignal = true; req->_lowLevelError = LowLevelError("DNSServiceBrowseReply", errorCode); return; } QDnsSd::BrowseEntry e; - e.added = (flags & kDNSServiceFlagsAdd) ? true: false; + e.added = (flags & kDNSServiceFlagsAdd) ? true : false; e.serviceName = QByteArray(serviceName); e.serviceType = QByteArray(regtype); e.replyDomain = QByteArray(replyDomain); req->_browseEntries += e; - if(!(flags & kDNSServiceFlagsMoreComing)) + if (!(flags & kDNSServiceFlagsMoreComing)) req->_doSignal = true; } - void handle_resolveReply(Request *req, DNSServiceErrorType errorCode, - const char *fullname, const char *hosttarget, uint16_t port, - uint16_t txtLen, const unsigned char *txtRecord) + void handle_resolveReply(Request *req, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, + uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) { - if(errorCode != kDNSServiceErr_NoError) - { - req->_doSignal = true; + if (errorCode != kDNSServiceErr_NoError) { + req->_doSignal = true; req->_lowLevelError = LowLevelError("DNSServiceResolveReply", errorCode); return; } - req->_resolveFullName = QByteArray(fullname); - req->_resolveHost = QByteArray(hosttarget); - req->_resolvePort = ntohs(port); + req->_resolveFullName = QByteArray(fullname); + req->_resolveHost = QByteArray(hosttarget); + req->_resolvePort = ntohs(port); req->_resolveTxtRecord = QByteArray((const char *)txtRecord, txtLen); req->_doSignal = true; } - void handle_regReply(Request *req, DNSServiceErrorType errorCode, - const char *name, const char *regtype, const char *domain) + void handle_regReply(Request *req, DNSServiceErrorType errorCode, const char *name, const char *regtype, + const char *domain) { Q_UNUSED(name); Q_UNUSED(regtype); - if(errorCode != kDNSServiceErr_NoError) - { - req->_doSignal = true; + if (errorCode != kDNSServiceErr_NoError) { + req->_doSignal = true; req->_lowLevelError = LowLevelError("DNSServiceRegisterReply", errorCode); - if(errorCode == kDNSServiceErr_NameConflict) + if (errorCode == kDNSServiceErr_NameConflict) req->_regConflict = true; else req->_regConflict = false; @@ -922,37 +782,25 @@ private slots: } req->_regDomain = QByteArray(domain); - req->_doSignal = true; + req->_doSignal = true; } }; -QDnsSd::QDnsSd(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} +QDnsSd::QDnsSd(QObject *parent) : QObject(parent) { d = new Private(this); } -QDnsSd::~QDnsSd() -{ - delete d; -} +QDnsSd::~QDnsSd() { delete d; } -int QDnsSd::query(const QByteArray &name, int qType) -{ - return d->query(name, qType); -} +int QDnsSd::query(const QByteArray &name, int qType) { return d->query(name, qType); } -int QDnsSd::browse(const QByteArray &serviceType, const QByteArray &domain) -{ - return d->browse(serviceType, domain); -} +int QDnsSd::browse(const QByteArray &serviceType, const QByteArray &domain) { return d->browse(serviceType, domain); } int QDnsSd::resolve(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain) { return d->resolve(serviceName, serviceType, domain); } -int QDnsSd::reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, const QByteArray &txtRecord) +int QDnsSd::reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, + const QByteArray &txtRecord) { return d->reg(serviceName, serviceType, domain, port, txtRecord); } @@ -965,7 +813,7 @@ int QDnsSd::recordAdd(int reg_id, const Record &rec, LowLevelError *lowLevelErro bool QDnsSd::recordUpdate(int rec_id, const Record &rec, LowLevelError *lowLevelError) { int reg_id = d->regIdForRecId(rec_id); - if(reg_id == -1) + if (reg_id == -1) return false; return d->recordUpdate(reg_id, rec_id, rec, lowLevelError); @@ -975,43 +823,33 @@ bool QDnsSd::recordUpdateTxt(int reg_id, const QByteArray &txtRecord, quint32 tt { Record rec; rec.rrtype = kDNSServiceType_TXT; - rec.rdata = txtRecord; - rec.ttl = ttl; + rec.rdata = txtRecord; + rec.ttl = ttl; return d->recordUpdate(reg_id, -1, rec, lowLevelError); } -void QDnsSd::recordRemove(int rec_id) -{ - d->recordRemove(rec_id); -} +void QDnsSd::recordRemove(int rec_id) { d->recordRemove(rec_id); } -void QDnsSd::stop(int id) -{ - d->stop(id); -} +void QDnsSd::stop(int id) { d->stop(id); } QByteArray QDnsSd::createTxtRecord(const QList &strings) { // split into var/val and validate QList vars; QList vals; // null = no value, empty = empty value - foreach(const QByteArray &i, strings) - { + foreach (const QByteArray &i, strings) { QByteArray var; QByteArray val; - int n = i.indexOf('='); - if(n != -1) - { + int n = i.indexOf('='); + if (n != -1) { var = i.mid(0, n); val = i.mid(n + 1); - } - else + } else var = i; - for(int n = 0; n < var.size(); ++n) - { + for (int n = 0; n < var.size(); ++n) { unsigned char c = var[n]; - if(c < 0x20 || c > 0x7e) + if (c < 0x20 || c > 0x7e) return QByteArray(); } @@ -1020,21 +858,18 @@ QByteArray QDnsSd::createTxtRecord(const QList &strings) } TXTRecordRef ref; - QByteArray buf(256, 0); + QByteArray buf(256, 0); TXTRecordCreate(&ref, buf.size(), buf.data()); - for(int n = 0; n < vars.count(); ++n) - { - int valueSize = vals[n].size(); + for (int n = 0; n < vars.count(); ++n) { + int valueSize = vals[n].size(); char *value; - if(!vals[n].isNull()) + if (!vals[n].isNull()) value = vals[n].data(); else value = 0; - DNSServiceErrorType err = TXTRecordSetValue(&ref, - vars[n].data(), valueSize, value); - if(err != kDNSServiceErr_NoError) - { + DNSServiceErrorType err = TXTRecordSetValue(&ref, vars[n].data(), valueSize, value); + if (err != kDNSServiceErr_NoError) { TXTRecordDeallocate(&ref); return QByteArray(); } @@ -1047,23 +882,20 @@ QByteArray QDnsSd::createTxtRecord(const QList &strings) QList QDnsSd::parseTxtRecord(const QByteArray &txtRecord) { QList out; - int count = TXTRecordGetCount(txtRecord.size(), txtRecord.data()); - for(int n = 0; n < count; ++n) - { - QByteArray keyBuf(256, 0); - uint8_t valueLen; - const void *value; - DNSServiceErrorType err = TXTRecordGetItemAtIndex( - txtRecord.size(), txtRecord.data(), n, keyBuf.size(), - keyBuf.data(), &valueLen, &value); - if(err != kDNSServiceErr_NoError) + int count = TXTRecordGetCount(txtRecord.size(), txtRecord.data()); + for (int n = 0; n < count; ++n) { + QByteArray keyBuf(256, 0); + uint8_t valueLen; + const void * value; + DNSServiceErrorType err = TXTRecordGetItemAtIndex(txtRecord.size(), txtRecord.data(), n, keyBuf.size(), + keyBuf.data(), &valueLen, &value); + if (err != kDNSServiceErr_NoError) return QList(); keyBuf.resize(qstrlen(keyBuf.data())); QByteArray entry = keyBuf; - if(value) - { + if (value) { entry += '='; entry += QByteArray((const char *)value, valueLen); } diff --git a/src/irisnet/appledns/qdnssd.h b/src/irisnet/appledns/qdnssd.h index 7996cd51..635ef489 100644 --- a/src/irisnet/appledns/qdnssd.h +++ b/src/irisnet/appledns/qdnssd.h @@ -24,43 +24,32 @@ #include // DOR-compliant -class QDnsSd : public QObject -{ +class QDnsSd : public QObject { Q_OBJECT public: - class LowLevelError - { + class LowLevelError { public: QString func; - int code; - - LowLevelError() : - code(0) - { - } - - LowLevelError(const QString &_func, int _code) : - func(_func), - code(_code) - { - } + int code; + + LowLevelError() : code(0) {} + + LowLevelError(const QString &_func, int _code) : func(_func), code(_code) {} }; - class Record - { + class Record { public: bool added; // only used by QueryResult QByteArray name; - int rrtype; + int rrtype; QByteArray rdata; - quint32 ttl; + quint32 ttl; }; - class BrowseEntry - { + class BrowseEntry { public: - bool added; + bool added; QByteArray serviceName; // these may be different from request, see dns_sd docs @@ -68,47 +57,39 @@ class QDnsSd : public QObject QByteArray replyDomain; }; - class QueryResult - { + class QueryResult { public: - bool success; + bool success; LowLevelError lowLevelError; QList records; }; - class BrowseResult - { + class BrowseResult { public: - bool success; + bool success; LowLevelError lowLevelError; QList entries; }; - class ResolveResult - { + class ResolveResult { public: - bool success; + bool success; LowLevelError lowLevelError; QByteArray fullName; QByteArray hostTarget; - int port; // host byte-order + int port; // host byte-order QByteArray txtRecord; }; - class RegResult - { + class RegResult { public: - enum Error - { - ErrorGeneric, - ErrorConflict - }; - - bool success; - Error errorCode; + enum Error { ErrorGeneric, ErrorConflict }; + + bool success; + Error errorCode; LowLevelError lowLevelError; QByteArray domain; @@ -125,7 +106,8 @@ class QDnsSd : public QObject int resolve(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain); // domain may be empty - int reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, const QByteArray &txtRecord); + int reg(const QByteArray &serviceName, const QByteArray &serviceType, const QByteArray &domain, int port, + const QByteArray &txtRecord); // return -1 on error, else a record id int recordAdd(int reg_id, const Record &rec, LowLevelError *lowLevelError = 0); diff --git a/src/irisnet/appledns/sdtest.cpp b/src/irisnet/appledns/sdtest.cpp index b60c6223..038e74b2 100644 --- a/src/irisnet/appledns/sdtest.cpp +++ b/src/irisnet/appledns/sdtest.cpp @@ -21,49 +21,37 @@ #include #include #ifdef Q_OS_WIN // for ntohl -# include +#include #else -# include +#include #endif -class Command -{ +class Command { public: - enum Type - { - Query, - Browse, - Resolve, - Reg - }; + enum Type { Query, Browse, Resolve, Reg }; Type type; - QString name; // query, resolve, reg - int rtype; // query - QString stype; // browse, resolve, reg - QString domain; // browse, resolve, reg - int port; // reg + QString name; // query, resolve, reg + int rtype; // query + QString stype; // browse, resolve, reg + QString domain; // browse, resolve, reg + int port; // reg QByteArray txtRecord; // reg - int id; - int dnsId; + int id; + int dnsId; bool error; bool done; // for resolve - Command() : - error(false), - done(false) - { - } + Command() : error(false), done(false) {} }; static QString nameToString(const QByteArray &in) { QStringList parts; - int at = 0; - while(at < in.size()) - { + int at = 0; + while (at < in.size()) { int len = in[at++]; parts += QString::fromUtf8(in.mid(at, len)); at += len; @@ -75,20 +63,17 @@ static QString recordToDesc(const QDnsSd::Record &rec) { QString desc; - if(rec.rrtype == 1) // A + if (rec.rrtype == 1) // A { quint32 *p = (quint32 *)rec.rdata.data(); - desc = QHostAddress(ntohl(*p)).toString(); - } - else if(rec.rrtype == 28) // AAAA + desc = QHostAddress(ntohl(*p)).toString(); + } else if (rec.rrtype == 28) // AAAA { desc = QHostAddress((quint8 *)rec.rdata.data()).toString(); - } - else if(rec.rrtype == 12) // PTR + } else if (rec.rrtype == 12) // PTR { desc = QString("[%1]").arg(nameToString(rec.rdata)); - } - else + } else desc = QString("%1 bytes").arg(rec.rdata.size()); return desc; @@ -97,11 +82,11 @@ static QString recordToDesc(const QDnsSd::Record &rec) static QStringList txtRecordToStringList(const QByteArray &rdata) { QList txtEntries = QDnsSd::parseTxtRecord(rdata); - if(txtEntries.isEmpty()) + if (txtEntries.isEmpty()) return QStringList(); QStringList out; - foreach(const QByteArray &entry, txtEntries) + foreach (const QByteArray &entry, txtEntries) out += QString::fromUtf8(entry); return out; } @@ -109,64 +94,56 @@ static QStringList txtRecordToStringList(const QByteArray &rdata) static void printIndentedTxt(const QByteArray &txtRecord) { QStringList list = txtRecordToStringList(txtRecord); - if(!list.isEmpty()) - { - foreach(const QString &s, list) + if (!list.isEmpty()) { + foreach (const QString &s, list) printf(" %s\n", qPrintable(s)); - } - else + } else printf(" (TXT parsing error)\n"); } -class App : public QObject -{ +class App : public QObject { Q_OBJECT public: QList commands; - QDnsSd *dns; + QDnsSd * dns; App() { dns = new QDnsSd(this); - connect(dns, SIGNAL(queryResult(int,QDnsSd::QueryResult)), SLOT(dns_queryResult(int,QDnsSd::QueryResult))); - connect(dns, SIGNAL(browseResult(int,QDnsSd::BrowseResult)), SLOT(dns_browseResult(int,QDnsSd::BrowseResult))); - connect(dns, SIGNAL(resolveResult(int,QDnsSd::ResolveResult)), SLOT(dns_resolveResult(int,QDnsSd::ResolveResult))); - connect(dns, SIGNAL(regResult(int,QDnsSd::RegResult)), SLOT(dns_regResult(int,QDnsSd::RegResult))); + connect(dns, SIGNAL(queryResult(int, QDnsSd::QueryResult)), SLOT(dns_queryResult(int, QDnsSd::QueryResult))); + connect(dns, SIGNAL(browseResult(int, QDnsSd::BrowseResult)), + SLOT(dns_browseResult(int, QDnsSd::BrowseResult))); + connect(dns, SIGNAL(resolveResult(int, QDnsSd::ResolveResult)), + SLOT(dns_resolveResult(int, QDnsSd::ResolveResult))); + connect(dns, SIGNAL(regResult(int, QDnsSd::RegResult)), SLOT(dns_regResult(int, QDnsSd::RegResult))); } public slots: void start() { - for(int n = 0; n < commands.count(); ++n) - { + for (int n = 0; n < commands.count(); ++n) { Command &c = commands[n]; c.id = n; - if(c.type == Command::Query) - { + if (c.type == Command::Query) { printf("%2d: Query name=[%s], type=%d ...\n", c.id, qPrintable(c.name), c.rtype); c.dnsId = dns->query(c.name.toUtf8(), c.rtype); - } - else if(c.type == Command::Browse) - { + } else if (c.type == Command::Browse) { printf("%2d: Browse type=[%s]", c.id, qPrintable(c.stype)); - if(!c.domain.isEmpty()) + if (!c.domain.isEmpty()) printf(", domain=[%s]", qPrintable(c.domain)); printf(" ...\n"); c.dnsId = dns->browse(c.stype.toUtf8(), c.domain.toUtf8()); - } - else if(c.type == Command::Resolve) - { - printf("%2d: Resolve name=[%s], type=[%s], domain=[%s] ...\n", c.id, qPrintable(c.name), qPrintable(c.stype), qPrintable(c.domain)); + } else if (c.type == Command::Resolve) { + printf("%2d: Resolve name=[%s], type=[%s], domain=[%s] ...\n", c.id, qPrintable(c.name), + qPrintable(c.stype), qPrintable(c.domain)); c.dnsId = dns->resolve(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8()); - } - else if(c.type == Command::Reg) - { + } else if (c.type == Command::Reg) { printf("%2d: Register name=[%s], type=[%s]", c.id, qPrintable(c.name), qPrintable(c.stype)); - if(!c.domain.isEmpty()) + if (!c.domain.isEmpty()) printf(", domain=[%s]", qPrintable(c.domain)); printf(", port=%d ...\n", c.port); - if(!c.txtRecord.isEmpty()) + if (!c.txtRecord.isEmpty()) printIndentedTxt(c.txtRecord); c.dnsId = dns->reg(c.name.toUtf8(), c.stype.toUtf8(), c.domain.toUtf8(), c.port, c.txtRecord); @@ -180,10 +157,9 @@ public slots: private: int cmdIdToCmdIndex(int cmdId) { - for(int n = 0; n < commands.count(); ++n) - { + for (int n = 0; n < commands.count(); ++n) { const Command &c = commands[n]; - if(c.id == cmdId) + if (c.id == cmdId) return n; } return -1; @@ -191,10 +167,9 @@ public slots: int dnsIdToCmdIndex(int dnsId) { - for(int n = 0; n < commands.count(); ++n) - { + for (int n = 0; n < commands.count(); ++n) { const Command &c = commands[n]; - if(c.dnsId == dnsId) + if (c.dnsId == dnsId) return n; } return -1; @@ -204,29 +179,27 @@ public slots: { // quit if there are nothing but errors or completed resolves bool doQuit = true; - foreach(const Command &c, commands) - { - if(c.error || (c.type == Command::Resolve && c.done)) + foreach (const Command &c, commands) { + if (c.error || (c.type == Command::Resolve && c.done)) continue; doQuit = false; break; } - if(doQuit) + if (doQuit) emit quit(); } private slots: void dns_queryResult(int id, const QDnsSd::QueryResult &result) { - int at = dnsIdToCmdIndex(id); - Command &c = commands[at]; + int at = dnsIdToCmdIndex(id); + Command &c = commands[at]; - if(!result.success) - { + if (!result.success) { printf("%2d: Error.", c.id); - if(!result.lowLevelError.func.isEmpty()) + if (!result.lowLevelError.func.isEmpty()) printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code); printf("\n"); c.error = true; @@ -234,28 +207,24 @@ private slots: return; } - foreach(const QDnsSd::Record &rec, result.records) - { - if(rec.added) - { + foreach (const QDnsSd::Record &rec, result.records) { + if (rec.added) { printf("%2d: Added: %s, ttl=%u\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl); - if(rec.rrtype == 16) + if (rec.rrtype == 16) printIndentedTxt(rec.rdata); - } - else + } else printf("%2d: Removed: %s, ttl=%u\n", c.id, qPrintable(recordToDesc(rec)), rec.ttl); } } void dns_browseResult(int id, const QDnsSd::BrowseResult &result) { - int at = dnsIdToCmdIndex(id); - Command &c = commands[at]; + int at = dnsIdToCmdIndex(id); + Command &c = commands[at]; - if(!result.success) - { + if (!result.success) { printf("%2d: Error.", c.id); - if(!result.lowLevelError.func.isEmpty()) + if (!result.lowLevelError.func.isEmpty()) printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code); printf("\n"); c.error = true; @@ -263,10 +232,10 @@ private slots: return; } - foreach(const QDnsSd::BrowseEntry &e, result.entries) - { - if(e.added) - printf("%2d: Added: [%s] [%s] [%s]\n", c.id, qPrintable(QString::fromUtf8(e.serviceName)), qPrintable(QString::fromUtf8(e.serviceType)), qPrintable(QString::fromUtf8(e.replyDomain))); + foreach (const QDnsSd::BrowseEntry &e, result.entries) { + if (e.added) + printf("%2d: Added: [%s] [%s] [%s]\n", c.id, qPrintable(QString::fromUtf8(e.serviceName)), + qPrintable(QString::fromUtf8(e.serviceType)), qPrintable(QString::fromUtf8(e.replyDomain))); else printf("%2d: Removed: [%s]\n", c.id, qPrintable(QString::fromUtf8(e.serviceName))); } @@ -274,13 +243,12 @@ private slots: void dns_resolveResult(int id, const QDnsSd::ResolveResult &result) { - int at = dnsIdToCmdIndex(id); - Command &c = commands[at]; + int at = dnsIdToCmdIndex(id); + Command &c = commands[at]; - if(!result.success) - { + if (!result.success) { printf("%2d: Error.", c.id); - if(!result.lowLevelError.func.isEmpty()) + if (!result.lowLevelError.func.isEmpty()) printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code); printf("\n"); c.error = true; @@ -289,7 +257,7 @@ private slots: } printf("%2d: Result: host=[%s] port=%d\n", c.id, qPrintable(QString::fromUtf8(result.hostTarget)), result.port); - if(!result.txtRecord.isEmpty()) + if (!result.txtRecord.isEmpty()) printIndentedTxt(result.txtRecord); c.done = true; @@ -298,18 +266,17 @@ private slots: void dns_regResult(int id, const QDnsSd::RegResult &result) { - int at = dnsIdToCmdIndex(id); - Command &c = commands[at]; + int at = dnsIdToCmdIndex(id); + Command &c = commands[at]; - if(!result.success) - { + if (!result.success) { QString errstr; - if(result.errorCode == QDnsSd::RegResult::ErrorConflict) + if (result.errorCode == QDnsSd::RegResult::ErrorConflict) errstr = "Conflict"; else errstr = "Generic"; printf("%2d: Error (%s).", c.id, qPrintable(errstr)); - if(!result.lowLevelError.func.isEmpty()) + if (!result.lowLevelError.func.isEmpty()) printf(" (%s, %d)", qPrintable(result.lowLevelError.func), result.lowLevelError.code); printf("\n"); c.error = true; @@ -342,8 +309,7 @@ int main(int argc, char **argv) QStringList args = qapp.arguments(); args.removeFirst(); - if(args.count() < 1) - { + if (args.count() < 1) { usage(); return 1; } @@ -351,35 +317,28 @@ int main(int argc, char **argv) // options QStringList txt; - for(int n = 0; n < args.count(); ++n) - { + for (int n = 0; n < args.count(); ++n) { QString s = args[n]; - if(!s.startsWith("--")) + if (!s.startsWith("--")) continue; QString var; QString val; - int x = s.indexOf('='); - if(x != -1) - { + int x = s.indexOf('='); + if (x != -1) { var = s.mid(2, x - 2); val = s.mid(x + 1); - } - else - { + } else { var = s.mid(2); } bool known = true; - if(var == "txt") - { + if (var == "txt") { txt = val.split(','); - } - else + } else known = false; - if(known) - { + if (known) { args.removeAt(n); --n; // adjust position } @@ -388,89 +347,74 @@ int main(int argc, char **argv) // commands QList commands; - for(int n = 0; n < args.count(); ++n) - { + for (int n = 0; n < args.count(); ++n) { QString str = args[n]; - int n = str.indexOf('='); - if(n == -1) - { + int n = str.indexOf('='); + if (n == -1) { printf("Error: bad format of command.\n"); return 1; } - QString type = str.mid(0, n); - QString rest = str.mid(n + 1); + QString type = str.mid(0, n); + QString rest = str.mid(n + 1); QStringList parts = rest.split(','); - if(type == "q") - { - if(parts.count() < 2) - { + if (type == "q") { + if (parts.count() < 2) { usage(); return 1; } Command c; - c.type = Command::Query; - c.name = parts[0]; + c.type = Command::Query; + c.name = parts[0]; c.rtype = parts[1].toInt(); commands += c; - } - else if(type == "b") - { - if(parts.count() < 1) - { + } else if (type == "b") { + if (parts.count() < 1) { usage(); return 1; } Command c; - c.type = Command::Browse; + c.type = Command::Browse; c.stype = parts[0]; - if(parts.count() >= 2) + if (parts.count() >= 2) c.domain = parts[1]; commands += c; - } - else if(type == "r") - { - if(parts.count() < 3) - { + } else if (type == "r") { + if (parts.count() < 3) { usage(); return 1; } Command c; - c.type = Command::Resolve; - c.name = parts[0]; - c.stype = parts[1]; + c.type = Command::Resolve; + c.name = parts[0]; + c.stype = parts[1]; c.domain = parts[2]; commands += c; - } - else if(type == "e") - { - if(parts.count() < 3) - { + } else if (type == "e") { + if (parts.count() < 3) { usage(); return 1; } Command c; - c.type = Command::Reg; - c.name = parts[0]; + c.type = Command::Reg; + c.name = parts[0]; c.stype = parts[1]; - c.port = parts[2].toInt(); - if(parts.count() >= 4) + c.port = parts[2].toInt(); + if (parts.count() >= 4) c.domain = parts[3]; - if(!txt.isEmpty()) - { + if (!txt.isEmpty()) { QList strings; - foreach(const QString &str, txt) + foreach (const QString &str, txt) strings += str.toUtf8(); QByteArray txtRecord = QDnsSd::createTxtRecord(strings); - if(txtRecord.isEmpty()) - { + if (txtRecord.isEmpty()) { printf("Error: failed to create TXT record, input too large or invalid\n"); return 1; } @@ -479,9 +423,7 @@ int main(int argc, char **argv) } commands += c; - } - else - { + } else { printf("Error: unknown command type '%s'.\n", qPrintable(type)); return 1; } diff --git a/src/irisnet/corelib/addressresolver.cpp b/src/irisnet/corelib/addressresolver.cpp index d43f1dd4..9985797d 100644 --- a/src/irisnet/corelib/addressresolver.cpp +++ b/src/irisnet/corelib/addressresolver.cpp @@ -22,34 +22,24 @@ #include "objectsession.h" namespace XMPP { -class AddressResolver::Private : public QObject -{ +class AddressResolver::Private : public QObject { Q_OBJECT public: - enum State - { - AddressWait, - AddressFirstCome - }; - - AddressResolver *q; - ObjectSession sess; - State state; - NameResolver req6; - NameResolver req4; - bool done6; - bool done4; + enum State { AddressWait, AddressFirstCome }; + + AddressResolver * q; + ObjectSession sess; + State state; + NameResolver req6; + NameResolver req4; + bool done6; + bool done4; QList addrs6; QList addrs4; - QTimer *opTimer; - - Private(AddressResolver *_q) : - QObject(_q), - q(_q), - sess(this), - req6(this), - req4(this) + QTimer * opTimer; + + Private(AddressResolver *_q) : QObject(_q), q(_q), sess(this), req6(this), req4(this) { connect(&req6, SIGNAL(resultsReady(QList)), SLOT(req6_resultsReady(QList))); connect(&req6, SIGNAL(error(XMPP::NameResolver::Error)), SLOT(req6_error(XMPP::NameResolver::Error))); @@ -75,12 +65,11 @@ class AddressResolver::Private : public QObject // was an IP address used as input? QHostAddress addr; - if(addr.setAddress(QString::fromLatin1(hostName))) - { + if (addr.setAddress(QString::fromLatin1(hostName))) { // use this as the result, no need to perform dns query done6 = true; done4 = true; - if(addr.protocol() == QAbstractSocket::IPv6Protocol) + if (addr.protocol() == QAbstractSocket::IPv6Protocol) addrs6 += addr; else addrs4 += addr; @@ -100,10 +89,7 @@ class AddressResolver::Private : public QObject req4.start(hostName, NameRecord::A); } - void stop() - { - cleanup(); - } + void stop() { cleanup(); } private: void cleanup() @@ -120,12 +106,11 @@ class AddressResolver::Private : public QObject bool tryDone() { - if((done6 && done4) || (state == AddressFirstCome && (done6 || done4))) - { + if ((done6 && done4) || (state == AddressFirstCome && (done6 || done4))) { QList results = addrs6 + addrs4; cleanup(); - if(!results.isEmpty()) + if (!results.isEmpty()) emit q->resultsReady(results); else emit q->error(ErrorGeneric); @@ -139,7 +124,7 @@ class AddressResolver::Private : public QObject private slots: void req6_resultsReady(const QList &results) { - foreach(const NameRecord &rec, results) + foreach (const NameRecord &rec, results) addrs6 += rec.address(); done6 = true; @@ -156,7 +141,7 @@ private slots: void req4_resultsReady(const QList &results) { - foreach(const NameRecord &rec, results) + foreach (const NameRecord &rec, results) addrs4 += rec.address(); done4 = true; @@ -175,36 +160,20 @@ private slots: { state = AddressFirstCome; - if(done6 || done4) + if (done6 || done4) tryDone(); } - void ipAddress_input() - { - tryDone(); - } + void ipAddress_input() { tryDone(); } }; -AddressResolver::AddressResolver(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} - -AddressResolver::~AddressResolver() -{ - delete d; -} - -void AddressResolver::start(const QByteArray &hostName) -{ - d->start(hostName); -} - -void AddressResolver::stop() -{ - d->stop(); -} +AddressResolver::AddressResolver(QObject *parent) : QObject(parent) { d = new Private(this); } + +AddressResolver::~AddressResolver() { delete d; } + +void AddressResolver::start(const QByteArray &hostName) { d->start(hostName); } + +void AddressResolver::stop() { d->stop(); } } // namespace XMPP diff --git a/src/irisnet/corelib/addressresolver.h b/src/irisnet/corelib/addressresolver.h index 39d1bee9..417574af 100644 --- a/src/irisnet/corelib/addressresolver.h +++ b/src/irisnet/corelib/addressresolver.h @@ -24,15 +24,11 @@ namespace XMPP { // resolve both AAAA and A for a hostname -class AddressResolver : public QObject -{ +class AddressResolver : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric - }; + enum Error { ErrorGeneric }; AddressResolver(QObject *parent = nullptr); ~AddressResolver(); diff --git a/src/irisnet/corelib/irisnetexport.h b/src/irisnet/corelib/irisnetexport.h index 3eaf4970..0e07278b 100644 --- a/src/irisnet/corelib/irisnetexport.h +++ b/src/irisnet/corelib/irisnetexport.h @@ -22,13 +22,13 @@ #include #ifdef IRISNET_STATIC -# define IRISNET_EXPORT +#define IRISNET_EXPORT #else -# ifdef IRISNET_MAKEDLL -# define IRISNET_EXPORT Q_DECL_EXPORT -# else -# define IRISNET_EXPORT Q_DECL_IMPORT -# endif +#ifdef IRISNET_MAKEDLL +#define IRISNET_EXPORT Q_DECL_EXPORT +#else +#define IRISNET_EXPORT Q_DECL_IMPORT +#endif #endif #endif // IRISNETEXPORT_H diff --git a/src/irisnet/corelib/irisnetglobal.cpp b/src/irisnet/corelib/irisnetglobal.cpp index 848b262d..4bd0dd23 100644 --- a/src/irisnet/corelib/irisnetglobal.cpp +++ b/src/irisnet/corelib/irisnetglobal.cpp @@ -37,65 +37,59 @@ extern IrisNetProvider *irisnet_createAppleProvider(); //---------------------------------------------------------------------------- // internal //---------------------------------------------------------------------------- -class PluginInstance -{ +class PluginInstance { private: QPluginLoader *_loader; - QObject *_instance; - bool _ownInstance; + QObject * _instance; + bool _ownInstance; - PluginInstance() - { - } + PluginInstance() {} public: static PluginInstance *fromFile(const QString &fname) { QPluginLoader *loader = new QPluginLoader(fname); - if(!loader->load()) - { + if (!loader->load()) { delete loader; return nullptr; } QObject *obj = loader->instance(); - if(!obj) - { + if (!obj) { loader->unload(); delete loader; return nullptr; } PluginInstance *i = new PluginInstance; - i->_loader = loader; - i->_instance = obj; - i->_ownInstance = true; + i->_loader = loader; + i->_instance = obj; + i->_ownInstance = true; return i; } static PluginInstance *fromStatic(QObject *obj) { PluginInstance *i = new PluginInstance; - i->_loader = nullptr; - i->_instance = obj; - i->_ownInstance = false; + i->_loader = nullptr; + i->_instance = obj; + i->_ownInstance = false; return i; } static PluginInstance *fromInstance(QObject *obj) { PluginInstance *i = new PluginInstance; - i->_loader = nullptr; - i->_instance = obj; - i->_ownInstance = true; + i->_loader = nullptr; + i->_instance = obj; + i->_ownInstance = true; return i; } ~PluginInstance() { - if(_ownInstance) + if (_ownInstance) delete _instance; - if(_loader) - { + if (_loader) { _loader->unload(); delete _loader; } @@ -103,64 +97,53 @@ class PluginInstance void claim() { - if(_loader) + if (_loader) _loader->moveToThread(0); - if(_ownInstance) + if (_ownInstance) _instance->moveToThread(nullptr); } - QObject *instance() - { - return _instance; - } + QObject *instance() { return _instance; } bool sameType(const PluginInstance *other) { - if(!_instance || !other->_instance) + if (!_instance || !other->_instance) return false; - if(qstrcmp(_instance->metaObject()->className(), other->_instance->metaObject()->className()) != 0) + if (qstrcmp(_instance->metaObject()->className(), other->_instance->metaObject()->className()) != 0) return false; return true; } }; -class PluginManager -{ +class PluginManager { public: - bool builtin_done; - QStringList paths; - QList plugins; - QList providers; + bool builtin_done; + QStringList paths; + QList plugins; + QList providers; - PluginManager() - { - builtin_done = false; - } + PluginManager() { builtin_done = false; } - ~PluginManager() - { - unload(); - } + ~PluginManager() { unload(); } bool tryAdd(PluginInstance *i, bool lowPriority = false) { // is it the right kind of plugin? - IrisNetProvider *p = qobject_cast(i->instance()); - if(!p) + IrisNetProvider *p = qobject_cast(i->instance()); + if (!p) return false; // make sure we don't have it already - for(int n = 0; n < plugins.count(); ++n) - { - if(i->sameType(plugins[n])) + for (int n = 0; n < plugins.count(); ++n) { + if (i->sameType(plugins[n])) return false; } i->claim(); plugins += i; - if(lowPriority) + if (lowPriority) providers.append(p); else providers.prepend(p); @@ -170,14 +153,13 @@ class PluginManager void addBuiltIn(IrisNetProvider *p) { PluginInstance *i = PluginInstance::fromInstance(p); - if(!tryAdd(i, true)) + if (!tryAdd(i, true)) delete i; } void scan() { - if(!builtin_done) - { + if (!builtin_done) { addBuiltIn(irisnet_createQtNetProvider()); // interfaces. crossplatform. no need to reimplement #ifdef Q_OS_UNIX addBuiltIn(irisnet_createUnixNetProvider()); // gateways @@ -191,30 +173,27 @@ class PluginManager } QObjectList list = QPluginLoader::staticInstances(); - for(int n = 0; n < list.count(); ++n) - { + for (int n = 0; n < list.count(); ++n) { PluginInstance *i = PluginInstance::fromStatic(list[n]); - if(!tryAdd(i)) + if (!tryAdd(i)) delete i; } - for(int n = 0; n < paths.count(); ++n) - { + for (int n = 0; n < paths.count(); ++n) { QDir dir(paths[n]); - if(!dir.exists()) + if (!dir.exists()) continue; QStringList entries = dir.entryList(); - for(int k = 0; k < entries.count(); ++k) - { + for (int k = 0; k < entries.count(); ++k) { QFileInfo fi(dir.filePath(entries[k])); - if(!fi.exists()) + if (!fi.exists()) continue; - QString fname = fi.filePath(); - PluginInstance *i = PluginInstance::fromFile(fname); - if(!i) + QString fname = fi.filePath(); + PluginInstance *i = PluginInstance::fromFile(fname); + if (!i) continue; - if(!tryAdd(i)) + if (!tryAdd(i)) delete i; } } @@ -223,8 +202,8 @@ class PluginManager void unload() { // unload in reverse order - QList revlist; - for(int n = 0; n < plugins.count(); ++n) + QList revlist; + for (int n = 0; n < plugins.count(); ++n) revlist.prepend(plugins[n]); qDeleteAll(revlist); @@ -233,11 +212,10 @@ class PluginManager } }; -class IrisNetGlobal -{ +class IrisNetGlobal { public: - QMutex m; - PluginManager pluginManager; + QMutex m; + PluginManager pluginManager; QList cleanupList; }; @@ -249,7 +227,7 @@ static void deinit(); static void init() { QMutexLocker locker(global_mutex()); - if(global) + if (global) return; global = new IrisNetGlobal; @@ -258,10 +236,10 @@ static void init() void deinit() { - if(!global) + if (!global) return; - while(!global->cleanupList.isEmpty()) + while (!global->cleanupList.isEmpty()) (global->cleanupList.takeFirst())(); delete global; @@ -293,7 +271,7 @@ void irisNetAddPostRoutine(IrisNetCleanUpFunction func) global->cleanupList.prepend(func); } -QList irisNetProviders() +QList irisNetProviders() { init(); diff --git a/src/irisnet/corelib/irisnetglobal_p.h b/src/irisnet/corelib/irisnetglobal_p.h index 2864627e..0ff31856 100644 --- a/src/irisnet/corelib/irisnetglobal_p.h +++ b/src/irisnet/corelib/irisnetglobal_p.h @@ -26,7 +26,7 @@ namespace XMPP { typedef void (*IrisNetCleanUpFunction)(); IRISNET_EXPORT void irisNetAddPostRoutine(IrisNetCleanUpFunction func); -IRISNET_EXPORT QList irisNetProviders(); +IRISNET_EXPORT QList irisNetProviders(); } // namespace XMPP #endif // IRISNETGLOBAL_P_H diff --git a/src/irisnet/corelib/irisnetplugin.cpp b/src/irisnet/corelib/irisnetplugin.cpp index 6e1faaae..a2d24fe7 100644 --- a/src/irisnet/corelib/irisnetplugin.cpp +++ b/src/irisnet/corelib/irisnetplugin.cpp @@ -22,48 +22,24 @@ namespace XMPP { //---------------------------------------------------------------------------- // IrisNetProvider //---------------------------------------------------------------------------- -NetInterfaceProvider *IrisNetProvider::createNetInterfaceProvider() -{ - return nullptr; -} +NetInterfaceProvider *IrisNetProvider::createNetInterfaceProvider() { return nullptr; } -NetGatewayProvider *IrisNetProvider::createNetGatewayProvider() -{ - return nullptr; -} +NetGatewayProvider *IrisNetProvider::createNetGatewayProvider() { return nullptr; } -NetAvailabilityProvider *IrisNetProvider::createNetAvailabilityProvider() -{ - return nullptr; -} +NetAvailabilityProvider *IrisNetProvider::createNetAvailabilityProvider() { return nullptr; } -NameProvider *IrisNetProvider::createNameProviderInternet() -{ - return nullptr; -} +NameProvider *IrisNetProvider::createNameProviderInternet() { return nullptr; } -NameProvider *IrisNetProvider::createNameProviderLocal() -{ - return nullptr; -} +NameProvider *IrisNetProvider::createNameProviderLocal() { return nullptr; } -ServiceProvider *IrisNetProvider::createServiceProvider() -{ - return nullptr; -} +ServiceProvider *IrisNetProvider::createServiceProvider() { return nullptr; } //---------------------------------------------------------------------------- // NameProvider //---------------------------------------------------------------------------- -bool NameProvider::supportsSingle() const -{ - return false; -} +bool NameProvider::supportsSingle() const { return false; } -bool NameProvider::supportsLongLived() const -{ - return false; -} +bool NameProvider::supportsLongLived() const { return false; } bool NameProvider::supportsRecordType(int type) const { diff --git a/src/irisnet/corelib/irisnetplugin.h b/src/irisnet/corelib/irisnetplugin.h index 5005129c..a3844de4 100644 --- a/src/irisnet/corelib/irisnetplugin.h +++ b/src/irisnet/corelib/irisnetplugin.h @@ -31,107 +31,88 @@ class NetGatewayProvider; class NetInterfaceProvider; class ServiceProvider; -class IRISNET_EXPORT IrisNetProvider : public QObject -{ +class IRISNET_EXPORT IrisNetProvider : public QObject { Q_OBJECT public: - virtual NetInterfaceProvider *createNetInterfaceProvider(); - virtual NetGatewayProvider *createNetGatewayProvider(); + virtual NetInterfaceProvider * createNetInterfaceProvider(); + virtual NetGatewayProvider * createNetGatewayProvider(); virtual NetAvailabilityProvider *createNetAvailabilityProvider(); - virtual NameProvider *createNameProviderInternet(); - virtual NameProvider *createNameProviderLocal(); - virtual ServiceProvider *createServiceProvider(); + virtual NameProvider * createNameProviderInternet(); + virtual NameProvider * createNameProviderLocal(); + virtual ServiceProvider * createServiceProvider(); }; -class IRISNET_EXPORT NetInterfaceProvider : public QObject -{ +class IRISNET_EXPORT NetInterfaceProvider : public QObject { Q_OBJECT public: - class Info - { + class Info { public: - QString id, name; - bool isLoopback; + QString id, name; + bool isLoopback; QList addresses; }; - NetInterfaceProvider(QObject *parent = nullptr) : - QObject(parent) - { - } + NetInterfaceProvider(QObject *parent = nullptr) : QObject(parent) {} // calling start should populate an initial list that can be // immediately fetched. do not signal updated() for this. - virtual void start() = 0; + virtual void start() = 0; virtual QList interfaces() const = 0; signals: void updated(); }; -class IRISNET_EXPORT NetGatewayProvider : public QObject -{ +class IRISNET_EXPORT NetGatewayProvider : public QObject { Q_OBJECT public: - class Info - { + class Info { public: - QString ifaceId; + QString ifaceId; QHostAddress gateway; }; - NetGatewayProvider(QObject *parent = nullptr) : - QObject(parent) - { - } + NetGatewayProvider(QObject *parent = nullptr) : QObject(parent) {} // calling start should populate an initial list that can be // immediately fetched. do not signal updated() for this. - virtual void start() = 0; + virtual void start() = 0; virtual QList gateways() const = 0; signals: void updated(); }; -class IRISNET_EXPORT NetAvailabilityProvider : public QObject -{ +class IRISNET_EXPORT NetAvailabilityProvider : public QObject { Q_OBJECT public: - NetAvailabilityProvider(QObject *parent = nullptr) : - QObject(parent) - { - } + NetAvailabilityProvider(QObject *parent = nullptr) : QObject(parent) {} // calling start should populate an initial value that can be // immediately fetched. do not signal updated() for this. - virtual void start() = 0; + virtual void start() = 0; virtual bool isAvailable() const = 0; signals: void updated(); }; -class IRISNET_EXPORT NameProvider : public QObject -{ +class IRISNET_EXPORT NameProvider : public QObject { Q_OBJECT public: - NameProvider(QObject *parent = nullptr) : - QObject(parent) - { - } + NameProvider(QObject *parent = nullptr) : QObject(parent) {} virtual bool supportsSingle() const; virtual bool supportsLongLived() const; virtual bool supportsRecordType(int type) const; - virtual int resolve_start(const QByteArray &name, int qType, bool longLived) = 0; - virtual void resolve_stop(int id) = 0; + virtual int resolve_start(const QByteArray &name, int qType, bool longLived) = 0; + virtual void resolve_stop(int id) = 0; // transfer from local back to internet virtual void resolve_localResultsReady(int id, const QList &results); @@ -145,35 +126,32 @@ class IRISNET_EXPORT NameProvider : public QObject void resolve_useLocal(int id, const QByteArray &name); }; -class IRISNET_EXPORT ServiceProvider : public QObject -{ +class IRISNET_EXPORT ServiceProvider : public QObject { Q_OBJECT public: - class ResolveResult - { + class ResolveResult { public: - QMap attributes; - QHostAddress address; - int port; - QByteArray hostName; // optional + QMap attributes; + QHostAddress address; + int port; + QByteArray hostName; // optional }; - ServiceProvider(QObject *parent = nullptr) : - QObject(parent) - { - } - - virtual int browse_start(const QString &type, const QString &domain) = 0; - virtual void browse_stop(int id) = 0; - virtual int resolve_start(const QByteArray &name) = 0; - virtual void resolve_stop(int id) = 0; - virtual int publish_start(const QString &instance, const QString &type, int port, const QMap &attributes) = 0; - virtual void publish_update(int id, const QMap &attributes) = 0; - virtual void publish_stop(int id) = 0; - virtual int publish_extra_start(int pub_id, const NameRecord &name) = 0; - virtual void publish_extra_update(int id, const NameRecord &name) = 0; - virtual void publish_extra_stop(int id) = 0; + ServiceProvider(QObject *parent = nullptr) : QObject(parent) {} + + virtual int browse_start(const QString &type, const QString &domain) = 0; + virtual void browse_stop(int id) = 0; + virtual int resolve_start(const QByteArray &name) = 0; + virtual void resolve_stop(int id) = 0; + virtual int publish_start(const QString &instance, const QString &type, int port, + const QMap &attributes) + = 0; + virtual void publish_update(int id, const QMap &attributes) = 0; + virtual void publish_stop(int id) = 0; + virtual int publish_extra_start(int pub_id, const NameRecord &name) = 0; + virtual void publish_extra_update(int id, const NameRecord &name) = 0; + virtual void publish_extra_stop(int id) = 0; signals: void browse_instanceAvailable(int id, const XMPP::ServiceInstance &instance); @@ -192,10 +170,10 @@ class IRISNET_EXPORT ServiceProvider : public QObject }; } // namespace XMPP -Q_DECLARE_INTERFACE(XMPP::NetGatewayProvider, "com.affinix.irisnet.IrisGatewayProvider/1.0") -Q_DECLARE_INTERFACE(XMPP::IrisNetProvider, "com.affinix.irisnet.IrisNetProvider/1.0") +Q_DECLARE_INTERFACE(XMPP::NetGatewayProvider, "com.affinix.irisnet.IrisGatewayProvider/1.0") +Q_DECLARE_INTERFACE(XMPP::IrisNetProvider, "com.affinix.irisnet.IrisNetProvider/1.0") Q_DECLARE_INTERFACE(XMPP::NetInterfaceProvider, "com.affinix.irisnet.NetInterfaceProvider/2.0") -Q_DECLARE_INTERFACE(XMPP::NameProvider, "com.affinix.irisnet.NameProvider/1.0") -Q_DECLARE_INTERFACE(XMPP::ServiceProvider, "com.affinix.irisnet.ServiceProvider/1.0") +Q_DECLARE_INTERFACE(XMPP::NameProvider, "com.affinix.irisnet.NameProvider/1.0") +Q_DECLARE_INTERFACE(XMPP::ServiceProvider, "com.affinix.irisnet.ServiceProvider/1.0") #endif // IRISNETPLUGIN_H diff --git a/src/irisnet/corelib/netavailability.cpp b/src/irisnet/corelib/netavailability.cpp index 782e3c68..1172dcae 100644 --- a/src/irisnet/corelib/netavailability.cpp +++ b/src/irisnet/corelib/netavailability.cpp @@ -19,30 +19,18 @@ #include "netavailability.h" namespace XMPP { -class NetAvailability::Private : public QObject -{ +class NetAvailability::Private : public QObject { Q_OBJECT public: NetAvailability *q; - Private(NetAvailability *_q) : - QObject(_q), - q(_q) - { - } + Private(NetAvailability *_q) : QObject(_q), q(_q) {} }; -NetAvailability::NetAvailability(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} +NetAvailability::NetAvailability(QObject *parent) : QObject(parent) { d = new Private(this); } -NetAvailability::~NetAvailability() -{ - delete d; -} +NetAvailability::~NetAvailability() { delete d; } bool NetAvailability::isAvailable() const { diff --git a/src/irisnet/corelib/netavailability.h b/src/irisnet/corelib/netavailability.h index 884957a6..aa9da916 100644 --- a/src/irisnet/corelib/netavailability.h +++ b/src/irisnet/corelib/netavailability.h @@ -22,8 +22,7 @@ #include "irisnetglobal.h" namespace XMPP { -class NetAvailability : public QObject -{ +class NetAvailability : public QObject { Q_OBJECT public: diff --git a/src/irisnet/corelib/netinterface.cpp b/src/irisnet/corelib/netinterface.cpp index 17564818..4824541d 100644 --- a/src/irisnet/corelib/netinterface.cpp +++ b/src/irisnet/corelib/netinterface.cpp @@ -32,19 +32,22 @@ namespace XMPP { class NetTracker : public QObject { Q_OBJECT public: - QList getInterfaces() { + QList getInterfaces() + { QMutexLocker locker(&m); return info; } - NetTracker() { - QList list = irisNetProviders(); + NetTracker() + { + QList list = irisNetProviders(); c = nullptr; - foreach(IrisNetProvider* p, list) { + foreach (IrisNetProvider *p, list) { c = p->createNetInterfaceProvider(); - if(c) break; + if (c) + break; } Q_ASSERT(c); // we have built-in support, so this should never fail connect(c, SIGNAL(updated()), SLOT(c_updated())); @@ -53,26 +56,29 @@ class NetTracker : public QObject { info = filterList(c->interfaces()); } - ~NetTracker() { + ~NetTracker() + { QMutexLocker locker(&m); delete c; } signals: void updated(); -private: - static QList filterList(const QList &in) { +private: + static QList filterList(const QList &in) + { QList out; - for(int n = 0; n < in.count(); ++n) - { - if(!in[n].isLoopback) out += in[n]; + for (int n = 0; n < in.count(); ++n) { + if (!in[n].isLoopback) + out += in[n]; } return out; } private slots: - void c_updated() { + void c_updated() + { { QMutexLocker locker(&m); info = filterList(c->interfaces()); @@ -82,10 +88,9 @@ private slots: private: // this are all protected by m - NetInterfaceProvider *c; - QMutex m; + NetInterfaceProvider * c; + QMutex m; QList info; - }; // Global because static getRef needs this too. @@ -97,7 +102,8 @@ class NetTrackerThread : public QThread { /** Get a reference to the NetTracker singleton. Calls to getInterfaces will immediately give valid results */ - static NetTrackerThread* getRef() { + static NetTrackerThread *getRef() + { QMutexLocker locker(nettracker_mutex()); if (!self) { @@ -109,7 +115,8 @@ class NetTrackerThread : public QThread { /** Release reference. */ - void releaseRef() { + void releaseRef() + { QMutexLocker locker(nettracker_mutex()); Q_ASSERT(refs > 0); @@ -122,18 +129,19 @@ class NetTrackerThread : public QThread { } } - QList getInterfaces() { - return nettracker->getInterfaces(); - } + QList getInterfaces() { return nettracker->getInterfaces(); } - ~NetTrackerThread() { + ~NetTrackerThread() + { // locked from caller } signals: void updated(); + private: - NetTrackerThread() { + NetTrackerThread() + { // locked from caller refs = 0; moveToThread(QCoreApplication::instance()->thread()); @@ -147,7 +155,8 @@ class NetTrackerThread : public QThread { startMutex = nullptr; } - void run() { + void run() + { { QMutexLocker locker(startMutex); @@ -163,11 +172,11 @@ class NetTrackerThread : public QThread { private: QWaitCondition startCond; - QMutex *startMutex; + QMutex * startMutex; // these are all protected by global nettracker_mutex. - int refs; + int refs; static NetTrackerThread *self; - NetTracker *nettracker; + NetTracker * nettracker; }; NetTrackerThread *NetTrackerThread::self = nullptr; @@ -175,8 +184,7 @@ NetTrackerThread *NetTrackerThread::self = nullptr; //---------------------------------------------------------------------------- // NetInterface //---------------------------------------------------------------------------- -class NetInterfacePrivate : public QObject -{ +class NetInterfacePrivate : public QObject { Q_OBJECT public: friend class NetInterfaceManagerPrivate; @@ -184,36 +192,34 @@ class NetInterfacePrivate : public QObject NetInterface *q; QPointer man; - bool valid; - QString id, name; - QList addrs; + bool valid; + QString id, name; + QList addrs; - NetInterfacePrivate(NetInterface *_q) : QObject(_q), q(_q) - { - valid = false; - } + NetInterfacePrivate(NetInterface *_q) : QObject(_q), q(_q) { valid = false; } void doUnavailable() { - if (!valid) return; + if (!valid) + return; valid = false; - if (man.isNull()) return; + if (man.isNull()) + return; man->unreg(q); emit q->unavailable(); } }; -NetInterface::NetInterface(const QString &id, NetInterfaceManager *manager) - : QObject(manager) +NetInterface::NetInterface(const QString &id, NetInterfaceManager *manager) : QObject(manager) { - d = new NetInterfacePrivate(this); + d = new NetInterfacePrivate(this); d->man = manager; NetInterfaceProvider::Info *info = (NetInterfaceProvider::Info *)d->man->reg(id, this); if (info) { d->valid = true; - d->id = info->id; - d->name = info->name; + d->id = info->id; + d->name = info->name; d->addrs = info->addresses; delete info; } @@ -221,42 +227,30 @@ NetInterface::NetInterface(const QString &id, NetInterfaceManager *manager) NetInterface::~NetInterface() { - if (d->valid && !d->man.isNull()) d->man->unreg(this); + if (d->valid && !d->man.isNull()) + d->man->unreg(this); delete d; } -bool NetInterface::isValid() const -{ - return d->valid && !d->man.isNull(); -} +bool NetInterface::isValid() const { return d->valid && !d->man.isNull(); } -QString NetInterface::id() const -{ - return d->id; -} +QString NetInterface::id() const { return d->id; } -QString NetInterface::name() const -{ - return d->name; -} +QString NetInterface::name() const { return d->name; } -QList NetInterface::addresses() const -{ - return d->addrs; -} +QList NetInterface::addresses() const { return d->addrs; } //---------------------------------------------------------------------------- // NetInterfaceManager //---------------------------------------------------------------------------- -class NetInterfaceManagerPrivate : public QObject -{ +class NetInterfaceManagerPrivate : public QObject { Q_OBJECT public: NetInterfaceManager *q; QList info; - QList listeners; - NetTrackerThread *tracker; + QList listeners; + NetTrackerThread * tracker; bool pending; @@ -267,15 +261,17 @@ class NetInterfaceManagerPrivate : public QObject connect(tracker, SIGNAL(updated()), SLOT(tracker_updated())); } - ~NetInterfaceManagerPrivate() { + ~NetInterfaceManagerPrivate() + { tracker->releaseRef(); tracker = nullptr; } static int lookup(const QList &list, const QString &id) { - for(int n = 0; n < list.count(); ++n) { - if(list[n].id == id) return n; + for (int n = 0; n < list.count(); ++n) { + if (list[n].id == id) + return n; } return -1; } @@ -294,13 +290,12 @@ class NetInterfaceManagerPrivate : public QObject QStringList here_ids, gone_ids; // removed / changed - for(int n = 0; n < info.count(); ++n) - { + for (int n = 0; n < info.count(); ++n) { int i = lookup(newinfo, info[n].id); // id is still here - if(i != -1) { + if (i != -1) { // content changed? - if(!sameContent(info[n], newinfo[i])) { + if (!sameContent(info[n], newinfo[i])) { gone_ids += info[n].id; here_ids += info[n].id; } @@ -310,29 +305,29 @@ class NetInterfaceManagerPrivate : public QObject } // added - for(int n = 0; n < newinfo.count(); ++n) { + for (int n = 0; n < newinfo.count(); ++n) { int i = lookup(info, newinfo[n].id); - if(i == -1) + if (i == -1) here_ids += newinfo[n].id; } info = newinfo; // announce gone - for(int n = 0; n < gone_ids.count(); ++n) { + for (int n = 0; n < gone_ids.count(); ++n) { // work on a copy, just in case the list changes. // it is important to make the copy here, and not // outside the outer loop, in case the items // get deleted - QList list = listeners; - for(int i = 0; i < list.count(); ++i) { - if(list[i]->d->id == gone_ids[n]) { + QList list = listeners; + for (int i = 0; i < list.count(); ++i) { + if (list[i]->d->id == gone_ids[n]) { list[i]->d->doUnavailable(); } } } // announce here - for(int n = 0; n < here_ids.count(); ++n) + for (int n = 0; n < here_ids.count(); ++n) emit q->interfaceAvailable(here_ids[n]); } @@ -340,7 +335,7 @@ public slots: void tracker_updated() { // collapse multiple updates by queuing up an update if there isn't any queued yet. - if(!pending) { + if (!pending) { QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection); pending = true; } @@ -353,22 +348,18 @@ public slots: } }; -NetInterfaceManager::NetInterfaceManager(QObject *parent) - :QObject(parent) +NetInterfaceManager::NetInterfaceManager(QObject *parent) : QObject(parent) { d = new NetInterfaceManagerPrivate(this); } -NetInterfaceManager::~NetInterfaceManager() -{ - delete d; -} +NetInterfaceManager::~NetInterfaceManager() { delete d; } QStringList NetInterfaceManager::interfaces() const { d->info = d->tracker->getInterfaces(); QStringList out; - for(int n = 0; n < d->info.count(); ++n) { + for (int n = 0; n < d->info.count(); ++n) { out += d->info[n].id; } return out; @@ -377,18 +368,19 @@ QStringList NetInterfaceManager::interfaces() const QString NetInterfaceManager::interfaceForAddress(const QHostAddress &a) { NetInterfaceManager netman; - QStringList list = netman.interfaces(); - for(int n = 0; n < list.count(); ++n) { + QStringList list = netman.interfaces(); + for (int n = 0; n < list.count(); ++n) { NetInterface iface(list[n], &netman); - if(iface.addresses().contains(a)) return list[n]; + if (iface.addresses().contains(a)) + return list[n]; } return QString(); } void *NetInterfaceManager::reg(const QString &id, NetInterface *i) { - for(int n = 0; n < d->info.count(); ++n) { - if(d->info[n].id == id) { + for (int n = 0; n < d->info.count(); ++n) { + if (d->info[n].id == id) { d->listeners += i; return new NetInterfaceProvider::Info(d->info[n]); } @@ -396,10 +388,7 @@ void *NetInterfaceManager::reg(const QString &id, NetInterface *i) return nullptr; } -void NetInterfaceManager::unreg(NetInterface *i) -{ - d->listeners.removeAll(i); -} +void NetInterfaceManager::unreg(NetInterface *i) { d->listeners.removeAll(i); } } // namespace XMPP #include "netinterface.moc" diff --git a/src/irisnet/corelib/netinterface.h b/src/irisnet/corelib/netinterface.h index 1d1e7b4a..9bdd939f 100644 --- a/src/irisnet/corelib/netinterface.h +++ b/src/irisnet/corelib/netinterface.h @@ -29,9 +29,11 @@ class NetInterfacePrivate; /** \brief Provides information about a network interface - NetInterface provides information about a particular network interface. Construct it by passing the interface id of interest (e.g. "eth0") and a NetInterfaceManager parent object. Interface ids can be obtained from NetInterfaceManager. + NetInterface provides information about a particular network interface. Construct it by passing the interface id of +interest (e.g. "eth0") and a NetInterfaceManager parent object. Interface ids can be obtained from NetInterfaceManager. - To test if a NetInterface is valid, call isValid(). Use name() to return a display-friendly name of the interface. The addresses() function returns a list of IP addresses for this interface. + To test if a NetInterface is valid, call isValid(). Use name() to return a display-friendly name of the interface. +The addresses() function returns a list of IP addresses for this interface. Here's an example of how to print the IP addresses of eth0: \code @@ -48,14 +50,15 @@ if(iface.isValid()) \sa NetInterfaceManager */ -class IRISNET_EXPORT NetInterface : public QObject -{ +class IRISNET_EXPORT NetInterface : public QObject { Q_OBJECT public: /** \brief Constructs a new interface object with the given \a id and \a manager - If \a id is not a valid interface id, then the object will not be valid (isValid() will return false). Normally it is not necessary to check for validity, since interface ids obtained from NetInterfaceManager are guaranteed to be valid until the event loop resumes. + If \a id is not a valid interface id, then the object will not be valid (isValid() will return false). Normally + it is not necessary to check for validity, since interface ids obtained from NetInterfaceManager are guaranteed + to be valid until the event loop resumes. \sa isValid */ @@ -92,7 +95,8 @@ class IRISNET_EXPORT NetInterface : public QObject /** \brief Returns the addresses of this interface - There will always be at least one address. In some cases there might be multiple, such as on Unix where it is possible for the same interface to have both an IPv4 and an IPv6 address. + There will always be at least one address. In some cases there might be multiple, such as on Unix where it is + possible for the same interface to have both an IPv4 and an IPv6 address. */ QList addresses() const; @@ -100,7 +104,8 @@ class IRISNET_EXPORT NetInterface : public QObject /** \brief Notifies when the interface becomes unavailable - Once this signal is emitted, the NetInterface object becomes invalid and is no longer very useful. A new NetInterface object must be created if a valid object with current information is desired. + Once this signal is emitted, the NetInterface object becomes invalid and is no longer very useful. A new + NetInterface object must be created if a valid object with current information is desired. \note If the interface information changes, the interface is considered to have become unavailable. @@ -122,7 +127,8 @@ class IRISNET_EXPORT NetInterface : public QObject An interface is considered available if it exists, is "Up", has at least one IP address, and is non-Loopback. - The interfaces() function returns a list of available interface ids. These ids can be used with NetInterface to get information about the interfaces. For example, here is how you could print the names of the available interfaces: + The interfaces() function returns a list of available interface ids. These ids can be used with NetInterface to get +information about the interfaces. For example, here is how you could print the names of the available interfaces: \code NetInterfaceManager netman; @@ -134,14 +140,16 @@ for(int n = 0; n < id_list.count(); ++n) } \endcode - When a new network interface is available, the interfaceAvailable() signal will be emitted. Note that interface unavailability is not notified by NetInterfaceManager. Instead, use NetInterface to monitor a specific network interface for unavailability. + When a new network interface is available, the interfaceAvailable() signal will be emitted. Note that interface +unavailability is not notified by NetInterfaceManager. Instead, use NetInterface to monitor a specific network +interface for unavailability. - Interface ids obtained through NetInterfaceManager are guaranteed to be valid until the event loop resumes, or until the next call to interfaces() or interfaceForAddress(). + Interface ids obtained through NetInterfaceManager are guaranteed to be valid until the event loop resumes, or until +the next call to interfaces() or interfaceForAddress(). \sa NetInterface */ -class IRISNET_EXPORT NetInterfaceManager : public QObject -{ +class IRISNET_EXPORT NetInterfaceManager : public QObject { Q_OBJECT public: /** @@ -165,7 +173,8 @@ class IRISNET_EXPORT NetInterfaceManager : public QObject /** \brief Looks up an interface id by IP address - This function looks for an interface that has the address \a a. If there is no such interface, a null string is returned. + This function looks for an interface that has the address \a a. If there is no such interface, a null string is +returned. This is useful for determing the network interface associated with an outgoing QTcpSocket: @@ -193,7 +202,7 @@ QString iface = NetInterfaceManager::interfaceForAddress(tcpSocket->localAddress friend class NetInterfacePrivate; void *reg(const QString &id, NetInterface *i); - void unreg(NetInterface *i); + void unreg(NetInterface *i); }; } // namespace XMPP diff --git a/src/irisnet/corelib/netinterface_qtname.cpp b/src/irisnet/corelib/netinterface_qtname.cpp index ddfcc931..3c96a4e1 100644 --- a/src/irisnet/corelib/netinterface_qtname.cpp +++ b/src/irisnet/corelib/netinterface_qtname.cpp @@ -21,49 +21,40 @@ #include namespace XMPP { -class IrisQtName : public NameProvider -{ +class IrisQtName : public NameProvider { Q_OBJECT Q_INTERFACES(XMPP::NameProvider) struct Query { - bool isHostInfo; + bool isHostInfo; quintptr handle; }; - int currentId; - QHash lookups; - QHash hostInfo; // we need all these tricks with double mapping because we still support Qt 5.5.1. (5.12 is way better) + int currentId; + QHash lookups; + QHash hostInfo; // we need all these tricks with double mapping because we still support Qt 5.5.1. (5.12 + // is way better) public: - IrisQtName(QObject *parent = nullptr) : - NameProvider(parent), - currentId(0) - { - - } + IrisQtName(QObject *parent = nullptr) : NameProvider(parent), currentId(0) {} ~IrisQtName() { - for (auto const &l: lookups) { + for (auto const &l : lookups) { if (!l.isHostInfo) { - delete reinterpret_cast(l.handle); + delete reinterpret_cast(l.handle); } } } - bool supportsSingle() const - { - return true; - } + bool supportsSingle() const { return true; } bool supportsRecordType(int type) const { // yes the types matched to ones from jdns, so it's fine. - static QVector types = { - QDnsLookup::A, QDnsLookup::AAAA, QDnsLookup::ANY, - QDnsLookup::CNAME, QDnsLookup::MX, QDnsLookup::NS, - QDnsLookup::PTR, QDnsLookup::SRV, QDnsLookup::TXT}; + static QVector types + = { QDnsLookup::A, QDnsLookup::AAAA, QDnsLookup::ANY, QDnsLookup::CNAME, QDnsLookup::MX, + QDnsLookup::NS, QDnsLookup::PTR, QDnsLookup::SRV, QDnsLookup::TXT }; return types.contains(type); } @@ -76,22 +67,22 @@ class IrisQtName : public NameProvider QHostAddress addr(QString::fromLatin1(name)); if (!addr.isNull()) { QList results; - XMPP::NameRecord r; + XMPP::NameRecord r; r.setAddress(addr); results.append(r); - QMetaObject::invokeMethod(this, "resolve_resultsReady", Qt::QueuedConnection, - Q_ARG(int, id), Q_ARG(QList, results)); + QMetaObject::invokeMethod(this, "resolve_resultsReady", Qt::QueuedConnection, Q_ARG(int, id), + Q_ARG(QList, results)); } else { if (qType == QDnsLookup::A || qType == QDnsLookup::AAAA) { // QDnsLookup doesn't support A and AAAA according to docs (see corresponding note) int hiid = QHostInfo::lookupHost(QString::fromLatin1(name), this, SLOT(hostInfoFinished(QHostInfo))); hostInfo.insert(hiid, id); - lookups.insert(id, Query{true, quintptr(hiid)}); + lookups.insert(id, Query { true, quintptr(hiid) }); } else { QDnsLookup *lookup = new QDnsLookup((QDnsLookup::Type)qType, QString::fromLatin1(name), this); connect(lookup, SIGNAL(finished()), this, SLOT(handleLookup())); lookup->setProperty("iid", id); - lookups.insert(id, Query{false, quintptr(lookup)}); + lookups.insert(id, Query { false, quintptr(lookup) }); QMetaObject::invokeMethod(lookup, "lookup", Qt::QueuedConnection); } } @@ -109,14 +100,15 @@ class IrisQtName : public NameProvider hostInfo.remove(hiid); lookups.erase(it); } else { - auto lookup = reinterpret_cast(q.handle); + auto lookup = reinterpret_cast(q.handle); lookup->abort(); // handleLookup will catch it and delete } } } private slots: - void hostInfoFinished(const QHostInfo &info) { + void hostInfoFinished(const QHostInfo &info) + { auto hiid = info.lookupId(); auto idIt = hostInfo.find(hiid); if (idIt == hostInfo.end()) { // removed already? @@ -135,7 +127,7 @@ private slots: return; } QList results; - for (const auto &a: info.addresses()) { + for (const auto &a : info.addresses()) { XMPP::NameRecord ir(info.hostName().toLatin1(), 5 * 60); // ttl = 5 mins ir.setAddress(a); results += ir; @@ -146,25 +138,25 @@ private slots: void handleLookup() { QDnsLookup *lookup = static_cast(sender()); - int id = lookup->property("iid").toInt(); + int id = lookup->property("iid").toInt(); lookups.remove(id); if (lookup->error() != QDnsLookup::NoError) { XMPP::NameResolver::Error e; switch (lookup->error()) { - case QDnsLookup::InvalidReplyError: - e = XMPP::NameResolver::ErrorTimeout; - break; - case QDnsLookup::NotFoundError: - e = XMPP::NameResolver::ErrorNoName; - break; - case QDnsLookup::ResolverError: - case QDnsLookup::OperationCancelledError: - case QDnsLookup::InvalidRequestError: - case QDnsLookup::ServerFailureError: - case QDnsLookup::ServerRefusedError: - default: - e = XMPP::NameResolver::ErrorGeneric; - break; + case QDnsLookup::InvalidReplyError: + e = XMPP::NameResolver::ErrorTimeout; + break; + case QDnsLookup::NotFoundError: + e = XMPP::NameResolver::ErrorNoName; + break; + case QDnsLookup::ResolverError: + case QDnsLookup::OperationCancelledError: + case QDnsLookup::InvalidRequestError: + case QDnsLookup::ServerFailureError: + case QDnsLookup::ServerRefusedError: + default: + e = XMPP::NameResolver::ErrorGeneric; + break; } if (lookup->error() != QDnsLookup::OperationCancelledError) { // don't report after resolve_stop() emit resolve_error(id, e); @@ -174,37 +166,37 @@ private slots: } QList results; - for (auto &qtr: lookup->hostAddressRecords()) { + for (auto &qtr : lookup->hostAddressRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setAddress(qtr.value()); results += ir; } - for (auto &qtr: lookup->mailExchangeRecords()) { + for (auto &qtr : lookup->mailExchangeRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setMx(qtr.exchange().toLatin1(), qtr.preference()); results += ir; } - for (auto &qtr: lookup->nameServerRecords()) { + for (auto &qtr : lookup->nameServerRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setNs(qtr.value().toLatin1()); results += ir; } - for (auto &qtr: lookup->pointerRecords()) { + for (auto &qtr : lookup->pointerRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setPtr(qtr.value().toLatin1()); results += ir; } - for (auto &qtr: lookup->canonicalNameRecords()) { + for (auto &qtr : lookup->canonicalNameRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setCname(qtr.value().toLatin1()); results += ir; } - for (auto &qtr: lookup->serviceRecords()) { + for (auto &qtr : lookup->serviceRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); - ir.setSrv(qtr.target().toLatin1(),qtr.port(),qtr.priority(),qtr.weight()); + ir.setSrv(qtr.target().toLatin1(), qtr.port(), qtr.priority(), qtr.weight()); results += ir; } - for (auto &qtr: lookup->textRecords()) { + for (auto &qtr : lookup->textRecords()) { XMPP::NameRecord ir(qtr.name().toLatin1(), qtr.timeToLive()); ir.setTxt(qtr.values()); results += ir; @@ -214,22 +206,14 @@ private slots: } }; -class IrisQtNameProvider : public IrisNetProvider -{ +class IrisQtNameProvider : public IrisNetProvider { Q_OBJECT Q_INTERFACES(XMPP::IrisNetProvider) public: - - NameProvider *createNameProviderInternet() - { - return new IrisQtName; - } + NameProvider *createNameProviderInternet() { return new IrisQtName; } }; -IrisNetProvider *irisnet_createQtNameProvider() -{ - return new IrisQtNameProvider; -} +IrisNetProvider *irisnet_createQtNameProvider() { return new IrisQtNameProvider; } } // namespace XMPP #include "netinterface_qtname.moc" diff --git a/src/irisnet/corelib/netinterface_qtnet.cpp b/src/irisnet/corelib/netinterface_qtnet.cpp index f33079a4..64539f18 100644 --- a/src/irisnet/corelib/netinterface_qtnet.cpp +++ b/src/irisnet/corelib/netinterface_qtnet.cpp @@ -21,12 +21,11 @@ #include namespace XMPP { -class IrisQtNet : public NetInterfaceProvider -{ +class IrisQtNet : public NetInterfaceProvider { Q_OBJECT Q_INTERFACES(XMPP::NetInterfaceProvider) public: - QList info; + QList info; QNetworkConfigurationManager ncm; IrisQtNet() @@ -36,26 +35,20 @@ class IrisQtNet : public NetInterfaceProvider connect(&ncm, SIGNAL(configurationRemoved(QNetworkConfiguration)), SLOT(check())); } - void start() - { - poll(); - } + void start() { poll(); } - QList interfaces() const - { - return info; - } + QList interfaces() const { return info; } void poll() { QList ifaces; - for (auto &iface: QNetworkInterface::allInterfaces()) { + for (auto &iface : QNetworkInterface::allInterfaces()) { Info i; - i.id = iface.name(); - i.name = iface.humanReadableName(); + i.id = iface.name(); + i.name = iface.humanReadableName(); i.isLoopback = (iface.flags() & QNetworkInterface::IsLoopBack); - for (auto &ae: iface.addressEntries()) { + for (auto &ae : iface.addressEntries()) { i.addresses.append(ae.ip()); } ifaces << i; @@ -72,21 +65,14 @@ public slots: } }; -class IrisQtNetProvider : public IrisNetProvider -{ +class IrisQtNetProvider : public IrisNetProvider { Q_OBJECT Q_INTERFACES(XMPP::IrisNetProvider) public: - NetInterfaceProvider *createNetInterfaceProvider() - { - return new IrisQtNet; - } + NetInterfaceProvider *createNetInterfaceProvider() { return new IrisQtNet; } }; -IrisNetProvider *irisnet_createQtNetProvider() -{ - return new IrisQtNetProvider; -} +IrisNetProvider *irisnet_createQtNetProvider() { return new IrisQtNetProvider; } } // namespace XMPP #include "netinterface_qtnet.moc" diff --git a/src/irisnet/corelib/netinterface_unix.cpp b/src/irisnet/corelib/netinterface_unix.cpp index 8cb5765a..47e6c109 100644 --- a/src/irisnet/corelib/netinterface_unix.cpp +++ b/src/irisnet/corelib/netinterface_unix.cpp @@ -31,7 +31,7 @@ #include #include #ifndef SIOCGIFCONF // for solaris -# include +#include #endif #include #include @@ -42,16 +42,15 @@ static QStringList read_proc_as_lines(const char *procfile) QStringList out; FILE *f = fopen(procfile, "r"); - if(!f) + if (!f) return out; QByteArray buf; - while(!feof(f)) - { + while (!feof(f)) { // max read on a proc is 4K QByteArray block(4096, 0); - int ret = fread(block.data(), 1, block.size(), f); - if(ret <= 0) + int ret = fread(block.data(), 1, block.size(), f); + if (ret <= 0) break; block.resize(ret); buf += block; @@ -59,21 +58,20 @@ static QStringList read_proc_as_lines(const char *procfile) fclose(f); QString str = QString::fromLocal8Bit(buf); - out = str.split('\n', QString::SkipEmptyParts); + out = str.split('\n', QString::SkipEmptyParts); return out; } static QHostAddress linux_ipv6_to_qaddr(const QString &in) { QHostAddress out; - if(in.length() != 32) + if (in.length() != 32) return out; quint8 raw[16]; - for(int n = 0; n < 16; ++n) - { + for (int n = 0; n < 16; ++n) { bool ok; - int x = in.mid(n * 2, 2).toInt(&ok, 16); - if(!ok) + int x = in.mid(n * 2, 2).toInt(&ok, 16); + if (!ok) return out; raw[n] = (quint8)x; } @@ -84,17 +82,16 @@ static QHostAddress linux_ipv6_to_qaddr(const QString &in) static QHostAddress linux_ipv4_to_qaddr(const QString &in) { QHostAddress out; - if(in.length() != 8) + if (in.length() != 8) return out; - quint32 raw; + quint32 raw; unsigned char *rawp = (unsigned char *)&raw; - for(int n = 0; n < 4; ++n) - { + for (int n = 0; n < 4; ++n) { bool ok; - int x = in.mid(n * 2, 2).toInt(&ok, 16); - if(!ok) + int x = in.mid(n * 2, 2).toInt(&ok, 16); + if (!ok) return out; - rawp[n] = (unsigned char )x; + rawp[n] = (unsigned char)x; } out.setAddress(raw); return out; @@ -106,22 +103,21 @@ static QList get_linux_gateways() QStringList lines = read_proc_as_lines("/proc/net/route"); // skip the first line, so we start at 1 - for(int n = 1; n < lines.count(); ++n) - { - const QString &line = lines[n]; - QStringList parts = line.simplified().split(' ', QString::SkipEmptyParts); - if(parts.count() < 10) // net-tools does 10, but why not 11? + for (int n = 1; n < lines.count(); ++n) { + const QString &line = lines[n]; + QStringList parts = line.simplified().split(' ', QString::SkipEmptyParts); + if (parts.count() < 10) // net-tools does 10, but why not 11? continue; QHostAddress addr = linux_ipv4_to_qaddr(parts[2]); - if(addr.isNull()) + if (addr.isNull()) continue; int iflags = parts[3].toInt(nullptr, 16); - if(!(iflags & RTF_UP)) + if (!(iflags & RTF_UP)) continue; - if(!(iflags & RTF_GATEWAY)) + if (!(iflags & RTF_GATEWAY)) continue; XMPP::NetGatewayProvider::Info g; @@ -131,22 +127,21 @@ static QList get_linux_gateways() } lines = read_proc_as_lines("/proc/net/ipv6_route"); - for(int n = 0; n < lines.count(); ++n) - { - const QString &line = lines[n]; - QStringList parts = line.simplified().split(' ', QString::SkipEmptyParts); - if(parts.count() < 10) + for (int n = 0; n < lines.count(); ++n) { + const QString &line = lines[n]; + QStringList parts = line.simplified().split(' ', QString::SkipEmptyParts); + if (parts.count() < 10) continue; QHostAddress addr = linux_ipv6_to_qaddr(parts[4]); - if(addr.isNull()) + if (addr.isNull()) continue; int iflags = parts[8].toInt(nullptr, 16); - if(!(iflags & RTF_UP)) + if (!(iflags & RTF_UP)) continue; - if(!(iflags & RTF_GATEWAY)) + if (!(iflags & RTF_GATEWAY)) continue; XMPP::NetGatewayProvider::Info g; @@ -170,35 +165,28 @@ static QList get_unix_gateways() } namespace XMPP { -class UnixGateway : public NetGatewayProvider -{ +class UnixGateway : public NetGatewayProvider { Q_OBJECT Q_INTERFACES(XMPP::NetGatewayProvider) public: QList info; - //QTimer t; + // QTimer t; UnixGateway() //: t(this) { - //connect(&t, SIGNAL(timeout()), SLOT(check())); + // connect(&t, SIGNAL(timeout()), SLOT(check())); // TODO track changes without timers } void start() { - //t.start(5000); + // t.start(5000); poll(); } - QList gateways() const - { - return info; - } + QList gateways() const { return info; } - void poll() - { - info = get_unix_gateways(); - } + void poll() { info = get_unix_gateways(); } public slots: void check() @@ -208,21 +196,14 @@ public slots: } }; -class UnixNetProvider : public IrisNetProvider -{ +class UnixNetProvider : public IrisNetProvider { Q_OBJECT Q_INTERFACES(XMPP::IrisNetProvider) public: - virtual NetGatewayProvider *createNetGatewayProvider() - { - return new UnixGateway; - } + virtual NetGatewayProvider *createNetGatewayProvider() { return new UnixGateway; } }; -IrisNetProvider *irisnet_createUnixNetProvider() -{ - return new UnixNetProvider; -} +IrisNetProvider *irisnet_createUnixNetProvider() { return new UnixNetProvider; } } // namespace XMPP #include "netinterface_unix.moc" diff --git a/src/irisnet/corelib/netnames.cpp b/src/irisnet/corelib/netnames.cpp index c44da895..ae5099fc 100644 --- a/src/irisnet/corelib/netnames.cpp +++ b/src/irisnet/corelib/netnames.cpp @@ -28,92 +28,83 @@ //#define NETNAMES_DEBUG #ifdef NETNAMES_DEBUG -# define NNDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") +#define NNDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif namespace XMPP { //---------------------------------------------------------------------------- // NameRecord //---------------------------------------------------------------------------- -class NameRecord::Private : public QSharedData -{ +class NameRecord::Private : public QSharedData { public: - QByteArray owner; + QByteArray owner; NameRecord::Type type; - int ttl; + int ttl; - QHostAddress address; - QByteArray name; - int priority, weight, port; + QHostAddress address; + QByteArray name; + int priority, weight, port; QList texts; - QByteArray cpu, os; - QByteArray rawData; + QByteArray cpu, os; + QByteArray rawData; }; -#define ENSURE_D { if(!d) d = new Private; } +#define ENSURE_D \ + { \ + if (!d) \ + d = new Private; \ + } -NameRecord::NameRecord() : - d(nullptr) -{ -} +NameRecord::NameRecord() : d(nullptr) {} -NameRecord::NameRecord(const QByteArray &owner, int ttl) : - d(nullptr) +NameRecord::NameRecord(const QByteArray &owner, int ttl) : d(nullptr) { setOwner(owner); setTtl(ttl); } -NameRecord::NameRecord(const NameRecord &from) : - d(nullptr) -{ - *this = from; -} +NameRecord::NameRecord(const NameRecord &from) : d(nullptr) { *this = from; } -NameRecord::~NameRecord() -{ -} +NameRecord::~NameRecord() {} -NameRecord & NameRecord::operator=(const NameRecord &from) +NameRecord &NameRecord::operator=(const NameRecord &from) { d = from.d; return *this; } -bool NameRecord::operator==(const NameRecord &o) { +bool NameRecord::operator==(const NameRecord &o) +{ if (isNull() != o.isNull() || owner() != o.owner() || ttl() != o.ttl() || type() != o.type()) { return false; } switch (type()) { - case XMPP::NameRecord::A: - case XMPP::NameRecord::Aaaa: - return address() == o.address(); - case XMPP::NameRecord::Mx: - return name() == o.name() && priority() == o.priority(); - case XMPP::NameRecord::Srv: - return name() == o.name() && port() == o.port() && priority() == o.priority() && weight() == o.weight(); - case XMPP::NameRecord::Cname: - case XMPP::NameRecord::Ptr: - case XMPP::NameRecord::Ns: - return name() == o.name(); - case XMPP::NameRecord::Txt: - return texts() == o.texts(); - case XMPP::NameRecord::Hinfo: - return cpu() == o.cpu() && os() == o.os(); - case XMPP::NameRecord::Null: - return rawData() == o.rawData(); - case XMPP::NameRecord::Any: - return false; + case XMPP::NameRecord::A: + case XMPP::NameRecord::Aaaa: + return address() == o.address(); + case XMPP::NameRecord::Mx: + return name() == o.name() && priority() == o.priority(); + case XMPP::NameRecord::Srv: + return name() == o.name() && port() == o.port() && priority() == o.priority() && weight() == o.weight(); + case XMPP::NameRecord::Cname: + case XMPP::NameRecord::Ptr: + case XMPP::NameRecord::Ns: + return name() == o.name(); + case XMPP::NameRecord::Txt: + return texts() == o.texts(); + case XMPP::NameRecord::Hinfo: + return cpu() == o.cpu() && os() == o.os(); + case XMPP::NameRecord::Null: + return rawData() == o.rawData(); + case XMPP::NameRecord::Any: + return false; } return false; } -bool NameRecord::isNull() const -{ - return (d ? false : true); -} +bool NameRecord::isNull() const { return (d ? false : true); } QByteArray NameRecord::owner() const { @@ -202,7 +193,7 @@ void NameRecord::setTtl(int seconds) void NameRecord::setAddress(const QHostAddress &a) { ENSURE_D - if(a.protocol() == QAbstractSocket::IPv6Protocol) + if (a.protocol() == QAbstractSocket::IPv6Protocol) d->type = NameRecord::Aaaa; else d->type = NameRecord::A; @@ -212,19 +203,19 @@ void NameRecord::setAddress(const QHostAddress &a) void NameRecord::setMx(const QByteArray &name, int priority) { ENSURE_D - d->type = NameRecord::Mx; - d->name = name; + d->type = NameRecord::Mx; + d->name = name; d->priority = priority; } void NameRecord::setSrv(const QByteArray &name, int port, int priority, int weight) { ENSURE_D - d->type = NameRecord::Srv; - d->name = name; - d->port = port; + d->type = NameRecord::Srv; + d->name = name; + d->port = port; d->priority = priority; - d->weight = weight; + d->weight = weight; } void NameRecord::setCname(const QByteArray &name) @@ -244,7 +235,7 @@ void NameRecord::setPtr(const QByteArray &name) void NameRecord::setTxt(const QList &texts) { ENSURE_D - d->type = NameRecord::Txt; + d->type = NameRecord::Txt; d->texts = texts; } @@ -252,8 +243,8 @@ void NameRecord::setHinfo(const QByteArray &cpu, const QByteArray &os) { ENSURE_D d->type = NameRecord::Hinfo; - d->cpu = cpu; - d->os = os; + d->cpu = cpu; + d->os = os; } void NameRecord::setNs(const QByteArray &name) @@ -266,7 +257,7 @@ void NameRecord::setNs(const QByteArray &name) void NameRecord::setNull(const QByteArray &rawData) { ENSURE_D - d->type = NameRecord::Null; + d->type = NameRecord::Null; d->rawData = rawData; } @@ -274,41 +265,40 @@ QDebug operator<<(QDebug dbg, XMPP::NameRecord::Type type) { dbg.nospace() << "XMPP::NameRecord::"; - switch(type) - { - case XMPP::NameRecord::A: - dbg.nospace() << "A"; - break; - case XMPP::NameRecord::Aaaa: - dbg.nospace() << "Aaaa"; - break; - case XMPP::NameRecord::Mx: - dbg.nospace() << "Mx"; - break; - case XMPP::NameRecord::Srv: - dbg.nospace() << "Srv"; - break; - case XMPP::NameRecord::Cname: - dbg.nospace() << "Cname"; - break; - case XMPP::NameRecord::Ptr: - dbg.nospace() << "Ptr"; - break; - case XMPP::NameRecord::Txt: - dbg.nospace() << "Txt"; - break; - case XMPP::NameRecord::Hinfo: - dbg.nospace() << "Hinfo"; - break; - case XMPP::NameRecord::Ns: - dbg.nospace() << "Ns"; - break; - case XMPP::NameRecord::Null: - dbg.nospace() << "Null"; - break; - case XMPP::NameRecord::Any: - dbg.nospace() << "Any"; - break; + switch (type) { + case XMPP::NameRecord::A: + dbg.nospace() << "A"; + break; + case XMPP::NameRecord::Aaaa: + dbg.nospace() << "Aaaa"; + break; + case XMPP::NameRecord::Mx: + dbg.nospace() << "Mx"; + break; + case XMPP::NameRecord::Srv: + dbg.nospace() << "Srv"; + break; + case XMPP::NameRecord::Cname: + dbg.nospace() << "Cname"; + break; + case XMPP::NameRecord::Ptr: + dbg.nospace() << "Ptr"; + break; + case XMPP::NameRecord::Txt: + dbg.nospace() << "Txt"; + break; + case XMPP::NameRecord::Hinfo: + dbg.nospace() << "Hinfo"; + break; + case XMPP::NameRecord::Ns: + dbg.nospace() << "Ns"; + break; + case XMPP::NameRecord::Null: + dbg.nospace() << "Null"; + break; + case XMPP::NameRecord::Any: + dbg.nospace() << "Any"; + break; } return dbg; @@ -317,47 +307,39 @@ QDebug operator<<(QDebug dbg, XMPP::NameRecord::Type type) QDebug operator<<(QDebug dbg, const XMPP::NameRecord &record) { dbg.nospace() << "XMPP::NameRecord(" - << "owner=" << record.owner() - << ", ttl=" << record.ttl() - << ", type=" << record.type(); - - switch(record.type()) - { - case XMPP::NameRecord::A: - case XMPP::NameRecord::Aaaa: - dbg.nospace() << ", address=" << record.address(); - break; - case XMPP::NameRecord::Mx: - dbg.nospace() - << ", name=" << record.name() - << ", priority=" << record.priority(); - break; - case XMPP::NameRecord::Srv: - dbg.nospace() - << ", name=" << record.name() - << ", port=" << record.port() - << ", priority=" << record.priority() - << ", weight=" << record.weight(); - break; - case XMPP::NameRecord::Cname: - case XMPP::NameRecord::Ptr: - case XMPP::NameRecord::Ns: - dbg.nospace() << ", name=" << record.name(); - break; - case XMPP::NameRecord::Txt: - dbg.nospace() << ", texts={" << record.texts() << "}"; - break; - case XMPP::NameRecord::Hinfo: - dbg.nospace() << ", cpu=" << record.cpu() << ", os=" << record.os(); - break; - case XMPP::NameRecord::Null: - dbg.nospace() << ", size=" << record.rawData().size(); - break; - case XMPP::NameRecord::Any: - dbg.nospace() << ", "; - // should not happen - Q_ASSERT(false); - break; + << "owner=" << record.owner() << ", ttl=" << record.ttl() << ", type=" << record.type(); + + switch (record.type()) { + case XMPP::NameRecord::A: + case XMPP::NameRecord::Aaaa: + dbg.nospace() << ", address=" << record.address(); + break; + case XMPP::NameRecord::Mx: + dbg.nospace() << ", name=" << record.name() << ", priority=" << record.priority(); + break; + case XMPP::NameRecord::Srv: + dbg.nospace() << ", name=" << record.name() << ", port=" << record.port() << ", priority=" << record.priority() + << ", weight=" << record.weight(); + break; + case XMPP::NameRecord::Cname: + case XMPP::NameRecord::Ptr: + case XMPP::NameRecord::Ns: + dbg.nospace() << ", name=" << record.name(); + break; + case XMPP::NameRecord::Txt: + dbg.nospace() << ", texts={" << record.texts() << "}"; + break; + case XMPP::NameRecord::Hinfo: + dbg.nospace() << ", cpu=" << record.cpu() << ", os=" << record.os(); + break; + case XMPP::NameRecord::Null: + dbg.nospace() << ", size=" << record.rawData().size(); + break; + case XMPP::NameRecord::Any: + dbg.nospace() << ", "; + // should not happen + Q_ASSERT(false); + break; } dbg.nospace() << ")"; @@ -368,71 +350,47 @@ QDebug operator<<(QDebug dbg, const XMPP::NameRecord &record) //---------------------------------------------------------------------------- // ServiceInstance //---------------------------------------------------------------------------- -class ServiceInstance::Private : public QSharedData -{ +class ServiceInstance::Private : public QSharedData { public: - QString instance, type, domain; - QMap attribs; - QByteArray name; + QString instance, type, domain; + QMap attribs; + QByteArray name; }; -ServiceInstance::ServiceInstance() : - d(new Private) -{ -} +ServiceInstance::ServiceInstance() : d(new Private) {} -ServiceInstance::ServiceInstance(const QString &instance, const QString &type, const QString &domain, const QMap &attribs) : +ServiceInstance::ServiceInstance(const QString &instance, const QString &type, const QString &domain, + const QMap &attribs) : d(new Private) { d->instance = instance; - d->type = type; - d->domain = domain; - d->attribs = attribs; + d->type = type; + d->domain = domain; + d->attribs = attribs; // FIXME: escape the items d->name = instance.toLatin1() + '.' + type.toLatin1() + '.' + domain.toLatin1(); } -ServiceInstance::ServiceInstance(const ServiceInstance &from) : - d(nullptr) -{ - *this = from; -} +ServiceInstance::ServiceInstance(const ServiceInstance &from) : d(nullptr) { *this = from; } -ServiceInstance::~ServiceInstance() -{ -} +ServiceInstance::~ServiceInstance() {} -ServiceInstance & ServiceInstance::operator=(const ServiceInstance &from) +ServiceInstance &ServiceInstance::operator=(const ServiceInstance &from) { d = from.d; return *this; } -QString ServiceInstance::instance() const -{ - return d->instance; -} +QString ServiceInstance::instance() const { return d->instance; } -QString ServiceInstance::type() const -{ - return d->type; -} +QString ServiceInstance::type() const { return d->type; } -QString ServiceInstance::domain() const -{ - return d->domain; -} +QString ServiceInstance::domain() const { return d->domain; } -QMap ServiceInstance::attributes() const -{ - return d->attribs; -} +QMap ServiceInstance::attributes() const { return d->attribs; } -QByteArray ServiceInstance::name() const -{ - return d->name; -} +QByteArray ServiceInstance::name() const { return d->name; } //---------------------------------------------------------------------------- // NameManager @@ -442,74 +400,60 @@ class NameManager; Q_GLOBAL_STATIC(QMutex, nman_mutex) static NameManager *g_nman = nullptr; -class NameResolver::Private -{ +class NameResolver::Private { public: NameResolver *q; - int type; + int type; bool longLived; - int id; + int id; - Private(NameResolver *_q) : q(_q) - { - } + Private(NameResolver *_q) : q(_q) {} }; -class ServiceBrowser::Private -{ +class ServiceBrowser::Private { public: ServiceBrowser *q; int id; - Private(ServiceBrowser *_q) : q(_q) - { - } + Private(ServiceBrowser *_q) : q(_q) {} }; -class ServiceResolver::Private : public QObject -{ +class ServiceResolver::Private : public QObject { Q_OBJECT public: - Private(ServiceResolver *parent) - : q(parent), dns_sd_resolve_id(0), requestedProtocol(IPv6_IPv4), port(0), protocol(QAbstractSocket::IPv6Protocol) + Private(ServiceResolver *parent) : + q(parent), dns_sd_resolve_id(0), requestedProtocol(IPv6_IPv4), port(0), protocol(QAbstractSocket::IPv6Protocol) { } /* DNS-SD interaction with NameManager */ - ServiceResolver *q; //!< Pointing upwards, so NameManager can call its signals - int dns_sd_resolve_id; //!< DNS-SD lookup id, set by NameManager + ServiceResolver *q; //!< Pointing upwards, so NameManager can call its signals + int dns_sd_resolve_id; //!< DNS-SD lookup id, set by NameManager /* configuration */ Protocol requestedProtocol; //!< IP protocol requested by user /* state trackers */ - QString domain; //!< Domain we are currently looking up - QString host; //!< Hostname we are currently looking up - QHostAddress address; //!< IP address we are currently looking up - quint16 port; //!< Port we are currently looking up + QString domain; //!< Domain we are currently looking up + QString host; //!< Hostname we are currently looking up + QHostAddress address; //!< IP address we are currently looking up + quint16 port; //!< Port we are currently looking up QAbstractSocket::NetworkLayerProtocol protocol; //!< IP protocol we are currently looking up - XMPP::WeightedNameRecordList srvList; //!< List of resolved SRV names - QList hostList; //!< List or resolved hostnames for current SRV name - QList resolverList; //!< NameResolvers currently in use, needed for cleanup - + XMPP::WeightedNameRecordList srvList; //!< List of resolved SRV names + QList hostList; //!< List or resolved hostnames for current SRV name + QList resolverList; //!< NameResolvers currently in use, needed for cleanup }; -WeightedNameRecordList::WeightedNameRecordList() - : currentPriorityGroup(priorityGroups.end()) /* void current state */ -{} - -WeightedNameRecordList::WeightedNameRecordList(const QList &list) +WeightedNameRecordList::WeightedNameRecordList() : currentPriorityGroup(priorityGroups.end()) /* void current state */ { - append(list); } -WeightedNameRecordList::WeightedNameRecordList(const WeightedNameRecordList &other) -{ - *this = other; -} +WeightedNameRecordList::WeightedNameRecordList(const QList &list) { append(list); } + +WeightedNameRecordList::WeightedNameRecordList(const WeightedNameRecordList &other) { *this = other; } WeightedNameRecordList &WeightedNameRecordList::operator=(const WeightedNameRecordList &other) { @@ -522,14 +466,15 @@ WeightedNameRecordList &WeightedNameRecordList::operator=(const WeightedNameReco return *this; } -WeightedNameRecordList::~WeightedNameRecordList() { -} +WeightedNameRecordList::~WeightedNameRecordList() {} -bool WeightedNameRecordList::isEmpty() const { +bool WeightedNameRecordList::isEmpty() const +{ return currentPriorityGroup == const_cast(this)->priorityGroups.end(); } -XMPP::NameRecord WeightedNameRecordList::takeNext() { +XMPP::NameRecord WeightedNameRecordList::takeNext() +{ /* Find the next useful priority group */ while (currentPriorityGroup != priorityGroups.end() && currentPriorityGroup->empty()) { ++currentPriorityGroup; @@ -553,7 +498,7 @@ XMPP::NameRecord WeightedNameRecordList::takeNext() { #endif /* Pick a random entry */ - int randomWeight = qrand()/static_cast(RAND_MAX)*totalWeight; + int randomWeight = qrand() / static_cast(RAND_MAX) * totalWeight; #ifdef NETNAMES_DEBUG NNDEBUG << "Picked weight:" << randomWeight; @@ -561,7 +506,8 @@ XMPP::NameRecord WeightedNameRecordList::takeNext() { /* Iterate through the priority group until we found the randomly selected entry */ WeightedNameRecordPriorityGroup::iterator it(currentPriorityGroup->begin()); - for (int currentWeight = it->weight(); currentWeight < randomWeight; currentWeight += (++it)->weight()) {} + for (int currentWeight = it->weight(); currentWeight < randomWeight; currentWeight += (++it)->weight()) { + } Q_ASSERT(it != currentPriorityGroup->end()); /* We are going to delete the entry in the list, so save it */ @@ -580,17 +526,19 @@ XMPP::NameRecord WeightedNameRecordList::takeNext() { return result; } -void WeightedNameRecordList::clear() { +void WeightedNameRecordList::clear() +{ priorityGroups.clear(); /* void current state */ currentPriorityGroup = priorityGroups.end(); } -void WeightedNameRecordList::append(const XMPP::WeightedNameRecordList &list) { +void WeightedNameRecordList::append(const XMPP::WeightedNameRecordList &list) +{ /* Copy over all records from all groups */ foreach (const WeightedNameRecordPriorityGroup &group, list.priorityGroups) { - foreach(const NameRecord& record, group) { + foreach (const NameRecord &record, group) { append(record); } } @@ -599,7 +547,8 @@ void WeightedNameRecordList::append(const XMPP::WeightedNameRecordList &list) { currentPriorityGroup = priorityGroups.begin(); } -void WeightedNameRecordList::append(const QList &list) { +void WeightedNameRecordList::append(const QList &list) +{ foreach (const XMPP::NameRecord &record, list) { if (record.type() != XMPP::NameRecord::Srv) { continue; @@ -617,7 +566,8 @@ void WeightedNameRecordList::append(const QList &list) { currentPriorityGroup = priorityGroups.begin(); } -void WeightedNameRecordList::append(const XMPP::NameRecord &record) { +void WeightedNameRecordList::append(const XMPP::NameRecord &record) +{ WeightedNameRecordPriorityGroup group(priorityGroups.value(record.priority())); Q_ASSERT(record.type() == XMPP::NameRecord::Srv); @@ -631,7 +581,8 @@ void WeightedNameRecordList::append(const XMPP::NameRecord &record) { currentPriorityGroup = priorityGroups.begin(); } -void WeightedNameRecordList::append(const QString &hostname, quint16 port) { +void WeightedNameRecordList::append(const QString &hostname, quint16 port) +{ NameRecord record(hostname.toLocal8Bit(), std::numeric_limits::max()); record.setSrv(hostname.toLocal8Bit(), port, std::numeric_limits::max(), 0); @@ -641,32 +592,37 @@ void WeightedNameRecordList::append(const QString &hostname, quint16 port) { currentPriorityGroup = priorityGroups.begin(); } -XMPP::WeightedNameRecordList& WeightedNameRecordList::operator<<(const XMPP::WeightedNameRecordList &list) { +XMPP::WeightedNameRecordList &WeightedNameRecordList::operator<<(const XMPP::WeightedNameRecordList &list) +{ append(list); return *this; } -WeightedNameRecordList& WeightedNameRecordList::operator<<(const QList &list) { +WeightedNameRecordList &WeightedNameRecordList::operator<<(const QList &list) +{ append(list); return *this; } -XMPP::WeightedNameRecordList& WeightedNameRecordList::operator<<(const XMPP::NameRecord &record) { +XMPP::WeightedNameRecordList &WeightedNameRecordList::operator<<(const XMPP::NameRecord &record) +{ append(record); return *this; } -QDebug operator<<(QDebug dbg, const XMPP::WeightedNameRecordList &list) { +QDebug operator<<(QDebug dbg, const XMPP::WeightedNameRecordList &list) +{ dbg.nospace() << "XMPP::WeightedNameRecordList(\n"; - /* operator(QDebug, QMap const&) has a bug which makes it crash when trying to print the dereferenced end() iterator */ + /* operator(QDebug, QMap const&) has a bug which makes it crash when trying to print the dereferenced end() iterator + */ if (!list.isEmpty()) { dbg.nospace() << "current=" << *list.currentPriorityGroup << endl; } dbg.nospace() << "{"; - foreach(int priority, list.priorityGroups.keys()) { + foreach (int priority, list.priorityGroups.keys()) { dbg.nospace() << "\t" << priority << "->" << list.priorityGroups.value(priority) << endl; } @@ -674,36 +630,32 @@ QDebug operator<<(QDebug dbg, const XMPP::WeightedNameRecordList &list) { return dbg; } -class ServiceLocalPublisher::Private -{ +class ServiceLocalPublisher::Private { public: ServiceLocalPublisher *q; int id; - Private(ServiceLocalPublisher *_q) : q(_q) - { - } + Private(ServiceLocalPublisher *_q) : q(_q) {} }; -class NameManager : public QObject -{ +class NameManager : public QObject { Q_OBJECT public: - NameProvider *p_net, *p_local; - ServiceProvider *p_serv; - QHash res_instances; - QHash res_sub_instances; + NameProvider * p_net, *p_local; + ServiceProvider * p_serv; + QHash res_instances; + QHash res_sub_instances; - QHash br_instances; - QHash sres_instances; - QHash slp_instances; + QHash br_instances; + QHash sres_instances; + QHash slp_instances; NameManager(QObject *parent = nullptr) : QObject(parent) { - p_net = nullptr; + p_net = nullptr; p_local = nullptr; - p_serv = 0; + p_serv = 0; } ~NameManager() @@ -716,8 +668,7 @@ class NameManager : public QObject static NameManager *instance() { QMutexLocker locker(nman_mutex()); - if(!g_nman) - { + if (!g_nman) { g_nman = new NameManager; irisNetAddPostRoutine(NetNames::cleanup); } @@ -734,33 +685,33 @@ class NameManager : public QObject { QMutexLocker locker(nman_mutex()); - np->type = qType; + np->type = qType; np->longLived = longLived; - if(!p_net) - { - NameProvider *c = 0; - QList list = irisNetProviders(); - for(int n = 0; n < list.count(); ++n) - { + if (!p_net) { + NameProvider * c = 0; + QList list = irisNetProviders(); + for (int n = 0; n < list.count(); ++n) { IrisNetProvider *p = list[n]; - c = p->createNameProviderInternet(); - if(c) + c = p->createNameProviderInternet(); + if (c) break; } Q_ASSERT(c); // we have built-in support, so this should never fail p_net = c; // use queued connections - qRegisterMetaType< QList >("QList"); + qRegisterMetaType>("QList"); qRegisterMetaType("XMPP::NameResolver::Error"); - connect(p_net, SIGNAL(resolve_resultsReady(int,QList)), SLOT(provider_resolve_resultsReady(int,QList))); - connect(p_net, SIGNAL(resolve_error(int,XMPP::NameResolver::Error)), SLOT(provider_resolve_error(int,XMPP::NameResolver::Error))); - connect(p_net, SIGNAL(resolve_useLocal(int,QByteArray)), SLOT(provider_resolve_useLocal(int,QByteArray))); + connect(p_net, SIGNAL(resolve_resultsReady(int, QList)), + SLOT(provider_resolve_resultsReady(int, QList))); + connect(p_net, SIGNAL(resolve_error(int, XMPP::NameResolver::Error)), + SLOT(provider_resolve_error(int, XMPP::NameResolver::Error))); + connect(p_net, SIGNAL(resolve_useLocal(int, QByteArray)), SLOT(provider_resolve_useLocal(int, QByteArray))); } np->id = p_net->resolve_start(name, qType, longLived); - //printf("assigning %d to %p\n", req_id, np); + // printf("assigning %d to %p\n", req_id, np); res_instances.insert(np->id, np); } @@ -775,17 +726,15 @@ class NameManager : public QObject { // clean up any sub instances - QList sub_instances_to_remove; + QList sub_instances_to_remove; QHashIterator it(res_sub_instances); - while(it.hasNext()) - { + while (it.hasNext()) { it.next(); - if(it.value() == np->id) + if (it.value() == np->id) sub_instances_to_remove += it.key(); } - foreach(int res_sub_id, sub_instances_to_remove) - { + foreach (int res_sub_id, sub_instances_to_remove) { res_sub_instances.remove(res_sub_id); p_local->resolve_stop(res_sub_id); } @@ -802,15 +751,13 @@ class NameManager : public QObject { QMutexLocker locker(nman_mutex()); - if(!p_serv) - { - ServiceProvider *c = nullptr; - QList list = irisNetProviders(); - for(int n = 0; n < list.count(); ++n) - { + if (!p_serv) { + ServiceProvider * c = nullptr; + QList list = irisNetProviders(); + for (int n = 0; n < list.count(); ++n) { IrisNetProvider *p = list[n]; - c = p->createServiceProvider(); - if(c) + c = p->createServiceProvider(); + if (c) break; } Q_ASSERT(c); // we have built-in support, so this should never fail @@ -820,9 +767,12 @@ class NameManager : public QObject qRegisterMetaType("XMPP::ServiceInstance"); qRegisterMetaType("XMPP::ServiceBrowser::Error"); - connect(p_serv, SIGNAL(browse_instanceAvailable(int,XMPP::ServiceInstance)), SLOT(provider_browse_instanceAvailable(int,XMPP::ServiceInstance)), Qt::QueuedConnection); - connect(p_serv, SIGNAL(browse_instanceUnavailable(int,XMPP::ServiceInstance)), SLOT(provider_browse_instanceUnavailable(int,XMPP::ServiceInstance)), Qt::QueuedConnection); - connect(p_serv, SIGNAL(browse_error(int,XMPP::ServiceBrowser::Error)), SLOT(provider_browse_error(int,XMPP::ServiceBrowser::Error)), Qt::QueuedConnection); + connect(p_serv, SIGNAL(browse_instanceAvailable(int, XMPP::ServiceInstance)), + SLOT(provider_browse_instanceAvailable(int, XMPP::ServiceInstance)), Qt::QueuedConnection); + connect(p_serv, SIGNAL(browse_instanceUnavailable(int, XMPP::ServiceInstance)), + SLOT(provider_browse_instanceUnavailable(int, XMPP::ServiceInstance)), Qt::QueuedConnection); + connect(p_serv, SIGNAL(browse_error(int, XMPP::ServiceBrowser::Error)), + SLOT(provider_browse_error(int, XMPP::ServiceBrowser::Error)), Qt::QueuedConnection); } /*np->id = */ @@ -836,15 +786,13 @@ class NameManager : public QObject { QMutexLocker locker(nman_mutex()); - if(!p_serv) - { - ServiceProvider *c = nullptr; - QList list = irisNetProviders(); - for(int n = 0; n < list.count(); ++n) - { + if (!p_serv) { + ServiceProvider * c = nullptr; + QList list = irisNetProviders(); + for (int n = 0; n < list.count(); ++n) { IrisNetProvider *p = list[n]; - c = p->createServiceProvider(); - if(c) + c = p->createServiceProvider(); + if (c) break; } Q_ASSERT(c); // we have built-in support, so this should never fail @@ -852,8 +800,11 @@ class NameManager : public QObject // use queued connections qRegisterMetaType("QHostAddress"); - qRegisterMetaType< QList >("QList"); - connect(p_serv, SIGNAL(resolve_resultsReady(int,QList)), SLOT(provider_resolve_resultsReady(int,QList)), Qt::QueuedConnection); + qRegisterMetaType>( + "QList"); + connect(p_serv, SIGNAL(resolve_resultsReady(int, QList)), + SLOT(provider_resolve_resultsReady(int, QList)), + Qt::QueuedConnection); } /* store the id so we can stop it later */ @@ -862,19 +813,18 @@ class NameManager : public QObject sres_instances.insert(np->dns_sd_resolve_id, np); } - void publish_start(ServiceLocalPublisher::Private *np, const QString &instance, const QString &type, int port, const QMap &attribs) + void publish_start(ServiceLocalPublisher::Private *np, const QString &instance, const QString &type, int port, + const QMap &attribs) { QMutexLocker locker(nman_mutex()); - if(!p_serv) - { - ServiceProvider *c = nullptr; - QList list = irisNetProviders(); - for(int n = 0; n < list.count(); ++n) - { + if (!p_serv) { + ServiceProvider * c = nullptr; + QList list = irisNetProviders(); + for (int n = 0; n < list.count(); ++n) { IrisNetProvider *p = list[n]; - c = p->createServiceProvider(); - if(c) + c = p->createServiceProvider(); + if (c) break; } Q_ASSERT(c); // we have built-in support, so this should never fail @@ -882,8 +832,10 @@ class NameManager : public QObject // use queued connections qRegisterMetaType("XMPP::ServiceLocalPublisher::Error"); - connect(p_serv, SIGNAL(publish_published(int)), SLOT(provider_publish_published(int)), Qt::QueuedConnection); - connect(p_serv, SIGNAL(publish_extra_published(int)), SLOT(provider_publish_extra_published(int)), Qt::QueuedConnection); + connect(p_serv, SIGNAL(publish_published(int)), SLOT(provider_publish_published(int)), + Qt::QueuedConnection); + connect(p_serv, SIGNAL(publish_extra_published(int)), SLOT(provider_publish_extra_published(int)), + Qt::QueuedConnection); } /*np->id = */ @@ -902,8 +854,8 @@ private slots: void provider_resolve_resultsReady(int id, const QList &results) { NameResolver::Private *np = res_instances.value(id); - NameResolver *q = np->q; // resolve_cleanup deletes np - if(!np->longLived) + NameResolver * q = np->q; // resolve_cleanup deletes np + if (!np->longLived) resolve_cleanup(np); emit q->resultsReady(results); } @@ -911,16 +863,16 @@ private slots: void provider_resolve_error(int id, XMPP::NameResolver::Error e) { NameResolver::Private *np = res_instances.value(id); - NameResolver *q = np->q; // resolve_cleanup deletes np + NameResolver * q = np->q; // resolve_cleanup deletes np resolve_cleanup(np); emit q->error(e); } void provider_local_resolve_resultsReady(int id, const QList &results) { - int par_id = res_sub_instances.value(id); - NameResolver::Private *np = res_instances.value(par_id); - if(!np->longLived) + int par_id = res_sub_instances.value(id); + NameResolver::Private *np = res_instances.value(par_id); + if (!np->longLived) res_sub_instances.remove(id); p_net->resolve_localResultsReady(par_id, results); } @@ -935,15 +887,13 @@ private slots: void provider_resolve_useLocal(int id, const QByteArray &name) { // transfer to local - if(!p_local) - { - NameProvider *c = nullptr; - QList list = irisNetProviders(); - for(int n = 0; n < list.count(); ++n) - { + if (!p_local) { + NameProvider * c = nullptr; + QList list = irisNetProviders(); + for (int n = 0; n < list.count(); ++n) { IrisNetProvider *p = list[n]; - c = p->createNameProviderLocal(); - if(c) + c = p->createNameProviderLocal(); + if (c) break; } Q_ASSERT(c); // we have built-in support, so this should never fail @@ -951,10 +901,12 @@ private slots: p_local = c; // use queued connections - qRegisterMetaType< QList >("QList"); + qRegisterMetaType>("QList"); qRegisterMetaType("XMPP::NameResolver::Error"); - connect(p_local, SIGNAL(resolve_resultsReady(int,QList)), SLOT(provider_local_resolve_resultsReady(int,QList)), Qt::QueuedConnection); - connect(p_local, SIGNAL(resolve_error(int,XMPP::NameResolver::Error)), SLOT(provider_local_resolve_error(int,XMPP::NameResolver::Error)), Qt::QueuedConnection); + connect(p_local, SIGNAL(resolve_resultsReady(int, QList)), + SLOT(provider_local_resolve_resultsReady(int, QList)), Qt::QueuedConnection); + connect(p_local, SIGNAL(resolve_error(int, XMPP::NameResolver::Error)), + SLOT(provider_local_resolve_error(int, XMPP::NameResolver::Error)), Qt::QueuedConnection); } NameResolver::Private *np = res_instances.value(id); @@ -982,13 +934,13 @@ private slots: void provider_browse_instanceAvailable(int id, const XMPP::ServiceInstance &i) { ServiceBrowser::Private *np = br_instances.value(id); - emit np->q->instanceAvailable(i); + emit np->q->instanceAvailable(i); } void provider_browse_instanceUnavailable(int id, const XMPP::ServiceInstance &i) { ServiceBrowser::Private *np = br_instances.value(id); - emit np->q->instanceUnavailable(i); + emit np->q->instanceUnavailable(i); } void provider_browse_error(int id, XMPP::ServiceBrowser::Error e) @@ -1002,20 +954,20 @@ private slots: void provider_resolve_resultsReady(int id, const QList &results) { ServiceResolver::Private *np = sres_instances.value(id); - emit np->q->resultReady(results[0].address, results[0].port); + emit np->q->resultReady(results[0].address, results[0].port); } void provider_publish_published(int id) { ServiceLocalPublisher::Private *np = slp_instances.value(id); - emit np->q->published(); + emit np->q->published(); } void provider_publish_extra_published(int id) { Q_UNUSED(id); - //ServiceLocalPublisher::Private *np = slp_instances.value(id); - //emit np->q->published(); + // ServiceLocalPublisher::Private *np = slp_instances.value(id); + // emit np->q->published(); } }; @@ -1024,61 +976,63 @@ private slots: //---------------------------------------------------------------------------- // copied from JDNS -#define JDNS_RTYPE_A 1 -#define JDNS_RTYPE_AAAA 28 -#define JDNS_RTYPE_MX 15 -#define JDNS_RTYPE_SRV 33 -#define JDNS_RTYPE_CNAME 5 -#define JDNS_RTYPE_PTR 12 -#define JDNS_RTYPE_TXT 16 -#define JDNS_RTYPE_HINFO 13 -#define JDNS_RTYPE_NS 2 -#define JDNS_RTYPE_ANY 255 +#define JDNS_RTYPE_A 1 +#define JDNS_RTYPE_AAAA 28 +#define JDNS_RTYPE_MX 15 +#define JDNS_RTYPE_SRV 33 +#define JDNS_RTYPE_CNAME 5 +#define JDNS_RTYPE_PTR 12 +#define JDNS_RTYPE_TXT 16 +#define JDNS_RTYPE_HINFO 13 +#define JDNS_RTYPE_NS 2 +#define JDNS_RTYPE_ANY 255 static int recordType2Rtype(NameRecord::Type type) { - switch(type) - { - case NameRecord::A: return JDNS_RTYPE_A; - case NameRecord::Aaaa: return JDNS_RTYPE_AAAA; - case NameRecord::Mx: return JDNS_RTYPE_MX; - case NameRecord::Srv: return JDNS_RTYPE_SRV; - case NameRecord::Cname: return JDNS_RTYPE_CNAME; - case NameRecord::Ptr: return JDNS_RTYPE_PTR; - case NameRecord::Txt: return JDNS_RTYPE_TXT; - case NameRecord::Hinfo: return JDNS_RTYPE_HINFO; - case NameRecord::Ns: return JDNS_RTYPE_NS; - case NameRecord::Null: return 10; - case NameRecord::Any: return JDNS_RTYPE_ANY; + switch (type) { + case NameRecord::A: + return JDNS_RTYPE_A; + case NameRecord::Aaaa: + return JDNS_RTYPE_AAAA; + case NameRecord::Mx: + return JDNS_RTYPE_MX; + case NameRecord::Srv: + return JDNS_RTYPE_SRV; + case NameRecord::Cname: + return JDNS_RTYPE_CNAME; + case NameRecord::Ptr: + return JDNS_RTYPE_PTR; + case NameRecord::Txt: + return JDNS_RTYPE_TXT; + case NameRecord::Hinfo: + return JDNS_RTYPE_HINFO; + case NameRecord::Ns: + return JDNS_RTYPE_NS; + case NameRecord::Null: + return 10; + case NameRecord::Any: + return JDNS_RTYPE_ANY; } return -1; } -NameResolver::NameResolver(QObject *parent) -:QObject(parent) -{ - d = nullptr; -} +NameResolver::NameResolver(QObject *parent) : QObject(parent) { d = nullptr; } -NameResolver::~NameResolver() -{ - stop(); -} +NameResolver::~NameResolver() { stop(); } void NameResolver::start(const QByteArray &name, NameRecord::Type type, Mode mode) { stop(); - d = new Private(this); + d = new Private(this); int qType = recordType2Rtype(type); - if(qType == -1) + if (qType == -1) qType = JDNS_RTYPE_A; NameManager::instance()->resolve_start(d, name, qType, mode == NameResolver::LongLived ? true : false); } void NameResolver::stop() { - if(d) - { + if (d) { NameManager::instance()->resolve_stop(d); delete d; d = nullptr; @@ -1089,23 +1043,22 @@ QDebug operator<<(QDebug dbg, XMPP::NameResolver::Error e) { dbg.nospace() << "XMPP::NameResolver::"; - switch(e) - { - case XMPP::NameResolver::ErrorGeneric: - dbg.nospace() << "ErrorGeneric"; - break; - case XMPP::NameResolver::ErrorNoName: - dbg.nospace() << "ErrorNoName"; - break; - case XMPP::NameResolver::ErrorTimeout: - dbg.nospace() << "ErrorTimeout"; - break; - case XMPP::NameResolver::ErrorNoLocal: - dbg.nospace() << "ErrorNoLocal"; - break; - case XMPP::NameResolver::ErrorNoLongLived: - dbg.nospace() << "ErrorNoLongLived"; - break; + switch (e) { + case XMPP::NameResolver::ErrorGeneric: + dbg.nospace() << "ErrorGeneric"; + break; + case XMPP::NameResolver::ErrorNoName: + dbg.nospace() << "ErrorNoName"; + break; + case XMPP::NameResolver::ErrorTimeout: + dbg.nospace() << "ErrorTimeout"; + break; + case XMPP::NameResolver::ErrorNoLocal: + dbg.nospace() << "ErrorNoLocal"; + break; + case XMPP::NameResolver::ErrorNoLongLived: + dbg.nospace() << "ErrorNoLongLived"; + break; } return dbg; @@ -1114,31 +1067,21 @@ QDebug operator<<(QDebug dbg, XMPP::NameResolver::Error e) //---------------------------------------------------------------------------- // ServiceBrowser //---------------------------------------------------------------------------- -ServiceBrowser::ServiceBrowser(QObject *parent) -:QObject(parent) -{ - d = new Private(this); -} +ServiceBrowser::ServiceBrowser(QObject *parent) : QObject(parent) { d = new Private(this); } -ServiceBrowser::~ServiceBrowser() -{ - delete d; -} +ServiceBrowser::~ServiceBrowser() { delete d; } void ServiceBrowser::start(const QString &type, const QString &domain) { NameManager::instance()->browse_start(d, type, domain); } -void ServiceBrowser::stop() -{ -} +void ServiceBrowser::stop() {} //---------------------------------------------------------------------------- // ServiceResolver //---------------------------------------------------------------------------- -ServiceResolver::ServiceResolver(QObject *parent) - : QObject(parent) +ServiceResolver::ServiceResolver(QObject *parent) : QObject(parent) { #ifdef NETNAMES_DEBUG NNDEBUG; @@ -1147,10 +1090,7 @@ ServiceResolver::ServiceResolver(QObject *parent) d = new Private(this); } -ServiceResolver::~ServiceResolver() -{ - delete d; -} +ServiceResolver::~ServiceResolver() { delete d; } void ServiceResolver::clear_resolvers() { @@ -1184,18 +1124,12 @@ void ServiceResolver::cleanup_resolver(XMPP::NameResolver *resolver) } } -ServiceResolver::Protocol ServiceResolver::protocol() const { - return d->requestedProtocol; -} +ServiceResolver::Protocol ServiceResolver::protocol() const { return d->requestedProtocol; } -void ServiceResolver::setProtocol(ServiceResolver::Protocol p) { - d->requestedProtocol = p; -} +void ServiceResolver::setProtocol(ServiceResolver::Protocol p) { d->requestedProtocol = p; } /* DNS-SD lookup */ -void ServiceResolver::start(const QByteArray &name) { - NameManager::instance()->resolve_instance_start(d, name); -} +void ServiceResolver::start(const QByteArray &name) { NameManager::instance()->resolve_instance_start(d, name); } /* normal host lookup */ void ServiceResolver::start(const QString &host, quint16 port) @@ -1207,19 +1141,23 @@ void ServiceResolver::start(const QString &host, quint16 port) /* clear host list */ d->hostList.clear(); - d->protocol = (d->requestedProtocol == IPv6_IPv4 || d->requestedProtocol == IPv6 ? QAbstractSocket::IPv6Protocol : QAbstractSocket::IPv4Protocol); - d->host = host; - d->port = port; + d->protocol = (d->requestedProtocol == IPv6_IPv4 || d->requestedProtocol == IPv6 ? QAbstractSocket::IPv6Protocol + : QAbstractSocket::IPv4Protocol); + d->host = host; + d->port = port; #ifdef NETNAMES_DEBUG NNDEBUG << "d->p:" << d->protocol; #endif /* initiate the host lookup */ - XMPP::NameRecord::Type querytype = (d->protocol == QAbstractSocket::IPv6Protocol ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A); + XMPP::NameRecord::Type querytype + = (d->protocol == QAbstractSocket::IPv6Protocol ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A); XMPP::NameResolver *resolver = new XMPP::NameResolver; - connect(resolver, SIGNAL(resultsReady(QList)), this, SLOT(handle_host_ready(QList))); - connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, SLOT(handle_host_error(XMPP::NameResolver::Error))); + connect(resolver, SIGNAL(resultsReady(QList)), this, + SLOT(handle_host_ready(QList))); + connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, + SLOT(handle_host_error(XMPP::NameResolver::Error))); resolver->start(host.toLocal8Bit(), querytype); d->resolverList << resolver; } @@ -1241,16 +1179,17 @@ void ServiceResolver::start(const QString &service, const QString &transport, co /* after we tried all SRV hosts, we shall connect directly (if requested) */ if (port < std::numeric_limits::max()) { d->srvList.append(domain.toLocal8Bit(), port); - } - else { + } else { /* The only "valid" port above the valid port range is our specification of an invalid port */ Q_ASSERT(port == std::numeric_limits::max()); } /* initiate the SRV lookup */ XMPP::NameResolver *resolver = new XMPP::NameResolver; - connect(resolver, SIGNAL(resultsReady(QList)), this, SLOT(handle_srv_ready(QList))); - connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, SLOT(handle_srv_error(XMPP::NameResolver::Error))); + connect(resolver, SIGNAL(resultsReady(QList)), this, + SLOT(handle_srv_ready(QList))); + connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, + SLOT(handle_srv_error(XMPP::NameResolver::Error))); resolver->start(srv_request.toLocal8Bit(), XMPP::NameRecord::Srv); d->resolverList << resolver; } @@ -1263,7 +1202,7 @@ void ServiceResolver::handle_srv_ready(const QList &r) #endif /* cleanup resolver */ - cleanup_resolver(static_cast(sender())); + cleanup_resolver(static_cast(sender())); /* lookup srv pointers */ d->srvList << r; @@ -1283,7 +1222,7 @@ void ServiceResolver::handle_srv_error(XMPP::NameResolver::Error e) #endif /* cleanup resolver */ - cleanup_resolver(static_cast(sender())); + cleanup_resolver(static_cast(sender())); /* srvList already contains a failsafe host, try that */ emit srvFailed(); @@ -1300,7 +1239,7 @@ void ServiceResolver::handle_host_ready(const QList &r) #endif /* cleanup resolver */ - cleanup_resolver(static_cast(sender())); + cleanup_resolver(static_cast(sender())); /* connect to host */ d->hostList << r; @@ -1315,7 +1254,7 @@ void ServiceResolver::handle_host_error(XMPP::NameResolver::Error e) #endif /* cleanup resolver */ - cleanup_resolver(static_cast(sender())); + cleanup_resolver(static_cast(sender())); /* try a fallback lookup if requested*/ if (!lookup_host_fallback()) { @@ -1334,7 +1273,7 @@ void ServiceResolver::handle_host_fallback_error(XMPP::NameResolver::Error e) #endif /* cleanup resolver */ - cleanup_resolver(static_cast(sender())); + cleanup_resolver(static_cast(sender())); /* lookup next SRV */ try_next_srv(); @@ -1348,7 +1287,8 @@ bool ServiceResolver::check_protocol_fallback() } /* lookup the fallback host */ -bool ServiceResolver::lookup_host_fallback() { +bool ServiceResolver::lookup_host_fallback() +{ #ifdef NETNAMES_DEBUG NNDEBUG; #endif @@ -1358,17 +1298,21 @@ bool ServiceResolver::lookup_host_fallback() { return false; } - d->protocol = (d->protocol == QAbstractSocket::IPv6Protocol ? QAbstractSocket::IPv4Protocol : QAbstractSocket::IPv6Protocol); + d->protocol = (d->protocol == QAbstractSocket::IPv6Protocol ? QAbstractSocket::IPv4Protocol + : QAbstractSocket::IPv6Protocol); #ifdef NETNAMES_DEBUG NNDEBUG << "d->p:" << d->protocol; #endif /* initiate the fallback host lookup */ - XMPP::NameRecord::Type querytype = (d->protocol == QAbstractSocket::IPv6Protocol ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A); + XMPP::NameRecord::Type querytype + = (d->protocol == QAbstractSocket::IPv6Protocol ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A); XMPP::NameResolver *resolver = new XMPP::NameResolver; - connect(resolver, SIGNAL(resultsReady(QList)), this, SLOT(handle_host_ready(QList))); - connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, SLOT(handle_host_fallback_error(XMPP::NameResolver::Error))); + connect(resolver, SIGNAL(resultsReady(QList)), this, + SLOT(handle_host_ready(QList))); + connect(resolver, SIGNAL(error(XMPP::NameResolver::Error)), this, + SLOT(handle_host_fallback_error(XMPP::NameResolver::Error))); resolver->start(d->host.toLocal8Bit(), querytype); d->resolverList << resolver; @@ -1376,7 +1320,8 @@ bool ServiceResolver::lookup_host_fallback() { } /* notify user about next host */ -bool ServiceResolver::try_next_host() { +bool ServiceResolver::try_next_host() +{ #ifdef NETNAMES_DEBUG NNDEBUG << "hl:" << d->hostList; #endif @@ -1405,8 +1350,7 @@ void ServiceResolver::try_next_srv() XMPP::NameRecord record(d->srvList.takeNext()); /* lookup host by name and specify port for later use */ start(record.name(), record.port()); - } - else { + } else { #ifdef NETNAMES_DEBUG NNDEBUG << "SRV list empty, failing"; #endif @@ -1415,21 +1359,17 @@ void ServiceResolver::try_next_srv() } } -void ServiceResolver::tryNext() { +void ServiceResolver::tryNext() +{ /* if the host list cannot help, try the SRV list */ if (!try_next_host()) { - try_next_srv(); + try_next_srv(); } } -void ServiceResolver::stop() { - clear_resolvers(); -} +void ServiceResolver::stop() { clear_resolvers(); } -bool ServiceResolver::hasPendingSrv() const -{ - return !d->srvList.isEmpty(); -} +bool ServiceResolver::hasPendingSrv() const { return !d->srvList.isEmpty(); } ServiceResolver::ProtoSplit ServiceResolver::happySplit() { @@ -1437,57 +1377,40 @@ ServiceResolver::ProtoSplit ServiceResolver::happySplit() ProtoSplit s; s.ipv4 = new ServiceResolver(this); s.ipv4->setProtocol(IPv4); - s.ipv4->d->srvList = d->srvList; + s.ipv4->d->srvList = d->srvList; s.ipv4->d->hostList = d->hostList; - s.ipv4->d->domain = d->domain; - s.ipv6 = new ServiceResolver(this); + s.ipv4->d->domain = d->domain; + s.ipv6 = new ServiceResolver(this); s.ipv6->setProtocol(IPv6); - s.ipv6->d->srvList = d->srvList; + s.ipv6->d->srvList = d->srvList; s.ipv6->d->hostList = d->hostList; - s.ipv6->d->domain = d->domain; + s.ipv6->d->domain = d->domain; return s; } //---------------------------------------------------------------------------- // ServiceLocalPublisher //---------------------------------------------------------------------------- -ServiceLocalPublisher::ServiceLocalPublisher(QObject *parent) -:QObject(parent) -{ - d = new Private(this); -} +ServiceLocalPublisher::ServiceLocalPublisher(QObject *parent) : QObject(parent) { d = new Private(this); } -ServiceLocalPublisher::~ServiceLocalPublisher() -{ - delete d; -} +ServiceLocalPublisher::~ServiceLocalPublisher() { delete d; } -void ServiceLocalPublisher::publish(const QString &instance, const QString &type, int port, const QMap &attributes) +void ServiceLocalPublisher::publish(const QString &instance, const QString &type, int port, + const QMap &attributes) { NameManager::instance()->publish_start(d, instance, type, port, attributes); } -void ServiceLocalPublisher::updateAttributes(const QMap &attributes) -{ - Q_UNUSED(attributes); -} +void ServiceLocalPublisher::updateAttributes(const QMap &attributes) { Q_UNUSED(attributes); } -void ServiceLocalPublisher::addRecord(const NameRecord &rec) -{ - NameManager::instance()->publish_extra_start(d, rec); -} +void ServiceLocalPublisher::addRecord(const NameRecord &rec) { NameManager::instance()->publish_extra_start(d, rec); } -void ServiceLocalPublisher::cancel() -{ -} +void ServiceLocalPublisher::cancel() {} //---------------------------------------------------------------------------- // NetNames //---------------------------------------------------------------------------- -void NetNames::cleanup() -{ - NameManager::cleanup(); -} +void NetNames::cleanup() { NameManager::cleanup(); } QString NetNames::diagnosticText() { diff --git a/src/irisnet/corelib/netnames.h b/src/irisnet/corelib/netnames.h index f5989875..87a9e093 100644 --- a/src/irisnet/corelib/netnames.h +++ b/src/irisnet/corelib/netnames.h @@ -28,14 +28,13 @@ // it seems visual studio defines it somewhere #ifdef max -# undef max +#undef max #endif namespace XMPP { class NameManager; -class IRISNET_EXPORT NetNames -{ +class IRISNET_EXPORT NetNames { public: // free any shared data, shutdown internal dns sessions if necessary. static void cleanup(); @@ -45,7 +44,7 @@ class IRISNET_EXPORT NetNames // convert idn names static QByteArray idnaFromString(const QString &in); - static QString idnaToString(const QByteArray &in); + static QString idnaToString(const QByteArray &in); // dns escaping static QByteArray escapeDomain(const QByteArray &in); @@ -58,9 +57,13 @@ class IRISNET_EXPORT NetNames /** \brief Provides a DNS record - NameRecord provides a DNS (Domain Name System) record, which is information assicated with a domain name. For most purposes, the information is an IP address. However, DNS records are capable of holding a variety of data types, such as named pointers to other domain names and even arbitrary text strings. The results of a NameResolver operation are a list of NameRecords. + NameRecord provides a DNS (Domain Name System) record, which is information assicated with a domain name. For most +purposes, the information is an IP address. However, DNS records are capable of holding a variety of data types, such +as named pointers to other domain names and even arbitrary text strings. The results of a NameResolver operation are a +list of NameRecords. - The most common type is the address record, "A", which contains an IPv4 address. Here is an example of how to get the IP address out of an address record: + The most common type is the address record, "A", which contains an IPv4 address. Here is an example of how to get +the IP address out of an address record: \code NameRecord record = ... // obtain a record from somewhere @@ -71,9 +74,13 @@ if(record.type() == NameRecord::A) } \endcode - Getting the data out of a NameRecord involves calling the right retrieval functions, depending on the type. Many types share retrieval functions. For example, the "AAAA" type holds an IPv6 address, which is accessed the same way as the "A" type, by calling address(). See the NameRecord::Type enum for further information about which retrieval functions should be called for each type. + Getting the data out of a NameRecord involves calling the right retrieval functions, depending on the type. Many +types share retrieval functions. For example, the "AAAA" type holds an IPv6 address, which is accessed the same way as +the "A" type, by calling address(). See the NameRecord::Type enum for further information about which retrieval +functions should be called for each type. - To create a NameRecord, use setOwner() and setTtl() as necessary, and then call one of the setX functions (where X is the desired type). For example, to set an A or AAAA record, use setAddress() like this: + To create a NameRecord, use setOwner() and setTtl() as necessary, and then call one of the setX functions +(where X is the desired type). For example, to set an A or AAAA record, use setAddress() like this: \code // make example.com the owner, with 1 hour TTL @@ -81,20 +88,19 @@ NameRecord record("example.com", 3600); record.setAddress(QHostAddress("1.2.3.4")); \endcode - Note that in the case of setAddress(), the record type need not be specified. NameRecord will determine the type to use based on the given QHostAddress. + Note that in the case of setAddress(), the record type need not be specified. NameRecord will determine the type to +use based on the given QHostAddress. \sa NameResolver */ -class IRISNET_EXPORT NameRecord -{ +class IRISNET_EXPORT NameRecord { public: /** \brief The type of DNS record The retrieval functions are shown for each type. */ - enum Type - { + enum Type { A, ///< IPv4 address. Use address(). Aaaa, ///< IPv6 address. Use address(). Mx, ///< Mail server. Use name() and priority(). @@ -105,7 +111,7 @@ class IRISNET_EXPORT NameRecord Hinfo, ///< Host information. Use cpu() and os(). Ns, ///< Name server. Use name(). Null, ///< Null type. Use rawData(). - Any ///< "Any record", for use with NameResolver::start() only. A NameRecord object will never be of this type. + Any ///< "Any record", for use with NameResolver::start() only. A NameRecord object will never be of this type. }; /** @@ -118,7 +124,8 @@ class IRISNET_EXPORT NameRecord /** \brief Constructs a partially initialized record object, with the given \a owner and \a ttl - For the record to be usable, call an appropriate setX function (where X is the desired type) afterwards. + For the record to be usable, call an appropriate setX function (where X is the desired type) + afterwards. */ NameRecord(const QByteArray &owner, int ttl); @@ -135,7 +142,7 @@ class IRISNET_EXPORT NameRecord /** \brief Assigns \a from to this object and returns a reference to this object */ - NameRecord & operator=(const NameRecord &from); + NameRecord &operator=(const NameRecord &from); /** \brief Compares \a other with this object @@ -145,14 +152,17 @@ class IRISNET_EXPORT NameRecord /** \brief Returns true if this record object is null, otherwise returns false - Be sure not to confuse a null object with the NULL type (NameRecord::Null). Don't ask why DNS has a type called NULL that contains valid data. + Be sure not to confuse a null object with the NULL type (NameRecord::Null). Don't ask why DNS has a type called + NULL that contains valid data. */ bool isNull() const; // don't confuse with Null type /** \brief Returns the owner of this record - The owner is usually not a useful attribute, since it will be the same as the name searched for with NameResolver. For example, if the A record of "example.com" is looked up, then the resulting records will all have "example.com" as the owner. + The owner is usually not a useful attribute, since it will be the same as the name searched for with + NameResolver. For example, if the A record of "example.com" is looked up, then the resulting records will all + have "example.com" as the owner. \sa setOwner */ @@ -161,9 +171,11 @@ class IRISNET_EXPORT NameRecord /** \brief Returns the TTL (time-to-live) of this record - This is the number of seconds the record should be considered valid, which is useful information when performing caching. + This is the number of seconds the record should be considered valid, which is useful information when performing + caching. - As a special exception, a TTL of 0 when performing a long-lived lookup indicates that a record is no longer available. + As a special exception, a TTL of 0 when performing a long-lived lookup indicates that a record is no longer + available. \sa setTtl */ @@ -306,20 +318,20 @@ class IRISNET_EXPORT NameRecord IRISNET_EXPORT QDebug operator<<(QDebug, XMPP::NameRecord::Type); IRISNET_EXPORT QDebug operator<<(QDebug, const XMPP::NameRecord &); -class IRISNET_EXPORT ServiceInstance -{ +class IRISNET_EXPORT ServiceInstance { public: ServiceInstance(); - ServiceInstance(const QString &instance, const QString &type, const QString &domain, const QMap &attributes); + ServiceInstance(const QString &instance, const QString &type, const QString &domain, + const QMap &attributes); ServiceInstance(const ServiceInstance &from); ~ServiceInstance(); - ServiceInstance & operator=(const ServiceInstance &from); + ServiceInstance &operator=(const ServiceInstance &from); - QString instance() const; - QString type() const; - QString domain() const; - QMap attributes() const; - QByteArray name() const; // full dns label + QString instance() const; + QString type() const; + QString domain() const; + QMap attributes() const; + QByteArray name() const; // full dns label private: class Private; @@ -331,9 +343,11 @@ class IRISNET_EXPORT ServiceInstance /** \brief Represents a DNS query/lookup - NameResolver performs an asynchronous DNS lookup for a given domain name and record type. Call start() to begin. The resultsReady() signal is emitted on success, otherwise error() is emitted. To cancel a lookup, call stop(). + NameResolver performs an asynchronous DNS lookup for a given domain name and record type. Call start() to begin. The +resultsReady() signal is emitted on success, otherwise error() is emitted. To cancel a lookup, call stop(). - Each NameResolver object can only perform one DNS lookup at a time. If start() is called while a lookup is already in progress, then the existing lookup is stopped before starting the new lookup. + Each NameResolver object can only perform one DNS lookup at a time. If start() is called while a lookup is already +in progress, then the existing lookup is stopped before starting the new lookup. Each NameResolver object should be used for just one DNS query and then be deleted. Otherwise ambiguity might arise when receiving multiple answers to future queries. @@ -368,51 +382,56 @@ void dns_error(XMPP::NameResolver::Error error) } \endcode - Yes, a domain name can have multiple IP addresses. Many applications ignore this fact, and use only one of the answers. A proper network application should try connecting to each IP address until one succeeds. + Yes, a domain name can have multiple IP addresses. Many applications ignore this fact, and use only one of the +answers. A proper network application should try connecting to each IP address until one succeeds. - To lookup other types, pass the desired type to start(). For example, suppose you want to look up the MX record of a domain name: + To lookup other types, pass the desired type to start(). For example, suppose you want to look up the MX record of a +domain name: \code // look up the MX record for affinix.com resolver->start("affinix.com", NameRecord::Mx); \endcode - It is also possible to perform long-lived queries. This is generally useful for DNS Service Discovery. Long-lived queries are continuous, and resultsReady() may be emitted multiple times. Unlike a normal lookup, which stops once the results are returned, a long-lived query will keep going until stop() is called. + It is also possible to perform long-lived queries. This is generally useful for DNS Service Discovery. Long-lived +queries are continuous, and resultsReady() may be emitted multiple times. Unlike a normal lookup, which stops once the +results are returned, a long-lived query will keep going until stop() is called. - For example, suppose you want to scan the local network for SSH services. According to the DNS-SD protocol, this is done by querying for the name "_ssh._tcp.local." of type PTR. + For example, suppose you want to scan the local network for SSH services. According to the DNS-SD protocol, this is +done by querying for the name "_ssh._tcp.local." of type PTR. \code // monitor for SSH services on the local network resolver->start("_ssh._tcp.local.", NameRecord::Ptr, NameResolver::LongLived); \endcode - Don't be alarmed by the trailing dot (".") character in this last example. It is not well known, but all valid DNS domain names end with a dot. However, NameResolver, like most DNS programming interfaces, allows the dot to be left out. What this means is that if a trailing dot is missing in the input to start(), NameResolver will internally append one before performing the query. + Don't be alarmed by the trailing dot (".") character in this last example. It is not well known, but all valid DNS +domain names end with a dot. However, NameResolver, like most DNS programming interfaces, allows the dot to be left +out. What this means is that if a trailing dot is missing in the input to start(), NameResolver will internally append +one before performing the query. \sa NameRecord */ -class IRISNET_EXPORT NameResolver : public QObject -{ +class IRISNET_EXPORT NameResolver : public QObject { Q_OBJECT public: /** \brief Resolve mode */ - enum Mode - { - Single, ///< A normal DNS query with a single result set. - LongLived ///< An endless query, with multiple result sets allowed. + enum Mode { + Single, ///< A normal DNS query with a single result set. + LongLived ///< An endless query, with multiple result sets allowed. }; /** \brief Resolve error */ - enum Error - { - ErrorGeneric, ///< General failure during lookup, no further details. - ErrorNoName, ///< Name does not exist. - ErrorTimeout, ///< The operation timed out. - ErrorNoLocal, ///< The query is to the local network, but no mechanism for Multicast DNS is available. - ErrorNoLongLived ///< The query requires long-lived capability, but no mechanism for doing so is available. + enum Error { + ErrorGeneric, ///< General failure during lookup, no further details. + ErrorNoName, ///< Name does not exist. + ErrorTimeout, ///< The operation timed out. + ErrorNoLocal, ///< The query is to the local network, but no mechanism for Multicast DNS is available. + ErrorNoLongLived ///< The query requires long-lived capability, but no mechanism for doing so is available. }; /** @@ -430,7 +449,8 @@ class IRISNET_EXPORT NameResolver : public QObject /** \brief Starts a lookup - A lookup for \a name of \a type is started. For normal queries, \a mode should be NameResolver::Single (this is the default). For long-lived queries, use NameResolver::LongLived. + A lookup for \a name of \a type is started. For normal queries, \a mode should be NameResolver::Single (this is + the default). For long-lived queries, use NameResolver::LongLived. If a lookup is already in progress, it is stopped before starting the new lookup. @@ -441,7 +461,8 @@ class IRISNET_EXPORT NameResolver : public QObject /** \brief Stops a lookup - Use this function if you want to stop the current lookup, such that the resolver object may be reused again later. If you don't plan to reuse the object, then destroying the object is enough. + Use this function if you want to stop the current lookup, such that the resolver object may be reused again + later. If you don't plan to reuse the object, then destroying the object is enough. \sa start */ @@ -451,16 +472,21 @@ class IRISNET_EXPORT NameResolver : public QObject /** \brief Notification of result records - This signal is emitted when results of the lookup operation have arrived. The \a results parameter is a list of NameRecords. All records will be of the type queried for with start(), unless the NameRecord::Any type was specified, in which case the records may be of any type + This signal is emitted when results of the lookup operation have arrived. The \a results parameter is a list of + NameRecords. All records will be of the type queried for with start(), unless the NameRecord::Any type was + specified, in which case the records may be of any type - When using the NameResolver::Single mode, the lookup is stopped once results are ready. However, with the NameResolver::LongLived mode, the lookup stays active, and in that case this signal may be emitted multiple times. + When using the NameResolver::Single mode, the lookup is stopped once results are ready. However, with the + NameResolver::LongLived mode, the lookup stays active, and in that case this signal may be emitted multiple + times. */ void resultsReady(const QList &results); /** \brief Notification of error - This signal is emitted if an error has occurred while performing a lookup. The reason for error can be found in \a e. Regardless of the mode used, the lookup is stopped when an error occurs. + This signal is emitted if an error has occurred while performing a lookup. The reason for error can be found in + \a e. Regardless of the mode used, the lookup is stopped when an error occurs. */ void error(XMPP::NameResolver::Error e); @@ -474,49 +500,42 @@ class IRISNET_EXPORT NameResolver : public QObject IRISNET_EXPORT QDebug operator<<(QDebug, XMPP::NameResolver::Error); -class IRISNET_EXPORT WeightedNameRecordList -{ - friend QDebug operator<<(QDebug, const WeightedNameRecordList&); +class IRISNET_EXPORT WeightedNameRecordList { + friend QDebug operator<<(QDebug, const WeightedNameRecordList &); public: WeightedNameRecordList(); WeightedNameRecordList(const QList &list); WeightedNameRecordList(const WeightedNameRecordList &other); - WeightedNameRecordList& operator=(const WeightedNameRecordList &other); + WeightedNameRecordList &operator=(const WeightedNameRecordList &other); ~WeightedNameRecordList(); - bool isEmpty() const; //!< Returns true if the list contains no items; otherwise returns false. - NameRecord takeNext(); //!< Removes the next host to try from the list and returns it. + bool isEmpty() const; //!< Returns true if the list contains no items; otherwise returns false. + NameRecord takeNext(); //!< Removes the next host to try from the list and returns it. void clear(); //!< Removes all items from the list. - void append(const WeightedNameRecordList&); - void append(const QList&); - void append(const NameRecord&); + void append(const WeightedNameRecordList &); + void append(const QList &); + void append(const NameRecord &); void append(const QString &hostname, quint16 port); - WeightedNameRecordList& operator<<(const WeightedNameRecordList&); - WeightedNameRecordList& operator<<(const QList&); - WeightedNameRecordList& operator<<(const NameRecord&); + WeightedNameRecordList &operator<<(const WeightedNameRecordList &); + WeightedNameRecordList &operator<<(const QList &); + WeightedNameRecordList &operator<<(const NameRecord &); private: - typedef QMultiMap WeightedNameRecordPriorityGroup; + typedef QMultiMap WeightedNameRecordPriorityGroup; typedef QMap WNRL; - WNRL priorityGroups; + WNRL priorityGroups; WNRL::iterator currentPriorityGroup; }; -QDebug operator<<(QDebug, const XMPP::WeightedNameRecordList&); +QDebug operator<<(QDebug, const XMPP::WeightedNameRecordList &); -class IRISNET_EXPORT ServiceBrowser : public QObject -{ +class IRISNET_EXPORT ServiceBrowser : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric, - ErrorNoLocal, - ErrorNoWide - }; + enum Error { ErrorGeneric, ErrorNoLocal, ErrorNoWide }; ServiceBrowser(QObject *parent = nullptr); ~ServiceBrowser(); @@ -560,12 +579,10 @@ class IRISNET_EXPORT ServiceBrowser : public QObject 8) host[] empty -> (9) 9) Try servername directly */ -class IRISNET_EXPORT ServiceResolver : public QObject -{ +class IRISNET_EXPORT ServiceResolver : public QObject { Q_OBJECT public: - struct ProtoSplit - { + struct ProtoSplit { ServiceResolver *ipv4; ServiceResolver *ipv6; }; @@ -573,8 +590,10 @@ class IRISNET_EXPORT ServiceResolver : public QObject /*! Error codes for (SRV) lookups */ enum Error { ServiceNotFound, //!< There is no service with the specified parameters - NoHostLeft, //!< we did all we could, none of the found host seemed to suffice the users needs - ErrorGeneric, ErrorTimeout, ErrorNoLocal // Stuff that netnames_jdns.cpp needs ... + NoHostLeft, //!< we did all we could, none of the found host seemed to suffice the users needs + ErrorGeneric, + ErrorTimeout, + ErrorNoLocal // Stuff that netnames_jdns.cpp needs ... }; /*! Order of lookup / IP protocols to try */ enum Protocol { IPv6_IPv4, IPv4_IPv6, HappyEyeballs, IPv6, IPv4 }; @@ -586,8 +605,8 @@ class IRISNET_EXPORT ServiceResolver : public QObject ServiceResolver(QObject *parent = nullptr); ~ServiceResolver(); - Protocol protocol() const; //!< IP protocol to use, defaults to IPv6_IPv4 - void setProtocol(Protocol); //!< Set IP protocol to use, \sa protocol + Protocol protocol() const; //!< IP protocol to use, defaults to IPv6_IPv4 + void setProtocol(Protocol); //!< Set IP protocol to use, \sa protocol /*! * Start a DNS-SD lookup @@ -608,7 +627,8 @@ class IRISNET_EXPORT ServiceResolver : public QObject * \param domain Domainname to lookup * \param port Specify a valid port number to make ServiceResolver fallback to domain:port */ - void start(const QString &service, const QString &transport, const QString &domain, int port = std::numeric_limits::max()); + void start(const QString &service, const QString &transport, const QString &domain, + int port = std::numeric_limits::max()); /*! Announce the next resolved host, \sa resultReady */ void tryNext(); @@ -637,15 +657,15 @@ class IRISNET_EXPORT ServiceResolver : public QObject void srvFailed(); private slots: - void handle_srv_ready(const QList&); + void handle_srv_ready(const QList &); void handle_srv_error(XMPP::NameResolver::Error); - void handle_host_ready(const QList&); + void handle_host_ready(const QList &); void handle_host_error(XMPP::NameResolver::Error); void handle_host_fallback_error(XMPP::NameResolver::Error); private: void clear_resolvers(); - void cleanup_resolver(XMPP::NameResolver*); + void cleanup_resolver(XMPP::NameResolver *); bool check_protocol_fallback(); bool lookup_host_fallback(); bool try_next_host(); @@ -658,12 +678,10 @@ private slots: friend class NameManager; }; -class IRISNET_EXPORT ServiceLocalPublisher : public QObject -{ +class IRISNET_EXPORT ServiceLocalPublisher : public QObject { Q_OBJECT public: - enum Error - { + enum Error { ErrorGeneric, // generic error ErrorConflict, // name in use ErrorNoLocal // unable to setup multicast dns @@ -672,8 +690,8 @@ class IRISNET_EXPORT ServiceLocalPublisher : public QObject ServiceLocalPublisher(QObject *parent = nullptr); ~ServiceLocalPublisher(); - void publish(const QString &instance, const QString &type, int port, const QMap &attributes); - void updateAttributes(const QMap &attributes); + void publish(const QString &instance, const QString &type, int port, const QMap &attributes); + void updateAttributes(const QMap &attributes); void addRecord(const NameRecord &rec); void cancel(); diff --git a/src/irisnet/corelib/netnames_jdns.cpp b/src/irisnet/corelib/netnames_jdns.cpp index 008eddcc..311d986a 100644 --- a/src/irisnet/corelib/netnames_jdns.cpp +++ b/src/irisnet/corelib/netnames_jdns.cpp @@ -24,7 +24,7 @@ //#define JDNS_DEBUG Q_DECLARE_METATYPE(XMPP::NameRecord) -//Q_DECLARE_METATYPE(XMPP::NameResolver::Error) +// Q_DECLARE_METATYPE(XMPP::NameResolver::Error) Q_DECLARE_METATYPE(XMPP::ServiceBrowser::Error) Q_DECLARE_METATYPE(XMPP::ServiceResolver::Error) Q_DECLARE_METATYPE(XMPP::ServiceLocalPublisher::Error) @@ -33,20 +33,39 @@ namespace XMPP { static NameRecord importJDNSRecord(const QJDns::Record &in) { NameRecord out; - switch(in.type) - { - case QJDns::A: out.setAddress(in.address); break; - case QJDns::Aaaa: out.setAddress(in.address); break; - case QJDns::Mx: out.setMx(in.name, in.priority); break; - case QJDns::Srv: out.setSrv(in.name, in.port, in.priority, in.weight); break; - case QJDns::Cname: out.setCname(in.name); break; - case QJDns::Ptr: out.setPtr(in.name); break; - case QJDns::Txt: out.setTxt(in.texts); break; - case QJDns::Hinfo: out.setHinfo(in.cpu, in.os); break; - case QJDns::Ns: out.setNs(in.name); break; - case 10: out.setNull(in.rdata); break; - default: - return out; + switch (in.type) { + case QJDns::A: + out.setAddress(in.address); + break; + case QJDns::Aaaa: + out.setAddress(in.address); + break; + case QJDns::Mx: + out.setMx(in.name, in.priority); + break; + case QJDns::Srv: + out.setSrv(in.name, in.port, in.priority, in.weight); + break; + case QJDns::Cname: + out.setCname(in.name); + break; + case QJDns::Ptr: + out.setPtr(in.name); + break; + case QJDns::Txt: + out.setTxt(in.texts); + break; + case QJDns::Hinfo: + out.setHinfo(in.cpu, in.os); + break; + case QJDns::Ns: + out.setNs(in.name); + break; + case 10: + out.setNull(in.rdata); + break; + default: + return out; } out.setOwner(in.owner); out.setTtl(in.ttl); @@ -56,90 +75,87 @@ static NameRecord importJDNSRecord(const QJDns::Record &in) static QJDns::Record exportJDNSRecord(const NameRecord &in) { QJDns::Record out; - switch(in.type()) - { - case NameRecord::A: - out.type = QJDns::A; - out.haveKnown = true; - out.address = in.address(); - break; - case NameRecord::Aaaa: - out.type = QJDns::Aaaa; - out.haveKnown = true; - out.address = in.address(); - break; - case NameRecord::Mx: - out.type = QJDns::Mx; - out.haveKnown = true; - out.name = in.name(); - out.priority = in.priority(); - break; - case NameRecord::Srv: - out.type = QJDns::Srv; - out.haveKnown = true; - out.name = in.name(); - out.port = in.port(); - out.priority = in.priority(); - out.weight = in.weight(); - break; - case NameRecord::Cname: - out.type = QJDns::Cname; - out.haveKnown = true; - out.name = in.name(); - break; - case NameRecord::Ptr: - out.type = QJDns::Ptr; - out.haveKnown = true; - out.name = in.name(); - break; - case NameRecord::Txt: - out.type = QJDns::Txt; - out.haveKnown = true; - out.texts = in.texts(); - break; - case NameRecord::Hinfo: - out.type = QJDns::Hinfo; - out.haveKnown = true; - out.cpu = in.cpu(); - out.os = in.os(); - break; - case NameRecord::Ns: - out.type = QJDns::Ns; - out.haveKnown = true; - out.name = in.name(); - break; - case NameRecord::Null: - out.type = 10; - out.rdata = in.rawData(); - break; - default: - return out; + switch (in.type()) { + case NameRecord::A: + out.type = QJDns::A; + out.haveKnown = true; + out.address = in.address(); + break; + case NameRecord::Aaaa: + out.type = QJDns::Aaaa; + out.haveKnown = true; + out.address = in.address(); + break; + case NameRecord::Mx: + out.type = QJDns::Mx; + out.haveKnown = true; + out.name = in.name(); + out.priority = in.priority(); + break; + case NameRecord::Srv: + out.type = QJDns::Srv; + out.haveKnown = true; + out.name = in.name(); + out.port = in.port(); + out.priority = in.priority(); + out.weight = in.weight(); + break; + case NameRecord::Cname: + out.type = QJDns::Cname; + out.haveKnown = true; + out.name = in.name(); + break; + case NameRecord::Ptr: + out.type = QJDns::Ptr; + out.haveKnown = true; + out.name = in.name(); + break; + case NameRecord::Txt: + out.type = QJDns::Txt; + out.haveKnown = true; + out.texts = in.texts(); + break; + case NameRecord::Hinfo: + out.type = QJDns::Hinfo; + out.haveKnown = true; + out.cpu = in.cpu(); + out.os = in.os(); + break; + case NameRecord::Ns: + out.type = QJDns::Ns; + out.haveKnown = true; + out.name = in.name(); + break; + case NameRecord::Null: + out.type = 10; + out.rdata = in.rawData(); + break; + default: + return out; } out.owner = in.owner(); - out.ttl = in.ttl(); + out.ttl = in.ttl(); return out; } static bool validServiceType(const QByteArray &in) { // can't be empty, or start/end with a dot - if(in.isEmpty() || in[0] == '.' || in[in.length() - 1] == '.') + if (in.isEmpty() || in[0] == '.' || in[in.length() - 1] == '.') return false; // must contain exactly one dot int dotcount = 0; - for(int n = 0; n < in.length(); ++n) - { - if(in[n] == '.') - { + for (int n = 0; n < in.length(); ++n) { + if (in[n] == '.') { ++dotcount; // no need to count more than 2 - if(dotcount >= 2) + if (dotcount >= 2) break; } } - if(dotcount != 1) + if (dotcount != 1) return false; return true; @@ -148,11 +164,10 @@ static bool validServiceType(const QByteArray &in) static QByteArray escapeDomainPart(const QByteArray &in) { QByteArray out; - for(int n = 0; n < in.length(); ++n) - { - if(in[n] == '\\') + for (int n = 0; n < in.length(); ++n) { + if (in[n] == '\\') out += "\\\\"; - else if(in[n] == '.') + else if (in[n] == '.') out += "\\."; else out += in[n]; @@ -163,47 +178,38 @@ static QByteArray escapeDomainPart(const QByteArray &in) static QByteArray unescapeDomainPart(const QByteArray &in) { QByteArray out; - for(int n = 0; n < in.length(); ++n) - { - if(in[n] == '\\') - { - if(n + 1 >= in.length()) + for (int n = 0; n < in.length(); ++n) { + if (in[n] == '\\') { + if (n + 1 >= in.length()) return QByteArray(); out += in[n + 1]; - } - else + } else out += in[n]; } return out; } -class IdManager -{ +class IdManager { private: QSet set; - int at; + int at; inline void bump_at() { - if(at == 0x7fffffff) + if (at == 0x7fffffff) at = 0; else ++at; } public: - IdManager() : - at(0) - { - } + IdManager() : at(0) {} int reserveId() { - while(1) - { - if(!set.contains(at)) - { + while (1) { + if (!set.contains(at)) { int id = at; set.insert(id); bump_at(); @@ -214,10 +220,7 @@ class IdManager } } - void releaseId(int id) - { - set.remove(id); - } + void releaseId(int id) { set.remove(id); } void clear() { @@ -229,23 +232,22 @@ class IdManager //---------------------------------------------------------------------------- // JDnsGlobal //---------------------------------------------------------------------------- -class JDnsGlobal : public QObject -{ +class JDnsGlobal : public QObject { Q_OBJECT public: - QJDnsSharedDebug db; - QJDnsShared *uni_net, *uni_local, *mul; - QHostAddress mul_addr4, mul_addr6; - NetInterfaceManager netman; - QList ifaces; - QTimer *updateTimer; + QJDnsSharedDebug db; + QJDnsShared * uni_net, *uni_local, *mul; + QHostAddress mul_addr4, mul_addr6; + NetInterfaceManager netman; + QList ifaces; + QTimer * updateTimer; JDnsGlobal() { - uni_net = 0; + uni_net = 0; uni_local = 0; - mul = 0; + mul = 0; qRegisterMetaType(); qRegisterMetaType(); @@ -268,12 +270,12 @@ class JDnsGlobal : public QObject qDeleteAll(ifaces); - QList list; - if(uni_net) + QList list; + if (uni_net) list += uni_net; - if(uni_local) + if (uni_local) list += uni_local; - if(mul) + if (mul) list += mul; // calls shutdown on the list, waits for shutdownFinished, deletes @@ -285,14 +287,12 @@ class JDnsGlobal : public QObject QJDnsShared *ensure_uni_net() { - if(!uni_net) - { + if (!uni_net) { uni_net = new QJDnsShared(QJDnsShared::UnicastInternet, this); uni_net->setDebug(&db, "U"); bool ok4 = uni_net->addInterface(QHostAddress::Any); bool ok6 = uni_net->addInterface(QHostAddress::AnyIPv6); - if(!ok4 && !ok6) - { + if (!ok4 && !ok6) { delete uni_net; uni_net = 0; } @@ -302,14 +302,12 @@ class JDnsGlobal : public QObject QJDnsShared *ensure_uni_local() { - if(!uni_local) - { + if (!uni_local) { uni_local = new QJDnsShared(QJDnsShared::UnicastLocal, this); uni_local->setDebug(&db, "L"); bool ok4 = uni_local->addInterface(QHostAddress::Any); bool ok6 = uni_local->addInterface(QHostAddress::AnyIPv6); - if(!ok4 && !ok6) - { + if (!ok4 && !ok6) { delete uni_local; uni_local = 0; } @@ -319,8 +317,7 @@ class JDnsGlobal : public QObject QJDnsShared *ensure_mul() { - if(!mul) - { + if (!mul) { mul = new QJDnsShared(QJDnsShared::Multicast, this); mul->setDebug(&db, "M"); @@ -330,8 +327,7 @@ class JDnsGlobal : public QObject // fetching should not trigger any calls to // updateMulticastInterfaces(). only future // activity should do that. - foreach(const QString &id, netman.interfaces()) - { + foreach (const QString &id, netman.interfaces()) { NetInterface *iface = new NetInterface(id, &netman); connect(iface, SIGNAL(unavailable()), SLOT(iface_unavailable())); ifaces += iface; @@ -342,15 +338,9 @@ class JDnsGlobal : public QObject return mul; } - bool haveMulticast4() const - { - return !mul_addr4.isNull(); - } + bool haveMulticast4() const { return !mul_addr4.isNull(); } - bool haveMulticast6() const - { - return !mul_addr6.isNull(); - } + bool haveMulticast6() const { return !mul_addr6.isNull(); } signals: void interfacesChanged(); @@ -360,7 +350,7 @@ private slots: { QStringList lines = db.readDebugLines(); #ifdef JDNS_DEBUG - for(int n = 0; n < lines.count(); ++n) + for (int n = 0; n < lines.count(); ++n) qDebug("jdns: %s\n", qPrintable(lines[n])); #else Q_UNUSED(lines); @@ -385,10 +375,7 @@ private slots: updateTimer->start(100); } - void doUpdateMulticastInterfaces() - { - updateMulticastInterfaces(true); - } + void doUpdateMulticastInterfaces() { updateMulticastInterfaces(true); } private: void updateMulticastInterfaces(bool useSignals) @@ -406,23 +393,21 @@ private slots: bool have6 = !mul_addr6.isNull(); // did we gain/lose something? - if(had4 != have4 || had6 != have6) - { - if(useSignals) + if (had4 != have4 || had6 != have6) { + if (useSignals) emit interfacesChanged(); } } void updateMulticastInterface(QHostAddress *curaddr, const QHostAddress &newaddr) { - if(!(newaddr == *curaddr)) // QHostAddress doesn't have operator!= + if (!(newaddr == *curaddr)) // QHostAddress doesn't have operator!= { - if(!curaddr->isNull()) + if (!curaddr->isNull()) mul->removeInterface(*curaddr); *curaddr = newaddr; - if(!curaddr->isNull()) - { - if(!mul->addInterface(*curaddr)) + if (!curaddr->isNull()) { + if (!mul->addInterface(*curaddr)) *curaddr = QHostAddress(); } } @@ -432,81 +417,61 @@ private slots: //---------------------------------------------------------------------------- // JDnsNameProvider //---------------------------------------------------------------------------- -class JDnsNameProvider : public NameProvider -{ +class JDnsNameProvider : public NameProvider { Q_OBJECT Q_INTERFACES(XMPP::NameProvider) public: enum Mode { Internet, Local }; - JDnsGlobal *global; - Mode mode; - IdManager idman; + JDnsGlobal * global; + Mode mode; + IdManager idman; ObjectSession sess; - class Item - { + class Item { public: - int id; + int id; QJDnsSharedRequest *req; - int type; - bool longLived; - ObjectSession sess; - bool useLocal; - bool localResult; + int type; + bool longLived; + ObjectSession sess; + bool useLocal; + bool localResult; NameResolver::Error error; NameResolver::Error localError; - Item(QObject *parent = 0) : - id(-1), - req(0), - sess(parent), - useLocal(false), - localResult(false) - { - } + Item(QObject *parent = 0) : id(-1), req(0), sess(parent), useLocal(false), localResult(false) {} - ~Item() - { - delete req; - } + ~Item() { delete req; } }; - QList items; + QList items; static JDnsNameProvider *create(JDnsGlobal *global, Mode mode, QObject *parent = 0) { - if(mode == Internet) - { - if(!global->ensure_uni_net()) + if (mode == Internet) { + if (!global->ensure_uni_net()) return 0; - } - else - { - if(!global->ensure_uni_local()) + } else { + if (!global->ensure_uni_local()) return 0; } return new JDnsNameProvider(global, mode, parent); } - JDnsNameProvider(JDnsGlobal *_global, Mode _mode, QObject *parent = 0) : - NameProvider(parent) + JDnsNameProvider(JDnsGlobal *_global, Mode _mode, QObject *parent = 0) : NameProvider(parent) { global = _global; - mode = _mode; + mode = _mode; } - ~JDnsNameProvider() - { - qDeleteAll(items); - } + ~JDnsNameProvider() { qDeleteAll(items); } Item *getItemById(int id) { - for(int n = 0; n < items.count(); ++n) - { - if(items[n]->id == id) + for (int n = 0; n < items.count(); ++n) { + if (items[n]->id == id) return items[n]; } @@ -515,9 +480,8 @@ class JDnsNameProvider : public NameProvider Item *getItemByReq(QJDnsSharedRequest *req) { - for(int n = 0; n < items.count(); ++n) - { - if(items[n]->req == req) + for (int n = 0; n < items.count(); ++n) { + if (items[n]->req == req) return items[n]; } @@ -534,24 +498,21 @@ class JDnsNameProvider : public NameProvider void tryError(Item *i) { // if we are doing dual resolves, make sure both are done - if(!i->longLived && (i->req || (i->useLocal && !i->localResult))) + if (!i->longLived && (i->req || (i->useLocal && !i->localResult))) return; - int id = i->id; + int id = i->id; NameResolver::Error error = i->error; releaseItem(i); emit resolve_error(id, error); } - virtual bool supportsSingle() const - { - return true; - } + virtual bool supportsSingle() const { return true; } virtual bool supportsLongLived() const { - if(mode == Local) - return true; // we support long-lived local queries + if (mode == Local) + return true; // we support long-lived local queries else return false; // we do NOT support long-lived internet queries } @@ -565,10 +526,9 @@ class JDnsNameProvider : public NameProvider virtual int resolve_start(const QByteArray &name, int qType, bool longLived) { - if(mode == Internet) - { + if (mode == Internet) { bool isLocalName = false; - if(name.right(6) == ".local" || name.right(7) == ".local.") + if (name.right(6) == ".local" || name.right(7) == ".local.") isLocalName = true; // if query ends in .local, switch to local resolver @@ -583,65 +543,57 @@ class JDnsNameProvider : public NameProvider }*/ // we don't support long-lived internet queries - if(longLived) - { + if (longLived) { // but we do support long-lived local queries - if(isLocalName) - { - Item *i = new Item(this); - i->id = idman.reserveId(); + if (isLocalName) { + Item *i = new Item(this); + i->id = idman.reserveId(); i->longLived = longLived; - i->useLocal = true; + i->useLocal = true; items += i; i->sess.defer(this, "do_local", Q_ARG(int, i->id), Q_ARG(QByteArray, name)); return i->id; } Item *i = new Item(this); - i->id = idman.reserveId(); + i->id = idman.reserveId(); items += i; i->sess.defer(this, "do_error", Q_ARG(int, i->id), - Q_ARG(XMPP::NameResolver::Error, NameResolver::ErrorNoLongLived)); + Q_ARG(XMPP::NameResolver::Error, NameResolver::ErrorNoLongLived)); return i->id; } // perform the query Item *i = new Item(this); - i->id = idman.reserveId(); - i->req = new QJDnsSharedRequest(global->uni_net); + i->id = idman.reserveId(); + i->req = new QJDnsSharedRequest(global->uni_net); connect(i->req, SIGNAL(resultsReady()), SLOT(req_resultsReady())); - i->type = qType; + i->type = qType; i->longLived = false; - if(isLocalName) + if (isLocalName) i->useLocal = true; items += i; i->req->query(name, qType); // if query ends in .local, simultaneously do local resolve - if(isLocalName) + if (isLocalName) i->sess.defer(this, "do_local", Q_ARG(int, i->id), Q_ARG(QByteArray, name)); return i->id; - } - else - { + } else { Item *i = new Item(this); - i->id = idman.reserveId(); + i->id = idman.reserveId(); i->type = qType; - if(longLived) - { - if(!global->ensure_mul()) - { + if (longLived) { + if (!global->ensure_mul()) { items += i; i->sess.defer(this, "do_error", Q_ARG(int, i->id), - Q_ARG(XMPP::NameResolver::Error, NameResolver::ErrorNoLocal)); + Q_ARG(XMPP::NameResolver::Error, NameResolver::ErrorNoLocal)); return i->id; } - i->req = new QJDnsSharedRequest(global->mul); + i->req = new QJDnsSharedRequest(global->mul); i->longLived = true; - } - else - { - i->req = new QJDnsSharedRequest(global->uni_local); + } else { + i->req = new QJDnsSharedRequest(global->uni_local); i->longLived = false; } connect(i->req, SIGNAL(resultsReady()), SLOT(req_resultsReady())); @@ -656,7 +608,7 @@ class JDnsNameProvider : public NameProvider Item *i = getItemById(id); Q_ASSERT(i); - if(i->req) + if (i->req) i->req->cancel(); releaseItem(i); } @@ -668,8 +620,7 @@ class JDnsNameProvider : public NameProvider Q_ASSERT(!i->localResult); i->localResult = true; - i->sess.defer(this, "do_local_ready", Q_ARG(int, id), - Q_ARG(QList, results)); + i->sess.defer(this, "do_local_ready", Q_ARG(int, id), Q_ARG(QList, results)); } virtual void resolve_localError(int id, XMPP::NameResolver::Error e) @@ -679,71 +630,62 @@ class JDnsNameProvider : public NameProvider Q_ASSERT(!i->localResult); i->localResult = true; - i->sess.defer(this, "do_local_error", Q_ARG(int, id), - Q_ARG(XMPP::NameResolver::Error, e)); + i->sess.defer(this, "do_local_error", Q_ARG(int, id), Q_ARG(XMPP::NameResolver::Error, e)); } private slots: void req_resultsReady() { QJDnsSharedRequest *req = static_cast(sender()); - Item *i = getItemByReq(req); + Item * i = getItemByReq(req); Q_ASSERT(i); int id = i->id; NameResolver::Error error; - if(req->success()) - { + if (req->success()) { QList out; - foreach(const QJDns::Record &r, req->results()) - { + foreach (const QJDns::Record &r, req->results()) { // unless we are asking for all types, only // accept the type we asked for - if(i->type == QJDns::Any || r.type == i->type) - { + if (i->type == QJDns::Any || r.type == i->type) { NameRecord rec = importJDNSRecord(r); - if(!rec.isNull()) + if (!rec.isNull()) out += rec; } } // don't report anything if long-lived gives no results - if(i->longLived && out.isEmpty()) + if (i->longLived && out.isEmpty()) return; // only emit success if we have at least 1 result - if(!out.isEmpty()) - { + if (!out.isEmpty()) { // FIXME: need a way to cancel related local // query if still active - if(!i->longLived) + if (!i->longLived) releaseItem(i); emit resolve_resultsReady(id, out); return; - } - else - { + } else { error = NameResolver::ErrorGeneric; } - } - else - { + } else { QJDnsSharedRequest::Error e = req->error(); error = NameResolver::ErrorGeneric; - if(e == QJDnsSharedRequest::ErrorNXDomain) + if (e == QJDnsSharedRequest::ErrorNXDomain) error = NameResolver::ErrorNoName; - else if(e == QJDnsSharedRequest::ErrorTimeout) + else if (e == QJDnsSharedRequest::ErrorTimeout) error = NameResolver::ErrorTimeout; else // ErrorGeneric or ErrorNoNet error = NameResolver::ErrorGeneric; } delete i->req; - i->req = 0; + i->req = 0; i->error = error; tryError(i); } @@ -762,8 +704,8 @@ private slots: void do_local(int id, const QByteArray &name) { - //Item *i = getItemById(id); - //Q_ASSERT(i); + // Item *i = getItemById(id); + // Q_ASSERT(i); /*// resolve_useLocal has two behaviors: // - if longlived, then it indicates a hand-off @@ -779,10 +721,9 @@ private slots: Item *i = getItemById(id); Q_ASSERT(i); - if(!i->longLived) - { + if (!i->longLived) { // stop any simultaneous internet resolve - if(i->req) + if (i->req) i->req->cancel(); // for non-longlived, we're done @@ -805,17 +746,14 @@ private slots: //---------------------------------------------------------------------------- // JDnsBrowse //---------------------------------------------------------------------------- -class JDnsBrowse : public QObject -{ +class JDnsBrowse : public QObject { Q_OBJECT public: - QByteArray type, typeAndDomain; + QByteArray type, typeAndDomain; QJDnsSharedRequest req; - JDnsBrowse(QJDnsShared *_jdns, QObject *parent = 0) : - QObject(parent), - req(_jdns, this) + JDnsBrowse(QJDnsShared *_jdns, QObject *parent = 0) : QObject(parent), req(_jdns, this) { connect(&req, SIGNAL(resultsReady()), SLOT(jdns_resultsReady())); } @@ -836,19 +774,19 @@ class JDnsBrowse : public QObject QByteArray parseInstanceName(const QByteArray &name) { // needs to be at least X + '.' + typeAndDomain - if(name.length() < typeAndDomain.length() + 2) + if (name.length() < typeAndDomain.length() + 2) return QByteArray(); // index of the '.' character int at = name.length() - typeAndDomain.length() - 1; - if(name[at] != '.') + if (name[at] != '.') return QByteArray(); - if(name.mid(at + 1) != typeAndDomain) + if (name.mid(at + 1) != typeAndDomain) return QByteArray(); QByteArray friendlyName = unescapeDomainPart(name.mid(0, at)); - if(friendlyName.isEmpty()) + if (friendlyName.isEmpty()) return QByteArray(); return friendlyName; @@ -858,20 +796,19 @@ private slots: void jdns_resultsReady() { // ignore errors - if(!req.success()) + if (!req.success()) return; QJDns::Record rec = req.results().first(); Q_ASSERT(rec.type == QJDns::Ptr); - QByteArray name = rec.name; + QByteArray name = rec.name; QByteArray instance = parseInstanceName(name); - if(instance.isEmpty()) + if (instance.isEmpty()) return; - if(rec.ttl == 0) - { + if (rec.ttl == 0) { emit unavailable(instance); return; } @@ -886,37 +823,28 @@ private slots: // 5 second timeout waiting for both A and AAAA // 8 second timeout waiting for at least one record -class JDnsServiceResolve : public QObject -{ +class JDnsServiceResolve : public QObject { Q_OBJECT public: - enum SrvState - { - Srv = 0, - AddressWait = 1, - AddressFirstCome = 2 - }; + enum SrvState { Srv = 0, AddressWait = 1, AddressFirstCome = 2 }; QJDnsSharedRequest reqtxt; // for TXT QJDnsSharedRequest req; // for SRV/A QJDnsSharedRequest req6; // for AAAA - bool haveTxt; - SrvState srvState; - QTimer *opTimer; + bool haveTxt; + SrvState srvState; + QTimer * opTimer; // out QList attribs; - QByteArray host; - int port; - bool have4, have6; - QHostAddress addr4, addr6; + QByteArray host; + int port; + bool have4, have6; + QHostAddress addr4, addr6; JDnsServiceResolve(QJDnsShared *_jdns, QObject *parent = 0) : - QObject(parent), - reqtxt(_jdns, this), - req(_jdns, this), - req6(_jdns, this) + QObject(parent), reqtxt(_jdns, this), req(_jdns, this), req6(_jdns, this) { connect(&reqtxt, SIGNAL(resultsReady()), SLOT(reqtxt_ready())); connect(&req, SIGNAL(resultsReady()), SLOT(req_ready())); @@ -936,10 +864,10 @@ class JDnsServiceResolve : public QObject void start(const QByteArray name) { - haveTxt = false; + haveTxt = false; srvState = Srv; - have4 = false; - have6 = false; + have4 = false; + have6 = false; opTimer->start(8000); @@ -954,21 +882,20 @@ class JDnsServiceResolve : public QObject private: void cleanup() { - if(opTimer->isActive()) + if (opTimer->isActive()) opTimer->stop(); - if(!haveTxt) + if (!haveTxt) reqtxt.cancel(); - if(srvState == Srv || !have4) + if (srvState == Srv || !have4) req.cancel(); - if(srvState >= AddressWait && !have6) + if (srvState >= AddressWait && !have6) req6.cancel(); } bool tryDone() { // we're done when we have txt and addresses - if(haveTxt && ( (have4 && have6) || (srvState == AddressFirstCome && (have4 || have6)) )) - { + if (haveTxt && ((have4 && have6) || (srvState == AddressFirstCome && (have4 || have6)))) { cleanup(); emit finished(); return true; @@ -980,8 +907,7 @@ class JDnsServiceResolve : public QObject private slots: void reqtxt_ready() { - if(!reqtxt.success()) - { + if (!reqtxt.success()) { cleanup(); emit error(reqtxt.error()); return; @@ -993,11 +919,10 @@ private slots: Q_ASSERT(rec.type == QJDns::Txt); attribs.clear(); - if(!rec.texts.isEmpty()) - { + if (!rec.texts.isEmpty()) { // if there is only 1 text, it needs to be // non-empty for us to care - if(rec.texts.count() != 1 || !rec.texts[0].isEmpty()) + if (rec.texts.count() != 1 || !rec.texts[0].isEmpty()) attribs = rec.texts; } @@ -1008,8 +933,7 @@ private slots: void req_ready() { - if(!req.success()) - { + if (!req.success()) { cleanup(); emit error(req.error()); return; @@ -1018,8 +942,7 @@ private slots: QJDns::Record rec = req.results().first(); req.cancel(); - if(srvState == Srv) - { + if (srvState == Srv) { // in Srv state, req is used for SRV records Q_ASSERT(rec.type == QJDns::Srv); @@ -1032,9 +955,7 @@ private slots: req.query(host, QJDns::A); req6.query(host, QJDns::Aaaa); - } - else - { + } else { // in the other states, req is used for A records Q_ASSERT(rec.type == QJDns::A); @@ -1048,8 +969,7 @@ private slots: void req6_ready() { - if(!req6.success()) - { + if (!req6.success()) { cleanup(); emit error(req6.error()); return; @@ -1068,17 +988,14 @@ private slots: void op_timeout() { - if(srvState == Srv) - { + if (srvState == Srv) { // timeout getting SRV. it is possible that we could // have obtained the TXT record, but if SRV times // out then we consider the whole job to have // failed. cleanup(); emit error(QJDnsSharedRequest::ErrorTimeout); - } - else if(srvState == AddressWait) - { + } else if (srvState == AddressWait) { // timeout while waiting for both A and AAAA. we now // switch to the AddressFirstCome state, where an // answer for either will do @@ -1086,11 +1003,10 @@ private slots: srvState = AddressFirstCome; // if we have at least one of these, we're done - if(have4 || have6) - { + if (have4 || have6) { // well, almost. we might still be waiting // for the TXT record - if(tryDone()) + if (tryDone()) return; } @@ -1099,12 +1015,10 @@ private slots: // wait 3 more seconds opTimer->start(3000); - } - else // AddressFirstCome + } else // AddressFirstCome { // last chance! - if(!tryDone()) - { + if (!tryDone()) { cleanup(); emit error(QJDnsSharedRequest::ErrorTimeout); } @@ -1117,27 +1031,20 @@ private slots: //---------------------------------------------------------------------------- // helper class for JDnsPublishAddresses. publishes A+PTR or AAAA+PTR pair. -class JDnsPublishAddress : public QObject -{ +class JDnsPublishAddress : public QObject { Q_OBJECT public: - enum Type - { - IPv4, - IPv6 - }; + enum Type { IPv4, IPv6 }; - Type type; - QByteArray host; + Type type; + QByteArray host; QJDnsSharedRequest pub_addr; QJDnsSharedRequest pub_ptr; - bool success_; + bool success_; JDnsPublishAddress(QJDnsShared *_jdns, QObject *parent = 0) : - QObject(parent), - pub_addr(_jdns, this), - pub_ptr(_jdns, this) + QObject(parent), pub_addr(_jdns, this), pub_ptr(_jdns, this) { connect(&pub_addr, SIGNAL(resultsReady()), SLOT(pub_addr_ready())); connect(&pub_ptr, SIGNAL(resultsReady()), SLOT(pub_ptr_ready())); @@ -1145,19 +1052,19 @@ class JDnsPublishAddress : public QObject void start(Type _type, const QByteArray &_host) { - type = _type; - host = _host; + type = _type; + host = _host; success_ = false; QJDns::Record rec; - if(type == IPv6) + if (type == IPv6) rec.type = QJDns::Aaaa; else rec.type = QJDns::A; - rec.owner = host; - rec.ttl = 120; + rec.owner = host; + rec.ttl = 120; rec.haveKnown = true; - rec.address = QHostAddress(); // null address, will be filled in + rec.address = QHostAddress(); // null address, will be filled in pub_addr.publish(QJDns::Unique, rec); } @@ -1167,10 +1074,7 @@ class JDnsPublishAddress : public QObject pub_ptr.cancel(); } - bool success() const - { - return success_; - } + bool success() const { return success_; } signals: void resultsReady(); @@ -1178,21 +1082,18 @@ class JDnsPublishAddress : public QObject private slots: void pub_addr_ready() { - if(pub_addr.success()) - { + if (pub_addr.success()) { QJDns::Record rec; rec.type = QJDns::Ptr; - if(type == IPv6) + if (type == IPv6) rec.owner = ".ip6.arpa."; else rec.owner = ".in-addr.arpa."; - rec.ttl = 120; + rec.ttl = 120; rec.haveKnown = true; - rec.name = host; + rec.name = host; pub_ptr.publish(QJDns::Shared, rec); - } - else - { + } else { pub_ptr.cancel(); // needed if addr fails during or after ptr success_ = false; emit resultsReady(); @@ -1201,12 +1102,9 @@ private slots: void pub_ptr_ready() { - if(pub_ptr.success()) - { + if (pub_ptr.success()) { success_ = true; - } - else - { + } else { pub_addr.cancel(); success_ = false; } @@ -1226,29 +1124,22 @@ private slots: // once the conflict is resolved. A missing hostname is considered a // temporary problem, and so other publish operations that depend on a // hostname (SRV, etc) should block until a hostname is available. -class JDnsPublishAddresses : public QObject -{ +class JDnsPublishAddresses : public QObject { Q_OBJECT public: - bool started; - bool use6, use4; + bool started; + bool use6, use4; JDnsPublishAddress pub6; JDnsPublishAddress pub4; - int counter; - QByteArray host; - bool success; - bool have6, have4; - ObjectSession sess; + int counter; + QByteArray host; + bool success; + bool have6, have4; + ObjectSession sess; JDnsPublishAddresses(QJDnsShared *_jdns, QObject *parent = 0) : - QObject(parent), - started(false), - use6(false), - use4(false), - pub6(_jdns, this), - pub4(_jdns, this), - sess(this) + QObject(parent), started(false), use6(false), use4(false), pub6(_jdns, this), pub4(_jdns, this), sess(this) { connect(&pub6, SIGNAL(resultsReady()), SLOT(pub6_ready())); connect(&pub4, SIGNAL(resultsReady()), SLOT(pub4_ready())); @@ -1258,25 +1149,22 @@ class JDnsPublishAddresses : public QObject { counter = 1; success = false; - have6 = false; - have4 = false; + have6 = false; + have4 = false; started = true; tryPublish(); } - bool isStarted() const - { - return started; - } + bool isStarted() const { return started; } // comments in this method apply to setUseIPv4 as well. void setUseIPv6(bool b) { - if(b == use6) + if (b == use6) return; use6 = b; - if(!started) + if (!started) return; // a "deferred call to doDisable" and "publish operations" @@ -1285,58 +1173,46 @@ class JDnsPublishAddresses : public QObject // deferred call is canceled if any of the publishes are // reinstantiated. - if(use6) - { - if(use4) - { + if (use6) { + if (use4) { // if the other is already active, then // just activate this one without // recomputing the hostname tryPublish6(); - } - else - { + } else { sess.reset(); // otherwise, recompute the hostname tryPublish(); } - } - else - { + } else { pub6.cancel(); have6 = false; - if(!use4) + if (!use4) sess.defer(this, "doDisable"); } } void setUseIPv4(bool b) { - if(b == use4) + if (b == use4) return; use4 = b; - if(!started) + if (!started) return; - if(use4) - { - if(use6) - { + if (use4) { + if (use6) { tryPublish4(); - } - else - { + } else { sess.reset(); tryPublish(); } - } - else - { + } else { pub4.cancel(); have4 = false; - if(!use6) + if (!use6) sess.defer(this, "doDisable"); } } @@ -1350,44 +1226,37 @@ class JDnsPublishAddresses : public QObject QString me = QHostInfo::localHostName(); // some hosts may already have ".local" in their name - if(me.endsWith(".local")) + if (me.endsWith(".local")) me.truncate(me.length() - 6); // prefix our hostname so we don't conflict with a system // mdns daemon me.prepend("jdns-"); - if(counter > 1) + if (counter > 1) me += QString("-%1").arg(counter); host = escapeDomainPart(me.toUtf8()) + ".local."; - if(use6) + if (use6) tryPublish6(); - if(use4) + if (use4) tryPublish4(); } - void tryPublish6() - { - pub6.start(JDnsPublishAddress::IPv6, host); - } + void tryPublish6() { pub6.start(JDnsPublishAddress::IPv6, host); } - void tryPublish4() - { - pub4.start(JDnsPublishAddress::IPv4, host); - } + void tryPublish4() { pub4.start(JDnsPublishAddress::IPv4, host); } void tryDone() { bool done = true; - if(use6 && !have6) + if (use6 && !have6) done = false; - if(use4 && !have4) + if (use4 && !have4) done = false; - if(done) - { + if (done) { success = true; emit hostName(host); } @@ -1400,11 +1269,11 @@ class JDnsPublishAddresses : public QObject // latter case it means we "lost" our host records. bool lostHost = success; // as in earlier publish success - success = false; + success = false; // if we lost a hostname with a suffix, or counter is // at 99, then start counter over at 1 (no suffix). - if((lostHost && counter > 1) || counter >= 99) + if ((lostHost && counter > 1) || counter >= 99) counter = 1; else ++counter; @@ -1412,7 +1281,7 @@ class JDnsPublishAddresses : public QObject tryPublish(); // only emit lost host signal once - if(lostHost) + if (lostHost) emit hostName(QByteArray()); } @@ -1420,21 +1289,18 @@ private slots: void doDisable() { bool lostHost = success; - success = false; + success = false; - if(lostHost) + if (lostHost) emit hostName(QByteArray()); } void pub6_ready() { - if(pub6.success()) - { + if (pub6.success()) { have6 = true; tryDone(); - } - else - { + } else { have6 = false; have4 = false; pub4.cancel(); @@ -1444,13 +1310,10 @@ private slots: void pub4_ready() { - if(pub4.success()) - { + if (pub4.success()) { have4 = true; tryDone(); - } - else - { + } else { have4 = false; have6 = false; pub6.cancel(); @@ -1464,8 +1327,7 @@ private slots: //---------------------------------------------------------------------------- class JDnsPublish; -class JDnsPublishExtra : public QObject -{ +class JDnsPublishExtra : public QObject { Q_OBJECT public: @@ -1482,12 +1344,12 @@ class JDnsPublishExtra : public QObject private: friend class JDnsPublish; - JDnsPublish *jdnsPub; - bool started; + JDnsPublish * jdnsPub; + bool started; QJDnsSharedRequest pub; - QJDns::Record rec; - bool have; - bool need_update; + QJDns::Record rec; + bool have; + bool need_update; }; // This class publishes SRV/TXT/PTR for a service. if a hostName is not @@ -1503,12 +1365,11 @@ class JDnsPublishExtra : public QObject // It's important to note that published() is only emitted once ever, even // if a hostName change causes a republishing. this way, hostName changes // are completely transparent. -class JDnsPublish : public QObject -{ +class JDnsPublish : public QObject { Q_OBJECT public: - QJDnsShared *jdns; + QJDnsShared * jdns; QJDnsSharedRequest pub_srv; QJDnsSharedRequest pub_txt; QJDnsSharedRequest pub_ptr; @@ -1516,62 +1377,55 @@ class JDnsPublish : public QObject bool have_srv, have_txt, have_ptr; bool need_update_txt; - QByteArray fullname; - QByteArray instance; - QByteArray type; - QByteArray host; - int port; + QByteArray fullname; + QByteArray instance; + QByteArray type; + QByteArray host; + int port; QList attribs; - QSet extraList; + QSet extraList; JDnsPublish(QJDnsShared *_jdns, QObject *parent = 0) : - QObject(parent), - jdns(_jdns), - pub_srv(_jdns, this), - pub_txt(_jdns, this), - pub_ptr(_jdns, this) + QObject(parent), jdns(_jdns), pub_srv(_jdns, this), pub_txt(_jdns, this), pub_ptr(_jdns, this) { connect(&pub_srv, SIGNAL(resultsReady()), SLOT(pub_srv_ready())); connect(&pub_txt, SIGNAL(resultsReady()), SLOT(pub_txt_ready())); connect(&pub_ptr, SIGNAL(resultsReady()), SLOT(pub_ptr_ready())); } - ~JDnsPublish() - { - qDeleteAll(extraList); - } + ~JDnsPublish() { qDeleteAll(extraList); } - void start(const QString &_instance, const QByteArray &_type, const QByteArray &localHost, int _port, const QMap &attributes) + void start(const QString &_instance, const QByteArray &_type, const QByteArray &localHost, int _port, + const QMap &attributes) { type = _type; Q_ASSERT(validServiceType(type)); instance = escapeDomainPart(_instance.toUtf8()); fullname = instance + '.' + type + ".local."; - host = localHost; - port = _port; - attribs = makeTxtList(attributes); + host = localHost; + port = _port; + attribs = makeTxtList(attributes); - have_srv = false; - have_txt = false; - have_ptr = false; + have_srv = false; + have_txt = false; + have_ptr = false; need_update_txt = false; // no host? defer publishing till we have one - if(host.isEmpty()) + if (host.isEmpty()) return; doPublish(); } - void update(const QMap &attributes) + void update(const QMap &attributes) { attribs = makeTxtList(attributes); // still publishing the initial txt? - if(!have_txt) - { + if (!have_txt) { // flag that we want to update once the publish // succeeds. need_update_txt = true; @@ -1580,8 +1434,7 @@ class JDnsPublish : public QObject // no SRV, but have TXT? this means we lost SRV due to // a hostname change. - if(!have_srv) - { + if (!have_srv) { // in that case, revoke the TXT. it'll get // republished after SRV then. have_txt = false; @@ -1598,18 +1451,14 @@ public slots: { bool changed = (host != _host); - if(changed) - { + if (changed) { host = _host; - if(host.isEmpty()) - { + if (host.isEmpty()) { // cancel srv record momentarily have_srv = false; pub_srv.cancel(); - } - else - { + } else { // we now have a host, publish doPublish(); } @@ -1623,17 +1472,16 @@ public slots: private: friend class JDnsPublishExtra; - static QList makeTxtList(const QMap &attributes) + static QList makeTxtList(const QMap &attributes) { QList out; - QMapIterator it(attributes); - while(it.hasNext()) - { + QMapIterator it(attributes); + while (it.hasNext()) { it.next(); out += it.key().toLatin1() + '=' + it.value(); } - if(out.isEmpty()) + if (out.isEmpty()) out += QByteArray(); return out; @@ -1643,25 +1491,24 @@ public slots: { // SRV QJDns::Record rec; - rec.type = QJDns::Srv; - rec.owner = fullname; - rec.ttl = 120; + rec.type = QJDns::Srv; + rec.owner = fullname; + rec.ttl = 120; rec.haveKnown = true; - rec.name = host; - rec.port = port; - rec.priority = 0; - rec.weight = 0; + rec.name = host; + rec.port = port; + rec.priority = 0; + rec.weight = 0; pub_srv.publish(QJDns::Unique, rec); // if we're just republishing SRV after losing/regaining // our hostname, then TXT is already published - if(!have_txt) + if (!have_txt) doPublishTxt(); // publish extra records as needed - foreach(JDnsPublishExtra *extra, extraList) - { - if(!extra->have) + foreach (JDnsPublishExtra *extra, extraList) { + if (!extra->have) doPublishExtra(extra); } } @@ -1670,13 +1517,13 @@ public slots: { // TXT QJDns::Record rec; - rec.type = QJDns::Txt; - rec.owner = fullname; - rec.ttl = 4500; + rec.type = QJDns::Txt; + rec.owner = fullname; + rec.ttl = 4500; rec.haveKnown = true; - rec.texts = attribs; + rec.texts = attribs; - if(!have_txt) + if (!have_txt) pub_txt.publish(QJDns::Unique, rec); else pub_txt.publishUpdate(rec); @@ -1684,22 +1531,21 @@ public slots: void tryDone() { - if(have_srv && have_txt) - { + if (have_srv && have_txt) { // PTR QJDns::Record rec; - rec.type = QJDns::Ptr; - rec.owner = type + ".local."; - rec.ttl = 4500; + rec.type = QJDns::Ptr; + rec.owner = type + ".local."; + rec.ttl = 4500; rec.haveKnown = true; - rec.name = fullname; + rec.name = fullname; pub_ptr.publish(QJDns::Shared, rec); } } void cleanup() { - foreach(JDnsPublishExtra *extra, extraList) + foreach (JDnsPublishExtra *extra, extraList) cleanupExtra(extra); qDeleteAll(extraList); extraList.clear(); @@ -1720,7 +1566,7 @@ public slots: extraList += extra; // defer publishing until SRV is ready - if(!have_srv) + if (!have_srv) return; doPublishExtra(extra); @@ -1728,14 +1574,12 @@ public slots: void publishExtraUpdate(JDnsPublishExtra *extra) { - if(!extra->have) - { + if (!extra->have) { extra->need_update = true; return; } - if(!have_srv) - { + if (!have_srv) { extra->have = false; extra->pub.cancel(); return; @@ -1744,14 +1588,11 @@ public slots: doPublishExtra(extra); } - void unpublishExtra(JDnsPublishExtra *extra) - { - extraList.remove(extra); - } + void unpublishExtra(JDnsPublishExtra *extra) { extraList.remove(extra); } void doPublishExtra(JDnsPublishExtra *extra) { - if(!extra->have) + if (!extra->have) extra->pub.publish(QJDns::Unique, extra->rec); else extra->pub.publishUpdate(extra->rec); @@ -1762,19 +1603,16 @@ public slots: extra->pub.cancel(); extra->disconnect(this); extra->started = false; - extra->have = false; + extra->have = false; } private slots: void pub_srv_ready() { - if(pub_srv.success()) - { + if (pub_srv.success()) { have_srv = true; tryDone(); - } - else - { + } else { QJDnsSharedRequest::Error e = pub_srv.error(); cleanup(); emit error(e); @@ -1783,20 +1621,16 @@ private slots: void pub_txt_ready() { - if(pub_txt.success()) - { + if (pub_txt.success()) { have_txt = true; - if(need_update_txt) - { + if (need_update_txt) { need_update_txt = false; doPublishTxt(); } tryDone(); - } - else - { + } else { QJDnsSharedRequest::Error e = pub_txt.error(); cleanup(); emit error(e); @@ -1805,13 +1639,10 @@ private slots: void pub_ptr_ready() { - if(pub_ptr.success()) - { + if (pub_ptr.success()) { have_ptr = true; emit published(); - } - else - { + } else { QJDnsSharedRequest::Error e = pub_ptr.error(); cleanup(); emit error(e); @@ -1820,32 +1651,26 @@ private slots: void pub_extra_ready() { - QJDnsSharedRequest *req = static_cast(sender()); - JDnsPublishExtra *extra = 0; - foreach(JDnsPublishExtra *e, extraList) - { - if(&e->pub == req) - { + QJDnsSharedRequest *req = static_cast(sender()); + JDnsPublishExtra * extra = 0; + foreach (JDnsPublishExtra *e, extraList) { + if (&e->pub == req) { extra = e; break; } } Q_ASSERT(extra); - if(extra->pub.success()) - { + if (extra->pub.success()) { extra->have = true; - if(extra->need_update) - { + if (extra->need_update) { extra->need_update = false; doPublishExtra(extra); } emit extra->published(); - } - else - { + } else { QJDnsSharedRequest::Error e = extra->pub.error(); cleanupExtra(extra); emit extra->error(e); @@ -1854,24 +1679,21 @@ private slots: }; JDnsPublishExtra::JDnsPublishExtra(JDnsPublish *_jdnsPub) : - QObject(_jdnsPub), - jdnsPub(_jdnsPub), - started(false), - pub(_jdnsPub->jdns, this) + QObject(_jdnsPub), jdnsPub(_jdnsPub), started(false), pub(_jdnsPub->jdns, this) { } JDnsPublishExtra::~JDnsPublishExtra() { - if(started) + if (started) jdnsPub->unpublishExtra(this); } void JDnsPublishExtra::start(const QJDns::Record &_rec) { - rec = _rec; - started = true; - have = false; + rec = _rec; + started = true; + have = false; need_update = false; jdnsPub->publishExtra(this); } @@ -1885,19 +1707,13 @@ void JDnsPublishExtra::update(const QJDns::Record &_rec) //---------------------------------------------------------------------------- // JDnsServiceProvider //---------------------------------------------------------------------------- -class BrowseItem -{ +class BrowseItem { public: - const int id; - JDnsBrowse * const browse; - ObjectSession *sess; + const int id; + JDnsBrowse *const browse; + ObjectSession * sess; - BrowseItem(int _id, JDnsBrowse *_browse) : - id(_id), - browse(_browse), - sess(0) - { - } + BrowseItem(int _id, JDnsBrowse *_browse) : id(_id), browse(_browse), sess(0) {} ~BrowseItem() { @@ -1906,24 +1722,17 @@ class BrowseItem } }; -class BrowseItemList -{ +class BrowseItemList { private: - QSet items; - QHash indexById; - QHash indexByBrowse; - IdManager idman; + QSet items; + QHash indexById; + QHash indexByBrowse; + IdManager idman; public: - ~BrowseItemList() - { - qDeleteAll(items); - } + ~BrowseItemList() { qDeleteAll(items); } - int reserveId() - { - return idman.reserveId(); - } + int reserveId() { return idman.reserveId(); } void insert(BrowseItem *item) { @@ -1937,35 +1746,23 @@ class BrowseItemList indexById.remove(item->id); indexByBrowse.remove(item->browse); items.remove(item); - if(item->id != -1) + if (item->id != -1) idman.releaseId(item->id); delete item; } - BrowseItem *itemById(int id) const - { - return indexById.value(id); - } + BrowseItem *itemById(int id) const { return indexById.value(id); } - BrowseItem *itemByBrowse(JDnsBrowse *browse) const - { - return indexByBrowse.value(browse); - } + BrowseItem *itemByBrowse(JDnsBrowse *browse) const { return indexByBrowse.value(browse); } }; -class ResolveItem -{ +class ResolveItem { public: - const int id; - JDnsServiceResolve * const resolve; - ObjectSession *sess; + const int id; + JDnsServiceResolve *const resolve; + ObjectSession * sess; - ResolveItem(int _id, JDnsServiceResolve *_resolve) : - id(_id), - resolve(_resolve), - sess(0) - { - } + ResolveItem(int _id, JDnsServiceResolve *_resolve) : id(_id), resolve(_resolve), sess(0) {} ~ResolveItem() { @@ -1974,24 +1771,17 @@ class ResolveItem } }; -class ResolveItemList -{ +class ResolveItemList { private: - QSet items; - QHash indexById; - QHash indexByResolve; - IdManager idman; + QSet items; + QHash indexById; + QHash indexByResolve; + IdManager idman; public: - ~ResolveItemList() - { - qDeleteAll(items); - } + ~ResolveItemList() { qDeleteAll(items); } - int reserveId() - { - return idman.reserveId(); - } + int reserveId() { return idman.reserveId(); } void insert(ResolveItem *item) { @@ -2005,35 +1795,23 @@ class ResolveItemList indexById.remove(item->id); indexByResolve.remove(item->resolve); items.remove(item); - if(item->id != -1) + if (item->id != -1) idman.releaseId(item->id); delete item; } - ResolveItem *itemById(int id) const - { - return indexById.value(id); - } + ResolveItem *itemById(int id) const { return indexById.value(id); } - ResolveItem *itemByResolve(JDnsServiceResolve *resolve) const - { - return indexByResolve.value(resolve); - } + ResolveItem *itemByResolve(JDnsServiceResolve *resolve) const { return indexByResolve.value(resolve); } }; -class PublishItem -{ +class PublishItem { public: - const int id; - JDnsPublish * const publish; - ObjectSession *sess; + const int id; + JDnsPublish *const publish; + ObjectSession * sess; - PublishItem(int _id, JDnsPublish *_publish) : - id(_id), - publish(_publish), - sess(0) - { - } + PublishItem(int _id, JDnsPublish *_publish) : id(_id), publish(_publish), sess(0) {} ~PublishItem() { @@ -2042,26 +1820,19 @@ class PublishItem } }; -class PublishItemList -{ +class PublishItemList { public: - QSet items; + QSet items; private: - QHash indexById; - QHash indexByPublish; - IdManager idman; + QHash indexById; + QHash indexByPublish; + IdManager idman; public: - ~PublishItemList() - { - qDeleteAll(items); - } + ~PublishItemList() { qDeleteAll(items); } - int reserveId() - { - return idman.reserveId(); - } + int reserveId() { return idman.reserveId(); } void insert(PublishItem *item) { @@ -2075,35 +1846,23 @@ class PublishItemList indexById.remove(item->id); indexByPublish.remove(item->publish); items.remove(item); - if(item->id != -1) + if (item->id != -1) idman.releaseId(item->id); delete item; } - PublishItem *itemById(int id) const - { - return indexById.value(id); - } + PublishItem *itemById(int id) const { return indexById.value(id); } - PublishItem *itemByPublish(JDnsPublish *publish) const - { - return indexByPublish.value(publish); - } + PublishItem *itemByPublish(JDnsPublish *publish) const { return indexByPublish.value(publish); } }; -class PublishExtraItem -{ +class PublishExtraItem { public: - const int id; - JDnsPublishExtra * const publish; - ObjectSession *sess; + const int id; + JDnsPublishExtra *const publish; + ObjectSession * sess; - PublishExtraItem(int _id, JDnsPublishExtra *_publish) : - id(_id), - publish(_publish), - sess(0) - { - } + PublishExtraItem(int _id, JDnsPublishExtra *_publish) : id(_id), publish(_publish), sess(0) {} ~PublishExtraItem() { @@ -2112,21 +1871,17 @@ class PublishExtraItem } }; -class PublishExtraItemList -{ +class PublishExtraItemList { public: - QSet items; + QSet items; private: - QHash indexById; - QHash indexByPublish; - IdManager idman; + QHash indexById; + QHash indexByPublish; + IdManager idman; public: - ~PublishExtraItemList() - { - qDeleteAll(items); - } + ~PublishExtraItemList() { qDeleteAll(items); } void clear() { @@ -2137,10 +1892,7 @@ class PublishExtraItemList idman.clear(); } - int reserveId() - { - return idman.reserveId(); - } + int reserveId() { return idman.reserveId(); } void insert(PublishExtraItem *item) { @@ -2154,50 +1906,41 @@ class PublishExtraItemList indexById.remove(item->id); indexByPublish.remove(item->publish); items.remove(item); - if(item->id != -1) + if (item->id != -1) idman.releaseId(item->id); delete item; } - PublishExtraItem *itemById(int id) const - { - return indexById.value(id); - } + PublishExtraItem *itemById(int id) const { return indexById.value(id); } - PublishExtraItem *itemByPublish(JDnsPublishExtra *publish) const - { - return indexByPublish.value(publish); - } + PublishExtraItem *itemByPublish(JDnsPublishExtra *publish) const { return indexByPublish.value(publish); } }; -class JDnsServiceProvider : public ServiceProvider -{ +class JDnsServiceProvider : public ServiceProvider { Q_OBJECT public: JDnsGlobal *global; // browse - BrowseItemList browseItemList; - QHash items; + BrowseItemList browseItemList; + QHash items; // resolve ResolveItemList resolveItemList; // publish JDnsPublishAddresses *pub_addresses; - QByteArray localHost; - PublishItemList publishItemList; - PublishExtraItemList publishExtraItemList; + QByteArray localHost; + PublishItemList publishItemList; + PublishExtraItemList publishExtraItemList; static JDnsServiceProvider *create(JDnsGlobal *global, QObject *parent = 0) { return new JDnsServiceProvider(global, parent); } - JDnsServiceProvider(JDnsGlobal *_global, QObject *parent = 0) : - ServiceProvider(parent), - pub_addresses(0) + JDnsServiceProvider(JDnsGlobal *_global, QObject *parent = 0) : ServiceProvider(parent), pub_addresses(0) { global = _global; connect(global, SIGNAL(interfacesChanged()), SLOT(interfacesChanged())); @@ -2212,12 +1955,12 @@ class JDnsServiceProvider : public ServiceProvider virtual int browse_start(const QString &_type, const QString &_domain) { QString domain; - if(_domain.isEmpty() || _domain == ".") + if (_domain.isEmpty() || _domain == ".") domain = "local."; else domain = _domain; - if(domain[domain.length() - 1] != '.') + if (domain[domain.length() - 1] != '.') domain += '.'; Q_ASSERT(domain.length() >= 2 && domain[domain.length() - 1] == '.'); @@ -2225,34 +1968,31 @@ class JDnsServiceProvider : public ServiceProvider int id = browseItemList.reserveId(); // no support for non-local domains - if(domain != "local.") - { + if (domain != "local.") { BrowseItem *i = new BrowseItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); browseItemList.insert(i); i->sess->defer(this, "do_browse_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorNoWide)); + Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorNoWide)); return i->id; } - if(!global->ensure_mul()) - { + if (!global->ensure_mul()) { BrowseItem *i = new BrowseItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); browseItemList.insert(i); i->sess->defer(this, "do_browse_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorNoLocal)); + Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorNoLocal)); return i->id; } QByteArray type = _type.toUtf8(); - if(!validServiceType(type)) - { + if (!validServiceType(type)) { BrowseItem *i = new BrowseItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); browseItemList.insert(i); i->sess->defer(this, "do_browse_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorGeneric)); + Q_ARG(XMPP::ServiceBrowser::Error, ServiceBrowser::ErrorGeneric)); return i->id; } @@ -2276,13 +2016,12 @@ class JDnsServiceProvider : public ServiceProvider { int id = resolveItemList.reserveId(); - if(!global->ensure_mul()) - { + if (!global->ensure_mul()) { ResolveItem *i = new ResolveItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); resolveItemList.insert(i); i->sess->defer(this, "do_resolve_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceResolver::Error, ServiceResolver::ErrorNoLocal)); + Q_ARG(XMPP::ServiceResolver::Error, ServiceResolver::ErrorNoLocal)); return i->id; } @@ -2302,34 +2041,32 @@ class JDnsServiceProvider : public ServiceProvider resolveItemList.remove(i); } - virtual int publish_start(const QString &instance, const QString &_type, int port, const QMap &attributes) + virtual int publish_start(const QString &instance, const QString &_type, int port, + const QMap &attributes) { int id = publishItemList.reserveId(); - if(!global->ensure_mul()) - { + if (!global->ensure_mul()) { PublishItem *i = new PublishItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); publishItemList.insert(i); i->sess->defer(this, "do_publish_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorNoLocal)); + Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorNoLocal)); return i->id; } QByteArray type = _type.toUtf8(); - if(!validServiceType(type)) - { + if (!validServiceType(type)) { PublishItem *i = new PublishItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); publishItemList.insert(i); i->sess->defer(this, "do_publish_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); + Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); return i->id; } // make sure A/AAAA records are published - if(!pub_addresses) - { + if (!pub_addresses) { pub_addresses = new JDnsPublishAddresses(global->mul, this); connect(pub_addresses, SIGNAL(hostName(QByteArray)), SLOT(pub_addresses_hostName(QByteArray))); pub_addresses->setUseIPv6(global->haveMulticast6()); @@ -2348,13 +2085,13 @@ class JDnsServiceProvider : public ServiceProvider return i->id; } - virtual void publish_update(int id, const QMap &attributes) + virtual void publish_update(int id, const QMap &attributes) { PublishItem *i = publishItemList.itemById(id); Q_ASSERT(i); // if we already have an error queued, do nothing - if(i->sess->isDeferred(this, "do_publish_error")) + if (i->sess->isDeferred(this, "do_publish_error")) return; i->publish->update(attributes); @@ -2377,22 +2114,21 @@ class JDnsServiceProvider : public ServiceProvider int id = publishItemList.reserveId(); QJDns::Record rec = exportJDNSRecord(name); - if(rec.type == -1) - { + if (rec.type == -1) { PublishExtraItem *i = new PublishExtraItem(id, 0); - i->sess = new ObjectSession(this); + i->sess = new ObjectSession(this); publishExtraItemList.insert(i); i->sess->defer(this, "do_publish_extra_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); + Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); return i->id; } // fill in owner if necessary - if(rec.owner.isEmpty()) + if (rec.owner.isEmpty()) rec.owner = pi->publish->fullname; // fill in the ttl if necessary - if(rec.ttl == 0) + if (rec.ttl == 0) rec.ttl = 4500; PublishExtraItem *i = new PublishExtraItem(id, new JDnsPublishExtra(pi->publish)); @@ -2409,24 +2145,23 @@ class JDnsServiceProvider : public ServiceProvider Q_ASSERT(i); // if we already have an error queued, do nothing - if(i->sess->isDeferred(this, "do_publish_extra_error")) + if (i->sess->isDeferred(this, "do_publish_extra_error")) return; QJDns::Record rec = exportJDNSRecord(name); - if(rec.type == -1) - { + if (rec.type == -1) { i->sess = new ObjectSession(this); i->sess->defer(this, "do_publish_extra_error", Q_ARG(int, i->id), - Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); + Q_ARG(XMPP::ServiceLocalPublisher::Error, ServiceLocalPublisher::ErrorGeneric)); return; } // fill in owner if necessary - if(rec.owner.isEmpty()) - rec.owner = static_cast(i->publish->parent())->fullname; + if (rec.owner.isEmpty()) + rec.owner = static_cast(i->publish->parent())->fullname; // fill in the ttl if necessary - if(rec.ttl == 0) + if (rec.ttl == 0) rec.ttl = 4500; i->publish->update(rec); @@ -2445,22 +2180,20 @@ class JDnsServiceProvider : public ServiceProvider { // remove all extra publishes associated with this publish. // the association can be checked via QObject parenting. - QSet remove; - foreach(PublishExtraItem *i, publishExtraItemList.items) - { - if(static_cast(i->publish->parent()) == pi->publish) + QSet remove; + foreach (PublishExtraItem *i, publishExtraItemList.items) { + if (static_cast(i->publish->parent()) == pi->publish) remove += i; } - foreach(PublishExtraItem *i, remove) + foreach (PublishExtraItem *i, remove) publishExtraItemList.remove(i); } private slots: void interfacesChanged() { - if(pub_addresses) - { + if (pub_addresses) { pub_addresses->setUseIPv6(global->haveMulticast6()); pub_addresses->setUseIPv4(global->haveMulticast4()); } @@ -2469,11 +2202,12 @@ private slots: void jb_available(const QByteArray &instance) { JDnsBrowse *jb = static_cast(sender()); - BrowseItem *i = browseItemList.itemByBrowse(jb); + BrowseItem *i = browseItemList.itemByBrowse(jb); Q_ASSERT(i); - QByteArray name = instance + '.' + jb->typeAndDomain; - ServiceInstance si(QString::fromLatin1(instance), QString::fromLatin1(jb->type), "local.", QMap()); + QByteArray name = instance + '.' + jb->typeAndDomain; + ServiceInstance si(QString::fromLatin1(instance), QString::fromLatin1(jb->type), "local.", + QMap()); items.insert(name, si); emit browse_instanceAvailable(i->id, si); @@ -2482,7 +2216,7 @@ private slots: void jb_unavailable(const QByteArray &instance) { JDnsBrowse *jb = static_cast(sender()); - BrowseItem *i = browseItemList.itemByBrowse(jb); + BrowseItem *i = browseItemList.itemByBrowse(jb); Q_ASSERT(i); QByteArray name = instance + '.' + jb->typeAndDomain; @@ -2506,24 +2240,20 @@ private slots: void jr_finished() { JDnsServiceResolve *jr = static_cast(sender()); - ResolveItem *i = resolveItemList.itemByResolve(jr); + ResolveItem * i = resolveItemList.itemByResolve(jr); Q_ASSERT(i); // parse TXT list into attribute map - QMap attribs; - for(int n = 0; n < jr->attribs.count(); ++n) - { + QMap attribs; + for (int n = 0; n < jr->attribs.count(); ++n) { const QByteArray &a = jr->attribs[n]; - QString key; - QByteArray value; - int x = a.indexOf('='); - if(x != -1) - { - key = QString::fromLatin1(a.mid(0, x)); + QString key; + QByteArray value; + int x = a.indexOf('='); + if (x != -1) { + key = QString::fromLatin1(a.mid(0, x)); value = a.mid(x + 1); - } - else - { + } else { key = QString::fromLatin1(a); } @@ -2534,22 +2264,20 @@ private slots: Q_ASSERT(jr->have4 || jr->have6); QList results; - if(jr->have6) - { + if (jr->have6) { ResolveResult r; r.attributes = attribs; - r.address = jr->addr6; - r.port = jr->port; - r.hostName = jr->host; + r.address = jr->addr6; + r.port = jr->port; + r.hostName = jr->host; results += r; } - if(jr->have4) - { + if (jr->have4) { ResolveResult r; r.attributes = attribs; - r.address = jr->addr4; - r.port = jr->port; - r.hostName = jr->host; + r.address = jr->addr4; + r.port = jr->port; + r.hostName = jr->host; results += r; } @@ -2561,11 +2289,11 @@ private slots: void jr_error(QJDnsSharedRequest::Error e) { JDnsServiceResolve *jr = static_cast(sender()); - ResolveItem *i = resolveItemList.itemByResolve(jr); + ResolveItem * i = resolveItemList.itemByResolve(jr); Q_ASSERT(i); ServiceResolver::Error err; - if(e == QJDnsSharedRequest::ErrorTimeout) + if (e == QJDnsSharedRequest::ErrorTimeout) err = ServiceResolver::ErrorTimeout; else err = ServiceResolver::ErrorGeneric; @@ -2587,14 +2315,14 @@ private slots: void pub_addresses_hostName(const QByteArray &name) { // tell all active publishes about the change - foreach(PublishItem *item, publishItemList.items) + foreach (PublishItem *item, publishItemList.items) item->publish->hostChanged(name); } void jp_published() { JDnsPublish *jp = static_cast(sender()); - PublishItem *i = publishItemList.itemByPublish(jp); + PublishItem *i = publishItemList.itemByPublish(jp); Q_ASSERT(i); emit publish_published(i->id); @@ -2603,11 +2331,11 @@ private slots: void jp_error(QJDnsSharedRequest::Error e) { JDnsPublish *jp = static_cast(sender()); - PublishItem *i = publishItemList.itemByPublish(jp); + PublishItem *i = publishItemList.itemByPublish(jp); Q_ASSERT(i); ServiceLocalPublisher::Error err; - if(e == QJDnsSharedRequest::ErrorConflict) + if (e == QJDnsSharedRequest::ErrorConflict) err = ServiceLocalPublisher::ErrorConflict; else err = ServiceLocalPublisher::ErrorGeneric; @@ -2631,7 +2359,7 @@ private slots: void jpe_published() { JDnsPublishExtra *jp = static_cast(sender()); - PublishExtraItem *i = publishExtraItemList.itemByPublish(jp); + PublishExtraItem *i = publishExtraItemList.itemByPublish(jp); Q_ASSERT(i); emit publish_extra_published(i->id); @@ -2640,11 +2368,11 @@ private slots: void jpe_error(QJDnsSharedRequest::Error e) { JDnsPublishExtra *jp = static_cast(sender()); - PublishExtraItem *i = publishExtraItemList.itemByPublish(jp); + PublishExtraItem *i = publishExtraItemList.itemByPublish(jp); Q_ASSERT(i); ServiceLocalPublisher::Error err; - if(e == QJDnsSharedRequest::ErrorConflict) + if (e == QJDnsSharedRequest::ErrorConflict) err = ServiceLocalPublisher::ErrorConflict; else err = ServiceLocalPublisher::ErrorGeneric; @@ -2667,27 +2395,20 @@ private slots: //---------------------------------------------------------------------------- // JDnsProvider //---------------------------------------------------------------------------- -class JDnsProvider : public IrisNetProvider -{ +class JDnsProvider : public IrisNetProvider { Q_OBJECT Q_INTERFACES(XMPP::IrisNetProvider) public: JDnsGlobal *global; - JDnsProvider() - { - global = 0; - } + JDnsProvider() { global = 0; } - ~JDnsProvider() - { - delete global; - } + ~JDnsProvider() { delete global; } void ensure_global() { - if(!global) + if (!global) global = new JDnsGlobal; } @@ -2710,10 +2431,7 @@ class JDnsProvider : public IrisNetProvider } }; -IrisNetProvider *irisnet_createJDnsProvider() -{ - return new JDnsProvider; -} +IrisNetProvider *irisnet_createJDnsProvider() { return new JDnsProvider; } } // namespace XMPP #include "netnames_jdns.moc" diff --git a/src/irisnet/corelib/objectsession.cpp b/src/irisnet/corelib/objectsession.cpp index ad12b7e7..d4f40a14 100644 --- a/src/irisnet/corelib/objectsession.cpp +++ b/src/irisnet/corelib/objectsession.cpp @@ -26,88 +26,60 @@ #include namespace XMPP { -class ObjectSessionWatcherPrivate -{ +class ObjectSessionWatcherPrivate { public: ObjectSession *sess; }; -class ObjectSessionPrivate : public QObject -{ +class ObjectSessionPrivate : public QObject { Q_OBJECT public: ObjectSession *q; - class MethodCall - { + class MethodCall { public: - QObject *obj; + QObject * obj; QByteArray method; - class Argument - { + class Argument { public: - int type; + int type; void *data; }; QList args; - MethodCall(QObject *_obj, const char *_method) : - obj(_obj), - method(_method) - { - } + MethodCall(QObject *_obj, const char *_method) : obj(_obj), method(_method) {} - ~MethodCall() - { - clearArgs(); - } + ~MethodCall() { clearArgs(); } void clearArgs() { - for(int n = 0; n < args.count(); ++n) + for (int n = 0; n < args.count(); ++n) QMetaType::destroy(args[n].type, args[n].data); args.clear(); } - bool setArgs(QGenericArgument val0 = QGenericArgument(), - QGenericArgument val1 = QGenericArgument(), - QGenericArgument val2 = QGenericArgument(), - QGenericArgument val3 = QGenericArgument(), - QGenericArgument val4 = QGenericArgument(), - QGenericArgument val5 = QGenericArgument(), - QGenericArgument val6 = QGenericArgument(), - QGenericArgument val7 = QGenericArgument(), - QGenericArgument val8 = QGenericArgument(), - QGenericArgument val9 = QGenericArgument()) + bool setArgs(QGenericArgument val0 = QGenericArgument(), QGenericArgument val1 = QGenericArgument(), + QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument(), + QGenericArgument val4 = QGenericArgument(), QGenericArgument val5 = QGenericArgument(), + QGenericArgument val6 = QGenericArgument(), QGenericArgument val7 = QGenericArgument(), + QGenericArgument val8 = QGenericArgument(), QGenericArgument val9 = QGenericArgument()) { - const char *arg_name[] = - { - val0.name(), val1.name(), val2.name(), - val3.name(), val4.name(), val5.name(), - val6.name(), val7.name(), val8.name(), - val9.name() - }; - - void *arg_data[] = - { - val0.data(), val1.data(), val2.data(), - val3.data(), val4.data(), val5.data(), - val6.data(), val7.data(), val8.data(), - val9.data() - }; + const char *arg_name[] = { val0.name(), val1.name(), val2.name(), val3.name(), val4.name(), + val5.name(), val6.name(), val7.name(), val8.name(), val9.name() }; + + void *arg_data[] = { val0.data(), val1.data(), val2.data(), val3.data(), val4.data(), + val5.data(), val6.data(), val7.data(), val8.data(), val9.data() }; clearArgs(); - for(int n = 0; n < 10; ++n) - { - if(arg_name[n] == nullptr) + for (int n = 0; n < 10; ++n) { + if (arg_name[n] == nullptr) break; Argument arg; arg.type = QMetaType::type(arg_name[n]); - if(!arg.type) - { + if (!arg.type) { clearArgs(); return false; } @@ -120,15 +92,12 @@ class ObjectSessionPrivate : public QObject } }; - QList pendingCalls; - QTimer *callTrigger; - bool paused; - QList watchers; + QList pendingCalls; + QTimer * callTrigger; + bool paused; + QList watchers; - ObjectSessionPrivate(ObjectSession *_q) : - QObject(_q), - q(_q), - paused(false) + ObjectSessionPrivate(ObjectSession *_q) : QObject(_q), q(_q), paused(false) { callTrigger = new QTimer(this); connect(callTrigger, SIGNAL(timeout()), SLOT(doCall())); @@ -149,15 +118,14 @@ class ObjectSessionPrivate : public QObject void addPendingCall(MethodCall *call) { pendingCalls += call; - if(!paused && !callTrigger->isActive()) + if (!paused && !callTrigger->isActive()) callTrigger->start(); } bool havePendingCall(QObject *obj, const char *method) const { - foreach(const MethodCall *call, pendingCalls) - { - if(call->obj == obj && qstrcmp(call->method.data(), method) == 0) + foreach (const MethodCall *call, pendingCalls) { + if (call->obj == obj && qstrcmp(call->method.data(), method) == 0) return true; } return false; @@ -165,7 +133,7 @@ class ObjectSessionPrivate : public QObject void invalidateWatchers() { - for(int n = 0; n < watchers.count(); ++n) + for (int n = 0; n < watchers.count(); ++n) watchers[n]->sess = nullptr; watchers.clear(); } @@ -174,22 +142,20 @@ private slots: void doCall() { MethodCall *call = pendingCalls.takeFirst(); - if(!pendingCalls.isEmpty()) + if (!pendingCalls.isEmpty()) callTrigger->start(); Q_ASSERT(call->args.count() <= 10); QGenericArgument arg[10]; - for(int n = 0; n < call->args.count(); ++n) - arg[n] = QGenericArgument(QMetaType::typeName(call->args[n].type), call->args[n].data); + for (int n = 0; n < call->args.count(); ++n) + arg[n] = QGenericArgument(QMetaType::typeName(call->args[n].type), call->args[n].data); bool ok; - ok = QMetaObject::invokeMethod(call->obj, call->method.data(), - Qt::DirectConnection, - arg[0], arg[1], arg[2], arg[3], arg[4], - arg[5], arg[6], arg[7], arg[8], arg[9]); + ok = QMetaObject::invokeMethod(call->obj, call->method.data(), Qt::DirectConnection, arg[0], arg[1], arg[2], + arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9]); Q_ASSERT(ok); - if(!ok) + if (!ok) abort(); delete call; @@ -198,82 +164,57 @@ private slots: ObjectSessionWatcher::ObjectSessionWatcher(ObjectSession *sess) { - d = new ObjectSessionWatcherPrivate; + d = new ObjectSessionWatcherPrivate; d->sess = sess; - if(d->sess) + if (d->sess) d->sess->d->watchers += d; } ObjectSessionWatcher::~ObjectSessionWatcher() { - if(d->sess) + if (d->sess) d->sess->d->watchers.removeAll(d); delete d; } bool ObjectSessionWatcher::isValid() const { - if(d->sess) + if (d->sess) return true; else return false; } -ObjectSession::ObjectSession(QObject *parent) : - QObject(parent) -{ - d = new ObjectSessionPrivate(this); -} +ObjectSession::ObjectSession(QObject *parent) : QObject(parent) { d = new ObjectSessionPrivate(this); } -ObjectSession::~ObjectSession() -{ - delete d; -} +ObjectSession::~ObjectSession() { delete d; } void ObjectSession::reset() { d->invalidateWatchers(); - if(d->callTrigger->isActive()) + if (d->callTrigger->isActive()) d->callTrigger->stop(); qDeleteAll(d->pendingCalls); d->pendingCalls.clear(); } -bool ObjectSession::isDeferred(QObject *obj, const char *method) -{ - return d->havePendingCall(obj, method); -} +bool ObjectSession::isDeferred(QObject *obj, const char *method) { return d->havePendingCall(obj, method); } -void ObjectSession::defer(QObject *obj, const char *method, - QGenericArgument val0, - QGenericArgument val1, - QGenericArgument val2, - QGenericArgument val3, - QGenericArgument val4, - QGenericArgument val5, - QGenericArgument val6, - QGenericArgument val7, - QGenericArgument val8, - QGenericArgument val9) +void ObjectSession::defer(QObject *obj, const char *method, QGenericArgument val0, QGenericArgument val1, + QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, + QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9) { ObjectSessionPrivate::MethodCall *call = new ObjectSessionPrivate::MethodCall(obj, method); call->setArgs(val0, val1, val2, val3, val4, val5, val6, val7, val8, val9); d->addPendingCall(call); } -void ObjectSession::deferExclusive(QObject *obj, const char *method, - QGenericArgument val0, - QGenericArgument val1, - QGenericArgument val2, - QGenericArgument val3, - QGenericArgument val4, - QGenericArgument val5, - QGenericArgument val6, - QGenericArgument val7, - QGenericArgument val8, - QGenericArgument val9) +void ObjectSession::deferExclusive(QObject *obj, const char *method, QGenericArgument val0, QGenericArgument val1, + QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, + QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, + QGenericArgument val8, QGenericArgument val9) { - if(d->havePendingCall(obj, method)) + if (d->havePendingCall(obj, method)) return; ObjectSessionPrivate::MethodCall *call = new ObjectSessionPrivate::MethodCall(obj, method); @@ -285,7 +226,7 @@ void ObjectSession::pause() { Q_ASSERT(!d->paused); - if(d->callTrigger->isActive()) + if (d->callTrigger->isActive()) d->callTrigger->stop(); d->paused = true; } @@ -295,7 +236,7 @@ void ObjectSession::resume() Q_ASSERT(d->paused); d->paused = false; - if(!d->pendingCalls.isEmpty()) + if (!d->pendingCalls.isEmpty()) d->callTrigger->start(); } } // namespace XMPP diff --git a/src/irisnet/corelib/objectsession.h b/src/irisnet/corelib/objectsession.h index 427d949e..b68d06d6 100644 --- a/src/irisnet/corelib/objectsession.h +++ b/src/irisnet/corelib/objectsession.h @@ -25,8 +25,7 @@ namespace XMPP { class ObjectSessionPrivate; class ObjectSessionWatcherPrivate; -class ObjectSession : public QObject -{ +class ObjectSession : public QObject { Q_OBJECT public: @@ -37,28 +36,18 @@ class ObjectSession : public QObject void reset(); bool isDeferred(QObject *obj, const char *method); - void defer(QObject *obj, const char *method, - QGenericArgument val0 = QGenericArgument(), - QGenericArgument val1 = QGenericArgument(), - QGenericArgument val2 = QGenericArgument(), - QGenericArgument val3 = QGenericArgument(), - QGenericArgument val4 = QGenericArgument(), - QGenericArgument val5 = QGenericArgument(), - QGenericArgument val6 = QGenericArgument(), - QGenericArgument val7 = QGenericArgument(), - QGenericArgument val8 = QGenericArgument(), - QGenericArgument val9 = QGenericArgument()); - void deferExclusive(QObject *obj, const char *method, - QGenericArgument val0 = QGenericArgument(), - QGenericArgument val1 = QGenericArgument(), - QGenericArgument val2 = QGenericArgument(), - QGenericArgument val3 = QGenericArgument(), - QGenericArgument val4 = QGenericArgument(), - QGenericArgument val5 = QGenericArgument(), - QGenericArgument val6 = QGenericArgument(), - QGenericArgument val7 = QGenericArgument(), - QGenericArgument val8 = QGenericArgument(), - QGenericArgument val9 = QGenericArgument()); + void defer(QObject *obj, const char *method, QGenericArgument val0 = QGenericArgument(), + QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), + QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), + QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), + QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), + QGenericArgument val9 = QGenericArgument()); + void deferExclusive(QObject *obj, const char *method, QGenericArgument val0 = QGenericArgument(), + QGenericArgument val1 = QGenericArgument(), QGenericArgument val2 = QGenericArgument(), + QGenericArgument val3 = QGenericArgument(), QGenericArgument val4 = QGenericArgument(), + QGenericArgument val5 = QGenericArgument(), QGenericArgument val6 = QGenericArgument(), + QGenericArgument val7 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(), + QGenericArgument val9 = QGenericArgument()); void pause(); void resume(); @@ -68,8 +57,7 @@ class ObjectSession : public QObject ObjectSessionPrivate *d; }; -class ObjectSessionWatcher -{ +class ObjectSessionWatcher { public: ObjectSessionWatcher(ObjectSession *sess); ~ObjectSessionWatcher(); diff --git a/src/irisnet/noncore/cutestuff/bsocket.cpp b/src/irisnet/noncore/cutestuff/bsocket.cpp index cc3a2d99..869aa7aa 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.cpp +++ b/src/irisnet/noncore/cutestuff/bsocket.cpp @@ -27,18 +27,16 @@ //#define BS_DEBUG #ifdef BS_DEBUG -# define BSDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") +#define BSDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif #define READBUFSIZE 65536 // CS_NAMESPACE_BEGIN -class QTcpSocketSignalRelay : public QObject -{ +class QTcpSocketSignalRelay : public QObject { Q_OBJECT public: - QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = nullptr) - :QObject(parent) + QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = nullptr) : QObject(parent) { qRegisterMetaType("QAbstractSocket::SocketError"); connect(sock, SIGNAL(hostFound()), SLOT(sock_hostFound()), Qt::QueuedConnection); @@ -46,7 +44,8 @@ class QTcpSocketSignalRelay : public QObject connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()), Qt::QueuedConnection); connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()), Qt::QueuedConnection); connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)), Qt::QueuedConnection); - connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)), Qt::QueuedConnection); + connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)), + Qt::QueuedConnection); } signals: @@ -58,86 +57,60 @@ class QTcpSocketSignalRelay : public QObject void error(QAbstractSocket::SocketError); public slots: - void sock_hostFound() - { - emit hostFound(); - } + void sock_hostFound() { emit hostFound(); } - void sock_connected() - { - emit connected(); - } + void sock_connected() { emit connected(); } - void sock_disconnected() - { - emit disconnected(); - } + void sock_disconnected() { emit disconnected(); } - void sock_readyRead() - { - emit readyRead(); - } + void sock_readyRead() { emit readyRead(); } - void sock_bytesWritten(qint64 x) - { - emit bytesWritten(x); - } + void sock_bytesWritten(qint64 x) { emit bytesWritten(x); } - void sock_error(QAbstractSocket::SocketError x) - { - emit error(x); - } + void sock_error(QAbstractSocket::SocketError x) { emit error(x); } }; -class HappyEyeballsConnector : public QObject -{ +class HappyEyeballsConnector : public QObject { Q_OBJECT public: - enum State { - Failure, - Created, - Resolve, - Connecting, - Connected - }; + enum State { Failure, Created, Resolve, Connecting, Connected }; struct SockData { - QTcpSocket *sock; + QTcpSocket * sock; QTcpSocketSignalRelay *relay; - State state; + State state; XMPP::ServiceResolver *resolver; }; /*! source data */ - QString service; - QString transport; - QString domain; - quint16 port = 0; - QHostAddress address; + QString service; + QString transport; + QString domain; + quint16 port = 0; + QHostAddress address; QAbstractSocket::NetworkLayerProtocol fallbackProtocol = QAbstractSocket::IPv4Protocol; /*! runtime data */ - QString lastError; - int lastIndex; + QString lastError; + int lastIndex; QList sockets; - QTimer fallbackTimer; + QTimer fallbackTimer; - HappyEyeballsConnector(QObject *parent) : - QObject(parent) + HappyEyeballsConnector(QObject *parent) : QObject(parent) { fallbackTimer.setSingleShot(true); fallbackTimer.setInterval(250); /* rfc recommends 150-250ms */ connect(&fallbackTimer, SIGNAL(timeout()), SLOT(startFallback())); } - SockData& addSocket() + SockData &addSocket() { SockData sd; sd.state = Created; - sd.sock = new QTcpSocket(this); + sd.sock = new QTcpSocket(this); sd.sock->setProxy(QNetworkProxy::NoProxy); sd.sock->setReadBufferSize(READBUFSIZE); - sd.relay = new QTcpSocketSignalRelay(sd.sock, this); + sd.relay = new QTcpSocketSignalRelay(sd.sock, this); sd.resolver = nullptr; connect(sd.relay, SIGNAL(connected()), SLOT(qs_connected())); connect(sd.relay, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(qs_error(QAbstractSocket::SocketError))); @@ -159,8 +132,8 @@ class HappyEyeballsConnector : public QObject BSDEBUG << "a:" << address << "p:" << port; #endif this->address = address; - SockData &sd = addSocket(); - sd.state = Connecting; + SockData &sd = addSocket(); + sd.state = Connecting; sd.sock->connectToHost(address, port); } @@ -171,16 +144,19 @@ class HappyEyeballsConnector : public QObject BSDEBUG << "h:" << host << "p:" << port << "pr:" << protocol; #endif this->domain = host; - this->port = port; + this->port = port; SockData &sd = addSocket(); QHostAddress addr(host); if (addr.isNull()) { sd.resolver = new XMPP::ServiceResolver; initResolver(sd.resolver); - sd.resolver->setProtocol(protocol == QAbstractSocket::UnknownNetworkLayerProtocol? - (fallbackProtocol == QAbstractSocket::IPv4Protocol? XMPP::ServiceResolver::IPv6 : XMPP::ServiceResolver::IPv4) : - (protocol== QAbstractSocket::IPv4Protocol? XMPP::ServiceResolver::IPv4 : XMPP::ServiceResolver::IPv6)); + sd.resolver->setProtocol(protocol == QAbstractSocket::UnknownNetworkLayerProtocol + ? (fallbackProtocol == QAbstractSocket::IPv4Protocol + ? XMPP::ServiceResolver::IPv6 + : XMPP::ServiceResolver::IPv4) + : (protocol == QAbstractSocket::IPv4Protocol ? XMPP::ServiceResolver::IPv4 + : XMPP::ServiceResolver::IPv6)); if (protocol == QAbstractSocket::UnknownNetworkLayerProtocol) { addSocket(); fallbackTimer.start(); @@ -190,7 +166,7 @@ class HappyEyeballsConnector : public QObject } else { // connecting by IP. lastIndex = sockets.count() - 1; - sd.state = Connecting; + sd.state = Connecting; sd.sock->connectToHost(addr, port); } } @@ -200,12 +176,12 @@ class HappyEyeballsConnector : public QObject #ifdef BS_DEBUG BSDEBUG << "s:" << service << "t:" << transport << "d:" << domain; #endif - this->service = service; + this->service = service; this->transport = transport; - this->domain = domain; - this->port = port; - SockData &sd = addSocket(); - sd.resolver = new XMPP::ServiceResolver(this); + this->domain = domain; + this->port = port; + SockData &sd = addSocket(); + sd.resolver = new XMPP::ServiceResolver(this); sd.resolver->setProtocol(XMPP::ServiceResolver::HappyEyeballs); connect(sd.resolver, SIGNAL(srvReady()), SLOT(splitSrvResolvers())); // we don't care about special handling of fail. we have fallback host there anyway @@ -217,11 +193,12 @@ class HappyEyeballsConnector : public QObject SockData takeCurrent(QObject *parent) { SockData csd = sockets.takeAt(lastIndex); - lastIndex = -1; + lastIndex = -1; disconnect(csd.relay); csd.relay->setParent(parent); csd.sock->setParent(parent); - delete csd.resolver; // FIME ensure it's accessible only from connected signal. we don't delete resolver from its slot + delete csd + .resolver; // FIME ensure it's accessible only from connected signal. we don't delete resolver from its slot csd.resolver = nullptr; return csd; } @@ -245,8 +222,10 @@ class HappyEyeballsConnector : public QObject void initResolver(XMPP::ServiceResolver *resolver) { resolver->setParent(this); - connect(resolver, SIGNAL(resultReady(QHostAddress,quint16)), this, SLOT(handleDnsReady(QHostAddress,quint16))); - connect(resolver, SIGNAL(error(XMPP::ServiceResolver::Error)), this, SLOT(handleDnsError(XMPP::ServiceResolver::Error))); + connect(resolver, SIGNAL(resultReady(QHostAddress, quint16)), this, + SLOT(handleDnsReady(QHostAddress, quint16))); + connect(resolver, SIGNAL(error(XMPP::ServiceResolver::Error)), this, + SLOT(handleDnsError(XMPP::ServiceResolver::Error))); } void setCurrentByResolver(XMPP::ServiceResolver *resolver) @@ -280,7 +259,7 @@ private slots: #ifdef BS_DEBUG BSDEBUG; #endif - setCurrentByRelay(static_cast(sender())); + setCurrentByRelay(static_cast(sender())); for (int i = 0; i < sockets.count(); i++) { if (i != lastIndex) { abortSocket(sockets[i]); @@ -294,7 +273,7 @@ private slots: void qs_error(QAbstractSocket::SocketError errorCode) { - setCurrentByRelay(static_cast(sender())); + setCurrentByRelay(static_cast(sender())); // TODO remember error code lastError = sockets[lastIndex].sock->errorString(); #ifdef BS_DEBUG @@ -315,10 +294,10 @@ private slots: #ifdef BS_DEBUG BSDEBUG << "splitting resolvers"; #endif - setCurrentByResolver(static_cast(sender())); - SockData &sdv4 = sockets[lastIndex]; - SockData &sdv6 = addSocket(); - XMPP::ServiceResolver::ProtoSplit ps = sdv4.resolver->happySplit(); + setCurrentByResolver(static_cast(sender())); + SockData & sdv4 = sockets[lastIndex]; + SockData & sdv6 = addSocket(); + XMPP::ServiceResolver::ProtoSplit ps = sdv4.resolver->happySplit(); initResolver(ps.ipv4); initResolver(ps.ipv6); @@ -326,7 +305,7 @@ private slots: sdv4.resolver->deleteLater(); sdv4.resolver = ps.ipv4; - sdv4.state = Created; + sdv4.state = Created; sdv6.resolver = ps.ipv6; if (fallbackProtocol == QAbstractSocket::IPv4Protocol) { @@ -345,13 +324,14 @@ private slots: #ifdef BS_DEBUG BSDEBUG << "a:" << address << "p:" << port; #endif - setCurrentByResolver(static_cast(sender())); + setCurrentByResolver(static_cast(sender())); sockets[lastIndex].state = Connecting; sockets[lastIndex].sock->connectToHost(address, port); } /* resolver failed the dns lookup */ - void handleDnsError(XMPP::ServiceResolver::Error e) { + void handleDnsError(XMPP::ServiceResolver::Error e) + { #ifdef BS_DEBUG BSDEBUG << "e:" << e; #else @@ -367,7 +347,7 @@ private slots: #ifdef BS_DEBUG BSDEBUG; #endif - for(int i = 0; i < sockets.count(); i++) { + for (int i = 0; i < sockets.count(); i++) { SockData &sd = sockets[i]; if (sd.state == Created) { sd.state = Resolve; @@ -376,8 +356,9 @@ private slots: } else { sd.resolver = new XMPP::ServiceResolver; initResolver(sd.resolver); - sd.resolver->setProtocol(fallbackProtocol == QAbstractSocket::IPv4Protocol? - XMPP::ServiceResolver::IPv4 : XMPP::ServiceResolver::IPv6); + sd.resolver->setProtocol(fallbackProtocol == QAbstractSocket::IPv4Protocol + ? XMPP::ServiceResolver::IPv4 + : XMPP::ServiceResolver::IPv6); sd.resolver->start(domain, port); } } @@ -389,29 +370,27 @@ private slots: void error(QAbstractSocket::SocketError); }; -class BSocket::Private -{ +class BSocket::Private { public: Private() { - qsock = nullptr; + qsock = nullptr; qsock_relay = nullptr; } - QTcpSocket *qsock; + QTcpSocket * qsock; QTcpSocketSignalRelay *qsock_relay; - int state; + int state; - QString domain; //!< Domain we are currently connected to - QString host; //!< Hostname we are currently connected to + QString domain; //!< Domain we are currently connected to + QString host; //!< Hostname we are currently connected to QHostAddress address; //!< IP address we are currently connected to - quint16 port; //!< Port we are currently connected to + quint16 port; //!< Port we are currently connected to QPointer connector; }; -BSocket::BSocket(QObject *parent) -:ByteStream(parent) +BSocket::BSocket(QObject *parent) : ByteStream(parent) { d = new Private; resetConnection(); @@ -432,13 +411,14 @@ void BSocket::resetConnection(bool clear) delete d->connector; // fixme: deleteLater? } - if(d->qsock) { + if (d->qsock) { delete d->qsock_relay; d->qsock_relay = nullptr; // move remaining into the local queue if (d->qsock->isOpen()) { - QByteArray block(int(d->qsock->bytesAvailable()), 0); // memory won't never be cheap enough to have gigabytes for socket buffer + QByteArray block(int(d->qsock->bytesAvailable()), + 0); // memory won't never be cheap enough to have gigabytes for socket buffer if (block.size()) { d->qsock->read(block.data(), block.size()); appendRead(block); @@ -446,29 +426,29 @@ void BSocket::resetConnection(bool clear) d->qsock->close(); } - //d->sd.deleteLater(d->qsock); + // d->sd.deleteLater(d->qsock); d->qsock->deleteLater(); d->qsock = nullptr; - } - else { - if(clear) + } else { + if (clear) clearReadBuffer(); } - d->state = Idle; - d->domain = ""; - d->host = ""; + d->state = Idle; + d->domain = ""; + d->host = ""; d->address = QHostAddress(); - d->port = 0; + d->port = 0; setOpenMode(QIODevice::NotOpen); } void BSocket::ensureConnector() { - if(!d->connector) { + if (!d->connector) { d->connector = new HappyEyeballsConnector(this); connect(d->connector, SIGNAL(connected()), SLOT(qs_connected())); - connect(d->connector, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(qs_error(QAbstractSocket::SocketError))); + connect(d->connector, SIGNAL(error(QAbstractSocket::SocketError)), + SLOT(qs_error(QAbstractSocket::SocketError))); } } @@ -477,8 +457,8 @@ void BSocket::connectToHost(const QHostAddress &address, quint16 port) { resetConnection(true); d->address = address; - d->port = port; - d->state = Connecting; + d->port = port; + d->state = Connecting; ensureConnector(); d->connector->connectToHost(address, port); @@ -488,8 +468,8 @@ void BSocket::connectToHost(const QHostAddress &address, quint16 port) void BSocket::connectToHost(const QString &host, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol) { resetConnection(true); - d->host = host; - d->port = port; + d->host = host; + d->port = port; d->state = Connecting; ensureConnector(); @@ -501,20 +481,17 @@ void BSocket::connectToHost(const QString &service, const QString &transport, co { resetConnection(true); d->domain = domain; - d->state = Connecting; + d->state = Connecting; ensureConnector(); d->connector->connectToHost(service, transport, domain, port); } -QAbstractSocket* BSocket::abstractSocket() const -{ - return d->qsock; -} +QAbstractSocket *BSocket::abstractSocket() const { return d->qsock; } qintptr BSocket::socket() const { - if(d->qsock) + if (d->qsock) return d->qsock->socketDescriptor(); else return -1; @@ -524,19 +501,16 @@ void BSocket::setSocket(QTcpSocket *s) { resetConnection(true); s->setParent(this); - d->qsock = s; + d->qsock = s; d->qsock_relay = new QTcpSocketSignalRelay(d->qsock, this); qs_connected_step2(false); // we have desriptor already. so it's already known to be connected } -int BSocket::state() const -{ - return d->state; -} +int BSocket::state() const { return d->state; } bool BSocket::isOpen() const { - if(d->state == Connected) + if (d->state == Connected) return true; else return false; @@ -544,10 +518,10 @@ bool BSocket::isOpen() const void BSocket::close() { - if(d->state == Idle) + if (d->state == Idle) return; - if(d->qsock) { + if (d->qsock) { d->state = Closing; d->qsock->close(); if (d->qsock->state() == QAbstractSocket::ClosingState) { @@ -555,15 +529,14 @@ void BSocket::close() } else { resetConnection(); } - } - else { + } else { resetConnection(); } } qint64 BSocket::writeData(const char *data, qint64 maxSize) { - if(d->state != Connected) + if (d->state != Connected) return 0; #ifdef BS_DEBUG_EXTRA BSDEBUG << "- [" << maxSize << "]: {" << QByteArray::fromRawData(data, maxSize) << "}"; @@ -573,13 +546,13 @@ qint64 BSocket::writeData(const char *data, qint64 maxSize) qint64 BSocket::readData(char *data, qint64 maxSize) { - if(!maxSize) { + if (!maxSize) { return 0; } qint64 readSize; - if(d->qsock) { + if (d->qsock) { qint64 max = bytesAvailable(); - if(maxSize <= 0 || maxSize > max) { + if (maxSize <= 0 || maxSize > max) { maxSize = max; } readSize = d->qsock->read(data, maxSize); @@ -595,7 +568,7 @@ qint64 BSocket::readData(char *data, qint64 maxSize) qint64 BSocket::bytesAvailable() const { - if(d->qsock) + if (d->qsock) return d->qsock->bytesAvailable(); else return ByteStream::bytesAvailable(); @@ -603,14 +576,14 @@ qint64 BSocket::bytesAvailable() const qint64 BSocket::bytesToWrite() const { - if(!d->qsock) + if (!d->qsock) return 0; return d->qsock->bytesToWrite(); } QHostAddress BSocket::address() const { - if(d->qsock) + if (d->qsock) return d->qsock->localAddress(); else return QHostAddress(); @@ -618,7 +591,7 @@ QHostAddress BSocket::address() const quint16 BSocket::port() const { - if(d->qsock) + if (d->qsock) return d->qsock->localPort(); else return 0; @@ -626,7 +599,7 @@ quint16 BSocket::port() const QHostAddress BSocket::peerAddress() const { - if(d->qsock) + if (d->qsock) return d->qsock->peerAddress(); else return QHostAddress(); @@ -634,7 +607,7 @@ QHostAddress BSocket::peerAddress() const quint16 BSocket::peerPort() const { - if(d->qsock) + if (d->qsock) return d->qsock->peerPort(); else return 0; @@ -643,8 +616,8 @@ quint16 BSocket::peerPort() const void BSocket::qs_connected() { HappyEyeballsConnector::SockData sd = d->connector->takeCurrent(this); - d->qsock = sd.sock; - d->qsock_relay = sd.relay; + d->qsock = sd.sock; + d->qsock_relay = sd.relay; d->connector->deleteLater(); qs_connected_step2(true); } @@ -672,8 +645,7 @@ void BSocket::qs_connected_step2(bool signalConnected) void BSocket::qs_closed() { - if(d->state == Closing) - { + if (d->state == Closing) { #ifdef BS_DEBUG BSDEBUG << "Delayed Close Finished"; #endif @@ -682,10 +654,7 @@ void BSocket::qs_closed() } } -void BSocket::qs_readyRead() -{ - emit readyRead(); -} +void BSocket::qs_readyRead() { emit readyRead(); } void BSocket::qs_bytesWritten(qint64 x64) { @@ -698,7 +667,7 @@ void BSocket::qs_bytesWritten(qint64 x64) void BSocket::qs_error(QAbstractSocket::SocketError x) { - if(x == QTcpSocket::RemoteHostClosedError) { + if (x == QTcpSocket::RemoteHostClosedError) { #ifdef BS_DEBUG BSDEBUG << "Connection Closed"; #endif @@ -711,9 +680,9 @@ void BSocket::qs_error(QAbstractSocket::SocketError x) BSDEBUG << "Error"; #endif resetConnection(); - if(x == QTcpSocket::ConnectionRefusedError) + if (x == QTcpSocket::ConnectionRefusedError) emit error(ErrConnectionRefused); - else if(x == QTcpSocket::HostNotFoundError) + else if (x == QTcpSocket::HostNotFoundError) emit error(ErrHostNotFound); else emit error(ErrRead); diff --git a/src/irisnet/noncore/cutestuff/bsocket.h b/src/irisnet/noncore/cutestuff/bsocket.h index e0f59416..66fc476e 100644 --- a/src/irisnet/noncore/cutestuff/bsocket.h +++ b/src/irisnet/noncore/cutestuff/bsocket.h @@ -35,25 +35,26 @@ class QString; /*! Socket with automatic hostname lookups, using SRV, AAAA and A DNS queries. */ -class BSocket : public ByteStream -{ +class BSocket : public ByteStream { Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound }; enum State { Idle, HostLookup, Connecting, Connected, Closing }; - BSocket(QObject *parent=nullptr); + BSocket(QObject *parent = nullptr); ~BSocket(); /*! Connect to an already resolved host */ void connectToHost(const QHostAddress &address, quint16 port); /*! Connect to a host via the specified protocol, or the default protocols if not specified */ - void connectToHost(const QString &host, quint16 port, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::UnknownNetworkLayerProtocol); + void connectToHost(const QString &host, quint16 port, + QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::UnknownNetworkLayerProtocol); /*! Connect to the hosts for the specified service */ - void connectToHost(const QString &service, const QString &transport, const QString &domain, quint16 port = std::numeric_limits::max()); - virtual QAbstractSocket* abstractSocket() const; - qintptr socket() const; - void setSocket(QTcpSocket *); - int state() const; + void connectToHost(const QString &service, const QString &transport, const QString &domain, + quint16 port = std::numeric_limits::max()); + virtual QAbstractSocket *abstractSocket() const; + qintptr socket() const; + void setSocket(QTcpSocket *); + int state() const; // from ByteStream bool isOpen() const; @@ -64,11 +65,11 @@ class BSocket : public ByteStream // local QHostAddress address() const; - quint16 port() const; + quint16 port() const; // remote QHostAddress peerAddress() const; - quint16 peerPort() const; + quint16 peerPort() const; protected: qint64 writeData(const char *data, qint64 maxSize); @@ -89,7 +90,7 @@ private slots: class Private; Private *d; - void resetConnection(bool clear=false); + void resetConnection(bool clear = false); void ensureConnector(); void recreate_resolver(); bool check_protocol_fallback(); diff --git a/src/irisnet/noncore/cutestuff/bytestream.cpp b/src/irisnet/noncore/cutestuff/bytestream.cpp index b352435f..053a737d 100644 --- a/src/irisnet/noncore/cutestuff/bytestream.cpp +++ b/src/irisnet/noncore/cutestuff/bytestream.cpp @@ -55,41 +55,33 @@ //! Also available are the static convenience functions ByteStream::appendArray() //! and ByteStream::takeArray(), which make dealing with byte queues very easy. -class ByteStream::Private -{ +class ByteStream::Private { public: Private() {} QByteArray readBuf, writeBuf; - int errorCode; - QString errorText; + int errorCode; + QString errorText; }; //! //! Constructs a ByteStream object with parent \a parent. -ByteStream::ByteStream(QObject *parent) -:QIODevice(parent) -{ - d = new Private; -} +ByteStream::ByteStream(QObject *parent) : QIODevice(parent) { d = new Private; } //! //! Destroys the object and frees allocated resources. -ByteStream::~ByteStream() -{ - delete d; -} +ByteStream::~ByteStream() { delete d; } //! //! Writes array \a a to the stream. qint64 ByteStream::writeData(const char *data, qint64 maxSize) { - if(!isOpen()) - return - 1; + if (!isOpen()) + return -1; - bool doWrite = bytesToWrite() == 0 ? true: false; + bool doWrite = bytesToWrite() == 0 ? true : false; d->writeBuf.append(data, maxSize); - if(doWrite) + if (doWrite) tryWrite(); return maxSize; } @@ -99,7 +91,7 @@ qint64 ByteStream::writeData(const char *data, qint64 maxSize) //! \a read will return all available data. qint64 ByteStream::readData(char *data, qint64 maxSize) { - maxSize = maxSize > d->readBuf.size()? d->readBuf.size() : maxSize; + maxSize = maxSize > d->readBuf.size() ? d->readBuf.size() : maxSize; memcpy(data, d->readBuf.constData(), maxSize); d->readBuf.remove(0, maxSize); return maxSize; @@ -107,85 +99,52 @@ qint64 ByteStream::readData(char *data, qint64 maxSize) //! //! Returns the number of bytes available for reading. -qint64 ByteStream::bytesAvailable() const -{ - return QIODevice::bytesAvailable() + d->readBuf.size(); -} +qint64 ByteStream::bytesAvailable() const { return QIODevice::bytesAvailable() + d->readBuf.size(); } //! //! Returns the number of bytes that are waiting to be written. -qint64 ByteStream::bytesToWrite() const -{ - return d->writeBuf.size(); -} +qint64 ByteStream::bytesToWrite() const { return d->writeBuf.size(); } //! //! Clears the read buffer. -void ByteStream::clearReadBuffer() -{ - d->readBuf.resize(0); -} +void ByteStream::clearReadBuffer() { d->readBuf.resize(0); } //! //! Clears the write buffer. -void ByteStream::clearWriteBuffer() -{ - d->writeBuf.resize(0); -} +void ByteStream::clearWriteBuffer() { d->writeBuf.resize(0); } //! //! Appends \a block to the end of the read buffer. -void ByteStream::appendRead(const QByteArray &block) -{ - d->readBuf += block; -} +void ByteStream::appendRead(const QByteArray &block) { d->readBuf += block; } //! //! Appends \a block to the end of the write buffer. -void ByteStream::appendWrite(const QByteArray &block) -{ - d->writeBuf += block; -} +void ByteStream::appendWrite(const QByteArray &block) { d->writeBuf += block; } //! //! Returns \a size bytes from the start of the read buffer. //! If \a size is 0, then all available data will be returned. //! If \a del is TRUE, then the bytes are also removed. -QByteArray ByteStream::takeRead(int size, bool del) -{ - return takeArray(d->readBuf, size, del); -} +QByteArray ByteStream::takeRead(int size, bool del) { return takeArray(d->readBuf, size, del); } //! //! Returns \a size bytes from the start of the write buffer. //! If \a size is 0, then all available data will be returned. //! If \a del is TRUE, then the bytes are also removed. -QByteArray ByteStream::takeWrite(int size, bool del) -{ - return takeArray(d->writeBuf, size, del); -} +QByteArray ByteStream::takeWrite(int size, bool del) { return takeArray(d->writeBuf, size, del); } //! //! Returns a reference to the read buffer. -QByteArray & ByteStream::readBuf() -{ - return d->readBuf; -} +QByteArray &ByteStream::readBuf() { return d->readBuf; } //! //! Returns a reference to the write buffer. -QByteArray & ByteStream::writeBuf() -{ - return d->writeBuf; -} +QByteArray &ByteStream::writeBuf() { return d->writeBuf; } //! //! Attempts to try and write some bytes from the write buffer, and returns the number //! successfully written or -1 on error. The default implementation returns -1. -int ByteStream::tryWrite() -{ - return -1; -} +int ByteStream::tryWrite() { return -1; } //! //! Returns \a size bytes from the start of the array pointed to by \a from. @@ -194,12 +153,11 @@ int ByteStream::tryWrite() QByteArray ByteStream::takeArray(QByteArray &from, int size, bool del) { QByteArray result; - if(size == 0) { + if (size == 0) { result = from; - if(del) + if (del) from.resize(0); - } - else { + } else { result = from.left(size); if (del) { from.remove(0, size); @@ -210,17 +168,11 @@ QByteArray ByteStream::takeArray(QByteArray &from, int size, bool del) //! //! Returns last error code. -int ByteStream::errorCode() const -{ - return d->errorCode; -} +int ByteStream::errorCode() const { return d->errorCode; } //! //! Returns last error string corresponding to last error code. -QString &ByteStream::errorText() const -{ - return d->errorText; -} +QString &ByteStream::errorText() const { return d->errorText; } //! //! Sets last error with \a code and \a text and emit it @@ -233,11 +185,11 @@ void ByteStream::setError(int code, const QString &text) } } - void connectionClosed(); - void delayedCloseFinished(); - void readyRead(); - void bytesWritten(qint64); - void error(int); +void connectionClosed(); +void delayedCloseFinished(); +void readyRead(); +void bytesWritten(qint64); +void error(int); //! \fn void ByteStream::connectionClosed() //! This signal is emitted when the remote end of the stream closes. diff --git a/src/irisnet/noncore/cutestuff/bytestream.h b/src/irisnet/noncore/cutestuff/bytestream.h index 2b88b429..c11335cc 100644 --- a/src/irisnet/noncore/cutestuff/bytestream.h +++ b/src/irisnet/noncore/cutestuff/bytestream.h @@ -28,24 +28,23 @@ class QAbstractSocket; // CS_NAMESPACE_BEGIN // CS_EXPORT_BEGIN -class ByteStream : public QIODevice -{ +class ByteStream : public QIODevice { Q_OBJECT public: enum Error { ErrOk, ErrRead, ErrWrite, ErrCustom = 10 }; - ByteStream(QObject *parent=nullptr); - ~ByteStream()=0; + ByteStream(QObject *parent = nullptr); + ~ByteStream() = 0; - bool isSequential() const { return true; } + bool isSequential() const { return true; } qint64 bytesAvailable() const; qint64 bytesToWrite() const; - static QByteArray takeArray(QByteArray &from, int size=0, bool del=true); + static QByteArray takeArray(QByteArray &from, int size = 0, bool del = true); - int errorCode() const; + int errorCode() const; QString &errorText() const; - virtual QAbstractSocket* abstractSocket() const { return nullptr; } + virtual QAbstractSocket *abstractSocket() const { return nullptr; } signals: void connectionClosed(); @@ -56,22 +55,22 @@ class ByteStream : public QIODevice qint64 writeData(const char *data, qint64 maxSize); qint64 readData(char *data, qint64 maxSize); - void setError(int code = ErrOk, const QString &text = QString()); - void clearReadBuffer(); - void clearWriteBuffer(); - void appendRead(const QByteArray &); - void appendWrite(const QByteArray &); - QByteArray takeRead(int size=0, bool del=true); - QByteArray takeWrite(int size=0, bool del=true); - QByteArray & readBuf(); - QByteArray & writeBuf(); + void setError(int code = ErrOk, const QString &text = QString()); + void clearReadBuffer(); + void clearWriteBuffer(); + void appendRead(const QByteArray &); + void appendWrite(const QByteArray &); + QByteArray takeRead(int size = 0, bool del = true); + QByteArray takeWrite(int size = 0, bool del = true); + QByteArray &readBuf(); + QByteArray &writeBuf(); virtual int tryWrite(); private: -//! \if _hide_doc_ + //! \if _hide_doc_ class Private; Private *d; -//! \endif + //! \endif }; // CS_EXPORT_END // CS_NAMESPACE_END diff --git a/src/irisnet/noncore/cutestuff/httpconnect.cpp b/src/irisnet/noncore/cutestuff/httpconnect.cpp index 0bd8a8cd..9c2c88f5 100644 --- a/src/irisnet/noncore/cutestuff/httpconnect.cpp +++ b/src/irisnet/noncore/cutestuff/httpconnect.cpp @@ -35,14 +35,12 @@ QString escapeOutput(const QByteArray &in) { QString out; - for(int n = 0; n < in.size(); ++n) { - if(in[n] == '\\') { + for (int n = 0; n < in.size(); ++n) { + if (in[n] == '\\') { out += QString("\\\\"); - } - else if(in[n] >= 32 && in[n] < 127) { + } else if (in[n] >= 32 && in[n] < 127) { out += QChar::fromLatin1(in[n]); - } - else { + } else { out += QString().sprintf("\\x%02x", (unsigned char)in[n]); } } @@ -53,14 +51,13 @@ QString escapeOutput(const QByteArray &in) static QString extractLine(QByteArray *buf, bool *found) { // Scan for newline - int index = buf->indexOf ("\r\n"); + int index = buf->indexOf("\r\n"); if (index == -1) { // Newline not found if (found) *found = false; return ""; - } - else { + } else { // Found newline QString s = QString::fromLatin1(buf->left(index)); buf->remove(0, index + 2); @@ -74,48 +71,43 @@ static QString extractLine(QByteArray *buf, bool *found) static bool extractMainHeader(const QString &line, QString *proto, int *code, QString *msg) { int n = line.indexOf(' '); - if(n == -1) + if (n == -1) return false; - if(proto) + if (proto) *proto = line.mid(0, n); ++n; int n2 = line.indexOf(' ', n); - if(n2 == -1) + if (n2 == -1) return false; - if(code) - *code = line.mid(n, n2-n).toInt(); - n = n2+1; - if(msg) + if (code) + *code = line.mid(n, n2 - n).toInt(); + n = n2 + 1; + if (msg) *msg = line.mid(n); return true; } -class HttpConnect::Private -{ +class HttpConnect::Private { public: - Private(HttpConnect *_q) : - sock(_q) - { - } + Private(HttpConnect *_q) : sock(_q) {} BSocket sock; QString host; - int port; + int port; QString user, pass; QString real_host; - int real_port; + int real_port; QByteArray recvBuf; - bool inHeader; + bool inHeader; QStringList headerLines; - int toWrite; + int toWrite; bool active; }; -HttpConnect::HttpConnect(QObject *parent) -:ByteStream(parent) +HttpConnect::HttpConnect(QObject *parent) : ByteStream(parent) { d = new Private(this); connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected())); @@ -136,9 +128,9 @@ HttpConnect::~HttpConnect() void HttpConnect::resetConnection(bool clear) { - if(d->sock.state() != BSocket::Idle) + if (d->sock.state() != BSocket::Idle) d->sock.close(); - if(clear) { + if (clear) { clearReadBuffer(); d->recvBuf.resize(0); } @@ -156,14 +148,14 @@ void HttpConnect::connectToHost(const QString &proxyHost, int proxyPort, const Q { resetConnection(true); - d->host = proxyHost; - d->port = proxyPort; + d->host = proxyHost; + d->port = proxyPort; d->real_host = host; d->real_port = port; #ifdef PROX_DEBUG fprintf(stderr, "HttpConnect: Connecting to %s:%d", qPrintable(proxyHost), proxyPort); - if(d->user.isEmpty()) + if (d->user.isEmpty()) fprintf(stderr, "\n"); else fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass)); @@ -174,20 +166,20 @@ void HttpConnect::connectToHost(const QString &proxyHost, int proxyPort, const Q void HttpConnect::close() { d->sock.close(); - if(d->sock.bytesToWrite() == 0) + if (d->sock.bytesToWrite() == 0) resetConnection(); } qint64 HttpConnect::writeData(const char *data, qint64 maxSize) { - if(d->active) + if (d->active) return d->sock.write(data, maxSize); return 0; } qint64 HttpConnect::bytesToWrite() const { - if(d->active) + if (d->active) return d->sock.bytesToWrite(); else return 0; @@ -204,7 +196,7 @@ void HttpConnect::sock_connected() // connected, now send the request QString s; s += QString("CONNECT ") + d->real_host + ':' + QString::number(d->real_port) + " HTTP/1.0\r\n"; - if(!d->user.isEmpty()) { + if (!d->user.isEmpty()) { QString str = d->user + ':' + d->pass; s += QString("Proxy-Authorization: Basic ") + QCA::Base64().encodeString(str) + "\r\n"; } @@ -221,18 +213,17 @@ void HttpConnect::sock_connected() void HttpConnect::sock_connectionClosed() { - if(d->active) { + if (d->active) { resetConnection(); connectionClosed(); - } - else { + } else { setError(ErrProxyNeg); } } void HttpConnect::sock_delayedCloseFinished() { - if(d->active) { + if (d->active) { resetConnection(); delayedCloseFinished(); } @@ -242,17 +233,17 @@ void HttpConnect::sock_readyRead() { QByteArray block = d->sock.readAll(); - if(!d->active) { + if (!d->active) { d->recvBuf += block; - if(d->inHeader) { + if (d->inHeader) { // grab available lines - while(1) { - bool found; + while (1) { + bool found; QString line = extractLine(&d->recvBuf, &found); - if(!found) + if (!found) break; - if(line.isEmpty()) { + if (line.isEmpty()) { d->inHeader = false; break; } @@ -260,30 +251,30 @@ void HttpConnect::sock_readyRead() } // done with grabbing the header? - if(!d->inHeader) { + if (!d->inHeader) { QString str = d->headerLines.first(); d->headerLines.takeFirst(); QString proto; - int code; + int code; QString msg; - if(!extractMainHeader(str, &proto, &code, &msg)) { + if (!extractMainHeader(str, &proto, &code, &msg)) { #ifdef PROX_DEBUG fprintf(stderr, "HttpConnect: invalid header!\n"); #endif resetConnection(true); setError(ErrProxyNeg); return; - } - else { + } else { #ifdef PROX_DEBUG - fprintf(stderr, "HttpConnect: header proto=[%s] code=[%d] msg=[%s]\n", qPrintable(proto), code, qPrintable(msg)); - for(QStringList::ConstIterator it = d->headerLines.begin(); it != d->headerLines.end(); ++it) + fprintf(stderr, "HttpConnect: header proto=[%s] code=[%d] msg=[%s]\n", qPrintable(proto), code, + qPrintable(msg)); + for (QStringList::ConstIterator it = d->headerLines.begin(); it != d->headerLines.end(); ++it) fprintf(stderr, "HttpConnect: * [%s]\n", qPrintable(*it)); #endif } - if(code == 200) { // OK + if (code == 200) { // OK #ifdef PROX_DEBUG fprintf(stderr, "HttpConnect: << Success >>\n"); #endif @@ -291,34 +282,29 @@ void HttpConnect::sock_readyRead() setOpenMode(QIODevice::ReadWrite); connected(); - if(!d->recvBuf.isEmpty()) { + if (!d->recvBuf.isEmpty()) { appendRead(d->recvBuf); d->recvBuf.resize(0); readyRead(); return; } - } - else { - int err; + } else { + int err; QString errStr; - if(code == 407) { // Authentication failed - err = ErrProxyAuth; + if (code == 407) { // Authentication failed + err = ErrProxyAuth; errStr = tr("Authentication failed"); - } - else if(code == 404) { // Host not found - err = ErrHostNotFound; + } else if (code == 404) { // Host not found + err = ErrHostNotFound; errStr = tr("Host not found"); - } - else if(code == 403) { // Access denied - err = ErrProxyNeg; + } else if (code == 403) { // Access denied + err = ErrProxyNeg; errStr = tr("Access denied"); - } - else if(code == 503) { // Connection refused - err = ErrConnectionRefused; + } else if (code == 503) { // Connection refused + err = ErrConnectionRefused; errStr = tr("Connection refused"); - } - else { // invalid reply - err = ErrProxyNeg; + } else { // invalid reply + err = ErrProxyNeg; errStr = tr("Invalid reply"); } @@ -331,8 +317,7 @@ void HttpConnect::sock_readyRead() } } } - } - else { + } else { appendRead(block); readyRead(); return; @@ -341,31 +326,30 @@ void HttpConnect::sock_readyRead() void HttpConnect::sock_bytesWritten(qint64 x) { - if(d->toWrite > 0) { + if (d->toWrite > 0) { int size = x; - if(d->toWrite < x) + if (d->toWrite < x) size = d->toWrite; d->toWrite -= size; x -= size; } - if(d->active && x > 0) + if (d->active && x > 0) bytesWritten(x); } void HttpConnect::sock_error(int x) { - if(d->active) { + if (d->active) { resetConnection(); setError(ErrRead); - } - else { + } else { resetConnection(true); - if(x == BSocket::ErrHostNotFound) + if (x == BSocket::ErrHostNotFound) setError(ErrProxyConnect); - else if(x == BSocket::ErrConnectionRefused) + else if (x == BSocket::ErrConnectionRefused) setError(ErrProxyConnect); - else if(x == BSocket::ErrRead) + else if (x == BSocket::ErrRead) setError(ErrProxyNeg); } } diff --git a/src/irisnet/noncore/cutestuff/httpconnect.h b/src/irisnet/noncore/cutestuff/httpconnect.h index 4039b61f..61ef8ed0 100644 --- a/src/irisnet/noncore/cutestuff/httpconnect.h +++ b/src/irisnet/noncore/cutestuff/httpconnect.h @@ -23,20 +23,20 @@ #include "bytestream.h" // CS_NAMESPACE_BEGIN -class HttpConnect : public ByteStream -{ +class HttpConnect : public ByteStream { Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpConnect(QObject *parent=nullptr); + HttpConnect(QObject *parent = nullptr); ~HttpConnect(); - void setAuth(const QString &user, const QString &pass=""); + void setAuth(const QString &user, const QString &pass = ""); void connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port); // from ByteStream - void close(); + void close(); qint64 bytesToWrite() const; + protected: qint64 writeData(const char *data, qint64 maxSize); @@ -55,7 +55,7 @@ private slots: class Private; Private *d; - void resetConnection(bool clear=false); + void resetConnection(bool clear = false); }; // CS_NAMESPACE_END diff --git a/src/irisnet/noncore/cutestuff/httppoll.cpp b/src/irisnet/noncore/cutestuff/httppoll.cpp index 572e6bfa..54db6d04 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.cpp +++ b/src/irisnet/noncore/cutestuff/httppoll.cpp @@ -28,7 +28,7 @@ #include #include #ifdef PROX_DEBUG -# include +#include #endif #include @@ -38,9 +38,9 @@ static QByteArray randomArray(int size) { QByteArray a; - a.resize(size); - for(int n = 0; n < size; ++n) - a[n] = (char)(256.0*rand()/(RAND_MAX+1.0)); + a.resize(size); + for (int n = 0; n < size; ++n) + a[n] = (char)(256.0 * rand() / (RAND_MAX + 1.0)); return a; } @@ -49,48 +49,43 @@ static QByteArray randomArray(int size) //---------------------------------------------------------------------------- static QString hpk(int n, const QString &s) { - if(n == 0) + if (n == 0) return s; else - return QCA::Base64().arrayToString( QCA::Hash("sha1").hash( hpk(n - 1, s).toLatin1() ).toByteArray() ); + return QCA::Base64().arrayToString(QCA::Hash("sha1").hash(hpk(n - 1, s).toLatin1()).toByteArray()); } -class HttpPoll::Private -{ +class HttpPoll::Private { public: - Private(HttpPoll *_q) : - http(_q) - { - } + Private(HttpPoll *_q) : http(_q) {} HttpProxyPost http; - QString host; - int port; - QString user, pass; - QUrl url; - bool use_proxy; + QString host; + int port; + QString user, pass; + QUrl url; + bool use_proxy; QByteArray out; - int state; - bool closing; + int state; + bool closing; QString ident; QTimer *t; QString key[POLL_KEYS]; - int key_n; + int key_n; int polltime; }; -HttpPoll::HttpPoll(QObject *parent) -:ByteStream(parent) +HttpPoll::HttpPoll(QObject *parent) : ByteStream(parent) { d = new Private(this); d->polltime = 30; - d->t = new QTimer(this); + d->t = new QTimer(this); d->t->setSingleShot(true); connect(d->t, SIGNAL(timeout()), SLOT(do_sync())); @@ -107,20 +102,17 @@ HttpPoll::~HttpPoll() delete d; } -QAbstractSocket* HttpPoll::abstractSocket() const -{ - return d->http.abstractSocket(); -} +QAbstractSocket *HttpPoll::abstractSocket() const { return d->http.abstractSocket(); } void HttpPoll::resetConnection(bool clear) { - if(d->http.isActive()) + if (d->http.isActive()) d->http.stop(); - if(clear) + if (clear) clearReadBuffer(); clearWriteBuffer(); d->out.resize(0); - d->state = 0; + d->state = 0; d->closing = false; d->t->stop(); } @@ -131,50 +123,46 @@ void HttpPoll::setAuth(const QString &user, const QString &pass) d->pass = pass; } -void HttpPoll::connectToUrl(const QUrl &url) -{ - connectToHost("", 0, url); -} +void HttpPoll::connectToUrl(const QUrl &url) { connectToHost("", 0, url); } void HttpPoll::connectToHost(const QString &proxyHost, int proxyPort, const QUrl &url) { resetConnection(true); bool useSsl = false; - d->port = 80; + d->port = 80; // using proxy? - if(!proxyHost.isEmpty()) { - d->host = proxyHost; - d->port = proxyPort; - d->url = url; + if (!proxyHost.isEmpty()) { + d->host = proxyHost; + d->port = proxyPort; + d->url = url; d->use_proxy = true; - } - else { + } else { d->host = url.host(); - if(url.port() != -1) + if (url.port() != -1) d->port = url.port(); else if (url.scheme() == "https") { d->port = 443; - useSsl = true; + useSsl = true; } d->url.setUrl(url.path() + "?" + url.query(QUrl::FullyEncoded), QUrl::StrictMode); d->use_proxy = false; } resetKey(); - bool last; + bool last; QString key = getKey(&last); #ifdef PROX_DEBUG fprintf(stderr, "HttpPoll: Connecting to %s:%d [%s]", d->host.latin1(), d->port, d->url.latin1()); - if(d->user.isEmpty()) + if (d->user.isEmpty()) fprintf(stderr, "\n"); else fprintf(stderr, ", auth {%s,%s}\n", d->user.latin1(), d->pass.latin1()); #endif QPointer self = this; syncStarted(); - if(!self) + if (!self) return; d->state = 1; @@ -183,49 +171,41 @@ void HttpPoll::connectToHost(const QString &proxyHost, int proxyPort, const QUrl d->http.post(d->host, d->port, d->url, makePacket("0", key, "", QByteArray()), d->use_proxy); } -QByteArray HttpPoll::makePacket(const QString &ident, const QString &key, const QString &newkey, const QByteArray &block) +QByteArray HttpPoll::makePacket(const QString &ident, const QString &key, const QString &newkey, + const QByteArray &block) { QString str = ident; - if(!key.isEmpty()) { + if (!key.isEmpty()) { str += ';'; str += key; } - if(!newkey.isEmpty()) { + if (!newkey.isEmpty()) { str += ';'; str += newkey; } str += ','; - QByteArray cs = str.toLatin1(); - int len = cs.length(); + QByteArray cs = str.toLatin1(); + int len = cs.length(); QByteArray a; - a.resize(len + block.size()); + a.resize(len + block.size()); memcpy(a.data(), cs.data(), len); memcpy(a.data() + len, block.data(), block.size()); return a; } -int HttpPoll::pollInterval() const -{ - return d->polltime; -} +int HttpPoll::pollInterval() const { return d->polltime; } -void HttpPoll::setPollInterval(int seconds) -{ - d->polltime = seconds; -} +void HttpPoll::setPollInterval(int seconds) { d->polltime = seconds; } -bool HttpPoll::isOpen() const -{ - return (d->state == 2 ? true: false); -} +bool HttpPoll::isOpen() const { return (d->state == 2 ? true : false); } void HttpPoll::close() { - if(d->state == 0 || d->closing) + if (d->state == 0 || d->closing) return; - if(bytesToWrite() == 0) + if (bytesToWrite() == 0) resetConnection(); else d->closing = true; @@ -236,58 +216,56 @@ void HttpPoll::http_result() // check for death :) QPointer self = this; syncFinished(); - if(!self) + if (!self) return; // get id and packet QString id; QString cookie = d->http.getHeader("Set-Cookie"); - int n = cookie.indexOf("ID="); - if(n == -1) { + int n = cookie.indexOf("ID="); + if (n == -1) { resetConnection(); setError(ErrRead); return; } n += 3; int n2 = cookie.indexOf(';', n); - if(n2 != -1) - id = cookie.mid(n, n2-n); + if (n2 != -1) + id = cookie.mid(n, n2 - n); else id = cookie.mid(n); QByteArray block = d->http.body(); // session error? - if(id.right(2) == ":0") { - if(id == "0:0" && d->state == 2) { + if (id.right(2) == ":0") { + if (id == "0:0" && d->state == 2) { resetConnection(); connectionClosed(); return; - } - else { + } else { resetConnection(); setError(ErrRead); return; } } - d->ident = id; + d->ident = id; bool justNowConnected = false; - if(d->state == 1) { - d->state = 2; + if (d->state == 1) { + d->state = 2; justNowConnected = true; } // sync up again soon - if(bytesToWrite() > 0 || !d->closing) { + if (bytesToWrite() > 0 || !d->closing) { d->t->start(d->polltime * 1000); - } + } // connecting - if(justNowConnected) { + if (justNowConnected) { connected(); - } - else { - if(!d->out.isEmpty()) { + } else { + if (!d->out.isEmpty()) { int x = d->out.size(); d->out.resize(0); takeWrite(x); @@ -295,22 +273,21 @@ void HttpPoll::http_result() } } - if(!self) + if (!self) return; - if(!block.isEmpty()) { + if (!block.isEmpty()) { appendRead(block); readyRead(); } - if(!self) + if (!self) return; - if(bytesToWrite() > 0) { + if (bytesToWrite() > 0) { do_sync(); - } - else { - if(d->closing) { + } else { + if (d->closing) { resetConnection(); delayedCloseFinished(); return; @@ -321,46 +298,46 @@ void HttpPoll::http_result() void HttpPoll::http_error(int x) { resetConnection(); - if(x == HttpProxyPost::ErrConnectionRefused) + if (x == HttpProxyPost::ErrConnectionRefused) setError(ErrConnectionRefused); - else if(x == HttpProxyPost::ErrHostNotFound) + else if (x == HttpProxyPost::ErrHostNotFound) setError(ErrHostNotFound); - else if(x == HttpProxyPost::ErrSocket) + else if (x == HttpProxyPost::ErrSocket) setError(ErrRead); - else if(x == HttpProxyPost::ErrProxyConnect) + else if (x == HttpProxyPost::ErrProxyConnect) setError(ErrProxyConnect); - else if(x == HttpProxyPost::ErrProxyNeg) + else if (x == HttpProxyPost::ErrProxyNeg) setError(ErrProxyNeg); - else if(x == HttpProxyPost::ErrProxyAuth) + else if (x == HttpProxyPost::ErrProxyAuth) setError(ErrProxyAuth); } int HttpPoll::tryWrite() { - if(!d->http.isActive()) + if (!d->http.isActive()) do_sync(); return 0; } void HttpPoll::do_sync() { - if(d->http.isActive()) + if (d->http.isActive()) return; d->t->stop(); d->out = takeWrite(0, false); - bool last; + bool last; QString key = getKey(&last); QString newkey; - if(last) { + if (last) { resetKey(); newkey = getKey(&last); } QPointer self = this; syncStarted(); - if(!self) + if (!self) return; d->http.post(d->host, d->port, d->url, makePacket(d->ident, key, newkey, d->out), d->use_proxy); @@ -371,19 +348,19 @@ void HttpPoll::resetKey() #ifdef PROX_DEBUG fprintf(stderr, "HttpPoll: reset key!\n"); #endif - QByteArray a = randomArray(64); - QString str = QString::fromLatin1(a.data(), a.size()); + QByteArray a = randomArray(64); + QString str = QString::fromLatin1(a.data(), a.size()); d->key_n = POLL_KEYS; - for(int n = 0; n < POLL_KEYS; ++n) - d->key[n] = hpk(n+1, str); + for (int n = 0; n < POLL_KEYS; ++n) + d->key[n] = hpk(n + 1, str); } -const QString & HttpPoll::getKey(bool *last) +const QString &HttpPoll::getKey(bool *last) { *last = false; --(d->key_n); - if(d->key_n == 0) + if (d->key_n == 0) *last = true; return d->key[d->key_n]; } @@ -395,8 +372,8 @@ static QString extractLine(QByteArray *buf, bool *found) { // scan for newline int n; - for(n = 0; n < (int)buf->size()-1; ++n) { - if(buf->at(n) == '\r' && buf->at(n+1) == '\n') { + for (n = 0; n < (int)buf->size() - 1; ++n) { + if (buf->at(n) == '\r' && buf->at(n + 1) == '\n') { QByteArray cstr; cstr.resize(n); memcpy(cstr.data(), buf->data(), n); @@ -406,13 +383,13 @@ static QString extractLine(QByteArray *buf, bool *found) buf->resize(buf->size() - n); QString s = QString::fromUtf8(cstr); - if(found) + if (found) *found = true; return s; } } - if(found) + if (found) *found = false; return ""; } @@ -420,51 +397,42 @@ static QString extractLine(QByteArray *buf, bool *found) static bool extractMainHeader(const QString &line, QString *proto, int *code, QString *msg) { int n = line.indexOf(' '); - if(n == -1) + if (n == -1) return false; - if(proto) + if (proto) *proto = line.mid(0, n); ++n; int n2 = line.indexOf(' ', n); - if(n2 == -1) + if (n2 == -1) return false; - if(code) - *code = line.mid(n, n2-n).toInt(); - n = n2+1; - if(msg) + if (code) + *code = line.mid(n, n2 - n).toInt(); + n = n2 + 1; + if (msg) *msg = line.mid(n); return true; } -class HttpProxyPost::Private -{ +class HttpProxyPost::Private { public: - Private(HttpProxyPost *_q) : - sock(_q), - tls(nullptr) - { - } + Private(HttpProxyPost *_q) : sock(_q), tls(nullptr) {} - ~Private() - { - delete tls; - } + ~Private() { delete tls; } - BSocket sock; + BSocket sock; QHostAddress lastAddress; - QByteArray postdata, recvBuf, body; - QUrl url; - QString user, pass; - bool inHeader; - QStringList headerLines; - bool asProxy; - bool useSsl; - QString host; - QCA::TLS *tls; + QByteArray postdata, recvBuf, body; + QUrl url; + QString user, pass; + bool inHeader; + QStringList headerLines; + bool asProxy; + bool useSsl; + QString host; + QCA::TLS * tls; }; -HttpProxyPost::HttpProxyPost(QObject *parent) -:QObject(parent) +HttpProxyPost::HttpProxyPost(QObject *parent) : QObject(parent) { d = new Private(this); connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected())); @@ -480,22 +448,16 @@ HttpProxyPost::~HttpProxyPost() delete d; } -void HttpProxyPost::setUseSsl(bool state) -{ - d->useSsl = state; -} +void HttpProxyPost::setUseSsl(bool state) { d->useSsl = state; } -QAbstractSocket* HttpProxyPost::abstractSocket() const -{ - return d->sock.abstractSocket(); -} +QAbstractSocket *HttpProxyPost::abstractSocket() const { return d->sock.abstractSocket(); } void HttpProxyPost::resetConnection(bool clear) { - if(d->sock.state() != BSocket::Idle) + if (d->sock.state() != BSocket::Idle) d->sock.close(); d->recvBuf.resize(0); - if(clear) + if (clear) d->body.resize(0); } @@ -505,23 +467,20 @@ void HttpProxyPost::setAuth(const QString &user, const QString &pass) d->pass = pass; } -bool HttpProxyPost::isActive() const -{ - return (d->sock.state() == BSocket::Idle ? false: true); -} +bool HttpProxyPost::isActive() const { return (d->sock.state() == BSocket::Idle ? false : true); } void HttpProxyPost::post(const QString &proxyHost, int proxyPort, const QUrl &url, const QByteArray &data, bool asProxy) { resetConnection(true); - d->host = proxyHost; - d->url = url; + d->host = proxyHost; + d->url = url; d->postdata = data; - d->asProxy = asProxy; + d->asProxy = asProxy; #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyPost: Connecting to %s:%d", proxyHost.latin1(), proxyPort); - if(d->user.isEmpty()) + if (d->user.isEmpty()) fprintf(stderr, "\n"); else fprintf(stderr, ", auth {%s,%s}\n", d->user.latin1(), d->pass.latin1()); @@ -535,25 +494,19 @@ void HttpProxyPost::post(const QString &proxyHost, int proxyPort, const QUrl &ur } } -void HttpProxyPost::stop() -{ - resetConnection(); -} +void HttpProxyPost::stop() { resetConnection(); } -QByteArray HttpProxyPost::body() const -{ - return d->body; -} +QByteArray HttpProxyPost::body() const { return d->body; } QString HttpProxyPost::getHeader(const QString &var) const { foreach (const QString &s, d->headerLines) { int n = s.indexOf(": "); - if(n == -1) + if (n == -1) continue; QString v = s.mid(0, n); - if(v.toLower() == var.toLower()) - return s.mid(n+2); + if (v.toLower() == var.toLower()) + return s.mid(n + 2); } return ""; } @@ -563,7 +516,7 @@ void HttpProxyPost::sock_connected() #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyPost: Connected\n"); #endif - if(d->useSsl) { + if (d->useSsl) { d->tls = new QCA::TLS(this); connect(d->tls, SIGNAL(readyRead()), SLOT(tls_readyRead())); connect(d->tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing())); @@ -572,7 +525,7 @@ void HttpProxyPost::sock_connected() } d->lastAddress = d->sock.peerAddress(); - d->inHeader = true; + d->inHeader = true; d->headerLines.clear(); QUrl u = d->url; @@ -580,22 +533,21 @@ void HttpProxyPost::sock_connected() // connected, now send the request QByteArray s; s += QByteArray("POST ") + d->url.toEncoded() + " HTTP/1.1\r\n"; - if(d->asProxy) { - if(!d->user.isEmpty()) { + if (d->asProxy) { + if (!d->user.isEmpty()) { QByteArray str = d->user.toUtf8() + ':' + d->pass.toUtf8(); s += QByteArray("Proxy-Authorization: Basic ") + str.toBase64() + "\r\n"; } s += "Pragma: no-cache\r\n"; s += QByteArray("Host: ") + u.host().toUtf8() + "\r\n"; - } - else { + } else { s += QByteArray("Host: ") + d->host.toUtf8() + "\r\n"; } s += "Content-Type: application/x-www-form-urlencoded\r\n"; s += QByteArray("Content-Length: ") + QByteArray::number(d->postdata.size()) + "\r\n"; s += "\r\n"; - if(d->useSsl) { + if (d->useSsl) { // write request d->tls->write(s); @@ -619,13 +571,13 @@ void HttpProxyPost::sock_connectionClosed() void HttpProxyPost::tls_readyRead() { - //printf("tls_readyRead\n"); + // printf("tls_readyRead\n"); processData(d->tls->read()); } void HttpProxyPost::tls_readyReadOutgoing() { - //printf("tls_readyReadOutgoing\n"); + // printf("tls_readyReadOutgoing\n"); d->sock.write(d->tls->readOutgoing()); } @@ -641,7 +593,7 @@ void HttpProxyPost::tls_error() void HttpProxyPost::sock_readyRead() { QByteArray block = d->sock.readAll(); - if(d->useSsl) + if (d->useSsl) d->tls->writeIncoming(block); else processData(block); @@ -651,14 +603,14 @@ void HttpProxyPost::processData(const QByteArray &block) { d->recvBuf += block; - if(d->inHeader) { + if (d->inHeader) { // grab available lines - while(1) { - bool found; + while (1) { + bool found; QString line = extractLine(&d->recvBuf, &found); - if(!found) + if (!found) break; - if(line.isEmpty()) { + if (line.isEmpty()) { d->inHeader = false; break; } @@ -666,55 +618,50 @@ void HttpProxyPost::processData(const QByteArray &block) } // done with grabbing the header? - if(!d->inHeader) { + if (!d->inHeader) { QString str = d->headerLines.first(); d->headerLines.takeFirst(); QString proto; - int code; + int code; QString msg; - if(!extractMainHeader(str, &proto, &code, &msg)) { + if (!extractMainHeader(str, &proto, &code, &msg)) { #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyPost: invalid header!\n"); #endif resetConnection(true); error(ErrProxyNeg); return; - } - else { + } else { #ifdef PROX_DEBUG - fprintf(stderr, "HttpProxyPost: header proto=[%s] code=[%d] msg=[%s]\n", proto.latin1(), code, msg.latin1()); + fprintf(stderr, "HttpProxyPost: header proto=[%s] code=[%d] msg=[%s]\n", proto.latin1(), code, + msg.latin1()); foreach (const QString &s, d->headerLines) fprintf(stderr, "HttpProxyPost: * [%s]\n", qPrintable(s)); #endif } - if(code == 200) { // OK + if (code == 200) { // OK #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyPost: << Success >>\n"); #endif - } - else { - int err; + } else { + int err; QString errStr; - if(code == 407) { // Authentication failed - err = ErrProxyAuth; + if (code == 407) { // Authentication failed + err = ErrProxyAuth; errStr = tr("Authentication failed"); - } - else if(code == 404) { // Host not found - err = ErrHostNotFound; + } else if (code == 404) { // Host not found + err = ErrHostNotFound; errStr = tr("Host not found"); - } - else if(code == 403) { // Access denied - err = ErrProxyNeg; + } else if (code == 403) { // Access denied + err = ErrProxyNeg; errStr = tr("Access denied"); - } - else if(code == 503) { // Connection refused - err = ErrConnectionRefused; + } else if (code == 503) { // Connection refused + err = ErrConnectionRefused; errStr = tr("Connection refused"); - } - else { // invalid reply - err = ErrProxyNeg; + } else { // invalid reply + err = ErrProxyNeg; errStr = tr("Invalid reply"); } @@ -735,43 +682,38 @@ void HttpProxyPost::sock_error(int x) fprintf(stderr, "HttpProxyPost: socket error: %d\n", x); #endif resetConnection(true); - if(x == BSocket::ErrHostNotFound) + if (x == BSocket::ErrHostNotFound) error(ErrProxyConnect); - else if(x == BSocket::ErrConnectionRefused) + else if (x == BSocket::ErrConnectionRefused) error(ErrProxyConnect); - else if(x == BSocket::ErrRead) + else if (x == BSocket::ErrRead) error(ErrProxyNeg); } //---------------------------------------------------------------------------- // HttpProxyGetStream //---------------------------------------------------------------------------- -class HttpProxyGetStream::Private -{ +class HttpProxyGetStream::Private { public: - Private(HttpProxyGetStream *_q) : - sock(_q) - { - } + Private(HttpProxyGetStream *_q) : sock(_q) {} - BSocket sock; - QByteArray recvBuf; - QString url; - QString user, pass; - bool inHeader; + BSocket sock; + QByteArray recvBuf; + QString url; + QString user, pass; + bool inHeader; QStringList headerLines; - bool use_ssl; - bool asProxy; - QString host; - int length; + bool use_ssl; + bool asProxy; + QString host; + int length; QCA::TLS *tls; }; -HttpProxyGetStream::HttpProxyGetStream(QObject *parent) -:QObject(parent) +HttpProxyGetStream::HttpProxyGetStream(QObject *parent) : QObject(parent) { - d = new Private(this); + d = new Private(this); d->tls = nullptr; connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected())); connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed())); @@ -788,14 +730,14 @@ HttpProxyGetStream::~HttpProxyGetStream() void HttpProxyGetStream::resetConnection(bool /*clear*/) { - if(d->tls) { + if (d->tls) { delete d->tls; d->tls = nullptr; } - if(d->sock.state() != BSocket::Idle) + if (d->sock.state() != BSocket::Idle) d->sock.close(); d->recvBuf.resize(0); - //if(clear) + // if(clear) // d->body.resize(0); d->length = -1; } @@ -806,23 +748,20 @@ void HttpProxyGetStream::setAuth(const QString &user, const QString &pass) d->pass = pass; } -bool HttpProxyGetStream::isActive() const -{ - return (d->sock.state() == BSocket::Idle ? false: true); -} +bool HttpProxyGetStream::isActive() const { return (d->sock.state() == BSocket::Idle ? false : true); } void HttpProxyGetStream::get(const QString &proxyHost, int proxyPort, const QString &url, bool ssl, bool asProxy) { resetConnection(true); - d->host = proxyHost; - d->url = url; + d->host = proxyHost; + d->url = url; d->use_ssl = ssl; d->asProxy = asProxy; #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyGetStream: Connecting to %s:%d", proxyHost.latin1(), proxyPort); - if(d->user.isEmpty()) + if (d->user.isEmpty()) fprintf(stderr, "\n"); else fprintf(stderr, ", auth {%s,%s}\n", d->user.latin1(), d->pass.latin1()); @@ -830,35 +769,29 @@ void HttpProxyGetStream::get(const QString &proxyHost, int proxyPort, const QStr d->sock.connectToHost(proxyHost, proxyPort); } -void HttpProxyGetStream::stop() -{ - resetConnection(); -} +void HttpProxyGetStream::stop() { resetConnection(); } QString HttpProxyGetStream::getHeader(const QString &var) const { foreach (const QString &s, d->headerLines) { int n = s.indexOf(": "); - if(n == -1) + if (n == -1) continue; QString v = s.mid(0, n); - if(v.toLower() == var.toLower()) - return s.mid(n+2); + if (v.toLower() == var.toLower()) + return s.mid(n + 2); } return ""; } -int HttpProxyGetStream::length() const -{ - return d->length; -} +int HttpProxyGetStream::length() const { return d->length; } void HttpProxyGetStream::sock_connected() { #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyGetStream: Connected\n"); #endif - if(d->use_ssl) { + if (d->use_ssl) { d->tls = new QCA::TLS(this); connect(d->tls, SIGNAL(readyRead()), SLOT(tls_readyRead())); connect(d->tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing())); @@ -874,21 +807,20 @@ void HttpProxyGetStream::sock_connected() // connected, now send the request QString s; s += QString("GET ") + d->url + " HTTP/1.0\r\n"; - if(d->asProxy) { - if(!d->user.isEmpty()) { + if (d->asProxy) { + if (!d->user.isEmpty()) { QString str = d->user + ':' + d->pass; s += QString("Proxy-Authorization: Basic ") + QCA::Base64().encodeString(str) + "\r\n"; } s += "Pragma: no-cache\r\n"; s += QString("Host: ") + u.host() + "\r\n"; - } - else { + } else { s += QString("Host: ") + d->host + "\r\n"; } s += "\r\n"; // write request - if(d->use_ssl) + if (d->use_ssl) d->tls->write(s.toUtf8()); else d->sock.write(s.toUtf8()); @@ -896,7 +828,7 @@ void HttpProxyGetStream::sock_connected() void HttpProxyGetStream::sock_connectionClosed() { - //d->body = d->recvBuf; + // d->body = d->recvBuf; resetConnection(); emit finished(); } @@ -905,7 +837,7 @@ void HttpProxyGetStream::sock_readyRead() { QByteArray block = d->sock.readAll(); - if(d->use_ssl) + if (d->use_ssl) d->tls->writeIncoming(block); else processData(block); @@ -914,21 +846,21 @@ void HttpProxyGetStream::sock_readyRead() void HttpProxyGetStream::processData(const QByteArray &block) { printf("processData: %d bytes\n", block.size()); - if(!d->inHeader) { + if (!d->inHeader) { emit dataReady(block); return; } d->recvBuf += block; - if(d->inHeader) { + if (d->inHeader) { // grab available lines - while(1) { - bool found; + while (1) { + bool found; QString line = extractLine(&d->recvBuf, &found); - if(!found) + if (!found) break; - if(line.isEmpty()) { + if (line.isEmpty()) { printf("empty line\n"); d->inHeader = false; break; @@ -938,65 +870,60 @@ void HttpProxyGetStream::processData(const QByteArray &block) } // done with grabbing the header? - if(!d->inHeader) { + if (!d->inHeader) { QString str = d->headerLines.first(); d->headerLines.takeFirst(); QString proto; - int code; + int code; QString msg; - if(!extractMainHeader(str, &proto, &code, &msg)) { + if (!extractMainHeader(str, &proto, &code, &msg)) { #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyGetStream: invalid header!\n"); #endif resetConnection(true); error(ErrProxyNeg); return; - } - else { + } else { #ifdef PROX_DEBUG - fprintf(stderr, "HttpProxyGetStream: header proto=[%s] code=[%d] msg=[%s]\n", proto.latin1(), code, msg.latin1()); + fprintf(stderr, "HttpProxyGetStream: header proto=[%s] code=[%d] msg=[%s]\n", proto.latin1(), code, + msg.latin1()); foreach (const QString &s, d->headerLines) fprintf(stderr, "HttpProxyGetStream: * [%s]\n", qPrintable(s)); #endif } - if(code == 200) { // OK + if (code == 200) { // OK #ifdef PROX_DEBUG fprintf(stderr, "HttpProxyGetStream: << Success >>\n"); #endif bool ok; - int x = getHeader("Content-Length").toInt(&ok); - if(ok) + int x = getHeader("Content-Length").toInt(&ok); + if (ok) d->length = x; QPointer self = this; - emit handshaken(); - if(!self) + emit handshaken(); + if (!self) return; - } - else { - int err; + } else { + int err; QString errStr; - if(code == 407) { // Authentication failed - err = ErrProxyAuth; + if (code == 407) { // Authentication failed + err = ErrProxyAuth; errStr = tr("Authentication failed"); - } - else if(code == 404) { // Host not found - err = ErrHostNotFound; + } else if (code == 404) { // Host not found + err = ErrHostNotFound; errStr = tr("Host not found"); - } - else if(code == 403) { // Access denied - err = ErrProxyNeg; + } else if (code == 403) { // Access denied + err = ErrProxyNeg; errStr = tr("Access denied"); - } - else if(code == 503) { // Connection refused - err = ErrConnectionRefused; + } else if (code == 503) { // Connection refused + err = ErrConnectionRefused; errStr = tr("Connection refused"); - } - else { // invalid reply - err = ErrProxyNeg; + } else { // invalid reply + err = ErrProxyNeg; errStr = tr("Invalid reply"); } @@ -1008,7 +935,7 @@ void HttpProxyGetStream::processData(const QByteArray &block) return; } - if(!d->recvBuf.isEmpty()) { + if (!d->recvBuf.isEmpty()) { QByteArray a = d->recvBuf; d->recvBuf.clear(); emit dataReady(a); @@ -1023,23 +950,23 @@ void HttpProxyGetStream::sock_error(int x) fprintf(stderr, "HttpProxyGetStream: socket error: %d\n", x); #endif resetConnection(true); - if(x == BSocket::ErrHostNotFound) + if (x == BSocket::ErrHostNotFound) error(ErrProxyConnect); - else if(x == BSocket::ErrConnectionRefused) + else if (x == BSocket::ErrConnectionRefused) error(ErrProxyConnect); - else if(x == BSocket::ErrRead) + else if (x == BSocket::ErrRead) error(ErrProxyNeg); } void HttpProxyGetStream::tls_readyRead() { - //printf("tls_readyRead\n"); + // printf("tls_readyRead\n"); processData(d->tls->read()); } void HttpProxyGetStream::tls_readyReadOutgoing() { - //printf("tls_readyReadOutgoing\n"); + // printf("tls_readyReadOutgoing\n"); d->sock.write(d->tls->readOutgoing()); } diff --git a/src/irisnet/noncore/cutestuff/httppoll.h b/src/irisnet/noncore/cutestuff/httppoll.h index db10005c..36ba95fc 100644 --- a/src/irisnet/noncore/cutestuff/httppoll.h +++ b/src/irisnet/noncore/cutestuff/httppoll.h @@ -25,21 +25,20 @@ class QUrl; // CS_NAMESPACE_BEGIN -class HttpPoll : public ByteStream -{ +class HttpPoll : public ByteStream { Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpPoll(QObject *parent=nullptr); + HttpPoll(QObject *parent = nullptr); ~HttpPoll(); - virtual QAbstractSocket* abstractSocket() const; + virtual QAbstractSocket *abstractSocket() const; - void setAuth(const QString &user, const QString &pass=""); + void setAuth(const QString &user, const QString &pass = ""); void connectToUrl(const QUrl &url); void connectToHost(const QString &proxyHost, int proxyPort, const QUrl &url); - int pollInterval() const; + int pollInterval() const; void setPollInterval(int seconds); // from ByteStream @@ -63,29 +62,28 @@ private slots: class Private; Private *d; - void resetConnection(bool clear=false); - QByteArray makePacket(const QString &ident, const QString &key, const QString &newkey, const QByteArray &block); - void resetKey(); - const QString & getKey(bool *); + void resetConnection(bool clear = false); + QByteArray makePacket(const QString &ident, const QString &key, const QString &newkey, const QByteArray &block); + void resetKey(); + const QString &getKey(bool *); }; -class HttpProxyPost : public QObject -{ +class HttpProxyPost : public QObject { Q_OBJECT public: enum Error { ErrConnectionRefused, ErrHostNotFound, ErrSocket, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpProxyPost(QObject *parent=nullptr); + HttpProxyPost(QObject *parent = nullptr); ~HttpProxyPost(); - QAbstractSocket* abstractSocket() const; + QAbstractSocket *abstractSocket() const; void setUseSsl(bool state); - void setAuth(const QString &user, const QString &pass=""); + void setAuth(const QString &user, const QString &pass = ""); bool isActive() const; - void post(const QString &proxyHost, int proxyPort, const QUrl &url, const QByteArray &data, bool asProxy=true); + void post(const QString &proxyHost, int proxyPort, const QUrl &url, const QByteArray &data, bool asProxy = true); void stop(); QByteArray body() const; - QString getHeader(const QString &) const; + QString getHeader(const QString &) const; signals: void result(); @@ -104,24 +102,23 @@ private slots: class Private; Private *d; - void resetConnection(bool clear=false); + void resetConnection(bool clear = false); void processData(const QByteArray &block); }; -class HttpProxyGetStream : public QObject -{ +class HttpProxyGetStream : public QObject { Q_OBJECT public: enum Error { ErrConnectionRefused, ErrHostNotFound, ErrSocket, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - HttpProxyGetStream(QObject *parent=nullptr); + HttpProxyGetStream(QObject *parent = nullptr); ~HttpProxyGetStream(); - void setAuth(const QString &user, const QString &pass=""); - bool isActive() const; - void get(const QString &proxyHost, int proxyPort, const QString &url, bool ssl=false, bool asProxy=false); - void stop(); + void setAuth(const QString &user, const QString &pass = ""); + bool isActive() const; + void get(const QString &proxyHost, int proxyPort, const QString &url, bool ssl = false, bool asProxy = false); + void stop(); QString getHeader(const QString &) const; - int length() const; // -1 for unknown + int length() const; // -1 for unknown signals: void handshaken(); @@ -143,7 +140,7 @@ private slots: class Private; Private *d; - void resetConnection(bool clear=false); + void resetConnection(bool clear = false); void processData(const QByteArray &block); }; diff --git a/src/irisnet/noncore/cutestuff/socks.cpp b/src/irisnet/noncore/cutestuff/socks.cpp index 41ad6b33..0f754e41 100644 --- a/src/irisnet/noncore/cutestuff/socks.cpp +++ b/src/irisnet/noncore/cutestuff/socks.cpp @@ -50,26 +50,25 @@ // SocksUDP //---------------------------------------------------------------------------- -class SocksUDP::Private -{ +class SocksUDP::Private { public: - QUdpSocket *sd; + QUdpSocket * sd; SocksClient *sc; QHostAddress routeAddr; - int routePort; - QString host; - int port; + int routePort; + QString host; + int port; }; -SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort) -:QObject(sc) +SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort) : + QObject(sc) { - d = new Private; + d = new Private; d->sc = sc; d->sd = new QUdpSocket(this); connect(d->sd, SIGNAL(readyRead()), SLOT(sd_readyRead())); - d->host = host; - d->port = port; + d->host = host; + d->port = port; d->routeAddr = routeAddr; d->routePort = routePort; } @@ -86,10 +85,7 @@ void SocksUDP::change(const QString &host, int port) d->port = port; } -void SocksUDP::write(const QByteArray &data) -{ - d->sd->writeDatagram(data, d->routeAddr, d->routePort); -} +void SocksUDP::write(const QByteArray &data) { d->sd->writeDatagram(data, d->routeAddr, d->routePort); } void SocksUDP::sd_activated() { @@ -104,13 +100,13 @@ void SocksUDP::sd_activated() //---------------------------------------------------------------------------- // SocksClient //---------------------------------------------------------------------------- -#define REQ_CONNECT 0x01 -#define REQ_BIND 0x02 +#define REQ_CONNECT 0x01 +#define REQ_BIND 0x02 #define REQ_UDPASSOCIATE 0x03 -#define RET_SUCCESS 0x00 -#define RET_UNREACHABLE 0x04 -#define RET_CONNREFUSED 0x05 +#define RET_SUCCESS 0x00 +#define RET_UNREACHABLE 0x04 +#define RET_CONNREFUSED 0x05 // spc = socks packet client // sps = socks packet server @@ -121,7 +117,7 @@ void SocksUDP::sd_activated() static QByteArray spc_set_version(bool hasCreds) { QByteArray ver; - ver.resize(hasCreds? 4 : 3); + ver.resize(hasCreds ? 4 : 3); ver[0] = 0x05; // socks version 5 ver[2] = 0x00; // no-auth if (hasCreds) { @@ -142,46 +138,44 @@ static QByteArray sps_set_version(int method) return ver; } -struct SPCS_VERSION -{ +struct SPCS_VERSION { unsigned char version; - QByteArray methodList; + QByteArray methodList; }; static int spc_get_version(QByteArray &from, SPCS_VERSION *s) { - if(from.size() < 1) + if (from.size() < 1) return 0; - if(from.at(0) != 0x05) // only SOCKS5 supported + if (from.at(0) != 0x05) // only SOCKS5 supported return -1; - if(from.size() < 2) + if (from.size() < 2) return 0; unsigned char mlen = from.at(1); - int num = mlen; - if(num > 16) // who the heck has over 16 auth methods?? + int num = mlen; + if (num > 16) // who the heck has over 16 auth methods?? return -1; - if(from.size() < 2 + num) + if (from.size() < 2 + num) return 0; - QByteArray a = ByteStream::takeArray(from, 2+num); - s->version = a[0]; + QByteArray a = ByteStream::takeArray(from, 2 + num); + s->version = a[0]; s->methodList.resize(num); memcpy(s->methodList.data(), a.data() + 2, num); return 1; } -struct SPSS_VERSION -{ +struct SPSS_VERSION { unsigned char version; unsigned char method; }; static int sps_get_version(QByteArray &from, SPSS_VERSION *s) { - if(from.size() < 2) + if (from.size() < 2) return 0; QByteArray a = ByteStream::takeArray(from, 2); - s->version = a[0]; - s->method = a[1]; + s->version = a[0]; + s->method = a[1]; return 1; } @@ -190,16 +184,16 @@ static QByteArray spc_set_authUsername(const QByteArray &user, const QByteArray { int len1 = user.length(); int len2 = pass.length(); - if(len1 > 255) + if (len1 > 255) len1 = 255; - if(len2 > 255) + if (len2 > 255) len2 = 255; QByteArray a; - a.resize(1+1+len1+1+len2); + a.resize(1 + 1 + len1 + 1 + len2); a[0] = 0x01; // username auth version 1 a[1] = len1; memcpy(a.data() + 2, user.data(), len1); - a[2+len1] = len2; + a[2 + len1] = len2; memcpy(a.data() + 3 + len1, pass.data(), len2); return a; } @@ -213,80 +207,78 @@ static QByteArray sps_set_authUsername(bool success) return a; } -struct SPCS_AUTHUSERNAME -{ +struct SPCS_AUTHUSERNAME { QString user, pass; }; static int spc_get_authUsername(QByteArray &from, SPCS_AUTHUSERNAME *s) { - if(from.size() < 1) + if (from.size() < 1) return 0; unsigned char ver = from.at(0); - if(ver != 0x01) + if (ver != 0x01) return -1; - if(from.size() < 2) + if (from.size() < 2) return 0; unsigned char ulen = from.at(1); - if((int)from.size() < ulen + 3) + if ((int)from.size() < ulen + 3) return 0; - unsigned char plen = from.at(ulen+2); - if((int)from.size() < ulen + plen + 3) + unsigned char plen = from.at(ulen + 2); + if ((int)from.size() < ulen + plen + 3) return 0; QByteArray a = ByteStream::takeArray(from, ulen + plen + 3); QByteArray user, pass; user.resize(ulen); pass.resize(plen); - memcpy(user.data(), a.data()+2, ulen); - memcpy(pass.data(), a.data()+ulen+3, plen); + memcpy(user.data(), a.data() + 2, ulen); + memcpy(pass.data(), a.data() + ulen + 3, plen); s->user = QString::fromUtf8(user); s->pass = QString::fromUtf8(pass); return 1; } -struct SPSS_AUTHUSERNAME -{ +struct SPSS_AUTHUSERNAME { unsigned char version; - bool success; + bool success; }; static int sps_get_authUsername(QByteArray &from, SPSS_AUTHUSERNAME *s) { - if(from.size() < 2) + if (from.size() < 2) return 0; QByteArray a = ByteStream::takeArray(from, 2); - s->version = a[0]; - s->success = ((char) a[1] == 0 ? true: false); + s->version = a[0]; + s->success = ((char)a[1] == 0 ? true : false); return 1; } // connectRequest static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1) { - int at = 0; + int at = 0; QByteArray a; a.resize(4); a[at++] = 0x05; // socks version 5 a[at++] = cmd1; a[at++] = 0x00; // reserved - if(addr.protocol() == QAbstractSocket::IPv4Protocol || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { - a[at++] = 0x01; // address type = ipv4 + if (addr.protocol() == QAbstractSocket::IPv4Protocol + || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) { + a[at++] = 0x01; // address type = ipv4 quint32 ip4 = htonl(addr.toIPv4Address()); - a.resize(at+4); + a.resize(at + 4); memcpy(a.data() + at, &ip4, 4); at += 4; - } - else { - a[at++] = 0x04; + } else { + a[at++] = 0x04; Q_IPV6ADDR ip6 = addr.toIPv6Address(); - a.resize(at+16); - for(int i = 0; i < 16; ++i) + a.resize(at + 16); + for (int i = 0; i < 16; ++i) a[at++] = ip6[i]; } // port - a.resize(at+2); + a.resize(at + 2); quint16 p = htons(port); memcpy(a.data() + at, &p, 2); @@ -297,15 +289,15 @@ static QByteArray sp_set_request(const QString &host, quint16 port, unsigned cha { // detect for IP addresses QHostAddress addr; - if(addr.setAddress(host)) + if (addr.setAddress(host)) return sp_set_request(addr, port, cmd1); QByteArray h = host.toUtf8(); h.truncate(255); - h = QString::fromUtf8(h).toUtf8(); // delete any partial characters? + h = QString::fromUtf8(h).toUtf8(); // delete any partial characters? int hlen = h.length(); - int at = 0; + int at = 0; QByteArray a; a.resize(4); a[at++] = 0x05; // socks version 5 @@ -314,63 +306,60 @@ static QByteArray sp_set_request(const QString &host, quint16 port, unsigned cha a[at++] = 0x03; // address type = domain // host - a.resize(at+hlen+1); + a.resize(at + hlen + 1); a[at++] = hlen; memcpy(a.data() + at, h.data(), hlen); at += hlen; // port - a.resize(at+2); + a.resize(at + 2); unsigned short p = htons(port); memcpy(a.data() + at, &p, 2); return a; } -struct SPS_CONNREQ -{ +struct SPS_CONNREQ { unsigned char version; unsigned char cmd; - int address_type; - QString host; - QHostAddress addr; - quint16 port; + int address_type; + QString host; + QHostAddress addr; + quint16 port; }; static int sp_get_request(QByteArray &from, SPS_CONNREQ *s) { int full_len = 4; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; - QString host; - QHostAddress addr; + QString host; + QHostAddress addr; unsigned char atype = from.at(3); - if(atype == 0x01) { + if (atype == 0x01) { full_len += 4; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; quint32 ip4; memcpy(&ip4, from.data() + 4, 4); addr.setAddress(ntohl(ip4)); - } - else if(atype == 0x03) { + } else if (atype == 0x03) { ++full_len; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; unsigned char host_len = from.at(4); full_len += host_len; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; QByteArray cs; cs.resize(host_len); memcpy(cs.data(), from.data() + 5, host_len); host = QString::fromLatin1(cs); - } - else if(atype == 0x04) { + } else if (atype == 0x04) { full_len += 16; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; quint8 a6[16]; memcpy(a6, from.data() + 4, 16); @@ -378,7 +367,7 @@ static int sp_get_request(QByteArray &from, SPS_CONNREQ *s) } full_len += 2; - if((int)from.size() < full_len) + if ((int)from.size() < full_len) return 0; QByteArray a = ByteStream::takeArray(from, full_len); @@ -386,63 +375,57 @@ static int sp_get_request(QByteArray &from, SPS_CONNREQ *s) quint16 p; memcpy(&p, a.data() + full_len - 2, 2); - s->version = a[0]; - s->cmd = a[1]; + s->version = a[0]; + s->cmd = a[1]; s->address_type = atype; - s->host = host; - s->addr = addr; - s->port = ntohs(p); + s->host = host; + s->addr = addr; + s->port = ntohs(p); return 1; } enum { StepVersion, StepAuth, StepRequest }; -class SocksClient::Private -{ +class SocksClient::Private { public: - Private(SocksClient *_q) : - sock(_q) - { - } + Private(SocksClient *_q) : sock(_q) {} BSocket sock; QString host; - int port; + int port; QString user, pass; QString real_host; - int real_port; + int real_port; QByteArray recvBuf; - int step; - int authMethod; - bool incoming, waiting; + int step; + int authMethod; + bool incoming, waiting; QString rhost; - int rport; + int rport; int pending; - bool udp; + bool udp; QString udpAddr; - int udpPort; + int udpPort; }; -SocksClient::SocksClient(QObject *parent) -:ByteStream(parent) +SocksClient::SocksClient(QObject *parent) : ByteStream(parent) { init(); d->incoming = false; } -SocksClient::SocksClient(QTcpSocket *s, QObject *parent) -:ByteStream(parent) +SocksClient::SocksClient(QTcpSocket *s, QObject *parent) : ByteStream(parent) { init(); d->incoming = true; - d->waiting = true; + d->waiting = true; d->sock.setSocket(s); } @@ -465,20 +448,17 @@ SocksClient::~SocksClient() delete d; } -QAbstractSocket* SocksClient::abstractSocket() const -{ - return d->sock.abstractSocket(); -} +QAbstractSocket *SocksClient::abstractSocket() const { return d->sock.abstractSocket(); } void SocksClient::resetConnection(bool clear) { - if(d->sock.state() != BSocket::Idle) + if (d->sock.state() != BSocket::Idle) d->sock.close(); - if(clear) + if (clear) clearReadBuffer(); d->recvBuf.resize(0); d->waiting = false; - d->udp = false; + d->udp = false; d->pending = 0; if (bytesAvailable()) { setOpenMode(QIODevice::ReadOnly); @@ -487,10 +467,7 @@ void SocksClient::resetConnection(bool clear) } } -bool SocksClient::isIncoming() const -{ - return d->incoming; -} +bool SocksClient::isIncoming() const { return d->incoming; } void SocksClient::setAuth(const QString &user, const QString &pass) { @@ -502,15 +479,15 @@ void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const Q { resetConnection(true); - d->host = proxyHost; - d->port = proxyPort; + d->host = proxyHost; + d->port = proxyPort; d->real_host = host; d->real_port = port; - d->udp = udpMode; + d->udp = udpMode; #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: Connecting to %s:%d", qPrintable(proxyHost), proxyPort); - if(d->user.isEmpty()) + if (d->user.isEmpty()) fprintf(stderr, "\n"); else fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass)); @@ -521,7 +498,7 @@ void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const Q void SocksClient::close() { d->sock.close(); - if(d->sock.bytesToWrite() == 0) + if (d->sock.bytesToWrite() == 0) resetConnection(); } @@ -530,7 +507,7 @@ void SocksClient::writeData(const QByteArray &buf) #ifdef PROX_DEBUG // show hex fprintf(stderr, "SocksClient: client write { "); - for(int n = 0; n < (int)buf.size(); ++n) + for (int n = 0; n < (int)buf.size(); ++n) fprintf(stderr, "%02X ", (unsigned char)buf[n]); fprintf(stderr, " } \n"); #endif @@ -540,7 +517,7 @@ void SocksClient::writeData(const QByteArray &buf) qint64 SocksClient::writeData(const char *data, qint64 maxSize) { - if(isOpen() && !d->udp) + if (isOpen() && !d->udp) return d->sock.write(data, maxSize); return 0; } @@ -554,14 +531,11 @@ qint64 SocksClient::readData(char *data, qint64 maxSize) return ret; } -qint64 SocksClient::bytesAvailable() const -{ - return ByteStream::bytesAvailable(); -} +qint64 SocksClient::bytesAvailable() const { return ByteStream::bytesAvailable(); } qint64 SocksClient::bytesToWrite() const { - if(isOpen()) + if (isOpen()) return d->sock.bytesToWrite(); else return 0; @@ -579,18 +553,17 @@ void SocksClient::sock_connected() void SocksClient::sock_connectionClosed() { - if(isOpen()) { + if (isOpen()) { resetConnection(); emit connectionClosed(); - } - else { + } else { setError(ErrProxyNeg); } } void SocksClient::sock_delayedCloseFinished() { - if(isOpen()) { + if (isOpen()) { resetConnection(); delayedCloseFinished(); } @@ -600,16 +573,15 @@ void SocksClient::sock_readyRead() { QByteArray block = d->sock.readAll(); - //qDebug() << this << "::sock_readyRead " << block.size() << " bytes." << + // qDebug() << this << "::sock_readyRead " << block.size() << " bytes." << // "udp=" << d->udp << openMode(); - if(!isOpen()) { - if(d->incoming) + if (!isOpen()) { + if (d->incoming) processIncoming(block); else processOutgoing(block); - } - else { - if(!d->udp) { + } else { + if (!d->udp) { appendRead(block); emit readyRead(); } @@ -621,22 +593,21 @@ void SocksClient::processOutgoing(const QByteArray &block) #ifdef PROX_DEBUG // show hex fprintf(stderr, "SocksClient: client recv { "); - for(int n = 0; n < (int)block.size(); ++n) + for (int n = 0; n < (int)block.size(); ++n) fprintf(stderr, "%02X ", (unsigned char)block[n]); fprintf(stderr, " } \n"); #endif d->recvBuf += block; - if(d->step == StepVersion) { + if (d->step == StepVersion) { SPSS_VERSION s; - int r = sps_get_version(d->recvBuf, &s); - if(r == -1) { + int r = sps_get_version(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { - if(s.version != 0x05 || s.method == 0xff) { + } else if (r == 1) { + if (s.version != 0x05 || s.method == 0xff) { #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: Method selection failed\n"); #endif @@ -646,15 +617,13 @@ void SocksClient::processOutgoing(const QByteArray &block) } QString str; - if(s.method == 0x00) { - str = "None"; + if (s.method == 0x00) { + str = "None"; d->authMethod = AuthNone; - } - else if(s.method == 0x02) { - str = "Username/Password"; + } else if (s.method == 0x02) { + str = "Username/Password"; d->authMethod = AuthUsername; - } - else { + } else { #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: Server wants to use unknown method '%02x'\n", s.method); #endif @@ -663,11 +632,10 @@ void SocksClient::processOutgoing(const QByteArray &block) return; } - if(d->authMethod == AuthNone) { + if (d->authMethod == AuthNone) { // no auth, go straight to the request do_request(); - } - else if(d->authMethod == AuthUsername) { + } else if (d->authMethod == AuthUsername) { d->step = StepAuth; #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: Authenticating [Username] ...\n"); @@ -676,22 +644,21 @@ void SocksClient::processOutgoing(const QByteArray &block) } } } - if(d->step == StepAuth) { - if(d->authMethod == AuthUsername) { + if (d->step == StepAuth) { + if (d->authMethod == AuthUsername) { SPSS_AUTHUSERNAME s; - int r = sps_get_authUsername(d->recvBuf, &s); - if(r == -1) { + int r = sps_get_authUsername(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { - if(s.version != 0x01) { + } else if (r == 1) { + if (s.version != 0x01) { resetConnection(true); setError(ErrProxyNeg); return; } - if(!s.success) { + if (!s.success) { resetConnection(true); setError(ErrProxyAuth); return; @@ -700,24 +667,22 @@ void SocksClient::processOutgoing(const QByteArray &block) do_request(); } } - } - else if(d->step == StepRequest) { + } else if (d->step == StepRequest) { SPS_CONNREQ s; - int r = sp_get_request(d->recvBuf, &s); - if(r == -1) { + int r = sp_get_request(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { - if(s.cmd != RET_SUCCESS) { + } else if (r == 1) { + if (s.cmd != RET_SUCCESS) { #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: client << Error >> [%02x]\n", s.cmd); #endif resetConnection(true); - if(s.cmd == RET_UNREACHABLE) + if (s.cmd == RET_UNREACHABLE) setError(ErrHostNotFound); - else if(s.cmd == RET_CONNREFUSED) + else if (s.cmd == RET_CONNREFUSED) setError(ErrConnectionRefused); else setError(ErrProxyNeg); @@ -727,8 +692,8 @@ void SocksClient::processOutgoing(const QByteArray &block) #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: client << Success >>\n"); #endif - if(d->udp) { - if(s.address_type == 0x03) + if (d->udp) { + if (s.address_type == 0x03) d->udpAddr = s.host; else d->udpAddr = s.addr.toString(); @@ -740,10 +705,10 @@ void SocksClient::processOutgoing(const QByteArray &block) QPointer self = this; setOpenMode(QIODevice::ReadWrite); emit connected(); - if(!self) + if (!self) return; - if(!d->recvBuf.isEmpty()) { + if (!d->recvBuf.isEmpty()) { appendRead(d->recvBuf); d->recvBuf.resize(0); readyRead(); @@ -757,10 +722,10 @@ void SocksClient::do_request() #ifdef PROX_DEBUG fprintf(stderr, "SocksClient: Requesting ...\n"); #endif - d->step = StepRequest; - int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT; + d->step = StepRequest; + int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT; QByteArray buf; - if(!d->real_host.isEmpty()) + if (!d->real_host.isEmpty()) buf = sp_set_request(d->real_host, d->real_port, cmd); else buf = sp_set_request(QHostAddress(), 0, cmd); @@ -770,31 +735,29 @@ void SocksClient::do_request() void SocksClient::sock_bytesWritten(qint64 x) { int bytes = x; - if(d->pending >= bytes) { + if (d->pending >= bytes) { d->pending -= bytes; bytes = 0; - } - else { + } else { bytes -= d->pending; d->pending = 0; } - if(bytes > 0) + if (bytes > 0) bytesWritten(bytes); } void SocksClient::sock_error(int x) { - if(isOpen()) { + if (isOpen()) { resetConnection(); setError(ErrRead); - } - else { + } else { resetConnection(true); - if(x == BSocket::ErrHostNotFound) + if (x == BSocket::ErrHostNotFound) setError(ErrProxyConnect); - else if(x == BSocket::ErrConnectionRefused) + else if (x == BSocket::ErrConnectionRefused) setError(ErrProxyConnect); - else if(x == BSocket::ErrRead) + else if (x == BSocket::ErrRead) setError(ErrProxyNeg); } } @@ -802,7 +765,7 @@ void SocksClient::sock_error(int x) void SocksClient::serve() { d->waiting = false; - d->step = StepVersion; + d->step = StepVersion; continueIncoming(); } @@ -811,84 +774,77 @@ void SocksClient::processIncoming(const QByteArray &block) #ifdef PROX_DEBUG // show hex fprintf(stderr, "SocksClient: server recv { "); - for(int n = 0; n < (int)block.size(); ++n) + for (int n = 0; n < (int)block.size(); ++n) fprintf(stderr, "%02X ", (unsigned char)block[n]); fprintf(stderr, " } \n"); #endif d->recvBuf += block; - if(!d->waiting) + if (!d->waiting) continueIncoming(); } void SocksClient::continueIncoming() { - if(d->recvBuf.isEmpty()) + if (d->recvBuf.isEmpty()) return; - if(d->step == StepVersion) { + if (d->step == StepVersion) { SPCS_VERSION s; - int r = spc_get_version(d->recvBuf, &s); - if(r == -1) { + int r = spc_get_version(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { - if(s.version != 0x05) { + } else if (r == 1) { + if (s.version != 0x05) { resetConnection(true); setError(ErrProxyNeg); return; } int methods = 0; - for(int n = 0; n < (int)s.methodList.size(); ++n) { + for (int n = 0; n < (int)s.methodList.size(); ++n) { unsigned char c = s.methodList[n]; - if(c == 0x00) + if (c == 0x00) methods |= AuthNone; - else if(c == 0x02) + else if (c == 0x02) methods |= AuthUsername; } d->waiting = true; emit incomingMethods(methods); } - } - else if(d->step == StepAuth) { + } else if (d->step == StepAuth) { SPCS_AUTHUSERNAME s; - int r = spc_get_authUsername(d->recvBuf, &s); - if(r == -1) { + int r = spc_get_authUsername(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { + } else if (r == 1) { d->waiting = true; incomingAuth(s.user, s.pass); } - } - else if(d->step == StepRequest) { + } else if (d->step == StepRequest) { SPS_CONNREQ s; - int r = sp_get_request(d->recvBuf, &s); - if(r == -1) { + int r = sp_get_request(d->recvBuf, &s); + if (r == -1) { resetConnection(true); setError(ErrProxyNeg); return; - } - else if(r == 1) { + } else if (r == 1) { d->waiting = true; - if(s.cmd == REQ_CONNECT) { - if(!s.host.isEmpty()) + if (s.cmd == REQ_CONNECT) { + if (!s.host.isEmpty()) d->rhost = s.host; else d->rhost = s.addr.toString(); d->rport = s.port; QIODevice::open(QIODevice::ReadWrite); incomingConnectRequest(d->rhost, d->rport); - } - else if(s.cmd == REQ_UDPASSOCIATE) { + } else if (s.cmd == REQ_UDPASSOCIATE) { incomingUDPAssociateRequest(); - } - else { + } else { requestDeny(); return; } @@ -898,17 +854,16 @@ void SocksClient::continueIncoming() void SocksClient::chooseMethod(int method) { - if(d->step != StepVersion || !d->waiting) + if (d->step != StepVersion || !d->waiting) return; unsigned char c; - if(method == AuthNone) { + if (method == AuthNone) { d->step = StepRequest; - c = 0x00; - } - else { + c = 0x00; + } else { d->step = StepAuth; - c = 0x02; + c = 0x02; } // version response @@ -919,16 +874,16 @@ void SocksClient::chooseMethod(int method) void SocksClient::authGrant(bool b) { - if(d->step != StepAuth || !d->waiting) + if (d->step != StepAuth || !d->waiting) return; - if(b) + if (b) d->step = StepRequest; // auth response d->waiting = false; writeData(sps_set_authUsername(b)); - if(!b) { + if (!b) { resetConnection(true); return; } @@ -937,7 +892,7 @@ void SocksClient::authGrant(bool b) void SocksClient::requestDeny() { - if(d->step != StepRequest || !d->waiting) + if (d->step != StepRequest || !d->waiting) return; // response @@ -948,7 +903,7 @@ void SocksClient::requestDeny() void SocksClient::grantConnect() { - if(d->step != StepRequest || !d->waiting) + if (d->step != StepRequest || !d->waiting) return; // response @@ -959,7 +914,7 @@ void SocksClient::grantConnect() fprintf(stderr, "SocksClient: server << Success >>\n"); #endif - if(!d->recvBuf.isEmpty()) { + if (!d->recvBuf.isEmpty()) { appendRead(d->recvBuf); d->recvBuf.resize(0); readyRead(); @@ -968,7 +923,7 @@ void SocksClient::grantConnect() void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort) { - if(d->step != StepRequest || !d->waiting) + if (d->step != StepRequest || !d->waiting) return; // response @@ -980,29 +935,17 @@ void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort) fprintf(stderr, "SocksClient: server << Success >>\n"); #endif - if(!d->recvBuf.isEmpty()) + if (!d->recvBuf.isEmpty()) d->recvBuf.resize(0); } -QHostAddress SocksClient::peerAddress() const -{ - return d->sock.peerAddress(); -} +QHostAddress SocksClient::peerAddress() const { return d->sock.peerAddress(); } -quint16 SocksClient::peerPort() const -{ - return d->sock.peerPort(); -} +quint16 SocksClient::peerPort() const { return d->sock.peerPort(); } -QString SocksClient::udpAddress() const -{ - return d->udpAddr; -} +QString SocksClient::udpAddress() const { return d->udpAddr; } -quint16 SocksClient::udpPort() const -{ - return d->udpPort; -} +quint16 SocksClient::udpPort() const { return d->udpPort; } SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort) { @@ -1012,19 +955,14 @@ SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddre //---------------------------------------------------------------------------- // SocksServer //---------------------------------------------------------------------------- -class SocksServer::Private -{ +class SocksServer::Private { public: - QTcpServer *serv = nullptr; - QList incomingConns; - QUdpSocket *sd = nullptr; + QTcpServer * serv = nullptr; + QList incomingConns; + QUdpSocket * sd = nullptr; }; -SocksServer::SocksServer(QObject *parent) -:QObject(parent) -{ - d = new Private; -} +SocksServer::SocksServer(QObject *parent) : QObject(parent) { d = new Private; } SocksServer::~SocksServer() { @@ -1041,10 +979,7 @@ void SocksServer::setServerSocket(QTcpServer *server) connect(d->serv, SIGNAL(newConnection()), SLOT(newConnection())); } -bool SocksServer::isActive() const -{ - return d->serv->isListening(); -} +bool SocksServer::isActive() const { return d->serv->isListening(); } bool SocksServer::listen(quint16 port, bool udp) { @@ -1052,11 +987,11 @@ bool SocksServer::listen(quint16 port, bool udp) if (!d->serv) { setServerSocket(new QTcpServer(this)); } - if(!d->serv->listen(QHostAddress::Any, port)) + if (!d->serv->listen(QHostAddress::Any, port)) return false; - if(udp) { + if (udp) { d->sd = new QUdpSocket(this); - if(!d->sd->bind(QHostAddress::LocalHost, port)) { + if (!d->sd->bind(QHostAddress::LocalHost, port)) { delete d->sd; d->sd = nullptr; delete d->serv; @@ -1076,19 +1011,13 @@ void SocksServer::stop() d->serv = nullptr; } -int SocksServer::port() const -{ - return d->serv? d->serv->serverPort(): 0; -} +int SocksServer::port() const { return d->serv ? d->serv->serverPort() : 0; } -QHostAddress SocksServer::address() const -{ - return d->serv? d->serv->serverAddress(): QHostAddress(); -} +QHostAddress SocksServer::address() const { return d->serv ? d->serv->serverAddress() : QHostAddress(); } SocksClient *SocksServer::takeIncoming() { - if(d->incomingConns.isEmpty()) + if (d->incomingConns.isEmpty()) return nullptr; SocksClient *c = d->incomingConns.takeFirst(); @@ -1104,7 +1033,7 @@ SocksClient *SocksServer::takeIncoming() void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data) { - if(d->sd) { + if (d->sd) { d->sd->writeDatagram(data.data(), data.size(), addr, port); } } @@ -1127,10 +1056,10 @@ void SocksServer::connectionError() void SocksServer::sd_activated() { while (d->sd->hasPendingDatagrams()) { - QByteArray datagram(d->sd->pendingDatagramSize(), Qt::Uninitialized); + QByteArray datagram(d->sd->pendingDatagramSize(), Qt::Uninitialized); QHostAddress sender; - quint16 senderPort; - auto sz = d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + quint16 senderPort; + auto sz = d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); if (sz >= 0) { datagram.truncate(sz); incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram); diff --git a/src/irisnet/noncore/cutestuff/socks.h b/src/irisnet/noncore/cutestuff/socks.h index 8605e7fd..039b9a13 100644 --- a/src/irisnet/noncore/cutestuff/socks.h +++ b/src/irisnet/noncore/cutestuff/socks.h @@ -29,8 +29,7 @@ class QTcpSocket; class SocksClient; class SocksServer; -class SocksUDP : public QObject -{ +class SocksUDP : public QObject { Q_OBJECT public: ~SocksUDP(); @@ -52,24 +51,23 @@ private slots: SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort); }; -class SocksClient : public ByteStream -{ +class SocksClient : public ByteStream { Q_OBJECT public: enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth }; - enum Method { AuthNone=0x0001, AuthUsername=0x0002 }; + enum Method { AuthNone = 0x0001, AuthUsername = 0x0002 }; enum Request { ReqConnect, ReqUDPAssociate }; - SocksClient(QObject *parent=nullptr); - SocksClient(QTcpSocket *, QObject *parent=nullptr); + SocksClient(QObject *parent = nullptr); + SocksClient(QTcpSocket *, QObject *parent = nullptr); ~SocksClient(); - virtual QAbstractSocket* abstractSocket() const; + virtual QAbstractSocket *abstractSocket() const; bool isIncoming() const; // outgoing - void setAuth(const QString &user, const QString &pass=""); - void connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode=false); + void setAuth(const QString &user, const QString &pass = ""); + void connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode = false); // incoming void chooseMethod(int); @@ -79,17 +77,17 @@ class SocksClient : public ByteStream void grantUDPAssociate(const QString &relayHost, int relayPort); // from ByteStream - void close(); + void close(); qint64 bytesAvailable() const; qint64 bytesToWrite() const; // remote address QHostAddress peerAddress() const; - quint16 peerPort() const; + quint16 peerPort() const; // udp - QString udpAddress() const; - quint16 udpPort() const; + QString udpAddress() const; + quint16 udpPort() const; SocksUDP *createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort); protected: @@ -120,7 +118,7 @@ private slots: Private *d; void init(); - void resetConnection(bool clear=false); + void resetConnection(bool clear = false); void do_request(); void processOutgoing(const QByteArray &); void processIncoming(const QByteArray &); @@ -128,18 +126,17 @@ private slots: void writeData(const QByteArray &a); }; -class SocksServer : public QObject -{ +class SocksServer : public QObject { Q_OBJECT public: - SocksServer(QObject *parent=nullptr); + SocksServer(QObject *parent = nullptr); ~SocksServer(); - void setServerSocket(QTcpServer *server); - bool isActive() const; - bool listen(quint16 port, bool udp=false); - void stop(); - int port() const; + void setServerSocket(QTcpServer *server); + bool isActive() const; + bool listen(quint16 port, bool udp = false); + void stop(); + int port() const; QHostAddress address() const; SocksClient *takeIncoming(); diff --git a/src/irisnet/noncore/ice176.cpp b/src/irisnet/noncore/ice176.cpp index 079eb239..54a4a765 100644 --- a/src/irisnet/noncore/ice176.cpp +++ b/src/irisnet/noncore/ice176.cpp @@ -32,11 +32,7 @@ #include namespace XMPP { -enum -{ - Direct, - Relayed -}; +enum { Direct, Relayed }; static QChar randomPrintableChar() { @@ -45,9 +41,9 @@ static QChar randomPrintableChar() // 52-61 = 0-9 uchar c = QCA::Random::randomChar() % 62; - if(c <= 25) + if (c <= 25) return 'a' + c; - else if(c <= 51) + else if (c <= 51) return 'A' + (c - 26); else return '0' + (c - 52); @@ -56,7 +52,7 @@ static QChar randomPrintableChar() static QString randomCredential(int len) { QString out; - for(int n = 0; n < len; ++n) + for (int n = 0; n < len; ++n) out += randomPrintableChar(); return out; } @@ -65,7 +61,7 @@ static qint64 calc_pair_priority(int a, int b) { qint64 priority = ((qint64)1 << 32) * qMin(a, b); priority += (qint64)2 * qMax(a, b); - if(a > b) + if (a > b) ++priority; return priority; } @@ -73,7 +69,7 @@ static qint64 calc_pair_priority(int a, int b) // see if candidates are considered the same for pruning purposes static bool compare_candidates(const IceComponent::CandidateInfo &a, const IceComponent::CandidateInfo &b) { - if(a.addr == b.addr && a.componentId == b.componentId) + if (a.addr == b.addr && a.componentId == b.componentId) return true; else return false; @@ -83,72 +79,49 @@ static bool compare_candidates(const IceComponent::CandidateInfo &a, const IceCo // FIXME: dry (this is in psi avcall also) static int getAddressScope(const QHostAddress &a) { - if(a.protocol() == QAbstractSocket::IPv6Protocol) - { - if(a == QHostAddress(QHostAddress::LocalHostIPv6)) + if (a.protocol() == QAbstractSocket::IPv6Protocol) { + if (a == QHostAddress(QHostAddress::LocalHostIPv6)) return 0; - else if(XMPP::Ice176::isIPv6LinkLocalAddress(a)) + else if (XMPP::Ice176::isIPv6LinkLocalAddress(a)) return 1; - } - else if(a.protocol() == QAbstractSocket::IPv4Protocol) - { + } else if (a.protocol() == QAbstractSocket::IPv4Protocol) { quint32 v4 = a.toIPv4Address(); - quint8 a0 = v4 >> 24; - quint8 a1 = (v4 >> 16) & 0xff; - if(a0 == 127) + quint8 a0 = v4 >> 24; + quint8 a1 = (v4 >> 16) & 0xff; + if (a0 == 127) return 0; - else if(a0 == 169 && a1 == 254) + else if (a0 == 169 && a1 == 254) return 1; - else if(a0 == 10) + else if (a0 == 10) return 2; - else if(a0 == 172 && a1 >= 16 && a1 <= 31) + else if (a0 == 172 && a1 >= 16 && a1 <= 31) return 2; - else if(a0 == 192 && a1 == 168) + else if (a0 == 192 && a1 == 168) return 2; } return 3; } -class Ice176::Private : public QObject -{ +class Ice176::Private : public QObject { Q_OBJECT public: - enum State - { - Stopped, - Starting, - Started, - Stopping - }; + enum State { Stopped, Starting, Started, Stopping }; - enum CandidatePairState - { - PWaiting, - PInProgress, - PSucceeded, - PFailed, - PFrozen - }; + enum CandidatePairState { PWaiting, PInProgress, PSucceeded, PFailed, PFrozen }; - enum CheckListState - { - LRunning, - LCompleted, - LFailed - }; + enum CheckListState { LRunning, LCompleted, LFailed }; - class CandidatePair - { + class CandidatePair { public: IceComponent::CandidateInfo local, remote; - bool isDefault; - bool isValid; - bool isNominated; - CandidatePairState state; + bool isDefault; + bool isValid; + bool isNominated; + CandidatePairState state; - qint64 priority; + qint64 priority; QString foundation; StunBinding *binding; @@ -157,93 +130,72 @@ class Ice176::Private : public QObject // or such, to multiplex ids StunTransactionPool *pool; - CandidatePair() : - binding(nullptr), - pool(nullptr) - { - } + CandidatePair() : binding(nullptr), pool(nullptr) {} }; - class CheckList - { + class CheckList { public: QList pairs; - CheckListState state; + CheckListState state; }; - class Component - { + class Component { public: - int id; + int id; IceComponent *ic; - bool localFinished; - bool stopped; - bool lowOverhead; - - Component() : - localFinished(false), - stopped(false), - lowOverhead(false) - { - } + bool localFinished; + bool stopped; + bool lowOverhead; + + Component() : localFinished(false), stopped(false), lowOverhead(false) {} }; - Ice176 *q; - Ice176::Mode mode; - State state; - TurnClient::Proxy proxy; - UdpPortReserver *portReserver; - int componentCount; - QList localAddrs; + Ice176 * q; + Ice176::Mode mode; + State state; + TurnClient::Proxy proxy; + UdpPortReserver * portReserver; + int componentCount; + QList localAddrs; QList extAddrs; - QHostAddress stunBindAddr; - int stunBindPort; - QHostAddress stunRelayUdpAddr; - int stunRelayUdpPort; - QString stunRelayUdpUser; - QCA::SecureArray stunRelayUdpPass; - QHostAddress stunRelayTcpAddr; - int stunRelayTcpPort; - QString stunRelayTcpUser; - QCA::SecureArray stunRelayTcpPass; - QString localUser, localPass; - QString peerUser, peerPass; - QList components; + QHostAddress stunBindAddr; + int stunBindPort; + QHostAddress stunRelayUdpAddr; + int stunRelayUdpPort; + QString stunRelayUdpUser; + QCA::SecureArray stunRelayUdpPass; + QHostAddress stunRelayTcpAddr; + int stunRelayTcpPort; + QString stunRelayTcpUser; + QCA::SecureArray stunRelayTcpPass; + QString localUser, localPass; + QString peerUser, peerPass; + QList components; QList localCandidates; - QSet iceTransports; - CheckList checkList; - QList< QList > in; - bool useLocal; - bool useStunBind; - bool useStunRelayUdp; - bool useStunRelayTcp; - bool useTrickle; - QTimer *collectTimer; + QSet iceTransports; + CheckList checkList; + QList> in; + bool useLocal; + bool useStunBind; + bool useStunRelayUdp; + bool useStunRelayTcp; + bool useTrickle; + QTimer * collectTimer; Private(Ice176 *_q) : - QObject(_q), - q(_q), - state(Stopped), - portReserver(nullptr), - componentCount(0), - useLocal(true), - useStunBind(true), - useStunRelayUdp(true), - useStunRelayTcp(true), - useTrickle(false), - collectTimer(nullptr) + QObject(_q), q(_q), state(Stopped), portReserver(nullptr), componentCount(0), useLocal(true), useStunBind(true), + useStunRelayUdp(true), useStunRelayTcp(true), useTrickle(false), collectTimer(nullptr) { } ~Private() { - if(collectTimer) - { + if (collectTimer) { collectTimer->disconnect(this); collectTimer->deleteLater(); } - foreach(const Component &c, components) + foreach (const Component &c, components) delete c.ic; // no need to delete pools and bindings since pools already deleted here @@ -273,9 +225,8 @@ class Ice176::Private : public QObject int findLocalAddress(const QHostAddress &addr) { - for(int n = 0; n < localAddrs.count(); ++n) - { - if(localAddrs[n].addr == addr) + for (int n = 0; n < localAddrs.count(); ++n) { + if (localAddrs[n].addr == addr) return n; } @@ -285,14 +236,13 @@ class Ice176::Private : public QObject void updateLocalAddresses(const QList &addrs) { // for now, ignore address changes during operation - if(state != Stopped) + if (state != Stopped) return; localAddrs.clear(); - foreach(const LocalAddress &la, addrs) - { + foreach (const LocalAddress &la, addrs) { int at = findLocalAddress(la.addr); - if(at == -1) + if (at == -1) localAddrs += la; } } @@ -300,14 +250,13 @@ class Ice176::Private : public QObject void updateExternalAddresses(const QList &addrs) { // for now, ignore address changes during operation - if(state != Stopped) + if (state != Stopped) return; extAddrs.clear(); - foreach(const ExternalAddress &ea, addrs) - { + foreach (const ExternalAddress &ea, addrs) { int at = findLocalAddress(ea.base.addr); - if(at != -1) + if (at != -1) extAddrs += ea; } } @@ -321,33 +270,34 @@ class Ice176::Private : public QObject localUser = randomCredential(4); localPass = randomCredential(22); - QList socketList; - if(portReserver) + QList socketList; + if (portReserver) socketList = portReserver->borrowSockets(componentCount, this); - for(int n = 0; n < componentCount; ++n) - { + for (int n = 0; n < componentCount; ++n) { Component c; c.id = n + 1; c.ic = new IceComponent(c.id, this); c.ic->setDebugLevel(IceComponent::DL_Info); - connect(c.ic, SIGNAL(candidateAdded(XMPP::IceComponent::Candidate)), SLOT(ic_candidateAdded(XMPP::IceComponent::Candidate))); - connect(c.ic, SIGNAL(candidateRemoved(XMPP::IceComponent::Candidate)), SLOT(ic_candidateRemoved(XMPP::IceComponent::Candidate))); + connect(c.ic, SIGNAL(candidateAdded(XMPP::IceComponent::Candidate)), + SLOT(ic_candidateAdded(XMPP::IceComponent::Candidate))); + connect(c.ic, SIGNAL(candidateRemoved(XMPP::IceComponent::Candidate)), + SLOT(ic_candidateRemoved(XMPP::IceComponent::Candidate))); connect(c.ic, SIGNAL(localFinished()), SLOT(ic_localFinished())); connect(c.ic, SIGNAL(stopped()), SLOT(ic_stopped())); connect(c.ic, SIGNAL(debugLine(QString)), SLOT(ic_debugLine(QString))); c.ic->setClientSoftwareNameAndVersion("Iris"); c.ic->setProxy(proxy); - if(portReserver) + if (portReserver) c.ic->setPortReserver(portReserver); c.ic->setLocalAddresses(localAddrs); c.ic->setExternalAddresses(extAddrs); - if(!stunBindAddr.isNull()) + if (!stunBindAddr.isNull()) c.ic->setStunBindService(stunBindAddr, stunBindPort); - if(!stunRelayUdpAddr.isNull()) + if (!stunRelayUdpAddr.isNull()) c.ic->setStunRelayUdpService(stunRelayUdpAddr, stunRelayUdpPort, stunRelayUdpUser, stunRelayUdpPass); - if(!stunRelayTcpAddr.isNull()) + if (!stunRelayTcpAddr.isNull()) c.ic->setStunRelayTcpService(stunRelayTcpAddr, stunRelayTcpPort, stunRelayTcpUser, stunRelayTcpPass); c.ic->setUseLocal(useLocal); @@ -367,7 +317,7 @@ class Ice176::Private : public QObject // the app provided a different address list to // UdpPortReserver and Ice176. and that would really be // a dumb thing to do but I'm not going to Q_ASSERT it - if(!socketList.isEmpty()) + if (!socketList.isEmpty()) portReserver->returnSockets(socketList); } @@ -377,13 +327,10 @@ class Ice176::Private : public QObject state = Stopping; - if(!components.isEmpty()) - { - for(int n = 0; n < components.count(); ++n) + if (!components.isEmpty()) { + for (int n = 0; n < components.count(); ++n) components[n].ic->stop(); - } - else - { + } else { // TODO: hmm, is it possible to have no components? QMetaObject::invokeMethod(this, "postStop", Qt::QueuedConnection); } @@ -392,41 +339,37 @@ class Ice176::Private : public QObject void addRemoteCandidates(const QList &list) { QList remoteCandidates; - foreach(const Candidate &c, list) - { + foreach (const Candidate &c, list) { IceComponent::CandidateInfo ci; ci.addr.addr = c.ip; ci.addr.addr.setScopeId(QString()); - ci.addr.port = c.port; - ci.type = (IceComponent::CandidateType)string_to_candidateType(c.type); // TODO: handle error + ci.addr.port = c.port; + ci.type = (IceComponent::CandidateType)string_to_candidateType(c.type); // TODO: handle error ci.componentId = c.component; - ci.priority = c.priority; - ci.foundation = c.foundation; - if(!c.rel_addr.isNull()) - { + ci.priority = c.priority; + ci.foundation = c.foundation; + if (!c.rel_addr.isNull()) { ci.base.addr = c.rel_addr; ci.base.addr.setScopeId(QString()); ci.base.port = c.rel_port; } ci.network = c.network; - ci.id = c.id; + ci.id = c.id; remoteCandidates += ci; } printf("adding %d remote candidates\n", remoteCandidates.count()); QList pairs; - foreach(const IceComponent::Candidate &cc, localCandidates) - { + foreach (const IceComponent::Candidate &cc, localCandidates) { const IceComponent::CandidateInfo &lc = cc.info; - foreach(const IceComponent::CandidateInfo &rc, remoteCandidates) - { - if(lc.componentId != rc.componentId) + foreach (const IceComponent::CandidateInfo &rc, remoteCandidates) { + if (lc.componentId != rc.componentId) continue; // don't pair ipv4 with ipv6. FIXME: is this right? - if(lc.addr.addr.protocol() != rc.addr.addr.protocol()) + if (lc.addr.addr.protocol() != rc.addr.addr.protocol()) continue; // don't relay to localhost. turnserver @@ -434,19 +377,20 @@ class Ice176::Private : public QObject // should qualify as a HACK or not. // trying to relay to localhost is pretty // stupid anyway - if(lc.type == IceComponent::RelayedType && getAddressScope(rc.addr.addr) == 0) + if (lc.type == IceComponent::RelayedType && getAddressScope(rc.addr.addr) == 0) continue; CandidatePair pair; - pair.state = PFrozen; // FIXME: setting state here may be wrong - pair.local = lc; + pair.state = PFrozen; // FIXME: setting state here may be wrong + pair.local = lc; pair.remote = rc; - if(pair.local.addr.addr.protocol() == QAbstractSocket::IPv6Protocol && isIPv6LinkLocalAddress(pair.local.addr.addr)) + if (pair.local.addr.addr.protocol() == QAbstractSocket::IPv6Protocol + && isIPv6LinkLocalAddress(pair.local.addr.addr)) pair.remote.addr.addr.setScopeId(pair.local.addr.addr.scopeId()); - pair.isDefault = false; - pair.isValid = false; + pair.isDefault = false; + pair.isValid = false; pair.isNominated = false; - if(mode == Ice176::Initiator) + if (mode == Ice176::Initiator) pair.priority = calc_pair_priority(lc.priority, rc.priority); else pair.priority = calc_pair_priority(rc.priority, lc.priority); @@ -459,12 +403,10 @@ class Ice176::Private : public QObject // combine pairs with existing, and sort pairs = checkList.pairs + pairs; checkList.pairs.clear(); - foreach(const CandidatePair &pair, pairs) - { + foreach (const CandidatePair &pair, pairs) { int at; - for(at = 0; at < checkList.pairs.count(); ++at) - { - if(compare_pair(pair, checkList.pairs[at]) < 0) + for (at = 0; at < checkList.pairs.count(); ++at) { + if (compare_pair(pair, checkList.pairs[at]) < 0) break; } @@ -473,30 +415,27 @@ class Ice176::Private : public QObject // pruning - for(int n = 0; n < checkList.pairs.count(); ++n) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { CandidatePair &pair = checkList.pairs[n]; - if(pair.local.type == IceComponent::ServerReflexiveType) + if (pair.local.type == IceComponent::ServerReflexiveType) pair.local.addr = pair.local.base; } - for(int n = 0; n < checkList.pairs.count(); ++n) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { CandidatePair &pair = checkList.pairs[n]; - printf("%d, %s:%d -> %s:%d\n", pair.local.componentId, qPrintable(pair.local.addr.addr.toString()), pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); + printf("%d, %s:%d -> %s:%d\n", pair.local.componentId, qPrintable(pair.local.addr.addr.toString()), + pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); bool found = false; - for(int i = n - 1; i >= 0; --i) - { - if(compare_candidates(pair.local, checkList.pairs[i].local) && compare_candidates(pair.remote, checkList.pairs[i].remote)) - { + for (int i = n - 1; i >= 0; --i) { + if (compare_candidates(pair.local, checkList.pairs[i].local) + && compare_candidates(pair.remote, checkList.pairs[i].remote)) { found = true; break; } } - if(found ) - { + if (found) { checkList.pairs.removeAt(n); --n; // adjust position } @@ -504,18 +443,17 @@ class Ice176::Private : public QObject // max pairs is 100 * number of components int max_pairs = 100 * components.count(); - while(checkList.pairs.count() > max_pairs) + while (checkList.pairs.count() > max_pairs) checkList.pairs.removeLast(); printf("%d after pruning\n", checkList.pairs.count()); // set state - for(int n = 0; n < checkList.pairs.count(); ++n) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { CandidatePair &pair = checkList.pairs[n]; // only initialize the new pairs - if(pair.state != PFrozen) + if (pair.state != PFrozen) continue; pair.foundation = pair.local.foundation + pair.remote.foundation; @@ -531,9 +469,10 @@ class Ice176::Private : public QObject Component &c = components[findComponent(lc.info.componentId)]; pair.pool = new StunTransactionPool(StunTransaction::Udp, this); - connect(pair.pool, SIGNAL(outgoingMessage(QByteArray,QHostAddress,int)), SLOT(pool_outgoingMessage(QByteArray,QHostAddress,int))); - //pair.pool->setUsername(peerUser + ':' + localUser); - //pair.pool->setPassword(peerPass.toUtf8()); + connect(pair.pool, SIGNAL(outgoingMessage(QByteArray, QHostAddress, int)), + SLOT(pool_outgoingMessage(QByteArray, QHostAddress, int))); + // pair.pool->setUsername(peerUser + ':' + localUser); + // pair.pool->setPassword(peerPass.toUtf8()); pair.binding = new StunBinding(pair.pool); connect(pair.binding, SIGNAL(success()), SLOT(binding_success())); @@ -541,12 +480,10 @@ class Ice176::Private : public QObject int prflx_priority = c.ic->peerReflexivePriority(lc.iceTransport, lc.path); pair.binding->setPriority(prflx_priority); - if(mode == Ice176::Initiator) - { + if (mode == Ice176::Initiator) { pair.binding->setIceControlling(0); pair.binding->setUseCandidate(true); - } - else + } else pair.binding->setIceControlled(0); pair.binding->setShortTermUsername(peerUser + ':' + localUser); @@ -559,38 +496,37 @@ class Ice176::Private : public QObject void write(int componentIndex, const QByteArray &datagram) { int at = -1; - for(int n = 0; n < checkList.pairs.count(); ++n) - { - if(checkList.pairs[n].local.componentId - 1 == componentIndex && checkList.pairs[n].isValid) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { + if (checkList.pairs[n].local.componentId - 1 == componentIndex && checkList.pairs[n].isValid) { at = n; break; } } - if(at == -1) + if (at == -1) return; CandidatePair &pair = checkList.pairs[at]; at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port); - if(at == -1) // FIXME: assert? + if (at == -1) // FIXME: assert? return; IceComponent::Candidate &lc = localCandidates[at]; IceTransport *sock = lc.iceTransport; - int path = lc.path; + int path = lc.path; sock->writeDatagram(path, datagram, pair.remote.addr.addr, pair.remote.addr.port); // DOR-SR? - QMetaObject::invokeMethod(q, "datagramsWritten", Qt::QueuedConnection, Q_ARG(int, componentIndex), Q_ARG(int, 1)); + QMetaObject::invokeMethod(q, "datagramsWritten", Qt::QueuedConnection, Q_ARG(int, componentIndex), + Q_ARG(int, 1)); } void flagComponentAsLowOverhead(int componentIndex) { // FIXME: ok to assume in order? - Component &c = components[componentIndex]; + Component &c = components[componentIndex]; c.lowOverhead = true; // FIXME: actually do something @@ -599,9 +535,8 @@ class Ice176::Private : public QObject private: int findComponent(const IceComponent *ic) const { - for(int n = 0; n < components.count(); ++n) - { - if(components[n].ic == ic) + for (int n = 0; n < components.count(); ++n) { + if (components[n].ic == ic) return n; } @@ -610,9 +545,8 @@ class Ice176::Private : public QObject int findComponent(int id) const { - for(int n = 0; n < components.count(); ++n) - { - if(components[n].id == id) + for (int n = 0; n < components.count(); ++n) { + if (components[n].id == id) return n; } @@ -621,10 +555,9 @@ class Ice176::Private : public QObject int findLocalCandidate(const IceTransport *iceTransport, int path) const { - for(int n = 0; n < localCandidates.count(); ++n) - { + for (int n = 0; n < localCandidates.count(); ++n) { const IceComponent::Candidate &cc = localCandidates[n]; - if(cc.iceTransport == iceTransport && cc.path == path) + if (cc.iceTransport == iceTransport && cc.path == path) return n; } @@ -633,10 +566,9 @@ class Ice176::Private : public QObject int findLocalCandidate(const QHostAddress &fromAddr, int fromPort) { - for(int n = 0; n < localCandidates.count(); ++n) - { + for (int n = 0; n < localCandidates.count(); ++n) { const IceComponent::Candidate &cc = localCandidates[n]; - if(cc.info.addr.addr == fromAddr && cc.info.addr.port == fromPort) + if (cc.info.addr.addr == fromAddr && cc.info.addr.port == fromPort) return n; } @@ -646,26 +578,34 @@ class Ice176::Private : public QObject static QString candidateType_to_string(IceComponent::CandidateType type) { QString out; - switch(type) - { - case IceComponent::HostType: out = "host"; break; - case IceComponent::PeerReflexiveType: out = "prflx"; break; - case IceComponent::ServerReflexiveType: out = "srflx"; break; - case IceComponent::RelayedType: out = "relay"; break; - default: Q_ASSERT(0); + switch (type) { + case IceComponent::HostType: + out = "host"; + break; + case IceComponent::PeerReflexiveType: + out = "prflx"; + break; + case IceComponent::ServerReflexiveType: + out = "srflx"; + break; + case IceComponent::RelayedType: + out = "relay"; + break; + default: + Q_ASSERT(0); } return out; } static int string_to_candidateType(const QString &in) { - if(in == "host") + if (in == "host") return IceComponent::HostType; - else if(in == "prflx") + else if (in == "prflx") return IceComponent::PeerReflexiveType; - else if(in == "srflx") + else if (in == "srflx") return IceComponent::ServerReflexiveType; - else if(in == "relay") + else if (in == "relay") return IceComponent::RelayedType; else return -1; @@ -674,14 +614,17 @@ class Ice176::Private : public QObject static int compare_pair(const CandidatePair &a, const CandidatePair &b) { // prefer remote srflx, for leap - if(a.remote.type == IceComponent::ServerReflexiveType && b.remote.type != IceComponent::ServerReflexiveType && b.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol) + if (a.remote.type == IceComponent::ServerReflexiveType && b.remote.type != IceComponent::ServerReflexiveType + && b.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol) return -1; - else if(b.remote.type == IceComponent::ServerReflexiveType && a.remote.type != IceComponent::ServerReflexiveType && a.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol) + else if (b.remote.type == IceComponent::ServerReflexiveType + && a.remote.type != IceComponent::ServerReflexiveType + && a.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol) return 1; - if(a.priority > b.priority) + if (a.priority > b.priority) return -1; - else if(b.priority > a.priority) + else if (b.priority > a.priority) return 1; return 0; @@ -697,50 +640,47 @@ private slots: void ic_candidateAdded(const XMPP::IceComponent::Candidate &_cc) { IceComponent::Candidate cc = _cc; - cc.info.id = randomCredential(10); // FIXME: ensure unique - cc.info.foundation = "0"; // FIXME + cc.info.id = randomCredential(10); // FIXME: ensure unique + cc.info.foundation = "0"; // FIXME // TODO localCandidates += cc; - printf("C%d: candidate added: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), cc.info.addr.port); + printf("C%d: candidate added: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), + cc.info.addr.port); - if(!iceTransports.contains(cc.iceTransport)) - { + if (!iceTransports.contains(cc.iceTransport)) { connect(cc.iceTransport, SIGNAL(readyRead(int)), SLOT(it_readyRead(int))); - connect(cc.iceTransport, SIGNAL(datagramsWritten(int,int,QHostAddress,int)), SLOT(it_datagramsWritten(int,int,QHostAddress,int))); + connect(cc.iceTransport, SIGNAL(datagramsWritten(int, int, QHostAddress, int)), + SLOT(it_datagramsWritten(int, int, QHostAddress, int))); iceTransports += cc.iceTransport; } - if(state == Started && useTrickle) - { + if (state == Started && useTrickle) { QList list; Ice176::Candidate c; - c.component = cc.info.componentId; + c.component = cc.info.componentId; c.foundation = cc.info.foundation; c.generation = 0; // TODO - c.id = cc.info.id; - c.ip = cc.info.addr.addr; + c.id = cc.info.id; + c.ip = cc.info.addr.addr; c.ip.setScopeId(QString()); - c.network = cc.info.network; - c.port = cc.info.addr.port; + c.network = cc.info.network; + c.port = cc.info.addr.port; c.priority = cc.info.priority; c.protocol = "udp"; - if(cc.info.type != IceComponent::HostType) - { + if (cc.info.type != IceComponent::HostType) { c.rel_addr = cc.info.base.addr; c.rel_addr.setScopeId(QString()); c.rel_port = cc.info.base.port; - } - else - { + } else { c.rel_addr = QHostAddress(); c.rel_port = -1; } c.rem_addr = QHostAddress(); c.rem_port = -1; - c.type = candidateType_to_string(cc.info.type); + c.type = candidateType_to_string(cc.info.type); list += c; emit q->localCandidatesReady(list); @@ -750,13 +690,12 @@ private slots: void ic_candidateRemoved(const XMPP::IceComponent::Candidate &cc) { // TODO - printf("C%d: candidate removed: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), cc.info.addr.port); + printf("C%d: candidate removed: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), + cc.info.addr.port); QStringList idList; - for(int n = 0; n < localCandidates.count(); ++n) - { - if(localCandidates[n].id == cc.id && localCandidates[n].info.componentId == cc.info.componentId) - { + for (int n = 0; n < localCandidates.count(); ++n) { + if (localCandidates[n].id == cc.id && localCandidates[n].info.componentId == cc.info.componentId) { // FIXME: this is rather ridiculous I think idList += localCandidates[n].info.id; @@ -766,31 +705,25 @@ private slots: } bool iceTransportInUse = false; - foreach(const IceComponent::Candidate &lc, localCandidates) - { - if(lc.iceTransport == cc.iceTransport) - { + foreach (const IceComponent::Candidate &lc, localCandidates) { + if (lc.iceTransport == cc.iceTransport) { iceTransportInUse = true; break; } } - if(!iceTransportInUse) - { + if (!iceTransportInUse) { cc.iceTransport->disconnect(this); iceTransports.remove(cc.iceTransport); } - for(int n = 0; n < checkList.pairs.count(); ++n) - { - if(idList.contains(checkList.pairs[n].local.id)) - { - StunBinding *binding = checkList.pairs[n].binding; - StunTransactionPool *pool = checkList.pairs[n].pool; + for (int n = 0; n < checkList.pairs.count(); ++n) { + if (idList.contains(checkList.pairs[n].local.id)) { + StunBinding * binding = checkList.pairs[n].binding; + StunTransactionPool *pool = checkList.pairs[n].pool; delete binding; - if(pool) - { + if (pool) { pool->disconnect(this); pool->setParent(nullptr); pool->deleteLater(); @@ -805,29 +738,25 @@ private slots: void ic_localFinished() { IceComponent *ic = static_cast(sender()); - int at = findComponent(ic); + int at = findComponent(ic); Q_ASSERT(at != -1); components[at].localFinished = true; bool allFinished = true; - foreach(const Component &c, components) - { - if(!c.localFinished) - { + foreach (const Component &c, components) { + if (!c.localFinished) { allFinished = false; break; } } - if(allFinished) - { + if (allFinished) { state = Started; emit q->started(); - if(!useTrickle) - { + if (!useTrickle) { // FIXME: there should be a way to not wait if // we know for sure there is nothing else // possibly coming @@ -840,36 +769,32 @@ private slots: // FIXME: DOR-SS QList list; - foreach(const IceComponent::Candidate &cc, localCandidates) - { + foreach (const IceComponent::Candidate &cc, localCandidates) { Ice176::Candidate c; - c.component = cc.info.componentId; + c.component = cc.info.componentId; c.foundation = cc.info.foundation; c.generation = 0; // TODO - c.id = cc.info.id; - c.ip = cc.info.addr.addr; + c.id = cc.info.id; + c.ip = cc.info.addr.addr; c.ip.setScopeId(QString()); - c.network = cc.info.network; - c.port = cc.info.addr.port; + c.network = cc.info.network; + c.port = cc.info.addr.port; c.priority = cc.info.priority; c.protocol = "udp"; - if(cc.info.type != IceComponent::HostType) - { + if (cc.info.type != IceComponent::HostType) { c.rel_addr = cc.info.base.addr; c.rel_addr.setScopeId(QString()); c.rel_port = cc.info.base.port; - } - else - { + } else { c.rel_addr = QHostAddress(); c.rel_port = -1; } c.rem_addr = QHostAddress(); c.rem_port = -1; - c.type = candidateType_to_string(cc.info.type); + c.type = candidateType_to_string(cc.info.type); list += c; } - if(!list.isEmpty()) + if (!list.isEmpty()) emit q->localCandidatesReady(list); } } @@ -877,29 +802,27 @@ private slots: void ic_stopped() { IceComponent *ic = static_cast(sender()); - int at = findComponent(ic); + int at = findComponent(ic); Q_ASSERT(at != -1); components[at].stopped = true; bool allStopped = true; - foreach(const Component &c, components) - { - if(!c.stopped) - { + foreach (const Component &c, components) { + if (!c.stopped) { allStopped = false; break; } } - if(allStopped) + if (allStopped) postStop(); } void ic_debugLine(const QString &line) { IceComponent *ic = static_cast(sender()); - int at = findComponent(ic); + int at = findComponent(ic); Q_ASSERT(at != -1); // FIXME: components are always sorted? @@ -913,74 +836,69 @@ private slots: collectTimer = nullptr; QList list; - foreach(const IceComponent::Candidate &cc, localCandidates) - { + foreach (const IceComponent::Candidate &cc, localCandidates) { Ice176::Candidate c; - c.component = cc.info.componentId; + c.component = cc.info.componentId; c.foundation = cc.info.foundation; c.generation = 0; // TODO - c.id = cc.info.id; - c.ip = cc.info.addr.addr; + c.id = cc.info.id; + c.ip = cc.info.addr.addr; c.ip.setScopeId(QString()); - c.network = cc.info.network; - c.port = cc.info.addr.port; + c.network = cc.info.network; + c.port = cc.info.addr.port; c.priority = cc.info.priority; c.protocol = "udp"; - if(cc.info.type != IceComponent::HostType) - { + if (cc.info.type != IceComponent::HostType) { c.rel_addr = cc.info.base.addr; c.rel_addr.setScopeId(QString()); c.rel_port = cc.info.base.port; - } - else - { + } else { c.rel_addr = QHostAddress(); c.rel_port = -1; } c.rem_addr = QHostAddress(); c.rem_port = -1; - c.type = candidateType_to_string(cc.info.type); + c.type = candidateType_to_string(cc.info.type); list += c; } - if(!list.isEmpty()) + if (!list.isEmpty()) emit q->localCandidatesReady(list); } void it_readyRead(int path) { IceTransport *it = static_cast(sender()); - int at = findLocalCandidate(it, path); + int at = findLocalCandidate(it, path); Q_ASSERT(at != -1); IceComponent::Candidate &cc = localCandidates[at]; IceTransport *sock = it; - while(sock->hasPendingDatagrams(path)) - { + while (sock->hasPendingDatagrams(path)) { QHostAddress fromAddr; - int fromPort; - QByteArray buf = sock->readDatagram(path, &fromAddr, &fromPort); + int fromPort; + QByteArray buf = sock->readDatagram(path, &fromAddr, &fromPort); - //printf("port %d: received packet (%d bytes)\n", lt->sock->localPort(), buf.size()); + // printf("port %d: received packet (%d bytes)\n", lt->sock->localPort(), buf.size()); - QString requser = localUser + ':' + peerUser; - QByteArray reqkey = localPass.toUtf8(); + QString requser = localUser + ':' + peerUser; + QByteArray reqkey = localPass.toUtf8(); StunMessage::ConvertResult result; - StunMessage msg = StunMessage::fromBinary(buf, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, reqkey); - if(!msg.isNull() && (msg.mclass() == StunMessage::Request || msg.mclass() == StunMessage::Indication)) - { - printf("received validated request or indication from %s:%d\n", qPrintable(fromAddr.toString()), fromPort); + StunMessage msg = StunMessage::fromBinary(buf, &result, + StunMessage::MessageIntegrity | StunMessage::Fingerprint, reqkey); + if (!msg.isNull() && (msg.mclass() == StunMessage::Request || msg.mclass() == StunMessage::Indication)) { + printf("received validated request or indication from %s:%d\n", qPrintable(fromAddr.toString()), + fromPort); QString user = QString::fromUtf8(msg.attribute(0x0006)); // USERNAME - if(requser != user) - { - printf("user [%s] is wrong. it should be [%s]. skipping\n", qPrintable(user), qPrintable(requser)); + if (requser != user) { + printf("user [%s] is wrong. it should be [%s]. skipping\n", qPrintable(user), + qPrintable(requser)); continue; } - if(msg.method() != 0x001) - { + if (msg.method() != 0x001) { printf("not a binding request. skipping\n"); continue; } @@ -990,14 +908,14 @@ private slots: response.setMethod(0x001); response.setId(msg.id()); - quint16 port16 = fromPort; - quint32 addr4 = fromAddr.toIPv4Address(); - QByteArray val(8, 0); - quint8 *p = (quint8 *)val.data(); + quint16 port16 = fromPort; + quint32 addr4 = fromAddr.toIPv4Address(); + QByteArray val(8, 0); + quint8 * p = (quint8 *)val.data(); const quint8 *magic = response.magic(); - p[0] = 0; - p[1] = 0x01; - p[2] = (port16 >> 8) & 0xff; + p[0] = 0; + p[1] = 0x01; + p[2] = (port16 >> 8) & 0xff; p[2] ^= magic[0]; p[3] = port16 & 0xff; p[3] ^= magic[1]; @@ -1011,8 +929,8 @@ private slots: p[7] ^= magic[3]; QList list; - StunMessage::Attribute attr; - attr.type = 0x0020; + StunMessage::Attribute attr; + attr.type = 0x0020; attr.value = val; list += attr; @@ -1020,52 +938,44 @@ private slots: QByteArray packet = response.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, reqkey); sock->writeDatagram(path, packet, fromAddr, fromPort); - } - else - { - QByteArray reskey = peerPass.toUtf8(); - StunMessage msg = StunMessage::fromBinary(buf, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, reskey); - if(!msg.isNull() && (msg.mclass() == StunMessage::SuccessResponse || msg.mclass() == StunMessage::ErrorResponse)) - { + } else { + QByteArray reskey = peerPass.toUtf8(); + StunMessage msg = StunMessage::fromBinary( + buf, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, reskey); + if (!msg.isNull() + && (msg.mclass() == StunMessage::SuccessResponse || msg.mclass() == StunMessage::ErrorResponse)) { printf("received validated response\n"); // FIXME: this is so gross and completely defeats the point of having pools - for(int n = 0; n < checkList.pairs.count(); ++n) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { CandidatePair &pair = checkList.pairs[n]; - if(pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port) + if (pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port) pair.pool->writeIncomingMessage(msg); } - } - else - { - //printf("received some non-stun or invalid stun packet\n"); + } else { + // printf("received some non-stun or invalid stun packet\n"); // FIXME: i don't know if this is good enough - if(StunMessage::isProbablyStun(buf)) - { + if (StunMessage::isProbablyStun(buf)) { printf("unexpected stun packet (loopback?), skipping.\n"); continue; } int at = -1; - for(int n = 0; n < checkList.pairs.count(); ++n) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { CandidatePair &pair = checkList.pairs[n]; - if(pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port) - { + if (pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port) { at = n; break; } } - if(at == -1) - { + if (at == -1) { printf("the local transport does not seem to be associated with a candidate?!\n"); continue; } int componentIndex = checkList.pairs[at].local.componentId - 1; - //printf("packet is considered to be application data for component index %d\n", componentIndex); + // printf("packet is considered to be application data for component index %d\n", componentIndex); // FIXME: this assumes components are ordered by id in our local arrays in[componentIndex] += buf; @@ -1090,46 +1000,43 @@ private slots: Q_UNUSED(port); StunTransactionPool *pool = static_cast(sender()); - int at = -1; - for(int n = 0; n < checkList.pairs.count(); ++n) - { - if(checkList.pairs[n].pool == pool) - { + int at = -1; + for (int n = 0; n < checkList.pairs.count(); ++n) { + if (checkList.pairs[n].pool == pool) { at = n; break; } } - if(at == -1) // FIXME: assert? + if (at == -1) // FIXME: assert? return; CandidatePair &pair = checkList.pairs[at]; at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port); - if(at == -1) // FIXME: assert? + if (at == -1) // FIXME: assert? return; IceComponent::Candidate &lc = localCandidates[at]; IceTransport *sock = lc.iceTransport; - int path = lc.path; + int path = lc.path; - printf("connectivity check from %s:%d to %s:%d\n", qPrintable(pair.local.addr.addr.toString()), pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); + printf("connectivity check from %s:%d to %s:%d\n", qPrintable(pair.local.addr.addr.toString()), + pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); sock->writeDatagram(path, packet, pair.remote.addr.addr, pair.remote.addr.port); } void binding_success() { StunBinding *binding = static_cast(sender()); - int at = -1; - for(int n = 0; n < checkList.pairs.count(); ++n) - { - if(checkList.pairs[n].binding == binding) - { + int at = -1; + for (int n = 0; n < checkList.pairs.count(); ++n) { + if (checkList.pairs[n].binding == binding) { at = n; break; } } - if(at == -1) + if (at == -1) return; printf("check success\n"); @@ -1145,10 +1052,8 @@ private slots: // check if there's a candidate already valid at = -1; - for(int n = 0; n < checkList.pairs.count(); ++n) - { - if(checkList.pairs[n].local.componentId == pair.local.componentId && checkList.pairs[n].isValid) - { + for (int n = 0; n < checkList.pairs.count(); ++n) { + if (checkList.pairs[n].local.componentId == pair.local.componentId && checkList.pairs[n].isValid) { at = n; break; } @@ -1156,48 +1061,32 @@ private slots: pair.isValid = true; - if(at == -1) - { - int at = findComponent(pair.local.componentId); - Component &c = components[at]; - if(c.lowOverhead) - { + if (at == -1) { + int at = findComponent(pair.local.componentId); + Component &c = components[at]; + if (c.lowOverhead) { printf("component is flagged for low overhead. setting up for %s;%d -> %s;%d\n", - qPrintable(pair.local.addr.addr.toString()), pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); - at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port); + qPrintable(pair.local.addr.addr.toString()), pair.local.addr.port, + qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port); + at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port); IceComponent::Candidate &cc = localCandidates[at]; c.ic->flagPathAsLowOverhead(cc.id, pair.remote.addr.addr, pair.remote.addr.port); } emit q->componentReady(pair.local.componentId - 1); - } - else - { + } else { printf("component %d already active, not signalling\n", pair.local.componentId); } } }; -Ice176::Ice176(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} +Ice176::Ice176(QObject *parent) : QObject(parent) { d = new Private(this); } -Ice176::~Ice176() -{ - delete d; -} +Ice176::~Ice176() { delete d; } -void Ice176::reset() -{ - d->reset(); -} +void Ice176::reset() { d->reset(); } -void Ice176::setProxy(const TurnClient::Proxy &proxy) -{ - d->proxy = proxy; -} +void Ice176::setProxy(const TurnClient::Proxy &proxy) { d->proxy = proxy; } void Ice176::setPortReserver(UdpPortReserver *portReserver) { @@ -1206,15 +1095,9 @@ void Ice176::setPortReserver(UdpPortReserver *portReserver) d->portReserver = portReserver; } -void Ice176::setLocalAddresses(const QList &addrs) -{ - d->updateLocalAddresses(addrs); -} +void Ice176::setLocalAddresses(const QList &addrs) { d->updateLocalAddresses(addrs); } -void Ice176::setExternalAddresses(const QList &addrs) -{ - d->updateExternalAddresses(addrs); -} +void Ice176::setExternalAddresses(const QList &addrs) { d->updateExternalAddresses(addrs); } void Ice176::setStunBindService(const QHostAddress &addr, int port) { @@ -1222,7 +1105,8 @@ void Ice176::setStunBindService(const QHostAddress &addr, int port) d->stunBindPort = port; } -void Ice176::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass) +void Ice176::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, + const QCA::SecureArray &pass) { d->stunRelayUdpAddr = addr; d->stunRelayUdpPort = port; @@ -1230,7 +1114,8 @@ void Ice176::setStunRelayUdpService(const QHostAddress &addr, int port, const QS d->stunRelayUdpPass = pass; } -void Ice176::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass) +void Ice176::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, + const QCA::SecureArray &pass) { d->stunRelayTcpAddr = addr; d->stunRelayTcpPort = port; @@ -1238,25 +1123,13 @@ void Ice176::setStunRelayTcpService(const QHostAddress &addr, int port, const QS d->stunRelayTcpPass = pass; } -void Ice176::setUseLocal(bool enabled) -{ - d->useLocal = enabled; -} +void Ice176::setUseLocal(bool enabled) { d->useLocal = enabled; } -void Ice176::setUseStunBind(bool enabled) -{ - d->useStunBind = enabled; -} +void Ice176::setUseStunBind(bool enabled) { d->useStunBind = enabled; } -void Ice176::setUseStunRelayUdp(bool enabled) -{ - d->useStunRelayUdp = enabled; -} +void Ice176::setUseStunRelayUdp(bool enabled) { d->useStunRelayUdp = enabled; } -void Ice176::setUseStunRelayTcp(bool enabled) -{ - d->useStunRelayTcp = enabled; -} +void Ice176::setUseStunRelayTcp(bool enabled) { d->useStunRelayTcp = enabled; } void Ice176::setComponentCount(int count) { @@ -1265,10 +1138,7 @@ void Ice176::setComponentCount(int count) d->componentCount = count; } -void Ice176::setLocalCandidateTrickle(bool enabled) -{ - d->useTrickle = enabled; -} +void Ice176::setLocalCandidateTrickle(bool enabled) { d->useTrickle = enabled; } void Ice176::start(Mode mode) { @@ -1276,64 +1146,34 @@ void Ice176::start(Mode mode) d->start(); } -void Ice176::stop() -{ - d->stop(); -} +void Ice176::stop() { d->stop(); } -QString Ice176::localUfrag() const -{ - return d->localUser; -} +QString Ice176::localUfrag() const { return d->localUser; } -QString Ice176::localPassword() const -{ - return d->localPass; -} +QString Ice176::localPassword() const { return d->localPass; } -void Ice176::setPeerUfrag(const QString &ufrag) -{ - d->peerUser = ufrag; -} +void Ice176::setPeerUfrag(const QString &ufrag) { d->peerUser = ufrag; } -void Ice176::setPeerPassword(const QString &pass) -{ - d->peerPass = pass; -} +void Ice176::setPeerPassword(const QString &pass) { d->peerPass = pass; } -void Ice176::addRemoteCandidates(const QList &list) -{ - d->addRemoteCandidates(list); -} +void Ice176::addRemoteCandidates(const QList &list) { d->addRemoteCandidates(list); } -bool Ice176::hasPendingDatagrams(int componentIndex) const -{ - return !d->in[componentIndex].isEmpty(); -} +bool Ice176::hasPendingDatagrams(int componentIndex) const { return !d->in[componentIndex].isEmpty(); } -QByteArray Ice176::readDatagram(int componentIndex) -{ - return d->in[componentIndex].takeFirst(); -} +QByteArray Ice176::readDatagram(int componentIndex) { return d->in[componentIndex].takeFirst(); } -void Ice176::writeDatagram(int componentIndex, const QByteArray &datagram) -{ - d->write(componentIndex, datagram); -} +void Ice176::writeDatagram(int componentIndex, const QByteArray &datagram) { d->write(componentIndex, datagram); } -void Ice176::flagComponentAsLowOverhead(int componentIndex) -{ - d->flagComponentAsLowOverhead(componentIndex); -} +void Ice176::flagComponentAsLowOverhead(int componentIndex) { d->flagComponentAsLowOverhead(componentIndex); } bool Ice176::isIPv6LinkLocalAddress(const QHostAddress &addr) { Q_ASSERT(addr.protocol() == QAbstractSocket::IPv6Protocol); Q_IPV6ADDR addr6 = addr.toIPv6Address(); - quint16 hi = addr6[0]; + quint16 hi = addr6[0]; hi <<= 8; hi += addr6[1]; - if((hi & 0xffc0) == 0xfe80) + if ((hi & 0xffc0) == 0xfe80) return true; else return false; diff --git a/src/irisnet/noncore/ice176.h b/src/irisnet/noncore/ice176.h index 4a9c5ef7..690b7efe 100644 --- a/src/irisnet/noncore/ice176.h +++ b/src/irisnet/noncore/ice176.h @@ -26,83 +26,56 @@ #include namespace QCA { - class SecureArray; +class SecureArray; } namespace XMPP { class UdpPortReserver; -class Ice176 : public QObject -{ +class Ice176 : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric - }; + enum Error { ErrorGeneric }; - enum Mode - { - Initiator, - Responder - }; + enum Mode { Initiator, Responder }; - class LocalAddress - { + class LocalAddress { public: QHostAddress addr; - int network; // -1 = unknown - bool isVpn; - - LocalAddress() : - network(-1), - isVpn(false) - { - } + int network; // -1 = unknown + bool isVpn; + + LocalAddress() : network(-1), isVpn(false) {} }; - class ExternalAddress - { + class ExternalAddress { public: LocalAddress base; QHostAddress addr; - int portBase; // -1 = same as base + int portBase; // -1 = same as base - ExternalAddress() : - portBase(-1) - { - } + ExternalAddress() : portBase(-1) {} }; - class Candidate - { + class Candidate { public: - int component; - QString foundation; - int generation; - QString id; + int component; + QString foundation; + int generation; + QString id; QHostAddress ip; - int network; // -1 = unknown - int port; - int priority; - QString protocol; + int network; // -1 = unknown + int port; + int priority; + QString protocol; QHostAddress rel_addr; - int rel_port; + int rel_port; QHostAddress rem_addr; - int rem_port; - QString type; - - Candidate() : - component(-1), - generation(-1), - network(-1), - port(-1), - priority(-1), - rel_port(-1), - rem_port(-1) - { - } + int rem_port; + QString type; + + Candidate() : component(-1), generation(-1), network(-1), port(-1), priority(-1), rel_port(-1), rem_port(-1) {} }; Ice176(QObject *parent = nullptr); @@ -147,9 +120,9 @@ class Ice176 : public QObject void addRemoteCandidates(const QList &list); - bool hasPendingDatagrams(int componentIndex) const; + bool hasPendingDatagrams(int componentIndex) const; QByteArray readDatagram(int componentIndex); - void writeDatagram(int componentIndex, const QByteArray &datagram); + void writeDatagram(int componentIndex, const QByteArray &datagram); // this call will ensure that TURN headers are minimized on this // component, with the drawback that packets might not be able to diff --git a/src/irisnet/noncore/icecomponent.cpp b/src/irisnet/noncore/icecomponent.cpp index b8aa609b..45282dba 100644 --- a/src/irisnet/noncore/icecomponent.cpp +++ b/src/irisnet/noncore/icecomponent.cpp @@ -40,118 +40,96 @@ static int calc_priority(int typePref, int localPref, int componentId) return priority; } -class IceComponent::Private : public QObject -{ +class IceComponent::Private : public QObject { Q_OBJECT public: - class Config - { + class Config { public: - QList localAddrs; + QList localAddrs; QList extAddrs; QHostAddress stunBindAddr; - int stunBindPort; + int stunBindPort; - QHostAddress stunRelayUdpAddr; - int stunRelayUdpPort; - QString stunRelayUdpUser; + QHostAddress stunRelayUdpAddr; + int stunRelayUdpPort; + QString stunRelayUdpUser; QCA::SecureArray stunRelayUdpPass; - QHostAddress stunRelayTcpAddr; - int stunRelayTcpPort; - QString stunRelayTcpUser; + QHostAddress stunRelayTcpAddr; + int stunRelayTcpPort; + QString stunRelayTcpUser; QCA::SecureArray stunRelayTcpPass; }; - class LocalTransport - { + class LocalTransport { public: - QUdpSocket *qsock; - bool borrowedSocket; - QHostAddress addr; + QUdpSocket * qsock; + bool borrowedSocket; + QHostAddress addr; IceLocalTransport *sock; - int network; - bool isVpn; - bool started; - bool stun_started; - bool stun_finished, turn_finished; - QHostAddress extAddr; - bool ext_finished; + int network; + bool isVpn; + bool started; + bool stun_started; + bool stun_finished, turn_finished; + QHostAddress extAddr; + bool ext_finished; LocalTransport() : - qsock(nullptr), - borrowedSocket(false), - sock(nullptr), - network(-1), - isVpn(false), - started(false), - stun_started(false), - stun_finished(false), - turn_finished(false), - ext_finished(false) + qsock(nullptr), borrowedSocket(false), sock(nullptr), network(-1), isVpn(false), started(false), + stun_started(false), stun_finished(false), turn_finished(false), ext_finished(false) { } }; - IceComponent *q; - ObjectSession sess; - int id; - QString clientSoftware; - TurnClient::Proxy proxy; - UdpPortReserver *portReserver; - Config pending; - Config config; - bool stopping; - QList localLeap; - QList localStun; - IceTurnTransport *tt; - QList localCandidates; - QHash > channelPeers; - bool useLocal; - bool useStunBind; - bool useStunRelayUdp; - bool useStunRelayTcp; - bool local_finished; - int debugLevel; + IceComponent * q; + ObjectSession sess; + int id; + QString clientSoftware; + TurnClient::Proxy proxy; + UdpPortReserver * portReserver; + Config pending; + Config config; + bool stopping; + QList localLeap; + QList localStun; + IceTurnTransport * tt; + QList localCandidates; + QHash> channelPeers; + bool useLocal; + bool useStunBind; + bool useStunRelayUdp; + bool useStunRelayTcp; + bool local_finished; + int debugLevel; Private(IceComponent *_q) : - QObject(_q), - q(_q), - sess(this), - portReserver(nullptr), - stopping(false), - tt(nullptr), - useLocal(true), - useStunBind(true), - useStunRelayUdp(true), - useStunRelayTcp(true), - local_finished(false), - debugLevel(DL_None) + QObject(_q), q(_q), sess(this), portReserver(nullptr), stopping(false), tt(nullptr), useLocal(true), + useStunBind(true), useStunRelayUdp(true), useStunRelayTcp(true), local_finished(false), debugLevel(DL_None) { } ~Private() { - QList socketsToReturn; + QList socketsToReturn; - for(int n = 0; n < localLeap.count(); ++n) - { + for (int n = 0; n < localLeap.count(); ++n) { delete localLeap[n]->sock; - if(localLeap[n]->borrowedSocket) + if (localLeap[n]->borrowedSocket) socketsToReturn += localLeap[n]->qsock; else localLeap[n]->qsock->deleteLater(); } - if(!socketsToReturn.isEmpty()) + if (!socketsToReturn.isEmpty()) portReserver->returnSockets(socketsToReturn); qDeleteAll(localLeap); - for(int n = 0; n < localStun.count(); ++n) + for (int n = 0; n < localStun.count(); ++n) delete localStun[n]->sock; qDeleteAll(localStun); @@ -159,21 +137,18 @@ class IceComponent::Private : public QObject delete tt; } - void update(QList *socketList) + void update(QList *socketList) { Q_ASSERT(!stopping); // for now, only allow setting localAddrs once - if(!pending.localAddrs.isEmpty() && config.localAddrs.isEmpty()) - { - foreach(const Ice176::LocalAddress &la, pending.localAddrs) - { + if (!pending.localAddrs.isEmpty() && config.localAddrs.isEmpty()) { + foreach (const Ice176::LocalAddress &la, pending.localAddrs) { // skip duplicate addrs - if(findLocalAddr(la.addr) != -1) + if (findLocalAddr(la.addr) != -1) continue; - if(!useLocal) - { + if (!useLocal) { // skip out, but log the address in // case we need it for stun config.localAddrs += la; @@ -181,20 +156,16 @@ class IceComponent::Private : public QObject } QUdpSocket *qsock = nullptr; - if(socketList) + if (socketList) qsock = takeFromSocketList(socketList, la.addr, this); bool borrowedSocket; - if(qsock) - { + if (qsock) { borrowedSocket = true; - } - else - { + } else { // otherwise, bind to random qsock = new QUdpSocket(this); - if(!qsock->bind(la.addr, 0)) - { + if (!qsock->bind(la.addr, 0)) { delete qsock; emit q->debugLine("Warning: unable to bind to random port."); continue; @@ -208,13 +179,13 @@ class IceComponent::Private : public QObject config.localAddrs += la; LocalTransport *lt = new LocalTransport; - lt->addr = la.addr; - lt->qsock = qsock; + lt->addr = la.addr; + lt->qsock = qsock; lt->borrowedSocket = borrowedSocket; - lt->sock = new IceLocalTransport(this); + lt->sock = new IceLocalTransport(this); lt->sock->setDebugLevel((IceTransport::DebugLevel)debugLevel); lt->network = la.network; - lt->isVpn = la.isVpn; + lt->isVpn = la.isVpn; connect(lt->sock, SIGNAL(started()), SLOT(lt_started())); connect(lt->sock, SIGNAL(stopped()), SLOT(lt_stopped())); connect(lt->sock, SIGNAL(addressesChanged()), SLOT(lt_addressesChanged())); @@ -223,54 +194,50 @@ class IceComponent::Private : public QObject localLeap += lt; lt->sock->start(qsock); - emit q->debugLine(QString("starting transport ") + la.addr.toString() + ';' + QString::number(port) + " for component " + QString::number(id)); + emit q->debugLine(QString("starting transport ") + la.addr.toString() + ';' + QString::number(port) + + " for component " + QString::number(id)); } } // extAddrs created on demand if present, but only once - if(!pending.extAddrs.isEmpty() && config.extAddrs.isEmpty()) - { + if (!pending.extAddrs.isEmpty() && config.extAddrs.isEmpty()) { config.extAddrs = pending.extAddrs; bool need_doExt = false; - foreach(LocalTransport *lt, localLeap) - { + foreach (LocalTransport *lt, localLeap) { // already assigned an ext address? skip - if(!lt->extAddr.isNull()) + if (!lt->extAddr.isNull()) continue; QHostAddress laddr = lt->sock->localAddress(); - int lport = lt->sock->localPort(); + int lport = lt->sock->localPort(); int at = -1; - for(int n = 0; n < config.extAddrs.count(); ++n) - { + for (int n = 0; n < config.extAddrs.count(); ++n) { const Ice176::ExternalAddress &ea = config.extAddrs[n]; - if(laddr.protocol() != QAbstractSocket::IPv6Protocol && ea.base.addr == laddr && (ea.portBase == -1 || ea.portBase == lport)) - { + if (laddr.protocol() != QAbstractSocket::IPv6Protocol && ea.base.addr == laddr + && (ea.portBase == -1 || ea.portBase == lport)) { at = n; break; } } - if(at != -1) - { + if (at != -1) { lt->extAddr = config.extAddrs[at].addr; - if(lt->started) + if (lt->started) need_doExt = true; } } - if(need_doExt) + if (need_doExt) sess.defer(this, "doExt"); } // only allow setting stun stuff once - if(!pending.stunBindAddr.isNull() && config.stunBindAddr.isNull()) - { - config.stunBindAddr = pending.stunBindAddr; - config.stunBindPort = pending.stunBindPort; + if (!pending.stunBindAddr.isNull() && config.stunBindAddr.isNull()) { + config.stunBindAddr = pending.stunBindAddr; + config.stunBindPort = pending.stunBindPort; config.stunRelayUdpAddr = pending.stunRelayUdpAddr; config.stunRelayUdpPort = pending.stunRelayUdpPort; config.stunRelayUdpUser = pending.stunRelayUdpUser; @@ -283,20 +250,20 @@ class IceComponent::Private : public QObject // localStun sockets created on demand if stun settings are // present, but only once (cannot be changed, for now) - if(((useStunBind && !config.stunBindAddr.isNull()) || (useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty())) && !config.localAddrs.isEmpty() && localStun.isEmpty()) - { - foreach(const Ice176::LocalAddress &la, config.localAddrs) - { + if (((useStunBind && !config.stunBindAddr.isNull()) + || (useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty())) + && !config.localAddrs.isEmpty() && localStun.isEmpty()) { + foreach (const Ice176::LocalAddress &la, config.localAddrs) { // don't setup stun ports for ipv6 - if(la.addr.protocol() == QAbstractSocket::IPv6Protocol) + if (la.addr.protocol() == QAbstractSocket::IPv6Protocol) continue; LocalTransport *lt = new LocalTransport; - lt->addr = la.addr; - lt->sock = new IceLocalTransport(this); + lt->addr = la.addr; + lt->sock = new IceLocalTransport(this); lt->sock->setDebugLevel((IceTransport::DebugLevel)debugLevel); lt->network = la.network; - lt->isVpn = la.isVpn; + lt->isVpn = la.isVpn; connect(lt->sock, SIGNAL(started()), SLOT(lt_started())); connect(lt->sock, SIGNAL(stopped()), SLOT(lt_stopped())); connect(lt->sock, SIGNAL(addressesChanged()), SLOT(lt_addressesChanged())); @@ -306,21 +273,19 @@ class IceComponent::Private : public QObject lt->sock->setClientSoftwareNameAndVersion(clientSoftware); lt->sock->start(la.addr); - emit q->debugLine(QString("starting transport ") + la.addr.toString() + ";(dyn)" + " for component " + QString::number(id)); + emit q->debugLine(QString("starting transport ") + la.addr.toString() + ";(dyn)" + " for component " + + QString::number(id)); } } - if((!config.stunBindAddr.isNull() || !config.stunRelayUdpAddr.isNull()) && !localStun.isEmpty()) - { - for(int n = 0; n < localStun.count(); ++n) - { - if(localStun[n]->started && !localStun[n]->stun_started) + if ((!config.stunBindAddr.isNull() || !config.stunRelayUdpAddr.isNull()) && !localStun.isEmpty()) { + for (int n = 0; n < localStun.count(); ++n) { + if (localStun[n]->started && !localStun[n]->stun_started) tryStun(n); } } - if(useStunRelayTcp && !config.stunRelayTcpAddr.isNull() && !config.stunRelayTcpUser.isEmpty() && !tt) - { + if (useStunRelayTcp && !config.stunRelayTcpAddr.isNull() && !config.stunRelayTcpUser.isEmpty() && !tt) { tt = new IceTurnTransport(this); tt->setDebugLevel((IceTransport::DebugLevel)debugLevel); connect(tt, SIGNAL(started()), SLOT(tt_started())); @@ -333,11 +298,11 @@ class IceComponent::Private : public QObject tt->setPassword(config.stunRelayTcpPass); tt->start(config.stunRelayTcpAddr, config.stunRelayTcpPort); - emit q->debugLine(QString("starting TURN transport with server ") + config.stunRelayTcpAddr.toString() + ';' + QString::number(config.stunRelayTcpPort) + " for component " + QString::number(id)); + emit q->debugLine(QString("starting TURN transport with server ") + config.stunRelayTcpAddr.toString() + ';' + + QString::number(config.stunRelayTcpPort) + " for component " + QString::number(id)); } - if(localLeap.isEmpty() && localStun.isEmpty() && !local_finished) - { + if (localLeap.isEmpty() && localStun.isEmpty() && !local_finished) { local_finished = true; sess.defer(q, "localFinished"); } @@ -350,38 +315,33 @@ class IceComponent::Private : public QObject stopping = true; // nothing to stop? - if(allStopped()) - { + if (allStopped()) { sess.defer(this, "postStop"); return; } - foreach(LocalTransport *lt, localLeap) + foreach (LocalTransport *lt, localLeap) lt->sock->stop(); - foreach(LocalTransport *lt, localStun) + foreach (LocalTransport *lt, localStun) lt->sock->stop(); - if(tt) + if (tt) tt->stop(); } int peerReflexivePriority(const IceTransport *iceTransport, int path) const { - int addrAt = -1; - const IceLocalTransport *lt = qobject_cast(iceTransport); - if(lt) - { + int addrAt = -1; + const IceLocalTransport *lt = qobject_cast(iceTransport); + if (lt) { bool isLocalLeap = false; - addrAt = findLocalTransport(lt, &isLocalLeap); - if(addrAt != -1 && path == 1) - { + addrAt = findLocalTransport(lt, &isLocalLeap); + if (addrAt != -1 && path == 1) { // lower priority, but not as far as IceTurnTransport addrAt += 512; } - } - else if(qobject_cast(iceTransport) == tt) - { + } else if (qobject_cast(iceTransport) == tt) { // lower priority by making it seem like the last nic addrAt = 1024; } @@ -394,10 +354,8 @@ class IceComponent::Private : public QObject void flagPathAsLowOverhead(int id, const QHostAddress &addr, int port) { int at = -1; - for(int n = 0; n < localCandidates.count(); ++n) - { - if(localCandidates[n].id == id) - { + for (int n = 0; n < localCandidates.count(); ++n) { + if (localCandidates[n].id == id) { at = n; break; } @@ -410,10 +368,9 @@ class IceComponent::Private : public QObject Candidate &c = localCandidates[at]; - TransportAddress ta(addr, port); + TransportAddress ta(addr, port); QSet &addrs = channelPeers[c.id]; - if(!addrs.contains(ta)) - { + if (!addrs.contains(ta)) { addrs += ta; c.iceTransport->addChannelPeer(ta.addr, ta.port); } @@ -427,16 +384,14 @@ class IceComponent::Private : public QObject static int choose_default_priority(CandidateType type, int localPref, bool isVpn, int componentId) { int typePref; - if(type == HostType) - { - if(isVpn) + if (type == HostType) { + if (isVpn) typePref = 0; else typePref = 126; - } - else if(type == PeerReflexiveType) + } else if (type == PeerReflexiveType) typePref = 110; - else if(type == ServerReflexiveType) + else if (type == ServerReflexiveType) typePref = 100; else // RelayedType typePref = 0; @@ -444,12 +399,11 @@ class IceComponent::Private : public QObject return calc_priority(typePref, localPref, componentId); } - static QUdpSocket *takeFromSocketList(QList *socketList, const QHostAddress &addr, QObject *parent = nullptr) + static QUdpSocket *takeFromSocketList(QList *socketList, const QHostAddress &addr, + QObject *parent = nullptr) { - for(int n = 0; n < socketList->count(); ++n) - { - if((*socketList)[n]->localAddress() == addr) - { + for (int n = 0; n < socketList->count(); ++n) { + if ((*socketList)[n]->localAddress() == addr) { QUdpSocket *sock = socketList->takeAt(n); sock->setParent(parent); return sock; @@ -461,28 +415,24 @@ class IceComponent::Private : public QObject int getId() const { - for(int n = 0;; ++n) - { + for (int n = 0;; ++n) { bool found = false; - foreach(const Candidate &c, localCandidates) - { - if(c.id == n) - { + foreach (const Candidate &c, localCandidates) { + if (c.id == n) { found = true; break; } } - if(!found) + if (!found) return n; } } int findLocalAddr(const QHostAddress &addr) { - for(int n = 0; n < config.localAddrs.count(); ++n) - { - if(config.localAddrs[n].addr == addr) + for (int n = 0; n < config.localAddrs.count(); ++n) { + if (config.localAddrs[n].addr == addr) return n; } @@ -491,19 +441,15 @@ class IceComponent::Private : public QObject int findLocalTransport(const IceLocalTransport *sock, bool *isLocalLeap) const { - for(int n = 0; n < localLeap.count(); ++n) - { - if(localLeap[n]->sock == sock) - { + for (int n = 0; n < localLeap.count(); ++n) { + if (localLeap[n]->sock == sock) { *isLocalLeap = true; return n; } } - for(int n = 0; n < localStun.count(); ++n) - { - if(localStun[n]->sock == sock) - { + for (int n = 0; n < localStun.count(); ++n) { + if (localStun[n]->sock == sock) { *isLocalLeap = false; return n; } @@ -517,19 +463,18 @@ class IceComponent::Private : public QObject LocalTransport *lt = localStun[at]; bool atLeastOne = false; - if(useStunBind && !config.stunBindAddr.isNull()) - { + if (useStunBind && !config.stunBindAddr.isNull()) { atLeastOne = true; lt->sock->setStunBindService(config.stunBindAddr, config.stunBindPort); } - if(useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty()) - { + if (useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty()) { atLeastOne = true; - lt->sock->setStunRelayService(config.stunRelayUdpAddr, config.stunRelayUdpPort, config.stunRelayUdpUser, config.stunRelayUdpPass); + lt->sock->setStunRelayService(config.stunRelayUdpAddr, config.stunRelayUdpPort, config.stunRelayUdpUser, + config.stunRelayUdpPass); } Q_ASSERT(atLeastOne); - if(!atLeastOne) + if (!atLeastOne) abort(); lt->stun_started = true; @@ -538,23 +483,22 @@ class IceComponent::Private : public QObject void ensureExt(LocalTransport *lt, int addrAt) { - if(!lt->extAddr.isNull() && !lt->ext_finished) - { + if (!lt->extAddr.isNull() && !lt->ext_finished) { CandidateInfo ci; - ci.addr.addr = lt->extAddr; - ci.addr.port = lt->sock->localPort(); - ci.type = ServerReflexiveType; + ci.addr.addr = lt->extAddr; + ci.addr.port = lt->sock->localPort(); + ci.type = ServerReflexiveType; ci.componentId = id; - ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); - ci.base.addr = lt->sock->localAddress(); - ci.base.port = lt->sock->localPort(); - ci.network = lt->network; + ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); + ci.base.addr = lt->sock->localAddress(); + ci.base.port = lt->sock->localPort(); + ci.network = lt->network; Candidate c; - c.id = getId(); - c.info = ci; + c.id = getId(); + c.info = ci; c.iceTransport = lt->sock; - c.path = 0; + c.path = 0; localCandidates += c; lt->ext_finished = true; @@ -567,19 +511,17 @@ class IceComponent::Private : public QObject { ObjectSessionWatcher watch(&sess); - for(int n = 0; n < localCandidates.count(); ++n) - { + for (int n = 0; n < localCandidates.count(); ++n) { Candidate &c = localCandidates[n]; - if(c.iceTransport == sock) - { + if (c.iceTransport == sock) { Candidate tmp = localCandidates.takeAt(n); --n; // adjust position channelPeers.remove(tmp.id); emit q->candidateRemoved(tmp); - if(!watch.isValid()) + if (!watch.isValid()) return; } } @@ -587,7 +529,7 @@ class IceComponent::Private : public QObject bool allStopped() const { - if(localLeap.isEmpty() && localStun.isEmpty() && !tt) + if (localLeap.isEmpty() && localStun.isEmpty() && !tt) return true; else return false; @@ -595,27 +537,25 @@ class IceComponent::Private : public QObject void tryStopped() { - if(allStopped()) + if (allStopped()) postStop(); } private slots: void doExt() { - if(stopping) + if (stopping) return; ObjectSessionWatcher watch(&sess); - foreach(LocalTransport *lt, localLeap) - { - if(lt->started) - { + foreach (LocalTransport *lt, localLeap) { + if (lt->started) { int addrAt = findLocalAddr(lt->addr); Q_ASSERT(addrAt != -1); ensureExt(lt, addrAt); - if(!watch.isValid()) + if (!watch.isValid()) return; } } @@ -630,13 +570,13 @@ private slots: void lt_started() { - IceLocalTransport *sock = static_cast(sender()); - bool isLocalLeap = false; - int at = findLocalTransport(sock, &isLocalLeap); + IceLocalTransport *sock = static_cast(sender()); + bool isLocalLeap = false; + int at = findLocalTransport(sock, &isLocalLeap); Q_ASSERT(at != -1); LocalTransport *lt; - if(isLocalLeap) + if (isLocalLeap) lt = localLeap[at]; else lt = localStun[at]; @@ -648,60 +588,53 @@ private slots: ObjectSessionWatcher watch(&sess); - if(useLocal && isLocalLeap) - { + if (useLocal && isLocalLeap) { CandidateInfo ci; - ci.addr.addr = lt->sock->localAddress(); - ci.addr.port = lt->sock->localPort(); - ci.type = HostType; + ci.addr.addr = lt->sock->localAddress(); + ci.addr.port = lt->sock->localPort(); + ci.type = HostType; ci.componentId = id; - ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); - ci.base = ci.addr; - ci.network = lt->network; + ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); + ci.base = ci.addr; + ci.network = lt->network; Candidate c; - c.id = getId(); - c.info = ci; + c.id = getId(); + c.info = ci; c.iceTransport = sock; - c.path = 0; + c.path = 0; localCandidates += c; emit q->candidateAdded(c); - if(!watch.isValid()) + if (!watch.isValid()) return; ensureExt(lt, addrAt); - if(!watch.isValid()) + if (!watch.isValid()) return; } - if(!isLocalLeap && !lt->stun_started) + if (!isLocalLeap && !lt->stun_started) tryStun(at); bool allFinished = true; - foreach(const LocalTransport *lt, localLeap) - { - if(!lt->started) - { + foreach (const LocalTransport *lt, localLeap) { + if (!lt->started) { allFinished = false; break; } } - if(allFinished) - { - foreach(const LocalTransport *lt, localStun) - { - if(!lt->started) - { + if (allFinished) { + foreach (const LocalTransport *lt, localStun) { + if (!lt->started) { allFinished = false; break; } } } - if(allFinished && !local_finished) - { + if (allFinished && !local_finished) { local_finished = true; emit q->localFinished(); } @@ -709,13 +642,13 @@ private slots: void lt_stopped() { - IceLocalTransport *sock = static_cast(sender()); - bool isLocalLeap = false; - int at = findLocalTransport(sock, &isLocalLeap); + IceLocalTransport *sock = static_cast(sender()); + bool isLocalLeap = false; + int at = findLocalTransport(sock, &isLocalLeap); Q_ASSERT(at != -1); LocalTransport *lt; - if(isLocalLeap) + if (isLocalLeap) lt = localLeap[at]; else lt = localStun[at]; @@ -723,24 +656,21 @@ private slots: ObjectSessionWatcher watch(&sess); removeLocalCandidates(lt->sock); - if(!watch.isValid()) + if (!watch.isValid()) return; delete lt->sock; lt->sock = nullptr; - if(isLocalLeap) - { - if(lt->borrowedSocket) - portReserver->returnSockets(QList() << lt->qsock); + if (isLocalLeap) { + if (lt->borrowedSocket) + portReserver->returnSockets(QList() << lt->qsock); else lt->qsock->deleteLater(); delete lt; localLeap.removeAt(at); - } - else - { + } else { delete lt; localStun.removeAt(at); } @@ -750,9 +680,9 @@ private slots: void lt_addressesChanged() { - IceLocalTransport *sock = static_cast(sender()); - bool isLocalLeap = false; - int at = findLocalTransport(sock, &isLocalLeap); + IceLocalTransport *sock = static_cast(sender()); + bool isLocalLeap = false; + int at = findLocalTransport(sock, &isLocalLeap); Q_ASSERT(at != -1); // leap does not use stun, so we should not get this signal @@ -765,68 +695,63 @@ private slots: ObjectSessionWatcher watch(&sess); - if(useStunBind && !lt->sock->serverReflexiveAddress().isNull() && !lt->stun_finished) - { + if (useStunBind && !lt->sock->serverReflexiveAddress().isNull() && !lt->stun_finished) { // automatically assign ext to related leaps, if possible - foreach(LocalTransport *i, localLeap) - { - if(i->extAddr.isNull() && i->sock->localAddress() == lt->sock->localAddress()) - { + foreach (LocalTransport *i, localLeap) { + if (i->extAddr.isNull() && i->sock->localAddress() == lt->sock->localAddress()) { i->extAddr = lt->sock->serverReflexiveAddress(); - if(i->started) - { + if (i->started) { ensureExt(i, addrAt); - if(!watch.isValid()) + if (!watch.isValid()) return; } } } CandidateInfo ci; - ci.addr.addr = lt->sock->serverReflexiveAddress(); - ci.addr.port = lt->sock->serverReflexivePort(); - ci.type = ServerReflexiveType; + ci.addr.addr = lt->sock->serverReflexiveAddress(); + ci.addr.port = lt->sock->serverReflexivePort(); + ci.type = ServerReflexiveType; ci.componentId = id; - ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); + ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); // stun is only used on non-leap sockets, but we don't // announce non-leap local candidates, so make the // base the same as the srflx - //ci.base.addr = lt->sock->localAddress(); - //ci.base.port = lt->sock->localPort(); - ci.base = ci.addr; + // ci.base.addr = lt->sock->localAddress(); + // ci.base.port = lt->sock->localPort(); + ci.base = ci.addr; ci.network = lt->network; Candidate c; - c.id = getId(); - c.info = ci; + c.id = getId(); + c.info = ci; c.iceTransport = sock; - c.path = 0; + c.path = 0; localCandidates += c; lt->stun_finished = true; emit q->candidateAdded(c); - if(!watch.isValid()) + if (!watch.isValid()) return; } - if(!lt->sock->relayedAddress().isNull() && !lt->turn_finished) - { + if (!lt->sock->relayedAddress().isNull() && !lt->turn_finished) { CandidateInfo ci; - ci.addr.addr = lt->sock->relayedAddress(); - ci.addr.port = lt->sock->relayedPort(); - ci.type = RelayedType; + ci.addr.addr = lt->sock->relayedAddress(); + ci.addr.port = lt->sock->relayedPort(); + ci.type = RelayedType; ci.componentId = id; - ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); - ci.base.addr = lt->sock->serverReflexiveAddress(); - ci.base.port = lt->sock->serverReflexivePort(); - ci.network = lt->network; + ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId); + ci.base.addr = lt->sock->serverReflexiveAddress(); + ci.base.port = lt->sock->serverReflexivePort(); + ci.network = lt->network; Candidate c; - c.id = getId(); - c.info = ci; + c.id = getId(); + c.info = ci; c.iceTransport = sock; - c.path = 1; + c.path = 1; localCandidates += c; lt->turn_finished = true; @@ -839,13 +764,13 @@ private slots: { Q_UNUSED(e); - IceLocalTransport *sock = static_cast(sender()); - bool isLocalLeap = false; - int at = findLocalTransport(sock, &isLocalLeap); + IceLocalTransport *sock = static_cast(sender()); + bool isLocalLeap = false; + int at = findLocalTransport(sock, &isLocalLeap); Q_ASSERT(at != -1); LocalTransport *lt; - if(isLocalLeap) + if (isLocalLeap) lt = localLeap[at]; else lt = localStun[at]; @@ -853,33 +778,27 @@ private slots: ObjectSessionWatcher watch(&sess); removeLocalCandidates(lt->sock); - if(!watch.isValid()) + if (!watch.isValid()) return; delete lt->sock; lt->sock = nullptr; - if(isLocalLeap) - { - if(lt->borrowedSocket) - portReserver->returnSockets(QList() << lt->qsock); + if (isLocalLeap) { + if (lt->borrowedSocket) + portReserver->returnSockets(QList() << lt->qsock); else lt->qsock->deleteLater(); delete lt; localLeap.removeAt(at); - } - else - { + } else { delete lt; localStun.removeAt(at); } } - void lt_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void lt_debugLine(const QString &line) { emit q->debugLine(line); } void tt_started() { @@ -887,19 +806,19 @@ private slots: int addrAt = 1024; CandidateInfo ci; - ci.addr.addr = tt->relayedAddress(); - ci.addr.port = tt->relayedPort(); - ci.type = RelayedType; + ci.addr.addr = tt->relayedAddress(); + ci.addr.port = tt->relayedPort(); + ci.type = RelayedType; ci.componentId = id; - ci.priority = choose_default_priority(ci.type, 65535 - addrAt, false, ci.componentId); - ci.base = ci.addr; - ci.network = 0; // not relevant + ci.priority = choose_default_priority(ci.type, 65535 - addrAt, false, ci.componentId); + ci.base = ci.addr; + ci.network = 0; // not relevant Candidate c; - c.id = getId(); - c.info = ci; + c.id = getId(); + c.info = ci; c.iceTransport = tt; - c.path = 0; + c.path = 0; localCandidates += c; @@ -911,7 +830,7 @@ private slots: ObjectSessionWatcher watch(&sess); removeLocalCandidates(tt); - if(!watch.isValid()) + if (!watch.isValid()) return; delete tt; @@ -927,60 +846,35 @@ private slots: ObjectSessionWatcher watch(&sess); removeLocalCandidates(tt); - if(!watch.isValid()) + if (!watch.isValid()) return; delete tt; tt = nullptr; } - void tt_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void tt_debugLine(const QString &line) { emit q->debugLine(line); } }; -IceComponent::IceComponent(int id, QObject *parent) : - QObject(parent) +IceComponent::IceComponent(int id, QObject *parent) : QObject(parent) { - d = new Private(this); + d = new Private(this); d->id = id; } -IceComponent::~IceComponent() -{ - delete d; -} +IceComponent::~IceComponent() { delete d; } -int IceComponent::id() const -{ - return d->id; -} +int IceComponent::id() const { return d->id; } -void IceComponent::setClientSoftwareNameAndVersion(const QString &str) -{ - d->clientSoftware = str; -} +void IceComponent::setClientSoftwareNameAndVersion(const QString &str) { d->clientSoftware = str; } -void IceComponent::setProxy(const TurnClient::Proxy &proxy) -{ - d->proxy = proxy; -} +void IceComponent::setProxy(const TurnClient::Proxy &proxy) { d->proxy = proxy; } -void IceComponent::setPortReserver(UdpPortReserver *portReserver) -{ - d->portReserver = portReserver; -} +void IceComponent::setPortReserver(UdpPortReserver *portReserver) { d->portReserver = portReserver; } -void IceComponent::setLocalAddresses(const QList &addrs) -{ - d->pending.localAddrs = addrs; -} +void IceComponent::setLocalAddresses(const QList &addrs) { d->pending.localAddrs = addrs; } -void IceComponent::setExternalAddresses(const QList &addrs) -{ - d->pending.extAddrs = addrs; -} +void IceComponent::setExternalAddresses(const QList &addrs) { d->pending.extAddrs = addrs; } void IceComponent::setStunBindService(const QHostAddress &addr, int port) { @@ -988,7 +882,8 @@ void IceComponent::setStunBindService(const QHostAddress &addr, int port) d->pending.stunBindPort = port; } -void IceComponent::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass) +void IceComponent::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, + const QCA::SecureArray &pass) { d->pending.stunRelayUdpAddr = addr; d->pending.stunRelayUdpPort = port; @@ -996,7 +891,8 @@ void IceComponent::setStunRelayUdpService(const QHostAddress &addr, int port, co d->pending.stunRelayUdpPass = pass; } -void IceComponent::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass) +void IceComponent::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, + const QCA::SecureArray &pass) { d->pending.stunRelayTcpAddr = addr; d->pending.stunRelayTcpPort = port; @@ -1004,35 +900,17 @@ void IceComponent::setStunRelayTcpService(const QHostAddress &addr, int port, co d->pending.stunRelayTcpPass = pass; } -void IceComponent::setUseLocal(bool enabled) -{ - d->useLocal = enabled; -} +void IceComponent::setUseLocal(bool enabled) { d->useLocal = enabled; } -void IceComponent::setUseStunBind(bool enabled) -{ - d->useStunBind = enabled; -} +void IceComponent::setUseStunBind(bool enabled) { d->useStunBind = enabled; } -void IceComponent::setUseStunRelayUdp(bool enabled) -{ - d->useStunRelayUdp = enabled; -} +void IceComponent::setUseStunRelayUdp(bool enabled) { d->useStunRelayUdp = enabled; } -void IceComponent::setUseStunRelayTcp(bool enabled) -{ - d->useStunRelayTcp = enabled; -} +void IceComponent::setUseStunRelayTcp(bool enabled) { d->useStunRelayTcp = enabled; } -void IceComponent::update(QList *socketList) -{ - d->update(socketList); -} +void IceComponent::update(QList *socketList) { d->update(socketList); } -void IceComponent::stop() -{ - d->stop(); -} +void IceComponent::stop() { d->stop(); } int IceComponent::peerReflexivePriority(const IceTransport *iceTransport, int path) const { @@ -1047,11 +925,11 @@ void IceComponent::flagPathAsLowOverhead(int id, const QHostAddress &addr, int p void IceComponent::setDebugLevel(DebugLevel level) { d->debugLevel = level; - foreach(const Private::LocalTransport *lt, d->localLeap) + foreach (const Private::LocalTransport *lt, d->localLeap) lt->sock->setDebugLevel((IceTransport::DebugLevel)level); - foreach(const Private::LocalTransport *lt, d->localStun) + foreach (const Private::LocalTransport *lt, d->localStun) lt->sock->setDebugLevel((IceTransport::DebugLevel)level); - if(d->tt) + if (d->tt) d->tt->setDebugLevel((IceTransport::DebugLevel)level); } diff --git a/src/irisnet/noncore/icecomponent.h b/src/irisnet/noncore/icecomponent.h index b31b58b7..74055b0c 100644 --- a/src/irisnet/noncore/icecomponent.h +++ b/src/irisnet/noncore/icecomponent.h @@ -30,66 +30,46 @@ class QUdpSocket; namespace XMPP { class UdpPortReserver; -class IceComponent : public QObject -{ +class IceComponent : public QObject { Q_OBJECT public: - enum CandidateType - { - HostType, - PeerReflexiveType, - ServerReflexiveType, - RelayedType - }; + enum CandidateType { HostType, PeerReflexiveType, ServerReflexiveType, RelayedType }; - class TransportAddress - { + class TransportAddress { public: QHostAddress addr; - int port; + int port; - TransportAddress() : - port(-1) - { - } + TransportAddress() : port(-1) {} - TransportAddress(const QHostAddress &_addr, int _port) : - addr(_addr), - port(_port) - { - } + TransportAddress(const QHostAddress &_addr, int _port) : addr(_addr), port(_port) {} bool operator==(const TransportAddress &other) const { - if(addr == other.addr && port == other.port) + if (addr == other.addr && port == other.port) return true; else return false; } - inline bool operator!=(const TransportAddress &other) const - { - return !operator==(other); - } + inline bool operator!=(const TransportAddress &other) const { return !operator==(other); } }; - class CandidateInfo - { + class CandidateInfo { public: TransportAddress addr; - CandidateType type; - int priority; - QString foundation; - int componentId; + CandidateType type; + int priority; + QString foundation; + int componentId; TransportAddress base; TransportAddress related; - QString id; - int network; + QString id; + int network; }; - class Candidate - { + class Candidate { public: // unique across all candidates within this component int id; @@ -103,15 +83,10 @@ class IceComponent : public QObject // note that these may be the same for multiple candidates IceTransport *iceTransport; - int path; + int path; }; - enum DebugLevel - { - DL_None, - DL_Info, - DL_Packet - }; + enum DebugLevel { DL_None, DL_Info, DL_Packet }; IceComponent(int id, QObject *parent = nullptr); ~IceComponent(); @@ -143,7 +118,7 @@ class IceComponent : public QObject void setUseStunRelayTcp(bool enabled); // if socketList is not null then port reserver must be set - void update(QList *socketList = nullptr); + void update(QList *socketList = nullptr); void stop(); // prflx priority to use when replying from this transport/path @@ -180,6 +155,6 @@ inline uint qHash(const XMPP::IceComponent::TransportAddress &key, uint seed = 0 { return ::qHash(key.addr, seed) ^ ::qHash(key.port, seed); } -} //namespace XMPP +} // namespace XMPP #endif // ICECOMPONENT_H diff --git a/src/irisnet/noncore/icelocaltransport.cpp b/src/irisnet/noncore/icelocaltransport.cpp index 53e009c4..d0a799fe 100644 --- a/src/irisnet/noncore/icelocaltransport.cpp +++ b/src/irisnet/noncore/icelocaltransport.cpp @@ -33,30 +33,22 @@ #define MAX_PACKET_QUEUE 64 namespace XMPP { -enum -{ - Direct, - Relayed -}; +enum { Direct, Relayed }; //---------------------------------------------------------------------------- // SafeUdpSocket //---------------------------------------------------------------------------- // DOR-safe wrapper for QUdpSocket -class SafeUdpSocket : public QObject -{ +class SafeUdpSocket : public QObject { Q_OBJECT private: ObjectSession sess; - QUdpSocket *sock; - int writtenCount; + QUdpSocket * sock; + int writtenCount; public: - SafeUdpSocket(QUdpSocket *_sock, QObject *parent = nullptr) : - QObject(parent), - sess(this), - sock(_sock) + SafeUdpSocket(QUdpSocket *_sock, QObject *parent = nullptr) : QObject(parent), sess(this), sock(_sock) { sock->setParent(this); connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead())); @@ -67,8 +59,7 @@ class SafeUdpSocket : public QObject ~SafeUdpSocket() { - if(sock) - { + if (sock) { QUdpSocket *out = release(); out->deleteLater(); } @@ -79,28 +70,19 @@ class SafeUdpSocket : public QObject sock->disconnect(this); sock->setParent(nullptr); QUdpSocket *out = sock; - sock = nullptr; + sock = nullptr; return out; } - QHostAddress localAddress() const - { - return sock->localAddress(); - } + QHostAddress localAddress() const { return sock->localAddress(); } - quint16 localPort() const - { - return sock->localPort(); - } + quint16 localPort() const { return sock->localPort(); } - bool hasPendingDatagrams() const - { - return sock->hasPendingDatagrams(); - } + bool hasPendingDatagrams() const { return sock->hasPendingDatagrams(); } QByteArray readDatagram(QHostAddress *address = nullptr, quint16 *port = nullptr) { - if(!sock->hasPendingDatagrams()) + if (!sock->hasPendingDatagrams()) return QByteArray(); QByteArray buf; @@ -119,10 +101,7 @@ class SafeUdpSocket : public QObject void datagramsWritten(int count); private slots: - void sock_readyRead() - { - emit readyRead(); - } + void sock_readyRead() { emit readyRead(); } void sock_bytesWritten(qint64 bytes) { @@ -134,7 +113,7 @@ private slots: void processWritten() { - int count = writtenCount; + int count = writtenCount; writtenCount = 0; emit datagramsWritten(count); @@ -144,93 +123,69 @@ private slots: //---------------------------------------------------------------------------- // IceLocalTransport //---------------------------------------------------------------------------- -class IceLocalTransport::Private : public QObject -{ +class IceLocalTransport::Private : public QObject { Q_OBJECT public: - class WriteItem - { + class WriteItem { public: - enum Type - { - Direct, - Pool, - Turn - }; - - Type type; + enum Type { Direct, Pool, Turn }; + + Type type; QHostAddress addr; - int port; + int port; }; - class Written - { + class Written { public: QHostAddress addr; - int port; - int count; + int port; + int count; }; - class Datagram - { + class Datagram { public: QHostAddress addr; - int port; - QByteArray buf; + int port; + QByteArray buf; }; - IceLocalTransport *q; - ObjectSession sess; - QUdpSocket *extSock; - SafeUdpSocket *sock; + IceLocalTransport * q; + ObjectSession sess; + QUdpSocket * extSock; + SafeUdpSocket * sock; StunTransactionPool *pool; - StunBinding *stunBinding; - TurnClient *turn; - bool turnActivated; - QHostAddress addr; - int port; - QHostAddress refAddr; - int refPort; - QHostAddress relAddr; - int relPort; - QHostAddress stunBindAddr; - int stunBindPort; - QHostAddress stunRelayAddr; - int stunRelayPort; - QString stunUser; - QCA::SecureArray stunPass; - QString clientSoftware; - QList in; - QList inRelayed; - QList pendingWrites; - int retryCount; - bool stopping; - int debugLevel; + StunBinding * stunBinding; + TurnClient * turn; + bool turnActivated; + QHostAddress addr; + int port; + QHostAddress refAddr; + int refPort; + QHostAddress relAddr; + int relPort; + QHostAddress stunBindAddr; + int stunBindPort; + QHostAddress stunRelayAddr; + int stunRelayPort; + QString stunUser; + QCA::SecureArray stunPass; + QString clientSoftware; + QList in; + QList inRelayed; + QList pendingWrites; + int retryCount; + bool stopping; + int debugLevel; Private(IceLocalTransport *_q) : - QObject(_q), - q(_q), - sess(this), - extSock(nullptr), - sock(nullptr), - pool(nullptr), - stunBinding(nullptr), - turn(nullptr), - turnActivated(false), - port(-1), - refPort(-1), - relPort(-1), - retryCount(0), - stopping(false), + QObject(_q), q(_q), sess(this), extSock(nullptr), sock(nullptr), pool(nullptr), stunBinding(nullptr), + turn(nullptr), turnActivated(false), port(-1), refPort(-1), relPort(-1), retryCount(0), stopping(false), debugLevel(IceTransport::DL_None) { } - ~Private() - { - reset(); - } + ~Private() { reset(); } void reset() { @@ -240,13 +195,11 @@ class IceLocalTransport::Private : public QObject stunBinding = nullptr; delete turn; - turn = nullptr; + turn = nullptr; turnActivated = false; - if(sock) - { - if(extSock) - { + if (sock) { + if (extSock) { sock->release(); extSock = nullptr; } @@ -269,7 +222,7 @@ class IceLocalTransport::Private : public QObject pendingWrites.clear(); retryCount = 0; - stopping = false; + stopping = false; } void start() @@ -286,7 +239,7 @@ class IceLocalTransport::Private : public QObject stopping = true; - if(turn) + if (turn) turn->close(); else sess.defer(this, "postStop"); @@ -298,27 +251,26 @@ class IceLocalTransport::Private : public QObject pool = new StunTransactionPool(StunTransaction::Udp, this); pool->setDebugLevel((StunTransactionPool::DebugLevel)debugLevel); - connect(pool, SIGNAL(outgoingMessage(QByteArray,QHostAddress,int)), SLOT(pool_outgoingMessage(QByteArray,QHostAddress,int))); + connect(pool, SIGNAL(outgoingMessage(QByteArray, QHostAddress, int)), + SLOT(pool_outgoingMessage(QByteArray, QHostAddress, int))); connect(pool, SIGNAL(needAuthParams()), SLOT(pool_needAuthParams())); connect(pool, SIGNAL(debugLine(QString)), SLOT(pool_debugLine(QString))); pool->setLongTermAuthEnabled(true); - if(!stunUser.isEmpty()) - { + if (!stunUser.isEmpty()) { pool->setUsername(stunUser); pool->setPassword(stunPass); } - if(!stunBindAddr.isNull()) - { + if (!stunBindAddr.isNull()) { stunBinding = new StunBinding(pool); connect(stunBinding, SIGNAL(success()), SLOT(binding_success())); - connect(stunBinding, SIGNAL(error(XMPP::StunBinding::Error)), SLOT(binding_error(XMPP::StunBinding::Error))); + connect(stunBinding, SIGNAL(error(XMPP::StunBinding::Error)), + SLOT(binding_error(XMPP::StunBinding::Error))); stunBinding->start(stunBindAddr, stunBindPort); } - if(!stunRelayAddr.isNull()) - { + if (!stunRelayAddr.isNull()) { do_turn(); } } @@ -331,7 +283,8 @@ class IceLocalTransport::Private : public QObject connect(turn, SIGNAL(tlsHandshaken()), SLOT(turn_tlsHandshaken())); connect(turn, SIGNAL(closed()), SLOT(turn_closed())); connect(turn, SIGNAL(activated()), SLOT(turn_activated())); - connect(turn, SIGNAL(packetsWritten(int,QHostAddress,int)), SLOT(turn_packetsWritten(int,QHostAddress,int))); + connect(turn, SIGNAL(packetsWritten(int, QHostAddress, int)), + SLOT(turn_packetsWritten(int, QHostAddress, int))); connect(turn, SIGNAL(error(XMPP::TurnClient::Error)), SLOT(turn_error(XMPP::TurnClient::Error))); connect(turn, SIGNAL(outgoingDatagram(QByteArray)), SLOT(turn_outgoingDatagram(QByteArray))); connect(turn, SIGNAL(debugLine(QString)), SLOT(turn_debugLine(QString))); @@ -346,8 +299,7 @@ class IceLocalTransport::Private : public QObject QUdpSocket *createSocket() { QUdpSocket *qsock = new QUdpSocket(this); - if(!qsock->bind(addr, 0)) - { + if (!qsock->bind(addr, 0)) { delete qsock; emit q->error(IceLocalTransport::ErrorBind); return nullptr; @@ -369,13 +321,12 @@ class IceLocalTransport::Private : public QObject bool handleRetry() { // don't allow retrying if activated or stopping) - if(turnActivated || stopping) + if (turnActivated || stopping) return false; ++retryCount; - if(retryCount < 3) - { - if(debugLevel >= IceTransport::DL_Info) + if (retryCount < 3) { + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("retrying..."); delete sock; @@ -383,11 +334,10 @@ class IceLocalTransport::Private : public QObject // to receive this error, it is a Relay, so change // the mode - //stunType = IceLocalTransport::Relay; + // stunType = IceLocalTransport::Relay; QUdpSocket *qsock = createSocket(); - if(!qsock) - { + if (!qsock) { // signal emitted in this case. bail. // (return true so caller takes no action) return true; @@ -417,25 +367,22 @@ class IceLocalTransport::Private : public QObject // return true if data packet, false if pool or nothing bool processIncomingStun(const QByteArray &buf, const QHostAddress &fromAddr, int fromPort, Datagram *dg) { - QByteArray data; + QByteArray data; QHostAddress dataAddr; - int dataPort; + int dataPort; bool notStun; - if(!pool->writeIncomingMessage(buf, ¬Stun, fromAddr, fromPort) && turn) - { + if (!pool->writeIncomingMessage(buf, ¬Stun, fromAddr, fromPort) && turn) { data = turn->processIncomingDatagram(buf, notStun, &dataAddr, &dataPort); - if(!data.isNull()) - { + if (!data.isNull()) { dg->addr = dataAddr; dg->port = dataPort; - dg->buf = data; + dg->buf = data; return true; - } - else - { - if(debugLevel >= IceTransport::DL_Packet) - emit q->debugLine("Warning: server responded with what doesn't seem to be a STUN or data packet, skipping."); + } else { + if (debugLevel >= IceTransport::DL_Packet) + emit q->debugLine( + "Warning: server responded with what doesn't seem to be a STUN or data packet, skipping."); } } @@ -445,18 +392,14 @@ class IceLocalTransport::Private : public QObject private slots: void postStart() { - if(stopping) + if (stopping) return; - if(extSock) - { + if (extSock) { sock = new SafeUdpSocket(extSock, this); - } - else - { + } else { QUdpSocket *qsock = createSocket(); - if(!qsock) - { + if (!qsock) { // signal emitted in this case. bail return; } @@ -482,45 +425,40 @@ private slots: QList dreads; QList rreads; - while(sock->hasPendingDatagrams()) - { + while (sock->hasPendingDatagrams()) { QHostAddress from; - quint16 fromPort; + quint16 fromPort; Datagram dg; QByteArray buf = sock->readDatagram(&from, &fromPort); - if((from == stunBindAddr && fromPort == stunBindPort) || (from == stunRelayAddr && fromPort == stunRelayPort)) - { + if ((from == stunBindAddr && fromPort == stunBindPort) + || (from == stunRelayAddr && fromPort == stunRelayPort)) { bool haveData = processIncomingStun(buf, from, fromPort, &dg); // processIncomingStun could cause signals to // emit. for example, stopped() - if(!watch.isValid()) + if (!watch.isValid()) return; - if(haveData) + if (haveData) rreads += dg; - } - else - { + } else { dg.addr = from; dg.port = fromPort; - dg.buf = buf; + dg.buf = buf; dreads += dg; } } - if(dreads.count() > 0) - { + if (dreads.count() > 0) { in += dreads; emit q->readyRead(Direct); - if(!watch.isValid()) + if (!watch.isValid()) return; } - if(rreads.count() > 0) - { + if (rreads.count() > 0) { inRelayed += rreads; emit q->readyRead(Relayed); } @@ -529,60 +467,49 @@ private slots: void sock_datagramsWritten(int count) { QList dwrites; - int twrites = 0; + int twrites = 0; - while(count > 0) - { + while (count > 0) { Q_ASSERT(!pendingWrites.isEmpty()); WriteItem wi = pendingWrites.takeFirst(); --count; - if(wi.type == WriteItem::Direct) - { + if (wi.type == WriteItem::Direct) { int at = -1; - for(int n = 0; n < dwrites.count(); ++n) - { - if(dwrites[n].addr == wi.addr && dwrites[n].port == wi.port) - { + for (int n = 0; n < dwrites.count(); ++n) { + if (dwrites[n].addr == wi.addr && dwrites[n].port == wi.port) { at = n; break; } } - if(at != -1) - { + if (at != -1) { ++dwrites[at].count; - } - else - { + } else { Written wr; - wr.addr = wi.addr; - wr.port = wi.port; + wr.addr = wi.addr; + wr.port = wi.port; wr.count = 1; dwrites += wr; } - } - else if(wi.type == WriteItem::Turn) + } else if (wi.type == WriteItem::Turn) ++twrites; } - if(dwrites.isEmpty() && twrites == 0) + if (dwrites.isEmpty() && twrites == 0) return; ObjectSessionWatcher watch(&sess); - if(!dwrites.isEmpty()) - { - foreach(const Written &wr, dwrites) - { + if (!dwrites.isEmpty()) { + foreach (const Written &wr, dwrites) { emit q->datagramsWritten(Direct, wr.count, wr.addr, wr.port); - if(!watch.isValid()) + if (!watch.isValid()) return; } } - if(twrites > 0) - { + if (twrites > 0) { // note: this will invoke turn_packetsWritten() turn->outgoingDatagramsWritten(twrites); } @@ -608,10 +535,7 @@ private slots: pool->continueAfterParams(); } - void pool_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void pool_debugLine(const QString &line) { emit q->debugLine(line); } void binding_success() { @@ -632,29 +556,29 @@ private slots: stunBinding = nullptr; // don't report any error - //if(stunType == IceLocalTransport::Basic || (stunType == IceLocalTransport::Auto && !turn)) + // if(stunType == IceLocalTransport::Basic || (stunType == IceLocalTransport::Auto && !turn)) // emit q->addressesChanged(); } void turn_connected() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_connected"); } void turn_tlsHandshaken() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_tlsHandshaken"); } void turn_closed() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_closed"); delete turn; - turn = nullptr; + turn = nullptr; turnActivated = false; postStop(); @@ -666,18 +590,18 @@ private slots: // take reflexive address from TURN only if we are not using a // separate STUN server - if(stunBindAddr.isNull() || stunBindAddr == stunRelayAddr) - { + if (stunBindAddr.isNull() || stunBindAddr == stunRelayAddr) { refAddr = allocate->reflexiveAddress(); refPort = allocate->reflexivePort(); } - if(debugLevel >= IceTransport::DL_Info) - emit q->debugLine(QString("Server says we are ") + allocate->reflexiveAddress().toString() + ';' + QString::number(allocate->reflexivePort())); + if (debugLevel >= IceTransport::DL_Info) + emit q->debugLine(QString("Server says we are ") + allocate->reflexiveAddress().toString() + ';' + + QString::number(allocate->reflexivePort())); relAddr = allocate->relayedAddress(); relPort = allocate->relayedPort(); - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine(QString("Server relays via ") + relAddr.toString() + ';' + QString::number(relPort)); turnActivated = true; @@ -692,27 +616,26 @@ private slots: void turn_error(XMPP::TurnClient::Error e) { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine(QString("turn_error: ") + turn->errorString()); delete turn; - turn = nullptr; + turn = nullptr; bool wasActivated = turnActivated; - turnActivated = false; + turnActivated = false; - if(e == TurnClient::ErrorMismatch) - { - if(!extSock && handleRetry()) + if (e == TurnClient::ErrorMismatch) { + if (!extSock && handleRetry()) return; } // this means our relay died on us. in the future we might // consider reporting this - if(wasActivated) + if (wasActivated) return; // don't report any error - //if(stunType == IceLocalTransport::Relay || (stunType == IceLocalTransport::Auto && !stunBinding)) + // if(stunType == IceLocalTransport::Relay || (stunType == IceLocalTransport::Auto && !stunBinding)) // emit q->addressesChanged(); } @@ -724,27 +647,14 @@ private slots: sock->writeDatagram(buf, stunRelayAddr, stunRelayPort); } - void turn_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void turn_debugLine(const QString &line) { emit q->debugLine(line); } }; -IceLocalTransport::IceLocalTransport(QObject *parent) : - IceTransport(parent) -{ - d = new Private(this); -} +IceLocalTransport::IceLocalTransport(QObject *parent) : IceTransport(parent) { d = new Private(this); } -IceLocalTransport::~IceLocalTransport() -{ - delete d; -} +IceLocalTransport::~IceLocalTransport() { delete d; } -void IceLocalTransport::setClientSoftwareNameAndVersion(const QString &str) -{ - d->clientSoftware = str; -} +void IceLocalTransport::setClientSoftwareNameAndVersion(const QString &str) { d->clientSoftware = str; } void IceLocalTransport::start(QUdpSocket *sock) { @@ -758,10 +668,7 @@ void IceLocalTransport::start(const QHostAddress &addr) d->start(); } -void IceLocalTransport::stop() -{ - d->stop(); -} +void IceLocalTransport::stop() { d->stop(); } void IceLocalTransport::setStunBindService(const QHostAddress &addr, int port) { @@ -769,63 +676,42 @@ void IceLocalTransport::setStunBindService(const QHostAddress &addr, int port) d->stunBindPort = port; } -void IceLocalTransport::setStunRelayService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass) +void IceLocalTransport::setStunRelayService(const QHostAddress &addr, int port, const QString &user, + const QCA::SecureArray &pass) { d->stunRelayAddr = addr; d->stunRelayPort = port; - d->stunUser = user; - d->stunPass = pass; + d->stunUser = user; + d->stunPass = pass; } -void IceLocalTransport::stunStart() -{ - d->stunStart(); -} +void IceLocalTransport::stunStart() { d->stunStart(); } -QHostAddress IceLocalTransport::localAddress() const -{ - return d->addr; -} +QHostAddress IceLocalTransport::localAddress() const { return d->addr; } -int IceLocalTransport::localPort() const -{ - return d->port; -} +int IceLocalTransport::localPort() const { return d->port; } -QHostAddress IceLocalTransport::serverReflexiveAddress() const -{ - return d->refAddr; -} +QHostAddress IceLocalTransport::serverReflexiveAddress() const { return d->refAddr; } -int IceLocalTransport::serverReflexivePort() const -{ - return d->refPort; -} +int IceLocalTransport::serverReflexivePort() const { return d->refPort; } -QHostAddress IceLocalTransport::relayedAddress() const -{ - return d->relAddr; -} +QHostAddress IceLocalTransport::relayedAddress() const { return d->relAddr; } -int IceLocalTransport::relayedPort() const -{ - return d->relPort; -} +int IceLocalTransport::relayedPort() const { return d->relPort; } void IceLocalTransport::addChannelPeer(const QHostAddress &addr, int port) { - if(d->turn) + if (d->turn) d->turn->addChannelPeer(addr, port); } bool IceLocalTransport::hasPendingDatagrams(int path) const { - if(path == Direct) + if (path == Direct) return !d->in.isEmpty(); - else if(path == Relayed) + else if (path == Relayed) return !d->inRelayed.isEmpty(); - else - { + else { Q_ASSERT(0); return false; } @@ -834,50 +720,44 @@ bool IceLocalTransport::hasPendingDatagrams(int path) const QByteArray IceLocalTransport::readDatagram(int path, QHostAddress *addr, int *port) { QList *in = nullptr; - if(path == Direct) + if (path == Direct) in = &d->in; - else if(path == Relayed) + else if (path == Relayed) in = &d->inRelayed; else Q_ASSERT(0); - if(!in->isEmpty()) - { + if (!in->isEmpty()) { Private::Datagram datagram = in->takeFirst(); - *addr = datagram.addr; - *port = datagram.port; + *addr = datagram.addr; + *port = datagram.port; return datagram.buf; - } - else + } else return QByteArray(); } void IceLocalTransport::writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port) { - if(path == Direct) - { + if (path == Direct) { Private::WriteItem wi; wi.type = Private::WriteItem::Direct; wi.addr = addr; wi.port = port; d->pendingWrites += wi; d->sock->writeDatagram(buf, addr, port); - } - else if(path == Relayed) - { - if(d->turn && d->turnActivated) + } else if (path == Relayed) { + if (d->turn && d->turnActivated) d->turn->write(buf, addr, port); - } - else + } else Q_ASSERT(0); } void IceLocalTransport::setDebugLevel(DebugLevel level) { d->debugLevel = level; - if(d->pool) + if (d->pool) d->pool->setDebugLevel((StunTransactionPool::DebugLevel)level); - if(d->turn) + if (d->turn) d->turn->setDebugLevel((TurnClient::DebugLevel)level); } diff --git a/src/irisnet/noncore/icelocaltransport.h b/src/irisnet/noncore/icelocaltransport.h index 05738c40..aa43f178 100644 --- a/src/irisnet/noncore/icelocaltransport.h +++ b/src/irisnet/noncore/icelocaltransport.h @@ -28,7 +28,7 @@ class QHostAddress; class QUdpSocket; namespace QCA { - class SecureArray; +class SecureArray; } namespace XMPP { @@ -36,15 +36,11 @@ namespace XMPP { // relationship with an associated STUN/TURN server. if TURN is used, this // class offers two paths (0=direct and 1=relayed), otherwise it offers // just one path (0=direct) -class IceLocalTransport : public IceTransport -{ +class IceLocalTransport : public IceTransport { Q_OBJECT public: - enum Error - { - ErrorBind = ErrorCustom - }; + enum Error { ErrorBind = ErrorCustom }; IceLocalTransport(QObject *parent = nullptr); ~IceLocalTransport(); @@ -66,21 +62,21 @@ class IceLocalTransport : public IceTransport void stunStart(); QHostAddress localAddress() const; - int localPort() const; + int localPort() const; QHostAddress serverReflexiveAddress() const; - int serverReflexivePort() const; + int serverReflexivePort() const; QHostAddress relayedAddress() const; - int relayedPort() const; + int relayedPort() const; // reimplemented - virtual void stop(); - virtual bool hasPendingDatagrams(int path) const; + virtual void stop(); + virtual bool hasPendingDatagrams(int path) const; virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port); - virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port); - virtual void addChannelPeer(const QHostAddress &addr, int port); - virtual void setDebugLevel(DebugLevel level); + virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port); + virtual void addChannelPeer(const QHostAddress &addr, int port); + virtual void setDebugLevel(DebugLevel level); signals: // may be emitted multiple times. diff --git a/src/irisnet/noncore/icetransport.cpp b/src/irisnet/noncore/icetransport.cpp index 4c7825ee..dfeb3057 100644 --- a/src/irisnet/noncore/icetransport.cpp +++ b/src/irisnet/noncore/icetransport.cpp @@ -19,13 +19,8 @@ #include "icetransport.h" namespace XMPP { -IceTransport::IceTransport(QObject *parent) : - QObject(parent) -{ -} +IceTransport::IceTransport(QObject *parent) : QObject(parent) {} -IceTransport::~IceTransport() -{ -} +IceTransport::~IceTransport() {} } // namespace XMPP diff --git a/src/irisnet/noncore/icetransport.h b/src/irisnet/noncore/icetransport.h index 97dfe6de..e3789378 100644 --- a/src/irisnet/noncore/icetransport.h +++ b/src/irisnet/noncore/icetransport.h @@ -25,33 +25,23 @@ class QHostAddress; namespace XMPP { -class IceTransport : public QObject -{ +class IceTransport : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric, - ErrorCustom - }; + enum Error { ErrorGeneric, ErrorCustom }; - enum DebugLevel - { - DL_None, - DL_Info, - DL_Packet - }; + enum DebugLevel { DL_None, DL_Info, DL_Packet }; IceTransport(QObject *parent = nullptr); ~IceTransport(); virtual void stop() = 0; - virtual bool hasPendingDatagrams(int path) const = 0; - virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port) = 0; - virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port) = 0; - virtual void addChannelPeer(const QHostAddress &addr, int port) = 0; + virtual bool hasPendingDatagrams(int path) const = 0; + virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port) = 0; + virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port) = 0; + virtual void addChannelPeer(const QHostAddress &addr, int port) = 0; virtual void setDebugLevel(DebugLevel level) = 0; diff --git a/src/irisnet/noncore/iceturntransport.cpp b/src/irisnet/noncore/iceturntransport.cpp index e46f5467..62145739 100644 --- a/src/irisnet/noncore/iceturntransport.cpp +++ b/src/irisnet/noncore/iceturntransport.cpp @@ -23,28 +23,23 @@ #include namespace XMPP { -class IceTurnTransport::Private : public QObject -{ +class IceTurnTransport::Private : public QObject { Q_OBJECT public: IceTurnTransport *q; - int mode; - QHostAddress serverAddr; - int serverPort; - QString relayUser; - QCA::SecureArray relayPass; - QHostAddress relayAddr; - int relayPort; - TurnClient turn; - int turnErrorCode; - int debugLevel; - - Private(IceTurnTransport *_q) : - QObject(_q), - q(_q), - turn(this), - debugLevel(IceTransport::DL_None) + int mode; + QHostAddress serverAddr; + int serverPort; + QString relayUser; + QCA::SecureArray relayPass; + QHostAddress relayAddr; + int relayPort; + TurnClient turn; + int turnErrorCode; + int debugLevel; + + Private(IceTurnTransport *_q) : QObject(_q), q(_q), turn(this), debugLevel(IceTransport::DL_None) { connect(&turn, SIGNAL(connected()), SLOT(turn_connected())); connect(&turn, SIGNAL(tlsHandshaken()), SLOT(turn_tlsHandshaken())); @@ -53,7 +48,8 @@ class IceTurnTransport::Private : public QObject connect(&turn, SIGNAL(retrying()), SLOT(turn_retrying())); connect(&turn, SIGNAL(activated()), SLOT(turn_activated())); connect(&turn, SIGNAL(readyRead()), SLOT(turn_readyRead())); - connect(&turn, SIGNAL(packetsWritten(int,QHostAddress,int)), SLOT(turn_packetsWritten(int,QHostAddress,int))); + connect(&turn, SIGNAL(packetsWritten(int, QHostAddress, int)), + SLOT(turn_packetsWritten(int, QHostAddress, int))); connect(&turn, SIGNAL(error(XMPP::TurnClient::Error)), SLOT(turn_error(XMPP::TurnClient::Error))); connect(&turn, SIGNAL(debugLine(QString)), SLOT(turn_debugLine(QString))); } @@ -65,27 +61,24 @@ class IceTurnTransport::Private : public QObject turn.connectToHost(serverAddr, serverPort, (TurnClient::Mode)mode); } - void stop() - { - turn.close(); - } + void stop() { turn.close(); } private slots: void turn_connected() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_connected"); } void turn_tlsHandshaken() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_tlsHandshaken"); } void turn_closed() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_closed"); emit q->stopped(); @@ -102,7 +95,7 @@ private slots: void turn_retrying() { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine("turn_retrying"); } @@ -111,12 +104,12 @@ private slots: StunAllocate *allocate = turn.stunAllocate(); QHostAddress saddr = allocate->reflexiveAddress(); - quint16 sport = allocate->reflexivePort(); - if(debugLevel >= IceTransport::DL_Info) + quint16 sport = allocate->reflexivePort(); + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine(QString("Server says we are ") + saddr.toString() + ';' + QString::number(sport)); saddr = allocate->relayedAddress(); sport = allocate->relayedPort(); - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine(QString("Server relays via ") + saddr.toString() + ';' + QString::number(sport)); relayAddr = saddr; @@ -125,10 +118,7 @@ private slots: emit q->started(); } - void turn_readyRead() - { - emit q->readyRead(0); - } + void turn_readyRead() { emit q->readyRead(0); } void turn_packetsWritten(int count, const QHostAddress &addr, int port) { @@ -137,82 +127,48 @@ private slots: void turn_error(XMPP::TurnClient::Error e) { - if(debugLevel >= IceTransport::DL_Info) + if (debugLevel >= IceTransport::DL_Info) emit q->debugLine(QString("turn_error: ") + turn.errorString()); turnErrorCode = e; emit q->error(IceTurnTransport::ErrorTurn); } - void turn_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void turn_debugLine(const QString &line) { emit q->debugLine(line); } }; -IceTurnTransport::IceTurnTransport(QObject *parent) : - IceTransport(parent) -{ - d = new Private(this); -} +IceTurnTransport::IceTurnTransport(QObject *parent) : IceTransport(parent) { d = new Private(this); } -IceTurnTransport::~IceTurnTransport() -{ - delete d; -} +IceTurnTransport::~IceTurnTransport() { delete d; } void IceTurnTransport::setClientSoftwareNameAndVersion(const QString &str) { d->turn.setClientSoftwareNameAndVersion(str); } -void IceTurnTransport::setUsername(const QString &user) -{ - d->relayUser = user; -} +void IceTurnTransport::setUsername(const QString &user) { d->relayUser = user; } -void IceTurnTransport::setPassword(const QCA::SecureArray &pass) -{ - d->relayPass = pass; -} +void IceTurnTransport::setPassword(const QCA::SecureArray &pass) { d->relayPass = pass; } -void IceTurnTransport::setProxy(const TurnClient::Proxy &proxy) -{ - d->turn.setProxy(proxy); -} +void IceTurnTransport::setProxy(const TurnClient::Proxy &proxy) { d->turn.setProxy(proxy); } void IceTurnTransport::start(const QHostAddress &addr, int port, TurnClient::Mode mode) { d->serverAddr = addr; d->serverPort = port; - d->mode = mode; + d->mode = mode; d->start(); } -QHostAddress IceTurnTransport::relayedAddress() const -{ - return d->relayAddr; -} +QHostAddress IceTurnTransport::relayedAddress() const { return d->relayAddr; } -int IceTurnTransport::relayedPort() const -{ - return d->relayPort; -} +int IceTurnTransport::relayedPort() const { return d->relayPort; } -void IceTurnTransport::addChannelPeer(const QHostAddress &addr, int port) -{ - d->turn.addChannelPeer(addr, port); -} +void IceTurnTransport::addChannelPeer(const QHostAddress &addr, int port) { d->turn.addChannelPeer(addr, port); } -TurnClient::Error IceTurnTransport::turnErrorCode() const -{ - return (TurnClient::Error)d->turnErrorCode; -} +TurnClient::Error IceTurnTransport::turnErrorCode() const { return (TurnClient::Error)d->turnErrorCode; } -void IceTurnTransport::stop() -{ - d->stop(); -} +void IceTurnTransport::stop() { d->stop(); } bool IceTurnTransport::hasPendingDatagrams(int path) const { diff --git a/src/irisnet/noncore/iceturntransport.h b/src/irisnet/noncore/iceturntransport.h index 98604cb1..8d9ecd89 100644 --- a/src/irisnet/noncore/iceturntransport.h +++ b/src/irisnet/noncore/iceturntransport.h @@ -28,15 +28,11 @@ namespace XMPP { // for the turn transport, only path 0 is used -class IceTurnTransport : public IceTransport -{ +class IceTurnTransport : public IceTransport { Q_OBJECT public: - enum Error - { - ErrorTurn = ErrorCustom - }; + enum Error { ErrorTurn = ErrorCustom }; IceTurnTransport(QObject *parent = nullptr); ~IceTurnTransport(); @@ -52,17 +48,17 @@ class IceTurnTransport : public IceTransport void start(const QHostAddress &addr, int port, TurnClient::Mode mode = TurnClient::PlainMode); QHostAddress relayedAddress() const; - int relayedPort() const; + int relayedPort() const; TurnClient::Error turnErrorCode() const; // reimplemented - virtual void stop(); - virtual bool hasPendingDatagrams(int path) const; + virtual void stop(); + virtual bool hasPendingDatagrams(int path) const; virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port); - virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port); - virtual void addChannelPeer(const QHostAddress &addr, int port); - virtual void setDebugLevel(DebugLevel level); + virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port); + virtual void addChannelPeer(const QHostAddress &addr, int port); + virtual void setDebugLevel(DebugLevel level); private: class Private; diff --git a/src/irisnet/noncore/legacy/ndns.cpp b/src/irisnet/noncore/legacy/ndns.cpp index 7ae585bc..753e2359 100644 --- a/src/irisnet/noncore/legacy/ndns.cpp +++ b/src/irisnet/noncore/legacy/ndns.cpp @@ -61,8 +61,7 @@ //! //! Constructs an NDns object with parent \a parent. -NDns::NDns(QObject *parent) -:QObject(parent),dns(this) +NDns::NDns(QObject *parent) : QObject(parent), dns(this) { busy = false; @@ -72,10 +71,7 @@ NDns::NDns(QObject *parent) //! //! Destroys the object and frees allocated resources. -NDns::~NDns() -{ - stop(); -} +NDns::~NDns() { stop(); } //! //! Resolves hostname \a host (eg. psi.affinix.com) @@ -98,25 +94,16 @@ void NDns::stop() //! //! Returns the IP address as a 32-bit integer in host-byte-order. This will be 0 if the lookup failed. //! \sa resultsReady() -QHostAddress NDns::result() const -{ - return addr; -} +QHostAddress NDns::result() const { return addr; } //! //! Returns the IP address as a string. This will be an empty string if the lookup failed. //! \sa resultsReady() -QString NDns::resultString() const -{ - return addr.toString(); -} +QString NDns::resultString() const { return addr.toString(); } //! //! Returns TRUE if busy resolving a hostname. -bool NDns::isBusy() const -{ - return busy; -} +bool NDns::isBusy() const { return busy; } void NDns::dns_resultsReady(const QList &results) { @@ -133,4 +120,3 @@ void NDns::dns_error(XMPP::NameResolver::Error) } // CS_NAMESPACE_END - diff --git a/src/irisnet/noncore/legacy/ndns.h b/src/irisnet/noncore/legacy/ndns.h index 2b8a3d86..fedf4ddb 100644 --- a/src/irisnet/noncore/legacy/ndns.h +++ b/src/irisnet/noncore/legacy/ndns.h @@ -26,11 +26,10 @@ #include // CS_NAMESPACE_BEGIN -class NDns : public QObject -{ +class NDns : public QObject { Q_OBJECT public: - NDns(QObject *parent=nullptr); + NDns(QObject *parent = nullptr); ~NDns(); void resolve(const QString &); @@ -38,7 +37,7 @@ class NDns : public QObject bool isBusy() const; QHostAddress result() const; - QString resultString() const; + QString resultString() const; signals: void resultsReady(); @@ -49,8 +48,8 @@ private slots: private: XMPP::NameResolver dns; - bool busy; - QHostAddress addr; + bool busy; + QHostAddress addr; }; // CS_NAMESPACE_END diff --git a/src/irisnet/noncore/legacy/srvresolver.cpp b/src/irisnet/noncore/legacy/srvresolver.cpp index 16ae25bd..8c1b43b9 100644 --- a/src/irisnet/noncore/legacy/srvresolver.cpp +++ b/src/irisnet/noncore/legacy/srvresolver.cpp @@ -20,7 +20,7 @@ #include "srvresolver.h" #ifndef NO_NDNS -# include "ndns.h" +#include "ndns.h" #endif // CS_NAMESPACE_BEGIN @@ -29,17 +29,17 @@ static void sortSRVList(QList &list) QList tmp = list; list.clear(); - while(!tmp.isEmpty()) { + while (!tmp.isEmpty()) { QList::Iterator p = tmp.end(); - for(QList::Iterator it = tmp.begin(); it != tmp.end(); ++it) { - if(p == tmp.end()) + for (QList::Iterator it = tmp.begin(); it != tmp.end(); ++it) { + if (p == tmp.end()) p = it; else { int a = (*it).priority; int b = (*p).priority; int j = (*it).weight; int k = (*p).weight; - if(a < b || (a == b && j < k)) + if (a < b || (a == b && j < k)) p = it; } } @@ -48,8 +48,7 @@ static void sortSRVList(QList &list) } } -class SrvResolver::Private -{ +class SrvResolver::Private { public: Private(SrvResolver *_q) : nndns(_q), @@ -60,33 +59,33 @@ class SrvResolver::Private { } - XMPP::NameResolver nndns; + XMPP::NameResolver nndns; XMPP::NameRecord::Type nntype; - bool nndns_busy; + bool nndns_busy; #ifndef NO_NDNS NDns ndns; #endif - bool failed; + bool failed; QHostAddress resultAddress; - quint16 resultPort; + quint16 resultPort; - bool srvonly; - QString srv; + bool srvonly; + QString srv; QList servers; - bool aaaa; + bool aaaa; QTimer t; }; -SrvResolver::SrvResolver(QObject *parent) -:QObject(parent) +SrvResolver::SrvResolver(QObject *parent) : QObject(parent) { - d = new Private(this); + d = new Private(this); d->nndns_busy = false; - connect(&d->nndns, SIGNAL(resultsReady(QList)), SLOT(nndns_resultsReady(QList))); + connect(&d->nndns, SIGNAL(resultsReady(QList)), + SLOT(nndns_resultsReady(QList))); connect(&d->nndns, SIGNAL(error(XMPP::NameResolver::Error)), SLOT(nndns_error(XMPP::NameResolver::Error))); #ifndef NO_NDNS @@ -106,13 +105,13 @@ void SrvResolver::resolve(const QString &server, const QString &type, const QStr { stop(); - d->failed = false; + d->failed = false; d->srvonly = false; - d->srv = QString("_") + type + "._" + proto + '.' + server; + d->srv = QString("_") + type + "._" + proto + '.' + server; d->t.setSingleShot(true); d->t.start(15000); d->nndns_busy = true; - d->nntype = XMPP::NameRecord::Srv; + d->nntype = XMPP::NameRecord::Srv; d->nndns.start(d->srv.toLatin1(), d->nntype); } @@ -120,19 +119,19 @@ void SrvResolver::resolveSrvOnly(const QString &server, const QString &type, con { stop(); - d->failed = false; + d->failed = false; d->srvonly = true; - d->srv = QString("_") + type + "._" + proto + '.' + server; + d->srv = QString("_") + type + "._" + proto + '.' + server; d->t.setSingleShot(true); d->t.start(15000); d->nndns_busy = true; - d->nntype = XMPP::NameRecord::Srv; + d->nntype = XMPP::NameRecord::Srv; d->nndns.start(d->srv.toLatin1(), d->nntype); } void SrvResolver::next() { - if(d->servers.isEmpty()) + if (d->servers.isEmpty()) return; tryNext(); @@ -140,54 +139,42 @@ void SrvResolver::next() void SrvResolver::stop() { - if(d->t.isActive()) + if (d->t.isActive()) d->t.stop(); - if(d->nndns_busy) { + if (d->nndns_busy) { d->nndns.stop(); d->nndns_busy = false; } #ifndef NO_NDNS - if(d->ndns.isBusy()) + if (d->ndns.isBusy()) d->ndns.stop(); #endif d->resultAddress = QHostAddress(); - d->resultPort = 0; + d->resultPort = 0; d->servers.clear(); - d->srv = ""; + d->srv = ""; d->failed = true; } bool SrvResolver::isBusy() const { #ifndef NO_NDNS - if(d->nndns_busy || d->ndns.isBusy()) + if (d->nndns_busy || d->ndns.isBusy()) #else - if(d->nndns_busy) + if (d->nndns_busy) #endif return true; else return false; } -QList SrvResolver::servers() const -{ - return d->servers; -} +QList SrvResolver::servers() const { return d->servers; } -bool SrvResolver::failed() const -{ - return d->failed; -} +bool SrvResolver::failed() const { return d->failed; } -QHostAddress SrvResolver::resultAddress() const -{ - return d->resultAddress; -} +QHostAddress SrvResolver::resultAddress() const { return d->resultAddress; } -quint16 SrvResolver::resultPort() const -{ - return d->resultPort; -} +quint16 SrvResolver::resultPort() const { return d->resultPort; } void SrvResolver::tryNext() { @@ -195,30 +182,30 @@ void SrvResolver::tryNext() d->ndns.resolve(d->servers.first().name); #else d->nndns_busy = true; - d->nntype = d->aaaa ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A; + d->nntype = d->aaaa ? XMPP::NameRecord::Aaaa : XMPP::NameRecord::A; d->nndns.start(d->servers.first().name.toLatin1(), d->nntype); #endif } void SrvResolver::nndns_resultsReady(const QList &results) { - if(!d->nndns_busy) + if (!d->nndns_busy) return; d->t.stop(); - if(d->nntype == XMPP::NameRecord::Srv) { + if (d->nntype == XMPP::NameRecord::Srv) { // grab the server list and destroy the qdns object QList list; - for(int n = 0; n < results.count(); ++n) - { - list += Q3Dns::Server(QString::fromLatin1(results[n].name()), results[n].priority(), results[n].weight(), results[n].port()); + for (int n = 0; n < results.count(); ++n) { + list += Q3Dns::Server(QString::fromLatin1(results[n].name()), results[n].priority(), results[n].weight(), + results[n].port()); } d->nndns_busy = false; d->nndns.stop(); - if(list.isEmpty()) { + if (list.isEmpty()) { stop(); resultsReady(); return; @@ -226,43 +213,39 @@ void SrvResolver::nndns_resultsReady(const QList &results) sortSRVList(list); d->servers = list; - if(d->srvonly) + if (d->srvonly) resultsReady(); else { // kick it off d->aaaa = true; tryNext(); } - } - else { + } else { // grab the address list and destroy the qdns object QList list; - if(d->nntype == XMPP::NameRecord::A || d->nntype == XMPP::NameRecord::Aaaa) - { - for(int n = 0; n < results.count(); ++n) - { + if (d->nntype == XMPP::NameRecord::A || d->nntype == XMPP::NameRecord::Aaaa) { + for (int n = 0; n < results.count(); ++n) { list += results[n].address(); } } d->nndns_busy = false; d->nndns.stop(); - if(!list.isEmpty()) { + if (!list.isEmpty()) { int port = d->servers.first().port; d->servers.removeFirst(); d->aaaa = true; d->resultAddress = list.first(); - d->resultPort = port; + d->resultPort = port; resultsReady(); - } - else { - if(!d->aaaa) + } else { + if (!d->aaaa) d->servers.removeFirst(); d->aaaa = !d->aaaa; // failed? bail if last one - if(d->servers.isEmpty()) { + if (d->servers.isEmpty()) { stop(); resultsReady(); return; @@ -274,26 +257,22 @@ void SrvResolver::nndns_resultsReady(const QList &results) } } -void SrvResolver::nndns_error(XMPP::NameResolver::Error) -{ - nndns_resultsReady(QList()); -} +void SrvResolver::nndns_error(XMPP::NameResolver::Error) { nndns_resultsReady(QList()); } void SrvResolver::ndns_done() { #ifndef NO_NDNS - QHostAddress r = d->ndns.result(); - int port = d->servers.first().port; + QHostAddress r = d->ndns.result(); + int port = d->servers.first().port; d->servers.removeFirst(); - if(!r.isNull()) { + if (!r.isNull()) { d->resultAddress = d->ndns.result(); - d->resultPort = port; + d->resultPort = port; resultsReady(); - } - else { + } else { // failed? bail if last one - if(d->servers.isEmpty()) { + if (d->servers.isEmpty()) { stop(); resultsReady(); return; diff --git a/src/irisnet/noncore/legacy/srvresolver.h b/src/irisnet/noncore/legacy/srvresolver.h index ecca77e5..ded8502a 100644 --- a/src/irisnet/noncore/legacy/srvresolver.h +++ b/src/irisnet/noncore/legacy/srvresolver.h @@ -26,14 +26,14 @@ #include // CS_NAMESPACE_BEGIN -class Q3Dns -{ +class Q3Dns { public: - class Server - { + class Server { public: - Server(const QString &n = QString(), quint16 p = 0, quint16 w = 0, quint16 po = 0) - :name(n), priority(p), weight(w), port(po) {} + Server(const QString &n = QString(), quint16 p = 0, quint16 w = 0, quint16 po = 0) : + name(n), priority(p), weight(w), port(po) + { + } QString name; quint16 priority; @@ -42,11 +42,10 @@ class Q3Dns }; }; -class SrvResolver : public QObject -{ +class SrvResolver : public QObject { Q_OBJECT public: - SrvResolver(QObject *parent=nullptr); + SrvResolver(QObject *parent = nullptr); ~SrvResolver(); void resolve(const QString &server, const QString &type, const QString &proto); @@ -57,9 +56,9 @@ class SrvResolver : public QObject QList servers() const; - bool failed() const; + bool failed() const; QHostAddress resultAddress() const; - quint16 resultPort() const; + quint16 resultPort() const; signals: void resultsReady(); diff --git a/src/irisnet/noncore/processquit.cpp b/src/irisnet/noncore/processquit.cpp index 6c05f2ba..049cefdf 100644 --- a/src/irisnet/noncore/processquit.cpp +++ b/src/irisnet/noncore/processquit.cpp @@ -19,18 +19,18 @@ #include "processquit.h" #ifndef NO_IRISNET -# include "irisnetglobal_p.h" +#include "irisnetglobal_p.h" #endif #ifdef QT_GUI_LIB -# include +#include #endif #ifdef Q_OS_UNIX -# include -# include +#include +#include #endif #ifdef Q_OS_WIN -# include +#include #endif namespace { @@ -42,13 +42,10 @@ void releaseAndDeleteLater(QObject *owner, QObject *obj) obj->deleteLater(); } -class SafeSocketNotifier : public QObject -{ +class SafeSocketNotifier : public QObject { Q_OBJECT public: - SafeSocketNotifier(int socket, QSocketNotifier::Type type, - QObject *parent = nullptr) : - QObject(parent) + SafeSocketNotifier(int socket, QSocketNotifier::Type type, QObject *parent = nullptr) : QObject(parent) { sn = new QSocketNotifier(socket, type, this); connect(sn, SIGNAL(activated(int)), SIGNAL(activated(int))); @@ -60,12 +57,12 @@ class SafeSocketNotifier : public QObject releaseAndDeleteLater(this, sn); } - bool isEnabled() const { return sn->isEnabled(); } - int socket() const { return sn->socket(); } + bool isEnabled() const { return sn->isEnabled(); } + int socket() const { return sn->socket(); } QSocketNotifier::Type type() const { return sn->type(); } public slots: - void setEnabled(bool enable) { sn->setEnabled(enable); } + void setEnabled(bool enable) { sn->setEnabled(enable); } signals: void activated(int socket); @@ -91,8 +88,7 @@ inline bool is_gui_app() #endif } -class ProcessQuit::Private : public QObject -{ +class ProcessQuit::Private : public QObject { Q_OBJECT public: ProcessQuit *q; @@ -102,7 +98,7 @@ class ProcessQuit::Private : public QObject bool use_handler; #endif #ifdef Q_OS_UNIX - int sig_pipe[2]; + int sig_pipe[2]; SafeSocketNotifier *sig_notifier; #endif @@ -111,12 +107,11 @@ class ProcessQuit::Private : public QObject done = false; #ifdef Q_OS_WIN use_handler = !is_gui_app(); - if(use_handler) + if (use_handler) SetConsoleCtrlHandler((PHANDLER_ROUTINE)winHandler, TRUE); #endif #ifdef Q_OS_UNIX - if(pipe(sig_pipe) == -1) - { + if (pipe(sig_pipe) == -1) { // no support then return; } @@ -132,7 +127,7 @@ class ProcessQuit::Private : public QObject ~Private() { #ifdef Q_OS_WIN - if(use_handler) + if (use_handler) SetConsoleCtrlHandler((PHANDLER_ROUTINE)winHandler, FALSE); #endif #ifdef Q_OS_UNIX @@ -159,8 +154,7 @@ class ProcessQuit::Private : public QObject { Q_UNUSED(sig); unsigned char c = 0; - if(::write(g_pq->d->sig_pipe[1], &c, 1) == -1) - { + if (::write(g_pq->d->sig_pipe[1], &c, 1) == -1) { // TODO: error handling? return; } @@ -172,10 +166,10 @@ class ProcessQuit::Private : public QObject sigaction(sig, nullptr, &sa); // if the signal is ignored, don't take it over. this is // recommended by the glibc manual - if(sa.sa_handler == SIG_IGN) + if (sa.sa_handler == SIG_IGN) return; sigemptyset(&(sa.sa_mask)); - sa.sa_flags = 0; + sa.sa_flags = 0; sa.sa_handler = unixHandler; sigaction(sig, &sa, nullptr); } @@ -186,10 +180,10 @@ class ProcessQuit::Private : public QObject sigaction(sig, nullptr, &sa); // ignored means we skipped it earlier, so we should // skip it again - if(sa.sa_handler == SIG_IGN) + if (sa.sa_handler == SIG_IGN) return; sigemptyset(&(sa.sa_mask)); - sa.sa_flags = 0; + sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigaction(sig, &sa, nullptr); } @@ -207,8 +201,7 @@ public slots: { #ifdef Q_OS_UNIX unsigned char c; - if(::read(sig_pipe[0], &c, 1) == -1) - { + if (::read(sig_pipe[0], &c, 1) == -1) { // TODO: error handling? return; } @@ -221,30 +214,21 @@ public slots: void do_emit() { // only signal once - if(!done) - { + if (!done) { done = true; emit q->quit(); } } }; -ProcessQuit::ProcessQuit(QObject *parent) -:QObject(parent) -{ - d = new Private(this); -} +ProcessQuit::ProcessQuit(QObject *parent) : QObject(parent) { d = new Private(this); } -ProcessQuit::~ProcessQuit() -{ - delete d; -} +ProcessQuit::~ProcessQuit() { delete d; } ProcessQuit *ProcessQuit::instance() { QMutexLocker locker(pq_mutex()); - if(!g_pq) - { + if (!g_pq) { g_pq = new ProcessQuit; g_pq->moveToThread(QCoreApplication::instance()->thread()); #ifndef NO_IRISNET @@ -257,7 +241,7 @@ ProcessQuit *ProcessQuit::instance() void ProcessQuit::reset() { QMutexLocker locker(pq_mutex()); - if(g_pq) + if (g_pq) g_pq->d->done = false; } diff --git a/src/irisnet/noncore/processquit.h b/src/irisnet/noncore/processquit.h index 363088ca..26cc3958 100644 --- a/src/irisnet/noncore/processquit.h +++ b/src/irisnet/noncore/processquit.h @@ -20,10 +20,10 @@ #define PROCESSQUIT_H #ifdef NO_IRISNET -# include -# define IRISNET_EXPORT +#include +#define IRISNET_EXPORT #else -# include "irisnetglobal.h" +#include "irisnetglobal.h" #endif #ifndef NO_IRISNET @@ -55,8 +55,7 @@ myapp.connect(ProcessQuit::instance(), SIGNAL(quit()), SLOT(do_quit())); The quit() signal is emitted when a request to terminate is received. The quit() signal is only emitted once, future termination requests are ignored. Call reset() to allow the quit() signal to be emitted again. */ -class IRISNET_EXPORT ProcessQuit : public QObject -{ +class IRISNET_EXPORT ProcessQuit : public QObject { Q_OBJECT public: /** @@ -71,7 +70,10 @@ class IRISNET_EXPORT ProcessQuit : public QObject /** \brief Allows the quit() signal to be emitted again - ProcessQuit only emits the quit() signal once, so that if a user repeatedly presses Ctrl-C or sends SIGTERM, your shutdown slot will not be called multiple times. This is normally the desired behavior, but if you are ignoring the termination request then you may want to allow future notifications. Calling this function will allow the quit() signal to be emitted again, if a new termination request arrives. + ProcessQuit only emits the quit() signal once, so that if a user repeatedly presses Ctrl-C or sends SIGTERM, your + shutdown slot will not be called multiple times. This is normally the desired behavior, but if you are ignoring + the termination request then you may want to allow future notifications. Calling this function will allow the + quit() signal to be emitted again, if a new termination request arrives. \sa quit */ @@ -80,7 +82,9 @@ class IRISNET_EXPORT ProcessQuit : public QObject /** \brief Frees all resources used by ProcessQuit - This function will free any resources used by ProcessQuit, including the global instance, and the termination handlers will be uninstalled (reverted to default). Future termination requests will cause the application to exit abruptly. + This function will free any resources used by ProcessQuit, including the global instance, and the termination + handlers will be uninstalled (reverted to default). Future termination requests will cause the application to + exit abruptly. \note You normally do not need to call this function directly. When IrisNet cleans up, it will be called. @@ -92,9 +96,11 @@ class IRISNET_EXPORT ProcessQuit : public QObject /** \brief Notification of termination request - This signal is emitted when a termination request is received. It is only emitted once, unless reset() is called. + This signal is emitted when a termination request is received. It is only emitted once, unless reset() is + called. - Upon receiving this signal, the application should proceed to exit gracefully, and generally without user interaction. + Upon receiving this signal, the application should proceed to exit gracefully, and generally without user + interaction. \sa reset */ diff --git a/src/irisnet/noncore/stunallocate.cpp b/src/irisnet/noncore/stunallocate.cpp index 96ee4ea4..2ae8f479 100644 --- a/src/irisnet/noncore/stunallocate.cpp +++ b/src/irisnet/noncore/stunallocate.cpp @@ -30,10 +30,10 @@ #include // permissions last 5 minutes, update them every 4 minutes -#define PERM_INTERVAL (4 * 60 * 1000) +#define PERM_INTERVAL (4 * 60 * 1000) // channels last 10 minutes, update them every 9 minutes -#define CHAN_INTERVAL (9 * 60 * 1000) +#define CHAN_INTERVAL (9 * 60 * 1000) namespace XMPP { void releaseAndDeleteLater(QObject *owner, QObject *obj) @@ -47,58 +47,45 @@ void releaseAndDeleteLater(QObject *owner, QObject *obj) static int check_channelData(const quint8 *data, int size) { // top two bits are never zero for ChannelData - if((data[0] & 0xc0) == 0) + if ((data[0] & 0xc0) == 0) return -1; - if(size < 4) + if (size < 4) return -1; quint16 len = StunUtil::read16(data + 2); - if(size - 4 < (int)len) + if (size - 4 < (int)len) return -1; // data from a stream must be 4 byte aligned - int plen = len; + int plen = len; int remainder = plen % 4; - if(remainder != 0) + if (remainder != 0) plen += (4 - remainder); int need = plen + 4; - if(size < need) + if (size < need) return -1; return need; } -class StunAllocatePermission : public QObject -{ +class StunAllocatePermission : public QObject { Q_OBJECT public: - QTimer *timer; + QTimer * timer; StunTransactionPool *pool; - StunTransaction *trans; - QHostAddress stunAddr; - int stunPort; - QHostAddress addr; - bool active; + StunTransaction * trans; + QHostAddress stunAddr; + int stunPort; + QHostAddress addr; + bool active; - enum Error - { - ErrorGeneric, - ErrorProtocol, - ErrorCapacity, - ErrorForbidden, - ErrorRejected, - ErrorTimeout - }; + enum Error { ErrorGeneric, ErrorProtocol, ErrorCapacity, ErrorForbidden, ErrorRejected, ErrorTimeout }; StunAllocatePermission(StunTransactionPool *_pool, const QHostAddress &_addr) : - QObject(_pool), - pool(_pool), - trans(nullptr), - addr(_addr), - active(false) + QObject(_pool), pool(_pool), trans(nullptr), addr(_addr), active(false) { timer = new QTimer(this); connect(timer, SIGNAL(timeout()), SLOT(timer_timeout())); @@ -125,19 +112,18 @@ class StunAllocatePermission : public QObject static StunAllocate::Error errorToStunAllocateError(Error e) { - switch(e) - { - case ErrorProtocol: - return StunAllocate::ErrorProtocol; - case ErrorCapacity: - return StunAllocate::ErrorCapacity; - case ErrorForbidden: - case ErrorRejected: - return StunAllocate::ErrorRejected; - case ErrorTimeout: - return StunAllocate::ErrorTimeout; - default: - return StunAllocate::ErrorGeneric; + switch (e) { + case ErrorProtocol: + return StunAllocate::ErrorProtocol; + case ErrorCapacity: + return StunAllocate::ErrorCapacity; + case ErrorForbidden: + case ErrorRejected: + return StunAllocate::ErrorRejected; + case ErrorTimeout: + return StunAllocate::ErrorTimeout; + default: + return StunAllocate::ErrorGeneric; } } @@ -166,10 +152,7 @@ class StunAllocatePermission : public QObject trans->start(pool, stunAddr, stunPort); } - void restartTimer() - { - timer->start(); - } + void restartTimer() { timer->start(); } private slots: void trans_createMessage(const QByteArray &transactionId) @@ -187,7 +170,7 @@ private slots: { StunMessage::Attribute a; - a.type = StunTypes::XOR_PEER_ADDRESS; + a.type = StunTypes::XOR_PEER_ADDRESS; a.value = StunTypes::createXorPeerAddress(addr, 0, message.magic(), message.id()); list += a; } @@ -202,13 +185,11 @@ private slots: delete trans; trans = nullptr; - bool err = false; - int code; + bool err = false; + int code; QString reason; - if(response.mclass() == StunMessage::ErrorResponse) - { - if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) - { + if (response.mclass() == StunMessage::ErrorResponse) { + if (!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) { cleanup(); emit error(ErrorProtocol, "Unable to parse ERROR-CODE in error response."); return; @@ -217,13 +198,12 @@ private slots: err = true; } - if(err) - { + if (err) { cleanup(); - if(code == StunTypes::InsufficientCapacity) + if (code == StunTypes::InsufficientCapacity) emit error(ErrorCapacity, reason); - else if(code == StunTypes::Forbidden) + else if (code == StunTypes::Forbidden) emit error(ErrorForbidden, reason); else emit error(ErrorRejected, reason); @@ -233,8 +213,7 @@ private slots: restartTimer(); - if(!active) - { + if (!active) { active = true; emit ready(); } @@ -244,51 +223,33 @@ private slots: { cleanup(); - if(e == XMPP::StunTransaction::ErrorTimeout) + if (e == XMPP::StunTransaction::ErrorTimeout) emit error(ErrorTimeout, "Request timed out."); else emit error(ErrorGeneric, "Generic transaction error."); } - void timer_timeout() - { - doTransaction(); - } + void timer_timeout() { doTransaction(); } }; -class StunAllocateChannel : public QObject -{ +class StunAllocateChannel : public QObject { Q_OBJECT public: - QTimer *timer; + QTimer * timer; StunTransactionPool *pool; - StunTransaction *trans; - QHostAddress stunAddr; - int stunPort; - int channelId; - QHostAddress addr; - int port; - bool active; - - enum Error - { - ErrorGeneric, - ErrorProtocol, - ErrorCapacity, - ErrorForbidden, - ErrorRejected, - ErrorTimeout - }; + StunTransaction * trans; + QHostAddress stunAddr; + int stunPort; + int channelId; + QHostAddress addr; + int port; + bool active; + + enum Error { ErrorGeneric, ErrorProtocol, ErrorCapacity, ErrorForbidden, ErrorRejected, ErrorTimeout }; StunAllocateChannel(StunTransactionPool *_pool, int _channelId, const QHostAddress &_addr, int _port) : - QObject(_pool), - pool(_pool), - trans(nullptr), - channelId(_channelId), - addr(_addr), - port(_port), - active(false) + QObject(_pool), pool(_pool), trans(nullptr), channelId(_channelId), addr(_addr), port(_port), active(false) { timer = new QTimer(this); connect(timer, SIGNAL(timeout()), SLOT(timer_timeout())); @@ -315,19 +276,18 @@ class StunAllocateChannel : public QObject static StunAllocate::Error errorToStunAllocateError(Error e) { - switch(e) - { - case ErrorProtocol: - return StunAllocate::ErrorProtocol; - case ErrorCapacity: - return StunAllocate::ErrorCapacity; - case ErrorForbidden: - case ErrorRejected: - return StunAllocate::ErrorRejected; - case ErrorTimeout: - return StunAllocate::ErrorTimeout; - default: - return StunAllocate::ErrorGeneric; + switch (e) { + case ErrorProtocol: + return StunAllocate::ErrorProtocol; + case ErrorCapacity: + return StunAllocate::ErrorCapacity; + case ErrorForbidden: + case ErrorRejected: + return StunAllocate::ErrorRejected; + case ErrorTimeout: + return StunAllocate::ErrorTimeout; + default: + return StunAllocate::ErrorGeneric; } } @@ -344,7 +304,7 @@ class StunAllocateChannel : public QObject timer->stop(); channelId = -1; - active = false; + active = false; } void doTransaction() @@ -357,10 +317,7 @@ class StunAllocateChannel : public QObject trans->start(pool, stunAddr, stunPort); } - void restartTimer() - { - timer->start(); - } + void restartTimer() { timer->start(); } private slots: void trans_createMessage(const QByteArray &transactionId) @@ -374,14 +331,14 @@ private slots: { StunMessage::Attribute a; - a.type = StunTypes::CHANNEL_NUMBER; + a.type = StunTypes::CHANNEL_NUMBER; a.value = StunTypes::createChannelNumber(channelId); list += a; } { StunMessage::Attribute a; - a.type = StunTypes::XOR_PEER_ADDRESS; + a.type = StunTypes::XOR_PEER_ADDRESS; a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id()); list += a; } @@ -396,13 +353,11 @@ private slots: delete trans; trans = nullptr; - bool err = false; - int code; + bool err = false; + int code; QString reason; - if(response.mclass() == StunMessage::ErrorResponse) - { - if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) - { + if (response.mclass() == StunMessage::ErrorResponse) { + if (!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) { cleanup(); emit error(ErrorProtocol, "Unable to parse ERROR-CODE in error response."); return; @@ -411,13 +366,12 @@ private slots: err = true; } - if(err) - { + if (err) { cleanup(); - if(code == StunTypes::InsufficientCapacity) + if (code == StunTypes::InsufficientCapacity) emit error(ErrorCapacity, reason); - else if(code == StunTypes::Forbidden) + else if (code == StunTypes::Forbidden) emit error(ErrorForbidden, reason); else emit error(ErrorRejected, reason); @@ -427,8 +381,7 @@ private slots: restartTimer(); - if(!active) - { + if (!active) { active = true; emit ready(); } @@ -438,32 +391,22 @@ private slots: { cleanup(); - if(e == XMPP::StunTransaction::ErrorTimeout) + if (e == XMPP::StunTransaction::ErrorTimeout) emit error(ErrorTimeout, "Request timed out."); else emit error(ErrorGeneric, "Generic transaction error."); } - void timer_timeout() - { - doTransaction(); - } + void timer_timeout() { doTransaction(); } }; -class StunAllocate::Private : public QObject -{ +class StunAllocate::Private : public QObject { Q_OBJECT public: - enum DontFragmentState - { - DF_Unknown, - DF_Supported, - DF_Unsupported - }; + enum DontFragmentState { DF_Unknown, DF_Supported, DF_Unsupported }; - enum State - { + enum State { Stopped, Starting, Started, @@ -472,36 +415,30 @@ class StunAllocate::Private : public QObject Erroring // like stopping, but emits error when finished }; - StunAllocate *q; - ObjectSession sess; - StunTransactionPool *pool; - StunTransaction *trans; - QHostAddress stunAddr; - int stunPort; - State state; - QString errorString; - DontFragmentState dfState; - QString clientSoftware, serverSoftware; - QHostAddress reflexiveAddress, relayedAddress; - int reflexivePort, relayedPort; - StunMessage msg; - int allocateLifetime; - QTimer *allocateRefreshTimer; - QList perms; - QList channels; - QList permsOut; - QList channelsOut; - int erroringCode; - QString erroringString; + StunAllocate * q; + ObjectSession sess; + StunTransactionPool * pool; + StunTransaction * trans; + QHostAddress stunAddr; + int stunPort; + State state; + QString errorString; + DontFragmentState dfState; + QString clientSoftware, serverSoftware; + QHostAddress reflexiveAddress, relayedAddress; + int reflexivePort, relayedPort; + StunMessage msg; + int allocateLifetime; + QTimer * allocateRefreshTimer; + QList perms; + QList channels; + QList permsOut; + QList channelsOut; + int erroringCode; + QString erroringString; Private(StunAllocate *_q) : - QObject(_q), - q(_q), - sess(this), - pool(nullptr), - trans(nullptr), - state(Stopped), - dfState(DF_Unknown), + QObject(_q), q(_q), sess(this), pool(nullptr), trans(nullptr), state(Stopped), dfState(DF_Unknown), erroringCode(-1) { allocateRefreshTimer = new QTimer(this); @@ -530,7 +467,7 @@ class StunAllocate::Private : public QObject void stop() { // erroring already? no need to do anything - if(state == Erroring) + if (state == Erroring) return; Q_ASSERT(state == Started); @@ -545,16 +482,16 @@ class StunAllocate::Private : public QObject Q_ASSERT(state == Started); cleanupTasks(); - erroringCode = code; + erroringCode = code; erroringString = str; - state = Erroring; + state = Erroring; doTransaction(); } void setPermissions(const QList &newPerms) { // if currently erroring out, skip - if(state == Erroring) + if (state == Erroring) return; Q_ASSERT(state == Started); @@ -562,25 +499,19 @@ class StunAllocate::Private : public QObject int freeCount = 0; // removed? - for(int n = 0; n < perms.count(); ++n) - { + for (int n = 0; n < perms.count(); ++n) { bool found = false; - for(int k = 0; k < newPerms.count(); ++k) - { - if(newPerms[k] == perms[n]->addr) - { + for (int k = 0; k < newPerms.count(); ++k) { + if (newPerms[k] == perms[n]->addr) { found = true; break; } } - if(!found) - { + if (!found) { // delete related channels - for(int j = 0; j < channels.count(); ++j) - { - if(channels[j]->addr == perms[n]->addr) - { + for (int j = 0; j < channels.count(); ++j) { + if (channels[j]->addr == perms[n]->addr) { delete channels[j]; channels.removeAt(j); --j; // adjust position @@ -595,37 +526,32 @@ class StunAllocate::Private : public QObject } } - if(freeCount > 0) - { + if (freeCount > 0) { // removals count as a change, so emit the signal sess.deferExclusive(q, "permissionsChanged"); // wake up inactive perms now that we've freed space - for(int n = 0; n < perms.count(); ++n) - { - if(!perms[n]->active) + for (int n = 0; n < perms.count(); ++n) { + if (!perms[n]->active) perms[n]->start(stunAddr, stunPort); } } // added? - for(int n = 0; n < newPerms.count(); ++n) - { + for (int n = 0; n < newPerms.count(); ++n) { bool found = false; - for(int k = 0; k < perms.count(); ++k) - { - if(perms[k]->addr == newPerms[n]) - { + for (int k = 0; k < perms.count(); ++k) { + if (perms[k]->addr == newPerms[n]) { found = true; break; } } - if(!found) - { + if (!found) { StunAllocatePermission *perm = new StunAllocatePermission(pool, newPerms[n]); connect(perm, SIGNAL(ready()), SLOT(perm_ready())); - connect(perm, SIGNAL(error(XMPP::StunAllocatePermission::Error,QString)), SLOT(perm_error(XMPP::StunAllocatePermission::Error,QString))); + connect(perm, SIGNAL(error(XMPP::StunAllocatePermission::Error, QString)), + SLOT(perm_error(XMPP::StunAllocatePermission::Error, QString))); perms += perm; perm->start(stunAddr, stunPort); } @@ -635,7 +561,7 @@ class StunAllocate::Private : public QObject void setChannels(const QList &newChannels) { // if currently erroring out, skip - if(state == Erroring) + if (state == Erroring) return; Q_ASSERT(state == Started); @@ -643,20 +569,16 @@ class StunAllocate::Private : public QObject int freeCount = 0; // removed? - for(int n = 0; n < channels.count(); ++n) - { + for (int n = 0; n < channels.count(); ++n) { bool found = false; - for(int k = 0; k < newChannels.count(); ++k) - { - if(newChannels[k].address == channels[n]->addr && newChannels[k].port == channels[n]->port) - { + for (int k = 0; k < newChannels.count(); ++k) { + if (newChannels[k].address == channels[n]->addr && newChannels[k].port == channels[n]->port) { found = true; break; } } - if(!found) - { + if (!found) { ++freeCount; delete channels[n]; @@ -665,20 +587,17 @@ class StunAllocate::Private : public QObject } } - if(freeCount > 0) - { + if (freeCount > 0) { // removals count as a change, so emit the signal sess.deferExclusive(q, "channelsChanged"); // wake up inactive channels now that we've freed space - for(int n = 0; n < channels.count(); ++n) - { - if(!channels[n]->active) - { + for (int n = 0; n < channels.count(); ++n) { + if (!channels[n]->active) { int channelId = getFreeChannelNumber(); // out of channels? give up - if(channelId == -1) + if (channelId == -1) break; channels[n]->channelId = channelId; @@ -688,42 +607,37 @@ class StunAllocate::Private : public QObject } // added? - for(int n = 0; n < newChannels.count(); ++n) - { + for (int n = 0; n < newChannels.count(); ++n) { bool found = false; - for(int k = 0; k < channels.count(); ++k) - { - if(channels[k]->addr == newChannels[n].address && channels[k]->port == newChannels[n].port) - { + for (int k = 0; k < channels.count(); ++k) { + if (channels[k]->addr == newChannels[n].address && channels[k]->port == newChannels[n].port) { found = true; break; } } - if(!found) - { + if (!found) { // look up the permission for this channel int at = -1; - for(int k = 0; k < perms.count(); ++k) - { - if(perms[k]->addr == newChannels[n].address) - { + for (int k = 0; k < perms.count(); ++k) { + if (perms[k]->addr == newChannels[n].address) { at = k; break; } } // only install a channel if we have a permission - if(at != -1) - { + if (at != -1) { int channelId = getFreeChannelNumber(); - StunAllocateChannel *channel = new StunAllocateChannel(pool, channelId, newChannels[n].address, newChannels[n].port); + StunAllocateChannel *channel + = new StunAllocateChannel(pool, channelId, newChannels[n].address, newChannels[n].port); connect(channel, SIGNAL(ready()), SLOT(channel_ready())); - connect(channel, SIGNAL(error(XMPP::StunAllocateChannel::Error,QString)), SLOT(channel_error(XMPP::StunAllocateChannel::Error,QString))); + connect(channel, SIGNAL(error(XMPP::StunAllocateChannel::Error, QString)), + SLOT(channel_error(XMPP::StunAllocateChannel::Error, QString))); channels += channel; - if(channelId != -1) + if (channelId != -1) channel->start(stunAddr, stunPort); } } @@ -732,19 +646,16 @@ class StunAllocate::Private : public QObject int getFreeChannelNumber() { - for(int tryId = 0x4000; tryId <= 0x7fff; ++tryId) - { + for (int tryId = 0x4000; tryId <= 0x7fff; ++tryId) { bool found = false; - for(int n = 0; n < channels.count(); ++n) - { - if(channels[n]->channelId == tryId) - { + for (int n = 0; n < channels.count(); ++n) { + if (channels[n]->channelId == tryId) { found = true; break; } } - if(!found) + if (!found) return tryId; } @@ -753,9 +664,8 @@ class StunAllocate::Private : public QObject int getChannel(const QHostAddress &addr, int port) { - for(int n = 0; n < channels.count(); ++n) - { - if(channels[n]->active && channels[n]->addr == addr && channels[n]->port == port) + for (int n = 0; n < channels.count(); ++n) { + if (channels[n]->active && channels[n]->addr == addr && channels[n]->port == port) return channels[n]->channelId; } @@ -767,10 +677,8 @@ class StunAllocate::Private : public QObject // ChannelBind success response is still processable bool getAddressPort(int channelId, QHostAddress *addr, int *port) { - for(int n = 0; n < channels.count(); ++n) - { - if(channels[n]->channelId == channelId) - { + for (int n = 0; n < channels.count(); ++n) { + if (channels[n]->channelId == channelId) { *addr = channels[n]->addr; *port = channels[n]->port; return true; @@ -830,13 +738,12 @@ class StunAllocate::Private : public QObject { QList newList; - for(int n = 0; n < perms.count(); ++n) - { - if(perms[n]->active) + for (int n = 0; n < perms.count(); ++n) { + if (perms[n]->active) newList += perms[n]->addr; } - if(newList == permsOut) + if (newList == permsOut) return false; permsOut = newList; @@ -847,13 +754,12 @@ class StunAllocate::Private : public QObject { QList newList; - for(int n = 0; n < channels.count(); ++n) - { - if(channels[n]->active) + for (int n = 0; n < channels.count(); ++n) { + if (channels[n]->active) newList += StunAllocate::Channel(channels[n]->addr, channels[n]->port); } - if(newList == channelsOut) + if (newList == channelsOut) return false; channelsOut = newList; @@ -871,8 +777,7 @@ private slots: void trans_createMessage(const QByteArray &transactionId) { - if(state == Starting) - { + if (state == Starting) { // send Allocate request StunMessage message; message.setMethod(StunTypes::Allocate); @@ -880,30 +785,28 @@ private slots: QList list; - if(!clientSoftware.isEmpty()) - { + if (!clientSoftware.isEmpty()) { StunMessage::Attribute a; - a.type = StunTypes::SOFTWARE; + a.type = StunTypes::SOFTWARE; a.value = StunTypes::createSoftware(clientSoftware); list += a; } { StunMessage::Attribute a; - a.type = StunTypes::LIFETIME; + a.type = StunTypes::LIFETIME; a.value = StunTypes::createLifetime(3600); list += a; } { StunMessage::Attribute a; - a.type = StunTypes::REQUESTED_TRANSPORT; + a.type = StunTypes::REQUESTED_TRANSPORT; a.value = StunTypes::createRequestedTransport(17); // 17=UDP list += a; } - if(dfState == DF_Unknown) - { + if (dfState == DF_Unknown) { StunMessage::Attribute a; a.type = StunTypes::DONT_FRAGMENT; list += a; @@ -912,9 +815,7 @@ private slots: message.setAttributes(list); trans->setMessage(message); - } - else if(state == Stopping || state == Erroring) - { + } else if (state == Stopping || state == Erroring) { StunMessage message; message.setMethod(StunTypes::Refresh); message.setId((const quint8 *)transactionId.data()); @@ -923,7 +824,7 @@ private slots: { StunMessage::Attribute a; - a.type = StunTypes::LIFETIME; + a.type = StunTypes::LIFETIME; a.value = StunTypes::createLifetime(0); list += a; } @@ -931,9 +832,7 @@ private slots: message.setAttributes(list); trans->setMessage(message); - } - else if(state == Refreshing) - { + } else if (state == Refreshing) { StunMessage message; message.setMethod(StunTypes::Refresh); message.setId((const quint8 *)transactionId.data()); @@ -942,7 +841,7 @@ private slots: { StunMessage::Attribute a; - a.type = StunTypes::LIFETIME; + a.type = StunTypes::LIFETIME; a.value = StunTypes::createLifetime(3600); list += a; } @@ -958,13 +857,11 @@ private slots: delete trans; trans = nullptr; - bool error = false; - int code; + bool error = false; + int code; QString reason; - if(response.mclass() == StunMessage::ErrorResponse) - { - if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) - { + if (response.mclass() == StunMessage::ErrorResponse) { + if (!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) { cleanup(); errorString = "Unable to parse ERROR-CODE in error response."; emit q->error(StunAllocate::ErrorProtocol); @@ -974,60 +871,46 @@ private slots: error = true; } - if(state == Starting) - { - if(error) - { - if(code == StunTypes::UnknownAttribute) - { + if (state == Starting) { + if (error) { + if (code == StunTypes::UnknownAttribute) { QList typeList; - if(!StunTypes::parseUnknownAttributes(response.attribute(StunTypes::UNKNOWN_ATTRIBUTES), &typeList)) - { + if (!StunTypes::parseUnknownAttributes(response.attribute(StunTypes::UNKNOWN_ATTRIBUTES), + &typeList)) { cleanup(); errorString = "Unable to parse UNKNOWN-ATTRIBUTES in 420 (Unknown Attribute) error response."; emit q->error(StunAllocate::ErrorProtocol); return; } - if(typeList.contains(StunTypes::DONT_FRAGMENT)) - { + if (typeList.contains(StunTypes::DONT_FRAGMENT)) { dfState = DF_Unsupported; // stay in same state, try again doTransaction(); - } - else - { + } else { cleanup(); errorString = reason; emit q->error(StunAllocate::ErrorGeneric); } return; - } - else if(code == StunTypes::AllocationMismatch) - { + } else if (code == StunTypes::AllocationMismatch) { cleanup(); errorString = "437 (Allocation Mismatch)."; emit q->error(StunAllocate::ErrorMismatch); return; - } - else if(code == StunTypes::InsufficientCapacity) - { + } else if (code == StunTypes::InsufficientCapacity) { cleanup(); errorString = reason; emit q->error(StunAllocate::ErrorCapacity); return; - } - else if(code == StunTypes::Unauthorized) - { + } else if (code == StunTypes::Unauthorized) { cleanup(); errorString = "Unauthorized"; emit q->error(StunAllocate::ErrorAuth); return; - } - else - { + } else { cleanup(); errorString = reason; emit q->error(StunAllocate::ErrorGeneric); @@ -1036,8 +919,7 @@ private slots: } quint32 lifetime; - if(!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime)) - { + if (!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime)) { cleanup(); errorString = "Unable to parse LIFETIME."; emit q->error(StunAllocate::ErrorProtocol); @@ -1045,9 +927,9 @@ private slots: } QHostAddress raddr; - quint16 rport; - if(!StunTypes::parseXorRelayedAddress(response.attribute(StunTypes::XOR_RELAYED_ADDRESS), response.magic(), response.id(), &raddr, &rport)) - { + quint16 rport; + if (!StunTypes::parseXorRelayedAddress(response.attribute(StunTypes::XOR_RELAYED_ADDRESS), response.magic(), + response.id(), &raddr, &rport)) { cleanup(); errorString = "Unable to parse XOR-RELAYED-ADDRESS."; emit q->error(StunAllocate::ErrorProtocol); @@ -1055,50 +937,43 @@ private slots: } QHostAddress saddr; - quint16 sport; - if(!StunTypes::parseXorMappedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), response.id(), &saddr, &sport)) - { + quint16 sport; + if (!StunTypes::parseXorMappedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), + response.id(), &saddr, &sport)) { cleanup(); errorString = "Unable to parse XOR-MAPPED-ADDRESS."; emit q->error(StunAllocate::ErrorProtocol); return; } - if(lifetime < 120) - { + if (lifetime < 120) { state = Started; // stopWithError requires this - stopWithError(StunAllocate::ErrorProtocol, - "LIFETIME is less than two minutes. That is ridiculous."); + stopWithError(StunAllocate::ErrorProtocol, "LIFETIME is less than two minutes. That is ridiculous."); return; } QString str; - if(StunTypes::parseSoftware(response.attribute(StunTypes::SOFTWARE), &str)) - { + if (StunTypes::parseSoftware(response.attribute(StunTypes::SOFTWARE), &str)) { serverSoftware = str; } allocateLifetime = lifetime; - relayedAddress = raddr; - relayedPort = rport; + relayedAddress = raddr; + relayedPort = rport; reflexiveAddress = saddr; - reflexivePort = sport; + reflexivePort = sport; - if(dfState == DF_Unknown) + if (dfState == DF_Unknown) dfState = DF_Supported; state = Started; restartRefreshTimer(); emit q->started(); - } - else if(state == Stopping || state == Erroring) - { - if(error) - { + } else if (state == Stopping || state == Erroring) { + if (error) { // AllocationMismatch on session cancel doesn't count as an error - if(code != StunTypes::AllocationMismatch) - { + if (code != StunTypes::AllocationMismatch) { cleanup(); errorString = reason; emit q->error(StunAllocate::ErrorGeneric); @@ -1106,27 +981,22 @@ private slots: } } - if(state == Stopping) - { + if (state == Stopping) { // cleanup will set the state to Stopped cleanup(); emit q->stopped(); - } - else // Erroring + } else // Erroring { - int code = erroringCode; - QString str = erroringString; + int code = erroringCode; + QString str = erroringString; // cleanup will set the state to Stopped cleanup(); errorString = str; emit q->error((StunAllocate::Error)code); } - } - else if(state == Refreshing) - { - if(error) - { + } else if (state == Refreshing) { + if (error) { cleanup(); errorString = reason; emit q->error(StunAllocate::ErrorRejected); @@ -1134,8 +1004,7 @@ private slots: } quint32 lifetime; - if(!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime)) - { + if (!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime)) { cleanup(); errorString = "Unable to parse LIFETIME."; emit q->error(StunAllocate::ErrorProtocol); @@ -1151,25 +1020,22 @@ private slots: void perm_ready() { - if(updatePermsOut()) + if (updatePermsOut()) emit q->permissionsChanged(); } void perm_error(XMPP::StunAllocatePermission::Error e, const QString &reason) { - if(e == StunAllocatePermission::ErrorCapacity) - { + if (e == StunAllocatePermission::ErrorCapacity) { // if we aren't allowed to make anymore permissions, // don't consider this an error. the perm stays // in the list inactive. we'll try it again if // any perms get removed. return; - } - else if(e == StunAllocatePermission::ErrorForbidden) - { + } else if (e == StunAllocatePermission::ErrorForbidden) { // silently discard the permission request StunAllocatePermission *perm = static_cast(sender()); - QHostAddress addr = perm->addr; + QHostAddress addr = perm->addr; delete perm; perms.removeAll(perm); emit q->debugLine(QString("Warning: permission forbidden to %1").arg(addr.toString())); @@ -1183,14 +1049,13 @@ private slots: void channel_ready() { - if(updateChannelsOut()) + if (updateChannelsOut()) emit q->channelsChanged(); } void channel_error(XMPP::StunAllocateChannel::Error e, const QString &reason) { - if(e == StunAllocateChannel::ErrorCapacity) - { + if (e == StunAllocateChannel::ErrorCapacity) { // if we aren't allowed to make anymore channels, // don't consider this an error. the channel stays // in the list inactive. we'll try it again if @@ -1210,118 +1075,66 @@ private slots: cleanup(); - if(e == StunTransaction::ErrorTimeout) - { + if (e == StunTransaction::ErrorTimeout) { errorString = "Request timed out."; emit q->error(StunAllocate::ErrorTimeout); - } - else - { + } else { errorString = "Generic transaction error."; emit q->error(StunAllocate::ErrorGeneric); } } }; -StunAllocate::StunAllocate(StunTransactionPool *pool) : - QObject(pool) +StunAllocate::StunAllocate(StunTransactionPool *pool) : QObject(pool) { - d = new Private(this); + d = new Private(this); d->pool = pool; } -StunAllocate::~StunAllocate() -{ - delete d; -} +StunAllocate::~StunAllocate() { delete d; } -void StunAllocate::setClientSoftwareNameAndVersion(const QString &str) -{ - d->clientSoftware = str; -} +void StunAllocate::setClientSoftwareNameAndVersion(const QString &str) { d->clientSoftware = str; } -void StunAllocate::start() -{ - d->start(); -} +void StunAllocate::start() { d->start(); } -void StunAllocate::start(const QHostAddress &addr, int port) -{ - d->start(addr, port); -} +void StunAllocate::start(const QHostAddress &addr, int port) { d->start(addr, port); } -void StunAllocate::stop() -{ - d->stop(); -} +void StunAllocate::stop() { d->stop(); } -QString StunAllocate::serverSoftwareNameAndVersion() const -{ - return d->serverSoftware; -} +QString StunAllocate::serverSoftwareNameAndVersion() const { return d->serverSoftware; } -QHostAddress StunAllocate::reflexiveAddress() const -{ - return d->reflexiveAddress; -} +QHostAddress StunAllocate::reflexiveAddress() const { return d->reflexiveAddress; } -int StunAllocate::reflexivePort() const -{ - return d->reflexivePort; -} +int StunAllocate::reflexivePort() const { return d->reflexivePort; } -QHostAddress StunAllocate::relayedAddress() const -{ - return d->relayedAddress; -} +QHostAddress StunAllocate::relayedAddress() const { return d->relayedAddress; } -int StunAllocate::relayedPort() const -{ - return d->relayedPort; -} +int StunAllocate::relayedPort() const { return d->relayedPort; } -QList StunAllocate::permissions() const -{ - return d->permsOut; -} +QList StunAllocate::permissions() const { return d->permsOut; } -void StunAllocate::setPermissions(const QList &perms) -{ - d->setPermissions(perms); -} +void StunAllocate::setPermissions(const QList &perms) { d->setPermissions(perms); } -QList StunAllocate::channels() const -{ - return d->channelsOut; -} +QList StunAllocate::channels() const { return d->channelsOut; } -void StunAllocate::setChannels(const QList &channels) -{ - d->setChannels(channels); -} +void StunAllocate::setChannels(const QList &channels) { d->setChannels(channels); } int StunAllocate::packetHeaderOverhead(const QHostAddress &addr, int port) const { int channelId = d->getChannel(addr, port); - if(channelId != -1) - { + if (channelId != -1) { // overhead of ChannelData - if(d->pool->mode() == StunTransaction::Udp) + if (d->pool->mode() == StunTransaction::Udp) return 4; - else // Tcp + else // Tcp return 4 + 3; // add 3 for potential padding - } - else - { + } else { // we add 3 for potential padding - if(d->dfState == StunAllocate::Private::DF_Supported) - { + if (d->dfState == StunAllocate::Private::DF_Supported) { // overhead of STUN-based data, with DONT_FRAGMENT return 40 + 3; - } - else - { + } else { // overhead of STUN-based data, without DONT-FRAGMENT return 36 + 3; } @@ -1334,9 +1147,8 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & { int channelId = d->getChannel(addr, port); - if(channelId != -1) - { - if(datagram.size() > 65535) + if (channelId != -1) { + if (datagram.size() > 65535) return QByteArray(); quint16 num = channelId; @@ -1345,10 +1157,9 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & int plen = len; // in tcp mode, round to up to nearest 4 bytes - if(d->pool->mode() == StunTransaction::Tcp) - { + if (d->pool->mode() == StunTransaction::Tcp) { int remainder = plen % 4; - if(remainder != 0) + if (remainder != 0) plen += (4 - remainder); } @@ -1358,9 +1169,7 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & memcpy(out.data() + 4, datagram.data(), datagram.size()); return out; - } - else - { + } else { StunMessage message; message.setClass(StunMessage::Indication); message.setMethod(StunTypes::Send); @@ -1371,13 +1180,12 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & { StunMessage::Attribute a; - a.type = StunTypes::XOR_PEER_ADDRESS; + a.type = StunTypes::XOR_PEER_ADDRESS; a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id()); list += a; } - if(d->dfState == StunAllocate::Private::DF_Supported) - { + if (d->dfState == StunAllocate::Private::DF_Supported) { StunMessage::Attribute a; a.type = StunTypes::DONT_FRAGMENT; list += a; @@ -1385,7 +1193,7 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & { StunMessage::Attribute a; - a.type = StunTypes::DATA; + a.type = StunTypes::DATA; a.value = datagram; list += a; } @@ -1398,15 +1206,15 @@ QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress & QByteArray StunAllocate::decode(const QByteArray &encoded, QHostAddress *addr, int *port) { - if(encoded.size() < 4) + if (encoded.size() < 4) return QByteArray(); quint16 num = StunUtil::read16((const quint8 *)encoded.data()); quint16 len = StunUtil::read16((const quint8 *)encoded.data() + 2); - if(encoded.size() - 4 < (int)len) + if (encoded.size() - 4 < (int)len) return QByteArray(); - if(!d->getAddressPort(num, addr, port)) + if (!d->getAddressPort(num, addr, port)) return QByteArray(); return encoded.mid(4, len); @@ -1415,13 +1223,14 @@ QByteArray StunAllocate::decode(const QByteArray &encoded, QHostAddress *addr, i QByteArray StunAllocate::decode(const StunMessage &encoded, QHostAddress *addr, int *port) { QHostAddress paddr; - quint16 pport; + quint16 pport; - if(!StunTypes::parseXorPeerAddress(encoded.attribute(StunTypes::XOR_PEER_ADDRESS), encoded.magic(), encoded.id(), &paddr, &pport)) + if (!StunTypes::parseXorPeerAddress(encoded.attribute(StunTypes::XOR_PEER_ADDRESS), encoded.magic(), encoded.id(), + &paddr, &pport)) return QByteArray(); QByteArray data = encoded.attribute(StunTypes::DATA); - if(data.isNull()) + if (data.isNull()) return QByteArray(); *addr = paddr; @@ -1429,10 +1238,7 @@ QByteArray StunAllocate::decode(const StunMessage &encoded, QHostAddress *addr, return data; } -QString StunAllocate::errorString() const -{ - return d->errorString; -} +QString StunAllocate::errorString() const { return d->errorString; } bool StunAllocate::containsChannelData(const quint8 *data, int size) { @@ -1442,7 +1248,7 @@ bool StunAllocate::containsChannelData(const quint8 *data, int size) QByteArray StunAllocate::readChannelData(const quint8 *data, int size) { int len = check_channelData(data, size); - if(len != -1) + if (len != -1) return QByteArray((const char *)data, len); else return QByteArray(); diff --git a/src/irisnet/noncore/stunallocate.h b/src/irisnet/noncore/stunallocate.h index e802ddef..6dc7b88c 100644 --- a/src/irisnet/noncore/stunallocate.h +++ b/src/irisnet/noncore/stunallocate.h @@ -29,46 +29,28 @@ namespace XMPP { class StunMessage; class StunTransactionPool; -class StunAllocate : public QObject -{ +class StunAllocate : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric, - ErrorTimeout, - ErrorAuth, - ErrorRejected, - ErrorProtocol, - ErrorCapacity, - ErrorMismatch - }; + enum Error { ErrorGeneric, ErrorTimeout, ErrorAuth, ErrorRejected, ErrorProtocol, ErrorCapacity, ErrorMismatch }; - class Channel - { + class Channel { public: QHostAddress address; - int port; + int port; - Channel(const QHostAddress &_address, int _port) : - address(_address), - port(_port) - { - } + Channel(const QHostAddress &_address, int _port) : address(_address), port(_port) {} inline bool operator==(const Channel &other) { - if(address == other.address && port == other.port) + if (address == other.address && port == other.port) return true; else return false; } - inline bool operator!=(const Channel &other) - { - return !operator==(other); - } + inline bool operator!=(const Channel &other) { return !operator==(other); } }; StunAllocate(StunTransactionPool *pool); @@ -83,16 +65,16 @@ class StunAllocate : public QObject QString serverSoftwareNameAndVersion() const; QHostAddress reflexiveAddress() const; - int reflexivePort() const; + int reflexivePort() const; QHostAddress relayedAddress() const; - int relayedPort() const; + int relayedPort() const; QList permissions() const; - void setPermissions(const QList &perms); + void setPermissions(const QList &perms); QList channels() const; - void setChannels(const QList &channels); + void setChannels(const QList &channels); int packetHeaderOverhead(const QHostAddress &addr, int port) const; @@ -102,7 +84,7 @@ class StunAllocate : public QObject QString errorString() const; - static bool containsChannelData(const quint8 *data, int size); + static bool containsChannelData(const quint8 *data, int size); static QByteArray readChannelData(const quint8 *data, int size); signals: diff --git a/src/irisnet/noncore/stunbinding.cpp b/src/irisnet/noncore/stunbinding.cpp index 524097b2..86ca1a3a 100644 --- a/src/irisnet/noncore/stunbinding.cpp +++ b/src/irisnet/noncore/stunbinding.cpp @@ -25,43 +25,32 @@ #include namespace XMPP { -class StunBinding::Private : public QObject -{ +class StunBinding::Private : public QObject { Q_OBJECT public: - StunBinding *q; + StunBinding * q; StunTransactionPool *pool; - StunTransaction *trans; - QHostAddress stunAddr; - int stunPort; - QHostAddress addr; - int port; - QString errorString; - bool use_extPriority, use_extIceControlling, use_extIceControlled; - quint32 extPriority; - bool extUseCandidate; - quint64 extIceControlling, extIceControlled; - QString stuser, stpass; - bool fpRequired; + StunTransaction * trans; + QHostAddress stunAddr; + int stunPort; + QHostAddress addr; + int port; + QString errorString; + bool use_extPriority, use_extIceControlling, use_extIceControlled; + quint32 extPriority; + bool extUseCandidate; + quint64 extIceControlling, extIceControlled; + QString stuser, stpass; + bool fpRequired; Private(StunBinding *_q) : - QObject(_q), - q(_q), - pool(nullptr), - trans(nullptr), - use_extPriority(false), - use_extIceControlling(false), - use_extIceControlled(false), - extUseCandidate(false), - fpRequired(false) + QObject(_q), q(_q), pool(nullptr), trans(nullptr), use_extPriority(false), use_extIceControlling(false), + use_extIceControlled(false), extUseCandidate(false), fpRequired(false) { } - ~Private() - { - delete trans; - } + ~Private() { delete trans; } void start(const QHostAddress &_addr = QHostAddress(), int _port = -1) { @@ -75,8 +64,7 @@ class StunBinding::Private : public QObject connect(trans, SIGNAL(finished(XMPP::StunMessage)), SLOT(trans_finished(XMPP::StunMessage))); connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error))); - if(!stuser.isEmpty()) - { + if (!stuser.isEmpty()) { trans->setShortTermUsername(stuser); trans->setShortTermPassword(stpass); } @@ -95,33 +83,29 @@ private slots: QList list; - if(use_extPriority) - { + if (use_extPriority) { StunMessage::Attribute a; - a.type = StunTypes::PRIORITY; + a.type = StunTypes::PRIORITY; a.value = StunTypes::createPriority(extPriority); list += a; } - if(extUseCandidate) - { + if (extUseCandidate) { StunMessage::Attribute a; a.type = StunTypes::USE_CANDIDATE; list += a; } - if(use_extIceControlling) - { + if (use_extIceControlling) { StunMessage::Attribute a; - a.type = StunTypes::ICE_CONTROLLING; + a.type = StunTypes::ICE_CONTROLLING; a.value = StunTypes::createIceControlling(extIceControlling); list += a; } - if(use_extIceControlled) - { + if (use_extIceControlled) { StunMessage::Attribute a; - a.type = StunTypes::ICE_CONTROLLED; + a.type = StunTypes::ICE_CONTROLLED; a.value = StunTypes::createIceControlled(extIceControlled); list += a; } @@ -136,13 +120,11 @@ private slots: delete trans; trans = nullptr; - bool error = false; - int code; + bool error = false; + int code; QString reason; - if(response.mclass() == StunMessage::ErrorResponse) - { - if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) - { + if (response.mclass() == StunMessage::ErrorResponse) { + if (!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason)) { errorString = "Unable to parse ERROR-CODE in error response."; emit q->error(StunBinding::ErrorProtocol); return; @@ -151,10 +133,9 @@ private slots: error = true; } - if(error) - { + if (error) { errorString = reason; - if(code == StunTypes::RoleConflict) + if (code == StunTypes::RoleConflict) emit q->error(StunBinding::ErrorConflict); else emit q->error(StunBinding::ErrorRejected); @@ -162,33 +143,25 @@ private slots: } QHostAddress saddr; - quint16 sport = 0; + quint16 sport = 0; QByteArray val; val = response.attribute(StunTypes::XOR_MAPPED_ADDRESS); - if(!val.isNull()) - { - if(!StunTypes::parseXorMappedAddress(val, response.magic(), response.id(), &saddr, &sport)) - { + if (!val.isNull()) { + if (!StunTypes::parseXorMappedAddress(val, response.magic(), response.id(), &saddr, &sport)) { errorString = "Unable to parse XOR-MAPPED-ADDRESS response."; emit q->error(StunBinding::ErrorProtocol); return; } - } - else - { + } else { val = response.attribute(StunTypes::MAPPED_ADDRESS); - if(!val.isNull()) - { - if(!StunTypes::parseMappedAddress(val, &saddr, &sport)) - { + if (!val.isNull()) { + if (!StunTypes::parseMappedAddress(val, &saddr, &sport)) { errorString = "Unable to parse MAPPED-ADDRESS response."; emit q->error(StunBinding::ErrorProtocol); return; } - } - else - { + } else { errorString = "Response does not contain XOR-MAPPED-ADDRESS or MAPPED-ADDRESS."; emit q->error(StunBinding::ErrorProtocol); return; @@ -205,93 +178,59 @@ private slots: delete trans; trans = nullptr; - if(e == StunTransaction::ErrorTimeout) - { + if (e == StunTransaction::ErrorTimeout) { errorString = "Request timed out."; emit q->error(StunBinding::ErrorTimeout); - } - else - { + } else { errorString = "Generic transaction error."; emit q->error(StunBinding::ErrorGeneric); } } }; -StunBinding::StunBinding(StunTransactionPool *pool) : - QObject(pool) +StunBinding::StunBinding(StunTransactionPool *pool) : QObject(pool) { - d = new Private(this); + d = new Private(this); d->pool = pool; } -StunBinding::~StunBinding() -{ - delete d; -} +StunBinding::~StunBinding() { delete d; } void StunBinding::setPriority(quint32 i) { d->use_extPriority = true; - d->extPriority = i; + d->extPriority = i; } -void StunBinding::setUseCandidate(bool enabled) -{ - d->extUseCandidate = enabled; -} +void StunBinding::setUseCandidate(bool enabled) { d->extUseCandidate = enabled; } void StunBinding::setIceControlling(quint64 i) { d->use_extIceControlling = true; - d->extIceControlling = i; + d->extIceControlling = i; } void StunBinding::setIceControlled(quint64 i) { d->use_extIceControlled = true; - d->extIceControlled = i; + d->extIceControlled = i; } -void StunBinding::setShortTermUsername(const QString &username) -{ - d->stuser = username; -} +void StunBinding::setShortTermUsername(const QString &username) { d->stuser = username; } -void StunBinding::setShortTermPassword(const QString &password) -{ - d->stpass = password; -} +void StunBinding::setShortTermPassword(const QString &password) { d->stpass = password; } -void StunBinding::setFingerprintRequired(bool enabled) -{ - d->fpRequired = enabled; -} +void StunBinding::setFingerprintRequired(bool enabled) { d->fpRequired = enabled; } -void StunBinding::start() -{ - d->start(); -} +void StunBinding::start() { d->start(); } -void StunBinding::start(const QHostAddress &addr, int port) -{ - d->start(addr, port); -} +void StunBinding::start(const QHostAddress &addr, int port) { d->start(addr, port); } -QHostAddress StunBinding::reflexiveAddress() const -{ - return d->addr; -} +QHostAddress StunBinding::reflexiveAddress() const { return d->addr; } -int StunBinding::reflexivePort() const -{ - return d->port; -} +int StunBinding::reflexivePort() const { return d->port; } -QString StunBinding::errorString() const -{ - return d->errorString; -} +QString StunBinding::errorString() const { return d->errorString; } } // namespace XMPP #include "stunbinding.moc" diff --git a/src/irisnet/noncore/stunbinding.h b/src/irisnet/noncore/stunbinding.h index 963e5fd2..3fcc490e 100644 --- a/src/irisnet/noncore/stunbinding.h +++ b/src/irisnet/noncore/stunbinding.h @@ -26,19 +26,11 @@ class QHostAddress; namespace XMPP { class StunTransactionPool; -class StunBinding : public QObject -{ +class StunBinding : public QObject { Q_OBJECT public: - enum Error - { - ErrorGeneric, - ErrorTimeout, - ErrorRejected, - ErrorProtocol, - ErrorConflict - }; + enum Error { ErrorGeneric, ErrorTimeout, ErrorRejected, ErrorProtocol, ErrorConflict }; StunBinding(StunTransactionPool *pool); ~StunBinding(); @@ -58,7 +50,7 @@ class StunBinding : public QObject void start(const QHostAddress &addr, int port); // use addr association QHostAddress reflexiveAddress() const; - int reflexivePort() const; + int reflexivePort() const; // non-translatable diagnostic string for convenience QString errorString() const; diff --git a/src/irisnet/noncore/stunmessage.cpp b/src/irisnet/noncore/stunmessage.cpp index 87e6a6ec..ca8b75e9 100644 --- a/src/irisnet/noncore/stunmessage.cpp +++ b/src/irisnet/noncore/stunmessage.cpp @@ -23,113 +23,67 @@ #include #include -#define ENSURE_D { if(!d) d = new Private; } +#define ENSURE_D \ + { \ + if (!d) \ + d = new Private; \ + } namespace XMPP { using namespace StunUtil; // some attribute types we need to explicitly support -enum -{ - AttribMessageIntegrity = 0x0008, - AttribFingerprint = 0x8028 -}; +enum { AttribMessageIntegrity = 0x0008, AttribFingerprint = 0x8028 }; // adapted from public domain source by Ross Williams and Eric Durbin -unsigned long crctable[256] = -{ - 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, - 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, - 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, - 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, - 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, - 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, - 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, - 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, - 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, - 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, - 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, - 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, - 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, - 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, - 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, - 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, - 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, - 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, - 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, - 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, - 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, - 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, - 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, - 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, - 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, - 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, - 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, - 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, - 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, - 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, - 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, - 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, - 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, - 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, - 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, - 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, - 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, - 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, - 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, - 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, - 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, - 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, - 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, - 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, - 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, - 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, - 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, - 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, - 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, - 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, - 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, - 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, - 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, - 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, - 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, - 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, - 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, - 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, - 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, - 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, - 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, - 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, - 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, +unsigned long crctable[256] = { + 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, + 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, + 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, + 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, + 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, + 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, + 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, + 0xB6662D3DL, 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, + 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, + 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, + 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, + 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, + 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, + 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, + 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, + 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, + 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, + 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, + 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, + 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, + 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, + 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, + 0x72076785L, 0x05005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, + 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, + 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, + 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, + 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, + 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL }; -class Crc32 -{ +class Crc32 { private: quint32 result; public: - Crc32() - { - clear(); - } + Crc32() { clear(); } - void clear() - { - result = 0xffffffff; - } + void clear() { result = 0xffffffff; } void update(const QByteArray &in) { - for(int n = 0; n < in.size(); ++n) + for (int n = 0; n < in.size(); ++n) result = (result >> 8) ^ (crctable[(result & 0xff) ^ (quint8)in[n]]); } - quint32 final() - { - return result ^= 0xffffffff; - } + quint32 final() { return result ^= 0xffffffff; } static quint32 process(const QByteArray &in) { @@ -146,36 +100,36 @@ static quint8 magic_cookie[4] = { 0x21, 0x12, 0xA4, 0x42 }; static int check_and_get_length(const QByteArray &buf) { // stun packets are at least 20 bytes - if(buf.size() < 20) + if (buf.size() < 20) return -1; // minimal 3-field check // top 2 bits of packet must be 0 - if(buf[0] & 0xC0) + if (buf[0] & 0xC0) return -1; - const quint8 *p = (const quint8 *)buf.data(); - quint16 mlen = read16(p + 2); + const quint8 *p = (const quint8 *)buf.data(); + quint16 mlen = read16(p + 2); // bottom 2 bits of message length field must be 0 - if(mlen & 0x03) + if (mlen & 0x03) return -1; // (also, the message length should be a reasonable size) - if(mlen + 20 > buf.size()) + if (mlen + 20 > buf.size()) return -1; // magic cookie must be set - if(memcmp(p + 4, magic_cookie, 4) != 0) + if (memcmp(p + 4, magic_cookie, 4) != 0) return -1; return mlen; } -#define ATTRIBUTE_AREA_START 20 -#define ATTRIBUTE_AREA_MAX 65535 -#define ATTRIBUTE_VALUE_MAX 65531 +#define ATTRIBUTE_AREA_START 20 +#define ATTRIBUTE_AREA_MAX 65535 +#define ATTRIBUTE_VALUE_MAX 65531 // note: because the attribute area of the packet has a maximum size of // 2^16-1, and each attribute itself has a 4 byte header, it follows that @@ -185,9 +139,9 @@ static int check_and_get_length(const QByteArray &buf) static quint16 round_up_length(quint16 in) { Q_ASSERT(in <= ATTRIBUTE_VALUE_MAX); - quint16 out = in; + quint16 out = in; quint16 remainder = out % 4; - if(remainder != 0) + if (remainder != 0) out += (4 - remainder); return out; } @@ -204,7 +158,7 @@ static int get_attribute_props(const QByteArray &buf, int offset, quint16 *type, const quint8 *p = (const quint8 *)buf.data(); // need at least 4 bytes for an attribute - if(offset + 4 > buf.size()) + if (offset + 4 > buf.size()) return -1; quint16 _type = read16(p + offset); @@ -215,11 +169,11 @@ static int get_attribute_props(const QByteArray &buf, int offset, quint16 *type, // get physical length. stun attributes are 4-byte aligned, and may // contain 0-3 bytes of padding. quint16 plen = round_up_length(_alen); - if(offset + plen > buf.size()) + if (offset + plen > buf.size()) return -1; *type = _type; - *len = _alen; + *len = _alen; return offset + plen; } @@ -230,20 +184,18 @@ static int get_attribute_props(const QByteArray &buf, int offset, quint16 *type, // returns offset of found attribute, -1 if not found static int find_attribute(const QByteArray &buf, quint16 type, int *len, int *next = nullptr) { - int at = ATTRIBUTE_AREA_START; + int at = ATTRIBUTE_AREA_START; quint16 _type; - int _len; - int _next; + int _len; + int _next; - while(1) - { + while (1) { _next = get_attribute_props(buf, at, &_type, &_len); - if(_next == -1) + if (_next == -1) break; - if(_type == type) - { + if (_type == type) { *len = _len; - if(next) + if (next) *next = _next; return at; } @@ -261,13 +213,13 @@ static int find_attribute(const QByteArray &buf, quint16 type, int *len, int *ne // note: padding following attribute is zeroed out static int append_attribute_uninitialized(QByteArray *buf, quint16 type, int len) { - if(len > ATTRIBUTE_VALUE_MAX) + if (len > ATTRIBUTE_VALUE_MAX) return -1; quint16 alen = (quint16)len; quint16 plen = round_up_length(alen); - if((buf->size() - ATTRIBUTE_AREA_START) + 4 + plen > ATTRIBUTE_AREA_MAX) + if ((buf->size() - ATTRIBUTE_AREA_START) + 4 + plen > ATTRIBUTE_AREA_MAX) return -1; int at = buf->size(); @@ -278,7 +230,7 @@ static int append_attribute_uninitialized(QByteArray *buf, quint16 type, int len write16(p + at + 2, alen); // padding - for(int n = 0; n < plen - alen; ++n) + for (int n = 0; n < plen - alen; ++n) p[at + alen + n] = 0; return at; @@ -293,8 +245,8 @@ static quint32 fingerprint_calc(const quint8 *buf, int size) static QByteArray message_integrity_calc(const quint8 *buf, int size, const QByteArray &key) { QCA::MessageAuthenticationCode hmac("hmac(sha1)", key); - QByteArray region = QByteArray::fromRawData((const char *)buf, size); - QByteArray result = hmac.process(region).toByteArray(); + QByteArray region = QByteArray::fromRawData((const char *)buf, size); + QByteArray result = hmac.process(region).toByteArray(); Q_ASSERT(result.size() == 20); return result; } @@ -306,13 +258,13 @@ static bool fingerprint_check(const QByteArray &buf) { int at, len; at = find_attribute(buf, AttribFingerprint, &len); - if(at == -1 || len != 4) // value must be 4 bytes + if (at == -1 || len != 4) // value must be 4 bytes return false; - const quint8 *p = (const quint8 *)buf.data(); - quint32 fpval = read32(p + at + 4); - quint32 fpcalc = fingerprint_calc(p, at); - if(fpval == fpcalc) + const quint8 *p = (const quint8 *)buf.data(); + quint32 fpval = read32(p + at + 4); + quint32 fpcalc = fingerprint_calc(p, at); + if (fpval == fpcalc) return true; else return false; @@ -331,14 +283,14 @@ static bool message_integrity_prep(const QByteArray &buf, QByteArray *out, int * { int at, len, next; at = find_attribute(buf, AttribMessageIntegrity, &len, &next); - if(at == -1 || len != 20) // value must be 20 bytes + if (at == -1 || len != 20) // value must be 20 bytes return false; // prepare new attribute area size int i = next - ATTRIBUTE_AREA_START; // new value must be divisible by 4 - if(i % 4 != 0) + if (i % 4 != 0) return false; // copy truncated packet @@ -359,22 +311,21 @@ static bool message_integrity_prep(const QByteArray &buf, QByteArray *out, int * // returns true if correct static bool message_integrity_check(const QByteArray &buf, int offset, const QByteArray &key) { - QByteArray mival = QByteArray::fromRawData(buf.data() + offset + 4, 20); + QByteArray mival = QByteArray::fromRawData(buf.data() + offset + 4, 20); QByteArray micalc = message_integrity_calc((const quint8 *)buf.data(), offset, key); - if(mival == micalc) + if (mival == micalc) return true; else return false; } -class StunMessage::Private : public QSharedData -{ +class StunMessage::Private : public QSharedData { public: StunMessage::Class mclass; - quint16 method; - quint8 magic[4]; - quint8 id[12]; - QList attribs; + quint16 method; + quint8 magic[4]; + quint8 id[12]; + QList attribs; Private() { @@ -385,30 +336,19 @@ class StunMessage::Private : public QSharedData } }; -StunMessage::StunMessage() : - d(nullptr) -{ -} +StunMessage::StunMessage() : d(nullptr) {} -StunMessage::StunMessage(const StunMessage &from) : - d(from.d) -{ -} +StunMessage::StunMessage(const StunMessage &from) : d(from.d) {} -StunMessage::~StunMessage() -{ -} +StunMessage::~StunMessage() {} -StunMessage & StunMessage::operator=(const StunMessage &from) +StunMessage &StunMessage::operator=(const StunMessage &from) { d = from.d; return *this; } -bool StunMessage::isNull() const -{ - return (d ? false : true); -} +bool StunMessage::isNull() const { return (d ? false : true); } StunMessage::Class StunMessage::mclass() const { @@ -444,9 +384,8 @@ QByteArray StunMessage::attribute(quint16 type) const { Q_ASSERT(d); - foreach(const Attribute &i, d->attribs) - { - if(i.type == type) + foreach (const Attribute &i, d->attribs) { + if (i.type == type) return i.value; } return QByteArray(); @@ -488,16 +427,16 @@ QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) con // header QByteArray buf(20, 0); - quint8 *p = (quint8 *)buf.data(); + quint8 * p = (quint8 *)buf.data(); quint8 classbits = 0; - if(d->mclass == Request) + if (d->mclass == Request) classbits = 0; // 00 - else if(d->mclass == Indication) + else if (d->mclass == Indication) classbits = 1; // 01 - else if(d->mclass == SuccessResponse) + else if (d->mclass == SuccessResponse) classbits = 2; // 10 - else if(d->mclass == ErrorResponse) + else if (d->mclass == ErrorResponse) classbits = 3; // 11 else Q_ASSERT(0); @@ -523,10 +462,9 @@ QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) con memcpy(p + 4, d->magic, 4); memcpy(p + 8, d->id, 12); - foreach(const Attribute &i, d->attribs) - { + foreach (const Attribute &i, d->attribs) { int at = append_attribute_uninitialized(&buf, i.type, i.value.size()); - if(at == -1) + if (at == -1) return QByteArray(); p = (quint8 *)buf.data(); // follow the resize @@ -537,11 +475,10 @@ QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) con // set attribute area size write16(p + 2, buf.size() - ATTRIBUTE_AREA_START); - if(validationFlags & MessageIntegrity) - { + if (validationFlags & MessageIntegrity) { quint16 alen = 20; // size of hmac(sha1) - int at = append_attribute_uninitialized(&buf, AttribMessageIntegrity, alen); - if(at == -1) + int at = append_attribute_uninitialized(&buf, AttribMessageIntegrity, alen); + if (at == -1) return QByteArray(); p = (quint8 *)buf.data(); // follow the resize @@ -555,11 +492,10 @@ QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) con memcpy(p + at + 4, result.data(), alen); } - if(validationFlags & Fingerprint) - { + if (validationFlags & Fingerprint) { quint16 alen = 4; // size of crc32 - int at = append_attribute_uninitialized(&buf, AttribFingerprint, alen); - if(at == -1) + int at = append_attribute_uninitialized(&buf, AttribFingerprint, alen); + if (at == -1) return QByteArray(); p = (quint8 *)buf.data(); // follow the resize @@ -575,21 +511,19 @@ QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) con return buf; } -StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, int validationFlags, const QByteArray &key) +StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, int validationFlags, + const QByteArray &key) { int mlen = check_and_get_length(a); - if(mlen == -1) - { - if(result) + if (mlen == -1) { + if (result) *result = ErrorFormat; return StunMessage(); } - if(validationFlags & Fingerprint) - { - if(!fingerprint_check(a)) - { - if(result) + if (validationFlags & Fingerprint) { + if (!fingerprint_check(a)) { + if (result) *result = ErrorFingerprint; return StunMessage(); } @@ -597,24 +531,20 @@ StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, QByteArray in; - if(validationFlags & MessageIntegrity) - { + if (validationFlags & MessageIntegrity) { int offset; - if(!message_integrity_prep(a, &in, &offset)) - { - if(result) + if (!message_integrity_prep(a, &in, &offset)) { + if (result) *result = ErrorMessageIntegrity; return StunMessage(); } - if(!message_integrity_check(in, offset, key)) - { - if(result) + if (!message_integrity_check(in, offset, key)) { + if (result) *result = ErrorMessageIntegrity; return StunMessage(); } - } - else + } else in = a; // all validating complete, now just parse the packet @@ -636,15 +566,15 @@ StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, c2 = p[1] & 0x10; // C0 c2 >>= 4; - quint16 method = m1 | m2 | m3; - quint8 classbits = c1 | c2; + quint16 method = m1 | m2 | m3; + quint8 classbits = c1 | c2; Class mclass; - if(classbits == 0) // 00 + if (classbits == 0) // 00 mclass = Request; - else if(classbits == 1) // 01 + else if (classbits == 1) // 01 mclass = Indication; - else if(classbits == 2) // 10 + else if (classbits == 2) // 10 mclass = SuccessResponse; else // 11 mclass = ErrorResponse; @@ -656,19 +586,18 @@ StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, out.setId(p + 8); QList list; - int at = ATTRIBUTE_AREA_START; - while(1) - { + int at = ATTRIBUTE_AREA_START; + while (1) { quint16 type; - int len; - int next; + int len; + int next; next = get_attribute_props(in, at, &type, &len); - if(next == -1) + if (next == -1) break; Attribute attrib; - attrib.type = type; + attrib.type = type; attrib.value = in.mid(at + 4, len); list += attrib; @@ -676,15 +605,12 @@ StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, } out.setAttributes(list); - if(result) + if (result) *result = ConvertGood; return out; } -bool StunMessage::isProbablyStun(const QByteArray &a) -{ - return (check_and_get_length(a) != -1 ? true : false); -} +bool StunMessage::isProbablyStun(const QByteArray &a) { return (check_and_get_length(a) != -1 ? true : false); } StunMessage::Class StunMessage::extractClass(const QByteArray &in) { @@ -700,11 +626,11 @@ StunMessage::Class StunMessage::extractClass(const QByteArray &in) quint8 classbits = c1 | c2; Class mclass; - if(classbits == 0) // 00 + if (classbits == 0) // 00 mclass = Request; - else if(classbits == 1) // 01 + else if (classbits == 1) // 01 mclass = Indication; - else if(classbits == 2) // 10 + else if (classbits == 2) // 10 mclass = SuccessResponse; else // 11 mclass = ErrorResponse; @@ -720,9 +646,9 @@ bool StunMessage::containsStun(const quint8 *data, int size) QByteArray StunMessage::readStun(const quint8 *data, int size) { - QByteArray in = QByteArray::fromRawData((const char *)data, size); - int mlen = check_and_get_length(in); - if(mlen != -1) + QByteArray in = QByteArray::fromRawData((const char *)data, size); + int mlen = check_and_get_length(in); + if (mlen != -1) return QByteArray((const char *)data, mlen + 20); else return QByteArray(); diff --git a/src/irisnet/noncore/stunmessage.h b/src/irisnet/noncore/stunmessage.h index 8563712e..e9bb3d6c 100644 --- a/src/irisnet/noncore/stunmessage.h +++ b/src/irisnet/noncore/stunmessage.h @@ -24,51 +24,35 @@ #include namespace XMPP { -class StunMessage -{ +class StunMessage { public: - enum Class - { - Request, - SuccessResponse, - ErrorResponse, - Indication - }; + enum Class { Request, SuccessResponse, ErrorResponse, Indication }; - enum ValidationFlags - { - Fingerprint = 0x01, + enum ValidationFlags { + Fingerprint = 0x01, // you must have the hmac(sha1) algorithm in QCA to use MessageIntegrity = 0x02 }; - enum ConvertResult - { - ConvertGood, - ErrorFormat, - ErrorFingerprint, - ErrorMessageIntegrity, - ErrorConvertUnknown = 64 - }; + enum ConvertResult { ConvertGood, ErrorFormat, ErrorFingerprint, ErrorMessageIntegrity, ErrorConvertUnknown = 64 }; - class Attribute - { + class Attribute { public: - quint16 type; + quint16 type; QByteArray value; }; StunMessage(); StunMessage(const StunMessage &from); ~StunMessage(); - StunMessage & operator=(const StunMessage &from); + StunMessage &operator=(const StunMessage &from); - bool isNull() const; - Class mclass() const; - quint16 method() const; - const quint8 *magic() const; // 4 bytes - const quint8 *id() const; // 12 bytes + bool isNull() const; + Class mclass() const; + quint16 method() const; + const quint8 * magic() const; // 4 bytes + const quint8 * id() const; // 12 bytes QList attributes() const; // returns the first instance or null @@ -77,11 +61,12 @@ class StunMessage void setClass(Class mclass); void setMethod(quint16 method); void setMagic(const quint8 *magic); // 4 bytes - void setId(const quint8 *id); // 12 bytes + void setId(const quint8 *id); // 12 bytes void setAttributes(const QList &attribs); - QByteArray toBinary(int validationFlags = 0, const QByteArray &key = QByteArray()) const; - static StunMessage fromBinary(const QByteArray &a, ConvertResult *result = nullptr, int validationFlags = 0, const QByteArray &key = QByteArray()); + QByteArray toBinary(int validationFlags = 0, const QByteArray &key = QByteArray()) const; + static StunMessage fromBinary(const QByteArray &a, ConvertResult *result = nullptr, int validationFlags = 0, + const QByteArray &key = QByteArray()); // minimal 3-field check static bool isProbablyStun(const QByteArray &a); diff --git a/src/irisnet/noncore/stuntransaction.cpp b/src/irisnet/noncore/stuntransaction.cpp index 70a13c75..3c12f512 100644 --- a/src/irisnet/noncore/stuntransaction.cpp +++ b/src/irisnet/noncore/stuntransaction.cpp @@ -44,42 +44,37 @@ static StunMessage parse_stun_message(const QByteArray &packet, int *validationF // parsing the packet, so we should be able to avoid most redundant // processing. fromBinary checks the fingerprint first, and we // can use that knowledge to avoid duplicating integrity checks. - int flags = 0; + int flags = 0; StunMessage::ConvertResult result; - StunMessage msg = StunMessage::fromBinary(packet, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, key); - if(result == StunMessage::ErrorFingerprint) - { + StunMessage msg + = StunMessage::fromBinary(packet, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, key); + if (result == StunMessage::ErrorFingerprint) { // if fingerprint fails, then it is the only thing that was // performed and we can skip it now. msg = StunMessage::fromBinary(packet, &result, StunMessage::MessageIntegrity, key); - if(result == StunMessage::ErrorMessageIntegrity) - { + if (result == StunMessage::ErrorMessageIntegrity) { // if message-integrity fails, then it is the only // thing that was performed and we can skip it now msg = StunMessage::fromBinary(packet, &result); - if(result == StunMessage::ConvertGood) + if (result == StunMessage::ConvertGood) flags = 0; else return msg; // null - } - else if(result == StunMessage::ConvertGood) + } else if (result == StunMessage::ConvertGood) flags = StunMessage::MessageIntegrity; else return msg; // null - } - else if(result == StunMessage::ErrorMessageIntegrity) - { + } else if (result == StunMessage::ErrorMessageIntegrity) { // fingerprint succeeded, but message-integrity failed. parse // without validation now (to skip redundant // fingerprint/message-integrity checks), and assume correct // fingerprint msg = StunMessage::fromBinary(packet, &result); - if(result == StunMessage::ConvertGood) + if (result == StunMessage::ConvertGood) flags = StunMessage::Fingerprint; else return msg; // null - } - else if(result == StunMessage::ConvertGood) + } else if (result == StunMessage::ConvertGood) flags = StunMessage::MessageIntegrity | StunMessage::Fingerprint; else return msg; // null @@ -88,76 +83,66 @@ static StunMessage parse_stun_message(const QByteArray &packet, int *validationF return msg; } -class StunTransactionPoolPrivate : public QObject -{ +class StunTransactionPoolPrivate : public QObject { Q_OBJECT public: - StunTransactionPool *q; - StunTransaction::Mode mode; - QSet transactions; - QHash transToId; - QHash idToTrans; - bool useLongTermAuth; - bool needLongTermAuth; - bool triedLongTermAuth; - QString user; - QCA::SecureArray pass; - QString realm; - QString nonce; - int debugLevel; + StunTransactionPool * q; + StunTransaction::Mode mode; + QSet transactions; + QHash transToId; + QHash idToTrans; + bool useLongTermAuth; + bool needLongTermAuth; + bool triedLongTermAuth; + QString user; + QCA::SecureArray pass; + QString realm; + QString nonce; + int debugLevel; StunTransactionPoolPrivate(StunTransactionPool *_q) : - QObject(_q), - q(_q), - useLongTermAuth(false), - needLongTermAuth(false), - triedLongTermAuth(false), + QObject(_q), q(_q), useLongTermAuth(false), needLongTermAuth(false), triedLongTermAuth(false), debugLevel(StunTransactionPool::DL_None) { } QByteArray generateId() const; - void insert(StunTransaction *trans); - void remove(StunTransaction *trans); - void transmit(StunTransaction *trans); + void insert(StunTransaction *trans); + void remove(StunTransaction *trans); + void transmit(StunTransaction *trans); }; //---------------------------------------------------------------------------- // StunTransaction //---------------------------------------------------------------------------- -class StunTransactionPrivate : public QObject -{ +class StunTransactionPrivate : public QObject { Q_OBJECT public: StunTransaction *q; - StunTransactionPool *pool; - bool active; + StunTransactionPool * pool; + bool active; StunTransaction::Mode mode; - StunMessage origMessage; - QByteArray id; - QByteArray packet; - QHostAddress to_addr; - int to_port; - - int rto, rc, rm, ti; - int tries; - int last_interval; + StunMessage origMessage; + QByteArray id; + QByteArray packet; + QHostAddress to_addr; + int to_port; + + int rto, rc, rm, ti; + int tries; + int last_interval; QTimer *t; - QString stuser; - QString stpass; - bool fpRequired; + QString stuser; + QString stpass; + bool fpRequired; QByteArray key; - QTime time; + QTime time; - StunTransactionPrivate(StunTransaction *_q) : - QObject(_q), - q(_q), - pool(nullptr), - fpRequired(false) + StunTransactionPrivate(StunTransaction *_q) : QObject(_q), q(_q), pool(nullptr), fpRequired(false) { qRegisterMetaType(); @@ -169,14 +154,14 @@ class StunTransactionPrivate : public QObject // defaults from RFC 5389 rto = 500; - rc = 7; - rm = 16; - ti = 39500; + rc = 7; + rm = 16; + ti = 39500; } ~StunTransactionPrivate() { - if(pool) + if (pool) pool->d->remove(q); t->disconnect(this); @@ -186,18 +171,15 @@ class StunTransactionPrivate : public QObject void start(StunTransactionPool *_pool, const QHostAddress &toAddress, int toPort) { - pool = _pool; - mode = pool->d->mode; + pool = _pool; + mode = pool->d->mode; to_addr = toAddress; to_port = toPort; tryRequest(); } - void setMessage(const StunMessage &request) - { - origMessage = request; - } + void setMessage(const StunMessage &request) { origMessage = request; } void retry() { @@ -211,12 +193,11 @@ class StunTransactionPrivate : public QObject { emit q->createMessage(pool->d->generateId()); - if(origMessage.isNull()) - { + if (origMessage.isNull()) { // since a transaction is not cancelable nor reusable, // there's no DOR-SR issue here QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection, - Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric)); + Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric)); return; } @@ -225,35 +206,34 @@ class StunTransactionPrivate : public QObject out.setClass(StunMessage::Request); id = QByteArray((const char *)out.id(), 12); - if(!stuser.isEmpty()) - { + if (!stuser.isEmpty()) { QList list = out.attributes(); - StunMessage::Attribute attr; + StunMessage::Attribute attr; attr.type = StunTypes::USERNAME; - attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(stuser.toUtf8()).toByteArray())); + attr.value + = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(stuser.toUtf8()).toByteArray())); list += attr; out.setAttributes(list); key = StunUtil::saslPrep(stpass.toUtf8()).toByteArray(); - } - else if(!pool->d->nonce.isEmpty()) - { + } else if (!pool->d->nonce.isEmpty()) { QList list = out.attributes(); { StunMessage::Attribute attr; - attr.type = StunTypes::USERNAME; - attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(pool->d->user.toUtf8()).toByteArray())); + attr.type = StunTypes::USERNAME; + attr.value = StunTypes::createUsername( + QString::fromUtf8(StunUtil::saslPrep(pool->d->user.toUtf8()).toByteArray())); list += attr; } { StunMessage::Attribute attr; - attr.type = StunTypes::REALM; + attr.type = StunTypes::REALM; attr.value = StunTypes::createRealm(pool->d->realm); list += attr; } { StunMessage::Attribute attr; - attr.type = StunTypes::NONCE; + attr.type = StunTypes::NONCE; attr.value = StunTypes::createNonce(pool->d->nonce); list += attr; } @@ -269,34 +249,29 @@ class StunTransactionPrivate : public QObject key = QCA::Hash("md5").process(buf).toByteArray(); } - if(!key.isEmpty()) + if (!key.isEmpty()) packet = out.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, key); else packet = out.toBinary(StunMessage::Fingerprint); - if(packet.isEmpty()) - { + if (packet.isEmpty()) { // since a transaction is not cancelable nor reusable, // there's no DOR-SR issue here QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection, - Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric)); + Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric)); return; } active = true; - tries = 1; // we transmit immediately here, so count it + tries = 1; // we transmit immediately here, so count it - if(mode == StunTransaction::Udp) - { + if (mode == StunTransaction::Udp) { last_interval = rm * rto; t->start(rto); rto *= 2; - } - else if(mode == StunTransaction::Tcp) - { + } else if (mode == StunTransaction::Tcp) { t->start(ti); - } - else + } else Q_ASSERT(0); time.start(); @@ -307,20 +282,16 @@ class StunTransactionPrivate : public QObject private slots: void t_timeout() { - if(mode == StunTransaction::Tcp || tries == rc) - { + if (mode == StunTransaction::Tcp || tries == rc) { pool->d->remove(q); emit q->error(StunTransaction::ErrorTimeout); return; } ++tries; - if(tries == rc) - { + if (tries == rc) { t->start(last_interval); - } - else - { + } else { t->start(rto); rto *= 2; } @@ -331,15 +302,14 @@ private slots: private: void transmit() { - if(pool->d->debugLevel >= StunTransactionPool::DL_Packet) - { + if (pool->d->debugLevel >= StunTransactionPool::DL_Packet) { QString str = QString("STUN SEND: elapsed=") + QString::number(time.elapsed()); - if(!to_addr.isNull()) + if (!to_addr.isNull()) str += QString(" to=(") + to_addr.toString() + ';' + QString::number(to_port) + ')'; emit pool->debugLine(str); StunMessage msg = StunMessage::fromBinary(packet); - emit pool->debugLine(StunTypes::print_packet_str(msg)); + emit pool->debugLine(StunTypes::print_packet_str(msg)); } pool->d->transmit(q); @@ -347,10 +317,10 @@ private slots: bool checkActiveAndFrom(const QHostAddress &from_addr, int from_port) { - if(!active) + if (!active) return false; - if(!to_addr.isNull() && (to_addr != from_addr || to_port != from_port)) + if (!to_addr.isNull() && (to_addr != from_addr || to_port != from_port)) return false; return true; @@ -361,46 +331,39 @@ private slots: active = false; t->stop(); - if(pool->d->debugLevel >= StunTransactionPool::DL_Packet) - emit pool->debugLine(QString("matched incoming response to existing request. elapsed=") + QString::number(time.elapsed())); + if (pool->d->debugLevel >= StunTransactionPool::DL_Packet) + emit pool->debugLine(QString("matched incoming response to existing request. elapsed=") + + QString::number(time.elapsed())); // will be set to true when receiving an Unauthorized error bool unauthError = false; - if(msg.mclass() == StunMessage::ErrorResponse && pool->d->useLongTermAuth) - { + if (msg.mclass() == StunMessage::ErrorResponse && pool->d->useLongTermAuth) { // we'll handle certain error codes at this layer - int code; + int code; QString reason; - if(StunTypes::parseErrorCode(msg.attribute(StunTypes::ERROR_CODE), &code, &reason)) - { - if(code == StunTypes::Unauthorized) + if (StunTypes::parseErrorCode(msg.attribute(StunTypes::ERROR_CODE), &code, &reason)) { + if (code == StunTypes::Unauthorized) unauthError = true; - if(unauthError && !pool->d->triedLongTermAuth) - { + if (unauthError && !pool->d->triedLongTermAuth) { QString realm; QString nonce; - if(StunTypes::parseRealm(msg.attribute(StunTypes::REALM), &realm) && - StunTypes::parseRealm(msg.attribute(StunTypes::NONCE), &nonce)) - { + if (StunTypes::parseRealm(msg.attribute(StunTypes::REALM), &realm) + && StunTypes::parseRealm(msg.attribute(StunTypes::NONCE), &nonce)) { // always set these to the latest received values, // which will be used for all transactions // once creds are provided. - if(pool->d->realm.isEmpty()) + if (pool->d->realm.isEmpty()) pool->d->realm = realm; pool->d->nonce = nonce; - if(!pool->d->needLongTermAuth) - { - if(!pool->d->user.isEmpty()) - { + if (!pool->d->needLongTermAuth) { + if (!pool->d->user.isEmpty()) { // creds already set? use them pool->d->triedLongTermAuth = true; retry(); - } - else - { + } else { // else ask the user pool->d->needLongTermAuth = true; emit pool->needAuthParams(); @@ -408,12 +371,9 @@ private slots: } return; } - } - else if(code == StunTypes::StaleNonce && pool->d->triedLongTermAuth) - { + } else if (code == StunTypes::StaleNonce && pool->d->triedLongTermAuth) { QString nonce; - if(StunTypes::parseNonce(msg.attribute(StunTypes::NONCE), &nonce) && nonce != pool->d->nonce) - { + if (StunTypes::parseNonce(msg.attribute(StunTypes::NONCE), &nonce) && nonce != pool->d->nonce) { pool->d->nonce = nonce; retry(); return; @@ -423,7 +383,7 @@ private slots: } // require message integrity when auth is used - if(!unauthError && (!stuser.isEmpty() || pool->d->triedLongTermAuth) && !authed) + if (!unauthError && (!stuser.isEmpty() || pool->d->triedLongTermAuth) && !authed) return; pool->d->remove(q); @@ -433,7 +393,7 @@ private slots: public: bool writeIncomingMessage(const StunMessage &msg, const QHostAddress &from_addr, int from_port) { - if(!checkActiveAndFrom(from_addr, from_port)) + if (!checkActiveAndFrom(from_addr, from_port)) return false; // if a StunMessage is passed directly to us then we assume @@ -444,24 +404,21 @@ private slots: bool writeIncomingMessage(const QByteArray &packet, bool *notStun, const QHostAddress &from_addr, int from_port) { - if(!checkActiveAndFrom(from_addr, from_port)) - { + if (!checkActiveAndFrom(from_addr, from_port)) { // could be STUN, don't really know for sure *notStun = false; return false; } - int validationFlags = 0; - StunMessage msg = parse_stun_message(packet, &validationFlags, key); - if(msg.isNull()) - { + int validationFlags = 0; + StunMessage msg = parse_stun_message(packet, &validationFlags, key); + if (msg.isNull()) { // packet doesn't parse at all, surely not STUN *notStun = true; return false; } - if(fpRequired && !(validationFlags & StunMessage::Fingerprint)) - { + if (fpRequired && !(validationFlags & StunMessage::Fingerprint)) { // fingerprint failed when required. consider the // packet to be surely not STUN *notStun = true; @@ -473,22 +430,12 @@ private slots: } public slots: - void continueAfterParams() - { - retry(); - } + void continueAfterParams() { retry(); } }; -StunTransaction::StunTransaction(QObject *parent) : - QObject(parent) -{ - d = new StunTransactionPrivate(this); -} +StunTransaction::StunTransaction(QObject *parent) : QObject(parent) { d = new StunTransactionPrivate(this); } -StunTransaction::~StunTransaction() -{ - delete d; -} +StunTransaction::~StunTransaction() { delete d; } void StunTransaction::start(StunTransactionPool *pool, const QHostAddress &toAddress, int toPort) { @@ -496,10 +443,7 @@ void StunTransaction::start(StunTransactionPool *pool, const QHostAddress &toAdd d->start(pool, toAddress, toPort); } -void StunTransaction::setMessage(const StunMessage &request) -{ - d->setMessage(request); -} +void StunTransaction::setMessage(const StunMessage &request) { d->setMessage(request); } void StunTransaction::setRTO(int i) { @@ -525,20 +469,11 @@ void StunTransaction::setTi(int i) d->ti = i; } -void StunTransaction::setShortTermUsername(const QString &username) -{ - d->stuser = username; -} +void StunTransaction::setShortTermUsername(const QString &username) { d->stuser = username; } -void StunTransaction::setShortTermPassword(const QString &password) -{ - d->stpass = password; -} +void StunTransaction::setShortTermPassword(const QString &password) { d->stpass = password; } -void StunTransaction::setFingerprintRequired(bool enabled) -{ - d->fpRequired = enabled; -} +void StunTransaction::setFingerprintRequired(bool enabled) { d->fpRequired = enabled; } //---------------------------------------------------------------------------- // StunTransactionPool @@ -547,10 +482,9 @@ QByteArray StunTransactionPoolPrivate::generateId() const { QByteArray id; - do - { + do { id = QCA::Random::randomArray(12).toByteArray(); - } while(idToTrans.contains(id)); + } while (idToTrans.contains(id)); return id; } @@ -567,8 +501,7 @@ void StunTransactionPoolPrivate::insert(StunTransaction *trans) void StunTransactionPoolPrivate::remove(StunTransaction *trans) { - if(transactions.contains(trans)) - { + if (transactions.contains(trans)) { transactions.remove(trans); QByteArray id = transToId.value(trans); transToId.remove(trans); @@ -581,63 +514,58 @@ void StunTransactionPoolPrivate::transmit(StunTransaction *trans) emit q->outgoingMessage(trans->d->packet, trans->d->to_addr, trans->d->to_port); } -StunTransactionPool::StunTransactionPool(StunTransaction::Mode mode, QObject *parent) : - QObject(parent) +StunTransactionPool::StunTransactionPool(StunTransaction::Mode mode, QObject *parent) : QObject(parent) { - d = new StunTransactionPoolPrivate(this); + d = new StunTransactionPoolPrivate(this); d->mode = mode; } StunTransactionPool::~StunTransactionPool() { - qDeleteAll(findChildren()); // early remove of binding since they require alive pool (should fix one crash) + qDeleteAll( + findChildren()); // early remove of binding since they require alive pool (should fix one crash) delete d; } -StunTransaction::Mode StunTransactionPool::mode() const -{ - return d->mode; -} +StunTransaction::Mode StunTransactionPool::mode() const { return d->mode; } bool StunTransactionPool::writeIncomingMessage(const StunMessage &msg, const QHostAddress &addr, int port) { - if(d->debugLevel >= DL_Packet) - { + if (d->debugLevel >= DL_Packet) { QString str = "STUN RECV"; - if(!addr.isNull()) + if (!addr.isNull()) str += QString(" from=(") + addr.toString() + ';' + QString::number(port) + ')'; emit debugLine(str); emit debugLine(StunTypes::print_packet_str(msg)); } - QByteArray id = QByteArray::fromRawData((const char *)msg.id(), 12); + QByteArray id = QByteArray::fromRawData((const char *)msg.id(), 12); StunMessage::Class mclass = msg.mclass(); - if(mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse) + if (mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse) return false; StunTransaction *trans = d->idToTrans.value(id); - if(!trans) + if (!trans) return false; return trans->d->writeIncomingMessage(msg, addr, port); } -bool StunTransactionPool::writeIncomingMessage(const QByteArray &packet, bool *notStun, const QHostAddress &addr, int port) +bool StunTransactionPool::writeIncomingMessage(const QByteArray &packet, bool *notStun, const QHostAddress &addr, + int port) { - if(!StunMessage::isProbablyStun(packet)) - { + if (!StunMessage::isProbablyStun(packet)) { // basic stun check failed? surely not STUN - if(notStun) + if (notStun) *notStun = true; return false; } - if(d->debugLevel >= DL_Packet) - { + if (d->debugLevel >= DL_Packet) { StunMessage msg = StunMessage::fromBinary(packet); - QString str = "STUN RECV"; - if(!addr.isNull()) + QString str = "STUN RECV"; + if (!addr.isNull()) str += QString(" from=(") + addr.toString() + ';' + QString::number(port) + ')'; emit debugLine(str); emit debugLine(StunTypes::print_packet_str(msg)); @@ -649,59 +577,41 @@ bool StunTransactionPool::writeIncomingMessage(const QByteArray &packet, bool *n StunMessage::Class mclass = StunMessage::extractClass(packet); - if(mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse) - { + if (mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse) { // could be STUN, don't really know for sure - if(notStun) + if (notStun) *notStun = false; return false; } StunTransaction *trans = d->idToTrans.value(id); - if(!trans) - { + if (!trans) { // could be STUN, don't really know for sure - if(notStun) + if (notStun) *notStun = false; return false; } bool _notStun = false; - bool ret = trans->d->writeIncomingMessage(packet, &_notStun, addr, port); - if(!ret && notStun) + bool ret = trans->d->writeIncomingMessage(packet, &_notStun, addr, port); + if (!ret && notStun) *notStun = _notStun; return ret; } -void StunTransactionPool::setLongTermAuthEnabled(bool enabled) -{ - d->useLongTermAuth = enabled; -} +void StunTransactionPool::setLongTermAuthEnabled(bool enabled) { d->useLongTermAuth = enabled; } -QString StunTransactionPool::realm() const -{ - return d->realm; -} +QString StunTransactionPool::realm() const { return d->realm; } -void StunTransactionPool::setUsername(const QString &username) -{ - d->user = username; -} +void StunTransactionPool::setUsername(const QString &username) { d->user = username; } -void StunTransactionPool::setPassword(const QCA::SecureArray &password) -{ - d->pass = password; -} +void StunTransactionPool::setPassword(const QCA::SecureArray &password) { d->pass = password; } -void StunTransactionPool::setRealm(const QString &realm) -{ - d->realm = realm; -} +void StunTransactionPool::setRealm(const QString &realm) { d->realm = realm; } void StunTransactionPool::continueAfterParams() { - if(d->debugLevel >= DL_Info) - { + if (d->debugLevel >= DL_Info) { emit debugLine("continue after params:"); emit debugLine(QString(" U=[%1]").arg(d->user)); emit debugLine(QString(" P=[%1]").arg(d->pass.data())); @@ -713,32 +623,23 @@ void StunTransactionPool::continueAfterParams() Q_ASSERT(d->needLongTermAuth); Q_ASSERT(!d->triedLongTermAuth); - d->needLongTermAuth = false; + d->needLongTermAuth = false; d->triedLongTermAuth = true; - foreach(StunTransaction *trans, d->transactions) - { + foreach (StunTransaction *trans, d->transactions) { // the only reason an inactive transaction would be in the // list is if it is waiting for an auth retry - if(!trans->d->active) - { + if (!trans->d->active) { // use queued call to prevent all sorts of DOR-SS // nastiness - QMetaObject::invokeMethod(trans->d, "continueAfterParams", - Qt::QueuedConnection); + QMetaObject::invokeMethod(trans->d, "continueAfterParams", Qt::QueuedConnection); } } } -QByteArray StunTransactionPool::generateId() const -{ - return d->generateId(); -} +QByteArray StunTransactionPool::generateId() const { return d->generateId(); } -void StunTransactionPool::setDebugLevel(DebugLevel level) -{ - d->debugLevel = level; -} +void StunTransactionPool::setDebugLevel(DebugLevel level) { d->debugLevel = level; } } // namespace XMPP diff --git a/src/irisnet/noncore/stuntransaction.h b/src/irisnet/noncore/stuntransaction.h index 6d924b3b..43b8b44d 100644 --- a/src/irisnet/noncore/stuntransaction.h +++ b/src/irisnet/noncore/stuntransaction.h @@ -24,7 +24,7 @@ #include namespace QCA { - class SecureArray; +class SecureArray; } namespace XMPP { @@ -57,22 +57,16 @@ class StunTransactionPrivate; // - if short term or long term auth is used, then the request is authenticated // and the response is required to be authenticated. -class StunTransaction : public QObject -{ +class StunTransaction : public QObject { Q_OBJECT public: - enum Mode - { + enum Mode { Udp, // handle retransmissions Tcp // send once }; - enum Error - { - ErrorGeneric, - ErrorTimeout - }; + enum Error { ErrorGeneric, ErrorTimeout }; StunTransaction(QObject *parent = nullptr); ~StunTransaction(); @@ -126,17 +120,11 @@ class StunTransaction : public QObject // emitted as a direct result of calling certain member functions of this // class as well as any other class that might use it (such as StunBinding). // so, be careful with what you do in your retransmit slot. -class StunTransactionPool : public QObject -{ +class StunTransactionPool : public QObject { Q_OBJECT public: - enum DebugLevel - { - DL_None, - DL_Info, - DL_Packet - }; + enum DebugLevel { DL_None, DL_Info, DL_Packet }; StunTransactionPool(StunTransaction::Mode mode, QObject *parent = nullptr); ~StunTransactionPool(); @@ -155,15 +143,16 @@ class StunTransactionPool : public QObject // not be a STUN message. *notStun will be set to true if the packet // is surely not STUN, or set to false if it is unclear whether the // packet is STUN or not. - bool writeIncomingMessage(const QByteArray &packet, bool *notStun = nullptr, const QHostAddress &addr = QHostAddress(), int port = -1); + bool writeIncomingMessage(const QByteArray &packet, bool *notStun = nullptr, + const QHostAddress &addr = QHostAddress(), int port = -1); void setLongTermAuthEnabled(bool enabled); QString realm() const; - void setUsername(const QString &username); - void setPassword(const QCA::SecureArray &password); - void setRealm(const QString &realm); - void continueAfterParams(); + void setUsername(const QString &username); + void setPassword(const QCA::SecureArray &password); + void setRealm(const QString &realm); + void continueAfterParams(); // for use with stun indications QByteArray generateId() const; diff --git a/src/irisnet/noncore/stuntypes.cpp b/src/irisnet/noncore/stuntypes.cpp index 9cc72ff8..99fa0bcb 100644 --- a/src/irisnet/noncore/stuntypes.cpp +++ b/src/irisnet/noncore/stuntypes.cpp @@ -29,590 +29,522 @@ namespace XMPP { using namespace StunUtil; namespace StunTypes { -static void xorIPv4(QByteArray *in, const quint8 *magic) -{ - quint8 *p = (quint8 *)in->data(); - p[2] ^= magic[0]; - p[3] ^= magic[1]; - for(int n = 0; n < 4; ++n) - p[n + 4] ^= magic[n]; -} - -static void xorIPv6(QByteArray *in, const quint8 *magic, const quint8 *id) -{ - quint8 *p = (quint8 *)in->data(); - p[2] ^= magic[0]; - p[3] ^= magic[1]; - for(int n = 0; n < 4; ++n) - p[n + 4] ^= magic[n]; - for(int n = 0; n < 12; ++n) - p[n + 8] ^= id[n]; -} - -static bool validateString(const QByteArray &in, QString *out) -{ - if(in.size() <= STRING_MAX_BYTES) - { - QString s = QString::fromUtf8(in); - if(s.length() <= STRING_MAX_CHARS) - { - *out = s; - return true; - } + static void xorIPv4(QByteArray *in, const quint8 *magic) + { + quint8 *p = (quint8 *)in->data(); + p[2] ^= magic[0]; + p[3] ^= magic[1]; + for (int n = 0; n < 4; ++n) + p[n + 4] ^= magic[n]; } - return false; -} - -QByteArray createMappedAddress(const QHostAddress &addr, quint16 port) -{ - QByteArray out; - - if(addr.protocol() == QAbstractSocket::IPv6Protocol) - { - out = QByteArray(20, 0); - out[1] = 0x02; // IPv6 - Q_IPV6ADDR addr6 = addr.toIPv6Address(); - memcpy(out.data() + 4, addr6.c, 16); - } - else if(addr.protocol() == QAbstractSocket::IPv4Protocol) - { - out = QByteArray(8, 0); - out[1] = 0x01; // IPv4 - write32((quint8 *)out.data() + 4, addr.toIPv4Address()); - } - else - Q_ASSERT(0); - - write16((quint8 *)out.data() + 2, port); - return out; -} - -QByteArray createUsername(const QString &username) -{ - return username.left(STRING_MAX_CHARS).toUtf8(); -} - -QByteArray createErrorCode(int code, const QString &reason) -{ - QByteArray out(4, 0); - - int ih = code / 100; - int il = code % 100; - ih &= 0x07; // keep only lower 3 bits - - unsigned char ch = (unsigned char)ih; - unsigned char cl = (unsigned char)il; - out[2] = ch; - out[3] = cl; - out += reason.left(STRING_MAX_CHARS).toUtf8(); - return out; -} - -QByteArray createUnknownAttributes(const QList &typeList) -{ - if(typeList.isEmpty()) - return QByteArray(); - - QByteArray out(typeList.count() * 2, 0); - for(int n = 0; n < typeList.count(); ++n) - write16((quint8 *)out.data() + (n * 2), typeList[n]); - return out; -} - -QByteArray createRealm(const QString &realm) -{ - return realm.left(STRING_MAX_CHARS).toUtf8(); -} - -QByteArray createNonce(const QString &nonce) -{ - return nonce.left(STRING_MAX_CHARS).toUtf8(); -} - -QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) -{ - QByteArray out = createMappedAddress(addr, port); - if(addr.protocol() == QAbstractSocket::IPv6Protocol) - xorIPv6(&out, magic, id); - else // IPv4 - xorIPv4(&out, magic); - return out; -} - -QByteArray createChannelNumber(quint16 i) -{ - QByteArray val(4, 0); - write16((quint8 *)val.data(), i); - // bytes 2-3 are zeroed out - return val; -} - -QByteArray createLifetime(quint32 i) -{ - QByteArray val(4, 0); - write32((quint8 *)val.data(), i); - return val; -} - -QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) -{ - return createXorMappedAddress(addr, port, magic, id); -} - -QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) -{ - return createXorMappedAddress(addr, port, magic, id); -} - -QByteArray createEvenPort(bool reserve) -{ - QByteArray val(1, 0); - unsigned char c = 0; - if(reserve) - c |= 0x80; // set high bit - val[0] = c; - return val; -} - -QByteArray createRequestedTransport(quint8 proto) -{ - QByteArray val(4, 0); - val[0] = proto; - // bytes 1-3 are zeroed out - return val; -} - -QByteArray createReservationToken(const QByteArray &token) -{ - Q_ASSERT(token.size() == 8); - return token; -} - -QByteArray createPriority(quint32 i) -{ - QByteArray val(4, 0); - write32((quint8 *)val.data(), i); - return val; -} - -QByteArray createSoftware(const QString &str) -{ - return str.left(STRING_MAX_CHARS).toUtf8(); -} - -QByteArray createAlternateServer(const QHostAddress &addr, quint16 port) -{ - return createMappedAddress(addr, port); -} - -QByteArray createIceControlled(quint64 i) -{ - QByteArray val(8, 0); - write64((quint8 *)val.data(), i); - return val; -} - -QByteArray createIceControlling(quint64 i) -{ - QByteArray val(8, 0); - write64((quint8 *)val.data(), i); - return val; -} - -bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port) -{ - if(val[1] == 0x02 && val.size() == 20) // IPv6 - { - *port = read16((const quint8 *)val.data() + 2); - QByteArray buf = val.mid(4); - *addr = QHostAddress((quint8 *)buf.data()); - return true; - } - else if(val[1] == 0x01 && val.size() == 8) // IPv4 + static void xorIPv6(QByteArray *in, const quint8 *magic, const quint8 *id) { - *port = read16((const quint8 *)val.data() + 2); - *addr = QHostAddress(read32((const quint8 *)val.data() + 4)); - return true; + quint8 *p = (quint8 *)in->data(); + p[2] ^= magic[0]; + p[3] ^= magic[1]; + for (int n = 0; n < 4; ++n) + p[n + 4] ^= magic[n]; + for (int n = 0; n < 12; ++n) + p[n + 8] ^= id[n]; } - else - return false; -} -bool parseUsername(const QByteArray &val, QString *username) -{ - return validateString(val, username); -} + static bool validateString(const QByteArray &in, QString *out) + { + if (in.size() <= STRING_MAX_BYTES) { + QString s = QString::fromUtf8(in); + if (s.length() <= STRING_MAX_CHARS) { + *out = s; + return true; + } + } -bool parseErrorCode(const QByteArray &val, int *code, QString *reason) -{ - if(val.size() < 4) return false; + } - unsigned char ch = (unsigned char)val[2]; - unsigned char cl = (unsigned char)val[3]; - int ih = ch & 0x07; // lower 3 bits - int x = ih * 100 + (int)cl; + QByteArray createMappedAddress(const QHostAddress &addr, quint16 port) + { + QByteArray out; + + if (addr.protocol() == QAbstractSocket::IPv6Protocol) { + out = QByteArray(20, 0); + out[1] = 0x02; // IPv6 + Q_IPV6ADDR addr6 = addr.toIPv6Address(); + memcpy(out.data() + 4, addr6.c, 16); + } else if (addr.protocol() == QAbstractSocket::IPv4Protocol) { + out = QByteArray(8, 0); + out[1] = 0x01; // IPv4 + write32((quint8 *)out.data() + 4, addr.toIPv4Address()); + } else + Q_ASSERT(0); + + write16((quint8 *)out.data() + 2, port); + return out; + } - QString str; - if(validateString(val.mid(4), &str)) + QByteArray createUsername(const QString &username) { return username.left(STRING_MAX_CHARS).toUtf8(); } + + QByteArray createErrorCode(int code, const QString &reason) { - *code = x; - *reason = str; - return true; + QByteArray out(4, 0); + + int ih = code / 100; + int il = code % 100; + ih &= 0x07; // keep only lower 3 bits + + unsigned char ch = (unsigned char)ih; + unsigned char cl = (unsigned char)il; + out[2] = ch; + out[3] = cl; + out += reason.left(STRING_MAX_CHARS).toUtf8(); + return out; } - return false; -} + QByteArray createUnknownAttributes(const QList &typeList) + { + if (typeList.isEmpty()) + return QByteArray(); -bool parseUnknownAttributes(const QByteArray &val, QList *typeList) -{ - if(val.size() % 2 != 0) - return false; + QByteArray out(typeList.count() * 2, 0); + for (int n = 0; n < typeList.count(); ++n) + write16((quint8 *)out.data() + (n * 2), typeList[n]); + return out; + } - typeList->clear(); - int count = val.size() / 2; - for(int n = 0; n < count; ++n) - typeList->append(read16((const quint8 *)val.data() + (n * 2))); - return true; -} - -bool parseRealm(const QByteArray &val, QString *realm) -{ - return validateString(val, realm); -} - -bool parseNonce(const QByteArray &val, QString *nonce) -{ - return validateString(val, nonce); -} - -bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port) -{ - if(val.size() < 4) - return false; + QByteArray createRealm(const QString &realm) { return realm.left(STRING_MAX_CHARS).toUtf8(); } + + QByteArray createNonce(const QString &nonce) { return nonce.left(STRING_MAX_CHARS).toUtf8(); } - QByteArray buf; - if(val[1] == 0x02 && val.size() == 20) // IPv6 + QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) { - buf = val; - xorIPv6(&buf, magic, id); + QByteArray out = createMappedAddress(addr, port); + if (addr.protocol() == QAbstractSocket::IPv6Protocol) + xorIPv6(&out, magic, id); + else // IPv4 + xorIPv4(&out, magic); + return out; } - else if(val[1] == 0x01 && val.size() == 8) // IPv4 + + QByteArray createChannelNumber(quint16 i) { - buf = val; - xorIPv4(&buf, magic); + QByteArray val(4, 0); + write16((quint8 *)val.data(), i); + // bytes 2-3 are zeroed out + return val; } - else - return false; - return parseMappedAddress(buf, addr, port); -} + QByteArray createLifetime(quint32 i) + { + QByteArray val(4, 0); + write32((quint8 *)val.data(), i); + return val; + } -bool parseChannelNumber(const QByteArray &val, quint16 *i) -{ - if(val.size() != 4) - return false; + QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) + { + return createXorMappedAddress(addr, port, magic, id); + } - const quint8 *p = (const quint8 *)val.data(); - *i = read16(p); - return true; -} + QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id) + { + return createXorMappedAddress(addr, port, magic, id); + } -bool parseLifetime(const QByteArray &val, quint32 *i) -{ - if(val.size() != 4) - return false; + QByteArray createEvenPort(bool reserve) + { + QByteArray val(1, 0); + unsigned char c = 0; + if (reserve) + c |= 0x80; // set high bit + val[0] = c; + return val; + } - const quint8 *p = (const quint8 *)val.data(); - *i = read32(p); - return true; -} + QByteArray createRequestedTransport(quint8 proto) + { + QByteArray val(4, 0); + val[0] = proto; + // bytes 1-3 are zeroed out + return val; + } -bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port) -{ - return parseXorMappedAddress(val, magic, id, addr, port); -} + QByteArray createReservationToken(const QByteArray &token) + { + Q_ASSERT(token.size() == 8); + return token; + } -bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port) -{ - return parseXorMappedAddress(val, magic, id, addr, port); -} + QByteArray createPriority(quint32 i) + { + QByteArray val(4, 0); + write32((quint8 *)val.data(), i); + return val; + } -bool parseEvenPort(const QByteArray &val, bool *reserve) -{ - if(val.size() != 1) - return false; + QByteArray createSoftware(const QString &str) { return str.left(STRING_MAX_CHARS).toUtf8(); } - unsigned char c = val[0]; - if(c & 0x80) - *reserve = true; - else - *reserve = false; + QByteArray createAlternateServer(const QHostAddress &addr, quint16 port) { return createMappedAddress(addr, port); } - return true; -} + QByteArray createIceControlled(quint64 i) + { + QByteArray val(8, 0); + write64((quint8 *)val.data(), i); + return val; + } -bool parseRequestedTransport(const QByteArray &val, quint8 *proto) -{ - if(val.size() != 4) - return false; + QByteArray createIceControlling(quint64 i) + { + QByteArray val(8, 0); + write64((quint8 *)val.data(), i); + return val; + } - *proto = val[0]; - return true; -} + bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port) + { + if (val[1] == 0x02 && val.size() == 20) // IPv6 + { + *port = read16((const quint8 *)val.data() + 2); + QByteArray buf = val.mid(4); + *addr = QHostAddress((quint8 *)buf.data()); + return true; + } else if (val[1] == 0x01 && val.size() == 8) // IPv4 + { + *port = read16((const quint8 *)val.data() + 2); + *addr = QHostAddress(read32((const quint8 *)val.data() + 4)); + return true; + } else + return false; + } -bool parseReservationToken(const QByteArray &val, QByteArray *token) -{ - if(val.size() != 8) - return false; + bool parseUsername(const QByteArray &val, QString *username) { return validateString(val, username); } - *token = val; - return true; -} + bool parseErrorCode(const QByteArray &val, int *code, QString *reason) + { + if (val.size() < 4) + return false; + + unsigned char ch = (unsigned char)val[2]; + unsigned char cl = (unsigned char)val[3]; + int ih = ch & 0x07; // lower 3 bits + int x = ih * 100 + (int)cl; + + QString str; + if (validateString(val.mid(4), &str)) { + *code = x; + *reason = str; + return true; + } -bool parsePriority(const QByteArray &val, quint32 *i) -{ - if(val.size() != 4) return false; + } - const quint8 *p = (const quint8 *)val.data(); - *i = read32(p); - return true; -} - -bool parseSoftware(const QByteArray &val, QString *str) -{ - *str = QString::fromUtf8(val); - return true; -} - -bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port) -{ - return parseMappedAddress(val, addr, port); -} - -bool parseIceControlled(const QByteArray &val, quint64 *i) -{ - if(val.size() != 8) - return false; + bool parseUnknownAttributes(const QByteArray &val, QList *typeList) + { + if (val.size() % 2 != 0) + return false; - const quint8 *p = (const quint8 *)val.data(); - *i = read64(p); - return true; -} + typeList->clear(); + int count = val.size() / 2; + for (int n = 0; n < count; ++n) + typeList->append(read16((const quint8 *)val.data() + (n * 2))); + return true; + } -bool parseIceControlling(const QByteArray &val, quint64 *i) -{ - if(val.size() != 8) - return false; + bool parseRealm(const QByteArray &val, QString *realm) { return validateString(val, realm); } - const quint8 *p = (const quint8 *)val.data(); - *i = read64(p); - return true; -} - -#define METHOD_ENTRY(x) \ - { x, #x } - -struct MethodEntry -{ - Method method; - const char *str; -} method_table[] = -{ - METHOD_ENTRY(Binding), - METHOD_ENTRY(Allocate), - METHOD_ENTRY(Refresh), - METHOD_ENTRY(Send), - METHOD_ENTRY(Data), - METHOD_ENTRY(CreatePermission), - METHOD_ENTRY(ChannelBind), - { (Method)-1, nullptr } -}; - -QString methodToString(int method) -{ - for(int n = 0; method_table[n].str; ++n) - { - if(method_table[n].method == (Method)method) - return QString::fromLatin1(method_table[n].str); - } - - return QString(); -} - -#define ATTRIB_ENTRY(x) \ - { x, #x } - -struct AttribEntry -{ - Attribute type; - const char *str; -} attrib_table[] = -{ - ATTRIB_ENTRY(MAPPED_ADDRESS), - ATTRIB_ENTRY(USERNAME), - ATTRIB_ENTRY(MESSAGE_INTEGRITY), - ATTRIB_ENTRY(ERROR_CODE), - ATTRIB_ENTRY(UNKNOWN_ATTRIBUTES), - ATTRIB_ENTRY(REALM), - ATTRIB_ENTRY(NONCE), - ATTRIB_ENTRY(XOR_MAPPED_ADDRESS), - ATTRIB_ENTRY(CHANNEL_NUMBER), - ATTRIB_ENTRY(LIFETIME), - ATTRIB_ENTRY(XOR_PEER_ADDRESS), - ATTRIB_ENTRY(DATA), - ATTRIB_ENTRY(XOR_RELAYED_ADDRESS), - ATTRIB_ENTRY(EVEN_PORT), - ATTRIB_ENTRY(REQUESTED_TRANSPORT), - ATTRIB_ENTRY(DONT_FRAGMENT), - ATTRIB_ENTRY(RESERVATION_TOKEN), - ATTRIB_ENTRY(PRIORITY), - ATTRIB_ENTRY(USE_CANDIDATE), - ATTRIB_ENTRY(SOFTWARE), - ATTRIB_ENTRY(ALTERNATE_SERVER), - ATTRIB_ENTRY(FINGERPRINT), - ATTRIB_ENTRY(ICE_CONTROLLED), - ATTRIB_ENTRY(ICE_CONTROLLING), - { (Attribute)-1, nullptr } -}; - -QString attributeTypeToString(int type) -{ - for(int n = 0; attrib_table[n].str; ++n) - { - if(attrib_table[n].type == (Attribute)type) + bool parseNonce(const QByteArray &val, QString *nonce) { return validateString(val, nonce); } + + bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port) + { + if (val.size() < 4) + return false; + + QByteArray buf; + if (val[1] == 0x02 && val.size() == 20) // IPv6 + { + buf = val; + xorIPv6(&buf, magic, id); + } else if (val[1] == 0x01 && val.size() == 8) // IPv4 { - QString name = QString::fromLatin1(attrib_table[n].str); - name.replace('_', '-'); - return name; + buf = val; + xorIPv4(&buf, magic); + } else + return false; + + return parseMappedAddress(buf, addr, port); + } + + bool parseChannelNumber(const QByteArray &val, quint16 *i) + { + if (val.size() != 4) + return false; + + const quint8 *p = (const quint8 *)val.data(); + *i = read16(p); + return true; + } + + bool parseLifetime(const QByteArray &val, quint32 *i) + { + if (val.size() != 4) + return false; + + const quint8 *p = (const quint8 *)val.data(); + *i = read32(p); + return true; + } + + bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port) + { + return parseXorMappedAddress(val, magic, id, addr, port); + } + + bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port) + { + return parseXorMappedAddress(val, magic, id, addr, port); + } + + bool parseEvenPort(const QByteArray &val, bool *reserve) + { + if (val.size() != 1) + return false; + + unsigned char c = val[0]; + if (c & 0x80) + *reserve = true; + else + *reserve = false; + + return true; + } + + bool parseRequestedTransport(const QByteArray &val, quint8 *proto) + { + if (val.size() != 4) + return false; + + *proto = val[0]; + return true; + } + + bool parseReservationToken(const QByteArray &val, QByteArray *token) + { + if (val.size() != 8) + return false; + + *token = val; + return true; + } + + bool parsePriority(const QByteArray &val, quint32 *i) + { + if (val.size() != 4) + return false; + + const quint8 *p = (const quint8 *)val.data(); + *i = read32(p); + return true; + } + + bool parseSoftware(const QByteArray &val, QString *str) + { + *str = QString::fromUtf8(val); + return true; + } + + bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port) + { + return parseMappedAddress(val, addr, port); + } + + bool parseIceControlled(const QByteArray &val, quint64 *i) + { + if (val.size() != 8) + return false; + + const quint8 *p = (const quint8 *)val.data(); + *i = read64(p); + return true; + } + + bool parseIceControlling(const QByteArray &val, quint64 *i) + { + if (val.size() != 8) + return false; + + const quint8 *p = (const quint8 *)val.data(); + *i = read64(p); + return true; + } + +#define METHOD_ENTRY(x) \ + { \ + x, #x \ + } + + struct MethodEntry { + Method method; + const char *str; + } method_table[] + = { METHOD_ENTRY(Binding), METHOD_ENTRY(Allocate), METHOD_ENTRY(Refresh), METHOD_ENTRY(Send), + METHOD_ENTRY(Data), METHOD_ENTRY(CreatePermission), METHOD_ENTRY(ChannelBind), { (Method)-1, nullptr } }; + + QString methodToString(int method) + { + for (int n = 0; method_table[n].str; ++n) { + if (method_table[n].method == (Method)method) + return QString::fromLatin1(method_table[n].str); } + + return QString(); } - return QString(); -} +#define ATTRIB_ENTRY(x) \ + { \ + x, #x \ + } -static QString quoted(const QString &in) -{ - return QString("\"") + in + '\"'; -} + struct AttribEntry { + Attribute type; + const char *str; + } attrib_table[] = { ATTRIB_ENTRY(MAPPED_ADDRESS), + ATTRIB_ENTRY(USERNAME), + ATTRIB_ENTRY(MESSAGE_INTEGRITY), + ATTRIB_ENTRY(ERROR_CODE), + ATTRIB_ENTRY(UNKNOWN_ATTRIBUTES), + ATTRIB_ENTRY(REALM), + ATTRIB_ENTRY(NONCE), + ATTRIB_ENTRY(XOR_MAPPED_ADDRESS), + ATTRIB_ENTRY(CHANNEL_NUMBER), + ATTRIB_ENTRY(LIFETIME), + ATTRIB_ENTRY(XOR_PEER_ADDRESS), + ATTRIB_ENTRY(DATA), + ATTRIB_ENTRY(XOR_RELAYED_ADDRESS), + ATTRIB_ENTRY(EVEN_PORT), + ATTRIB_ENTRY(REQUESTED_TRANSPORT), + ATTRIB_ENTRY(DONT_FRAGMENT), + ATTRIB_ENTRY(RESERVATION_TOKEN), + ATTRIB_ENTRY(PRIORITY), + ATTRIB_ENTRY(USE_CANDIDATE), + ATTRIB_ENTRY(SOFTWARE), + ATTRIB_ENTRY(ALTERNATE_SERVER), + ATTRIB_ENTRY(FINGERPRINT), + ATTRIB_ENTRY(ICE_CONTROLLED), + ATTRIB_ENTRY(ICE_CONTROLLING), + { (Attribute)-1, nullptr } }; + + QString attributeTypeToString(int type) + { + for (int n = 0; attrib_table[n].str; ++n) { + if (attrib_table[n].type == (Attribute)type) { + QString name = QString::fromLatin1(attrib_table[n].str); + name.replace('_', '-'); + return name; + } + } -QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id) -{ - switch((Attribute)type) + return QString(); + } + + static QString quoted(const QString &in) { return QString("\"") + in + '\"'; } + + QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id) { - case MAPPED_ADDRESS: - { + switch ((Attribute)type) { + case MAPPED_ADDRESS: { QHostAddress addr; - quint16 port; - if(parseMappedAddress(val, &addr, &port)) + quint16 port; + if (parseMappedAddress(val, &addr, &port)) return addr.toString() + ';' + QString::number(port); break; } - case USERNAME: - { + case USERNAME: { QString str; - if(parseUsername(val, &str)) + if (parseUsername(val, &str)) return quoted(str); break; } - case MESSAGE_INTEGRITY: - { + case MESSAGE_INTEGRITY: { return QCA::arrayToHex(val); } - case ERROR_CODE: - { - int code; + case ERROR_CODE: { + int code; QString reason; - if(parseErrorCode(val, &code, &reason)) - { + if (parseErrorCode(val, &code, &reason)) { QString out = QString::number(code); - if(!reason.isEmpty()) + if (!reason.isEmpty()) out += QString(", ") + quoted(reason); return out; } break; } - case UNKNOWN_ATTRIBUTES: - { + case UNKNOWN_ATTRIBUTES: { QList typeList; - if(parseUnknownAttributes(val, &typeList)) - { - if(!typeList.isEmpty()) - { + if (parseUnknownAttributes(val, &typeList)) { + if (!typeList.isEmpty()) { QStringList strList; - foreach(quint16 i, typeList) + foreach (quint16 i, typeList) strList += QString().sprintf("0x%04x", i); return strList.join(", "); - } - else + } else return "(None)"; } break; } - case REALM: - { + case REALM: { QString str; - if(parseRealm(val, &str)) + if (parseRealm(val, &str)) return quoted(str); break; } - case NONCE: - { + case NONCE: { QString str; - if(parseNonce(val, &str)) + if (parseNonce(val, &str)) return quoted(str); break; } - case XOR_MAPPED_ADDRESS: - { + case XOR_MAPPED_ADDRESS: { QHostAddress addr; - quint16 port; - if(parseXorMappedAddress(val, magic, id, &addr, &port)) + quint16 port; + if (parseXorMappedAddress(val, magic, id, &addr, &port)) return addr.toString() + ';' + QString::number(port); break; } - case CHANNEL_NUMBER: - { + case CHANNEL_NUMBER: { quint16 i; - if(parseChannelNumber(val, &i)) + if (parseChannelNumber(val, &i)) return QString().sprintf("0x%04x", (int)i); break; } - case LIFETIME: - { + case LIFETIME: { quint32 i; - if(parseLifetime(val, &i)) + if (parseLifetime(val, &i)) return QString::number(i); break; } - case XOR_PEER_ADDRESS: - { + case XOR_PEER_ADDRESS: { return attributeValueToString(XOR_MAPPED_ADDRESS, val, magic, id); } - case DATA: - { + case DATA: { return QString("len=%1, ").arg(val.size()) + QCA::arrayToHex(val); } - case XOR_RELAYED_ADDRESS: - { + case XOR_RELAYED_ADDRESS: { return attributeValueToString(XOR_MAPPED_ADDRESS, val, magic, id); } - case EVEN_PORT: - { + case EVEN_PORT: { bool reserve; - if(parseEvenPort(val, &reserve)) + if (parseEvenPort(val, &reserve)) return QString("reserve=") + (reserve ? "true" : "false"); break; } - case REQUESTED_TRANSPORT: - { + case REQUESTED_TRANSPORT: { quint8 proto; - if(parseRequestedTransport(val, &proto)) - { + if (parseRequestedTransport(val, &proto)) { QString str = QString::number((int)proto); - if(proto == 17) // UDP + if (proto == 17) // UDP str += " (UDP)"; else str += " (Unknown)"; @@ -620,113 +552,96 @@ QString attributeValueToString(int type, const QByteArray &val, const quint8 *ma } break; } - case DONT_FRAGMENT: - { + case DONT_FRAGMENT: { return QString(""); } - case RESERVATION_TOKEN: - { + case RESERVATION_TOKEN: { QByteArray token; - if(parseReservationToken(val, &token)) + if (parseReservationToken(val, &token)) return QCA::arrayToHex(token); break; } - case PRIORITY: - { + case PRIORITY: { quint32 i; - if(parsePriority(val, &i)) + if (parsePriority(val, &i)) return QString::number(i); break; } - case USE_CANDIDATE: - { + case USE_CANDIDATE: { return QString(""); } - case SOFTWARE: - { + case SOFTWARE: { QString out; - if(parseSoftware(val, &out)) + if (parseSoftware(val, &out)) return quoted(out); break; } - case ALTERNATE_SERVER: - { + case ALTERNATE_SERVER: { return attributeValueToString(MAPPED_ADDRESS, val, magic, id); } - case FINGERPRINT: - { + case FINGERPRINT: { return QCA::arrayToHex(val); } - case ICE_CONTROLLED: - { + case ICE_CONTROLLED: { quint64 i; - if(parseIceControlled(val, &i)) + if (parseIceControlled(val, &i)) return QString::number(i); break; } - case ICE_CONTROLLING: - { + case ICE_CONTROLLING: { quint64 i; - if(parseIceControlling(val, &i)) + if (parseIceControlling(val, &i)) return QString::number(i); break; } + } + + return QString(); } - return QString(); -} - -QString print_packet_str(const StunMessage &message) -{ - QString out; - - QString mclass; - if(message.mclass() == StunMessage::Request) - mclass = "Request"; - else if(message.mclass() == StunMessage::SuccessResponse) - mclass = "Response (Success)"; - else if(message.mclass() == StunMessage::ErrorResponse) - mclass = "Response (Error)"; - else if(message.mclass() == StunMessage::Indication) - mclass = "Indication"; - else - Q_ASSERT(0); - - out += QString("Class: %1\n").arg(mclass); - out += QString("Method: %1\n").arg(methodToString(message.method())); - out += QString("Transaction id: %1\n").arg(QCA::arrayToHex(QByteArray((const char *)message.id(), 12))); - out += "Attributes:"; - QList attribs = message.attributes(); - if(!attribs.isEmpty()) - { - foreach(const StunMessage::Attribute &a, attribs) - { - out += '\n'; - - QString name = attributeTypeToString(a.type); - if(!name.isNull()) - { - QString val = attributeValueToString(a.type, a.value, message.magic(), message.id()); - if(val.isNull()) - val = QString("Unable to parse %1 bytes").arg(a.value.size()); - - out += QString(" %1").arg(name); - if(!val.isEmpty()) - out += QString(" = %1").arg(val); + QString print_packet_str(const StunMessage &message) + { + QString out; + + QString mclass; + if (message.mclass() == StunMessage::Request) + mclass = "Request"; + else if (message.mclass() == StunMessage::SuccessResponse) + mclass = "Response (Success)"; + else if (message.mclass() == StunMessage::ErrorResponse) + mclass = "Response (Error)"; + else if (message.mclass() == StunMessage::Indication) + mclass = "Indication"; + else + Q_ASSERT(0); + + out += QString("Class: %1\n").arg(mclass); + out += QString("Method: %1\n").arg(methodToString(message.method())); + out += QString("Transaction id: %1\n").arg(QCA::arrayToHex(QByteArray((const char *)message.id(), 12))); + out += "Attributes:"; + QList attribs = message.attributes(); + if (!attribs.isEmpty()) { + foreach (const StunMessage::Attribute &a, attribs) { + out += '\n'; + + QString name = attributeTypeToString(a.type); + if (!name.isNull()) { + QString val = attributeValueToString(a.type, a.value, message.magic(), message.id()); + if (val.isNull()) + val = QString("Unable to parse %1 bytes").arg(a.value.size()); + + out += QString(" %1").arg(name); + if (!val.isEmpty()) + out += QString(" = %1").arg(val); + } else + out += QString().sprintf(" Unknown attribute (0x%04x) of %d bytes", a.type, a.value.size()); } - else - out += QString().sprintf(" Unknown attribute (0x%04x) of %d bytes", a.type, a.value.size()); - } - } - else - out += "\n (None)"; + } else + out += "\n (None)"; - return out; -} + return out; + } -void print_packet(const StunMessage &message) -{ - printf("%s\n", qPrintable(print_packet_str(message))); -} + void print_packet(const StunMessage &message) { printf("%s\n", qPrintable(print_packet_str(message))); } } // namespace StunTypes } // namespace XMPP diff --git a/src/irisnet/noncore/stuntypes.h b/src/irisnet/noncore/stuntypes.h index c09da16b..636a527d 100644 --- a/src/irisnet/noncore/stuntypes.h +++ b/src/irisnet/noncore/stuntypes.h @@ -26,115 +26,114 @@ #include #include -namespace XMPP { -namespace StunTypes { -enum Method -{ - Binding = 0x001, - Allocate = 0x003, - Refresh = 0x004, - Send = 0x006, - Data = 0x007, - CreatePermission = 0x008, - ChannelBind = 0x009 -}; - -enum Attribute -{ - MAPPED_ADDRESS = 0x0001, - USERNAME = 0x0006, - MESSAGE_INTEGRITY = 0x0008, - ERROR_CODE = 0x0009, - UNKNOWN_ATTRIBUTES = 0x000a, - REALM = 0x0014, - NONCE = 0x0015, - XOR_MAPPED_ADDRESS = 0x0020, - CHANNEL_NUMBER = 0x000c, - LIFETIME = 0x000d, - XOR_PEER_ADDRESS = 0x0012, - DATA = 0x0013, - XOR_RELAYED_ADDRESS = 0x0016, - EVEN_PORT = 0x0018, - REQUESTED_TRANSPORT = 0x0019, - DONT_FRAGMENT = 0x001a, - RESERVATION_TOKEN = 0x0022, - - PRIORITY = 0x0024, - USE_CANDIDATE = 0x0025, - - SOFTWARE = 0x8022, - ALTERNATE_SERVER = 0x8023, - FINGERPRINT = 0x8028, - - ICE_CONTROLLED = 0x8029, - ICE_CONTROLLING = 0x802a -}; - -enum Error -{ - TryAlternate = 300, - BadRequest = 400, - Unauthorized = 401, - UnknownAttribute = 420, - StaleNonce = 438, - ServerError = 500, - - Forbidden = 403, - AllocationMismatch = 437, - WrongCredentials = 441, - UnsupportedTransportProtocol = 442, - AllocationQuotaReached = 486, - InsufficientCapacity = 508, - - RoleConflict = 487 -}; - -QByteArray createMappedAddress(const QHostAddress &addr, quint16 port); -QByteArray createUsername(const QString &username); -QByteArray createErrorCode(int code, const QString &reason); -QByteArray createUnknownAttributes(const QList &typeList); -QByteArray createRealm(const QString &realm); -QByteArray createNonce(const QString &nonce); -QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); -QByteArray createChannelNumber(quint16 i); -QByteArray createLifetime(quint32 i); -QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); -QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); -QByteArray createEvenPort(bool reserve); -QByteArray createRequestedTransport(quint8 proto); -QByteArray createReservationToken(const QByteArray &token); -QByteArray createPriority(quint32 i); -QByteArray createSoftware(const QString &str); -QByteArray createAlternateServer(const QHostAddress &addr, quint16 port); -QByteArray createIceControlled(quint64 i); -QByteArray createIceControlling(quint64 i); - -bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port); -bool parseUsername(const QByteArray &val, QString *username); -bool parseErrorCode(const QByteArray &val, int *code, QString *reason); -bool parseUnknownAttributes(const QByteArray &val, QList *typeList); -bool parseRealm(const QByteArray &val, QString *realm); -bool parseNonce(const QByteArray &val, QString *nonce); -bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port); -bool parseChannelNumber(const QByteArray &val, quint16 *i); -bool parseLifetime(const QByteArray &val, quint32 *i); -bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port); -bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port); -bool parseEvenPort(const QByteArray &val, bool *reserve); -bool parseRequestedTransport(const QByteArray &val, quint8 *proto); -bool parseReservationToken(const QByteArray &val, QByteArray *token); -bool parsePriority(const QByteArray &val, quint32 *i); -bool parseSoftware(const QByteArray &val, QString *str); -bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port); -bool parseIceControlled(const QByteArray &val, quint64 *i); -bool parseIceControlling(const QByteArray &val, quint64 *i); - -QString methodToString(int method); -QString attributeTypeToString(int type); -QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id); - -QString print_packet_str(const StunMessage &message); -void print_packet(const StunMessage &message); +namespace XMPP { namespace StunTypes { + enum Method { + Binding = 0x001, + Allocate = 0x003, + Refresh = 0x004, + Send = 0x006, + Data = 0x007, + CreatePermission = 0x008, + ChannelBind = 0x009 + }; + + enum Attribute { + MAPPED_ADDRESS = 0x0001, + USERNAME = 0x0006, + MESSAGE_INTEGRITY = 0x0008, + ERROR_CODE = 0x0009, + UNKNOWN_ATTRIBUTES = 0x000a, + REALM = 0x0014, + NONCE = 0x0015, + XOR_MAPPED_ADDRESS = 0x0020, + CHANNEL_NUMBER = 0x000c, + LIFETIME = 0x000d, + XOR_PEER_ADDRESS = 0x0012, + DATA = 0x0013, + XOR_RELAYED_ADDRESS = 0x0016, + EVEN_PORT = 0x0018, + REQUESTED_TRANSPORT = 0x0019, + DONT_FRAGMENT = 0x001a, + RESERVATION_TOKEN = 0x0022, + + PRIORITY = 0x0024, + USE_CANDIDATE = 0x0025, + + SOFTWARE = 0x8022, + ALTERNATE_SERVER = 0x8023, + FINGERPRINT = 0x8028, + + ICE_CONTROLLED = 0x8029, + ICE_CONTROLLING = 0x802a + }; + + enum Error { + TryAlternate = 300, + BadRequest = 400, + Unauthorized = 401, + UnknownAttribute = 420, + StaleNonce = 438, + ServerError = 500, + + Forbidden = 403, + AllocationMismatch = 437, + WrongCredentials = 441, + UnsupportedTransportProtocol = 442, + AllocationQuotaReached = 486, + InsufficientCapacity = 508, + + RoleConflict = 487 + }; + + QByteArray createMappedAddress(const QHostAddress &addr, quint16 port); + QByteArray createUsername(const QString &username); + QByteArray createErrorCode(int code, const QString &reason); + QByteArray createUnknownAttributes(const QList &typeList); + QByteArray createRealm(const QString &realm); + QByteArray createNonce(const QString &nonce); + QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); + QByteArray createChannelNumber(quint16 i); + QByteArray createLifetime(quint32 i); + QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); + QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id); + QByteArray createEvenPort(bool reserve); + QByteArray createRequestedTransport(quint8 proto); + QByteArray createReservationToken(const QByteArray &token); + QByteArray createPriority(quint32 i); + QByteArray createSoftware(const QString &str); + QByteArray createAlternateServer(const QHostAddress &addr, quint16 port); + QByteArray createIceControlled(quint64 i); + QByteArray createIceControlling(quint64 i); + + bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port); + bool parseUsername(const QByteArray &val, QString *username); + bool parseErrorCode(const QByteArray &val, int *code, QString *reason); + bool parseUnknownAttributes(const QByteArray &val, QList *typeList); + bool parseRealm(const QByteArray &val, QString *realm); + bool parseNonce(const QByteArray &val, QString *nonce); + bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port); + bool parseChannelNumber(const QByteArray &val, quint16 *i); + bool parseLifetime(const QByteArray &val, quint32 *i); + bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port); + bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, + quint16 *port); + bool parseEvenPort(const QByteArray &val, bool *reserve); + bool parseRequestedTransport(const QByteArray &val, quint8 *proto); + bool parseReservationToken(const QByteArray &val, QByteArray *token); + bool parsePriority(const QByteArray &val, quint32 *i); + bool parseSoftware(const QByteArray &val, QString *str); + bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port); + bool parseIceControlled(const QByteArray &val, quint64 *i); + bool parseIceControlling(const QByteArray &val, quint64 *i); + + QString methodToString(int method); + QString attributeTypeToString(int type); + QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id); + + QString print_packet_str(const StunMessage &message); + void print_packet(const StunMessage &message); } // namespace StunTypes } // namespace XMPP diff --git a/src/irisnet/noncore/stunutil.cpp b/src/irisnet/noncore/stunutil.cpp index 46afe447..4331fe41 100644 --- a/src/irisnet/noncore/stunutil.cpp +++ b/src/irisnet/noncore/stunutil.cpp @@ -18,78 +18,77 @@ #include "stunutil.h" -namespace XMPP { -namespace StunUtil { -quint16 read16(const quint8 *in) -{ - quint16 out = in[0]; - out <<= 8; - out += in[1]; - return out; -} +namespace XMPP { namespace StunUtil { + quint16 read16(const quint8 *in) + { + quint16 out = in[0]; + out <<= 8; + out += in[1]; + return out; + } -quint32 read32(const quint8 *in) -{ - quint32 out = in[0]; - out <<= 8; - out += in[1]; - out <<= 8; - out += in[2]; - out <<= 8; - out += in[3]; - return out; -} + quint32 read32(const quint8 *in) + { + quint32 out = in[0]; + out <<= 8; + out += in[1]; + out <<= 8; + out += in[2]; + out <<= 8; + out += in[3]; + return out; + } -quint64 read64(const quint8 *in) -{ - quint64 out = in[0]; - out <<= 8; - out += in[1]; - out <<= 8; - out += in[2]; - out <<= 8; - out += in[3]; - out <<= 8; - out += in[4]; - out <<= 8; - out += in[5]; - out <<= 8; - out += in[6]; - out <<= 8; - out += in[7]; - return out; -} + quint64 read64(const quint8 *in) + { + quint64 out = in[0]; + out <<= 8; + out += in[1]; + out <<= 8; + out += in[2]; + out <<= 8; + out += in[3]; + out <<= 8; + out += in[4]; + out <<= 8; + out += in[5]; + out <<= 8; + out += in[6]; + out <<= 8; + out += in[7]; + return out; + } -void write16(quint8 *out, quint16 i) -{ - out[0] = (i >> 8) & 0xff; - out[1] = i & 0xff; -} + void write16(quint8 *out, quint16 i) + { + out[0] = (i >> 8) & 0xff; + out[1] = i & 0xff; + } -void write32(quint8 *out, quint32 i) -{ - out[0] = (i >> 24) & 0xff; - out[1] = (i >> 16) & 0xff; - out[2] = (i >> 8) & 0xff; - out[3] = i & 0xff; -} + void write32(quint8 *out, quint32 i) + { + out[0] = (i >> 24) & 0xff; + out[1] = (i >> 16) & 0xff; + out[2] = (i >> 8) & 0xff; + out[3] = i & 0xff; + } -void write64(quint8 *out, quint64 i) -{ - out[0] = (i >> 56) & 0xff; - out[1] = (i >> 48) & 0xff; - out[2] = (i >> 40) & 0xff; - out[3] = (i >> 32) & 0xff; - out[4] = (i >> 24) & 0xff; - out[5] = (i >> 16) & 0xff; - out[6] = (i >> 8) & 0xff; - out[7] = i & 0xff; -} + void write64(quint8 *out, quint64 i) + { + out[0] = (i >> 56) & 0xff; + out[1] = (i >> 48) & 0xff; + out[2] = (i >> 40) & 0xff; + out[3] = (i >> 32) & 0xff; + out[4] = (i >> 24) & 0xff; + out[5] = (i >> 16) & 0xff; + out[6] = (i >> 8) & 0xff; + out[7] = i & 0xff; + } -QCA::SecureArray saslPrep(const QCA::SecureArray &in) -{ - // TODO - return in; -} + QCA::SecureArray saslPrep(const QCA::SecureArray &in) + { + // TODO + return in; + } } // namespace StunUtil } // namespace XMPP diff --git a/src/irisnet/noncore/stunutil.h b/src/irisnet/noncore/stunutil.h index ca71f011..7ec74cf2 100644 --- a/src/irisnet/noncore/stunutil.h +++ b/src/irisnet/noncore/stunutil.h @@ -21,17 +21,16 @@ #include -namespace XMPP { -namespace StunUtil { -quint16 read16(const quint8 *in); -quint32 read32(const quint8 *in); -quint64 read64(const quint8 *in); +namespace XMPP { namespace StunUtil { + quint16 read16(const quint8 *in); + quint32 read32(const quint8 *in); + quint64 read64(const quint8 *in); -void write16(quint8 *out, quint16 i); -void write32(quint8 *out, quint32 i); -void write64(quint8 *out, quint64 i); + void write16(quint8 *out, quint16 i); + void write32(quint8 *out, quint32 i); + void write64(quint8 *out, quint64 i); -QCA::SecureArray saslPrep(const QCA::SecureArray &in); + QCA::SecureArray saslPrep(const QCA::SecureArray &in); } // namespace StunUtil } // namespace XMPP diff --git a/src/irisnet/noncore/tcpportreserver.cpp b/src/irisnet/noncore/tcpportreserver.cpp index 32039e91..ba4fe14d 100644 --- a/src/irisnet/noncore/tcpportreserver.cpp +++ b/src/irisnet/noncore/tcpportreserver.cpp @@ -26,14 +26,10 @@ #include namespace XMPP { -TcpPortDiscoverer::TcpPortDiscoverer(TcpPortScope *scope) : - QObject(scope), - scope(scope) -{ - -} +TcpPortDiscoverer::TcpPortDiscoverer(TcpPortScope *scope) : QObject(scope), scope(scope) {} -bool TcpPortDiscoverer::setExternalHost(const QString &extHost, quint16 extPort, const QHostAddress &localAddr, quint16 localPort) +bool TcpPortDiscoverer::setExternalHost(const QString &extHost, quint16 extPort, const QHostAddress &localAddr, + quint16 localPort) { if (!(typeMask & TcpPortServer::NatAssited)) { return false; // seems like we don't need nat-assited @@ -43,7 +39,7 @@ bool TcpPortDiscoverer::setExternalHost(const QString &extHost, quint16 extPort, return false; } TcpPortServer::Port p; - p.portType = TcpPortServer::NatAssited; + p.portType = TcpPortServer::NatAssited; p.publishHost = extHost; p.publishPort = extPort; server->setPortInfo(p); @@ -66,10 +62,11 @@ TcpPortServer::PortTypes TcpPortDiscoverer::setTypeMask(TcpPortServer::PortTypes { this->typeMask = mask; // drop ready ports if any - std::remove_if(servers.begin(), servers.end(), [mask](auto &s){ return !(s->portType() & mask); }); + std::remove_if(servers.begin(), servers.end(), [mask](auto &s) { return !(s->portType() & mask); }); TcpPortServer::PortTypes pendingTypes; - for (auto &s: servers) pendingTypes |= s->portType(); + for (auto &s : servers) + pendingTypes |= s->portType(); // TODO drop pending subdiscoveries too and update pendingType when implemented return pendingTypes; @@ -78,8 +75,7 @@ TcpPortServer::PortTypes TcpPortDiscoverer::setTypeMask(TcpPortServer::PortTypes void TcpPortDiscoverer::start() { QList listenAddrs; - foreach(const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) - { + foreach (const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) { if (!(ni.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning))) { continue; } @@ -87,8 +83,7 @@ void TcpPortDiscoverer::start() continue; } QList entries = ni.addressEntries(); - foreach(const QNetworkAddressEntry &na, entries) - { + foreach (const QNetworkAddressEntry &na, entries) { QHostAddress h = na.ip(); if (h.isLoopback()) { continue; @@ -99,25 +94,25 @@ void TcpPortDiscoverer::start() // two link-local ipv6 interfaces // with the exact same address, we // only use the first one - if(listenAddrs.contains(h)) + if (listenAddrs.contains(h)) continue; -#if QT_VERSION >= QT_VERSION_CHECK(5,11,0) - if(h.protocol() == QAbstractSocket::IPv6Protocol && h.isLinkLocal()) +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + if (h.protocol() == QAbstractSocket::IPv6Protocol && h.isLinkLocal()) #else - if(h.protocol() == QAbstractSocket::IPv6Protocol && XMPP::Ice176::isIPv6LinkLocalAddress(h)) + if (h.protocol() == QAbstractSocket::IPv6Protocol && XMPP::Ice176::isIPv6LinkLocalAddress(h)) #endif h.setScopeId(ni.name()); listenAddrs += h; } } - for (auto &h: listenAddrs) { + for (auto &h : listenAddrs) { auto server = scope->bind(h, 0); if (!server) { continue; } TcpPortServer::Port p; - p.portType = TcpPortServer::Direct; + p.portType = TcpPortServer::Direct; QHostAddress addr = server->serverAddress(); addr.setScopeId(QString()); p.publishHost = addr.toString(); @@ -140,7 +135,7 @@ QList TcpPortDiscoverer::takeServers() { auto ret = servers; servers.clear(); - for (auto &p: ret) { + for (auto &p : ret) { p->disconnect(this); } return ret; @@ -149,25 +144,18 @@ QList TcpPortDiscoverer::takeServers() // -------------------------------------------------------------------------- // TcpPortScope // -------------------------------------------------------------------------- -struct TcpPortScope::Private -{ - QHash, QWeakPointer> servers; +struct TcpPortScope::Private { + QHash, QWeakPointer> servers; }; -TcpPortScope::TcpPortScope() : - d(new Private) -{ -} - -TcpPortScope::~TcpPortScope() -{ +TcpPortScope::TcpPortScope() : d(new Private) {} -} +TcpPortScope::~TcpPortScope() {} TcpPortDiscoverer *TcpPortScope::disco() { auto discoverer = new TcpPortDiscoverer(this); - QMetaObject::invokeMethod(parent(), "newDiscoverer", Q_ARG(TcpPortDiscoverer*, discoverer)); + QMetaObject::invokeMethod(parent(), "newDiscoverer", Q_ARG(TcpPortDiscoverer *, discoverer)); QMetaObject::invokeMethod(discoverer, "start"); return discoverer; } @@ -175,7 +163,7 @@ TcpPortDiscoverer *TcpPortScope::disco() QList TcpPortScope::allServers() const { QList ret; - for (auto &s: d->servers) { + for (auto &s : d->servers) { auto sl = s.lock(); if (sl) { ret.append(sl); @@ -184,15 +172,12 @@ QList TcpPortScope::allServers() const return ret; } -void TcpPortScope::destroyServer(TcpPortServer *server) -{ - delete server; -} +void TcpPortScope::destroyServer(TcpPortServer *server) { delete server; } TcpPortServer::Ptr TcpPortScope::bind(const QHostAddress &addr, quint16 port) { if (port) { - auto srv = d->servers.value(qMakePair(addr,port)).toStrongRef(); + auto srv = d->servers.value(qMakePair(addr, port)).toStrongRef(); if (srv) { return srv; } @@ -204,10 +189,10 @@ TcpPortServer::Ptr TcpPortScope::bind(const QHostAddress &addr, quint16 port) } auto server = makeServer(socket); - TcpPortServer::Ptr shared(server, [](TcpPortServer *s){ - auto scope = qobject_cast(s->parent()); + TcpPortServer::Ptr shared(server, [](TcpPortServer *s) { + auto scope = qobject_cast(s->parent()); if (scope) { - scope->d->servers.remove(qMakePair(s->serverAddress(),s->serverPort())); + scope->d->servers.remove(qMakePair(s->serverAddress(), s->serverPort())); scope->destroyServer(s); } else { delete s; @@ -221,19 +206,13 @@ TcpPortServer::Ptr TcpPortScope::bind(const QHostAddress &addr, quint16 port) // -------------------------------------------------------------------------- // TcpPortScope // -------------------------------------------------------------------------- -TcpPortReserver::TcpPortReserver(QObject *parent) : QObject(parent) -{ - -} - -TcpPortReserver::~TcpPortReserver() -{ +TcpPortReserver::TcpPortReserver(QObject *parent) : QObject(parent) {} -} +TcpPortReserver::~TcpPortReserver() {} TcpPortScope *TcpPortReserver::scope(const QString &id) { - return findChild(id, Qt::FindDirectChildrenOnly); + return findChild(id, Qt::FindDirectChildrenOnly); } void TcpPortReserver::registerScope(const QString &id, TcpPortScope *scope) diff --git a/src/irisnet/noncore/tcpportreserver.h b/src/irisnet/noncore/tcpportreserver.h index a4068bc4..12151b74 100644 --- a/src/irisnet/noncore/tcpportreserver.h +++ b/src/irisnet/noncore/tcpportreserver.h @@ -26,22 +26,15 @@ #include namespace XMPP { -class TcpPortServer : public QObject -{ +class TcpPortServer : public QObject { Q_OBJECT public: using Ptr = QSharedPointer; - enum PortType { - NoType = 0x0, - Direct = 0x1, - NatAssited = 0x2, - Tunneled = 0x4 - }; + enum PortType { NoType = 0x0, Direct = 0x1, NatAssited = 0x2, Tunneled = 0x4 }; Q_DECLARE_FLAGS(PortTypes, PortType) - struct Port - { + struct Port { PortType portType = NoType; QString publishHost; quint16 publishPort = 0; @@ -52,14 +45,14 @@ class TcpPortServer : public QObject inline void setPortInfo(const Port &port) { this->port = port; } inline QHostAddress serverAddress() const { return serverSocket->serverAddress(); } inline quint16 serverPort() const { return serverSocket->serverPort(); } - inline const QString &publishHost() const { return port.publishHost; } + inline const QString & publishHost() const { return port.publishHost; } inline quint16 publishPort() const { return port.publishPort; } inline PortType portType() const { return port.portType; } inline const QVariant &meta() const { return port.meta; } protected: QTcpServer *serverSocket = nullptr; - Port port; + Port port; }; class TcpPortScope; @@ -68,16 +61,14 @@ class TcpPortScope; * * Discovers / starts listening on a set of unique tcp ports. */ -class TcpPortDiscoverer : public QObject -{ +class TcpPortDiscoverer : public QObject { Q_OBJECT public: - TcpPortDiscoverer(TcpPortScope *scope); bool setExternalHost(const QString &extHost, quint16 extPort, const QHostAddress &localIp, quint16 localPort); TcpPortServer::PortTypes inProgressPortTypes() const; - bool isDepleted() const; + bool isDepleted() const; /** * @brief setTypeMask sets expected port types mask and frees unnecessary resources @@ -96,9 +87,11 @@ public slots: void stop(); signals: void portAvailable(); + private: - TcpPortServer::PortTypes typeMask = TcpPortServer::PortTypes(TcpPortServer::Direct | TcpPortServer::NatAssited | TcpPortServer::Tunneled); - TcpPortScope *scope = nullptr; + TcpPortServer::PortTypes typeMask + = TcpPortServer::PortTypes(TcpPortServer::Direct | TcpPortServer::NatAssited | TcpPortServer::Tunneled); + TcpPortScope * scope = nullptr; QList servers; }; @@ -109,17 +102,17 @@ class TcpPortReserver; * Handles scopes of ports. For example just S5B dedicated ports. * There only on scope instance per scope id */ -class TcpPortScope: public QObject -{ +class TcpPortScope : public QObject { Q_OBJECT public: TcpPortScope(); ~TcpPortScope(); - TcpPortDiscoverer* disco(); + TcpPortDiscoverer * disco(); QList allServers() const; + protected: - virtual TcpPortServer* makeServer(QTcpServer *socket) = 0; - virtual void destroyServer(TcpPortServer *server); + virtual TcpPortServer *makeServer(QTcpServer *socket) = 0; + virtual void destroyServer(TcpPortServer *server); private: friend class TcpPortDiscoverer; @@ -134,8 +127,7 @@ class TcpPortScope: public QObject * @brief The TcpPortReserver class * This class should have the only instance per application */ -class TcpPortReserver : public QObject -{ +class TcpPortReserver : public QObject { Q_OBJECT public: explicit TcpPortReserver(QObject *parent = nullptr); @@ -149,7 +141,7 @@ class TcpPortReserver : public QObject */ TcpPortScope *scope(const QString &id); - void registerScope(const QString &id, TcpPortScope *scope); + void registerScope(const QString &id, TcpPortScope *scope); TcpPortScope *unregisterScope(const QString &id); signals: void newDiscoverer(TcpPortDiscoverer *discoverer); diff --git a/src/irisnet/noncore/turnclient.cpp b/src/irisnet/noncore/turnclient.cpp index fd1ea2e9..87515903 100644 --- a/src/irisnet/noncore/turnclient.cpp +++ b/src/irisnet/noncore/turnclient.cpp @@ -34,50 +34,30 @@ namespace XMPP { //---------------------------------------------------------------------------- // TurnClient::Proxy //---------------------------------------------------------------------------- -TurnClient::Proxy::Proxy() -{ - t = None; -} +TurnClient::Proxy::Proxy() { t = None; } -TurnClient::Proxy::~Proxy() -{ -} +TurnClient::Proxy::~Proxy() {} -int TurnClient::Proxy::type() const -{ - return t; -} +int TurnClient::Proxy::type() const { return t; } -QString TurnClient::Proxy::host() const -{ - return v_host; -} +QString TurnClient::Proxy::host() const { return v_host; } -quint16 TurnClient::Proxy::port() const -{ - return v_port; -} +quint16 TurnClient::Proxy::port() const { return v_port; } -QString TurnClient::Proxy::user() const -{ - return v_user; -} +QString TurnClient::Proxy::user() const { return v_user; } -QString TurnClient::Proxy::pass() const -{ - return v_pass; -} +QString TurnClient::Proxy::pass() const { return v_pass; } void TurnClient::Proxy::setHttpConnect(const QString &host, quint16 port) { - t = HttpConnect; + t = HttpConnect; v_host = host; v_port = port; } void TurnClient::Proxy::setSocks(const QString &host, quint16 port) { - t = Socks; + t = Socks; v_host = host; v_port = port; } @@ -91,119 +71,84 @@ void TurnClient::Proxy::setUserPass(const QString &user, const QString &pass) //---------------------------------------------------------------------------- // TurnClient //---------------------------------------------------------------------------- -class TurnClient::Private : public QObject -{ +class TurnClient::Private : public QObject { Q_OBJECT public: - TurnClient *q; - Proxy proxy; - QString clientSoftware; - TurnClient::Mode mode; - QHostAddress serverAddr; - int serverPort; - ObjectSession sess; - ByteStream *bs; - QCA::TLS *tls; - bool tlsHandshaken; - QByteArray inStream; - bool udp; + TurnClient * q; + Proxy proxy; + QString clientSoftware; + TurnClient::Mode mode; + QHostAddress serverAddr; + int serverPort; + ObjectSession sess; + ByteStream * bs; + QCA::TLS * tls; + bool tlsHandshaken; + QByteArray inStream; + bool udp; StunTransactionPool *pool; - StunAllocate *allocate; - bool allocateStarted; - QString user; - QCA::SecureArray pass; - QString realm; - int retryCount; - QString errorString; - int debugLevel; - - class WriteItem - { + StunAllocate * allocate; + bool allocateStarted; + QString user; + QCA::SecureArray pass; + QString realm; + int retryCount; + QString errorString; + int debugLevel; + + class WriteItem { public: - enum Type - { - Data, - Other - }; + enum Type { Data, Other }; - Type type; - int size; + Type type; + int size; QHostAddress addr; - int port; + int port; - WriteItem(int _size) : - type(Other), - size(_size), - port(-1) - { - } + WriteItem(int _size) : type(Other), size(_size), port(-1) {} - WriteItem(int _size, const QHostAddress &_addr, int _port) : - type(Data), - size(_size), - addr(_addr), - port(_port) + WriteItem(int _size, const QHostAddress &_addr, int _port) : type(Data), size(_size), addr(_addr), port(_port) { } }; QList writeItems; - int writtenBytes; - bool stopping; + int writtenBytes; + bool stopping; - class Packet - { + class Packet { public: QHostAddress addr; - int port; - QByteArray data; + int port; + QByteArray data; // for outbound bool requireChannel; - Packet() : - port(-1), - requireChannel(false) - { - } + Packet() : port(-1), requireChannel(false) {} }; - QList in; - QList outPending; - int outPendingWrite; - QList desiredPerms; + QList in; + QList outPending; + int outPendingWrite; + QList desiredPerms; QList pendingChannels, desiredChannels; - class Written - { + class Written { public: QHostAddress addr; - int port; - int count; + int port; + int count; }; Private(TurnClient *_q) : - QObject(_q), - q(_q), - sess(this), - bs(nullptr), - tls(0), - udp(false), - pool(nullptr), - allocate(nullptr), - retryCount(0), - debugLevel(TurnClient::DL_None), - writtenBytes(0), - stopping(false), - outPendingWrite(0) + QObject(_q), q(_q), sess(this), bs(nullptr), tls(0), udp(false), pool(nullptr), allocate(nullptr), + retryCount(0), debugLevel(TurnClient::DL_None), writtenBytes(0), stopping(false), outPendingWrite(0) { } - ~Private() - { - cleanup(); - } + ~Private() { cleanup(); } void cleanup() { @@ -211,7 +156,7 @@ class TurnClient::Private : public QObject allocate = nullptr; // in udp mode, we don't own the pool - if(!udp) + if (!udp) delete pool; pool = nullptr; @@ -229,7 +174,7 @@ class TurnClient::Private : public QObject retryCount = 0; writeItems.clear(); writtenBytes = 0; - stopping = false; + stopping = false; outPending.clear(); outPendingWrite = 0; desiredPerms.clear(); @@ -239,36 +184,30 @@ class TurnClient::Private : public QObject void do_connect() { - if(udp) - { + if (udp) { after_connected(); return; } - if(proxy.type() == Proxy::HttpConnect) - { + if (proxy.type() == Proxy::HttpConnect) { HttpConnect *s = new HttpConnect(this); - bs = s; + bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!proxy.user().isEmpty()) + if (!proxy.user().isEmpty()) s->setAuth(proxy.user(), proxy.pass()); s->connectToHost(proxy.host(), proxy.port(), serverAddr.toString(), serverPort); - } - else if(proxy.type() == Proxy::Socks) - { + } else if (proxy.type() == Proxy::Socks) { SocksClient *s = new SocksClient(this); - bs = s; + bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!proxy.user().isEmpty()) + if (!proxy.user().isEmpty()) s->setAuth(proxy.user(), proxy.pass()); s->connectToHost(proxy.host(), proxy.port(), serverAddr.toString(), serverPort); - } - else - { + } else { BSocket *s = new BSocket(this); - bs = s; + bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); s->connectToHost(serverAddr.toString(), serverPort); @@ -284,23 +223,20 @@ class TurnClient::Private : public QObject { stopping = true; - if(allocate && allocateStarted) - { - if(debugLevel >= TurnClient::DL_Info) + if (allocate && allocateStarted) { + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("Deallocating..."); allocate->stop(); - } - else - { + } else { delete allocate; allocate = nullptr; // in udp mode, we don't own the pool - if(!udp) + if (!udp) delete pool; pool = nullptr; - if(udp) + if (udp) sess.defer(q, "closed"); else do_transport_close(); @@ -309,12 +245,9 @@ class TurnClient::Private : public QObject void do_transport_close() { - if(tls && tlsHandshaken) - { + if (tls && tlsHandshaken) { tls->close(); - } - else - { + } else { delete tls; tls = nullptr; @@ -325,12 +258,11 @@ class TurnClient::Private : public QObject void do_sock_close() { bool waitForSignal = false; - if(bs->bytesToWrite() > 0) + if (bs->bytesToWrite() > 0) waitForSignal = true; bs->close(); - if(!waitForSignal) - { + if (!waitForSignal) { cleanup(); sess.defer(q, "closed"); } @@ -339,20 +271,19 @@ class TurnClient::Private : public QObject void after_connected() { // when retrying, pool will be non-null because we reuse it - if(!udp && !pool) - { + if (!udp && !pool) { pool = new StunTransactionPool(StunTransaction::Tcp, this); pool->setDebugLevel((StunTransactionPool::DebugLevel)debugLevel); - connect(pool, SIGNAL(outgoingMessage(QByteArray,QHostAddress,int)), SLOT(pool_outgoingMessage(QByteArray,QHostAddress,int))); + connect(pool, SIGNAL(outgoingMessage(QByteArray, QHostAddress, int)), + SLOT(pool_outgoingMessage(QByteArray, QHostAddress, int))); connect(pool, SIGNAL(needAuthParams()), SLOT(pool_needAuthParams())); connect(pool, SIGNAL(debugLine(QString)), SLOT(pool_debugLine(QString))); pool->setLongTermAuthEnabled(true); - if(!user.isEmpty()) - { + if (!user.isEmpty()) { pool->setUsername(user); pool->setPassword(pass); - if(!realm.isEmpty()) + if (!realm.isEmpty()) pool->setRealm(realm); } } @@ -368,10 +299,10 @@ class TurnClient::Private : public QObject allocate->setClientSoftwareNameAndVersion(clientSoftware); allocateStarted = false; - if(debugLevel >= TurnClient::DL_Info) + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("Allocating..."); // only use addr association in udp mode - if(udp) + if (udp) allocate->start(serverAddr, serverPort); else allocate->start(); @@ -382,17 +313,15 @@ class TurnClient::Private : public QObject inStream += in; ObjectSessionWatcher watch(&sess); - while(1) - { + while (1) { QByteArray packet; // try to extract ChannelData or a STUN message from // the stream packet = StunAllocate::readChannelData((const quint8 *)inStream.data(), inStream.size()); - if(packet.isNull()) - { + if (packet.isNull()) { packet = StunMessage::readStun((const quint8 *)inStream.data(), inStream.size()); - if(packet.isNull()) + if (packet.isNull()) break; } @@ -401,7 +330,7 @@ class TurnClient::Private : public QObject // processDatagram may cause the session to be reset // or the object to be deleted processDatagram(packet); - if(!watch.isValid()) + if (!watch.isValid()) break; } } @@ -409,49 +338,40 @@ class TurnClient::Private : public QObject void processDatagram(const QByteArray &buf) { bool notStun; - if(!pool->writeIncomingMessage(buf, ¬Stun)) - { - QByteArray data; + if (!pool->writeIncomingMessage(buf, ¬Stun)) { + QByteArray data; QHostAddress fromAddr; - int fromPort; + int fromPort; data = processNonPoolPacket(buf, notStun, &fromAddr, &fromPort); - if(!data.isNull()) + if (!data.isNull()) processDataPacket(data, fromAddr, fromPort); } } QByteArray processNonPoolPacket(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port) { - if(notStun) - { + if (notStun) { // not stun? maybe it is a data packet QByteArray data = allocate->decode(buf, addr, port); - if(!data.isNull()) - { - if(debugLevel >= TurnClient::DL_Packet) + if (!data.isNull()) { + if (debugLevel >= TurnClient::DL_Packet) emit q->debugLine("Received ChannelData-based data packet"); return data; } - } - else - { + } else { // packet might be stun not owned by pool. // let's see StunMessage message = StunMessage::fromBinary(buf); - if(!message.isNull()) - { + if (!message.isNull()) { QByteArray data = allocate->decode(message, addr, port); - if(!data.isNull()) - { - if(debugLevel >= TurnClient::DL_Packet) + if (!data.isNull()) { + if (debugLevel >= TurnClient::DL_Packet) emit q->debugLine("Received STUN-based data packet"); return data; - } - else - { - if(debugLevel >= TurnClient::DL_Packet) + } else { + if (debugLevel >= TurnClient::DL_Packet) emit q->debugLine("Warning: server responded with an unexpected STUN packet, skipping."); } @@ -459,8 +379,9 @@ class TurnClient::Private : public QObject } } - if(debugLevel >= TurnClient::DL_Packet) - emit q->debugLine("Warning: server responded with what doesn't seem to be a STUN or data packet, skipping."); + if (debugLevel >= TurnClient::DL_Packet) + emit q->debugLine( + "Warning: server responded with what doesn't seem to be a STUN or data packet, skipping."); return QByteArray(); } @@ -480,32 +401,26 @@ class TurnClient::Private : public QObject Q_ASSERT(allocateStarted); StunAllocate::Channel c(addr, port); - bool writeImmediately = false; - bool requireChannel = pendingChannels.contains(c) || desiredChannels.contains(c); + bool writeImmediately = false; + bool requireChannel = pendingChannels.contains(c) || desiredChannels.contains(c); QList actualPerms = allocate->permissions(); - if(actualPerms.contains(addr)) - { - if(requireChannel) - { + if (actualPerms.contains(addr)) { + if (requireChannel) { QList actualChannels = allocate->channels(); - if(actualChannels.contains(c)) + if (actualChannels.contains(c)) writeImmediately = true; - } - else + } else writeImmediately = true; } - if(writeImmediately) - { + if (writeImmediately) { write(buf, addr, port); - } - else - { + } else { Packet p; - p.addr = addr; - p.port = port; - p.data = buf; + p.addr = addr; + p.port = port; + p.data = buf; p.requireChannel = requireChannel; outPending += p; @@ -515,16 +430,13 @@ class TurnClient::Private : public QObject void tryWriteQueued() { - QList actualPerms = allocate->permissions(); + QList actualPerms = allocate->permissions(); QList actualChannels = allocate->channels(); - for(int n = 0; n < outPending.count(); ++n) - { + for (int n = 0; n < outPending.count(); ++n) { const Packet &p = outPending[n]; - if(actualPerms.contains(p.addr)) - { + if (actualPerms.contains(p.addr)) { StunAllocate::Channel c(p.addr, p.port); - if(!p.requireChannel || actualChannels.contains(c)) - { + if (!p.requireChannel || actualChannels.contains(c)) { Packet po = outPending[n]; outPending.removeAt(n); --n; // adjust position @@ -537,21 +449,18 @@ class TurnClient::Private : public QObject void tryChannelQueued() { - if(!pendingChannels.isEmpty()) - { - QList actualPerms = allocate->permissions(); + if (!pendingChannels.isEmpty()) { + QList actualPerms = allocate->permissions(); QList list; - for(int n = 0; n < pendingChannels.count(); ++n) - { - if(actualPerms.contains(pendingChannels[n].address)) - { + for (int n = 0; n < pendingChannels.count(); ++n) { + if (actualPerms.contains(pendingChannels[n].address)) { list += pendingChannels[n]; pendingChannels.removeAt(n); --n; // adjust position } } - if(!list.isEmpty()) + if (!list.isEmpty()) ensureChannels(list); } } @@ -560,27 +469,21 @@ class TurnClient::Private : public QObject { QByteArray packet = allocate->encode(buf, addr, port); - if(debugLevel >= TurnClient::DL_Packet) - { + if (debugLevel >= TurnClient::DL_Packet) { StunMessage msg = StunMessage::fromBinary(packet); - if(!msg.isNull()) - { + if (!msg.isNull()) { emit q->debugLine("STUN SEND"); emit q->debugLine(StunTypes::print_packet_str(msg)); - } - else + } else emit q->debugLine("Sending ChannelData-based data packet"); } writeItems += WriteItem(packet.size(), addr, port); ++outPendingWrite; - if(udp) - { + if (udp) { emit q->outgoingDatagram(packet); - } - else - { - if(tls) + } else { + if (tls) tls->write(packet); else bs->write(packet); @@ -589,9 +492,8 @@ class TurnClient::Private : public QObject void ensurePermission(const QHostAddress &addr) { - if(!desiredPerms.contains(addr)) - { - if(debugLevel >= TurnClient::DL_Info) + if (!desiredPerms.contains(addr)) { + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine(QString("Setting permission for peer address %1").arg(addr.toString())); desiredPerms += addr; @@ -603,19 +505,18 @@ class TurnClient::Private : public QObject void ensureChannels(const QList &channels) { bool changed = false; - foreach(const StunAllocate::Channel &c, channels) - { - if(!desiredChannels.contains(c)) - { - if(debugLevel >= TurnClient::DL_Info) - emit q->debugLine(QString("Setting channel for peer address/port %1;%2").arg(c.address.toString()).arg(c.port)); + foreach (const StunAllocate::Channel &c, channels) { + if (!desiredChannels.contains(c)) { + if (debugLevel >= TurnClient::DL_Info) + emit q->debugLine( + QString("Setting channel for peer address/port %1;%2").arg(c.address.toString()).arg(c.port)); desiredChannels += c; changed = true; } } - if(changed) + if (changed) allocate->setChannels(desiredChannels); } @@ -624,8 +525,7 @@ class TurnClient::Private : public QObject ensurePermission(addr); StunAllocate::Channel c(addr, port); - if(!pendingChannels.contains(c) && !desiredChannels.contains(c)) - { + if (!pendingChannels.contains(c) && !desiredChannels.contains(c)) { pendingChannels += c; tryChannelQueued(); @@ -636,33 +536,26 @@ class TurnClient::Private : public QObject { QList writtenDests; - while(count > 0) - { + while (count > 0) { Q_ASSERT(!writeItems.isEmpty()); WriteItem wi = writeItems.takeFirst(); --count; - if(wi.type == WriteItem::Data) - { + if (wi.type == WriteItem::Data) { int at = -1; - for(int n = 0; n < writtenDests.count(); ++n) - { - if(writtenDests[n].addr == wi.addr && writtenDests[n].port == wi.port) - { + for (int n = 0; n < writtenDests.count(); ++n) { + if (writtenDests[n].addr == wi.addr && writtenDests[n].port == wi.port) { at = n; break; } } - if(at != -1) - { + if (at != -1) { ++writtenDests[at].count; - } - else - { + } else { Written wr; - wr.addr = wi.addr; - wr.port = wi.port; + wr.addr = wi.addr; + wr.port = wi.port; wr.count = 1; writtenDests += wr; } @@ -675,10 +568,9 @@ class TurnClient::Private : public QObject void emitPacketsWritten(const QList &writtenDests) { ObjectSessionWatcher watch(&sess); - foreach(const Written &wr, writtenDests) - { + foreach (const Written &wr, writtenDests) { emit q->packetsWritten(wr.count, wr.addr, wr.port); - if(!watch.isValid()) + if (!watch.isValid()) return; } } @@ -687,22 +579,21 @@ class TurnClient::Private : public QObject bool handleRetry() { ++retryCount; - if(retryCount < 3 && !stopping) - { - if(debugLevel >= TurnClient::DL_Info) + if (retryCount < 3 && !stopping) { + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("retrying..."); // start completely over, but retain the same pool // so the user isn't asked to auth again - int tmp_retryCount = retryCount; - StunTransactionPool *tmp_pool = pool; - pool = nullptr; + int tmp_retryCount = retryCount; + StunTransactionPool *tmp_pool = pool; + pool = nullptr; cleanup(); retryCount = tmp_retryCount; - pool = tmp_pool; + pool = tmp_pool; do_connect(); return true; @@ -715,23 +606,21 @@ private slots: void bs_connected() { ObjectSessionWatcher watch(&sess); - emit q->connected(); - if(!watch.isValid()) + emit q->connected(); + if (!watch.isValid()) return; - if(mode == TurnClient::TlsMode) - { + if (mode == TurnClient::TlsMode) { tls = new QCA::TLS(this); connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken())); connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead())); connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing())); connect(tls, SIGNAL(error()), SLOT(tls_error())); tlsHandshaken = false; - if(debugLevel >= TurnClient::DL_Info) + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("TLS handshaking..."); tls->startClient(); - } - else + } else after_connected(); } @@ -752,7 +641,7 @@ private slots: { QByteArray buf = bs->readAll(); - if(tls) + if (tls) tls->writeIncoming(buf); else processStream(buf); @@ -760,11 +649,10 @@ private slots: void bs_bytesWritten(qint64 written) { - if(tls) - { + if (tls) { // convertBytesWritten() is unsafe to call unless // the TLS handshake is completed - if(!tlsHandshaken) + if (!tlsHandshaken) return; written = tls->convertBytesWritten(written); @@ -774,36 +662,29 @@ private slots: QList writtenDests; - while(writtenBytes > 0) - { + while (writtenBytes > 0) { Q_ASSERT(!writeItems.isEmpty()); - if(writtenBytes < writeItems.first().size) + if (writtenBytes < writeItems.first().size) break; WriteItem wi = writeItems.takeFirst(); writtenBytes -= wi.size; - if(wi.type == WriteItem::Data) - { + if (wi.type == WriteItem::Data) { int at = -1; - for(int n = 0; n < writtenDests.count(); ++n) - { - if(writtenDests[n].addr == wi.addr && writtenDests[n].port == wi.port) - { + for (int n = 0; n < writtenDests.count(); ++n) { + if (writtenDests[n].addr == wi.addr && writtenDests[n].port == wi.port) { at = n; break; } } - if(at != -1) - { + if (at != -1) { ++writtenDests[at].count; - } - else - { + } else { Written wr; - wr.addr = wi.addr; - wr.port = wi.port; + wr.addr = wi.addr; + wr.port = wi.port; wr.count = 1; writtenDests += wr; } @@ -816,41 +697,36 @@ private slots: void bs_error(int e) { TurnClient::Error te; - if(qobject_cast(bs)) - { - if(e == HttpConnect::ErrConnectionRefused) + if (qobject_cast(bs)) { + if (e == HttpConnect::ErrConnectionRefused) te = TurnClient::ErrorConnect; - else if(e == HttpConnect::ErrHostNotFound) + else if (e == HttpConnect::ErrHostNotFound) te = TurnClient::ErrorHostNotFound; - else if(e == HttpConnect::ErrProxyConnect) + else if (e == HttpConnect::ErrProxyConnect) te = TurnClient::ErrorProxyConnect; - else if(e == HttpConnect::ErrProxyNeg) + else if (e == HttpConnect::ErrProxyNeg) te = TurnClient::ErrorProxyNeg; - else if(e == HttpConnect::ErrProxyAuth) + else if (e == HttpConnect::ErrProxyAuth) te = TurnClient::ErrorProxyAuth; else te = TurnClient::ErrorStream; - } - else if(qobject_cast(bs)) - { - if(e == SocksClient::ErrConnectionRefused) + } else if (qobject_cast(bs)) { + if (e == SocksClient::ErrConnectionRefused) te = TurnClient::ErrorConnect; - else if(e == SocksClient::ErrHostNotFound) + else if (e == SocksClient::ErrHostNotFound) te = TurnClient::ErrorHostNotFound; - else if(e == SocksClient::ErrProxyConnect) + else if (e == SocksClient::ErrProxyConnect) te = TurnClient::ErrorProxyConnect; - else if(e == SocksClient::ErrProxyNeg) + else if (e == SocksClient::ErrProxyNeg) te = TurnClient::ErrorProxyNeg; - else if(e == SocksClient::ErrProxyAuth) + else if (e == SocksClient::ErrProxyAuth) te = TurnClient::ErrorProxyAuth; else te = TurnClient::ErrorStream; - } - else - { - if(e == BSocket::ErrConnectionRefused) + } else { + if (e == BSocket::ErrConnectionRefused) te = TurnClient::ErrorConnect; - else if(e == BSocket::ErrHostNotFound) + else if (e == BSocket::ErrHostNotFound) te = TurnClient::ErrorHostNotFound; else te = TurnClient::ErrorStream; @@ -866,23 +742,17 @@ private slots: tlsHandshaken = true; ObjectSessionWatcher watch(&sess); - emit q->tlsHandshaken(); - if(!watch.isValid()) + emit q->tlsHandshaken(); + if (!watch.isValid()) return; tls->continueAfterStep(); after_connected(); } - void tls_readyRead() - { - processStream(tls->read()); - } + void tls_readyRead() { processStream(tls->read()); } - void tls_readyReadOutgoing() - { - bs->write(tls->readOutgoing()); - } + void tls_readyReadOutgoing() { bs->write(tls->readOutgoing()); } void tls_closed() { @@ -907,26 +777,20 @@ private slots: writeItems += WriteItem(packet.size()); - if(tls) + if (tls) tls->write(packet); else bs->write(packet); } - void pool_needAuthParams() - { - emit q->needAuthParams(); - } + void pool_needAuthParams() { emit q->needAuthParams(); } - void pool_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void pool_debugLine(const QString &line) { emit q->debugLine(line); } void allocate_started() { allocateStarted = true; - if(debugLevel >= TurnClient::DL_Info) + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("Allocate started"); emit q->activated(); @@ -938,11 +802,11 @@ private slots: allocate = nullptr; // in udp mode, we don't own the pool - if(!udp) + if (!udp) delete pool; pool = nullptr; - if(udp) + if (udp) emit q->closed(); else do_transport_close(); @@ -953,22 +817,20 @@ private slots: QString str = allocate->errorString(); TurnClient::Error te; - if(e == StunAllocate::ErrorAuth) + if (e == StunAllocate::ErrorAuth) te = TurnClient::ErrorAuth; - else if(e == StunAllocate::ErrorRejected) + else if (e == StunAllocate::ErrorRejected) te = TurnClient::ErrorRejected; - else if(e == StunAllocate::ErrorProtocol) + else if (e == StunAllocate::ErrorProtocol) te = TurnClient::ErrorProtocol; - else if(e == StunAllocate::ErrorCapacity) + else if (e == StunAllocate::ErrorCapacity) te = TurnClient::ErrorCapacity; - else if(e == StunAllocate::ErrorMismatch) - { - if(!udp && handleRetry()) + else if (e == StunAllocate::ErrorMismatch) { + if (!udp && handleRetry()) return; te = TurnClient::ErrorMismatch; - } - else + } else te = TurnClient::ErrorGeneric; cleanup(); @@ -978,7 +840,7 @@ private slots: void allocate_permissionsChanged() { - if(debugLevel >= TurnClient::DL_Info) + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("PermissionsChanged"); tryChannelQueued(); @@ -987,45 +849,29 @@ private slots: void allocate_channelsChanged() { - if(debugLevel >= TurnClient::DL_Info) + if (debugLevel >= TurnClient::DL_Info) emit q->debugLine("ChannelsChanged"); tryWriteQueued(); } - void allocate_debugLine(const QString &line) - { - emit q->debugLine(line); - } + void allocate_debugLine(const QString &line) { emit q->debugLine(line); } }; -TurnClient::TurnClient(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} +TurnClient::TurnClient(QObject *parent) : QObject(parent) { d = new Private(this); } -TurnClient::~TurnClient() -{ - delete d; -} +TurnClient::~TurnClient() { delete d; } -void TurnClient::setProxy(const Proxy &proxy) -{ - d->proxy = proxy; -} +void TurnClient::setProxy(const Proxy &proxy) { d->proxy = proxy; } -void TurnClient::setClientSoftwareNameAndVersion(const QString &str) -{ - d->clientSoftware = str; -} +void TurnClient::setClientSoftwareNameAndVersion(const QString &str) { d->clientSoftware = str; } void TurnClient::connectToHost(StunTransactionPool *pool, const QHostAddress &addr, int port) { d->serverAddr = addr; d->serverPort = port; - d->udp = true; - d->pool = pool; + d->udp = true; + d->pool = pool; d->in.clear(); d->do_connect(); } @@ -1034,8 +880,8 @@ void TurnClient::connectToHost(const QHostAddress &addr, int port, Mode mode) { d->serverAddr = addr; d->serverPort = port; - d->udp = false; - d->mode = mode; + d->udp = false; + d->mode = mode; d->in.clear(); d->do_connect(); } @@ -1045,14 +891,11 @@ QByteArray TurnClient::processIncomingDatagram(const QByteArray &buf, bool notSt return d->processNonPoolPacket(buf, notStun, addr, port); } -void TurnClient::outgoingDatagramsWritten(int count) -{ - d->udp_datagramsWritten(count); -} +void TurnClient::outgoingDatagramsWritten(int count) { d->udp_datagramsWritten(count); } QString TurnClient::realm() const { - if(d->pool) + if (d->pool) return d->pool->realm(); else return d->realm; @@ -1061,21 +904,21 @@ QString TurnClient::realm() const void TurnClient::setUsername(const QString &username) { d->user = username; - if(d->pool) + if (d->pool) d->pool->setUsername(d->user); } void TurnClient::setPassword(const QCA::SecureArray &password) { d->pass = password; - if(d->pool) + if (d->pool) d->pool->setPassword(d->pass); } void TurnClient::setRealm(const QString &realm) { d->realm = realm; - if(d->pool) + if (d->pool) d->pool->setRealm(d->realm); } @@ -1085,58 +928,35 @@ void TurnClient::continueAfterParams() d->pool->continueAfterParams(); } -void TurnClient::close() -{ - d->do_close(); -} +void TurnClient::close() { d->do_close(); } -StunAllocate *TurnClient::stunAllocate() -{ - return d->allocate; -} +StunAllocate *TurnClient::stunAllocate() { return d->allocate; } -void TurnClient::addChannelPeer(const QHostAddress &addr, int port) -{ - d->addChannelPeer(addr, port); -} +void TurnClient::addChannelPeer(const QHostAddress &addr, int port) { d->addChannelPeer(addr, port); } -int TurnClient::packetsToRead() const -{ - return d->in.count(); -} +int TurnClient::packetsToRead() const { return d->in.count(); } -int TurnClient::packetsToWrite() const -{ - return d->outPending.count() + d->outPendingWrite; -} +int TurnClient::packetsToWrite() const { return d->outPending.count() + d->outPendingWrite; } QByteArray TurnClient::read(QHostAddress *addr, int *port) { - if(!d->in.isEmpty()) - { + if (!d->in.isEmpty()) { Private::Packet p = d->in.takeFirst(); - *addr = p.addr; - *port = p.port; + *addr = p.addr; + *port = p.port; return p.data; - } - else + } else return QByteArray(); } -void TurnClient::write(const QByteArray &buf, const QHostAddress &addr, int port) -{ - d->writeOrQueue(buf, addr, port); -} +void TurnClient::write(const QByteArray &buf, const QHostAddress &addr, int port) { d->writeOrQueue(buf, addr, port); } -QString TurnClient::errorString() const -{ - return d->errorString; -} +QString TurnClient::errorString() const { return d->errorString; } void TurnClient::setDebugLevel(DebugLevel level) { d->debugLevel = level; - if(d->pool) + if (d->pool) d->pool->setDebugLevel((StunTransactionPool::DebugLevel)level); } } // namespace XMPP diff --git a/src/irisnet/noncore/turnclient.h b/src/irisnet/noncore/turnclient.h index 74e7b6a7..69ccd7f8 100644 --- a/src/irisnet/noncore/turnclient.h +++ b/src/irisnet/noncore/turnclient.h @@ -25,20 +25,18 @@ #include namespace QCA { - class SecureArray; +class SecureArray; } namespace XMPP { class StunAllocate; class StunTransactionPool; -class TurnClient : public QObject -{ +class TurnClient : public QObject { Q_OBJECT public: - enum Error - { + enum Error { ErrorGeneric, ErrorHostNotFound, ErrorConnect, @@ -66,34 +64,19 @@ class TurnClient : public QObject ErrorMismatch }; - enum Mode - { - PlainMode, - TlsMode - }; + enum Mode { PlainMode, TlsMode }; - enum DebugLevel - { - DL_None, - DL_Info, - DL_Packet - }; + enum DebugLevel { DL_None, DL_Info, DL_Packet }; // adapted from XMPP::AdvancedConnector - class Proxy - { + class Proxy { public: - enum - { - None, - HttpConnect, - Socks - }; + enum { None, HttpConnect, Socks }; Proxy(); ~Proxy(); - int type() const; + int type() const; QString host() const; quint16 port() const; QString user() const; @@ -104,7 +87,7 @@ class TurnClient : public QObject void setUserPass(const QString &user, const QString &pass); private: - int t; + int t; QString v_host; quint16 v_port; QString v_user, v_pass; @@ -135,10 +118,10 @@ class TurnClient : public QObject void outgoingDatagramsWritten(int count); QString realm() const; - void setUsername(const QString &username); - void setPassword(const QCA::SecureArray &password); - void setRealm(const QString &realm); - void continueAfterParams(); + void setUsername(const QString &username); + void setPassword(const QCA::SecureArray &password); + void setRealm(const QString &realm); + void continueAfterParams(); void close(); @@ -165,7 +148,7 @@ class TurnClient : public QObject void tlsHandshaken(); void closed(); void needAuthParams(); - void retrying(); // mismatch error received, starting all over + void retrying(); // mismatch error received, starting all over void activated(); // ready for read/write // TCP mode only diff --git a/src/irisnet/noncore/udpportreserver.cpp b/src/irisnet/noncore/udpportreserver.cpp index 94ded097..96ba77cc 100644 --- a/src/irisnet/noncore/udpportreserver.cpp +++ b/src/irisnet/noncore/udpportreserver.cpp @@ -22,37 +22,30 @@ #include namespace XMPP { -class UdpPortReserver::Private : public QObject -{ +class UdpPortReserver::Private : public QObject { Q_OBJECT public: - class Item - { + class Item { public: - int port; // port to reserve + int port; // port to reserve bool lent; // list of sockets for this port, one socket per address. // note that we may have sockets bound for addresses // we no longer care about, if we are currently lending // them out - QList sockList; + QList sockList; // keep track of which addresses we lent out QList lentAddrs; - Item() : - port(-1), - lent(false) - { - } + Item() : port(-1), lent(false) {} bool haveAddress(const QHostAddress &addr) const { - foreach(const QUdpSocket *sock, sockList) - { - if(sock->localAddress() == addr) + foreach (const QUdpSocket *sock, sockList) { + if (sock->localAddress() == addr) return true; } @@ -60,36 +53,29 @@ class UdpPortReserver::Private : public QObject } }; - UdpPortReserver *q; + UdpPortReserver * q; QList addrs; - QList ports; // sorted - QList items; // in order sorted by port + QList ports; // sorted + QList items; // in order sorted by port - Private(UdpPortReserver *_q) : - QObject(_q), - q(_q) - { - } + Private(UdpPortReserver *_q) : QObject(_q), q(_q) {} ~Private() { bool lendingAny = false; - foreach(const Item &i, items) - { - if(i.lent) - { + foreach (const Item &i, items) { + if (i.lent) { lendingAny = true; break; } } Q_ASSERT(!lendingAny); - if(lendingAny) + if (lendingAny) abort(); - foreach(const Item &i, items) - { - foreach(QUdpSocket *sock, i.sockList) + foreach (const Item &i, items) { + foreach (QUdpSocket *sock, i.sockList) sock->deleteLater(); } } @@ -105,19 +91,16 @@ class UdpPortReserver::Private : public QObject void updatePorts(const QList &newPorts) { QList added; - foreach(int x, newPorts) - { + foreach (int x, newPorts) { bool found = false; - foreach(const Item &i, items) - { - if(i.port == x) - { + foreach (const Item &i, items) { + if (i.port == x) { found = true; break; } } - if(!found) + if (!found) added += x; } @@ -126,13 +109,10 @@ class UdpPortReserver::Private : public QObject // keep ports in sorted order std::sort(ports.begin(), ports.end()); - foreach(int x, added) - { + foreach (int x, added) { int insert_before = items.count(); - for(int n = 0; n < items.count(); ++n) - { - if(x < items[n].port) - { + for (int n = 0; n < items.count(); ++n) { + if (x < items[n].port) { insert_before = n; break; } @@ -150,14 +130,12 @@ class UdpPortReserver::Private : public QObject bool reservedAll() const { bool ok = true; - foreach(const Item &i, items) - { + foreach (const Item &i, items) { // skip ports we don't care about - if(!ports.contains(i.port)) + if (!ports.contains(i.port)) continue; - if(!isReserved(i)) - { + if (!isReserved(i)) { ok = false; break; } @@ -166,59 +144,50 @@ class UdpPortReserver::Private : public QObject return ok; } - QList borrowSockets(int portCount, QObject *parent) + QList borrowSockets(int portCount, QObject *parent) { Q_ASSERT(portCount > 0); - QList out; + QList out; - if(portCount > 1) - { + if (portCount > 1) { // first try to see if we can find something all in a // row, starting with best alignment to worst - for(int align = portCount; align >= 2; align /= 2) - { + for (int align = portCount; align >= 2; align /= 2) { int at = findConsecutive(portCount, align); - if(at != -1) - { - for(int n = 0; n < portCount; ++n) + if (at != -1) { + for (int n = 0; n < portCount; ++n) out += lendItem(&items[at + n], parent); break; } } - if(out.isEmpty()) - { + if (out.isEmpty()) { // otherwise, try splitting them up into // smaller consecutive chunks int chunks[2]; chunks[0] = portCount / 2 + (portCount % 2); chunks[1] = portCount / 2; - for(int n = 0; n < 2; ++n) + for (int n = 0; n < 2; ++n) out += borrowSockets(chunks[n], parent); } - } - else - { + } else { // take the next available port int at = findConsecutive(1, 1); - if(at != -1) + if (at != -1) out += lendItem(&items[at], parent); } return out; } - void returnSockets(const QList &sockList) + void returnSockets(const QList &sockList) { - foreach(QUdpSocket *sock, sockList) - { + foreach (QUdpSocket *sock, sockList) { int at = -1; - for(int n = 0; n < items.count(); ++n) - { - if(items[n].sockList.contains(sock)) - { + for (int n = 0; n < items.count(); ++n) { + if (items[n].sockList.contains(sock)) { at = n; break; } @@ -240,7 +209,7 @@ class UdpPortReserver::Private : public QObject connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead())); i.lentAddrs.removeAll(a); - if(i.lentAddrs.isEmpty()) + if (i.lentAddrs.isEmpty()) i.lent = false; } @@ -253,34 +222,30 @@ private slots: QUdpSocket *sock = static_cast(sender()); // eat all packets - while(sock->hasPendingDatagrams()) + while (sock->hasPendingDatagrams()) sock->readDatagram(nullptr, 0); } private: void tryBind() { - for(int n = 0; n < items.count(); ++n) - { + for (int n = 0; n < items.count(); ++n) { Item &i = items[n]; // skip ports we don't care about - if(!ports.contains(i.port)) + if (!ports.contains(i.port)) continue; QList neededAddrs; - foreach(const QHostAddress &a, addrs) - { - if(!i.haveAddress(a)) + foreach (const QHostAddress &a, addrs) { + if (!i.haveAddress(a)) neededAddrs += a; } - foreach(const QHostAddress &a, neededAddrs) - { + foreach (const QHostAddress &a, neededAddrs) { QUdpSocket *sock = new QUdpSocket(q); - if(!sock->bind(a, i.port)) - { + if (!sock->bind(a, i.port)) { delete sock; continue; } @@ -294,14 +259,12 @@ private slots: void tryCleanup() { - for(int n = 0; n < items.count(); ++n) - { + for (int n = 0; n < items.count(); ++n) { Item &i = items[n]; // don't care about this port anymore? - if(!i.lent && !ports.contains(i.port)) - { - foreach(QUdpSocket *sock, i.sockList) + if (!i.lent && !ports.contains(i.port)) { + foreach (QUdpSocket *sock, i.sockList) sock->deleteLater(); items.removeAt(n); @@ -310,14 +273,12 @@ private slots: } // any addresses we don't care about? - for(int k = 0; k < i.sockList.count(); ++k) - { + for (int k = 0; k < i.sockList.count(); ++k) { QUdpSocket *sock = i.sockList[k]; QHostAddress a = sock->localAddress(); - if(!addrs.contains(a) && !i.lentAddrs.contains(a)) - { + if (!addrs.contains(a) && !i.lentAddrs.contains(a)) { sock->deleteLater(); i.sockList.removeAt(k); --k; // adjust position @@ -330,12 +291,11 @@ private slots: bool isReserved(const Item &i) const { // must have desired addrs to consider a port reserved - if(addrs.isEmpty()) + if (addrs.isEmpty()) return false; - foreach(const QHostAddress &a, addrs) - { - if(!i.haveAddress(a)) + foreach (const QHostAddress &a, addrs) { + if (!i.haveAddress(a)) return false; } @@ -344,17 +304,16 @@ private slots: bool isConsecutive(int at, int count) const { - if(at + count > items.count()) + if (at + count > items.count()) return false; - for(int n = 0; n < count; ++n) - { + for (int n = 0; n < count; ++n) { const Item &i = items[at + n]; - if(i.lent || !isReserved(i)) + if (i.lent || !isReserved(i)) return false; - if(n > 0 && (i.port != items[at + n - 1].port + 1)) + if (n > 0 && (i.port != items[at + n - 1].port + 1)) return false; } @@ -363,22 +322,20 @@ private slots: int findConsecutive(int count, int align) const { - for(int n = 0; n < items.count(); n += align) - { - if(isConsecutive(n, count)) + for (int n = 0; n < items.count(); n += align) { + if (isConsecutive(n, count)) return n; } return -1; } - QList lendItem(Item *i, QObject *parent) + QList lendItem(Item *i, QObject *parent) { - QList out; + QList out; i->lent = true; - foreach(QUdpSocket *sock, i->sockList) - { + foreach (QUdpSocket *sock, i->sockList) { i->lentAddrs += sock->localAddress(); sock->disconnect(this); sock->setParent(parent); @@ -389,49 +346,30 @@ private slots: } }; -UdpPortReserver::UdpPortReserver(QObject *parent) : - QObject(parent) -{ - d = new Private(this); -} +UdpPortReserver::UdpPortReserver(QObject *parent) : QObject(parent) { d = new Private(this); } -UdpPortReserver::~UdpPortReserver() -{ - delete d; -} +UdpPortReserver::~UdpPortReserver() { delete d; } -void UdpPortReserver::setAddresses(const QList &addrs) -{ - d->updateAddresses(addrs); -} +void UdpPortReserver::setAddresses(const QList &addrs) { d->updateAddresses(addrs); } void UdpPortReserver::setPorts(int start, int len) { QList ports; - for(int n = 0; n < len; ++n) + for (int n = 0; n < len; ++n) ports += start + n; setPorts(ports); } -void UdpPortReserver::setPorts(const QList &ports) -{ - d->updatePorts(ports); -} +void UdpPortReserver::setPorts(const QList &ports) { d->updatePorts(ports); } -bool UdpPortReserver::reservedAll() const -{ - return d->reservedAll(); -} +bool UdpPortReserver::reservedAll() const { return d->reservedAll(); } -QList UdpPortReserver::borrowSockets(int portCount, QObject *parent) +QList UdpPortReserver::borrowSockets(int portCount, QObject *parent) { return d->borrowSockets(portCount, parent); } -void UdpPortReserver::returnSockets(const QList &sockList) -{ - d->returnSockets(sockList); -} +void UdpPortReserver::returnSockets(const QList &sockList) { d->returnSockets(sockList); } } // namespace XMPP #include "udpportreserver.moc" diff --git a/src/irisnet/noncore/udpportreserver.h b/src/irisnet/noncore/udpportreserver.h index 8604b38b..9043b9cd 100644 --- a/src/irisnet/noncore/udpportreserver.h +++ b/src/irisnet/noncore/udpportreserver.h @@ -31,8 +31,7 @@ namespace XMPP { // (interfaces) and ports to reserve. note that the port must be available // on all addresses in order for it to get reserved. // note: you must return all sockets back to this class before destructing -class UdpPortReserver : public QObject -{ +class UdpPortReserver : public QObject { Q_OBJECT public: @@ -57,9 +56,9 @@ class UdpPortReserver : public QObject // able to bind to a port for it to be considered reserved, this // function always returns a list with a size that is a multiple of // the number of addresses. - QList borrowSockets(int portCount, QObject *parent = nullptr); + QList borrowSockets(int portCount, QObject *parent = nullptr); - void returnSockets(const QList &sockList); + void returnSockets(const QList &sockList); private: class Private; diff --git a/src/xmpp/base/randomnumbergenerator.cpp b/src/xmpp/base/randomnumbergenerator.cpp index 672c0611..f4521451 100644 --- a/src/xmpp/base/randomnumbergenerator.cpp +++ b/src/xmpp/base/randomnumbergenerator.cpp @@ -21,13 +21,11 @@ #include namespace XMPP { -RandomNumberGenerator::~RandomNumberGenerator() -{ -} +RandomNumberGenerator::~RandomNumberGenerator() {} double RandomNumberGenerator::generateNumberBetween(double a, double b) const { assert(b > a); - return a + (generateNumber()/getMaximumGeneratedNumber())*(b-a); + return a + (generateNumber() / getMaximumGeneratedNumber()) * (b - a); } } // namespace XMPP diff --git a/src/xmpp/base/randomnumbergenerator.h b/src/xmpp/base/randomnumbergenerator.h index abadb9a9..458fc138 100644 --- a/src/xmpp/base/randomnumbergenerator.h +++ b/src/xmpp/base/randomnumbergenerator.h @@ -20,17 +20,16 @@ #define RANDOMNUMBERGENERATOR_H namespace XMPP { - class RandomNumberGenerator - { - public: - virtual ~RandomNumberGenerator(); +class RandomNumberGenerator { +public: + virtual ~RandomNumberGenerator(); - double generateNumberBetween(double a, double b) const; + double generateNumberBetween(double a, double b) const; - protected: - virtual double generateNumber() const = 0; - virtual double getMaximumGeneratedNumber() const = 0; - }; +protected: + virtual double generateNumber() const = 0; + virtual double getMaximumGeneratedNumber() const = 0; +}; } // namespace XMPP #endif // RANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/randrandomnumbergenerator.h b/src/xmpp/base/randrandomnumbergenerator.h index 985786cf..9d03cfd5 100644 --- a/src/xmpp/base/randrandomnumbergenerator.h +++ b/src/xmpp/base/randrandomnumbergenerator.h @@ -24,19 +24,14 @@ #include namespace XMPP { - class RandRandomNumberGenerator : public RandomNumberGenerator - { - public: - RandRandomNumberGenerator() {} +class RandRandomNumberGenerator : public RandomNumberGenerator { +public: + RandRandomNumberGenerator() {} - virtual double generateNumber() const { - return rand(); - } + virtual double generateNumber() const { return rand(); } - virtual double getMaximumGeneratedNumber() const { - return RAND_MAX; - } - }; + virtual double getMaximumGeneratedNumber() const { return RAND_MAX; } +}; } // namespace XMPP #endif // RANDRANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/timezone.cpp b/src/xmpp/base/timezone.cpp index 4e7e5d20..e31aef61 100644 --- a/src/xmpp/base/timezone.cpp +++ b/src/xmpp/base/timezone.cpp @@ -19,22 +19,22 @@ #include "timezone.h" #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) -# include -# include -# ifdef Q_OS_UNIX -# include -# endif -# ifdef Q_OS_WIN -# include -# endif +#include +#include +#ifdef Q_OS_UNIX +#include +#endif +#ifdef Q_OS_WIN +#include +#endif #else -# include +#include #endif #include -#if QT_VERSION < QT_VERSION_CHECK(5,2,0) -static bool inited = false; -static int timezone_offset_; +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) +static bool inited = false; +static int timezone_offset_; static QString timezone_str_; static void init() @@ -44,47 +44,48 @@ static void init() time(&x); char str[256]; char fmt[32]; - int size; + int size; strcpy(fmt, "%z"); size = strftime(str, 256, fmt, localtime(&x)); - if(size && strncmp(fmt, str, size)) { - timezone_offset_ = QByteArray::fromRawData(str + 1, 2).toInt() * 60 + QByteArray::fromRawData(str + 3, 2).toInt(); - if(str[0] == '-') + if (size && strncmp(fmt, str, size)) { + timezone_offset_ + = QByteArray::fromRawData(str + 1, 2).toInt() * 60 + QByteArray::fromRawData(str + 3, 2).toInt(); + if (str[0] == '-') timezone_offset_ = -timezone_offset_; } strcpy(fmt, "%Z"); strftime(str, 256, fmt, localtime(&x)); - if(strcmp(fmt, str)) + if (strcmp(fmt, str)) timezone_str_ = str; #elif defined(Q_OS_WIN) TIME_ZONE_INFORMATION i; memset(&i, 0, sizeof(i)); bool inDST = (GetTimeZoneInformation(&i) == TIME_ZONE_ID_DAYLIGHT); - int bias = i.Bias; - if(inDST) + int bias = i.Bias; + if (inDST) bias += i.DaylightBias; timezone_offset_ = -bias; - timezone_str_ = ""; - for(int n = 0; n < 32; ++n) { + timezone_str_ = ""; + for (int n = 0; n < 32; ++n) { int w = inDST ? i.DaylightName[n] : i.StandardName[n]; - if(w == 0) + if (w == 0) break; timezone_str_ += QChar(w); } #else qWarning("Failed to properly init timezone data. Use UTC offset instead"); - inited = true; + inited = true; timezone_offset_ = 0; - timezone_str_ = QLatin1String("N/A"); + timezone_str_ = QLatin1String("N/A"); #endif } #endif int TimeZone::offsetFromUtc() { -#if QT_VERSION < QT_VERSION_CHECK(5,2,0) +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) if (!inited) { init(); } @@ -96,7 +97,7 @@ int TimeZone::offsetFromUtc() QString TimeZone::abbreviation() { -#if QT_VERSION < QT_VERSION_CHECK(5,2,0) +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) return timezone_str_; #else return QTimeZone::systemTimeZone().abbreviation(QDateTime::currentDateTime()); diff --git a/src/xmpp/base/timezone.h b/src/xmpp/base/timezone.h index d49cdc10..2a091c5a 100644 --- a/src/xmpp/base/timezone.h +++ b/src/xmpp/base/timezone.h @@ -21,12 +21,11 @@ #include -class TimeZone -{ +class TimeZone { public: - static int offsetFromUtc(); // in minutes + static int offsetFromUtc(); // in minutes static QString abbreviation(); - static int tzdToInt(const QString &tzd); + static int tzdToInt(const QString &tzd); }; #endif // IRIS_TIMEZONE_H diff --git a/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h b/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h index 132ea8b8..cde964f2 100644 --- a/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h +++ b/src/xmpp/base/unittest/incrementingrandomnumbergenerator.h @@ -24,24 +24,25 @@ #include namespace XMPP { - class IncrementingRandomNumberGenerator : public RandomNumberGenerator +class IncrementingRandomNumberGenerator : public RandomNumberGenerator { +public: + IncrementingRandomNumberGenerator(int maximumNumber = 10) : + maximumNumber_(maximumNumber), currentNumber_(maximumNumber_) { - public: - IncrementingRandomNumberGenerator(int maximumNumber = 10) : maximumNumber_(maximumNumber), currentNumber_(maximumNumber_) {} - - virtual double generateNumber() const { - currentNumber_ = (currentNumber_ + 1) % (maximumNumber_ + 1); - return currentNumber_; - } - - virtual double getMaximumGeneratedNumber() const { - return maximumNumber_; - } - - private: - int maximumNumber_; - mutable int currentNumber_; - }; + } + + virtual double generateNumber() const + { + currentNumber_ = (currentNumber_ + 1) % (maximumNumber_ + 1); + return currentNumber_; + } + + virtual double getMaximumGeneratedNumber() const { return maximumNumber_; } + +private: + int maximumNumber_; + mutable int currentNumber_; +}; } // namespace XMPP #endif // INCREMENTINGRANDOMNUMBERGENERATOR_H diff --git a/src/xmpp/base/unittest/randomnumbergeneratortest.cpp b/src/xmpp/base/unittest/randomnumbergeneratortest.cpp index d2b01c59..cba6b0aa 100644 --- a/src/xmpp/base/unittest/randomnumbergeneratortest.cpp +++ b/src/xmpp/base/unittest/randomnumbergeneratortest.cpp @@ -16,47 +16,48 @@ * */ -#include "qttestutil/qttestutil.h" #include "xmpp/base/randomnumbergenerator.h" +#include "qttestutil/qttestutil.h" #include #include using namespace XMPP; -class RandomNumberGeneratorTest : public QObject -{ - Q_OBJECT +class RandomNumberGeneratorTest : public QObject { + Q_OBJECT + +private: + class DummyRandomNumberGenerator : public RandomNumberGenerator { + public: + DummyRandomNumberGenerator(double value, double maximum) : value_(value), maximum_(maximum) {} + + double generateNumber() const { return value_; } + double getMaximumGeneratedNumber() const { return maximum_; } private: - class DummyRandomNumberGenerator : public RandomNumberGenerator - { - public: - DummyRandomNumberGenerator(double value, double maximum) : value_(value), maximum_(maximum) {} - - double generateNumber() const { return value_; } - double getMaximumGeneratedNumber() const { return maximum_; } - - private: - double value_; - double maximum_; - }; - - private slots: - void testGenerateNumberBetween() { - DummyRandomNumberGenerator testling(5,10); - QCOMPARE(75.0, testling.generateNumberBetween(50.0, 100.0)); - } - - void testGenerateNumberBetween_Minimum() { - DummyRandomNumberGenerator testling(0,10); - QCOMPARE(0.0, testling.generateNumberBetween(0.0, 100.0)); - } - - void testGenerateNumberBetween_Maximum() { - DummyRandomNumberGenerator testling(10,10); - QCOMPARE(100.0, testling.generateNumberBetween(0.0, 100.0)); - } + double value_; + double maximum_; + }; + +private slots: + void testGenerateNumberBetween() + { + DummyRandomNumberGenerator testling(5, 10); + QCOMPARE(75.0, testling.generateNumberBetween(50.0, 100.0)); + } + + void testGenerateNumberBetween_Minimum() + { + DummyRandomNumberGenerator testling(0, 10); + QCOMPARE(0.0, testling.generateNumberBetween(0.0, 100.0)); + } + + void testGenerateNumberBetween_Maximum() + { + DummyRandomNumberGenerator testling(10, 10); + QCOMPARE(100.0, testling.generateNumberBetween(0.0, 100.0)); + } }; QTTESTUTIL_REGISTER_TEST(RandomNumberGeneratorTest); diff --git a/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp b/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp index a7255dd6..58ef5dbc 100644 --- a/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp +++ b/src/xmpp/base/unittest/randrandomnumbergeneratortest.cpp @@ -16,28 +16,28 @@ * */ -#include "qttestutil/qttestutil.h" #include "xmpp/base/randrandomnumbergenerator.h" +#include "qttestutil/qttestutil.h" #include #include using namespace XMPP; -class RandRandomNumberGeneratorTest : public QObject -{ - Q_OBJECT +class RandRandomNumberGeneratorTest : public QObject { + Q_OBJECT - private slots: - void testGenerateNumber() { - RandRandomNumberGenerator testling; +private slots: + void testGenerateNumber() + { + RandRandomNumberGenerator testling; - double a = testling.generateNumberBetween(0.0,100.0); - double b = testling.generateNumberBetween(0.0,100.0); + double a = testling.generateNumberBetween(0.0, 100.0); + double b = testling.generateNumberBetween(0.0, 100.0); - QVERIFY(a != b); - } - }; + QVERIFY(a != b); + } +}; QTTESTUTIL_REGISTER_TEST(RandRandomNumberGeneratorTest); #include "randrandomnumbergeneratortest.moc" diff --git a/src/xmpp/blake2/blake2-impl.h b/src/xmpp/blake2/blake2-impl.h index 6369ac76..1197c651 100644 --- a/src/xmpp/blake2/blake2-impl.h +++ b/src/xmpp/blake2/blake2-impl.h @@ -19,142 +19,123 @@ #include #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) - #if defined(_MSC_VER) - #define BLAKE2_INLINE __inline - #elif defined(__GNUC__) - #define BLAKE2_INLINE __inline__ - #else - #define BLAKE2_INLINE - #endif +#if defined(_MSC_VER) +#define BLAKE2_INLINE __inline +#elif defined(__GNUC__) +#define BLAKE2_INLINE __inline__ #else - #define BLAKE2_INLINE inline +#define BLAKE2_INLINE +#endif +#else +#define BLAKE2_INLINE inline #endif -static BLAKE2_INLINE uint32_t load32( const void *src ) +static BLAKE2_INLINE uint32_t load32(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; + uint32_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return (( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8) | - (( uint32_t )( p[2] ) << 16) | - (( uint32_t )( p[3] ) << 24) ; + const uint8_t *p = (const uint8_t *)src; + return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); #endif } -static BLAKE2_INLINE uint64_t load64( const void *src ) +static BLAKE2_INLINE uint64_t load64(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; + uint64_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) | - (( uint64_t )( p[6] ) << 48) | - (( uint64_t )( p[7] ) << 56) ; + const uint8_t *p = (const uint8_t *)src; + return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) + | ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) | ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56); #endif } -static BLAKE2_INLINE uint16_t load16( const void *src ) +static BLAKE2_INLINE uint16_t load16(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint16_t w; - memcpy(&w, src, sizeof w); - return w; + uint16_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return ( uint16_t )((( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8)); + const uint8_t *p = (const uint8_t *)src; + return (uint16_t)(((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8)); #endif } -static BLAKE2_INLINE void store16( void *dst, uint16_t w ) +static BLAKE2_INLINE void store16(void *dst, uint16_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - *p++ = ( uint8_t )w; w >>= 8; - *p++ = ( uint8_t )w; + uint8_t *p = (uint8_t *)dst; + *p++ = (uint8_t)w; + w >>= 8; + *p++ = (uint8_t)w; #endif } -static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +static BLAKE2_INLINE void store32(void *dst, uint32_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); #endif } -static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +static BLAKE2_INLINE void store64(void *dst, uint64_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); - p[6] = (uint8_t)(w >> 48); - p[7] = (uint8_t)(w >> 56); + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); #endif } -static BLAKE2_INLINE uint64_t load48( const void *src ) +static BLAKE2_INLINE uint64_t load48(const void *src) { - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) ; + const uint8_t *p = (const uint8_t *)src; + return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) | ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) + | ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40); } -static BLAKE2_INLINE void store48( void *dst, uint64_t w ) +static BLAKE2_INLINE void store48(void *dst, uint64_t w) { - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); + uint8_t *p = (uint8_t *)dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); } -static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 32 - c ) ); -} +static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) { return (w >> c) | (w << (32 - c)); } -static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 64 - c ) ); -} +static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { return (w >> c) | (w << (64 - c)); } /* prevents compiler optimizing out memset() */ static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) { - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); } #endif // BLAKE2_IMPL_H diff --git a/src/xmpp/blake2/blake2.h b/src/xmpp/blake2/blake2.h index e547afb9..87bfeb40 100644 --- a/src/xmpp/blake2/blake2.h +++ b/src/xmpp/blake2/blake2.h @@ -28,26 +28,23 @@ extern "C" { #endif - enum blake2s_constant - { - BLAKE2S_BLOCKBYTES = 64, - BLAKE2S_OUTBYTES = 32, - BLAKE2S_KEYBYTES = 32, - BLAKE2S_SALTBYTES = 8, +enum blake2s_constant { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, BLAKE2S_PERSONALBYTES = 8 - }; - - enum blake2b_constant - { - BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, +}; + +enum blake2b_constant { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, BLAKE2B_PERSONALBYTES = 16 - }; +}; - typedef struct blake2s_state__ - { +typedef struct blake2s_state__ { uint32_t h[8]; uint32_t t[2]; uint32_t f[2]; @@ -55,10 +52,9 @@ extern "C" { size_t buflen; size_t outlen; uint8_t last_node; - } blake2s_state; +} blake2s_state; - typedef struct blake2b_state__ - { +typedef struct blake2b_state__ { uint64_t h[8]; uint64_t t[2]; uint64_t f[2]; @@ -66,126 +62,120 @@ extern "C" { size_t buflen; size_t outlen; uint8_t last_node; - } blake2b_state; +} blake2b_state; - typedef struct blake2sp_state__ - { +typedef struct blake2sp_state__ { blake2s_state S[8][1]; blake2s_state R[1]; uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; size_t buflen; size_t outlen; - } blake2sp_state; +} blake2sp_state; - typedef struct blake2bp_state__ - { +typedef struct blake2bp_state__ { blake2b_state S[4][1]; blake2b_state R[1]; uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; size_t buflen; size_t outlen; - } blake2bp_state; +} blake2bp_state; - BLAKE2_PACKED(struct blake2s_param__ - { +BLAKE2_PACKED(struct blake2s_param__ { uint8_t digest_length; /* 1 */ uint8_t key_length; /* 2 */ uint8_t fanout; /* 3 */ uint8_t depth; /* 4 */ uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ + uint32_t node_offset; /* 12 */ uint16_t xof_length; /* 14 */ uint8_t node_depth; /* 15 */ uint8_t inner_length; /* 16 */ /* uint8_t reserved[0]; */ - uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ - uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ - }); - - typedef struct blake2s_param__ blake2s_param; - - BLAKE2_PACKED(struct blake2b_param__ - { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ - }); - - typedef struct blake2b_param__ blake2b_param; - - typedef struct blake2xs_state__ - { + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ +}); + +typedef struct blake2s_param__ blake2s_param; + +BLAKE2_PACKED(struct blake2b_param__ { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ +}); + +typedef struct blake2b_param__ blake2b_param; + +typedef struct blake2xs_state__ { blake2s_state S[1]; blake2s_param P[1]; - } blake2xs_state; +} blake2xs_state; - typedef struct blake2xb_state__ - { +typedef struct blake2xb_state__ { blake2b_state S[1]; blake2b_param P[1]; - } blake2xb_state; - - /* Padded structs result in a compile-time error */ - enum { - BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), - BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) - }; - - /* Streaming API */ - int blake2s_init( blake2s_state *S, size_t outlen ); - int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); - int blake2s_update( blake2s_state *S, const void *in, size_t inlen ); - int blake2s_final( blake2s_state *S, void *out, size_t outlen ); - - int blake2b_init( blake2b_state *S, size_t outlen ); - int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); - int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); - int blake2b_final( blake2b_state *S, void *out, size_t outlen ); - - int blake2sp_init( blake2sp_state *S, size_t outlen ); - int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen ); - int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ); - - int blake2bp_init( blake2bp_state *S, size_t outlen ); - int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen ); - int blake2bp_final( blake2bp_state *S, void *out, size_t outlen ); - - /* Variable output length API */ - int blake2xs_init( blake2xs_state *S, const size_t outlen ); - int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ); - int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ); - int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); - - int blake2xb_init( blake2xb_state *S, const size_t outlen ); - int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen ); - int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ); - int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); - - /* Simple API */ - int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - /* This is simply an alias for blake2b */ - int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); +} blake2xb_state; + +/* Padded structs result in a compile-time error */ +enum { + BLAKE2_DUMMY_1 = 1 / (sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1 / (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) +}; + +/* Streaming API */ +int blake2s_init(blake2s_state *S, size_t outlen); +int blake2s_init_key(blake2s_state *S, size_t outlen, const void *key, size_t keylen); +int blake2s_init_param(blake2s_state *S, const blake2s_param *P); +int blake2s_update(blake2s_state *S, const void *in, size_t inlen); +int blake2s_final(blake2s_state *S, void *out, size_t outlen); + +int blake2b_init(blake2b_state *S, size_t outlen); +int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); +int blake2b_init_param(blake2b_state *S, const blake2b_param *P); +int blake2b_update(blake2b_state *S, const void *in, size_t inlen); +int blake2b_final(blake2b_state *S, void *out, size_t outlen); + +int blake2sp_init(blake2sp_state *S, size_t outlen); +int blake2sp_init_key(blake2sp_state *S, size_t outlen, const void *key, size_t keylen); +int blake2sp_update(blake2sp_state *S, const void *in, size_t inlen); +int blake2sp_final(blake2sp_state *S, void *out, size_t outlen); + +int blake2bp_init(blake2bp_state *S, size_t outlen); +int blake2bp_init_key(blake2bp_state *S, size_t outlen, const void *key, size_t keylen); +int blake2bp_update(blake2bp_state *S, const void *in, size_t inlen); +int blake2bp_final(blake2bp_state *S, void *out, size_t outlen); + +/* Variable output length API */ +int blake2xs_init(blake2xs_state *S, const size_t outlen); +int blake2xs_init_key(blake2xs_state *S, const size_t outlen, const void *key, size_t keylen); +int blake2xs_update(blake2xs_state *S, const void *in, size_t inlen); +int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); + +int blake2xb_init(blake2xb_state *S, const size_t outlen); +int blake2xb_init_key(blake2xb_state *S, const size_t outlen, const void *key, size_t keylen); +int blake2xb_update(blake2xb_state *S, const void *in, size_t inlen); +int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); + +/* Simple API */ +int blake2s(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); +int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + +int blake2sp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); +int blake2bp(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + +int blake2xs(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); +int blake2xb(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); + +/* This is simply an alias for blake2b */ +int blake2(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen); #if defined(__cplusplus) } diff --git a/src/xmpp/blake2/blake2qt.cpp b/src/xmpp/blake2/blake2qt.cpp index 381d5b58..ea9bfec6 100644 --- a/src/xmpp/blake2/blake2qt.cpp +++ b/src/xmpp/blake2/blake2qt.cpp @@ -8,7 +8,7 @@ namespace XMPP { QByteArray computeBlake2Hash(const QByteArray &ba, Blake2DigestSize digestSize) { QByteArray ret; - int retCode; + int retCode; if (digestSize == Blake2Digest256) { ret.reserve(BLAKE2S_OUTBYTES); retCode = blake2s(ret.data(), BLAKE2S_OUTBYTES, ba.data(), ba.size(), nullptr, 0); @@ -26,7 +26,7 @@ QByteArray computeBlake2Hash(const QByteArray &ba, Blake2DigestSize digestSize) static QByteArray computeBlake2Hash256(QIODevice *dev) { - int retCode; + int retCode; blake2s_state state; if (!dev->isOpen()) { @@ -60,7 +60,7 @@ static QByteArray computeBlake2Hash256(QIODevice *dev) static QByteArray computeBlake2Hash512(QIODevice *dev) { - int retCode; + int retCode; blake2b_state state; if (!dev->isOpen()) { @@ -101,4 +101,4 @@ QByteArray computeBlake2Hash(QIODevice *dev, Blake2DigestSize digestSize) return computeBlake2Hash512(dev); } } -} //namespace XMPP +} // namespace XMPP diff --git a/src/xmpp/blake2/blake2qt.h b/src/xmpp/blake2/blake2qt.h index 78f08481..e9f9f65f 100644 --- a/src/xmpp/blake2/blake2qt.h +++ b/src/xmpp/blake2/blake2qt.h @@ -6,10 +6,7 @@ class QIODevice; namespace XMPP { -enum Blake2DigestSize { - Blake2Digest256, - Blake2Digest512 -}; +enum Blake2DigestSize { Blake2Digest256, Blake2Digest512 }; QByteArray computeBlake2Hash(const QByteArray &ba, Blake2DigestSize digestSize); QByteArray computeBlake2Hash(QIODevice *dev, Blake2DigestSize digestSize); diff --git a/src/xmpp/jid/jid.cpp b/src/xmpp/jid/jid.cpp index e33b8682..e1149d07 100644 --- a/src/xmpp/jid/jid.cpp +++ b/src/xmpp/jid/jid.cpp @@ -20,7 +20,7 @@ #include "xmpp/jid/jid.h" #ifndef NO_IRISNET -# include "irisnetglobal_p.h" +#include "irisnetglobal_p.h" #endif #include @@ -31,169 +31,156 @@ using namespace XMPP; //---------------------------------------------------------------------------- // StringPrepCache //---------------------------------------------------------------------------- - QScopedPointer StringPrepCache::_instance; +QScopedPointer StringPrepCache::_instance; - bool StringPrepCache::nameprep(const QString &in, int maxbytes, QString& out) - { - if (in.trimmed().isEmpty()) { - out = QString(); - return false; // empty names or just spaces are disallowed (rfc5892+rfc6122) - } - - StringPrepCache *that = instance(); +bool StringPrepCache::nameprep(const QString &in, int maxbytes, QString &out) +{ + if (in.trimmed().isEmpty()) { + out = QString(); + return false; // empty names or just spaces are disallowed (rfc5892+rfc6122) + } - auto it = that->nameprep_table.constFind(in);\ - if (it != that->nameprep_table.constEnd()) { - if (it.value().isNull()) { - return false; - } - out = it.value(); - return true; - } + StringPrepCache *that = instance(); - QByteArray cs = in.toUtf8(); - cs.resize(maxbytes); - if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0) - { - that->nameprep_table.insert(in, QString()); + auto it = that->nameprep_table.constFind(in); + if (it != that->nameprep_table.constEnd()) { + if (it.value().isNull()) { return false; } - - QString norm = QString::fromUtf8(cs); - that->nameprep_table.insert(in, norm); - out = norm; + out = it.value(); return true; } - bool StringPrepCache::nodeprep(const QString &in, int maxbytes, QString& out) - { - if(in.isEmpty()) { - out = QString(); - return true; - } + QByteArray cs = in.toUtf8(); + cs.resize(maxbytes); + if (stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_nameprep) != 0) { + that->nameprep_table.insert(in, QString()); + return false; + } - StringPrepCache *that = instance(); + QString norm = QString::fromUtf8(cs); + that->nameprep_table.insert(in, norm); + out = norm; + return true; +} - auto it = that->nodeprep_table.constFind(in);\ - if (it != that->nodeprep_table.constEnd()) { - if (it.value().isNull()) { - return false; - } - out = it.value(); - return true; - } +bool StringPrepCache::nodeprep(const QString &in, int maxbytes, QString &out) +{ + if (in.isEmpty()) { + out = QString(); + return true; + } - QByteArray cs = in.toUtf8(); - cs.resize(maxbytes); - if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0) { - that->nodeprep_table.insert(in, QString()); + StringPrepCache *that = instance(); + + auto it = that->nodeprep_table.constFind(in); + if (it != that->nodeprep_table.constEnd()) { + if (it.value().isNull()) { return false; } - - QString norm = QString::fromUtf8(cs); - that->nodeprep_table.insert(in, norm); - out = norm; + out = it.value(); return true; } - bool StringPrepCache::resourceprep(const QString &in, int maxbytes, QString& out) - { - if(in.isEmpty()) { - out = QString(); - return true; - } + QByteArray cs = in.toUtf8(); + cs.resize(maxbytes); + if (stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_nodeprep) != 0) { + that->nodeprep_table.insert(in, QString()); + return false; + } - StringPrepCache *that = instance(); + QString norm = QString::fromUtf8(cs); + that->nodeprep_table.insert(in, norm); + out = norm; + return true; +} - auto it = that->resourceprep_table.constFind(in);\ - if (it != that->resourceprep_table.constEnd()) { - if (it.value().isNull()) { - return false; - } - out = it.value(); - return true; - } +bool StringPrepCache::resourceprep(const QString &in, int maxbytes, QString &out) +{ + if (in.isEmpty()) { + out = QString(); + return true; + } - QByteArray cs = in.toUtf8(); - cs.resize(maxbytes); - if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0) { - that->resourceprep_table.insert(in, QString()); + StringPrepCache *that = instance(); + + auto it = that->resourceprep_table.constFind(in); + if (it != that->resourceprep_table.constEnd()) { + if (it.value().isNull()) { return false; } - - QString norm = QString::fromUtf8(cs); - that->resourceprep_table.insert(in, norm); - out = norm; + out = it.value(); return true; } - bool StringPrepCache::saslprep(const QString &in, int maxbytes, QString& out) - { - if(in.isEmpty()) { - out = QString(); - return true; - } + QByteArray cs = in.toUtf8(); + cs.resize(maxbytes); + if (stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_xmpp_resourceprep) != 0) { + that->resourceprep_table.insert(in, QString()); + return false; + } - StringPrepCache *that = instance(); + QString norm = QString::fromUtf8(cs); + that->resourceprep_table.insert(in, norm); + out = norm; + return true; +} - auto it = that->saslprep_table.constFind(in);\ - if (it != that->saslprep_table.constEnd()) { - if (it.value().isNull()) { - return false; - } - out = it.value(); - return true; - } +bool StringPrepCache::saslprep(const QString &in, int maxbytes, QString &out) +{ + if (in.isEmpty()) { + out = QString(); + return true; + } - QByteArray cs = in.toUtf8(); - cs.resize(maxbytes); - if(stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_saslprep) != 0) { - that->saslprep_table.insert(in, QString()); + StringPrepCache *that = instance(); + + auto it = that->saslprep_table.constFind(in); + if (it != that->saslprep_table.constEnd()) { + if (it.value().isNull()) { return false; } - - QString norm = QString::fromUtf8(cs); - that->saslprep_table.insert(in, norm); - out = norm; + out = it.value(); return true; } - void StringPrepCache::cleanup() - { - _instance.reset(nullptr); + QByteArray cs = in.toUtf8(); + cs.resize(maxbytes); + if (stringprep(cs.data(), maxbytes, (Stringprep_profile_flags)0, stringprep_saslprep) != 0) { + that->saslprep_table.insert(in, QString()); + return false; } - StringPrepCache *StringPrepCache::instance() - { - if(!_instance) - { - _instance.reset(new StringPrepCache); + QString norm = QString::fromUtf8(cs); + that->saslprep_table.insert(in, norm); + out = norm; + return true; +} + +void StringPrepCache::cleanup() { _instance.reset(nullptr); } + +StringPrepCache *StringPrepCache::instance() +{ + if (!_instance) { + _instance.reset(new StringPrepCache); #ifndef NO_IRISNET - irisNetAddPostRoutine(cleanup); // REVIEW probably not necessary since heap will be deallocated with destructors + irisNetAddPostRoutine(cleanup); // REVIEW probably not necessary since heap will be deallocated with destructors #endif - } - return _instance.data(); } + return _instance.data(); +} - StringPrepCache::StringPrepCache() - { - } +StringPrepCache::StringPrepCache() {} //---------------------------------------------------------------------------- // Jid //---------------------------------------------------------------------------- // -static inline bool validDomain(const QString &s, QString& norm) -{ - return StringPrepCache::nameprep(s, 1024, norm); -} +static inline bool validDomain(const QString &s, QString &norm) { return StringPrepCache::nameprep(s, 1024, norm); } -static inline bool validNode(const QString &s, QString& norm) -{ - return StringPrepCache::nodeprep(s, 1024, norm); -} +static inline bool validNode(const QString &s, QString &norm) { return StringPrepCache::nodeprep(s, 1024, norm); } -static inline bool validResource(const QString &s, QString& norm) +static inline bool validResource(const QString &s, QString &norm) { return StringPrepCache::resourceprep(s, 1024, norm); } @@ -201,35 +188,24 @@ static inline bool validResource(const QString &s, QString& norm) Jid::Jid() { valid = false; - null = true; + null = true; } -Jid::~Jid() -{ -} +Jid::~Jid() {} -Jid::Jid(const QString &s) -{ - set(s); -} +Jid::Jid(const QString &s) { set(s); } -Jid::Jid(const QString &node, const QString& domain, const QString& resource) -{ - set(domain, node, resource); -} +Jid::Jid(const QString &node, const QString &domain, const QString &resource) { set(domain, node, resource); } -Jid::Jid(const char *s) -{ - set(QString(s)); -} +Jid::Jid(const char *s) { set(QString(s)); } -Jid & Jid::operator=(const QString &s) +Jid &Jid::operator=(const QString &s) { set(s); return *this; } -Jid & Jid::operator=(const char *s) +Jid &Jid::operator=(const char *s) { set(QString(s)); return *this; @@ -237,27 +213,27 @@ Jid & Jid::operator=(const char *s) void Jid::reset() { - f = QString(); - b = QString(); - d = QString(); - n = QString(); - r = QString(); + f = QString(); + b = QString(); + d = QString(); + n = QString(); + r = QString(); valid = false; - null = true; + null = true; } void Jid::update() { // build 'bare' and 'full' jids - if(n.isEmpty()) + if (n.isEmpty()) b = d; else b = n + '@' + d; - if(r.isEmpty()) + if (r.isEmpty()) f = b; else f = b + '/' + r; - if(f.isEmpty()) + if (f.isEmpty()) valid = false; null = f.isEmpty() && r.isEmpty(); } @@ -266,66 +242,61 @@ void Jid::set(const QString &s) { QString rest, domain, node, resource; QString norm_domain, norm_node, norm_resource; - int x = s.indexOf('/'); - if(x != -1) { - rest = s.mid(0, x); - resource = s.mid(x+1); - } - else { - rest = s; + int x = s.indexOf('/'); + if (x != -1) { + rest = s.mid(0, x); + resource = s.mid(x + 1); + } else { + rest = s; resource = QString(); } - if(!validResource(resource, norm_resource)) { + if (!validResource(resource, norm_resource)) { reset(); return; } x = rest.indexOf('@'); - if(x != -1) { - node = rest.mid(0, x); - domain = rest.mid(x+1); - } - else { - node = QString(); + if (x != -1) { + node = rest.mid(0, x); + domain = rest.mid(x + 1); + } else { + node = QString(); domain = rest; } - if(!validDomain(domain, norm_domain) || !validNode(node, norm_node)) { + if (!validDomain(domain, norm_domain) || !validNode(node, norm_node)) { reset(); return; } valid = true; - null = false; - d = norm_domain; - n = norm_node; - r = norm_resource; + null = false; + d = norm_domain; + n = norm_node; + r = norm_resource; update(); } void Jid::set(const QString &domain, const QString &node, const QString &resource) { QString norm_domain, norm_node, norm_resource; - if(!validDomain(domain, norm_domain) || - !validNode(node, norm_node) || - !validResource(resource, norm_resource)) - { + if (!validDomain(domain, norm_domain) || !validNode(node, norm_node) || !validResource(resource, norm_resource)) { reset(); return; } valid = true; - null = false; - d = norm_domain; - n = norm_node; - r = norm_resource; + null = false; + d = norm_domain; + n = norm_node; + r = norm_resource; update(); } void Jid::setDomain(const QString &s) { - if(!valid) + if (!valid) return; QString norm; - if(!validDomain(s, norm)) { + if (!validDomain(s, norm)) { reset(); return; } @@ -335,10 +306,10 @@ void Jid::setDomain(const QString &s) void Jid::setNode(const QString &s) { - if(!valid) + if (!valid) return; QString norm; - if(!validNode(s, norm)) { + if (!validNode(s, norm)) { reset(); return; } @@ -348,10 +319,10 @@ void Jid::setNode(const QString &s) void Jid::setResource(const QString &s) { - if(!valid) + if (!valid) return; QString norm; - if(!validResource(s, norm)) { + if (!validResource(s, norm)) { reset(); return; } @@ -380,26 +351,20 @@ Jid Jid::withResource(const QString &s) const return j; } -bool Jid::isValid() const -{ - return valid; -} +bool Jid::isValid() const { return valid; } -bool Jid::isEmpty() const -{ - return f.isEmpty(); -} +bool Jid::isEmpty() const { return f.isEmpty(); } bool Jid::compare(const Jid &a, bool compareRes) const { - if(null && a.null) + if (null && a.null) return true; // only compare valid jids - if(!valid || !a.valid) + if (!valid || !a.valid) return false; - if(compareRes ? (f != a.f) : (b != a.b)) + if (compareRes ? (f != a.f) : (b != a.b)) return false; return true; diff --git a/src/xmpp/jid/jid.h b/src/xmpp/jid/jid.h index b334150b..85a36ad6 100644 --- a/src/xmpp/jid/jid.h +++ b/src/xmpp/jid/jid.h @@ -26,77 +26,75 @@ #include namespace XMPP { - class StringPrepCache - { - public: - static bool nameprep(const QString &in, int maxbytes, QString& out); - static bool nodeprep(const QString &in, int maxbytes, QString& out); - static bool resourceprep(const QString &in, int maxbytes, QString& out); - static bool saslprep(const QString &in, int maxbytes, QString& out); - - static void cleanup(); - private: - - QHash nameprep_table; - QHash nodeprep_table; - QHash resourceprep_table; - QHash saslprep_table; - - static QScopedPointer _instance; - static StringPrepCache *instance(); - - StringPrepCache(); - }; - - class Jid - { - public: - Jid(); - ~Jid(); - - Jid(const QString &s); - Jid(const QString &node, const QString& domain, const QString& resource = ""); - Jid(const char *s); - Jid & operator=(const QString &s); - Jid & operator=(const char *s); - - bool isNull() const { return null; } - const QString & domain() const { return d; } - const QString & node() const { return n; } - const QString & resource() const { return r; } - const QString & bare() const { return b; } - const QString & full() const { return f; } - - Jid withNode(const QString &s) const; - Jid withDomain(const QString &s) const; - Jid withResource(const QString &s) const; - - bool isValid() const; - bool isEmpty() const; - bool compare(const Jid &a, bool compareRes=true) const; - inline bool operator==(const Jid &other) const { return compare(other, true); } - inline bool operator!=(const Jid &other) const { return !(*this == other); } - - private: - void set(const QString &s); - void set(const QString &domain, const QString &node, const QString &resource=""); - - void setDomain(const QString &s); - void setNode(const QString &s); - void setResource(const QString &s); - - private: - void reset(); - void update(); - - QString f, b, d, n, r; - bool valid, null; - }; - - Q_DECL_PURE_FUNCTION inline uint qHash(const XMPP::Jid &key, uint seed = 0) Q_DECL_NOTHROW - { - return qHash(key.full(), seed); - } +class StringPrepCache { +public: + static bool nameprep(const QString &in, int maxbytes, QString &out); + static bool nodeprep(const QString &in, int maxbytes, QString &out); + static bool resourceprep(const QString &in, int maxbytes, QString &out); + static bool saslprep(const QString &in, int maxbytes, QString &out); + + static void cleanup(); + +private: + QHash nameprep_table; + QHash nodeprep_table; + QHash resourceprep_table; + QHash saslprep_table; + + static QScopedPointer _instance; + static StringPrepCache * instance(); + + StringPrepCache(); +}; + +class Jid { +public: + Jid(); + ~Jid(); + + Jid(const QString &s); + Jid(const QString &node, const QString &domain, const QString &resource = ""); + Jid(const char *s); + Jid &operator=(const QString &s); + Jid &operator=(const char *s); + + bool isNull() const { return null; } + const QString &domain() const { return d; } + const QString &node() const { return n; } + const QString &resource() const { return r; } + const QString &bare() const { return b; } + const QString &full() const { return f; } + + Jid withNode(const QString &s) const; + Jid withDomain(const QString &s) const; + Jid withResource(const QString &s) const; + + bool isValid() const; + bool isEmpty() const; + bool compare(const Jid &a, bool compareRes = true) const; + inline bool operator==(const Jid &other) const { return compare(other, true); } + inline bool operator!=(const Jid &other) const { return !(*this == other); } + +private: + void set(const QString &s); + void set(const QString &domain, const QString &node, const QString &resource = ""); + + void setDomain(const QString &s); + void setNode(const QString &s); + void setResource(const QString &s); + +private: + void reset(); + void update(); + + QString f, b, d, n, r; + bool valid, null; +}; + +Q_DECL_PURE_FUNCTION inline uint qHash(const XMPP::Jid &key, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(key.full(), seed); +} } // namespace XMPP #endif // XMPP_JID_H diff --git a/src/xmpp/jid/unittest/jidtest.cpp b/src/xmpp/jid/unittest/jidtest.cpp index b3c417e5..1acbe9e3 100644 --- a/src/xmpp/jid/unittest/jidtest.cpp +++ b/src/xmpp/jid/unittest/jidtest.cpp @@ -18,26 +18,26 @@ // FIXME: Complete this -#include "qttestutil/qttestutil.h" #include "xmpp/jid/jid.h" +#include "qttestutil/qttestutil.h" #include #include using namespace XMPP; -class JidTest : public QObject -{ - Q_OBJECT +class JidTest : public QObject { + Q_OBJECT - private slots: - void testConstructorWithString() { - Jid testling("foo@bar/baz"); +private slots: + void testConstructorWithString() + { + Jid testling("foo@bar/baz"); - QCOMPARE(testling.node(), QString("foo")); - QCOMPARE(testling.domain(), QString("bar")); - QCOMPARE(testling.resource(), QString("baz")); - } + QCOMPARE(testling.node(), QString("foo")); + QCOMPARE(testling.domain(), QString("bar")); + QCOMPARE(testling.resource(), QString("baz")); + } }; QTTESTUTIL_REGISTER_TEST(JidTest); diff --git a/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp b/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp index a62835b7..243768ff 100644 --- a/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp +++ b/src/xmpp/qa/qttestutil/example/myfirstclasstest.cpp @@ -3,20 +3,18 @@ #include #include -class MyFirstClassTest : public QObject -{ - Q_OBJECT +class MyFirstClassTest : public QObject { + Q_OBJECT - private slots: - void initTestCase() { - } +private slots: + void initTestCase() {} - void cleanupTestCase() { - } + void cleanupTestCase() {} - void testMyMethod() { - QCOMPARE(1, 1); // Dummy test - } + void testMyMethod() + { + QCOMPARE(1, 1); // Dummy test + } }; QTTESTUTIL_REGISTER_TEST(MyFirstClassTest); diff --git a/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp b/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp index c2b57159..15b762c6 100644 --- a/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp +++ b/src/xmpp/qa/qttestutil/example/mysecondclasstest.cpp @@ -3,20 +3,18 @@ #include #include -class MySecondClassTest : public QObject -{ - Q_OBJECT +class MySecondClassTest : public QObject { + Q_OBJECT - private slots: - void initTestCase() { - } +private slots: + void initTestCase() {} - void cleanupTestCase() { - } + void cleanupTestCase() {} - void testMyMethod() { - QCOMPARE(1, 0); // Dummy test - } + void testMyMethod() + { + QCOMPARE(1, 0); // Dummy test + } }; QTTESTUTIL_REGISTER_TEST(MySecondClassTest); diff --git a/src/xmpp/qa/qttestutil/qttestutil.h b/src/xmpp/qa/qttestutil/qttestutil.h index d53a8363..91f19baf 100644 --- a/src/xmpp/qa/qttestutil/qttestutil.h +++ b/src/xmpp/qa/qttestutil/qttestutil.h @@ -35,7 +35,6 @@ * * QTTESTUTIL_REGISTER_TEST(MyTest) */ -#define QTTESTUTIL_REGISTER_TEST(TestClass) \ - static QtTestUtil::TestRegistration TestClass##Registration +#define QTTESTUTIL_REGISTER_TEST(TestClass) static QtTestUtil::TestRegistration TestClass##Registration #endif // QTTESTUTIL_H diff --git a/src/xmpp/qa/qttestutil/simplechecker.cpp b/src/xmpp/qa/qttestutil/simplechecker.cpp index 50a6f11e..17710777 100644 --- a/src/xmpp/qa/qttestutil/simplechecker.cpp +++ b/src/xmpp/qa/qttestutil/simplechecker.cpp @@ -23,7 +23,7 @@ /** * Runs all tests registered with the QtTestUtil registry. */ -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { QCoreApplication application(argc, argv); return QtTestUtil::TestRegistry::getInstance()->runTests(argc, argv); diff --git a/src/xmpp/qa/qttestutil/testregistration.h b/src/xmpp/qa/qttestutil/testregistration.h index 0378ea05..741d6464 100644 --- a/src/xmpp/qa/qttestutil/testregistration.h +++ b/src/xmpp/qa/qttestutil/testregistration.h @@ -22,28 +22,25 @@ #include "qttestutil/testregistry.h" namespace QtTestUtil { - /** - * A wrapper class around a test to manage registration and static - * creation of an instance of the test class. - * This class is used by QTTESTUTIL_REGISTER_TEST(), and you should not - * use this class directly. - */ - template - class TestRegistration +/** + * A wrapper class around a test to manage registration and static + * creation of an instance of the test class. + * This class is used by QTTESTUTIL_REGISTER_TEST(), and you should not + * use this class directly. + */ +template class TestRegistration { +public: + TestRegistration() { - public: - TestRegistration() { - test_ = new TestClass(); - TestRegistry::getInstance()->registerTest(test_); - } + test_ = new TestClass(); + TestRegistry::getInstance()->registerTest(test_); + } - ~TestRegistration() { - delete test_; - } + ~TestRegistration() { delete test_; } - private: - TestClass* test_; - }; +private: + TestClass *test_; +}; } // namespace QtTestUtil #endif // QTTESTUTIL_TESTREGISTRATION_H diff --git a/src/xmpp/qa/qttestutil/testregistry.cpp b/src/xmpp/qa/qttestutil/testregistry.cpp index 29d58d8d..ca5d91e8 100644 --- a/src/xmpp/qa/qttestutil/testregistry.cpp +++ b/src/xmpp/qa/qttestutil/testregistry.cpp @@ -21,23 +21,20 @@ #include namespace QtTestUtil { -TestRegistry* TestRegistry::getInstance() +TestRegistry *TestRegistry::getInstance() { static TestRegistry registry; return ®istry; } -void TestRegistry::registerTest(QObject* test) -{ - tests_ += test; -} +void TestRegistry::registerTest(QObject *test) { tests_ += test; } -int TestRegistry::runTests(int argc, char* argv[]) +int TestRegistry::runTests(int argc, char *argv[]) { int result = 0; - foreach(QObject* test, tests_) { + foreach (QObject *test, tests_) { result |= QTest::qExec(test, argc, argv); } return result; } -} // namespace QtTestUtil +} // namespace QtTestUtil diff --git a/src/xmpp/qa/qttestutil/testregistry.h b/src/xmpp/qa/qttestutil/testregistry.h index 95d7502c..de3f3339 100644 --- a/src/xmpp/qa/qttestutil/testregistry.h +++ b/src/xmpp/qa/qttestutil/testregistry.h @@ -24,38 +24,37 @@ class QObject; namespace QtTestUtil { +/** + * A registry of QtTest test classes. + * All test classes registered with QTTESTUTIL_REGISTER_TEST add + * themselves to this registry. All registered tests can then be run at + * once using runTests(). + */ +class TestRegistry { +public: /** - * A registry of QtTest test classes. - * All test classes registered with QTTESTUTIL_REGISTER_TEST add - * themselves to this registry. All registered tests can then be run at - * once using runTests(). + * Retrieve the single instance of the registry. */ - class TestRegistry - { - public: - /** - * Retrieve the single instance of the registry. - */ - static TestRegistry* getInstance(); - - /** - * Register a QtTest test. - * This method is called by QTTESTUTIL_REGISTER_TEST, and you should - * not use this method directly. - */ - void registerTest(QObject*); - - /** - * Run all registered tests using QTest::qExec() - */ - int runTests(int argc, char* argv[]); - - private: - TestRegistry() {} - - private: - QList tests_; - }; + static TestRegistry *getInstance(); + + /** + * Register a QtTest test. + * This method is called by QTTESTUTIL_REGISTER_TEST, and you should + * not use this method directly. + */ + void registerTest(QObject *); + + /** + * Run all registered tests using QTest::qExec() + */ + int runTests(int argc, char *argv[]); + +private: + TestRegistry() {} + +private: + QList tests_; +}; } // namespace QtTestUtil #endif // QTTESTUTIL_TESTREGISTRY_H diff --git a/src/xmpp/qa/unittest.template/myclasstest.cpp b/src/xmpp/qa/unittest.template/myclasstest.cpp index 05218989..d1555cb2 100644 --- a/src/xmpp/qa/unittest.template/myclasstest.cpp +++ b/src/xmpp/qa/unittest.template/myclasstest.cpp @@ -21,21 +21,19 @@ #include #include -class MyClassTest : public QObject -{ - Q_OBJECT +class MyClassTest : public QObject { + Q_OBJECT - private slots: - void initTestCase() { - } +private slots: + void initTestCase() {} - void cleanupTestCase() { - } + void cleanupTestCase() {} - void testMyMethod() { - //QCOMPARE(foo, bar); - //QVERIFY(baz); - } + void testMyMethod() + { + // QCOMPARE(foo, bar); + // QVERIFY(baz); + } }; QTTESTUTIL_REGISTER_TEST(MyClassTest); diff --git a/src/xmpp/sasl/digestmd5proplist.cpp b/src/xmpp/sasl/digestmd5proplist.cpp index 59c682e4..01bff42f 100644 --- a/src/xmpp/sasl/digestmd5proplist.cpp +++ b/src/xmpp/sasl/digestmd5proplist.cpp @@ -19,11 +19,10 @@ #include "xmpp/sasl/digestmd5proplist.h" namespace XMPP { -DIGESTMD5PropList::DIGESTMD5PropList() : QList() -{ -} +DIGESTMD5PropList::DIGESTMD5PropList() : QList() {} -void DIGESTMD5PropList::set(const QByteArray &var, const QByteArray &val) { +void DIGESTMD5PropList::set(const QByteArray &var, const QByteArray &val) +{ DIGESTMD5Prop p; p.var = var; p.val = val; @@ -32,8 +31,8 @@ void DIGESTMD5PropList::set(const QByteArray &var, const QByteArray &val) { QByteArray DIGESTMD5PropList::get(const QByteArray &var) const { - for(ConstIterator it = begin(); it != end(); ++it) { - if((*it).var == var) + for (ConstIterator it = begin(); it != end(); ++it) { + if ((*it).var == var) return (*it).val; } return QByteArray(); @@ -42,11 +41,12 @@ QByteArray DIGESTMD5PropList::get(const QByteArray &var) const QByteArray DIGESTMD5PropList::toString() const { QByteArray str; - bool first = true; - for(ConstIterator it = begin(); it != end(); ++it) { - if(!first) + bool first = true; + for (ConstIterator it = begin(); it != end(); ++it) { + if (!first) str += ','; - if ((*it).var == "realm" || (*it).var == "nonce" || (*it).var == "username" || (*it).var == "cnonce" || (*it).var == "digest-uri" || (*it).var == "authzid") + if ((*it).var == "realm" || (*it).var == "nonce" || (*it).var == "username" || (*it).var == "cnonce" + || (*it).var == "digest-uri" || (*it).var == "authzid") str += (*it).var + "=\"" + (*it).val + '\"'; else str += (*it).var + "=" + (*it).val; @@ -58,30 +58,29 @@ QByteArray DIGESTMD5PropList::toString() const bool DIGESTMD5PropList::fromString(const QByteArray &str) { DIGESTMD5PropList list; - int at = 0; - while(1) { + int at = 0; + while (1) { while (at < str.length() && (str[at] == ',' || str[at] == ' ' || str[at] == '\t')) - ++at; + ++at; int n = str.indexOf('=', at); - if(n == -1) + if (n == -1) break; QByteArray var, val; - var = str.mid(at, n-at); - at = n + 1; - if(str[at] == '\"') { + var = str.mid(at, n - at); + at = n + 1; + if (str[at] == '\"') { ++at; n = str.indexOf('\"', at); - if(n == -1) + if (n == -1) break; - val = str.mid(at, n-at); - at = n + 1; - } - else { + val = str.mid(at, n - at); + at = n + 1; + } else { n = at; while (n < str.length() && str[n] != ',' && str[n] != ' ' && str[n] != '\t') ++n; - val = str.mid(at, n-at); - at = n; + val = str.mid(at, n - at); + at = n; } DIGESTMD5Prop prop; prop.var = var; @@ -92,27 +91,26 @@ bool DIGESTMD5PropList::fromString(const QByteArray &str) ++a; if (a == val.length()) break; - n = a+1; + n = a + 1; while (n < val.length() && val[n] != ',' && val[n] != ' ' && val[n] != '\t') ++n; - prop.val = val.mid(a, n-a); + prop.val = val.mid(a, n - a); list.append(prop); - a = n+1; + a = n + 1; } - } - else { + } else { prop.val = val; list.append(prop); } - if(at >= str.size() - 1 || (str[at] != ',' && str[at] != ' ' && str[at] != '\t')) + if (at >= str.size() - 1 || (str[at] != ',' && str[at] != ' ' && str[at] != '\t')) break; } // integrity check - if(list.varCount("nonce") != 1) + if (list.varCount("nonce") != 1) return false; - if(list.varCount("algorithm") != 1) + if (list.varCount("algorithm") != 1) return false; *this = list; return true; @@ -121,8 +119,8 @@ bool DIGESTMD5PropList::fromString(const QByteArray &str) int DIGESTMD5PropList::varCount(const QByteArray &var) const { int n = 0; - for(ConstIterator it = begin(); it != end(); ++it) { - if((*it).var == var) + for (ConstIterator it = begin(); it != end(); ++it) { + if ((*it).var == var) ++n; } return n; diff --git a/src/xmpp/sasl/digestmd5proplist.h b/src/xmpp/sasl/digestmd5proplist.h index f94d36d4..a7f1ae99 100644 --- a/src/xmpp/sasl/digestmd5proplist.h +++ b/src/xmpp/sasl/digestmd5proplist.h @@ -23,24 +23,22 @@ #include namespace XMPP { - struct DIGESTMD5Prop - { - QByteArray var, val; - }; +struct DIGESTMD5Prop { + QByteArray var, val; +}; - class DIGESTMD5PropList : public QList - { - public: - DIGESTMD5PropList(); +class DIGESTMD5PropList : public QList { +public: + DIGESTMD5PropList(); - void set(const QByteArray &var, const QByteArray &val); - QByteArray get(const QByteArray &var) const; - QByteArray toString() const; - bool fromString(const QByteArray &str); + void set(const QByteArray &var, const QByteArray &val); + QByteArray get(const QByteArray &var) const; + QByteArray toString() const; + bool fromString(const QByteArray &str); - private: - int varCount(const QByteArray &var) const; - }; +private: + int varCount(const QByteArray &var) const; +}; } // namespace XMPP #endif // DIGESTMD5PROPLIST_H diff --git a/src/xmpp/sasl/digestmd5response.cpp b/src/xmpp/sasl/digestmd5response.cpp index 2cd4e9b9..4f0094b5 100644 --- a/src/xmpp/sasl/digestmd5response.cpp +++ b/src/xmpp/sasl/digestmd5response.cpp @@ -26,23 +26,26 @@ #include namespace XMPP { -DIGESTMD5Response::DIGESTMD5Response(const QByteArray& challenge, const QString& service, const QString& host, const QString& arealm, const QString& user, const QString& authz, const QByteArray& password, const RandomNumberGenerator& rand) : isValid_(true) +DIGESTMD5Response::DIGESTMD5Response(const QByteArray &challenge, const QString &service, const QString &host, + const QString &arealm, const QString &user, const QString &authz, + const QByteArray &password, const RandomNumberGenerator &rand) : + isValid_(true) { QString realm = arealm; // get props DIGESTMD5PropList in; - if(!in.fromString(challenge)) { + if (!in.fromString(challenge)) { isValid_ = false; return; } - //qDebug() << (QString("simplesasl.cpp: IN: %1").arg(QString(in.toString()))); + // qDebug() << (QString("simplesasl.cpp: IN: %1").arg(QString(in.toString()))); // make a cnonce QByteArray a; a.resize(32); - for(int n = 0; n < (int)a.size(); ++n) { - a[n] = (char) rand.generateNumberBetween(0, 255); + for (int n = 0; n < (int)a.size(); ++n) { + a[n] = (char)rand.generateNumberBetween(0, 255); } QByteArray cnonce = a.toBase64(); @@ -51,28 +54,28 @@ DIGESTMD5Response::DIGESTMD5Response(const QByteArray& challenge, const QString& realm = QString::fromUtf8(in.get("realm")); } QByteArray nonce = in.get("nonce"); - QByteArray nc = "00000001"; - QByteArray uri = service.toUtf8() + '/' + host.toUtf8(); - QByteArray qop = "auth"; + QByteArray nc = "00000001"; + QByteArray uri = service.toUtf8() + '/' + host.toUtf8(); + QByteArray qop = "auth"; // build 'response' - QByteArray X = user.toUtf8() + ':' + realm.toUtf8() + ':' + password; - QByteArray Y = QCA::Hash("md5").hash(X).toByteArray(); + QByteArray X = user.toUtf8() + ':' + realm.toUtf8() + ':' + password; + QByteArray Y = QCA::Hash("md5").hash(X).toByteArray(); QByteArray tmp = ':' + nonce + ':' + cnonce; if (!authz.isEmpty()) tmp += ':' + authz.toUtf8(); - //qDebug() << (QString(tmp)); + // qDebug() << (QString(tmp)); QByteArray A1(Y + tmp); - QByteArray A2 = QByteArray("AUTHENTICATE:") + uri; + QByteArray A2 = QByteArray("AUTHENTICATE:") + uri; QByteArray HA1 = QCA::Hash("md5").hashToString(A1).toLatin1(); QByteArray HA2 = QCA::Hash("md5").hashToString(A2).toLatin1(); - QByteArray KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2; - QByteArray Z = QCA::Hash("md5").hashToString(KD).toLatin1(); + QByteArray KD = HA1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + HA2; + QByteArray Z = QCA::Hash("md5").hashToString(KD).toLatin1(); - //qDebug() << QString("simplesasl.cpp: A1 = %1").arg(QString(A1)); - //qDebug() << QString("simplesasl.cpp: A2 = %1").arg(QString(A2)); - //qDebug() << QString("simplesasl.cpp: KD = %1").arg(QString(KD)); + // qDebug() << QString("simplesasl.cpp: A1 = %1").arg(QString(A1)); + // qDebug() << QString("simplesasl.cpp: A2 = %1").arg(QString(A2)); + // qDebug() << QString("simplesasl.cpp: KD = %1").arg(QString(KD)); // build output DIGESTMD5PropList out; @@ -82,14 +85,14 @@ DIGESTMD5Response::DIGESTMD5Response(const QByteArray& challenge, const QString& out.set("nonce", nonce); out.set("cnonce", cnonce); out.set("nc", nc); - //out.set("serv-type", service.toUtf8()); - //out.set("host", host.toUtf8()); + // out.set("serv-type", service.toUtf8()); + // out.set("host", host.toUtf8()); out.set("digest-uri", uri); out.set("qop", qop); out.set("response", Z); out.set("charset", "utf-8"); if (!authz.isEmpty()) out.set("authzid", authz.toUtf8()); - value_ = out.toString(); + value_ = out.toString(); } } // namespace XMPP diff --git a/src/xmpp/sasl/digestmd5response.h b/src/xmpp/sasl/digestmd5response.h index 60969974..26ca8e20 100644 --- a/src/xmpp/sasl/digestmd5response.h +++ b/src/xmpp/sasl/digestmd5response.h @@ -23,33 +23,22 @@ #include namespace XMPP { - class RandomNumberGenerator; - - class DIGESTMD5Response - { - public: - DIGESTMD5Response( - const QByteArray& challenge, - const QString& service, - const QString& host, - const QString& realm, - const QString& user, - const QString& authz, - const QByteArray& password, - const RandomNumberGenerator& rand); - - const QByteArray& getValue() const { - return value_; - } - - bool isValid() const { - return isValid_; - } - - private: - bool isValid_; - QByteArray value_; - }; +class RandomNumberGenerator; + +class DIGESTMD5Response { +public: + DIGESTMD5Response(const QByteArray &challenge, const QString &service, const QString &host, const QString &realm, + const QString &user, const QString &authz, const QByteArray &password, + const RandomNumberGenerator &rand); + + const QByteArray &getValue() const { return value_; } + + bool isValid() const { return isValid_; } + +private: + bool isValid_; + QByteArray value_; +}; } // namespace XMPP #endif // DIGESTMD5RESPONSE_H diff --git a/src/xmpp/sasl/plainmessage.cpp b/src/xmpp/sasl/plainmessage.cpp index 3585065a..46ac34cd 100644 --- a/src/xmpp/sasl/plainmessage.cpp +++ b/src/xmpp/sasl/plainmessage.cpp @@ -19,7 +19,7 @@ #include "xmpp/sasl/plainmessage.h" namespace XMPP { -PLAINMessage::PLAINMessage(const QString& authzid, const QString& authcid, const QByteArray& password) +PLAINMessage::PLAINMessage(const QString &authzid, const QString &authcid, const QByteArray &password) { value_ = authzid.toUtf8() + '\0' + authcid.toUtf8() + '\0' + password; } diff --git a/src/xmpp/sasl/plainmessage.h b/src/xmpp/sasl/plainmessage.h index a41c0b57..949a8749 100644 --- a/src/xmpp/sasl/plainmessage.h +++ b/src/xmpp/sasl/plainmessage.h @@ -23,18 +23,15 @@ #include namespace XMPP { - class PLAINMessage - { - public: - PLAINMessage(const QString& authzid, const QString& authcid, const QByteArray& password); +class PLAINMessage { +public: + PLAINMessage(const QString &authzid, const QString &authcid, const QByteArray &password); - const QByteArray& getValue() { - return value_; - } + const QByteArray &getValue() { return value_; } - private: - QByteArray value_; - }; +private: + QByteArray value_; +}; } // namespace XMPP #endif // PLAINMESSAGE_H diff --git a/src/xmpp/sasl/scramsha1message.cpp b/src/xmpp/sasl/scramsha1message.cpp index eac93f5c..74e3543a 100644 --- a/src/xmpp/sasl/scramsha1message.cpp +++ b/src/xmpp/sasl/scramsha1message.cpp @@ -27,7 +27,8 @@ #include namespace XMPP { -bool Normalize(const QString &username_in, QString &username_out ) { +bool Normalize(const QString &username_in, QString &username_out) +{ // SASLprep if (StringPrepCache::saslprep(username_in, 1024, username_out)) { // '=' -> '=3D' and ',' -> '=2C' @@ -39,11 +40,13 @@ bool Normalize(const QString &username_in, QString &username_out ) { } } -SCRAMSHA1Message::SCRAMSHA1Message(const QString& authzid, const QString& authcid, const QByteArray& cnonce, const RandomNumberGenerator& rand) : isValid_(true) +SCRAMSHA1Message::SCRAMSHA1Message(const QString &authzid, const QString &authcid, const QByteArray &cnonce, + const RandomNumberGenerator &rand) : + isValid_(true) { - QString result; + QString result; QByteArray clientnonce; - QString username; + QString username; if (!Normalize(authcid, username)) { isValid_ = false; @@ -54,11 +57,12 @@ SCRAMSHA1Message::SCRAMSHA1Message(const QString& authzid, const QString& authci // make a cnonce QByteArray a; a.resize(32); - for(int n = 0; n < (int)a.size(); ++n) { - a[n] = (char) rand.generateNumberBetween(0, 255); + for (int n = 0; n < (int)a.size(); ++n) { + a[n] = (char)rand.generateNumberBetween(0, 255); } clientnonce = a.toBase64(); - } else clientnonce = cnonce; + } else + clientnonce = cnonce; QTextStream(&result) << "n,"; if (authzid.size() > 0) { diff --git a/src/xmpp/sasl/scramsha1message.h b/src/xmpp/sasl/scramsha1message.h index 24fae6fb..98d7bbf6 100644 --- a/src/xmpp/sasl/scramsha1message.h +++ b/src/xmpp/sasl/scramsha1message.h @@ -25,23 +25,19 @@ #include namespace XMPP { - class SCRAMSHA1Message - { - public: - SCRAMSHA1Message(const QString& authzid, const QString& authcid, const QByteArray& cnonce, const RandomNumberGenerator& rand); - - const QByteArray& getValue() { - return value_; - } - - bool isValid() const { - return isValid_; - } - - private: - QByteArray value_; - bool isValid_; - }; +class SCRAMSHA1Message { +public: + SCRAMSHA1Message(const QString &authzid, const QString &authcid, const QByteArray &cnonce, + const RandomNumberGenerator &rand); + + const QByteArray &getValue() { return value_; } + + bool isValid() const { return isValid_; } + +private: + QByteArray value_; + bool isValid_; +}; } // namespace XMPP #endif // SCRAMSHA1MESSAGE_H diff --git a/src/xmpp/sasl/scramsha1response.cpp b/src/xmpp/sasl/scramsha1response.cpp index 960327e8..09d034b7 100644 --- a/src/xmpp/sasl/scramsha1response.cpp +++ b/src/xmpp/sasl/scramsha1response.cpp @@ -29,24 +29,27 @@ #include namespace XMPP { - QCA::SecureArray HMAC_SHA_1(const QCA::SecureArray &key, const QCA::SecureArray &str) { - QCA::SecureArray result = QCA::MessageAuthenticationCode("hmac(sha1)", key).process(str); - return result; - } +QCA::SecureArray HMAC_SHA_1(const QCA::SecureArray &key, const QCA::SecureArray &str) +{ + QCA::SecureArray result = QCA::MessageAuthenticationCode("hmac(sha1)", key).process(str); + return result; +} - SCRAMSHA1Response::SCRAMSHA1Response(const QByteArray& server_first_message, const QByteArray& password_in, const QByteArray& client_first_message, const QString &salted_password_base64, const RandomNumberGenerator& rand) +SCRAMSHA1Response::SCRAMSHA1Response(const QByteArray &server_first_message, const QByteArray &password_in, + const QByteArray &client_first_message, const QString &salted_password_base64, + const RandomNumberGenerator &rand) { Q_UNUSED(rand); QString pass_in = QString::fromUtf8(password_in); QString pass_out; QRegExp pattern("r=(.*),s=(.+),i=(\\d+)"); - int pos = pattern.indexIn(QString(server_first_message)); - isValid_ = true; + int pos = pattern.indexIn(QString(server_first_message)); + isValid_ = true; if (pos > -1) { QString clientservernonce = pattern.cap(1); - QString salt = pattern.cap(2); - QString icount = pattern.cap(3); + QString salt = pattern.cap(2); + QString icount = pattern.cap(3); unsigned int dkLen; @@ -60,7 +63,8 @@ namespace XMPP { // SaltedPassword := Hi(Normalize(password), salt, i) if (salted_password_base64.size() > 0) - salted_password_ = QCA::SymmetricKey(QCA::SecureArray(QCA::Base64().stringToArray(salted_password_base64.toUtf8()))); + salted_password_ + = QCA::SymmetricKey(QCA::SecureArray(QCA::Base64().stringToArray(salted_password_base64.toUtf8()))); if (salted_password_.size() == 0) { if (!StringPrepCache::saslprep(pass_in, 1023, pass_out)) { isValid_ = false; @@ -68,7 +72,9 @@ namespace XMPP { } password = pass_out.toUtf8(); - salted_password_ = hi.makeKey(QCA::SecureArray(password), QCA::InitializationVector(QCA::Base64().stringToArray(salt)), dkLen, icount.toULong()); + salted_password_ + = hi.makeKey(QCA::SecureArray(password), QCA::InitializationVector(QCA::Base64().stringToArray(salt)), + dkLen, icount.toULong()); } // ClientKey := HMAC(SaltedPassword, "Client Key") @@ -86,12 +92,13 @@ namespace XMPP { gs2_header = pattern.cap(1); } - QString client_final_message; + QString client_final_message; QTextStream final_message_stream(&client_final_message); final_message_stream << "c=" << QCA::Base64().arrayToString((gs2_header.toUtf8())); final_message_stream << ",r=" << clientservernonce; - // AuthMessage := client-first-message-bare + "," + server-first-message + "," + client-final-message-without-proof + // AuthMessage := client-first-message-bare + "," + server-first-message + "," + + // client-final-message-without-proof QRegExp extract_cfmb_pattern("(n=.+)"); if (extract_cfmb_pattern.indexIn(QString(client_first_message)) < 0) { isValid_ = false; @@ -109,7 +116,7 @@ namespace XMPP { // ClientProof := ClientKey XOR ClientSignature QCA::SecureArray client_proof(client_key.size()); - for(int i = 0; i < client_proof.size(); ++i) { + for (int i = 0; i < client_proof.size(); ++i) { client_proof[i] = client_key[i] ^ client_signature[i]; } @@ -127,7 +134,5 @@ namespace XMPP { } } -const QString SCRAMSHA1Response::getSaltedPassword() { - return QCA::Base64().arrayToString(salted_password_); -} +const QString SCRAMSHA1Response::getSaltedPassword() { return QCA::Base64().arrayToString(salted_password_); } } // namespace XMPP diff --git a/src/xmpp/sasl/scramsha1response.h b/src/xmpp/sasl/scramsha1response.h index 9d00dee8..e4cb723f 100644 --- a/src/xmpp/sasl/scramsha1response.h +++ b/src/xmpp/sasl/scramsha1response.h @@ -24,38 +24,28 @@ #include namespace XMPP { - class RandomNumberGenerator; - - class SCRAMSHA1Response - { - public: - SCRAMSHA1Response( - const QByteArray& server_first_message, - const QByteArray& password, - const QByteArray& client_first_message, - const QString &salted_password_base64, - const RandomNumberGenerator& rand); - - const QByteArray& getValue() const { - return value_; - } - - const QCA::SecureArray getServerSignature() const { - return server_signature_; - } - - const QString getSaltedPassword(); - - bool isValid() const { - return isValid_; - } - - private: - bool isValid_; - QByteArray value_; - QCA::SecureArray server_signature_; - QCA::SymmetricKey salted_password_; - }; +class RandomNumberGenerator; + +class SCRAMSHA1Response { +public: + SCRAMSHA1Response(const QByteArray &server_first_message, const QByteArray &password, + const QByteArray &client_first_message, const QString &salted_password_base64, + const RandomNumberGenerator &rand); + + const QByteArray &getValue() const { return value_; } + + const QCA::SecureArray getServerSignature() const { return server_signature_; } + + const QString getSaltedPassword(); + + bool isValid() const { return isValid_; } + +private: + bool isValid_; + QByteArray value_; + QCA::SecureArray server_signature_; + QCA::SymmetricKey salted_password_; +}; } // namespace XMPP #endif // SCRAMSHA1RESPONSE_H diff --git a/src/xmpp/sasl/scramsha1signature.cpp b/src/xmpp/sasl/scramsha1signature.cpp index 60b101ba..4051fe06 100644 --- a/src/xmpp/sasl/scramsha1signature.cpp +++ b/src/xmpp/sasl/scramsha1signature.cpp @@ -28,15 +28,17 @@ #include namespace XMPP { - SCRAMSHA1Signature::SCRAMSHA1Signature(const QByteArray &server_final_message, const QCA::SecureArray &server_signature_should) +SCRAMSHA1Signature::SCRAMSHA1Signature(const QByteArray & server_final_message, + const QCA::SecureArray &server_signature_should) { QRegExp pattern("v=([^,]*)"); - int pos = pattern.indexIn(QString(server_final_message)); - isValid_ = true; + int pos = pattern.indexIn(QString(server_final_message)); + isValid_ = true; if (pos > -1) { - QString server_signature = pattern.cap(1); + QString server_signature = pattern.cap(1); QCA::SecureArray server_sig(QCA::Base64().stringToArray(server_signature)); - if (server_sig != server_signature_should) isValid_ = false; + if (server_sig != server_signature_should) + isValid_ = false; } else { qWarning("SASL/SCRAM-SHA-1: Failed to match pattern for server-final-message."); isValid_ = false; diff --git a/src/xmpp/sasl/scramsha1signature.h b/src/xmpp/sasl/scramsha1signature.h index 5b4125d1..27990e34 100644 --- a/src/xmpp/sasl/scramsha1signature.h +++ b/src/xmpp/sasl/scramsha1signature.h @@ -24,18 +24,15 @@ #include namespace XMPP { - class SCRAMSHA1Signature - { - public: - SCRAMSHA1Signature(const QByteArray &server_final_message, const QCA::SecureArray &server_signature_should); +class SCRAMSHA1Signature { +public: + SCRAMSHA1Signature(const QByteArray &server_final_message, const QCA::SecureArray &server_signature_should); - bool isValid() const { - return isValid_; - } + bool isValid() const { return isValid_; } - private: - bool isValid_; - }; +private: + bool isValid_; +}; } // namespace XMPP #endif // SCRAMSHA1SIGNATURE_H diff --git a/src/xmpp/sasl/unittest/digestmd5responsetest.cpp b/src/xmpp/sasl/unittest/digestmd5responsetest.cpp index 6cf2d790..25c948bc 100644 --- a/src/xmpp/sasl/unittest/digestmd5responsetest.cpp +++ b/src/xmpp/sasl/unittest/digestmd5responsetest.cpp @@ -16,9 +16,9 @@ * */ +#include "xmpp/sasl/digestmd5response.h" #include "qttestutil/qttestutil.h" #include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" -#include "xmpp/sasl/digestmd5response.h" #include #include @@ -26,54 +26,49 @@ using namespace XMPP; -class DIGESTMD5ResponseTest : public QObject -{ - Q_OBJECT +class DIGESTMD5ResponseTest : public QObject { + Q_OBJECT - private slots: - void testConstructor_WithAuthzid() { - DIGESTMD5Response response( - "realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "qop=\"auth\",charset=\"utf-8\",algorithm=\"md5-sess\"", - "xmpp", "jabber.example.com", "example.com", "myuser", "myuser_authz", - "mypass", - IncrementingRandomNumberGenerator(255)); - QByteArray expectedValue( - "username=\"myuser\",realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "cnonce=\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"," - "nc=00000001," - "digest-uri=\"xmpp/jabber.example.com\"," - "qop=auth,response=8fe15bc2aa31956b62d9de831b21a5d4," - "charset=utf-8,authzid=\"myuser_authz\""); +private slots: + void testConstructor_WithAuthzid() + { + DIGESTMD5Response response("realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "qop=\"auth\",charset=\"utf-8\",algorithm=\"md5-sess\"", + "xmpp", "jabber.example.com", "example.com", "myuser", "myuser_authz", "mypass", + IncrementingRandomNumberGenerator(255)); + QByteArray expectedValue("username=\"myuser\",realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "cnonce=\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"," + "nc=00000001," + "digest-uri=\"xmpp/jabber.example.com\"," + "qop=auth,response=8fe15bc2aa31956b62d9de831b21a5d4," + "charset=utf-8,authzid=\"myuser_authz\""); - QVERIFY(response.isValid()); - QCOMPARE(response.getValue(), expectedValue); - } + QVERIFY(response.isValid()); + QCOMPARE(response.getValue(), expectedValue); + } - void testConstructor_WithoutAuthzid() { - DIGESTMD5Response response( - "realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "qop=\"auth\",charset=\"utf-8\",algorithm=\"md5-sess\"", - "xmpp", "jabber.example.com", "example.com", "myuser", "", - "mypass", - IncrementingRandomNumberGenerator(255)); - QByteArray expectedValue( - "username=\"myuser\",realm=\"example.com\"," - "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," - "cnonce=\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"," - "nc=00000001," - "digest-uri=\"xmpp/jabber.example.com\"," - "qop=auth,response=564b1c1cc16d97b019f18b14c979964b,charset=utf-8"); + void testConstructor_WithoutAuthzid() + { + DIGESTMD5Response response("realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "qop=\"auth\",charset=\"utf-8\",algorithm=\"md5-sess\"", + "xmpp", "jabber.example.com", "example.com", "myuser", "", "mypass", + IncrementingRandomNumberGenerator(255)); + QByteArray expectedValue("username=\"myuser\",realm=\"example.com\"," + "nonce=\"O6skKPuaCZEny3hteI19qXMBXSadoWs840MchORo\"," + "cnonce=\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=\"," + "nc=00000001," + "digest-uri=\"xmpp/jabber.example.com\"," + "qop=auth,response=564b1c1cc16d97b019f18b14c979964b,charset=utf-8"); - QVERIFY(response.isValid()); - QCOMPARE(response.getValue(), expectedValue); - } + QVERIFY(response.isValid()); + QCOMPARE(response.getValue(), expectedValue); + } - private: - QCA::Initializer initializer; +private: + QCA::Initializer initializer; }; QTTESTUTIL_REGISTER_TEST(DIGESTMD5ResponseTest); diff --git a/src/xmpp/sasl/unittest/plainmessagetest.cpp b/src/xmpp/sasl/unittest/plainmessagetest.cpp index 7bb1dc29..4ee25e3b 100644 --- a/src/xmpp/sasl/unittest/plainmessagetest.cpp +++ b/src/xmpp/sasl/unittest/plainmessagetest.cpp @@ -16,33 +16,36 @@ * */ -#include "qttestutil/qttestutil.h" #include "xmpp/sasl/plainmessage.h" +#include "qttestutil/qttestutil.h" #include #include using namespace XMPP; -class PlainMessageTest : public QObject -{ - Q_OBJECT - - private slots: - void testConstructor_WithoutAuthzID() { - PLAINMessage message("", QString("user"), "pass"); - QCOMPARE(message.getValue(), QByteArray("\0user\0pass", 10)); - } - - void testConstructor_WithAuthzID() { - PLAINMessage message(QString("authz"), QString("user"), "pass"); - QCOMPARE(message.getValue(), QByteArray("authz\0user\0pass", 15)); - } - - void testConstructor_WithNonASCIICharacters() { - PLAINMessage message(QString("authz") + QChar(0x03A8) /* psi */, QString("user") + QChar(0x03A8) /* psi */, "pass"); - QCOMPARE(message.getValue(), QByteArray("authz\xCE\xA8\0user\xCE\xA8\0pass", 19)); - } +class PlainMessageTest : public QObject { + Q_OBJECT + +private slots: + void testConstructor_WithoutAuthzID() + { + PLAINMessage message("", QString("user"), "pass"); + QCOMPARE(message.getValue(), QByteArray("\0user\0pass", 10)); + } + + void testConstructor_WithAuthzID() + { + PLAINMessage message(QString("authz"), QString("user"), "pass"); + QCOMPARE(message.getValue(), QByteArray("authz\0user\0pass", 15)); + } + + void testConstructor_WithNonASCIICharacters() + { + PLAINMessage message(QString("authz") + QChar(0x03A8) /* psi */, QString("user") + QChar(0x03A8) /* psi */, + "pass"); + QCOMPARE(message.getValue(), QByteArray("authz\xCE\xA8\0user\xCE\xA8\0pass", 19)); + } }; QTTESTUTIL_REGISTER_TEST(PlainMessageTest); diff --git a/src/xmpp/sasl/unittest/scramsha1messagetest.cpp b/src/xmpp/sasl/unittest/scramsha1messagetest.cpp index 0cf9121d..8310742c 100644 --- a/src/xmpp/sasl/unittest/scramsha1messagetest.cpp +++ b/src/xmpp/sasl/unittest/scramsha1messagetest.cpp @@ -16,9 +16,9 @@ * */ +#include "xmpp/sasl/scramsha1message.h" #include "qttestutil/qttestutil.h" #include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" -#include "xmpp/sasl/scramsha1message.h" #include #include @@ -26,28 +26,27 @@ using namespace XMPP; -class SCRAMSHA1MessageTest : public QObject -{ - Q_OBJECT +class SCRAMSHA1MessageTest : public QObject { + Q_OBJECT - private slots: - void testConstructor_WithAuthzid() { - } +private slots: + void testConstructor_WithAuthzid() {} - void testConstructor_WithoutAuthzid() { - SCRAMSHA1Message msg1("", "testuser", QByteArray(0, ' '), IncrementingRandomNumberGenerator(255)); - QByteArray msg1_good("n,,n=testuser,r=AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="); - QVERIFY(msg1.isValid()); - QCOMPARE(msg1.getValue(), msg1_good); + void testConstructor_WithoutAuthzid() + { + SCRAMSHA1Message msg1("", "testuser", QByteArray(0, ' '), IncrementingRandomNumberGenerator(255)); + QByteArray msg1_good("n,,n=testuser,r=AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="); + QVERIFY(msg1.isValid()); + QCOMPARE(msg1.getValue(), msg1_good); - SCRAMSHA1Message msg2("", "username=test,man", QByteArray(0, ' '), IncrementingRandomNumberGenerator(255)); - QByteArray msg2_good("n,,n=username=3Dtest=2Cman,r=AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="); - QVERIFY(msg2.isValid()); - QCOMPARE(msg2.getValue(), msg2_good); - } + SCRAMSHA1Message msg2("", "username=test,man", QByteArray(0, ' '), IncrementingRandomNumberGenerator(255)); + QByteArray msg2_good("n,,n=username=3Dtest=2Cman,r=AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="); + QVERIFY(msg2.isValid()); + QCOMPARE(msg2.getValue(), msg2_good); + } - private: - QCA::Initializer initializer; +private: + QCA::Initializer initializer; }; QTTESTUTIL_REGISTER_TEST(SCRAMSHA1MessageTest); diff --git a/src/xmpp/sasl/unittest/scramsha1responsetest.cpp b/src/xmpp/sasl/unittest/scramsha1responsetest.cpp index 6e0260fb..4d09222b 100644 --- a/src/xmpp/sasl/unittest/scramsha1responsetest.cpp +++ b/src/xmpp/sasl/unittest/scramsha1responsetest.cpp @@ -16,9 +16,9 @@ * */ +#include "xmpp/sasl/scramsha1response.h" #include "qttestutil/qttestutil.h" #include "xmpp/base/unittest/incrementingrandomnumbergenerator.h" -#include "xmpp/sasl/scramsha1response.h" #include "xmpp/sasl/scramsha1signature.h" #include @@ -27,32 +27,30 @@ using namespace XMPP; -class SCRAMSHA1ResponseTest : public QObject -{ - Q_OBJECT - - private slots: - void testConstructor_WithAuthzid() { - - } - - void testConstructor_WithoutAuthzid() { - if (QCA::isSupported("hmac(sha1)")) { - SCRAMSHA1Response resp1("r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096", - "pencil", "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL", "", IncrementingRandomNumberGenerator(255)); - const QCA::SecureArray sig = resp1.getServerSignature(); - QByteArray resp_sig("v=rmF9pqV8S7suAoZWja4dJRkFsKQ="); - SCRAMSHA1Signature sig1(resp_sig, sig); - QByteArray resp1_ok("c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts="); - QCOMPARE(resp1.getValue(), resp1_ok); - QVERIFY(sig1.isValid()); - } else { - QFAIL("hmac(sha1) not supported in QCA."); - } +class SCRAMSHA1ResponseTest : public QObject { + Q_OBJECT + +private slots: + void testConstructor_WithAuthzid() {} + + void testConstructor_WithoutAuthzid() + { + if (QCA::isSupported("hmac(sha1)")) { + SCRAMSHA1Response resp1("r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096", "pencil", + "n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL", "", IncrementingRandomNumberGenerator(255)); + const QCA::SecureArray sig = resp1.getServerSignature(); + QByteArray resp_sig("v=rmF9pqV8S7suAoZWja4dJRkFsKQ="); + SCRAMSHA1Signature sig1(resp_sig, sig); + QByteArray resp1_ok("c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts="); + QCOMPARE(resp1.getValue(), resp1_ok); + QVERIFY(sig1.isValid()); + } else { + QFAIL("hmac(sha1) not supported in QCA."); } + } - private: - QCA::Initializer initializer; +private: + QCA::Initializer initializer; }; QTTESTUTIL_REGISTER_TEST(SCRAMSHA1ResponseTest); diff --git a/src/xmpp/xmpp-core/compressionhandler.cpp b/src/xmpp/xmpp-core/compressionhandler.cpp index 6d051ca8..500fd8ab 100644 --- a/src/xmpp/xmpp-core/compressionhandler.cpp +++ b/src/xmpp/xmpp-core/compressionhandler.cpp @@ -5,8 +5,7 @@ #include #include -CompressionHandler::CompressionHandler() - : errorCode_(0) +CompressionHandler::CompressionHandler() : errorCode_(0) { outgoing_buffer_.open(QIODevice::ReadWrite); compressor_ = new ZLibCompressor(&outgoing_buffer_); @@ -21,10 +20,10 @@ CompressionHandler::~CompressionHandler() delete decompressor_; } -void CompressionHandler::writeIncoming(const QByteArray& a) +void CompressionHandler::writeIncoming(const QByteArray &a) { - //qDebug("CompressionHandler::writeIncoming"); - //qDebug() << QString("Incoming %1 bytes").arg(a.size()); + // qDebug("CompressionHandler::writeIncoming"); + // qDebug() << QString("Incoming %1 bytes").arg(a.size()); errorCode_ = decompressor_->write(a); if (!errorCode_) QTimer::singleShot(0, this, SIGNAL(readyRead())); @@ -32,9 +31,9 @@ void CompressionHandler::writeIncoming(const QByteArray& a) QTimer::singleShot(0, this, SIGNAL(error())); } -void CompressionHandler::write(const QByteArray& a) +void CompressionHandler::write(const QByteArray &a) { - //qDebug() << QString("CompressionHandler::write(%1)").arg(a.size()); + // qDebug() << QString("CompressionHandler::write(%1)").arg(a.size()); errorCode_ = compressor_->write(a); if (!errorCode_) QTimer::singleShot(0, this, SIGNAL(readyReadOutgoing())); @@ -44,17 +43,17 @@ void CompressionHandler::write(const QByteArray& a) QByteArray CompressionHandler::read() { - //qDebug("CompressionHandler::read"); + // qDebug("CompressionHandler::read"); QByteArray b = incoming_buffer_.buffer(); incoming_buffer_.buffer().clear(); incoming_buffer_.reset(); return b; } -QByteArray CompressionHandler::readOutgoing(int* i) +QByteArray CompressionHandler::readOutgoing(int *i) { - //qDebug("CompressionHandler::readOutgoing"); - //qDebug() << QString("Outgoing %1 bytes").arg(outgoing_buffer_.size()); + // qDebug("CompressionHandler::readOutgoing"); + // qDebug() << QString("Outgoing %1 bytes").arg(outgoing_buffer_.size()); QByteArray b = outgoing_buffer_.buffer(); outgoing_buffer_.buffer().clear(); outgoing_buffer_.reset(); @@ -62,7 +61,4 @@ QByteArray CompressionHandler::readOutgoing(int* i) return b; } -int CompressionHandler::errorCode() -{ - return errorCode_; -} +int CompressionHandler::errorCode() { return errorCode_; } diff --git a/src/xmpp/xmpp-core/compressionhandler.h b/src/xmpp/xmpp-core/compressionhandler.h index 13b2808d..740f32ca 100644 --- a/src/xmpp/xmpp-core/compressionhandler.h +++ b/src/xmpp/xmpp-core/compressionhandler.h @@ -7,18 +7,17 @@ class ZLibCompressor; class ZLibDecompressor; -class CompressionHandler : public QObject -{ +class CompressionHandler : public QObject { Q_OBJECT public: CompressionHandler(); ~CompressionHandler(); - void writeIncoming(const QByteArray& a); - void write(const QByteArray& a); + void writeIncoming(const QByteArray &a); + void write(const QByteArray &a); QByteArray read(); - QByteArray readOutgoing(int*); - int errorCode(); + QByteArray readOutgoing(int *); + int errorCode(); signals: void readyRead(); @@ -26,10 +25,10 @@ class CompressionHandler : public QObject void error(); private: - ZLibCompressor* compressor_; - ZLibDecompressor* decompressor_; - QBuffer outgoing_buffer_, incoming_buffer_; - int errorCode_; + ZLibCompressor * compressor_; + ZLibDecompressor *decompressor_; + QBuffer outgoing_buffer_, incoming_buffer_; + int errorCode_; }; #endif // COMPRESSIONHANDLER_H diff --git a/src/xmpp/xmpp-core/connector.cpp b/src/xmpp/xmpp-core/connector.cpp index b8617787..f10f75c7 100644 --- a/src/xmpp/xmpp-core/connector.cpp +++ b/src/xmpp/xmpp-core/connector.cpp @@ -42,131 +42,89 @@ //#define XMPP_DEBUG #ifdef XMPP_DEBUG -# define XDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") +#define XDEBUG (qDebug() << this << "#" << __FUNCTION__ << ":") #endif using namespace XMPP; -static const int XMPP_DEFAULT_PORT = 5222; -static const int XMPP_LEGACY_PORT = 5223; -static const char* XMPP_CLIENT_SRV = "xmpp-client"; -static const char* XMPP_CLIENT_TRANSPORT = "tcp"; +static const int XMPP_DEFAULT_PORT = 5222; +static const int XMPP_LEGACY_PORT = 5223; +static const char *XMPP_CLIENT_SRV = "xmpp-client"; +static const char *XMPP_CLIENT_TRANSPORT = "tcp"; //---------------------------------------------------------------------------- // Connector //---------------------------------------------------------------------------- -Connector::Connector(QObject *parent) -:QObject(parent) +Connector::Connector(QObject *parent) : QObject(parent) { setUseSSL(false); setPeerAddressNone(); } -Connector::~Connector() -{ -} +Connector::~Connector() {} -bool Connector::useSSL() const -{ - return ssl; -} +bool Connector::useSSL() const { return ssl; } -bool Connector::havePeerAddress() const -{ - return haveaddr; -} +bool Connector::havePeerAddress() const { return haveaddr; } -QHostAddress Connector::peerAddress() const -{ - return addr; -} +QHostAddress Connector::peerAddress() const { return addr; } -quint16 Connector::peerPort() const -{ - return port; -} +quint16 Connector::peerPort() const { return port; } -void Connector::setUseSSL(bool b) -{ - ssl = b; -} +void Connector::setUseSSL(bool b) { ssl = b; } void Connector::setPeerAddressNone() { haveaddr = false; - addr = QHostAddress(); - port = 0; + addr = QHostAddress(); + port = 0; } void Connector::setPeerAddress(const QHostAddress &_addr, quint16 _port) { haveaddr = true; - addr = _addr; - port = _port; + addr = _addr; + port = _port; } -QString Connector::host() const -{ - return QString(); -} +QString Connector::host() const { return QString(); } //---------------------------------------------------------------------------- // AdvancedConnector::Proxy //---------------------------------------------------------------------------- -int AdvancedConnector::Proxy::type() const -{ - return t; -} +int AdvancedConnector::Proxy::type() const { return t; } -QString AdvancedConnector::Proxy::host() const -{ - return v_host; -} +QString AdvancedConnector::Proxy::host() const { return v_host; } -quint16 AdvancedConnector::Proxy::port() const -{ - return v_port; -} +quint16 AdvancedConnector::Proxy::port() const { return v_port; } -QUrl AdvancedConnector::Proxy::url() const -{ - return v_url; -} +QUrl AdvancedConnector::Proxy::url() const { return v_url; } -QString AdvancedConnector::Proxy::user() const -{ - return v_user; -} +QString AdvancedConnector::Proxy::user() const { return v_user; } -QString AdvancedConnector::Proxy::pass() const -{ - return v_pass; -} +QString AdvancedConnector::Proxy::pass() const { return v_pass; } -int AdvancedConnector::Proxy::pollInterval() const -{ - return v_poll; -} +int AdvancedConnector::Proxy::pollInterval() const { return v_poll; } void AdvancedConnector::Proxy::setHttpConnect(const QString &host, quint16 port) { - t = HttpConnect; + t = HttpConnect; v_host = host; v_port = port; } void AdvancedConnector::Proxy::setHttpPoll(const QString &host, quint16 port, const QUrl &url) { - t = HttpPoll; + t = HttpPoll; v_host = host; v_port = port; - v_url = url; + v_url = url; } void AdvancedConnector::Proxy::setSocks(const QString &host, quint16 port) { - t = Socks; + t = Socks; v_host = host; v_port = port; } @@ -177,10 +135,7 @@ void AdvancedConnector::Proxy::setUserPass(const QString &user, const QString &p v_pass = pass; } -void AdvancedConnector::Proxy::setPollInterval(int secs) -{ - v_poll = secs; -} +void AdvancedConnector::Proxy::setPollInterval(int secs) { v_poll = secs; } //---------------------------------------------------------------------------- // AdvancedConnector @@ -188,29 +143,27 @@ void AdvancedConnector::Proxy::setPollInterval(int secs) typedef enum { Idle, Connecting, Connected } Mode; typedef enum { Force, Probe, Never } LegacySSL; -class AdvancedConnector::Private -{ +class AdvancedConnector::Private { public: ByteStream *bs; //!< Socket to use /* configuration values / "options" */ - QString opt_host; //!< explicit host from config - quint16 opt_port; //!< explicit port from config - LegacySSL opt_ssl; //!< Whether to use legacy SSL support - Proxy proxy; //!< Proxy configuration + QString opt_host; //!< explicit host from config + quint16 opt_port; //!< explicit port from config + LegacySSL opt_ssl; //!< Whether to use legacy SSL support + Proxy proxy; //!< Proxy configuration /* State tracking values */ - Mode mode; //!< Idle, Connecting, Connected - QString host; //!< Host we currently try to connect to, set from connectToServer() - int port; //!< Port we currently try to connect to, set from connectToServer() and bs_error() - int errorCode; //!< Current error, if any + Mode mode; //!< Idle, Connecting, Connected + QString host; //!< Host we currently try to connect to, set from connectToServer() + int port; //!< Port we currently try to connect to, set from connectToServer() and bs_error() + int errorCode; //!< Current error, if any }; -AdvancedConnector::AdvancedConnector(QObject *parent) -:Connector(parent) +AdvancedConnector::AdvancedConnector(QObject *parent) : Connector(parent) { - d = new Private; - d->bs = nullptr; + d = new Private; + d->bs = nullptr; d->opt_ssl = Never; cleanup(); d->errorCode = 0; @@ -236,7 +189,7 @@ void AdvancedConnector::cleanup() void AdvancedConnector::setProxy(const Proxy &proxy) { - if(d->mode != Idle) + if (d->mode != Idle) return; d->proxy = proxy; } @@ -247,11 +200,11 @@ void AdvancedConnector::setOptHostPort(const QString &_host, quint16 _port) XDEBUG << "h:" << _host << "p:" << _port; #endif - if(d->mode != Idle) + if (d->mode != Idle) return; // empty host means disable explicit host support - if(_host.isEmpty()) { + if (_host.isEmpty()) { d->opt_host.clear(); return; } @@ -265,7 +218,7 @@ void AdvancedConnector::setOptProbe(bool b) XDEBUG << "b:" << b; #endif - if(d->mode != Idle) + if (d->mode != Idle) return; d->opt_ssl = (b ? Probe : Never); } @@ -276,7 +229,7 @@ void AdvancedConnector::setOptSSL(bool b) XDEBUG << "b:" << b; #endif - if(d->mode != Idle) + if (d->mode != Idle) return; d->opt_ssl = (b ? Force : Never); } @@ -287,13 +240,13 @@ void AdvancedConnector::connectToServer(const QString &server) XDEBUG << "s:" << server; #endif - if(d->mode != Idle) + if (d->mode != Idle) return; - if(server.isEmpty()) + if (server.isEmpty()) return; d->errorCode = 0; - d->mode = Connecting; + d->mode = Connecting; // Encode the servername d->host = QUrl::toAce(server); @@ -310,61 +263,58 @@ void AdvancedConnector::connectToServer(const QString &server) d->opt_ssl = Never; // probe is possible only with direct connect } - if(d->proxy.type() == Proxy::HttpPoll) { + if (d->proxy.type() == Proxy::HttpPoll) { HttpPoll *s = new HttpPoll; - d->bs = s; + d->bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(syncStarted()), SLOT(http_syncStarted())); connect(s, SIGNAL(syncFinished()), SLOT(http_syncFinished())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!d->proxy.user().isEmpty()) + if (!d->proxy.user().isEmpty()) s->setAuth(d->proxy.user(), d->proxy.pass()); s->setPollInterval(d->proxy.pollInterval()); - if(d->proxy.host().isEmpty()) + if (d->proxy.host().isEmpty()) s->connectToUrl(d->proxy.url()); else s->connectToHost(d->proxy.host(), d->proxy.port(), d->proxy.url()); - } - else if (d->proxy.type() == Proxy::HttpConnect) { + } else if (d->proxy.type() == Proxy::HttpConnect) { HttpConnect *s = new HttpConnect; - d->bs = s; + d->bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!d->opt_host.isEmpty()) { + if (!d->opt_host.isEmpty()) { d->host = d->opt_host; d->port = d->opt_port; } - if(!d->proxy.user().isEmpty()) + if (!d->proxy.user().isEmpty()) s->setAuth(d->proxy.user(), d->proxy.pass()); s->connectToHost(d->proxy.host(), d->proxy.port(), d->host, d->port); - } - else if (d->proxy.type() == Proxy::Socks) { + } else if (d->proxy.type() == Proxy::Socks) { SocksClient *s = new SocksClient; - d->bs = s; + d->bs = s; connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!d->opt_host.isEmpty()) { + if (!d->opt_host.isEmpty()) { d->host = d->opt_host; d->port = d->opt_port; } - if(!d->proxy.user().isEmpty()) + if (!d->proxy.user().isEmpty()) s->setAuth(d->proxy.user(), d->proxy.pass()); s->connectToHost(d->proxy.host(), d->proxy.port(), d->host, d->port); - } - else { + } else { BSocket *s = new BSocket; - d->bs = s; + d->bs = s; #ifdef XMPP_DEBUG XDEBUG << "Adding socket:" << s; #endif @@ -372,7 +322,7 @@ void AdvancedConnector::connectToServer(const QString &server) connect(s, SIGNAL(connected()), SLOT(bs_connected())); connect(s, SIGNAL(error(int)), SLOT(bs_error(int))); - if(!d->opt_host.isEmpty()) { /* if custom host:port */ + if (!d->opt_host.isEmpty()) { /* if custom host:port */ d->host = d->opt_host; d->port = d->opt_port; s->connectToHost(d->host, d->port); @@ -387,46 +337,39 @@ void AdvancedConnector::connectToServer(const QString &server) void AdvancedConnector::changePollInterval(int secs) { - if(d->bs && (d->bs->inherits("XMPP::HttpPoll") || d->bs->inherits("HttpPoll"))) { - HttpPoll *s = static_cast(d->bs); + if (d->bs && (d->bs->inherits("XMPP::HttpPoll") || d->bs->inherits("HttpPoll"))) { + HttpPoll *s = static_cast(d->bs); s->setPollInterval(secs); } } ByteStream *AdvancedConnector::stream() const { - if(d->mode == Connected) + if (d->mode == Connected) return d->bs; else return nullptr; } -void AdvancedConnector::done() -{ - cleanup(); -} +void AdvancedConnector::done() { cleanup(); } -int AdvancedConnector::errorCode() const -{ - return d->errorCode; -} +int AdvancedConnector::errorCode() const { return d->errorCode; } void AdvancedConnector::bs_connected() { #ifdef XMPP_DEBUG XDEBUG; #endif - if(d->proxy.type() == Proxy::None) { - QHostAddress h = (static_cast(d->bs))->peerAddress(); - int p = (static_cast(d->bs))->peerPort(); + if (d->proxy.type() == Proxy::None) { + QHostAddress h = (static_cast(d->bs))->peerAddress(); + int p = (static_cast(d->bs))->peerPort(); setPeerAddress(h, p); } // We won't use ssl with HttpPoll since it has ow tls handler enabled for https. // The only variant for ssl is legacy port in probing or forced mde. - if(d->proxy.type() != Proxy::HttpPoll && (d->opt_ssl == Force || ( - d->opt_ssl == Probe && peerPort() == XMPP_LEGACY_PORT))) - { + if (d->proxy.type() != Proxy::HttpPoll + && (d->opt_ssl == Force || (d->opt_ssl == Probe && peerPort() == XMPP_LEGACY_PORT))) { // in case of Probe it's ok to check actual peer "port" since we are sure Proxy=None setUseSSL(true); } @@ -441,67 +384,64 @@ void AdvancedConnector::bs_error(int x) XDEBUG << "e:" << x; #endif - if(d->mode == Connected) { + if (d->mode == Connected) { d->errorCode = ErrStream; emit error(); return; } bool proxyError = false; - int err = ErrConnectionRefused; - int t = d->proxy.type(); + int err = ErrConnectionRefused; + int t = d->proxy.type(); #ifdef XMPP_DEBUG qDebug("bse1"); #endif // figure out the error - if(t == Proxy::None) { - if(x == BSocket::ErrHostNotFound) + if (t == Proxy::None) { + if (x == BSocket::ErrHostNotFound) err = ErrHostNotFound; else err = ErrConnectionRefused; - } - else if(t == Proxy::HttpConnect) { - if(x == HttpConnect::ErrConnectionRefused) + } else if (t == Proxy::HttpConnect) { + if (x == HttpConnect::ErrConnectionRefused) err = ErrConnectionRefused; - else if(x == HttpConnect::ErrHostNotFound) + else if (x == HttpConnect::ErrHostNotFound) err = ErrHostNotFound; else { proxyError = true; - if(x == HttpConnect::ErrProxyAuth) + if (x == HttpConnect::ErrProxyAuth) err = ErrProxyAuth; - else if(x == HttpConnect::ErrProxyNeg) + else if (x == HttpConnect::ErrProxyNeg) err = ErrProxyNeg; else err = ErrProxyConnect; } - } - else if(t == Proxy::HttpPoll) { - if(x == HttpPoll::ErrConnectionRefused) + } else if (t == Proxy::HttpPoll) { + if (x == HttpPoll::ErrConnectionRefused) err = ErrConnectionRefused; - else if(x == HttpPoll::ErrHostNotFound) + else if (x == HttpPoll::ErrHostNotFound) err = ErrHostNotFound; else { proxyError = true; - if(x == HttpPoll::ErrProxyAuth) + if (x == HttpPoll::ErrProxyAuth) err = ErrProxyAuth; - else if(x == HttpPoll::ErrProxyNeg) + else if (x == HttpPoll::ErrProxyNeg) err = ErrProxyNeg; else err = ErrProxyConnect; } - } - else if(t == Proxy::Socks) { - if(x == SocksClient::ErrConnectionRefused) + } else if (t == Proxy::Socks) { + if (x == SocksClient::ErrConnectionRefused) err = ErrConnectionRefused; - else if(x == SocksClient::ErrHostNotFound) + else if (x == SocksClient::ErrHostNotFound) err = ErrHostNotFound; else { proxyError = true; - if(x == SocksClient::ErrProxyAuth) + if (x == SocksClient::ErrProxyAuth) err = ErrProxyAuth; - else if(x == SocksClient::ErrProxyNeg) + else if (x == SocksClient::ErrProxyNeg) err = ErrProxyNeg; else err = ErrProxyConnect; @@ -509,7 +449,7 @@ void AdvancedConnector::bs_error(int x) } // no-multi or proxy error means we quit - if(proxyError) { + if (proxyError) { cleanup(); d->errorCode = err; emit error(); @@ -520,12 +460,12 @@ void AdvancedConnector::bs_error(int x) if we shall probe the ssl legacy port, and we just did that (port=legacy), then try to connect to the normal port instead */ - if(d->opt_ssl == Probe && d->port == XMPP_LEGACY_PORT) { + if (d->opt_ssl == Probe && d->port == XMPP_LEGACY_PORT) { #ifdef XMPP_DEBUG qDebug("bse1.2"); #endif - BSocket *s = static_cast(d->bs); - d->port = XMPP_DEFAULT_PORT; + BSocket *s = static_cast(d->bs); + d->port = XMPP_DEFAULT_PORT; // at this moment we already tried everything from srv. so just try the host itself s->connectToHost(d->host, d->port); } @@ -540,22 +480,13 @@ void AdvancedConnector::bs_error(int x) } } -void AdvancedConnector::http_syncStarted() -{ - httpSyncStarted(); -} +void AdvancedConnector::http_syncStarted() { httpSyncStarted(); } -void AdvancedConnector::http_syncFinished() -{ - httpSyncFinished(); -} +void AdvancedConnector::http_syncFinished() { httpSyncFinished(); } void AdvancedConnector::t_timeout() { - //bs_error(-1); + // bs_error(-1); } -QString AdvancedConnector::host() const -{ - return d->host; -} +QString AdvancedConnector::host() const { return d->host; } diff --git a/src/xmpp/xmpp-core/parser.cpp b/src/xmpp/xmpp-core/parser.cpp index 282839db..37bd9fdc 100644 --- a/src/xmpp/xmpp-core/parser.cpp +++ b/src/xmpp/xmpp-core/parser.cpp @@ -59,8 +59,7 @@ static bool qt_bug_have; //---------------------------------------------------------------------------- // StreamInput //---------------------------------------------------------------------------- -class StreamInput : public QXmlInputSource -{ +class StreamInput : public QXmlInputSource { public: StreamInput() { @@ -68,35 +67,26 @@ class StreamInput : public QXmlInputSource reset(); } - ~StreamInput() - { - delete dec; - } + ~StreamInput() { delete dec; } void reset() { delete dec; dec = nullptr; in.resize(0); - out = ""; - at = 0; - paused = false; + out = ""; + at = 0; + paused = false; mightChangeEncoding = true; - checkBad = true; - last = QChar(); - v_encoding = ""; + checkBad = true; + last = QChar(); + v_encoding = ""; resetLastData(); } - void resetLastData() - { - last_string = ""; - } + void resetLastData() { last_string = ""; } - QString lastString() const - { - return last_string; - } + QString lastString() const { return last_string; } void appendData(const QByteArray &a) { @@ -106,14 +96,11 @@ class StreamInput : public QXmlInputSource processBuf(); } - QChar lastRead() - { - return last; - } + QChar lastRead() { return last; } QChar next() { - if(paused) + if (paused) return EndOfData; else return readNext(); @@ -121,32 +108,30 @@ class StreamInput : public QXmlInputSource // NOTE: setting 'peek' to true allows the same char to be read again, // however this still advances the internal byte processing. - QChar readNext(bool peek=false) + QChar readNext(bool peek = false) { QChar c; - if(mightChangeEncoding) + if (mightChangeEncoding) c = EndOfData; else { - if(out.isEmpty()) { + if (out.isEmpty()) { QString s; - if(!tryExtractPart(&s)) + if (!tryExtractPart(&s)) c = EndOfData; else { out = s; - c = out[0]; + c = out[0]; } - } - else + } else c = out[0]; - if(!peek) + if (!peek) out.remove(0, 1); } - if(c == EndOfData) { + if (c == EndOfData) { #ifdef XMPP_PARSER_DEBUG printf("next() = EOD\n"); #endif - } - else { + } else { #ifdef XMPP_PARSER_DEBUG printf("next() = [%c]\n", c.latin1()); #endif @@ -164,87 +149,78 @@ class StreamInput : public QXmlInputSource return a; } - void pause(bool b) - { - paused = b; - } + void pause(bool b) { paused = b; } - bool isPaused() - { - return paused; - } + bool isPaused() { return paused; } - QString encoding() const - { - return v_encoding; - } + QString encoding() const { return v_encoding; } private: QTextDecoder *dec; - QByteArray in; - QString out; - int at; - bool paused; - bool mightChangeEncoding; - QChar last; - QString v_encoding; - QString last_string; - bool checkBad; + QByteArray in; + QString out; + int at; + bool paused; + bool mightChangeEncoding; + QChar last; + QString v_encoding; + QString last_string; + bool checkBad; void processBuf() { #ifdef XMPP_PARSER_DEBUG printf("processing. size=%d, at=%d\n", in.size(), at); #endif - if(!dec) { + if (!dec) { QTextCodec *codec = nullptr; - uchar *p = (uchar *)in.data() + at; - int size = in.size() - at; + uchar * p = (uchar *)in.data() + at; + int size = in.size() - at; // do we have enough information to determine the encoding? - if(size == 0) + if (size == 0) return; bool utf16 = false; - if(p[0] == 0xfe || p[0] == 0xff) { + if (p[0] == 0xfe || p[0] == 0xff) { // probably going to be a UTF-16 byte order mark - if(size < 2) + if (size < 2) return; - if((p[0] == 0xfe && p[1] == 0xff) || (p[0] == 0xff && p[1] == 0xfe)) { + if ((p[0] == 0xfe && p[1] == 0xff) || (p[0] == 0xff && p[1] == 0xfe)) { // ok it is UTF-16 utf16 = true; } } - if(utf16) + if (utf16) codec = QTextCodec::codecForMib(1000); // UTF-16 else codec = QTextCodec::codecForMib(106); // UTF-8 v_encoding = codec->name(); - dec = codec->makeDecoder(); + dec = codec->makeDecoder(); // for utf16, put in the byte order mark - if(utf16) { + if (utf16) { out += dec->toUnicode((const char *)p, 2); at += 2; } } - if(mightChangeEncoding) { - while(1) { + if (mightChangeEncoding) { + while (1) { int n = out.indexOf('<'); - if(n != -1) { + if (n != -1) { // we need a closing bracket int n2 = out.indexOf('>', n); - if(n2 != -1) { + if (n2 != -1) { ++n2; - QString h = out.mid(n, n2-n); - QString enc = processXmlHeader(h); + QString h = out.mid(n, n2 - n); + QString enc = processXmlHeader(h); QTextCodec *codec = nullptr; - if(!enc.isEmpty()) + if (!enc.isEmpty()) codec = QTextCodec::codecForName(enc.toLatin1()); // changing codecs - if(codec) { + if (codec) { v_encoding = codec->name(); delete dec; dec = codec->makeDecoder(); @@ -257,9 +233,9 @@ class StreamInput : public QXmlInputSource } } QString s; - if(!tryExtractPart(&s)) + if (!tryExtractPart(&s)) break; - if(checkBad && checkForBadChars(s)) { + if (checkBad && checkForBadChars(s)) { // go to the parser mightChangeEncoding = false; out.truncate(0); @@ -274,56 +250,55 @@ class StreamInput : public QXmlInputSource QString processXmlHeader(const QString &h) { - if(h.left(5) != ""); + int endPos = h.indexOf(">"); int startPos = h.indexOf("encoding"); - if(startPos < endPos && startPos != -1) { + if (startPos < endPos && startPos != -1) { QString encoding; do { startPos++; - if(startPos > endPos) { + if (startPos > endPos) { return ""; } - } while(h[startPos] != '"' && h[startPos] != '\''); + } while (h[startPos] != '"' && h[startPos] != '\''); startPos++; - while(h[startPos] != '"' && h[startPos] != '\'') { + while (h[startPos] != '"' && h[startPos] != '\'') { encoding += h[startPos]; startPos++; - if(startPos > endPos) { + if (startPos > endPos) { return ""; } } return encoding; - } - else + } else return ""; } bool tryExtractPart(QString *s) { int size = in.size() - at; - if(size == 0) + if (size == 0) return false; - uchar *p = (uchar *)in.data() + at; + uchar * p = (uchar *)in.data() + at; QString nextChars; - while(1) { + while (1) { nextChars = dec->toUnicode((const char *)p, 1); ++p; ++at; - if(!nextChars.isEmpty()) + if (!nextChars.isEmpty()) break; - if(at == (int)in.size()) + if (at == (int)in.size()) return false; } last_string += nextChars; *s = nextChars; // free processed data? - if(at >= 1024) { - char *p = in.data(); - int size = in.size() - at; + if (at >= 1024) { + char *p = in.data(); + int size = in.size() - at; memmove(p, p + at, size); in.resize(size); at = 0; @@ -335,12 +310,12 @@ class StreamInput : public QXmlInputSource bool checkForBadChars(const QString &s) { int len = s.indexOf('<'); - if(len == -1) + if (len == -1) len = s.length(); else checkBad = false; - for(int n = 0; n < len; ++n) { - if(!s.at(n).isSpace()) + for (int n = 0; n < len; ++n) { + if (!s.at(n).isSpace()) return true; } return false; @@ -351,371 +326,324 @@ class StreamInput : public QXmlInputSource // ParserHandler //---------------------------------------------------------------------------- namespace XMPP { - class ParserHandler : public QXmlDefaultHandler +class ParserHandler : public QXmlDefaultHandler { +public: + explicit ParserHandler(StreamInput *_in, QDomDocument *_doc) : in(_in), doc(_doc) {} + + ~ParserHandler() { - public: - explicit ParserHandler(StreamInput *_in, QDomDocument *_doc) - : in(_in) - , doc(_doc) - { + while (!eventList.isEmpty()) { + delete eventList.takeFirst(); } + } - ~ParserHandler() - { - while (!eventList.isEmpty()) { - delete eventList.takeFirst(); - } - } + bool startDocument() + { + depth = 0; + return true; + } - bool startDocument() - { - depth = 0; - return true; - } + bool endDocument() { return true; } - bool endDocument() - { - return true; + bool startPrefixMapping(const QString &prefix, const QString &uri) + { + if (depth == 0) { + nsnames += prefix; + nsvalues += uri; } + return true; + } - bool startPrefixMapping(const QString &prefix, const QString &uri) - { - if(depth == 0) { - nsnames += prefix; - nsvalues += uri; + bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, + const QXmlAttributes &atts) + { + if (depth == 0) { + Parser::Event *e = new Parser::Event; + QXmlAttributes a; + for (int n = 0; n < atts.length(); ++n) { + QString uri = atts.uri(n); + QString ln = atts.localName(n); + if (a.index(uri, ln) == -1) + a.append(atts.qName(n), uri, ln, atts.value(n)); } - return true; - } - - bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts) - { - if(depth == 0) { - Parser::Event *e = new Parser::Event; - QXmlAttributes a; - for(int n = 0; n < atts.length(); ++n) { - QString uri = atts.uri(n); - QString ln = atts.localName(n); - if(a.index(uri, ln) == -1) - a.append(atts.qName(n), uri, ln, atts.value(n)); - } - e->setDocumentOpen(namespaceURI, localName, qName, a, nsnames, nsvalues); - nsnames.clear(); - nsvalues.clear(); - e->setActualString(in->lastString()); + e->setDocumentOpen(namespaceURI, localName, qName, a, nsnames, nsvalues); + nsnames.clear(); + nsvalues.clear(); + e->setActualString(in->lastString()); - in->resetLastData(); - eventList.append(e); - in->pause(true); + in->resetLastData(); + eventList.append(e); + in->pause(true); + } else { + QDomElement e = doc->createElementNS(namespaceURI, qName); + for (int n = 0; n < atts.length(); ++n) { + QString uri = atts.uri(n); + QString ln = atts.localName(n); + bool have; + if (!uri.isEmpty()) { + have = e.hasAttributeNS(uri, ln); + if (qt_bug_have) + have = !have; + } else + have = e.hasAttribute(ln); + if (!have) + e.setAttributeNS(uri, atts.qName(n), atts.value(n)); } - else { - QDomElement e = doc->createElementNS(namespaceURI, qName); - for(int n = 0; n < atts.length(); ++n) { - QString uri = atts.uri(n); - QString ln = atts.localName(n); - bool have; - if(!uri.isEmpty()) { - have = e.hasAttributeNS(uri, ln); - if(qt_bug_have) - have = !have; - } - else - have = e.hasAttribute(ln); - if(!have) - e.setAttributeNS(uri, atts.qName(n), atts.value(n)); - } - if(depth == 1) { - elem = e; - current = e; - } - else { - current.appendChild(e); - current = e; - } + if (depth == 1) { + elem = e; + current = e; + } else { + current.appendChild(e); + current = e; } - ++depth; - return true; } + ++depth; + return true; + } - bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName) - { - --depth; - if(depth == 0) { + bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName) + { + --depth; + if (depth == 0) { + Parser::Event *e = new Parser::Event; + e->setDocumentClose(namespaceURI, localName, qName); + e->setActualString(in->lastString()); + in->resetLastData(); + eventList.append(e); + in->pause(true); + } else { + // done with a depth 1 element? + if (depth == 1) { Parser::Event *e = new Parser::Event; - e->setDocumentClose(namespaceURI, localName, qName); + e->setElement(elem); e->setActualString(in->lastString()); in->resetLastData(); eventList.append(e); in->pause(true); - } - else { - // done with a depth 1 element? - if(depth == 1) { - Parser::Event *e = new Parser::Event; - e->setElement(elem); - e->setActualString(in->lastString()); - in->resetLastData(); - eventList.append(e); - in->pause(true); - - elem = QDomElement(); - current = QDomElement(); - } - else - current = current.parentNode().toElement(); - } - - if(in->lastRead() == '/') - checkNeedMore(); - return true; + elem = QDomElement(); + current = QDomElement(); + } else + current = current.parentNode().toElement(); } - bool characters(const QString &str) - { - if(depth >= 1) { - QString content = str; - if(content.isEmpty()) - return true; + if (in->lastRead() == '/') + checkNeedMore(); - if(!current.isNull()) { - QDomText text = doc->createTextNode(content); - current.appendChild(text); - } + return true; + } + + bool characters(const QString &str) + { + if (depth >= 1) { + QString content = str; + if (content.isEmpty()) + return true; + + if (!current.isNull()) { + QDomText text = doc->createTextNode(content); + current.appendChild(text); } - return true; } + return true; + } - /*bool processingInstruction(const QString &target, const QString &data) - { - printf("Processing: [%s], [%s]\n", target.latin1(), data.latin1()); - in->resetLastData(); - return true; - }*/ - - void checkNeedMore() - { - // Here we will work around QXmlSimpleReader strangeness and self-closing tags. - // The problem is that endElement() is called when the '/' is read, not when - // the final '>' is read. This is a potential problem when obtaining unprocessed - // bytes from StreamInput after this event, as the '>' character will end up - // in the unprocessed chunk. To work around this, we need to advance StreamInput's - // internal byte processing, but not the xml character data. This way, the '>' - // will get processed and will no longer be in the unprocessed return, but - // QXmlSimpleReader can still read it. To do this, we call StreamInput::readNext - // with 'peek' mode. - QChar c = in->readNext(true); // peek - if(c == QXmlInputSource::EndOfData) { - needMore = true; - } - else { - // We'll assume the next char is a '>'. If it isn't, then - // QXmlSimpleReader will deal with that problem on the next - // parse. We don't need to take any action here. - needMore = false; - - // there should have been a pending event - if (!eventList.isEmpty()) { - Parser::Event *e = eventList.first(); - e->setActualString(e->actualString() + '>'); - in->resetLastData(); - } + /*bool processingInstruction(const QString &target, const QString &data) + { + printf("Processing: [%s], [%s]\n", target.latin1(), data.latin1()); + in->resetLastData(); + return true; + }*/ + + void checkNeedMore() + { + // Here we will work around QXmlSimpleReader strangeness and self-closing tags. + // The problem is that endElement() is called when the '/' is read, not when + // the final '>' is read. This is a potential problem when obtaining unprocessed + // bytes from StreamInput after this event, as the '>' character will end up + // in the unprocessed chunk. To work around this, we need to advance StreamInput's + // internal byte processing, but not the xml character data. This way, the '>' + // will get processed and will no longer be in the unprocessed return, but + // QXmlSimpleReader can still read it. To do this, we call StreamInput::readNext + // with 'peek' mode. + QChar c = in->readNext(true); // peek + if (c == QXmlInputSource::EndOfData) { + needMore = true; + } else { + // We'll assume the next char is a '>'. If it isn't, then + // QXmlSimpleReader will deal with that problem on the next + // parse. We don't need to take any action here. + needMore = false; + + // there should have been a pending event + if (!eventList.isEmpty()) { + Parser::Event *e = eventList.first(); + e->setActualString(e->actualString() + '>'); + in->resetLastData(); } } + } - Parser::Event *takeEvent() - { - if(needMore) - return nullptr; - if(eventList.isEmpty()) - return nullptr; + Parser::Event *takeEvent() + { + if (needMore) + return nullptr; + if (eventList.isEmpty()) + return nullptr; - Parser::Event *e = eventList.takeFirst(); - in->pause(false); - return e; - } + Parser::Event *e = eventList.takeFirst(); + in->pause(false); + return e; + } - StreamInput *in; - QDomDocument *doc; - int depth = 1; - QStringList nsnames, nsvalues; - QDomElement elem, current; - QList eventList; - bool needMore = false; - }; + StreamInput * in; + QDomDocument * doc; + int depth = 1; + QStringList nsnames, nsvalues; + QDomElement elem, current; + QList eventList; + bool needMore = false; +}; }; // namespace XMPP //---------------------------------------------------------------------------- // Event //---------------------------------------------------------------------------- -class Parser::Event::Private -{ +class Parser::Event::Private { public: - int type; - QString ns, ln, qn; + int type; + QString ns, ln, qn; QXmlAttributes a; - QDomElement e; - QString str; - QStringList nsnames, nsvalues; + QDomElement e; + QString str; + QStringList nsnames, nsvalues; }; -Parser::Event::Event() -{ - d = nullptr; -} +Parser::Event::Event() { d = nullptr; } Parser::Event::Event(const Event &from) { - d = nullptr; + d = nullptr; *this = from; } -Parser::Event & Parser::Event::operator=(const Event &from) +Parser::Event &Parser::Event::operator=(const Event &from) { - if(&from == this) + if (&from == this) return *this; delete d; d = nullptr; - if(from.d) + if (from.d) d = new Private(*from.d); return *this; } -Parser::Event::~Event() -{ - delete d; -} +Parser::Event::~Event() { delete d; } -bool Parser::Event::isNull() const -{ - return (d ? false: true); -} +bool Parser::Event::isNull() const { return (d ? false : true); } int Parser::Event::type() const { - if(isNull()) + if (isNull()) return -1; return d->type; } QString Parser::Event::nsprefix(const QString &s) const { - QStringList::ConstIterator it = d->nsnames.constBegin(); + QStringList::ConstIterator it = d->nsnames.constBegin(); QStringList::ConstIterator it2 = d->nsvalues.constBegin(); - for(; it != d->nsnames.constEnd(); ++it) { - if((*it) == s) + for (; it != d->nsnames.constEnd(); ++it) { + if ((*it) == s) return (*it2); ++it2; } return QString(); } -QString Parser::Event::namespaceURI() const -{ - return d->ns; -} +QString Parser::Event::namespaceURI() const { return d->ns; } -QString Parser::Event::localName() const -{ - return d->ln; -} +QString Parser::Event::localName() const { return d->ln; } -QString Parser::Event::qName() const -{ - return d->qn; -} +QString Parser::Event::qName() const { return d->qn; } -QXmlAttributes Parser::Event::atts() const -{ - return d->a; -} +QXmlAttributes Parser::Event::atts() const { return d->a; } -QString Parser::Event::actualString() const -{ - return d->str; -} +QString Parser::Event::actualString() const { return d->str; } -QDomElement Parser::Event::element() const -{ - return d->e; -} +QDomElement Parser::Event::element() const { return d->e; } -void Parser::Event::setDocumentOpen(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts, const QStringList &nsnames, const QStringList &nsvalues) +void Parser::Event::setDocumentOpen(const QString &namespaceURI, const QString &localName, const QString &qName, + const QXmlAttributes &atts, const QStringList &nsnames, const QStringList &nsvalues) { - if(!d) + if (!d) d = new Private; - d->type = DocumentOpen; - d->ns = namespaceURI; - d->ln = localName; - d->qn = qName; - d->a = atts; - d->nsnames = nsnames; + d->type = DocumentOpen; + d->ns = namespaceURI; + d->ln = localName; + d->qn = qName; + d->a = atts; + d->nsnames = nsnames; d->nsvalues = nsvalues; } void Parser::Event::setDocumentClose(const QString &namespaceURI, const QString &localName, const QString &qName) { - if(!d) + if (!d) d = new Private; d->type = DocumentClose; - d->ns = namespaceURI; - d->ln = localName; - d->qn = qName; + d->ns = namespaceURI; + d->ln = localName; + d->qn = qName; } void Parser::Event::setElement(const QDomElement &elem) { - if(!d) + if (!d) d = new Private; d->type = Element; - d->e = elem; + d->e = elem; } void Parser::Event::setError() { - if(!d) + if (!d) d = new Private; d->type = Error; } -void Parser::Event::setActualString(const QString &str) -{ - d->str = str; -} +void Parser::Event::setActualString(const QString &str) { d->str = str; } //---------------------------------------------------------------------------- // Parser //---------------------------------------------------------------------------- -class Parser::Private -{ +class Parser::Private { public: Private() { - doc = nullptr; - in = 0; + doc = nullptr; + in = 0; handler = nullptr; - reader = 0; + reader = 0; reset(); } - ~Private() - { - reset(false); - } + ~Private() { reset(false); } - void reset(bool create=true) + void reset(bool create = true) { delete reader; delete handler; delete in; delete doc; - if(create) { - doc = new QDomDocument; - in = new StreamInput; + if (create) { + doc = new QDomDocument; + in = new StreamInput; handler = new ParserHandler(in, doc); - reader = new QXmlSimpleReader; + reader = new QXmlSimpleReader; reader->setContentHandler(handler); // initialize the reader @@ -723,16 +651,16 @@ class Parser::Private reader->parse(in, true); in->pause(false); } else { - reader = nullptr; + reader = nullptr; handler = nullptr; - in = nullptr; - doc = 0; + in = nullptr; + doc = 0; } } - QDomDocument *doc; - StreamInput *in; - ParserHandler *handler; + QDomDocument * doc; + StreamInput * in; + ParserHandler * handler; QXmlSimpleReader *reader; }; @@ -741,48 +669,42 @@ Parser::Parser() d = new Private; // check for evil bug in Qt <= 3.2.1 - if(!qt_bug_check) { - qt_bug_check = true; + if (!qt_bug_check) { + qt_bug_check = true; QDomElement e = d->doc->createElementNS("someuri", "somename"); - if(e.hasAttributeNS("someuri", "somename")) + if (e.hasAttributeNS("someuri", "somename")) qt_bug_have = true; else qt_bug_have = false; } } -Parser::~Parser() -{ - delete d; -} +Parser::~Parser() { delete d; } -void Parser::reset() -{ - d->reset(); -} +void Parser::reset() { d->reset(); } void Parser::appendData(const QByteArray &a) { d->in->appendData(a); // if handler was waiting for more, give it a kick - if(d->handler->needMore) + if (d->handler->needMore) d->handler->checkNeedMore(); } Parser::Event Parser::readNext() { Event e; - if(d->handler->needMore) + if (d->handler->needMore) return e; Event *ep = d->handler->takeEvent(); - if(!ep) { - if(!d->reader->parseContinue()) { + if (!ep) { + if (!d->reader->parseContinue()) { e.setError(); return e; } ep = d->handler->takeEvent(); - if(!ep) + if (!ep) return e; } e = *ep; @@ -790,12 +712,6 @@ Parser::Event Parser::readNext() return e; } -QByteArray Parser::unprocessed() const -{ - return d->in->unprocessed(); -} +QByteArray Parser::unprocessed() const { return d->in->unprocessed(); } -QString Parser::encoding() const -{ - return d->in->encoding(); -} +QString Parser::encoding() const { return d->in->encoding(); } diff --git a/src/xmpp/xmpp-core/parser.h b/src/xmpp/xmpp-core/parser.h index 3b7a9f63..8b153186 100644 --- a/src/xmpp/xmpp-core/parser.h +++ b/src/xmpp/xmpp-core/parser.h @@ -24,61 +24,60 @@ #include namespace XMPP { - class Parser - { - public: - Parser(); - ~Parser(); - - class Event - { - public: - enum Type { DocumentOpen, DocumentClose, Element, Error }; - Event(); - Event(const Event &); - Event & operator=(const Event &); - ~Event(); - - bool isNull() const; - int type() const; +class Parser { +public: + Parser(); + ~Parser(); - // for document open - QString nsprefix(const QString &s=QString()) const; + class Event { + public: + enum Type { DocumentOpen, DocumentClose, Element, Error }; + Event(); + Event(const Event &); + Event &operator=(const Event &); + ~Event(); - // for document open / close - QString namespaceURI() const; - QString localName() const; - QString qName() const; - QXmlAttributes atts() const; + bool isNull() const; + int type() const; - // for element - QDomElement element() const; + // for document open + QString nsprefix(const QString &s = QString()) const; - // for any - QString actualString() const; + // for document open / close + QString namespaceURI() const; + QString localName() const; + QString qName() const; + QXmlAttributes atts() const; - // setup - void setDocumentOpen(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts, const QStringList &nsnames, const QStringList &nsvalues); - void setDocumentClose(const QString &namespaceURI, const QString &localName, const QString &qName); - void setElement(const QDomElement &elem); - void setError(); - void setActualString(const QString &); + // for element + QDomElement element() const; - private: - class Private; - Private *d; - }; + // for any + QString actualString() const; - void reset(); - void appendData(const QByteArray &a); - Event readNext(); - QByteArray unprocessed() const; - QString encoding() const; + // setup + void setDocumentOpen(const QString &namespaceURI, const QString &localName, const QString &qName, + const QXmlAttributes &atts, const QStringList &nsnames, const QStringList &nsvalues); + void setDocumentClose(const QString &namespaceURI, const QString &localName, const QString &qName); + void setElement(const QDomElement &elem); + void setError(); + void setActualString(const QString &); private: class Private; Private *d; }; + + void reset(); + void appendData(const QByteArray &a); + Event readNext(); + QByteArray unprocessed() const; + QString encoding() const; + +private: + class Private; + Private *d; +}; } // namespace XMPP #endif // PARSER_H diff --git a/src/xmpp/xmpp-core/protocol.cpp b/src/xmpp/xmpp-core/protocol.cpp index 7ba0845a..a7cc706d 100644 --- a/src/xmpp/xmpp-core/protocol.cpp +++ b/src/xmpp/xmpp-core/protocol.cpp @@ -1,4 +1,4 @@ - /* +/* * protocol.cpp - XMPP-Core protocol state machine * Copyright (C) 2004 Justin Karneges * @@ -42,14 +42,13 @@ using namespace XMPP; static QString printArray(const QByteArray &a) { QString s; - for(int n = 0; n < a.size(); ++n) { + for (int n = 0; n < a.size(); ++n) { unsigned char c = (unsigned char)a[(int)n]; - if(c < 32 || c >= 127) { + if (c < 32 || c >= 127) { QString str; str.sprintf("[%02x]", c); s += str; - } - else + } else s += c; } return s; @@ -60,8 +59,8 @@ static QString printArray(const QByteArray &a) // Get an element's first child element static QDomElement firstChildElement(const QDomElement &e) { - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { - if(n.isElement()) + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + if (n.isElement()) return n.toElement(); } return QDomElement(); @@ -81,82 +80,74 @@ Version::Version(int maj, int min) //---------------------------------------------------------------------------- StreamFeatures::StreamFeatures() { - tls_supported = false; - sasl_supported = false; - bind_supported = false; - tls_required = false; + tls_supported = false; + sasl_supported = false; + bind_supported = false; + tls_required = false; compress_supported = false; - sm_supported = false; - session_supported = false; - session_required = false; + sm_supported = false; + session_supported = false; + session_required = false; } //---------------------------------------------------------------------------- // BasicProtocol //---------------------------------------------------------------------------- -BasicProtocol::SASLCondEntry BasicProtocol::saslCondTable[] = -{ - { "aborted", Aborted }, - { "account-disabled", AccountDisabled }, - { "credentials-expired", CredentialsExpired }, - { "encryption-required", EncryptionRequired }, - { "incorrect-encoding", IncorrectEncoding }, - { "invalid-authzid", InvalidAuthzid }, - { "invalid-mechanism", InvalidMech }, - { "malformed-request", MalformedRequest }, - { "mechanism-too-weak", MechTooWeak }, - { "not-authorized", NotAuthorized }, +BasicProtocol::SASLCondEntry BasicProtocol::saslCondTable[] = { + { "aborted", Aborted }, + { "account-disabled", AccountDisabled }, + { "credentials-expired", CredentialsExpired }, + { "encryption-required", EncryptionRequired }, + { "incorrect-encoding", IncorrectEncoding }, + { "invalid-authzid", InvalidAuthzid }, + { "invalid-mechanism", InvalidMech }, + { "malformed-request", MalformedRequest }, + { "mechanism-too-weak", MechTooWeak }, + { "not-authorized", NotAuthorized }, { "temporary-auth-failure", TemporaryAuthFailure }, { nullptr, 0 }, }; -BasicProtocol::StreamCondEntry BasicProtocol::streamCondTable[] = -{ - { "bad-format", BadFormat }, - { "bad-namespace-prefix", BadNamespacePrefix }, - { "conflict", Conflict }, - { "connection-timeout", ConnectionTimeout }, - { "host-gone", HostGone }, - { "host-unknown", HostUnknown }, - { "improper-addressing", ImproperAddressing }, - { "internal-server-error", InternalServerError }, - { "invalid-from", InvalidFrom }, - { "invalid-namespace", InvalidNamespace }, - { "invalid-xml", InvalidXml }, - { "not-authorized", StreamNotAuthorized }, - { "not-well-formed", NotWellFormed }, - { "policy-violation", PolicyViolation }, +BasicProtocol::StreamCondEntry BasicProtocol::streamCondTable[] = { + { "bad-format", BadFormat }, + { "bad-namespace-prefix", BadNamespacePrefix }, + { "conflict", Conflict }, + { "connection-timeout", ConnectionTimeout }, + { "host-gone", HostGone }, + { "host-unknown", HostUnknown }, + { "improper-addressing", ImproperAddressing }, + { "internal-server-error", InternalServerError }, + { "invalid-from", InvalidFrom }, + { "invalid-namespace", InvalidNamespace }, + { "invalid-xml", InvalidXml }, + { "not-authorized", StreamNotAuthorized }, + { "not-well-formed", NotWellFormed }, + { "policy-violation", PolicyViolation }, { "remote-connection-failed", RemoteConnectionFailed }, - { "reset", StreamReset }, - { "resource-constraint", ResourceConstraint }, - { "restricted-xml", RestrictedXml }, - { "see-other-host", SeeOtherHost }, - { "system-shutdown", SystemShutdown }, - { "undefined-condition", UndefinedCondition }, - { "unsupported-encoding", UnsupportedEncoding }, - { "unsupported-stanza-type", UnsupportedStanzaType }, - { "unsupported-version", UnsupportedVersion }, + { "reset", StreamReset }, + { "resource-constraint", ResourceConstraint }, + { "restricted-xml", RestrictedXml }, + { "see-other-host", SeeOtherHost }, + { "system-shutdown", SystemShutdown }, + { "undefined-condition", UndefinedCondition }, + { "unsupported-encoding", UnsupportedEncoding }, + { "unsupported-stanza-type", UnsupportedStanzaType }, + { "unsupported-version", UnsupportedVersion }, { nullptr, 0 }, }; -BasicProtocol::BasicProtocol() -:XmlProtocol() -{ - init(); -} +BasicProtocol::BasicProtocol() : XmlProtocol() { init(); } -BasicProtocol::~BasicProtocol() -{ -} +BasicProtocol::~BasicProtocol() {} void BasicProtocol::init() { - errCond = -1; - sasl_authed = false; - doShutdown = false; - delayedError = false; - closeError = false; - ready = false; + errCond = -1; + sasl_authed = false; + doShutdown = false; + delayedError = false; + closeError = false; + ready = false; stanzasPending = 0; stanzasWritten = 0; } @@ -166,14 +157,14 @@ void BasicProtocol::reset() XmlProtocol::reset(); init(); - to = QString(); - from = QString(); - id = QString(); - lang = QString(); - version = Version(1,0); - errText = QString(); + to = QString(); + from = QString(); + id = QString(); + lang = QString(); + version = Version(1, 0); + errText = QString(); errAppSpec = QDomElement(); - otherHost = QString(); + otherHost = QString(); spare.resize(0); sasl_mech = QString(); sasl_mechlist.clear(); @@ -203,22 +194,16 @@ void BasicProtocol::sendWhitespace() sendList += i; } -void BasicProtocol::clearSendQueue() -{ - sendList.clear(); -} +void BasicProtocol::clearSendQueue() { sendList.clear(); } QDomElement BasicProtocol::recvStanza() { QDomElement e = stanzaToRecv; - stanzaToRecv = QDomElement(); + stanzaToRecv = QDomElement(); return e; } -void BasicProtocol::shutdown() -{ - doShutdown = true; -} +void BasicProtocol::shutdown() { doShutdown = true; } void BasicProtocol::shutdownWithError(int cond, const QString &str) { @@ -226,30 +211,15 @@ void BasicProtocol::shutdownWithError(int cond, const QString &str) delayErrorAndClose(cond); } -bool BasicProtocol::isReady() const -{ - return ready; -} +bool BasicProtocol::isReady() const { return ready; } -void BasicProtocol::setReady(bool b) -{ - ready = b; -} +void BasicProtocol::setReady(bool b) { ready = b; } -QString BasicProtocol::saslMech() const -{ - return sasl_mech; -} +QString BasicProtocol::saslMech() const { return sasl_mech; } -QByteArray BasicProtocol::saslStep() const -{ - return sasl_step; -} +QByteArray BasicProtocol::saslStep() const { return sasl_step; } -void BasicProtocol::setSASLMechList(const QStringList &list) -{ - sasl_mechlist = list; -} +void BasicProtocol::setSASLMechList(const QStringList &list) { sasl_mechlist = list; } void BasicProtocol::setSASLFirst(const QString &mech, const QByteArray &step) { @@ -257,20 +227,14 @@ void BasicProtocol::setSASLFirst(const QString &mech, const QByteArray &step) sasl_step = step; } -void BasicProtocol::setSASLNext(const QByteArray &step) -{ - sasl_step = step; -} +void BasicProtocol::setSASLNext(const QByteArray &step) { sasl_step = step; } -void BasicProtocol::setSASLAuthed() -{ - sasl_authed = true; -} +void BasicProtocol::setSASLAuthed() { sasl_authed = true; } int BasicProtocol::stringToSASLCond(const QString &s) { - for(int n = 0; saslCondTable[n].str; ++n) { - if(s == saslCondTable[n].str) + for (int n = 0; saslCondTable[n].str; ++n) { + if (s == saslCondTable[n].str) return saslCondTable[n].cond; } return -1; @@ -278,8 +242,8 @@ int BasicProtocol::stringToSASLCond(const QString &s) int BasicProtocol::stringToStreamCond(const QString &s) { - for(int n = 0; streamCondTable[n].str; ++n) { - if(s == streamCondTable[n].str) + for (int n = 0; streamCondTable[n].str; ++n) { + if (s == streamCondTable[n].str) return streamCondTable[n].cond; } return -1; @@ -287,8 +251,8 @@ int BasicProtocol::stringToStreamCond(const QString &s) QString BasicProtocol::saslCondToString(int x) { - for(int n = 0; saslCondTable[n].str; ++n) { - if(x == saslCondTable[n].cond) + for (int n = 0; saslCondTable[n].str; ++n) { + if (x == saslCondTable[n].cond) return saslCondTable[n].str; } return QString(); @@ -296,8 +260,8 @@ QString BasicProtocol::saslCondToString(int x) QString BasicProtocol::streamCondToString(int x) { - for(int n = 0; streamCondTable[n].str; ++n) { - if(x == streamCondTable[n].cond) + for (int n = 0; streamCondTable[n].str; ++n) { + if (x == streamCondTable[n].cond) return streamCondTable[n].str; } return QString(); @@ -305,27 +269,26 @@ QString BasicProtocol::streamCondToString(int x) void BasicProtocol::extractStreamError(const QDomElement &e) { - QString text; - QHash langText; - QDomElement appSpec; + QString text; + QHash langText; + QDomElement appSpec; QDomElement t = firstChildElement(e); - if(t.isNull() || t.namespaceURI() != NS_STREAMS) { + if (t.isNull() || t.namespaceURI() != NS_STREAMS) { // probably old-style error errCond = -1; errText = e.text(); - } - else + } else errCond = stringToStreamCond(t.tagName()); - if(errCond != -1) { - if(errCond == SeeOtherHost) + if (errCond != -1) { + if (errCond == SeeOtherHost) otherHost = t.text(); auto nodes = e.elementsByTagNameNS(NS_STREAMS, "text"); if (nodes.count()) { for (int i = 0; i < nodes.count(); i++) { - auto e = nodes.item(i).toElement(); + auto e = nodes.item(i).toElement(); QString lang = e.attributeNS(NS_STREAMS, "lang", ""); langText.insert(lang, e.text()); } @@ -334,38 +297,32 @@ void BasicProtocol::extractStreamError(const QDomElement &e) // find first non-standard namespaced element QDomNodeList nl = e.childNodes(); - for(int n = 0; n < nl.count(); ++n) { + for (int n = 0; n < nl.count(); ++n) { QDomNode i = nl.item(n); - if(i.isElement() && i.namespaceURI() != NS_STREAMS) { + if (i.isElement() && i.namespaceURI() != NS_STREAMS) { appSpec = i.toElement(); break; } } - errText = text; + errText = text; errLangText = langText; - errAppSpec = appSpec; + errAppSpec = appSpec; } } -void BasicProtocol::send(const QDomElement &e, bool clip) -{ - writeElement(e, TypeElement, false, clip, false); -} +void BasicProtocol::send(const QDomElement &e, bool clip) { writeElement(e, TypeElement, false, clip, false); } -void BasicProtocol::sendUrgent(const QDomElement &e, bool clip) -{ - writeElement(e, TypeElement, false, clip, true); -} +void BasicProtocol::sendUrgent(const QDomElement &e, bool clip) { writeElement(e, TypeElement, false, clip, true); } void BasicProtocol::sendStreamError(int cond, const QString &text, const QDomElement &appSpec) { - QDomElement se = doc.createElementNS(NS_ETHERX, "stream:error"); + QDomElement se = doc.createElementNS(NS_ETHERX, "stream:error"); QDomElement err = doc.createElementNS(NS_STREAMS, streamCondToString(cond)); - if(!otherHost.isEmpty()) + if (!otherHost.isEmpty()) err.appendChild(doc.createTextNode(otherHost)); se.appendChild(err); - if(!text.isEmpty()) { + if (!text.isEmpty()) { QDomElement te = doc.createElementNS(NS_STREAMS, "text"); te.setAttributeNS(NS_XML, "xml:lang", "en"); te.appendChild(doc.createTextNode(text)); @@ -387,8 +344,8 @@ void BasicProtocol::sendStreamError(const QString &text) bool BasicProtocol::errorAndClose(int cond, const QString &text, const QDomElement &appSpec) { closeError = true; - errCond = cond; - errText = text; + errCond = cond; + errText = text; errAppSpec = appSpec; sendStreamError(cond, text, appSpec); return close(); @@ -396,23 +353,23 @@ bool BasicProtocol::errorAndClose(int cond, const QString &text, const QDomEleme bool BasicProtocol::error(int code) { - event = EError; + event = EError; errorCode = code; return true; } void BasicProtocol::delayErrorAndClose(int cond, const QString &text, const QDomElement &appSpec) { - errorCode = ErrStream; - errCond = cond; - errText = text; - errAppSpec = appSpec; + errorCode = ErrStream; + errCond = cond; + errText = text; + errAppSpec = appSpec; delayedError = true; } void BasicProtocol::delayError(int code) { - errorCode = code; + errorCode = code; delayedError = true; } @@ -421,79 +378,78 @@ QDomElement BasicProtocol::docElement() // create the root element QDomElement e = doc.createElementNS(NS_ETHERX, "stream:stream"); - QString defns = defaultNamespace(); - const QStringList list = extraNamespaces(); + QString defns = defaultNamespace(); + const QStringList list = extraNamespaces(); // HACK: using attributes seems to be the only way to get additional namespaces in here - if(!defns.isEmpty()) + if (!defns.isEmpty()) e.setAttribute(QString::fromLatin1("xmlns"), defns); - for(QStringList::ConstIterator it = list.begin(); it != list.end();) { + for (QStringList::ConstIterator it = list.begin(); it != list.end();) { QString prefix = *(it++); - QString uri = *(it++); + QString uri = *(it++); e.setAttribute(QString::fromLatin1("xmlns:") + prefix, uri); } // additional attributes - if(!isIncoming() && !to.isEmpty()) + if (!isIncoming() && !to.isEmpty()) e.setAttribute(QString::fromLatin1("to"), to); - if(isIncoming() && !from.isEmpty()) + if (isIncoming() && !from.isEmpty()) e.setAttribute(QString::fromLatin1("from"), from); - if(!id.isEmpty()) + if (!id.isEmpty()) e.setAttribute(QString::fromLatin1("id"), id); - if(!lang.isEmpty()) + if (!lang.isEmpty()) e.setAttributeNS(QString::fromLatin1(NS_XML), QString::fromLatin1("xml:lang"), lang); - if(version.major > 0 || version.minor > 0) - e.setAttribute(QString::fromLatin1("version"), QString::number(version.major) + '.' + QString::number(version.minor)); + if (version.major > 0 || version.minor > 0) + e.setAttribute(QString::fromLatin1("version"), + QString::number(version.major) + '.' + QString::number(version.minor)); return e; } void BasicProtocol::handleDocOpen(const Parser::Event &pe) { - if(isIncoming()) { - if(xmlEncoding() != "UTF-8") { + if (isIncoming()) { + if (xmlEncoding() != "UTF-8") { delayErrorAndClose(UnsupportedEncoding); return; } } - if(pe.namespaceURI() == NS_ETHERX && pe.localName() == "stream") { + if (pe.namespaceURI() == NS_ETHERX && pe.localName() == "stream") { QXmlAttributes atts = pe.atts(); // grab the version - int major = 0; - int minor = 0; + int major = 0; + int minor = 0; QString verstr = atts.value("version"); - if(!verstr.isEmpty()) { + if (!verstr.isEmpty()) { int n = verstr.indexOf('.'); - if(n != -1) { + if (n != -1) { major = verstr.mid(0, n).toInt(); - minor = verstr.mid(n+1).toInt(); - } - else { + minor = verstr.mid(n + 1).toInt(); + } else { major = verstr.toInt(); minor = 0; } } version = Version(major, minor); - if(isIncoming()) { - to = atts.value("to"); + if (isIncoming()) { + to = atts.value("to"); QString peerLang = atts.value(NS_XML, "lang"); - if(!peerLang.isEmpty()) + if (!peerLang.isEmpty()) lang = peerLang; } // outgoing else { from = atts.value("from"); lang = atts.value(NS_XML, "lang"); - id = atts.value("id"); + id = atts.value("id"); } handleStreamOpen(pe); - } - else { - if(isIncoming()) + } else { + if (isIncoming()) delayErrorAndClose(BadFormat); else delayError(ErrProtocol); @@ -502,7 +458,7 @@ void BasicProtocol::handleDocOpen(const Parser::Event &pe) bool BasicProtocol::handleError() { - if(isIncoming()) + if (isIncoming()) return errorAndClose(NotWellFormed); else return error(ErrParse); @@ -510,12 +466,11 @@ bool BasicProtocol::handleError() bool BasicProtocol::handleCloseFinished() { - if(closeError) { - event = EError; + if (closeError) { + event = EError; errorCode = ErrStream; // note: errCond and friends are already set at this point - } - else + } else event = EClosed; return true; } @@ -523,64 +478,63 @@ bool BasicProtocol::handleCloseFinished() bool BasicProtocol::doStep(const QDomElement &e) { // handle pending error - if(delayedError) { - if(isIncoming()) + if (delayedError) { + if (isIncoming()) return errorAndClose(errCond, errText, errAppSpec); else return error(errorCode); } // shutdown? - if(doShutdown) { + if (doShutdown) { doShutdown = false; return close(); } - if(!e.isNull()) { + if (!e.isNull()) { // check for error - if(e.namespaceURI() == NS_ETHERX && e.tagName() == "error") { + if (e.namespaceURI() == NS_ETHERX && e.tagName() == "error") { extractStreamError(e); return error(ErrStream); } } - if(ready) { + if (ready) { // stanzas written? - if(stanzasWritten > 0) { + if (stanzasWritten > 0) { --stanzasWritten; event = EStanzaSent; return true; } // send items? - if(!sendList.isEmpty()) { + if (!sendList.isEmpty()) { SendItem i; { QList::Iterator it = sendList.begin(); - i = (*it); + i = (*it); sendList.erase(it); } // outgoing stanza? - if(!i.stanzaToSend.isNull()) { + if (!i.stanzaToSend.isNull()) { ++stanzasPending; writeElement(i.stanzaToSend, TypeStanza, true); event = ESend; } // direct send? - else if(!i.stringToSend.isEmpty()) { + else if (!i.stringToSend.isEmpty()) { writeString(i.stringToSend, TypeDirect, true); event = ESend; } // whitespace keepalive? - else if(i.doWhitespace) { + else if (i.doWhitespace) { writeString("\n", TypePing, false); event = ESend; } return true; - } - else { + } else { // if we have pending outgoing stanzas, ask for write notification - if(stanzasPending) + if (stanzasPending) notify |= NSend; } } @@ -590,7 +544,7 @@ bool BasicProtocol::doStep(const QDomElement &e) void BasicProtocol::itemWritten(int id, int) { - if(id == TypeStanza) { + if (id == TypeStanza) { --stanzasPending; ++stanzasWritten; } @@ -616,15 +570,11 @@ void BasicProtocol::handleStreamOpen(const Parser::Event &) //---------------------------------------------------------------------------- // CoreProtocol //---------------------------------------------------------------------------- -CoreProtocol::CoreProtocol() -:BasicProtocol() -{ - init(); -} +CoreProtocol::CoreProtocol() : BasicProtocol() { init(); } CoreProtocol::~CoreProtocol() { - //fprintf(stderr, "\tCoreProtocol::~CoreProtocol()\n"); + // fprintf(stderr, "\tCoreProtocol::~CoreProtocol()\n"); } void CoreProtocol::init() @@ -632,29 +582,29 @@ void CoreProtocol::init() step = Start; // ?? - server = false; - dialback = false; + server = false; + dialback = false; dialback_verify = false; // settings - jid_ = Jid(); - password = QString(); - oldOnly = false; + jid_ = Jid(); + password = QString(); + oldOnly = false; allowPlain = false; - doTLS = true; - doAuth = true; + doTLS = true; + doAuth = true; doCompress = true; - doBinding = true; + doBinding = true; // input user = QString(); host = QString(); // status - old = false; - digest = false; - tls_started = false; - sasl_started = false; + old = false; + digest = false; + tls_started = false; + sasl_started = false; compress_started = false; sm.reset(); @@ -666,13 +616,15 @@ void CoreProtocol::reset() init(); } -void CoreProtocol::needTimer(int seconds) { +void CoreProtocol::needTimer(int seconds) +{ notify |= NTimeout; - need = NNotify; + need = NNotify; timeout_sec = seconds; } -void CoreProtocol::sendStanza(const QDomElement &e) { +void CoreProtocol::sendStanza(const QDomElement &e) +{ if (sm.isActive()) { int len = sm.addUnacknowledgedStanza(e); if (len > 5 && len % 4 == 0) @@ -684,43 +636,44 @@ void CoreProtocol::sendStanza(const QDomElement &e) { void CoreProtocol::startClientOut(const Jid &_jid, bool _oldOnly, bool tlsActive, bool _doAuth, bool _doCompress) { - jid_ = _jid; - to = _jid.domain(); - oldOnly = _oldOnly; - doAuth = _doAuth; - doCompress = _doCompress; + jid_ = _jid; + to = _jid.domain(); + oldOnly = _oldOnly; + doAuth = _doAuth; + doCompress = _doCompress; tls_started = tlsActive; - if(oldOnly) - version = Version(0,0); + if (oldOnly) + version = Version(0, 0); startConnect(); } void CoreProtocol::startServerOut(const QString &_to) { server = true; - to = _to; + to = _to; startConnect(); } void CoreProtocol::startDialbackOut(const QString &_to, const QString &_from) { - server = true; - dialback = true; - to = _to; + server = true; + dialback = true; + to = _to; self_from = _from; startConnect(); } -void CoreProtocol::startDialbackVerifyOut(const QString &_to, const QString &_from, const QString &id, const QString &key) +void CoreProtocol::startDialbackVerifyOut(const QString &_to, const QString &_from, const QString &id, + const QString &key) { - server = true; - dialback = true; + server = true; + dialback = true; dialback_verify = true; - to = _to; - self_from = _from; - dialback_id = id; - dialback_key = key; + to = _to; + self_from = _from; + dialback_id = id; + dialback_key = key; startConnect(); } @@ -733,49 +686,25 @@ void CoreProtocol::startClientIn(const QString &_id) void CoreProtocol::startServerIn(const QString &_id) { server = true; - id = _id; + id = _id; startAccept(); } -void CoreProtocol::setLang(const QString &s) -{ - lang = s; -} +void CoreProtocol::setLang(const QString &s) { lang = s; } -void CoreProtocol::setAllowTLS(bool b) -{ - doTLS = b; -} +void CoreProtocol::setAllowTLS(bool b) { doTLS = b; } -void CoreProtocol::setAllowBind(bool b) -{ - doBinding = b; -} +void CoreProtocol::setAllowBind(bool b) { doBinding = b; } -void CoreProtocol::setAllowPlain(bool b) -{ - allowPlain = b; -} +void CoreProtocol::setAllowPlain(bool b) { allowPlain = b; } -const Jid& CoreProtocol::jid() const -{ - return jid_; -} +const Jid &CoreProtocol::jid() const { return jid_; } -void CoreProtocol::setPassword(const QString &s) -{ - password = s; -} +void CoreProtocol::setPassword(const QString &s) { password = s; } -void CoreProtocol::setFrom(const QString &s) -{ - from = s; -} +void CoreProtocol::setFrom(const QString &s) { from = s; } -void CoreProtocol::setDialbackKey(const QString &s) -{ - dialback_key = s; -} +void CoreProtocol::setDialbackKey(const QString &s) { dialback_key = s; } bool CoreProtocol::loginComplete() { @@ -794,10 +723,10 @@ bool CoreProtocol::loginComplete() send(e); } event = ESend; - step = GetSMResponse; + step = GetSMResponse; } else { event = EReady; - step = Done; + step = Done; } return true; } @@ -805,7 +734,7 @@ bool CoreProtocol::loginComplete() int CoreProtocol::getOldErrorCode(const QDomElement &e) { QDomElement err = e.elementsByTagNameNS(NS_CLIENT, "error").item(0).toElement(); - if(err.isNull() || !err.hasAttribute("code")) + if (err.isNull() || !err.hasAttribute("code")) return -1; return err.attribute("code").toInt(); } @@ -825,9 +754,9 @@ int CoreProtocol::getOldErrorCode(const QDomElement &e) bool CoreProtocol::stepAdvancesParser() const { - if(stepRequiresElement()) + if (stepRequiresElement()) return true; - else if(isReady()) + else if (isReady()) return true; return false; } @@ -835,18 +764,18 @@ bool CoreProtocol::stepAdvancesParser() const // all element-needing steps need to be registered here bool CoreProtocol::stepRequiresElement() const { - switch(step) { - case GetFeatures: - case GetTLSProceed: - case GetCompressProceed: - case GetSASLChallenge: - case GetBindResponse: - case GetAuthGetResponse: - case GetAuthSetResponse: - case GetRequest: - case GetSASLResponse: - case GetSMResponse: - return true; + switch (step) { + case GetFeatures: + case GetTLSProceed: + case GetCompressProceed: + case GetSASLChallenge: + case GetBindResponse: + case GetAuthGetResponse: + case GetAuthSetResponse: + case GetRequest: + case GetSASLResponse: + case GetSMResponse: + return true; } return false; } @@ -867,7 +796,7 @@ void CoreProtocol::stringRecv(const QString &s) QString CoreProtocol::defaultNamespace() { - if(server) + if (server) return NS_SERVER; else return NS_CLIENT; @@ -876,7 +805,7 @@ QString CoreProtocol::defaultNamespace() QStringList CoreProtocol::extraNamespaces() { QStringList list; - if(dialback) { + if (dialback) { list += "db"; list += NS_DIALBACK; } @@ -885,30 +814,29 @@ QStringList CoreProtocol::extraNamespaces() void CoreProtocol::handleStreamOpen(const Parser::Event &pe) { - if(isIncoming()) { + if (isIncoming()) { QString ns = pe.nsprefix(); QString db; - if(server) { + if (server) { db = pe.nsprefix("db"); - if(!db.isEmpty()) + if (!db.isEmpty()) dialback = true; } // verify namespace - if((!server && ns != NS_CLIENT) || (server && ns != NS_SERVER) || (dialback && db != NS_DIALBACK)) { + if ((!server && ns != NS_CLIENT) || (server && ns != NS_SERVER) || (dialback && db != NS_DIALBACK)) { delayErrorAndClose(InvalidNamespace); return; } // verify version - if(version.major < 1 && !dialback) { + if (version.major < 1 && !dialback) { delayErrorAndClose(UnsupportedVersion); return; } - } - else { - if(!dialback) { - if(version.major >= 1 && !oldOnly) + } else { + if (!dialback) { + if (version.major >= 1 && !oldOnly) old = false; else old = true; @@ -932,7 +860,7 @@ void CoreProtocol::elementRecv(const QDomElement &e) bool CoreProtocol::doStep2(const QDomElement &e) { - if(dialback) + if (dialback) return dialbackStep(e); else return normalStep(e); @@ -940,9 +868,10 @@ bool CoreProtocol::doStep2(const QDomElement &e) bool CoreProtocol::isValidStanza(const QDomElement &e) const { - QString s = e.tagName(); + QString s = e.tagName(); Stanza::Kind kind = Stanza::kind(s); - if(e.namespaceURI() == (server ? NS_SERVER : NS_CLIENT) && (kind == Stanza::Message || kind == Stanza::Presence || kind == Stanza::IQ)) + if (e.namespaceURI() == (server ? NS_SERVER : NS_CLIENT) + && (kind == Stanza::Message || kind == Stanza::Presence || kind == Stanza::IQ)) return true; else return false; @@ -951,7 +880,7 @@ bool CoreProtocol::isValidStanza(const QDomElement &e) const bool CoreProtocol::streamManagementHandleStanza(const QDomElement &e) { QString s = e.tagName(); - if(s == "r") { + if (s == "r") { #ifdef IRIS_SM_DEBUG qDebug() << "Stream Management: [<-?] Received request from server"; #endif @@ -987,11 +916,11 @@ bool CoreProtocol::needSMRequest() bool CoreProtocol::grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item) { - for(QList::Iterator it = dbpending.begin(); it != dbpending.end(); ++it) { + for (QList::Iterator it = dbpending.begin(); it != dbpending.end(); ++it) { const DBItem &i = *it; - if(i.type == type && i.to.compare(to) && i.from.compare(from)) { + if (i.type == type && i.to.compare(to) && i.from.compare(from)) { const DBItem &i = (*it); - *item = i; + *item = i; dbpending.erase(it); return true; } @@ -1001,44 +930,41 @@ bool CoreProtocol::grabPendingItem(const Jid &to, const Jid &from, int type, DBI bool CoreProtocol::dialbackStep(const QDomElement &e) { - if(step == Start) { + if (step == Start) { setReady(true); - step = Done; + step = Done; event = EReady; return true; } - if(!dbrequests.isEmpty()) { + if (!dbrequests.isEmpty()) { // process a request DBItem i; { QList::Iterator it = dbrequests.begin(); - i = (*it); + i = (*it); dbrequests.erase(it); } QDomElement r; - if(i.type == DBItem::ResultRequest) { + if (i.type == DBItem::ResultRequest) { r = doc.createElementNS(NS_DIALBACK, "db:result"); r.setAttribute("to", i.to.full()); r.setAttribute("from", i.from.full()); r.appendChild(doc.createTextNode(i.key)); dbpending += i; - } - else if(i.type == DBItem::ResultGrant) { + } else if (i.type == DBItem::ResultGrant) { r = doc.createElementNS(NS_DIALBACK, "db:result"); r.setAttribute("to", i.to.full()); r.setAttribute("from", i.from.full()); r.setAttribute("type", i.ok ? "valid" : "invalid"); - if(i.ok) { + if (i.ok) { i.type = DBItem::Validated; dbvalidated += i; - } - else { + } else { // TODO: disconnect after writing element } - } - else if(i.type == DBItem::VerifyRequest) { + } else if (i.type == DBItem::VerifyRequest) { r = doc.createElementNS(NS_DIALBACK, "db:verify"); r.setAttribute("to", i.to.full()); r.setAttribute("from", i.from.full()); @@ -1060,60 +986,54 @@ bool CoreProtocol::dialbackStep(const QDomElement &e) return true; } - if(!e.isNull()) { - if(e.namespaceURI() == NS_DIALBACK) { - if(e.tagName() == "result") { + if (!e.isNull()) { + if (e.namespaceURI() == NS_DIALBACK) { + if (e.tagName() == "result") { Jid to(Jid(e.attribute("to")).domain()); Jid from(Jid(e.attribute("from")).domain()); - if(isIncoming()) { + if (isIncoming()) { QString key = e.text(); // TODO: report event - } - else { - bool ok = (e.attribute("type") == "valid") ? true: false; + } else { + bool ok = (e.attribute("type") == "valid") ? true : false; DBItem i; - if(grabPendingItem(from, to, DBItem::ResultRequest, &i)) { - if(ok) { + if (grabPendingItem(from, to, DBItem::ResultRequest, &i)) { + if (ok) { i.type = DBItem::Validated; - i.ok = true; + i.ok = true; dbvalidated += i; // TODO: report event - } - else { + } else { // TODO: report event } } } - } - else if(e.tagName() == "verify") { - Jid to(Jid(e.attribute("to")).domain()); - Jid from(Jid(e.attribute("from")).domain()); + } else if (e.tagName() == "verify") { + Jid to(Jid(e.attribute("to")).domain()); + Jid from(Jid(e.attribute("from")).domain()); QString id = e.attribute("id"); - if(isIncoming()) { + if (isIncoming()) { QString key = e.text(); // TODO: report event - } - else { - bool ok = (e.attribute("type") == "valid") ? true: false; + } else { + bool ok = (e.attribute("type") == "valid") ? true : false; DBItem i; - if(grabPendingItem(from, to, DBItem::VerifyRequest, &i)) { - if(ok) { + if (grabPendingItem(from, to, DBItem::VerifyRequest, &i)) { + if (ok) { // TODO: report event - } - else { + } else { // TODO: report event } } } } - } - else { - if(isReady()) { - if(isValidStanza(e)) { + } else { + if (isReady()) { + if (isValidStanza(e)) { // TODO: disconnect if stanza is from unverified sender // TODO: ignore packets from receiving servers stanzaToRecv = e; - event = EStanzaReady; + event = EStanzaReady; return true; } } @@ -1127,33 +1047,30 @@ bool CoreProtocol::dialbackStep(const QDomElement &e) bool CoreProtocol::normalStep(const QDomElement &e) { - if(step == Start) { - if(isIncoming()) { + if (step == Start) { + if (isIncoming()) { need = NSASLMechs; step = SendFeatures; return false; - } - else { - if(old) { - if(doAuth) + } else { + if (old) { + if (doAuth) step = HandleAuthGet; else return loginComplete(); - } - else + } else step = GetFeatures; return processStep(); } - } - else if(step == HandleFeatures) { + } else if (step == HandleFeatures) { // deal with TLS? - if(doTLS && !tls_started && !sasl_authed && features.tls_supported) { + if (doTLS && !tls_started && !sasl_authed && features.tls_supported) { QDomElement e = doc.createElementNS(NS_TLS, "starttls"); send(e, true); event = ESend; - step = GetTLSProceed; + step = GetTLSProceed; return true; } @@ -1162,28 +1079,29 @@ bool CoreProtocol::normalStep(const QDomElement &e) return loginComplete(); // Deal with compression - if (doCompress && !compress_started && features.compress_supported && features.compression_mechs.contains("zlib")) { + if (doCompress && !compress_started && features.compress_supported + && features.compression_mechs.contains("zlib")) { QDomElement e = doc.createElementNS(NS_COMPRESS_PROTOCOL, "compress"); QDomElement m = doc.createElementNS(NS_COMPRESS_PROTOCOL, "method"); m.appendChild(doc.createTextNode("zlib")); e.appendChild(m); - send(e,true); + send(e, true); event = ESend; - step = GetCompressProceed; + step = GetCompressProceed; return true; } // deal with SASL? - if(!sasl_authed) { - if(!features.sasl_supported) { + if (!sasl_authed) { + if (!features.sasl_supported) { // SASL MUST be supported - //event = EError; - //errorCode = ErrProtocol; - //return true; + // event = EError; + // errorCode = ErrProtocol; + // return true; // Fall back on auth for non-compliant servers step = HandleAuthGet; - old = true; + old = true; return true; } @@ -1195,18 +1113,17 @@ bool CoreProtocol::normalStep(const QDomElement &e) return false; } - if(server) { + if (server) { return loginComplete(); - } - else { - if(!doBinding) + } else { + if (!doBinding) return loginComplete(); } // deal with bind - if(!features.bind_supported) { + if (!features.bind_supported) { // bind MUST be supported - event = EError; + event = EError; errorCode = ErrProtocol; return true; } @@ -1222,7 +1139,7 @@ bool CoreProtocol::normalStep(const QDomElement &e) // request specific resource? QString resource = jid_.resource(); - if(!resource.isEmpty()) { + if (!resource.isEmpty()) { QDomElement r = doc.createElement("resource"); r.appendChild(doc.createTextNode(jid_.resource())); b.appendChild(r); @@ -1232,14 +1149,13 @@ bool CoreProtocol::normalStep(const QDomElement &e) send(e); event = ESend; - step = GetBindResponse; + step = GetBindResponse; return true; } - } - else if(step == GetSASLFirst) { + } else if (step == GetSASLFirst) { QDomElement e = doc.createElementNS(NS_SASL, "auth"); e.setAttribute("mechanism", sasl_mech); - if(!sasl_step.isEmpty()) { + if (!sasl_step.isEmpty()) { #ifdef XMPP_TEST TD::msg(QString("SASL OUT: [%1]").arg(printArray(sasl_step))); #endif @@ -1248,38 +1164,34 @@ bool CoreProtocol::normalStep(const QDomElement &e) send(e, true); event = ESend; - step = GetSASLChallenge; + step = GetSASLChallenge; return true; - } - else if(step == GetSASLNext) { - if(isIncoming()) { - if(sasl_authed) { + } else if (step == GetSASLNext) { + if (isIncoming()) { + if (sasl_authed) { QDomElement e = doc.createElementNS(NS_SASL, "success"); send(e, true); event = ESend; - step = IncHandleSASLSuccess; + step = IncHandleSASLSuccess; return true; - } - else { - QByteArray stepData = sasl_step; - QDomElement e = doc.createElementNS(NS_SASL, "challenge"); - if(!stepData.isEmpty()) + } else { + QByteArray stepData = sasl_step; + QDomElement e = doc.createElementNS(NS_SASL, "challenge"); + if (!stepData.isEmpty()) e.appendChild(doc.createTextNode(QCA::Base64().arrayToString(stepData))); send(e, true); event = ESend; - step = GetSASLResponse; + step = GetSASLResponse; return true; } - } - else { + } else { // already authed? then ignore last client step // (this happens if "additional data with success" // is used) - if(sasl_authed) - { + if (sasl_authed) { event = ESASLSuccess; - step = HandleSASLSuccess; + step = HandleSASLSuccess; return true; } @@ -1288,22 +1200,20 @@ bool CoreProtocol::normalStep(const QDomElement &e) TD::msg(QString("SASL OUT: [%1]").arg(printArray(sasl_step))); #endif QDomElement e = doc.createElementNS(NS_SASL, "response"); - if(!stepData.isEmpty()) + if (!stepData.isEmpty()) e.appendChild(doc.createTextNode(QCA::Base64().arrayToString(stepData))); send(e, true); event = ESend; - step = GetSASLChallenge; + step = GetSASLChallenge; return true; } - } - else if(step == HandleSASLSuccess) { - need = NSASLLayer; + } else if (step == HandleSASLSuccess) { + need = NSASLLayer; spare = resetStream(); - step = Start; + step = Start; return false; - } - else if(step == HandleAuthGet) { + } else if (step == HandleAuthGet) { QDomElement e = doc.createElement("iq"); e.setAttribute("to", to); e.setAttribute("type", "get"); @@ -1316,10 +1226,9 @@ bool CoreProtocol::normalStep(const QDomElement &e) send(e); event = ESend; - step = GetAuthGetResponse; + step = GetAuthGetResponse; return true; - } - else if(step == HandleAuthSet) { + } else if (step == HandleAuthSet) { QDomElement e = doc.createElement("iq"); e.setAttribute("to", to); e.setAttribute("type", "set"); @@ -1329,16 +1238,15 @@ bool CoreProtocol::normalStep(const QDomElement &e) u.appendChild(doc.createTextNode(jid_.node())); q.appendChild(u); QDomElement p; - if(digest) { + if (digest) { // need SHA1 here - //if(!QCA::isSupported(QCA::CAP_SHA1)) + // if(!QCA::isSupported(QCA::CAP_SHA1)) // QCA::insertProvider(createProviderHash()); - p = doc.createElement("digest"); + p = doc.createElement("digest"); QByteArray cs = id.toUtf8() + password.toUtf8(); p.appendChild(doc.createTextNode(QCA::Hash("sha1").hashToString(cs))); - } - else { + } else { p = doc.createElement("password"); p.appendChild(doc.createTextNode(password)); } @@ -1350,26 +1258,25 @@ bool CoreProtocol::normalStep(const QDomElement &e) send(e, true); event = ESend; - step = GetAuthSetResponse; + step = GetAuthSetResponse; return true; } // server - else if(step == SendFeatures) { + else if (step == SendFeatures) { QDomElement f = doc.createElementNS(NS_ETHERX, "stream:features"); - if(!tls_started && !sasl_authed) { // don't offer tls if we are already sasl'd + if (!tls_started && !sasl_authed) { // don't offer tls if we are already sasl'd QDomElement tls = doc.createElementNS(NS_TLS, "starttls"); f.appendChild(tls); } - if(sasl_authed) { - if(!server) { + if (sasl_authed) { + if (!server) { QDomElement bind = doc.createElementNS(NS_BIND, "bind"); f.appendChild(bind); } - } - else { + } else { QDomElement mechs = doc.createElementNS(NS_SASL, "mechanisms"); - foreach (const QString & it, sasl_mechlist) { + foreach (const QString &it, sasl_mechlist) { QDomElement m = doc.createElement("mechanism"); m.appendChild(doc.createTextNode(it)); mechs.appendChild(m); @@ -1379,31 +1286,30 @@ bool CoreProtocol::normalStep(const QDomElement &e) send(f); event = ESend; - step = GetRequest; + step = GetRequest; return true; } // server - else if(step == HandleTLS) { + else if (step == HandleTLS) { tls_started = true; - need = NStartTLS; - spare = resetStream(); - step = Start; + need = NStartTLS; + spare = resetStream(); + step = Start; return false; } // server - else if(step == IncHandleSASLSuccess) { + else if (step == IncHandleSASLSuccess) { event = ESASLSuccess; spare = resetStream(); - step = Start; + step = Start; printf("sasl success\n"); return true; - } - else if(step == GetFeatures) { + } else if (step == GetFeatures) { // we are waiting for stream features - if(e.namespaceURI() == NS_ETHERX && e.tagName() == QLatin1String("features")) { + if (e.namespaceURI() == NS_ETHERX && e.tagName() == QLatin1String("features")) { // extract features - StreamFeatures f; - QDomNodeList nl = e.childNodes(); + StreamFeatures f; + QDomNodeList nl = e.childNodes(); QList unhandled; for (int i = 0; i < nl.size(); i++) { QDomElement c = nl.item(i).toElement(); @@ -1412,18 +1318,18 @@ bool CoreProtocol::normalStep(const QDomElement &e) } if (c.localName() == QLatin1String("starttls") && c.namespaceURI() == NS_TLS) { f.tls_supported = true; - f.tls_required = c.elementsByTagNameNS(NS_TLS, QLatin1String("required")).count() > 0; + f.tls_required = c.elementsByTagNameNS(NS_TLS, QLatin1String("required")).count() > 0; } else if (c.localName() == QLatin1String("mechanisms") && c.namespaceURI() == NS_SASL) { f.sasl_supported = true; - QDomNodeList l = c.elementsByTagNameNS(NS_SASL, QLatin1String("mechanism")); - for(int n = 0; n < l.count(); ++n) + QDomNodeList l = c.elementsByTagNameNS(NS_SASL, QLatin1String("mechanism")); + for (int n = 0; n < l.count(); ++n) f.sasl_mechs += l.item(n).toElement().text(); } else if (c.localName() == QLatin1String("compression") && c.namespaceURI() == NS_COMPRESS_FEATURE) { f.compress_supported = true; - QDomNodeList l = c.elementsByTagNameNS(NS_COMPRESS_FEATURE, QLatin1String("method")); - for(int n = 0; n < l.count(); ++n) + QDomNodeList l = c.elementsByTagNameNS(NS_COMPRESS_FEATURE, QLatin1String("method")); + for (int n = 0; n < l.count(); ++n) f.compression_mechs += l.item(n).toElement().text(); } else if (c.localName() == QLatin1String("bind") && c.namespaceURI() == NS_BIND) { @@ -1431,7 +1337,7 @@ bool CoreProtocol::normalStep(const QDomElement &e) } else if (c.localName() == QLatin1String("hosts") && c.namespaceURI() == NS_HOSTS) { QDomNodeList l = c.elementsByTagNameNS(NS_HOSTS, QLatin1String("host")); - for(int n = 0; n < l.count(); ++n) + for (int n = 0; n < l.count(); ++n) f.hosts += l.item(n).toElement().text(); hosts += f.hosts; @@ -1441,7 +1347,7 @@ bool CoreProtocol::normalStep(const QDomElement &e) } else if (c.localName() == QLatin1String("session") && c.namespaceURI() == NS_SESSION) { f.session_supported = true; - f.session_required = c.elementsByTagName(QLatin1String("optional")).count() == 0; + f.session_required = c.elementsByTagName(QLatin1String("optional")).count() == 0; // more details https://tools.ietf.org/html/draft-cridland-xmpp-session-01 } else { @@ -1449,341 +1355,315 @@ bool CoreProtocol::normalStep(const QDomElement &e) } } - if(f.tls_supported) { + if (f.tls_supported) { #ifdef XMPP_TEST QString s = "STARTTLS is available"; - if(f.tls_required) + if (f.tls_required) s += " (required)"; TD::msg(s); #endif } - if(f.sasl_supported) { + if (f.sasl_supported) { #ifdef XMPP_TEST QString s = "SASL mechs:"; - for(QStringList::ConstIterator it = f.sasl_mechs.begin(); it != f.sasl_mechs.end(); ++it) + for (QStringList::ConstIterator it = f.sasl_mechs.begin(); it != f.sasl_mechs.end(); ++it) s += QString(" [%1]").arg((*it)); TD::msg(s); #endif } - if(f.compress_supported) { + if (f.compress_supported) { #ifdef XMPP_TEST QString s = "Compression mechs:"; - for(QStringList::ConstIterator it = f.compression_mechs.begin(); it != f.compression_mechs.end(); ++it) + for (QStringList::ConstIterator it = f.compression_mechs.begin(); it != f.compression_mechs.end(); ++it) s += QString(" [%1]").arg((*it)); TD::msg(s); #endif } - event = EFeatures; - features = f; + event = EFeatures; + features = f; unhandledFeatures = unhandled; - step = HandleFeatures; + step = HandleFeatures; return true; - } - else { + } else { // ignore } - } - else if(step == GetTLSProceed) { + } else if (step == GetTLSProceed) { // waiting for proceed to starttls - if(e.namespaceURI() == NS_TLS) { - if(e.tagName() == "proceed") { + if (e.namespaceURI() == NS_TLS) { + if (e.tagName() == "proceed") { #ifdef XMPP_TEST TD::msg("Server wants us to proceed with ssl handshake"); #endif tls_started = true; - need = NStartTLS; - spare = resetStream(); - step = Start; + need = NStartTLS; + spare = resetStream(); + step = Start; return false; - } - else if(e.tagName() == "failure") { - event = EError; + } else if (e.tagName() == "failure") { + event = EError; errorCode = ErrStartTLS; return true; - } - else { - event = EError; + } else { + event = EError; errorCode = ErrProtocol; return true; } - } - else { + } else { // ignore } - } - else if(step == GetCompressProceed) { + } else if (step == GetCompressProceed) { // waiting for proceed to compression - if(e.namespaceURI() == NS_COMPRESS_PROTOCOL) { - if(e.tagName() == "compressed") { + if (e.namespaceURI() == NS_COMPRESS_PROTOCOL) { + if (e.tagName() == "compressed") { #ifdef XMPP_TEST TD::msg("Server wants us to proceed with compression"); #endif compress_started = true; - need = NCompress; - spare = resetStream(); - step = Start; + need = NCompress; + spare = resetStream(); + step = Start; return false; - } - else if(e.tagName() == "failure") { - event = EError; + } else if (e.tagName() == "failure") { + event = EError; errorCode = ErrCompress; return true; - } - else { - event = EError; + } else { + event = EError; errorCode = ErrProtocol; return true; } - } - else { + } else { // ignore } - } - else if(step == GetSASLChallenge) { + } else if (step == GetSASLChallenge) { // waiting for sasl challenge/success/fail - if(e.namespaceURI() == NS_SASL) { - if(e.tagName() == "challenge") { + if (e.namespaceURI() == NS_SASL) { + if (e.tagName() == "challenge") { QByteArray a = QCA::Base64().stringToArray(e.text()).toByteArray(); #ifdef XMPP_TEST TD::msg(QString("SASL IN: [%1]").arg(printArray(a))); #endif sasl_step = a; - need = NSASLNext; - step = GetSASLNext; + need = NSASLNext; + step = GetSASLNext; return false; - } - else if(e.tagName() == "success") { + } else if (e.tagName() == "success") { QString str = e.text(); // "additional data with success" ? - if(!str.isEmpty()) - { + if (!str.isEmpty()) { QByteArray a = QCA::Base64().stringToArray(str).toByteArray(); - sasl_step = a; - sasl_authed = true; - need = NSASLNext; - step = GetSASLNext; + sasl_step = a; + sasl_authed = true; + need = NSASLNext; + step = GetSASLNext; return false; } sasl_authed = true; - event = ESASLSuccess; - step = HandleSASLSuccess; + event = ESASLSuccess; + step = HandleSASLSuccess; return true; - } - else if(e.tagName() == "failure") { + } else if (e.tagName() == "failure") { QDomElement t = firstChildElement(e); - if(t.isNull() || t.namespaceURI() != NS_SASL) + if (t.isNull() || t.namespaceURI() != NS_SASL) errCond = -1; else errCond = stringToSASLCond(t.tagName()); // handle text elements - auto nodes = e.elementsByTagNameNS(NS_SASL, QLatin1String("text")); + auto nodes = e.elementsByTagNameNS(NS_SASL, QLatin1String("text")); decltype(errLangText) lt; for (int i = 0; i < nodes.count(); i++) { - auto e = nodes.item(i).toElement(); + auto e = nodes.item(i).toElement(); QString lang = e.attributeNS(NS_SASL, "lang", ""); lt.insert(lang, e.text()); } errLangText = lt; - event = EError; - errorCode = ErrAuth; + event = EError; + errorCode = ErrAuth; return true; - } - else { - event = EError; + } else { + event = EError; errorCode = ErrProtocol; return true; } } - } - else if(step == GetBindResponse) { - if(e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { + } else if (step == GetBindResponse) { + if (e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { QString type(e.attribute("type")); QString id(e.attribute("id")); - if(id == "bind_1" && (type == "result" || type == "error")) { - if(type == "result") { + if (id == "bind_1" && (type == "result" || type == "error")) { + if (type == "result") { QDomElement b = e.elementsByTagNameNS(NS_BIND, "bind").item(0).toElement(); - Jid j; - if(!b.isNull()) { + Jid j; + if (!b.isNull()) { QDomElement je = e.elementsByTagName("jid").item(0).toElement(); - j = je.text(); + j = je.text(); } - if(!j.isValid()) { - event = EError; + if (!j.isValid()) { + event = EError; errorCode = ErrProtocol; return true; } jid_ = j; return loginComplete(); - } - else { + } else { errCond = -1; QDomElement err = e.elementsByTagNameNS(NS_CLIENT, "error").item(0).toElement(); - if(!err.isNull()) { + if (!err.isNull()) { // get error condition QDomNodeList nl = err.childNodes(); - QDomElement t; - for(int n = 0; n < nl.count(); ++n) { + QDomElement t; + for (int n = 0; n < nl.count(); ++n) { QDomNode i = nl.item(n); - if(i.isElement()) { + if (i.isElement()) { t = i.toElement(); break; } } - if(!t.isNull() && t.namespaceURI() == NS_STANZAS) { + if (!t.isNull() && t.namespaceURI() == NS_STANZAS) { QString cond = t.tagName(); - if(cond == "not-allowed") + if (cond == "not-allowed") errCond = BindNotAllowed; - else if(cond == "conflict") + else if (cond == "conflict") errCond = BindConflict; } } - event = EError; + event = EError; errorCode = ErrBind; return true; } - } - else { + } else { // ignore } - } - else { + } else { // ignore } - } - else if(step == GetAuthGetResponse) { + } else if (step == GetAuthGetResponse) { // waiting for an iq - if(e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { - Jid from(e.attribute("from")); + if (e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { + Jid from(e.attribute("from")); QString type(e.attribute("type")); QString id(e.attribute("id")); bool okfrom = (from.isEmpty() || from.compare(Jid(to))); - if(okfrom && id == "auth_1" && (type == "result" || type == "error")) { - if(type == "result") { + if (okfrom && id == "auth_1" && (type == "result" || type == "error")) { + if (type == "result") { QDomElement q = e.elementsByTagNameNS("jabber:iq:auth", "query").item(0).toElement(); - if(q.isNull() || q.elementsByTagName("username").item(0).isNull() || q.elementsByTagName("resource").item(0).isNull()) { - event = EError; + if (q.isNull() || q.elementsByTagName("username").item(0).isNull() + || q.elementsByTagName("resource").item(0).isNull()) { + event = EError; errorCode = ErrProtocol; return true; } - bool plain_supported = !q.elementsByTagName("password").item(0).isNull(); + bool plain_supported = !q.elementsByTagName("password").item(0).isNull(); bool digest_supported = !q.elementsByTagName("digest").item(0).isNull(); - if(!digest_supported && !plain_supported) { - event = EError; + if (!digest_supported && !plain_supported) { + event = EError; errorCode = ErrProtocol; return true; } // plain text not allowed? - if(!digest_supported && !allowPlain) { - event = EError; + if (!digest_supported && !allowPlain) { + event = EError; errorCode = ErrPlain; return true; } digest = digest_supported; - need = NPassword; - step = HandleAuthSet; + need = NPassword; + step = HandleAuthSet; return false; - } - else { + } else { errCond = getOldErrorCode(e); - event = EError; + event = EError; errorCode = ErrAuth; return true; } - } - else { + } else { // ignore } - } - else { + } else { // ignore } - } - else if(step == GetAuthSetResponse) { + } else if (step == GetAuthSetResponse) { // waiting for an iq - if(e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { - Jid from(e.attribute("from")); + if (e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { + Jid from(e.attribute("from")); QString type(e.attribute("type")); QString id(e.attribute("id")); bool okfrom = (from.isEmpty() || from.compare(Jid(to))); - if(okfrom && id == "auth_2" && (type == "result" || type == "error")) { - if(type == "result") { + if (okfrom && id == "auth_2" && (type == "result" || type == "error")) { + if (type == "result") { return loginComplete(); - } - else { + } else { errCond = getOldErrorCode(e); - event = EError; + event = EError; errorCode = ErrAuth; return true; } - } - else { + } else { // ignore } - } - else { + } else { // ignore } } // server - else if(step == GetRequest) { + else if (step == GetRequest) { printf("get request: [%s], %s\n", e.namespaceURI().toLatin1().data(), e.tagName().toLatin1().data()); - if(e.namespaceURI() == NS_TLS && e.localName() == "starttls") { + if (e.namespaceURI() == NS_TLS && e.localName() == "starttls") { // TODO: don't let this be done twice QDomElement e = doc.createElementNS(NS_TLS, "proceed"); send(e, true); event = ESend; - step = HandleTLS; + step = HandleTLS; return true; } - if(e.namespaceURI() == NS_SASL) { - if(e.localName() == "auth") { - if(sasl_started) { + if (e.namespaceURI() == NS_SASL) { + if (e.localName() == "auth") { + if (sasl_started) { // TODO printf("error\n"); return false; } sasl_started = true; - sasl_mech = e.attribute("mechanism"); + sasl_mech = e.attribute("mechanism"); // TODO: if child text missing, don't pass it sasl_step = QCA::Base64().stringToArray(e.text()).toByteArray(); - need = NSASLFirst; - step = GetSASLNext; + need = NSASLFirst; + step = GetSASLNext; return false; - } - else { + } else { // TODO printf("unknown sasl tag\n"); return false; } } - if(e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { + if (e.namespaceURI() == NS_CLIENT && e.tagName() == "iq") { QDomElement b = e.elementsByTagNameNS(NS_BIND, "bind").item(0).toElement(); - if(!b.isNull()) { - QDomElement res = b.elementsByTagName("resource").item(0).toElement(); - QString resource = res.text(); + if (!b.isNull()) { + QDomElement res = b.elementsByTagName("resource").item(0).toElement(); + QString resource = res.text(); QDomElement r = doc.createElement("iq"); r.setAttribute("type", "result"); r.setAttribute("id", e.attribute("id")); QDomElement bind = doc.createElementNS(NS_BIND, "bind"); - QDomElement jid = doc.createElement("jid"); - Jid j = QString(user + '@' + host + '/' + resource); + QDomElement jid = doc.createElement("jid"); + Jid j = QString(user + '@' + host + '/' + resource); jid.appendChild(doc.createTextNode(j.full())); bind.appendChild(jid); r.appendChild(bind); @@ -1792,21 +1672,18 @@ bool CoreProtocol::normalStep(const QDomElement &e) event = ESend; // TODO return true; - } - else { + } else { // TODO } } - } - else if(step == GetSASLResponse) { - if(e.namespaceURI() == NS_SASL && e.localName() == "response") { + } else if (step == GetSASLResponse) { + if (e.namespaceURI() == NS_SASL && e.localName() == "response") { sasl_step = QCA::Base64().stringToArray(e.text()).toByteArray(); - need = NSASLNext; - step = GetSASLNext; + need = NSASLNext; + step = GetSASLNext; return false; } - } - else if(step == GetSMResponse) { + } else if (step == GetSMResponse) { #ifdef IRIS_SM_DEBUG qWarning() << "HandleSM: step"; #endif @@ -1824,9 +1701,9 @@ bool CoreProtocol::normalStep(const QDomElement &e) #endif QString location = e.attribute("location").trimmed(); if (!location.isEmpty()) { - int port_off = 0; + int port_off = 0; QStringRef sm_host; - int sm_port = 0; + int sm_port = 0; if (location.startsWith('[')) { // ipv6 port_off = location.indexOf(']'); if (port_off != -1) { // looks valid @@ -1849,11 +1726,11 @@ bool CoreProtocol::normalStep(const QDomElement &e) } // else resumption is not supported on this server needTimer(SM_TIMER_INTERVAL_SECS); event = EReady; - step = Done; + step = Done; return true; } else if (e.localName() == "resumed") { sm.resume(e.attribute("h").toULong()); - while(true) { + while (true) { QDomElement st = sm.getUnacknowledgedStanza(); if (st.isNull()) break; @@ -1861,12 +1738,12 @@ bool CoreProtocol::normalStep(const QDomElement &e) } needTimer(SM_TIMER_INTERVAL_SECS); event = EReady; - step = Done; + step = Done; return true; } else if (e.localName() == "failed") { if (sm.state().isResumption()) { // tried to resume? ok, then try to just enable sm.state().resumption_id.clear(); - //step = HandleFeatures; + // step = HandleFeatures; event = ESMResumeFailed; return true; } @@ -1874,11 +1751,11 @@ bool CoreProtocol::normalStep(const QDomElement &e) } } - if(isReady()) { + if (isReady()) { if (!e.isNull()) { - if(isValidStanza(e)) { + if (isValidStanza(e)) { stanzaToRecv = e; - event = EStanzaReady; + event = EStanzaReady; setIncomingAsExternal(); return true; } else if (sm.isActive()) { diff --git a/src/xmpp/xmpp-core/protocol.h b/src/xmpp/xmpp-core/protocol.h index 13cb6531..50608c6b 100644 --- a/src/xmpp/xmpp-core/protocol.h +++ b/src/xmpp/xmpp-core/protocol.h @@ -29,359 +29,348 @@ #include #include -#define NS_ETHERX "http://etherx.jabber.org/streams" -#define NS_CLIENT "jabber:client" -#define NS_SERVER "jabber:server" +#define NS_ETHERX "http://etherx.jabber.org/streams" +#define NS_CLIENT "jabber:client" +#define NS_SERVER "jabber:server" #define NS_DIALBACK "jabber:server:dialback" -#define NS_STREAMS "urn:ietf:params:xml:ns:xmpp-streams" -#define NS_TLS "urn:ietf:params:xml:ns:xmpp-tls" -#define NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" -#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session" -#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" -#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind" -#define NS_CAPS "http://jabber.org/protocol/caps" +#define NS_STREAMS "urn:ietf:params:xml:ns:xmpp-streams" +#define NS_TLS "urn:ietf:params:xml:ns:xmpp-tls" +#define NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl" +#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session" +#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" +#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind" +#define NS_CAPS "http://jabber.org/protocol/caps" #define NS_COMPRESS_FEATURE "http://jabber.org/features/compress" #define NS_COMPRESS_PROTOCOL "http://jabber.org/protocol/compress" -#define NS_HOSTS "http://barracuda.com/xmppextensions/hosts" +#define NS_HOSTS "http://barracuda.com/xmppextensions/hosts" namespace XMPP { - class Version - { - public: - Version(int maj=0, int min=0); +class Version { +public: + Version(int maj = 0, int min = 0); + + int major, minor; +}; + +class StreamFeatures { +public: + StreamFeatures(); + + bool tls_supported, sasl_supported, bind_supported, compress_supported; + bool tls_required; + bool sm_supported; + bool session_supported; + bool session_required; + QStringList sasl_mechs; + QStringList compression_mechs; + QStringList hosts; +}; + +class BasicProtocol : public XmlProtocol { +public: + // xmpp 1.0 error conditions // rfc6120 + enum SASLCond { + Aborted, // server confirms auth abort + AccountDisabled, // account temporrily disabled + CredentialsExpired, // credential expired + EncryptionRequired, // can't use mech without TLS + IncorrectEncoding, // Incorrect encoding. should not happen + InvalidAuthzid, // bad input JID + InvalidMech, // bad mechanism + MalformedRequest, // malformded request + MechTooWeak, // can't use mech with this authzid + NotAuthorized, // bad user, bad password, bad creditials + TemporaryAuthFailure, // please try again later! + }; + enum StreamCond { + BadFormat, + BadNamespacePrefix, + Conflict, + ConnectionTimeout, + HostGone, + HostUnknown, + ImproperAddressing, + InternalServerError, + InvalidFrom, + InvalidNamespace, + InvalidXml, + StreamNotAuthorized, + PolicyViolation, + RemoteConnectionFailed, + StreamReset, + ResourceConstraint, + RestrictedXml, + SeeOtherHost, + SystemShutdown, + UndefinedCondition, + UnsupportedEncoding, + UnsupportedStanzaType, + UnsupportedVersion, + NotWellFormed + }; + enum BindCond { BindBadRequest, BindNotAllowed, BindConflict }; + + // extend the XmlProtocol enums + enum Need { + NSASLMechs = XmlProtocol::NCustom, // need SASL mechlist + NStartTLS, // need to switch on TLS layer + NCompress, // need to switch on compression layer + NSASLFirst, // need SASL first step + NSASLNext, // need SASL next step + NSASLLayer, // need to switch on SASL layer + NCustom = XmlProtocol::NCustom + 10 + }; + enum Event { + EFeatures = XmlProtocol::ECustom, // breakpoint after features packet is received + ESASLSuccess, // breakpoint after successful sasl auth + EStanzaReady, // a stanza was received + EStanzaSent, // a stanza was sent + EReady, // stream is ready for stanza use + EAck, // received SM ack response from server + ECustom = XmlProtocol::ECustom + 10 + }; + enum Error { + ErrProtocol = XmlProtocol::ErrCustom, // there was an error in the xmpp-core protocol exchange + ErrStream, // , see errCond, errText, and errAppSpec for details + ErrStartTLS, // server refused starttls + ErrCompress, // server refused compression + ErrAuth, // authorization error. errCond holds sasl condition (or numeric code for old-protocol) + ErrBind, // server refused resource bind + ErrCustom = XmlProtocol::ErrCustom + 10 + }; - int major, minor; + BasicProtocol(); + ~BasicProtocol(); + + void reset(); + + // for outgoing xml + QDomDocument doc; + + // sasl-related + QString saslMech() const; + QByteArray saslStep() const; + void setSASLMechList(const QStringList &list); + void setSASLFirst(const QString &mech, const QByteArray &step); + void setSASLNext(const QByteArray &step); + void setSASLAuthed(); + + // send / recv + void sendStanza(const QDomElement &e); + void sendDirect(const QString &s); + void sendWhitespace(); + void clearSendQueue(); + QDomElement recvStanza(); + + // shutdown + void shutdown(); + void shutdownWithError(int cond, const QString &otherHost = ""); + + // information + QString to, from, id, lang; + Version version; + + // error output + int errCond; + QString errText; + QHash errLangText; + QDomElement errAppSpec; + QString otherHost; + + QByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer + + bool isReady() const; + + enum { TypeElement, TypeStanza, TypeDirect, TypePing }; + +protected: + static int stringToSASLCond(const QString &s); + static int stringToStreamCond(const QString &s); + static QString saslCondToString(int); + static QString streamCondToString(int); + + void send(const QDomElement &e, bool clip = false); + void sendUrgent(const QDomElement &e, bool clip = false); + void sendStreamError(int cond, const QString &text = "", const QDomElement &appSpec = QDomElement()); + void sendStreamError(const QString &text); // old-style + + bool errorAndClose(int cond, const QString &text = "", const QDomElement &appSpec = QDomElement()); + bool error(int code); + void delayErrorAndClose(int cond, const QString &text = "", const QDomElement &appSpec = QDomElement()); + void delayError(int code); + + // reimplemented + QDomElement docElement(); + void handleDocOpen(const Parser::Event &pe); + bool handleError(); + bool handleCloseFinished(); + bool doStep(const QDomElement &e); + void itemWritten(int id, int size); + + virtual QString defaultNamespace(); + virtual QStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...] + virtual void handleStreamOpen(const Parser::Event &pe); + virtual bool doStep2(const QDomElement &e) = 0; + + void setReady(bool b); + + QString sasl_mech; + QStringList sasl_mechlist; + QByteArray sasl_step; + bool sasl_authed; + + QDomElement stanzaToRecv; + +private: + struct SASLCondEntry { + const char *str; + int cond; }; + static SASLCondEntry saslCondTable[]; - class StreamFeatures - { - public: - StreamFeatures(); - - bool tls_supported, sasl_supported, bind_supported, compress_supported; - bool tls_required; - bool sm_supported; - bool session_supported; - bool session_required; - QStringList sasl_mechs; - QStringList compression_mechs; - QStringList hosts; + struct StreamCondEntry { + const char *str; + int cond; }; + static StreamCondEntry streamCondTable[]; - class BasicProtocol : public XmlProtocol - { - public: - // xmpp 1.0 error conditions // rfc6120 - enum SASLCond { - Aborted, // server confirms auth abort - AccountDisabled, // account temporrily disabled - CredentialsExpired, // credential expired - EncryptionRequired, // can't use mech without TLS - IncorrectEncoding, // Incorrect encoding. should not happen - InvalidAuthzid, // bad input JID - InvalidMech, // bad mechanism - MalformedRequest, // malformded request - MechTooWeak, // can't use mech with this authzid - NotAuthorized, // bad user, bad password, bad creditials - TemporaryAuthFailure, // please try again later! - }; - enum StreamCond { - BadFormat, - BadNamespacePrefix, - Conflict, - ConnectionTimeout, - HostGone, - HostUnknown, - ImproperAddressing, - InternalServerError, - InvalidFrom, - InvalidNamespace, - InvalidXml, - StreamNotAuthorized, - PolicyViolation, - RemoteConnectionFailed, - StreamReset, - ResourceConstraint, - RestrictedXml, - SeeOtherHost, - SystemShutdown, - UndefinedCondition, - UnsupportedEncoding, - UnsupportedStanzaType, - UnsupportedVersion, - NotWellFormed - }; - enum BindCond { - BindBadRequest, - BindNotAllowed, - BindConflict - }; - - // extend the XmlProtocol enums - enum Need { - NSASLMechs = XmlProtocol::NCustom, // need SASL mechlist - NStartTLS, // need to switch on TLS layer - NCompress, // need to switch on compression layer - NSASLFirst, // need SASL first step - NSASLNext, // need SASL next step - NSASLLayer, // need to switch on SASL layer - NCustom = XmlProtocol::NCustom+10 - }; - enum Event { - EFeatures = XmlProtocol::ECustom, // breakpoint after features packet is received - ESASLSuccess, // breakpoint after successful sasl auth - EStanzaReady, // a stanza was received - EStanzaSent, // a stanza was sent - EReady, // stream is ready for stanza use - EAck, // received SM ack response from server - ECustom = XmlProtocol::ECustom+10 - }; - enum Error { - ErrProtocol = XmlProtocol::ErrCustom, // there was an error in the xmpp-core protocol exchange - ErrStream, // , see errCond, errText, and errAppSpec for details - ErrStartTLS, // server refused starttls - ErrCompress, // server refused compression - ErrAuth, // authorization error. errCond holds sasl condition (or numeric code for old-protocol) - ErrBind, // server refused resource bind - ErrCustom = XmlProtocol::ErrCustom+10 - }; - - BasicProtocol(); - ~BasicProtocol(); - - void reset(); - - // for outgoing xml - QDomDocument doc; - - // sasl-related - QString saslMech() const; - QByteArray saslStep() const; - void setSASLMechList(const QStringList &list); - void setSASLFirst(const QString &mech, const QByteArray &step); - void setSASLNext(const QByteArray &step); - void setSASLAuthed(); - - // send / recv - void sendStanza(const QDomElement &e); - void sendDirect(const QString &s); - void sendWhitespace(); - void clearSendQueue(); - QDomElement recvStanza(); - - // shutdown - void shutdown(); - void shutdownWithError(int cond, const QString &otherHost=""); - - // information - QString to, from, id, lang; - Version version; - - // error output - int errCond; - QString errText; - QHash errLangText; - QDomElement errAppSpec; - QString otherHost; - - QByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer - - bool isReady() const; - - enum { TypeElement, TypeStanza, TypeDirect, TypePing }; - - protected: - static int stringToSASLCond(const QString &s); - static int stringToStreamCond(const QString &s); - static QString saslCondToString(int); - static QString streamCondToString(int); - - void send(const QDomElement &e, bool clip=false); - void sendUrgent(const QDomElement &e, bool clip=false); - void sendStreamError(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); - void sendStreamError(const QString &text); // old-style - - bool errorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); - bool error(int code); - void delayErrorAndClose(int cond, const QString &text="", const QDomElement &appSpec=QDomElement()); - void delayError(int code); - - // reimplemented - QDomElement docElement(); - void handleDocOpen(const Parser::Event &pe); - bool handleError(); - bool handleCloseFinished(); - bool doStep(const QDomElement &e); - void itemWritten(int id, int size); - - virtual QString defaultNamespace(); - virtual QStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...] - virtual void handleStreamOpen(const Parser::Event &pe); - virtual bool doStep2(const QDomElement &e)=0; - - void setReady(bool b); - - QString sasl_mech; - QStringList sasl_mechlist; - QByteArray sasl_step; - bool sasl_authed; - - QDomElement stanzaToRecv; - - private: - struct SASLCondEntry - { - const char *str; - int cond; - }; - static SASLCondEntry saslCondTable[]; - - struct StreamCondEntry - { - const char *str; - int cond; - }; - static StreamCondEntry streamCondTable[]; - - struct SendItem - { - QDomElement stanzaToSend; - QString stringToSend; - bool doWhitespace; - }; - QList sendList; - - bool doShutdown, delayedError, closeError, ready; - int stanzasPending, stanzasWritten; - - void init(); - void extractStreamError(const QDomElement &e); + struct SendItem { + QDomElement stanzaToSend; + QString stringToSend; + bool doWhitespace; + }; + QList sendList; + + bool doShutdown, delayedError, closeError, ready; + int stanzasPending, stanzasWritten; + + void init(); + void extractStreamError(const QDomElement &e); +}; + +class CoreProtocol : public BasicProtocol { +public: + enum { + NPassword = NCustom, // need password for old-mode + EDBVerify = ECustom, // breakpoint after db:verify request + ErrPlain = ErrCustom // server only supports plain, but allowPlain is false locally }; - class CoreProtocol : public BasicProtocol - { + CoreProtocol(); + ~CoreProtocol(); + + void reset(); + void needTimer(int seconds); + + // reimplemented to do SM + void sendStanza(const QDomElement &e); + + void startClientOut(const Jid &jid, bool oldOnly, bool tlsActive, bool doAuth, bool doCompression); + void startServerOut(const QString &to); + void startDialbackOut(const QString &to, const QString &from); + void startDialbackVerifyOut(const QString &to, const QString &from, const QString &id, const QString &key); + void startClientIn(const QString &id); + void startServerIn(const QString &id); + + void setLang(const QString &s); + void setAllowTLS(bool b); + void setAllowBind(bool b); + void setAllowPlain(bool b); // old-mode + const Jid &jid() const; + + void setPassword(const QString &s); + void setFrom(const QString &s); + void setDialbackKey(const QString &s); + + // input + QString user, host; + + // status + bool old; + + StreamFeatures features; + QList unhandledFeatures; + QStringList hosts; + + // static QString xmlToString(const QDomElement &e, bool clip=false); + + StreamManagement sm; + + class DBItem { public: - enum { - NPassword = NCustom, // need password for old-mode - EDBVerify = ECustom, // breakpoint after db:verify request - ErrPlain = ErrCustom // server only supports plain, but allowPlain is false locally - }; - - CoreProtocol(); - ~CoreProtocol(); - - void reset(); - void needTimer(int seconds); - - // reimplemented to do SM - void sendStanza(const QDomElement &e); - - void startClientOut(const Jid &jid, bool oldOnly, bool tlsActive, bool doAuth, bool doCompression); - void startServerOut(const QString &to); - void startDialbackOut(const QString &to, const QString &from); - void startDialbackVerifyOut(const QString &to, const QString &from, const QString &id, const QString &key); - void startClientIn(const QString &id); - void startServerIn(const QString &id); - - void setLang(const QString &s); - void setAllowTLS(bool b); - void setAllowBind(bool b); - void setAllowPlain(bool b); // old-mode - const Jid& jid() const; - - void setPassword(const QString &s); - void setFrom(const QString &s); - void setDialbackKey(const QString &s); - - // input - QString user, host; - - // status - bool old; - - StreamFeatures features; - QList unhandledFeatures; - QStringList hosts; - - //static QString xmlToString(const QDomElement &e, bool clip=false); - - StreamManagement sm; - - class DBItem - { - public: - enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated }; - int type; - Jid to, from; - QString key, id; - bool ok; - }; - private: - enum Step { - Start, - Done, - SendFeatures, - GetRequest, - HandleTLS, - GetSASLResponse, - IncHandleSASLSuccess, - GetFeatures, // read features packet - HandleFeatures, // act on features, by initiating tls, sasl, or bind - GetTLSProceed, // read tls response - GetCompressProceed, // read compression response - GetSASLFirst, // perform sasl first step using provided data - GetSASLChallenge, // read server sasl challenge - GetSASLNext, // perform sasl next step using provided data - HandleSASLSuccess, // handle what must be done after reporting sasl success - GetBindResponse, // read bind response - HandleAuthGet, // send old-protocol auth-get - GetAuthGetResponse, // read auth-get response - HandleAuthSet, // send old-protocol auth-set - GetAuthSetResponse, // read auth-set response - GetSMResponse // read SM init response - }; - - QList dbrequests, dbpending, dbvalidated; - - bool server, dialback, dialback_verify; - int step; - - bool digest; - bool tls_started, sasl_started, compress_started; - - Jid jid_; - bool oldOnly; - bool allowPlain; - bool doTLS, doAuth, doBinding, doCompress; - QString password; - - QString dialback_id, dialback_key; - QString self_from; - - void init(); - static int getOldErrorCode(const QDomElement &e); - bool loginComplete(); - - bool isValidStanza(const QDomElement &e) const; - bool streamManagementHandleStanza(const QDomElement &e); - bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item); - bool normalStep(const QDomElement &e); - bool dialbackStep(const QDomElement &e); - - bool needSMRequest(); - - // reimplemented - bool stepAdvancesParser() const; - bool stepRequiresElement() const; - void stringSend(const QString &s); - void stringRecv(const QString &s); - QString defaultNamespace(); - QStringList extraNamespaces(); - void handleStreamOpen(const Parser::Event &pe); - bool doStep2(const QDomElement &e); - void elementSend(const QDomElement &e); - void elementRecv(const QDomElement &e); + enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated }; + int type; + Jid to, from; + QString key, id; + bool ok; }; + +private: + enum Step { + Start, + Done, + SendFeatures, + GetRequest, + HandleTLS, + GetSASLResponse, + IncHandleSASLSuccess, + GetFeatures, // read features packet + HandleFeatures, // act on features, by initiating tls, sasl, or bind + GetTLSProceed, // read tls response + GetCompressProceed, // read compression response + GetSASLFirst, // perform sasl first step using provided data + GetSASLChallenge, // read server sasl challenge + GetSASLNext, // perform sasl next step using provided data + HandleSASLSuccess, // handle what must be done after reporting sasl success + GetBindResponse, // read bind response + HandleAuthGet, // send old-protocol auth-get + GetAuthGetResponse, // read auth-get response + HandleAuthSet, // send old-protocol auth-set + GetAuthSetResponse, // read auth-set response + GetSMResponse // read SM init response + }; + + QList dbrequests, dbpending, dbvalidated; + + bool server, dialback, dialback_verify; + int step; + + bool digest; + bool tls_started, sasl_started, compress_started; + + Jid jid_; + bool oldOnly; + bool allowPlain; + bool doTLS, doAuth, doBinding, doCompress; + QString password; + + QString dialback_id, dialback_key; + QString self_from; + + void init(); + static int getOldErrorCode(const QDomElement &e); + bool loginComplete(); + + bool isValidStanza(const QDomElement &e) const; + bool streamManagementHandleStanza(const QDomElement &e); + bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item); + bool normalStep(const QDomElement &e); + bool dialbackStep(const QDomElement &e); + + bool needSMRequest(); + + // reimplemented + bool stepAdvancesParser() const; + bool stepRequiresElement() const; + void stringSend(const QString &s); + void stringRecv(const QString &s); + QString defaultNamespace(); + QStringList extraNamespaces(); + void handleStreamOpen(const Parser::Event &pe); + bool doStep2(const QDomElement &e); + void elementSend(const QDomElement &e); + void elementRecv(const QDomElement &e); +}; } // namespace XMPP #endif // PROTOCOL_H diff --git a/src/xmpp/xmpp-core/securestream.cpp b/src/xmpp/xmpp-core/securestream.cpp index 74cf9238..0f648e3f 100644 --- a/src/xmpp/xmpp-core/securestream.cpp +++ b/src/xmpp/xmpp-core/securestream.cpp @@ -39,11 +39,9 @@ //---------------------------------------------------------------------------- // LayerTracker //---------------------------------------------------------------------------- -class LayerTracker -{ +class LayerTracker { public: - struct Item - { + struct Item { int plain; int encoded; }; @@ -53,16 +51,13 @@ class LayerTracker void reset(); void addPlain(int plain); void specifyEncoded(int encoded, int plain); - int finished(int encoded); + int finished(int encoded); - int p; + int p; QList list; }; -LayerTracker::LayerTracker() -{ - p = 0; -} +LayerTracker::LayerTracker() { p = 0; } void LayerTracker::reset() { @@ -70,19 +65,16 @@ void LayerTracker::reset() list.clear(); } -void LayerTracker::addPlain(int plain) -{ - p += plain; -} +void LayerTracker::addPlain(int plain) { p += plain; } void LayerTracker::specifyEncoded(int encoded, int plain) { // can't specify more bytes than we have - if(plain > p) + if (plain > p) plain = p; p -= plain; Item i; - i.plain = plain; + i.plain = plain; i.encoded = encoded; list += i; } @@ -90,11 +82,11 @@ void LayerTracker::specifyEncoded(int encoded, int plain) int LayerTracker::finished(int encoded) { int plain = 0; - for(QList::Iterator it = list.begin(); it != list.end();) { + for (QList::Iterator it = list.begin(); it != list.end();) { Item &i = *it; // not enough? - if(encoded < i.encoded) { + if (encoded < i.encoded) { i.encoded -= encoded; break; } @@ -109,14 +101,13 @@ int LayerTracker::finished(int encoded) //---------------------------------------------------------------------------- // SecureStream //---------------------------------------------------------------------------- -class SecureLayer : public QObject -{ +class SecureLayer : public QObject { Q_OBJECT public: enum { TLS, SASL, TLSH, Compression }; int type; union { - QCA::TLS *tls; + QCA::TLS * tls; QCA::SASL *sasl; #ifdef USE_TLSHANDLER XMPP::TLSHandler *tlsHandler; @@ -124,12 +115,12 @@ class SecureLayer : public QObject CompressionHandler *compressionHandler; } p; LayerTracker layer; - bool tls_done; - int prebytes; + bool tls_done; + int prebytes; SecureLayer(QCA::TLS *t) { - type = TLS; + type = TLS; p.tls = t; init(); connect(p.tls, SIGNAL(handshaken()), SLOT(tls_handshaken())); @@ -141,7 +132,7 @@ class SecureLayer : public QObject SecureLayer(QCA::SASL *s) { - type = SASL; + type = SASL; p.sasl = s; init(); connect(p.sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead())); @@ -152,7 +143,7 @@ class SecureLayer : public QObject SecureLayer(CompressionHandler *t) { t->setParent(this); // automatically clean up CompressionHandler when SecureLayer is destroyed - type = Compression; + type = Compression; p.compressionHandler = t; init(); connect(p.compressionHandler, SIGNAL(readyRead()), SLOT(compressionHandler_readyRead())); @@ -163,14 +154,15 @@ class SecureLayer : public QObject #ifdef USE_TLSHANDLER SecureLayer(XMPP::TLSHandler *t) { - type = TLSH; + type = TLSH; p.tlsHandler = t; init(); connect(p.tlsHandler, SIGNAL(success()), SLOT(tlsHandler_success())); connect(p.tlsHandler, SIGNAL(fail()), SLOT(tlsHandler_fail())); connect(p.tlsHandler, SIGNAL(closed()), SLOT(tlsHandler_closed())); connect(p.tlsHandler, SIGNAL(readyRead(QByteArray)), SLOT(tlsHandler_readyRead(QByteArray))); - connect(p.tlsHandler, SIGNAL(readyReadOutgoing(QByteArray,int)), SLOT(tlsHandler_readyReadOutgoing(QByteArray,int))); + connect(p.tlsHandler, SIGNAL(readyReadOutgoing(QByteArray, int)), + SLOT(tlsHandler_readyReadOutgoing(QByteArray, int))); } #endif @@ -183,25 +175,49 @@ class SecureLayer : public QObject void write(const QByteArray &a) { layer.addPlain(a.size()); - switch(type) { - case TLS: { p.tls->write(a); break; } - case SASL: { p.sasl->write(a); break; } + switch (type) { + case TLS: { + p.tls->write(a); + break; + } + case SASL: { + p.sasl->write(a); + break; + } #ifdef USE_TLSHANDLER - case TLSH: { p.tlsHandler->write(a); break; } + case TLSH: { + p.tlsHandler->write(a); + break; + } #endif - case Compression: { p.compressionHandler->write(a); break; } + case Compression: { + p.compressionHandler->write(a); + break; + } } } void writeIncoming(const QByteArray &a) { - switch(type) { - case TLS: { p.tls->writeIncoming(a); break; } - case SASL: { p.sasl->writeIncoming(a); break; } + switch (type) { + case TLS: { + p.tls->writeIncoming(a); + break; + } + case SASL: { + p.sasl->writeIncoming(a); + break; + } #ifdef USE_TLSHANDLER - case TLSH: { p.tlsHandler->writeIncoming(a); break; } + case TLSH: { + p.tlsHandler->writeIncoming(a); + break; + } #endif - case Compression: { p.compressionHandler->writeIncoming(a); break; } + case Compression: { + p.compressionHandler->writeIncoming(a); + break; + } } } @@ -210,13 +226,12 @@ class SecureLayer : public QObject int written = 0; // deal with prebytes (bytes sent prior to this security layer) - if(prebytes > 0) { - if(prebytes >= plain) { + if (prebytes > 0) { + if (prebytes >= plain) { written += plain; prebytes -= plain; plain = 0; - } - else { + } else { written += prebytes; plain -= prebytes; prebytes = 0; @@ -224,7 +239,7 @@ class SecureLayer : public QObject } // put remainder into the layer tracker - if(type == SASL || tls_done) + if (type == SASL || tls_done) written += layer.finished(plain); return written; @@ -253,7 +268,7 @@ private slots: void tls_readyReadOutgoing(int plainBytes) { QByteArray a = p.tls->readOutgoing(); - if(tls_done) + if (tls_done) layer.specifyEncoded(a.size(), plainBytes); needWrite(a); } @@ -264,10 +279,7 @@ private slots: tlsClosed(a); } - void tls_error(int x) - { - error(x); - } + void tls_error(int x) { error(x); } void sasl_readyRead() { @@ -277,16 +289,13 @@ private slots: void sasl_readyReadOutgoing() { - int plainBytes; + int plainBytes; QByteArray a = p.sasl->readOutgoing(&plainBytes); layer.specifyEncoded(a.size(), plainBytes); needWrite(a); } - void sasl_error() - { - error(p.sasl->errorCode()); - } + void sasl_error() { error(p.sasl->errorCode()); } void compressionHandler_readyRead() { @@ -296,16 +305,13 @@ private slots: void compressionHandler_readyReadOutgoing() { - int plainBytes; + int plainBytes; QByteArray a = p.compressionHandler->readOutgoing(&plainBytes); layer.specifyEncoded(a.size(), plainBytes); needWrite(a); } - void compressionHandler_error() - { - error(p.compressionHandler->errorCode()); - } + void compressionHandler_error() { error(p.compressionHandler->errorCode()); } #ifdef USE_TLSHANDLER void tlsHandler_success() @@ -314,24 +320,15 @@ private slots: tlsHandshaken(); } - void tlsHandler_fail() - { - error(0); - } + void tlsHandler_fail() { error(0); } - void tlsHandler_closed() - { - tlsClosed(QByteArray()); - } + void tlsHandler_closed() { tlsClosed(QByteArray()); } - void tlsHandler_readyRead(const QByteArray &a) - { - readyRead(a); - } + void tlsHandler_readyRead(const QByteArray &a) { readyRead(a); } void tlsHandler_readyReadOutgoing(const QByteArray &a, int plainBytes) { - if(tls_done) + if (tls_done) layer.specifyEncoded(a.size(), plainBytes); needWrite(a); } @@ -340,22 +337,21 @@ private slots: #include "securestream.moc" -class SecureStream::Private -{ +class SecureStream::Private { public: - ByteStream *bs; - QList layers; - int pending; - int errorCode; - bool active; - bool topInProgress; + ByteStream * bs; + QList layers; + int pending; + int errorCode; + bool active; + bool topInProgress; bool haveTLS() const { - foreach(SecureLayer *s, layers) { - if(s->type == SecureLayer::TLS + foreach (SecureLayer *s, layers) { + if (s->type == SecureLayer::TLS #ifdef USE_TLSHANDLER - || s->type == SecureLayer::TLSH + || s->type == SecureLayer::TLSH #endif ) { return true; @@ -366,8 +362,8 @@ class SecureStream::Private bool haveSASL() const { - foreach(SecureLayer *s, layers) { - if(s->type == SecureLayer::SASL) + foreach (SecureLayer *s, layers) { + if (s->type == SecureLayer::SASL) return true; } return false; @@ -375,8 +371,8 @@ class SecureStream::Private bool haveCompress() const { - foreach(SecureLayer *s, layers) { - if(s->type == SecureLayer::Compression) + foreach (SecureLayer *s, layers) { + if (s->type == SecureLayer::Compression) return true; } return false; @@ -389,8 +385,7 @@ class SecureStream::Private } }; -SecureStream::SecureStream(ByteStream *s) -:ByteStream(nullptr) +SecureStream::SecureStream(ByteStream *s) : ByteStream(nullptr) { d = new Private; @@ -398,8 +393,8 @@ SecureStream::SecureStream(ByteStream *s) connect(d->bs, SIGNAL(readyRead()), SLOT(bs_readyRead())); connect(d->bs, SIGNAL(bytesWritten(qint64)), SLOT(bs_bytesWritten(qint64))); - d->pending = 0; - d->active = true; + d->pending = 0; + d->active = true; d->topInProgress = false; setOpenMode(QIODevice::ReadWrite); } @@ -422,7 +417,7 @@ void SecureStream::linkLayer(QObject *s) int SecureStream::calcPrebytes() const { int x = 0; - foreach(SecureLayer *s, d->layers) { + foreach (SecureLayer *s, d->layers) { x += s->prebytes; } return (d->pending - x); @@ -430,11 +425,11 @@ int SecureStream::calcPrebytes() const void SecureStream::startTLSClient(QCA::TLS *t, const QByteArray &spare) { - if(!d->active || d->topInProgress || d->haveTLS()) + if (!d->active || d->topInProgress || d->haveTLS()) return; SecureLayer *s = new SecureLayer(t); - s->prebytes = calcPrebytes(); + s->prebytes = calcPrebytes(); linkLayer(s); d->layers.append(s); d->topInProgress = true; @@ -444,11 +439,11 @@ void SecureStream::startTLSClient(QCA::TLS *t, const QByteArray &spare) void SecureStream::startTLSServer(QCA::TLS *t, const QByteArray &spare) { - if(!d->active || d->topInProgress || d->haveTLS()) + if (!d->active || d->topInProgress || d->haveTLS()) return; SecureLayer *s = new SecureLayer(t); - s->prebytes = calcPrebytes(); + s->prebytes = calcPrebytes(); linkLayer(s); d->layers.append(s); d->topInProgress = true; @@ -456,13 +451,13 @@ void SecureStream::startTLSServer(QCA::TLS *t, const QByteArray &spare) insertData(spare); } -void SecureStream::setLayerCompress(const QByteArray& spare) +void SecureStream::setLayerCompress(const QByteArray &spare) { - if(!d->active || d->topInProgress || d->haveCompress()) + if (!d->active || d->topInProgress || d->haveCompress()) return; SecureLayer *s = new SecureLayer(new CompressionHandler()); - s->prebytes = calcPrebytes(); + s->prebytes = calcPrebytes(); linkLayer(s); d->layers.append(s); @@ -471,11 +466,11 @@ void SecureStream::setLayerCompress(const QByteArray& spare) void SecureStream::setLayerSASL(QCA::SASL *sasl, const QByteArray &spare) { - if(!d->active || d->topInProgress || d->haveSASL()) + if (!d->active || d->topInProgress || d->haveSASL()) return; SecureLayer *s = new SecureLayer(sasl); - s->prebytes = calcPrebytes(); + s->prebytes = calcPrebytes(); linkLayer(s); d->layers.append(s); @@ -485,11 +480,11 @@ void SecureStream::setLayerSASL(QCA::SASL *sasl, const QByteArray &spare) #ifdef USE_TLSHANDLER void SecureStream::startTLSClient(XMPP::TLSHandler *t, const QString &server, const QByteArray &spare) { - if(!d->active || d->topInProgress || d->haveTLS()) + if (!d->active || d->topInProgress || d->haveTLS()) return; SecureLayer *s = new SecureLayer(t); - s->prebytes = calcPrebytes(); + s->prebytes = calcPrebytes(); linkLayer(s); d->layers.append(s); d->topInProgress = true; @@ -505,25 +500,19 @@ void SecureStream::closeTLS() { if (!d->layers.isEmpty()) { SecureLayer *s = d->layers.last(); - if(s->type == SecureLayer::TLS) { + if (s->type == SecureLayer::TLS) { s->p.tls->close(); } } } -int SecureStream::errorCode() const -{ - return d->errorCode; -} +int SecureStream::errorCode() const { return d->errorCode; } -bool SecureStream::isOpen() const -{ - return d->active; -} +bool SecureStream::isOpen() const { return d->active; } void SecureStream::write(const QByteArray &a) { - if(!isOpen()) { + if (!isOpen()) { qDebug("Writing to closed stream!"); return; } @@ -534,16 +523,12 @@ void SecureStream::write(const QByteArray &a) if (!d->layers.isEmpty()) { SecureLayer *s = d->layers.last(); s->write(a); - } - else { + } else { writeRawData(a); } } -qint64 SecureStream::bytesToWrite() const -{ - return d->pending; -} +qint64 SecureStream::bytesToWrite() const { return d->pending; } void SecureStream::bs_readyRead() { @@ -553,19 +538,18 @@ void SecureStream::bs_readyRead() if (!d->layers.isEmpty()) { SecureLayer *s = d->layers.first(); s->writeIncoming(a); - } - else { + } else { incomingData(a); } } void SecureStream::bs_bytesWritten(qint64 bytes) { - foreach(SecureLayer *s, d->layers) { + foreach (SecureLayer *s, d->layers) { bytes = s->finished(bytes); } - if(bytes > 0) { + if (bytes > 0) { d->pending -= bytes; bytesWritten(bytes); } @@ -587,9 +571,9 @@ void SecureStream::layer_tlsClosed(const QByteArray &) void SecureStream::layer_readyRead(const QByteArray &a) { - SecureLayer *s = static_cast(sender()); - QList::Iterator it(d->layers.begin()); - while((*it) != s) { + SecureLayer * s = static_cast(sender()); + QList::Iterator it(d->layers.begin()); + while ((*it) != s) { Q_ASSERT(it != d->layers.end()); ++it; } @@ -600,17 +584,16 @@ void SecureStream::layer_readyRead(const QByteArray &a) if (it != d->layers.end()) { s = (*it); s->writeIncoming(a); - } - else { + } else { incomingData(a); } } void SecureStream::layer_needWrite(const QByteArray &a) { - SecureLayer *s = static_cast(sender()); - QList::Iterator it(d->layers.begin()); - while((*it) != s) { + SecureLayer * s = static_cast(sender()); + QList::Iterator it(d->layers.begin()); + while ((*it) != s) { Q_ASSERT(it != d->layers.end()); ++it; } @@ -621,51 +604,46 @@ void SecureStream::layer_needWrite(const QByteArray &a) --it; s = (*it); s->write(a); - } - else { + } else { writeRawData(a); } } void SecureStream::layer_error(int x) { - SecureLayer *s = static_cast(sender()); - int type = s->type; - d->errorCode = x; + SecureLayer *s = static_cast(sender()); + int type = s->type; + d->errorCode = x; setOpenMode(QIODevice::NotOpen); d->active = false; d->deleteLayers(); - if(type == SecureLayer::TLS) + if (type == SecureLayer::TLS) setError(ErrTLS); - else if(type == SecureLayer::SASL) + else if (type == SecureLayer::SASL) setError(ErrSASL); #ifdef USE_TLSHANDLER - else if(type == SecureLayer::TLSH) + else if (type == SecureLayer::TLSH) setError(ErrTLS); #endif } void SecureStream::insertData(const QByteArray &a) { - if(!a.isEmpty()) { + if (!a.isEmpty()) { if (!d->layers.isEmpty()) { SecureLayer *s = d->layers.last(); s->writeIncoming(a); - } - else { + } else { incomingData(a); } } } -void SecureStream::writeRawData(const QByteArray &a) -{ - d->bs->write(a); -} +void SecureStream::writeRawData(const QByteArray &a) { d->bs->write(a); } void SecureStream::incomingData(const QByteArray &a) { appendRead(a); - if(bytesAvailable()) + if (bytesAvailable()) emit readyRead(); } diff --git a/src/xmpp/xmpp-core/securestream.h b/src/xmpp/xmpp-core/securestream.h index 6abc2ca6..15f16401 100644 --- a/src/xmpp/xmpp-core/securestream.h +++ b/src/xmpp/xmpp-core/securestream.h @@ -27,34 +27,33 @@ #define USE_TLSHANDLER #ifdef USE_TLSHANDLER namespace XMPP { - class TLSHandler; +class TLSHandler; } #endif class CompressionHandler; -class SecureStream : public ByteStream -{ +class SecureStream : public ByteStream { Q_OBJECT public: enum Error { ErrTLS = ErrCustom, ErrSASL }; SecureStream(ByteStream *s); ~SecureStream(); - void startTLSClient(QCA::TLS *t, const QByteArray &spare=QByteArray()); - void startTLSServer(QCA::TLS *t, const QByteArray &spare=QByteArray()); - void setLayerCompress(const QByteArray &spare=QByteArray()); - void setLayerSASL(QCA::SASL *s, const QByteArray &spare=QByteArray()); + void startTLSClient(QCA::TLS *t, const QByteArray &spare = QByteArray()); + void startTLSServer(QCA::TLS *t, const QByteArray &spare = QByteArray()); + void setLayerCompress(const QByteArray &spare = QByteArray()); + void setLayerSASL(QCA::SASL *s, const QByteArray &spare = QByteArray()); #ifdef USE_TLSHANDLER - void startTLSClient(XMPP::TLSHandler *t, const QString &server, const QByteArray &spare=QByteArray()); + void startTLSClient(XMPP::TLSHandler *t, const QString &server, const QByteArray &spare = QByteArray()); #endif void closeTLS(); - int errorCode() const; + int errorCode() const; // reimplemented - bool isOpen() const; - void write(const QByteArray &); + bool isOpen() const; + void write(const QByteArray &); qint64 bytesToWrite() const; signals: @@ -73,7 +72,7 @@ private slots: private: void linkLayer(QObject *); - int calcPrebytes() const; + int calcPrebytes() const; void insertData(const QByteArray &a); void writeRawData(const QByteArray &a); void incomingData(const QByteArray &a); diff --git a/src/xmpp/xmpp-core/simplesasl.cpp b/src/xmpp/xmpp-core/simplesasl.cpp index c17930c8..4194a9aa 100644 --- a/src/xmpp/xmpp-core/simplesasl.cpp +++ b/src/xmpp/xmpp-core/simplesasl.cpp @@ -37,85 +37,77 @@ #include namespace XMPP { -class SimpleSASLContext : public QCA::SASLContext -{ +class SimpleSASLContext : public QCA::SASLContext { Q_OBJECT public: - class ParamsMutable - { - public: - /** - User is held - */ - bool user; - - /** - Authorization ID is held - */ - bool authzid; - - /** - Password is held - */ - bool pass; - - /** - Realm is held - */ - bool realm; - }; + class ParamsMutable { + public: + /** + User is held + */ + bool user; + + /** + Authorization ID is held + */ + bool authzid; + + /** + Password is held + */ + bool pass; + + /** + Realm is held + */ + bool realm; + }; // core props QString service, host; // state - int step; - bool capable; - bool allow_plain; + int step; + bool capable; + bool allow_plain; QByteArray out_buf, in_buf; - QString mechanism_; - QString out_mech; - - ParamsMutable need; - ParamsMutable have; - QString user, authz, realm; - QCA::SecureArray pass; - Result result_; + QString mechanism_; + QString out_mech; + + ParamsMutable need; + ParamsMutable have; + QString user, authz, realm; + QCA::SecureArray pass; + Result result_; QCA::SASL::AuthCondition authCondition_; - QByteArray result_to_net_, result_to_app_; - int encoded_; + QByteArray result_to_net_, result_to_app_; + int encoded_; // scram specific stuff - QByteArray client_first_message; + QByteArray client_first_message; QCA::SecureArray server_signature; - SimpleSASLContext(QCA::Provider* p) : QCA::SASLContext(p) - { - reset(); - } + SimpleSASLContext(QCA::Provider *p) : QCA::SASLContext(p) { reset(); } - ~SimpleSASLContext() - { - reset(); - } + ~SimpleSASLContext() { reset(); } void reset() { resetState(); - capable = true; - allow_plain = false; - need.user = false; + capable = true; + allow_plain = false; + need.user = false; need.authzid = false; - need.pass = false; - need.realm = false; - have.user = false; + need.pass = false; + need.realm = false; + have.user = false; have.authzid = false; - have.pass = false; - have.realm = false; - user = QString(); - authz = QString(); - pass = QCA::SecureArray(); - realm = QString(); + have.pass = false; + have.realm = false; + user = QString(); + authz = QString(); + pass = QCA::SecureArray(); + realm = QString(); } void resetState() @@ -125,24 +117,30 @@ class SimpleSASLContext : public QCA::SASLContext authCondition_ = QCA::SASL::AuthFail; } - virtual void setConstraints(QCA::SASL::AuthFlags flags, int ssfMin, int) { - if(flags & (QCA::SASL::RequireForwardSecrecy | QCA::SASL::RequirePassCredentials | QCA::SASL::RequireMutualAuth) || ssfMin > 0) + virtual void setConstraints(QCA::SASL::AuthFlags flags, int ssfMin, int) + { + if (flags + & (QCA::SASL::RequireForwardSecrecy | QCA::SASL::RequirePassCredentials | QCA::SASL::RequireMutualAuth) + || ssfMin > 0) capable = false; else capable = true; allow_plain = flags & QCA::SASL::AllowPlain; } - virtual void setup(const QString& _service, const QString& _host, const QCA::SASLContext::HostPort*, const QCA::SASLContext::HostPort*, const QString&, int) { + virtual void setup(const QString &_service, const QString &_host, const QCA::SASLContext::HostPort *, + const QCA::SASLContext::HostPort *, const QString &, int) + { service = _service; - host = _host; + host = _host; } - virtual void startClient(const QStringList &mechlist, bool allowClientSendFirst) { + virtual void startClient(const QStringList &mechlist, bool allowClientSendFirst) + { Q_UNUSED(allowClientSendFirst); mechanism_ = QString(); - foreach(QString mech, mechlist) { + foreach (QString mech, mechlist) { if (mech == "SCRAM-SHA-1") { mechanism_ = "SCRAM-SHA-1"; break; @@ -155,8 +153,8 @@ class SimpleSASLContext : public QCA::SASLContext mechanism_ = "PLAIN"; } - if(!capable || mechanism_.isEmpty()) { - result_ = Error; + if (!capable || mechanism_.isEmpty()) { + result_ = Error; authCondition_ = QCA::SASL::NoMechanism; if (!capable) qWarning("simplesasl.cpp: Not enough capabilities"); @@ -168,34 +166,36 @@ class SimpleSASLContext : public QCA::SASLContext resetState(); result_ = Continue; - step = 0; + step = 0; tryAgain(); } - virtual void nextStep(const QByteArray &from_net) { + virtual void nextStep(const QByteArray &from_net) + { in_buf = from_net; tryAgain(); } - virtual void tryAgain() { + virtual void tryAgain() + { // All exits of the method must emit the ready signal // so all exits go through a goto ready; - if(step == 0) { + if (step == 0) { out_mech = mechanism_; // PLAIN if (out_mech == "PLAIN" || out_mech == "SCRAM-SHA-1") { // First, check if we have everything - if(need.user || need.pass) { + if (need.user || need.pass) { qWarning("simplesasl.cpp: Did not receive necessary auth parameters"); result_ = Error; goto ready; } - if(!have.user) + if (!have.user) need.user = true; - if(!have.pass) + if (!have.pass) need.pass = true; - if(need.user || need.pass) { + if (need.user || need.pass) { result_ = Params; goto ready; } @@ -206,7 +206,7 @@ class SimpleSASLContext : public QCA::SASLContext // send client-first-message SCRAMSHA1Message msg(authz, user, QByteArray(0, ' '), RandRandomNumberGenerator()); if (msg.isValid()) { - out_buf = msg.getValue(); + out_buf = msg.getValue(); client_first_message = out_buf; } else { qWarning("simplesasl.cpp: SASLprep failed."); @@ -219,32 +219,33 @@ class SimpleSASLContext : public QCA::SASLContext result_ = Success; else result_ = Continue; - } else if(step == 1) { + } else if (step == 1) { Q_ASSERT(out_mech != "PLAIN"); if (out_mech == "DIGEST-MD5") { // if we still need params, then the app has failed us! - if(need.user || need.authzid || need.pass || need.realm) { + if (need.user || need.authzid || need.pass || need.realm) { qWarning("simplesasl.cpp: Did not receive necessary auth parameters"); result_ = Error; goto ready; } // see if some params are needed - if(!have.user) + if (!have.user) need.user = true; - //if(!have.authzid) + // if(!have.authzid) // need.authzid = true; - if(!have.pass) + if (!have.pass) need.pass = true; - if(need.user || need.authzid || need.pass) { + if (need.user || need.authzid || need.pass) { result_ = Params; goto ready; } - DIGESTMD5Response response(in_buf, service, host, realm, user, authz, pass.toByteArray(), RandRandomNumberGenerator()); + DIGESTMD5Response response(in_buf, service, host, realm, user, authz, pass.toByteArray(), + RandRandomNumberGenerator()); if (!response.isValid()) { authCondition_ = QCA::SASL::BadProtocol; - result_ = Error; + result_ = Error; goto ready; } out_buf = response.getValue(); @@ -252,38 +253,39 @@ class SimpleSASLContext : public QCA::SASLContext result_ = Continue; } else if (out_mech == "SCRAM-SHA-1") { // if we still need params, then the app has failed us! - if(need.user || need.pass) { + if (need.user || need.pass) { qWarning("simplesasl.cpp: Did not receive necessary auth parameters"); result_ = Error; goto ready; } // see if some params are needed - if(!have.user) + if (!have.user) need.user = true; - //if(!have.authzid) + // if(!have.authzid) // need.authzid = true; - if(!have.pass) + if (!have.pass) need.pass = true; - if(need.user || need.pass) { + if (need.user || need.pass) { result_ = Params; goto ready; } // parse server-first-message, send client-final-message QVariant prop = property("scram-salted-password-base64"); - QString salted_password_base64; + QString salted_password_base64; if (prop.isValid()) { salted_password_base64 = prop.toString(); } - SCRAMSHA1Response response(in_buf, pass.toByteArray(), client_first_message, salted_password_base64, RandRandomNumberGenerator()); + SCRAMSHA1Response response(in_buf, pass.toByteArray(), client_first_message, salted_password_base64, + RandRandomNumberGenerator()); if (!response.isValid()) { authCondition_ = QCA::SASL::BadProtocol; - result_ = Error; + result_ = Error; goto ready; } setProperty("scram-salted-password-base64", QVariant(response.getSaltedPassword())); server_signature = response.getServerSignature(); - out_buf = response.getValue(); + out_buf = response.getValue(); ++step; result_ = Continue; } @@ -295,7 +297,7 @@ class SimpleSASLContext : public QCA::SASLContext } else { qWarning() << "ServerSignature doesn't match the one we've calculated."; authCondition_ = QCA::SASL::AuthFail; - result_ = Error; + result_ = Error; goto ready; } } @@ -309,87 +311,72 @@ class SimpleSASLContext : public QCA::SASLContext out_buf.resize(0); result_ = Success; } -ready: + ready: QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection); } - virtual void update(const QByteArray &from_net, const QByteArray &from_app) { + virtual void update(const QByteArray &from_net, const QByteArray &from_app) + { result_to_app_ = from_net; result_to_net_ = from_app; - encoded_ = from_app.size(); - result_ = Success; + encoded_ = from_app.size(); + result_ = Success; QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection); } - virtual bool waitForResultsReady(int msecs) { + virtual bool waitForResultsReady(int msecs) + { // TODO: for now, all operations block anyway Q_UNUSED(msecs); return true; } - virtual Result result() const { - return result_; - } + virtual Result result() const { return result_; } - virtual QStringList mechlist() const { - return QStringList(); - } + virtual QStringList mechlist() const { return QStringList(); } - virtual QString mech() const { - return out_mech; - } + virtual QString mech() const { return out_mech; } - virtual bool haveClientInit() const { - return out_mech == "PLAIN"; - } + virtual bool haveClientInit() const { return out_mech == "PLAIN"; } - virtual QByteArray stepData() const { - return out_buf; - } + virtual QByteArray stepData() const { return out_buf; } - virtual QByteArray to_net() { - return result_to_net_; - } + virtual QByteArray to_net() { return result_to_net_; } - virtual int encoded() const { - return encoded_; - } + virtual int encoded() const { return encoded_; } - virtual QByteArray to_app() { - return result_to_app_; - } + virtual QByteArray to_app() { return result_to_app_; } - virtual int ssf() const { - return 0; - } + virtual int ssf() const { return 0; } - virtual QCA::SASL::AuthCondition authCondition() const { - return authCondition_; - } + virtual QCA::SASL::AuthCondition authCondition() const { return authCondition_; } - virtual QCA::SASL::Params clientParams() const { + virtual QCA::SASL::Params clientParams() const + { return QCA::SASL::Params(need.user, need.authzid, need.pass, need.realm); } - virtual void setClientParams(const QString *_user, const QString *_authzid, const QCA::SecureArray *_pass, const QString *_realm) { - if(_user) { - user = *_user; + virtual void setClientParams(const QString *_user, const QString *_authzid, const QCA::SecureArray *_pass, + const QString *_realm) + { + if (_user) { + user = *_user; need.user = false; have.user = true; } - if(_authzid) { - authz = *_authzid; + if (_authzid) { + authz = *_authzid; need.authzid = false; have.authzid = true; } - if(_pass) { - pass = *_pass; + if (_pass) { + pass = *_pass; need.pass = false; have.pass = true; } - if(_realm) { - realm = *_realm; + if (_realm) { + realm = *_realm; need.realm = false; have.realm = true; } @@ -401,65 +388,50 @@ class SimpleSASLContext : public QCA::SASLContext return QStringList(); } - virtual QString username() const { - return QString(); - } + virtual QString username() const { return QString(); } - virtual QString authzid() const { - return QString(); - } + virtual QString authzid() const { return QString(); } - virtual QCA::Provider::Context* clone() const { - SimpleSASLContext* s = new SimpleSASLContext(provider()); + virtual QCA::Provider::Context *clone() const + { + SimpleSASLContext *s = new SimpleSASLContext(provider()); // TODO: Copy all the members return s; } - virtual void startServer(const QString &, bool) { - result_ = QCA::SASLContext::Error; + virtual void startServer(const QString &, bool) + { + result_ = QCA::SASLContext::Error; QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection); } - virtual void serverFirstStep(const QString &, const QByteArray *) { - result_ = QCA::SASLContext::Error; + virtual void serverFirstStep(const QString &, const QByteArray *) + { + result_ = QCA::SASLContext::Error; QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection); } - }; -class QCASimpleSASL : public QCA::Provider -{ +class QCASimpleSASL : public QCA::Provider { public: QCASimpleSASL() {} ~QCASimpleSASL() {} - void init() - { - } + void init() {} - QString name() const { - return "simplesasl"; - } + QString name() const { return "simplesasl"; } - QStringList features() const { - return QStringList("sasl"); - } + QStringList features() const { return QStringList("sasl"); } - QCA::Provider::Context* createContext(const QString& cap) + QCA::Provider::Context *createContext(const QString &cap) { - if(cap == "sasl") + if (cap == "sasl") return new SimpleSASLContext(this); return nullptr; } - int qcaVersion() const - { - return QCA_VERSION; - } + int qcaVersion() const { return QCA_VERSION; } }; -QCA::Provider *createProviderSimpleSASL() -{ - return (new QCASimpleSASL); -} +QCA::Provider *createProviderSimpleSASL() { return (new QCASimpleSASL); } } // namespace XMPP #include "simplesasl.moc" diff --git a/src/xmpp/xmpp-core/simplesasl.h b/src/xmpp/xmpp-core/simplesasl.h index fb880cf0..62acf1dd 100644 --- a/src/xmpp/xmpp-core/simplesasl.h +++ b/src/xmpp/xmpp-core/simplesasl.h @@ -21,11 +21,11 @@ #define SIMPLESASL_H namespace QCA { - class Provider; +class Provider; } namespace XMPP { - QCA::Provider* createProviderSimpleSASL(); +QCA::Provider *createProviderSimpleSASL(); } #endif // SIMPLESASL_H diff --git a/src/xmpp/xmpp-core/sm.cpp b/src/xmpp/xmpp-core/sm.cpp index 7ed53e3e..2f42c539 100644 --- a/src/xmpp/xmpp-core/sm.cpp +++ b/src/xmpp/xmpp-core/sm.cpp @@ -36,27 +36,23 @@ SMState::SMState() void SMState::resetCounters() { - received_count = 0; + received_count = 0; server_last_handled = 0; send_queue.clear(); } -StreamManagement::StreamManagement(QObject *parent) - : QObject(parent) - , sm_started(false) - , sm_resumed(false) - , sm_stanzas_notify(0) - , sm_resend_pos(0) +StreamManagement::StreamManagement(QObject *parent) : + QObject(parent), sm_started(false), sm_resumed(false), sm_stanzas_notify(0), sm_resend_pos(0) { } void StreamManagement::reset() { - sm_started = false; - sm_resumed = false; - sm_stanzas_notify = 0; - sm_resend_pos = 0; - sm_timeout_data.elapsed_timer = QElapsedTimer(); + sm_started = false; + sm_resumed = false; + sm_stanzas_notify = 0; + sm_resend_pos = 0; + sm_timeout_data.elapsed_timer = QElapsedTimer(); sm_timeout_data.waiting_answer = false; } @@ -65,13 +61,13 @@ void StreamManagement::start(const QString &resumption_id) reset(); state_.resetCounters(); state_.resumption_id = resumption_id; - sm_started = true; + sm_started = true; sm_timeout_data.elapsed_timer.start(); } void StreamManagement::resume(quint32 last_handled) { - sm_resumed = true; + sm_resumed = true; sm_resend_pos = 0; processAcknowledgement(last_handled); sm_timeout_data.waiting_answer = false; @@ -90,7 +86,7 @@ int StreamManagement::lastAckElapsed() const return 0; int msecs = sm_timeout_data.elapsed_timer.elapsed(); - int secs = msecs / 1000; + int secs = msecs / 1000; if (msecs % 1000 != 0) ++secs; return secs; @@ -98,7 +94,7 @@ int StreamManagement::lastAckElapsed() const int StreamManagement::takeAckedCount() { - int cnt = sm_stanzas_notify; + int cnt = sm_stanzas_notify; sm_stanzas_notify = 0; return cnt; } @@ -147,7 +143,8 @@ void StreamManagement::processAcknowledgement(quint32 last_handled) if (f) { qDebug() << "Stream Management: [INF] Send queue length is changed: " << state_.send_queue.length(); if (state_.send_queue.isEmpty() && last_handled != state_.server_last_handled) - qDebug() << "Stream Management: [ERR] Send queue is empty but last_handled != server_last_handled " << last_handled << state_.server_last_handled; + qDebug() << "Stream Management: [ERR] Send queue is empty but last_handled != server_last_handled " + << last_handled << state_.server_last_handled; } #endif } diff --git a/src/xmpp/xmpp-core/sm.h b/src/xmpp/xmpp-core/sm.h index 0be89a4f..26fb5ac3 100644 --- a/src/xmpp/xmpp-core/sm.h +++ b/src/xmpp/xmpp-core/sm.h @@ -25,67 +25,65 @@ #include #include -#define NS_STREAM_MANAGEMENT "urn:xmpp:sm:3" +#define NS_STREAM_MANAGEMENT "urn:xmpp:sm:3" #define SM_TIMER_INTERVAL_SECS 40 //#define IRIS_SM_DEBUG namespace XMPP { - class SMState - { - public: - SMState(); - void resetCounters(); - bool isResumption() const { return !resumption_id.isEmpty(); } - bool isEnabled() const { return enabled; } - bool isLocationValid() { return !resumption_location.host.isEmpty() && resumption_location.port != 0; } - void setEnabled(bool e) { enabled = e; } +class SMState { +public: + SMState(); + void resetCounters(); + bool isResumption() const { return !resumption_id.isEmpty(); } + bool isEnabled() const { return enabled; } + bool isLocationValid() { return !resumption_location.host.isEmpty() && resumption_location.port != 0; } + void setEnabled(bool e) { enabled = e; } - public: - bool enabled; - quint32 received_count; - quint32 server_last_handled; - QQueue send_queue; - QString resumption_id; - struct { - QString host; - quint16 port; - } resumption_location; - }; +public: + bool enabled; + quint32 received_count; + quint32 server_last_handled; + QQueue send_queue; + QString resumption_id; + struct { + QString host; + quint16 port; + } resumption_location; +}; - class StreamManagement : QObject - { - public: - StreamManagement(QObject *parent = nullptr); - XMPP::SMState &state() { return state_; } - const XMPP::SMState &state() const { return state_; } - bool isActive() const { return sm_started || sm_resumed; } - bool isResumed() const { return sm_resumed; } - void reset(); - void start(const QString &resumption_id); - void resume(quint32 last_handled); - void setLocation(const QString &host, int port); - int lastAckElapsed() const; - int takeAckedCount(); - void countInputRawData(int bytes); - QDomElement getUnacknowledgedStanza(); - int addUnacknowledgedStanza(const QDomElement &e); - void processAcknowledgement(quint32 last_handled); - void markStanzaHandled(); - QDomElement generateRequestStanza(QDomDocument &doc); - QDomElement makeResponseStanza(QDomDocument &doc); +class StreamManagement : QObject { +public: + StreamManagement(QObject *parent = nullptr); + XMPP::SMState & state() { return state_; } + const XMPP::SMState &state() const { return state_; } + bool isActive() const { return sm_started || sm_resumed; } + bool isResumed() const { return sm_resumed; } + void reset(); + void start(const QString &resumption_id); + void resume(quint32 last_handled); + void setLocation(const QString &host, int port); + int lastAckElapsed() const; + int takeAckedCount(); + void countInputRawData(int bytes); + QDomElement getUnacknowledgedStanza(); + int addUnacknowledgedStanza(const QDomElement &e); + void processAcknowledgement(quint32 last_handled); + void markStanzaHandled(); + QDomElement generateRequestStanza(QDomDocument &doc); + QDomElement makeResponseStanza(QDomDocument &doc); - private: - SMState state_; - bool sm_started; - bool sm_resumed; - int sm_stanzas_notify; - int sm_resend_pos; - struct { - QElapsedTimer elapsed_timer; - bool waiting_answer = false; - } sm_timeout_data; - }; +private: + SMState state_; + bool sm_started; + bool sm_resumed; + int sm_stanzas_notify; + int sm_resend_pos; + struct { + QElapsedTimer elapsed_timer; + bool waiting_answer = false; + } sm_timeout_data; +}; } // namespace XMPP #endif // XMPP_SM_H diff --git a/src/xmpp/xmpp-core/stream.cpp b/src/xmpp/xmpp-core/stream.cpp index 5e468d80..68dac8b8 100644 --- a/src/xmpp/xmpp-core/stream.cpp +++ b/src/xmpp/xmpp-core/stream.cpp @@ -43,13 +43,13 @@ #include "bytestream.h" #ifndef NO_IRISNET -# include "irisnetglobal_p.h" +#include "irisnetglobal_p.h" #endif #include "protocol.h" #include "securestream.h" #include "simplesasl.h" #ifdef XMPP_TEST -# include "td.h" +#include "td.h" #endif #include @@ -67,24 +67,21 @@ using namespace XMPP; static Debug *debug_ptr = nullptr; -void XMPP::setDebug(Debug *p) -{ - debug_ptr = p; -} +void XMPP::setDebug(Debug *p) { debug_ptr = p; } static QByteArray randomArray(int size) { QByteArray a; a.resize(size); - for(int n = 0; n < size; ++n) - a[n] = (char)(256.0*rand()/(RAND_MAX+1.0)); + for (int n = 0; n < size; ++n) + a[n] = (char)(256.0 * rand() / (RAND_MAX + 1.0)); return a; } static QString genId() { // need SHA1 here - //if(!QCA::isSupported(QCA::CAP_SHA1)) + // if(!QCA::isSupported(QCA::CAP_SHA1)) // QCA::insertProvider(createProviderHash()); return QCA::Hash("sha1").hashToString(randomArray(128)); @@ -94,29 +91,20 @@ static QString genId() // Stream //---------------------------------------------------------------------------- static XmlProtocol *foo = nullptr; -Stream::Stream(QObject *parent) -:QObject(parent) -{ -} +Stream::Stream(QObject *parent) : QObject(parent) {} -Stream::~Stream() -{ -} +Stream::~Stream() {} Stanza Stream::createStanza(Stanza::Kind k, const Jid &to, const QString &type, const QString &id) { return Stanza(this, k, to, type, id); } -Stanza Stream::createStanza(const QDomElement &e) -{ - return Stanza(this, e); -} +Stanza Stream::createStanza(const QDomElement &e) { return Stanza(this, e); } QString Stream::xmlToString(const QDomElement &e, bool clip) { - if(!foo) - { + if (!foo) { foo = new CoreProtocol; #ifndef NO_IRISNET irisNetAddPostRoutine(cleanup); @@ -134,71 +122,58 @@ void Stream::cleanup() //---------------------------------------------------------------------------- // ClientStream //---------------------------------------------------------------------------- -enum { - Idle, - Connecting, - WaitVersion, - WaitTLS, - NeedParams, - AuthAbort, - Active, - Closing -}; +enum { Idle, Connecting, WaitVersion, WaitTLS, NeedParams, AuthAbort, Active, Closing }; -enum { - Client, - Server -}; +enum { Client, Server }; -class ClientStream::Private -{ +class ClientStream::Private { public: Private() = default; void reset() { - state = Idle; - notify = 0; + state = Idle; + notify = 0; newStanzas = false; - sasl_ssf = 0; + sasl_ssf = 0; tls_warned = false; - using_tls = false; + using_tls = false; } - Jid jid; - QString server; - bool oldOnly = false; - bool mutualAuth = false; - AllowPlainType allowPlain = NoAllowPlain; - bool haveLocalAddr = false; - QHostAddress localAddr; - quint16 localPort; - QString connectHost; - int minimumSSF = 0; - int maximumSSF = 0; - QString sasl_mech; - QMap mechProviders; // mech to provider map - bool doBinding = true; + Jid jid; + QString server; + bool oldOnly = false; + bool mutualAuth = false; + AllowPlainType allowPlain = NoAllowPlain; + bool haveLocalAddr = false; + QHostAddress localAddr; + quint16 localPort; + QString connectHost; + int minimumSSF = 0; + int maximumSSF = 0; + QString sasl_mech; + QMap mechProviders; // mech to provider map + bool doBinding = true; bool in_rrsig = false; - Connector *conn = nullptr; - ByteStream *bs = nullptr; - TLSHandler *tlsHandler = nullptr; - QCA::TLS *tls = nullptr; - QCA::SASL *sasl = nullptr; - SecureStream *ss = nullptr; - CoreProtocol client; - CoreProtocol srv; - QString lang; + Connector * conn = nullptr; + ByteStream * bs = nullptr; + TLSHandler * tlsHandler = nullptr; + QCA::TLS * tls = nullptr; + QCA::SASL * sasl = nullptr; + SecureStream *ss = nullptr; + CoreProtocol client; + CoreProtocol srv; + QString lang; QString defRealm; - int mode; - int state = Idle; - int notify = 0; + int mode; + int state = Idle; + int notify = 0; bool newStanzas = false; - int sasl_ssf = 0; + int sasl_ssf = 0; bool tls_warned = false; bool using_tls; bool doAuth; @@ -206,23 +181,22 @@ class ClientStream::Private QStringList sasl_mechlist; - int errCond; - QString errText; - QHash errLangText; // xml:lang => error text - QDomElement errAppSpec; + int errCond; + QString errText; + QHash errLangText; // xml:lang => error text + QDomElement errAppSpec; - QList in; + QList in; QTimer timeout_timer; QTimer noopTimer; - int noop_time; - bool quiet_reconnection = false; + int noop_time; + bool quiet_reconnection = false; }; -ClientStream::ClientStream(Connector *conn, TLSHandler *tlsHandler, QObject *parent) -:Stream(parent) +ClientStream::ClientStream(Connector *conn, TLSHandler *tlsHandler, QObject *parent) : Stream(parent) { - d = new Private; + d = new Private; d->mode = Client; d->conn = conn; connect(d->conn, SIGNAL(connected()), SLOT(cr_connected())); @@ -234,12 +208,13 @@ ClientStream::ClientStream(Connector *conn, TLSHandler *tlsHandler, QObject *par d->tlsHandler = tlsHandler; } -ClientStream::ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls, QObject *parent) -:Stream(parent) +ClientStream::ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls, + QObject *parent) : + Stream(parent) { - d = new Private; + d = new Private; d->mode = Server; - d->bs = bs; + d->bs = bs; connect(d->bs, SIGNAL(connectionClosed()), SLOT(bs_connectionClosed())); connect(d->bs, SIGNAL(delayedCloseFinished()), SLOT(bs_delayedCloseFinished())); connect(d->bs, SIGNAL(error(int)), SLOT(bs_error(int))); @@ -253,32 +228,32 @@ ClientStream::ClientStream(const QString &host, const QString &defRealm, ByteStr connect(d->ss, SIGNAL(tlsClosed()), SLOT(ss_tlsClosed())); connect(d->ss, SIGNAL(error(int)), SLOT(ss_error(int))); - d->server = host; + d->server = host; d->defRealm = defRealm; d->tls = tls; d->srv.startClientIn(genId()); - //d->srv.startServerIn(genId()); - //d->state = Connecting; - //d->jid = Jid(); - //d->server = QString(); + // d->srv.startServerIn(genId()); + // d->state = Connecting; + // d->jid = Jid(); + // d->server = QString(); connect(&(d->timeout_timer), SIGNAL(timeout()), SLOT(sm_timeout())); } ClientStream::~ClientStream() { - //fprintf(stderr, "\tClientStream::~ClientStream\n"); - //fflush(stderr); + // fprintf(stderr, "\tClientStream::~ClientStream\n"); + // fflush(stderr); reset(); delete d; } void ClientStream::reset(bool all) { - //fprintf(stderr, "\tClientStream::reset\n"); - //fflush(stderr); + // fprintf(stderr, "\tClientStream::reset\n"); + // fflush(stderr); d->reset(); d->noopTimer.stop(); @@ -291,7 +266,7 @@ void ClientStream::reset(bool all) delete d->sasl; d->sasl = nullptr; - if(all) { + if (all) { while (!d->in.isEmpty()) { delete d->in.takeFirst(); } @@ -303,14 +278,14 @@ void ClientStream::reset(bool all) } // client - if(d->mode == Client) { + if (d->mode == Client) { // reset tls // FIXME: Temporarily disabled - //if(d->tlsHandler) + // if(d->tlsHandler) // d->tlsHandler->reset(); // reset connector - if(d->bs) { + if (d->bs) { d->bs->close(); d->bs = nullptr; } @@ -321,10 +296,10 @@ void ClientStream::reset(bool all) } // server else { - if(d->tls) + if (d->tls) d->tls->reset(); - if(d->bs) { + if (d->bs) { d->bs->close(); d->bs = nullptr; } @@ -333,16 +308,13 @@ void ClientStream::reset(bool all) } } -Jid ClientStream::jid() const -{ - return d->jid; -} +Jid ClientStream::jid() const { return d->jid; } void ClientStream::connectToServer(const Jid &jid, bool auth) { reset(true); - d->state = Connecting; - d->jid = jid; + d->state = Connecting; + d->jid = jid; d->doAuth = auth; d->server = d->jid.domain(); @@ -351,18 +323,17 @@ void ClientStream::connectToServer(const Jid &jid, bool auth) void ClientStream::continueAfterWarning() { - if(d->state == WaitVersion) { + if (d->state == WaitVersion) { // if we don't have TLS yet, then we're never going to get it - if(!d->tls_warned && !d->using_tls) { + if (!d->tls_warned && !d->using_tls) { d->tls_warned = true; - d->state = WaitTLS; + d->state = WaitTLS; warning(WarnNoTLS); return; } d->state = Connecting; processNext(); - } - else if(d->state == WaitTLS) { + } else if (d->state == WaitTLS) { d->state = Connecting; processNext(); } @@ -374,54 +345,46 @@ void ClientStream::accept() processNext(); } -bool ClientStream::isActive() const -{ - return (d->state != Idle) ? true: false; -} +bool ClientStream::isActive() const { return (d->state != Idle) ? true : false; } -bool ClientStream::isAuthenticated() const -{ - return (d->state == Active) ? true: false; -} +bool ClientStream::isAuthenticated() const { return (d->state == Active) ? true : false; } void ClientStream::setUsername(const QString &s) { - if(d->sasl) + if (d->sasl) d->sasl->setUsername(s); } void ClientStream::setPassword(const QString &s) { - if(d->client.old) { + if (d->client.old) { d->client.setPassword(s); - } - else { - if(d->sasl) + } else { + if (d->sasl) d->sasl->setPassword(QCA::SecureArray(s.toUtf8())); } } void ClientStream::setRealm(const QString &s) { - if(d->sasl) + if (d->sasl) d->sasl->setRealm(s); } void ClientStream::setAuthzid(const QString &s) { - if(d->sasl) + if (d->sasl) d->sasl->setAuthzid(s); } void ClientStream::continueAfterParams() { - if(d->state == NeedParams) { + if (d->state == NeedParams) { d->state = Connecting; - if(d->client.old) { + if (d->client.old) { processNext(); - } - else { - if(d->sasl) + } else { + if (d->sasl) d->sasl->continueAfterParams(); } } else if (d->state == AuthAbort) { @@ -439,15 +402,9 @@ void ClientStream::abortAuth() d->state = AuthAbort; } -void ClientStream::setSaslMechanismProvider(const QString &m, const QString &p) -{ - d->mechProviders.insert(m, p); -} +void ClientStream::setSaslMechanismProvider(const QString &m, const QString &p) { d->mechProviders.insert(m, p); } -QString ClientStream::saslMechanismProvider(const QString &m) const -{ - return d->mechProviders.value(m); -} +QString ClientStream::saslMechanismProvider(const QString &m) const { return d->mechProviders.value(m); } QCA::Provider::Context *ClientStream::currentSASLContext() const { @@ -457,14 +414,16 @@ QCA::Provider::Context *ClientStream::currentSASLContext() const return nullptr; } -void ClientStream::setSCRAMStoredSaltedHash(const QString &s) { +void ClientStream::setSCRAMStoredSaltedHash(const QString &s) +{ QCA::SASLContext *context = (QCA::SASLContext *)(d->sasl->context()); if (context) { context->setProperty("scram-salted-password-base64", s); } } -const QString ClientStream::getSCRAMStoredSaltedHash() { +const QString ClientStream::getSCRAMStoredSaltedHash() +{ QCA::SASLContext *context = (QCA::SASLContext *)(d->sasl->context()); if (context) { return context->property("scram-salted-password-base64").toString(); @@ -472,113 +431,67 @@ const QString ClientStream::getSCRAMStoredSaltedHash() { return QString(); } -void ClientStream::setResourceBinding(bool b) -{ - d->doBinding = b; -} +void ClientStream::setResourceBinding(bool b) { d->doBinding = b; } -void ClientStream::setLang(const QString& lang) -{ - d->lang = lang; -} +void ClientStream::setLang(const QString &lang) { d->lang = lang; } void ClientStream::setNoopTime(int mills) { d->noop_time = mills; - if(d->state != Active) + if (d->state != Active) return; - if(d->noop_time == 0) { + if (d->noop_time == 0) { d->noopTimer.stop(); return; } d->noopTimer.start(d->noop_time); } -QString ClientStream::saslMechanism() const -{ - return d->client.saslMech(); -} +QString ClientStream::saslMechanism() const { return d->client.saslMech(); } -int ClientStream::saslSSF() const -{ - return d->sasl_ssf; -} +int ClientStream::saslSSF() const { return d->sasl_ssf; } -void ClientStream::setSASLMechanism(const QString &s) -{ - d->sasl_mech = s; -} +void ClientStream::setSASLMechanism(const QString &s) { d->sasl_mech = s; } void ClientStream::setLocalAddr(const QHostAddress &addr, quint16 port) { d->haveLocalAddr = true; - d->localAddr = addr; - d->localPort = port; + d->localAddr = addr; + d->localPort = port; } -void ClientStream::setCompress(bool compress) -{ - d->doCompress = compress; -} +void ClientStream::setCompress(bool compress) { d->doCompress = compress; } -int ClientStream::errorCondition() const -{ - return d->errCond; -} +int ClientStream::errorCondition() const { return d->errCond; } -QString ClientStream::errorText() const -{ - return d->errText; -} +QString ClientStream::errorText() const { return d->errText; } -QHash ClientStream::errorLangText() const -{ - return d->errLangText; -} +QHash ClientStream::errorLangText() const { return d->errLangText; } -QDomElement ClientStream::errorAppSpec() const -{ - return d->errAppSpec; -} +QDomElement ClientStream::errorAppSpec() const { return d->errAppSpec; } -bool ClientStream::old() const -{ - return d->client.old; -} +bool ClientStream::old() const { return d->client.old; } void ClientStream::close() { - if(d->state == Active) { + if (d->state == Active) { d->state = Closing; d->client.shutdown(); processNext(); - } - else if(d->state != Idle && d->state != Closing) { + } else if (d->state != Idle && d->state != Closing) { reset(); } } -QDomDocument & ClientStream::doc() const -{ - return d->client.doc; -} +QDomDocument &ClientStream::doc() const { return d->client.doc; } -QString ClientStream::baseNS() const -{ - return NS_CLIENT; -} +QString ClientStream::baseNS() const { return NS_CLIENT; } -void ClientStream::setAllowPlain(AllowPlainType a) -{ - d->allowPlain = a; -} +void ClientStream::setAllowPlain(AllowPlainType a) { d->allowPlain = a; } -void ClientStream::setRequireMutualAuth(bool b) -{ - d->mutualAuth = b; -} +void ClientStream::setRequireMutualAuth(bool b) { d->mutualAuth = b; } void ClientStream::setSSFRange(int low, int high) { @@ -586,23 +499,17 @@ void ClientStream::setSSFRange(int low, int high) d->maximumSSF = high; } -void ClientStream::setOldOnly(bool b) -{ - d->oldOnly = b; -} +void ClientStream::setOldOnly(bool b) { d->oldOnly = b; } -bool ClientStream::stanzaAvailable() const -{ - return (!d->in.isEmpty()); -} +bool ClientStream::stanzaAvailable() const { return (!d->in.isEmpty()); } Stanza ClientStream::read() { - if(d->in.isEmpty()) + if (d->in.isEmpty()) return Stanza(); else { Stanza *sp = d->in.takeFirst(); - Stanza s = *sp; + Stanza s = *sp; delete sp; return s; } @@ -610,21 +517,18 @@ Stanza ClientStream::read() void ClientStream::write(const Stanza &s) { - if(d->state == Active) { + if (d->state == Active) { d->client.sendStanza(s.element()); processNext(); } } -void ClientStream::clearSendQueue() -{ - d->client.clearSendQueue(); -} +void ClientStream::clearSendQueue() { d->client.clearSendQueue(); } void ClientStream::cr_connected() { d->connectHost = d->conn->host(); - d->bs = d->conn->stream(); + d->bs = d->conn->stream(); connect(d->bs, SIGNAL(connectionClosed()), SLOT(bs_connectionClosed())); connect(d->bs, SIGNAL(delayedCloseFinished()), SLOT(bs_delayedCloseFinished())); @@ -637,11 +541,11 @@ void ClientStream::cr_connected() connect(d->ss, SIGNAL(tlsClosed()), SLOT(ss_tlsClosed())); connect(d->ss, SIGNAL(error(int)), SLOT(ss_error(int))); - //d->client.startDialbackOut("andbit.net", "im.pyxa.org"); - //d->client.startServerOut(d->server); + // d->client.startDialbackOut("andbit.net", "im.pyxa.org"); + // d->client.startServerOut(d->server); d->client.startClientOut(d->jid, d->oldOnly, d->conn->useSSL(), d->doAuth, d->doCompress); - d->client.setAllowTLS(d->tlsHandler ? true: false); + d->client.setAllowTLS(d->tlsHandler ? true : false); d->client.setAllowBind(d->doBinding); d->client.setAllowPlain(d->allowPlain == AllowPlain || (d->allowPlain == AllowPlainOverTLS && d->conn->useSSL())); d->client.setLang(d->lang); @@ -657,15 +561,14 @@ void ClientStream::cr_connected() QPointer self = this; if (!d->quiet_reconnection) emit connected(); - if(!self) + if (!self) return; // immediate SSL? - if(d->conn->useSSL()) { + if (d->conn->useSSL()) { d->using_tls = true; d->ss->startTLSClient(d->tlsHandler, d->server, spare); - } - else { + } else { d->client.addIncomingData(spare); processNext(); } @@ -701,15 +604,14 @@ void ClientStream::ss_readyRead() qDebug("ClientStream: recv: %d [%s]\n", a.size(), a.data()); #endif - if(d->mode == Client) { + if (d->mode == Client) { d->client.addIncomingData(a); d->client.sm.countInputRawData(a.size()); - } - else { + } else { d->srv.addIncomingData(a); d->srv.sm.countInputRawData(a.size()); } - if(d->notify & CoreProtocol::NRecv) { + if (d->notify & CoreProtocol::NRecv) { #ifdef XMPP_DEBUG qDebug("We needed data, so let's process it\n"); #endif @@ -719,12 +621,12 @@ void ClientStream::ss_readyRead() void ClientStream::ss_bytesWritten(qint64 bytes) { - if(d->mode == Client) + if (d->mode == Client) d->client.outgoingDataWritten(bytes); else d->srv.outgoingDataWritten(bytes); - if(d->notify & CoreProtocol::NSend) { + if (d->notify & CoreProtocol::NSend) { #ifdef XMPP_DEBUG qDebug("We were waiting for data to be written, so let's process\n"); #endif @@ -737,7 +639,7 @@ void ClientStream::ss_tlsHandshaken() QPointer self = this; if (!d->quiet_reconnection) securityLayerActivated(LayerTLS); - if(!self) + if (!self) return; d->client.setAllowPlain(d->allowPlain == AllowPlain || d->allowPlain == AllowPlainOverTLS); processNext(); @@ -751,65 +653,63 @@ void ClientStream::ss_tlsClosed() void ClientStream::ss_error(int x) { - if(x == SecureStream::ErrTLS) { + if (x == SecureStream::ErrTLS) { reset(); d->errCond = TLSFail; error(ErrTLS); - } - else { + } else { reset(); error(ErrSecurityLayer); } } -void ClientStream::sasl_clientFirstStep(bool, const QByteArray& ba) +void ClientStream::sasl_clientFirstStep(bool, const QByteArray &ba) { d->client.setSASLFirst(d->sasl->mechanism(), ba); - //d->client.sasl_mech = mech; - //d->client.sasl_firstStep = stepData ? true : false; - //d->client.sasl_step = stepData ? *stepData : QByteArray(); + // d->client.sasl_mech = mech; + // d->client.sasl_firstStep = stepData ? true : false; + // d->client.sasl_step = stepData ? *stepData : QByteArray(); processNext(); } void ClientStream::sasl_nextStep(const QByteArray &stepData) { - if(d->mode == Client) + if (d->mode == Client) d->client.setSASLNext(stepData); - //d->client.sasl_step = stepData; + // d->client.sasl_step = stepData; else d->srv.setSASLNext(stepData); - //d->srv.sasl_step = stepData; + // d->srv.sasl_step = stepData; processNext(); } -void ClientStream::sasl_needParams(const QCA::SASL::Params& p) +void ClientStream::sasl_needParams(const QCA::SASL::Params &p) { #ifdef XMPP_DEBUG qDebug("need params: needUsername: %d, canSendAuthzid: %d, needPassword: %d, canSendRealm: %d\n", - p.needUsername()?1:0, p.canSendAuthzid()? 1:0, p.needPassword()? 1:0, p.canSendRealm()? 1:0); + p.needUsername() ? 1 : 0, p.canSendAuthzid() ? 1 : 0, p.needPassword() ? 1 : 0, p.canSendRealm() ? 1 : 0); #endif /*if(p.authzid && !p.user) { d->sasl->setAuthzid(d->jid.bare()); //d->sasl->setAuthzid("infiniti.homelesshackers.org"); }*/ - if(p.needUsername() || p.needPassword() || p.canSendRealm()) { + if (p.needUsername() || p.needPassword() || p.canSendRealm()) { d->state = NeedParams; needAuthParams(p.needUsername(), p.needPassword(), p.canSendRealm()); - } - else + } else d->sasl->continueAfterParams(); } void ClientStream::sasl_authCheck(const QString &user, const QString &) { -//#ifdef XMPP_DEBUG -// qDebug("authcheck: [%s], [%s]\n", user.latin1(), authzid.latin1()); -//#endif + //#ifdef XMPP_DEBUG + // qDebug("authcheck: [%s], [%s]\n", user.latin1(), authzid.latin1()); + //#endif QString u = user; - int n = u.indexOf('@'); - if(n != -1) + int n = u.indexOf('@'); + if (n != -1) u.truncate(n); d->srv.user = u; d->sasl->continueAfterAuthCheck(); @@ -822,7 +722,7 @@ void ClientStream::sasl_authenticated() #endif d->sasl_ssf = d->sasl->ssf(); - if(d->mode == Server) { + if (d->mode == Server) { d->srv.setSASLAuthed(); processNext(); } @@ -834,7 +734,7 @@ void ClientStream::sasl_error() qDebug("sasl error: %d\n", d->sasl->authCondition()); #endif // has to be auth error - int x = convertedSASLCond(); + int x = convertedSASLCond(); d->errText = tr("Offered mechanisms: ") + d->client.features.sasl_mechs.join(", "); reset(); d->errCond = x; @@ -843,30 +743,29 @@ void ClientStream::sasl_error() void ClientStream::srvProcessNext() { - while(1) { + while (1) { qDebug("Processing step...\n"); - if(!d->srv.processStep()) { + if (!d->srv.processStep()) { int need = d->srv.need; - if(need == CoreProtocol::NNotify) { + if (need == CoreProtocol::NNotify) { d->notify = d->srv.notify; - if(d->notify & CoreProtocol::NSend) + if (d->notify & CoreProtocol::NSend) qDebug("More data needs to be written to process next step\n"); - if(d->notify & CoreProtocol::NRecv) + if (d->notify & CoreProtocol::NRecv) qDebug("More data is needed to process next step\n"); - } - else if(need == CoreProtocol::NSASLMechs) { - if(!d->sasl) { + } else if (need == CoreProtocol::NSASLMechs) { + if (!d->sasl) { d->sasl = new QCA::SASL; - connect(d->sasl, SIGNAL(authCheck(QString,QString)), SLOT(sasl_authCheck(QString,QString))); + connect(d->sasl, SIGNAL(authCheck(QString, QString)), SLOT(sasl_authCheck(QString, QString))); connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray))); connect(d->sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated())); connect(d->sasl, SIGNAL(error()), SLOT(sasl_error())); - //d->sasl->setAllowAnonymous(false); - //d->sasl->setRequirePassCredentials(true); - //d->sasl->setExternalAuthID("localhost"); - QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags) 0; - d->sasl->setConstraints(auth_flags,0,256); + // d->sasl->setAllowAnonymous(false); + // d->sasl->setRequirePassCredentials(true); + // d->sasl->setExternalAuthID("localhost"); + QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags)0; + d->sasl->setConstraints(auth_flags, 0, 256); QStringList list; // TODO: d->server is probably wrong here @@ -875,30 +774,26 @@ void ClientStream::srvProcessNext() } d->srv.setSASLMechList(d->sasl_mechlist); continue; - } - else if(need == CoreProtocol::NStartTLS) { + } else if (need == CoreProtocol::NStartTLS) { qDebug("Need StartTLS\n"); - //if(!d->tls->startServer()) { + // if(!d->tls->startServer()) { d->tls->startServer(); QByteArray a = d->srv.spare; d->ss->startTLSServer(d->tls, a); - } - else if(need == CoreProtocol::NSASLFirst) { + } else if (need == CoreProtocol::NSASLFirst) { qDebug("Need SASL First Step\n"); QByteArray a = d->srv.saslStep(); d->sasl->putServerFirstStep(d->srv.saslMech(), a); - } - else if(need == CoreProtocol::NSASLNext) { + } else if (need == CoreProtocol::NSASLNext) { qDebug("Need SASL Next Step\n"); QByteArray a = d->srv.saslStep(); qDebug("[%s]\n", a.data()); d->sasl->putStep(a); - } - else if(need == CoreProtocol::NSASLLayer) { + } else if (need == CoreProtocol::NSASLLayer) { } // now we can announce stanzas - //if(!d->in.isEmpty()) + // if(!d->in.isEmpty()) // readyRead(); return; } @@ -907,101 +802,99 @@ void ClientStream::srvProcessNext() int event = d->srv.event; qDebug("event: %d\n", event); - switch(event) { - case CoreProtocol::EError: { - qDebug("Error! Code=%d\n", d->srv.errorCode); - reset(); - error(ErrProtocol); - //handleError(); - return; - } - case CoreProtocol::ESend: { - while (true) { - QByteArray a = d->srv.takeOutgoingData(); - if (a.isEmpty()) - break; + switch (event) { + case CoreProtocol::EError: { + qDebug("Error! Code=%d\n", d->srv.errorCode); + reset(); + error(ErrProtocol); + // handleError(); + return; + } + case CoreProtocol::ESend: { + while (true) { + QByteArray a = d->srv.takeOutgoingData(); + if (a.isEmpty()) + break; #ifdef XMPP_DEBUG - qDebug("Need Send: {%s}\n", a.data()); + qDebug("Need Send: {%s}\n", a.data()); #endif - d->ss->write(a); - } - break; - } - case CoreProtocol::ERecvOpen: { - qDebug("Break (RecvOpen)\n"); - - // calculate key - QByteArray str = QCA::Hash("sha1").hashToString("secret").toUtf8(); - str = QCA::Hash("sha1").hashToString(QByteArray(str + "im.pyxa.org")).toUtf8(); - str = QCA::Hash("sha1").hashToString(QByteArray(str + d->srv.id.toUtf8())).toUtf8(); - d->srv.setDialbackKey(str); - - //d->srv.setDialbackKey("3c5d721ea2fcc45b163a11420e4e358f87e3142a"); - - if(d->srv.to != d->server) { - // host-gone, host-unknown, see-other-host - d->srv.shutdownWithError(CoreProtocol::HostUnknown); - } - else - d->srv.setFrom(d->server); - break; - } - case CoreProtocol::ESASLSuccess: { - qDebug("Break SASL Success\n"); - disconnect(d->sasl, SIGNAL(error()), this, SLOT(sasl_error())); - QByteArray a = d->srv.spare; - d->ss->setLayerSASL(d->sasl, a); - break; - } - case CoreProtocol::EPeerClosed: { - // TODO: this isn' an error - qDebug("peer closed\n"); - reset(); - error(ErrProtocol); - return; + d->ss->write(a); } + break; + } + case CoreProtocol::ERecvOpen: { + qDebug("Break (RecvOpen)\n"); + + // calculate key + QByteArray str = QCA::Hash("sha1").hashToString("secret").toUtf8(); + str = QCA::Hash("sha1").hashToString(QByteArray(str + "im.pyxa.org")).toUtf8(); + str = QCA::Hash("sha1").hashToString(QByteArray(str + d->srv.id.toUtf8())).toUtf8(); + d->srv.setDialbackKey(str); + + // d->srv.setDialbackKey("3c5d721ea2fcc45b163a11420e4e358f87e3142a"); + + if (d->srv.to != d->server) { + // host-gone, host-unknown, see-other-host + d->srv.shutdownWithError(CoreProtocol::HostUnknown); + } else + d->srv.setFrom(d->server); + break; + } + case CoreProtocol::ESASLSuccess: { + qDebug("Break SASL Success\n"); + disconnect(d->sasl, SIGNAL(error()), this, SLOT(sasl_error())); + QByteArray a = d->srv.spare; + d->ss->setLayerSASL(d->sasl, a); + break; + } + case CoreProtocol::EPeerClosed: { + // TODO: this isn' an error + qDebug("peer closed\n"); + reset(); + error(ErrProtocol); + return; + } } } } void ClientStream::doReadyRead() { - //QGuardedPtr self = this; + // QGuardedPtr self = this; if (isActive()) emit readyRead(); - //if(!self) + // if(!self) // return; - //d->in_rrsig = false; + // d->in_rrsig = false; } void ClientStream::processNext() { - if(d->mode == Server) { + if (d->mode == Server) { srvProcessNext(); return; } QPointer self = this; - while(1) { + while (1) { #ifdef XMPP_DEBUG qDebug("Processing step...\n"); #endif bool ok = d->client.processStep(); // deal with send/received items foreach (const XmlProtocol::TransferItem &i, d->client.transferItemList) { - if(i.isExternal) + if (i.isExternal) continue; QString str; - if(i.isString) { + if (i.isString) { // skip whitespace pings - if(i.str.trimmed().isEmpty()) + if (i.str.trimmed().isEmpty()) continue; str = i.str; - } - else + } else str = d->client.elementToString(i.elem); - if(i.isSent) + if (i.isSent) emit outgoingXml(str); else emit incomingXml(str); @@ -1010,9 +903,9 @@ void ClientStream::processNext() #ifdef XMPP_DEBUG qDebug("\tNOTIFY: %d\n", d->client.notify); #endif - if (d->client.notify & CoreProtocol::NTimeout ) { + if (d->client.notify & CoreProtocol::NTimeout) { #ifdef XMPP_DEBUG - qDebug() << "Time = "<< d->client.timeout_sec; + qDebug() << "Time = " << d->client.timeout_sec; #endif setTimer(d->client.timeout_sec); #ifdef XMPP_DEBUG @@ -1020,175 +913,176 @@ void ClientStream::processNext() #endif } - if(!ok) { + if (!ok) { bool cont = handleNeed(); // now we can announce stanzas - //if(!d->in_rrsig && !d->in.isEmpty()) { - if(!d->in.isEmpty()) { - //d->in_rrsig = true; - //fprintf(stderr, "\tClientStream::processNext() QTimer::singleShot\n"); - //fflush(stderr); + // if(!d->in_rrsig && !d->in.isEmpty()) { + if (!d->in.isEmpty()) { + // d->in_rrsig = true; + // fprintf(stderr, "\tClientStream::processNext() QTimer::singleShot\n"); + // fflush(stderr); QTimer::singleShot(0, this, SLOT(doReadyRead())); } - if(cont) + if (cont) continue; return; } int event = d->client.event; d->notify = 0; - switch(event) { - case CoreProtocol::EError: { + switch (event) { + case CoreProtocol::EError: { #ifdef XMPP_DEBUG - qDebug("Error! Code=%d\n", d->client.errorCode); + qDebug("Error! Code=%d\n", d->client.errorCode); #endif - handleError(); - return; - } - case CoreProtocol::ESend: { - while (true) { - QByteArray a = d->client.takeOutgoingData(); - if (a.isEmpty()) - break; + handleError(); + return; + } + case CoreProtocol::ESend: { + while (true) { + QByteArray a = d->client.takeOutgoingData(); + if (a.isEmpty()) + break; #ifdef XMPP_DEBUG - qDebug("Need Send: {%s}\n", a.data()); + qDebug("Need Send: {%s}\n", a.data()); #endif - d->ss->write(a); - } - break; + d->ss->write(a); } - case CoreProtocol::ERecvOpen: { + break; + } + case CoreProtocol::ERecvOpen: { #ifdef XMPP_DEBUG - qDebug("Break (RecvOpen)\n"); + qDebug("Break (RecvOpen)\n"); #endif #ifdef XMPP_TEST - QString s = QString("handshake success (lang=[%1]").arg(d->client.lang); - if(!d->client.from.isEmpty()) - s += QString(", from=[%1]").arg(d->client.from); - s += ')'; - TD::msg(s); + QString s = QString("handshake success (lang=[%1]").arg(d->client.lang); + if (!d->client.from.isEmpty()) + s += QString(", from=[%1]").arg(d->client.from); + s += ')'; + TD::msg(s); #endif - if(d->client.old) { - d->state = WaitVersion; - warning(WarnOldVersion); - return; - } - break; + if (d->client.old) { + d->state = WaitVersion; + warning(WarnOldVersion); + return; } - case CoreProtocol::EFeatures: { + break; + } + case CoreProtocol::EFeatures: { #ifdef XMPP_DEBUG - qDebug("Break (Features)\n"); + qDebug("Break (Features)\n"); #endif - if (d->client.unhandledFeatures.count()) { - emit haveUnhandledFeatures(); - } - if(!d->tls_warned && !d->using_tls && !d->client.features.tls_supported) { - d->tls_warned = true; - d->state = WaitTLS; - warning(WarnNoTLS); - return; - } - break; + if (d->client.unhandledFeatures.count()) { + emit haveUnhandledFeatures(); } - case CoreProtocol::ESASLSuccess: { -#ifdef XMPP_DEBUG - qDebug("Break SASL Success\n"); -#endif - break; + if (!d->tls_warned && !d->using_tls && !d->client.features.tls_supported) { + d->tls_warned = true; + d->state = WaitTLS; + warning(WarnNoTLS); + return; } - case CoreProtocol::EReady: { + break; + } + case CoreProtocol::ESASLSuccess: { #ifdef XMPP_DEBUG - qDebug("Done!\n"); + qDebug("Break SASL Success\n"); #endif - // grab the JID, in case it changed - d->jid = d->client.jid(); - d->state = Active; - setNoopTime(d->noop_time); - if (!d->quiet_reconnection) - authenticated(); - if(!self) - return; - break; - } - case CoreProtocol::EPeerClosed: { + break; + } + case CoreProtocol::EReady: { #ifdef XMPP_DEBUG - qDebug("DocumentClosed\n"); + qDebug("Done!\n"); #endif - reset(); - connectionClosed(); + // grab the JID, in case it changed + d->jid = d->client.jid(); + d->state = Active; + setNoopTime(d->noop_time); + if (!d->quiet_reconnection) + authenticated(); + if (!self) return; - } - case CoreProtocol::EStanzaReady: { + break; + } + case CoreProtocol::EPeerClosed: { #ifdef XMPP_DEBUG - qDebug("StanzaReady\n"); + qDebug("DocumentClosed\n"); #endif - // store the stanza for now, announce after processing all events - // TODO: add a method to the stanza to mark them handled. - Stanza s = createStanza(d->client.recvStanza()); - if(s.isNull()) - break; - if (d->client.sm.isActive()) - d->client.sm.markStanzaHandled(); - d->in.append(new Stanza(s)); - break; - } - case CoreProtocol::EStanzaSent: { + reset(); + connectionClosed(); + return; + } + case CoreProtocol::EStanzaReady: { #ifdef XMPP_DEBUG - qDebug("StanzasSent\n"); + qDebug("StanzaReady\n"); #endif - stanzaWritten(); - if(!self) - return; + // store the stanza for now, announce after processing all events + // TODO: add a method to the stanza to mark them handled. + Stanza s = createStanza(d->client.recvStanza()); + if (s.isNull()) break; - } - case CoreProtocol::EClosed: { + if (d->client.sm.isActive()) + d->client.sm.markStanzaHandled(); + d->in.append(new Stanza(s)); + break; + } + case CoreProtocol::EStanzaSent: { #ifdef XMPP_DEBUG - qDebug("Closed\n"); + qDebug("StanzasSent\n"); #endif - reset(); - delayedCloseFinished(); + stanzaWritten(); + if (!self) return; - } - case CoreProtocol::EAck: { - int ack_cnt = d->client.sm.takeAckedCount(); + break; + } + case CoreProtocol::EClosed: { #ifdef XMPP_DEBUG - qDebug() << "Stream Management: [INF] Received ack amount: " << ack_cnt; + qDebug("Closed\n"); #endif - emit stanzasAcked(ack_cnt); - break; - } - case CoreProtocol::ESMConnTimeout: { + reset(); + delayedCloseFinished(); + return; + } + case CoreProtocol::EAck: { + int ack_cnt = d->client.sm.takeAckedCount(); #ifdef XMPP_DEBUG - qDebug() << "Stream Management: [INF] Connection timeout"; + qDebug() << "Stream Management: [INF] Received ack amount: " << ack_cnt; #endif - reset(); - if (d->client.sm.state().isResumption()) { - d->state = Connecting; - emit warning(WarnSMReconnection); - d->quiet_reconnection = true; - if (d->client.sm.state().isLocationValid()) - d->conn->setOptHostPort(d->client.sm.state().resumption_location.host , d->client.sm.state().resumption_location.port); - d->conn->connectToServer(d->server); - } else { - d->quiet_reconnection = false; - emit connectionClosed(); - } - return; - } - case CoreProtocol::ESMResumeFailed: { + emit stanzasAcked(ack_cnt); + break; + } + case CoreProtocol::ESMConnTimeout: { #ifdef XMPP_DEBUG - qDebug() << "Stream Management: [INF] Resuming session failed"; + qDebug() << "Stream Management: [INF] Connection timeout"; #endif - reset(); + reset(); + if (d->client.sm.state().isResumption()) { + d->state = Connecting; + emit warning(WarnSMReconnection); + d->quiet_reconnection = true; + if (d->client.sm.state().isLocationValid()) + d->conn->setOptHostPort(d->client.sm.state().resumption_location.host, + d->client.sm.state().resumption_location.port); + d->conn->connectToServer(d->server); + } else { d->quiet_reconnection = false; - emit error(ErrSmResume); - return; + emit connectionClosed(); } + return; + } + case CoreProtocol::ESMResumeFailed: { +#ifdef XMPP_DEBUG + qDebug() << "Stream Management: [INF] Resuming session failed"; +#endif + reset(); + d->quiet_reconnection = false; + emit error(ErrSmResume); + return; + } } } } @@ -1196,146 +1090,144 @@ void ClientStream::processNext() bool ClientStream::handleNeed() { int need = d->client.need; - if(need == CoreProtocol::NNotify) { + if (need == CoreProtocol::NNotify) { d->notify = d->client.notify; #ifdef XMPP_DEBUG - if(d->notify & CoreProtocol::NSend) + if (d->notify & CoreProtocol::NSend) qDebug("More data needs to be written to process next step\n"); - if(d->notify & CoreProtocol::NRecv) + if (d->notify & CoreProtocol::NRecv) qDebug("More data is needed to process next step\n"); #endif return false; } d->notify = 0; - switch(need) { - case CoreProtocol::NStartTLS: { + switch (need) { + case CoreProtocol::NStartTLS: { #ifdef XMPP_DEBUG - qDebug("Need StartTLS\n"); + qDebug("Need StartTLS\n"); #endif - d->using_tls = true; - d->ss->startTLSClient(d->tlsHandler, d->server, d->client.spare); - return false; - } - case CoreProtocol::NCompress: { + d->using_tls = true; + d->ss->startTLSClient(d->tlsHandler, d->server, d->client.spare); + return false; + } + case CoreProtocol::NCompress: { #ifdef XMPP_DEBUG - qDebug("Need compress\n"); + qDebug("Need compress\n"); #endif - d->ss->setLayerCompress(d->client.spare); - return true; - } - case CoreProtocol::NSASLFirst: { + d->ss->setLayerCompress(d->client.spare); + return true; + } + case CoreProtocol::NSASLFirst: { #ifdef XMPP_DEBUG - qDebug("Need SASL First Step\n"); + qDebug("Need SASL First Step\n"); #endif - // ensure simplesasl provider is installed - bool found = false; - foreach(QCA::Provider *p, QCA::providers()) { - if(p->name() == "simplesasl") { - found = true; - break; - } - } - if(!found) { - // install with low-priority - QCA::insertProvider(createProviderSimpleSASL()); - QCA::setProviderPriority("simplesasl", 10); + // ensure simplesasl provider is installed + bool found = false; + foreach (QCA::Provider *p, QCA::providers()) { + if (p->name() == "simplesasl") { + found = true; + break; } + } + if (!found) { + // install with low-priority + QCA::insertProvider(createProviderSimpleSASL()); + QCA::setProviderPriority("simplesasl", 10); + } - static QStringList preference{ "GSSAPI", "SCRAM-SHA-512-PLUS", "SCRAM-SHA-512", - "SCRAM-SHA-384-PLUS", "SCRAM-SHA-384", - "SCRAM-SHA-256-PLUS", "SCRAM-SHA-256", - "SCRAM-SHA-1-PLUS", "SCRAM-SHA-1", - "DIGEST-MD5", "PLAIN" }; - // TODO qca should maintain the list of preferred - - QStringList ml; - if(!d->sasl_mech.isEmpty()) - ml += d->sasl_mech; - else { - QMap prefOrdered; - QStringList unpreferred; - for (auto const &m : d->client.features.sasl_mechs) { - int i = preference.indexOf(m); - if (i != -1) { - prefOrdered.insert(i, m); - } else { - unpreferred.append(m); - } + static QStringList preference { "GSSAPI", "SCRAM-SHA-512-PLUS", "SCRAM-SHA-512", "SCRAM-SHA-384-PLUS", + "SCRAM-SHA-384", "SCRAM-SHA-256-PLUS", "SCRAM-SHA-256", "SCRAM-SHA-1-PLUS", + "SCRAM-SHA-1", "DIGEST-MD5", "PLAIN" }; + // TODO qca should maintain the list of preferred + + QStringList ml; + if (!d->sasl_mech.isEmpty()) + ml += d->sasl_mech; + else { + QMap prefOrdered; + QStringList unpreferred; + for (auto const &m : d->client.features.sasl_mechs) { + int i = preference.indexOf(m); + if (i != -1) { + prefOrdered.insert(i, m); + } else { + unpreferred.append(m); } - ml = prefOrdered.values() + unpreferred; } + ml = prefOrdered.values() + unpreferred; + } - QString saslProvider; - foreach (const QString &mech, d->mechProviders.keys()) { - if (ml.contains(mech)) { - saslProvider = d->mechProviders[mech]; - break; - } + QString saslProvider; + foreach (const QString &mech, d->mechProviders.keys()) { + if (ml.contains(mech)) { + saslProvider = d->mechProviders[mech]; + break; } + } - d->sasl = new QCA::SASL(nullptr, saslProvider); - connect(d->sasl, SIGNAL(clientStarted(bool,QByteArray)), SLOT(sasl_clientFirstStep(bool,QByteArray))); - connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray))); - connect(d->sasl, SIGNAL(needParams(QCA::SASL::Params)), SLOT(sasl_needParams(QCA::SASL::Params))); - connect(d->sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated())); - connect(d->sasl, SIGNAL(error()), SLOT(sasl_error())); - - if(d->haveLocalAddr) - d->sasl->setLocalAddress(d->localAddr.toString(), d->localPort); - if(d->conn->havePeerAddress()) - d->sasl->setRemoteAddress(d->conn->peerAddress().toString(), d->conn->peerPort()); - - //d->sasl_mech = "ANONYMOUS"; - //d->sasl->setRequirePassCredentials(true); - //d->sasl->setExternalAuthID("localhost"); - //d->sasl->setExternalSSF(64); - //d->sasl_mech = "EXTERNAL"; - - QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags) 0; - if (d->allowPlain == AllowPlain || (d->allowPlain == AllowPlainOverTLS && d->using_tls)) - auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::AllowPlain); - if (d->mutualAuth) - auth_flags = (QCA::SASL::AuthFlags) (auth_flags | QCA::SASL::RequireMutualAuth); - d->sasl->setConstraints(auth_flags,d->minimumSSF,d->maximumSSF); + d->sasl = new QCA::SASL(nullptr, saslProvider); + connect(d->sasl, SIGNAL(clientStarted(bool, QByteArray)), SLOT(sasl_clientFirstStep(bool, QByteArray))); + connect(d->sasl, SIGNAL(nextStep(QByteArray)), SLOT(sasl_nextStep(QByteArray))); + connect(d->sasl, SIGNAL(needParams(QCA::SASL::Params)), SLOT(sasl_needParams(QCA::SASL::Params))); + connect(d->sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated())); + connect(d->sasl, SIGNAL(error()), SLOT(sasl_error())); + + if (d->haveLocalAddr) + d->sasl->setLocalAddress(d->localAddr.toString(), d->localPort); + if (d->conn->havePeerAddress()) + d->sasl->setRemoteAddress(d->conn->peerAddress().toString(), d->conn->peerPort()); + + // d->sasl_mech = "ANONYMOUS"; + // d->sasl->setRequirePassCredentials(true); + // d->sasl->setExternalAuthID("localhost"); + // d->sasl->setExternalSSF(64); + // d->sasl_mech = "EXTERNAL"; + + QCA::SASL::AuthFlags auth_flags = (QCA::SASL::AuthFlags)0; + if (d->allowPlain == AllowPlain || (d->allowPlain == AllowPlainOverTLS && d->using_tls)) + auth_flags = (QCA::SASL::AuthFlags)(auth_flags | QCA::SASL::AllowPlain); + if (d->mutualAuth) + auth_flags = (QCA::SASL::AuthFlags)(auth_flags | QCA::SASL::RequireMutualAuth); + d->sasl->setConstraints(auth_flags, d->minimumSSF, d->maximumSSF); #ifdef IRIS_SASLCONNECTHOST - d->sasl->startClient("xmpp", QUrl::toAce(d->connectHost), ml, QCA::SASL::AllowClientSendFirst); + d->sasl->startClient("xmpp", QUrl::toAce(d->connectHost), ml, QCA::SASL::AllowClientSendFirst); #else - d->sasl->startClient("xmpp", QUrl::toAce(d->server), ml, QCA::SASL::AllowClientSendFirst); + d->sasl->startClient("xmpp", QUrl::toAce(d->server), ml, QCA::SASL::AllowClientSendFirst); #endif - return false; - } - case CoreProtocol::NSASLNext: { + return false; + } + case CoreProtocol::NSASLNext: { #ifdef XMPP_DEBUG - qDebug("Need SASL Next Step\n"); + qDebug("Need SASL Next Step\n"); #endif - QByteArray a = d->client.saslStep(); - d->sasl->putStep(a); - return false; - } - case CoreProtocol::NSASLLayer: { - // SecureStream will handle the errors from this point - disconnect(d->sasl, SIGNAL(error()), this, SLOT(sasl_error())); - d->ss->setLayerSASL(d->sasl, d->client.spare); - if(d->sasl_ssf > 0) { - QPointer self = this; - if (!d->quiet_reconnection) - securityLayerActivated(LayerSASL); - if(!self) - return false; - } - break; + QByteArray a = d->client.saslStep(); + d->sasl->putStep(a); + return false; + } + case CoreProtocol::NSASLLayer: { + // SecureStream will handle the errors from this point + disconnect(d->sasl, SIGNAL(error()), this, SLOT(sasl_error())); + d->ss->setLayerSASL(d->sasl, d->client.spare); + if (d->sasl_ssf > 0) { + QPointer self = this; + if (!d->quiet_reconnection) + securityLayerActivated(LayerSASL); + if (!self) + return false; } - case CoreProtocol::NPassword: { + break; + } + case CoreProtocol::NPassword: { #ifdef XMPP_DEBUG - qDebug("Need Password\n"); + qDebug("Need Password\n"); #endif - d->state = NeedParams; - needAuthParams(false, true, false); - return false; - } + d->state = NeedParams; + needAuthParams(false, true, false); + return false; + } } return true; @@ -1344,13 +1236,13 @@ bool ClientStream::handleNeed() int ClientStream::convertedSASLCond() const { int x = d->sasl->authCondition(); - if(x == QCA::SASL::NoMechanism) + if (x == QCA::SASL::NoMechanism) return NoMech; - else if(x == QCA::SASL::BadProtocol) + else if (x == QCA::SASL::BadProtocol) return MalformedRequest; - else if(x == QCA::SASL::BadServer) + else if (x == QCA::SASL::BadServer) return BadServ; - else if(x == QCA::SASL::TooWeak) + else if (x == QCA::SASL::TooWeak) return MechTooWeak; else return GenericAuthError; @@ -1365,8 +1257,7 @@ void ClientStream::sm_timeout() int elapsed = d->client.sm.lastAckElapsed(); if (elapsed < d->client.timeout_sec) { setTimer(d->client.timeout_sec - elapsed); - } - else { + } else { d->client.timeout_sec = 0; processNext(); } @@ -1374,7 +1265,7 @@ void ClientStream::sm_timeout() void ClientStream::doNoop() { - if(d->state == Active) { + if (d->state == Active) { #ifdef XMPP_DEBUG qDebug("doPing\n"); #endif @@ -1385,7 +1276,7 @@ void ClientStream::doNoop() void ClientStream::writeDirect(const QString &s) { - if(d->state == Active) { + if (d->state == Active) { #ifdef XMPP_DEBUG qDebug("writeDirect\n"); #endif @@ -1397,208 +1288,275 @@ void ClientStream::writeDirect(const QString &s) void ClientStream::handleError() { int c = d->client.errorCode; - if(c == CoreProtocol::ErrParse) { + if (c == CoreProtocol::ErrParse) { reset(); error(ErrParse); - } - else if(c == CoreProtocol::ErrProtocol) { + } else if (c == CoreProtocol::ErrProtocol) { reset(); error(ErrProtocol); - } - else if(c == CoreProtocol::ErrStream) { - int x = d->client.errCond; - QString text = d->client.errText; - auto langText = d->client.errLangText; - QDomElement appSpec = d->client.errAppSpec; + } else if (c == CoreProtocol::ErrStream) { + int x = d->client.errCond; + QString text = d->client.errText; + auto langText = d->client.errLangText; + QDomElement appSpec = d->client.errAppSpec; int connErr = -1; - int strErr = -1; - - switch(x) { - case CoreProtocol::BadFormat: { break; } // should NOT happen (we send the right format) - case CoreProtocol::BadNamespacePrefix: { break; } // should NOT happen (we send prefixes) - case CoreProtocol::Conflict: { strErr = Conflict; break; } - case CoreProtocol::ConnectionTimeout: { strErr = ConnectionTimeout; break; } - case CoreProtocol::HostGone: { connErr = HostGone; break; } - case CoreProtocol::HostUnknown: { connErr = HostUnknown; break; } - case CoreProtocol::ImproperAddressing: { break; } // should NOT happen (we aren't a server) - case CoreProtocol::InternalServerError: { strErr = InternalServerError; break; } - case CoreProtocol::InvalidFrom: { strErr = InvalidFrom; break; } - case CoreProtocol::InvalidNamespace: { break; } // should NOT happen (we set the right ns) - case CoreProtocol::InvalidXml: { strErr = InvalidXml; break; } // shouldn't happen either, but just in case ... - case CoreProtocol::StreamNotAuthorized: { break; } // should NOT happen (we're not stupid) - case CoreProtocol::PolicyViolation: { strErr = PolicyViolation; break; } - case CoreProtocol::RemoteConnectionFailed: { connErr = RemoteConnectionFailed; break; } - case CoreProtocol::StreamReset: { strErr = StreamReset; break; } - case CoreProtocol::ResourceConstraint: { strErr = ResourceConstraint; break; } - case CoreProtocol::RestrictedXml: { strErr = InvalidXml; break; } // group with this one - case CoreProtocol::SeeOtherHost: { connErr = SeeOtherHost; break; } - case CoreProtocol::SystemShutdown: { strErr = SystemShutdown; break; } - case CoreProtocol::UndefinedCondition: { break; } // leave as null error - case CoreProtocol::UnsupportedEncoding: { break; } // should NOT happen (we send good encoding) - case CoreProtocol::UnsupportedStanzaType: { break; } // should NOT happen (we're not stupid) - case CoreProtocol::UnsupportedVersion: { connErr = UnsupportedVersion; break; } - case CoreProtocol::NotWellFormed: { strErr = InvalidXml; break; } // group with this one - default: { break; } + int strErr = -1; + + switch (x) { + case CoreProtocol::BadFormat: { + break; + } // should NOT happen (we send the right format) + case CoreProtocol::BadNamespacePrefix: { + break; + } // should NOT happen (we send prefixes) + case CoreProtocol::Conflict: { + strErr = Conflict; + break; + } + case CoreProtocol::ConnectionTimeout: { + strErr = ConnectionTimeout; + break; + } + case CoreProtocol::HostGone: { + connErr = HostGone; + break; + } + case CoreProtocol::HostUnknown: { + connErr = HostUnknown; + break; + } + case CoreProtocol::ImproperAddressing: { + break; + } // should NOT happen (we aren't a server) + case CoreProtocol::InternalServerError: { + strErr = InternalServerError; + break; + } + case CoreProtocol::InvalidFrom: { + strErr = InvalidFrom; + break; + } + case CoreProtocol::InvalidNamespace: { + break; + } // should NOT happen (we set the right ns) + case CoreProtocol::InvalidXml: { + strErr = InvalidXml; + break; + } // shouldn't happen either, but just in case ... + case CoreProtocol::StreamNotAuthorized: { + break; + } // should NOT happen (we're not stupid) + case CoreProtocol::PolicyViolation: { + strErr = PolicyViolation; + break; + } + case CoreProtocol::RemoteConnectionFailed: { + connErr = RemoteConnectionFailed; + break; + } + case CoreProtocol::StreamReset: { + strErr = StreamReset; + break; + } + case CoreProtocol::ResourceConstraint: { + strErr = ResourceConstraint; + break; + } + case CoreProtocol::RestrictedXml: { + strErr = InvalidXml; + break; + } // group with this one + case CoreProtocol::SeeOtherHost: { + connErr = SeeOtherHost; + break; + } + case CoreProtocol::SystemShutdown: { + strErr = SystemShutdown; + break; + } + case CoreProtocol::UndefinedCondition: { + break; + } // leave as null error + case CoreProtocol::UnsupportedEncoding: { + break; + } // should NOT happen (we send good encoding) + case CoreProtocol::UnsupportedStanzaType: { + break; + } // should NOT happen (we're not stupid) + case CoreProtocol::UnsupportedVersion: { + connErr = UnsupportedVersion; + break; + } + case CoreProtocol::NotWellFormed: { + strErr = InvalidXml; + break; + } // group with this one + default: { + break; + } } reset(); - d->errText = text; + d->errText = text; d->errLangText = langText; - d->errAppSpec = appSpec; - if(connErr != -1) { + d->errAppSpec = appSpec; + if (connErr != -1) { d->errCond = connErr; error(ErrNeg); - } - else { - if(strErr != -1) + } else { + if (strErr != -1) d->errCond = strErr; else d->errCond = GenericStreamError; error(ErrStream); } - } - else if(c == CoreProtocol::ErrStartTLS) { + } else if (c == CoreProtocol::ErrStartTLS) { reset(); d->errCond = TLSStart; error(ErrTLS); - } - else if(c == CoreProtocol::ErrAuth) { + } else if (c == CoreProtocol::ErrAuth) { int x = d->client.errCond; int r = GenericAuthError; - if(d->client.old) { - if(x == 401) // not authorized + if (d->client.old) { + if (x == 401) // not authorized r = NotAuthorized; - else if(x == 409) // conflict + else if (x == 409) // conflict r = GenericAuthError; - else if(x == 406) // not acceptable (this should NOT happen) + else if (x == 406) // not acceptable (this should NOT happen) r = GenericAuthError; - } - else { - switch(x) { - case CoreProtocol::Aborted: { r = GenericAuthError; break; } // should NOT happen (we never send ) - case CoreProtocol::AccountDisabled: { r = AccountDisabled; break; } // account temporrily disabled - case CoreProtocol::CredentialsExpired: { r = CredentialsExpired; break; } // credential expired - case CoreProtocol::EncryptionRequired: { r = EncryptionRequired; break; } // can't use mech without TLS - case CoreProtocol::IncorrectEncoding: { r = GenericAuthError; break; } // should NOT happen - case CoreProtocol::InvalidAuthzid: { r = InvalidAuthzid; break; } - case CoreProtocol::InvalidMech: { r = InvalidMech; break; } - case CoreProtocol::MalformedRequest: { r = MalformedRequest; break; } - case CoreProtocol::MechTooWeak: { r = MechTooWeak; break; } - case CoreProtocol::NotAuthorized: { r = NotAuthorized; break; } - case CoreProtocol::TemporaryAuthFailure: { r = TemporaryAuthFailure; break; } + } else { + switch (x) { + case CoreProtocol::Aborted: { + r = GenericAuthError; + break; + } // should NOT happen (we never send ) + case CoreProtocol::AccountDisabled: { + r = AccountDisabled; + break; + } // account temporrily disabled + case CoreProtocol::CredentialsExpired: { + r = CredentialsExpired; + break; + } // credential expired + case CoreProtocol::EncryptionRequired: { + r = EncryptionRequired; + break; + } // can't use mech without TLS + case CoreProtocol::IncorrectEncoding: { + r = GenericAuthError; + break; + } // should NOT happen + case CoreProtocol::InvalidAuthzid: { + r = InvalidAuthzid; + break; + } + case CoreProtocol::InvalidMech: { + r = InvalidMech; + break; + } + case CoreProtocol::MalformedRequest: { + r = MalformedRequest; + break; + } + case CoreProtocol::MechTooWeak: { + r = MechTooWeak; + break; + } + case CoreProtocol::NotAuthorized: { + r = NotAuthorized; + break; + } + case CoreProtocol::TemporaryAuthFailure: { + r = TemporaryAuthFailure; + break; + } } } reset(); - d->errCond = r; + d->errCond = r; d->errLangText = d->client.errLangText; error(ErrAuth); - } - else if(c == CoreProtocol::ErrPlain) { + } else if (c == CoreProtocol::ErrPlain) { reset(); d->errCond = NoMech; error(ErrAuth); - } - else if(c == CoreProtocol::ErrBind) { + } else if (c == CoreProtocol::ErrBind) { int r = -1; - if(d->client.errCond == CoreProtocol::BindBadRequest) { + if (d->client.errCond == CoreProtocol::BindBadRequest) { // should NOT happen - } - else if(d->client.errCond == CoreProtocol::BindNotAllowed) { + } else if (d->client.errCond == CoreProtocol::BindNotAllowed) { r = BindNotAllowed; - } - else if(d->client.errCond == CoreProtocol::BindConflict) { + } else if (d->client.errCond == CoreProtocol::BindConflict) { r = BindConflict; } - if(r != -1) { + if (r != -1) { reset(); d->errCond = r; error(ErrBind); - } - else { + } else { reset(); error(ErrProtocol); } } } -bool ClientStream::isResumed() const -{ - return d->client.sm.isResumed(); -} +bool ClientStream::isResumed() const { return d->client.sm.isResumed(); } -void ClientStream::setSMEnabled(bool e) -{ - d->client.sm.state().setEnabled(e); -} +void ClientStream::setSMEnabled(bool e) { d->client.sm.state().setEnabled(e); } void ClientStream::setTimer(int secs) { d->timeout_timer.setSingleShot(true); d->timeout_timer.start(secs * 1000); - d->client.notify &= ~ CoreProtocol::NTimeout; + d->client.notify &= ~CoreProtocol::NTimeout; } -QStringList ClientStream::hosts() const -{ - return d->client.hosts; -} +QStringList ClientStream::hosts() const { return d->client.hosts; } -const StreamFeatures &ClientStream::streamFeatures() const -{ - return d->client.features; -} +const StreamFeatures &ClientStream::streamFeatures() const { return d->client.features; } -QList ClientStream::unhandledFeatures() const -{ - return d->client.unhandledFeatures; -} +QList ClientStream::unhandledFeatures() const { return d->client.unhandledFeatures; } //---------------------------------------------------------------------------- // Debug //---------------------------------------------------------------------------- -Debug::~Debug() -{ -} +Debug::~Debug() {} #ifdef XMPP_TEST -TD::TD() -{ -} +TD::TD() {} -TD::~TD() -{ -} +TD::~TD() {} void TD::msg(const QString &s) { - if(debug_ptr) + if (debug_ptr) debug_ptr->msg(s); } void TD::outgoingTag(const QString &s) { - if(debug_ptr) + if (debug_ptr) debug_ptr->outgoingTag(s); } void TD::incomingTag(const QString &s) { - if(debug_ptr) + if (debug_ptr) debug_ptr->incomingTag(s); } void TD::outgoingXml(const QDomElement &e) { - if(debug_ptr) + if (debug_ptr) debug_ptr->outgoingXml(e); } void TD::incomingXml(const QDomElement &e) { - if(debug_ptr) + if (debug_ptr) debug_ptr->incomingXml(e); } #endif diff --git a/src/xmpp/xmpp-core/td.h b/src/xmpp/xmpp-core/td.h index 192dc01b..be3c54e0 100644 --- a/src/xmpp/xmpp-core/td.h +++ b/src/xmpp/xmpp-core/td.h @@ -3,8 +3,7 @@ #include -class TD -{ +class TD { public: TD(); ~TD(); diff --git a/src/xmpp/xmpp-core/tlshandler.cpp b/src/xmpp/xmpp-core/tlshandler.cpp index 2a5fe27c..7bc311ec 100644 --- a/src/xmpp/xmpp-core/tlshandler.cpp +++ b/src/xmpp/xmpp-core/tlshandler.cpp @@ -32,65 +32,51 @@ using namespace QCA; static QByteArray ipaddr_str2bin(const QString &str) { // ipv6 - if(str.contains(':')) - { + if (str.contains(':')) { QStringList parts = str.split(':', QString::KeepEmptyParts); - if(parts.count() < 3 || parts.count() > 8) + if (parts.count() < 3 || parts.count() > 8) return QByteArray(); QByteArray ipv6(16, 0); - int at = 16; - int fill = 9 - parts.count(); - for(int n = parts.count() - 1; n >= 0; --n) - { - if(at <= 0) + int at = 16; + int fill = 9 - parts.count(); + for (int n = parts.count() - 1; n >= 0; --n) { + if (at <= 0) return QByteArray(); - if(parts[n].isEmpty()) - { - if(n == parts.count() - 1) - { - if(!parts[n - 1].isEmpty()) + if (parts[n].isEmpty()) { + if (n == parts.count() - 1) { + if (!parts[n - 1].isEmpty()) return QByteArray(); ipv6[--at] = 0; ipv6[--at] = 0; - } - else if(n == 0) - { - if(!parts[n + 1].isEmpty()) + } else if (n == 0) { + if (!parts[n + 1].isEmpty()) return QByteArray(); ipv6[--at] = 0; ipv6[--at] = 0; - } - else - { - for(int i = 0; i < fill; ++i) - { - if(at <= 0) + } else { + for (int i = 0; i < fill; ++i) { + if (at <= 0) return QByteArray(); ipv6[--at] = 0; ipv6[--at] = 0; } } - } - else - { - if(parts[n].indexOf('.') == -1) - { + } else { + if (parts[n].indexOf('.') == -1) { bool ok; - int x = parts[n].toInt(&ok, 16); - if(!ok || x < 0 || x > 0xffff) + int x = parts[n].toInt(&ok, 16); + if (!ok || x < 0 || x > 0xffff) return QByteArray(); ipv6[--at] = x & 0xff; ipv6[--at] = (x >> 8) & 0xff; - } - else - { - if(n != parts.count() - 1) + } else { + if (n != parts.count() - 1) return QByteArray(); QByteArray buf = ipaddr_str2bin(parts[n]); - if(buf.isEmpty()) + if (buf.isEmpty()) return QByteArray(); ipv6[--at] = buf[3]; @@ -103,25 +89,21 @@ static QByteArray ipaddr_str2bin(const QString &str) } return ipv6; - } - else if(str.contains('.')) - { + } else if (str.contains('.')) { QStringList parts = str.split('.', QString::KeepEmptyParts); - if(parts.count() != 4) + if (parts.count() != 4) return QByteArray(); QByteArray out(4, 0); - for(int n = 0; n < 4; ++n) - { + for (int n = 0; n < 4; ++n) { bool ok; - int x = parts[n].toInt(&ok); - if(!ok || x < 0 || x > 0xff) + int x = parts[n].toInt(&ok); + if (!ok || x < 0 || x > 0xff) return QByteArray(); out[n] = (unsigned char)x; } return out; - } - else + } else return QByteArray(); } @@ -134,47 +116,45 @@ static bool cert_match_domain(const QString &certname, const QString &acedomain) // KSSL strips trailing dot, even though the dot is probably not // legal anyway. (compat) - if(name.length() > 0 && name[name.length()-1] == '.') - name.truncate(name.length()-1); + if (name.length() > 0 && name[name.length() - 1] == '.') + name.truncate(name.length() - 1); // after our compatibility modifications, make sure the name isn't // empty. - if(name.isEmpty()) + if (name.isEmpty()) return false; // lowercase, for later performing case insensitive matching name = name.toLower(); // ensure the cert field contains valid characters only - if(QRegExp("[^a-z0-9\\.\\*\\-]").indexIn(name) >= 0) + if (QRegExp("[^a-z0-9\\.\\*\\-]").indexIn(name) >= 0) return false; // hack into parts, and require at least 1 part QStringList parts_name = name.split('.', QString::KeepEmptyParts); - if(parts_name.isEmpty()) + if (parts_name.isEmpty()) return false; // KSSL checks to make sure the last two parts don't contain // wildcards. I don't know where it is written that this // should be done, but for compat sake we'll do it. - if(parts_name[parts_name.count()-1].contains('*')) + if (parts_name[parts_name.count() - 1].contains('*')) return false; - if(parts_name.count() >= 2 && parts_name[parts_name.count()-2].contains('*')) + if (parts_name.count() >= 2 && parts_name[parts_name.count() - 2].contains('*')) return false; QStringList parts_compare = acedomain.split('.', QString::KeepEmptyParts); - if(parts_compare.isEmpty()) + if (parts_compare.isEmpty()) return false; // don't allow empty parts - foreach(const QString &s, parts_name) - { - if(s.isEmpty()) + foreach (const QString &s, parts_name) { + if (s.isEmpty()) return false; } - foreach(const QString &s, parts_compare) - { - if(s.isEmpty()) + foreach (const QString &s, parts_compare) { + if (s.isEmpty()) return false; } @@ -189,16 +169,15 @@ static bool cert_match_domain(const QString &certname, const QString &acedomain) // they reside in. // // First, make sure the number of parts is equal. - if(parts_name.count() != parts_compare.count()) + if (parts_name.count() != parts_compare.count()) return false; // Now compare each part - for(int n = 0; n < parts_name.count(); ++n) - { + for (int n = 0; n < parts_name.count(); ++n) { const QString &p1 = parts_name[n]; const QString &p2 = parts_compare[n]; - if(!QRegExp(p1, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(p2)) + if (!QRegExp(p1, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(p2)) return false; } @@ -215,21 +194,21 @@ static bool cert_match_ipaddress(const QString &certname, const QByteArray &ipad // KSSL accepts IPv6 in brackets, which is usually done for URIs, but // IMO sounds very strange for a certificate. We'll follow this // behavior anyway. (compat) - if(name.length() >= 2 && name[0] == '[' && name[name.length()-1] == ']') + if (name.length() >= 2 && name[0] == '[' && name[name.length() - 1] == ']') name = name.mid(1, name.length() - 2); // chop off brackets // after our compatibility modifications, make sure the name isn't // empty. - if(name.isEmpty()) + if (name.isEmpty()) return false; // convert to binary form QByteArray addr = ipaddr_str2bin(name); - if(addr.isEmpty()) + if (addr.isEmpty()) return false; // not the same? - if(addr != ipaddress) + if (addr != ipaddress) return false; return true; @@ -238,30 +217,26 @@ static bool cert_match_ipaddress(const QString &certname, const QByteArray &ipad static bool matchesHostName(const QCA::Certificate &cert, const QString &host) { QByteArray ipaddr = ipaddr_str2bin(host); - if(!ipaddr.isEmpty()) // ip address + if (!ipaddr.isEmpty()) // ip address { // check iPAddress - foreach(const QString &s, cert.subjectInfo().values(IPAddress)) - { - if(cert_match_ipaddress(s, ipaddr)) + foreach (const QString &s, cert.subjectInfo().values(IPAddress)) { + if (cert_match_ipaddress(s, ipaddr)) return true; } // check dNSName - foreach(const QString &s, cert.subjectInfo().values(DNS)) - { - if(cert_match_ipaddress(s, ipaddr)) + foreach (const QString &s, cert.subjectInfo().values(DNS)) { + if (cert_match_ipaddress(s, ipaddr)) return true; } // check commonName - foreach(const QString &s, cert.subjectInfo().values(CommonName)) - { - if(cert_match_ipaddress(s, ipaddr)) + foreach (const QString &s, cert.subjectInfo().values(CommonName)) { + if (cert_match_ipaddress(s, ipaddr)) return true; } - } - else // domain + } else // domain { // lowercase QString name = host.toLower(); @@ -270,28 +245,26 @@ static bool matchesHostName(const QCA::Certificate &cert, const QString &host) name = QString::fromLatin1(QUrl::toAce(name)); // don't allow wildcards in the comparison host - if(name.contains('*')) + if (name.contains('*')) return false; // strip out trailing dot - if(name.length() > 0 && name[name.length()-1] == '.') - name.truncate(name.length()-1); + if (name.length() > 0 && name[name.length() - 1] == '.') + name.truncate(name.length() - 1); // make sure the name is not empty after our modifications - if(name.isEmpty()) + if (name.isEmpty()) return false; // check dNSName - foreach(const QString &s, cert.subjectInfo().values(DNS)) - { - if(cert_match_domain(s, name)) + foreach (const QString &s, cert.subjectInfo().values(DNS)) { + if (cert_match_domain(s, name)) return true; } // check commonName - foreach(const QString &s, cert.subjectInfo().values(CommonName)) - { - if(cert_match_domain(s, name)) + foreach (const QString &s, cert.subjectInfo().values(CommonName)) { + if (cert_match_domain(s, name)) return true; } } @@ -302,58 +275,43 @@ static bool matchesHostName(const QCA::Certificate &cert, const QString &host) //---------------------------------------------------------------------------- // TLSHandler //---------------------------------------------------------------------------- -TLSHandler::TLSHandler(QObject *parent) -:QObject(parent) -{ -} +TLSHandler::TLSHandler(QObject *parent) : QObject(parent) {} -TLSHandler::~TLSHandler() -{ -} +TLSHandler::~TLSHandler() {} //---------------------------------------------------------------------------- // QCATLSHandler //---------------------------------------------------------------------------- -class QCATLSHandler::Private -{ +class QCATLSHandler::Private { public: QCA::TLS *tls; - int state, err; - QString host; - bool internalHostMatch; + int state, err; + QString host; + bool internalHostMatch; }; -QCATLSHandler::QCATLSHandler(QCA::TLS *parent) -:TLSHandler(parent) +QCATLSHandler::QCATLSHandler(QCA::TLS *parent) : TLSHandler(parent) { - d = new Private; + d = new Private; d->tls = parent; connect(d->tls, SIGNAL(handshaken()), SLOT(tls_handshaken())); connect(d->tls, SIGNAL(readyRead()), SLOT(tls_readyRead())); connect(d->tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing())); connect(d->tls, SIGNAL(closed()), SLOT(tls_closed())); connect(d->tls, SIGNAL(error()), SLOT(tls_error())); - d->state = 0; - d->err = -1; + d->state = 0; + d->err = -1; d->internalHostMatch = false; } -QCATLSHandler::~QCATLSHandler() -{ - delete d; -} +QCATLSHandler::~QCATLSHandler() { delete d; } -void QCATLSHandler::setXMPPCertCheck(bool enable) -{ - d->internalHostMatch = enable; -} -bool QCATLSHandler::XMPPCertCheck() -{ - return d->internalHostMatch; -} +void QCATLSHandler::setXMPPCertCheck(bool enable) { d->internalHostMatch = enable; } +bool QCATLSHandler::XMPPCertCheck() { return d->internalHostMatch; } bool QCATLSHandler::certMatchesHostname() { - if (!d->internalHostMatch) return false; + if (!d->internalHostMatch) + return false; QCA::CertificateChain peerCert = d->tls->peerCertificateChain(); if (matchesHostName(peerCert.primary(), d->host)) @@ -361,7 +319,7 @@ bool QCATLSHandler::certMatchesHostname() Jid host(d->host); - foreach( const QString &idOnXmppAddr, peerCert.primary().subjectInfo().values(QCA::XMPP) ) { + foreach (const QString &idOnXmppAddr, peerCert.primary().subjectInfo().values(QCA::XMPP)) { if (host.compare(Jid(idOnXmppAddr))) return true; } @@ -369,15 +327,9 @@ bool QCATLSHandler::certMatchesHostname() return false; } -QCA::TLS *QCATLSHandler::tls() const -{ - return d->tls; -} +QCA::TLS *QCATLSHandler::tls() const { return d->tls; } -int QCATLSHandler::tlsError() const -{ - return d->err; -} +int QCATLSHandler::tlsError() const { return d->err; } void QCATLSHandler::reset() { @@ -388,24 +340,19 @@ void QCATLSHandler::reset() void QCATLSHandler::startClient(const QString &host) { d->state = 0; - d->err = -1; - if (d->internalHostMatch) d->host = host; + d->err = -1; + if (d->internalHostMatch) + d->host = host; d->tls->startClient(d->internalHostMatch ? QString() : host); } -void QCATLSHandler::write(const QByteArray &a) -{ - d->tls->write(a); -} +void QCATLSHandler::write(const QByteArray &a) { d->tls->write(a); } -void QCATLSHandler::writeIncoming(const QByteArray &a) -{ - d->tls->writeIncoming(a); -} +void QCATLSHandler::writeIncoming(const QByteArray &a) { d->tls->writeIncoming(a); } void QCATLSHandler::continueAfterHandshake() { - if(d->state == 2) { + if (d->state == 2) { d->tls->continueAfterStep(); success(); d->state = 3; @@ -418,26 +365,20 @@ void QCATLSHandler::tls_handshaken() tlsHandshaken(); } -void QCATLSHandler::tls_readyRead() -{ - readyRead(d->tls->read()); -} +void QCATLSHandler::tls_readyRead() { readyRead(d->tls->read()); } void QCATLSHandler::tls_readyReadOutgoing() { - int plainBytes; + int plainBytes; QByteArray buf = d->tls->readOutgoing(&plainBytes); readyReadOutgoing(buf, plainBytes); } -void QCATLSHandler::tls_closed() -{ - closed(); -} +void QCATLSHandler::tls_closed() { closed(); } void QCATLSHandler::tls_error() { - d->err = d->tls->errorCode(); + d->err = d->tls->errorCode(); d->state = 0; fail(); } diff --git a/src/xmpp/xmpp-core/xmlprotocol.cpp b/src/xmpp/xmpp-core/xmlprotocol.cpp index 32e6aa85..43761085 100644 --- a/src/xmpp/xmpp-core/xmlprotocol.cpp +++ b/src/xmpp/xmpp-core/xmlprotocol.cpp @@ -37,33 +37,33 @@ static QDomElement stripExtraNS(const QDomElement &e) { // find closest parent with a namespace QDomNode par = e.parentNode(); - while(!par.isNull() && par.namespaceURI().isNull()) + while (!par.isNull() && par.namespaceURI().isNull()) par = par.parentNode(); bool noShowNS = false; - if(!par.isNull() && par.namespaceURI() == e.namespaceURI()) + if (!par.isNull() && par.namespaceURI() == e.namespaceURI()) noShowNS = true; // build qName (prefix:localName) QString qName; - if(!e.prefix().isEmpty()) + if (!e.prefix().isEmpty()) qName = e.prefix() + ':' + e.localName(); else qName = e.tagName(); QDomElement i; - int x; - if(noShowNS) + int x; + if (noShowNS) i = e.ownerDocument().createElement(qName); else i = e.ownerDocument().createElementNS(e.namespaceURI(), qName); // copy attributes QDomNamedNodeMap al = e.attributes(); - for(x = 0; x < al.count(); ++x) { + for (x = 0; x < al.count(); ++x) { QDomAttr a = al.item(x).cloneNode().toAttr(); // don't show xml namespace - if(a.namespaceURI() == NS_XML) + if (a.namespaceURI() == NS_XML) i.setAttribute(QString("xml:") + a.name(), a.value()); else i.setAttributeNodeNS(a); @@ -71,9 +71,9 @@ static QDomElement stripExtraNS(const QDomElement &e) // copy children QDomNodeList nl = e.childNodes(); - for(x = 0; x < nl.count(); ++x) { + for (x = 0; x < nl.count(); ++x) { QDomNode n = nl.item(x); - if(n.isElement()) + if (n.isElement()) i.appendChild(stripExtraNS(n.toElement())); else i.appendChild(n.cloneNode()); @@ -108,9 +108,9 @@ static QString xmlToString(const QDomElement &e, const QString &fakeNS, const QS fake.firstChild().save(ts, 0); } // 'clip' means to remove any unwanted (and unneeded) characters, such as a trailing newline - if(clip) { + if (clip) { int n = out.lastIndexOf('>'); - out.truncate(n+1); + out.truncate(n + 1); } return out; } @@ -139,14 +139,14 @@ static void createRootXmlTags(const QDomElement &root, QString *xmlHeader, QStri } // parse the tags out - int n = str.indexOf('<'); + int n = str.indexOf('<'); int n2 = str.indexOf('>', n); ++n2; - *tagOpen = str.mid(n, n2-n); - n2 = str.lastIndexOf('>'); - n = str.lastIndexOf('<'); + *tagOpen = str.mid(n, n2 - n); + n2 = str.lastIndexOf('>'); + n = str.lastIndexOf('<'); ++n2; - *tagClose = str.mid(n, n2-n); + *tagClose = str.mid(n, n2 - n); // generate a nice xml processing header *xmlHeader = ""; @@ -156,21 +156,13 @@ static void createRootXmlTags(const QDomElement &root, QString *xmlHeader, QStri // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] static inline bool validChar(const quint32 ch) { - return ch == 0x9 || ch == 0xA || ch == 0xD - || (ch >= 0x20 && ch <= 0xD7FF) - || (ch >= 0xE000 && ch <= 0xFFFD) - || (ch >= 0x10000 && ch <= 0x10FFFF); + return ch == 0x9 || ch == 0xA || ch == 0xD || (ch >= 0x20 && ch <= 0xD7FF) || (ch >= 0xE000 && ch <= 0xFFFD) + || (ch >= 0x10000 && ch <= 0x10FFFF); } -static inline bool lowSurrogate(const quint32 ch) -{ - return ch >= 0xDC00 && ch <= 0xDFFF; -} +static inline bool lowSurrogate(const quint32 ch) { return ch >= 0xDC00 && ch <= 0xDFFF; } -static inline bool highSurrogate(const quint32 ch) -{ - return ch >= 0xD800 && ch <= 0xDBFF; -} +static inline bool highSurrogate(const quint32 ch) { return ch >= 0xD800 && ch <= 0xDBFF; } // force encoding of '>'. this function is needed for XMPP-Core, which // requires the '>' character to be encoded as ">" even though this is @@ -180,63 +172,53 @@ static inline bool highSurrogate(const quint32 ch) static QString sanitizeForStream(const QString &in) { QString out; - bool intag = false; - bool inquote = false; - QChar quotechar; - int inlength = in.length(); - for(int n = 0; n < inlength; ++n) - { - QChar c = in[n]; - bool escape = false; - if(c == '<') - { + bool intag = false; + bool inquote = false; + QChar quotechar; + int inlength = in.length(); + for (int n = 0; n < inlength; ++n) { + QChar c = in[n]; + bool escape = false; + if (c == '<') { intag = true; - } - else if(c == '>') - { - if(inquote) { + } else if (c == '>') { + if (inquote) { escape = true; - } else if(!intag) { + } else if (!intag) { escape = true; } else { intag = false; } - } - else if(c == '\'' || c == '\"') - { - if(intag) - { - if(!inquote) - { - inquote = true; + } else if (c == '\'' || c == '\"') { + if (intag) { + if (!inquote) { + inquote = true; quotechar = c; - } - else - { - if(quotechar == c) { + } else { + if (quotechar == c) { inquote = false; } } } } - if(escape) { + if (escape) { out += ">"; - } else { + } else { // don't silently drop invalid chars in element or attribute names, // because that's something that should not happen. if (intag && (!inquote)) { out += c; - } else if (validChar(c.unicode())) { + } else if (validChar(c.unicode())) { out += c; - } else if (highSurrogate(c.unicode()) && (n+1 < inlength) && lowSurrogate(in[n+1].unicode())) { - //uint unicode = (c.unicode() & 0x3FF) << 10 | in[n+1].unicode() & 0x3FF + 0x10000; + } else if (highSurrogate(c.unicode()) && (n + 1 < inlength) && lowSurrogate(in[n + 1].unicode())) { + // uint unicode = (c.unicode() & 0x3FF) << 10 | in[n+1].unicode() & 0x3FF + 0x10000; // we don't need to recheck this, because 0x10000 <= unicode <= 0x100000 is always true out += c; - out += in[n+1]; + out += in[n + 1]; ++n; } else { - qDebug("Dropping invalid XML char U+%04x",c.unicode()); + qDebug("Dropping invalid XML char U+%04x", c.unicode()); } } } @@ -246,39 +228,26 @@ static QString sanitizeForStream(const QString &in) //---------------------------------------------------------------------------- // Protocol //---------------------------------------------------------------------------- -XmlProtocol::TransferItem::TransferItem() -{ -} +XmlProtocol::TransferItem::TransferItem() {} -XmlProtocol::TransferItem::TransferItem(const QString &_str, bool sent, bool external) - : isSent(sent) - , isString(true) - , isExternal(external) - , str(_str) +XmlProtocol::TransferItem::TransferItem(const QString &_str, bool sent, bool external) : + isSent(sent), isString(true), isExternal(external), str(_str) { } -XmlProtocol::TransferItem::TransferItem(const QDomElement &_elem, bool sent, bool external) - : isSent(sent) - , isString(false) - , isExternal(external) - , elem(_elem) +XmlProtocol::TransferItem::TransferItem(const QDomElement &_elem, bool sent, bool external) : + isSent(sent), isString(false), isExternal(external), elem(_elem) { } -XmlProtocol::XmlProtocol() -{ - init(); -} +XmlProtocol::XmlProtocol() { init(); } -XmlProtocol::~XmlProtocol() -{ -} +XmlProtocol::~XmlProtocol() {} void XmlProtocol::init() { - incoming = false; - peerClosed = false; + incoming = false; + peerClosed = false; closeWritten = false; } @@ -286,9 +255,9 @@ void XmlProtocol::reset() { init(); - elem = QDomElement(); - elemDoc = QDomDocument(); - tagOpen = QString(); + elem = QDomElement(); + elemDoc = QDomDocument(); + tagOpen = QString(); tagClose = QString(); xml.reset(); outDataNormal.resize(0); @@ -298,10 +267,7 @@ void XmlProtocol::reset() transferItemList.clear(); } -void XmlProtocol::addIncomingData(const QByteArray &a) -{ - xml.appendData(a); -} +void XmlProtocol::addIncomingData(const QByteArray &a) { xml.appendData(a); } QByteArray XmlProtocol::takeOutgoingData() { @@ -328,60 +294,57 @@ bool XmlProtocol::processStep() notify = 0; transferItemList.clear(); - if(state != Closing && (state == RecvOpen || stepAdvancesParser())) { + if (state != Closing && (state == RecvOpen || stepAdvancesParser())) { // if we get here, then it's because we're in some step that advances the parser pe = xml.readNext(); - if(!pe.isNull()) { + if (!pe.isNull()) { // note: error/close events should be handled for ALL steps, so do them here - switch(pe.type()) { - case Parser::Event::DocumentOpen: { - transferItemList += TransferItem(pe.actualString(), false); + switch (pe.type()) { + case Parser::Event::DocumentOpen: { + transferItemList += TransferItem(pe.actualString(), false); - //stringRecv(pe.actualString()); - break; - } - case Parser::Event::DocumentClose: { - transferItemList += TransferItem(pe.actualString(), false); - - //stringRecv(pe.actualString()); - if(incoming) { - sendTagClose(); - event = ESend; - peerClosed = true; - state = Closing; - } - else { - event = EPeerClosed; - } - return true; + // stringRecv(pe.actualString()); + break; + } + case Parser::Event::DocumentClose: { + transferItemList += TransferItem(pe.actualString(), false); + + // stringRecv(pe.actualString()); + if (incoming) { + sendTagClose(); + event = ESend; + peerClosed = true; + state = Closing; + } else { + event = EPeerClosed; } - case Parser::Event::Element: { - QDomElement e = elemDoc.importNode(pe.element(),true).toElement(); - transferItemList += TransferItem(e, false); + return true; + } + case Parser::Event::Element: { + QDomElement e = elemDoc.importNode(pe.element(), true).toElement(); + transferItemList += TransferItem(e, false); - //elementRecv(pe.element()); - break; - } - case Parser::Event::Error: { - if(incoming) { - // If we get a parse error during the initial element exchange, - // flip immediately into 'open' mode so that we can report an error. - if(state == RecvOpen) { - sendTagOpen(); - state = Open; - } - return handleError(); - } - else { - event = EError; - errorCode = ErrParse; - return true; + // elementRecv(pe.element()); + break; + } + case Parser::Event::Error: { + if (incoming) { + // If we get a parse error during the initial element exchange, + // flip immediately into 'open' mode so that we can report an error. + if (state == RecvOpen) { + sendTagOpen(); + state = Open; } + return handleError(); + } else { + event = EError; + errorCode = ErrParse; + return true; } } - } - else { - if(state == RecvOpen || stepRequiresElement()) { + } + } else { + if (state == RecvOpen || stepRequiresElement()) { need = NNotify; notify |= NRecv; return false; @@ -392,14 +355,11 @@ bool XmlProtocol::processStep() return baseStep(pe); } -QString XmlProtocol::xmlEncoding() const -{ - return xml.encoding(); -} +QString XmlProtocol::xmlEncoding() const { return xml.encoding(); } QString XmlProtocol::elementToString(const QDomElement &e, bool clip) { - if(elem.isNull()) + if (elem.isNull()) elem = elemDoc.importNode(docElement(), true).toElement(); // Determine the appropriate 'fakeNS' to use @@ -407,29 +367,28 @@ QString XmlProtocol::elementToString(const QDomElement &e, bool clip) // first, check root namespace QString pre = e.prefix(); - if(pre.isNull()) + if (pre.isNull()) pre = ""; - if(pre == elem.prefix()) { + if (pre == elem.prefix()) { ns = elem.namespaceURI(); - } - else { + } else { // scan the root attributes for 'xmlns' (oh joyous hacks) QDomNamedNodeMap al = elem.attributes(); - int n; - for(n = 0; n < al.count(); ++n) { + int n; + for (n = 0; n < al.count(); ++n) { QDomAttr a = al.item(n).toAttr(); - QString s = a.name(); - int x = s.indexOf(':'); - if(x != -1) - s = s.mid(x+1); + QString s = a.name(); + int x = s.indexOf(':'); + if (x != -1) + s = s.mid(x + 1); else s = ""; - if(pre == s) { + if (pre == s) { ns = a.value(); break; } } - if(n >= al.count()) { + if (n >= al.count()) { // if we get here, then no appropriate ns was found. use root then.. ns = elem.namespaceURI(); } @@ -437,7 +396,7 @@ QString XmlProtocol::elementToString(const QDomElement &e, bool clip) // build qName QString qn; - if(!elem.prefix().isEmpty()) + if (!elem.prefix().isEmpty()) qn = elem.prefix() + ':'; qn += elem.localName(); @@ -479,13 +438,13 @@ void XmlProtocol::elementRecv(const QDomElement &) void XmlProtocol::startConnect() { incoming = false; - state = SendOpen; + state = SendOpen; } void XmlProtocol::startAccept() { incoming = true; - state = RecvOpen; + state = RecvOpen; } bool XmlProtocol::close() @@ -504,11 +463,11 @@ int XmlProtocol::writeString(const QString &s, int id, bool external) int XmlProtocol::writeElement(const QDomElement &e, int id, bool external, bool clip, bool urgent) { - if(e.isNull()) + if (e.isNull()) return 0; transferItemList += TransferItem(e, true, external); - //elementSend(e); + // elementSend(e); QString out = sanitizeForStream(elementToString(e, clip)); return internalWriteString(out, TrackItem::Custom, id, urgent); } @@ -516,7 +475,7 @@ int XmlProtocol::writeElement(const QDomElement &e, int id, bool external, bool QByteArray XmlProtocol::resetStream() { // reset the state - if(incoming) + if (incoming) state = RecvOpen; else state = SendOpen; @@ -531,14 +490,13 @@ int XmlProtocol::internalWriteData(const QByteArray &a, TrackItem::Type t, int i { TrackItem i; i.type = t; - i.id = id; + i.id = id; i.size = a.size(); if (urgent) { trackQueueUrgent += i; outDataUrgent += a; - } - else { + } else { trackQueueNormal += i; outDataNormal += a; } @@ -547,34 +505,32 @@ int XmlProtocol::internalWriteData(const QByteArray &a, TrackItem::Type t, int i int XmlProtocol::internalWriteString(const QString &s, TrackItem::Type t, int id, bool urgent) { - QString out=sanitizeForStream(s); + QString out = sanitizeForStream(s); return internalWriteData(s.toUtf8(), t, id, urgent); } int XmlProtocol::processTrackQueue(QList &queue, int bytes) { - for(QList::Iterator it = queue.begin(); it != queue.end();) { + for (QList::Iterator it = queue.begin(); it != queue.end();) { TrackItem &i = *it; // enough bytes? - if(bytes < i.size) { + if (bytes < i.size) { i.size -= bytes; bytes = 0; break; } int type = i.type; - int id = i.id; + int id = i.id; int size = i.size; bytes -= i.size; it = queue.erase(it); - if(type == TrackItem::Raw) { + if (type == TrackItem::Raw) { // do nothing - } - else if(type == TrackItem::Close) { + } else if (type == TrackItem::Close) { closeWritten = true; - } - else if(type == TrackItem::Custom) { + } else if (type == TrackItem::Custom) { itemWritten(id, size); } if (bytes == 0) @@ -585,7 +541,7 @@ int XmlProtocol::processTrackQueue(QList &queue, int bytes) void XmlProtocol::sendTagOpen() { - if(elem.isNull()) + if (elem.isNull()) elem = elemDoc.importNode(docElement(), true).toElement(); QString xmlHeader; @@ -598,8 +554,8 @@ void XmlProtocol::sendTagOpen() transferItemList += TransferItem(xmlHeader, true); transferItemList += TransferItem(tagOpen, true); - //stringSend(xmlHeader); - //stringSend(tagOpen); + // stringSend(xmlHeader); + // stringSend(tagOpen); internalWriteString(s, TrackItem::Raw); } @@ -607,24 +563,23 @@ void XmlProtocol::sendTagClose() { transferItemList += TransferItem(tagClose, true); - //stringSend(tagClose); + // stringSend(tagClose); internalWriteString(tagClose, TrackItem::Close); } bool XmlProtocol::baseStep(const Parser::Event &pe) { // Basic - if(state == SendOpen) { + if (state == SendOpen) { sendTagOpen(); event = ESend; - if(incoming) + if (incoming) state = Open; else state = RecvOpen; return true; - } - else if(state == RecvOpen) { - if(incoming) + } else if (state == RecvOpen) { + if (incoming) state = SendOpen; else state = Open; @@ -633,25 +588,23 @@ bool XmlProtocol::baseStep(const Parser::Event &pe) handleDocOpen(pe); event = ERecvOpen; return true; - } - else if(state == Open) { + } else if (state == Open) { QDomElement e; - if(pe.type() == Parser::Event::Element) + if (pe.type() == Parser::Event::Element) e = pe.element(); return doStep(e); } // Closing else { - if(closeWritten) { - if(peerClosed) { + if (closeWritten) { + if (peerClosed) { event = EPeerClosed; return true; - } - else + } else return handleCloseFinished(); } - need = NNotify; + need = NNotify; notify = NSend; return false; } @@ -659,11 +612,10 @@ bool XmlProtocol::baseStep(const Parser::Event &pe) void XmlProtocol::setIncomingAsExternal() { - for(QList::Iterator it = transferItemList.begin(); it != transferItemList.end(); ++it) { + for (QList::Iterator it = transferItemList.begin(); it != transferItemList.end(); ++it) { TransferItem &i = *it; // look for elements received - if(!i.isString && !i.isSent) + if (!i.isString && !i.isSent) i.isExternal = true; } } - diff --git a/src/xmpp/xmpp-core/xmlprotocol.h b/src/xmpp/xmpp-core/xmlprotocol.h index 2f02a75a..4e061eb7 100644 --- a/src/xmpp/xmpp-core/xmlprotocol.h +++ b/src/xmpp/xmpp-core/xmlprotocol.h @@ -29,124 +29,121 @@ #define NS_XML "http://www.w3.org/XML/1998/namespace" namespace XMPP { - class XmlProtocol : public QObject - { +class XmlProtocol : public QObject { +public: + enum Need { + NNotify, // need a data send and/or recv update + NCustom = 10 + }; + enum Event { + EError, // unrecoverable error, see errorCode for details + ESend, // data needs to be sent, use takeOutgoingData() + ERecvOpen, // breakpoint after root element open tag is received + EPeerClosed, // root element close tag received + EClosed, // finished closing + ESMConnTimeout, // absence of responses to query + ESMResumeFailed, // failed to resume sm session + ECustom = 10 + }; + enum Error { + ErrParse, // there was an error parsing the xml + ErrCustom = 10 + }; + enum Notify { + NSend = 0x01, // need to know if data has been written + NRecv = 0x02, // need incoming data + NTimeout = 0x04 // need to know when time passed + }; + + XmlProtocol(); + virtual ~XmlProtocol(); + + virtual void reset(); + + // byte I/O for the stream + void addIncomingData(const QByteArray &); + QByteArray takeOutgoingData(); + void outgoingDataWritten(int); + + // advance the state machine + bool processStep(); + + // set these before returning from a step + int need = 0, event = 0, errorCode = 0, notify = 0, timeout_sec = 0; + + inline bool isIncoming() const { return incoming; } + QString xmlEncoding() const; + QString elementToString(const QDomElement &e, bool clip = false); + + class TransferItem { public: - enum Need { - NNotify, // need a data send and/or recv update - NCustom = 10 - }; - enum Event { - EError, // unrecoverable error, see errorCode for details - ESend, // data needs to be sent, use takeOutgoingData() - ERecvOpen, // breakpoint after root element open tag is received - EPeerClosed, // root element close tag received - EClosed, // finished closing - ESMConnTimeout, // absence of responses to query - ESMResumeFailed, // failed to resume sm session - ECustom = 10 - }; - enum Error { - ErrParse, // there was an error parsing the xml - ErrCustom = 10 - }; - enum Notify { - NSend = 0x01, // need to know if data has been written - NRecv = 0x02, // need incoming data - NTimeout = 0x04 // need to know when time passed - }; - - XmlProtocol(); - virtual ~XmlProtocol(); - - virtual void reset(); - - // byte I/O for the stream - void addIncomingData(const QByteArray &); - QByteArray takeOutgoingData(); - void outgoingDataWritten(int); - - // advance the state machine - bool processStep(); - - // set these before returning from a step - int need = 0, event = 0, errorCode = 0, notify = 0, timeout_sec = 0; - - inline bool isIncoming() const { return incoming; } - QString xmlEncoding() const; - QString elementToString(const QDomElement &e, bool clip=false); - - class TransferItem - { - public: - TransferItem(); - TransferItem(const QString &str, bool sent, bool external=false); - TransferItem(const QDomElement &elem, bool sent, bool external=false); - - bool isSent; // else, received - bool isString; // else, is element - bool isExternal; // not owned by protocol - QString str; - QDomElement elem; - }; - QList transferItemList; - void setIncomingAsExternal(); - - protected: - virtual QDomElement docElement()=0; - virtual void handleDocOpen(const Parser::Event &pe)=0; - virtual bool handleError()=0; - virtual bool handleCloseFinished()=0; - virtual bool stepAdvancesParser() const=0; - virtual bool stepRequiresElement() const; - virtual bool doStep(const QDomElement &e)=0; - virtual void itemWritten(int id, int size); - - // 'debug' - virtual void stringSend(const QString &s); - virtual void stringRecv(const QString &s); - virtual void elementSend(const QDomElement &e); - virtual void elementRecv(const QDomElement &e); - - void startConnect(); - void startAccept(); - bool close(); - int writeString(const QString &s, int id, bool external); - int writeElement(const QDomElement &e, int id, bool external, bool clip=false, bool urgent = false); - QByteArray resetStream(); - - private: - enum { SendOpen, RecvOpen, Open, Closing }; - class TrackItem - { - public: - enum Type { Raw, Close, Custom }; - int type, id, size; - }; - - bool incoming; - QDomDocument elemDoc; + TransferItem(); + TransferItem(const QString &str, bool sent, bool external = false); + TransferItem(const QDomElement &elem, bool sent, bool external = false); + + bool isSent; // else, received + bool isString; // else, is element + bool isExternal; // not owned by protocol + QString str; QDomElement elem; - QString tagOpen; - QString tagClose; - int state = 0; - bool peerClosed; - bool closeWritten; - - Parser xml; - QByteArray outDataNormal; - QByteArray outDataUrgent; - QList trackQueueNormal; - QList trackQueueUrgent; - - void init(); - int internalWriteData(const QByteArray &a, TrackItem::Type t, int id=-1, bool urgent = false); - int internalWriteString(const QString &s, TrackItem::Type t, int id=-1, bool urgent = false); - int processTrackQueue(QList &queue, int bytes); - void sendTagOpen(); - void sendTagClose(); - bool baseStep(const Parser::Event &pe); }; + QList transferItemList; + void setIncomingAsExternal(); + +protected: + virtual QDomElement docElement() = 0; + virtual void handleDocOpen(const Parser::Event &pe) = 0; + virtual bool handleError() = 0; + virtual bool handleCloseFinished() = 0; + virtual bool stepAdvancesParser() const = 0; + virtual bool stepRequiresElement() const; + virtual bool doStep(const QDomElement &e) = 0; + virtual void itemWritten(int id, int size); + + // 'debug' + virtual void stringSend(const QString &s); + virtual void stringRecv(const QString &s); + virtual void elementSend(const QDomElement &e); + virtual void elementRecv(const QDomElement &e); + + void startConnect(); + void startAccept(); + bool close(); + int writeString(const QString &s, int id, bool external); + int writeElement(const QDomElement &e, int id, bool external, bool clip = false, bool urgent = false); + QByteArray resetStream(); + +private: + enum { SendOpen, RecvOpen, Open, Closing }; + class TrackItem { + public: + enum Type { Raw, Close, Custom }; + int type, id, size; + }; + + bool incoming; + QDomDocument elemDoc; + QDomElement elem; + QString tagOpen; + QString tagClose; + int state = 0; + bool peerClosed; + bool closeWritten; + + Parser xml; + QByteArray outDataNormal; + QByteArray outDataUrgent; + QList trackQueueNormal; + QList trackQueueUrgent; + + void init(); + int internalWriteData(const QByteArray &a, TrackItem::Type t, int id = -1, bool urgent = false); + int internalWriteString(const QString &s, TrackItem::Type t, int id = -1, bool urgent = false); + int processTrackQueue(QList &queue, int bytes); + void sendTagOpen(); + void sendTagClose(); + bool baseStep(const Parser::Event &pe); +}; } // namespace XMPP #endif // XMLPROTOCOL_H diff --git a/src/xmpp/xmpp-core/xmpp.h b/src/xmpp/xmpp-core/xmpp.h index 2bb59c63..834a40ae 100644 --- a/src/xmpp/xmpp-core/xmpp.h +++ b/src/xmpp/xmpp-core/xmpp.h @@ -35,199 +35,193 @@ #include // For QCA::SASL::Params #ifndef CS_XMPP - class ByteStream; +class ByteStream; #endif namespace QCA { - class TLS; +class TLS; }; namespace XMPP { - // CS_IMPORT_BEGIN cutestuff/bytestream.h +// CS_IMPORT_BEGIN cutestuff/bytestream.h #ifdef CS_XMPP - class ByteStream; +class ByteStream; #endif - // CS_IMPORT_END +// CS_IMPORT_END - class Debug - { - public: - virtual ~Debug(); +class Debug { +public: + virtual ~Debug(); - virtual void msg(const QString &)=0; - virtual void outgoingTag(const QString &)=0; - virtual void incomingTag(const QString &)=0; - virtual void outgoingXml(const QDomElement &)=0; - virtual void incomingXml(const QDomElement &)=0; - }; + virtual void msg(const QString &) = 0; + virtual void outgoingTag(const QString &) = 0; + virtual void incomingTag(const QString &) = 0; + virtual void outgoingXml(const QDomElement &) = 0; + virtual void incomingXml(const QDomElement &) = 0; +}; - void setDebug(Debug *); +void setDebug(Debug *); - class Connector : public QObject - { - Q_OBJECT - public: - Connector(QObject *parent=nullptr); - virtual ~Connector(); +class Connector : public QObject { + Q_OBJECT +public: + Connector(QObject *parent = nullptr); + virtual ~Connector(); - virtual void setOptHostPort(const QString &host, quint16 port)=0; - virtual void connectToServer(const QString &server)=0; - virtual ByteStream *stream() const=0; - virtual void done()=0; + virtual void setOptHostPort(const QString &host, quint16 port) = 0; + virtual void connectToServer(const QString &server) = 0; + virtual ByteStream *stream() const = 0; + virtual void done() = 0; - bool useSSL() const; - bool havePeerAddress() const; - QHostAddress peerAddress() const; - quint16 peerPort() const; + bool useSSL() const; + bool havePeerAddress() const; + QHostAddress peerAddress() const; + quint16 peerPort() const; - virtual QString host() const; + virtual QString host() const; - signals: - void connected(); - void error(); +signals: + void connected(); + void error(); - protected: - void setUseSSL(bool b); - void setPeerAddressNone(); - void setPeerAddress(const QHostAddress &addr, quint16 port); +protected: + void setUseSSL(bool b); + void setPeerAddressNone(); + void setPeerAddress(const QHostAddress &addr, quint16 port); - private: - bool ssl; // a flag to start ssl handshake immediately - bool haveaddr; - QHostAddress addr; - quint16 port; - }; +private: + bool ssl; // a flag to start ssl handshake immediately + bool haveaddr; + QHostAddress addr; + quint16 port; +}; - class AdvancedConnector : public Connector - { - Q_OBJECT +class AdvancedConnector : public Connector { + Q_OBJECT +public: + enum Error { ErrConnectionRefused, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth, ErrStream }; + AdvancedConnector(QObject *parent = nullptr); + virtual ~AdvancedConnector(); + + class Proxy { public: - enum Error { ErrConnectionRefused, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth, ErrStream }; - AdvancedConnector(QObject *parent=nullptr); - virtual ~AdvancedConnector(); - - class Proxy - { - public: - enum { None, HttpConnect, HttpPoll, Socks }; - Proxy() = default; - ~Proxy() {} - - int type() const; - QString host() const; - quint16 port() const; - QUrl url() const; - QString user() const; - QString pass() const; - int pollInterval() const; - - void setHttpConnect(const QString &host, quint16 port); - void setHttpPoll(const QString &host, quint16 port, const QUrl &url); - void setSocks(const QString &host, quint16 port); - void setUserPass(const QString &user, const QString &pass); - void setPollInterval(int secs); - - private: - int t = None; - QUrl v_url; - QString v_host; - quint16 v_port = 0; - QString v_user; - QString v_pass; - int v_poll = 30; - }; - - void setProxy(const Proxy &proxy); - void setOptProbe(bool); - void setOptSSL(bool); - - void changePollInterval(int secs); - - void setOptHostPort(const QString &host, quint16 port); - void connectToServer(const QString &server); - ByteStream *stream() const; - void done(); - - int errorCode() const; - - virtual QString host() const; - - signals: - void srvLookup(const QString &server); - void srvResult(bool success); - void httpSyncStarted(); - void httpSyncFinished(); - - private slots: - void bs_connected(); - void bs_error(int); - void http_syncStarted(); - void http_syncFinished(); - void t_timeout(); + enum { None, HttpConnect, HttpPoll, Socks }; + Proxy() = default; + ~Proxy() {} + + int type() const; + QString host() const; + quint16 port() const; + QUrl url() const; + QString user() const; + QString pass() const; + int pollInterval() const; + + void setHttpConnect(const QString &host, quint16 port); + void setHttpPoll(const QString &host, quint16 port, const QUrl &url); + void setSocks(const QString &host, quint16 port); + void setUserPass(const QString &user, const QString &pass); + void setPollInterval(int secs); private: - class Private; - Private *d; - - void cleanup(); + int t = None; + QUrl v_url; + QString v_host; + quint16 v_port = 0; + QString v_user; + QString v_pass; + int v_poll = 30; }; - class TLSHandler : public QObject - { - Q_OBJECT - public: - TLSHandler(QObject *parent=nullptr); - virtual ~TLSHandler(); - - virtual void reset()=0; - virtual void startClient(const QString &host)=0; - virtual void write(const QByteArray &a)=0; - virtual void writeIncoming(const QByteArray &a)=0; - - signals: - void success(); - void fail(); - void closed(); - void readyRead(const QByteArray &a); - void readyReadOutgoing(const QByteArray &a, int plainBytes); - }; + void setProxy(const Proxy &proxy); + void setOptProbe(bool); + void setOptSSL(bool); - class QCATLSHandler : public TLSHandler - { - Q_OBJECT - public: - QCATLSHandler(QCA::TLS *parent); - ~QCATLSHandler(); + void changePollInterval(int secs); - QCA::TLS *tls() const; - int tlsError() const; + void setOptHostPort(const QString &host, quint16 port); + void connectToServer(const QString &server); + ByteStream *stream() const; + void done(); - void setXMPPCertCheck(bool enable); - bool XMPPCertCheck(); - bool certMatchesHostname(); + int errorCode() const; - void reset(); - void startClient(const QString &host); - void write(const QByteArray &a); - void writeIncoming(const QByteArray &a); + virtual QString host() const; - signals: - void tlsHandshaken(); +signals: + void srvLookup(const QString &server); + void srvResult(bool success); + void httpSyncStarted(); + void httpSyncFinished(); - public slots: - void continueAfterHandshake(); +private slots: + void bs_connected(); + void bs_error(int); + void http_syncStarted(); + void http_syncFinished(); + void t_timeout(); - private slots: - void tls_handshaken(); - void tls_readyRead(); - void tls_readyReadOutgoing(); - void tls_closed(); - void tls_error(); +private: + class Private; + Private *d; - private: - class Private; - Private *d; - }; + void cleanup(); +}; + +class TLSHandler : public QObject { + Q_OBJECT +public: + TLSHandler(QObject *parent = nullptr); + virtual ~TLSHandler(); + + virtual void reset() = 0; + virtual void startClient(const QString &host) = 0; + virtual void write(const QByteArray &a) = 0; + virtual void writeIncoming(const QByteArray &a) = 0; + +signals: + void success(); + void fail(); + void closed(); + void readyRead(const QByteArray &a); + void readyReadOutgoing(const QByteArray &a, int plainBytes); +}; + +class QCATLSHandler : public TLSHandler { + Q_OBJECT +public: + QCATLSHandler(QCA::TLS *parent); + ~QCATLSHandler(); + + QCA::TLS *tls() const; + int tlsError() const; + + void setXMPPCertCheck(bool enable); + bool XMPPCertCheck(); + bool certMatchesHostname(); + + void reset(); + void startClient(const QString &host); + void write(const QByteArray &a); + void writeIncoming(const QByteArray &a); + +signals: + void tlsHandshaken(); + +public slots: + void continueAfterHandshake(); + +private slots: + void tls_handshaken(); + void tls_readyRead(); + void tls_readyReadOutgoing(); + void tls_closed(); + void tls_error(); + +private: + class Private; + Private *d; +}; }; // namespace XMPP #endif // XMPP_H diff --git a/src/xmpp/xmpp-core/xmpp_clientstream.h b/src/xmpp/xmpp-core/xmpp_clientstream.h index f06d1e39..20551943 100644 --- a/src/xmpp/xmpp-core/xmpp_clientstream.h +++ b/src/xmpp/xmpp-core/xmpp_clientstream.h @@ -32,199 +32,192 @@ class QObject; class QString; namespace XMPP { - class Connector; - class StreamFeatures; - class TLSHandler; - - class ClientStream : public Stream - { - Q_OBJECT - public: - enum Error { - ErrConnection = ErrCustom, // Connection error, ask Connector-subclass what's up - ErrNeg, // Negotiation error, see condition - ErrTLS, // TLS error, see condition - ErrAuth, // Auth error, see condition - ErrSecurityLayer, // broken SASL security layer - ErrSmResume, // SM resume error - ErrBind // Resource binding error - }; - enum Warning { - WarnOldVersion, // server uses older XMPP/Jabber "0.9" protocol - WarnNoTLS, // there is no chance for TLS at this point - WarnSMReconnection // SM started a quiet stream reconnection - }; - enum NegCond { - HostGone, // host no longer hosted - HostUnknown, // unknown host - RemoteConnectionFailed, // unable to connect to a required remote resource - SeeOtherHost, // a 'redirect', see errorText() for other host - UnsupportedVersion // unsupported XMPP version - }; - enum TLSCond { - TLSStart, // server rejected STARTTLS - TLSFail // TLS failed, ask TLSHandler-subclass what's up - }; - enum SecurityLayer { - LayerTLS, - LayerSASL - }; - enum AuthCond { - GenericAuthError, // all-purpose "can't login" error (includes: IncorrectEncoding, ) - - // standard xmpp auth errors (not all. some of the converted to GenericAuthError): - Aborted, // server confirms auth abort - AccountDisabled, // account temporrily disabled - CredentialsExpired, // credential expired - EncryptionRequired, // can't use mech without TLS - InvalidAuthzid, // bad input JID - InvalidMech, // bad mechanism - MalformedRequest, // malformded request - MechTooWeak, // can't use mech with this authzid - NotAuthorized, // bad user, bad password, bad creditials - TemporaryAuthFailure, // please try again later! - - // non-xmpp - NoMech, // No appropriate auth mech available - BadServ, // Server failed mutual auth - }; - enum BindCond { - BindNotAllowed, // not allowed to bind a resource - BindConflict // resource in-use - }; - enum AllowPlainType { - NoAllowPlain, - AllowPlain, - AllowPlainOverTLS - }; - - ClientStream(Connector *conn, TLSHandler *tlsHandler=nullptr, QObject *parent=nullptr); - ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls=nullptr, QObject *parent=nullptr); // server - ~ClientStream(); - - Jid jid() const; - void connectToServer(const Jid &jid, bool auth=true); - void accept(); // server - bool isActive() const; - bool isAuthenticated() const; - - // login params - void setUsername(const QString &s); - void setPassword(const QString &s); - void setRealm(const QString &s); - void setAuthzid(const QString &s); - void continueAfterParams(); - void abortAuth(); - void setSaslMechanismProvider(const QString &m, const QString &p); - QString saslMechanismProvider(const QString &m) const; - QCA::Provider::Context *currentSASLContext() const; - - void setSCRAMStoredSaltedHash(const QString &s); - const QString getSCRAMStoredSaltedHash(); - - // SASL information - QString saslMechanism() const; - int saslSSF() const; - - // binding - void setResourceBinding(bool); - - // Language - void setLang(const QString&); - - // security options (old protocol only uses the first !) - void setAllowPlain(AllowPlainType); - void setRequireMutualAuth(bool); - void setSSFRange(int low, int high); - void setOldOnly(bool); - void setSASLMechanism(const QString &s); - void setLocalAddr(const QHostAddress &addr, quint16 port); - - // Compression - void setCompress(bool); - - // reimplemented - QDomDocument & doc() const; - QString baseNS() const; - bool old() const; - - void close(); - bool stanzaAvailable() const; - Stanza read(); - void write(const Stanza &s); - void clearSendQueue(); - - int errorCondition() const; - QString errorText() const; - QHash errorLangText() const; - QDomElement errorAppSpec() const; - - // extra - void writeDirect(const QString &s); - void setNoopTime(int mills); - - // Stream management - bool isResumed() const; - void setSMEnabled(bool enable); - - // barracuda extension - QStringList hosts() const; - - const StreamFeatures &streamFeatures() const; - QList unhandledFeatures() const; - - signals: - void connected(); - void securityLayerActivated(int); - void needAuthParams(bool user, bool pass, bool realm); - void authenticated(); - void warning(int); - void haveUnhandledFeatures(); - void incomingXml(const QString &s); - void outgoingXml(const QString &s); - void stanzasAcked(int); - - public slots: - void continueAfterWarning(); - - private slots: - void cr_connected(); - void cr_error(); - - void bs_connectionClosed(); - void bs_delayedCloseFinished(); - void bs_error(int); // server only - - void ss_readyRead(); - void ss_bytesWritten(qint64); - void ss_tlsHandshaken(); - void ss_tlsClosed(); - void ss_error(int); - - void sasl_clientFirstStep(bool, const QByteArray&); - void sasl_nextStep(const QByteArray &stepData); - void sasl_needParams(const QCA::SASL::Params&); - void sasl_authCheck(const QString &user, const QString &authzid); - void sasl_authenticated(); - void sasl_error(); - - void sm_timeout(); - - void doNoop(); - void doReadyRead(); - - private: - class Private; - Private *d; - - void reset(bool all=false); - void processNext(); - int convertedSASLCond() const; - bool handleNeed(); - void handleError(); - void srvProcessNext(); - void setTimer(int secs); +class Connector; +class StreamFeatures; +class TLSHandler; + +class ClientStream : public Stream { + Q_OBJECT +public: + enum Error { + ErrConnection = ErrCustom, // Connection error, ask Connector-subclass what's up + ErrNeg, // Negotiation error, see condition + ErrTLS, // TLS error, see condition + ErrAuth, // Auth error, see condition + ErrSecurityLayer, // broken SASL security layer + ErrSmResume, // SM resume error + ErrBind // Resource binding error }; + enum Warning { + WarnOldVersion, // server uses older XMPP/Jabber "0.9" protocol + WarnNoTLS, // there is no chance for TLS at this point + WarnSMReconnection // SM started a quiet stream reconnection + }; + enum NegCond { + HostGone, // host no longer hosted + HostUnknown, // unknown host + RemoteConnectionFailed, // unable to connect to a required remote resource + SeeOtherHost, // a 'redirect', see errorText() for other host + UnsupportedVersion // unsupported XMPP version + }; + enum TLSCond { + TLSStart, // server rejected STARTTLS + TLSFail // TLS failed, ask TLSHandler-subclass what's up + }; + enum SecurityLayer { LayerTLS, LayerSASL }; + enum AuthCond { + GenericAuthError, // all-purpose "can't login" error (includes: IncorrectEncoding, ) + + // standard xmpp auth errors (not all. some of the converted to GenericAuthError): + Aborted, // server confirms auth abort + AccountDisabled, // account temporrily disabled + CredentialsExpired, // credential expired + EncryptionRequired, // can't use mech without TLS + InvalidAuthzid, // bad input JID + InvalidMech, // bad mechanism + MalformedRequest, // malformded request + MechTooWeak, // can't use mech with this authzid + NotAuthorized, // bad user, bad password, bad creditials + TemporaryAuthFailure, // please try again later! + + // non-xmpp + NoMech, // No appropriate auth mech available + BadServ, // Server failed mutual auth + }; + enum BindCond { + BindNotAllowed, // not allowed to bind a resource + BindConflict // resource in-use + }; + enum AllowPlainType { NoAllowPlain, AllowPlain, AllowPlainOverTLS }; + + ClientStream(Connector *conn, TLSHandler *tlsHandler = nullptr, QObject *parent = nullptr); + ClientStream(const QString &host, const QString &defRealm, ByteStream *bs, QCA::TLS *tls = nullptr, + QObject *parent = nullptr); // server + ~ClientStream(); + + Jid jid() const; + void connectToServer(const Jid &jid, bool auth = true); + void accept(); // server + bool isActive() const; + bool isAuthenticated() const; + + // login params + void setUsername(const QString &s); + void setPassword(const QString &s); + void setRealm(const QString &s); + void setAuthzid(const QString &s); + void continueAfterParams(); + void abortAuth(); + void setSaslMechanismProvider(const QString &m, const QString &p); + QString saslMechanismProvider(const QString &m) const; + QCA::Provider::Context *currentSASLContext() const; + + void setSCRAMStoredSaltedHash(const QString &s); + const QString getSCRAMStoredSaltedHash(); + + // SASL information + QString saslMechanism() const; + int saslSSF() const; + + // binding + void setResourceBinding(bool); + + // Language + void setLang(const QString &); + + // security options (old protocol only uses the first !) + void setAllowPlain(AllowPlainType); + void setRequireMutualAuth(bool); + void setSSFRange(int low, int high); + void setOldOnly(bool); + void setSASLMechanism(const QString &s); + void setLocalAddr(const QHostAddress &addr, quint16 port); + + // Compression + void setCompress(bool); + + // reimplemented + QDomDocument &doc() const; + QString baseNS() const; + bool old() const; + + void close(); + bool stanzaAvailable() const; + Stanza read(); + void write(const Stanza &s); + void clearSendQueue(); + + int errorCondition() const; + QString errorText() const; + QHash errorLangText() const; + QDomElement errorAppSpec() const; + + // extra + void writeDirect(const QString &s); + void setNoopTime(int mills); + + // Stream management + bool isResumed() const; + void setSMEnabled(bool enable); + + // barracuda extension + QStringList hosts() const; + + const StreamFeatures &streamFeatures() const; + QList unhandledFeatures() const; + +signals: + void connected(); + void securityLayerActivated(int); + void needAuthParams(bool user, bool pass, bool realm); + void authenticated(); + void warning(int); + void haveUnhandledFeatures(); + void incomingXml(const QString &s); + void outgoingXml(const QString &s); + void stanzasAcked(int); + +public slots: + void continueAfterWarning(); + +private slots: + void cr_connected(); + void cr_error(); + + void bs_connectionClosed(); + void bs_delayedCloseFinished(); + void bs_error(int); // server only + + void ss_readyRead(); + void ss_bytesWritten(qint64); + void ss_tlsHandshaken(); + void ss_tlsClosed(); + void ss_error(int); + + void sasl_clientFirstStep(bool, const QByteArray &); + void sasl_nextStep(const QByteArray &stepData); + void sasl_needParams(const QCA::SASL::Params &); + void sasl_authCheck(const QString &user, const QString &authzid); + void sasl_authenticated(); + void sasl_error(); + + void sm_timeout(); + + void doNoop(); + void doReadyRead(); + +private: + class Private; + Private *d; + + void reset(bool all = false); + void processNext(); + int convertedSASLCond() const; + bool handleNeed(); + void handleError(); + void srvProcessNext(); + void setTimer(int secs); +}; } // namespace XMPP #endif // XMPP_CLIENTSTREAM_H diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp index 6dfea235..a3e89b78 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.cpp +++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp @@ -74,51 +74,46 @@ using namespace XMPP; */ Stanza::Error::Error(int _type, int _condition, const QString &_text, const QDomElement &_appSpec) { - type = _type; - condition = _condition; - text = _text; - appSpec = _appSpec; + type = _type; + condition = _condition; + text = _text; + appSpec = _appSpec; originalCode = 0; } void Stanza::Error::reset() { - type = 0; + type = 0; condition = UndefinedCondition; text.clear(); by.clear(); - appSpec = QDomElement(); + appSpec = QDomElement(); originalCode = 0; } -class Stanza::Error::Private -{ +class Stanza::Error::Private { public: - struct ErrorTypeEntry - { + struct ErrorTypeEntry { const char *str; - int type; + int type; }; static ErrorTypeEntry errorTypeTable[]; - struct ErrorCondEntry - { + struct ErrorCondEntry { const char *str; - int cond; + int cond; }; static ErrorCondEntry errorCondTable[]; - struct ErrorCodeEntry - { + struct ErrorCodeEntry { int cond; int type; int code; }; static ErrorCodeEntry errorCodeTable[]; - struct ErrorDescEntry - { - int cond; + struct ErrorDescEntry { + int cond; const char *name; const char *str; }; @@ -126,8 +121,8 @@ class Stanza::Error::Private static int stringToErrorType(const QString &s) { - for(int n = 0; errorTypeTable[n].str; ++n) { - if(s == errorTypeTable[n].str) + for (int n = 0; errorTypeTable[n].str; ++n) { + if (s == errorTypeTable[n].str) return errorTypeTable[n].type; } return -1; @@ -135,8 +130,8 @@ class Stanza::Error::Private static QString errorTypeToString(int x) { - for(int n = 0; errorTypeTable[n].str; ++n) { - if(x == errorTypeTable[n].type) + for (int n = 0; errorTypeTable[n].str; ++n) { + if (x == errorTypeTable[n].type) return errorTypeTable[n].str; } return QString(); @@ -144,8 +139,8 @@ class Stanza::Error::Private static int stringToErrorCond(const QString &s) { - for(int n = 0; errorCondTable[n].str; ++n) { - if(s == errorCondTable[n].str) + for (int n = 0; errorCondTable[n].str; ++n) { + if (s == errorCondTable[n].str) return errorCondTable[n].cond; } return -1; @@ -153,8 +148,8 @@ class Stanza::Error::Private static QString errorCondToString(int x) { - for(int n = 0; errorCondTable[n].str; ++n) { - if(x == errorCondTable[n].cond) + for (int n = 0; errorCondTable[n].str; ++n) { + if (x == errorCondTable[n].cond) return errorCondTable[n].str; } return QString(); @@ -163,8 +158,8 @@ class Stanza::Error::Private static int errorTypeCondToCode(int t, int c) { Q_UNUSED(t); - for(int n = 0; errorCodeTable[n].cond; ++n) { - if(c == errorCodeTable[n].cond) + for (int n = 0; errorCodeTable[n].cond; ++n) { + if (c == errorCodeTable[n].cond) return errorCodeTable[n].code; } return 0; @@ -172,109 +167,135 @@ class Stanza::Error::Private static QPair errorCodeToTypeCond(int x) { - for(int n = 0; errorCodeTable[n].cond; ++n) { - if(x == errorCodeTable[n].code) + for (int n = 0; errorCodeTable[n].cond; ++n) { + if (x == errorCodeTable[n].code) return QPair(errorCodeTable[n].type, errorCodeTable[n].cond); } return QPair(-1, -1); } - static QPair errorCondToDesc(int x) + static QPair errorCondToDesc(int x) { - for(int n = 0; errorDescriptions[n].str; ++n) { - if(x == errorDescriptions[n].cond) - return QPair(QCoreApplication::translate("Stanza::Error::Private", errorDescriptions[n].name), - QCoreApplication::translate("Stanza::Error::Private", errorDescriptions[n].str)); + for (int n = 0; errorDescriptions[n].str; ++n) { + if (x == errorDescriptions[n].cond) + return QPair( + QCoreApplication::translate("Stanza::Error::Private", errorDescriptions[n].name), + QCoreApplication::translate("Stanza::Error::Private", errorDescriptions[n].str)); } - return QPair(); + return QPair(); } }; -Stanza::Error::Private::ErrorTypeEntry Stanza::Error::Private::errorTypeTable[] = -{ - { "cancel", Cancel }, - { "continue", Continue }, - { "modify", Modify }, - { "auth", Auth }, - { "wait", Wait }, - { nullptr, 0 }, +Stanza::Error::Private::ErrorTypeEntry Stanza::Error::Private::errorTypeTable[] = { + { "cancel", Cancel }, { "continue", Continue }, { "modify", Modify }, + { "auth", Auth }, { "wait", Wait }, { nullptr, 0 }, }; -Stanza::Error::Private::ErrorCondEntry Stanza::Error::Private::errorCondTable[] = -{ - { "bad-request", BadRequest }, - { "conflict", Conflict }, +Stanza::Error::Private::ErrorCondEntry Stanza::Error::Private::errorCondTable[] = { + { "bad-request", BadRequest }, + { "conflict", Conflict }, { "feature-not-implemented", FeatureNotImplemented }, - { "forbidden", Forbidden }, - { "gone", Gone }, - { "internal-server-error", InternalServerError }, - { "item-not-found", ItemNotFound }, - { "jid-malformed", JidMalformed }, - { "not-acceptable", NotAcceptable }, - { "not-allowed", NotAllowed }, - { "not-authorized", NotAuthorized }, - { "recipient-unavailable", RecipientUnavailable }, - { "redirect", Redirect }, - { "registration-required", RegistrationRequired }, + { "forbidden", Forbidden }, + { "gone", Gone }, + { "internal-server-error", InternalServerError }, + { "item-not-found", ItemNotFound }, + { "jid-malformed", JidMalformed }, + { "not-acceptable", NotAcceptable }, + { "not-allowed", NotAllowed }, + { "not-authorized", NotAuthorized }, + { "recipient-unavailable", RecipientUnavailable }, + { "redirect", Redirect }, + { "registration-required", RegistrationRequired }, { "remote-server-not-found", RemoteServerNotFound }, - { "remote-server-timeout", RemoteServerTimeout }, - { "resource-constraint", ResourceConstraint }, - { "service-unavailable", ServiceUnavailable }, - { "subscription-required", SubscriptionRequired }, - { "undefined-condition", UndefinedCondition }, - { "unexpected-request", UnexpectedRequest }, + { "remote-server-timeout", RemoteServerTimeout }, + { "resource-constraint", ResourceConstraint }, + { "service-unavailable", ServiceUnavailable }, + { "subscription-required", SubscriptionRequired }, + { "undefined-condition", UndefinedCondition }, + { "unexpected-request", UnexpectedRequest }, { nullptr, 0 }, }; -Stanza::Error::Private::ErrorCodeEntry Stanza::Error::Private::errorCodeTable[] = -{ - { BadRequest, Modify, 400 }, - { Conflict, Cancel, 409 }, +Stanza::Error::Private::ErrorCodeEntry Stanza::Error::Private::errorCodeTable[] = { + { BadRequest, Modify, 400 }, + { Conflict, Cancel, 409 }, { FeatureNotImplemented, Cancel, 501 }, - { Forbidden, Auth, 403 }, - { Gone, Modify, 302 }, // permanent - { InternalServerError, Wait, 500 }, - { ItemNotFound, Cancel, 404 }, - { JidMalformed, Modify, 400 }, - { NotAcceptable, Modify, 406 }, - { NotAllowed, Cancel, 405 }, - { NotAuthorized, Auth, 401 }, - { RecipientUnavailable, Wait, 404 }, - { Redirect, Modify, 302 }, // temporary - { RegistrationRequired, Auth, 407 }, - { RemoteServerNotFound, Cancel, 404 }, - { RemoteServerTimeout, Wait, 504 }, - { ResourceConstraint, Wait, 500 }, - { ServiceUnavailable, Cancel, 503 }, - { SubscriptionRequired, Auth, 407 }, - { UndefinedCondition, Wait, 500 }, // Note: any type matches really - { UnexpectedRequest, Wait, 400 }, + { Forbidden, Auth, 403 }, + { Gone, Modify, 302 }, // permanent + { InternalServerError, Wait, 500 }, + { ItemNotFound, Cancel, 404 }, + { JidMalformed, Modify, 400 }, + { NotAcceptable, Modify, 406 }, + { NotAllowed, Cancel, 405 }, + { NotAuthorized, Auth, 401 }, + { RecipientUnavailable, Wait, 404 }, + { Redirect, Modify, 302 }, // temporary + { RegistrationRequired, Auth, 407 }, + { RemoteServerNotFound, Cancel, 404 }, + { RemoteServerTimeout, Wait, 504 }, + { ResourceConstraint, Wait, 500 }, + { ServiceUnavailable, Cancel, 503 }, + { SubscriptionRequired, Auth, 407 }, + { UndefinedCondition, Wait, 500 }, // Note: any type matches really + { UnexpectedRequest, Wait, 400 }, { 0, 0, 0 }, }; -Stanza::Error::Private::ErrorDescEntry Stanza::Error::Private::errorDescriptions[] = -{ - { BadRequest, QT_TR_NOOP("Bad request"), QT_TR_NOOP("The sender has sent XML that is malformed or that cannot be processed.") }, - { Conflict, QT_TR_NOOP("Conflict"), QT_TR_NOOP("Access cannot be granted because an existing resource or session exists with the same name or address.") }, - { FeatureNotImplemented, QT_TR_NOOP("Feature not implemented"), QT_TR_NOOP("The feature requested is not implemented by the recipient or server and therefore cannot be processed.") }, - { Forbidden, QT_TR_NOOP("Forbidden"), QT_TR_NOOP("The requesting entity does not possess the required permissions to perform the action.") }, - { Gone, QT_TR_NOOP("Gone"), QT_TR_NOOP("The recipient or server can no longer be contacted at this address.") }, - { InternalServerError, QT_TR_NOOP("Internal server error"), QT_TR_NOOP("The server could not process the stanza because of a misconfiguration or an otherwise-undefined internal server error.") }, - { ItemNotFound, QT_TR_NOOP("Item not found"), QT_TR_NOOP("The addressed JID or item requested cannot be found.") }, - { JidMalformed, QT_TR_NOOP("JID malformed"), QT_TR_NOOP("The sending entity has provided or communicated an XMPP address (e.g., a value of the 'to' attribute) or aspect thereof (e.g., a resource identifier) that does not adhere to the syntax defined in Addressing Scheme.") }, - { NotAcceptable, QT_TR_NOOP("Not acceptable"), QT_TR_NOOP("The recipient or server understands the request but is refusing to process it because it does not meet criteria defined by the recipient or server (e.g., a local policy regarding acceptable words in messages).") }, - { NotAllowed, QT_TR_NOOP("Not allowed"), QT_TR_NOOP("The recipient or server does not allow any entity to perform the action.") }, - { NotAuthorized, QT_TR_NOOP("Not authorized"), QT_TR_NOOP("The sender must provide proper credentials before being allowed to perform the action, or has provided improper credentials.") }, - { RecipientUnavailable, QT_TR_NOOP("Recipient unavailable"), QT_TR_NOOP("The intended recipient is temporarily unavailable.") }, - { Redirect, QT_TR_NOOP("Redirect"), QT_TR_NOOP("The recipient or server is redirecting requests for this information to another entity, usually temporarily.") }, - { RegistrationRequired, QT_TR_NOOP("Registration required"), QT_TR_NOOP("The requesting entity is not authorized to access the requested service because registration is required.") }, - { RemoteServerNotFound, QT_TR_NOOP("Remote server not found"), QT_TR_NOOP("A remote server or service specified as part or all of the JID of the intended recipient does not exist.") }, - { RemoteServerTimeout, QT_TR_NOOP("Remote server timeout"), QT_TR_NOOP("A remote server or service specified as part or all of the JID of the intended recipient (or required to fulfill a request) could not be contacted within a reasonable amount of time.") }, - { ResourceConstraint, QT_TR_NOOP("Resource constraint"), QT_TR_NOOP("The server or recipient lacks the system resources necessary to service the request.") }, - { ServiceUnavailable, QT_TR_NOOP("Service unavailable"), QT_TR_NOOP("The server or recipient does not currently provide the requested service.") }, - { SubscriptionRequired, QT_TR_NOOP("Subscription required"), QT_TR_NOOP("The requesting entity is not authorized to access the requested service because a subscription is required.") }, - { UndefinedCondition, QT_TR_NOOP("Undefined condition"), QT_TR_NOOP("The error condition is not one of those defined by the other conditions in this list.") }, - { UnexpectedRequest, QT_TR_NOOP("Unexpected request"), QT_TR_NOOP("The recipient or server understood the request but was not expecting it at this time (e.g., the request was out of order).") }, +Stanza::Error::Private::ErrorDescEntry Stanza::Error::Private::errorDescriptions[] = { + { BadRequest, QT_TR_NOOP("Bad request"), + QT_TR_NOOP("The sender has sent XML that is malformed or that cannot be processed.") }, + { Conflict, QT_TR_NOOP("Conflict"), + QT_TR_NOOP( + "Access cannot be granted because an existing resource or session exists with the same name or address.") }, + { FeatureNotImplemented, QT_TR_NOOP("Feature not implemented"), + QT_TR_NOOP( + "The feature requested is not implemented by the recipient or server and therefore cannot be processed.") }, + { Forbidden, QT_TR_NOOP("Forbidden"), + QT_TR_NOOP("The requesting entity does not possess the required permissions to perform the action.") }, + { Gone, QT_TR_NOOP("Gone"), QT_TR_NOOP("The recipient or server can no longer be contacted at this address.") }, + { InternalServerError, QT_TR_NOOP("Internal server error"), + QT_TR_NOOP("The server could not process the stanza because of a misconfiguration or an otherwise-undefined " + "internal server error.") }, + { ItemNotFound, QT_TR_NOOP("Item not found"), QT_TR_NOOP("The addressed JID or item requested cannot be found.") }, + { JidMalformed, QT_TR_NOOP("JID malformed"), + QT_TR_NOOP("The sending entity has provided or communicated an XMPP address (e.g., a value of the 'to' " + "attribute) or aspect thereof (e.g., a resource identifier) that does not adhere to the syntax " + "defined in Addressing Scheme.") }, + { NotAcceptable, QT_TR_NOOP("Not acceptable"), + QT_TR_NOOP("The recipient or server understands the request but is refusing to process it because it does not " + "meet criteria defined by the recipient or server (e.g., a local policy regarding acceptable words in " + "messages).") }, + { NotAllowed, QT_TR_NOOP("Not allowed"), + QT_TR_NOOP("The recipient or server does not allow any entity to perform the action.") }, + { NotAuthorized, QT_TR_NOOP("Not authorized"), + QT_TR_NOOP("The sender must provide proper credentials before being allowed to perform the action, or has " + "provided improper credentials.") }, + { RecipientUnavailable, QT_TR_NOOP("Recipient unavailable"), + QT_TR_NOOP("The intended recipient is temporarily unavailable.") }, + { Redirect, QT_TR_NOOP("Redirect"), + QT_TR_NOOP("The recipient or server is redirecting requests for this information to another entity, usually " + "temporarily.") }, + { RegistrationRequired, QT_TR_NOOP("Registration required"), + QT_TR_NOOP("The requesting entity is not authorized to access the requested service because registration is " + "required.") }, + { RemoteServerNotFound, QT_TR_NOOP("Remote server not found"), + QT_TR_NOOP( + "A remote server or service specified as part or all of the JID of the intended recipient does not exist.") }, + { RemoteServerTimeout, QT_TR_NOOP("Remote server timeout"), + QT_TR_NOOP("A remote server or service specified as part or all of the JID of the intended recipient (or " + "required to fulfill a request) could not be contacted within a reasonable amount of time.") }, + { ResourceConstraint, QT_TR_NOOP("Resource constraint"), + QT_TR_NOOP("The server or recipient lacks the system resources necessary to service the request.") }, + { ServiceUnavailable, QT_TR_NOOP("Service unavailable"), + QT_TR_NOOP("The server or recipient does not currently provide the requested service.") }, + { SubscriptionRequired, QT_TR_NOOP("Subscription required"), + QT_TR_NOOP("The requesting entity is not authorized to access the requested service because a subscription is " + "required.") }, + { UndefinedCondition, QT_TR_NOOP("Undefined condition"), + QT_TR_NOOP("The error condition is not one of those defined by the other conditions in this list.") }, + { UnexpectedRequest, QT_TR_NOOP("Unexpected request"), + QT_TR_NOOP("The recipient or server understood the request but was not expecting it at this time (e.g., the " + "request was out of order).") }, }; /** @@ -285,10 +306,7 @@ Stanza::Error::Private::ErrorDescEntry Stanza::Error::Private::errorDescriptions 0 means unknown code. */ -int Stanza::Error::code() const -{ - return originalCode ? originalCode : Private::errorTypeCondToCode(type, condition); -} +int Stanza::Error::code() const { return originalCode ? originalCode : Private::errorTypeCondToCode(type, condition); } /** \brief Creates a StanzaError from \a code. @@ -299,11 +317,11 @@ int Stanza::Error::code() const bool Stanza::Error::fromCode(int code) { QPair guess = Private::errorCodeToTypeCond(code); - if(guess.first == -1 || guess.second == -1) + if (guess.first == -1 || guess.second == -1) return false; - type = guess.first; - condition = guess.second; + type = guess.first; + condition = guess.second; originalCode = code; return true; @@ -319,17 +337,17 @@ bool Stanza::Error::fromCode(int code) */ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS) { - if(e.tagName() != "error" && e.namespaceURI() != baseNS) + if (e.tagName() != "error" && e.namespaceURI() != baseNS) return false; // type - type = Private::stringToErrorType(e.attribute("type")); - by = e.attribute(QLatin1String("by")); + type = Private::stringToErrorType(e.attribute("type")); + by = e.attribute(QLatin1String("by")); condition = -1; QString textTag(QString::fromLatin1("text")); for (auto t = e.firstChildElement(); !t.isNull(); t = t.nextSiblingElement()) { - if(t.namespaceURI() == NS_STANZAS) { + if (t.namespaceURI() == NS_STANZAS) { if (t.tagName() == textTag) { text = t.text().trimmed(); } else { @@ -344,10 +362,11 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS) } // code - originalCode = e.attribute("code").toInt(); // deprecated. rfc6120 has just a little note about it. also see XEP-0086 + originalCode + = e.attribute("code").toInt(); // deprecated. rfc6120 has just a little note about it. also see XEP-0086 // try to guess type/condition - if(type == -1 || condition == -1) { + if (type == -1 || condition == -1) { QPair guess(-1, -1); if (originalCode) guess = Private::errorCodeToTypeCond(originalCode); @@ -376,10 +395,10 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const // XMPP error QString stype = Private::errorTypeToString(type); - if(stype.isEmpty()) + if (stype.isEmpty()) return errElem; QString scond = Private::errorCondToString(condition); - if(scond.isEmpty()) + if (scond.isEmpty()) return errElem; errElem.setAttribute("type", stype); @@ -387,17 +406,17 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const errElem.setAttribute("by", by); } errElem.appendChild(t = doc.createElementNS(NS_STANZAS, scond)); - //t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed + // t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed // old code int scode = code(); - if(scode) + if (scode) errElem.setAttribute("code", scode); // text - if(!text.isEmpty()) { + if (!text.isEmpty()) { t = doc.createElementNS(NS_STANZAS, "text"); - //t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed + // t.setAttribute("xmlns", NS_STANZAS); // FIX-ME: this shouldn't be needed t.appendChild(doc.createTextNode(text)); errElem.appendChild(t); } @@ -413,10 +432,7 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const Returns the error name (e.g. "Not Allowed") and generic description. */ -QPair Stanza::Error::description() const -{ - return Private::errorCondToDesc(condition); -} +QPair Stanza::Error::description() const { return Private::errorCondToDesc(condition); } /** * \brief Returns string human-reabable representation of the error @@ -433,16 +449,15 @@ QString Stanza::Error::toString() const //---------------------------------------------------------------------------- // Stanza //---------------------------------------------------------------------------- -class Stanza::Private -{ +class Stanza::Private { public: static int stringToKind(const QString &s) { - if(s == QLatin1String("message")) + if (s == QLatin1String("message")) return Message; - else if(s == QLatin1String("presence")) + else if (s == QLatin1String("presence")) return Presence; - else if(s == QLatin1String("iq")) + else if (s == QLatin1String("iq")) return IQ; else return -1; @@ -450,23 +465,20 @@ class Stanza::Private static QString kindToString(Kind k) { - if(k == Message) + if (k == Message) return QLatin1String("message"); - else if(k == Presence) + else if (k == Presence) return QLatin1String("presence"); else return QLatin1String("iq"); } - Stream *s; - QDomElement e; + Stream * s; + QDomElement e; QSharedPointer sharedDoc; }; -Stanza::Stanza() -{ - d = nullptr; -} +Stanza::Stanza() { d = nullptr; } Stanza::Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QString &id) { @@ -474,19 +486,19 @@ Stanza::Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QStr d = new Private; Kind kind; - if(k == Message || k == Presence || k == IQ) + if (k == Message || k == Presence || k == IQ) kind = k; else kind = Message; d->s = s; - if(d->s) + if (d->s) d->e = d->s->doc().createElementNS(s->baseNS(), Private::kindToString(kind)); - if(to.isValid()) + if (to.isValid()) setTo(to); - if(!type.isEmpty()) + if (!type.isEmpty()) setType(type); - if(!id.isEmpty()) + if (!id.isEmpty()) setId(id); } @@ -494,63 +506,45 @@ Stanza::Stanza(Stream *s, const QDomElement &e) { Q_ASSERT(s); d = nullptr; - if(e.namespaceURI() != s->baseNS()) + if (e.namespaceURI() != s->baseNS()) return; int x = Private::stringToKind(e.tagName()); - if(x == -1) + if (x == -1) return; - d = new Private; + d = new Private; d->s = s; d->e = e; } Stanza::Stanza(const Stanza &from) { - d = nullptr; + d = nullptr; *this = from; } -Stanza & Stanza::operator=(const Stanza &from) +Stanza &Stanza::operator=(const Stanza &from) { - if(&from == this) + if (&from == this) return *this; delete d; d = nullptr; - if(from.d) + if (from.d) d = new Private(*from.d); return *this; } -Stanza::~Stanza() -{ - delete d; -} +Stanza::~Stanza() { delete d; } -bool Stanza::isNull() const -{ - return (d ? false: true); -} +bool Stanza::isNull() const { return (d ? false : true); } -QDomElement Stanza::element() const -{ - return d->e; -} +QDomElement Stanza::element() const { return d->e; } -QString Stanza::toString() const -{ - return Stream::xmlToString(d->e); -} +QString Stanza::toString() const { return Stream::xmlToString(d->e); } -QDomDocument & Stanza::doc() const -{ - return d->s->doc(); -} +QDomDocument &Stanza::doc() const { return d->s->doc(); } -QString Stanza::baseNS() const -{ - return d->s->baseNS(); -} +QString Stanza::baseNS() const { return d->s->baseNS(); } QDomElement Stanza::createElement(const QString &ns, const QString &tagName) { @@ -564,81 +558,39 @@ QDomElement Stanza::createTextElement(const QString &ns, const QString &tagName, return e; } -void Stanza::appendChild(const QDomElement &e) -{ - d->e.appendChild(e); -} +void Stanza::appendChild(const QDomElement &e) { d->e.appendChild(e); } -Stanza::Kind Stanza::kind() const -{ - return (Kind)Private::stringToKind(d->e.tagName()); -} +Stanza::Kind Stanza::kind() const { return (Kind)Private::stringToKind(d->e.tagName()); } -Stanza::Kind Stanza::kind(const QString &tagName) -{ - return (Kind)Private::stringToKind(tagName); -} +Stanza::Kind Stanza::kind(const QString &tagName) { return (Kind)Private::stringToKind(tagName); } -void Stanza::setKind(Kind k) -{ - d->e.setTagName(Private::kindToString(k)); -} +void Stanza::setKind(Kind k) { d->e.setTagName(Private::kindToString(k)); } -Jid Stanza::to() const -{ - return Jid(d->e.attribute("to")); -} +Jid Stanza::to() const { return Jid(d->e.attribute("to")); } -Jid Stanza::from() const -{ - return Jid(d->e.attribute("from")); -} +Jid Stanza::from() const { return Jid(d->e.attribute("from")); } -QString Stanza::id() const -{ - return d->e.attribute("id"); -} +QString Stanza::id() const { return d->e.attribute("id"); } -QString Stanza::type() const -{ - return d->e.attribute("type"); -} +QString Stanza::type() const { return d->e.attribute("type"); } -QString Stanza::lang() const -{ - return d->e.attributeNS(NS_XML, "lang", QString()); -} +QString Stanza::lang() const { return d->e.attributeNS(NS_XML, "lang", QString()); } -void Stanza::setTo(const Jid &j) -{ - d->e.setAttribute("to", j.full()); -} +void Stanza::setTo(const Jid &j) { d->e.setAttribute("to", j.full()); } -void Stanza::setFrom(const Jid &j) -{ - d->e.setAttribute("from", j.full()); -} +void Stanza::setFrom(const Jid &j) { d->e.setAttribute("from", j.full()); } -void Stanza::setId(const QString &id) -{ - d->e.setAttribute("id", id); -} +void Stanza::setId(const QString &id) { d->e.setAttribute("id", id); } -void Stanza::setType(const QString &type) -{ - d->e.setAttribute("type", type); -} +void Stanza::setType(const QString &type) { d->e.setAttribute("type", type); } -void Stanza::setLang(const QString &lang) -{ - d->e.setAttribute("xml:lang", lang); -} +void Stanza::setLang(const QString &lang) { d->e.setAttribute("xml:lang", lang); } Stanza::Error Stanza::error() const { - Error err; + Error err; QDomElement e = d->e.elementsByTagNameNS(d->s->baseNS(), "error").item(0).toElement(); - if(!e.isNull()) + if (!e.isNull()) err.fromXml(e, d->s->baseNS()); return err; @@ -646,14 +598,13 @@ Stanza::Error Stanza::error() const void Stanza::setError(const Error &err) { - QDomDocument doc = d->e.ownerDocument(); - QDomElement errElem = err.toXml(doc, d->s->baseNS()); + QDomDocument doc = d->e.ownerDocument(); + QDomElement errElem = err.toXml(doc, d->s->baseNS()); QDomElement oldElem = d->e.elementsByTagNameNS(d->s->baseNS(), "error").item(0).toElement(); - if(oldElem.isNull()) { + if (oldElem.isNull()) { d->e.appendChild(errElem); - } - else { + } else { d->e.replaceChild(errElem, oldElem); } } @@ -661,7 +612,7 @@ void Stanza::setError(const Error &err) void Stanza::clearError() { QDomElement errElem = d->e.elementsByTagNameNS(d->s->baseNS(), "error").item(0).toElement(); - if(!errElem.isNull()) + if (!errElem.isNull()) d->e.removeChild(errElem); } @@ -670,7 +621,7 @@ QSharedPointer Stanza::unboundDocument(QSharedPointer(new QDomDocument); } - d->e = sd->importNode(d->e, true).toElement(); + d->e = sd->importNode(d->e, true).toElement(); d->sharedDoc = sd; return d->sharedDoc; } diff --git a/src/xmpp/xmpp-core/xmpp_stanza.h b/src/xmpp/xmpp-core/xmpp_stanza.h index c2fd7ae4..c562f58c 100644 --- a/src/xmpp/xmpp-core/xmpp_stanza.h +++ b/src/xmpp/xmpp-core/xmpp_stanza.h @@ -27,117 +27,115 @@ class QDomDocument; namespace XMPP { - class Jid; - class Stream; +class Jid; +class Stream; - class Stanza - { - public: - enum Kind { Message, Presence, IQ }; - - Stanza(); - Stanza(const Stanza &from); - Stanza & operator=(const Stanza &from); - virtual ~Stanza(); - - class Error - { - public: - enum ErrorType { Cancel = 1, Continue, Modify, Auth, Wait }; - enum ErrorCond - { - BadRequest = 1, - Conflict, - FeatureNotImplemented, - Forbidden, - Gone, - InternalServerError, - ItemNotFound, - JidMalformed, - NotAcceptable, - NotAllowed, - NotAuthorized, - PaymentRequired, - RecipientUnavailable, - Redirect, - RegistrationRequired, - RemoteServerNotFound, - RemoteServerTimeout, - ResourceConstraint, - ServiceUnavailable, - SubscriptionRequired, - UndefinedCondition, - UnexpectedRequest - }; - - Error(int type=Cancel, int condition=UndefinedCondition, const QString &text=QString(), const QDomElement &appSpec=QDomElement()); - - int type; - int condition; - QString text; - QString by; - QDomElement appSpec; - - void reset(); - - int code() const; - bool fromCode(int code); - - QPair description() const; - QString toString() const; - - QDomElement toXml(QDomDocument &doc, const QString &baseNS) const; - bool fromXml(const QDomElement &e, const QString &baseNS); - private: - class Private; - int originalCode; +class Stanza { +public: + enum Kind { Message, Presence, IQ }; + + Stanza(); + Stanza(const Stanza &from); + Stanza &operator=(const Stanza &from); + virtual ~Stanza(); + class Error { + public: + enum ErrorType { Cancel = 1, Continue, Modify, Auth, Wait }; + enum ErrorCond { + BadRequest = 1, + Conflict, + FeatureNotImplemented, + Forbidden, + Gone, + InternalServerError, + ItemNotFound, + JidMalformed, + NotAcceptable, + NotAllowed, + NotAuthorized, + PaymentRequired, + RecipientUnavailable, + Redirect, + RegistrationRequired, + RemoteServerNotFound, + RemoteServerTimeout, + ResourceConstraint, + ServiceUnavailable, + SubscriptionRequired, + UndefinedCondition, + UnexpectedRequest }; - bool isNull() const; + Error(int type = Cancel, int condition = UndefinedCondition, const QString &text = QString(), + const QDomElement &appSpec = QDomElement()); - QDomElement element() const; - QString toString() const; + int type; + int condition; + QString text; + QString by; + QDomElement appSpec; - QDomDocument & doc() const; - QString baseNS() const; - QDomElement createElement(const QString &ns, const QString &tagName); - QDomElement createTextElement(const QString &ns, const QString &tagName, const QString &text); - void appendChild(const QDomElement &e); + void reset(); - Kind kind() const; - static Kind kind(const QString &tagName); - void setKind(Kind k); + int code() const; + bool fromCode(int code); - Jid to() const; - Jid from() const; - QString id() const; - QString type() const; - QString lang() const; + QPair description() const; + QString toString() const; - void setTo(const Jid &j); - void setFrom(const Jid &j); - void setId(const QString &id); - void setType(const QString &type); - void setLang(const QString &lang); + QDomElement toXml(QDomDocument &doc, const QString &baseNS) const; + bool fromXml(const QDomElement &e, const QString &baseNS); - Error error() const; - void setError(const Error &err); - void clearError(); + private: + class Private; + int originalCode; + }; - void markHandled(); - void setSMId(unsigned long id); + bool isNull() const; - QSharedPointer unboundDocument(QSharedPointer); + QDomElement element() const; + QString toString() const; - private: - friend class Stream; - Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QString &id); - Stanza(Stream *s, const QDomElement &e); + QDomDocument &doc() const; + QString baseNS() const; + QDomElement createElement(const QString &ns, const QString &tagName); + QDomElement createTextElement(const QString &ns, const QString &tagName, const QString &text); + void appendChild(const QDomElement &e); - class Private; - Private *d; - }; + Kind kind() const; + static Kind kind(const QString &tagName); + void setKind(Kind k); + + Jid to() const; + Jid from() const; + QString id() const; + QString type() const; + QString lang() const; + + void setTo(const Jid &j); + void setFrom(const Jid &j); + void setId(const QString &id); + void setType(const QString &type); + void setLang(const QString &lang); + + Error error() const; + void setError(const Error &err); + void clearError(); + + void markHandled(); + void setSMId(unsigned long id); + + QSharedPointer unboundDocument(QSharedPointer); + +private: + friend class Stream; + Stanza(Stream *s, Kind k, const Jid &to, const QString &type, const QString &id); + Stanza(Stream *s, const QDomElement &e); + + class Private; + Private *d; +}; } // namespace XMPP #endif // XMPP_STANZA_H diff --git a/src/xmpp/xmpp-core/xmpp_stream.h b/src/xmpp/xmpp-core/xmpp_stream.h index cb0d4cdb..bf1a3fee 100644 --- a/src/xmpp/xmpp-core/xmpp_stream.h +++ b/src/xmpp/xmpp-core/xmpp_stream.h @@ -29,55 +29,54 @@ class QDomDocument; namespace XMPP { - class Stream : public QObject - { - Q_OBJECT - public: - enum Error { ErrParse, ErrProtocol, ErrStream, ErrCustom = 10 }; - enum StreamCond { - GenericStreamError, - Conflict, - ConnectionTimeout, - InternalServerError, - InvalidFrom, - InvalidXml, - PolicyViolation, - ResourceConstraint, - SystemShutdown, - StreamReset - }; +class Stream : public QObject { + Q_OBJECT +public: + enum Error { ErrParse, ErrProtocol, ErrStream, ErrCustom = 10 }; + enum StreamCond { + GenericStreamError, + Conflict, + ConnectionTimeout, + InternalServerError, + InvalidFrom, + InvalidXml, + PolicyViolation, + ResourceConstraint, + SystemShutdown, + StreamReset + }; - Stream(QObject *parent=nullptr); - virtual ~Stream(); + Stream(QObject *parent = nullptr); + virtual ~Stream(); - virtual QDomDocument & doc() const=0; - virtual QString baseNS() const=0; - virtual bool old() const=0; + virtual QDomDocument &doc() const = 0; + virtual QString baseNS() const = 0; + virtual bool old() const = 0; - virtual void close()=0; - virtual bool stanzaAvailable() const=0; - virtual Stanza read()=0; - virtual void write(const Stanza &s)=0; + virtual void close() = 0; + virtual bool stanzaAvailable() const = 0; + virtual Stanza read() = 0; + virtual void write(const Stanza &s) = 0; - virtual int errorCondition() const=0; - virtual QString errorText() const=0; - virtual QHash errorLangText() const=0; // localized error descriptions - virtual QDomElement errorAppSpec() const=0; + virtual int errorCondition() const = 0; + virtual QString errorText() const = 0; + virtual QHash errorLangText() const = 0; // localized error descriptions + virtual QDomElement errorAppSpec() const = 0; - Stanza createStanza(Stanza::Kind k, const Jid &to="", const QString &type="", const QString &id=""); - Stanza createStanza(const QDomElement &e); + Stanza createStanza(Stanza::Kind k, const Jid &to = "", const QString &type = "", const QString &id = ""); + Stanza createStanza(const QDomElement &e); - static QString xmlToString(const QDomElement &e, bool clip=false); + static QString xmlToString(const QDomElement &e, bool clip = false); - static void cleanup(); + static void cleanup(); - signals: - void connectionClosed(); - void delayedCloseFinished(); - void readyRead(); - void stanzaWritten(); - void error(int); - }; +signals: + void connectionClosed(); + void delayedCloseFinished(); + void readyRead(); + void stanzaWritten(); + void error(int); +}; } // namespace XMPP #endif // XMPP_STREAM_H diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp index 681645f8..2531e2c3 100644 --- a/src/xmpp/xmpp-im/client.cpp +++ b/src/xmpp/xmpp-im/client.cpp @@ -97,61 +97,58 @@ namespace XMPP { //---------------------------------------------------------------------------- // Client //---------------------------------------------------------------------------- -class Client::GroupChat -{ +class Client::GroupChat { public: enum { Connecting, Connected, Closing }; - GroupChat() = default; + GroupChat() = default; - Jid j; - int status = 0; + Jid j; + int status = 0; QString password; }; -class Client::ClientPrivate -{ +class Client::ClientPrivate { public: ClientPrivate() {} - QPointer stream; - QDomDocument doc; - int id_seed = 0xaaaa; - Task *root = nullptr; - QNetworkAccessManager *qnam = nullptr; - QString host, user, pass, resource; - QString osName, osVersion, tzname, clientName, clientVersion; - CapsSpec caps, serverCaps; - DiscoItem::Identity identity; - Features features; - QMap extension_features; - int tzoffset = 0; - bool useTzoffset = false; // manual tzoffset is old way of doing utc<->local translations - bool active = false; - - LiveRoster roster; - ResourceList resourceList; - CapsManager *capsman = nullptr; - TcpPortReserver *tcpPortReserver = nullptr; - S5BManager *s5bman = nullptr; - Jingle::S5B::Manager *jingleS5BManager = nullptr; - Jingle::IBB::Manager *jingleIBBManager = nullptr; - IBBManager *ibbman = nullptr; - BoBManager *bobman = nullptr; - FileTransferManager *ftman = nullptr; - ServerInfoManager *serverInfoManager = nullptr; + QPointer stream; + QDomDocument doc; + int id_seed = 0xaaaa; + Task * root = nullptr; + QNetworkAccessManager * qnam = nullptr; + QString host, user, pass, resource; + QString osName, osVersion, tzname, clientName, clientVersion; + CapsSpec caps, serverCaps; + DiscoItem::Identity identity; + Features features; + QMap extension_features; + int tzoffset = 0; + bool useTzoffset = false; // manual tzoffset is old way of doing utc<->local translations + bool active = false; + + LiveRoster roster; + ResourceList resourceList; + CapsManager * capsman = nullptr; + TcpPortReserver * tcpPortReserver = nullptr; + S5BManager * s5bman = nullptr; + Jingle::S5B::Manager * jingleS5BManager = nullptr; + Jingle::IBB::Manager * jingleIBBManager = nullptr; + IBBManager * ibbman = nullptr; + BoBManager * bobman = nullptr; + FileTransferManager * ftman = nullptr; + ServerInfoManager * serverInfoManager = nullptr; HttpFileUploadManager *httpFileUploadManager = nullptr; - Jingle::Manager *jingleManager = nullptr; - QList groupChatList; - EncryptionHandler *encryptionHandler = nullptr; + Jingle::Manager * jingleManager = nullptr; + QList groupChatList; + EncryptionHandler * encryptionHandler = nullptr; }; -Client::Client(QObject *par) -:QObject(par) +Client::Client(QObject *par) : QObject(par) { - d = new ClientPrivate; - d->active = false; - d->osName = "N/A"; - d->clientName = "N/A"; + d = new ClientPrivate; + d->active = false; + d->osName = "N/A"; + d->clientName = "N/A"; d->clientVersion = "0.0"; d->root = new Task(this, true); @@ -168,11 +165,11 @@ Client::Client(QObject *par) d->capsman = new CapsManager(this); - d->serverInfoManager = new ServerInfoManager(this); + d->serverInfoManager = new ServerInfoManager(this); d->httpFileUploadManager = new HttpFileUploadManager(this); d->jingleManager = new Jingle::Manager(this); - auto ft = new Jingle::FileTransfer::Manager(this); + auto ft = new Jingle::FileTransfer::Manager(this); d->jingleManager->registerApp(Jingle::FileTransfer::NS, ft); d->jingleS5BManager = new Jingle::S5B::Manager(d->jingleManager); d->jingleIBBManager = new Jingle::IBB::Manager(d->jingleManager); @@ -182,8 +179,8 @@ Client::Client(QObject *par) Client::~Client() { - //fprintf(stderr, "\tClient::~Client\n"); - //fflush(stderr); + // fprintf(stderr, "\tClient::~Client\n"); + // fflush(stderr); close(true); @@ -193,18 +190,18 @@ Client::~Client() delete d->jingleManager; delete d->root; delete d; - //fprintf(stderr, "\tClient::~Client\n"); + // fprintf(stderr, "\tClient::~Client\n"); } void Client::connectToServer(ClientStream *s, const Jid &j, bool auth) { d->stream = s; - //connect(d->stream, SIGNAL(connected()), SLOT(streamConnected())); - //connect(d->stream, SIGNAL(handshaken()), SLOT(streamHandshaken())); + // connect(d->stream, SIGNAL(connected()), SLOT(streamConnected())); + // connect(d->stream, SIGNAL(handshaken()), SLOT(streamHandshaken())); connect(d->stream, SIGNAL(error(int)), SLOT(streamError(int))); - //connect(d->stream, SIGNAL(sslCertificateReady(QSSLCert)), SLOT(streamSSLCertificateReady(QSSLCert))); + // connect(d->stream, SIGNAL(sslCertificateReady(QSSLCert)), SLOT(streamSSLCertificateReady(QSSLCert))); connect(d->stream, SIGNAL(readyRead()), SLOT(streamReadyRead())); - //connect(d->stream, SIGNAL(closeFinished()), SLOT(streamCloseFinished())); + // connect(d->stream, SIGNAL(closeFinished()), SLOT(streamCloseFinished())); connect(d->stream, SIGNAL(incomingXml(QString)), SLOT(streamIncomingXml(QString))); connect(d->stream, SIGNAL(outgoingXml(QString)), SLOT(streamOutgoingXml(QString))); connect(d->stream, SIGNAL(haveUnhandledFeatures()), SLOT(parseUnhandledStreamFeatures())); @@ -215,9 +212,9 @@ void Client::connectToServer(ClientStream *s, const Jid &j, bool auth) void Client::start(const QString &host, const QString &user, const QString &pass, const QString &_resource) { // TODO - d->host = host; - d->user = user; - d->pass = pass; + d->host = host; + d->user = user; + d->pass = pass; d->resource = _resource; Status stat; @@ -225,8 +222,8 @@ void Client::start(const QString &host, const QString &user, const QString &pass d->resourceList += Resource(resource(), stat); JT_PushPresence *pp = new JT_PushPresence(rootTask()); - connect(pp, SIGNAL(subscription(Jid,QString,QString)), SLOT(ppSubscription(Jid,QString,QString))); - connect(pp, SIGNAL(presence(Jid,Status)), SLOT(ppPresence(Jid,Status))); + connect(pp, SIGNAL(subscription(Jid, QString, QString)), SLOT(ppSubscription(Jid, QString, QString))); + connect(pp, SIGNAL(presence(Jid, Status)), SLOT(ppPresence(Jid, Status))); JT_PushMessage *pm = new JT_PushMessage(rootTask(), d->encryptionHandler); connect(pm, SIGNAL(message(Message)), SLOT(pmMessage(Message))); @@ -240,90 +237,50 @@ void Client::start(const QString &host, const QString &user, const QString &pass d->active = true; } -void Client::setTcpPortReserver(TcpPortReserver *portReserver) -{ - d->tcpPortReserver = portReserver; -} +void Client::setTcpPortReserver(TcpPortReserver *portReserver) { d->tcpPortReserver = portReserver; } -TcpPortReserver * Client::tcpPortReserver() const -{ - return d->tcpPortReserver; -} +TcpPortReserver *Client::tcpPortReserver() const { return d->tcpPortReserver; } void Client::setFileTransferEnabled(bool b) { - if(b) { - if(!d->ftman) + if (b) { + if (!d->ftman) d->ftman = new FileTransferManager(this); - } - else { - if(d->ftman) { + } else { + if (d->ftman) { delete d->ftman; d->ftman = nullptr; } } } -FileTransferManager *Client::fileTransferManager() const -{ - return d->ftman; -} +FileTransferManager *Client::fileTransferManager() const { return d->ftman; } -S5BManager *Client::s5bManager() const -{ - return d->s5bman; -} +S5BManager *Client::s5bManager() const { return d->s5bman; } -Jingle::S5B::Manager *Client::jingleS5BManager() const -{ - return d->jingleS5BManager; -} +Jingle::S5B::Manager *Client::jingleS5BManager() const { return d->jingleS5BManager; } -Jingle::IBB::Manager *Client::jingleIBBManager() const -{ - return d->jingleIBBManager; -} +Jingle::IBB::Manager *Client::jingleIBBManager() const { return d->jingleIBBManager; } -IBBManager *Client::ibbManager() const -{ - return d->ibbman; -} +IBBManager *Client::ibbManager() const { return d->ibbman; } -BoBManager *Client::bobManager() const -{ - return d->bobman; -} +BoBManager *Client::bobManager() const { return d->bobman; } -CapsManager *Client::capsManager() const -{ - return d->capsman; -} +CapsManager *Client::capsManager() const { return d->capsman; } -ServerInfoManager *Client::serverInfoManager() const -{ - return d->serverInfoManager; -} +ServerInfoManager *Client::serverInfoManager() const { return d->serverInfoManager; } -HttpFileUploadManager *Client::httpFileUploadManager() const -{ - return d->httpFileUploadManager; -} +HttpFileUploadManager *Client::httpFileUploadManager() const { return d->httpFileUploadManager; } -Jingle::Manager *Client::jingleManager() const -{ - return d->jingleManager; -} +Jingle::Manager *Client::jingleManager() const { return d->jingleManager; } -bool Client::isActive() const -{ - return d->active; -} +bool Client::isActive() const { return d->active; } -QString Client::groupChatPassword(const QString& host, const QString& room) const +QString Client::groupChatPassword(const QString &host, const QString &room) const { Jid jid(room + "@" + host); - foreach(const GroupChat &i, d->groupChatList) { - if(i.j.compare(jid, false)) { + foreach (const GroupChat &i, d->groupChatList) { + if (i.j.compare(jid, false)) { return i.password; } } @@ -333,9 +290,9 @@ QString Client::groupChatPassword(const QString& host, const QString& room) cons void Client::groupChatChangeNick(const QString &host, const QString &room, const QString &nick, const Status &_s) { Jid jid(room + "@" + host + "/" + nick); - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { GroupChat &i = *it; - if(i.j.compare(jid, false)) { + if (i.j.compare(jid, false)) { i.j = jid; Status s = _s; @@ -350,37 +307,37 @@ void Client::groupChatChangeNick(const QString &host, const QString &room, const } } -bool Client::groupChatJoin(const QString &host, const QString &room, const QString &nick, const QString& password, int maxchars, int maxstanzas, int seconds, const QDateTime &since, const Status& _s) +bool Client::groupChatJoin(const QString &host, const QString &room, const QString &nick, const QString &password, + int maxchars, int maxstanzas, int seconds, const QDateTime &since, const Status &_s) { Jid jid(room + "@" + host + "/" + nick); - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end();) { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end();) { GroupChat &i = *it; - if(i.j.compare(jid, false)) { + if (i.j.compare(jid, false)) { // if this room is shutting down, then free it up - if(i.status == GroupChat::Closing) + if (i.status == GroupChat::Closing) it = d->groupChatList.erase(it); else return false; - } - else + } else ++it; } debug(QString("Client: Joined: [%1]\n").arg(jid.full())); GroupChat i; - i.j = jid; - i.status = GroupChat::Connecting; + i.j = jid; + i.status = GroupChat::Connecting; i.password = password; d->groupChatList += i; JT_Presence *j = new JT_Presence(rootTask()); - Status s = _s; + Status s = _s; s.setMUC(); s.setMUCHistory(maxchars, maxstanzas, seconds, since); if (!password.isEmpty()) { s.setMUCPassword(password); } - j->pres(jid,s); + j->pres(jid, s); j->go(true); return true; @@ -388,16 +345,16 @@ bool Client::groupChatJoin(const QString &host, const QString &room, const QStri void Client::groupChatSetStatus(const QString &host, const QString &room, const Status &_s) { - Jid jid(room + "@" + host); + Jid jid(room + "@" + host); bool found = false; foreach (const GroupChat &i, d->groupChatList) { - if(i.j.compare(jid, false)) { + if (i.j.compare(jid, false)) { found = true; - jid = i.j; + jid = i.j; break; } } - if(!found) + if (!found) return; Status s = _s; @@ -411,17 +368,17 @@ void Client::groupChatSetStatus(const QString &host, const QString &room, const void Client::groupChatLeave(const QString &host, const QString &room, const QString &statusStr) { Jid jid(room + "@" + host); - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { GroupChat &i = *it; - if(!i.j.compare(jid, false)) + if (!i.j.compare(jid, false)) continue; i.status = GroupChat::Closing; debug(QString("Client: Leaving: [%1]\n").arg(i.j.full())); JT_Presence *j = new JT_Presence(rootTask()); - Status s; + Status s; s.setIsAvailable(false); s.setStatus(statusStr); j->pres(i.j, s); @@ -432,12 +389,12 @@ void Client::groupChatLeave(const QString &host, const QString &room, const QStr void Client::groupChatLeaveAll(const QString &statusStr) { if (d->stream && d->active) { - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { GroupChat &i = *it; - i.status = GroupChat::Closing; + i.status = GroupChat::Closing; JT_Presence *j = new JT_Presence(rootTask()); - Status s; + Status s; s.setIsAvailable(false); s.setStatus(statusStr); j->pres(i.j, s); @@ -472,10 +429,10 @@ QString Client::groupChatNick(const QString &host, const QString &room) const // TODO: fast close void Client::close(bool) { - //fprintf(stderr, "\tClient::close\n"); - //fflush(stderr); + // fprintf(stderr, "\tClient::close\n"); + // fflush(stderr); - if(d->stream) { + if (d->stream) { d->stream->disconnect(this); d->stream->close(); d->stream = nullptr; @@ -487,7 +444,7 @@ void Client::close(bool) void Client::cleanup() { d->active = false; - //d->authed = false; + // d->authed = false; d->groupChatList.clear(); } @@ -508,12 +465,12 @@ void Client::streamHandshaken() void Client::streamError(int) { - //StreamError e = err; - //error(e); + // StreamError e = err; + // error(e); - //if(!e.isWarning()) { - disconnected(); - cleanup(); + // if(!e.isWarning()) { + disconnected(); + cleanup(); //} } // namespace XMPP @@ -531,32 +488,32 @@ static QDomElement oldStyleNS(const QDomElement &e) { // find closest parent with a namespace QDomNode par = e.parentNode(); - while(!par.isNull() && par.namespaceURI().isNull()) + while (!par.isNull() && par.namespaceURI().isNull()) par = par.parentNode(); bool noShowNS = false; - if(!par.isNull() && par.namespaceURI() == e.namespaceURI()) + if (!par.isNull() && par.namespaceURI() == e.namespaceURI()) noShowNS = true; QDomElement i; - int x; - //if(noShowNS) - i = e.ownerDocument().createElement(e.tagName()); - //else + int x; + // if(noShowNS) + i = e.ownerDocument().createElement(e.tagName()); + // else // i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName()); // copy attributes QDomNamedNodeMap al = e.attributes(); - for(x = 0; x < al.count(); ++x) + for (x = 0; x < al.count(); ++x) i.setAttributeNode(al.item(x).cloneNode().toAttr()); - if(!noShowNS) + if (!noShowNS) i.setAttribute("xmlns", e.namespaceURI()); // copy children QDomNodeList nl = e.childNodes(); - for(x = 0; x < nl.count(); ++x) { + for (x = 0; x < nl.count(); ++x) { QDomNode n = nl.item(x); - if(n.isElement()) + if (n.isElement()) i.appendChild(oldStyleNS(n.toElement())); else i.appendChild(n.cloneNode()); @@ -566,17 +523,17 @@ static QDomElement oldStyleNS(const QDomElement &e) void Client::streamReadyRead() { - //fprintf(stderr, "\tClientStream::streamReadyRead\n"); - //fflush(stderr); + // fprintf(stderr, "\tClientStream::streamReadyRead\n"); + // fflush(stderr); - while(d->stream && d->stream->stanzaAvailable()) { + while (d->stream && d->stream->stanzaAvailable()) { Stanza s = d->stream->read(); QString out = s.toString(); debug(QString("Client: incoming: [\n%1]\n").arg(out)); emit xmlIncoming(out); - QDomElement x = s.element();//oldStyleNS(s.element()); + QDomElement x = s.element(); // oldStyleNS(s.element()); distribute(x); } } @@ -584,7 +541,7 @@ void Client::streamReadyRead() void Client::streamIncomingXml(const QString &s) { QString str = s; - if(str.at(str.length()-1) != '\n') + if (str.at(str.length() - 1) != '\n') str += '\n'; emit xmlIncoming(str); } @@ -592,7 +549,7 @@ void Client::streamIncomingXml(const QString &s) void Client::streamOutgoingXml(const QString &s) { QString str = s; - if(str.at(str.length()-1) != '\n') + if (str.at(str.length() - 1) != '\n') str += '\n'; emit xmlOutgoing(str); } @@ -610,10 +567,7 @@ void Client::parseUnhandledStreamFeatures() } } -void Client::debug(const QString &str) -{ - emit debugText(str); -} +void Client::debug(const QString &str) { emit debugText(str); } QString Client::genUniqueId() { @@ -623,28 +577,22 @@ QString Client::genUniqueId() return s; } -Task *Client::rootTask() -{ - return d->root; -} +Task *Client::rootTask() { return d->root; } -QDomDocument *Client::doc() const -{ - return &d->doc; -} +QDomDocument *Client::doc() const { return &d->doc; } void Client::distribute(const QDomElement &x) { static QString fromAttr(QStringLiteral("from")); - if(x.hasAttribute(fromAttr)) { + if (x.hasAttribute(fromAttr)) { Jid j(x.attribute(fromAttr)); - if(!j.isValid()) { + if (!j.isValid()) { debug("Client: bad 'from' JID\n"); return; } } - if(!rootTask()->take(x) && (x.attribute("type") == "get" || x.attribute("type") == "set") ) { + if (!rootTask()->take(x) && (x.attribute("type") == "get" || x.attribute("type") == "set")) { debug("Client: Unrecognized IQ.\n"); // Create reply element @@ -657,7 +605,7 @@ void Client::distribute(const QDomElement &x) // Add error QDomElement error = doc()->createElement("error"); - error.setAttribute("type","cancel"); + error.setAttribute("type", "cancel"); reply.appendChild(error); QDomElement error_type = doc()->createElementNS(QLatin1String("urn:ietf:params:xml:ns:xmpp-stanzas"), @@ -670,109 +618,80 @@ void Client::distribute(const QDomElement &x) void Client::send(const QDomElement &x) { - if(!d->stream) + if (!d->stream) return; - //QString out; - //QTextStream ts(&out, IO_WriteOnly); - //x.save(ts, 0); + // QString out; + // QTextStream ts(&out, IO_WriteOnly); + // x.save(ts, 0); - //QString out = Stream::xmlToString(x); - //debug(QString("Client: outgoing: [\n%1]\n").arg(out)); - //xmlOutgoing(out); + // QString out = Stream::xmlToString(x); + // debug(QString("Client: outgoing: [\n%1]\n").arg(out)); + // xmlOutgoing(out); QDomElement e = addCorrectNS(x); - Stanza s = d->stream->createStanza(e); - if(s.isNull()) { // e's namespace is not "jabber:client" or e.tagName is not in (message,presence,iq) - //printf("bad stanza??\n"); + Stanza s = d->stream->createStanza(e); + if (s.isNull()) { // e's namespace is not "jabber:client" or e.tagName is not in (message,presence,iq) + // printf("bad stanza??\n"); return; } emit stanzaElementOutgoing(e); // signal handler may change the node (TODO weird design?) - if (e.isNull()) { // so it was changed by signal above + if (e.isNull()) { // so it was changed by signal above return; } QString out = s.toString(); - //qWarning() << "Out: " << out; + // qWarning() << "Out: " << out; debug(QString("Client: outgoing: [\n%1]\n").arg(out)); emit xmlOutgoing(out); - //printf("x[%s] x2[%s] s[%s]\n", Stream::xmlToString(x).toLatin1(), Stream::xmlToString(e).toLatin1(), s.toString().toLatin1()); + // printf("x[%s] x2[%s] s[%s]\n", Stream::xmlToString(x).toLatin1(), Stream::xmlToString(e).toLatin1(), + // s.toString().toLatin1()); d->stream->write(s); } void Client::send(const QString &str) { - if(!d->stream) + if (!d->stream) return; debug(QString("Client: outgoing: [\n%1]\n").arg(str)); emit xmlOutgoing(str); - static_cast(d->stream)->writeDirect(str); + static_cast(d->stream)->writeDirect(str); } /* drops any pending outgoing xml elements */ -void Client::clearSendQueue() -{ - d->stream->clearSendQueue(); -} +void Client::clearSendQueue() { d->stream->clearSendQueue(); } -bool Client::hasStream() const -{ - return !!d->stream; -} +bool Client::hasStream() const { return !!d->stream; } -Stream & Client::stream() -{ - return *(d->stream.data()); -} +Stream &Client::stream() { return *(d->stream.data()); } -QString Client::streamBaseNS() const -{ - return d->stream->baseNS(); -} +QString Client::streamBaseNS() const { return d->stream->baseNS(); } -const LiveRoster & Client::roster() const -{ - return d->roster; -} +const LiveRoster &Client::roster() const { return d->roster; } -const ResourceList & Client::resourceList() const -{ - return d->resourceList; -} +const ResourceList &Client::resourceList() const { return d->resourceList; } bool Client::isSessionRequired() const { return d->stream && !d->stream->old() && d->stream->streamFeatures().session_required; } -QString Client::host() const -{ - return d->host; -} +QString Client::host() const { return d->host; } -QString Client::user() const -{ - return d->user; -} +QString Client::user() const { return d->user; } -QString Client::pass() const -{ - return d->pass; -} +QString Client::pass() const { return d->pass; } -QString Client::resource() const -{ - return d->resource; -} +QString Client::resource() const { return d->resource; } Jid Client::jid() const { QString s; - if(!d->user.isEmpty()) + if (!d->user.isEmpty()) s += d->user + '@'; s += d->host; - if(!d->resource.isEmpty()) { + if (!d->resource.isEmpty()) { s += '/'; s += d->resource; } @@ -780,89 +699,78 @@ Jid Client::jid() const return Jid(s); } -void Client::setNetworkAccessManager(QNetworkAccessManager *qnam) -{ - d->qnam = qnam; -} +void Client::setNetworkAccessManager(QNetworkAccessManager *qnam) { d->qnam = qnam; } -QNetworkAccessManager *Client::networkAccessManager() const -{ - return d->qnam; -} +QNetworkAccessManager *Client::networkAccessManager() const { return d->qnam; } -void Client::ppSubscription(const Jid &j, const QString &s, const QString& n) -{ - emit subscription(j, s, n); -} +void Client::ppSubscription(const Jid &j, const QString &s, const QString &n) { emit subscription(j, s, n); } void Client::ppPresence(const Jid &j, const Status &s) { - if(s.isAvailable()) + if (s.isAvailable()) debug(QString("Client: %1 is available.\n").arg(j.full())); else debug(QString("Client: %1 is unavailable.\n").arg(j.full())); - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { GroupChat &i = *it; - if(i.j.compare(j, false)) { - bool us = (i.j.resource() == j.resource() || j.resource().isEmpty()) ? true: false; + if (i.j.compare(j, false)) { + bool us = (i.j.resource() == j.resource() || j.resource().isEmpty()) ? true : false; debug(QString("for groupchat i=[%1] pres=[%2], [us=%3].\n").arg(i.j.full()).arg(j.full()).arg(us)); - switch(i.status) { - case GroupChat::Connecting: - if(us && s.hasError()) { - Jid j = i.j; - d->groupChatList.erase(it); - emit groupChatError(j, s.errorCode(), s.errorString()); + switch (i.status) { + case GroupChat::Connecting: + if (us && s.hasError()) { + Jid j = i.j; + d->groupChatList.erase(it); + emit groupChatError(j, s.errorCode(), s.errorString()); + } else { + // don't signal success unless it is a non-error presence + if (!s.hasError()) { + i.status = GroupChat::Connected; + emit groupChatJoined(i.j); } - else { - // don't signal success unless it is a non-error presence - if(!s.hasError()) { - i.status = GroupChat::Connected; - emit groupChatJoined(i.j); - } - emit groupChatPresence(j, s); - } - break; - case GroupChat::Connected: emit groupChatPresence(j, s); - break; - case GroupChat::Closing: - if(us && !s.isAvailable()) { - Jid j = i.j; - d->groupChatList.erase(it); - emit groupChatLeft(j); - } - break; - default: - break; + } + break; + case GroupChat::Connected: + emit groupChatPresence(j, s); + break; + case GroupChat::Closing: + if (us && !s.isAvailable()) { + Jid j = i.j; + d->groupChatList.erase(it); + emit groupChatLeft(j); + } + break; + default: + break; } return; } } - if(s.hasError()) { + if (s.hasError()) { emit presenceError(j, s.errorCode(), s.errorString()); return; } // is it me? - if(j.compare(jid(), false)) { + if (j.compare(jid(), false)) { updateSelfPresence(j, s); - } - else { + } else { // update all relavent roster entries - for(LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end(); ++it) { + for (LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end(); ++it) { LiveRosterItem &i = *it; - if(!i.jid().compare(j, false)) + if (!i.jid().compare(j, false)) continue; // roster item has its own resource? - if(!i.jid().resource().isEmpty()) { - if(i.jid().resource() != j.resource()) + if (!i.jid().resource().isEmpty()) { + if (i.jid().resource() != j.resource()) continue; } @@ -873,12 +781,12 @@ void Client::ppPresence(const Jid &j, const Status &s) void Client::updateSelfPresence(const Jid &j, const Status &s) { - ResourceList::Iterator rit = d->resourceList.find(j.resource()); - bool found = (rit == d->resourceList.end()) ? false: true; + ResourceList::Iterator rit = d->resourceList.find(j.resource()); + bool found = (rit == d->resourceList.end()) ? false : true; // unavailable? remove the resource - if(!s.isAvailable()) { - if(found) { + if (!s.isAvailable()) { + if (found) { debug(QString("Client: Removing self resource: name=[%1]\n").arg(j.resource())); (*rit).setStatus(s); emit resourceUnavailable(j, *rit); @@ -888,12 +796,11 @@ void Client::updateSelfPresence(const Jid &j, const Status &s) // available? add/update the resource else { Resource r; - if(!found) { + if (!found) { r = Resource(j.resource(), s); d->resourceList += r; debug(QString("Client: Adding self resource: name=[%1]\n").arg(j.resource())); - } - else { + } else { (*rit).setStatus(s); r = *rit; debug(QString("Client: Updating self resource: name=[%1]\n").arg(j.resource())); @@ -905,19 +812,18 @@ void Client::updateSelfPresence(const Jid &j, const Status &s) void Client::updatePresence(LiveRosterItem *i, const Jid &j, const Status &s) { - ResourceList::Iterator rit = i->resourceList().find(j.resource()); - bool found = (rit == i->resourceList().end()) ? false: true; + ResourceList::Iterator rit = i->resourceList().find(j.resource()); + bool found = (rit == i->resourceList().end()) ? false : true; // unavailable? remove the resource - if(!s.isAvailable()) { - if(found) { + if (!s.isAvailable()) { + if (found) { (*rit).setStatus(s); debug(QString("Client: Removing resource from [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource())); emit resourceUnavailable(j, *rit); i->resourceList().erase(rit); i->setLastUnavailableStatus(s); - } - else { + } else { // create the resource just for the purpose of emit Resource r = Resource(j.resource(), s); i->resourceList() += r; @@ -930,12 +836,11 @@ void Client::updatePresence(LiveRosterItem *i, const Jid &j, const Status &s) // available? add/update the resource else { Resource r; - if(!found) { + if (!found) { r = Resource(j.resource(), s); i->resourceList() += r; debug(QString("Client: Adding resource to [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource())); - } - else { + } else { (*rit).setStatus(s); r = *rit; debug(QString("Client: Updating resource to [%1]: name=[%2]\n").arg(i->jid().full()).arg(j.resource())); @@ -958,29 +863,25 @@ void Client::pmMessage(const Message &m) d->ibbman->takeIncomingData(m.from(), m.id(), m.ibbData(), Stanza::Message); } - if(m.type() == "groupchat") { - for(QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { + if (m.type() == "groupchat") { + for (QList::Iterator it = d->groupChatList.begin(); it != d->groupChatList.end(); it++) { const GroupChat &i = *it; - if(!i.j.compare(m.from(), false)) + if (!i.j.compare(m.from(), false)) continue; - if(i.status == GroupChat::Connected) + if (i.status == GroupChat::Connected) messageReceived(m); } - } - else + } else messageReceived(m); } -void Client::prRoster(const Roster &r) -{ - importRoster(r); -} +void Client::prRoster(const Roster &r) { importRoster(r); } void Client::rosterRequest() { - if(!d->active) + if (!d->active) return; JT_Roster *r = new JT_Roster(rootTask()); @@ -994,24 +895,22 @@ void Client::slotRosterRequestFinished() { JT_Roster *r = static_cast(sender()); // on success, let's take it - if(r->success()) { - //d->roster.flagAllForDelete(); // mod_groups patch + if (r->success()) { + // d->roster.flagAllForDelete(); // mod_groups patch importRoster(r->roster()); - for(LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end();) { + for (LiveRoster::Iterator it = d->roster.begin(); it != d->roster.end();) { LiveRosterItem &i = *it; - if(i.flagForDelete()) { + if (i.flagForDelete()) { emit rosterItemRemoved(i); it = d->roster.erase(it); - } - else + } else ++it; } - } - else { + } else { // don't report a disconnect. Client::error() will do that. - if(r->statusCode() == Task::ErrDisc) + if (r->statusCode() == Task::ErrDisc) return; } @@ -1022,7 +921,7 @@ void Client::slotRosterRequestFinished() void Client::importRoster(const Roster &r) { emit beginImportRoster(); - for(Roster::ConstIterator it = r.begin(); it != r.end(); ++it) { + for (Roster::ConstIterator it = r.begin(); it != r.end(); ++it) { importRosterItem(*it); } emit endImportRoster(); @@ -1031,30 +930,35 @@ void Client::importRoster(const Roster &r) void Client::importRosterItem(const RosterItem &item) { QString substr; - switch(item.subscription().type()) { - case Subscription::Both: - substr = "<-->"; break; - case Subscription::From: - substr = " ->"; break; - case Subscription::To: - substr = "<- "; break; - case Subscription::Remove: - substr = "xxxx"; break; - case Subscription::None: - default: - substr = "----"; break; + switch (item.subscription().type()) { + case Subscription::Both: + substr = "<-->"; + break; + case Subscription::From: + substr = " ->"; + break; + case Subscription::To: + substr = "<- "; + break; + case Subscription::Remove: + substr = "xxxx"; + break; + case Subscription::None: + default: + substr = "----"; + break; } QString dstr, str; str.sprintf(" %s %-32s", qPrintable(substr), qPrintable(item.jid().full())); - if(!item.name().isEmpty()) + if (!item.name().isEmpty()) str += QString(" [") + item.name() + "]"; str += '\n'; // Remove - if(item.subscription().type() == Subscription::Remove) { + if (item.subscription().type() == Subscription::Remove) { LiveRoster::Iterator it = d->roster.find(item.jid()); - if(it != d->roster.end()) { + if (it != d->roster.end()) { emit rosterItemRemoved(*it); d->roster.erase(it); } @@ -1063,14 +967,13 @@ void Client::importRosterItem(const RosterItem &item) // Add/Update else { LiveRoster::Iterator it = d->roster.find(item.jid()); - if(it != d->roster.end()) { + if (it != d->roster.end()) { LiveRosterItem &i = *it; i.setFlagForDelete(false); i.setRosterItem(item); emit rosterItemUpdated(i); dstr = "Client: (Updated) "; - } - else { + } else { LiveRosterItem i(item); d->roster += i; @@ -1089,7 +992,7 @@ void Client::sendMessage(Message &m) j->go(true); } -void Client::sendSubscription(const Jid &jid, const QString &type, const QString& nick) +void Client::sendSubscription(const Jid &jid, const QString &type, const QString &nick) { JT_Presence *j = new JT_Presence(rootTask()); j->sub(jid, type, nick); @@ -1110,30 +1013,18 @@ void Client::setPresence(const Status &s) // update our resourceList ppPresence(jid(), s); - //ResourceList::Iterator rit = d->resourceList.find(resource()); - //Resource &r = *rit; - //r.setStatus(s); + // ResourceList::Iterator rit = d->resourceList.find(resource()); + // Resource &r = *rit; + // r.setStatus(s); } -QString Client::OSName() const -{ - return d->osName; -} +QString Client::OSName() const { return d->osName; } -QString Client::OSVersion() const -{ - return d->osVersion; -} +QString Client::OSVersion() const { return d->osVersion; } -QString Client::timeZone() const -{ - return d->tzname; -} +QString Client::timeZone() const { return d->tzname; } -int Client::timeZoneOffset() const -{ - return d->tzoffset; -} +int Client::timeZoneOffset() const { return d->tzoffset; } /** \brief Returns true if Client is using old, manual time zone conversions. @@ -1145,77 +1036,38 @@ int Client::timeZoneOffset() const However, if you call setTimeZone(), Client instance switches to old mode and uses given time zone offset for all calculations. */ -bool Client::manualTimeZoneOffset() const -{ - return d->useTzoffset; -} +bool Client::manualTimeZoneOffset() const { return d->useTzoffset; } -QString Client::clientName() const -{ - return d->clientName; -} +QString Client::clientName() const { return d->clientName; } -QString Client::clientVersion() const -{ - return d->clientVersion; -} +QString Client::clientVersion() const { return d->clientVersion; } -CapsSpec Client::caps() const -{ - return d->caps; -} +CapsSpec Client::caps() const { return d->caps; } -CapsSpec Client::serverCaps() const -{ - return d->serverCaps; -} +CapsSpec Client::serverCaps() const { return d->serverCaps; } -void Client::setOSName(const QString &name) -{ - d->osName = name; -} +void Client::setOSName(const QString &name) { d->osName = name; } -void Client::setOSVersion(const QString &version) -{ - d->osVersion = version; -} +void Client::setOSVersion(const QString &version) { d->osVersion = version; } void Client::setTimeZone(const QString &name, int offset) { - d->tzname = name; - d->tzoffset = offset; + d->tzname = name; + d->tzoffset = offset; d->useTzoffset = true; } -void Client::setClientName(const QString &s) -{ - d->clientName = s; -} +void Client::setClientName(const QString &s) { d->clientName = s; } -void Client::setClientVersion(const QString &s) -{ - d->clientVersion = s; -} +void Client::setClientVersion(const QString &s) { d->clientVersion = s; } -void Client::setCaps(const CapsSpec &s) -{ - d->caps = s; -} +void Client::setCaps(const CapsSpec &s) { d->caps = s; } -void Client::setEncryptionHandler(EncryptionHandler *encryptionHandler) -{ - d->encryptionHandler = encryptionHandler; -} +void Client::setEncryptionHandler(EncryptionHandler *encryptionHandler) { d->encryptionHandler = encryptionHandler; } -EncryptionHandler *Client::encryptionHandler() const -{ - return d->encryptionHandler; -} +EncryptionHandler *Client::encryptionHandler() const { return d->encryptionHandler; } -DiscoItem::Identity Client::identity() const -{ - return d->identity; -} +DiscoItem::Identity Client::identity() const { return d->identity; } void Client::setIdentity(const DiscoItem::Identity &identity) { @@ -1225,7 +1077,7 @@ void Client::setIdentity(const DiscoItem::Identity &identity) d->identity = identity; } -void Client::setFeatures(const Features& f) +void Client::setFeatures(const Features &f) { if (!(d->features == f)) { d->caps.resetVersion(); @@ -1233,10 +1085,7 @@ void Client::setFeatures(const Features& f) d->features = f; } -const Features& Client::features() const -{ - return d->features; -} +const Features &Client::features() const { return d->features; } DiscoItem Client::makeDiscoResult(const QString &node) const { @@ -1245,7 +1094,7 @@ DiscoItem Client::makeDiscoResult(const QString &node) const DiscoItem::Identity id = identity(); if (id.category.isEmpty() || id.type.isEmpty()) { id.category = "client"; - id.type = "pc"; + id.type = "pc"; } item.setIdentities(id); @@ -1267,18 +1116,19 @@ DiscoItem Client::makeDiscoResult(const QString &node) const // TODO rather do foreach for all registered jingle apps and transports features.addFeature("urn:xmpp:jingle:transports:s5b:1"); features.addFeature("urn:xmpp:jingle:transports:ibb:1"); - features.addFeature("urn:xmpp:jingle:apps:file-transfer:5"); // TODO: since it depends on UI it needs a way to be disabled + features.addFeature( + "urn:xmpp:jingle:apps:file-transfer:5"); // TODO: since it depends on UI it needs a way to be disabled Hash::populateFeatures(features); // Client-specific features - foreach (const QString & i, d->features.list()) { + foreach (const QString &i, d->features.list()) { features.addFeature(i); } item.setFeatures(features); // xep-0232 Software Information - XData si; + XData si; XData::FieldList si_fields; XData::Field si_type_field; @@ -1319,10 +1169,7 @@ DiscoItem Client::makeDiscoResult(const QString &node) const return item; } -void Client::s5b_incomingReady() -{ - handleIncoming(d->s5bman->takeIncoming()); -} +void Client::s5b_incomingReady() { handleIncoming(d->s5bman->takeIncoming()); } void Client::ibb_incomingReady() { @@ -1337,9 +1184,9 @@ void Client::ibb_incomingReady() void Client::handleIncoming(BSConnection *c) { - if(!c) + if (!c) return; - if(!d->ftman) { + if (!d->ftman) { c->close(); c->deleteLater(); return; @@ -1347,18 +1194,12 @@ void Client::handleIncoming(BSConnection *c) d->ftman->stream_incomingReady(c); } -void Client::handleSMAckResponse(int h) { - qDebug() << "handleSMAckResponse: h = " << h; -} +void Client::handleSMAckResponse(int h) { qDebug() << "handleSMAckResponse: h = " << h; } //--------------------------------------------------------------------------- // LiveRosterItem //--------------------------------------------------------------------------- -LiveRosterItem::LiveRosterItem(const Jid &jid) -:RosterItem(jid) -{ - setFlagForDelete(false); -} +LiveRosterItem::LiveRosterItem(const Jid &jid) : RosterItem(jid) { setFlagForDelete(false); } LiveRosterItem::LiveRosterItem(const RosterItem &i) { @@ -1366,9 +1207,7 @@ LiveRosterItem::LiveRosterItem(const RosterItem &i) setFlagForDelete(false); } -LiveRosterItem::~LiveRosterItem() -{ -} +LiveRosterItem::~LiveRosterItem() {} void LiveRosterItem::setRosterItem(const RosterItem &i) { @@ -1380,76 +1219,47 @@ void LiveRosterItem::setRosterItem(const RosterItem &i) setIsPush(i.isPush()); } -ResourceList & LiveRosterItem::resourceList() -{ - return v_resourceList; -} +ResourceList &LiveRosterItem::resourceList() { return v_resourceList; } -ResourceList::Iterator LiveRosterItem::priority() -{ - return v_resourceList.priority(); -} +ResourceList::Iterator LiveRosterItem::priority() { return v_resourceList.priority(); } -const ResourceList & LiveRosterItem::resourceList() const -{ - return v_resourceList; -} +const ResourceList &LiveRosterItem::resourceList() const { return v_resourceList; } -ResourceList::ConstIterator LiveRosterItem::priority() const -{ - return v_resourceList.priority(); -} +ResourceList::ConstIterator LiveRosterItem::priority() const { return v_resourceList.priority(); } bool LiveRosterItem::isAvailable() const { - if(v_resourceList.count() > 0) + if (v_resourceList.count() > 0) return true; return false; } -const Status & LiveRosterItem::lastUnavailableStatus() const -{ - return v_lastUnavailableStatus; -} +const Status &LiveRosterItem::lastUnavailableStatus() const { return v_lastUnavailableStatus; } -bool LiveRosterItem::flagForDelete() const -{ - return v_flagForDelete; -} +bool LiveRosterItem::flagForDelete() const { return v_flagForDelete; } -void LiveRosterItem::setLastUnavailableStatus(const Status &s) -{ - v_lastUnavailableStatus = s; -} +void LiveRosterItem::setLastUnavailableStatus(const Status &s) { v_lastUnavailableStatus = s; } -void LiveRosterItem::setFlagForDelete(bool b) -{ - v_flagForDelete = b; -} +void LiveRosterItem::setFlagForDelete(bool b) { v_flagForDelete = b; } //--------------------------------------------------------------------------- // LiveRoster //--------------------------------------------------------------------------- -LiveRoster::LiveRoster() -:QList() -{ -} +LiveRoster::LiveRoster() : QList() {} -LiveRoster::~LiveRoster() -{ -} +LiveRoster::~LiveRoster() {} void LiveRoster::flagAllForDelete() { - for(Iterator it = begin(); it != end(); ++it) + for (Iterator it = begin(); it != end(); ++it) (*it).setFlagForDelete(true); } LiveRoster::Iterator LiveRoster::find(const Jid &j, bool compareRes) { Iterator it; - for(it = begin(); it != end(); ++it) { - if((*it).jid().compare(j, compareRes)) + for (it = begin(); it != end(); ++it) { + if ((*it).jid().compare(j, compareRes)) break; } return it; @@ -1458,8 +1268,8 @@ LiveRoster::Iterator LiveRoster::find(const Jid &j, bool compareRes) LiveRoster::ConstIterator LiveRoster::find(const Jid &j, bool compareRes) const { ConstIterator it; - for(it = begin(); it != end(); ++it) { - if((*it).jid().compare(j, compareRes)) + for (it = begin(); it != end(); ++it) { + if ((*it).jid().compare(j, compareRes)) break; } return it; diff --git a/src/xmpp/xmpp-im/filetransfer.cpp b/src/xmpp/xmpp-im/filetransfer.cpp index 2a66c8b1..3f110003 100644 --- a/src/xmpp/xmpp-im/filetransfer.cpp +++ b/src/xmpp/xmpp-im/filetransfer.cpp @@ -38,8 +38,8 @@ using namespace XMPP; // Get an element's first child element static QDomElement firstChildElement(const QDomElement &e) { - for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { - if(n.isElement()) + for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) { + if (n.isElement()) return n.toElement(); } return QDomElement(); @@ -48,46 +48,43 @@ static QDomElement firstChildElement(const QDomElement &e) //---------------------------------------------------------------------------- // FileTransfer //---------------------------------------------------------------------------- -class FileTransfer::Private -{ +class FileTransfer::Private { public: FileTransferManager *m; - JT_FT *ft; - Jid peer; - QString fname; - qlonglong size; - qlonglong sent; - QString desc; - bool rangeSupported; - qlonglong rangeOffset, rangeLength, length; - QString streamType; - Thumbnail thumbnail; - bool needStream; - QString id, iq_id; - BSConnection *c; - Jid proxy; - int state; - bool sender; + JT_FT * ft; + Jid peer; + QString fname; + qlonglong size; + qlonglong sent; + QString desc; + bool rangeSupported; + qlonglong rangeOffset, rangeLength, length; + QString streamType; + Thumbnail thumbnail; + bool needStream; + QString id, iq_id; + BSConnection * c; + Jid proxy; + int state; + bool sender; }; -FileTransfer::FileTransfer(FileTransferManager *m, QObject *parent) -:QObject(parent) +FileTransfer::FileTransfer(FileTransferManager *m, QObject *parent) : QObject(parent) { - d = new Private; - d->m = m; + d = new Private; + d->m = m; d->ft = nullptr; - d->c = nullptr; + d->c = nullptr; reset(); } -FileTransfer::FileTransfer(const FileTransfer& other) - : QObject(other.parent()) +FileTransfer::FileTransfer(const FileTransfer &other) : QObject(other.parent()) { - d = new Private; - *d = *other.d; - d->m = other.d->m; + d = new Private; + *d = *other.d; + d->m = other.d->m; d->ft = nullptr; - d->c = 0; + d->c = 0; reset(); if (d->m->isActive(&other)) @@ -100,10 +97,7 @@ FileTransfer::~FileTransfer() delete d; } -FileTransfer *FileTransfer::copy() const -{ - return new FileTransfer(*this); -} +FileTransfer *FileTransfer::copy() const { return new FileTransfer(*this); } void FileTransfer::reset() { @@ -114,32 +108,27 @@ void FileTransfer::reset() if (d->c) { d->c->disconnect(this); - d->c->manager()->deleteConnection(d->c, d->state == Active && !d->sender ? - 3000 : 0); + d->c->manager()->deleteConnection(d->c, d->state == Active && !d->sender ? 3000 : 0); d->c = nullptr; } - d->state = Idle; + d->state = Idle; d->needStream = false; - d->sent = 0; - d->sender = false; + d->sent = 0; + d->sender = false; } -void FileTransfer::setProxy(const Jid &proxy) -{ - d->proxy = proxy; -} +void FileTransfer::setProxy(const Jid &proxy) { d->proxy = proxy; } -void FileTransfer::sendFile(const Jid &to, const QString &fname, qlonglong size, - const QString &desc, Thumbnail &thumb) +void FileTransfer::sendFile(const Jid &to, const QString &fname, qlonglong size, const QString &desc, Thumbnail &thumb) { - d->state = Requesting; - d->peer = to; - d->fname = fname; - d->size = size; - d->desc = desc; + d->state = Requesting; + d->peer = to; + d->fname = fname; + d->size = size; + d->desc = desc; d->sender = true; - d->id = d->m->link(this); + d->id = d->m->link(this); d->ft = new JT_FT(d->m->client()->rootTask()); connect(d->ft, SIGNAL(finished()), SLOT(ft_finished())); @@ -150,78 +139,53 @@ void FileTransfer::sendFile(const Jid &to, const QString &fname, qlonglong size, int FileTransfer::dataSizeNeeded() const { int pending = d->c->bytesToWrite(); - if(pending >= SENDBUFSIZE) + if (pending >= SENDBUFSIZE) return 0; qlonglong left = d->length - (d->sent + pending); - int size = SENDBUFSIZE - pending; - if((qlonglong)size > left) + int size = SENDBUFSIZE - pending; + if ((qlonglong)size > left) size = (int)left; return size; } void FileTransfer::writeFileData(const QByteArray &a) { - int pending = d->c->bytesToWrite(); - qlonglong left = d->length - (d->sent + pending); - if(left == 0) + int pending = d->c->bytesToWrite(); + qlonglong left = d->length - (d->sent + pending); + if (left == 0) return; QByteArray block; - if((qlonglong)a.size() > left) { + if ((qlonglong)a.size() > left) { block = a; block.resize((uint)left); - } - else + } else block = a; d->c->write(block); } -const Thumbnail &FileTransfer::thumbnail() const -{ - return d->thumbnail; -} +const Thumbnail &FileTransfer::thumbnail() const { return d->thumbnail; } -Jid FileTransfer::peer() const -{ - return d->peer; -} +Jid FileTransfer::peer() const { return d->peer; } -QString FileTransfer::fileName() const -{ - return d->fname; -} +QString FileTransfer::fileName() const { return d->fname; } -qlonglong FileTransfer::fileSize() const -{ - return d->size; -} +qlonglong FileTransfer::fileSize() const { return d->size; } -QString FileTransfer::description() const -{ - return d->desc; -} +QString FileTransfer::description() const { return d->desc; } -bool FileTransfer::rangeSupported() const -{ - return d->rangeSupported; -} +bool FileTransfer::rangeSupported() const { return d->rangeSupported; } -qlonglong FileTransfer::offset() const -{ - return d->rangeOffset; -} +qlonglong FileTransfer::offset() const { return d->rangeOffset; } -qlonglong FileTransfer::length() const -{ - return d->length; -} +qlonglong FileTransfer::length() const { return d->length; } void FileTransfer::accept(qlonglong offset, qlonglong length) { - d->state = Connecting; + d->state = Connecting; d->rangeOffset = offset; d->rangeLength = length; - if(length > 0) + if (length > 0) d->length = length; else d->length = d->size; @@ -230,38 +194,35 @@ void FileTransfer::accept(qlonglong offset, qlonglong length) void FileTransfer::close() { - if(d->state == Idle) + if (d->state == Idle) return; - if(d->state == WaitingForAccept) + if (d->state == WaitingForAccept) d->m->con_reject(this); - else if(d->state == Active) + else if (d->state == Active) d->c->close(); reset(); } -BSConnection *FileTransfer::bsConnection() const -{ - return d->c; -} +BSConnection *FileTransfer::bsConnection() const { return d->c; } // file transfer request accepted or error happened void FileTransfer::ft_finished() { JT_FT *ft = d->ft; - d->ft = nullptr; + d->ft = nullptr; - if(ft->success()) { - d->state = Connecting; + if (ft->success()) { + d->state = Connecting; d->rangeOffset = ft->rangeOffset(); - d->length = ft->rangeLength(); - if(d->length == 0) + d->length = ft->rangeLength(); + if (d->length == 0) d->length = d->size - d->rangeOffset; - d->streamType = ft->streamType(); + d->streamType = ft->streamType(); BytestreamManager *streamManager = d->m->streamManager(d->streamType); if (streamManager) { d->c = streamManager->createConnection(); - if (dynamic_cast(streamManager) && d->proxy.isValid()) { - ((S5BConnection*)(d->c))->setProxy(d->proxy); + if (dynamic_cast(streamManager) && d->proxy.isValid()) { + ((S5BConnection *)(d->c))->setProxy(d->proxy); } connect(d->c, SIGNAL(connected()), SLOT(stream_connected())); connect(d->c, SIGNAL(connectionClosed()), SLOT(stream_connectionClosed())); @@ -270,16 +231,14 @@ void FileTransfer::ft_finished() d->c->connectToJid(d->peer, d->id); accepted(); - } - else { + } else { emit error(Err400); reset(); } - } - else { - if(ft->statusCode() == 403) + } else { + if (ft->statusCode() == 403) emit error(ErrReject); - else if(ft->statusCode() == 400) + else if (ft->statusCode() == 400) emit error(Err400); else emit error(ErrNeg); @@ -295,8 +254,8 @@ void FileTransfer::takeConnection(BSConnection *c) connect(d->c, SIGNAL(readyRead()), SLOT(stream_readyRead())); connect(d->c, SIGNAL(error(int)), SLOT(stream_error(int))); - S5BConnection *s5b = dynamic_cast(c); - if(s5b && d->proxy.isValid()) + S5BConnection *s5b = dynamic_cast(c); + if (s5b && d->proxy.isValid()) s5b->setProxy(d->proxy); accepted(); QTimer::singleShot(0, this, SLOT(doAccept())); @@ -318,20 +277,20 @@ void FileTransfer::stream_connectionClosed() void FileTransfer::stream_readyRead() { - QByteArray a = d->c->readAll(); - qlonglong need = d->length - d->sent; - if((qlonglong)a.size() > need) + QByteArray a = d->c->readAll(); + qlonglong need = d->length - d->sent; + if ((qlonglong)a.size() > need) a.resize((uint)need); d->sent += a.size(); -// if(d->sent == d->length) // we close it in stream_connectionClosed. at least for ibb -// reset(); // in other words we wait for another party to close the connection + // if(d->sent == d->length) // we close it in stream_connectionClosed. at least for ibb + // reset(); // in other words we wait for another party to close the connection readyRead(a); } void FileTransfer::stream_bytesWritten(qint64 x) { d->sent += x; - if(d->sent == d->length) + if (d->sent == d->length) reset(); emit bytesWritten(x); } @@ -339,9 +298,9 @@ void FileTransfer::stream_bytesWritten(qint64 x) void FileTransfer::stream_error(int x) { reset(); - if(x == BSConnection::ErrRefused || x == BSConnection::ErrConnect) + if (x == BSConnection::ErrRefused || x == BSConnection::ErrConnect) error(ErrConnect); - else if(x == BSConnection::ErrProxy) + else if (x == BSConnection::ErrProxy) error(ErrProxy); else error(ErrStream); @@ -349,41 +308,36 @@ void FileTransfer::stream_error(int x) void FileTransfer::man_waitForAccept(const FTRequest &req, const QString &streamType) { - d->state = WaitingForAccept; - d->peer = req.from; - d->id = req.id; - d->iq_id = req.iq_id; - d->fname = req.fname; - d->size = req.size; - d->desc = req.desc; + d->state = WaitingForAccept; + d->peer = req.from; + d->id = req.id; + d->iq_id = req.iq_id; + d->fname = req.fname; + d->size = req.size; + d->desc = req.desc; d->rangeSupported = req.rangeSupported; - d->streamType = streamType; - d->thumbnail = req.thumbnail; + d->streamType = streamType; + d->thumbnail = req.thumbnail; } -void FileTransfer::doAccept() -{ - d->c->accept(); -} +void FileTransfer::doAccept() { d->c->accept(); } //---------------------------------------------------------------------------- // FileTransferManager //---------------------------------------------------------------------------- -class FileTransferManager::Private -{ +class FileTransferManager::Private { public: - Client *client; - QList list, incoming; - QStringList streamPriority; - QHash streamMap; - QSet disabledStreamTypes; - JT_PushFT *pft; + Client * client; + QList list, incoming; + QStringList streamPriority; + QHash streamMap; + QSet disabledStreamTypes; + JT_PushFT * pft; }; -FileTransferManager::FileTransferManager(Client *client) -:QObject(client) +FileTransferManager::FileTransferManager(Client *client) : QObject(client) { - d = new Private; + d = new Private; d->client = client; if (client->s5bManager()) { d->streamPriority.append(S5BManager::ns()); @@ -407,10 +361,7 @@ FileTransferManager::~FileTransferManager() delete d; } -Client *FileTransferManager::client() const -{ - return d->client; -} +Client *FileTransferManager::client() const { return d->client; } FileTransfer *FileTransferManager::createTransfer() { @@ -420,7 +371,7 @@ FileTransfer *FileTransferManager::createTransfer() FileTransfer *FileTransferManager::takeIncoming() { - if(d->incoming.isEmpty()) + if (d->incoming.isEmpty()) return nullptr; FileTransfer *ft = d->incoming.takeFirst(); @@ -432,15 +383,14 @@ FileTransfer *FileTransferManager::takeIncoming() bool FileTransferManager::isActive(const FileTransfer *ft) const { - return d->list.contains(const_cast(ft)); + return d->list.contains(const_cast(ft)); } void FileTransferManager::setDisabled(const QString &ns, bool state) { if (state) { d->disabledStreamTypes.insert(ns); - } - else { + } else { d->disabledStreamTypes.remove(ns); } } @@ -448,8 +398,8 @@ void FileTransferManager::setDisabled(const QString &ns, bool state) void FileTransferManager::pft_incoming(const FTRequest &req) { QString streamType; - foreach(const QString& ns, d->streamPriority) { - if(req.streamTypes.contains(ns)) { + foreach (const QString &ns, d->streamPriority) { + if (req.streamTypes.contains(ns)) { BytestreamManager *manager = streamManager(ns); if (manager && manager->isAcceptableSID(req.from, req.id)) { streamType = ns; @@ -458,9 +408,8 @@ void FileTransferManager::pft_incoming(const FTRequest &req) } } - if(streamType.isEmpty()) { - d->pft->respondError(req.from, req.iq_id, Stanza::Error::NotAcceptable, - "No valid stream types"); + if (streamType.isEmpty()) { + d->pft->respondError(req.from, req.iq_id, Stanza::Error::NotAcceptable, "No valid stream types"); return; } @@ -470,7 +419,7 @@ void FileTransferManager::pft_incoming(const FTRequest &req) incomingReady(); } -BytestreamManager* FileTransferManager::streamManager(const QString &ns) const +BytestreamManager *FileTransferManager::streamManager(const QString &ns) const { if (d->disabledStreamTypes.contains(ns)) { return nullptr; @@ -491,8 +440,8 @@ QStringList FileTransferManager::streamPriority() const void FileTransferManager::stream_incomingReady(BSConnection *c) { - foreach(FileTransfer* ft, d->list) { - if(ft->d->needStream && ft->d->peer.compare(c->peer()) && ft->d->id == c->sid()) { + foreach (FileTransfer *ft, d->list) { + if (ft->d->needStream && ft->d->peer.compare(c->peer()) && ft->d->id == c->sid()) { ft->takeConnection(c); return; } @@ -504,17 +453,17 @@ void FileTransferManager::stream_incomingReady(BSConnection *c) QString FileTransferManager::link(FileTransfer *ft) { QString id; - bool found; + bool found; do { found = false; - id = QString("ft_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - foreach (FileTransfer* ft, d->list) { + id = QString("ft_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + foreach (FileTransfer *ft, d->list) { if (ft->d->peer.compare(ft->d->peer) && ft->d->id == id) { found = true; break; } } - } while(found); + } while (found); d->list.append(ft); return id; } @@ -530,42 +479,30 @@ void FileTransferManager::con_reject(FileTransfer *ft) d->pft->respondError(ft->d->peer, ft->d->iq_id, Stanza::Error::Forbidden, "Declined"); } -void FileTransferManager::unlink(FileTransfer *ft) -{ - d->list.removeAll(ft); -} +void FileTransferManager::unlink(FileTransfer *ft) { d->list.removeAll(ft); } //---------------------------------------------------------------------------- // JT_FT //---------------------------------------------------------------------------- -class JT_FT::Private -{ +class JT_FT::Private { public: QDomElement iq; - Jid to; - qlonglong size, rangeOffset, rangeLength; - QString streamType; + Jid to; + qlonglong size, rangeOffset, rangeLength; + QString streamType; QStringList streamTypes; }; -JT_FT::JT_FT(Task *parent) -:Task(parent) -{ - d = new Private; -} +JT_FT::JT_FT(Task *parent) : Task(parent) { d = new Private; } -JT_FT::~JT_FT() -{ - delete d; -} +JT_FT::~JT_FT() { delete d; } -void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, - qlonglong size, const QString &desc, +void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, qlonglong size, const QString &desc, const QStringList &streamTypes, Thumbnail &thumb) { QDomElement iq; - d->to = to; - iq = createIQ(doc(), "set", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement si = doc()->createElementNS("http://jabber.org/protocol/si", "si"); si.setAttribute("id", _id); si.setAttribute("profile", "http://jabber.org/protocol/si/profile/file-transfer"); @@ -573,7 +510,7 @@ void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, QDomElement file = doc()->createElementNS("http://jabber.org/protocol/si/profile/file-transfer", "file"); file.setAttribute("name", fname); file.setAttribute("size", QString::number(size)); - if(!desc.isEmpty()) { + if (!desc.isEmpty()) { QDomElement de = doc()->createElement("desc"); de.appendChild(doc()->createTextNode(desc)); file.appendChild(de); @@ -583,22 +520,22 @@ void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, if (!thumb.data.isEmpty()) { BoBData data = client()->bobManager()->append(thumb.data, thumb.mimeType); - thumb.uri = QLatin1String("cid:") + data.cid(); + thumb.uri = QLatin1String("cid:") + data.cid(); file.appendChild(thumb.toXml(doc())); } si.appendChild(file); QDomElement feature = doc()->createElementNS("http://jabber.org/protocol/feature-neg", "feature"); - QDomElement x = doc()->createElementNS("jabber:x:data", "x"); + QDomElement x = doc()->createElementNS("jabber:x:data", "x"); x.setAttribute("type", "form"); QDomElement field = doc()->createElement("field"); field.setAttribute("var", "stream-method"); field.setAttribute("type", "list-single"); - for(QStringList::ConstIterator it = streamTypes.begin(); it != streamTypes.end(); ++it) { + for (QStringList::ConstIterator it = streamTypes.begin(); it != streamTypes.end(); ++it) { QDomElement option = doc()->createElement("option"); - QDomElement value = doc()->createElement("value"); + QDomElement value = doc()->createElement("value"); value.appendChild(doc()->createTextNode(*it)); option.appendChild(value); field.appendChild(option); @@ -611,38 +548,26 @@ void JT_FT::request(const Jid &to, const QString &_id, const QString &fname, iq.appendChild(si); d->streamTypes = streamTypes; - d->size = size; - d->iq = iq; + d->size = size; + d->iq = iq; } -qlonglong JT_FT::rangeOffset() const -{ - return d->rangeOffset; -} +qlonglong JT_FT::rangeOffset() const { return d->rangeOffset; } -qlonglong JT_FT::rangeLength() const -{ - return d->rangeLength; -} +qlonglong JT_FT::rangeLength() const { return d->rangeLength; } -QString JT_FT::streamType() const -{ - return d->streamType; -} +QString JT_FT::streamType() const { return d->streamType; } -void JT_FT::onGo() -{ - send(d->iq); -} +void JT_FT::onGo() { send(d->iq); } bool JT_FT::take(const QDomElement &x) { - if(!iqVerify(x, d->to, id())) + if (!iqVerify(x, d->to, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { QDomElement si = firstChildElement(x); - if(si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") { + if (si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") { setError(900, ""); return true; } @@ -653,22 +578,22 @@ bool JT_FT::take(const QDomElement &x) qlonglong range_length = 0; QDomElement file = si.elementsByTagName("file").item(0).toElement(); - if(!file.isNull()) { + if (!file.isNull()) { QDomElement range = file.elementsByTagName("range").item(0).toElement(); - if(!range.isNull()) { + if (!range.isNull()) { qlonglong x; - bool ok; - if(range.hasAttribute("offset")) { + bool ok; + if (range.hasAttribute("offset")) { x = range.attribute("offset").toLongLong(&ok); - if(!ok || x < 0) { + if (!ok || x < 0) { setError(900, ""); return true; } range_offset = x; } - if(range.hasAttribute("length")) { + if (range.hasAttribute("length")) { x = range.attribute("length").toLongLong(&ok); - if(!ok || x < 0) { + if (!ok || x < 0) { setError(900, ""); return true; } @@ -677,20 +602,20 @@ bool JT_FT::take(const QDomElement &x) } } - if(range_offset > d->size || (range_length > (d->size - range_offset))) { + if (range_offset > d->size || (range_length > (d->size - range_offset))) { setError(900, ""); return true; } - QString streamtype; + QString streamtype; QDomElement feature = si.elementsByTagName("feature").item(0).toElement(); - if(!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { + if (!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { QDomElement x = feature.elementsByTagName("x").item(0).toElement(); - if(!x.isNull() && x.attribute("type") == "submit") { + if (!x.isNull() && x.attribute("type") == "submit") { QDomElement field = x.elementsByTagName("field").item(0).toElement(); - if(!field.isNull() && field.attribute("var") == "stream-method") { + if (!field.isNull() && field.attribute("var") == "stream-method") { QDomElement value = field.elementsByTagName("value").item(0).toElement(); - if(!value.isNull()) + if (!value.isNull()) streamtype = value.text(); } } @@ -703,10 +628,9 @@ bool JT_FT::take(const QDomElement &x) d->rangeOffset = range_offset; d->rangeLength = range_length; - d->streamType = streamtype; + d->streamType = streamtype; setSuccess(); - } - else { + } else { setError(x); } @@ -716,33 +640,29 @@ bool JT_FT::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_PushFT //---------------------------------------------------------------------------- -JT_PushFT::JT_PushFT(Task *parent) -:Task(parent) -{ -} +JT_PushFT::JT_PushFT(Task *parent) : Task(parent) {} -JT_PushFT::~JT_PushFT() -{ -} +JT_PushFT::~JT_PushFT() {} -void JT_PushFT::respondSuccess(const Jid &to, const QString &id, qlonglong rangeOffset, qlonglong rangeLength, const QString &streamType) +void JT_PushFT::respondSuccess(const Jid &to, const QString &id, qlonglong rangeOffset, qlonglong rangeLength, + const QString &streamType) { QDomElement iq = createIQ(doc(), "result", to.full(), id); QDomElement si = doc()->createElementNS("http://jabber.org/protocol/si", "si"); - if(rangeOffset != 0 || rangeLength != 0) { - QDomElement file = doc()->createElementNS("http://jabber.org/protocol/si/profile/file-transfer", "file"); + if (rangeOffset != 0 || rangeLength != 0) { + QDomElement file = doc()->createElementNS("http://jabber.org/protocol/si/profile/file-transfer", "file"); QDomElement range = doc()->createElement("range"); - if(rangeOffset > 0) + if (rangeOffset > 0) range.setAttribute("offset", QString::number(rangeOffset)); - if(rangeLength > 0) + if (rangeLength > 0) range.setAttribute("length", QString::number(rangeLength)); file.appendChild(range); si.appendChild(file); } QDomElement feature = doc()->createElementNS("http://jabber.org/protocol/feature-neg", "feature"); - QDomElement x = doc()->createElementNS("jabber:x:data", "x"); + QDomElement x = doc()->createElementNS("jabber:x:data", "x"); x.setAttribute("type", "submit"); QDomElement field = doc()->createElement("field"); @@ -759,10 +679,9 @@ void JT_PushFT::respondSuccess(const Jid &to, const QString &id, qlonglong range send(iq); } -void JT_PushFT::respondError(const Jid &to, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str) +void JT_PushFT::respondError(const Jid &to, const QString &id, Stanza::Error::ErrorCond cond, const QString &str) { - QDomElement iq = createIQ(doc(), "error", to.full(), id); + QDomElement iq = createIQ(doc(), "error", to.full(), id); Stanza::Error error(Stanza::Error::Cancel, cond, str); iq.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); send(iq); @@ -771,26 +690,26 @@ void JT_PushFT::respondError(const Jid &to, const QString &id, bool JT_PushFT::take(const QDomElement &e) { // must be an iq-set tag - if(e.tagName() != "iq") + if (e.tagName() != "iq") return false; - if(e.attribute("type") != "set") + if (e.attribute("type") != "set") return false; QDomElement si = firstChildElement(e); - if(si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") + if (si.namespaceURI() != "http://jabber.org/protocol/si" || si.tagName() != "si") return false; - if(si.attribute("profile") != "http://jabber.org/protocol/si/profile/file-transfer") + if (si.attribute("profile") != "http://jabber.org/protocol/si/profile/file-transfer") return false; - Jid from(e.attribute("from")); + Jid from(e.attribute("from")); QString id = si.attribute("id"); QDomElement file = si.elementsByTagName("file").item(0).toElement(); - if(file.isNull()) + if (file.isNull()) return true; QString fname = file.attribute("name"); - if(fname.isEmpty()) { + if (fname.isEmpty()) { respondError(from, id, Stanza::Error::BadRequest, "Bad file name"); return true; } @@ -801,35 +720,36 @@ bool JT_PushFT::take(const QDomElement &e) fname = fi.fileName(); } - bool ok; + bool ok; qlonglong size = file.attribute("size").toLongLong(&ok); - if(!ok || size < 0) { + if (!ok || size < 0) { respondError(from, id, Stanza::Error::BadRequest, "Bad file size"); return true; } - QString desc; + QString desc; QDomElement de = file.elementsByTagName("desc").item(0).toElement(); - if(!de.isNull()) + if (!de.isNull()) desc = de.text(); - bool rangeSupported = false; - QDomElement range = file.elementsByTagName("range").item(0).toElement(); - if(!range.isNull()) + bool rangeSupported = false; + QDomElement range = file.elementsByTagName("range").item(0).toElement(); + if (!range.isNull()) rangeSupported = true; QStringList streamTypes; QDomElement feature = si.elementsByTagName("feature").item(0).toElement(); - if(!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { + if (!feature.isNull() && feature.namespaceURI() == "http://jabber.org/protocol/feature-neg") { QDomElement x = feature.elementsByTagName("x").item(0).toElement(); - if(!x.isNull() /*&& x.attribute("type") == "form"*/) { + if (!x.isNull() /*&& x.attribute("type") == "form"*/) { QDomElement field = x.elementsByTagName("field").item(0).toElement(); - if(!field.isNull() && field.attribute("var") == "stream-method" && field.attribute("type") == "list-single") { + if (!field.isNull() && field.attribute("var") == "stream-method" + && field.attribute("type") == "list-single") { QDomNodeList nl = field.elementsByTagName("option"); - for(int n = 0; n < nl.count(); ++n) { - QDomElement e = nl.item(n).toElement(); + for (int n = 0; n < nl.count(); ++n) { + QDomElement e = nl.item(n).toElement(); QDomElement value = e.elementsByTagName("value").item(0).toElement(); - if(!value.isNull()) + if (!value.isNull()) streamTypes += value.text(); } } @@ -837,15 +757,15 @@ bool JT_PushFT::take(const QDomElement &e) } FTRequest r; - r.from = from; - r.iq_id = e.attribute("id"); - r.id = id; - r.fname = fname; - r.size = size; - r.desc = desc; + r.from = from; + r.iq_id = e.attribute("id"); + r.id = id; + r.fname = fname; + r.size = size; + r.desc = desc; r.rangeSupported = rangeSupported; - r.streamTypes = streamTypes; - r.thumbnail = Thumbnail(file.firstChildElement(QLatin1String("thumbnail"))); + r.streamTypes = streamTypes; + r.thumbnail = Thumbnail(file.firstChildElement(QLatin1String("thumbnail"))); emit incoming(r); return true; diff --git a/src/xmpp/xmpp-im/filetransfer.h b/src/xmpp/xmpp-im/filetransfer.h index 9f2de709..8e903090 100644 --- a/src/xmpp/xmpp-im/filetransfer.h +++ b/src/xmpp/xmpp-im/filetransfer.h @@ -23,167 +23,162 @@ #include "im.h" namespace XMPP { - class BSConnection; - class BytestreamManager; - struct FTRequest; - - /*class AbstractFileTransfer - { - public: - // Receive - virtual Jid peer() const = 0; - virtual QString fileName() const = 0; - virtual qlonglong fileSize() const = 0; - virtual QString description() const { return ""; } - virtual bool rangeSupported() const { return false; } - virtual void accept(qlonglong offset=0, qlonglong length=0) = 0; - };*/ - - class FileTransfer : public QObject /*, public AbstractFileTransfer */ - { - Q_OBJECT - public: - enum { ErrReject, ErrNeg, ErrConnect, ErrProxy, ErrStream, Err400 }; - enum { Idle, Requesting, Connecting, WaitingForAccept, Active }; - ~FileTransfer(); - - FileTransfer *copy() const; - - void setProxy(const Jid &proxy); - - // send - void sendFile(const Jid &to, const QString &fname, qlonglong size, const QString &desc, Thumbnail &thumb); - qlonglong offset() const; - qlonglong length() const; - int dataSizeNeeded() const; - void writeFileData(const QByteArray &a); - const Thumbnail &thumbnail() const; - - // receive - Jid peer() const; - QString fileName() const; - qlonglong fileSize() const; - QString description() const; - bool rangeSupported() const; - void accept(qlonglong offset=0, qlonglong length=0); - - // both - void close(); // reject, or stop sending/receiving - BSConnection *bsConnection() const; // active link - - signals: - void accepted(); // indicates BSConnection has started - void connected(); - void readyRead(const QByteArray &a); - void bytesWritten(qint64); - void error(int); - - private slots: - void ft_finished(); - void stream_connected(); - void stream_connectionClosed(); - void stream_readyRead(); - void stream_bytesWritten(qint64); - void stream_error(int); - void doAccept(); - void reset(); - - private: - class Private; - Private *d; - - friend class FileTransferManager; - FileTransfer(FileTransferManager *, QObject *parent=nullptr); - FileTransfer(const FileTransfer& other); - void man_waitForAccept(const FTRequest &req, const QString &streamType); - void takeConnection(BSConnection *c); - }; - - class FileTransferManager : public QObject - { - Q_OBJECT - public: - FileTransferManager(Client *); - ~FileTransferManager(); - - bool isActive(const FileTransfer *ft) const; - void setDisabled(const QString &ns, bool state = true); - - Client *client() const; - FileTransfer *createTransfer(); - FileTransfer *takeIncoming(); - - signals: - void incomingReady(); - - private slots: - void pft_incoming(const FTRequest &req); - - private: - class Private; - Private *d; +class BSConnection; +class BytestreamManager; +struct FTRequest; - friend class Client; - void stream_incomingReady(BSConnection *); - - friend class FileTransfer; - BytestreamManager* streamManager(const QString &ns) const; - QStringList streamPriority() const; - QString link(FileTransfer *); - void con_accept(FileTransfer *); - void con_reject(FileTransfer *); - void unlink(FileTransfer *); - }; - - class JT_FT : public Task - { - Q_OBJECT - public: - JT_FT(Task *parent); - ~JT_FT(); - - void request(const Jid &to, const QString &id, const QString &fname, - qlonglong size, const QString &desc, - const QStringList &streamTypes, Thumbnail &thumb); - qlonglong rangeOffset() const; - qlonglong rangeLength() const; - QString streamType() const; - - void onGo(); - bool take(const QDomElement &); - - private: - class Private; - Private *d; - }; - - struct FTRequest - { - Jid from; - QString iq_id, id; - QString fname; - qlonglong size; - QString desc; - bool rangeSupported; - QStringList streamTypes; - Thumbnail thumbnail; - }; - class JT_PushFT : public Task - { - Q_OBJECT +/*class AbstractFileTransfer +{ public: - JT_PushFT(Task *parent); - ~JT_PushFT(); - - void respondSuccess(const Jid &to, const QString &id, qlonglong rangeOffset, qlonglong rangeLength, const QString &streamType); - void respondError(const Jid &to, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str); - - bool take(const QDomElement &); - - signals: - void incoming(const FTRequest &req); - }; + // Receive + virtual Jid peer() const = 0; + virtual QString fileName() const = 0; + virtual qlonglong fileSize() const = 0; + virtual QString description() const { return ""; } + virtual bool rangeSupported() const { return false; } + virtual void accept(qlonglong offset=0, qlonglong length=0) = 0; +};*/ + +class FileTransfer : public QObject /*, public AbstractFileTransfer */ +{ + Q_OBJECT +public: + enum { ErrReject, ErrNeg, ErrConnect, ErrProxy, ErrStream, Err400 }; + enum { Idle, Requesting, Connecting, WaitingForAccept, Active }; + ~FileTransfer(); + + FileTransfer *copy() const; + + void setProxy(const Jid &proxy); + + // send + void sendFile(const Jid &to, const QString &fname, qlonglong size, const QString &desc, Thumbnail &thumb); + qlonglong offset() const; + qlonglong length() const; + int dataSizeNeeded() const; + void writeFileData(const QByteArray &a); + const Thumbnail &thumbnail() const; + + // receive + Jid peer() const; + QString fileName() const; + qlonglong fileSize() const; + QString description() const; + bool rangeSupported() const; + void accept(qlonglong offset = 0, qlonglong length = 0); + + // both + void close(); // reject, or stop sending/receiving + BSConnection *bsConnection() const; // active link + +signals: + void accepted(); // indicates BSConnection has started + void connected(); + void readyRead(const QByteArray &a); + void bytesWritten(qint64); + void error(int); + +private slots: + void ft_finished(); + void stream_connected(); + void stream_connectionClosed(); + void stream_readyRead(); + void stream_bytesWritten(qint64); + void stream_error(int); + void doAccept(); + void reset(); + +private: + class Private; + Private *d; + + friend class FileTransferManager; + FileTransfer(FileTransferManager *, QObject *parent = nullptr); + FileTransfer(const FileTransfer &other); + void man_waitForAccept(const FTRequest &req, const QString &streamType); + void takeConnection(BSConnection *c); +}; + +class FileTransferManager : public QObject { + Q_OBJECT +public: + FileTransferManager(Client *); + ~FileTransferManager(); + + bool isActive(const FileTransfer *ft) const; + void setDisabled(const QString &ns, bool state = true); + + Client * client() const; + FileTransfer *createTransfer(); + FileTransfer *takeIncoming(); + +signals: + void incomingReady(); + +private slots: + void pft_incoming(const FTRequest &req); + +private: + class Private; + Private *d; + + friend class Client; + void stream_incomingReady(BSConnection *); + + friend class FileTransfer; + BytestreamManager *streamManager(const QString &ns) const; + QStringList streamPriority() const; + QString link(FileTransfer *); + void con_accept(FileTransfer *); + void con_reject(FileTransfer *); + void unlink(FileTransfer *); +}; + +class JT_FT : public Task { + Q_OBJECT +public: + JT_FT(Task *parent); + ~JT_FT(); + + void request(const Jid &to, const QString &id, const QString &fname, qlonglong size, const QString &desc, + const QStringList &streamTypes, Thumbnail &thumb); + qlonglong rangeOffset() const; + qlonglong rangeLength() const; + QString streamType() const; + + void onGo(); + bool take(const QDomElement &); + +private: + class Private; + Private *d; +}; + +struct FTRequest { + Jid from; + QString iq_id, id; + QString fname; + qlonglong size; + QString desc; + bool rangeSupported; + QStringList streamTypes; + Thumbnail thumbnail; +}; +class JT_PushFT : public Task { + Q_OBJECT +public: + JT_PushFT(Task *parent); + ~JT_PushFT(); + + void respondSuccess(const Jid &to, const QString &id, qlonglong rangeOffset, qlonglong rangeLength, + const QString &streamType); + void respondError(const Jid &to, const QString &id, Stanza::Error::ErrorCond cond, const QString &str); + + bool take(const QDomElement &); + +signals: + void incoming(const FTRequest &req); +}; } // namespace XMPP #endif // XMPP_FILETRANSFER_H diff --git a/src/xmpp/xmpp-im/httpfileupload.cpp b/src/xmpp/xmpp-im/httpfileupload.cpp index 2bf96890..1be7ee0c 100644 --- a/src/xmpp/xmpp-im/httpfileupload.cpp +++ b/src/xmpp/xmpp-im/httpfileupload.cpp @@ -37,25 +37,24 @@ static QLatin1String xmlns_v0_3_1("urn:xmpp:http:upload:0"); //---------------------------------------------------------------------------- // HttpFileUpload //---------------------------------------------------------------------------- -class HttpFileUpload::Private -{ +class HttpFileUpload::Private { public: - HttpFileUpload::State state = State::None; - XMPP::Client *client = nullptr; - QIODevice *sourceDevice = nullptr; - QPointer qnam = nullptr; - quint64 fileSize = 0; - QString fileName; - QString mediaType; - QList httpHosts; + HttpFileUpload::State state = State::None; + XMPP::Client * client = nullptr; + QIODevice * sourceDevice = nullptr; + QPointer qnam = nullptr; + quint64 fileSize = 0; + QString fileName; + QString mediaType; + QList httpHosts; struct { HttpFileUpload::ErrorCode statusCode = HttpFileUpload::ErrorCode::NoError; - QString statusString; - QString getUrl; - QString putUrl; - XEP0363::HttpHeaders putHeaders; - quint64 sizeLimit = 0; + QString statusString; + QString getUrl; + QString putUrl; + XEP0363::HttpHeaders putHeaders; + quint64 sizeLimit = 0; } result; }; @@ -64,22 +63,16 @@ HttpFileUpload::HttpFileUpload(XMPP::Client *client, QIODevice *source, size_t f QObject(client), d(new Private) { - d->client = client; + d->client = client; d->sourceDevice = source; - d->fileName = dstFilename; - d->fileSize = fsize; - d->mediaType = mType; + d->fileName = dstFilename; + d->fileSize = fsize; + d->mediaType = mType; } -HttpFileUpload::~HttpFileUpload() -{ - qDebug("destroying"); -} +HttpFileUpload::~HttpFileUpload() { qDebug("destroying"); } -void HttpFileUpload::setNetworkAccessManager(QNetworkAccessManager *qnam) -{ - d->qnam = qnam; -} +void HttpFileUpload::setNetworkAccessManager(QNetworkAccessManager *qnam) { d->qnam = qnam; } void HttpFileUpload::start() { @@ -109,67 +102,68 @@ void HttpFileUpload::start() featureOptions << (QSet() << xmlns_v0_2_5) << (QSet() << xmlns_v0_3_1); } d->client->serverInfoManager()->queryServiceInfo( - QLatin1String("store"), QLatin1String("file"), - featureOptions, QRegExp("^(upload|http|stor|file|dis|drive).*"), ServerInfoManager::SQ_CheckAllOnNoMatch, - [this](const QList &items) - { - d->httpHosts.clear(); - for (const auto &item: items) { - const QStringList &l = item.features().list(); - XEP0363::version ver = XEP0363::vUnknown; - QString xmlns; - quint64 sizeLimit = 0; - if (l.contains(xmlns_v0_3_1)) { - ver = XEP0363::v0_3_1; - xmlns = xmlns_v0_3_1; - } else if (l.contains(xmlns_v0_2_5)) { - ver = XEP0363::v0_2_5; - xmlns = xmlns_v0_2_5; - } - if (ver != XEP0363::vUnknown) { - QList> hosts; - const XData::Field field = item.registeredExtension(xmlns).getField(QLatin1String("max-file-size")); - if (field.isValid() && field.type() == XData::Field::Field_TextSingle) - sizeLimit = field.value().at(0).toULongLong(); - HttpHost host; - host.ver = ver; - host.jid = item.jid(); - host.sizeLimit = sizeLimit; - QVariant metaProps(d->client->serverInfoManager()->serviceMeta(host.jid, "httpprops")); - if (metaProps.isValid()) { - host.props = HostProps(metaProps.value()); - } else { - host.props = SecureGet | SecurePut; - if (ver == XEP0363::v0_3_1) - host.props |= NewestVer; + QLatin1String("store"), QLatin1String("file"), featureOptions, QRegExp("^(upload|http|stor|file|dis|drive).*"), + ServerInfoManager::SQ_CheckAllOnNoMatch, [this](const QList &items) { + d->httpHosts.clear(); + for (const auto &item : items) { + const QStringList &l = item.features().list(); + XEP0363::version ver = XEP0363::vUnknown; + QString xmlns; + quint64 sizeLimit = 0; + if (l.contains(xmlns_v0_3_1)) { + ver = XEP0363::v0_3_1; + xmlns = xmlns_v0_3_1; + } else if (l.contains(xmlns_v0_2_5)) { + ver = XEP0363::v0_2_5; + xmlns = xmlns_v0_2_5; } - int value = 0; - if (host.props & SecureGet) value += 5; - if (host.props & SecurePut) value += 5; - if (host.props & NewestVer) value += 3; - if (host.props & Failure) value -= 15; - if (!sizeLimit || d->fileSize < sizeLimit) - hosts.append({host,value}); - - // no sorting in preference order. most preferred go first - std::sort(hosts.begin(), hosts.end(), [](const auto &a, const auto &b){ - return a.second > b.second; - }); - for (auto &hp: hosts) { - d->httpHosts.append(hp.first); + if (ver != XEP0363::vUnknown) { + QList> hosts; + const XData::Field field = item.registeredExtension(xmlns).getField(QLatin1String("max-file-size")); + if (field.isValid() && field.type() == XData::Field::Field_TextSingle) + sizeLimit = field.value().at(0).toULongLong(); + HttpHost host; + host.ver = ver; + host.jid = item.jid(); + host.sizeLimit = sizeLimit; + QVariant metaProps(d->client->serverInfoManager()->serviceMeta(host.jid, "httpprops")); + if (metaProps.isValid()) { + host.props = HostProps(metaProps.value()); + } else { + host.props = SecureGet | SecurePut; + if (ver == XEP0363::v0_3_1) + host.props |= NewestVer; + } + int value = 0; + if (host.props & SecureGet) + value += 5; + if (host.props & SecurePut) + value += 5; + if (host.props & NewestVer) + value += 3; + if (host.props & Failure) + value -= 15; + if (!sizeLimit || d->fileSize < sizeLimit) + hosts.append({ host, value }); + + // no sorting in preference order. most preferred go first + std::sort(hosts.begin(), hosts.end(), + [](const auto &a, const auto &b) { return a.second > b.second; }); + for (auto &hp : hosts) { + d->httpHosts.append(hp.first); + } } } - } - //d->currentHost = d->httpHosts.begin(); - d->client->httpFileUploadManager()->setDiscoHosts(d->httpHosts); - if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services - d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; - d->result.statusString = "No suitable http upload services were found"; - done(State::Error); - } else { - tryNextServer(); - } - }); + // d->currentHost = d->httpHosts.begin(); + d->client->httpFileUploadManager()->setDiscoHosts(d->httpHosts); + if (d->httpHosts.isEmpty()) { // if empty as the last resort check all services + d->result.statusCode = HttpFileUpload::ErrorCode::NoUploadService; + d->result.statusString = "No suitable http upload services were found"; + done(State::Error); + } else { + tryNextServer(); + } + }); } void HttpFileUpload::tryNextServer() @@ -182,96 +176,89 @@ void HttpFileUpload::tryNextServer() done(State::Error); return; } - HttpHost host = d->httpHosts.takeFirst(); + HttpHost host = d->httpHosts.takeFirst(); d->result.sizeLimit = host.sizeLimit; - auto jt = new JT_HTTPFileUpload(d->client->rootTask()); - connect(jt, &JT_HTTPFileUpload::finished, this, [this, jt, host]() mutable { - if (!jt->success()) { - host.props |= Failure; - int code = jt->statusCode(); - if (code < 300) { - code++; // ErrDisc and ErrTimeout. but 0 code is already occupated + auto jt = new JT_HTTPFileUpload(d->client->rootTask()); + connect( + jt, &JT_HTTPFileUpload::finished, this, + [this, jt, host]() mutable { + if (!jt->success()) { + host.props |= Failure; + int code = jt->statusCode(); + if (code < 300) { + code++; // ErrDisc and ErrTimeout. but 0 code is already occupated + } + d->result.statusCode = static_cast(jt->statusCode()); + d->result.statusString = jt->statusString(); + d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props)); + if (d->httpHosts.isEmpty()) + done(State::Error); + else + tryNextServer(); + return; } - d->result.statusCode = static_cast(jt->statusCode()); - d->result.statusString = jt->statusString(); - d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props)); - if (d->httpHosts.isEmpty()) - done(State::Error); + + d->result.getUrl = jt->url(JT_HTTPFileUpload::GetUrl); + d->result.putUrl = jt->url(JT_HTTPFileUpload::PutUrl); + d->result.putHeaders = jt->headers(); + if (d->result.getUrl.startsWith("https://")) + host.props |= SecureGet; else - tryNextServer(); - return; - } + host.props &= ~SecureGet; + if (d->result.putUrl.startsWith("https://")) + host.props |= SecurePut; + else + host.props &= ~SecurePut; + host.props &= ~Failure; - d->result.getUrl = jt->url(JT_HTTPFileUpload::GetUrl); - d->result.putUrl = jt->url(JT_HTTPFileUpload::PutUrl); - d->result.putHeaders = jt->headers(); - if (d->result.getUrl.startsWith("https://")) - host.props |= SecureGet; - else - host.props &= ~SecureGet; - if (d->result.putUrl.startsWith("https://")) - host.props |= SecurePut; - else - host.props &= ~SecurePut; - host.props &= ~Failure; - - d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props)); - - if (!d->qnam) { // w/o network access manager, it's not more than getting slots - done(State::Success); - return; - } + d->client->serverInfoManager()->setServiceMeta(host.jid, QLatin1String("httpprops"), int(host.props)); - setState(State::HttpRequest); - // time for a http request - QNetworkRequest req(d->result.putUrl); - for (auto &h: d->result.putHeaders) { - req.setRawHeader(h.name.toLatin1(), h.value.toLatin1()); - } - auto reply = d->qnam->put(req, d->sourceDevice); - connect(reply, &QNetworkReply::uploadProgress, this, &HttpFileUpload::progress); - connect(reply, &QNetworkReply::finished, this, [this, reply](){ - if (reply->error() == QNetworkReply::NoError) { + if (!d->qnam) { // w/o network access manager, it's not more than getting slots done(State::Success); - } else { - d->result.statusCode = ErrorCode::HttpFailed; - d->result.statusString = reply->errorString(); - qDebug("http upload failed: %s", qPrintable(d->result.statusString)); - if (d->httpHosts.isEmpty()) - done(State::Error); - else - tryNextServer(); + return; } - reply->deleteLater(); - }); - }, Qt::QueuedConnection); + setState(State::HttpRequest); + // time for a http request + QNetworkRequest req(d->result.putUrl); + for (auto &h : d->result.putHeaders) { + req.setRawHeader(h.name.toLatin1(), h.value.toLatin1()); + } + auto reply = d->qnam->put(req, d->sourceDevice); + connect(reply, &QNetworkReply::uploadProgress, this, &HttpFileUpload::progress); + connect(reply, &QNetworkReply::finished, this, [this, reply]() { + if (reply->error() == QNetworkReply::NoError) { + done(State::Success); + } else { + d->result.statusCode = ErrorCode::HttpFailed; + d->result.statusString = reply->errorString(); + qDebug("http upload failed: %s", qPrintable(d->result.statusString)); + if (d->httpHosts.isEmpty()) + done(State::Error); + else + tryNextServer(); + } + reply->deleteLater(); + }); + }, + Qt::QueuedConnection); jt->request(host.jid, d->fileName, d->fileSize, d->mediaType, host.ver); jt->go(true); } -bool HttpFileUpload::success() const -{ - return d->state == State::Success; -} +bool HttpFileUpload::success() const { return d->state == State::Success; } -HttpFileUpload::ErrorCode HttpFileUpload::statusCode() const -{ - return d->result.statusCode; -} +HttpFileUpload::ErrorCode HttpFileUpload::statusCode() const { return d->result.statusCode; } -const QString & HttpFileUpload::statusString() const -{ - return d->result.statusString; -} +const QString &HttpFileUpload::statusString() const { return d->result.statusString; } HttpFileUpload::HttpSlot HttpFileUpload::getHttpSlot() { HttpSlot slot; if (d->state == State::Success) { - slot.get.url = d->result.getUrl; - slot.put.url = d->result.putUrl; - slot.put.headers = d->result.putHeaders; + slot.get.url = d->result.getUrl; + slot.put.url = d->result.putUrl; + slot.put.headers = d->result.putHeaders; slot.limits.fileSize = d->result.sizeLimit; } return slot; @@ -296,46 +283,44 @@ void HttpFileUpload::done(State state) //---------------------------------------------------------------------------- // JT_HTTPFileUpload //---------------------------------------------------------------------------- -class JT_HTTPFileUpload::Private -{ +class JT_HTTPFileUpload::Private { public: - Jid to; - QDomElement iq; - QStringList urls; - XEP0363::version ver; + Jid to; + QDomElement iq; + QStringList urls; + XEP0363::version ver; XEP0363::HttpHeaders headers; }; -JT_HTTPFileUpload::JT_HTTPFileUpload(Task *parent) - : Task(parent) +JT_HTTPFileUpload::JT_HTTPFileUpload(Task *parent) : Task(parent) { - d = new Private; + d = new Private; d->ver = XEP0363::vUnknown; d->urls << QString() << QString(); } -JT_HTTPFileUpload::~JT_HTTPFileUpload() -{ - delete d; -} +JT_HTTPFileUpload::~JT_HTTPFileUpload() { delete d; } -void JT_HTTPFileUpload::request(const Jid &to, const QString &fname, - quint64 fsize, const QString &ftype, XEP0363::version ver) +void JT_HTTPFileUpload::request(const Jid &to, const QString &fname, quint64 fsize, const QString &ftype, + XEP0363::version ver) { QString ns; - switch (ver) - { - case XEP0363::v0_2_5: ns = xmlns_v0_2_5; break; - case XEP0363::v0_3_1: ns = xmlns_v0_3_1; break; - default: return; + switch (ver) { + case XEP0363::v0_2_5: + ns = xmlns_v0_2_5; + break; + case XEP0363::v0_3_1: + ns = xmlns_v0_3_1; + break; + default: + return; } - d->to = to; - d->ver = ver; - d->iq = createIQ(doc(), "get", to.full(), id()); + d->to = to; + d->ver = ver; + d->iq = createIQ(doc(), "get", to.full(), id()); QDomElement req = doc()->createElementNS(ns, "request"); - switch (ver) - { + switch (ver) { case XEP0363::v0_2_5: ns = xmlns_v0_2_5; req.appendChild(textTag(doc(), "filename", fname)); @@ -358,15 +343,9 @@ void JT_HTTPFileUpload::request(const Jid &to, const QString &fname, d->iq.appendChild(req); } -QString JT_HTTPFileUpload::url(UrlType t) const -{ - return d->urls.value(t); -} +QString JT_HTTPFileUpload::url(UrlType t) const { return d->urls.value(t); } -XEP0363::HttpHeaders JT_HTTPFileUpload::headers() const -{ - return d->headers; -} +XEP0363::HttpHeaders JT_HTTPFileUpload::headers() const { return d->headers; } void JT_HTTPFileUpload::onGo() { @@ -384,36 +363,34 @@ bool JT_HTTPFileUpload::take(const QDomElement &e) return true; } - bool correct_xmlns = false; - QString getUrl, putUrl; + bool correct_xmlns = false; + QString getUrl, putUrl; XEP0363::HttpHeaders headers; - const QDomElement &slot = e.firstChildElement("slot"); + const QDomElement & slot = e.firstChildElement("slot"); if (!slot.isNull()) { const QDomElement &get = slot.firstChildElement("get"); const QDomElement &put = slot.firstChildElement("put"); - switch (d->ver) - { + switch (d->ver) { case XEP0363::v0_2_5: correct_xmlns = slot.namespaceURI() == xmlns_v0_2_5; - getUrl = tagContent(get); - putUrl = tagContent(put); + getUrl = tagContent(get); + putUrl = tagContent(put); break; case XEP0363::v0_3_1: correct_xmlns = slot.namespaceURI() == xmlns_v0_3_1; - getUrl = get.attribute("url"); + getUrl = get.attribute("url"); if (!put.isNull()) { - putUrl = put.attribute("url"); + putUrl = put.attribute("url"); QDomElement he = put.firstChildElement("header"); while (!he.isNull()) { // only next are allowed: Authorization, Cookie, Expires QString header = he.attribute("name").trimmed().remove(QLatin1Char('\n')); - QString value = he.text().trimmed().remove(QLatin1Char('\n')); - if (!value.isEmpty() && - (header.compare(QLatin1String("Authorization"), Qt::CaseInsensitive) == 0 || - header.compare(QLatin1String("Cookie"), Qt::CaseInsensitive) == 0 || - header.compare(QLatin1String("Expires"), Qt::CaseInsensitive) == 0)) - { - headers.append(XEP0363::HttpHeader{header, value}); + QString value = he.text().trimmed().remove(QLatin1Char('\n')); + if (!value.isEmpty() + && (header.compare(QLatin1String("Authorization"), Qt::CaseInsensitive) == 0 + || header.compare(QLatin1String("Cookie"), Qt::CaseInsensitive) == 0 + || header.compare(QLatin1String("Expires"), Qt::CaseInsensitive) == 0)) { + headers.append(XEP0363::HttpHeader { header, value }); } he = he.nextSiblingElement("header"); } @@ -432,46 +409,35 @@ bool JT_HTTPFileUpload::take(const QDomElement &e) d->urls[PutUrl] = putUrl; d->headers = headers; setSuccess(); - } - else + } else setError(ErrInvalidResponse, "Either `put` or `get` URL is missing in the server's reply."); return true; } class HttpFileUploadManager::Private { public: - Client *client = nullptr; - QPointer qnam; - int discoStatus = 0; - QList discoHosts; - bool externalQnam = false; + Client * client = nullptr; + QPointer qnam; + int discoStatus = 0; + QList discoHosts; + bool externalQnam = false; QLinkedList hosts; }; -HttpFileUploadManager::HttpFileUploadManager(Client *parent) : - QObject(parent), - d(new Private) -{ - d->client = parent; -} +HttpFileUploadManager::HttpFileUploadManager(Client *parent) : QObject(parent), d(new Private) { d->client = parent; } -HttpFileUploadManager::~HttpFileUploadManager() -{ - delete d; -} +HttpFileUploadManager::~HttpFileUploadManager() { delete d; } -int HttpFileUploadManager::discoveryStatus() const -{ - return d->discoStatus; -} +int HttpFileUploadManager::discoveryStatus() const { return d->discoStatus; } void HttpFileUploadManager::setNetworkAccessManager(QNetworkAccessManager *qnam) { d->externalQnam = true; - d->qnam = qnam; + d->qnam = qnam; } -HttpFileUpload* HttpFileUploadManager::upload(const QString &srcFilename, const QString &dstFilename, const QString &mType) +HttpFileUpload *HttpFileUploadManager::upload(const QString &srcFilename, const QString &dstFilename, + const QString &mType) { auto f = new QFile(srcFilename); f->open(QIODevice::ReadOnly); @@ -480,22 +446,20 @@ HttpFileUpload* HttpFileUploadManager::upload(const QString &srcFilename, const return hfu; } -HttpFileUpload* HttpFileUploadManager::upload(QIODevice *source, size_t fsize, const QString &dstFilename, const QString &mType) +HttpFileUpload *HttpFileUploadManager::upload(QIODevice *source, size_t fsize, const QString &dstFilename, + const QString &mType) { - auto hfu = new HttpFileUpload(d->client, source, fsize, dstFilename, mType); - QNetworkAccessManager *qnam = d->externalQnam? d->qnam.data() : d->client->networkAccessManager(); + auto hfu = new HttpFileUpload(d->client, source, fsize, dstFilename, mType); + QNetworkAccessManager *qnam = d->externalQnam ? d->qnam.data() : d->client->networkAccessManager(); hfu->setNetworkAccessManager(qnam); QMetaObject::invokeMethod(hfu, "start", Qt::QueuedConnection); return hfu; } -const QList &HttpFileUploadManager::discoHosts() const -{ - return d->discoHosts; -} +const QList &HttpFileUploadManager::discoHosts() const { return d->discoHosts; } void HttpFileUploadManager::setDiscoHosts(const QList &hosts) { - d->discoStatus = hosts.size()? DiscoFound : DiscoNotFound; - d->discoHosts = hosts; + d->discoStatus = hosts.size() ? DiscoFound : DiscoNotFound; + d->discoHosts = hosts; } diff --git a/src/xmpp/xmpp-im/httpfileupload.h b/src/xmpp/xmpp-im/httpfileupload.h index 3d923bba..1d2f2705 100644 --- a/src/xmpp/xmpp-im/httpfileupload.h +++ b/src/xmpp/xmpp-im/httpfileupload.h @@ -28,21 +28,23 @@ class QNetworkAccessManager; namespace XMPP { - namespace XEP0363 { - enum version { vUnknown, v0_2_5, v0_3_1 }; - struct HttpHeader { QString name; QString value; }; - typedef QList HttpHeaders; - } - -class HttpFileUpload : public QObject -{ +namespace XEP0363 { + enum version { vUnknown, v0_2_5, v0_3_1 }; + struct HttpHeader { + QString name; + QString value; + }; + typedef QList HttpHeaders; +} + +class HttpFileUpload : public QObject { Q_OBJECT public: enum HostPropFlag { SecureGet = 1, // 0.2.5 of the xep didn't require that SecurePut = 2, // 0.2.5 of the xep didn't require that NewestVer = 4, - Failure = 8 // had some failure (no/unexpected response to slot request, early http errors) + Failure = 8 // had some failure (no/unexpected response to slot request, early http errors) }; Q_DECLARE_FLAGS(HostProps, HostPropFlag) @@ -60,7 +62,7 @@ class HttpFileUpload : public QObject QString url; } get; struct { - QString url; + QString url; QList headers; } put; struct { @@ -70,9 +72,9 @@ class HttpFileUpload : public QObject struct HttpHost { XEP0363::version ver; - Jid jid; - quint64 sizeLimit; - HostProps props; + Jid jid; + quint64 sizeLimit; + HostProps props; }; HttpFileUpload(Client *client, QIODevice *source, size_t fsize, const QString &dstFilename, @@ -90,10 +92,10 @@ class HttpFileUpload : public QObject */ void setNetworkAccessManager(QNetworkAccessManager *qnam); - bool success() const; - ErrorCode statusCode() const; - const QString & statusString() const; - HttpSlot getHttpSlot(); + bool success() const; + ErrorCode statusCode() const; + const QString &statusString() const; + HttpSlot getHttpSlot(); public slots: void start(); @@ -118,18 +120,18 @@ public slots: }; Q_DECLARE_OPERATORS_FOR_FLAGS(HttpFileUpload::HostProps) -class JT_HTTPFileUpload : public Task -{ +class JT_HTTPFileUpload : public Task { Q_OBJECT public: enum UrlType { GetUrl = 0, PutUrl = 1 }; - enum { ErrInvalidResponse = int(HttpFileUpload::ErrorCode::SlotReceiveFailed) - 1 }; // -1 to be mapped to ErrDisc, ErrTimeout, ... + enum { + ErrInvalidResponse = int(HttpFileUpload::ErrorCode::SlotReceiveFailed) - 1 + }; // -1 to be mapped to ErrDisc, ErrTimeout, ... JT_HTTPFileUpload(Task *parent); ~JT_HTTPFileUpload(); - void request(const Jid &to, const QString &fname, - quint64 fsize, const QString &ftype, XEP0363::version ver); + void request(const Jid &to, const QString &fname, quint64 fsize, const QString &ftype, XEP0363::version ver); QString url(UrlType t) const; XEP0363::HttpHeaders headers() const; @@ -141,17 +143,13 @@ class JT_HTTPFileUpload : public Task Private *d; }; -class HttpFileUploadManager : public QObject -{ +class HttpFileUploadManager : public QObject { Q_OBJECT public: - enum { - DiscoNone = 0x0, - DiscoNotFound = 0x1, - DiscoFound = 0x2 - }; + enum { DiscoNone = 0x0, DiscoNotFound = 0x1, DiscoFound = 0x2 }; - typedef std::function Callback; // params: success, detail. where detail could be a "get" url + typedef std::function + Callback; // params: success, detail. where detail could be a "get" url HttpFileUploadManager(Client *parent); ~HttpFileUploadManager(); @@ -178,7 +176,7 @@ class HttpFileUploadManager : public QObject * @param mType meta type. image/png for example * @return returns a handler object which will signal "finished" when ready */ - HttpFileUpload* upload(const QString &srcFilename, const QString &dstFilename = QString(), + HttpFileUpload *upload(const QString &srcFilename, const QString &dstFilename = QString(), const QString &mType = QString()); /** @@ -189,13 +187,13 @@ class HttpFileUploadManager : public QObject * @param mType - meta type * @return returns a handler object which will signal "finished" when ready */ - HttpFileUpload* upload(QIODevice *source, size_t fsize, const QString &dstFilename, + HttpFileUpload *upload(QIODevice *source, size_t fsize, const QString &dstFilename, const QString &mType = QString()); private: friend class HttpFileUpload; const QList &discoHosts() const; - void setDiscoHosts(const QList &hosts); + void setDiscoHosts(const QList &hosts); class Private; Private *d; diff --git a/src/xmpp/xmpp-im/im.h b/src/xmpp/xmpp-im/im.h index 2842e30a..c2cc2814 100644 --- a/src/xmpp/xmpp-im/im.h +++ b/src/xmpp/xmpp-im/im.h @@ -52,79 +52,76 @@ #include namespace XMPP { - typedef QList AgentList; - typedef QList DiscoList; - - class FormField - { - public: - enum { username, nick, password, name, first, last, email, address, city, state, zip, phone, url, date, misc }; - FormField(const QString &type="", const QString &value=""); - ~FormField(); - - int type() const; - QString fieldName() const; - QString realName() const; - bool isSecret() const; - const QString & value() const; - void setType(int); - bool setType(const QString &); - void setValue(const QString &); - - private: - int tagNameToType(const QString &) const; - QString typeToTagName(int) const; - - int v_type; - QString v_value; - - class Private; - Private *d = nullptr; - }; - - class Form : public QList - { - public: - Form(const Jid &j=""); - ~Form(); - - Jid jid() const; - QString instructions() const; - QString key() const; - void setJid(const Jid &); - void setInstructions(const QString &); - void setKey(const QString &); - - private: - Jid v_jid; - QString v_instructions, v_key; - - class Private; - Private *d = nullptr; - }; - - class SearchResult - { - public: - SearchResult(const Jid &jid=""); - ~SearchResult(); - - const Jid & jid() const; - const QString & nick() const; - const QString & first() const; - const QString & last() const; - const QString & email() const; - - void setJid(const Jid &); - void setNick(const QString &); - void setFirst(const QString &); - void setLast(const QString &); - void setEmail(const QString &); - - private: - Jid v_jid; - QString v_nick, v_first, v_last, v_email; - }; +typedef QList AgentList; +typedef QList DiscoList; + +class FormField { +public: + enum { username, nick, password, name, first, last, email, address, city, state, zip, phone, url, date, misc }; + FormField(const QString &type = "", const QString &value = ""); + ~FormField(); + + int type() const; + QString fieldName() const; + QString realName() const; + bool isSecret() const; + const QString &value() const; + void setType(int); + bool setType(const QString &); + void setValue(const QString &); + +private: + int tagNameToType(const QString &) const; + QString typeToTagName(int) const; + + int v_type; + QString v_value; + + class Private; + Private *d = nullptr; +}; + +class Form : public QList { +public: + Form(const Jid &j = ""); + ~Form(); + + Jid jid() const; + QString instructions() const; + QString key() const; + void setJid(const Jid &); + void setInstructions(const QString &); + void setKey(const QString &); + +private: + Jid v_jid; + QString v_instructions, v_key; + + class Private; + Private *d = nullptr; +}; + +class SearchResult { +public: + SearchResult(const Jid &jid = ""); + ~SearchResult(); + + const Jid & jid() const; + const QString &nick() const; + const QString &first() const; + const QString &last() const; + const QString &email() const; + + void setJid(const Jid &); + void setNick(const QString &); + void setFirst(const QString &); + void setLast(const QString &); + void setEmail(const QString &); + +private: + Jid v_jid; + QString v_nick, v_first, v_last, v_email; +}; } // namespace XMPP #endif // XMPP_IM_H diff --git a/src/xmpp/xmpp-im/jingle-ft.cpp b/src/xmpp/xmpp-im/jingle-ft.cpp index 3c6690d8..0411fabd 100644 --- a/src/xmpp/xmpp-im/jingle-ft.cpp +++ b/src/xmpp/xmpp-im/jingle-ft.cpp @@ -27,1051 +27,922 @@ #include #include -namespace XMPP { -namespace Jingle { - namespace FileTransfer { - const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); - const QString AMPLITUDES_NS = QStringLiteral("urn:audio:amplitudes"); - - // tags - static const QString AMPLITUDES_TAG = QStringLiteral("amplitudes"); - static const QString FILETAG = QStringLiteral("file"); - static const QString DATE_TAG = QStringLiteral("date"); - static const QString DESC_TAG = QStringLiteral("desc"); - static const QString MEDIA_TYPE_TAG = QStringLiteral("media-type"); - static const QString NAME_TAG = QStringLiteral("name"); - static const QString SIZE_TAG = QStringLiteral("size"); - static const QString RANGE_TAG = QStringLiteral("range"); - static const QString THUMBNAIL_TAG = QStringLiteral("thumbnail"); - - QDomElement Range::toXml(QDomDocument *doc) const - { - auto r = doc->createElement(RANGE_TAG); - if (length) { - r.setAttribute(QStringLiteral("length"), QString::number(length)); - } - if (offset) { - r.setAttribute(QStringLiteral("offset"), QString::number(offset)); - } - for (auto const &h : hashes) { - auto hel = h.toXml(doc); - if (!hel.isNull()) { - r.appendChild(hel); +namespace XMPP { namespace Jingle { namespace FileTransfer { + const QString NS = QStringLiteral("urn:xmpp:jingle:apps:file-transfer:5"); + const QString AMPLITUDES_NS = QStringLiteral("urn:audio:amplitudes"); + + // tags + static const QString AMPLITUDES_TAG = QStringLiteral("amplitudes"); + static const QString FILETAG = QStringLiteral("file"); + static const QString DATE_TAG = QStringLiteral("date"); + static const QString DESC_TAG = QStringLiteral("desc"); + static const QString MEDIA_TYPE_TAG = QStringLiteral("media-type"); + static const QString NAME_TAG = QStringLiteral("name"); + static const QString SIZE_TAG = QStringLiteral("size"); + static const QString RANGE_TAG = QStringLiteral("range"); + static const QString THUMBNAIL_TAG = QStringLiteral("thumbnail"); + + QDomElement Range::toXml(QDomDocument *doc) const + { + auto r = doc->createElement(RANGE_TAG); + if (length) { + r.setAttribute(QStringLiteral("length"), QString::number(length)); + } + if (offset) { + r.setAttribute(QStringLiteral("offset"), QString::number(offset)); + } + for (auto const &h : hashes) { + auto hel = h.toXml(doc); + if (!hel.isNull()) { + r.appendChild(hel); + } + } + return r; + } + + //---------------------------------------------------------------------------- + // File + //---------------------------------------------------------------------------- + class File::Private : public QSharedData { + public: + QDateTime date; + QString mediaType; + QString name; + QString desc; + qint64 size = 0; + Range range; + bool rangeSupported = false; + bool hasSize = false; + QList hashes; + Thumbnail thumbnail; + QByteArray amplitudes; + }; + + File::File() {} + + File::~File() {} + + File &File::operator=(const File &other) + { + d = other.d; + return *this; + } + + File::File(const File &other) : d(other.d) {} + + File::File(const QDomElement &file) + { + QDateTime date; + QString mediaType; + QString name; + QString desc; + size_t size = 0; + bool rangeSupported = false; + bool hasSize = false; + Range range; + QList hashes; + Thumbnail thumbnail; + QByteArray amplitudes; + + bool ok; + + for (QDomElement ce = file.firstChildElement(); !ce.isNull(); ce = ce.nextSiblingElement()) { + + if (ce.tagName() == DATE_TAG) { + date = QDateTime::fromString(ce.text().left(19), Qt::ISODate); + if (!date.isValid()) { + return; } - } - return r; - } - //---------------------------------------------------------------------------- - // File - //---------------------------------------------------------------------------- - class File::Private : public QSharedData { - public: - QDateTime date; - QString mediaType; - QString name; - QString desc; - qint64 size = 0; - Range range; - bool rangeSupported = false; - bool hasSize = false; - QList hashes; - Thumbnail thumbnail; - QByteArray amplitudes; - }; + } else if (ce.tagName() == MEDIA_TYPE_TAG) { + mediaType = ce.text(); - File::File() - { - } + } else if (ce.tagName() == NAME_TAG) { + name = ce.text(); - File::~File() - { - } - - File &File::operator=(const File &other) - { - d = other.d; - return *this; - } - - File::File(const File &other) : - d(other.d) - { - } - - File::File(const QDomElement &file) - { - QDateTime date; - QString mediaType; - QString name; - QString desc; - size_t size = 0; - bool rangeSupported = false; - bool hasSize = false; - Range range; - QList hashes; - Thumbnail thumbnail; - QByteArray amplitudes; - - bool ok; - - for (QDomElement ce = file.firstChildElement(); - !ce.isNull(); ce = ce.nextSiblingElement()) { - - if (ce.tagName() == DATE_TAG) { - date = QDateTime::fromString(ce.text().left(19), Qt::ISODate); - if (!date.isValid()) { - return; - } - - } else if (ce.tagName() == MEDIA_TYPE_TAG) { - mediaType = ce.text(); - - } else if (ce.tagName() == NAME_TAG) { - name = ce.text(); + } else if (ce.tagName() == SIZE_TAG) { + size = ce.text().toULongLong(&ok); + if (!ok) { + return; + } + hasSize = true; - } else if (ce.tagName() == SIZE_TAG) { - size = ce.text().toULongLong(&ok); + } else if (ce.tagName() == RANGE_TAG) { + if (ce.hasAttribute(QLatin1String("offset"))) { + range.offset = ce.attribute(QLatin1String("offset")).toULongLong(&ok); if (!ok) { return; } - hasSize = true; - - } else if (ce.tagName() == RANGE_TAG) { - if (ce.hasAttribute(QLatin1String("offset"))) { - range.offset = ce.attribute(QLatin1String("offset")).toULongLong(&ok); - if (!ok) { - return; - } - } - if (ce.hasAttribute(QLatin1String("length"))) { - range.length = ce.attribute(QLatin1String("length")).toULongLong(&ok); - if (!ok || !range.length) { // length should absent if we need to read till end of file. 0-length is nonsense - return; - } + } + if (ce.hasAttribute(QLatin1String("length"))) { + range.length = ce.attribute(QLatin1String("length")).toULongLong(&ok); + if (!ok || !range.length) { // length should absent if we need to read till end of file. 0-length is + // nonsense + return; } - QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); - for (; !hashEl.isNull(); hashEl = hashEl.nextSiblingElement(QLatin1String("hash"))) { - if (hashEl.namespaceURI() == HASH_NS) { - auto hash = Hash(hashEl); - if (hash.type() == Hash::Type::Unknown) { - continue; - } - range.hashes.append(hash); + } + QDomElement hashEl = ce.firstChildElement(QLatin1String("hash")); + for (; !hashEl.isNull(); hashEl = hashEl.nextSiblingElement(QLatin1String("hash"))) { + if (hashEl.namespaceURI() == HASH_NS) { + auto hash = Hash(hashEl); + if (hash.type() == Hash::Type::Unknown) { + continue; } + range.hashes.append(hash); } - rangeSupported = true; + } + rangeSupported = true; - } else if (ce.tagName() == DESC_TAG) { - desc = ce.text(); + } else if (ce.tagName() == DESC_TAG) { + desc = ce.text(); - } else if (ce.tagName() == QLatin1String("hash")) { - if (ce.namespaceURI() == HASH_NS) { - Hash h(ce); - if (h.type() == Hash::Type::Unknown) { - return; - } - hashes.append(h); + } else if (ce.tagName() == QLatin1String("hash")) { + if (ce.namespaceURI() == HASH_NS) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { + return; } + hashes.append(h); + } - } else if (ce.tagName() == QLatin1String("hash-used")) { - if (ce.namespaceURI() == HASH_NS) { - Hash h(ce); - if (h.type() == Hash::Type::Unknown) { - return; - } - hashes.append(h); + } else if (ce.tagName() == QLatin1String("hash-used")) { + if (ce.namespaceURI() == HASH_NS) { + Hash h(ce); + if (h.type() == Hash::Type::Unknown) { + return; } - - } else if (ce.tagName() == THUMBNAIL_TAG) { - thumbnail = Thumbnail(ce); - } else if (ce.tagName() == AMPLITUDES_TAG && ce.namespaceURI() == AMPLITUDES_NS) { - amplitudes = QByteArray::fromBase64(ce.text().toLatin1()); + hashes.append(h); } - } - auto p = new Private; - p->date = date; - p->mediaType = mediaType; - p->name = name; - p->desc = desc; - p->size = size; - p->rangeSupported = rangeSupported; - p->hasSize = hasSize; - p->range = range; - p->hashes = hashes; - p->thumbnail = thumbnail; - p->amplitudes = amplitudes; - - d = p; + } else if (ce.tagName() == THUMBNAIL_TAG) { + thumbnail = Thumbnail(ce); + } else if (ce.tagName() == AMPLITUDES_TAG && ce.namespaceURI() == AMPLITUDES_NS) { + amplitudes = QByteArray::fromBase64(ce.text().toLatin1()); + } } - QDomElement File::toXml(QDomDocument *doc) const - { - if (!isValid() || d->hashes.isEmpty()) { - return QDomElement(); - } - QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); - if (d->date.isValid()) { - el.appendChild(XMLHelper::textTag(*doc, DATE_TAG, d->date.toString(Qt::ISODate))); - } - if (d->desc.size()) { - el.appendChild(XMLHelper::textTag(*doc, DESC_TAG, d->desc)); - } - for (const auto &h : d->hashes) { - el.appendChild(h.toXml(doc)); - } - if (d->mediaType.size()) { - el.appendChild(XMLHelper::textTag(*doc, MEDIA_TYPE_TAG, d->mediaType)); - } - if (d->name.size()) { - el.appendChild(XMLHelper::textTag(*doc, NAME_TAG, d->name)); - } - if (d->hasSize) { - el.appendChild(XMLHelper::textTag(*doc, SIZE_TAG, d->size)); - } - if (d->rangeSupported || d->range.isValid()) { - el.appendChild(d->range.toXml(doc)); - } - if (d->thumbnail.isValid()) { - el.appendChild(d->thumbnail.toXml(doc)); - } - if (d->amplitudes.size()) { - el.appendChild(XMLHelper::textTagNS(doc, AMPLITUDES_NS, AMPLITUDES_TAG, d->amplitudes)); - } - return el; + auto p = new Private; + p->date = date; + p->mediaType = mediaType; + p->name = name; + p->desc = desc; + p->size = size; + p->rangeSupported = rangeSupported; + p->hasSize = hasSize; + p->range = range; + p->hashes = hashes; + p->thumbnail = thumbnail; + p->amplitudes = amplitudes; + + d = p; + } + + QDomElement File::toXml(QDomDocument *doc) const + { + if (!isValid() || d->hashes.isEmpty()) { + return QDomElement(); + } + QDomElement el = doc->createElementNS(NS, QStringLiteral("file")); + if (d->date.isValid()) { + el.appendChild(XMLHelper::textTag(*doc, DATE_TAG, d->date.toString(Qt::ISODate))); + } + if (d->desc.size()) { + el.appendChild(XMLHelper::textTag(*doc, DESC_TAG, d->desc)); + } + for (const auto &h : d->hashes) { + el.appendChild(h.toXml(doc)); + } + if (d->mediaType.size()) { + el.appendChild(XMLHelper::textTag(*doc, MEDIA_TYPE_TAG, d->mediaType)); + } + if (d->name.size()) { + el.appendChild(XMLHelper::textTag(*doc, NAME_TAG, d->name)); + } + if (d->hasSize) { + el.appendChild(XMLHelper::textTag(*doc, SIZE_TAG, d->size)); + } + if (d->rangeSupported || d->range.isValid()) { + el.appendChild(d->range.toXml(doc)); + } + if (d->thumbnail.isValid()) { + el.appendChild(d->thumbnail.toXml(doc)); } + if (d->amplitudes.size()) { + el.appendChild(XMLHelper::textTagNS(doc, AMPLITUDES_NS, AMPLITUDES_TAG, d->amplitudes)); + } + return el; + } - bool File::merge(const File &other) - { - if (!d->thumbnail.isValid()) { - d->thumbnail = other.thumbnail(); - } - for (auto const &h : other.d->hashes) { - auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), [&h](auto const &v) { return h.type() == v.type(); }); - if (it == d->hashes.constEnd()) { - d->hashes.append(h); - } else if (h.data() != it->data()) { - return false; // hashes are different - } + bool File::merge(const File &other) + { + if (!d->thumbnail.isValid()) { + d->thumbnail = other.thumbnail(); + } + for (auto const &h : other.d->hashes) { + auto it = std::find_if(d->hashes.constBegin(), d->hashes.constEnd(), + [&h](auto const &v) { return h.type() == v.type(); }); + if (it == d->hashes.constEnd()) { + d->hashes.append(h); + } else if (h.data() != it->data()) { + return false; // hashes are different } - return true; } + return true; + } - bool File::hasComputedHashes() const - { - if (!d) - return false; - for (auto const &h : d->hashes) { - if (h.data().size()) - return true; - } + bool File::hasComputedHashes() const + { + if (!d) return false; + for (auto const &h : d->hashes) { + if (h.data().size()) + return true; } + return false; + } - bool File::hasSize() const - { - return d->hasSize; - } + bool File::hasSize() const { return d->hasSize; } - QDateTime File::date() const - { - return d ? d->date : QDateTime(); - } + QDateTime File::date() const { return d ? d->date : QDateTime(); } - QString File::description() const - { - return d ? d->desc : QString(); - } + QString File::description() const { return d ? d->desc : QString(); } - QList File::hashes() const - { - return d ? d->hashes : QList(); - } + QList File::hashes() const { return d ? d->hashes : QList(); } - Hash File::hash(Hash::Type t) const - { - if (d && d->hashes.count()) { - if (t == Hash::Unknown) - return d->hashes.at(0); - for (auto const &h : d->hashes) { - if (h.type() == t) { - return h; - } + Hash File::hash(Hash::Type t) const + { + if (d && d->hashes.count()) { + if (t == Hash::Unknown) + return d->hashes.at(0); + for (auto const &h : d->hashes) { + if (h.type() == t) { + return h; } } - return Hash(); } + return Hash(); + } - QString File::mediaType() const - { - return d ? d->mediaType : QString(); - } + QString File::mediaType() const { return d ? d->mediaType : QString(); } - QString File::name() const - { - return d ? d->name : QString(); - } + QString File::name() const { return d ? d->name : QString(); } - quint64 File::size() const - { - return d ? d->size : 0; - } + quint64 File::size() const { return d ? d->size : 0; } - Range File::range() const - { - return d ? d->range : Range(); - } + Range File::range() const { return d ? d->range : Range(); } - Thumbnail File::thumbnail() const - { - return d ? d->thumbnail : Thumbnail(); - } + Thumbnail File::thumbnail() const { return d ? d->thumbnail : Thumbnail(); } - QByteArray File::amplitudes() const - { - return d ? d->amplitudes : QByteArray(); - } + QByteArray File::amplitudes() const { return d ? d->amplitudes : QByteArray(); } - void File::setDate(const QDateTime &date) - { - ensureD()->date = date; - } + void File::setDate(const QDateTime &date) { ensureD()->date = date; } - void File::setDescription(const QString &desc) - { - ensureD()->desc = desc; - } + void File::setDescription(const QString &desc) { ensureD()->desc = desc; } - void File::addHash(const Hash &hash) - { - ensureD()->hashes.append(hash); - } + void File::addHash(const Hash &hash) { ensureD()->hashes.append(hash); } - void File::setMediaType(const QString &mediaType) - { - ensureD()->mediaType = mediaType; - } + void File::setMediaType(const QString &mediaType) { ensureD()->mediaType = mediaType; } - void File::setName(const QString &name) - { - ensureD()->name = name; - } + void File::setName(const QString &name) { ensureD()->name = name; } - void File::setSize(quint64 size) - { - ensureD()->size = size; - d->hasSize = true; - } + void File::setSize(quint64 size) + { + ensureD()->size = size; + d->hasSize = true; + } - void File::setRange(const Range &range) - { - ensureD()->range = range; - d->rangeSupported = true; - } + void File::setRange(const Range &range) + { + ensureD()->range = range; + d->rangeSupported = true; + } - void File::setThumbnail(const Thumbnail &thumb) - { - ensureD()->thumbnail = thumb; - } + void File::setThumbnail(const Thumbnail &thumb) { ensureD()->thumbnail = thumb; } - void File::setAmplitudes(const QByteArray &litudes) - { - d->amplitudes = amplitudes; - } + void File::setAmplitudes(const QByteArray &litudes) { d->amplitudes = amplitudes; } - File::Private *File::ensureD() - { - if (!d) { - d = new Private; - } - return d.data(); + File::Private *File::ensureD() + { + if (!d) { + d = new Private; } + return d.data(); + } - //---------------------------------------------------------------------------- - // Checksum - //---------------------------------------------------------------------------- - Checksum::Checksum(const QDomElement &cs) : - ContentBase(cs) - { - file = File(cs.firstChildElement(QLatin1String("file"))); - } + //---------------------------------------------------------------------------- + // Checksum + //---------------------------------------------------------------------------- + Checksum::Checksum(const QDomElement &cs) : ContentBase(cs) + { + file = File(cs.firstChildElement(QLatin1String("file"))); + } - bool Checksum::isValid() const - { - return ContentBase::isValid() && file.isValid(); - } + bool Checksum::isValid() const { return ContentBase::isValid() && file.isValid(); } - QDomElement Checksum::toXml(QDomDocument *doc) const - { - auto el = ContentBase::toXml(doc, "checksum"); - if (!el.isNull()) { - el.appendChild(file.toXml(doc)); - } - return el; + QDomElement Checksum::toXml(QDomDocument *doc) const + { + auto el = ContentBase::toXml(doc, "checksum"); + if (!el.isNull()) { + el.appendChild(file.toXml(doc)); } + return el; + } - //---------------------------------------------------------------------------- - // Received - //---------------------------------------------------------------------------- - QDomElement Received::toXml(QDomDocument *doc) const - { - return ContentBase::toXml(doc, "received"); - } + //---------------------------------------------------------------------------- + // Received + //---------------------------------------------------------------------------- + QDomElement Received::toXml(QDomDocument *doc) const { return ContentBase::toXml(doc, "received"); } - //---------------------------------------------------------------------------- - // ApplicationManager - //---------------------------------------------------------------------------- - Manager::Manager(QObject *parent) : - XMPP::Jingle::ApplicationManager(parent) - { - } + //---------------------------------------------------------------------------- + // ApplicationManager + //---------------------------------------------------------------------------- + Manager::Manager(QObject *parent) : XMPP::Jingle::ApplicationManager(parent) {} - Manager::~Manager() - { - if (jingleManager) - jingleManager->unregisterApp(NS); - } + Manager::~Manager() + { + if (jingleManager) + jingleManager->unregisterApp(NS); + } - void Manager::setJingleManager(XMPP::Jingle::Manager *jm) - { - jingleManager = jm; - } + void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { jingleManager = jm; } - Application *Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) - { - if (!(contentName.size() > 0 && (senders == Origin::Initiator || senders == Origin::Responder))) { - qDebug("Invalid Jignle FT App start parameters"); - return nullptr; - } - return new Application(pad.staticCast(), contentName, creator, senders); // ContentOrigin::Remote + Application *Manager::startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, + Origin creator, Origin senders) + { + if (!(contentName.size() > 0 && (senders == Origin::Initiator || senders == Origin::Responder))) { + qDebug("Invalid Jignle FT App start parameters"); + return nullptr; } - - ApplicationManagerPad *Manager::pad(Session *session) - { - return new Pad(this, session); + return new Application(pad.staticCast(), contentName, creator, senders); // ContentOrigin::Remote + } + + ApplicationManagerPad *Manager::pad(Session *session) { return new Pad(this, session); } + + void Manager::closeAll() {} + + Client *Manager::client() + { + if (jingleManager) { + return jingleManager->client(); + } + return nullptr; + } + + QStringList Manager::availableTransports() const { return jingleManager->availableTransports(Transport::Reliable); } + + //---------------------------------------------------------------------------- + // Application + //---------------------------------------------------------------------------- + class Application::Private { + public: + Application * q = nullptr; + State state = State::Created; + State transportReplaceState = State::Finished; + Action updateToSend = Action::NoAction; + QSharedPointer pad; + QString contentName; + File file; + File acceptFile; // as it comes with "accept" response + Origin creator; + Origin senders; + Origin transportReplaceOrigin = Origin::None; + XMPP::Stanza::Error lastError; + Reason terminationReason; + QSharedPointer transport; + Connection::Ptr connection; + QStringList availableTransports; + bool closeDeviceOnFinish = true; + bool streamigMode = false; + QIODevice * device = nullptr; + quint64 bytesLeft = 0; + + void setState(State s) + { + state = s; + if (s == State::Finished) { + if (device && closeDeviceOnFinish) { + device->close(); + } + if (connection) { + connection->close(); + } + } + emit q->stateChanged(s); } - void Manager::closeAll() + void handleStreamFail() { + terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("stream failed")); + setState(State::Finished); } - Client *Manager::client() + void writeNextBlockToTransport() { - if (jingleManager) { - return jingleManager->client(); + if (!bytesLeft) { + terminationReason = Reason(Reason::Condition::Success); + setState(State::Finished); + return; // everything is written } - return nullptr; - } - - QStringList Manager::availableTransports() const - { - return jingleManager->availableTransports(Transport::Reliable); - } - - //---------------------------------------------------------------------------- - // Application - //---------------------------------------------------------------------------- - class Application::Private { - public: - Application * q = nullptr; - State state = State::Created; - State transportReplaceState = State::Finished; - Action updateToSend = Action::NoAction; - QSharedPointer pad; - QString contentName; - File file; - File acceptFile; // as it comes with "accept" response - Origin creator; - Origin senders; - Origin transportReplaceOrigin = Origin::None; - XMPP::Stanza::Error lastError; - Reason terminationReason; - QSharedPointer transport; - Connection::Ptr connection; - QStringList availableTransports; - bool closeDeviceOnFinish = true; - bool streamigMode = false; - QIODevice * device = nullptr; - quint64 bytesLeft = 0; - - void setState(State s) - { - state = s; - if (s == State::Finished) { - if (device && closeDeviceOnFinish) { - device->close(); - } - if (connection) { - connection->close(); - } - } - emit q->stateChanged(s); + auto sz = connection->blockSize(); + sz = sz ? sz : 8192; + if (sz > bytesLeft) { + sz = bytesLeft; } - - void handleStreamFail() - { - terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("stream failed")); - setState(State::Finished); + QByteArray data = device->read(sz); + if (data.isEmpty()) { + handleStreamFail(); + return; } + if (connection->write(data) == -1) { + handleStreamFail(); + return; + } + emit q->progress(device->pos()); + bytesLeft -= sz; + } - void writeNextBlockToTransport() - { - if (!bytesLeft) { - terminationReason = Reason(Reason::Condition::Success); - setState(State::Finished); - return; // everything is written - } - auto sz = connection->blockSize(); - sz = sz ? sz : 8192; + void readNextBlockFromTransport() + { + quint64 bytesAvail; + while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { + quint64 sz = 65536; // shall we respect transport->blockSize() ? if (sz > bytesLeft) { sz = bytesLeft; } - QByteArray data = device->read(sz); + if (sz > bytesAvail) { + sz = bytesAvail; + } + QByteArray data = connection->read(sz); if (data.isEmpty()) { handleStreamFail(); return; } - if (connection->write(data) == -1) { + if (device->write(data) == -1) { handleStreamFail(); return; } emit q->progress(device->pos()); bytesLeft -= sz; } - - void readNextBlockFromTransport() - { - quint64 bytesAvail; - while (bytesLeft && (bytesAvail = connection->bytesAvailable())) { - quint64 sz = 65536; // shall we respect transport->blockSize() ? - if (sz > bytesLeft) { - sz = bytesLeft; - } - if (sz > bytesAvail) { - sz = bytesAvail; - } - QByteArray data = connection->read(sz); - if (data.isEmpty()) { - handleStreamFail(); - return; - } - if (device->write(data) == -1) { - handleStreamFail(); - return; - } - emit q->progress(device->pos()); - bytesLeft -= sz; - } - if (!bytesLeft) { - // TODO send - terminationReason = Reason(Reason::Condition::Success); - setState(State::Finished); - } + if (!bytesLeft) { + // TODO send + terminationReason = Reason(Reason::Condition::Success); + setState(State::Finished); } - }; - - Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, Origin senders) : - d(new Private) - { - d->q = this; - d->pad = pad; - d->contentName = contentName; - d->creator = creator; - d->senders = senders; - d->availableTransports = static_cast(pad->manager())->availableTransports(); } + }; - Application::~Application() - { - } + Application::Application(const QSharedPointer &pad, const QString &contentName, Origin creator, + Origin senders) : + d(new Private) + { + d->q = this; + d->pad = pad; + d->contentName = contentName; + d->creator = creator; + d->senders = senders; + d->availableTransports = static_cast(pad->manager())->availableTransports(); + } - ApplicationManagerPad::Ptr Application::pad() const - { - return d->pad.staticCast(); - } + Application::~Application() {} - State Application::state() const - { - return d->state; - } + ApplicationManagerPad::Ptr Application::pad() const { return d->pad.staticCast(); } - void Application::setState(State state) - { - d->setState(state); - } + State Application::state() const { return d->state; } - Stanza::Error Application::lastError() const - { - return d->lastError; - } + void Application::setState(State state) { d->setState(state); } - Reason Application::terminationReason() const - { - return d->terminationReason; - } + Stanza::Error Application::lastError() const { return d->lastError; } - QString Application::contentName() const - { - return d->contentName; - } + Reason Application::terminationReason() const { return d->terminationReason; } - Origin Application::creator() const - { - return d->creator; - } + QString Application::contentName() const { return d->contentName; } - Origin Application::senders() const - { - return d->senders; - } + Origin Application::creator() const { return d->creator; } - Application::SetDescError Application::setDescription(const QDomElement &description) - { - d->file = File(description.firstChildElement("file")); - //d->state = State::Pending; // basically it's incomming content. so if we parsed it it's pending. if not parsed if will rejected anyway. - return d->file.isValid() ? Ok : Unparsed; - } + Origin Application::senders() const { return d->senders; } - void Application::setFile(const File &file) - { - d->file = file; - } + Application::SetDescError Application::setDescription(const QDomElement &description) + { + d->file = File(description.firstChildElement("file")); + // d->state = State::Pending; // basically it's incomming content. so if we parsed it it's pending. if not + // parsed if will rejected anyway. + return d->file.isValid() ? Ok : Unparsed; + } - File Application::file() const - { - return d->file; - } + void Application::setFile(const File &file) { d->file = file; } - File Application::acceptFile() const - { - return d->acceptFile; - } + File Application::file() const { return d->file; } - // incoming one? or we have to check real direction - bool Application::setTransport(const QSharedPointer &transport) - { - if (!(transport->features() & Transport::Reliable)) - return false; + File Application::acceptFile() const { return d->acceptFile; } - int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); - if (nsIndex == -1) { - return false; - } + // incoming one? or we have to check real direction + bool Application::setTransport(const QSharedPointer &transport) + { + if (!(transport->features() & Transport::Reliable)) + return false; - // in case we automatically select a new transport on our own we definitely will come up to this point - if (d->transport) { - d->transport->disconnect(this); - d->transport.reset(); - } + int nsIndex = d->availableTransports.indexOf(transport->pad()->ns()); + if (nsIndex == -1) { + return false; + } - d->availableTransports.removeAt(nsIndex); - d->transport = transport; - connect(transport.data(), &Transport::updated, this, &Application::updated); - connect(transport.data(), &Transport::connected, this, [this]() { - d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; // not needed here probably - d->connection = d->transport->connection(); - if (d->streamigMode) { - connect(d->connection.data(), &Connection::readyRead, this, [this]() { - if (!d->device) { - return; - } - if (d->pad->session()->role() != d->senders) { - d->readNextBlockFromTransport(); - } - }); - connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes) { - Q_UNUSED(bytes) - if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { - d->writeNextBlockToTransport(); - } - }); - } - d->setState(State::Active); - if (d->streamigMode) { - if (d->acceptFile.range().isValid()) { - d->bytesLeft = d->acceptFile.range().length; - emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); - } else { - d->bytesLeft = d->file.size(); - emit deviceRequested(0, d->bytesLeft); - } - } else { - emit connectionReady(); - } - }); + // in case we automatically select a new transport on our own we definitely will come up to this point + if (d->transport) { + d->transport->disconnect(this); + d->transport.reset(); + } - connect(transport.data(), &Transport::failed, this, [this]() { - d->transportReplaceOrigin = d->pad->session()->role(); - if (d->state >= State::Active) { - emit updated(); // late failure are unhandled. just notify the remote - return; - } - // we can try to replace the transport - if (!selectNextTransport()) { // we can do transport-replace here - if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { - // we were unable to send even initial offer - d->setState(State::Finished); - } else { - emit updated(); // we have to notify our peer about failure + d->availableTransports.removeAt(nsIndex); + d->transport = transport; + connect(transport.data(), &Transport::updated, this, &Application::updated); + connect(transport.data(), &Transport::connected, this, [this]() { + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; // not needed here probably + d->connection = d->transport->connection(); + if (d->streamigMode) { + connect(d->connection.data(), &Connection::readyRead, this, [this]() { + if (!d->device) { + return; + } + if (d->pad->session()->role() != d->senders) { + d->readNextBlockFromTransport(); } + }); + connect(d->connection.data(), &Connection::bytesWritten, this, [this](qint64 bytes) { + Q_UNUSED(bytes) + if (d->pad->session()->role() == d->senders && !d->connection->bytesToWrite()) { + d->writeNextBlockToTransport(); + } + }); + } + d->setState(State::Active); + if (d->streamigMode) { + if (d->acceptFile.range().isValid()) { + d->bytesLeft = d->acceptFile.range().length; + emit deviceRequested(d->acceptFile.range().offset, d->bytesLeft); } else { - d->transportReplaceState = State::PrepareLocalOffer; + d->bytesLeft = d->file.size(); + emit deviceRequested(0, d->bytesLeft); } - }); - - if (d->state >= State::Unacked) { - // seems like we are in transport failure recovery. d->transportFailed may confirm this - d->transport->prepare(); + } else { + emit connectionReady(); } - return true; - } + }); - Origin Application::transportReplaceOrigin() const - { - return d->transportReplaceOrigin; - } - - bool Application::incomingTransportReplace(const QSharedPointer &transport) - { - auto prev = d->transportReplaceOrigin; - if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { - // if I'm a responder and tried to send transport-replace too, then push ns back - d->availableTransports.append(d->transport->pad()->ns()); + connect(transport.data(), &Transport::failed, this, [this]() { + d->transportReplaceOrigin = d->pad->session()->role(); + if (d->state >= State::Active) { + emit updated(); // late failure are unhandled. just notify the remote + return; } - d->transportReplaceOrigin = d->pad->session()->peerRole(); - auto ret = setTransport(transport); - if (ret) + // we can try to replace the transport + if (!selectNextTransport()) { // we can do transport-replace here + if (d->state == State::PrepareLocalOffer && d->creator == d->pad->session()->role()) { + // we were unable to send even initial offer + d->setState(State::Finished); + } else { + emit updated(); // we have to notify our peer about failure + } + } else { d->transportReplaceState = State::PrepareLocalOffer; - else { - d->transportReplaceOrigin = prev; - d->lastError.reset(); - // REVIEW We have to fail application here on tie-break or propose another transport } + }); - return ret; + if (d->state >= State::Unacked) { + // seems like we are in transport failure recovery. d->transportFailed may confirm this + d->transport->prepare(); } + return true; + } - QSharedPointer Application::transport() const - { - return d->transport; + Origin Application::transportReplaceOrigin() const { return d->transportReplaceOrigin; } + + bool Application::incomingTransportReplace(const QSharedPointer &transport) + { + auto prev = d->transportReplaceOrigin; + if (d->pad->session()->role() == Origin::Responder && prev == Origin::Responder && d->transport) { + // if I'm a responder and tried to send transport-replace too, then push ns back + d->availableTransports.append(d->transport->pad()->ns()); + } + d->transportReplaceOrigin = d->pad->session()->peerRole(); + auto ret = setTransport(transport); + if (ret) + d->transportReplaceState = State::PrepareLocalOffer; + else { + d->transportReplaceOrigin = prev; + d->lastError.reset(); + // REVIEW We have to fail application here on tie-break or propose another transport } - void Application::setStreamingMode(bool mode) - { - if (d->state <= State::Connecting) { - d->streamigMode = mode; - } + return ret; + } + + QSharedPointer Application::transport() const { return d->transport; } + + void Application::setStreamingMode(bool mode) + { + if (d->state <= State::Connecting) { + d->streamigMode = mode; } + } - Action Application::evaluateOutgoingUpdate() - { - d->updateToSend = Action::NoAction; - if (!isValid() || d->state == State::Created || d->state == State::Finished) { - return d->updateToSend; - } + Action Application::evaluateOutgoingUpdate() + { + d->updateToSend = Action::NoAction; + if (!isValid() || d->state == State::Created || d->state == State::Finished) { + return d->updateToSend; + } - auto evaluateTransportReplaceAction = [this]() { - if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) - return Action::NoAction; + auto evaluateTransportReplaceAction = [this]() { + if (d->transportReplaceState != State::PrepareLocalOffer || !d->transport->isInitialOfferReady()) + return Action::NoAction; - return d->transportReplaceOrigin == d->pad->session()->role() ? Action::TransportReplace : Action::TransportAccept; - }; + return d->transportReplaceOrigin == d->pad->session()->role() ? Action::TransportReplace + : Action::TransportAccept; + }; - switch (d->state) { - case State::Created: - break; - case State::PrepareLocalOffer: - if (d->transportReplaceOrigin != Origin::None) { - if (!d->transport) { - d->updateToSend = Action::ContentReject; // case me=creator was already handled by this momemnt in case of app.PrepareLocalOffer. see Transport::failed above - } - d->updateToSend = evaluateTransportReplaceAction(); - if (d->updateToSend == Action::TransportAccept) { - d->updateToSend = Action::ContentAccept; - } - return d->updateToSend; + switch (d->state) { + case State::Created: + break; + case State::PrepareLocalOffer: + if (d->transportReplaceOrigin != Origin::None) { + if (!d->transport) { + d->updateToSend + = Action::ContentReject; // case me=creator was already handled by this momemnt in case of + // app.PrepareLocalOffer. see Transport::failed above } - - if (d->transport->isInitialOfferReady()) - d->updateToSend = d->creator == d->pad->session()->role() ? Action::ContentAdd : Action::ContentAccept; - - break; - case State::Connecting: - case State::Pending: - case State::Active: - if (d->transportReplaceOrigin != Origin::None) { - if (d->state == State::Active || !d->transport) - d->updateToSend = Action::ContentRemove; - else - d->updateToSend = evaluateTransportReplaceAction(); - return d->updateToSend; + d->updateToSend = evaluateTransportReplaceAction(); + if (d->updateToSend == Action::TransportAccept) { + d->updateToSend = Action::ContentAccept; } + return d->updateToSend; + } - if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { - d->updateToSend = Action::ContentRemove; - } else if (d->transport->hasUpdates()) - d->updateToSend = Action::TransportInfo; + if (d->transport->isInitialOfferReady()) + d->updateToSend = d->creator == d->pad->session()->role() ? Action::ContentAdd : Action::ContentAccept; - break; - case State::Finishing: - if (d->transportReplaceOrigin != Origin::None || d->terminationReason.isValid()) { + break; + case State::Connecting: + case State::Pending: + case State::Active: + if (d->transportReplaceOrigin != Origin::None) { + if (d->state == State::Active || !d->transport) d->updateToSend = Action::ContentRemove; - } else { - d->updateToSend = Action::SessionInfo; // to send checksum - } - break; - default: - break; + else + d->updateToSend = evaluateTransportReplaceAction(); + return d->updateToSend; } - return d->updateToSend; // TODO - } - OutgoingUpdate Application::takeOutgoingUpdate() - { - if (d->updateToSend == Action::NoAction) { - return OutgoingUpdate(); + if (d->terminationReason.isValid() && d->terminationReason.condition() != Reason::Condition::Success) { + d->updateToSend = Action::ContentRemove; + } else if (d->transport->hasUpdates()) + d->updateToSend = Action::TransportInfo; + + break; + case State::Finishing: + if (d->transportReplaceOrigin != Origin::None || d->terminationReason.isValid()) { + d->updateToSend = Action::ContentRemove; + } else { + d->updateToSend = Action::SessionInfo; // to send checksum } + break; + default: + break; + } + return d->updateToSend; // TODO + } - auto client = d->pad->session()->manager()->client(); - auto doc = client->doc(); + OutgoingUpdate Application::takeOutgoingUpdate() + { + if (d->updateToSend == Action::NoAction) { + return OutgoingUpdate(); + } - if (d->updateToSend == Action::SessionInfo) { - if (d->state != State::Finishing) { - // TODO implement - return OutgoingUpdate(); - } - ContentBase cb(d->pad->session()->role(), d->contentName); - return OutgoingUpdate { QList() << cb.toXml(doc, "received"), [this]() { - d->setState(State::Finished); - } }; - } + auto client = d->pad->session()->manager()->client(); + auto doc = client->doc(); - QDomElement transportEl; - OutgoingUpdateCB transportCB; - - ContentBase cb(d->creator, d->contentName); - if (d->state == State::PrepareLocalOffer) - cb.senders = d->senders; - QList updates; - auto contentEl = cb.toXml(doc, "content"); - updates << contentEl; - - switch (d->updateToSend) { - case Action::ContentReject: - case Action::ContentRemove: - if (d->transportReplaceOrigin != Origin::None) - d->terminationReason = Reason(Reason::Condition::FailedTransport); - if (d->terminationReason.isValid()) - updates << d->terminationReason.toXml(doc); - return OutgoingUpdate { updates, [this]() { - d->setState(State::Finished); - } }; - case Action::ContentAdd: - case Action::ContentAccept: - Q_ASSERT(d->transport->isInitialOfferReady()); - if (d->file.thumbnail().data.size()) { - auto thumb = d->file.thumbnail(); - auto bm = client->bobManager(); - BoBData data = bm->append(thumb.data, thumb.mimeType); - thumb.uri = QLatin1String("cid:") + data.cid(); - d->file.setThumbnail(thumb); - } - contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))).appendChild(d->file.toXml(doc)); - std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); - contentEl.appendChild(transportEl); - - d->setState(State::Unacked); - return OutgoingUpdate { updates, [this, transportCB]() { - if (transportCB) { - transportCB(); - } - d->setState(d->pad->session()->role() == Origin::Initiator ? State::Pending : State::Connecting); - } }; - case Action::TransportInfo: - Q_ASSERT(d->transport->hasUpdates()); - std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); - contentEl.appendChild(transportEl); - return OutgoingUpdate { updates, transportCB }; - case Action::TransportReplace: - case Action::TransportAccept: { - Q_ASSERT(d->transport->isInitialOfferReady()); - d->transportReplaceState = State::Unacked; - std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); - contentEl.appendChild(transportEl); - auto action = d->updateToSend; - return OutgoingUpdate { updates, [this, transportCB, action]() { - if (transportCB) { - transportCB(); - } - d->transportReplaceState = action == Action::TransportReplace ? State::Pending : State::Finished; - } }; + if (d->updateToSend == Action::SessionInfo) { + if (d->state != State::Finishing) { + // TODO implement + return OutgoingUpdate(); } - default: - break; + ContentBase cb(d->pad->session()->role(), d->contentName); + return OutgoingUpdate { QList() << cb.toXml(doc, "received"), + [this]() { d->setState(State::Finished); } }; + } + + QDomElement transportEl; + OutgoingUpdateCB transportCB; + + ContentBase cb(d->creator, d->contentName); + if (d->state == State::PrepareLocalOffer) + cb.senders = d->senders; + QList updates; + auto contentEl = cb.toXml(doc, "content"); + updates << contentEl; + + switch (d->updateToSend) { + case Action::ContentReject: + case Action::ContentRemove: + if (d->transportReplaceOrigin != Origin::None) + d->terminationReason = Reason(Reason::Condition::FailedTransport); + if (d->terminationReason.isValid()) + updates << d->terminationReason.toXml(doc); + return OutgoingUpdate { updates, [this]() { d->setState(State::Finished); } }; + case Action::ContentAdd: + case Action::ContentAccept: + Q_ASSERT(d->transport->isInitialOfferReady()); + if (d->file.thumbnail().data.size()) { + auto thumb = d->file.thumbnail(); + auto bm = client->bobManager(); + BoBData data = bm->append(thumb.data, thumb.mimeType); + thumb.uri = QLatin1String("cid:") + data.cid(); + d->file.setThumbnail(thumb); + } + contentEl.appendChild(doc->createElementNS(NS, QString::fromLatin1("description"))) + .appendChild(d->file.toXml(doc)); + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); + contentEl.appendChild(transportEl); + + d->setState(State::Unacked); + return OutgoingUpdate { updates, [this, transportCB]() { + if (transportCB) { + transportCB(); + } + d->setState(d->pad->session()->role() == Origin::Initiator ? State::Pending + : State::Connecting); + } }; + case Action::TransportInfo: + Q_ASSERT(d->transport->hasUpdates()); + std::tie(transportEl, transportCB) = d->transport->takeOutgoingUpdate(); + contentEl.appendChild(transportEl); + return OutgoingUpdate { updates, transportCB }; + case Action::TransportReplace: + case Action::TransportAccept: { + Q_ASSERT(d->transport->isInitialOfferReady()); + d->transportReplaceState = State::Unacked; + std::tie(transportEl, transportCB) = d->transport->takeInitialOffer(); + contentEl.appendChild(transportEl); + auto action = d->updateToSend; + return OutgoingUpdate { updates, [this, transportCB, action]() { + if (transportCB) { + transportCB(); + } + d->transportReplaceState + = action == Action::TransportReplace ? State::Pending : State::Finished; + } }; + } + default: + break; + } + + return OutgoingUpdate(); // TODO + } + + bool Application::wantBetterTransport(const QSharedPointer &t) const + { + Q_UNUSED(t) + return true; // TODO check + } + + bool Application::selectNextTransport() + { + while (d->availableTransports.size()) { + auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.last()); + if (t && setTransport(t)) { + return true; + } else { + d->availableTransports.removeLast(); } + } + return false; + } - return OutgoingUpdate(); // TODO + void Application::prepare() + { + if (!d->transport) { + selectNextTransport(); } + if (d->transport) { + d->setState(State::PrepareLocalOffer); + d->transport->prepare(); + } + } - bool Application::wantBetterTransport(const QSharedPointer &t) const - { - Q_UNUSED(t) - return true; // TODO check + void Application::start() + { + if (d->transport) { + d->setState(State::Connecting); + d->transport->start(); } + // TODO we need QIODevice somewhere here + } - bool Application::selectNextTransport() - { - while (d->availableTransports.size()) { - auto t = d->pad->session()->newOutgoingTransport(d->availableTransports.last()); - if (t && setTransport(t)) { - return true; - } else { - d->availableTransports.removeLast(); - } - } + bool Application::accept(const QDomElement &el) + { + File f(el.firstChildElement("file")); + if (!f.isValid()) { return false; } + d->acceptFile = f; + // TODO validate if accept file matches to the offer + setState(State::Accepted); + return true; + } - void Application::prepare() - { - if (!d->transport) { - selectNextTransport(); - } - if (d->transport) { - d->setState(State::PrepareLocalOffer); - d->transport->prepare(); - } - } + void Application::remove(Reason::Condition cond, const QString &comment) + { + if (d->state >= State::Finishing) + return; - void Application::start() - { - if (d->transport) { - d->setState(State::Connecting); - d->transport->start(); - } - // TODO we need QIODevice somewhere here - } + d->terminationReason = Reason(cond, comment); + d->transportReplaceOrigin = Origin::None; // just in case + d->transport->disconnect(this); + d->transport.reset(); - bool Application::accept(const QDomElement &el) - { - File f(el.firstChildElement("file")); - if (!f.isValid()) { - return false; - } - d->acceptFile = f; - // TODO validate if accept file matches to the offer - setState(State::Accepted); - return true; + if (d->creator == d->pad->session()->role() && d->state <= State::PrepareLocalOffer) { + // local content, not yet sent to remote + setState(State::Finished); + return; } - void Application::remove(Reason::Condition cond, const QString &comment) - { - if (d->state >= State::Finishing) - return; + setState(State::Finishing); + emit updated(); + } - d->terminationReason = Reason(cond, comment); - d->transportReplaceOrigin = Origin::None; // just in case - d->transport->disconnect(this); - d->transport.reset(); - - if (d->creator == d->pad->session()->role() && d->state <= State::PrepareLocalOffer) { - // local content, not yet sent to remote - setState(State::Finished); - return; + bool Application::incomingTransportAccept(const QDomElement &transportEl) + { + if (d->transportReplaceOrigin != d->pad->session()->role()) { + d->lastError = ErrorUtil::makeOutOfOrder(*d->pad->doc()); + return false; + } + if (d->transport->update(transportEl)) { + d->transportReplaceOrigin = Origin::None; + d->transportReplaceState = State::Finished; + if (d->state >= State::Connecting) { + d->transport->start(); } - - setState(State::Finishing); emit updated(); + return true; } + return false; + } - bool Application::incomingTransportAccept(const QDomElement &transportEl) - { - if (d->transportReplaceOrigin != d->pad->session()->role()) { - d->lastError = ErrorUtil::makeOutOfOrder(*d->pad->doc()); - return false; - } - if (d->transport->update(transportEl)) { - d->transportReplaceOrigin = Origin::None; - d->transportReplaceState = State::Finished; - if (d->state >= State::Connecting) { - d->transport->start(); - } - emit updated(); - return true; - } - return false; - } + bool Application::isValid() const + { + return d->file.isValid() && d->contentName.size() > 0 + && (d->senders == Origin::Initiator || d->senders == Origin::Responder); + } - bool Application::isValid() const - { - return d->file.isValid() && d->contentName.size() > 0 && (d->senders == Origin::Initiator || d->senders == Origin::Responder); + void Application::setDevice(QIODevice *dev, bool closeOnFinish) + { + if (!dev) { // failed to provide proper device + d->terminationReason + = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("No destination device")); + emit updated(); + return; } - - void Application::setDevice(QIODevice *dev, bool closeOnFinish) - { - if (!dev) { // failed to provide proper device - d->terminationReason = Reason(Reason::Condition::FailedApplication, QString::fromLatin1("No destination device")); - emit updated(); - return; - } - d->device = dev; - d->closeDeviceOnFinish = closeOnFinish; - if (d->senders == d->pad->session()->role()) { - d->writeNextBlockToTransport(); - } else { - d->readNextBlockFromTransport(); - } + d->device = dev; + d->closeDeviceOnFinish = closeOnFinish; + if (d->senders == d->pad->session()->role()) { + d->writeNextBlockToTransport(); + } else { + d->readNextBlockFromTransport(); } + } - Connection::Ptr Application::connection() const - { - return d->connection.staticCast(); - } + Connection::Ptr Application::connection() const { return d->connection.staticCast(); } - Pad::Pad(Manager *manager, Session *session) : - _manager(manager), - _session(session) - { - } + Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) {} - QDomElement Pad::takeOutgoingSessionInfoUpdate() - { - return QDomElement(); // TODO - } + QDomElement Pad::takeOutgoingSessionInfoUpdate() + { + return QDomElement(); // TODO + } - QString Pad::ns() const - { - return NS; - } + QString Pad::ns() const { return NS; } - Session *Pad::session() const - { - return _session; - } + Session *Pad::session() const { return _session; } - ApplicationManager *Pad::manager() const - { - return _manager; - } + ApplicationManager *Pad::manager() const { return _manager; } - QString Pad::generateContentName(Origin senders) - { - QString prefix = senders == _session->role() ? "fileoffer" : "filereq"; - QString name; - do { - name = prefix + QString("_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - } while (_session->content(name, _session->role())); - return name; - } + QString Pad::generateContentName(Origin senders) + { + QString prefix = senders == _session->role() ? "fileoffer" : "filereq"; + QString name; + do { + name = prefix + QString("_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + } while (_session->content(name, _session->role())); + return name; + } - void Pad::addOutgoingOffer(const File &file) - { - auto selfp = _session->applicationPad(NS); - auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); - app->setFile(file); - } - } // namespace FileTransfer + void Pad::addOutgoingOffer(const File &file) + { + auto selfp = _session->applicationPad(NS); + auto app = _manager->startApplication(selfp, "ft", _session->role(), _session->role()); + app->setFile(file); + } +} // namespace FileTransfer } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ibb.cpp b/src/xmpp/xmpp-im/jingle-ibb.cpp index 8721ad43..a1ce2c9a 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.cpp +++ b/src/xmpp/xmpp-im/jingle-ibb.cpp @@ -25,458 +25,411 @@ #include -namespace XMPP { -namespace Jingle { -namespace IBB { -const QString NS(QStringLiteral("urn:xmpp:jingle:transports:ibb:1")); - -class Connection : public XMPP::Jingle::Connection -{ - Q_OBJECT - -public: - Client *client; - Jid peer; - QString sid; - size_t _blockSize; - IBBConnection *connection = nullptr; - - bool offerSent = false; - bool offerReceived = false; - bool closing = false; - bool finished = false; - - Connection(Client *client, const Jid &jid, const QString &sid, size_t blockSize) : - client(client), - peer(jid), - sid(sid), - _blockSize(blockSize) - { +namespace XMPP { namespace Jingle { namespace IBB { + const QString NS(QStringLiteral("urn:xmpp:jingle:transports:ibb:1")); + + class Connection : public XMPP::Jingle::Connection { + Q_OBJECT + + public: + Client * client; + Jid peer; + QString sid; + size_t _blockSize; + IBBConnection *connection = nullptr; + + bool offerSent = false; + bool offerReceived = false; + bool closing = false; + bool finished = false; + + Connection(Client *client, const Jid &jid, const QString &sid, size_t blockSize) : + client(client), peer(jid), sid(sid), _blockSize(blockSize) + { + } - } + void setConnection(IBBConnection *c) + { + connection = c; + connect(c, &IBBConnection::readyRead, this, &Connection::readyRead); + connect(c, &IBBConnection::bytesWritten, this, &Connection::bytesWritten); + connect(c, &IBBConnection::connectionClosed, this, &Connection::handleIBBClosed); + connect(c, &IBBConnection::delayedCloseFinished, this, &Connection::handleIBBClosed); + connect(c, &IBBConnection::aboutToClose, this, &Connection::aboutToClose); + connect(c, &IBBConnection::connected, this, [this]() { + setOpenMode(connection->openMode()); + emit connected(); + }); + } - void setConnection(IBBConnection *c) - { - connection = c; - connect(c, &IBBConnection::readyRead, this, &Connection::readyRead); - connect(c, &IBBConnection::bytesWritten, this, &Connection::bytesWritten); - connect(c, &IBBConnection::connectionClosed, this, &Connection::handleIBBClosed); - connect(c, &IBBConnection::delayedCloseFinished, this, &Connection::handleIBBClosed); - connect(c, &IBBConnection::aboutToClose, this, &Connection::aboutToClose); - connect(c, &IBBConnection::connected, this, [this](){ setOpenMode(connection->openMode()); emit connected(); }); - } + size_t blockSize() const { return _blockSize; } - size_t blockSize() const - { - return _blockSize; - } + qint64 bytesAvailable() const + { + return XMPP::Jingle::Connection::bytesAvailable() + (connection ? connection->bytesAvailable() : 0); + } + + qint64 bytesToWrite() const + { + return XMPP::Jingle::Connection::bytesToWrite() + (connection ? connection->bytesToWrite() : 0); + } + + void close() + { + if (connection) { + connection->close(); + setOpenMode(connection->openMode()); + } else { + XMPP::Jingle::Connection::close(); + emit connectionClosed(); + } + } + + signals: + void connected(); + + protected: + qint64 writeData(const char *data, qint64 maxSize) { return connection->write(data, maxSize); } + + qint64 readData(char *data, qint64 maxSize) + { + quint64 ret = connection->read(data, maxSize); + if (closing && !bytesAvailable()) { + postCloseAllDataRead(); + } + return ret; + } + + private: + void handleIBBClosed() + { + closing = true; + if (bytesAvailable()) + setOpenMode(QIODevice::ReadOnly); + else + postCloseAllDataRead(); + } + + void postCloseAllDataRead() + { + closing = false; + finished = true; + connection->deleteLater(); + connection = nullptr; + setOpenMode(QIODevice::NotOpen); + emit connectionClosed(); + } + }; + + struct Transport::Private { + Transport * q = nullptr; + Pad::Ptr pad; + QMap> connections; + QList> readyConnections; + QSharedPointer lastOfferedConnection; + size_t defaultBlockSize = 4096; + bool started = false; + bool initialOfferSent = false; // if we ever sent anything + + void checkAndStartConnection(const QSharedPointer &c) + { + if (!c->connection && !c->finished && c->offerReceived && c->offerSent + && pad->session()->role() == Origin::Initiator) { + auto con = pad->session()->manager()->client()->ibbManager()->createConnection(); + auto ibbcon = static_cast(con); + ibbcon->setPacketSize(defaultBlockSize); + c->setConnection(ibbcon); + ibbcon->connectToJid(pad->session()->peer(), c->sid); + } + } + + void handleConnected(const QSharedPointer &c) + { + if (c) { + readyConnections.append(c); + emit q->connected(); + } + } - qint64 bytesAvailable() const + OutgoingTransportInfoUpdate makeOffer(const QSharedPointer &connection) + { + OutgoingTransportInfoUpdate upd; + if (!connection) { + return upd; + } + + auto doc = pad->session()->manager()->client()->doc(); + + QDomElement tel = doc->createElementNS(NS, "transport"); + tel.setAttribute(QStringLiteral("sid"), connection->sid); + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->_blockSize)); + + upd = OutgoingTransportInfoUpdate { tel, [this, connection]() mutable { + if (started) + checkAndStartConnection(connection); + } }; + + lastOfferedConnection = connection; + connection->offerSent = true; + return upd; + } + }; + + Transport::Transport(const TransportManagerPad::Ptr &pad) : d(new Private) { - return XMPP::Jingle::Connection::bytesAvailable() + (connection? connection->bytesAvailable() : 0); + d->q = this; + d->pad = pad.staticCast(); + connect(pad->manager(), &TransportManager::abortAllRequested, this, [this]() { + for (auto &c : d->connections) { + c->close(); + } + // d->aborted = true; + emit failed(); + }); } - qint64 bytesToWrite() const + Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : d(new Private) { - return XMPP::Jingle::Connection::bytesToWrite() + (connection? connection->bytesToWrite() : 0); + d->q = this; + d->pad = pad.staticCast(); + update(transportEl); + if (d->connections.isEmpty()) { + d.reset(); + return; + } } - void close() + Transport::~Transport() { - if (connection) { - connection->close(); - setOpenMode(connection->openMode()); - } else { - XMPP::Jingle::Connection::close(); - emit connectionClosed(); + // we have to mark all of them as finished just in case they are captured somewhere else + if (d) { + for (auto &c : d->connections) { + c->finished = true; + } } } -signals: - void connected(); + TransportManagerPad::Ptr Transport::pad() const { return d->pad; } -protected: - qint64 writeData(const char *data, qint64 maxSize) + void Transport::prepare() { - return connection->write(data, maxSize); + if (d->connections.isEmpty()) { // seems like outgoing + auto conn = d->pad->makeConnection(QString(), d->defaultBlockSize); + auto ibbConn = conn.staticCast(); + connect(ibbConn.data(), &Connection::connected, this, [this]() { + auto c = static_cast(sender()); + d->handleConnected(d->connections.value(c->sid)); + }); + d->connections.insert(ibbConn->sid, ibbConn); + + connect(ibbConn.data(), &Connection::connectionClosed, this, [this]() { + Connection *c = static_cast(sender()); + d->connections.remove(c->sid); + QMutableListIterator> it(d->readyConnections); + while (it.hasNext()) { + auto &p = it.next(); + if (p.data() == c) { + it.remove(); + break; + } + } + }); + } + emit updated(); } - qint64 readData(char *data, qint64 maxSize) + void Transport::start() { - quint64 ret = connection->read(data, maxSize); - if (closing && !bytesAvailable()) { - postCloseAllDataRead(); + d->started = true; + + for (auto &c : d->connections) { + d->checkAndStartConnection(c); } - return ret; } -private: - - void handleIBBClosed() + bool Transport::update(const QDomElement &transportEl) { - closing = true; - if (bytesAvailable()) - setOpenMode(QIODevice::ReadOnly); - else - postCloseAllDataRead(); - } + QString sid = transportEl.attribute(QString::fromLatin1("sid")); + if (sid.isEmpty()) { + return false; + } - void postCloseAllDataRead() - { - closing = false; - finished = true; - connection->deleteLater(); - connection = nullptr; - setOpenMode(QIODevice::NotOpen); - emit connectionClosed(); + size_t bs_final = d->defaultBlockSize; + auto bs = transportEl.attribute(QString::fromLatin1("block-size")); + if (!bs.isEmpty()) { + size_t bsn = bs.toULongLong(); + if (bsn && bsn <= bs_final) { + bs_final = bsn; + } + } + + auto it = d->connections.find(sid); + if (it == d->connections.end()) { + auto c = d->pad->makeConnection(sid, bs_final); + if (c) { + auto ibbc = c.staticCast(); + it = d->connections.insert(ibbc->sid, ibbc); + connect(ibbc.data(), &Connection::connected, this, [this]() { + auto c = static_cast(sender()); + d->handleConnected(d->connections.value(c->sid)); + }); + } else { + qWarning("failed to create IBB connection"); + return false; + } + } else { + if (bs_final < (*it)->_blockSize) { + (*it)->_blockSize = bs_final; + } + } + + (*it)->offerReceived = true; + if (d->started) { + auto c = it.value(); + QTimer::singleShot(0, this, [this, c]() mutable { d->checkAndStartConnection(c); }); + } + return true; } -}; - -struct Transport::Private -{ - Transport *q = nullptr; - Pad::Ptr pad; - QMap> connections; - QList> readyConnections; - QSharedPointer lastOfferedConnection; - size_t defaultBlockSize = 4096; - bool started = false; - bool initialOfferSent = false; // if we ever sent anything - - void checkAndStartConnection(const QSharedPointer &c) + + bool Transport::isInitialOfferReady() const { return isValid() && (hasUpdates() || d->initialOfferSent); } + + OutgoingTransportInfoUpdate Transport::takeInitialOffer() { - if (!c->connection && !c->finished && c->offerReceived && c->offerSent && pad->session()->role() == Origin::Initiator) { - auto con = pad->session()->manager()->client()->ibbManager()->createConnection(); - auto ibbcon = static_cast(con); - ibbcon->setPacketSize(defaultBlockSize); - c->setConnection(ibbcon); - ibbcon->connectToJid(pad->session()->peer(), c->sid); + auto upd = takeOutgoingUpdate(); + if (std::get<0>(upd).isNull() && d->lastOfferedConnection) { + return d->makeOffer(d->lastOfferedConnection); } + return upd; } - void handleConnected(const QSharedPointer &c) + bool Transport::hasUpdates() const { - if (c) { - readyConnections.append(c); - emit q->connected(); + for (auto &c : d->connections) { + if (!c->offerSent) { + return true; + } } + return false; } - OutgoingTransportInfoUpdate makeOffer(const QSharedPointer &connection) + OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() { OutgoingTransportInfoUpdate upd; - if (!connection) { + if (!isValid()) { return upd; } - auto doc = pad->session()->manager()->client()->doc(); + QSharedPointer connection; + for (auto &c : d->connections) { + if (!c->offerSent) { + connection = c; + break; + } + } + return d->makeOffer(connection); + } - QDomElement tel = doc->createElementNS(NS, "transport"); - tel.setAttribute(QStringLiteral("sid"), connection->sid); - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(connection->_blockSize)); + bool Transport::isValid() const { return d; } - upd = OutgoingTransportInfoUpdate{tel, [this, connection]() mutable { - if (started) - checkAndStartConnection(connection); - }}; + Transport::Features Transport::features() const { return AlwaysConnect | Reliable | Slow; } - lastOfferedConnection = connection; - connection->offerSent = true; - return upd; - } -}; - -Transport::Transport(const TransportManagerPad::Ptr &pad) : - d(new Private) -{ - d->q = this; - d->pad = pad.staticCast(); - connect(pad->manager(), &TransportManager::abortAllRequested, this, [this](){ - for(auto &c: d->connections) { - c->close(); - } - //d->aborted = true; - emit failed(); - }); -} - -Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : - d(new Private) -{ - d->q = this; - d->pad = pad.staticCast(); - update(transportEl); - if (d->connections.isEmpty()) { - d.reset(); - return; + Connection::Ptr Transport::connection() const + { + return d->readyConnections.isEmpty() ? Connection::Ptr() + : d->readyConnections.takeFirst().staticCast(); } -} - -Transport::~Transport() -{ - // we have to mark all of them as finished just in case they are captured somewhere else - if (d) { - for (auto &c: d->connections) { - c->finished = true; - } + + Pad::Pad(Manager *manager, Session *session) + { + _manager = manager; + _session = session; } -} - -TransportManagerPad::Ptr Transport::pad() const -{ - return d->pad; -} - -void Transport::prepare() -{ - if (d->connections.isEmpty()) { // seems like outgoing - auto conn = d->pad->makeConnection(QString(), d->defaultBlockSize); - auto ibbConn = conn.staticCast(); - connect(ibbConn.data(), &Connection::connected, this, [this](){ - auto c = static_cast(sender()); - d->handleConnected(d->connections.value(c->sid)); - }); - d->connections.insert(ibbConn->sid, ibbConn); - - connect(ibbConn.data(), &Connection::connectionClosed, this, [this](){ - Connection *c = static_cast(sender()); - d->connections.remove(c->sid); - QMutableListIterator> it(d->readyConnections); - while (it.hasNext()) { - auto &p = it.next(); - if (p.data() == c) { - it.remove(); - break; - } - } - }); + + QString Pad::ns() const { return NS; } + + Session *Pad::session() const { return _session; } + + TransportManager *Pad::manager() const { return _manager; } + + Connection::Ptr Pad::makeConnection(const QString &sid, size_t blockSize) + { + return _manager->makeConnection(_session->peer(), sid, blockSize); } - emit updated(); -} -void Transport::start() -{ - d->started = true; + struct Manager::Private { + QHash, QSharedPointer> connections; + XMPP::Jingle::Manager * jingleManager = nullptr; + }; + + Manager::Manager(QObject *parent) : TransportManager(parent), d(new Private) {} - for (auto &c: d->connections) { - d->checkAndStartConnection(c); + Manager::~Manager() + { + if (d->jingleManager) + d->jingleManager->unregisterTransport(NS); } -} -bool Transport::update(const QDomElement &transportEl) -{ - QString sid = transportEl.attribute(QString::fromLatin1("sid")); - if (sid.isEmpty()) { - return false; + Transport::Features Manager::features() const + { + return Transport::AlwaysConnect | Transport::Reliable | Transport::Slow; } - size_t bs_final = d->defaultBlockSize; - auto bs = transportEl.attribute(QString::fromLatin1("block-size")); - if (!bs.isEmpty()) { - size_t bsn = bs.toULongLong(); - if (bsn && bsn <= bs_final) { - bs_final = bsn; - } + void Manager::setJingleManager(XMPP::Jingle::Manager *jm) { d->jingleManager = jm; } + + QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) + { + return QSharedPointer(new Transport(pad)); } - auto it = d->connections.find(sid); - if (it == d->connections.end()) { - auto c = d->pad->makeConnection(sid, bs_final); - if (c) { - auto ibbc = c.staticCast(); - it = d->connections.insert(ibbc->sid, ibbc); - connect(ibbc.data(), &Connection::connected, this, [this](){ - auto c = static_cast(sender()); - d->handleConnected(d->connections.value(c->sid)); - }); - } else { - qWarning("failed to create IBB connection"); - return false; - } - } else { - if (bs_final < (*it)->_blockSize) { - (*it)->_blockSize = bs_final; + QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad, + const QDomElement & transportEl) + { + auto t = new Transport(pad, transportEl); + QSharedPointer ret(t); + if (t->isValid()) { + return ret; } + return QSharedPointer(); } - (*it)->offerReceived = true; - if (d->started) { - auto c = it.value(); - QTimer::singleShot(0, this, [this,c]() mutable { d->checkAndStartConnection(c); }); - } - return true; -} - -bool Transport::isInitialOfferReady() const -{ - return isValid() && (hasUpdates() || d->initialOfferSent); -} - -OutgoingTransportInfoUpdate Transport::takeInitialOffer() -{ - auto upd = takeOutgoingUpdate(); - if (std::get<0>(upd).isNull() && d->lastOfferedConnection) { - return d->makeOffer(d->lastOfferedConnection); - } - return upd; -} + TransportManagerPad *Manager::pad(Session *session) { return new Pad(this, session); } -bool Transport::hasUpdates() const -{ - for (auto &c: d->connections) { - if (!c->offerSent) { - return true; + void Manager::closeAll() { emit abortAllRequested(); } + + XMPP::Jingle::Connection::Ptr Manager::makeConnection(const Jid &peer, const QString &sid, size_t blockSize) + { + if (!sid.isEmpty() && d->connections.contains(qMakePair(peer, sid))) { + qWarning("sid %s was already registered for %s", qPrintable(sid), qPrintable(peer.full())); + return Connection::Ptr(); } - } - return false; -} + QString s(sid); + if (s.isEmpty()) { + QPair key; + do { + s = QString("ibb_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + key = qMakePair(peer, s); + } while (d->connections.contains(key)); + } + auto conn = QSharedPointer::create(d->jingleManager->client(), peer, s, blockSize); + d->connections.insert(qMakePair(peer, s), conn); + connect(conn.data(), &Connection::connectionClosed, this, [this]() { + Connection *c = static_cast(sender()); + d->connections.remove(qMakePair(c->peer, c->sid)); + }); -OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() -{ - OutgoingTransportInfoUpdate upd; - if (!isValid()) { - return upd; + return conn.staticCast(); } - QSharedPointer connection; - for (auto &c: d->connections) { - if (!c->offerSent) { - connection = c; - break; + bool Manager::handleIncoming(IBBConnection *c) + { + auto conn = d->connections.value(qMakePair(c->peer(), c->sid())); + if (conn) { + conn->setConnection(c); + QTimer::singleShot(0, c, &IBBConnection::accept); + return true; } + return false; } - return d->makeOffer(connection); -} - -bool Transport::isValid() const -{ - return d; -} - -Transport::Features Transport::features() const -{ - return AlwaysConnect | Reliable | Slow; -} - -Connection::Ptr Transport::connection() const -{ - return d->readyConnections.isEmpty()? Connection::Ptr() : d->readyConnections.takeFirst().staticCast(); -} - -Pad::Pad(Manager *manager, Session *session) -{ - _manager = manager; - _session = session; -} - -QString Pad::ns() const -{ - return NS; -} - -Session *Pad::session() const -{ - return _session; -} - -TransportManager *Pad::manager() const -{ - return _manager; -} - -Connection::Ptr Pad::makeConnection(const QString &sid, size_t blockSize) -{ - return _manager->makeConnection(_session->peer(), sid, blockSize); -} - -struct Manager::Private -{ - QHash,QSharedPointer> connections; - XMPP::Jingle::Manager *jingleManager = nullptr; -}; - -Manager::Manager(QObject *parent) : - TransportManager(parent), - d(new Private) -{ - -} - -Manager::~Manager() -{ - if (d->jingleManager) - d->jingleManager->unregisterTransport(NS); -} - -Transport::Features Manager::features() const -{ - return Transport::AlwaysConnect | Transport::Reliable | Transport::Slow; -} - -void Manager::setJingleManager(XMPP::Jingle::Manager *jm) -{ - d->jingleManager = jm; -} - -QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) -{ - return QSharedPointer(new Transport(pad)); -} - -QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) -{ - auto t = new Transport(pad, transportEl); - QSharedPointer ret(t); - if (t->isValid()) { - return ret; - } - return QSharedPointer(); -} - -TransportManagerPad* Manager::pad(Session *session) -{ - return new Pad(this, session); -} - -void Manager::closeAll() -{ - emit abortAllRequested(); -} - -XMPP::Jingle::Connection::Ptr Manager::makeConnection(const Jid &peer, const QString &sid, size_t blockSize) -{ - if (!sid.isEmpty() && d->connections.contains(qMakePair(peer, sid))) { - qWarning("sid %s was already registered for %s", qPrintable(sid), qPrintable(peer.full())); - return Connection::Ptr(); - } - QString s(sid); - if (s.isEmpty()) { - QPair key; - do { - s = QString("ibb_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - key = qMakePair(peer, s); - } while (d->connections.contains(key)); - } - auto conn = QSharedPointer::create(d->jingleManager->client(), peer, s, blockSize); - d->connections.insert(qMakePair(peer, s), conn); - connect(conn.data(), &Connection::connectionClosed, this, [this](){ - Connection *c = static_cast(sender()); - d->connections.remove(qMakePair(c->peer, c->sid)); - }); - - return conn.staticCast(); -} - -bool Manager::handleIncoming(IBBConnection *c) -{ - auto conn = d->connections.value(qMakePair(c->peer(), c->sid())); - if (conn) { - conn->setConnection(c); - QTimer::singleShot(0, c, &IBBConnection::accept); - return true; - } - return false; -} } // namespace IBB } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-ibb.h b/src/xmpp/xmpp-im/jingle-ibb.h index acfd516c..8669f3ec 100644 --- a/src/xmpp/xmpp-im/jingle-ibb.h +++ b/src/xmpp/xmpp-im/jingle-ibb.h @@ -23,80 +23,81 @@ #include "jingle.h" namespace XMPP { - class IBBConnection; - -namespace Jingle { -namespace IBB { -extern const QString NS; - -class Transport : public XMPP::Jingle::Transport -{ - Q_OBJECT -public: - Transport(const TransportManagerPad::Ptr &pad); - Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); - ~Transport(); - - TransportManagerPad::Ptr pad() const override; - - void prepare() override; - void start() override; - bool isInitialOfferReady() const override; - OutgoingTransportInfoUpdate takeInitialOffer() override; - bool update(const QDomElement &transportEl) override; - bool hasUpdates() const override; - OutgoingTransportInfoUpdate takeOutgoingUpdate() override; - bool isValid() const override; - Features features() const override; - - Connection::Ptr connection() const override; - -private: - friend class Manager; - - class Private; - QScopedPointer d; -}; - -class Manager; -class Pad : public TransportManagerPad -{ - Q_OBJECT - // TODO -public: - typedef QSharedPointer Ptr; - - Pad(Manager *manager, Session *session); - QString ns() const override; - Session *session() const override; - TransportManager *manager() const override; - - Connection::Ptr makeConnection(const QString &sid, size_t blockSize); -private: - Manager *_manager = nullptr; - Session *_session = nullptr; -}; - -class Manager : public TransportManager { - Q_OBJECT -public: - Manager(QObject *parent = nullptr); - ~Manager(); - - XMPP::Jingle::Transport::Features features() const override; - void setJingleManager(XMPP::Jingle::Manager *jm) override; - QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) override; // outgoing. one have to call Transport::start to collect candidates - QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) override; // incoming - TransportManagerPad* pad(Session *session) override; - - void closeAll() override; - - Connection::Ptr makeConnection(const Jid &peer, const QString &sid, size_t blockSize); - bool handleIncoming(IBBConnection *c); -private: - class Private; - QScopedPointer d; -}; +class IBBConnection; + +namespace Jingle { namespace IBB { + extern const QString NS; + + class Transport : public XMPP::Jingle::Transport { + Q_OBJECT + public: + Transport(const TransportManagerPad::Ptr &pad); + Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); + ~Transport(); + + TransportManagerPad::Ptr pad() const override; + + void prepare() override; + void start() override; + bool isInitialOfferReady() const override; + OutgoingTransportInfoUpdate takeInitialOffer() override; + bool update(const QDomElement &transportEl) override; + bool hasUpdates() const override; + OutgoingTransportInfoUpdate takeOutgoingUpdate() override; + bool isValid() const override; + Features features() const override; + + Connection::Ptr connection() const override; + + private: + friend class Manager; + + class Private; + QScopedPointer d; + }; + + class Manager; + class Pad : public TransportManagerPad { + Q_OBJECT + // TODO + public: + typedef QSharedPointer Ptr; + + Pad(Manager *manager, Session *session); + QString ns() const override; + Session * session() const override; + TransportManager *manager() const override; + + Connection::Ptr makeConnection(const QString &sid, size_t blockSize); + + private: + Manager *_manager = nullptr; + Session *_session = nullptr; + }; + + class Manager : public TransportManager { + Q_OBJECT + public: + Manager(QObject *parent = nullptr); + ~Manager(); + + XMPP::Jingle::Transport::Features features() const override; + void setJingleManager(XMPP::Jingle::Manager *jm) override; + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) + override; // outgoing. one have to call Transport::start to collect candidates + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, + const QDomElement &transportEl) override; // incoming + TransportManagerPad * pad(Session *session) override; + + void closeAll() override; + + Connection::Ptr makeConnection(const Jid &peer, const QString &sid, size_t blockSize); + bool handleIncoming(IBBConnection *c); + + private: + class Private; + QScopedPointer d; + }; } // namespace IBB } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-s5b.cpp b/src/xmpp/xmpp-im/jingle-s5b.cpp index c0e394e6..ff155e2b 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.cpp +++ b/src/xmpp/xmpp-im/jingle-s5b.cpp @@ -30,1623 +30,1506 @@ #include #include -namespace XMPP { -namespace Jingle { -namespace S5B { -const QString NS(QStringLiteral("urn:xmpp:jingle:transports:s5b:1")); - -static QString makeKey(const QString &sid, const Jid &j1, const Jid &j2) -{ - return QString::fromLatin1(QCryptographicHash::hash((sid + - j1.full() + - j2.full()).toUtf8(), - QCryptographicHash::Sha1) - .toHex()); -} - -class Connection : public XMPP::Jingle::Connection -{ - Q_OBJECT - - QList datagrams; - SocksClient *client; - Transport::Mode mode; -public: - Connection(SocksClient *client, Transport::Mode mode) : - client(client), - mode(mode) - { - connect(client, &SocksClient::readyRead, this, &Connection::readyRead); - connect(client, &SocksClient::bytesWritten, this, &Connection::bytesWritten); - connect(client, &SocksClient::aboutToClose, this, &Connection::aboutToClose); - if (client->isOpen()) { - setOpenMode(client->openMode()); - } else { - qWarning("Creating S5B Transport connection on closed SockClient connection %p", client); - } - } +namespace XMPP { namespace Jingle { namespace S5B { + const QString NS(QStringLiteral("urn:xmpp:jingle:transports:s5b:1")); - bool hasPendingDatagrams() const + static QString makeKey(const QString &sid, const Jid &j1, const Jid &j2) { - return datagrams.size() > 0; + return QString::fromLatin1( + QCryptographicHash::hash((sid + j1.full() + j2.full()).toUtf8(), QCryptographicHash::Sha1).toHex()); } - NetworkDatagram receiveDatagram(qint64 maxSize = -1) - { - Q_UNUSED(maxSize); // TODO or not? - return datagrams.size()? datagrams.takeFirst(): NetworkDatagram(); - } + class Connection : public XMPP::Jingle::Connection { + Q_OBJECT - qint64 bytesAvailable() const - { - if(client) - return client->bytesAvailable(); - else - return 0; - } + QList datagrams; + SocksClient * client; + Transport::Mode mode; - qint64 bytesToWrite() const - { - return client->bytesToWrite(); - } + public: + Connection(SocksClient *client, Transport::Mode mode) : client(client), mode(mode) + { + connect(client, &SocksClient::readyRead, this, &Connection::readyRead); + connect(client, &SocksClient::bytesWritten, this, &Connection::bytesWritten); + connect(client, &SocksClient::aboutToClose, this, &Connection::aboutToClose); + if (client->isOpen()) { + setOpenMode(client->openMode()); + } else { + qWarning("Creating S5B Transport connection on closed SockClient connection %p", client); + } + } - void close() - { - if (client) { - client->disconnect(this); + bool hasPendingDatagrams() const { return datagrams.size() > 0; } + + NetworkDatagram receiveDatagram(qint64 maxSize = -1) + { + Q_UNUSED(maxSize); // TODO or not? + return datagrams.size() ? datagrams.takeFirst() : NetworkDatagram(); } - XMPP::Jingle::Connection::close(); - client->deleteLater(); - client = nullptr; - } -protected: - qint64 writeData(const char *data, qint64 maxSize) - { - if(mode == Transport::Tcp) - return client->write(data, maxSize); - return 0; - } + qint64 bytesAvailable() const + { + if (client) + return client->bytesAvailable(); + else + return 0; + } - qint64 readData(char *data, qint64 maxSize) - { - if(client) - return client->read(data, maxSize); - else + qint64 bytesToWrite() const { return client->bytesToWrite(); } + + void close() + { + if (client) { + client->disconnect(this); + } + XMPP::Jingle::Connection::close(); + client->deleteLater(); + client = nullptr; + } + + protected: + qint64 writeData(const char *data, qint64 maxSize) + { + if (mode == Transport::Tcp) + return client->write(data, maxSize); return 0; - } + } -private: - friend class Transport; - void enqueueIncomingUDP(const QByteArray &data) - { - datagrams.append(NetworkDatagram{data}); - emit readyRead(); - } -}; + qint64 readData(char *data, qint64 maxSize) + { + if (client) + return client->read(data, maxSize); + else + return 0; + } -class V6LinkLocalSocksConnector : public QObject -{ - Q_OBJECT + private: + friend class Transport; + void enqueueIncomingUDP(const QByteArray &data) + { + datagrams.append(NetworkDatagram { data }); + emit readyRead(); + } + }; - QMap clients; - SocksClient *client = nullptr; -public: - using QObject::QObject; + class V6LinkLocalSocksConnector : public QObject { + Q_OBJECT - void connectToHost(const QHostAddress &proxyHost, int proxyPort, const QString &host, bool udpMode) - { - foreach(const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) + QMap clients; + SocksClient * client = nullptr; + + public: + using QObject::QObject; + + void connectToHost(const QHostAddress &proxyHost, int proxyPort, const QString &host, bool udpMode) { - if (!(ni.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning))) { - continue; - } - if (ni.flags() & QNetworkInterface::IsLoopBack) { - continue; - } - QList entries = ni.addressEntries(); - foreach(const QNetworkAddressEntry &na, entries) - { - QHostAddress ha = na.ip(); - if (ha.protocol() == QAbstractSocket::IPv6Protocol && - #if QT_VERSION >= QT_VERSION_CHECK(5,11,0) + foreach (const QNetworkInterface &ni, QNetworkInterface::allInterfaces()) { + if (!(ni.flags() & (QNetworkInterface::IsUp | QNetworkInterface::IsRunning))) { + continue; + } + if (ni.flags() & QNetworkInterface::IsLoopBack) { + continue; + } + QList entries = ni.addressEntries(); + foreach (const QNetworkAddressEntry &na, entries) { + QHostAddress ha = na.ip(); + if (ha.protocol() == QAbstractSocket::IPv6Protocol && +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) ha.isLinkLocal() - #else +#else XMPP::Ice176::isIPv6LinkLocalAddress(ha) - #endif - ) // && proxyHost.isInSubnet(ha, na.prefixLength()) - { - auto client = new SocksClient(this); - clients.insert(ni.name(), client); - break; +#endif + ) // && proxyHost.isInSubnet(ha, na.prefixLength()) + { + auto client = new SocksClient(this); + clients.insert(ni.name(), client); + break; + } } } - } - - if (!clients.size()) { - emit ready(); - return; - } - QHostAddress ph(proxyHost); - for (auto it = clients.begin(); it != clients.end(); ++it) { - QString name = it.key(); - SocksClient *client = it.value(); - connect(client, &SocksClient::connected, this, [this, name, client](){ - this->client = client; - clients.remove(name); - qDeleteAll(clients); + if (!clients.size()) { emit ready(); - }); - connect(client, &SocksClient::error, this, [this, name, client](int error){ - Q_UNUSED(error); - clients.remove(name); - delete client; - if (clients.isEmpty()) { + return; + } + + QHostAddress ph(proxyHost); + for (auto it = clients.begin(); it != clients.end(); ++it) { + QString name = it.key(); + SocksClient *client = it.value(); + connect(client, &SocksClient::connected, this, [this, name, client]() { + this->client = client; + clients.remove(name); + qDeleteAll(clients); emit ready(); - } - }, Qt::QueuedConnection); - ph.setScopeId(name); - client->connectToHost(ph.toString(), proxyPort, host, 0, udpMode); + }); + connect( + client, &SocksClient::error, this, + [this, name, client](int error) { + Q_UNUSED(error); + clients.remove(name); + delete client; + if (clients.isEmpty()) { + emit ready(); + } + }, + Qt::QueuedConnection); + ph.setScopeId(name); + client->connectToHost(ph.toString(), proxyPort, host, 0, udpMode); + } } - } - SocksClient* takeClient() - { - auto c = client; - if (c) { - c->setParent(nullptr); - client = nullptr; + SocksClient *takeClient() + { + auto c = client; + if (c) { + c->setParent(nullptr); + client = nullptr; + } + return c; } - return c; - } -signals: - void ready(); -}; + signals: + void ready(); + }; -class Candidate::Private : public QObject, public QSharedData { - Q_OBJECT -public: - ~Private() - { - if (server && transport) { - server->unregisterKey(transport->directAddr()); + class Candidate::Private : public QObject, public QSharedData { + Q_OBJECT + public: + ~Private() + { + if (server && transport) { + server->unregisterKey(transport->directAddr()); + } + delete socksClient; } - delete socksClient; - } - QPointer transport; - QString cid; - QString host; - Jid jid; - quint16 port = 0; - quint32 priority = 0; - Candidate::Type type = Candidate::Direct; - Candidate::State state = Candidate::New; + QPointer transport; + QString cid; + QString host; + Jid jid; + quint16 port = 0; + quint32 priority = 0; + Candidate::Type type = Candidate::Direct; + Candidate::State state = Candidate::New; - QSharedPointer server; - SocksClient *socksClient = nullptr; + QSharedPointer server; + SocksClient * socksClient = nullptr; - void connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp) - { - QHostAddress ha(host); - if (!ha.isNull() && ha.protocol() == QAbstractSocket::IPv6Protocol && ha.scopeId().isEmpty() && - #if QT_VERSION >= QT_VERSION_CHECK(5,11,0) + void connectToHost(const QString &key, State successState, QObject *callbackContext, + std::function callback, bool isUdp) + { + QHostAddress ha(host); + if (!ha.isNull() && ha.protocol() == QAbstractSocket::IPv6Protocol && ha.scopeId().isEmpty() && +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) ha.isLinkLocal() - #else +#else XMPP::Ice176::isIPv6LinkLocalAddress(ha) - #endif - ) - { - qDebug() << "connect to host with cid=" << cid << "and key=" << key << "candidate using V6LinkLocalSocksConnector"; - // we have link local address without scope. We have to enumerate all possible scopes. - auto v6llConnector = new V6LinkLocalSocksConnector(this); - connect(v6llConnector, &V6LinkLocalSocksConnector::ready, this, [this, v6llConnector, callback, successState]() { - socksClient = v6llConnector->takeClient(); - delete v6llConnector; - if (state == Candidate::Discarded) { - return; - } +#endif + ) { + qDebug() << "connect to host with cid=" << cid << "and key=" << key + << "candidate using V6LinkLocalSocksConnector"; + // we have link local address without scope. We have to enumerate all possible scopes. + auto v6llConnector = new V6LinkLocalSocksConnector(this); + connect(v6llConnector, &V6LinkLocalSocksConnector::ready, this, + [this, v6llConnector, callback, successState]() { + socksClient = v6llConnector->takeClient(); + delete v6llConnector; + if (state == Candidate::Discarded) { + return; + } - if (socksClient) { + if (socksClient) { + state = successState; + qDebug() << "socks client" << socksClient << "is connected"; + callback(true); + return; + } + state = Candidate::Discarded; + qDebug() << "socks client" << socksClient << "failed to connect"; + callback(false); + }); + v6llConnector->connectToHost(ha, port, key, isUdp); + } else { + socksClient = new SocksClient; + qDebug() << "connect to host with cid=" << cid << ", key=" << key << " and socks client" << socksClient; + connect(socksClient, &SocksClient::connected, callbackContext, [this, callback, successState]() { state = successState; - qDebug() << "socks client" << socksClient << "is connected"; + qDebug() << "socks client" << socksClient << "is connected"; callback(true); - return; - } - state = Candidate::Discarded; - qDebug() << "socks client" << socksClient << "failed to connect"; - callback(false); - }); - v6llConnector->connectToHost(ha, port, key, isUdp); - } else { - socksClient = new SocksClient; - qDebug() << "connect to host with cid=" << cid << ", key=" << key << " and socks client" << socksClient; - connect(socksClient, &SocksClient::connected, callbackContext, [this, callback, successState](){ - state = successState; - qDebug() << "socks client" << socksClient << "is connected"; - callback(true); - }); - connect(socksClient, &SocksClient::error, callbackContext, [this, callback](int error){ + }); + connect(socksClient, &SocksClient::error, callbackContext, [this, callback](int error) { + Q_UNUSED(error); + state = Candidate::Discarded; + qDebug() << "socks client" << socksClient << "failed to connect"; + callback(false); + }); + // connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); + + socksClient->connectToHost(host, port, key, 0, isUdp); + } + } + + void setupIncomingSocksClient() + { + connect(socksClient, &SocksClient::error, [this](int error) { Q_UNUSED(error); state = Candidate::Discarded; - qDebug() << "socks client" << socksClient << "failed to connect"; - callback(false); }); - //connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); - - socksClient->connectToHost(host, port, key, 0, isUdp); } - } + }; + + Candidate::Candidate() {} - void setupIncomingSocksClient() + Candidate::Candidate(Transport *transport, const QDomElement &el) { - connect(socksClient, &SocksClient::error, [this](int error){ - Q_UNUSED(error); - state = Candidate::Discarded; - }); - } -}; - -Candidate::Candidate() -{ - -} - -Candidate::Candidate(Transport *transport, const QDomElement &el) -{ - bool ok; - QString host(el.attribute(QStringLiteral("host"))); - Jid jid(el.attribute(QStringLiteral("jid"))); - auto portStr = el.attribute(QStringLiteral("port")); - quint16 port = 0; - if (!portStr.isEmpty()) { - port = portStr.toUShort(&ok); + bool ok; + QString host(el.attribute(QStringLiteral("host"))); + Jid jid(el.attribute(QStringLiteral("jid"))); + auto portStr = el.attribute(QStringLiteral("port")); + quint16 port = 0; + if (!portStr.isEmpty()) { + port = portStr.toUShort(&ok); + if (!ok) { + return; // make the whole candidate invalid + } + } + auto priorityStr = el.attribute(QStringLiteral("priority")); + if (priorityStr.isEmpty()) { + return; + } + quint32 priority = priorityStr.toUInt(&ok); if (!ok) { return; // make the whole candidate invalid } - } - auto priorityStr = el.attribute(QStringLiteral("priority")); - if (priorityStr.isEmpty()) { - return; - } - quint32 priority = priorityStr.toUInt(&ok); - if (!ok) { - return; // make the whole candidate invalid - } - QString cid = el.attribute(QStringLiteral("cid")); - if (cid.isEmpty()) { - return; - } + QString cid = el.attribute(QStringLiteral("cid")); + if (cid.isEmpty()) { + return; + } - QString ct = el.attribute(QStringLiteral("type")); - if (ct.isEmpty()) { - ct = QStringLiteral("direct"); - } - static QMap types{{QStringLiteral("assisted"), Assisted}, - {QStringLiteral("direct"), Direct}, - {QStringLiteral("proxy"), Proxy}, - {QStringLiteral("tunnel"), Tunnel} - }; - auto candidateType = types.value(ct); - if (ct.isEmpty() || candidateType == None) { - return; + QString ct = el.attribute(QStringLiteral("type")); + if (ct.isEmpty()) { + ct = QStringLiteral("direct"); + } + static QMap types { { QStringLiteral("assisted"), Assisted }, + { QStringLiteral("direct"), Direct }, + { QStringLiteral("proxy"), Proxy }, + { QStringLiteral("tunnel"), Tunnel } }; + auto candidateType = types.value(ct); + if (ct.isEmpty() || candidateType == None) { + return; + } + + if ((candidateType == Proxy && !jid.isValid()) || (candidateType != Proxy && (host.isEmpty() || !port))) { + return; + } + + auto d = new Private; + d->transport = transport; + d->cid = cid; + d->host = host; + d->jid = jid; + d->port = port; + d->priority = priority; + d->type = candidateType; + d->state = New; + this->d = d; } - if ((candidateType == Proxy && !jid.isValid()) || - (candidateType != Proxy && (host.isEmpty() || !port))) + Candidate::Candidate(const Candidate &other) : d(other.d) {} + + Candidate::Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference) : + d(new Private) { - return; + d->transport = transport; + d->cid = cid; + d->jid = proxy; + d->priority = (ProxyPreference << 16) + localPreference; + d->type = Proxy; + d->state = Probing; // it's probing because it's a local side proxy and host and port are unknown } - auto d = new Private; - d->transport = transport; - d->cid = cid; - d->host = host; - d->jid = jid; - d->port = port; - d->priority = priority; - d->type = candidateType; - d->state = New; - this->d = d; -} - -Candidate::Candidate(const Candidate &other) : - d(other.d) -{ - -} - -Candidate::Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference) : - d(new Private) -{ - d->transport = transport; - d->cid = cid; - d->jid = proxy; - d->priority = (ProxyPreference << 16) + localPreference; - d->type = Proxy; - d->state = Probing; // it's probing because it's a local side proxy and host and port are unknown -} - -Candidate::Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, quint16 localPreference) : - d(new Private) -{ - Type type = None; - switch (server->portType()) { - case TcpPortServer::Direct: - type = Candidate::Direct; - break; - case TcpPortServer::NatAssited: - type = Candidate::Assisted; - break; - case TcpPortServer::Tunneled: - type = Candidate::Tunnel; - break; - case TcpPortServer::NoType: - default: - type = None; - } + Candidate::Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, + quint16 localPreference) : + d(new Private) + { + Type type = None; + switch (server->portType()) { + case TcpPortServer::Direct: + type = Candidate::Direct; + break; + case TcpPortServer::NatAssited: + type = Candidate::Assisted; + break; + case TcpPortServer::Tunneled: + type = Candidate::Tunnel; + break; + case TcpPortServer::NoType: + default: + type = None; + } - if (type == None) { - d.reset(); - return; - } + if (type == None) { + d.reset(); + return; + } - d->transport = transport; - d->server = server.staticCast(); - d->cid = cid; - d->host = server->publishHost(); - d->port = server->publishPort(); - d->type = type; - static const int priorities[] = {0, ProxyPreference, TunnelPreference, AssistedPreference, DirectPreference}; - if (type >= Type(0) && type <= Direct) { - d->priority = (priorities[type] << 16) + localPreference; - } else { - d->priority = 0; - } + d->transport = transport; + d->server = server.staticCast(); + d->cid = cid; + d->host = server->publishHost(); + d->port = server->publishPort(); + d->type = type; + static const int priorities[] = { 0, ProxyPreference, TunnelPreference, AssistedPreference, DirectPreference }; + if (type >= Type(0) && type <= Direct) { + d->priority = (priorities[type] << 16) + localPreference; + } else { + d->priority = 0; + } - d->state = New; -} - -Candidate::~Candidate() -{ -} - -Candidate::Type Candidate::type() const -{ - return d->type; -} - -QString Candidate::cid() const -{ - return d->cid; -} - -Jid Candidate::jid() const -{ - return d->jid; -} - -QString Candidate::host() const -{ - return d->host; -} - -void Candidate::setHost(const QString &host) -{ - d->host = host; -} - -quint16 Candidate::port() const -{ - return d->port; -} - -void Candidate::setPort(quint16 port) -{ - d->port = port; -} - -quint16 Candidate::localPort() const -{ - return d->server ? d->server->serverPort() : 0; -} - -QHostAddress Candidate::localAddress() const -{ - return d->server ? d->server->serverAddress() : QHostAddress(); -} - -Candidate::State Candidate::state() const -{ - return d->state; -} - -void Candidate::setState(Candidate::State s) -{ - // don't close sockets here since pending events may change state machine or remote side and closed socket may break it - d->state = s; -} - -const char *Candidate::stateText(Candidate::State s) -{ - switch (s) { - case New: return "New"; - case Probing: return "Probing"; - case Pending: return "Pending"; - case Unacked: return "Unacked"; - case Accepted: return "Accepted"; - case Active: return "Active"; - case Discarded: return "Discarded"; - } - return nullptr; -} - -quint32 Candidate::priority() const -{ - return d->priority; -} - -QDomElement Candidate::toXml(QDomDocument *doc) const -{ - auto e = doc->createElement(QStringLiteral("candidate")); - e.setAttribute(QStringLiteral("cid"), d->cid); - if (d->type == Proxy) { - e.setAttribute(QStringLiteral("jid"), d->jid.full()); + d->state = New; } - if (!d->host.isEmpty() && d->port) { - e.setAttribute(QStringLiteral("host"), d->host); - e.setAttribute(QStringLiteral("port"), d->port); - } - e.setAttribute(QStringLiteral("priority"), d->priority); - static const char *types[] = {"proxy", "tunnel", "assisted"}; // same order as in enum - if (d->type && d->type < Direct) { - e.setAttribute(QStringLiteral("type"), QLatin1String(types[d->type - 1])); - } - return e; -} - -void Candidate::connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp) -{ - d->connectToHost(key, successState, callbackContext, callback, isUdp); -} - -bool Candidate::incomingConnection(SocksClient *sc) -{ - qDebug() << "incoming connection on" << d->cid << "candidate with socks client" << sc; - if (d->socksClient) { - return false; + Candidate::~Candidate() {} + + Candidate::Type Candidate::type() const { return d->type; } + + QString Candidate::cid() const { return d->cid; } + + Jid Candidate::jid() const { return d->jid; } + + QString Candidate::host() const { return d->host; } + + void Candidate::setHost(const QString &host) { d->host = host; } + + quint16 Candidate::port() const { return d->port; } + + void Candidate::setPort(quint16 port) { d->port = port; } + + quint16 Candidate::localPort() const { return d->server ? d->server->serverPort() : 0; } + + QHostAddress Candidate::localAddress() const { return d->server ? d->server->serverAddress() : QHostAddress(); } + + Candidate::State Candidate::state() const { return d->state; } + + void Candidate::setState(Candidate::State s) + { + // don't close sockets here since pending events may change state machine or remote side and closed socket may + // break it + d->state = s; } - d->socksClient = sc; - d->setupIncomingSocksClient(); - return true; -} - -SocksClient *Candidate::takeSocksClient() -{ - qDebug() << "taking socks client" << d->socksClient << "from " << d->cid << "candidate"; - if (!d->socksClient) { + + const char *Candidate::stateText(Candidate::State s) + { + switch (s) { + case New: + return "New"; + case Probing: + return "Probing"; + case Pending: + return "Pending"; + case Unacked: + return "Unacked"; + case Accepted: + return "Accepted"; + case Active: + return "Active"; + case Discarded: + return "Discarded"; + } return nullptr; } - auto c = d->socksClient; - d->socksClient = nullptr; - d->disconnect(c); - return c; -} - -void Candidate::deleteSocksClient() -{ - if (d->socksClient) { - d->socksClient->disconnect(); - delete d->socksClient; - d->socksClient = nullptr; + + quint32 Candidate::priority() const { return d->priority; } + + QDomElement Candidate::toXml(QDomDocument *doc) const + { + auto e = doc->createElement(QStringLiteral("candidate")); + e.setAttribute(QStringLiteral("cid"), d->cid); + if (d->type == Proxy) { + e.setAttribute(QStringLiteral("jid"), d->jid.full()); + } + if (!d->host.isEmpty() && d->port) { + e.setAttribute(QStringLiteral("host"), d->host); + e.setAttribute(QStringLiteral("port"), d->port); + } + e.setAttribute(QStringLiteral("priority"), d->priority); + + static const char *types[] = { "proxy", "tunnel", "assisted" }; // same order as in enum + if (d->type && d->type < Direct) { + e.setAttribute(QStringLiteral("type"), QLatin1String(types[d->type - 1])); + } + return e; } -} - -TcpPortServer::Ptr Candidate::server() const -{ - return d->server.staticCast(); -} - -bool Candidate::operator==(const Candidate &other) const -{ - return d.data() == other.d.data(); -} - -class Transport::Private -{ -public: - enum PendingActions { - NewCandidate = 1, - CandidateUsed = 2, - CandidateError = 4, - Activated = 8, - ProxyError = 16 - }; - Transport *q = nullptr; - Pad::Ptr pad; - bool meCreator = true; // content created on local side - bool transportStarted = false; // where start() was called - bool offerSent = false; - bool waitingAck = true; - bool aborted = false; - bool remoteReportedCandidateError = false; - bool localReportedCandidateError = false; - bool proxyDiscoveryInProgress = false; // if we have valid proxy requests - quint16 pendingActions = 0; - int proxiesInDiscoCount = 0; - Application *application = nullptr; - QMap localCandidates; // cid to candidate mapping - QMap remoteCandidates; - Candidate localUsedCandidate; // we received "candidate-used" for this candidate from localCandidates list - Candidate remoteUsedCandidate; // we sent "candidate-used" for this candidate from remoteCandidates list - QString dstaddr; // an address for xmpp proxy as it comes from remote. each side calculates it like sha1(sid + local jid + remote jid) - QString directAddr; // like dstaddr but for direct connection. Basically it's sha1(sid + initiator jid + responder jid) - QString sid; - Transport::Mode mode = Transport::Tcp; - QTimer probingTimer; - QElapsedTimer lastConnectionStart; - size_t blockSize = 8192; - TcpPortDiscoverer *disco = nullptr; - - QSharedPointer connection; - - // udp stuff - bool udpInitialized; - quint16 udpPort; - QHostAddress udpAddress; - - inline Jid remoteJid() const + void Candidate::connectToHost(const QString &key, State successState, QObject *callbackContext, + std::function callback, bool isUdp) { - return pad->session()->peer(); + d->connectToHost(key, successState, callbackContext, callback, isUdp); } - QString generateCid() const + bool Candidate::incomingConnection(SocksClient *sc) { - QString cid; - do { - cid = QString("%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - } while (localCandidates.contains(cid) || remoteCandidates.contains(cid)); - return cid; + qDebug() << "incoming connection on" << d->cid << "candidate with socks client" << sc; + if (d->socksClient) { + return false; + } + d->socksClient = sc; + d->setupIncomingSocksClient(); + return true; } - bool isDup(const Candidate &c) const + SocksClient *Candidate::takeSocksClient() { - for (auto const &rc: remoteCandidates) { - if (c.host() == rc.host() && c.port() == rc.port()) { - return true; - } + qDebug() << "taking socks client" << d->socksClient << "from " << d->cid << "candidate"; + if (!d->socksClient) { + return nullptr; } - return false; + auto c = d->socksClient; + d->socksClient = nullptr; + d->disconnect(c); + return c; } - void discoS5BProxy() + void Candidate::deleteSocksClient() { - auto m = static_cast(pad->manager()); - Jid proxy = m->userProxy(); - if (proxy.isValid()) { - Candidate c(q, proxy, generateCid()); - if (!isDup(c)) { - localCandidates.insert(c.cid(), c); + if (d->socksClient) { + d->socksClient->disconnect(); + delete d->socksClient; + d->socksClient = nullptr; + } + } + + TcpPortServer::Ptr Candidate::server() const { return d->server.staticCast(); } + + bool Candidate::operator==(const Candidate &other) const { return d.data() == other.d.data(); } + + class Transport::Private { + public: + enum PendingActions { NewCandidate = 1, CandidateUsed = 2, CandidateError = 4, Activated = 8, ProxyError = 16 }; + + Transport * q = nullptr; + Pad::Ptr pad; + bool meCreator = true; // content created on local side + bool transportStarted = false; // where start() was called + bool offerSent = false; + bool waitingAck = true; + bool aborted = false; + bool remoteReportedCandidateError = false; + bool localReportedCandidateError = false; + bool proxyDiscoveryInProgress = false; // if we have valid proxy requests + quint16 pendingActions = 0; + int proxiesInDiscoCount = 0; + Application * application = nullptr; + QMap localCandidates; // cid to candidate mapping + QMap remoteCandidates; + Candidate localUsedCandidate; // we received "candidate-used" for this candidate from localCandidates list + Candidate remoteUsedCandidate; // we sent "candidate-used" for this candidate from remoteCandidates list + QString dstaddr; // an address for xmpp proxy as it comes from remote. each side calculates it like sha1(sid + + // local jid + remote jid) + QString directAddr; // like dstaddr but for direct connection. Basically it's sha1(sid + initiator jid + + // responder jid) + QString sid; + Transport::Mode mode = Transport::Tcp; + QTimer probingTimer; + QElapsedTimer lastConnectionStart; + size_t blockSize = 8192; + TcpPortDiscoverer *disco = nullptr; + + QSharedPointer connection; + + // udp stuff + bool udpInitialized; + quint16 udpPort; + QHostAddress udpAddress; + + inline Jid remoteJid() const { return pad->session()->peer(); } + + QString generateCid() const + { + QString cid; + do { + cid = QString("%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + } while (localCandidates.contains(cid) || remoteCandidates.contains(cid)); + return cid; + } + + bool isDup(const Candidate &c) const + { + for (auto const &rc : remoteCandidates) { + if (c.host() == rc.host() && c.port() == rc.port()) { + return true; + } } + return false; } - proxyDiscoveryInProgress = true; - QList> featureOptions = {{"http://jabber.org/protocol/bytestreams"}}; - pad->session()->manager()->client()->serverInfoManager()-> - queryServiceInfo(QStringLiteral("proxy"), - QStringLiteral("bytestreams"), - featureOptions, - QRegExp("proxy.*|socks.*|stream.*|s5b.*"), - ServerInfoManager::SQ_CheckAllOnNoMatch, - [this](const QList &items) + void discoS5BProxy() { - if (!proxyDiscoveryInProgress) { // check if new results are ever/still expected - // seems like we have successful connection via higher priority channel. so nobody cares about proxy - return; + auto m = static_cast(pad->manager()); + Jid proxy = m->userProxy(); + if (proxy.isValid()) { + Candidate c(q, proxy, generateCid()); + if (!isDup(c)) { + localCandidates.insert(c.cid(), c); + } } - auto m = static_cast(pad->manager()); - Jid userProxy = m->userProxy(); - - // queries proxy's host/port and sends the candidate to remote - auto queryProxy = [this](const Jid &j, const QString &cid) { - proxiesInDiscoCount++; - auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); - connect(query, &JT_S5B::finished, q, [this,query,cid](){ - if (!proxyDiscoveryInProgress) { + + proxyDiscoveryInProgress = true; + QList> featureOptions = { { "http://jabber.org/protocol/bytestreams" } }; + pad->session()->manager()->client()->serverInfoManager()->queryServiceInfo( + QStringLiteral("proxy"), QStringLiteral("bytestreams"), featureOptions, + QRegExp("proxy.*|socks.*|stream.*|s5b.*"), ServerInfoManager::SQ_CheckAllOnNoMatch, + [this](const QList &items) { + if (!proxyDiscoveryInProgress) { // check if new results are ever/still expected + // seems like we have successful connection via higher priority channel. so nobody cares about + // proxy return; } - bool candidateUpdated = false; - auto c = localCandidates.value(cid); - if (c && c.state() == Candidate::Probing) { - auto sh = query->proxyInfo(); - if (query->success() && !sh.host().isEmpty() && sh.port()) { - // it can be discarded by this moment (e.g. got success on a higher priority candidate). - // so we have to check. - c.setHost(sh.host()); - c.setPort(sh.port()); - c.setState(Candidate::New); - candidateUpdated = true; - pendingActions |= Private::NewCandidate; - } else { - c.setState(Candidate::Discarded); + auto m = static_cast(pad->manager()); + Jid userProxy = m->userProxy(); + + // queries proxy's host/port and sends the candidate to remote + auto queryProxy = [this](const Jid &j, const QString &cid) { + proxiesInDiscoCount++; + auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); + connect(query, &JT_S5B::finished, q, [this, query, cid]() { + if (!proxyDiscoveryInProgress) { + return; + } + bool candidateUpdated = false; + auto c = localCandidates.value(cid); + if (c && c.state() == Candidate::Probing) { + auto sh = query->proxyInfo(); + if (query->success() && !sh.host().isEmpty() && sh.port()) { + // it can be discarded by this moment (e.g. got success on a higher priority + // candidate). so we have to check. + c.setHost(sh.host()); + c.setPort(sh.port()); + c.setState(Candidate::New); + candidateUpdated = true; + pendingActions |= Private::NewCandidate; + } else { + c.setState(Candidate::Discarded); + } + } + proxiesInDiscoCount--; + if (!proxiesInDiscoCount) { + proxyDiscoveryInProgress = false; + } + if (candidateUpdated) { + emit q->updated(); + } else if (!proxiesInDiscoCount) { + // it's possible it was our last hope and probaby we have to send candidate-error now. + checkAndFinishNegotiation(); + } + }); + query->requestProxyInfo(j); + query->go(true); + }; + + bool userProxyFound = !userProxy.isValid(); + for (const auto i : items) { + int localPref = 0; + if (!userProxyFound && i.jid() == userProxy) { + localPref = 1; + userProxyFound = true; } + Candidate c(q, i.jid(), generateCid(), localPref); + localCandidates.insert(c.cid(), c); + + queryProxy(i.jid(), c.cid()); } - proxiesInDiscoCount--; - if (!proxiesInDiscoCount) { + if (!userProxyFound) { + Candidate c(q, userProxy, generateCid(), 1); + localCandidates.insert(c.cid(), c); + queryProxy(userProxy, c.cid()); + } else if (items.count() == 0) { + // seems like we don't have any proxy proxyDiscoveryInProgress = false; - } - if (candidateUpdated) { - emit q->updated(); - } else if (!proxiesInDiscoCount) { - // it's possible it was our last hope and probaby we have to send candidate-error now. checkAndFinishNegotiation(); } }); - query->requestProxyInfo(j); - query->go(true); - }; - - bool userProxyFound = !userProxy.isValid(); - for (const auto i: items) { - int localPref = 0; - if (!userProxyFound && i.jid() == userProxy) { - localPref = 1; - userProxyFound = true; - } - Candidate c(q, i.jid(), generateCid(), localPref); - localCandidates.insert(c.cid(), c); + } - queryProxy(i.jid(), c.cid()); - } - if (!userProxyFound) { - Candidate c(q, userProxy, generateCid(), 1); - localCandidates.insert(c.cid(), c); - queryProxy(userProxy, c.cid()); - } else if (items.count() == 0) { - // seems like we don't have any proxy - proxyDiscoveryInProgress = false; - checkAndFinishNegotiation(); + void tryConnectToRemoteCandidate() + { + if (!transportStarted) { + return; // will come back later } - }); - } - - void tryConnectToRemoteCandidate() - { - if (!transportStarted) { - return; // will come back later - } - quint64 maxProbingPrio = 0; - quint64 maxNewPrio = 0; - Candidate maxProbing; - QList maxNew; // keeps highest (same) priority New candidates - - /* - We have to find highest-priority already connecting candidate and highest-priority new candidate. - If already-connecting is not found then start connecting to new if it's found. - If both already-connecting and new are found then - if new candidate has higher priority or the same priority then start connecting - else ensure the new candidate starts connecting in 200ms after previous connection attempt - (if it's in future then reschedule this call for future) - In all the other cases just return and wait for events. - */ - - qDebug("tryConnectToRemoteCandidate()"); - for (auto &c: remoteCandidates) { - if (c.state() == Candidate::New) { - if (c.priority() > maxNewPrio) { - maxNew = QList(); - maxNew.append(c); - maxNewPrio = c.priority(); - } else if (c.priority() == maxNewPrio) { - maxNew.append(c); + quint64 maxProbingPrio = 0; + quint64 maxNewPrio = 0; + Candidate maxProbing; + QList maxNew; // keeps highest (same) priority New candidates + + /* + We have to find highest-priority already connecting candidate and highest-priority new candidate. + If already-connecting is not found then start connecting to new if it's found. + If both already-connecting and new are found then + if new candidate has higher priority or the same priority then start connecting + else ensure the new candidate starts connecting in 200ms after previous connection attempt + (if it's in future then reschedule this call for future) + In all the other cases just return and wait for events. + */ + + qDebug("tryConnectToRemoteCandidate()"); + for (auto &c : remoteCandidates) { + if (c.state() == Candidate::New) { + if (c.priority() > maxNewPrio) { + maxNew = QList(); + maxNew.append(c); + maxNewPrio = c.priority(); + } else if (c.priority() == maxNewPrio) { + maxNew.append(c); + } + } + if (c.state() == Candidate::Probing && c.priority() > maxProbingPrio) { + maxProbing = c; + maxProbingPrio = c.priority(); } } - if (c.state() == Candidate::Probing && c.priority() > maxProbingPrio) { - maxProbing = c; - maxProbingPrio = c.priority(); + if (maxNew.isEmpty()) { + qDebug(" tryConnectToRemoteCandidate() no maxNew candidates"); + return; // nowhere to connect } - } - if (maxNew.isEmpty()) { - qDebug(" tryConnectToRemoteCandidate() no maxNew candidates"); - return; // nowhere to connect - } - // check if we have to hang on for a little if a higher priority candidate is Probing - if (maxProbing) { - if (maxNewPrio < maxProbing.priority()) { - if (probingTimer.isActive()) { - qDebug(" tryConnectToRemoteCandidate() timer is already active. let's wait"); - return; // we will come back here soon - } - qint64 msToFuture = 200 - lastConnectionStart.elapsed(); - if (msToFuture > 0) { // seems like we have to rescheduler for future - probingTimer.start(int(msToFuture)); - qDebug(" tryConnectToRemoteCandidate() too early. timer started. let's wait"); - return; + // check if we have to hang on for a little if a higher priority candidate is Probing + if (maxProbing) { + if (maxNewPrio < maxProbing.priority()) { + if (probingTimer.isActive()) { + qDebug(" tryConnectToRemoteCandidate() timer is already active. let's wait"); + return; // we will come back here soon + } + qint64 msToFuture = 200 - lastConnectionStart.elapsed(); + if (msToFuture > 0) { // seems like we have to rescheduler for future + probingTimer.start(int(msToFuture)); + qDebug(" tryConnectToRemoteCandidate() too early. timer started. let's wait"); + return; + } } } - } - probingTimer.start(200); // for the next candidate if any - - // now we have to connect to maxNew candidates - for (auto &mnc: maxNew) { - lastConnectionStart.start(); - QString key = mnc.type() == Candidate::Proxy? dstaddr : directAddr; - mnc.setState(Candidate::Probing); - mnc.connectToHost(key, Candidate::Pending, q, [this, mnc](bool success) { - // candidate's status had to be changed by connectToHost, so we don't set it again - if (success) { - // let's reject candidates which are meaningless to try - bool hasUnckeckedNew = false; - for (auto &c: remoteCandidates) { - if (c.state() == Candidate::New) { - if (c.priority() <= mnc.priority()) { - c.setState(Candidate::Discarded); - } else { - hasUnckeckedNew = true; + probingTimer.start(200); // for the next candidate if any + + // now we have to connect to maxNew candidates + for (auto &mnc : maxNew) { + lastConnectionStart.start(); + QString key = mnc.type() == Candidate::Proxy ? dstaddr : directAddr; + mnc.setState(Candidate::Probing); + mnc.connectToHost( + key, Candidate::Pending, q, + [this, mnc](bool success) { + // candidate's status had to be changed by connectToHost, so we don't set it again + if (success) { + // let's reject candidates which are meaningless to try + bool hasUnckeckedNew = false; + for (auto &c : remoteCandidates) { + if (c.state() == Candidate::New) { + if (c.priority() <= mnc.priority()) { + c.setState(Candidate::Discarded); + } else { + hasUnckeckedNew = true; + } + } + } + if (!hasUnckeckedNew) { + pendingActions + &= ~Private::NewCandidate; // just if we had it for example after proxy discovery } + setLocalProbingMinimalPreference(mnc.priority() >> 16); + updateMinimalPriority(); } - } - if (!hasUnckeckedNew) { - pendingActions &= ~Private::NewCandidate; // just if we had it for example after proxy discovery - } - setLocalProbingMinimalPreference(mnc.priority() >> 16); - updateMinimalPriority(); - } - checkAndFinishNegotiation(); - }, mode == Transport::Udp); - } - } - - /** - * @brief limitTcpDiscoByMinimalPreference take upper part of candidate preference (type preference) - * and drops lower priority pending local servers disco - * @param preference - */ - void setLocalProbingMinimalPreference(quint32 preference) - { - if (proxyDiscoveryInProgress && preference > Candidate::ProxyPreference) { - proxyDiscoveryInProgress = false; // doesn't make sense anymore + checkAndFinishNegotiation(); + }, + mode == Transport::Udp); + } } - // and now local ports discoverer.. - if (!disco) { - return; - } - TcpPortServer::PortTypes types = TcpPortServer::Direct; - if (preference >= Candidate::AssistedPreference) { - types |= TcpPortServer::NatAssited; - } - if (preference >= Candidate::TunnelPreference) { - types |= TcpPortServer::Tunneled; - } - if (!disco->setTypeMask(types)) { - delete disco; - disco = nullptr; - } - } + /** + * @brief limitTcpDiscoByMinimalPreference take upper part of candidate preference (type preference) + * and drops lower priority pending local servers disco + * @param preference + */ + void setLocalProbingMinimalPreference(quint32 preference) + { + if (proxyDiscoveryInProgress && preference > Candidate::ProxyPreference) { + proxyDiscoveryInProgress = false; // doesn't make sense anymore + } - bool hasUnaknowledgedLocalCandidates() const - { - // now ensure all local were sent to remote and no hope left - if (proxyDiscoveryInProgress || (disco && !disco->isDepleted())) { - return true; + // and now local ports discoverer.. + if (!disco) { + return; + } + TcpPortServer::PortTypes types = TcpPortServer::Direct; + if (preference >= Candidate::AssistedPreference) { + types |= TcpPortServer::NatAssited; + } + if (preference >= Candidate::TunnelPreference) { + types |= TcpPortServer::Tunneled; + } + if (!disco->setTypeMask(types)) { + delete disco; + disco = nullptr; + } } - // now local candidates - for (const auto &c: localCandidates) { - auto s = c.state(); - if (s == Candidate::Probing || s == Candidate::New || s == Candidate::Unacked) { + bool hasUnaknowledgedLocalCandidates() const + { + // now ensure all local were sent to remote and no hope left + if (proxyDiscoveryInProgress || (disco && !disco->isDepleted())) { return true; } - } - return false; - } - - Candidate preferredUsedCandidate() const - { - if (localUsedCandidate) { - if (remoteUsedCandidate) { - if (localUsedCandidate.priority() == remoteUsedCandidate.priority()) { - if (pad->session()->role() == Origin::Initiator) { - return remoteUsedCandidate; - } - return localUsedCandidate; + // now local candidates + for (const auto &c : localCandidates) { + auto s = c.state(); + if (s == Candidate::Probing || s == Candidate::New || s == Candidate::Unacked) { + return true; } - return localUsedCandidate.priority() > remoteUsedCandidate.priority()? - localUsedCandidate : remoteUsedCandidate; } - return localUsedCandidate; - } - return remoteUsedCandidate; - } - void checkAndFinishNegotiation() - { - // Why we can't send candidate-used/error right when this happens: - // so the situation: we discarded all remote candidates (failed to connect) - // but we have some local candidates which are still in Probing state (upnp for example) - // if we send candidate-error while we have unsent candidates this may trigger transport failure. - // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more - // local candidates are expected to be discovered - - if (!transportStarted || connection) { // if not started or already finished - qDebug("checkAndFinishNegotiation not finished: !connectionStarted || connection"); - return; + return false; } - // sort out already handled states or states which will bring us here a little later - if (waitingAck || pendingActions || hasUnaknowledgedLocalCandidates()) + Candidate preferredUsedCandidate() const { - // waitingAck some query waits for ack and in the callback this func will be called again - // pendingActions means we reported to app we have data to send but the app didn't take this data yet, - // but as soon as it's taken it will switch to waitingAck. - // And with unacknowledged local candidates we can't send used/error as well as report connected()/failure() - // until tried them all - qDebug("checkAndFinishNegotiation not finished: waitingAck=%d || pendingActions=%x || hasUnaknowledgedLocalCandidates()=%d", - int(waitingAck), int(pendingActions), int(hasUnaknowledgedLocalCandidates())); - return; - } - - // if we already sent used/error. In other words if we already have finished local part of negotiation - if (localReportedCandidateError || remoteUsedCandidate) { - // maybe it's time to report connected()/failure() - if (remoteReportedCandidateError || localUsedCandidate) { - // so remote seems to be finished too. - // tell application about it and it has to change its state immediatelly - auto c = preferredUsedCandidate(); - if (c) { - if (c.state() != Candidate::Active) { - if (c.type() == Candidate::Proxy) { // local proxy - // If it's proxy, first it has to be activated - if (c == localUsedCandidate) { - // it's our side who proposed proxy. so we have to connect to it and activate - auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); - c.connectToHost(key, Candidate::Accepted, q, [this](bool success){ - if (!success) { - pendingActions |= Private::ProxyError; - emit q->updated(); - return; - } - - auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); - connect(query, &JT_S5B::finished, q, [this,query]() { - Q_ASSERT(localUsedCandidate.state() == Candidate::Accepted); - if (!query->success()) { - pendingActions |= Private::ProxyError; - emit q->updated(); - return; - } - pendingActions |= Private::Activated; - localUsedCandidate.setState(Candidate::Active); - emit q->updated(); - handleConnected(localUsedCandidate); - }); - query->requestActivation(localUsedCandidate.jid(), sid, pad->session()->peer()); - query->go(true); - }, mode == Transport::Udp); - } // else so it's remote proxy. let's just wait for from remote - } else { - c.setState(Candidate::Active); + if (localUsedCandidate) { + if (remoteUsedCandidate) { + if (localUsedCandidate.priority() == remoteUsedCandidate.priority()) { + if (pad->session()->role() == Origin::Initiator) { + return remoteUsedCandidate; } + return localUsedCandidate; } - if (c.state() == Candidate::Active) { - handleConnected(c); - } - else qDebug("checkAndFinishNegotiation not finished: preferred is not Active"); - } else { // both sides reported candidate error - emit q->failed(); + return localUsedCandidate.priority() > remoteUsedCandidate.priority() ? localUsedCandidate + : remoteUsedCandidate; } - } // else we have to wait till remote reports its status - else qDebug("checkAndFinishNegotiation not finished: remote didn't reported yet"); - return; + return localUsedCandidate; + } + return remoteUsedCandidate; } - qDebug("checkAndFinishNegotiation not finished: trying to send condidate-used/error if any"); - // if we are here then neither candidate-used nor candidate-error was sent to remote, - // but we can send it now. - // first let's check if we can send candidate-used - bool allRemoteDiscarded = true; - bool hasConnectedRemoteCandidate = false; - for (const auto &c: remoteCandidates) { - auto s = c.state(); - qDebug() << " candidate " << c.cid() << " is " << Candidate::stateText(s); - if (s != Candidate::Discarded) { - allRemoteDiscarded = false; + void checkAndFinishNegotiation() + { + // Why we can't send candidate-used/error right when this happens: + // so the situation: we discarded all remote candidates (failed to connect) + // but we have some local candidates which are still in Probing state (upnp for example) + // if we send candidate-error while we have unsent candidates this may trigger transport failure. + // So for candidate-error two conditions have to be met 1) all remote failed 2) all local were sent no more + // local candidates are expected to be discovered + + if (!transportStarted || connection) { // if not started or already finished + qDebug("checkAndFinishNegotiation not finished: !connectionStarted || connection"); + return; } - if (s == Candidate::Pending) { // connected but not yet sent - hasConnectedRemoteCandidate = true; + + // sort out already handled states or states which will bring us here a little later + if (waitingAck || pendingActions || hasUnaknowledgedLocalCandidates()) { + // waitingAck some query waits for ack and in the callback this func will be called again + // pendingActions means we reported to app we have data to send but the app didn't take this data yet, + // but as soon as it's taken it will switch to waitingAck. + // And with unacknowledged local candidates we can't send used/error as well as report + // connected()/failure() until tried them all + qDebug("checkAndFinishNegotiation not finished: waitingAck=%d || pendingActions=%x || " + "hasUnaknowledgedLocalCandidates()=%d", + int(waitingAck), int(pendingActions), int(hasUnaknowledgedLocalCandidates())); + return; } - } - // if we have connection to remote candidate it's time to send it - if (hasConnectedRemoteCandidate) { - pendingActions |= Private::CandidateUsed; - qDebug("checkAndFinishNegotiation: used"); - emit q->updated(); - return; - } + // if we already sent used/error. In other words if we already have finished local part of negotiation + if (localReportedCandidateError || remoteUsedCandidate) { + // maybe it's time to report connected()/failure() + if (remoteReportedCandidateError || localUsedCandidate) { + // so remote seems to be finished too. + // tell application about it and it has to change its state immediatelly + auto c = preferredUsedCandidate(); + if (c) { + if (c.state() != Candidate::Active) { + if (c.type() == Candidate::Proxy) { // local proxy + // If it's proxy, first it has to be activated + if (c == localUsedCandidate) { + // it's our side who proposed proxy. so we have to connect to it and activate + auto key = makeKey(sid, pad->session()->me(), pad->session()->peer()); + c.connectToHost( + key, Candidate::Accepted, q, + [this](bool success) { + if (!success) { + pendingActions |= Private::ProxyError; + emit q->updated(); + return; + } + + auto query = new JT_S5B(pad->session()->manager()->client()->rootTask()); + connect(query, &JT_S5B::finished, q, [this, query]() { + Q_ASSERT(localUsedCandidate.state() == Candidate::Accepted); + if (!query->success()) { + pendingActions |= Private::ProxyError; + emit q->updated(); + return; + } + pendingActions |= Private::Activated; + localUsedCandidate.setState(Candidate::Active); + emit q->updated(); + handleConnected(localUsedCandidate); + }); + query->requestActivation(localUsedCandidate.jid(), sid, + pad->session()->peer()); + query->go(true); + }, + mode == Transport::Udp); + } // else so it's remote proxy. let's just wait for from remote + } else { + c.setState(Candidate::Active); + } + } + if (c.state() == Candidate::Active) { + handleConnected(c); + } else + qDebug("checkAndFinishNegotiation not finished: preferred is not Active"); + } else { // both sides reported candidate error + emit q->failed(); + } + } // else we have to wait till remote reports its status + else + qDebug("checkAndFinishNegotiation not finished: remote didn't reported yet"); + return; + } - if (allRemoteDiscarded) { - pendingActions |= Private::CandidateError; - qDebug("checkAndFinishNegotiation: error"); - emit q->updated(); - return; - } + qDebug("checkAndFinishNegotiation not finished: trying to send condidate-used/error if any"); + // if we are here then neither candidate-used nor candidate-error was sent to remote, + // but we can send it now. + // first let's check if we can send candidate-used + bool allRemoteDiscarded = true; + bool hasConnectedRemoteCandidate = false; + for (const auto &c : remoteCandidates) { + auto s = c.state(); + qDebug() << " candidate " << c.cid() << " is " << Candidate::stateText(s); + if (s != Candidate::Discarded) { + allRemoteDiscarded = false; + } + if (s == Candidate::Pending) { // connected but not yet sent + hasConnectedRemoteCandidate = true; + } + } - qDebug("checkAndFinishNegotiation not finished: there are more remote candidates to try"); - // apparently we haven't connected anywhere but there are more remote candidates to try - } + // if we have connection to remote candidate it's time to send it + if (hasConnectedRemoteCandidate) { + pendingActions |= Private::CandidateUsed; + qDebug("checkAndFinishNegotiation: used"); + emit q->updated(); + return; + } - // take used-candidate with highest priority and discard all with lower. also update used candidates themselves - void updateMinimalPriority() { - quint32 prio = 0; - if (localUsedCandidate && localUsedCandidate.state() != Candidate::Discarded) { - prio = localUsedCandidate.priority(); - } - if (remoteUsedCandidate && prio < remoteUsedCandidate.priority() && remoteUsedCandidate.state() != Candidate::Discarded) { - prio = remoteUsedCandidate.priority(); + if (allRemoteDiscarded) { + pendingActions |= Private::CandidateError; + qDebug("checkAndFinishNegotiation: error"); + emit q->updated(); + return; + } + + qDebug("checkAndFinishNegotiation not finished: there are more remote candidates to try"); + // apparently we haven't connected anywhere but there are more remote candidates to try } - for (auto &c: localCandidates) { - if (c.priority() < prio && c.state() != Candidate::Discarded) { - c.setState(Candidate::Discarded); + // take used-candidate with highest priority and discard all with lower. also update used candidates themselves + void updateMinimalPriority() + { + quint32 prio = 0; + if (localUsedCandidate && localUsedCandidate.state() != Candidate::Discarded) { + prio = localUsedCandidate.priority(); } - } - for (auto &c: remoteCandidates) { - if (c.priority() < prio && c.state() != Candidate::Discarded) { - c.setState(Candidate::Discarded); + if (remoteUsedCandidate && prio < remoteUsedCandidate.priority() + && remoteUsedCandidate.state() != Candidate::Discarded) { + prio = remoteUsedCandidate.priority(); } - } - prio >>= 16; - setLocalProbingMinimalPreference(prio); - // if we discarded "used" candidates then reset them to invalid - if (localUsedCandidate && localUsedCandidate.state() == Candidate::Discarded) { - localUsedCandidate = Candidate(); - } - if (remoteUsedCandidate && remoteUsedCandidate.state() == Candidate::Discarded) { - remoteUsedCandidate = Candidate(); - } - if (localUsedCandidate && remoteUsedCandidate) { - if (pad->session()->role() == Origin::Initiator) { - // i'm initiator. see 2.4.4 - localUsedCandidate.setState(Candidate::Discarded); + + for (auto &c : localCandidates) { + if (c.priority() < prio && c.state() != Candidate::Discarded) { + c.setState(Candidate::Discarded); + } + } + for (auto &c : remoteCandidates) { + if (c.priority() < prio && c.state() != Candidate::Discarded) { + c.setState(Candidate::Discarded); + } + } + prio >>= 16; + setLocalProbingMinimalPreference(prio); + // if we discarded "used" candidates then reset them to invalid + if (localUsedCandidate && localUsedCandidate.state() == Candidate::Discarded) { localUsedCandidate = Candidate(); - remoteReportedCandidateError = true; // as a sign of completeness even if not true - } else { - remoteUsedCandidate.setState(Candidate::Discarded); + } + if (remoteUsedCandidate && remoteUsedCandidate.state() == Candidate::Discarded) { remoteUsedCandidate = Candidate(); - localReportedCandidateError = true; // as a sign of completeness even if not true } - } + if (localUsedCandidate && remoteUsedCandidate) { + if (pad->session()->role() == Origin::Initiator) { + // i'm initiator. see 2.4.4 + localUsedCandidate.setState(Candidate::Discarded); + localUsedCandidate = Candidate(); + remoteReportedCandidateError = true; // as a sign of completeness even if not true + } else { + remoteUsedCandidate.setState(Candidate::Discarded); + remoteUsedCandidate = Candidate(); + localReportedCandidateError = true; // as a sign of completeness even if not true + } + } - // now check and reset NewCandidate pending action - bool haveNewCandidates = false; - for (auto &c: remoteCandidates) { - if (c.state() == Candidate::New) { - haveNewCandidates = true; - break; + // now check and reset NewCandidate pending action + bool haveNewCandidates = false; + for (auto &c : remoteCandidates) { + if (c.state() == Candidate::New) { + haveNewCandidates = true; + break; + } + } + if (!haveNewCandidates) { + pendingActions &= ~NewCandidate; } } - if (!haveNewCandidates) { - pendingActions &= ~NewCandidate; - } - } - - void onLocalServerDiscovered() - { - bool hasNewCandidates = false; - for (auto serv: disco->takeServers()) { - auto s5bserv = serv.staticCast(); - s5bserv->registerKey(directAddr); - Candidate c(q, serv, generateCid()); - if (c.isValid() && !isDup(c) && c.priority()) { - QObject::connect(s5bserv.data(), &S5BServer::incomingConnection, q, [this, c](SocksClient *sc, const QString &key) mutable { - if (!connection && key == directAddr && (c.state() == Candidate::Pending || c.state() == Candidate::Unacked)) { - c.incomingConnection(sc); - c.server().data()->disconnect(q); // drop this connection. - if(mode == Transport::Udp) - sc->grantUDPAssociate("", 0); - else - sc->grantConnect(); - return; - } - sc->requestDeny(); - sc->deleteLater(); - }); - QObject::connect(s5bserv.data(), &S5BServer::incomingUdp, q, [this, c](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data){ - if (mode != Transport::Mode::Udp || !connection) { - return false; - } + void onLocalServerDiscovered() + { + bool hasNewCandidates = false; + for (auto serv : disco->takeServers()) { + auto s5bserv = serv.staticCast(); + s5bserv->registerKey(directAddr); + Candidate c(q, serv, generateCid()); + if (c.isValid() && !isDup(c) && c.priority()) { + QObject::connect(s5bserv.data(), &S5BServer::incomingConnection, q, + [this, c](SocksClient *sc, const QString &key) mutable { + if (!connection && key == directAddr + && (c.state() == Candidate::Pending || c.state() == Candidate::Unacked)) { + c.incomingConnection(sc); + c.server().data()->disconnect(q); // drop this connection. + if (mode == Transport::Udp) + sc->grantUDPAssociate("", 0); + else + sc->grantConnect(); + return; + } + + sc->requestDeny(); + sc->deleteLater(); + }); + QObject::connect( + s5bserv.data(), &S5BServer::incomingUdp, q, + [this, c](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, + const QByteArray &data) { + if (mode != Transport::Mode::Udp || !connection) { + return false; + } - if(isInit) { - // TODO probably we could create a Connection here and put all the params inside - if(udpInitialized) - return false; // only init once + if (isInit) { + // TODO probably we could create a Connection here and put all the params inside + if (udpInitialized) + return false; // only init once - // lock on to this sender - udpAddress = addr; - udpPort = sourcePort; - udpInitialized = true; + // lock on to this sender + udpAddress = addr; + udpPort = sourcePort; + udpInitialized = true; - // reply that initialization was successful - pad->session()->manager()->client()->s5bManager()->jtPush()->sendUDPSuccess(pad->session()->peer(), key); // TODO fix ->->-> - return true; - } + // reply that initialization was successful + pad->session()->manager()->client()->s5bManager()->jtPush()->sendUDPSuccess( + pad->session()->peer(), key); // TODO fix ->->-> + return true; + } - // not initialized yet? something went wrong - if(!udpInitialized) - return false; + // not initialized yet? something went wrong + if (!udpInitialized) + return false; - // must come from same source as when initialized - if(addr != udpAddress || sourcePort != udpPort) - return false; + // must come from same source as when initialized + if (addr != udpAddress || sourcePort != udpPort) + return false; - connection->enqueueIncomingUDP(data); // man_udpReady - return true; - }); - localCandidates.insert(c.cid(), c); - pendingActions |= NewCandidate; - hasNewCandidates = true; + connection->enqueueIncomingUDP(data); // man_udpReady + return true; + }); + localCandidates.insert(c.cid(), c); + pendingActions |= NewCandidate; + hasNewCandidates = true; + } + } + if (hasNewCandidates) { + emit q->updated(); } } - if (hasNewCandidates) { - emit q->updated(); - } - } - void handleConnected(Candidate &connCand) - { - connection.reset(new Connection(connCand.takeSocksClient(), mode)); - probingTimer.stop(); - for (auto &rc: remoteCandidates) { - if (rc != connCand && rc.state() == Candidate::Probing) { - rc.deleteSocksClient(); + void handleConnected(Candidate &connCand) + { + connection.reset(new Connection(connCand.takeSocksClient(), mode)); + probingTimer.stop(); + for (auto &rc : remoteCandidates) { + if (rc != connCand && rc.state() == Candidate::Probing) { + rc.deleteSocksClient(); + } } + QTimer::singleShot(0, q, [this]() { + localCandidates.clear(); + remoteCandidates.clear(); + emit q->connected(); + }); } - QTimer::singleShot(0, q, [this](){ - localCandidates.clear(); - remoteCandidates.clear(); - emit q->connected(); + }; + + Transport::Transport(const TransportManagerPad::Ptr &pad) : d(new Private) + { + d->q = this; + d->pad = pad.staticCast(); + d->probingTimer.setSingleShot(true); + connect(&d->probingTimer, &QTimer::timeout, [this]() { d->tryConnectToRemoteCandidate(); }); + connect(pad->manager(), &TransportManager::abortAllRequested, this, [this]() { + d->aborted = true; + emit failed(); }); } -}; - -Transport::Transport(const TransportManagerPad::Ptr &pad) : - d(new Private) -{ - d->q = this; - d->pad = pad.staticCast(); - d->probingTimer.setSingleShot(true); - connect(&d->probingTimer, &QTimer::timeout, [this](){ d->tryConnectToRemoteCandidate(); }); - connect(pad->manager(), &TransportManager::abortAllRequested, this, [this](){ - d->aborted = true; - emit failed(); - }); -} - -Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : - Transport::Transport(pad) -{ - d->meCreator = false; - d->sid = transportEl.attribute(QStringLiteral("sid")); - if (d->sid.isEmpty() || !update(transportEl)) { - d.reset(); - return; - } -} - -Transport::~Transport() -{ - if (d) { - // TODO unregister sid too - static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); - for (auto &c: d->remoteCandidates) { - c.deleteSocksClient(); + + Transport::Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) : + Transport::Transport(pad) + { + d->meCreator = false; + d->sid = transportEl.attribute(QStringLiteral("sid")); + if (d->sid.isEmpty() || !update(transportEl)) { + d.reset(); + return; } - for (auto &c: d->remoteCandidates) { - auto srv = c.server(); - if (srv) { - srv.staticCast()->unregisterKey(d->directAddr); + } + + Transport::~Transport() + { + if (d) { + // TODO unregister sid too + static_cast(d->pad->manager())->removeKeyMapping(d->directAddr); + for (auto &c : d->remoteCandidates) { + c.deleteSocksClient(); + } + for (auto &c : d->remoteCandidates) { + auto srv = c.server(); + if (srv) { + srv.staticCast()->unregisterKey(d->directAddr); + } } } } -} - -TransportManagerPad::Ptr Transport::pad() const -{ - return d->pad.staticCast(); -} - -void Transport::prepare() -{ - auto m = static_cast(d->pad->manager()); - if (d->meCreator) { - d->sid = d->pad->generateSid(); - } - d->pad->registerSid(d->sid); - d->directAddr = makeKey(d->sid, d->pad->session()->initiator(), d->pad->session()->responder()); - m->addKeyMapping(d->directAddr, this); - auto scope = d->pad->discoScope(); - d->disco = scope->disco(); // FIXME store and handle signale. delete when not needed + TransportManagerPad::Ptr Transport::pad() const { return d->pad.staticCast(); } - connect(d->disco, &TcpPortDiscoverer::portAvailable, this, [this](){ - d->onLocalServerDiscovered(); - }); - d->onLocalServerDiscovered(); - - d->discoS5BProxy(); - - emit updated(); -} - -// we got content acceptance from any side and not can connect -void Transport::start() -{ - d->transportStarted = true; - d->tryConnectToRemoteCandidate(); - // if there is no higher priority candidates than ours but they are already connected then - d->checkAndFinishNegotiation(); -} - -bool Transport::update(const QDomElement &transportEl) -{ - // we can just on type of elements in transport-info - // so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info - auto bs = transportEl.attribute(QString::fromLatin1("block-size")); - if (!bs.isEmpty()) { - size_t bsn = bs.toULongLong(); - if (bsn && bsn <= d->blockSize) { - d->blockSize = bsn; - } - } - auto dstaddr = transportEl.attribute(QStringLiteral("dstaddr")); - if (!dstaddr.isEmpty()) { - d->dstaddr = dstaddr; - } - QString candidateTag(QStringLiteral("candidate")); - int candidatesAdded = 0; - for(QDomElement ce = transportEl.firstChildElement(candidateTag); - !ce.isNull(); ce = ce.nextSiblingElement(candidateTag)) { - Candidate c(this, ce); - if (!c) { - return false; + void Transport::prepare() + { + auto m = static_cast(d->pad->manager()); + if (d->meCreator) { + d->sid = d->pad->generateSid(); } - d->remoteCandidates.insert(c.cid(), c); // TODO check for collisions! - candidatesAdded++; + d->pad->registerSid(d->sid); + d->directAddr = makeKey(d->sid, d->pad->session()->initiator(), d->pad->session()->responder()); + m->addKeyMapping(d->directAddr, this); + + auto scope = d->pad->discoScope(); + d->disco = scope->disco(); // FIXME store and handle signale. delete when not needed + + connect(d->disco, &TcpPortDiscoverer::portAvailable, this, [this]() { d->onLocalServerDiscovered(); }); + d->onLocalServerDiscovered(); + + d->discoS5BProxy(); + + emit updated(); } - if (candidatesAdded) { - d->pendingActions &= ~Private::CandidateError; - d->localReportedCandidateError = false; - QTimer::singleShot(0, this, [this](){ - d->tryConnectToRemoteCandidate(); - }); - return true; + + // we got content acceptance from any side and not can connect + void Transport::start() + { + d->transportStarted = true; + d->tryConnectToRemoteCandidate(); + // if there is no higher priority candidates than ours but they are already connected then + d->checkAndFinishNegotiation(); } - QDomElement el = transportEl.firstChildElement(QStringLiteral("candidate-used")); - if (!el.isNull()) { - auto cUsed = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!cUsed) { - return false; + bool Transport::update(const QDomElement &transportEl) + { + // we can just on type of elements in transport-info + // so return as soon as any type handled. Though it leaves a room for remote to send invalid transport-info + auto bs = transportEl.attribute(QString::fromLatin1("block-size")); + if (!bs.isEmpty()) { + size_t bsn = bs.toULongLong(); + if (bsn && bsn <= d->blockSize) { + d->blockSize = bsn; + } } - if (cUsed.state() == Candidate::Pending) { - cUsed.setState(Candidate::Accepted); - d->localUsedCandidate = cUsed; - d->updateMinimalPriority(); - QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); - } else { - //seems like we already rejected the candidate and either remote side already know about it or will soon - d->localUsedCandidate = Candidate(); - d->remoteReportedCandidateError = true; // as a sign remote has finished + auto dstaddr = transportEl.attribute(QStringLiteral("dstaddr")); + if (!dstaddr.isEmpty()) { + d->dstaddr = dstaddr; } - return true; - } - - el = transportEl.firstChildElement(QStringLiteral("candidate-error")); - if (!el.isNull()) { - d->remoteReportedCandidateError = true; - for (auto &c: d->localCandidates) { - if (c.state() == Candidate::Pending) { - c.setState(Candidate::Discarded); + QString candidateTag(QStringLiteral("candidate")); + int candidatesAdded = 0; + for (QDomElement ce = transportEl.firstChildElement(candidateTag); !ce.isNull(); + ce = ce.nextSiblingElement(candidateTag)) { + Candidate c(this, ce); + if (!c) { + return false; } + d->remoteCandidates.insert(c.cid(), c); // TODO check for collisions! + candidatesAdded++; } - qDebug("recv candidate-error: all local pending candidates were discarded"); - QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); - return true; - } - - el = transportEl.firstChildElement(QStringLiteral("activated")); - if (!el.isNull()) { - QString cid = el.attribute(QStringLiteral("cid")); - if (cid.isEmpty()) { - return false; + if (candidatesAdded) { + d->pendingActions &= ~Private::CandidateError; + d->localReportedCandidateError = false; + QTimer::singleShot(0, this, [this]() { d->tryConnectToRemoteCandidate(); }); + return true; } - auto c = d->remoteUsedCandidate; - if (!(c.cid() == cid && c.type() == Candidate::Proxy && c.state() == Candidate::Accepted)) { - qDebug("Received on a candidate in an inappropriate state. Ignored."); + + QDomElement el = transportEl.firstChildElement(QStringLiteral("candidate-used")); + if (!el.isNull()) { + auto cUsed = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); + if (!cUsed) { + return false; + } + if (cUsed.state() == Candidate::Pending) { + cUsed.setState(Candidate::Accepted); + d->localUsedCandidate = cUsed; + d->updateMinimalPriority(); + QTimer::singleShot(0, this, [this]() { d->checkAndFinishNegotiation(); }); + } else { + // seems like we already rejected the candidate and either remote side already know about it or will + // soon + d->localUsedCandidate = Candidate(); + d->remoteReportedCandidateError = true; // as a sign remote has finished + } return true; } - c.setState(Candidate::Active); - d->handleConnected(c); - return true; - } - el = transportEl.firstChildElement(QStringLiteral("proxy-error")); - if (!el.isNull()) { - auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); - if (!c) { - return false; + el = transportEl.firstChildElement(QStringLiteral("candidate-error")); + if (!el.isNull()) { + d->remoteReportedCandidateError = true; + for (auto &c : d->localCandidates) { + if (c.state() == Candidate::Pending) { + c.setState(Candidate::Discarded); + } + } + qDebug("recv candidate-error: all local pending candidates were discarded"); + QTimer::singleShot(0, this, [this]() { d->checkAndFinishNegotiation(); }); + return true; } - if (c != d->localUsedCandidate || c.state() != Candidate::Accepted) { - qDebug("Received on a candidate in an inappropriate state. Ignored."); + + el = transportEl.firstChildElement(QStringLiteral("activated")); + if (!el.isNull()) { + QString cid = el.attribute(QStringLiteral("cid")); + if (cid.isEmpty()) { + return false; + } + auto c = d->remoteUsedCandidate; + if (!(c.cid() == cid && c.type() == Candidate::Proxy && c.state() == Candidate::Accepted)) { + qDebug("Received on a candidate in an inappropriate state. Ignored."); + return true; + } + c.setState(Candidate::Active); + d->handleConnected(c); return true; } - // if we got proxy-error then the transport has to be considered failed according to spec - // so never send proxy-error while we have unaknowledged local non-proxy candidates, - // but we have to follow the standard. + el = transportEl.firstChildElement(QStringLiteral("proxy-error")); + if (!el.isNull()) { + auto c = d->localCandidates.value(el.attribute(QStringLiteral("cid"))); + if (!c) { + return false; + } + if (c != d->localUsedCandidate || c.state() != Candidate::Accepted) { + qDebug("Received on a candidate in an inappropriate state. Ignored."); + return true; + } - // Discard everything - for (auto &c: d->localCandidates) { - c.setState(Candidate::Discarded); - } - for (auto &c: d->remoteCandidates) { - c.setState(Candidate::Discarded); + // if we got proxy-error then the transport has to be considered failed according to spec + // so never send proxy-error while we have unaknowledged local non-proxy candidates, + // but we have to follow the standard. + + // Discard everything + for (auto &c : d->localCandidates) { + c.setState(Candidate::Discarded); + } + for (auto &c : d->remoteCandidates) { + c.setState(Candidate::Discarded); + } + d->proxyDiscoveryInProgress = false; + delete d->disco; + + QTimer::singleShot(0, this, [this]() { emit failed(); }); + return true; } - d->proxyDiscoveryInProgress = false; - delete d->disco; - QTimer::singleShot(0, this, [this](){ emit failed(); }); + // Seems like we got an empty transport. It's still valid though. + QTimer::singleShot(0, this, [this]() { d->checkAndFinishNegotiation(); }); + return true; } - // Seems like we got an empty transport. It's still valid though. - QTimer::singleShot(0, this, [this](){ d->checkAndFinishNegotiation(); }); - - return true; -} + bool Transport::isInitialOfferReady() const + { + return isValid() + && (d->pendingActions || d->offerSent + || (d->localCandidates.isEmpty() && !d->proxyDiscoveryInProgress + && !(d->disco && d->disco->inProgressPortTypes()))); + } -bool Transport::isInitialOfferReady() const -{ - return isValid() && (d->pendingActions || d->offerSent || - (d->localCandidates.isEmpty() && !d->proxyDiscoveryInProgress && - !(d->disco && d->disco->inProgressPortTypes()))); -} + OutgoingTransportInfoUpdate Transport::takeInitialOffer() + { + d->offerSent = true; + auto upd = takeOutgoingUpdate(); + auto tel = std::get<0>(upd); -OutgoingTransportInfoUpdate Transport::takeInitialOffer() -{ - d->offerSent = true; - auto upd = takeOutgoingUpdate(); - auto tel = std::get<0>(upd); + if (d->meCreator && d->mode != Tcp) { + tel.setAttribute(QStringLiteral("mode"), "udp"); + } + tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); - if (d->meCreator && d->mode != Tcp) { - tel.setAttribute(QStringLiteral("mode"), "udp"); + return upd; } - tel.setAttribute(QString::fromLatin1("block-size"), qulonglong(d->blockSize)); - return upd; -} + bool Transport::hasUpdates() const { return isValid() && d->pendingActions; } -bool Transport::hasUpdates() const -{ - return isValid() && d->pendingActions; -} + OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() + { + OutgoingTransportInfoUpdate upd; + if (!isValid()) { + return upd; + } -OutgoingTransportInfoUpdate Transport::takeOutgoingUpdate() -{ - OutgoingTransportInfoUpdate upd; - if (!isValid()) { - return upd; - } + auto doc = d->pad->session()->manager()->client()->doc(); - auto doc = d->pad->session()->manager()->client()->doc(); + QDomElement tel = doc->createElementNS(NS, "transport"); + tel.setAttribute(QStringLiteral("sid"), d->sid); - QDomElement tel = doc->createElementNS(NS, "transport"); - tel.setAttribute(QStringLiteral("sid"), d->sid); + if (d->pendingActions & Private::NewCandidate) { + d->pendingActions &= ~Private::NewCandidate; + bool useProxy = false; + QList candidatesToSend; + for (auto &c : d->localCandidates) { + if (c.state() != Candidate::New) { + continue; + } + if (c.type() == Candidate::Proxy) { + useProxy = true; + } + tel.appendChild(c.toXml(doc)); + candidatesToSend.append(c); + c.setState(Candidate::Unacked); + } + if (useProxy) { + QString dstaddr = makeKey(d->sid, d->pad->session()->me(), d->pad->session()->peer()); + tel.setAttribute(QStringLiteral("dstaddr"), dstaddr); + } + if (!candidatesToSend.isEmpty()) { + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate { tel, [this, candidatesToSend]() mutable { + d->waitingAck= false; + for (auto &c : candidatesToSend) { + if (c.state() == Candidate::Unacked) { + c.setState(Candidate::Pending); + } + } + d->checkAndFinishNegotiation(); + } }; + } else { + qWarning("Got NewCandidate pending action but no candidate to send"); + } + } else if (d->pendingActions & Private::CandidateUsed) { + d->pendingActions &= ~Private::CandidateUsed; + // we should have the only remote candidate in Pending state. + // all other has to be discarded by priority check + for (auto &c : d->remoteCandidates) { + if (c.state() != Candidate::Pending) { + continue; + } + auto el = tel.appendChild(doc->createElement(QStringLiteral("candidate-used"))).toElement(); + el.setAttribute(QStringLiteral("cid"), c.cid()); + c.setState(Candidate::Unacked); + + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate { tel, [this, c]() mutable { + d->waitingAck= false; + if (c.state() == Candidate::Unacked) { + c.setState(Candidate::Accepted); + d->remoteUsedCandidate = c; + } + d->checkAndFinishNegotiation(); + } }; - if (d->pendingActions & Private::NewCandidate) { - d->pendingActions &= ~Private::NewCandidate; - bool useProxy = false; - QList candidatesToSend; - for (auto &c: d->localCandidates) { - if (c.state() != Candidate::New) { - continue; + break; } - if (c.type() == Candidate::Proxy) { - useProxy = true; + if (std::get<0>(upd).isNull()) { + qWarning("Got CandidateUsed pending action but no pending candidates"); } - tel.appendChild(c.toXml(doc)); - candidatesToSend.append(c); - c.setState(Candidate::Unacked); - } - if (useProxy) { - QString dstaddr = makeKey(d->sid, d->pad->session()->me(), d->pad->session()->peer()); - tel.setAttribute(QStringLiteral("dstaddr"), dstaddr); - } - if (!candidatesToSend.isEmpty()) { + } else if (d->pendingActions & Private::CandidateError) { + d->pendingActions &= ~Private::CandidateError; + // we are here because all remote are already in Discardd state + tel.appendChild(doc->createElement(QStringLiteral("candidate-error"))); d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this, candidatesToSend]() mutable { - d->waitingAck = false; - for (auto &c: candidatesToSend) { - if (c.state() == Candidate::Unacked) { - c.setState(Candidate::Pending); + upd = OutgoingTransportInfoUpdate { tel, [this]() mutable { + d->waitingAck= false; + d->localReportedCandidateError= true; + d->checkAndFinishNegotiation(); + } }; + } else if (d->pendingActions & Private::Activated) { + d->pendingActions &= ~Private::Activated; + if (d->localUsedCandidate) { + auto cand = d->localUsedCandidate; + auto el = tel.appendChild(doc->createElement(QStringLiteral("activated"))).toElement(); + el.setAttribute(QStringLiteral("cid"), cand.cid()); + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate { tel, [this, cand]() mutable { d->waitingAck = false; } }; + } + } else if (d->pendingActions & Private::ProxyError) { + // we send proxy error only for local proxy + d->pendingActions &= ~Private::ProxyError; + if (d->localUsedCandidate) { + auto cand = d->localUsedCandidate; + tel.appendChild(doc->createElement(QStringLiteral("proxy-error"))); + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate { + tel, + [this, cand]() mutable { + d->waitingAck = false; + if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { + return; // seems like state was changed while we was waiting for an ack + } + cand.setState(Candidate::Discarded); + d->localUsedCandidate = Candidate(); + emit failed(); } - } - d->checkAndFinishNegotiation(); - }}; + }; + } else { + qWarning("Got ProxyError pending action but no local used candidate is not set"); + } } else { - qWarning("Got NewCandidate pending action but no candidate to send"); + d->waitingAck = true; + upd = OutgoingTransportInfoUpdate { tel, [this]() mutable { d->waitingAck = false; } }; } - } else if (d->pendingActions & Private::CandidateUsed) { - d->pendingActions &= ~Private::CandidateUsed; - // we should have the only remote candidate in Pending state. - // all other has to be discarded by priority check - for (auto &c: d->remoteCandidates) { - if (c.state() != Candidate::Pending) { - continue; - } - auto el = tel.appendChild(doc->createElement(QStringLiteral("candidate-used"))).toElement(); - el.setAttribute(QStringLiteral("cid"), c.cid()); - c.setState(Candidate::Unacked); - d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this, c]() mutable { - d->waitingAck = false; - if (c.state() == Candidate::Unacked) { - c.setState(Candidate::Accepted); - d->remoteUsedCandidate = c; - } - d->checkAndFinishNegotiation(); - }}; + return upd; // TODO + } - break; - } - if (std::get<0>(upd).isNull()) { - qWarning("Got CandidateUsed pending action but no pending candidates"); - } - } else if (d->pendingActions & Private::CandidateError) { - d->pendingActions &= ~Private::CandidateError; - // we are here because all remote are already in Discardd state - tel.appendChild(doc->createElement(QStringLiteral("candidate-error"))); - d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { - d->waitingAck = false; - d->localReportedCandidateError = true; - d->checkAndFinishNegotiation(); - }}; - } else if (d->pendingActions & Private::Activated) { - d->pendingActions &= ~Private::Activated; - if (d->localUsedCandidate) { - auto cand = d->localUsedCandidate; - auto el = tel.appendChild(doc->createElement(QStringLiteral("activated"))).toElement(); - el.setAttribute(QStringLiteral("cid"), cand.cid()); - d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this, cand]() mutable { - d->waitingAck = false; - }}; - } - } else if (d->pendingActions & Private::ProxyError) { - // we send proxy error only for local proxy - d->pendingActions &= ~Private::ProxyError; - if (d->localUsedCandidate) { - auto cand = d->localUsedCandidate; - tel.appendChild(doc->createElement(QStringLiteral("proxy-error"))); - d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this, cand]() mutable { - d->waitingAck = false; - if (cand.state() != Candidate::Accepted || d->localUsedCandidate != cand) { - return; // seems like state was changed while we was waiting for an ack - } - cand.setState(Candidate::Discarded); - d->localUsedCandidate = Candidate(); - emit failed(); - }}; - } else { - qWarning("Got ProxyError pending action but no local used candidate is not set"); - } - } else { - d->waitingAck = true; - upd = OutgoingTransportInfoUpdate{tel, [this]() mutable { - d->waitingAck = false; - }}; + bool Transport::isValid() const { return d != nullptr; } + + Transport::Features Transport::features() const { return Features(HardToConnect | Reliable | Fast); } + + QString Transport::sid() const { return d->sid; } + + QString Transport::directAddr() const { return d->directAddr; } + + Connection::Ptr Transport::connection() const { return d->connection.staticCast(); } + + //---------------------------------------------------------------- + // Manager + //---------------------------------------------------------------- + + class Manager::Private { + public: + XMPP::Jingle::Manager *jingleManager = nullptr; + + // FIMME it's reuiqred to split transports by direction otherwise we gonna hit conflicts. + // jid,transport-sid -> transport mapping + QSet> sids; + QHash key2transport; + Jid proxy; + }; + + Manager::Manager(QObject *parent) : TransportManager(parent), d(new Private) {} + + Manager::~Manager() + { + if (d->jingleManager) + d->jingleManager->unregisterTransport(NS); } - return upd; // TODO -} - -bool Transport::isValid() const -{ - return d != nullptr; -} - -Transport::Features Transport::features() const -{ - return Features(HardToConnect | Reliable | Fast); -} - -QString Transport::sid() const -{ - return d->sid; -} - -QString Transport::directAddr() const -{ - return d->directAddr; -} - -Connection::Ptr Transport::connection() const -{ - return d->connection.staticCast(); -} - -//---------------------------------------------------------------- -// Manager -//---------------------------------------------------------------- - -class Manager::Private -{ -public: - XMPP::Jingle::Manager *jingleManager = nullptr; - - // FIMME it's reuiqred to split transports by direction otherwise we gonna hit conflicts. - // jid,transport-sid -> transport mapping - QSet> sids; - QHash key2transport; - Jid proxy; -}; - -Manager::Manager(QObject *parent) : - TransportManager(parent), - d(new Private) -{ - -} - -Manager::~Manager() -{ - if (d->jingleManager) - d->jingleManager->unregisterTransport(NS); -} - -Transport::Features Manager::features() const -{ - return Transport::Reliable | Transport::Fast; -} - -void Manager::setJingleManager(XMPP::Jingle::Manager *jm) -{ - d->jingleManager = jm; - if (!jm) - return; - // ensure S5BManager is initialized - QTimer::singleShot(0, this, [this](){ - if (!d->jingleManager) // unregistered that early? + Transport::Features Manager::features() const { return Transport::Reliable | Transport::Fast; } + + void Manager::setJingleManager(XMPP::Jingle::Manager *jm) + { + d->jingleManager = jm; + if (!jm) return; - auto jt = d->jingleManager->client()->s5bManager()->jtPush(); - connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { - Q_UNUSED(from); - auto t = d->key2transport.value(dstaddr); - if (t) { - // TODO return t->incomingUDPSuccess(from); - } + // ensure S5BManager is initialized + QTimer::singleShot(0, this, [this]() { + if (!d->jingleManager) // unregistered that early? + return; + auto jt = d->jingleManager->client()->s5bManager()->jtPush(); + connect(jt, &JT_PushS5B::incomingUDPSuccess, this, [this](const Jid &from, const QString &dstaddr) { + Q_UNUSED(from); + auto t = d->key2transport.value(dstaddr); + if (t) { + // TODO return t->incomingUDPSuccess(from); + } + }); }); - }); -} - -QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) -{ - return QSharedPointer(new Transport(pad)); -} - -QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) -{ - auto t = new Transport(pad, transportEl); - QSharedPointer ret(t); - if (t->isValid()) { - return ret; } - return QSharedPointer(); -} - -TransportManagerPad* Manager::pad(Session *session) -{ - return new Pad(this, session); -} - -void Manager::closeAll() -{ - emit abortAllRequested(); -} - -void Manager::addKeyMapping(const QString &key, Transport *transport) -{ - d->key2transport.insert(key, transport); -} - -void Manager::removeKeyMapping(const QString &key) -{ - d->key2transport.remove(key); -} - -QString Manager::generateSid(const Jid &remote) -{ - auto servers = d->jingleManager->client()->tcpPortReserver()-> - scope(QString::fromLatin1("s5b"))->allServers(); - QString sid; - QPair key; - QString key1; - QString key2; - auto servChecker = [&](const TcpPortServer::Ptr &s){ - return s.staticCast()->hasKey(key1) || s.staticCast()->hasKey(key2); - }; - do { - sid = QString("s5b_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); - key = qMakePair(remote, sid); - key1 = makeKey(sid, remote, d->jingleManager->client()->jid()); - key2 = makeKey(sid, d->jingleManager->client()->jid(), remote); - } while (d->sids.contains(key) || std::find_if(servers.begin(), servers.end(), servChecker) != servers.end()); - return sid; -} - -void Manager::registerSid(const Jid &remote, const QString &sid) -{ - d->sids.insert(qMakePair(remote, sid)); -} - -Jid Manager::userProxy() const -{ - return d->proxy; -} - -void Manager::setUserProxy(const Jid &jid) -{ - d->proxy = jid; -} - -//---------------------------------------------------------------- -// Pad -//---------------------------------------------------------------- -Pad::Pad(Manager *manager, Session *session) : - _manager(manager), - _session(session) -{ - auto reserver = _session->manager()->client()->tcpPortReserver(); - _discoScope = reserver->scope(QString::fromLatin1("s5b")); -} - -QString Pad::ns() const -{ - return NS; -} - -Session *Pad::session() const -{ - return _session; -} - -TransportManager *Pad::manager() const -{ - return _manager; -} - -QString Pad::generateSid() const -{ - return _manager->generateSid(_session->peer()); -} - -void Pad::registerSid(const QString &sid) -{ - return _manager->registerSid(_session->peer(), sid); -} + QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad) + { + return QSharedPointer(new Transport(pad)); + } + + QSharedPointer Manager::newTransport(const TransportManagerPad::Ptr &pad, + const QDomElement & transportEl) + { + auto t = new Transport(pad, transportEl); + QSharedPointer ret(t); + if (t->isValid()) { + return ret; + } + return QSharedPointer(); + } + + TransportManagerPad *Manager::pad(Session *session) { return new Pad(this, session); } + + void Manager::closeAll() { emit abortAllRequested(); } + + void Manager::addKeyMapping(const QString &key, Transport *transport) { d->key2transport.insert(key, transport); } + + void Manager::removeKeyMapping(const QString &key) { d->key2transport.remove(key); } + + QString Manager::generateSid(const Jid &remote) + { + auto servers = d->jingleManager->client()->tcpPortReserver()->scope(QString::fromLatin1("s5b"))->allServers(); + QString sid; + QPair key; + QString key1; + QString key2; + auto servChecker = [&](const TcpPortServer::Ptr &s) { + return s.staticCast()->hasKey(key1) || s.staticCast()->hasKey(key2); + }; + + do { + sid = QString("s5b_%1").arg(qrand() & 0xffff, 4, 16, QChar('0')); + key = qMakePair(remote, sid); + key1 = makeKey(sid, remote, d->jingleManager->client()->jid()); + key2 = makeKey(sid, d->jingleManager->client()->jid(), remote); + } while (d->sids.contains(key) || std::find_if(servers.begin(), servers.end(), servChecker) != servers.end()); + return sid; + } + + void Manager::registerSid(const Jid &remote, const QString &sid) { d->sids.insert(qMakePair(remote, sid)); } + + Jid Manager::userProxy() const { return d->proxy; } + + void Manager::setUserProxy(const Jid &jid) { d->proxy = jid; } + + //---------------------------------------------------------------- + // Pad + //---------------------------------------------------------------- + Pad::Pad(Manager *manager, Session *session) : _manager(manager), _session(session) + { + auto reserver = _session->manager()->client()->tcpPortReserver(); + _discoScope = reserver->scope(QString::fromLatin1("s5b")); + } + + QString Pad::ns() const { return NS; } + + Session *Pad::session() const { return _session; } + + TransportManager *Pad::manager() const { return _manager; } + + QString Pad::generateSid() const { return _manager->generateSid(_session->peer()); } + + void Pad::registerSid(const QString &sid) { return _manager->registerSid(_session->peer(), sid); } } // namespace S5B } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle-s5b.h b/src/xmpp/xmpp-im/jingle-s5b.h index dffed154..e89e47c6 100644 --- a/src/xmpp/xmpp-im/jingle-s5b.h +++ b/src/xmpp/xmpp-im/jingle-s5b.h @@ -29,192 +29,188 @@ class SocksClient; namespace XMPP { class Client; -namespace Jingle { -namespace S5B { -extern const QString NS; - -class Transport; - -class Candidate { -public: - enum Type { - None, // non standard, just a default - Proxy, - Tunnel, - Assisted, - Direct +namespace Jingle { namespace S5B { + extern const QString NS; + + class Transport; + + class Candidate { + public: + enum Type { + None, // non standard, just a default + Proxy, + Tunnel, + Assisted, + Direct + }; + + enum { ProxyPreference = 10, TunnelPreference = 110, AssistedPreference = 120, DirectPreference = 126 }; + + /** + * Local candidates states: + * Probing - potential candidate but no ip:port yet. upnp for example + * New - candidate is ready to be sent to remote + * Unacked - candidate is sent to remote but no iq ack yet + * Pending - canidate sent to remote. we have iq ack but no "used" or "error" + * Accepted - we got "candidate-used" for this candidate + * Active - use this candidate for actual data transfer + * Discarded - we got "candidate-error" so all pending were marked Discarded + * + * Remote candidates states: + * New - the candidate waits its turn to start connection probing + * Probing - connection probing + * Pending - connection was successful, but we didn't send candidate-used to remote + * Unacked - connection was successful and we sent candidate-used to remote but no iq ack yet + * Accepted - we sent candidate-used and got iq ack + * Active - use this candidate for actual data transfer + * Discarded - failed to connect to all remote candidates + */ + enum State { + New, + Probing, + Pending, + Unacked, + Accepted, + Active, + Discarded, + }; + + Candidate(); + Candidate(Transport *transport, const QDomElement &el); + Candidate(const Candidate &other); + Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference = 0); + Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, + quint16 localPreference = 0); + ~Candidate(); + Candidate & operator=(const Candidate &other) = default; + inline bool isValid() const { return d != nullptr; } + inline operator bool() const { return isValid(); } + Type type() const; + QString cid() const; + Jid jid() const; + QString host() const; + void setHost(const QString &host); + quint16 port() const; + void setPort(quint16 port); + quint16 localPort() const; + QHostAddress localAddress() const; + State state() const; + void setState(State s); + static const char *stateText(State s); + quint32 priority() const; + + QDomElement toXml(QDomDocument *doc) const; + + void connectToHost(const QString &key, State successState, QObject *callbackContext, + std::function callback, bool isUdp = false); + bool incomingConnection(SocksClient *sc); + SocksClient * takeSocksClient(); + void deleteSocksClient(); + TcpPortServer::Ptr server() const; + + bool operator==(const Candidate &other) const; + inline bool operator!=(const Candidate &other) const { return !(*this == other); } + + private: + class Private; + friend class Transport; + QExplicitlySharedDataPointer d; }; - enum { - ProxyPreference = 10, - TunnelPreference = 110, - AssistedPreference = 120, - DirectPreference = 126 + class Manager; + class Transport : public XMPP::Jingle::Transport { + Q_OBJECT + public: + enum Mode { Tcp, Udp }; + + Transport(const TransportManagerPad::Ptr &pad); + Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); + ~Transport(); + + TransportManagerPad::Ptr pad() const override; + + void prepare() override; + void start() override; + bool update(const QDomElement &transportEl) override; + bool isInitialOfferReady() const override; + OutgoingTransportInfoUpdate takeInitialOffer() override; + bool hasUpdates() const override; + OutgoingTransportInfoUpdate takeOutgoingUpdate() override; + bool isValid() const override; + Features features() const override; + + QString sid() const; + QString directAddr() const; + Connection::Ptr connection() const override; + + private: + friend class Manager; + + class Private; + QScopedPointer d; }; - /** - * Local candidates states: - * Probing - potential candidate but no ip:port yet. upnp for example - * New - candidate is ready to be sent to remote - * Unacked - candidate is sent to remote but no iq ack yet - * Pending - canidate sent to remote. we have iq ack but no "used" or "error" - * Accepted - we got "candidate-used" for this candidate - * Active - use this candidate for actual data transfer - * Discarded - we got "candidate-error" so all pending were marked Discarded - * - * Remote candidates states: - * New - the candidate waits its turn to start connection probing - * Probing - connection probing - * Pending - connection was successful, but we didn't send candidate-used to remote - * Unacked - connection was successful and we sent candidate-used to remote but no iq ack yet - * Accepted - we sent candidate-used and got iq ack - * Active - use this candidate for actual data transfer - * Discarded - failed to connect to all remote candidates - */ - enum State { - New, - Probing, - Pending, - Unacked, - Accepted, - Active, - Discarded, - }; + class Pad : public TransportManagerPad { + Q_OBJECT + // TODO + public: + typedef QSharedPointer Ptr; + + Pad(Manager *manager, Session *session); + QString ns() const override; + Session * session() const override; + TransportManager *manager() const override; + + QString generateSid() const; + void registerSid(const QString &sid); - Candidate(); - Candidate(Transport *transport, const QDomElement &el); - Candidate(const Candidate &other); - Candidate(Transport *transport, const Jid &proxy, const QString &cid, quint16 localPreference = 0); - Candidate(Transport *transport, const TcpPortServer::Ptr &server, const QString &cid, quint16 localPreference = 0); - ~Candidate(); - Candidate& operator=(const Candidate& other) = default; - inline bool isValid() const { return d != nullptr; } - inline operator bool() const { return isValid(); } - Type type() const; - QString cid() const; - Jid jid() const; - QString host() const; - void setHost(const QString &host); - quint16 port() const; - void setPort(quint16 port); - quint16 localPort() const; - QHostAddress localAddress() const; - State state() const; - void setState(State s); - static const char *stateText(State s); - quint32 priority() const; - - QDomElement toXml(QDomDocument *doc) const; - - void connectToHost(const QString &key, State successState, QObject *callbackContext, std::function callback, bool isUdp = false); - bool incomingConnection(SocksClient *sc); - SocksClient* takeSocksClient(); - void deleteSocksClient(); - TcpPortServer::Ptr server() const; - - bool operator==(const Candidate &other) const; - inline bool operator!=(const Candidate &other) const { return !(*this == other); } -private: - class Private; - friend class Transport; - QExplicitlySharedDataPointer d; -}; - -class Manager; -class Transport : public XMPP::Jingle::Transport -{ - Q_OBJECT -public: - enum Mode { - Tcp, - Udp + inline TcpPortScope *discoScope() const { return _discoScope; } + + private: + Manager * _manager; + Session * _session; + TcpPortScope *_discoScope; }; - Transport(const TransportManagerPad::Ptr &pad); - Transport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl); - ~Transport(); - - TransportManagerPad::Ptr pad() const override; - - void prepare() override; - void start() override; - bool update(const QDomElement &transportEl) override; - bool isInitialOfferReady() const override; - OutgoingTransportInfoUpdate takeInitialOffer() override; - bool hasUpdates() const override; - OutgoingTransportInfoUpdate takeOutgoingUpdate() override; - bool isValid() const override; - Features features() const override; - - QString sid() const; - QString directAddr() const; - Connection::Ptr connection() const override; - -private: - friend class Manager; - - class Private; - QScopedPointer d; -}; - -class Pad : public TransportManagerPad -{ - Q_OBJECT - // TODO -public: - typedef QSharedPointer Ptr; - - Pad(Manager *manager, Session *session); - QString ns() const override; - Session *session() const override; - TransportManager *manager() const override; - - QString generateSid() const; - void registerSid(const QString &sid); - - inline TcpPortScope *discoScope() const { return _discoScope; } -private: - Manager *_manager; - Session *_session; - TcpPortScope *_discoScope; -}; - -class Manager : public TransportManager { - Q_OBJECT -public: - Manager(QObject *parent = nullptr); - ~Manager(); - - XMPP::Jingle::Transport::Features features() const override; - void setJingleManager(XMPP::Jingle::Manager *jm) override; - QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) override; // outgoing. one have to call Transport::start to collect candidates - QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) override; // incoming - TransportManagerPad* pad(Session *session) override; - - void closeAll() override; - - QString generateSid(const Jid &remote); - void registerSid(const Jid &remote, const QString &sid); - - /** - * @brief userProxy returns custom (set by user) SOCKS proxy JID - * @return - */ - Jid userProxy() const; - void setUserProxy(const Jid &jid); - - /** - * @brief addKeyMapping sets mapping between key/socks hostname used for direct connection and transport. - * The key is sha1(sid, initiator full jid, responder full jid) - * @param key - * @param transport - */ - void addKeyMapping(const QString &key, Transport *transport); - void removeKeyMapping(const QString &key); -private: - class Private; - QScopedPointer d; -}; + class Manager : public TransportManager { + Q_OBJECT + public: + Manager(QObject *parent = nullptr); + ~Manager(); + + XMPP::Jingle::Transport::Features features() const override; + void setJingleManager(XMPP::Jingle::Manager *jm) override; + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) + override; // outgoing. one have to call Transport::start to collect candidates + QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, + const QDomElement &transportEl) override; // incoming + TransportManagerPad * pad(Session *session) override; + + void closeAll() override; + + QString generateSid(const Jid &remote); + void registerSid(const Jid &remote, const QString &sid); + + /** + * @brief userProxy returns custom (set by user) SOCKS proxy JID + * @return + */ + Jid userProxy() const; + void setUserProxy(const Jid &jid); + + /** + * @brief addKeyMapping sets mapping between key/socks hostname used for direct connection and transport. + * The key is sha1(sid, initiator full jid, responder full jid) + * @param key + * @param transport + */ + void addKeyMapping(const QString &key, Transport *transport); + void removeKeyMapping(const QString &key); + + private: + class Private; + QScopedPointer d; + }; } // namespace S5B } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h index 6d166a81..fe5c0542 100644 --- a/src/xmpp/xmpp-im/jingle.h +++ b/src/xmpp/xmpp-im/jingle.h @@ -26,10 +26,10 @@ #include #include #include -#if QT_VERSION >= QT_VERSION_CHECK(5,8,0) -# include +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +#include #else -# include +#include #endif class QDomDocument; @@ -39,581 +39,576 @@ namespace XMPP { class Client; namespace Jingle { -extern const QString NS; + extern const QString NS; -class Manager; -class Session; + class Manager; + class Session; -enum class Origin { - None, - Both, - Initiator, - Responder -}; + enum class Origin { None, Both, Initiator, Responder }; -inline uint qHash(const XMPP::Jingle::Origin &o, uint seed = 0) -{ - return ::qHash(int(o), seed); -} + inline uint qHash(const XMPP::Jingle::Origin &o, uint seed = 0) { return ::qHash(int(o), seed); } -/* - Session states: - * Created - new session - * PrepareLocalOffer - user accepted session but it's not yet ready for session-initiate/accept message - * Unacked - session-initiate/accept was sent. wait for IQ ack - * Pending - session-initiate was acknowledged. awaits session-accept. - * Active - session was accepted and now active. - * Finihed - session-terminate was sent/received - - Locally initiated session passes all the above and remotely initiated skips Pending. -*/ -enum class State { - Created, // just after constructor - PrepareLocalOffer, // content accepted by local user but we are not ready yet to send content-accept or session-accept. - // same for content-add/session-initiate, where user already already sent/added in ui and it's network turn. - Unacked, // local content offer is sent to remote but no IQ ack yet - Pending, // waits for session-accept or content-accept from remote - Accepted, // app only: local: "accept" received, waits for start(). remote: "accept" sent and acknowledged, waits for start() - Connecting, // app only: s5b/ice probes etc (particular application state. can be omited for other entities) - Active, // active transfer. transport is connected. For session it means it was accepted - Finishing, // app only: basically it's finished but has some pending operations. like sending content-reject/remove to remote - Finished // transfering is finished for whatever reason. no more signals/state changes etc. can be deleted -}; - -enum class Action { - NoAction, // non-standard, just a default - ContentAccept, - ContentAdd, - ContentModify, - ContentReject, - ContentRemove, - DescriptionInfo, - SecurityInfo, - SessionAccept, - SessionInfo, - SessionInitiate, - SessionTerminate, - TransportAccept, - TransportInfo, - TransportReject, - TransportReplace -}; - -inline uint qHash(const XMPP::Jingle::Action &o, uint seed = 0) -{ - return ::qHash(int(o), seed); -} - -typedef QPair ContentKey; -typedef std::function OutgoingUpdateCB; -typedef std::tuple, OutgoingUpdateCB> OutgoingUpdate; // list of elements to b inserted to and success callback -typedef std::tuple OutgoingTransportInfoUpdate; // transport element and success callback - -class ErrorUtil -{ -public: - enum { - UnknownError, // unparsed/unknown error - OutOfOrder, - TieBreak, - UnknownSession, - UnsupportedInfo, - Last + /* + Session states: + * Created - new session + * PrepareLocalOffer - user accepted session but it's not yet ready for session-initiate/accept message + * Unacked - session-initiate/accept was sent. wait for IQ ack + * Pending - session-initiate was acknowledged. awaits session-accept. + * Active - session was accepted and now active. + * Finihed - session-terminate was sent/received + + Locally initiated session passes all the above and remotely initiated skips Pending. + */ + enum class State { + Created, // just after constructor + PrepareLocalOffer, // content accepted by local user but we are not ready yet to send content-accept or + // session-accept. same for content-add/session-initiate, where user already already + // sent/added in ui and it's network turn. + Unacked, // local content offer is sent to remote but no IQ ack yet + Pending, // waits for session-accept or content-accept from remote + Accepted, // app only: local: "accept" received, waits for start(). remote: "accept" sent and acknowledged, + // waits for start() + Connecting, // app only: s5b/ice probes etc (particular application state. can be omited for other entities) + Active, // active transfer. transport is connected. For session it means it was accepted + Finishing, // app only: basically it's finished but has some pending operations. like sending + // content-reject/remove to remote + Finished // transfering is finished for whatever reason. no more signals/state changes etc. can be deleted }; - static const char* names[Last]; - - static XMPP::Stanza::Error make(QDomDocument &doc, int jingleCond, int type=XMPP::Stanza::Error::Cancel, int condition=XMPP::Stanza::Error::UndefinedCondition, const QString &text=QString()); - - static XMPP::Stanza::Error makeTieBreak(QDomDocument &doc); - static XMPP::Stanza::Error makeOutOfOrder(QDomDocument &doc); - - static void fill(QDomDocument doc, XMPP::Stanza::Error &error, int jingleCond); - static int jingleCondition(const XMPP::Stanza::Error &error); -}; - -class Jingle -{ -public: - Jingle(); // make invalid jingle element - Jingle(Action action, const QString &sid); // start making outgoing jingle - Jingle(const QDomElement &e); // likely incoming - Jingle(const Jingle &); - ~Jingle(); - - QDomElement toXml(QDomDocument *doc) const; - inline bool isValid() const { return d != nullptr; } - Action action() const; - const QString &sid() const; - const Jid &initiator() const; - void setInitiator(const Jid &jid); - const Jid &responder() const; - void setResponder(const Jid &jid); -private: - class Private; - QSharedDataPointer d; - Jingle::Private *ensureD(); -}; - -class Reason { - class Private; -public: - enum Condition - { - NoReason = 0, // non-standard, just a default - AlternativeSession, - Busy, - Cancel, - ConnectivityError, - Decline, - Expired, - FailedApplication, - FailedTransport, - GeneralError, - Gone, - IncompatibleParameters, - MediaError, - SecurityError, - Success, - Timeout, - UnsupportedApplications, - UnsupportedTransports + enum class Action { + NoAction, // non-standard, just a default + ContentAccept, + ContentAdd, + ContentModify, + ContentReject, + ContentRemove, + DescriptionInfo, + SecurityInfo, + SessionAccept, + SessionInfo, + SessionInitiate, + SessionTerminate, + TransportAccept, + TransportInfo, + TransportReject, + TransportReplace }; - Reason(); - ~Reason(); - Reason(Condition cond, const QString &text = QString()); - Reason(const QDomElement &el); - Reason(const Reason &other); - Reason& operator=(const Reason &); - inline bool isValid() const { return d != nullptr; } - Condition condition() const; - void setCondition(Condition cond); - QString text() const; - void setText(const QString &text); + inline uint qHash(const XMPP::Jingle::Action &o, uint seed = 0) { return ::qHash(int(o), seed); } + + typedef QPair ContentKey; + typedef std::function OutgoingUpdateCB; + typedef std::tuple, OutgoingUpdateCB> + OutgoingUpdate; // list of elements to b inserted to and success callback + typedef std::tuple + OutgoingTransportInfoUpdate; // transport element and success callback + + class ErrorUtil { + public: + enum { + UnknownError, // unparsed/unknown error + OutOfOrder, + TieBreak, + UnknownSession, + UnsupportedInfo, + Last + }; + + static const char *names[Last]; + + static XMPP::Stanza::Error make(QDomDocument &doc, int jingleCond, int type = XMPP::Stanza::Error::Cancel, + int condition = XMPP::Stanza::Error::UndefinedCondition, + const QString &text = QString()); + + static XMPP::Stanza::Error makeTieBreak(QDomDocument &doc); + static XMPP::Stanza::Error makeOutOfOrder(QDomDocument &doc); + + static void fill(QDomDocument doc, XMPP::Stanza::Error &error, int jingleCond); + static int jingleCondition(const XMPP::Stanza::Error &error); + }; - QDomElement toXml(QDomDocument *doc) const; + class Jingle { + public: + Jingle(); // make invalid jingle element + Jingle(Action action, const QString &sid); // start making outgoing jingle + Jingle(const QDomElement &e); // likely incoming + Jingle(const Jingle &); + ~Jingle(); + + QDomElement toXml(QDomDocument *doc) const; + inline bool isValid() const { return d != nullptr; } + Action action() const; + const QString &sid() const; + const Jid & initiator() const; + void setInitiator(const Jid &jid); + const Jid & responder() const; + void setResponder(const Jid &jid); + + private: + class Private; + QSharedDataPointer d; + Jingle::Private * ensureD(); + }; -private: - Private *ensureD(); + class Reason { + class Private; + + public: + enum Condition { + NoReason = 0, // non-standard, just a default + AlternativeSession, + Busy, + Cancel, + ConnectivityError, + Decline, + Expired, + FailedApplication, + FailedTransport, + GeneralError, + Gone, + IncompatibleParameters, + MediaError, + SecurityError, + Success, + Timeout, + UnsupportedApplications, + UnsupportedTransports + }; + + Reason(); + ~Reason(); + Reason(Condition cond, const QString &text = QString()); + Reason(const QDomElement &el); + Reason(const Reason &other); + Reason & operator=(const Reason &); + inline bool isValid() const { return d != nullptr; } + Condition condition() const; + void setCondition(Condition cond); + QString text() const; + void setText(const QString &text); + + QDomElement toXml(QDomDocument *doc) const; + + private: + Private *ensureD(); + + QSharedDataPointer d; + }; - QSharedDataPointer d; -}; + class ContentBase { + public: + inline ContentBase() {} + ContentBase(Origin creator, const QString &name); + ContentBase(const QDomElement &el); -class ContentBase { -public: + inline bool isValid() const { return creator != Origin::None && !name.isEmpty(); } - inline ContentBase(){} - ContentBase(Origin creator, const QString &name); - ContentBase(const QDomElement &el); + QDomElement toXml(QDomDocument *doc, const char *tagName) const; + static Origin creatorAttr(const QDomElement &el); + static bool setCreatorAttr(QDomElement &el, Origin creator); - inline bool isValid() const { return creator != Origin::None && !name.isEmpty(); } + Origin creator = Origin::None; + QString name; + Origin senders = Origin::Both; + QString disposition; // default "session" + }; - QDomElement toXml(QDomDocument *doc, const char *tagName) const; - static Origin creatorAttr(const QDomElement &el); - static bool setCreatorAttr(QDomElement &el, Origin creator); + class Security { + }; - Origin creator = Origin::None; - QString name; - Origin senders = Origin::Both; - QString disposition; // default "session" -}; + /** + * @brief The SessionManagerPad class - TransportManager/AppManager PAD + * + * The class is intended to be used to monitor global session events + * as well as send them in context of specific application type. + * + * For example a session has 3 content elements (voice, video and whiteboard). + * voice and video are related to RTP application while whiteaboard (Jingle SXE) + * is a different application. Therefore the session will have 2 pads: + * rtp pad and whitebaord pad. + * The pads are connected to both session and transport/application manager + * and their main task to handle Jingle session-info events. + * + * SessionManagerPad is a base class for all kinds of pads. + * UI can connect to its signals. + */ + class SessionManagerPad : public QObject { + Q_OBJECT + public: + virtual QDomElement takeOutgoingSessionInfoUpdate(); + virtual QString ns() const = 0; + virtual Session * session() const = 0; + QDomDocument * doc() const; + }; -class Security -{ + class TransportManager; + class TransportManagerPad : public SessionManagerPad { + Q_OBJECT + public: + typedef QSharedPointer Ptr; -}; + virtual TransportManager *manager() const = 0; + }; -/** - * @brief The SessionManagerPad class - TransportManager/AppManager PAD - * - * The class is intended to be used to monitor global session events - * as well as send them in context of specific application type. - * - * For example a session has 3 content elements (voice, video and whiteboard). - * voice and video are related to RTP application while whiteaboard (Jingle SXE) - * is a different application. Therefore the session will have 2 pads: - * rtp pad and whitebaord pad. - * The pads are connected to both session and transport/application manager - * and their main task to handle Jingle session-info events. - * - * SessionManagerPad is a base class for all kinds of pads. - * UI can connect to its signals. - */ -class SessionManagerPad : public QObject -{ - Q_OBJECT -public: - virtual QDomElement takeOutgoingSessionInfoUpdate(); - virtual QString ns() const = 0; - virtual Session *session() const = 0; - QDomDocument* doc() const; -}; - -class TransportManager; -class TransportManagerPad : public SessionManagerPad -{ - Q_OBJECT -public: - typedef QSharedPointer Ptr; - - virtual TransportManager *manager() const = 0; -}; - -class ApplicationManager; -class ApplicationManagerPad : public SessionManagerPad -{ - Q_OBJECT -public: - typedef QSharedPointer Ptr; - - using SessionManagerPad::SessionManagerPad; - - virtual ApplicationManager *manager() const = 0; + class ApplicationManager; + class ApplicationManagerPad : public SessionManagerPad { + Q_OBJECT + public: + typedef QSharedPointer Ptr; - /* - * for example we transfer a file - * then first file may generate name "file1", next "file2" etc - * As result it will be sent as - */ - virtual QString generateContentName(Origin senders) = 0; -}; - -#if QT_VERSION < QT_VERSION_CHECK(5,8,0) -// stub implementation -class NetworkDatagram -{ -public: - bool _valid = false; - QByteArray _data; - inline NetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress = QHostAddress(), quint16 port = 0) : - _valid(true), - _data(data) - { - Q_UNUSED(destinationAddress); - Q_UNUSED(port) - } - inline NetworkDatagram(){} - - inline bool isValid() const { return _valid; } - inline QByteArray data() const { return _data; } -}; -#else -typedef QNetworkDatagram NetworkDatagram; -#endif + using SessionManagerPad::SessionManagerPad; -class Connection : public ByteStream -{ - Q_OBJECT -public: - using Ptr = QSharedPointer; // will be shared between transport and application - virtual bool hasPendingDatagrams() const; - virtual NetworkDatagram receiveDatagram(qint64 maxSize = -1); - virtual size_t blockSize() const; -}; - -class Application; -class Transport : public QObject { - Q_OBJECT -public: - /* - Categorization by speed, reliability and connectivity - - speed: realtim, fast, slow - - reliability: reliable, not reliable (some transport can both modes) - - connectivity: always connect, hard to connect + virtual ApplicationManager *manager() const = 0; - Some transports may change their qualities, so we have to consider worst case. + /* + * for example we transfer a file + * then first file may generate name "file1", next "file2" etc + * As result it will be sent as + */ + virtual QString generateContentName(Origin senders) = 0; + }; - ICE-UDP: RealTime, Not Reliable, Hard To Connect - S5B: Fast, Reliable, Hard To Connect - IBB: Slow, Reliable, Always Connect +#if QT_VERSION < QT_VERSION_CHECK(5, 8, 0) + // stub implementation + class NetworkDatagram { + public: + bool _valid = false; + QByteArray _data; + inline NetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress = QHostAddress(), + quint16 port = 0) : + _valid(true), + _data(data) + { + Q_UNUSED(destinationAddress); + Q_UNUSED(port) + } + inline NetworkDatagram() {} + + inline bool isValid() const { return _valid; } + inline QByteArray data() const { return _data; } + }; +#else + typedef QNetworkDatagram NetworkDatagram; +#endif - Also most of transports may add extra features but it's matter of configuration. - For example all of them can enable p2p crypto mode ( should work here) - */ - enum Feature { - // connection establishment - HardToConnect = 0x01, // anything else but ibb - AlwaysConnect = 0x02, // ibb. basically it's always connected - - // reliability - NotReliable = 0x10, // datagram-oriented - Reliable = 0x20, // connection-orinted - - // speed. - Slow = 0x100, // only ibb is here probably - Fast = 0x200, // basically all tcp-based and reliable part of sctp - RealTime = 0x400 // it's rather about synchronization of frames with time which implies fast + class Connection : public ByteStream { + Q_OBJECT + public: + using Ptr = QSharedPointer; // will be shared between transport and application + virtual bool hasPendingDatagrams() const; + virtual NetworkDatagram receiveDatagram(qint64 maxSize = -1); + virtual size_t blockSize() const; }; - Q_DECLARE_FLAGS(Features, Feature) - using QObject::QObject; + class Application; + class Transport : public QObject { + Q_OBJECT + public: + /* + Categorization by speed, reliability and connectivity + - speed: realtim, fast, slow + - reliability: reliable, not reliable (some transport can both modes) + - connectivity: always connect, hard to connect + + Some transports may change their qualities, so we have to consider worst case. + + ICE-UDP: RealTime, Not Reliable, Hard To Connect + S5B: Fast, Reliable, Hard To Connect + IBB: Slow, Reliable, Always Connect + + Also most of transports may add extra features but it's matter of configuration. + For example all of them can enable p2p crypto mode ( should work here) + */ + enum Feature { + // connection establishment + HardToConnect = 0x01, // anything else but ibb + AlwaysConnect = 0x02, // ibb. basically it's always connected + + // reliability + NotReliable = 0x10, // datagram-oriented + Reliable = 0x20, // connection-orinted + + // speed. + Slow = 0x100, // only ibb is here probably + Fast = 0x200, // basically all tcp-based and reliable part of sctp + RealTime = 0x400 // it's rather about synchronization of frames with time which implies fast + }; + Q_DECLARE_FLAGS(Features, Feature) + + using QObject::QObject; + + enum Direction { // incoming or outgoing file/data transfer. + Outgoing, + Incoming + }; + + /** + * @brief prepare to send content-add/session-initiate + * When ready, the application first set update type to ContentAdd and then emit updated() + */ + virtual void prepare() = 0; + + /** + * @brief start really transfer data. starting with connection to remote candidates for example + */ + virtual void start() = 0; // for local transport start searching for candidates (including probing proxy,stun + // etc) for remote transport try to connect to all proposed hosts in order their + // priority. in-band transport may just emit updated() here + virtual bool update(const QDomElement &el) = 0; // accepts transport element on incoming transport-info + virtual bool isInitialOfferReady() const = 0; + virtual bool hasUpdates() const = 0; + virtual OutgoingTransportInfoUpdate takeInitialOffer() = 0; + virtual OutgoingTransportInfoUpdate takeOutgoingUpdate() = 0; + virtual bool isValid() const = 0; + virtual Features features() const = 0; + virtual TransportManagerPad::Ptr pad() const = 0; + virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection + signals: + void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal + // handler. if it's just always ready then signal has to be sent at least once otherwise + // session-initiate won't be sent. + void connected(); // this signal is for app logic. maybe to finally start drawing some progress bar + void failed(); // transport ailed for whatever reason. aborted for example + }; - enum Direction { // incoming or outgoing file/data transfer. - Outgoing, - Incoming + class Application : public QObject { + Q_OBJECT + public: + enum SetDescError { + Ok, + Unparsed, + IncompatibleParameters // this one is for + }; + + virtual ApplicationManagerPad::Ptr pad() const = 0; + virtual State state() const = 0; + virtual void setState(State state) = 0; // likely just remember the state and not generate any signals + virtual XMPP::Stanza::Error lastError() const = 0; + virtual Reason terminationReason() const = 0; + + virtual Origin creator() const = 0; + virtual Origin senders() const = 0; + virtual QString contentName() const = 0; + virtual Origin transportReplaceOrigin() + const = 0; // returns Origin::None if no transport-replace in progress or the side triggered the replace. + virtual SetDescError setDescription(const QDomElement &description) = 0; + + /** + * @brief setTransport checks if transport is compatible and stores it + * @param transport + * @return false if not compatible + */ + virtual bool setTransport(const QSharedPointer &transport) = 0; + virtual QSharedPointer transport() const = 0; + + /** + * @brief evaluateOutgoingUpdate computes and prepares next update which will be taken with takeOutgoingUpdate + * The updated will be taked immediately if considered to be most preferred among other updates types of + * other applications. + * @return update type + */ + virtual Action evaluateOutgoingUpdate() = 0; + virtual OutgoingUpdate takeOutgoingUpdate() + = 0; // this may return something only when evaluateOutgoingUpdate() != NoAction + + /** + * @brief wantBetterTransport checks if the transport is a better match for the application + * @return + */ + virtual bool wantBetterTransport(const QSharedPointer &) const = 0; + + /** + * @brief selectNextTransport selects next transport from compatible transports list. + * The list is usually store in the application + * @return + */ + virtual bool selectNextTransport() = 0; + + /** + * @brief prepare to send content-add/session-initiate + * When ready, the application first set update type to ContentAdd and then emit updated() + */ + virtual void prepare() = 0; + virtual bool accept(const QDomElement &el) = 0; // remote accepted our content + virtual void start() = 0; + virtual void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) = 0; + + /** + * @brief incomingTransportReplace it's jingle transport-replace + * @param transport + * @return + */ + virtual bool incomingTransportReplace(const QSharedPointer &transport) = 0; + virtual bool incomingTransportAccept(const QDomElement &transportEl) = 0; + + signals: + void updated(); // signal for session it has to send updates to remote. so it will follow with + // takeOutgoingUpdate() eventually + void stateChanged(State); }; - /** - * @brief prepare to send content-add/session-initiate - * When ready, the application first set update type to ContentAdd and then emit updated() - */ - virtual void prepare() = 0; + class Session : public QObject { + Q_OBJECT + public: + // Note incoming session are not registered in Jingle Manager until validated. + // and then either rejected or registered in Pending state. - /** - * @brief start really transfer data. starting with connection to remote candidates for example - */ - virtual void start() = 0; // for local transport start searching for candidates (including probing proxy,stun etc) - // for remote transport try to connect to all proposed hosts in order their priority. - // in-band transport may just emit updated() here - virtual bool update(const QDomElement &el) = 0; // accepts transport element on incoming transport-info - virtual bool isInitialOfferReady() const = 0; - virtual bool hasUpdates() const = 0; - virtual OutgoingTransportInfoUpdate takeInitialOffer() = 0; - virtual OutgoingTransportInfoUpdate takeOutgoingUpdate() = 0; - virtual bool isValid() const = 0; - virtual Features features() const = 0; - virtual TransportManagerPad::Ptr pad() const = 0; - virtual Connection::Ptr connection() const = 0; // returns established QIODevice-based connection -signals: - void updated(); // found some candidates and they have to be sent. takeUpdate has to be called from this signal handler. - // if it's just always ready then signal has to be sent at least once otherwise session-initiate won't be sent. - void connected(); // this signal is for app logic. maybe to finally start drawing some progress bar - void failed(); // transport ailed for whatever reason. aborted for example -}; - -class Application : public QObject -{ - Q_OBJECT -public: - - enum SetDescError { - Ok, - Unparsed, - IncompatibleParameters // this one is for - }; + Session(Manager *manager, const Jid &peer, Origin role = Origin::Initiator); + ~Session(); - virtual ApplicationManagerPad::Ptr pad() const = 0; - virtual State state() const = 0; - virtual void setState(State state) = 0; // likely just remember the state and not generate any signals - virtual XMPP::Stanza::Error lastError() const = 0; - virtual Reason terminationReason() const = 0; + Manager *manager() const; + State state() const; - virtual Origin creator() const = 0; - virtual Origin senders() const = 0; - virtual QString contentName() const = 0; - virtual Origin transportReplaceOrigin() const = 0; // returns Origin::None if no transport-replace in progress or the side triggered the replace. - virtual SetDescError setDescription(const QDomElement &description) = 0; + Jid me() const; + Jid peer() const; + Jid initiator() const; + Jid responder() const; + QString sid() const; - /** - * @brief setTransport checks if transport is compatible and stores it - * @param transport - * @return false if not compatible - */ - virtual bool setTransport(const QSharedPointer &transport) = 0; - virtual QSharedPointer transport() const = 0; + Origin role() const; // my role in session: initiator or responder + Origin peerRole() const; - /** - * @brief evaluateOutgoingUpdate computes and prepares next update which will be taken with takeOutgoingUpdate - * The updated will be taked immediately if considered to be most preferred among other updates types of - * other applications. - * @return update type - */ - virtual Action evaluateOutgoingUpdate() = 0; - virtual OutgoingUpdate takeOutgoingUpdate() = 0; // this may return something only when evaluateOutgoingUpdate() != NoAction + XMPP::Stanza::Error lastError() const; - /** - * @brief wantBetterTransport checks if the transport is a better match for the application - * @return - */ - virtual bool wantBetterTransport(const QSharedPointer &) const = 0; + // make new local content but do not add it to session yet + Application *newContent(const QString &ns, Origin senders = Origin::Both); + // get registered content if any + Application * content(const QString &contentName, Origin creator); + void addContent(Application *content); + const QMap &contentList() const; - /** - * @brief selectNextTransport selects next transport from compatible transports list. - * The list is usually store in the application - * @return - */ - virtual bool selectNextTransport() = 0; + ApplicationManagerPad::Ptr applicationPad(const QString &ns); + TransportManagerPad::Ptr transportPad(const QString &ns); - /** - * @brief prepare to send content-add/session-initiate - * When ready, the application first set update type to ContentAdd and then emit updated() - */ - virtual void prepare() = 0; - virtual bool accept(const QDomElement &el) = 0; // remote accepted our content - virtual void start() = 0; - virtual void remove(Reason::Condition cond = Reason::Success, const QString &comment = QString()) = 0; + QSharedPointer newOutgoingTransport(const QString &ns); - /** - * @brief incomingTransportReplace it's jingle transport-replace - * @param transport - * @return - */ - virtual bool incomingTransportReplace(const QSharedPointer &transport) = 0; - virtual bool incomingTransportAccept(const QDomElement &transportEl) = 0; - -signals: - void updated(); // signal for session it has to send updates to remote. so it will follow with takeOutgoingUpdate() eventually - void stateChanged(State); -}; - -class Session : public QObject -{ - Q_OBJECT -public: - // Note incoming session are not registered in Jingle Manager until validated. - // and then either rejected or registered in Pending state. - - Session(Manager *manager, const Jid &peer, Origin role = Origin::Initiator); - ~Session(); - - Manager* manager() const; - State state() const; - - Jid me() const; - Jid peer() const; - Jid initiator() const; - Jid responder() const; - QString sid() const; - - Origin role() const; // my role in session: initiator or responder - Origin peerRole() const; - - XMPP::Stanza::Error lastError() const; - - // make new local content but do not add it to session yet - Application *newContent(const QString &ns, Origin senders = Origin::Both); - // get registered content if any - Application *content(const QString &contentName, Origin creator); - void addContent(Application *content); - const QMap &contentList() const; - - ApplicationManagerPad::Ptr applicationPad(const QString &ns); - TransportManagerPad::Ptr transportPad(const QString &ns); - - QSharedPointer newOutgoingTransport(const QString &ns); - - QString preferredApplication() const; - QStringList allApplicationTypes() const; - - void setLocalJid(const Jid &jid); // w/o real use case the implementation is rather stub - - void accept(); - void initiate(); - void terminate(Reason::Condition cond, const QString &comment = QString()); - - // allocates or returns existing pads - ApplicationManagerPad::Ptr applicationPadFactory(const QString &ns); - TransportManagerPad::Ptr transportPadFactory(const QString &ns); -signals: - void managerPadAdded(const QString &ns); - void initiated(); - void activated(); - void terminated(); - void newContentReceived(); - -private: - friend class Manager; - friend class JTPush; - bool incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl); - bool updateFromXml(Action action, const QDomElement &jingleEl); - - class Private; - QScopedPointer d; -}; - -class ApplicationManager : public QObject -{ - Q_OBJECT -public: - ApplicationManager(QObject *parent = nullptr); - - virtual void setJingleManager(Manager *jm) = 0; - virtual Application* startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, Origin creator, Origin senders) = 0; - virtual ApplicationManagerPad *pad(Session *session) = 0; - - // this method is supposed to gracefully close all related sessions as a preparation for plugin unload for example - virtual void closeAll() = 0; -}; - -class TransportManager : public QObject -{ - Q_OBJECT -public: - - TransportManager(QObject *parent = nullptr); - - // may show more features than Transport instance. For example some transports may work in both reliable and not reliable modes - virtual Transport::Features features() const = 0; - virtual void setJingleManager(Manager *jm) = 0; - - // FIXME rename methods - virtual QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) = 0; // outgoing. one have to call Transport::start to collect candidates - virtual QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, const QDomElement &transportEl) = 0; // incoming - virtual TransportManagerPad* pad(Session *session) = 0; - - // this method is supposed to gracefully close all related sessions as a preparation for plugin unload for example - virtual void closeAll() = 0; -signals: - void abortAllRequested(); // mostly used by transport instances to abort immediately -}; - -class Manager : public QObject -{ - Q_OBJECT - -public: - explicit Manager(XMPP::Client *client = nullptr); - ~Manager(); - - XMPP::Client* client() const; - - // if we have another jingle manager we can add its contents' namespaces here. - void addExternalManager(const QString &ns); - // on outgoing session destroy an external manager should call this function. - void registerExternalSession(const QString &sid); - void forgetExternalSession(const QString &sid); - - void setRedirection(const Jid &to); - const Jid &redirectionJid() const; - - void registerApp(const QString &ns, ApplicationManager *app); - void unregisterApp(const QString &ns); - bool isRegisteredApplication(const QString &ns); - ApplicationManagerPad* applicationPad(Session *session, const QString &ns); // allocates new pad on application manager - - void registerTransport(const QString &ns, TransportManager *transport); - void unregisterTransport(const QString &ns); - bool isRegisteredTransport(const QString &ns); - TransportManagerPad* transportPad(Session *session, const QString &ns); // allocates new pad on transport manager - QStringList availableTransports(const Transport::Features &features = Transport::Features()) const; + QString preferredApplication() const; + QStringList allApplicationTypes() const; - /** - * @brief isAllowedParty checks if the remote jid allowed to initiate a session - * @param jid - remote jid - * @return true if allowed - */ - bool isAllowedParty(const Jid &jid) const; - void setRemoteJidChecker(std::function checker); + void setLocalJid(const Jid &jid); // w/o real use case the implementation is rather stub - Session* session(const Jid &remoteJid, const QString &sid); - Session* newSession(const Jid &j); - QString registerSession(Session *session); - XMPP::Stanza::Error lastError() const; + void accept(); + void initiate(); + void terminate(Reason::Condition cond, const QString &comment = QString()); - void detachSession(Session *s); // disconnect the session from manager -signals: - void incomingSession(Session *); + // allocates or returns existing pads + ApplicationManagerPad::Ptr applicationPadFactory(const QString &ns); + TransportManagerPad::Ptr transportPadFactory(const QString &ns); + signals: + void managerPadAdded(const QString &ns); + void initiated(); + void activated(); + void terminated(); + void newContentReceived(); + + private: + friend class Manager; + friend class JTPush; + bool incomingInitiate(const Jingle &jingle, const QDomElement &jingleEl); + bool updateFromXml(Action action, const QDomElement &jingleEl); + + class Private; + QScopedPointer d; + }; -private: - friend class JTPush; - Session *incomingSessionInitiate(const Jid &from, const Jingle &jingle, const QDomElement &jingleEl); + class ApplicationManager : public QObject { + Q_OBJECT + public: + ApplicationManager(QObject *parent = nullptr); - class Private; - QScopedPointer d; -}; + virtual void setJingleManager(Manager *jm) = 0; + virtual Application *startApplication(const ApplicationManagerPad::Ptr &pad, const QString &contentName, + Origin creator, Origin senders) + = 0; + virtual ApplicationManagerPad *pad(Session *session) = 0; + + // this method is supposed to gracefully close all related sessions as a preparation for plugin unload for + // example + virtual void closeAll() = 0; + }; + + class TransportManager : public QObject { + Q_OBJECT + public: + TransportManager(QObject *parent = nullptr); + + // may show more features than Transport instance. For example some transports may work in both reliable and not + // reliable modes + virtual Transport::Features features() const = 0; + virtual void setJingleManager(Manager *jm) = 0; + + // FIXME rename methods + virtual QSharedPointer newTransport(const TransportManagerPad::Ptr &pad) + = 0; // outgoing. one have to call Transport::start to collect candidates + virtual QSharedPointer newTransport(const TransportManagerPad::Ptr &pad, + const QDomElement & transportEl) + = 0; // incoming + virtual TransportManagerPad *pad(Session *session) = 0; + + // this method is supposed to gracefully close all related sessions as a preparation for plugin unload for + // example + virtual void closeAll() = 0; + signals: + void abortAllRequested(); // mostly used by transport instances to abort immediately + }; + + class Manager : public QObject { + Q_OBJECT + + public: + explicit Manager(XMPP::Client *client = nullptr); + ~Manager(); + + XMPP::Client *client() const; + + // if we have another jingle manager we can add its contents' namespaces here. + void addExternalManager(const QString &ns); + // on outgoing session destroy an external manager should call this function. + void registerExternalSession(const QString &sid); + void forgetExternalSession(const QString &sid); + + void setRedirection(const Jid &to); + const Jid &redirectionJid() const; + + void registerApp(const QString &ns, ApplicationManager *app); + void unregisterApp(const QString &ns); + bool isRegisteredApplication(const QString &ns); + ApplicationManagerPad *applicationPad(Session * session, + const QString &ns); // allocates new pad on application manager + + void registerTransport(const QString &ns, TransportManager *transport); + void unregisterTransport(const QString &ns); + bool isRegisteredTransport(const QString &ns); + TransportManagerPad *transportPad(Session * session, + const QString &ns); // allocates new pad on transport manager + QStringList availableTransports(const Transport::Features &features = Transport::Features()) const; + + /** + * @brief isAllowedParty checks if the remote jid allowed to initiate a session + * @param jid - remote jid + * @return true if allowed + */ + bool isAllowedParty(const Jid &jid) const; + void setRemoteJidChecker(std::function checker); + + Session * session(const Jid &remoteJid, const QString &sid); + Session * newSession(const Jid &j); + QString registerSession(Session *session); + XMPP::Stanza::Error lastError() const; + + void detachSession(Session *s); // disconnect the session from manager + signals: + void incomingSession(Session *); + + private: + friend class JTPush; + Session *incomingSessionInitiate(const Jid &from, const Jingle &jingle, const QDomElement &jingleEl); + + class Private; + QScopedPointer d; + }; -Origin negateOrigin(Origin o); + Origin negateOrigin(Origin o); } // namespace Jingle } // namespace XMPP diff --git a/src/xmpp/xmpp-im/s5b.cpp b/src/xmpp/xmpp-im/s5b.cpp index d100d97c..4c8ff4ff 100644 --- a/src/xmpp/xmpp-im/s5b.cpp +++ b/src/xmpp/xmpp-im/s5b.cpp @@ -31,9 +31,9 @@ #include #include #ifdef Q_OS_WIN -# include +#include #else -# include +#include #endif #define MAXSTREAMHOSTS 5 @@ -44,8 +44,8 @@ namespace XMPP { static QString makeKey(const QString &sid, const Jid &requester, const Jid &target) { #ifdef S5B_DEBUG - qDebug("makeKey: sid=%s requester=%s target=%s %s", qPrintable(sid), - qPrintable(requester.full()), qPrintable(target.full()), + qDebug("makeKey: sid=%s requester=%s target=%s %s", qPrintable(sid), qPrintable(requester.full()), + qPrintable(target.full()), qPrintable(QCA::Hash("sha1").hashToString(QString(sid + requester.full() + target.full()).toUtf8()))); #endif QString str = sid + requester.full() + target.full(); @@ -54,15 +54,14 @@ static QString makeKey(const QString &sid, const Jid &requester, const Jid &targ static bool haveHost(const StreamHostList &list, const Jid &j) { - for(StreamHostList::ConstIterator it = list.begin(); it != list.end(); ++it) { - if((*it).jid().compare(j)) + for (StreamHostList::ConstIterator it = list.begin(); it != list.end(); ++it) { + if ((*it).jid().compare(j)) return true; } return false; } -class S5BManager::Item : public QObject -{ +class S5BManager::Item : public QObject { Q_OBJECT public: @@ -70,42 +69,41 @@ class S5BManager::Item : public QObject enum { ErrRefused, ErrConnect, ErrWrongHost, ErrProxy }; enum { Unknown, Fast, NotFast }; - S5BManager *m = nullptr; - int state = 0; - QString sid, key, out_key, out_id, in_id; - Jid self, peer; - StreamHostList in_hosts; - JT_S5B *task = nullptr; - JT_S5B *proxy_task = nullptr; + S5BManager * m = nullptr; + int state = 0; + QString sid, key, out_key, out_id, in_id; + Jid self, peer; + StreamHostList in_hosts; + JT_S5B * task = nullptr; + JT_S5B * proxy_task = nullptr; QList> relatedServers; - SocksClient *client = nullptr; - SocksClient *client_out = nullptr; - SocksUDP *client_udp = nullptr; - SocksUDP *client_out_udp = nullptr; - S5BConnector *conn = nullptr; - S5BConnector *proxy_conn = nullptr; - //S5BServersManager::S5BLocalServers *localServ = nullptr; - bool wantFast = false; + SocksClient * client = nullptr; + SocksClient * client_out = nullptr; + SocksUDP * client_udp = nullptr; + SocksUDP * client_out_udp = nullptr; + S5BConnector * conn = nullptr; + S5BConnector * proxy_conn = nullptr; + // S5BServersManager::S5BLocalServers *localServ = nullptr; + bool wantFast = false; StreamHost proxy; - int targetMode = 0; // requester sets this once it figures it out - bool fast; // target sets this - bool activated; - bool lateProxy; - bool connSuccess; - bool localFailed, remoteFailed; - bool allowIncoming; - bool udp; - int statusCode = 0; - Jid activatedStream; + int targetMode = 0; // requester sets this once it figures it out + bool fast; // target sets this + bool activated; + bool lateProxy; + bool connSuccess; + bool localFailed, remoteFailed; + bool allowIncoming; + bool udp; + int statusCode = 0; + Jid activatedStream; Item(S5BManager *manager); ~Item(); void resetConnection(); void startRequester(const QString &_sid, const Jid &_self, const Jid &_peer, bool fast, bool udp); - void startTarget(const QString &_sid, const Jid &_self, const Jid &_peer, - const QString &_dstaddr, const StreamHostList &hosts, - const QString &iq_id, bool fast, bool udp); + void startTarget(const QString &_sid, const Jid &_self, const Jid &_peer, const QString &_dstaddr, + const StreamHostList &hosts, const QString &iq_id, bool fast, bool udp); void handleFast(const StreamHostList &hosts, const QString &iq_id); void doOutgoing(); @@ -141,62 +139,44 @@ private slots: //---------------------------------------------------------------------------- // S5BDatagram //---------------------------------------------------------------------------- -S5BDatagram::S5BDatagram() -{ -} +S5BDatagram::S5BDatagram() {} -S5BDatagram::S5BDatagram(int source, int dest, const QByteArray &data) - : _source(source) - , _dest(dest) - , _buf(data) -{ -} +S5BDatagram::S5BDatagram(int source, int dest, const QByteArray &data) : _source(source), _dest(dest), _buf(data) {} -int S5BDatagram::sourcePort() const -{ - return _source; -} +int S5BDatagram::sourcePort() const { return _source; } -int S5BDatagram::destPort() const -{ - return _dest; -} +int S5BDatagram::destPort() const { return _dest; } -QByteArray S5BDatagram::data() const -{ - return _buf; -} +QByteArray S5BDatagram::data() const { return _buf; } //---------------------------------------------------------------------------- // S5BConnection //---------------------------------------------------------------------------- -class S5BConnection::Private -{ +class S5BConnection::Private { public: - S5BManager *m; - SocksClient *sc; - SocksUDP *su; - int state; - Jid peer; - QString sid; - bool remote; - bool switched; - bool notifyRead, notifyClose; - int id; - S5BRequest req; - Jid proxy; - Mode mode; - QList dglist; + S5BManager * m; + SocksClient * sc; + SocksUDP * su; + int state; + Jid peer; + QString sid; + bool remote; + bool switched; + bool notifyRead, notifyClose; + int id; + S5BRequest req; + Jid proxy; + Mode mode; + QList dglist; }; -static int id_conn = 0; +static int id_conn = 0; static int num_conn = 0; -S5BConnection::S5BConnection(S5BManager *m, QObject *parent) - : BSConnection(parent) +S5BConnection::S5BConnection(S5BManager *m, QObject *parent) : BSConnection(parent) { - d = new Private; - d->m = m; + d = new Private; + d->m = m; d->sc = nullptr; d->su = nullptr; @@ -224,47 +204,41 @@ S5BConnection::~S5BConnection() void S5BConnection::resetConnection(bool clear) { d->m->con_unlink(this); - if(clear && d->sc) { + if (clear && d->sc) { delete d->sc; d->sc = nullptr; } delete d->su; d->su = nullptr; - if(clear) { + if (clear) { while (!d->dglist.isEmpty()) { delete d->dglist.takeFirst(); } } d->state = Idle; setOpenMode(QIODevice::NotOpen); - d->peer = Jid(); - d->sid = QString(); - d->remote = false; - d->switched = false; - d->notifyRead = false; + d->peer = Jid(); + d->sid = QString(); + d->remote = false; + d->switched = false; + d->notifyRead = false; d->notifyClose = false; } -Jid S5BConnection::proxy() const -{ - return d->proxy; -} +Jid S5BConnection::proxy() const { return d->proxy; } -void S5BConnection::setProxy(const Jid &proxy) -{ - d->proxy = proxy; -} +void S5BConnection::setProxy(const Jid &proxy) { d->proxy = proxy; } void S5BConnection::connectToJid(const Jid &peer, const QString &sid, Mode m) { resetConnection(true); - if(!d->m->isAcceptableSID(peer, sid)) + if (!d->m->isAcceptableSID(peer, sid)) return; - d->peer = peer; - d->sid = sid; + d->peer = peer; + d->sid = sid; d->state = Requesting; - d->mode = m; + d->mode = m; #ifdef S5B_DEBUG qDebug("S5BConnection[%d]: connecting %s [%s]\n", d->id, qPrintable(d->peer.full()), qPrintable(d->sid)); #endif @@ -273,7 +247,7 @@ void S5BConnection::connectToJid(const Jid &peer, const QString &sid, Mode m) void S5BConnection::accept() { - if(d->state != WaitingForAccept) + if (d->state != WaitingForAccept) return; d->state = Connecting; @@ -285,12 +259,12 @@ void S5BConnection::accept() void S5BConnection::close() { - if(d->state == Idle) + if (d->state == Idle) return; - if(d->state == WaitingForAccept) + if (d->state == WaitingForAccept) d->m->con_reject(this); - else if(d->state == Active) + else if (d->state == Active) d->sc->close(); #ifdef S5B_DEBUG qDebug("S5BConnection[%d]: closing %s [%s]\n", d->id, qPrintable(d->peer.full()), qPrintable(d->sid)); @@ -298,46 +272,28 @@ void S5BConnection::close() resetConnection(); } -Jid S5BConnection::peer() const -{ - return d->peer; -} +Jid S5BConnection::peer() const { return d->peer; } -QString S5BConnection::sid() const -{ - return d->sid; -} +QString S5BConnection::sid() const { return d->sid; } -BytestreamManager* S5BConnection::manager() const -{ - return d->m; -} +BytestreamManager *S5BConnection::manager() const { return d->m; } -bool S5BConnection::isRemote() const -{ - return d->remote; -} +bool S5BConnection::isRemote() const { return d->remote; } -S5BConnection::Mode S5BConnection::mode() const -{ - return d->mode; -} +S5BConnection::Mode S5BConnection::mode() const { return d->mode; } -int S5BConnection::state() const -{ - return d->state; -} +int S5BConnection::state() const { return d->state; } qint64 S5BConnection::writeData(const char *data, qint64 maxSize) { - if(d->state == Active && d->mode == Stream) + if (d->state == Active && d->mode == Stream) return d->sc->write(data, maxSize); return 0; } qint64 S5BConnection::readData(char *data, qint64 maxSize) { - if(d->sc) + if (d->sc) return d->sc->read(data, maxSize); else return 0; @@ -345,7 +301,7 @@ qint64 S5BConnection::readData(char *data, qint64 maxSize) qint64 S5BConnection::bytesAvailable() const { - if(d->sc) + if (d->sc) return d->sc->bytesAvailable(); else return 0; @@ -353,7 +309,7 @@ qint64 S5BConnection::bytesAvailable() const qint64 S5BConnection::bytesToWrite() const { - if(d->state == Active) + if (d->state == Active) return d->sc->bytesToWrite(); else return 0; @@ -363,8 +319,8 @@ void S5BConnection::writeDatagram(const S5BDatagram &i) { QByteArray buf; buf.resize(i.data().size() + 4); - ushort ssp = htons(i.sourcePort()); - ushort sdp = htons(i.destPort()); + ushort ssp = htons(i.sourcePort()); + ushort sdp = htons(i.destPort()); QByteArray data = i.data(); memcpy(buf.data(), &ssp, 2); memcpy(buf.data() + 2, &sdp, 2); @@ -374,27 +330,24 @@ void S5BConnection::writeDatagram(const S5BDatagram &i) S5BDatagram S5BConnection::readDatagram() { - if(d->dglist.isEmpty()) + if (d->dglist.isEmpty()) return S5BDatagram(); - S5BDatagram *i = d->dglist.takeFirst(); - S5BDatagram val = *i; + S5BDatagram *i = d->dglist.takeFirst(); + S5BDatagram val = *i; delete i; return val; } -int S5BConnection::datagramsAvailable() const -{ - return d->dglist.count(); -} +int S5BConnection::datagramsAvailable() const { return d->dglist.count(); } void S5BConnection::man_waitForAccept(const S5BRequest &r) { - d->state = WaitingForAccept; + d->state = WaitingForAccept; d->remote = true; - d->req = r; - d->peer = r.from; - d->sid = r.sid; - d->mode = r.udp ? Datagram : Stream; + d->req = r; + d->peer = r.from; + d->sid = r.sid; + d->mode = r.udp ? Datagram : Stream; } void S5BConnection::man_clientReady(SocksClient *sc, SocksUDP *sc_udp) @@ -406,7 +359,7 @@ void S5BConnection::man_clientReady(SocksClient *sc, SocksUDP *sc_udp) connect(d->sc, SIGNAL(bytesWritten(qint64)), SLOT(sc_bytesWritten(qint64))); connect(d->sc, SIGNAL(error(int)), SLOT(sc_error(int))); - if(sc_udp) { + if (sc_udp) { d->su = sc_udp; connect(d->su, SIGNAL(packetReady(QByteArray)), SLOT(su_packetReady(QByteArray))); } @@ -418,57 +371,53 @@ void S5BConnection::man_clientReady(SocksClient *sc, SocksUDP *sc_udp) #endif // bytes already in the stream? - if(d->sc->bytesAvailable()) { + if (d->sc->bytesAvailable()) { #ifdef S5B_DEBUG qDebug("Stream has %d bytes in it.\n", (int)d->sc->bytesAvailable()); #endif d->notifyRead = true; } // closed before it got here? - if(!d->sc->isOpen()) { + if (!d->sc->isOpen()) { #ifdef S5B_DEBUG qDebug("Stream was closed before S5B request finished?\n"); #endif d->notifyClose = true; } - if(d->notifyRead || d->notifyClose) + if (d->notifyRead || d->notifyClose) QTimer::singleShot(0, this, SLOT(doPending())); emit connected(); } void S5BConnection::doPending() { - if(d->notifyRead) { - if(d->notifyClose) + if (d->notifyRead) { + if (d->notifyClose) QTimer::singleShot(0, this, SLOT(doPending())); sc_readyRead(); - } - else if(d->notifyClose) + } else if (d->notifyClose) sc_connectionClosed(); } -void S5BConnection::man_udpReady(const QByteArray &buf) -{ - handleUDP(buf); -} +void S5BConnection::man_udpReady(const QByteArray &buf) { handleUDP(buf); } void S5BConnection::man_failed(int x) { resetConnection(true); - if(x == S5BManager::Item::ErrRefused) + if (x == S5BManager::Item::ErrRefused) setError(ErrRefused); - if(x == S5BManager::Item::ErrConnect) + if (x == S5BManager::Item::ErrConnect) setError(ErrConnect); - if(x == S5BManager::Item::ErrWrongHost) + if (x == S5BManager::Item::ErrWrongHost) setError(ErrConnect); - if(x == S5BManager::Item::ErrProxy) + if (x == S5BManager::Item::ErrProxy) setError(ErrProxy); } void S5BConnection::sc_connectionClosed() { // if we have a pending read notification, postpone close - if(d->notifyRead) { + if (d->notifyRead) { #ifdef S5B_DEBUG qDebug("closed while pending read\n"); #endif @@ -488,7 +437,7 @@ void S5BConnection::sc_delayedCloseFinished() void S5BConnection::sc_readyRead() { - if(d->mode == Datagram) { + if (d->mode == Datagram) { // throw the data away d->sc->readAll(); return; @@ -511,22 +460,19 @@ void S5BConnection::sc_error(int) setError(ErrSocket); } -void S5BConnection::su_packetReady(const QByteArray &buf) -{ - handleUDP(buf); -} +void S5BConnection::su_packetReady(const QByteArray &buf) { handleUDP(buf); } void S5BConnection::handleUDP(const QByteArray &buf) { // must be at least 4 bytes, to accomodate virtual ports - if(buf.size() < 4) + if (buf.size() < 4) return; // drop ushort ssp, sdp; memcpy(&ssp, buf.data(), 2); memcpy(&sdp, buf.data() + 2, 2); - int source = ntohs(ssp); - int dest = ntohs(sdp); + int source = ntohs(ssp); + int dest = ntohs(sdp); QByteArray data; data.resize(buf.size() - 4); memcpy(data.data(), buf.data() + 4, data.size()); @@ -537,7 +483,7 @@ void S5BConnection::handleUDP(const QByteArray &buf) void S5BConnection::sendUDP(const QByteArray &buf) { - if(d->su) + if (d->su) d->su->write(buf); else d->m->con_sendUDP(this, buf); @@ -546,50 +492,44 @@ void S5BConnection::sendUDP(const QByteArray &buf) //---------------------------------------------------------------------------- // S5BManager //---------------------------------------------------------------------------- -class S5BManager::Entry -{ +class S5BManager::Entry { public: Entry() = default; - ~Entry() - { - delete query; - } + ~Entry() { delete query; } S5BConnection *c = nullptr; - Item *i = nullptr; - QString sid; - JT_S5B *query = nullptr; - StreamHost proxyInfo; + Item * i = nullptr; + QString sid; + JT_S5B * query = nullptr; + StreamHost proxyInfo; - bool udp_init = false; + bool udp_init = false; QHostAddress udp_addr; - int udp_port = 0; + int udp_port = 0; }; -class S5BManager::Private -{ +class S5BManager::Private { public: - Client *client; - QList activeList; + Client * client; + QList activeList; S5BConnectionList incomingConns; - JT_PushS5B *ps; + JT_PushS5B * ps; }; -S5BManager::S5BManager(Client *parent) - : BytestreamManager(parent) +S5BManager::S5BManager(Client *parent) : BytestreamManager(parent) { // S5B needs SHA1 - //if(!QCA::isSupported(QCA::CAP_SHA1)) + // if(!QCA::isSupported(QCA::CAP_SHA1)) // QCA::insertProvider(createProviderHash()); - d = new Private; + d = new Private; d->client = parent; d->ps = new JT_PushS5B(d->client->rootTask()); connect(d->ps, SIGNAL(incoming(S5BRequest)), SLOT(ps_incoming(S5BRequest))); - connect(d->ps, SIGNAL(incomingUDPSuccess(Jid,QString)), SLOT(ps_incomingUDPSuccess(Jid,QString))); - connect(d->ps, SIGNAL(incomingActivate(Jid,QString,Jid)), SLOT(ps_incomingActivate(Jid,QString,Jid))); + connect(d->ps, SIGNAL(incomingUDPSuccess(Jid, QString)), SLOT(ps_incomingUDPSuccess(Jid, QString))); + connect(d->ps, SIGNAL(incomingActivate(Jid, QString, Jid)), SLOT(ps_incomingActivate(Jid, QString, Jid))); } S5BManager::~S5BManager() @@ -601,37 +541,25 @@ S5BManager::~S5BManager() delete d; } -const char* S5BManager::ns() -{ - return S5B_NS; -} +const char *S5BManager::ns() { return S5B_NS; } -Client *S5BManager::client() const -{ - return d->client; -} +Client *S5BManager::client() const { return d->client; } -JT_PushS5B* S5BManager::jtPush() const -{ - return d->ps; -} +JT_PushS5B *S5BManager::jtPush() const { return d->ps; } -BSConnection *S5BManager::createConnection() -{ - return new S5BConnection(this); -} +BSConnection *S5BManager::createConnection() { return new S5BConnection(this); } S5BConnection *S5BManager::takeIncoming() { - if(d->incomingConns.isEmpty()) + if (d->incomingConns.isEmpty()) return nullptr; S5BConnection *c = d->incomingConns.takeFirst(); // move to activeList Entry *e = new Entry; - e->c = c; - e->sid = c->d->sid; + e->c = c; + e->sid = c->d->sid; d->activeList.append(e); return c; @@ -646,20 +574,20 @@ void S5BManager::ps_incoming(const S5BRequest &req) bool ok = false; // ensure we don't already have an incoming connection from this peer+sid S5BConnection *c = findIncoming(req.from, req.sid); - if(!c) { + if (!c) { // do we have an active entry with this sid already? Entry *e = findEntryBySID(req.from, req.sid); - if(e) { - if(e->i) { + if (e) { + if (e->i) { // loopback - if(req.from.compare(d->client->jid()) && (req.id == e->i->out_id)) { + if (req.from.compare(d->client->jid()) && (req.id == e->i->out_id)) { #ifdef S5B_DEBUG qDebug("ALLOWED: loopback\n"); #endif ok = true; } // allowed by 'fast mode' - else if(e->i->state == Item::Requester && e->i->targetMode == Item::Unknown) { + else if (e->i->state == Item::Requester && e->i->targetMode == Item::Unknown) { #ifdef S5B_DEBUG qDebug("ALLOWED: fast-mode\n"); #endif @@ -667,15 +595,14 @@ void S5BManager::ps_incoming(const S5BRequest &req) return; } } - } - else { + } else { #ifdef S5B_DEBUG qDebug("ALLOWED: we don't have it\n"); #endif ok = true; } } - if(!ok) { + if (!ok) { d->ps->respondError(req.from, req.id, Stanza::Error::NotAcceptable, "SID in use"); return; } @@ -690,10 +617,10 @@ void S5BManager::ps_incoming(const S5BRequest &req) void S5BManager::ps_incomingUDPSuccess(const Jid &from, const QString &key) { Entry *e = findEntryByHash(key); - if(e && e->i) { - if(e->i->conn) + if (e && e->i) { + if (e->i->conn) e->i->conn->man_udpSuccess(from); - else if(e->i->proxy_conn) + else if (e->i->proxy_conn) e->i->proxy_conn->man_udpSuccess(from); } } @@ -701,7 +628,7 @@ void S5BManager::ps_incomingUDPSuccess(const Jid &from, const QString &key) void S5BManager::ps_incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost) { Entry *e = findEntryBySID(from, sid); - if(e && e->i) + if (e && e->i) e->i->incomingActivate(streamHost); } @@ -710,8 +637,7 @@ void S5BManager::doSuccess(const Jid &peer, const QString &id, const Jid &stream d->ps->respondSuccess(peer, id, streamHost); } -void S5BManager::doError(const Jid &peer, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str) +void S5BManager::doError(const Jid &peer, const QString &id, Stanza::Error::ErrorCond cond, const QString &str) { d->ps->respondError(peer, id, cond, str); } @@ -723,15 +649,15 @@ void S5BManager::doActivate(const Jid &peer, const QString &sid, const Jid &stre bool S5BManager::isAcceptableSID(const Jid &peer, const QString &sid) const { - QString key = makeKey(sid, d->client->jid(), peer); - QString key_out = makeKey(sid, peer, d->client->jid()); //not valid in muc via proxy + QString key = makeKey(sid, d->client->jid(), peer); + QString key_out = makeKey(sid, peer, d->client->jid()); // not valid in muc via proxy - foreach(Entry *e, d->activeList) { - if(e->i) { + foreach (Entry *e, d->activeList) { + if (e->i) { if (e->i->key == key || e->i->key == key_out) return false; else { - for (auto &s: e->i->relatedServers) { + for (auto &s : e->i->relatedServers) { if (s->hasKey(key) || s->hasKey(key_out)) { return false; } @@ -743,15 +669,12 @@ bool S5BManager::isAcceptableSID(const Jid &peer, const QString &sid) const return true; } -const char* S5BManager::sidPrefix() const -{ - return "s5b_"; -} +const char *S5BManager::sidPrefix() const { return "s5b_"; } S5BConnection *S5BManager::findIncoming(const Jid &from, const QString &sid) const { - foreach(S5BConnection *c, d->incomingConns) { - if(c->d->peer.compare(from) && c->d->sid == sid) + foreach (S5BConnection *c, d->incomingConns) { + if (c->d->peer.compare(from) && c->d->sid == sid) return c; } return nullptr; @@ -759,8 +682,8 @@ S5BConnection *S5BManager::findIncoming(const Jid &from, const QString &sid) con S5BManager::Entry *S5BManager::findEntry(S5BConnection *c) const { - foreach(Entry *e, d->activeList) { - if(e->c == c) + foreach (Entry *e, d->activeList) { + if (e->c == c) return e; } return nullptr; @@ -768,8 +691,8 @@ S5BManager::Entry *S5BManager::findEntry(S5BConnection *c) const S5BManager::Entry *S5BManager::findEntry(Item *i) const { - foreach(Entry *e, d->activeList) { - if(e->i == i) + foreach (Entry *e, d->activeList) { + if (e->i == i) return e; } return nullptr; @@ -777,8 +700,8 @@ S5BManager::Entry *S5BManager::findEntry(Item *i) const S5BManager::Entry *S5BManager::findEntryByHash(const QString &key) const { - foreach(Entry *e, d->activeList) { - if(e->i && e->i->key == key) + foreach (Entry *e, d->activeList) { + if (e->i && e->i->key == key) return e; } return nullptr; @@ -786,8 +709,8 @@ S5BManager::Entry *S5BManager::findEntryByHash(const QString &key) const S5BManager::Entry *S5BManager::findEntryBySID(const Jid &peer, const QString &sid) const { - foreach(Entry *e, d->activeList) { - if(e->i && e->i->peer.compare(peer) && e->sid == sid) + foreach (Entry *e, d->activeList) { + if (e->i && e->i->peer.compare(peer) && e->sid == sid) return e; } return nullptr; @@ -795,7 +718,7 @@ S5BManager::Entry *S5BManager::findEntryBySID(const Jid &peer, const QString &si bool S5BManager::srv_ownsHash(const QString &key) const { - if(findEntryByHash(key)) + if (findEntryByHash(key)) return true; return false; } @@ -803,25 +726,26 @@ bool S5BManager::srv_ownsHash(const QString &key) const void S5BManager::srv_incomingReady(SocksClient *sc, const QString &key) { Entry *e = findEntryByHash(key); - if(!e->i->allowIncoming) { + if (!e->i->allowIncoming) { sc->requestDeny(); return; } - if(e->c->d->mode == S5BConnection::Datagram) + if (e->c->d->mode == S5BConnection::Datagram) sc->grantUDPAssociate("", 0); else sc->grantConnect(); e->i->setIncomingClient(sc); } -void S5BManager::srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data) +void S5BManager::srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, + const QByteArray &data) { Entry *e = findEntryByHash(key); - if(e->c->d->mode != S5BConnection::Datagram) + if (e->c->d->mode != S5BConnection::Datagram) return; // this key isn't in udp mode? drop! - if(init) { - if(e->udp_init) + if (init) { + if (e->udp_init) return; // only init once // lock on to this sender @@ -835,11 +759,11 @@ void S5BManager::srv_incomingUDP(bool init, const QHostAddress &addr, int port, } // not initialized yet? something went wrong - if(!e->udp_init) + if (!e->udp_init) return; // must come from same source as when initialized - if(addr.toString() != e->udp_addr.toString() || port != e->udp_port) + if (addr.toString() != e->udp_addr.toString() || port != e->udp_port) return; e->c->man_udpReady(data); @@ -847,14 +771,14 @@ void S5BManager::srv_incomingUDP(bool init, const QHostAddress &addr, int port, void S5BManager::con_connect(S5BConnection *c) { - if(findEntry(c)) + if (findEntry(c)) return; Entry *e = new Entry; - e->c = c; - e->sid = c->d->sid; + e->c = c; + e->sid = c->d->sid; d->activeList.append(e); - if(c->d->proxy.isValid()) { + if (c->d->proxy.isValid()) { queryProxy(e); return; } @@ -864,11 +788,11 @@ void S5BManager::con_connect(S5BConnection *c) void S5BManager::con_accept(S5BConnection *c) { Entry *e = findEntry(c); - if(!e) + if (!e) return; - if(e->c->d->req.fast) { - if(targetShouldOfferProxy(e)) { + if (e->c->d->req.fast) { + if (targetShouldOfferProxy(e)) { queryProxy(e); return; } @@ -878,20 +802,18 @@ void S5BManager::con_accept(S5BConnection *c) void S5BManager::con_reject(S5BConnection *c) { - d->ps->respondError(c->d->peer, c->d->req.id, Stanza::Error::NotAcceptable, - "Not acceptable"); + d->ps->respondError(c->d->peer, c->d->req.id, Stanza::Error::NotAcceptable, "Not acceptable"); } void S5BManager::con_unlink(S5BConnection *c) { Entry *e = findEntry(c); - if(!e) + if (!e) return; // active incoming request? cancel it - if(e->i && e->i->conn) - d->ps->respondError(e->i->peer, e->i->out_id, - Stanza::Error::NotAcceptable, "Not acceptable"); + if (e->i && e->i->conn) + d->ps->respondError(e->i->peer, e->i->out_id, Stanza::Error::NotAcceptable, "Not acceptable"); delete e->i; d->activeList.removeAll(e); delete e; @@ -900,18 +822,18 @@ void S5BManager::con_unlink(S5BConnection *c) void S5BManager::con_sendUDP(S5BConnection *c, const QByteArray &buf) { Entry *e = findEntry(c); - if(!e) + if (!e) return; - if(!e->udp_init) + if (!e->udp_init) return; - if(e->i->relatedServers.size()) // FIXME in fact we shoule keep eact related server in Connection + if (e->i->relatedServers.size()) // FIXME in fact we shoule keep eact related server in Connection e->i->relatedServers[0]->writeUDP(e->udp_addr, e->udp_port, buf); } void S5BManager::item_accepted() { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); emit e->c->accepted(); // signal @@ -919,7 +841,7 @@ void S5BManager::item_accepted() void S5BManager::item_tryingHosts(const StreamHostList &list) { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); e->c->tryingHosts(list); // signal @@ -927,7 +849,7 @@ void S5BManager::item_tryingHosts(const StreamHostList &list) void S5BManager::item_proxyConnect() { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); e->c->proxyConnect(); // signal @@ -935,7 +857,7 @@ void S5BManager::item_proxyConnect() void S5BManager::item_waitingForActivation() { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); e->c->waitingForActivation(); // signal @@ -943,14 +865,14 @@ void S5BManager::item_waitingForActivation() void S5BManager::item_connected() { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); // grab the client - SocksClient *client = i->client; - i->client = nullptr; + SocksClient *client = i->client; + i->client = nullptr; SocksUDP *client_udp = i->client_udp; - i->client_udp = nullptr; + i->client_udp = nullptr; // give it to the connection e->c->man_clientReady(client, client_udp); @@ -958,7 +880,7 @@ void S5BManager::item_connected() void S5BManager::item_error(int x) { - Item *i = static_cast(sender()); + Item * i = static_cast(sender()); Entry *e = findEntry(i); e->c->man_failed(x); @@ -966,7 +888,7 @@ void S5BManager::item_error(int x) void S5BManager::entryContinue(Entry *e) { - e->i = new Item(this); + e->i = new Item(this); e->i->proxy = e->proxyInfo; connect(e->i, SIGNAL(accepted()), SLOT(item_accepted())); @@ -976,12 +898,12 @@ void S5BManager::entryContinue(Entry *e) connect(e->i, SIGNAL(connected()), SLOT(item_connected())); connect(e->i, SIGNAL(error(int)), SLOT(item_error(int))); - if(e->c->isRemote()) { + if (e->c->isRemote()) { const S5BRequest &req = e->c->d->req; e->i->startTarget(e->sid, d->client->jid(), e->c->d->peer, req.dstaddr, req.hosts, req.id, req.fast, req.udp); - } - else { - e->i->startRequester(e->sid, d->client->jid(), e->c->d->peer, true, e->c->d->mode == S5BConnection::Datagram ? true: false); + } else { + e->i->startRequester(e->sid, d->client->jid(), e->c->d->peer, true, + e->c->d->mode == S5BConnection::Datagram ? true : false); e->c->requesting(); // signal } } @@ -990,7 +912,7 @@ void S5BManager::queryProxy(Entry *e) { QPointer self = this; e->c->proxyQuery(); // signal - if(!self) + if (!self) return; #ifdef S5B_DEBUG @@ -1005,27 +927,26 @@ void S5BManager::queryProxy(Entry *e) void S5BManager::query_finished() { JT_S5B *query = static_cast(sender()); - Entry* e = nullptr; - foreach(Entry* i, d->activeList) { - if(i->query == query) { + Entry * e = nullptr; + foreach (Entry *i, d->activeList) { + if (i->query == query) { e = i; break; } } - if(!e) + if (!e) return; e->query = nullptr; #ifdef S5B_DEBUG qDebug("query finished: "); #endif - if(query->success()) { + if (query->success()) { e->proxyInfo = query->proxyInfo(); #ifdef S5B_DEBUG qDebug("host/ip=[%s] port=[%d]\n", qPrintable(e->proxyInfo.host()), e->proxyInfo.port()); #endif - } - else { + } else { #ifdef S5B_DEBUG qDebug("fail\n"); #endif @@ -1033,7 +954,7 @@ void S5BManager::query_finished() QPointer self = this; e->c->proxyResult(query->success()); // signal - if(!self) + if (!self) return; entryContinue(e); @@ -1041,18 +962,18 @@ void S5BManager::query_finished() bool S5BManager::targetShouldOfferProxy(Entry *e) { - if(!e->c->d->proxy.isValid()) + if (!e->c->d->proxy.isValid()) return false; // if target, don't offer any proxy if the requester already did const StreamHostList &hosts = e->c->d->req.hosts; - for(StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { - if((*it).isProxy()) + for (StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { + if ((*it).isProxy()) return false; } // ensure we don't offer the same proxy as the requester - if(haveHost(hosts, e->c->d->proxy)) + if (haveHost(hosts, e->c->d->proxy)) return false; return true; @@ -1061,21 +982,13 @@ bool S5BManager::targetShouldOfferProxy(Entry *e) //---------------------------------------------------------------------------- // S5BManager::Item //---------------------------------------------------------------------------- -S5BManager::Item::Item(S5BManager *manager) - : QObject(nullptr) - , m(manager) -{ - resetConnection(); -} +S5BManager::Item::Item(S5BManager *manager) : QObject(nullptr), m(manager) { resetConnection(); } -S5BManager::Item::~Item() -{ - resetConnection(); -} +S5BManager::Item::~Item() { resetConnection(); } void S5BManager::Item::resetConnection() { - for (auto &s: relatedServers) { + for (auto &s : relatedServers) { s->unregisterKey(key); s.reset(); } @@ -1104,56 +1017,56 @@ void S5BManager::Item::resetConnection() delete client_out; client_out = nullptr; - state = Idle; - wantFast = false; - targetMode = Unknown; - fast = false; - activated = false; - lateProxy = false; - connSuccess = false; - localFailed = false; - remoteFailed = false; + state = Idle; + wantFast = false; + targetMode = Unknown; + fast = false; + activated = false; + lateProxy = false; + connSuccess = false; + localFailed = false; + remoteFailed = false; allowIncoming = false; - udp = false; + udp = false; } void S5BManager::Item::startRequester(const QString &_sid, const Jid &_self, const Jid &_peer, bool fast, bool _udp) { - sid = _sid; - self = _self; - peer = _peer; - key = makeKey(sid, self, peer); - out_key = makeKey(sid, peer, self); + sid = _sid; + self = _self; + peer = _peer; + key = makeKey(sid, self, peer); + out_key = makeKey(sid, peer, self); wantFast = fast; - udp = _udp; + udp = _udp; #ifdef S5B_DEBUG - qDebug("S5BManager::Item initiating request %s [%s] (inhash=%s)\n", qPrintable(peer.full()), qPrintable(sid), qPrintable(key)); + qDebug("S5BManager::Item initiating request %s [%s] (inhash=%s)\n", qPrintable(peer.full()), qPrintable(sid), + qPrintable(key)); #endif state = Requester; doOutgoing(); } -void S5BManager::Item::startTarget(const QString &_sid, const Jid &_self, - const Jid &_peer, const QString &_dstaddr, - const StreamHostList &hosts, const QString &iq_id, - bool _fast, bool _udp) +void S5BManager::Item::startTarget(const QString &_sid, const Jid &_self, const Jid &_peer, const QString &_dstaddr, + const StreamHostList &hosts, const QString &iq_id, bool _fast, bool _udp) { - sid = _sid; - peer = _peer; - self = _self; + sid = _sid; + peer = _peer; + self = _self; in_hosts = hosts; - in_id = iq_id; - fast = _fast; - key = makeKey(sid, self, peer); - out_key = _dstaddr.isEmpty() ? makeKey(sid, peer, self) : _dstaddr; - udp = _udp; + in_id = iq_id; + fast = _fast; + key = makeKey(sid, self, peer); + out_key = _dstaddr.isEmpty() ? makeKey(sid, peer, self) : _dstaddr; + udp = _udp; #ifdef S5B_DEBUG - qDebug("S5BManager::Item incoming request %s [%s] (inhash=%s)\n", qPrintable(peer.full()), qPrintable(sid), qPrintable(key)); + qDebug("S5BManager::Item incoming request %s [%s] (inhash=%s)\n", qPrintable(peer.full()), qPrintable(sid), + qPrintable(key)); #endif state = Target; - if(fast) + if (fast) doOutgoing(); doIncoming(); } @@ -1163,17 +1076,16 @@ void S5BManager::Item::handleFast(const StreamHostList &hosts, const QString &iq targetMode = Fast; QPointer self = this; - emit accepted(); - if(!self) + emit accepted(); + if (!self) return; // if we already have a stream, then bounce this request - if(client) { + if (client) { m->doError(peer, iq_id, Stanza::Error::NotAcceptable, "Not acceptable"); - } - else { + } else { in_hosts = hosts; - in_id = iq_id; + in_id = iq_id; doIncoming(); } } @@ -1181,8 +1093,8 @@ void S5BManager::Item::handleFast(const StreamHostList &hosts, const QString &iq void S5BManager::Item::doOutgoing() { StreamHostList hosts; - auto disco = m->client()->tcpPortReserver()->scope(QString::fromLatin1("s5b"))->disco(); - if(!haveHost(in_hosts, self)) { + auto disco = m->client()->tcpPortReserver()->scope(QString::fromLatin1("s5b"))->disco(); + if (!haveHost(in_hosts, self)) { foreach (auto &c, disco->takeServers()) { auto server = c.staticCast(); server->registerKey(key); @@ -1192,11 +1104,13 @@ void S5BManager::Item::doOutgoing() m->srv_incomingReady(c, key); } }); - connect(server.data(), &S5BServer::incomingUdp, this, [this](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data) { - if (key == this->key) { - m->srv_incomingUDP(isInit, addr, sourcePort, key, data); - } - }); + connect(server.data(), &S5BServer::incomingUdp, this, + [this](bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, + const QByteArray &data) { + if (key == this->key) { + m->srv_incomingUDP(isInit, addr, sourcePort, key, data); + } + }); StreamHost h; h.setJid(self); h.setHost(c->publishHost()); @@ -1207,11 +1121,11 @@ void S5BManager::Item::doOutgoing() delete disco; // FIXME we could start listening for signals instead. it may send us upnp candidate // if the proxy is valid, then it's ok to add (the manager already ensured that it doesn't conflict) - if(proxy.jid().isValid()) + if (proxy.jid().isValid()) hosts += proxy; // if we're the target and we have no streamhosts of our own, then don't even bother with fast-mode - if(state == Target && hosts.isEmpty()) { + if (state == Target && hosts.isEmpty()) { fast = false; return; } @@ -1227,40 +1141,38 @@ void S5BManager::Item::doOutgoing() void S5BManager::Item::doIncoming() { - if(in_hosts.isEmpty()) { + if (in_hosts.isEmpty()) { doConnectError(); return; } StreamHostList list; - if(lateProxy) { + if (lateProxy) { // take just the proxy streamhosts - foreach (const StreamHost& it, in_hosts) { + foreach (const StreamHost &it, in_hosts) { if (it.isProxy()) list += it; } lateProxy = false; - } - else { + } else { // only try doing the late proxy trick if using fast mode AND we did not offer a proxy - if((state == Requester || (state == Target && fast)) && !proxy.jid().isValid()) { + if ((state == Requester || (state == Target && fast)) && !proxy.jid().isValid()) { // take just the non-proxy streamhosts bool hasProxies = false; - foreach (const StreamHost& it, in_hosts) { + foreach (const StreamHost &it, in_hosts) { if (it.isProxy()) hasProxies = true; else list += it; } - if(hasProxies) { + if (hasProxies) { lateProxy = true; // no regular streamhosts? wait for remote error - if(list.isEmpty()) + if (list.isEmpty()) return; } - } - else + } else list = in_hosts; } @@ -1269,7 +1181,7 @@ void S5BManager::Item::doIncoming() QPointer self = this; tryingHosts(list); - if(!self) + if (!self) return; conn->start(this->self, list, out_key, udp, lateProxy ? 10 : 30); @@ -1286,13 +1198,13 @@ void S5BManager::Item::setIncomingClient(SocksClient *sc) connect(sc, SIGNAL(error(int)), SLOT(sc_error(int))); sc->setParent(nullptr); // avoid deleting it by SocksServer destructor - client = sc; + client = sc; allowIncoming = false; } void S5BManager::Item::incomingActivate(const Jid &streamHost) { - if(!activated) { + if (!activated) { activatedStream = streamHost; checkForActivation(); } @@ -1301,31 +1213,31 @@ void S5BManager::Item::incomingActivate(const Jid &streamHost) void S5BManager::Item::jt_finished() { JT_S5B *j = task; - task = nullptr; + task = nullptr; #ifdef S5B_DEBUG qDebug("jt_finished: state=%s, %s\n", state == Requester ? "requester" : "target", j->success() ? "ok" : "fail"); #endif - if(state == Requester) { - if(targetMode == Unknown) { - targetMode = NotFast; + if (state == Requester) { + if (targetMode == Unknown) { + targetMode = NotFast; QPointer self = this; - emit accepted(); - if(!self) + emit accepted(); + if (!self) return; } } // if we've already reported successfully connecting to them, then this response doesn't matter - if(state == Requester && connSuccess) { + if (state == Requester && connSuccess) { tryActivation(); return; } - if(j->success()) { + if (j->success()) { // stop connecting out - if(conn || lateProxy) { + if (conn || lateProxy) { delete conn; conn = nullptr; doConnectError(); @@ -1334,27 +1246,25 @@ void S5BManager::Item::jt_finished() Jid streamHost = j->streamHostUsed(); // they connected to us? - if(streamHost.compare(self)) { - if(client) { - if(state == Requester) { + if (streamHost.compare(self)) { + if (client) { + if (state == Requester) { activatedStream = streamHost; tryActivation(); - } - else + } else checkForActivation(); - } - else { + } else { #ifdef S5B_DEBUG - qDebug("S5BManager::Item %s claims to have connected to us, but we don't see this\n", qPrintable(peer.full())); + qDebug("S5BManager::Item %s claims to have connected to us, but we don't see this\n", + qPrintable(peer.full())); #endif resetConnection(); error(ErrWrongHost); } - } - else if(streamHost.compare(proxy.jid())) { + } else if (streamHost.compare(proxy.jid())) { // toss out any direct incoming, since it won't be used delete client; - client = nullptr; + client = nullptr; allowIncoming = false; #ifdef S5B_DEBUG @@ -1368,33 +1278,31 @@ void S5BManager::Item::jt_finished() QPointer self = this; proxyConnect(); - if(!self) + if (!self) return; proxy_conn->start(this->self, list, key, udp, 30); - } - else { + } else { #ifdef S5B_DEBUG - qDebug("S5BManager::Item %s claims to have connected to a streamhost we never offered\n", qPrintable(peer.full())); + qDebug("S5BManager::Item %s claims to have connected to a streamhost we never offered\n", + qPrintable(peer.full())); #endif resetConnection(); error(ErrWrongHost); } - } - else { + } else { #ifdef S5B_DEBUG qDebug("S5BManager::Item %s [%s] error\n", qPrintable(peer.full()), qPrintable(sid)); #endif remoteFailed = true; - statusCode = j->statusCode(); + statusCode = j->statusCode(); - if(lateProxy) { - if(!conn) + if (lateProxy) { + if (!conn) doIncoming(); - } - else { + } else { // if connSuccess is true at this point, then we're a Target - if(connSuccess) + if (connSuccess) checkForActivation(); else checkFailure(); @@ -1404,17 +1312,16 @@ void S5BManager::Item::jt_finished() void S5BManager::Item::conn_result(bool b) { - if(b) { - SocksClient *sc = conn->takeClient(); - SocksUDP *sc_udp = conn->takeUDP(); - StreamHost h = conn->streamHostUsed(); + if (b) { + SocksClient *sc = conn->takeClient(); + SocksUDP * sc_udp = conn->takeUDP(); + StreamHost h = conn->streamHostUsed(); delete conn; - conn = nullptr; + conn = nullptr; connSuccess = true; #ifdef S5B_DEBUG - qDebug("S5BManager::Item: %s [%s] successful outgoing connection\n", - qPrintable(peer.full()), qPrintable(sid)); + qDebug("S5BManager::Item: %s [%s] successful outgoing connection\n", qPrintable(peer.full()), qPrintable(sid)); #endif connect(sc, SIGNAL(readyRead()), SLOT(sc_readyRead())); @@ -1427,32 +1334,29 @@ void S5BManager::Item::conn_result(bool b) lateProxy = false; // if requester, run with this one - if(state == Requester) { + if (state == Requester) { // if we had an incoming one, toss it delete client_udp; client_udp = sc_udp; delete client; - client = sc; - allowIncoming = false; + client = sc; + allowIncoming = false; activatedStream = peer; tryActivation(); - } - else { + } else { client_out_udp = sc_udp; - client_out = sc; + client_out = sc; checkForActivation(); } - } - else { + } else { delete conn; conn = nullptr; // if we delayed the proxies for later, try now - if(lateProxy) { - if(remoteFailed) + if (lateProxy) { + if (remoteFailed) doIncoming(); - } - else + } else doConnectError(); } } @@ -1462,9 +1366,9 @@ void S5BManager::Item::proxy_result(bool b) #ifdef S5B_DEBUG qDebug("proxy_result: %s\n", b ? "ok" : "fail"); #endif - if(b) { - SocksClient *sc = proxy_conn->takeClient(); - SocksUDP *sc_udp = proxy_conn->takeUDP(); + if (b) { + SocksClient *sc = proxy_conn->takeClient(); + SocksUDP * sc_udp = proxy_conn->takeUDP(); delete proxy_conn; proxy_conn = nullptr; @@ -1472,7 +1376,7 @@ void S5BManager::Item::proxy_result(bool b) connect(sc, SIGNAL(bytesWritten(qint64)), SLOT(sc_bytesWritten(qint64))); connect(sc, SIGNAL(error(int)), SLOT(sc_error(int))); - client = sc; + client = sc; client_udp = sc_udp; // activate @@ -1483,8 +1387,7 @@ void S5BManager::Item::proxy_result(bool b) connect(proxy_task, SIGNAL(finished()), SLOT(proxy_finished())); proxy_task->requestActivation(proxy.jid(), sid, peer); proxy_task->go(true); - } - else { + } else { delete proxy_conn; proxy_conn = nullptr; resetConnection(); @@ -1494,21 +1397,19 @@ void S5BManager::Item::proxy_result(bool b) void S5BManager::Item::proxy_finished() { - JT_S5B *j = proxy_task; + JT_S5B *j = proxy_task; proxy_task = nullptr; - if(j->success()) { + if (j->success()) { #ifdef S5B_DEBUG qDebug("proxy stream activated\n"); #endif - if(state == Requester) { + if (state == Requester) { activatedStream = proxy.jid(); tryActivation(); - } - else + } else checkForActivation(); - } - else { + } else { resetConnection(); error(ErrProxy); } @@ -1520,7 +1421,7 @@ void S5BManager::Item::sc_readyRead() qDebug("sc_readyRead\n"); #endif // only targets check for activation, and only should do it if there is no pending outgoing iq-set - if(state == Target && !task && !proxy_task) + if (state == Target && !task && !proxy_task) checkForActivation(); } @@ -1545,8 +1446,7 @@ void S5BManager::Item::sc_error(int) void S5BManager::Item::doConnectError() { localFailed = true; - m->doError(peer, in_id, Stanza::Error::RemoteServerNotFound, - "Could not connect to given hosts"); + m->doError(peer, in_id, Stanza::Error::RemoteServerNotFound, "Could not connect to given hosts"); checkFailure(); } @@ -1555,21 +1455,20 @@ void S5BManager::Item::tryActivation() #ifdef S5B_DEBUG qDebug("tryActivation\n"); #endif - if(activated) { + if (activated) { #ifdef S5B_DEBUG qDebug("already activated !?\n"); #endif return; } - if(targetMode == NotFast) { + if (targetMode == NotFast) { #ifdef S5B_DEBUG qDebug("tryActivation: NotFast\n"); #endif // nothing to activate, we're done finished(); - } - else if(targetMode == Fast) { + } else if (targetMode == Fast) { // with fast mode, we don't wait for the iq reply, so delete the task (if any) delete task; task = nullptr; @@ -1577,10 +1476,9 @@ void S5BManager::Item::tryActivation() activated = true; // if udp, activate using special stanza - if(udp) { + if (udp) { m->doActivate(peer, sid, activatedStream); - } - else { + } else { #ifdef S5B_DEBUG qDebug("sending extra CR\n"); #endif @@ -1592,31 +1490,31 @@ void S5BManager::Item::tryActivation() void S5BManager::Item::checkForActivation() { - QList clientList; - if(client) + QList clientList; + if (client) clientList.append(client); - if(client_out) + if (client_out) clientList.append(client_out); - foreach(SocksClient *sc, clientList) { + foreach (SocksClient *sc, clientList) { #ifdef S5B_DEBUG qDebug("checking for activation\n"); #endif - if(fast) { + if (fast) { bool ok = false; - if(udp) { - if((sc == client_out && activatedStream.compare(self)) || (sc == client && !activatedStream.compare(self))) { + if (udp) { + if ((sc == client_out && activatedStream.compare(self)) + || (sc == client && !activatedStream.compare(self))) { clientList.removeAll(sc); ok = true; } - } - else { + } else { #ifdef S5B_DEBUG qDebug("need CR\n"); #endif - if(sc->bytesAvailable() >= 1) { + if (sc->bytesAvailable() >= 1) { clientList.removeAll(sc); char c; - if(!sc->getChar(&c) || c != '\r') { + if (!sc->getChar(&c) || c != '\r') { delete sc; // FIXME breaks S5BManager::Item destructor? return; } @@ -1624,34 +1522,32 @@ void S5BManager::Item::checkForActivation() } } - if(ok) { + if (ok) { SocksUDP *sc_udp = nullptr; - if(sc == client) { + if (sc == client) { delete client_out_udp; client_out_udp = nullptr; - sc_udp = client_udp; - } - else if(sc == client_out) { + sc_udp = client_udp; + } else if (sc == client_out) { delete client_udp; client_udp = nullptr; - sc_udp = client_out_udp; + sc_udp = client_out_udp; } sc->disconnect(this); while (!clientList.isEmpty()) { delete clientList.takeFirst(); } - client = sc; + client = sc; client_out = nullptr; client_udp = sc_udp; - activated = true; + activated = true; #ifdef S5B_DEBUG qDebug("activation success\n"); #endif break; } - } - else { + } else { #ifdef S5B_DEBUG qDebug("not fast mode, no need to wait for anything\n"); #endif @@ -1660,19 +1556,18 @@ void S5BManager::Item::checkForActivation() while (!clientList.isEmpty()) { delete clientList.takeFirst(); } - client = sc; + client = sc; client_out = nullptr; - activated = true; + activated = true; break; } } - if(activated) { + if (activated) { finished(); - } - else { + } else { // only emit waitingForActivation if there is nothing left to do - if((connSuccess || localFailed) && !proxy_task && !proxy_conn) + if ((connSuccess || localFailed) && !proxy_task && !proxy_conn) waitingForActivation(); } } @@ -1680,28 +1575,26 @@ void S5BManager::Item::checkForActivation() void S5BManager::Item::checkFailure() { bool failed = false; - if(state == Requester) { - if(remoteFailed) { - if((localFailed && targetMode == Fast) || targetMode == NotFast) + if (state == Requester) { + if (remoteFailed) { + if ((localFailed && targetMode == Fast) || targetMode == NotFast) failed = true; } - } - else { - if(localFailed) { - if((remoteFailed && fast) || !fast) + } else { + if (localFailed) { + if ((remoteFailed && fast) || !fast) failed = true; } } - if(failed) { - if(state == Requester) { + if (failed) { + if (state == Requester) { resetConnection(); - if(statusCode == 404) + if (statusCode == 404) error(ErrConnect); else error(ErrRefused); - } - else { + } else { resetConnection(); error(ErrConnect); } @@ -1721,43 +1614,30 @@ void S5BManager::Item::finished() //---------------------------------------------------------------------------- // S5BConnector //---------------------------------------------------------------------------- -class S5BConnector::Item : public QObject -{ +class S5BConnector::Item : public QObject { Q_OBJECT public: SocksClient *client; - SocksUDP *client_udp; - StreamHost host; - QString key; - bool udp; - int udp_tries; - QTimer t; - Jid jid; - - Item(const Jid &self, const StreamHost &_host, const QString &_key, bool _udp) - : QObject(nullptr) - , client(new SocksClient) - , client_udp(nullptr) - , host(_host) - , key(_key) - , udp(_udp) - , udp_tries(0) - , jid(self) + SocksUDP * client_udp; + StreamHost host; + QString key; + bool udp; + int udp_tries; + QTimer t; + Jid jid; + + Item(const Jid &self, const StreamHost &_host, const QString &_key, bool _udp) : + QObject(nullptr), client(new SocksClient), client_udp(nullptr), host(_host), key(_key), udp(_udp), udp_tries(0), + jid(self) { connect(client, SIGNAL(connected()), SLOT(sc_connected())); connect(client, SIGNAL(error(int)), SLOT(sc_error(int))); connect(&t, SIGNAL(timeout()), SLOT(trySendUDP())); } - ~Item() - { - cleanup(); - } + ~Item() { cleanup(); } - void start() - { - client->connectToHost(host.host(), host.port(), key, 0, udp); - } + void start() { client->connectToHost(host.host(), host.port(), key, 0, udp); } void udpSuccess() { @@ -1773,10 +1653,10 @@ private slots: void sc_connected() { // if udp, need to send init packet before we are good - if(udp) { + if (udp) { // port 1 is init client_udp = client->createUDP(key, 1, client->peerAddress(), client->peerPort()); - udp_tries = 0; + udp_tries = 0; t.start(5000); trySendUDP(); return; @@ -1796,7 +1676,7 @@ private slots: void trySendUDP() { - if(udp_tries == 5) { + if (udp_tries == 5) { t.stop(); cleanup(); result(false); @@ -1828,22 +1708,20 @@ private slots: } }; -class S5BConnector::Private -{ +class S5BConnector::Private { public: - SocksClient *active; - SocksUDP *active_udp; - QList itemList; - QString key; - StreamHost activeHost; - QTimer t; + SocksClient * active; + SocksUDP * active_udp; + QList itemList; + QString key; + StreamHost activeHost; + QTimer t; }; -S5BConnector::S5BConnector(QObject *parent) -:QObject(parent) +S5BConnector::S5BConnector(QObject *parent) : QObject(parent) { - d = new Private; - d->active = nullptr; + d = new Private; + d->active = nullptr; d->active_udp = nullptr; connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout())); } @@ -1873,7 +1751,7 @@ void S5BConnector::start(const Jid &self, const StreamHostList &hosts, const QSt #ifdef S5B_DEBUG qDebug("S5BConnector: starting [%p]!\n", this); #endif - for(StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { + for (StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { Item *i = new Item(self, *it, key, udp); connect(i, SIGNAL(result(bool)), SLOT(item_result(bool))); d->itemList.append(i); @@ -1885,28 +1763,25 @@ void S5BConnector::start(const Jid &self, const StreamHostList &hosts, const QSt SocksClient *S5BConnector::takeClient() { SocksClient *c = d->active; - d->active = nullptr; + d->active = nullptr; return c; } SocksUDP *S5BConnector::takeUDP() { - SocksUDP *c = d->active_udp; + SocksUDP *c = d->active_udp; d->active_udp = nullptr; return c; } -StreamHost S5BConnector::streamHostUsed() const -{ - return d->activeHost; -} +StreamHost S5BConnector::streamHostUsed() const { return d->activeHost; } void S5BConnector::item_result(bool b) { Item *i = static_cast(sender()); - if(b) { - d->active = i->client; - i->client = nullptr; + if (b) { + d->active = i->client; + i->client = nullptr; d->active_udp = i->client_udp; i->client_udp = nullptr; d->activeHost = i->host; @@ -1918,11 +1793,10 @@ void S5BConnector::item_result(bool b) qDebug("S5BConnector: complete! [%p]\n", this); #endif emit result(true); - } - else { + } else { d->itemList.removeAll(i); delete i; - if(d->itemList.isEmpty()) { + if (d->itemList.isEmpty()) { d->t.stop(); #ifdef S5B_DEBUG qDebug("S5BConnector: failed! [%p]\n", this); @@ -1944,8 +1818,8 @@ void S5BConnector::t_timeout() void S5BConnector::man_udpSuccess(const Jid &streamHost) { // was anyone sending to this streamhost? - foreach(Item *i, d->itemList) { - if(i->host.jid().compare(streamHost) && i->client_udp) { + foreach (Item *i, d->itemList) { + if (i->host.jid().compare(streamHost) && i->client_udp) { i->udpSuccess(); return; } @@ -1955,57 +1829,52 @@ void S5BConnector::man_udpSuccess(const Jid &streamHost) //---------------------------------------------------------------------------- // JT_S5B //---------------------------------------------------------------------------- -class JT_S5B::Private -{ +class JT_S5B::Private { public: QDomElement iq; - Jid to; - Jid streamHost; - StreamHost proxyInfo; - int mode; - QTimer t; + Jid to; + Jid streamHost; + StreamHost proxyInfo; + int mode; + QTimer t; }; -JT_S5B::JT_S5B(Task *parent) -:Task(parent) +JT_S5B::JT_S5B(Task *parent) : Task(parent) { - d = new Private; + d = new Private; d->mode = -1; connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout())); } -JT_S5B::~JT_S5B() -{ - delete d; -} +JT_S5B::~JT_S5B() { delete d; } -void JT_S5B::request(const Jid &to, const QString &sid, const QString &dstaddr, - const StreamHostList &hosts, bool fast, bool udp) +void JT_S5B::request(const Jid &to, const QString &sid, const QString &dstaddr, const StreamHostList &hosts, bool fast, + bool udp) { d->mode = 0; QDomElement iq; - d->to = to; - iq = createIQ(doc(), "set", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS(S5B_NS, "query"); query.setAttribute("sid", sid); if (!client()->groupChatNick(to.domain(), to.node()).isEmpty()) { query.setAttribute("dstaddr", dstaddr); // special case for muc as in xep-0065rc3 } - query.setAttribute("mode", udp ? "udp" : "tcp" ); + query.setAttribute("mode", udp ? "udp" : "tcp"); iq.appendChild(query); - for(StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { + for (StreamHostList::ConstIterator it = hosts.begin(); it != hosts.end(); ++it) { QDomElement shost = doc()->createElement("streamhost"); shost.setAttribute("jid", (*it).jid().full()); shost.setAttribute("host", (*it).host()); shost.setAttribute("port", QString::number((*it).port())); - if((*it).isProxy()) { + if ((*it).isProxy()) { QDomElement p = doc()->createElementNS("http://affinix.com/jabber/stream", "proxy"); shost.appendChild(p); } query.appendChild(shost); } - if(fast) { + if (fast) { QDomElement e = doc()->createElementNS("http://affinix.com/jabber/stream", "fast"); query.appendChild(e); } @@ -2017,8 +1886,8 @@ void JT_S5B::requestProxyInfo(const Jid &to) d->mode = 1; QDomElement iq; - d->to = to; - iq = createIQ(doc(), "get", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "get", to.full(), id()); QDomElement query = doc()->createElementNS(S5B_NS, "query"); iq.appendChild(query); d->iq = iq; @@ -2029,8 +1898,8 @@ void JT_S5B::requestActivation(const Jid &to, const QString &sid, const Jid &tar d->mode = 2; QDomElement iq; - d->to = to; - iq = createIQ(doc(), "set", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS(S5B_NS, "query"); query.setAttribute("sid", sid); iq.appendChild(query); @@ -2042,49 +1911,45 @@ void JT_S5B::requestActivation(const Jid &to, const QString &sid, const Jid &tar void JT_S5B::onGo() { - if(d->mode == 1) { + if (d->mode == 1) { d->t.setSingleShot(true); d->t.start(15000); } send(d->iq); } -void JT_S5B::onDisconnect() -{ - d->t.stop(); -} +void JT_S5B::onDisconnect() { d->t.stop(); } bool JT_S5B::take(const QDomElement &x) { - if(d->mode == -1) + if (d->mode == -1) return false; - if(!iqVerify(x, d->to, id())) + if (!iqVerify(x, d->to, id())) return false; d->t.stop(); - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { QDomElement q = queryTag(x); - if(d->mode == 0) { + if (d->mode == 0) { d->streamHost = ""; - if(!q.isNull()) { + if (!q.isNull()) { QDomElement shost = q.elementsByTagName("streamhost-used").item(0).toElement(); - if(!shost.isNull()) + if (!shost.isNull()) d->streamHost = shost.attribute("jid"); } setSuccess(); - } - else if(d->mode == 1) { - if(!q.isNull()) { + } else if (d->mode == 1) { + if (!q.isNull()) { QDomElement shost = q.elementsByTagName("streamhost").item(0).toElement(); - if(!shost.isNull()) { + if (!shost.isNull()) { Jid j = shost.attribute("jid"); - if(j.isValid()) { + if (j.isValid()) { QString host = shost.attribute("host"); - if(!host.isEmpty()) { - int port = shost.attribute("port").toInt(); + if (!host.isEmpty()) { + int port = shost.attribute("port").toInt(); StreamHost h; h.setJid(j); h.setHost(host); @@ -2097,12 +1962,10 @@ bool JT_S5B::take(const QDomElement &x) } setSuccess(); - } - else { + } else { setSuccess(); } - } - else { + } else { setError(x); } @@ -2115,44 +1978,30 @@ void JT_S5B::t_timeout() setError(500, "Timed out"); } -Jid JT_S5B::streamHostUsed() const -{ - return d->streamHost; -} +Jid JT_S5B::streamHostUsed() const { return d->streamHost; } -StreamHost JT_S5B::proxyInfo() const -{ - return d->proxyInfo; -} +StreamHost JT_S5B::proxyInfo() const { return d->proxyInfo; } //---------------------------------------------------------------------------- // JT_PushS5B //---------------------------------------------------------------------------- -JT_PushS5B::JT_PushS5B(Task *parent) -:Task(parent) -{ -} +JT_PushS5B::JT_PushS5B(Task *parent) : Task(parent) {} -JT_PushS5B::~JT_PushS5B() -{ -} +JT_PushS5B::~JT_PushS5B() {} -int JT_PushS5B::priority() const -{ - return 1; -} +int JT_PushS5B::priority() const { return 1; } bool JT_PushS5B::take(const QDomElement &e) { // look for udpsuccess - if(e.tagName() == "message") { + if (e.tagName() == "message") { QDomElement x = e.elementsByTagName("udpsuccess").item(0).toElement(); - if(!x.isNull() && x.namespaceURI() == S5B_NS) { + if (!x.isNull() && x.namespaceURI() == S5B_NS) { incomingUDPSuccess(Jid(x.attribute("from")), x.attribute("dstaddr")); return true; } x = e.elementsByTagName("activate").item(0).toElement(); - if(!x.isNull() && x.namespaceURI() == "http://affinix.com/jabber/stream") { + if (!x.isNull() && x.namespaceURI() == "http://affinix.com/jabber/stream") { incomingActivate(Jid(x.attribute("from")), x.attribute("sid"), Jid(x.attribute("jid"))); return true; } @@ -2160,32 +2009,32 @@ bool JT_PushS5B::take(const QDomElement &e) } // must be an iq-set tag - if(e.tagName() != "iq") + if (e.tagName() != "iq") return false; - if(e.attribute("type") != "set") + if (e.attribute("type") != "set") return false; - if(queryNS(e) != S5B_NS) + if (queryNS(e) != S5B_NS) return false; - Jid from(e.attribute("from")); - QDomElement q = queryTag(e); - QString sid = q.attribute("sid"); + Jid from(e.attribute("from")); + QDomElement q = queryTag(e); + QString sid = q.attribute("sid"); StreamHostList hosts; - QDomNodeList nl = q.elementsByTagName("streamhost"); - for(int n = 0; n < nl.count(); ++n) { + QDomNodeList nl = q.elementsByTagName("streamhost"); + for (int n = 0; n < nl.count(); ++n) { QDomElement shost = nl.item(n).toElement(); - if(hosts.count() < MAXSTREAMHOSTS) { + if (hosts.count() < MAXSTREAMHOSTS) { Jid j = shost.attribute("jid"); - if(!j.isValid()) + if (!j.isValid()) continue; QString host = shost.attribute("host"); - if(host.isEmpty()) + if (host.isEmpty()) continue; - int port = shost.attribute("port").toInt(); - QDomElement p = shost.elementsByTagName("proxy").item(0).toElement(); - bool isProxy = false; - if(!p.isNull() && p.namespaceURI() == "http://affinix.com/jabber/stream") + int port = shost.attribute("port").toInt(); + QDomElement p = shost.elementsByTagName("proxy").item(0).toElement(); + bool isProxy = false; + if (!p.isNull() && p.namespaceURI() == "http://affinix.com/jabber/stream") isProxy = true; StreamHost h; @@ -2197,20 +2046,20 @@ bool JT_PushS5B::take(const QDomElement &e) } } - bool fast = false; + bool fast = false; QDomElement t; t = q.elementsByTagName("fast").item(0).toElement(); - if(!t.isNull() && t.namespaceURI() == "http://affinix.com/jabber/stream") + if (!t.isNull() && t.namespaceURI() == "http://affinix.com/jabber/stream") fast = true; S5BRequest r; - r.from = from; - r.id = e.attribute("id"); - r.sid = sid; + r.from = from; + r.id = e.attribute("id"); + r.sid = sid; r.dstaddr = q.attribute("dstaddr"); // special case for muc as in xep-0065rc3 - r.hosts = hosts; - r.fast = fast; - r.udp = q.attribute("mode") == "udp" ? true: false; + r.hosts = hosts; + r.fast = fast; + r.udp = q.attribute("mode") == "udp" ? true : false; emit incoming(r); return true; @@ -2218,7 +2067,7 @@ bool JT_PushS5B::take(const QDomElement &e) void JT_PushS5B::respondSuccess(const Jid &to, const QString &id, const Jid &streamHost) { - QDomElement iq = createIQ(doc(), "result", to.full(), id); + QDomElement iq = createIQ(doc(), "result", to.full(), id); QDomElement query = doc()->createElementNS(S5B_NS, "query"); iq.appendChild(query); QDomElement shost = doc()->createElement("streamhost-used"); @@ -2227,10 +2076,9 @@ void JT_PushS5B::respondSuccess(const Jid &to, const QString &id, const Jid &str send(iq); } -void JT_PushS5B::respondError(const Jid &to, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str) +void JT_PushS5B::respondError(const Jid &to, const QString &id, Stanza::Error::ErrorCond cond, const QString &str) { - QDomElement iq = createIQ(doc(), "error", to.full(), id); + QDomElement iq = createIQ(doc(), "error", to.full(), id); Stanza::Error error(Stanza::Error::Cancel, cond, str); iq.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); send(iq); @@ -2263,102 +2111,66 @@ void JT_PushS5B::sendActivate(const Jid &to, const QString &sid, const Jid &stre StreamHost::StreamHost() { v_port = -1; - proxy = false; + proxy = false; } -const Jid & StreamHost::jid() const -{ - return j; -} +const Jid &StreamHost::jid() const { return j; } -const QString & StreamHost::host() const -{ - return v_host; -} +const QString &StreamHost::host() const { return v_host; } -int StreamHost::port() const -{ - return v_port; -} +int StreamHost::port() const { return v_port; } -bool StreamHost::isProxy() const -{ - return proxy; -} +bool StreamHost::isProxy() const { return proxy; } -void StreamHost::setJid(const Jid &_j) -{ - j = _j; -} +void StreamHost::setJid(const Jid &_j) { j = _j; } -void StreamHost::setHost(const QString &host) -{ - v_host = host; -} +void StreamHost::setHost(const QString &host) { v_host = host; } -void StreamHost::setPort(int port) -{ - v_port = port; -} +void StreamHost::setPort(int port) { v_port = port; } -void StreamHost::setIsProxy(bool b) -{ - proxy = b; -} +void StreamHost::setIsProxy(bool b) { proxy = b; } //---------------------------------------------------------------------------- // S5BServersProducer //---------------------------------------------------------------------------- -TcpPortServer *S5BServersProducer::makeServer(QTcpServer *socket) -{ - return new S5BServer(socket); -} +TcpPortServer *S5BServersProducer::makeServer(QTcpServer *socket) { return new S5BServer(socket); } //---------------------------------------------------------------------------- // S5BIncomingConnection //---------------------------------------------------------------------------- -class S5BIncomingConnection : public QObject -{ +class S5BIncomingConnection : public QObject { Q_OBJECT public: SocksClient *client; - QString host; - QTimer expire; + QString host; + QTimer expire; S5BIncomingConnection(SocksClient *c) : QObject(nullptr) { client = c; - connect(client, &SocksClient::incomingMethods, [this](int methods){ - if(methods & SocksClient::AuthNone) + connect(client, &SocksClient::incomingMethods, [this](int methods) { + if (methods & SocksClient::AuthNone) client->chooseMethod(SocksClient::AuthNone); else doError(); }); - connect(client, &SocksClient::incomingConnectRequest, [this](const QString &_host, int port) - { - if(port == 0) { + connect(client, &SocksClient::incomingConnectRequest, [this](const QString &_host, int port) { + if (port == 0) { host = _host; client->disconnect(this); expire.stop(); emit result(true); - } - else + } else doError(); }); - connect(client, &SocksClient::error, [this](){ doError(); }); + connect(client, &SocksClient::error, [this]() { doError(); }); connect(&expire, SIGNAL(timeout()), SLOT(doError())); resetExpiration(); } - ~S5BIncomingConnection() - { - delete client; - } + ~S5BIncomingConnection() { delete client; } - void resetExpiration() - { - expire.start(30000); - } + void resetExpiration() { expire.start(30000); } signals: void result(bool); @@ -2376,34 +2188,32 @@ private slots: //---------------------------------------------------------------------------- // S5BServer //---------------------------------------------------------------------------- -struct S5BServer::Private -{ - SocksServer serv; +struct S5BServer::Private { + SocksServer serv; QSet keys; }; -S5BServer::S5BServer(QTcpServer *serverSocket) : - TcpPortServer(serverSocket), - d(new Private) +S5BServer::S5BServer(QTcpServer *serverSocket) : TcpPortServer(serverSocket), d(new Private) { d->serv.setServerSocket(serverSocket); connect(&d->serv, &SocksServer::incomingReady, this, [this]() { S5BIncomingConnection *inConn = new S5BIncomingConnection(d->serv.takeIncoming()); #ifdef S5B_DEBUG - qDebug("S5BServer: incoming connection from %s:%d\n", qPrintable(i->client->peerAddress().toString()), i->client->peerPort()); + qDebug("S5BServer: incoming connection from %s:%d\n", qPrintable(i->client->peerAddress().toString()), + i->client->peerPort()); #endif - connect(inConn, &S5BIncomingConnection::result, this, [this, inConn](bool success){ + connect(inConn, &S5BIncomingConnection::result, this, [this, inConn](bool success) { #ifdef S5B_DEBUG qDebug("S5BServer item result: %d\n", success); #endif - if(!success) { + if (!success) { delete inConn; return; } SocksClient *c = inConn->client; inConn->client = nullptr; - QString key = inConn->host; + QString key = inConn->host; delete inConn; emit incomingConnection(c, key); @@ -2412,12 +2222,13 @@ S5BServer::S5BServer(QTcpServer *serverSocket) : } }); }); - connect(&d->serv, &SocksServer::incomingUDP, this, [this](const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data){ - if(port != 0 && port != 1) - return; - bool isInit = port == 1; - emit incomingUdp(isInit, addr, sourcePort, host, data); - }); + connect(&d->serv, &SocksServer::incomingUDP, this, + [this](const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data) { + if (port != 0 && port != 1) + return; + bool isInit = port == 1; + emit incomingUdp(isInit, addr, sourcePort, host, data); + }); } S5BServer::~S5BServer() @@ -2430,25 +2241,13 @@ void S5BServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &d d->serv.writeUDP(addr, port, data); } -bool S5BServer::isActive() const -{ - return d->serv.isActive(); -} +bool S5BServer::isActive() const { return d->serv.isActive(); } -bool S5BServer::hasKey(const QString &key) -{ - return d->keys.contains(key); -} +bool S5BServer::hasKey(const QString &key) { return d->keys.contains(key); } -void S5BServer::registerKey(const QString &key) -{ - d->keys.insert(key); -} +void S5BServer::registerKey(const QString &key) { d->keys.insert(key); } -void S5BServer::unregisterKey(const QString &key) -{ - d->keys.remove(key); -} +void S5BServer::unregisterKey(const QString &key) { d->keys.remove(key); } } // namespace XMPP #include "s5b.moc" diff --git a/src/xmpp/xmpp-im/s5b.h b/src/xmpp/xmpp-im/s5b.h index 86cd2d4a..7cbdbe24 100644 --- a/src/xmpp/xmpp-im/s5b.h +++ b/src/xmpp/xmpp-im/s5b.h @@ -35,316 +35,301 @@ class SocksClient; class SocksUDP; namespace XMPP { - namespace Jingle { - namespace S5B { - class Manager; - } - } - - class Client; - class JT_PushS5B; - class S5BConnection; - class S5BManager; - class StreamHost; - class TcpPortReserver; - struct S5BRequest; - typedef QList StreamHostList; - typedef QList S5BConnectionList; - - class S5BDatagram - { - public: - S5BDatagram(); - S5BDatagram(int source, int dest, const QByteArray &data); - - int sourcePort() const; - int destPort() const; - QByteArray data() const; - - private: - int _source = 0; - int _dest = 0; - QByteArray _buf; - }; - - class S5BConnection : public BSConnection - { - Q_OBJECT - public: - enum Mode { Stream, Datagram }; - - ~S5BConnection(); - - Jid proxy() const; - void setProxy(const Jid &proxy); - - void connectToJid(const Jid &peer, const QString &sid, Mode m = Stream); - void connectToJid(const Jid &peer, const QString &sid) { - connectToJid(peer, sid, Stream); - } - - void accept(); - void close(); - - Jid peer() const; - QString sid() const; - BytestreamManager* manager() const; - bool isRemote() const; - Mode mode() const; - int state() const; - - qint64 bytesAvailable() const; - qint64 bytesToWrite() const; - - void writeDatagram(const S5BDatagram &); - S5BDatagram readDatagram(); - int datagramsAvailable() const; - - protected: - qint64 writeData(const char *data, qint64 maxSize); - qint64 readData(char * data, qint64 maxSize); - - signals: - void proxyQuery(); // querying proxy for streamhost information - void proxyResult(bool b); // query success / fail - void requesting(); // sent actual S5B request (requester only) - void accepted(); // target accepted (requester only - void tryingHosts(const StreamHostList &hosts); // currently connecting to these hosts - void proxyConnect(); // connecting to proxy - void waitingForActivation(); // waiting for activation (target only) - void connected(); // connection active - void datagramReady(); - - private slots: - void doPending(); - - void sc_connectionClosed(); - void sc_delayedCloseFinished(); - void sc_readyRead(); - void sc_bytesWritten(qint64); - void sc_error(int); - - void su_packetReady(const QByteArray &buf); - - private: - class Private; - Private *d; - - void resetConnection(bool clear=false); - void handleUDP(const QByteArray &buf); - void sendUDP(const QByteArray &buf); - - friend class S5BManager; - void man_waitForAccept(const S5BRequest &r); - void man_clientReady(SocksClient *, SocksUDP *); - void man_udpReady(const QByteArray &buf); - void man_failed(int); - S5BConnection(S5BManager *, QObject *parent=nullptr); - }; - - class S5BManager : public BytestreamManager - { - Q_OBJECT - public: - S5BManager(Client *); - ~S5BManager(); - - static const char* ns(); - Client *client() const; - JT_PushS5B *jtPush() const; - - bool isAcceptableSID(const Jid &peer, const QString &sid) const; - - BSConnection *createConnection(); - S5BConnection *takeIncoming(); - - class Item; - class Entry; - - protected: - const char* sidPrefix() const; - - private slots: - void ps_incoming(const S5BRequest &req); - void ps_incomingUDPSuccess(const Jid &from, const QString &dstaddr); - void ps_incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost); - void item_accepted(); - void item_tryingHosts(const StreamHostList &list); - void item_proxyConnect(); - void item_waitingForActivation(); - void item_connected(); - void item_error(int); - void query_finished(); - - private: - class Private; - Private *d; - - S5BConnection *findIncoming(const Jid &from, const QString &sid) const; - Entry *findEntry(S5BConnection *) const; - Entry *findEntry(Item *) const; - Entry *findEntryByHash(const QString &key) const; - Entry *findEntryBySID(const Jid &peer, const QString &sid) const; - - void entryContinue(Entry *e); - void queryProxy(Entry *e); - bool targetShouldOfferProxy(Entry *e); - - friend class S5BConnection; - void con_connect(S5BConnection *); - void con_accept(S5BConnection *); - void con_reject(S5BConnection *); - void con_unlink(S5BConnection *); - void con_sendUDP(S5BConnection *, const QByteArray &buf); - - friend class S5BServer; - bool srv_ownsHash(const QString &key) const; - void srv_incomingReady(SocksClient *sc, const QString &key); - void srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); - - friend class Item; - void doSuccess(const Jid &peer, const QString &id, const Jid &streamHost); - void doError(const Jid &peer, const QString &id, Stanza::Error::ErrorCond, const QString &); - void doActivate(const Jid &peer, const QString &sid, const Jid &streamHost); - }; - - class S5BConnector : public QObject - { - Q_OBJECT - public: - S5BConnector(QObject *parent=nullptr); - ~S5BConnector(); - - void resetConnection(); - void start(const Jid &self, const StreamHostList &hosts, const QString &key, bool udp, int timeout); - SocksClient *takeClient(); - SocksUDP *takeUDP(); - StreamHost streamHostUsed() const; - - class Item; - - signals: - void result(bool); - - private slots: - void item_result(bool); - void t_timeout(); - - private: - class Private; - Private *d; - - friend class S5BManager; - void man_udpSuccess(const Jid &streamHost); - }; - - class S5BServersProducer : public TcpPortScope - { - protected: - TcpPortServer* makeServer(QTcpServer *socket); // in fact returns S5BServer - }; - - class S5BServer : public TcpPortServer - { - Q_OBJECT - - public: - S5BServer(QTcpServer *serverSocket); - ~S5BServer(); - - void writeUDP(const QHostAddress &addr, int port, const QByteArray &data); - bool isActive() const; - bool hasKey(const QString &key); - void registerKey(const QString &key); - void unregisterKey(const QString &key); - - signals: - void incomingConnection(SocksClient *c, const QString &key); - void incomingUdp(bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data); - - private: - class Private; - QScopedPointer d; - }; - - class JT_S5B : public Task - { - Q_OBJECT - public: - JT_S5B(Task *); - ~JT_S5B(); - - void request(const Jid &to, const QString &sid, const QString &dstaddr, - const StreamHostList &hosts, bool fast, bool udp=false); - void requestProxyInfo(const Jid &to); - void requestActivation(const Jid &to, const QString &sid, const Jid &target); - - void onGo(); - void onDisconnect(); - bool take(const QDomElement &); - - Jid streamHostUsed() const; - StreamHost proxyInfo() const; - - private slots: - void t_timeout(); - - private: - class Private; - Private *d; - }; - - struct S5BRequest - { - Jid from; - QString id, sid, dstaddr; - StreamHostList hosts; - bool fast; - bool udp; - }; - class JT_PushS5B : public Task - { - Q_OBJECT - public: - JT_PushS5B(Task *); - ~JT_PushS5B(); - - int priority() const; - - void respondSuccess(const Jid &to, const QString &id, const Jid &streamHost); - void respondError(const Jid &to, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str); - void sendUDPSuccess(const Jid &to, const QString &dstaddr); - void sendActivate(const Jid &to, const QString &sid, const Jid &streamHost); - - bool take(const QDomElement &); - - signals: - void incoming(const S5BRequest &req); - void incomingUDPSuccess(const Jid &from, const QString &dstaddr); - void incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost); - }; - - class StreamHost - { - public: - StreamHost(); - - const Jid & jid() const; - const QString & host() const; - int port() const; - bool isProxy() const; - void setJid(const Jid &); - void setHost(const QString &); - void setPort(int); - void setIsProxy(bool); - - private: - Jid j; - QString v_host; - int v_port; - bool proxy; - }; +namespace Jingle { namespace S5B { + class Manager; +}} + +class Client; +class JT_PushS5B; +class S5BConnection; +class S5BManager; +class StreamHost; +class TcpPortReserver; +struct S5BRequest; +typedef QList StreamHostList; +typedef QList S5BConnectionList; + +class S5BDatagram { +public: + S5BDatagram(); + S5BDatagram(int source, int dest, const QByteArray &data); + + int sourcePort() const; + int destPort() const; + QByteArray data() const; + +private: + int _source = 0; + int _dest = 0; + QByteArray _buf; +}; + +class S5BConnection : public BSConnection { + Q_OBJECT +public: + enum Mode { Stream, Datagram }; + + ~S5BConnection(); + + Jid proxy() const; + void setProxy(const Jid &proxy); + + void connectToJid(const Jid &peer, const QString &sid, Mode m = Stream); + void connectToJid(const Jid &peer, const QString &sid) { connectToJid(peer, sid, Stream); } + + void accept(); + void close(); + + Jid peer() const; + QString sid() const; + BytestreamManager *manager() const; + bool isRemote() const; + Mode mode() const; + int state() const; + + qint64 bytesAvailable() const; + qint64 bytesToWrite() const; + + void writeDatagram(const S5BDatagram &); + S5BDatagram readDatagram(); + int datagramsAvailable() const; + +protected: + qint64 writeData(const char *data, qint64 maxSize); + qint64 readData(char *data, qint64 maxSize); + +signals: + void proxyQuery(); // querying proxy for streamhost information + void proxyResult(bool b); // query success / fail + void requesting(); // sent actual S5B request (requester only) + void accepted(); // target accepted (requester only + void tryingHosts(const StreamHostList &hosts); // currently connecting to these hosts + void proxyConnect(); // connecting to proxy + void waitingForActivation(); // waiting for activation (target only) + void connected(); // connection active + void datagramReady(); + +private slots: + void doPending(); + + void sc_connectionClosed(); + void sc_delayedCloseFinished(); + void sc_readyRead(); + void sc_bytesWritten(qint64); + void sc_error(int); + + void su_packetReady(const QByteArray &buf); + +private: + class Private; + Private *d; + + void resetConnection(bool clear = false); + void handleUDP(const QByteArray &buf); + void sendUDP(const QByteArray &buf); + + friend class S5BManager; + void man_waitForAccept(const S5BRequest &r); + void man_clientReady(SocksClient *, SocksUDP *); + void man_udpReady(const QByteArray &buf); + void man_failed(int); + S5BConnection(S5BManager *, QObject *parent = nullptr); +}; + +class S5BManager : public BytestreamManager { + Q_OBJECT +public: + S5BManager(Client *); + ~S5BManager(); + + static const char *ns(); + Client * client() const; + JT_PushS5B * jtPush() const; + + bool isAcceptableSID(const Jid &peer, const QString &sid) const; + + BSConnection * createConnection(); + S5BConnection *takeIncoming(); + + class Item; + class Entry; + +protected: + const char *sidPrefix() const; + +private slots: + void ps_incoming(const S5BRequest &req); + void ps_incomingUDPSuccess(const Jid &from, const QString &dstaddr); + void ps_incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost); + void item_accepted(); + void item_tryingHosts(const StreamHostList &list); + void item_proxyConnect(); + void item_waitingForActivation(); + void item_connected(); + void item_error(int); + void query_finished(); + +private: + class Private; + Private *d; + + S5BConnection *findIncoming(const Jid &from, const QString &sid) const; + Entry * findEntry(S5BConnection *) const; + Entry * findEntry(Item *) const; + Entry * findEntryByHash(const QString &key) const; + Entry * findEntryBySID(const Jid &peer, const QString &sid) const; + + void entryContinue(Entry *e); + void queryProxy(Entry *e); + bool targetShouldOfferProxy(Entry *e); + + friend class S5BConnection; + void con_connect(S5BConnection *); + void con_accept(S5BConnection *); + void con_reject(S5BConnection *); + void con_unlink(S5BConnection *); + void con_sendUDP(S5BConnection *, const QByteArray &buf); + + friend class S5BServer; + bool srv_ownsHash(const QString &key) const; + void srv_incomingReady(SocksClient *sc, const QString &key); + void srv_incomingUDP(bool init, const QHostAddress &addr, int port, const QString &key, const QByteArray &data); + + friend class Item; + void doSuccess(const Jid &peer, const QString &id, const Jid &streamHost); + void doError(const Jid &peer, const QString &id, Stanza::Error::ErrorCond, const QString &); + void doActivate(const Jid &peer, const QString &sid, const Jid &streamHost); +}; + +class S5BConnector : public QObject { + Q_OBJECT +public: + S5BConnector(QObject *parent = nullptr); + ~S5BConnector(); + + void resetConnection(); + void start(const Jid &self, const StreamHostList &hosts, const QString &key, bool udp, int timeout); + SocksClient *takeClient(); + SocksUDP * takeUDP(); + StreamHost streamHostUsed() const; + + class Item; + +signals: + void result(bool); + +private slots: + void item_result(bool); + void t_timeout(); + +private: + class Private; + Private *d; + + friend class S5BManager; + void man_udpSuccess(const Jid &streamHost); +}; + +class S5BServersProducer : public TcpPortScope { +protected: + TcpPortServer *makeServer(QTcpServer *socket); // in fact returns S5BServer +}; + +class S5BServer : public TcpPortServer { + Q_OBJECT + +public: + S5BServer(QTcpServer *serverSocket); + ~S5BServer(); + + void writeUDP(const QHostAddress &addr, int port, const QByteArray &data); + bool isActive() const; + bool hasKey(const QString &key); + void registerKey(const QString &key); + void unregisterKey(const QString &key); + +signals: + void incomingConnection(SocksClient *c, const QString &key); + void incomingUdp(bool isInit, const QHostAddress &addr, int sourcePort, const QString &key, const QByteArray &data); + +private: + class Private; + QScopedPointer d; +}; + +class JT_S5B : public Task { + Q_OBJECT +public: + JT_S5B(Task *); + ~JT_S5B(); + + void request(const Jid &to, const QString &sid, const QString &dstaddr, const StreamHostList &hosts, bool fast, + bool udp = false); + void requestProxyInfo(const Jid &to); + void requestActivation(const Jid &to, const QString &sid, const Jid &target); + + void onGo(); + void onDisconnect(); + bool take(const QDomElement &); + + Jid streamHostUsed() const; + StreamHost proxyInfo() const; + +private slots: + void t_timeout(); + +private: + class Private; + Private *d; +}; + +struct S5BRequest { + Jid from; + QString id, sid, dstaddr; + StreamHostList hosts; + bool fast; + bool udp; +}; +class JT_PushS5B : public Task { + Q_OBJECT +public: + JT_PushS5B(Task *); + ~JT_PushS5B(); + + int priority() const; + + void respondSuccess(const Jid &to, const QString &id, const Jid &streamHost); + void respondError(const Jid &to, const QString &id, Stanza::Error::ErrorCond cond, const QString &str); + void sendUDPSuccess(const Jid &to, const QString &dstaddr); + void sendActivate(const Jid &to, const QString &sid, const Jid &streamHost); + + bool take(const QDomElement &); + +signals: + void incoming(const S5BRequest &req); + void incomingUDPSuccess(const Jid &from, const QString &dstaddr); + void incomingActivate(const Jid &from, const QString &sid, const Jid &streamHost); +}; + +class StreamHost { +public: + StreamHost(); + + const Jid & jid() const; + const QString &host() const; + int port() const; + bool isProxy() const; + void setJid(const Jid &); + void setHost(const QString &); + void setPort(int); + void setIsProxy(bool); + +private: + Jid j; + QString v_host; + int v_port; + bool proxy; +}; } // namespace XMPP #endif // XMPP_S5B_H diff --git a/src/xmpp/xmpp-im/types.cpp b/src/xmpp/xmpp-im/types.cpp index 6082b215..8ffd1bce 100644 --- a/src/xmpp/xmpp-im/types.cpp +++ b/src/xmpp/xmpp-im/types.cpp @@ -75,44 +75,29 @@ Url &Url::operator=(const Url &from) } //! \brief destroy Url object. -Url::~Url() -{ - delete d; -} +Url::~Url() { delete d; } //! \brief Get url information. //! //! Returns url information. -QString Url::url() const -{ - return d->url; -} +QString Url::url() const { return d->url; } //! \brief Get Description information. //! //! Returns desction of the URL. -QString Url::desc() const -{ - return d->desc; -} +QString Url::desc() const { return d->desc; } //! \brief Set Url information. //! //! Set url information. //! \param url - url string (eg: http://psi.affinix.com/) -void Url::setUrl(const QString &url) -{ - d->url = url; -} +void Url::setUrl(const QString &url) { d->url = url; } //! \brief Set Description information. //! //! Set description of the url. //! \param desc - description of url -void Url::setDesc(const QString &desc) -{ - d->desc = desc; -} +void Url::setDesc(const QString &desc) { d->desc = desc; } //---------------------------------------------------------------------------- // Address @@ -124,16 +109,9 @@ void Url::setDesc(const QString &desc) //! \param Type - type (default: Unknown) //! \param Jid - specify address (default: empty string) //! \sa setType() setJid() -Address::Address(Type type, const Jid &jid) : - v_jid(jid), v_delivered(false), v_type(type) -{ -} +Address::Address(Type type, const Jid &jid) : v_jid(jid), v_delivered(false), v_type(type) {} -Address::Address(const QDomElement &e) : - v_delivered(false) -{ - fromXml(e); -} +Address::Address(const QDomElement &e) : v_delivered(false) { fromXml(e); } void Address::fromXml(const QDomElement &t) { @@ -209,104 +187,68 @@ QDomElement Address::toXml(Stanza &s) const //! \brief Get Jid information. //! //! Returns jid information. -const Jid &Address::jid() const -{ - return v_jid; -} +const Jid &Address::jid() const { return v_jid; } //! \brief Get Uri information. //! //! Returns desction of the Address. -const QString &Address::uri() const -{ - return v_uri; -} +const QString &Address::uri() const { return v_uri; } //! \brief Get Node information. //! //! Returns node of the Address. -const QString &Address::node() const -{ - return v_node; -} +const QString &Address::node() const { return v_node; } //! \brief Get Description information. //! //! Returns desction of the Address. -const QString &Address::desc() const -{ - return v_desc; -} +const QString &Address::desc() const { return v_desc; } //! \brief Get Delivered information. //! //! Returns delivered of the Address. -bool Address::delivered() const -{ - return v_delivered; -} +bool Address::delivered() const { return v_delivered; } //! \brief Get Type information. //! //! Returns type of the Address. -Address::Type Address::type() const -{ - return v_type; -} +Address::Type Address::type() const { return v_type; } //! \brief Set Address information. //! //! Set jid information. //! \param jid - jid -void Address::setJid(const Jid &jid) -{ - v_jid = jid; -} +void Address::setJid(const Jid &jid) { v_jid = jid; } //! \brief Set Address information. //! //! Set uri information. //! \param uri - url string (eg: http://psi.affinix.com/) -void Address::setUri(const QString &uri) -{ - v_uri = uri; -} +void Address::setUri(const QString &uri) { v_uri = uri; } //! \brief Set Node information. //! //! Set node information. //! \param node - node string -void Address::setNode(const QString &node) -{ - v_node = node; -} +void Address::setNode(const QString &node) { v_node = node; } //! \brief Set Description information. //! //! Set description of the url. //! \param desc - description of url -void Address::setDesc(const QString &desc) -{ - v_desc = desc; -} +void Address::setDesc(const QString &desc) { v_desc = desc; } //! \brief Set delivered information. //! //! Set delivered information. //! \param delivered - delivered flag -void Address::setDelivered(bool delivered) -{ - v_delivered = delivered; -} +void Address::setDelivered(bool delivered) { v_delivered = delivered; } //! \brief Set Type information. //! //! Set type information. //! \param type - type -void Address::setType(Type type) -{ - v_type = type; -} +void Address::setType(Type type) { v_type = type; } //---------------------------------------------------------------------------- // Hash @@ -315,15 +257,13 @@ void Address::setType(Type type) static const struct { const char *text; Hash::Type hashType; -} hashTypes[] = { - { "sha-1", Hash::Type::Sha1 }, - { "sha-256", Hash::Type::Sha256 }, - { "sha-512", Hash::Type::Sha512 }, - { "sha3-256", Hash::Type::Sha3_256 }, - { "sha3-512", Hash::Type::Sha3_512 }, - { "blake2b-256", Hash::Type::Blake2b256 }, - { "blake2b-512", Hash::Type::Blake2b512 } -}; +} hashTypes[] = { { "sha-1", Hash::Type::Sha1 }, + { "sha-256", Hash::Type::Sha256 }, + { "sha-512", Hash::Type::Sha512 }, + { "sha3-256", Hash::Type::Sha3_256 }, + { "sha3-512", Hash::Type::Sha3_512 }, + { "blake2b-256", Hash::Type::Blake2b256 }, + { "blake2b-512", Hash::Type::Blake2b512 } }; Hash::Hash(const QDomElement &el) { @@ -502,56 +442,25 @@ RosterExchangeItem::RosterExchangeItem(const Jid &jid, const QString &name, cons { } -RosterExchangeItem::RosterExchangeItem(const QDomElement &el) : - action_(Add) -{ - fromXml(el); -} +RosterExchangeItem::RosterExchangeItem(const QDomElement &el) : action_(Add) { fromXml(el); } -const Jid &RosterExchangeItem::jid() const -{ - return jid_; -} +const Jid &RosterExchangeItem::jid() const { return jid_; } -RosterExchangeItem::Action RosterExchangeItem::action() const -{ - return action_; -} +RosterExchangeItem::Action RosterExchangeItem::action() const { return action_; } -const QString &RosterExchangeItem::name() const -{ - return name_; -} +const QString &RosterExchangeItem::name() const { return name_; } -const QStringList &RosterExchangeItem::groups() const -{ - return groups_; -} +const QStringList &RosterExchangeItem::groups() const { return groups_; } -bool RosterExchangeItem::isNull() const -{ - return jid_.isEmpty(); -} +bool RosterExchangeItem::isNull() const { return jid_.isEmpty(); } -void RosterExchangeItem::setJid(const Jid &jid) -{ - jid_ = jid; -} +void RosterExchangeItem::setJid(const Jid &jid) { jid_ = jid; } -void RosterExchangeItem::setAction(Action action) -{ - action_ = action; -} +void RosterExchangeItem::setAction(Action action) { action_ = action; } -void RosterExchangeItem::setName(const QString &name) -{ - name_ = name; -} +void RosterExchangeItem::setName(const QString &name) { name_ = name; } -void RosterExchangeItem::setGroups(const QStringList &groups) -{ - groups_ = groups; -} +void RosterExchangeItem::setGroups(const QStringList &groups) { groups_ = groups; } QDomElement RosterExchangeItem::toXml(Stanza &s) const { @@ -599,76 +508,33 @@ void RosterExchangeItem::fromXml(const QDomElement &e) //---------------------------------------------------------------------------- // MUCItem //---------------------------------------------------------------------------- -MUCItem::MUCItem(Role r, Affiliation a) : - affiliation_(a), role_(r) -{ -} +MUCItem::MUCItem(Role r, Affiliation a) : affiliation_(a), role_(r) {} -MUCItem::MUCItem(const QDomElement &el) : - affiliation_(UnknownAffiliation), role_(UnknownRole) -{ - fromXml(el); -} +MUCItem::MUCItem(const QDomElement &el) : affiliation_(UnknownAffiliation), role_(UnknownRole) { fromXml(el); } -void MUCItem::setNick(const QString &n) -{ - nick_ = n; -} +void MUCItem::setNick(const QString &n) { nick_ = n; } -void MUCItem::setJid(const Jid &j) -{ - jid_ = j; -} +void MUCItem::setJid(const Jid &j) { jid_ = j; } -void MUCItem::setAffiliation(Affiliation a) -{ - affiliation_ = a; -} +void MUCItem::setAffiliation(Affiliation a) { affiliation_ = a; } -void MUCItem::setRole(Role r) -{ - role_ = r; -} +void MUCItem::setRole(Role r) { role_ = r; } -void MUCItem::setActor(const Jid &a) -{ - actor_ = a; -} +void MUCItem::setActor(const Jid &a) { actor_ = a; } -void MUCItem::setReason(const QString &r) -{ - reason_ = r; -} +void MUCItem::setReason(const QString &r) { reason_ = r; } -const QString &MUCItem::nick() const -{ - return nick_; -} +const QString &MUCItem::nick() const { return nick_; } -const Jid &MUCItem::jid() const -{ - return jid_; -} +const Jid &MUCItem::jid() const { return jid_; } -MUCItem::Affiliation MUCItem::affiliation() const -{ - return affiliation_; -} +MUCItem::Affiliation MUCItem::affiliation() const { return affiliation_; } -MUCItem::Role MUCItem::role() const -{ - return role_; -} +MUCItem::Role MUCItem::role() const { return role_; } -const Jid &MUCItem::actor() const -{ - return actor_; -} +const Jid &MUCItem::actor() const { return actor_; } -const QString &MUCItem::reason() const -{ - return reason_; -} +const QString &MUCItem::reason() const { return reason_; } void MUCItem::fromXml(const QDomElement &e) { @@ -768,68 +634,36 @@ QDomElement MUCItem::toXml(QDomDocument &d) bool MUCItem::operator==(const MUCItem &o) { - return !nick_.compare(o.nick_) && ((!jid_.isValid() && !o.jid_.isValid()) || jid_.compare(o.jid_, true)) && ((!actor_.isValid() && !o.actor_.isValid()) || actor_.compare(o.actor_, true)) && affiliation_ == o.affiliation_ && role_ == o.role_ && !reason_.compare(o.reason_); + return !nick_.compare(o.nick_) && ((!jid_.isValid() && !o.jid_.isValid()) || jid_.compare(o.jid_, true)) + && ((!actor_.isValid() && !o.actor_.isValid()) || actor_.compare(o.actor_, true)) + && affiliation_ == o.affiliation_ && role_ == o.role_ && !reason_.compare(o.reason_); } //---------------------------------------------------------------------------- // MUCInvite //---------------------------------------------------------------------------- -MUCInvite::MUCInvite() : - cont_(false) -{ -} +MUCInvite::MUCInvite() : cont_(false) {} -MUCInvite::MUCInvite(const Jid &to, const QString &reason) : - to_(to), reason_(reason), cont_(false) -{ -} +MUCInvite::MUCInvite(const Jid &to, const QString &reason) : to_(to), reason_(reason), cont_(false) {} -MUCInvite::MUCInvite(const QDomElement &e) : - cont_(false) -{ - fromXml(e); -} +MUCInvite::MUCInvite(const QDomElement &e) : cont_(false) { fromXml(e); } -const Jid &MUCInvite::from() const -{ - return from_; -} +const Jid &MUCInvite::from() const { return from_; } -void MUCInvite::setFrom(const Jid &j) -{ - from_ = j; -} +void MUCInvite::setFrom(const Jid &j) { from_ = j; } -const Jid &MUCInvite::to() const -{ - return to_; -} +const Jid &MUCInvite::to() const { return to_; } -void MUCInvite::setTo(const Jid &j) -{ - to_ = j; -} +void MUCInvite::setTo(const Jid &j) { to_ = j; } -const QString &MUCInvite::reason() const -{ - return reason_; -} +const QString &MUCInvite::reason() const { return reason_; } -void MUCInvite::setReason(const QString &r) -{ - reason_ = r; -} +void MUCInvite::setReason(const QString &r) { reason_ = r; } -bool MUCInvite::cont() const -{ - return cont_; -} +bool MUCInvite::cont() const { return cont_; } -void MUCInvite::setCont(bool b) -{ - cont_ = b; -} +void MUCInvite::setCont(bool b) { cont_ = b; } void MUCInvite::fromXml(const QDomElement &e) { @@ -868,53 +702,27 @@ QDomElement MUCInvite::toXml(QDomDocument &d) const return invite; } -bool MUCInvite::isNull() const -{ - return to_.isEmpty() && from_.isEmpty(); -} +bool MUCInvite::isNull() const { return to_.isEmpty() && from_.isEmpty(); } //---------------------------------------------------------------------------- // MUCDecline //---------------------------------------------------------------------------- -MUCDecline::MUCDecline() -{ -} +MUCDecline::MUCDecline() {} -MUCDecline::MUCDecline(const QDomElement &e) -{ - fromXml(e); -} +MUCDecline::MUCDecline(const QDomElement &e) { fromXml(e); } -const Jid &MUCDecline::from() const -{ - return from_; -} +const Jid &MUCDecline::from() const { return from_; } -void MUCDecline::setFrom(const Jid &j) -{ - from_ = j; -} +void MUCDecline::setFrom(const Jid &j) { from_ = j; } -const Jid &MUCDecline::to() const -{ - return to_; -} +const Jid &MUCDecline::to() const { return to_; } -void MUCDecline::setTo(const Jid &j) -{ - to_ = j; -} +void MUCDecline::setTo(const Jid &j) { to_ = j; } -const QString &MUCDecline::reason() const -{ - return reason_; -} +const QString &MUCDecline::reason() const { return reason_; } -void MUCDecline::setReason(const QString &r) -{ - reason_ = r; -} +void MUCDecline::setReason(const QString &r) { reason_ = r; } void MUCDecline::fromXml(const QDomElement &e) { @@ -948,43 +756,23 @@ QDomElement MUCDecline::toXml(QDomDocument &d) const return decline; } -bool MUCDecline::isNull() const -{ - return to_.isEmpty() && from_.isEmpty(); -} +bool MUCDecline::isNull() const { return to_.isEmpty() && from_.isEmpty(); } //---------------------------------------------------------------------------- // MUCDestroy //---------------------------------------------------------------------------- -MUCDestroy::MUCDestroy() -{ -} +MUCDestroy::MUCDestroy() {} -MUCDestroy::MUCDestroy(const QDomElement &e) -{ - fromXml(e); -} +MUCDestroy::MUCDestroy(const QDomElement &e) { fromXml(e); } -const Jid &MUCDestroy::jid() const -{ - return jid_; -} +const Jid &MUCDestroy::jid() const { return jid_; } -void MUCDestroy::setJid(const Jid &j) -{ - jid_ = j; -} +void MUCDestroy::setJid(const Jid &j) { jid_ = j; } -const QString &MUCDestroy::reason() const -{ - return reason_; -} +const QString &MUCDestroy::reason() const { return reason_; } -void MUCDestroy::setReason(const QString &r) -{ - reason_ = r; -} +void MUCDestroy::setReason(const QString &r) { reason_ = r; } void MUCDestroy::fromXml(const QDomElement &e) { @@ -1017,21 +805,13 @@ QDomElement MUCDestroy::toXml(QDomDocument &d) const //---------------------------------------------------------------------------- // HTMLElement //---------------------------------------------------------------------------- -HTMLElement::HTMLElement() -{ -} +HTMLElement::HTMLElement() {} HTMLElement::HTMLElement(const QDomElement &body) { setBody(body); } -void HTMLElement::setBody(const QDomElement &body) -{ - body_ = doc_.importNode(body, true).toElement(); -} +void HTMLElement::setBody(const QDomElement &body) { body_ = doc_.importNode(body, true).toElement(); } -const QDomElement &HTMLElement::body() const -{ - return body_; -} +const QDomElement &HTMLElement::body() const { return body_; } /** * Returns the string reperesentation of the HTML element. @@ -1056,20 +836,17 @@ QString HTMLElement::toString(const QString &rootTagName) const return (Stream::xmlToString(e)); } -QString HTMLElement::text() const -{ - return body_.text(); -} +QString HTMLElement::text() const { return body_.text(); } void HTMLElement::filterOutUnwanted(bool strict) { - Q_UNUSED(strict) //TODO filter out not xhtml-im elements + Q_UNUSED(strict) // TODO filter out not xhtml-im elements filterOutUnwantedRecursive(body_, strict); } void HTMLElement::filterOutUnwantedRecursive(QDomElement &el, bool strict) { - Q_UNUSED(strict) //TODO filter out not xhtml-im elements + Q_UNUSED(strict) // TODO filter out not xhtml-im elements static QSet unwanted = QSet() << "script" << "iframe"; @@ -1083,7 +860,7 @@ void HTMLElement::filterOutUnwantedRecursive(QDomElement &el, bool strict) } else { QDomNamedNodeMap domAttrs = childEl.attributes(); int acnt = domAttrs.count(); - QStringList attrs; //attributes for removing + QStringList attrs; // attributes for removing for (int i = 0; i < acnt; i++) { QString name = domAttrs.item(i).toAttr().name(); if (name.startsWith("on")) { @@ -1145,7 +922,7 @@ class Message::Private : public QSharedData { bool spooled = false, wasEncrypted = false; - //XEP-0280 Message Carbons + // XEP-0280 Message Carbons bool isDisabledCarbons = false; Message::CarbonDir carbonDir = Message::NoCarbon; // it's a forwarded message Message::ProcessingHints processingHints; @@ -1160,25 +937,16 @@ class Message::Private : public QSharedData { //! //! This function will construct a Message container. //! \param to - specify receiver (default: empty string) -Message::Message() -{ -} +Message::Message() {} -Message::Message(const Jid &to) : - d(new Private) -{ - d->to = to; -} +Message::Message(const Jid &to) : d(new Private) { d->to = to; } //! \brief Constructs a copy of Message object //! //! Overloaded constructor which will constructs a exact copy of the Message //! object that was passed to the constructor. //! \param from - Message object you want to copy -Message::Message(const Message &from) : - d(from.d) -{ -} +Message::Message(const Message &from) : d(from.d) {} //! \brief Required for internel use. Message &Message::operator=(const Message &from) @@ -1188,60 +956,31 @@ Message &Message::operator=(const Message &from) } //! \brief Destroy Message object. -Message::~Message() -{ -} +Message::~Message() {} //! \brief Check if it's exactly the same instance. -bool Message::operator==(const Message &from) const -{ - return d == from.d; -} +bool Message::operator==(const Message &from) const { return d == from.d; } //! \brief Return receiver's Jid information. -Jid Message::to() const -{ - return d ? d->to : Jid(); -} +Jid Message::to() const { return d ? d->to : Jid(); } //! \brief Return sender's Jid information. -Jid Message::from() const -{ - return d ? d->from : Jid(); -} +Jid Message::from() const { return d ? d->from : Jid(); } -QString Message::id() const -{ - return d ? d->id : QString(); -} +QString Message::id() const { return d ? d->id : QString(); } //! \brief Return type information -QString Message::type() const -{ - return d ? d->type : QString(); -} +QString Message::type() const { return d ? d->type : QString(); } -QString Message::lang() const -{ - return d ? d->lang : QString(); -} +QString Message::lang() const { return d ? d->lang : QString(); } //! \brief Return subject information. -QString Message::subject(const QString &lang) const -{ - return d ? d->subject.value(lang) : QString(); -} +QString Message::subject(const QString &lang) const { return d ? d->subject.value(lang) : QString(); } //! \brief Return subject information. -QString Message::subject(const QLocale &lang) const -{ - return d ? d->subject.value(lang.bcp47Name()) : QString(); -} +QString Message::subject(const QLocale &lang) const { return d ? d->subject.value(lang.bcp47Name()) : QString(); } -StringMap Message::subjectMap() const -{ - return d ? d->subject : StringMap(); -} +StringMap Message::subjectMap() const { return d ? d->subject : StringMap(); } //! \brief Return body information. //! @@ -1268,10 +1007,7 @@ QString Message::body(const QString &lang) const //! //! \param lang - requested body's locale //! \note Returns first body if not found by locale. -QString Message::body(const QLocale &lang) const -{ - return body(lang.bcp47Name()); -} +QString Message::body(const QLocale &lang) const { return body(lang.bcp47Name()); } //! \brief Return xhtml body. //! @@ -1294,20 +1030,11 @@ HTMLElement Message::html(const QString &lang) const //! //! Returns true if there is at least one xhtml-im body //! in the message. -bool Message::containsHTML() const -{ - return d && !(d->htmlElements.isEmpty()); -} +bool Message::containsHTML() const { return d && !(d->htmlElements.isEmpty()); } -QString Message::thread() const -{ - return d ? d->thread : QString(); -} +QString Message::thread() const { return d ? d->thread : QString(); } -Stanza::Error Message::error() const -{ - return d ? d->error : Stanza::Error(); -} +Stanza::Error Message::error() const { return d ? d->error : Stanza::Error(); } //! \brief Set receivers information //! @@ -1315,19 +1042,16 @@ Stanza::Error Message::error() const void Message::setTo(const Jid &j) { MessageD()->to = j; - //d->flag = false; + // d->flag = false; } void Message::setFrom(const Jid &j) { MessageD()->from = j; - //d->flag = false; + // d->flag = false; } -void Message::setId(const QString &s) -{ - MessageD()->id = s; -} +void Message::setId(const QString &s) { MessageD()->id = s; } //! \brief Set Type of message //! @@ -1335,13 +1059,10 @@ void Message::setId(const QString &s) void Message::setType(const QString &s) { MessageD()->type = s; - //d->flag = false; + // d->flag = false; } -void Message::setLang(const QString &s) -{ - MessageD()->lang = s; -} +void Message::setLang(const QString &s) { MessageD()->lang = s; } //! \brief Set subject //! @@ -1349,7 +1070,7 @@ void Message::setLang(const QString &s) void Message::setSubject(const QString &s, const QString &lang) { MessageD()->subject[lang] = s; - //d->flag = false; + // d->flag = false; } //! \brief Set body @@ -1360,7 +1081,7 @@ void Message::setSubject(const QString &s, const QString &lang) void Message::setBody(const QString &s, const QString &lang) { MessageD()->body[lang] = s; - //d->flag = false; + // d->flag = false; } //! \brief Set xhtml body @@ -1368,10 +1089,7 @@ void Message::setBody(const QString &s, const QString &lang) //! \param s - body node //! \param lang - body language //! \note The body should be in xhtml. -void Message::setHTML(const HTMLElement &e, const QString &lang) -{ - MessageD()->htmlElements[lang] = e; -} +void Message::setHTML(const HTMLElement &e, const QString &lang) { MessageD()->htmlElements[lang] = e; } void Message::setThread(const QString &s, bool send) { @@ -1379,30 +1097,18 @@ void Message::setThread(const QString &s, bool send) d->thread = s; } -void Message::setError(const Stanza::Error &err) -{ - MessageD()->error = err; -} +void Message::setError(const Stanza::Error &err) { MessageD()->error = err; } -QString Message::pubsubNode() const -{ - return d ? d->pubsubNode : QString(); -} +QString Message::pubsubNode() const { return d ? d->pubsubNode : QString(); } -QList Message::pubsubItems() const -{ - return d ? d->pubsubItems : QList(); -} +QList Message::pubsubItems() const { return d ? d->pubsubItems : QList(); } QList Message::pubsubRetractions() const { return d ? d->pubsubRetractions : QList(); } -QDateTime Message::timeStamp() const -{ - return d ? d->timeStamp : QDateTime(); -} +QDateTime Message::timeStamp() const { return d ? d->timeStamp : QDateTime(); } void Message::setTimeStamp(const QDateTime &ts, bool send) { @@ -1411,18 +1117,12 @@ void Message::setTimeStamp(const QDateTime &ts, bool send) } //! \brief Return list of urls attached to message. -UrlList Message::urlList() const -{ - return d ? d->urlList : UrlList(); -} +UrlList Message::urlList() const { return d ? d->urlList : UrlList(); } //! \brief Add Url to the url list. //! //! \param url - url to append -void Message::urlAdd(const Url &u) -{ - MessageD()->urlList += u; -} +void Message::urlAdd(const Url &u) { MessageD()->urlList += u; } //! \brief clear out the url list. void Message::urlsClear() @@ -1435,24 +1135,15 @@ void Message::urlsClear() //! \brief Set urls to send //! //! \param urlList - list of urls to send -void Message::setUrlList(const UrlList &list) -{ - MessageD()->urlList = list; -} +void Message::setUrlList(const UrlList &list) { MessageD()->urlList = list; } //! \brief Return list of addresses attached to message. -AddressList Message::addresses() const -{ - return d ? d->addressList : AddressList(); -} +AddressList Message::addresses() const { return d ? d->addressList : AddressList(); } //! \brief Add Address to the address list. //! //! \param address - address to append -void Message::addAddress(const Address &a) -{ - MessageD()->addressList += a; -} +void Message::addAddress(const Address &a) { MessageD()->addressList += a; } //! \brief clear out the address list. void Message::clearAddresses() @@ -1478,40 +1169,19 @@ AddressList Message::findAddresses(Address::Type t) const //! \brief Set addresses to send //! //! \param list - list of addresses to send -void Message::setAddresses(const AddressList &list) -{ - MessageD()->addressList = list; -} +void Message::setAddresses(const AddressList &list) { MessageD()->addressList = list; } -RosterExchangeItems Message::rosterExchangeItems() const -{ - return d ? d->rosterExchangeItems : RosterExchangeItems(); -} +RosterExchangeItems Message::rosterExchangeItems() const { return d ? d->rosterExchangeItems : RosterExchangeItems(); } -void Message::setRosterExchangeItems(const RosterExchangeItems &items) -{ - MessageD()->rosterExchangeItems = items; -} +void Message::setRosterExchangeItems(const RosterExchangeItems &items) { MessageD()->rosterExchangeItems = items; } -QString Message::eventId() const -{ - return d ? d->eventId : QString(); -} +QString Message::eventId() const { return d ? d->eventId : QString(); } -void Message::setEventId(const QString &id) -{ - MessageD()->eventId = id; -} +void Message::setEventId(const QString &id) { MessageD()->eventId = id; } -bool Message::containsEvents() const -{ - return d && !d->eventList.isEmpty(); -} +bool Message::containsEvents() const { return d && !d->eventList.isEmpty(); } -bool Message::containsEvent(MsgEvent e) const -{ - return d && d->eventList.contains(e); -} +bool Message::containsEvent(MsgEvent e) const { return d && d->eventList.contains(e); } void Message::addEvent(MsgEvent e) { @@ -1522,270 +1192,111 @@ void Message::addEvent(MsgEvent e) } } -ChatState Message::chatState() const -{ - return d ? d->chatState : StateNone; -} +ChatState Message::chatState() const { return d ? d->chatState : StateNone; } -void Message::setChatState(ChatState state) -{ - MessageD()->chatState = state; -} +void Message::setChatState(ChatState state) { MessageD()->chatState = state; } -MessageReceipt Message::messageReceipt() const -{ - return d ? d->messageReceipt : ReceiptNone; -} +MessageReceipt Message::messageReceipt() const { return d ? d->messageReceipt : ReceiptNone; } -void Message::setMessageReceipt(MessageReceipt messageReceipt) -{ - MessageD()->messageReceipt = messageReceipt; -} +void Message::setMessageReceipt(MessageReceipt messageReceipt) { MessageD()->messageReceipt = messageReceipt; } -QString Message::messageReceiptId() const -{ - return d ? d->messageReceiptId : QString(); -} +QString Message::messageReceiptId() const { return d ? d->messageReceiptId : QString(); } -void Message::setMessageReceiptId(const QString &s) -{ - MessageD()->messageReceiptId = s; -} +void Message::setMessageReceiptId(const QString &s) { MessageD()->messageReceiptId = s; } -QString Message::xsigned() const -{ - return d ? d->xsigned : QString(); -} +QString Message::xsigned() const { return d ? d->xsigned : QString(); } -void Message::setXSigned(const QString &s) -{ - MessageD()->xsigned = s; -} +void Message::setXSigned(const QString &s) { MessageD()->xsigned = s; } -QString Message::xencrypted() const -{ - return d ? d->xencrypted : QString(); -} +QString Message::xencrypted() const { return d ? d->xencrypted : QString(); } -void Message::setXEncrypted(const QString &s) -{ - MessageD()->xencrypted = s; -} +void Message::setXEncrypted(const QString &s) { MessageD()->xencrypted = s; } -QList Message::getMUCStatuses() const -{ - return d ? d->mucStatuses : QList(); -} +QList Message::getMUCStatuses() const { return d ? d->mucStatuses : QList(); } -void Message::addMUCStatus(int i) -{ - MessageD()->mucStatuses += i; -} +void Message::addMUCStatus(int i) { MessageD()->mucStatuses += i; } -void Message::addMUCInvite(const MUCInvite &i) -{ - MessageD()->mucInvites += i; -} +void Message::addMUCInvite(const MUCInvite &i) { MessageD()->mucInvites += i; } -QList Message::mucInvites() const -{ - return d ? d->mucInvites : QList(); -} +QList Message::mucInvites() const { return d ? d->mucInvites : QList(); } -void Message::setMUCDecline(const MUCDecline &de) -{ - MessageD()->mucDecline = de; -} +void Message::setMUCDecline(const MUCDecline &de) { MessageD()->mucDecline = de; } -MUCDecline Message::mucDecline() const -{ - return d ? d->mucDecline : MUCDecline(); -} +MUCDecline Message::mucDecline() const { return d ? d->mucDecline : MUCDecline(); } -QString Message::mucPassword() const -{ - return d ? d->mucPassword : QString(); -} +QString Message::mucPassword() const { return d ? d->mucPassword : QString(); } -void Message::setMUCPassword(const QString &p) -{ - MessageD()->mucPassword = p; -} +void Message::setMUCPassword(const QString &p) { MessageD()->mucPassword = p; } -bool Message::hasMUCUser() const -{ - return d & d->hasMUCUser; -} +bool Message::hasMUCUser() const { return d & d->hasMUCUser; } -Message::StanzaId Message::stanzaId() const -{ - return d ? d->stanzaId : StanzaId(); -} +Message::StanzaId Message::stanzaId() const { return d ? d->stanzaId : StanzaId(); } -void Message::setStanzaId(const Message::StanzaId &id) -{ - MessageD()->stanzaId = id; -} +void Message::setStanzaId(const Message::StanzaId &id) { MessageD()->stanzaId = id; } -QString Message::originId() const -{ - return d ? d->originId : QString(); -} +QString Message::originId() const { return d ? d->originId : QString(); } -void Message::setOriginId(const QString &id) -{ - MessageD()->originId = id; -} +void Message::setOriginId(const QString &id) { MessageD()->originId = id; } -QList Message::references() const -{ - return d ? d->references : QList(); -} +QList Message::references() const { return d ? d->references : QList(); } -void Message::addReference(const Reference &r) -{ - MessageD()->references.append(r); -} +void Message::addReference(const Reference &r) { MessageD()->references.append(r); } -void Message::setReferences(const QList &r) -{ - MessageD()->references = r; -} +void Message::setReferences(const QList &r) { MessageD()->references = r; } -QString Message::invite() const -{ - return d ? d->invite : QString(); -} +QString Message::invite() const { return d ? d->invite : QString(); } -void Message::setInvite(const QString &s) -{ - MessageD()->invite = s; -} +void Message::setInvite(const QString &s) { MessageD()->invite = s; } -QString Message::nick() const -{ - return d ? d->nick : QString(); -} +QString Message::nick() const { return d ? d->nick : QString(); } -void Message::setNick(const QString &n) -{ - MessageD()->nick = n; -} +void Message::setNick(const QString &n) { MessageD()->nick = n; } -void Message::setHttpAuthRequest(const HttpAuthRequest &req) -{ - MessageD()->httpAuthRequest = req; -} +void Message::setHttpAuthRequest(const HttpAuthRequest &req) { MessageD()->httpAuthRequest = req; } -HttpAuthRequest Message::httpAuthRequest() const -{ - return d ? d->httpAuthRequest : HttpAuthRequest(); -} +HttpAuthRequest Message::httpAuthRequest() const { return d ? d->httpAuthRequest : HttpAuthRequest(); } -void Message::setForm(const XData &form) -{ - MessageD()->xdata = form; -} +void Message::setForm(const XData &form) { MessageD()->xdata = form; } -XData Message::getForm() const -{ - return d ? d->xdata : XData(); -} +XData Message::getForm() const { return d ? d->xdata : XData(); } -QDomElement Message::sxe() const -{ - return d ? d->sxe : QDomElement(); -} +QDomElement Message::sxe() const { return d ? d->sxe : QDomElement(); } -void Message::setSxe(const QDomElement &e) -{ - MessageD()->sxe = e; -} +void Message::setSxe(const QDomElement &e) { MessageD()->sxe = e; } -void Message::addBoBData(const BoBData &bob) -{ - MessageD()->bobDataList.append(bob); -} +void Message::addBoBData(const BoBData &bob) { MessageD()->bobDataList.append(bob); } -QList Message::bobDataList() const -{ - return d ? d->bobDataList : QList(); -} +QList Message::bobDataList() const { return d ? d->bobDataList : QList(); } -IBBData Message::ibbData() const -{ - return d ? d->ibbData : IBBData(); -} +IBBData Message::ibbData() const { return d ? d->ibbData : IBBData(); } -void Message::setDisabledCarbons(bool disabled) -{ - MessageD()->isDisabledCarbons = disabled; -} +void Message::setDisabledCarbons(bool disabled) { MessageD()->isDisabledCarbons = disabled; } -bool Message::isDisabledCarbons() const -{ - return d && d->isDisabledCarbons; -} +bool Message::isDisabledCarbons() const { return d && d->isDisabledCarbons; } -void Message::setCarbonDirection(Message::CarbonDir cd) -{ - MessageD()->carbonDir = cd; -} +void Message::setCarbonDirection(Message::CarbonDir cd) { MessageD()->carbonDir = cd; } -Message::CarbonDir Message::carbonDirection() const -{ - return d ? d->carbonDir : NoCarbon; -} +Message::CarbonDir Message::carbonDirection() const { return d ? d->carbonDir : NoCarbon; } -void Message::setForwardedFrom(const Jid &jid) -{ - MessageD()->forwardedFrom = jid; -} +void Message::setForwardedFrom(const Jid &jid) { MessageD()->forwardedFrom = jid; } -Jid Message::forwardedFrom() const -{ - return d ? d->forwardedFrom : Jid(); -} +Jid Message::forwardedFrom() const { return d ? d->forwardedFrom : Jid(); } -bool Message::spooled() const -{ - return d && d->spooled; -} +bool Message::spooled() const { return d && d->spooled; } -void Message::setSpooled(bool b) -{ - MessageD()->spooled = b; -} +void Message::setSpooled(bool b) { MessageD()->spooled = b; } -bool Message::wasEncrypted() const -{ - return d && d->wasEncrypted; -} +bool Message::wasEncrypted() const { return d && d->wasEncrypted; } -void Message::setWasEncrypted(bool b) -{ - MessageD()->wasEncrypted = b; -} +void Message::setWasEncrypted(bool b) { MessageD()->wasEncrypted = b; } -QString Message::replaceId() const -{ - return d ? d->replaceId : QString(); -} +QString Message::replaceId() const { return d ? d->replaceId : QString(); } -void Message::setReplaceId(const QString &id) -{ - MessageD()->replaceId = id; -} +void Message::setReplaceId(const QString &id) { MessageD()->replaceId = id; } -void Message::setProcessingHints(const ProcessingHints &hints) -{ - MessageD()->processingHints = hints; -} +void Message::setProcessingHints(const ProcessingHints &hints) { MessageD()->processingHints = hints; } -Message::ProcessingHints Message::processingHints() const -{ - return d ? d->processingHints : ProcessingHints(); -} +Message::ProcessingHints Message::processingHints() const { return d ? d->processingHints : ProcessingHints(); } Stanza Message::toStanza(Stream *stream) const { @@ -2064,18 +1575,12 @@ Stanza Message::toStanza(Stream *stream) const /** \brief Create Message from Stanza \a s, using given \a timeZoneOffset (old style) */ -bool Message::fromStanza(const Stanza &s, int timeZoneOffset) -{ - return fromStanza(s, true, timeZoneOffset); -} +bool Message::fromStanza(const Stanza &s, int timeZoneOffset) { return fromStanza(s, true, timeZoneOffset); } /** \brief Create Message from Stanza \a s */ -bool Message::fromStanza(const Stanza &s) -{ - return fromStanza(s, false, 0); -} +bool Message::fromStanza(const Stanza &s) { return fromStanza(s, false, 0); } /** \brief Create Message from Stanza \a s @@ -2123,7 +1628,8 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf } } else if (e.tagName() == QLatin1String("thread")) d->thread = e.text(); - } else if (e.tagName() == QLatin1String("event") && e.namespaceURI() == QLatin1String("http://jabber.org/protocol/pubsub#event")) { + } else if (e.tagName() == QLatin1String("event") + && e.namespaceURI() == QLatin1String("http://jabber.org/protocol/pubsub#event")) { for (QDomNode enode = e.firstChild(); !enode.isNull(); enode = enode.nextSibling()) { QDomElement eel = enode.toElement(); if (eel.tagName() == QLatin1String("items")) { @@ -2144,23 +1650,27 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf } } } - } else if (e.tagName() == QLatin1String("no-permanent-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("no-permanent-store") + && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoPermanentStore; - } else if (e.tagName() == QLatin1String("no-store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { + } else if (e.tagName() == QLatin1String("no-store") + && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoStore; } else if (e.tagName() == QLatin1String("no-copy") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= NoCopy; } else if (e.tagName() == QLatin1String("store") && e.namespaceURI() == QLatin1String("urn:xmpp:hints")) { d->processingHints |= Store; - } else if (e.tagName() == QLatin1String("origin-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { + } else if (e.tagName() == QLatin1String("origin-id") + && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { d->originId = e.attribute(QStringLiteral("id")); - } else if (e.tagName() == QLatin1String("stanza-id") && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { + } else if (e.tagName() == QLatin1String("stanza-id") + && e.namespaceURI() == QLatin1String("urn:xmpp:sid:0")) { d->stanzaId.id = e.attribute(QStringLiteral("id")); d->stanzaId.by = Jid(e.attribute(QStringLiteral("by"))); } else { - //printf("extension element: [%s]\n", e.tagName().latin1()); + // printf("extension element: [%s]\n", e.tagName().latin1()); } } } @@ -2368,10 +1878,7 @@ bool Message::fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOf d->httpAuthRequest = HttpAuthRequest(); } - QDomElement captcha = childElementsByTagNameNS(root, "urn:xmpp:captcha", - "captcha") - .item(0) - .toElement(); + QDomElement captcha = childElementsByTagNameNS(root, "urn:xmpp:captcha", "captcha").item(0).toElement(); QDomElement xdataRoot = root; if (!captcha.isNull()) { xdataRoot = captcha; @@ -2420,42 +1927,27 @@ HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u, const QStri /*! Constructs request of resource URL \a u, made by method \a m, without transaction id. */ -HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u) : - method_(m), url_(u), hasId_(false) -{ -} +HttpAuthRequest::HttpAuthRequest(const QString &m, const QString &u) : method_(m), url_(u), hasId_(false) {} /*! Constructs request object by reading XML element \a e. */ -HttpAuthRequest::HttpAuthRequest(const QDomElement &e) -{ - fromXml(e); -} +HttpAuthRequest::HttpAuthRequest(const QDomElement &e) { fromXml(e); } /*! Returns true is object is empty (not valid). */ -bool HttpAuthRequest::isEmpty() const -{ - return method_.isEmpty() && url_.isEmpty(); -} +bool HttpAuthRequest::isEmpty() const { return method_.isEmpty() && url_.isEmpty(); } /*! Sets request method. */ -void HttpAuthRequest::setMethod(const QString &m) -{ - method_ = m; -} +void HttpAuthRequest::setMethod(const QString &m) { method_ = m; } /*! Sets requested URL. */ -void HttpAuthRequest::setUrl(const QString &u) -{ - url_ = u; -} +void HttpAuthRequest::setUrl(const QString &u) { url_ = u; } /*! Sets transaction identifier. @@ -2469,35 +1961,23 @@ void HttpAuthRequest::setId(const QString &i) /*! Returns request method. */ -QString HttpAuthRequest::method() const -{ - return method_; -} +QString HttpAuthRequest::method() const { return method_; } /*! Returns requested URL. */ -QString HttpAuthRequest::url() const -{ - return url_; -} +QString HttpAuthRequest::url() const { return url_; } /*! Returns transaction identifier. Empty QString may mean both empty id or no id. Use hasId() to tell the difference. */ -QString HttpAuthRequest::id() const -{ - return id_; -} +QString HttpAuthRequest::id() const { return id_; } /*! Returns true if the request contains transaction id. */ -bool HttpAuthRequest::hasId() const -{ - return hasId_; -} +bool HttpAuthRequest::hasId() const { return hasId_; } /*! Returns XML element representing the request. @@ -2540,15 +2020,9 @@ bool HttpAuthRequest::fromXml(const QDomElement &e) //--------------------------------------------------------------------------- // Subscription //--------------------------------------------------------------------------- -Subscription::Subscription(SubType type) -{ - value = type; -} +Subscription::Subscription(SubType type) { value = type; } -int Subscription::type() const -{ - return value; -} +int Subscription::type() const { return value; } QString Subscription::toString() const { @@ -2591,10 +2065,7 @@ bool Subscription::fromString(const QString &s) /** * Default constructor. */ -CapsSpec::CapsSpec() : - hashAlgo_(CapsSpec::invalidAlgo) -{ -} +CapsSpec::CapsSpec() : hashAlgo_(CapsSpec::invalidAlgo) {} /** * \brief Basic constructor. @@ -2608,9 +2079,7 @@ CapsSpec::CapsSpec(const QString &node, QCryptographicHash::Algorithm hashAlgo, } CapsSpec::CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlgo) : - node_(disco.node().section('#', 0, 0)), - ver_(disco.capsHash(hashAlgo)), - hashAlgo_(hashAlgo) + node_(disco.node().section('#', 0, 0)), ver_(disco.capsHash(hashAlgo)), hashAlgo_(hashAlgo) { } @@ -2618,31 +2087,19 @@ CapsSpec::CapsSpec(const DiscoItem &disco, QCryptographicHash::Algorithm hashAlg * @brief Checks for validity * @return true on valid */ -bool CapsSpec::isValid() const -{ - return !node_.isEmpty() && !ver_.isEmpty() && (hashAlgo_ != CapsSpec::invalidAlgo); -} +bool CapsSpec::isValid() const { return !node_.isEmpty() && !ver_.isEmpty() && (hashAlgo_ != CapsSpec::invalidAlgo); } /** * \brief Returns the node of the capabilities specification. */ -const QString &CapsSpec::node() const -{ - return node_; -} +const QString &CapsSpec::node() const { return node_; } /** * \brief Returns the version of the capabilities specification. */ -const QString &CapsSpec::version() const -{ - return ver_; -} +const QString &CapsSpec::version() const { return ver_; } -QCryptographicHash::Algorithm CapsSpec::hashAlgorithm() const -{ - return hashAlgo_; -} +QCryptographicHash::Algorithm CapsSpec::hashAlgorithm() const { return hashAlgo_; } QDomElement CapsSpec::toXml(QDomDocument *doc) const { @@ -2709,24 +2166,20 @@ QString CapsSpec::flatten() const return QString(); } -void CapsSpec::resetVersion() -{ - ver_.clear(); -} +void CapsSpec::resetVersion() { ver_.clear(); } bool CapsSpec::operator==(const CapsSpec &s) const { return (node() == s.node() && version() == s.version() && hashAlgorithm() == s.hashAlgorithm()); } -bool CapsSpec::operator!=(const CapsSpec &s) const -{ - return !((*this) == s); -} +bool CapsSpec::operator!=(const CapsSpec &s) const { return !((*this) == s); } bool CapsSpec::operator<(const CapsSpec &s) const { - return (node() != s.node() ? node() < s.node() : (version() != s.version() ? version() < s.version() : hashAlgorithm() < s.hashAlgorithm())); + return (node() != s.node() + ? node() < s.node() + : (version() != s.version() ? version() < s.version() : hashAlgorithm() < s.hashAlgorithm())); } class StatusPrivate : public QSharedData { @@ -2764,8 +2217,7 @@ class StatusPrivate : public QSharedData { QString estr; }; -Status::Status(const QString &show, const QString &status, int priority, bool available) : - d(new StatusPrivate) +Status::Status(const QString &show, const QString &status, int priority, bool available) : d(new StatusPrivate) { d->isAvailable = available; d->show = show; @@ -2775,8 +2227,7 @@ Status::Status(const QString &show, const QString &status, int priority, bool av d->isInvisible = false; } -Status::Status(Type type, const QString &status, int priority) : - d(new StatusPrivate) +Status::Status(Type type, const QString &status, int priority) : d(new StatusPrivate) { d->status = status; d->priority = priority; @@ -2784,10 +2235,7 @@ Status::Status(Type type, const QString &status, int priority) : setType(type); } -Status::Status(const Status &other) : - d(other.d) -{ -} +Status::Status(const Status &other) : d(other.d) {} Status &Status::operator=(const Status &other) { @@ -2795,14 +2243,9 @@ Status &Status::operator=(const Status &other) return *this; } -Status::~Status() -{ -} +Status::~Status() {} -bool Status::hasError() const -{ - return (d->ecode != -1); -} +bool Status::hasError() const { return (d->ecode != -1); } void Status::setError(int code, const QString &str) { @@ -2810,20 +2253,11 @@ void Status::setError(int code, const QString &str) d->estr = str; } -void Status::setIsAvailable(bool available) -{ - d->isAvailable = available; -} +void Status::setIsAvailable(bool available) { d->isAvailable = available; } -void Status::setIsInvisible(bool invisible) -{ - d->isInvisible = invisible; -} +void Status::setIsInvisible(bool invisible) { d->isInvisible = invisible; } -void Status::setPriority(int x) -{ - d->priority = x; -} +void Status::setPriority(int x) { d->priority = x; } void Status::setType(Status::Type _type) { @@ -2877,50 +2311,23 @@ Status::Type Status::txt2type(const QString &stat) return XMPP::Status::Away; } -void Status::setType(const QString &stat) -{ - setType(txt2type(stat)); -} +void Status::setType(const QString &stat) { setType(txt2type(stat)); } -void Status::setShow(const QString &_show) -{ - d->show = _show; -} +void Status::setShow(const QString &_show) { d->show = _show; } -void Status::setStatus(const QString &_status) -{ - d->status = _status; -} +void Status::setStatus(const QString &_status) { d->status = _status; } -void Status::setTimeStamp(const QDateTime &_timestamp) -{ - d->timeStamp = _timestamp; -} +void Status::setTimeStamp(const QDateTime &_timestamp) { d->timeStamp = _timestamp; } -void Status::setKeyID(const QString &key) -{ - d->key = key; -} +void Status::setKeyID(const QString &key) { d->key = key; } -void Status::setXSigned(const QString &s) -{ - d->xsigned = s; -} +void Status::setXSigned(const QString &s) { d->xsigned = s; } -void Status::setSongTitle(const QString &_songtitle) -{ - d->songTitle = _songtitle; -} +void Status::setSongTitle(const QString &_songtitle) { d->songTitle = _songtitle; } -void Status::setCaps(const CapsSpec &caps) -{ - d->caps = caps; -} +void Status::setCaps(const CapsSpec &caps) { d->caps = caps; } -void Status::setMUC() -{ - d->isMUC = true; -} +void Status::setMUC() { d->isMUC = true; } void Status::setMUCItem(const MUCItem &i) { @@ -2942,10 +2349,7 @@ void Status::setMUCHistory(int maxchars, int maxstanzas, int seconds, const QDat d->mucHistorySince = since; } -const QByteArray &Status::photoHash() const -{ - return d->photoHash; -} +const QByteArray &Status::photoHash() const { return d->photoHash; } void Status::setPhotoHash(const QByteArray &h) { @@ -2953,40 +2357,19 @@ void Status::setPhotoHash(const QByteArray &h) d->hasPhotoHash = true; } -bool Status::hasPhotoHash() const -{ - return d->hasPhotoHash; -} +bool Status::hasPhotoHash() const { return d->hasPhotoHash; } -void Status::addBoBData(const BoBData &bob) -{ - d->bobDataList.append(bob); -} +void Status::addBoBData(const BoBData &bob) { d->bobDataList.append(bob); } -QList Status::bobDataList() const -{ - return d->bobDataList; -} +QList Status::bobDataList() const { return d->bobDataList; } -bool Status::isAvailable() const -{ - return d->isAvailable; -} +bool Status::isAvailable() const { return d->isAvailable; } -bool Status::isAway() const -{ - return (d->show == "away" || d->show == "xa" || d->show == "dnd"); -} +bool Status::isAway() const { return (d->show == "away" || d->show == "xa" || d->show == "dnd"); } -bool Status::isInvisible() const -{ - return d->isInvisible; -} +bool Status::isInvisible() const { return d->isInvisible; } -int Status::priority() const -{ - return d->priority; -} +int Status::priority() const { return d->priority; } Status::Type Status::type() const { @@ -3040,164 +2423,76 @@ QString Status::typeString() const return stat; } -const QString &Status::show() const -{ - return d->show; -} -const QString &Status::status() const -{ - return d->status; -} +const QString &Status::show() const { return d->show; } +const QString &Status::status() const { return d->status; } -QDateTime Status::timeStamp() const -{ - return d->timeStamp; -} +QDateTime Status::timeStamp() const { return d->timeStamp; } -const QString &Status::keyID() const -{ - return d->key; -} +const QString &Status::keyID() const { return d->key; } -const QString &Status::xsigned() const -{ - return d->xsigned; -} +const QString &Status::xsigned() const { return d->xsigned; } -const QString &Status::songTitle() const -{ - return d->songTitle; -} +const QString &Status::songTitle() const { return d->songTitle; } -const CapsSpec &Status::caps() const -{ - return d->caps; -} +const CapsSpec &Status::caps() const { return d->caps; } -bool Status::isMUC() const -{ - return d->isMUC || !d->mucPassword.isEmpty() || hasMUCHistory(); -} +bool Status::isMUC() const { return d->isMUC || !d->mucPassword.isEmpty() || hasMUCHistory(); } -bool Status::hasMUCItem() const -{ - return d->hasMUCItem; -} +bool Status::hasMUCItem() const { return d->hasMUCItem; } -const MUCItem &Status::mucItem() const -{ - return d->mucItem; -} +const MUCItem &Status::mucItem() const { return d->mucItem; } -bool Status::hasMUCDestroy() const -{ - return d->hasMUCDestroy; -} +bool Status::hasMUCDestroy() const { return d->hasMUCDestroy; } -const MUCDestroy &Status::mucDestroy() const -{ - return d->mucDestroy; -} +const MUCDestroy &Status::mucDestroy() const { return d->mucDestroy; } -const QList &Status::getMUCStatuses() const -{ - return d->mucStatuses; -} +const QList &Status::getMUCStatuses() const { return d->mucStatuses; } -void Status::addMUCStatus(int i) -{ - d->mucStatuses += i; -} +void Status::addMUCStatus(int i) { d->mucStatuses += i; } -const QString &Status::mucPassword() const -{ - return d->mucPassword; -} +const QString &Status::mucPassword() const { return d->mucPassword; } bool Status::hasMUCHistory() const { - return d->mucHistoryMaxChars >= 0 || d->mucHistoryMaxStanzas >= 0 || d->mucHistorySeconds >= 0 || !d->mucHistorySince.isNull(); + return d->mucHistoryMaxChars >= 0 || d->mucHistoryMaxStanzas >= 0 || d->mucHistorySeconds >= 0 + || !d->mucHistorySince.isNull(); } -int Status::mucHistoryMaxChars() const -{ - return d->mucHistoryMaxChars; -} +int Status::mucHistoryMaxChars() const { return d->mucHistoryMaxChars; } -int Status::mucHistoryMaxStanzas() const -{ - return d->mucHistoryMaxStanzas; -} +int Status::mucHistoryMaxStanzas() const { return d->mucHistoryMaxStanzas; } -int Status::mucHistorySeconds() const -{ - return d->mucHistorySeconds; -} +int Status::mucHistorySeconds() const { return d->mucHistorySeconds; } -const QDateTime &Status::mucHistorySince() const -{ - return d->mucHistorySince; -} +const QDateTime &Status::mucHistorySince() const { return d->mucHistorySince; } -void Status::setMUCPassword(const QString &i) -{ - d->mucPassword = i; -} +void Status::setMUCPassword(const QString &i) { d->mucPassword = i; } -int Status::errorCode() const -{ - return d->ecode; -} +int Status::errorCode() const { return d->ecode; } -const QString &Status::errorString() const -{ - return d->estr; -} +const QString &Status::errorString() const { return d->estr; } //--------------------------------------------------------------------------- // Resource //--------------------------------------------------------------------------- -Resource::Resource(const QString &name, const Status &stat) : - v_name(name), v_status(stat) -{ -} +Resource::Resource(const QString &name, const Status &stat) : v_name(name), v_status(stat) {} -const QString &Resource::name() const -{ - return v_name; -} +const QString &Resource::name() const { return v_name; } -int Resource::priority() const -{ - return v_status.priority(); -} +int Resource::priority() const { return v_status.priority(); } -const Status &Resource::status() const -{ - return v_status; -} +const Status &Resource::status() const { return v_status; } -void Resource::setName(const QString &_name) -{ - v_name = _name; -} +void Resource::setName(const QString &_name) { v_name = _name; } -void Resource::setStatus(const Status &_status) -{ - v_status = _status; -} +void Resource::setStatus(const Status &_status) { v_status = _status; } //--------------------------------------------------------------------------- // ResourceList //--------------------------------------------------------------------------- -ResourceList::ResourceList() : - QList() -{ -} +ResourceList::ResourceList() : QList() {} -ResourceList::~ResourceList() -{ -} +ResourceList::~ResourceList() {} ResourceList::Iterator ResourceList::find(const QString &_find) { @@ -3246,55 +2541,27 @@ ResourceList::ConstIterator ResourceList::priority() const //--------------------------------------------------------------------------- // RosterItem //--------------------------------------------------------------------------- -RosterItem::RosterItem(const Jid &_jid) : - v_jid(_jid), - v_push(false) -{ -} +RosterItem::RosterItem(const Jid &_jid) : v_jid(_jid), v_push(false) {} RosterItem::RosterItem(const RosterItem &item) : - v_jid(item.v_jid), - v_name(item.v_name), - v_groups(item.v_groups), - v_subscription(item.v_subscription), - v_ask(item.v_ask), - v_push(item.v_push) + v_jid(item.v_jid), v_name(item.v_name), v_groups(item.v_groups), v_subscription(item.v_subscription), + v_ask(item.v_ask), v_push(item.v_push) { } -RosterItem::~RosterItem() -{ -} +RosterItem::~RosterItem() {} -const Jid &RosterItem::jid() const -{ - return v_jid; -} +const Jid &RosterItem::jid() const { return v_jid; } -const QString &RosterItem::name() const -{ - return v_name; -} +const QString &RosterItem::name() const { return v_name; } -const QStringList &RosterItem::groups() const -{ - return v_groups; -} +const QStringList &RosterItem::groups() const { return v_groups; } -const Subscription &RosterItem::subscription() const -{ - return v_subscription; -} +const Subscription &RosterItem::subscription() const { return v_subscription; } -const QString &RosterItem::ask() const -{ - return v_ask; -} +const QString &RosterItem::ask() const { return v_ask; } -bool RosterItem::isPush() const -{ - return v_push; -} +bool RosterItem::isPush() const { return v_push; } bool RosterItem::inGroup(const QString &g) const { @@ -3305,35 +2572,17 @@ bool RosterItem::inGroup(const QString &g) const return false; } -void RosterItem::setJid(const Jid &_jid) -{ - v_jid = _jid; -} +void RosterItem::setJid(const Jid &_jid) { v_jid = _jid; } -void RosterItem::setName(const QString &_name) -{ - v_name = _name; -} +void RosterItem::setName(const QString &_name) { v_name = _name; } -void RosterItem::setGroups(const QStringList &_groups) -{ - v_groups = _groups; -} +void RosterItem::setGroups(const QStringList &_groups) { v_groups = _groups; } -void RosterItem::setSubscription(const Subscription &type) -{ - v_subscription = type; -} +void RosterItem::setSubscription(const Subscription &type) { v_subscription = type; } -void RosterItem::setAsk(const QString &_ask) -{ - v_ask = _ask; -} +void RosterItem::setAsk(const QString &_ask) { v_ask = _ask; } -void RosterItem::setIsPush(bool b) -{ - v_push = b; -} +void RosterItem::setIsPush(bool b) { v_push = b; } bool RosterItem::addGroup(const QString &g) { @@ -3407,14 +2656,9 @@ bool RosterItem::fromXml(const QDomElement &item) //--------------------------------------------------------------------------- // Roster //--------------------------------------------------------------------------- -Roster::Roster() : - QList() -{ -} +Roster::Roster() : QList() {} -Roster::~Roster() -{ -} +Roster::~Roster() {} Roster::Iterator Roster::find(const Jid &j) { @@ -3450,19 +2694,11 @@ FormField::FormField(const QString &type, const QString &value) v_value = value; } -FormField::~FormField() -{ -} +FormField::~FormField() {} -int FormField::type() const -{ - return v_type; -} +int FormField::type() const { return v_type; } -QString FormField::realName() const -{ - return typeToTagName(v_type); -} +QString FormField::realName() const { return typeToTagName(v_type); } QString FormField::fieldName() const { @@ -3502,20 +2738,11 @@ QString FormField::fieldName() const }; } -bool FormField::isSecret() const -{ - return (type() == password); -} +bool FormField::isSecret() const { return (type() == password); } -const QString &FormField::value() const -{ - return v_value; -} +const QString &FormField::value() const { return v_value; } -void FormField::setType(int x) -{ - v_type = x; -} +void FormField::setType(int x) { v_type = x; } bool FormField::setType(const QString &in) { @@ -3527,10 +2754,7 @@ bool FormField::setType(const QString &in) return true; } -void FormField::setValue(const QString &in) -{ - v_value = in; -} +void FormField::setValue(const QString &in) { v_value = in; } int FormField::tagNameToType(const QString &in) const { @@ -3609,148 +2833,69 @@ QString FormField::typeToTagName(int type) const //--------------------------------------------------------------------------- // Form //--------------------------------------------------------------------------- -Form::Form(const Jid &j) : - QList() -{ - setJid(j); -} +Form::Form(const Jid &j) : QList() { setJid(j); } -Form::~Form() -{ -} +Form::~Form() {} -Jid Form::jid() const -{ - return v_jid; -} +Jid Form::jid() const { return v_jid; } -QString Form::instructions() const -{ - return v_instructions; -} +QString Form::instructions() const { return v_instructions; } -QString Form::key() const -{ - return v_key; -} +QString Form::key() const { return v_key; } -void Form::setJid(const Jid &j) -{ - v_jid = j; -} +void Form::setJid(const Jid &j) { v_jid = j; } -void Form::setInstructions(const QString &s) -{ - v_instructions = s; -} +void Form::setInstructions(const QString &s) { v_instructions = s; } -void Form::setKey(const QString &s) -{ - v_key = s; -} +void Form::setKey(const QString &s) { v_key = s; } //--------------------------------------------------------------------------- // SearchResult //--------------------------------------------------------------------------- -SearchResult::SearchResult(const Jid &jid) -{ - setJid(jid); -} +SearchResult::SearchResult(const Jid &jid) { setJid(jid); } -SearchResult::~SearchResult() -{ -} +SearchResult::~SearchResult() {} -const Jid &SearchResult::jid() const -{ - return v_jid; -} +const Jid &SearchResult::jid() const { return v_jid; } -const QString &SearchResult::nick() const -{ - return v_nick; -} +const QString &SearchResult::nick() const { return v_nick; } -const QString &SearchResult::first() const -{ - return v_first; -} +const QString &SearchResult::first() const { return v_first; } -const QString &SearchResult::last() const -{ - return v_last; -} +const QString &SearchResult::last() const { return v_last; } -const QString &SearchResult::email() const -{ - return v_email; -} +const QString &SearchResult::email() const { return v_email; } -void SearchResult::setJid(const Jid &jid) -{ - v_jid = jid; -} +void SearchResult::setJid(const Jid &jid) { v_jid = jid; } -void SearchResult::setNick(const QString &nick) -{ - v_nick = nick; -} +void SearchResult::setNick(const QString &nick) { v_nick = nick; } -void SearchResult::setFirst(const QString &first) -{ - v_first = first; -} +void SearchResult::setFirst(const QString &first) { v_first = first; } -void SearchResult::setLast(const QString &last) -{ - v_last = last; -} +void SearchResult::setLast(const QString &last) { v_last = last; } -void SearchResult::setEmail(const QString &email) -{ - v_email = email; -} +void SearchResult::setEmail(const QString &email) { v_email = email; } -PubSubItem::PubSubItem() -{ -} +PubSubItem::PubSubItem() {} -PubSubItem::PubSubItem(const QString &id, const QDomElement &payload) : - id_(id), payload_(payload) -{ -} +PubSubItem::PubSubItem(const QString &id, const QDomElement &payload) : id_(id), payload_(payload) {} -const QString &PubSubItem::id() const -{ - return id_; -} +const QString &PubSubItem::id() const { return id_; } -const QDomElement &PubSubItem::payload() const -{ - return payload_; -} +const QDomElement &PubSubItem::payload() const { return payload_; } -PubSubRetraction::PubSubRetraction() -{ -} +PubSubRetraction::PubSubRetraction() {} -PubSubRetraction::PubSubRetraction(const QString &id) : - id_(id) -{ -} +PubSubRetraction::PubSubRetraction(const QString &id) : id_(id) {} -const QString &PubSubRetraction::id() const -{ - return id_; -} +const QString &PubSubRetraction::id() const { return id_; } // ========================================= // CaptchaChallenge // ========================================= class CaptchaChallengePrivate : public QSharedData { public: - CaptchaChallengePrivate() : - state(CaptchaChallenge::New) {} + CaptchaChallengePrivate() : state(CaptchaChallenge::New) {} CaptchaChallenge::State state; Jid arbiter; @@ -3761,18 +2906,11 @@ class CaptchaChallengePrivate : public QSharedData { UrlList urls; }; -CaptchaChallenge::CaptchaChallenge() : - d(new CaptchaChallengePrivate) -{ -} +CaptchaChallenge::CaptchaChallenge() : d(new CaptchaChallengePrivate) {} -CaptchaChallenge::CaptchaChallenge(const CaptchaChallenge &other) : - d(other.d) -{ -} +CaptchaChallenge::CaptchaChallenge(const CaptchaChallenge &other) : d(other.d) {} -CaptchaChallenge::CaptchaChallenge(const Message &m) : - d(new CaptchaChallengePrivate) +CaptchaChallenge::CaptchaChallenge(const Message &m) : d(new CaptchaChallengePrivate) { if (m.spooled()) { if (m.timeStamp().secsTo(QDateTime::currentDateTime()) < Timeout) { @@ -3799,9 +2937,7 @@ CaptchaChallenge::CaptchaChallenge(const Message &m) : d->offendedJid = Jid(m.getForm().getField("from").value().value(0)); } -CaptchaChallenge::~CaptchaChallenge() -{ -} +CaptchaChallenge::~CaptchaChallenge() {} CaptchaChallenge &CaptchaChallenge::operator=(const CaptchaChallenge &from) { @@ -3809,25 +2945,13 @@ CaptchaChallenge &CaptchaChallenge::operator=(const CaptchaChallenge &from) return *this; } -const XData &CaptchaChallenge::form() const -{ - return d->form; -} +const XData &CaptchaChallenge::form() const { return d->form; } -QString CaptchaChallenge::explanation() const -{ - return d->explanation; -} +QString CaptchaChallenge::explanation() const { return d->explanation; } -const UrlList &CaptchaChallenge::urls() const -{ - return d->urls; -} +const UrlList &CaptchaChallenge::urls() const { return d->urls; } -CaptchaChallenge::State CaptchaChallenge::state() const -{ - return d->state; -} +CaptchaChallenge::State CaptchaChallenge::state() const { return d->state; } CaptchaChallenge::Result CaptchaChallenge::validateResponse(const XData &xd) { @@ -3841,15 +2965,9 @@ bool CaptchaChallenge::isValid() const return d->dt.isValid() && d->dt.secsTo(QDateTime::currentDateTime()) < Timeout && d->form.fields().count() > 0; } -const Jid &CaptchaChallenge::offendedJid() const -{ - return d->offendedJid; -} +const Jid &CaptchaChallenge::offendedJid() const { return d->offendedJid; } -const Jid &CaptchaChallenge::arbiter() const -{ - return d->arbiter; -} +const Jid &CaptchaChallenge::arbiter() const { return d->arbiter; } Thumbnail::Thumbnail(const QDomElement &el) { diff --git a/src/xmpp/xmpp-im/xmpp_address.h b/src/xmpp/xmpp-im/xmpp_address.h index 9343c888..60ce564d 100644 --- a/src/xmpp/xmpp-im/xmpp_address.h +++ b/src/xmpp/xmpp-im/xmpp_address.h @@ -27,39 +27,38 @@ class QDomElement; namespace XMPP { - class Address - { - public: - typedef enum { Unknown, To, Cc, Bcc, ReplyTo, ReplyRoom, NoReply, OriginalFrom, OriginalTo } Type; +class Address { +public: + typedef enum { Unknown, To, Cc, Bcc, ReplyTo, ReplyRoom, NoReply, OriginalFrom, OriginalTo } Type; - Address(Type type = Unknown, const Jid& jid = Jid()); - Address(const QDomElement&); + Address(Type type = Unknown, const Jid &jid = Jid()); + Address(const QDomElement &); - const Jid& jid() const; - const QString& uri() const; - const QString& node() const; - const QString& desc() const; - bool delivered() const; - Type type() const; + const Jid & jid() const; + const QString &uri() const; + const QString &node() const; + const QString &desc() const; + bool delivered() const; + Type type() const; - QDomElement toXml(Stanza&) const; - void fromXml(const QDomElement& t); + QDomElement toXml(Stanza &) const; + void fromXml(const QDomElement &t); - void setJid(const Jid &); - void setUri(const QString &); - void setNode(const QString &); - void setDesc(const QString &); - void setDelivered(bool); - void setType(Type); + void setJid(const Jid &); + void setUri(const QString &); + void setNode(const QString &); + void setDesc(const QString &); + void setDelivered(bool); + void setType(Type); - private: - Jid v_jid; - QString v_uri, v_node, v_desc; - bool v_delivered; - Type v_type; - }; +private: + Jid v_jid; + QString v_uri, v_node, v_desc; + bool v_delivered; + Type v_type; +}; - typedef QList
AddressList; +typedef QList
AddressList; } // namespace XMPP #endif // XMPP_ADDRESS_H diff --git a/src/xmpp/xmpp-im/xmpp_agentitem.h b/src/xmpp/xmpp-im/xmpp_agentitem.h index f9570424..03b43beb 100644 --- a/src/xmpp/xmpp-im/xmpp_agentitem.h +++ b/src/xmpp/xmpp-im/xmpp_agentitem.h @@ -26,28 +26,27 @@ #include namespace XMPP { - class AgentItem - { - public: - AgentItem() { } - - const Jid & jid() const { return v_jid; } - const QString & name() const { return v_name; } - const QString & category() const { return v_category; } - const QString & type() const { return v_type; } - const Features & features() const { return v_features; } - - void setJid(const Jid &j) { v_jid = j; } - void setName(const QString &n) { v_name = n; } - void setCategory(const QString &c) { v_category = c; } - void setType(const QString &t) { v_type = t; } - void setFeatures(const Features &f) { v_features = f; } - - private: - Jid v_jid; - QString v_name, v_category, v_type; - Features v_features; - }; +class AgentItem { +public: + AgentItem() {} + + const Jid & jid() const { return v_jid; } + const QString & name() const { return v_name; } + const QString & category() const { return v_category; } + const QString & type() const { return v_type; } + const Features &features() const { return v_features; } + + void setJid(const Jid &j) { v_jid = j; } + void setName(const QString &n) { v_name = n; } + void setCategory(const QString &c) { v_category = c; } + void setType(const QString &t) { v_type = t; } + void setFeatures(const Features &f) { v_features = f; } + +private: + Jid v_jid; + QString v_name, v_category, v_type; + Features v_features; +}; } // namespace XMPP #endif // XMPP_AGENTITEM diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp index 9b6ee453..6bbe76b8 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.cpp @@ -32,43 +32,28 @@ class BoBData::Private : public QSharedData { public: QByteArray data; // file data itself QString type; // mime type. e.g. image/png - //QString cid; // content identifier without "cid:" + // QString cid; // content identifier without "cid:" Hash hash; unsigned int maxAge; // seconds to live }; -BoBData::BoBData() : - d(new Private) -{ -} +BoBData::BoBData() : d(new Private) {} -BoBData::BoBData(const BoBData &other) : - d(other.d) -{ -} +BoBData::BoBData(const BoBData &other) : d(other.d) {} -BoBData::BoBData(const QDomElement &e) : - d(new Private) -{ - fromXml(e); -} +BoBData::BoBData(const QDomElement &e) : d(new Private) { fromXml(e); } -BoBData::~BoBData() -{ -} +BoBData::~BoBData() {} BoBData &BoBData::operator=(const BoBData &other) { if (this == &other) - return *this; //Protect against self-assignment + return *this; // Protect against self-assignment d = other.d; return *this; } -bool BoBData::isNull() const -{ - return !d->hash.isValid() || d->data.isNull(); -} +bool BoBData::isNull() const { return !d->hash.isValid() || d->data.isNull(); } Hash BoBData::cidToHash(const QString &cid) { @@ -84,50 +69,23 @@ QString BoBData::cid() const return QString("%1+%2@bob.xmpp.org").arg(d->hash.stringType(), QString::fromLatin1(d->hash.data().toHex())); } -void BoBData::setCid(const QString &cid) -{ - d->hash = cidToHash(cid); -} +void BoBData::setCid(const QString &cid) { d->hash = cidToHash(cid); } -const Hash &BoBData::hash() const -{ - return d->hash; -} +const Hash &BoBData::hash() const { return d->hash; } -void BoBData::setHash(const Hash &hash) -{ - d->hash = hash; -} +void BoBData::setHash(const Hash &hash) { d->hash = hash; } -QByteArray BoBData::data() const -{ - return d->data; -} +QByteArray BoBData::data() const { return d->data; } -void BoBData::setData(const QByteArray &data) -{ - d->data = data; -} +void BoBData::setData(const QByteArray &data) { d->data = data; } -QString BoBData::type() const -{ - return d->type; -} +QString BoBData::type() const { return d->type; } -void BoBData::setType(const QString &type) -{ - d->type = type; -} +void BoBData::setType(const QString &type) { d->type = type; } -unsigned int BoBData::maxAge() const -{ - return d->maxAge; -} +unsigned int BoBData::maxAge() const { return d->maxAge; } -void BoBData::setMaxAge(unsigned int maxAge) -{ - d->maxAge = maxAge; -} +void BoBData::setMaxAge(unsigned int maxAge) { d->maxAge = maxAge; } void BoBData::fromXml(const QDomElement &data) { @@ -150,24 +108,14 @@ QDomElement BoBData::toXml(QDomDocument *doc) const // --------------------------------------------------------- // BoBCache // --------------------------------------------------------- -BoBCache::BoBCache(QObject *parent) : - QObject(parent) -{ -} +BoBCache::BoBCache(QObject *parent) : QObject(parent) {} //------------------------------------------------------------------------------ // BoBManager //------------------------------------------------------------------------------ -BoBManager::BoBManager(Client *client) : - QObject(client), _cache(nullptr) -{ - new JT_BoBServer(client->rootTask()); -} +BoBManager::BoBManager(Client *client) : QObject(client), _cache(nullptr) { new JT_BoBServer(client->rootTask()); } -void BoBManager::setCache(BoBCache *cache) -{ - _cache = cache; -} +void BoBManager::setCache(BoBCache *cache) { _cache = cache; } BoBData BoBManager::bobData(const QString &cid) { @@ -192,8 +140,7 @@ BoBData BoBManager::bobData(const QString &cid) return bd; } -BoBData BoBManager::append(const QByteArray &data, const QString &type, - unsigned int maxAge) +BoBData BoBManager::append(const QByteArray &data, const QString &type, unsigned int maxAge) { BoBData b; b.setHash(Hash::from(Hash::Sha1, data)); diff --git a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h index c8f2de3a..e871d635 100644 --- a/src/xmpp/xmpp-im/xmpp_bitsofbinary.h +++ b/src/xmpp/xmpp-im/xmpp_bitsofbinary.h @@ -86,15 +86,14 @@ class BoBManager : public QObject { BoBData bobData(const QString &); // file data, mime type, max age in seconds - BoBData append(const QByteArray &data, const QString &type, - unsigned int maxAge = 0); + BoBData append(const QByteArray &data, const QString &type, unsigned int maxAge = 0); Hash append(QFile & file, const QString &type = "application/octet-stream"); // this method adds just to runtime cache void append(const BoBData &); private: BoBCache * _cache; - QHash> _localFiles; //cid => (filename, mime) + QHash> _localFiles; // cid => (filename, mime) }; } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_bytestream.cpp b/src/xmpp/xmpp-im/xmpp_bytestream.cpp index 71863929..0478b3f7 100644 --- a/src/xmpp/xmpp-im/xmpp_bytestream.cpp +++ b/src/xmpp/xmpp-im/xmpp_bytestream.cpp @@ -24,25 +24,17 @@ #include namespace XMPP { -BytestreamManager::BytestreamManager(Client *parent) - : QObject(parent) -{ - -} +BytestreamManager::BytestreamManager(Client *parent) : QObject(parent) {} -BytestreamManager::~BytestreamManager() -{ - -} +BytestreamManager::~BytestreamManager() {} QString BytestreamManager::genUniqueSID(const Jid &peer) const { // get unused key QString sid; do { - sid = QString("%1%2").arg(sidPrefix()) - .arg(qrand() & 0xffff, 4, 16, QChar('0')); - } while(!isAcceptableSID(peer, sid)); + sid = QString("%1%2").arg(sidPrefix()).arg(qrand() & 0xffff, 4, 16, QChar('0')); + } while (!isAcceptableSID(peer, sid)); return sid; } @@ -53,8 +45,7 @@ void BytestreamManager::deleteConnection(BSConnection *c, int msec) { if (msec) { QTimer::singleShot(msec, c, SLOT(deleteLater())); - } - else { + } else { delete c; } } diff --git a/src/xmpp/xmpp-im/xmpp_bytestream.h b/src/xmpp/xmpp-im/xmpp_bytestream.h index 5933ff2e..9cb892f5 100644 --- a/src/xmpp/xmpp-im/xmpp_bytestream.h +++ b/src/xmpp/xmpp-im/xmpp_bytestream.h @@ -26,44 +26,42 @@ #include namespace XMPP { - class BytestreamManager; - class Client; +class BytestreamManager; +class Client; - class BSConnection : public ByteStream - { - public: - enum Error { ErrRefused = ErrCustom, ErrConnect, ErrProxy, ErrSocket }; - enum State { Idle, Requesting, Connecting, WaitingForAccept, Active }; +class BSConnection : public ByteStream { +public: + enum Error { ErrRefused = ErrCustom, ErrConnect, ErrProxy, ErrSocket }; + enum State { Idle, Requesting, Connecting, WaitingForAccept, Active }; - BSConnection(QObject *parent = nullptr) : ByteStream(parent) {} + BSConnection(QObject *parent = nullptr) : ByteStream(parent) {} - virtual void connectToJid(const Jid &peer, const QString &sid) = 0; - virtual void accept() = 0; + virtual void connectToJid(const Jid &peer, const QString &sid) = 0; + virtual void accept() = 0; - virtual Jid peer() const = 0; - virtual QString sid() const = 0; - virtual BytestreamManager* manager() const = 0; - }; + virtual Jid peer() const = 0; + virtual QString sid() const = 0; + virtual BytestreamManager *manager() const = 0; +}; - class BytestreamManager : public QObject - { - Q_OBJECT +class BytestreamManager : public QObject { + Q_OBJECT - public: - BytestreamManager(Client *); - virtual ~BytestreamManager(); +public: + BytestreamManager(Client *); + virtual ~BytestreamManager(); - virtual bool isAcceptableSID(const Jid &peer, const QString &sid) const = 0; - QString genUniqueSID(const Jid &peer) const; - virtual BSConnection* createConnection() = 0; - virtual void deleteConnection(BSConnection *c, int msec = 0); + virtual bool isAcceptableSID(const Jid &peer, const QString &sid) const = 0; + QString genUniqueSID(const Jid &peer) const; + virtual BSConnection *createConnection() = 0; + virtual void deleteConnection(BSConnection *c, int msec = 0); - protected: - virtual const char* sidPrefix() const = 0; +protected: + virtual const char *sidPrefix() const = 0; - signals: - void incomingReady(); - }; +signals: + void incomingReady(); +}; } // namespace XMPP #endif // BYTESTREAM_MANAGER_H diff --git a/src/xmpp/xmpp-im/xmpp_caps.cpp b/src/xmpp/xmpp-im/xmpp_caps.cpp index 2637bd84..856d6ef1 100644 --- a/src/xmpp/xmpp-im/xmpp_caps.cpp +++ b/src/xmpp/xmpp-im/xmpp_caps.cpp @@ -49,7 +49,7 @@ QDomElement CapsInfo::toXml(QDomDocument *doc) const CapsInfo CapsInfo::fromXml(const QDomElement &caps) { QDateTime lastSeen = QDateTime::fromString(caps.firstChildElement("atime").nodeValue(), Qt::ISODate); - DiscoItem item = DiscoItem::fromDiscoInfoResult(caps.firstChildElement("query")); + DiscoItem item = DiscoItem::fromDiscoInfoResult(caps.firstChildElement("query")); if (item.features().isEmpty()) { // it's hardly possible if client does not support anything. return CapsInfo(); } @@ -67,10 +67,7 @@ CapsRegistry *CapsRegistry::instance_ = nullptr; /** * \brief Default constructor. */ -CapsRegistry::CapsRegistry(QObject *parent) : - QObject(parent) -{ -} +CapsRegistry::CapsRegistry(QObject *parent) : QObject(parent) {} CapsRegistry *CapsRegistry::instance() { @@ -80,10 +77,7 @@ CapsRegistry *CapsRegistry::instance() return instance_; } -void CapsRegistry::setInstance(CapsRegistry *instance) -{ - instance_ = instance; -} +void CapsRegistry::setInstance(CapsRegistry *instance) { instance_ = instance; } /** * \brief Convert all capabilities info to XML. @@ -92,12 +86,12 @@ void CapsRegistry::save() { // Generate XML QDomDocument doc; - QDomElement capabilities = doc.createElement("capabilities"); + QDomElement capabilities = doc.createElement("capabilities"); doc.appendChild(capabilities); - QHash::ConstIterator i = capsInfo_.constBegin(); - for( ; i != capsInfo_.end(); i++) { + QHash::ConstIterator i = capsInfo_.constBegin(); + for (; i != capsInfo_.end(); i++) { QDomElement info = i.value().toXml(&doc); - info.setAttribute("node",i.key()); + info.setAttribute("node", i.key()); capabilities.appendChild(info); } @@ -110,10 +104,7 @@ void CapsRegistry::saveData(const QByteArray &data) return; } -QByteArray CapsRegistry::loadData() -{ - return QByteArray(); -} +QByteArray CapsRegistry::loadData() { return QByteArray(); } /** * \brief Sets the file to save the capabilities info to @@ -141,28 +132,26 @@ void CapsRegistry::load() // keep unseen info for last 3 month. adjust if required QDateTime validTime = QDateTime::currentDateTime().addMonths(-3); - for(QDomNode n = caps.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = caps.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if(i.isNull()) { + if (i.isNull()) { qWarning("capsregistry.cpp: Null element"); continue; } - if(i.tagName() == "info") { + if (i.tagName() == "info") { QString node = i.attribute("node"); - int sep = node.indexOf('#'); + int sep = node.indexOf('#'); if (sep > 0 && sep + 1 < node.length()) { CapsInfo info = CapsInfo::fromXml(i); if (info.isValid() && info.lastSeen() > validTime) { capsInfo_[node] = CapsInfo::fromXml(i); } - //qDebug() << QString("Read %1 %2").arg(node).arg(ver); - } - else { + // qDebug() << QString("Read %1 %2").arg(node).arg(ver); + } else { qWarning() << "capsregistry.cpp: Node" << node << "invalid"; } - } - else { + } else { qWarning("capsregistry.cpp: Unknown element"); } } @@ -171,7 +160,7 @@ void CapsRegistry::load() /** * \brief Registers capabilities of a client. */ -void CapsRegistry::registerCaps(const CapsSpec& spec, const DiscoItem &item) +void CapsRegistry::registerCaps(const CapsSpec &spec, const DiscoItem &item) { QString dnode = spec.flatten(); if (!isRegistered(dnode)) { @@ -184,10 +173,7 @@ void CapsRegistry::registerCaps(const CapsSpec& spec, const DiscoItem &item) /** * \brief Checks if capabilities have been registered. */ -bool CapsRegistry::isRegistered(const QString& spec) const -{ - return capsInfo_.contains(spec); -} +bool CapsRegistry::isRegistered(const QString &spec) const { return capsInfo_.contains(spec); } DiscoItem CapsRegistry::disco(const QString &spec) const { @@ -216,30 +202,19 @@ DiscoItem CapsRegistry::disco(const QString &spec) const /** * \brief Default constructor. */ -CapsManager::CapsManager(Client *client) : - QObject(client), - client_(client), - isEnabled_(true) -{} +CapsManager::CapsManager(Client *client) : QObject(client), client_(client), isEnabled_(true) {} -CapsManager::~CapsManager() -{} +CapsManager::~CapsManager() {} /** * \brief Checks whether the caps manager is enabled (and does lookups). */ -bool CapsManager::isEnabled() -{ - return isEnabled_; -} +bool CapsManager::isEnabled() { return isEnabled_; } /** * \brief Enables or disables the caps manager. */ -void CapsManager::setEnabled(bool b) -{ - isEnabled_ = b; -} +void CapsManager::setEnabled(bool b) { isEnabled_ = b; } /** * \brief Registers new incoming capabilities information of a JID. @@ -251,14 +226,15 @@ void CapsManager::setEnabled(bool b) * @param ver The entity's caps version * @param ext The entity's caps extensions */ -void CapsManager::updateCaps(const Jid& jid, const CapsSpec &c) +void CapsManager::updateCaps(const Jid &jid, const CapsSpec &c) { - if (jid.compare(client_->jid(),false)) + if (jid.compare(client_->jid(), false)) return; QString fullNode = c.flatten(); if (capsSpecs_[jid.full()] != c) { - //qDebug() << QString("caps.cpp: Updating caps for %1 (node=%2,ver=%3,ext=%4)").arg(QString(jid.full()).replace('%',"%%")).arg(node).arg(ver).arg(ext); + // qDebug() << QString("caps.cpp: Updating caps for %1 + // (node=%2,ver=%3,ext=%4)").arg(QString(jid.full()).replace('%',"%%")).arg(node).arg(ver).arg(ext); // Unregister from all old caps node capsJids_[capsSpecs_[jid.full()].flatten()].removeAll(jid.full()); @@ -275,22 +251,24 @@ void CapsManager::updateCaps(const Jid& jid, const CapsSpec &c) // Register new caps and check if we need to discover features if (isEnabled()) { if (!CapsRegistry::instance()->isRegistered(fullNode) && capsJids_[fullNode].count() == 1) { - //qDebug() << QString("caps.cpp: Sending disco request to %1, node=%2").arg(QString(jid.full()).replace('%',"%%")).arg(node + "#" + s.extensions()); - JT_DiscoInfo* disco = new JT_DiscoInfo(client_->rootTask()); + // qDebug() << QString("caps.cpp: Sending disco request to %1, + // node=%2").arg(QString(jid.full()).replace('%',"%%")).arg(node + "#" + s.extensions()); + JT_DiscoInfo *disco = new JT_DiscoInfo(client_->rootTask()); disco->setAllowCache(false); connect(disco, SIGNAL(finished()), SLOT(discoFinished())); disco->get(jid, fullNode); disco->go(true); } } - } - else { + } else { // Remove all caps specifications - qWarning() << QString("caps.cpp: Illegal caps info from %1: node=%2, ver=%3").arg(QString(jid.full()).replace('%',"%%")).arg(fullNode).arg(c.version()); + qWarning() << QString("caps.cpp: Illegal caps info from %1: node=%2, ver=%3") + .arg(QString(jid.full()).replace('%', "%%")) + .arg(fullNode) + .arg(c.version()); capsSpecs_.remove(jid.full()); } - } - else { + } else { // Add to the list of jids capsJids_[fullNode].push_back(jid.full()); } @@ -301,9 +279,9 @@ void CapsManager::updateCaps(const Jid& jid, const CapsSpec &c) * * @param jid The entity's JID */ -void CapsManager::disableCaps(const Jid& jid) +void CapsManager::disableCaps(const Jid &jid) { - //qDebug() << QString("caps.cpp: Disabling caps for %1.").arg(QString(jid.full()).replace('%',"%%")); + // qDebug() << QString("caps.cpp: Disabling caps for %1.").arg(QString(jid.full()).replace('%',"%%")); if (capsEnabled(jid)) { QString node = capsSpecs_[jid.full()].flatten(); if (!node.isEmpty()) { @@ -341,11 +319,11 @@ void CapsManager::updateDisco(const Jid &jid, const DiscoItem &item) * \brief This slot is called whenever capabilities of a client were discovered. * All jids with the corresponding client are updated. */ -void CapsManager::capsRegistered(const CapsSpec& cs) +void CapsManager::capsRegistered(const CapsSpec &cs) { // Notify affected jids. - foreach(const QString &s, capsJids_[cs.flatten()]) { - //qDebug() << QString("caps.cpp: Notifying %1.").arg(s.replace('%',"%%")); + foreach (const QString &s, capsJids_[cs.flatten()]) { + // qDebug() << QString("caps.cpp: Notifying %1.").arg(s.replace('%',"%%")); emit capsChanged(s); } } @@ -353,54 +331,48 @@ void CapsManager::capsRegistered(const CapsSpec& cs) /** * \brief Checks whether a given JID is broadcastingn its entity capabilities. */ -bool CapsManager::capsEnabled(const Jid& jid) const -{ - return capsSpecs_.contains(jid.full()); -} +bool CapsManager::capsEnabled(const Jid &jid) const { return capsSpecs_.contains(jid.full()); } /** * \brief Requests the list of features of a given JID. */ -XMPP::DiscoItem CapsManager::disco(const Jid& jid) const +XMPP::DiscoItem CapsManager::disco(const Jid &jid) const { - //qDebug() << "caps.cpp: Retrieving features of " << jid.full(); + // qDebug() << "caps.cpp: Retrieving features of " << jid.full(); QStringList f; if (!capsEnabled(jid)) { return DiscoItem(); } QString node = capsSpecs_[jid.full()].flatten(); - //qDebug() << QString(" %1").arg(CapsRegistry::instance()->features(s).list().join("\n")); + // qDebug() << QString(" %1").arg(CapsRegistry::instance()->features(s).list().join("\n")); return CapsRegistry::instance()->disco(node); } /** * \brief Requests the list of features of a given JID. */ -XMPP::Features CapsManager::features(const Jid& jid) const -{ - return disco(jid).features(); -} +XMPP::Features CapsManager::features(const Jid &jid) const { return disco(jid).features(); } /** * \brief Returns the client name of a given jid. * \param jid the jid to retrieve the client name of */ -QString CapsManager::clientName(const Jid& jid) const +QString CapsManager::clientName(const Jid &jid) const { if (capsEnabled(jid)) { CapsSpec cs = capsSpecs_[jid.full()]; - QString name; + QString name; QString cs_str = cs.flatten(); if (CapsRegistry::instance()->isRegistered(cs_str)) { DiscoItem disco = CapsRegistry::instance()->disco(cs_str); - XData si = disco.registeredExtension(QLatin1String("urn:xmpp:dataforms:softwareinfo")); + XData si = disco.registeredExtension(QLatin1String("urn:xmpp:dataforms:softwareinfo")); if (si.isValid()) { name = si.getField("software").value().value(0); } if (name.isEmpty()) { - const DiscoItem::Identities& i = disco.identities(); + const DiscoItem::Identities &i = disco.identities(); if (i.count() > 0) { name = i.first().name; } @@ -409,8 +381,8 @@ QString CapsManager::clientName(const Jid& jid) const // Try to be intelligent about the name if (name.isEmpty()) { - const QString &node = cs.node(); - int startPos = 0, ds = 0; + const QString &node = cs.node(); + int startPos = 0, ds = 0; if (node.startsWith(QStringLiteral("http://"))) startPos = 7; else if (node.startsWith(QStringLiteral("https://"))) @@ -425,8 +397,7 @@ QString CapsManager::clientName(const Jid& jid) const } return name; - } - else { + } else { return QString(); } } @@ -434,17 +405,17 @@ QString CapsManager::clientName(const Jid& jid) const /** * \brief Returns the client version of a given jid. */ -QString CapsManager::clientVersion(const Jid& jid) const +QString CapsManager::clientVersion(const Jid &jid) const { if (!capsEnabled(jid)) return QString(); - QString version; - const CapsSpec &cs = capsSpecs_[jid.full()]; - QString cs_str = cs.flatten(); + QString version; + const CapsSpec &cs = capsSpecs_[jid.full()]; + QString cs_str = cs.flatten(); if (CapsRegistry::instance()->isRegistered(cs_str)) { XData form = CapsRegistry::instance()->disco(cs_str).registeredExtension("urn:xmpp:dataforms:softwareinfo"); - version = form.getField("software_version").value().value(0); + version = form.getField("software_version").value().value(0); } return version; @@ -460,7 +431,7 @@ QString CapsManager::osVersion(const Jid &jid) const QString cs_str = capsSpecs_[jid.full()].flatten(); if (CapsRegistry::instance()->isRegistered(cs_str)) { XData form = CapsRegistry::instance()->disco(cs_str).registeredExtension("urn:xmpp:dataforms:softwareinfo"); - os_str = form.getField("os").value().value(0).trimmed(); + os_str = form.getField("os").value().value(0).trimmed(); if (!os_str.isEmpty()) { QString os_ver = form.getField("os_version").value().value(0).trimmed(); if (!os_ver.isEmpty()) @@ -471,8 +442,5 @@ QString CapsManager::osVersion(const Jid &jid) const return os_str; } -CapsSpec CapsManager::capsSpec(const Jid &jid) const -{ - return capsSpecs_.value(jid.full()); -} +CapsSpec CapsManager::capsSpec(const Jid &jid) const { return capsSpecs_.value(jid.full()); } } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_caps.h b/src/xmpp/xmpp-im/xmpp_caps.h index 929c6f64..3acf4041 100644 --- a/src/xmpp/xmpp-im/xmpp_caps.h +++ b/src/xmpp/xmpp-im/xmpp_caps.h @@ -26,56 +26,54 @@ #include namespace XMPP { -class CapsInfo -{ +class CapsInfo { public: inline CapsInfo() {} inline CapsInfo(const XMPP::DiscoItem &disco, const QDateTime &lastSeen = QDateTime()) : - _lastSeen(lastSeen.isNull()? QDateTime::currentDateTime() : lastSeen), - _disco(disco) {} - inline bool isValid() const { return _lastSeen.isValid(); } - inline const QDateTime &lastSeen() const { return _lastSeen; } + _lastSeen(lastSeen.isNull() ? QDateTime::currentDateTime() : lastSeen), _disco(disco) + { + } + inline bool isValid() const { return _lastSeen.isValid(); } + inline const QDateTime & lastSeen() const { return _lastSeen; } inline const XMPP::DiscoItem &disco() const { return _disco; } - QDomElement toXml(QDomDocument *doc) const; - static CapsInfo fromXml(const QDomElement &ci); + QDomElement toXml(QDomDocument *doc) const; + static CapsInfo fromXml(const QDomElement &ci); private: - QDateTime _lastSeen; + QDateTime _lastSeen; XMPP::DiscoItem _disco; }; -class CapsRegistry : public QObject -{ +class CapsRegistry : public QObject { Q_OBJECT public: CapsRegistry(QObject *parent = nullptr); - static CapsRegistry* instance(); - static void setInstance(CapsRegistry*instance); + static CapsRegistry *instance(); + static void setInstance(CapsRegistry *instance); - void registerCaps(const CapsSpec&, const XMPP::DiscoItem &item); - bool isRegistered(const QString &) const; - DiscoItem disco(const QString&) const; + void registerCaps(const CapsSpec &, const XMPP::DiscoItem &item); + bool isRegistered(const QString &) const; + DiscoItem disco(const QString &) const; signals: - void registered(const XMPP::CapsSpec&); + void registered(const XMPP::CapsSpec &); public slots: void load(); void save(); protected: - virtual void saveData(const QByteArray &data); // reimplmenet these two functions - virtual QByteArray loadData(); // to have permanent cache + virtual void saveData(const QByteArray &data); // reimplmenet these two functions + virtual QByteArray loadData(); // to have permanent cache private: - static CapsRegistry *instance_; - QHash capsInfo_; + static CapsRegistry * instance_; + QHash capsInfo_; }; -class CapsManager : public QObject -{ +class CapsManager : public QObject { Q_OBJECT public: @@ -85,34 +83,34 @@ class CapsManager : public QObject bool isEnabled(); void setEnabled(bool); - void updateCaps(const Jid& jid, const CapsSpec& caps); - void disableCaps(const Jid& jid); - bool capsEnabled(const Jid& jid) const; + void updateCaps(const Jid &jid, const CapsSpec &caps); + void disableCaps(const Jid &jid); + bool capsEnabled(const Jid &jid) const; XMPP::DiscoItem disco(const Jid &jid) const; - void updateDisco(const Jid &jid, const XMPP::DiscoItem &item); + void updateDisco(const Jid &jid, const XMPP::DiscoItem &item); - XMPP::Features features(const Jid& jid) const; - QString clientName(const Jid& jid) const; - QString clientVersion(const Jid& jid) const; - QString osVersion(const Jid& jid) const; - CapsSpec capsSpec(const Jid &jid) const; + XMPP::Features features(const Jid &jid) const; + QString clientName(const Jid &jid) const; + QString clientVersion(const Jid &jid) const; + QString osVersion(const Jid &jid) const; + CapsSpec capsSpec(const Jid &jid) const; signals: /** * This signal is emitted when the feature list of a given JID have changed. */ - void capsChanged(const Jid& jid); + void capsChanged(const Jid &jid); protected slots: void discoFinished(); - void capsRegistered(const CapsSpec&); + void capsRegistered(const CapsSpec &); private: - Client *client_; - bool isEnabled_; - QMap capsSpecs_; - QMap > capsJids_; + Client * client_; + bool isEnabled_; + QMap capsSpecs_; + QMap> capsJids_; }; } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_captcha.h b/src/xmpp/xmpp-im/xmpp_captcha.h index 27b76e85..23af0d31 100644 --- a/src/xmpp/xmpp-im/xmpp_captcha.h +++ b/src/xmpp/xmpp-im/xmpp_captcha.h @@ -25,48 +25,39 @@ #include namespace XMPP { - class CaptchaChallengePrivate; - class Message; - class XData; +class CaptchaChallengePrivate; +class Message; +class XData; - class CaptchaChallenge - { - public: - enum Result { - Passed, - Unavailable, - NotAcceptable - }; +class CaptchaChallenge { +public: + enum Result { Passed, Unavailable, NotAcceptable }; - enum State { - New, - Success, - Fail - }; + enum State { New, Success, Fail }; - static const int Timeout = 120; // secs + static const int Timeout = 120; // secs - CaptchaChallenge(); - CaptchaChallenge(const Message &); - CaptchaChallenge(const CaptchaChallenge &); - ~CaptchaChallenge(); + CaptchaChallenge(); + CaptchaChallenge(const Message &); + CaptchaChallenge(const CaptchaChallenge &); + ~CaptchaChallenge(); - CaptchaChallenge & operator=(const CaptchaChallenge &); + CaptchaChallenge &operator=(const CaptchaChallenge &); - bool isValid() const; - const Jid &offendedJid() const; - const Jid &arbiter() const; - const XData &form() const; - QString explanation() const; - const UrlList &urls() const; - State state() const; + bool isValid() const; + const Jid & offendedJid() const; + const Jid & arbiter() const; + const XData & form() const; + QString explanation() const; + const UrlList &urls() const; + State state() const; - Result validateResponse(const XData &); + Result validateResponse(const XData &); - private: - friend class CaptchaChallengePrivate; - QSharedDataPointer d; - }; +private: + friend class CaptchaChallengePrivate; + QSharedDataPointer d; +}; } // namespace XMPP #endif // XMPP_CAPTCHA_H diff --git a/src/xmpp/xmpp-im/xmpp_chatstate.h b/src/xmpp/xmpp-im/xmpp_chatstate.h index 5596147d..a7a4e339 100644 --- a/src/xmpp/xmpp-im/xmpp_chatstate.h +++ b/src/xmpp/xmpp-im/xmpp_chatstate.h @@ -20,14 +20,7 @@ #define XMPP_CHATSTATE namespace XMPP { - typedef enum { - StateNone, - StateActive, - StateComposing, - StatePaused, - StateInactive, - StateGone - } ChatState; +typedef enum { StateNone, StateActive, StateComposing, StatePaused, StateInactive, StateGone } ChatState; } // namespace XMPP #endif // XMPP_CHATSTATE diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h index 2bd4528e..9d44ed18 100644 --- a/src/xmpp/xmpp-im/xmpp_client.h +++ b/src/xmpp/xmpp-im/xmpp_client.h @@ -34,201 +34,202 @@ class QNetworkAccessManager; class QString; namespace XMPP { - class BSConnection; - class CapsManager; - class ClientStream; - class EncryptionHandler; - class Features; - class FileTransferManager; - class HttpFileUploadManager; - class IBBManager; - class JidLinkManager; - class LiveRoster; - class LiveRosterItem; - class Message; - class Resource; - class ResourceList; - class Roster; - class RosterItem; - class S5BManager; - class ServerInfoManager; - class Stream; - class Task; - class TcpPortReserver; - namespace Jingle { +class BSConnection; +class CapsManager; +class ClientStream; +class EncryptionHandler; +class Features; +class FileTransferManager; +class HttpFileUploadManager; +class IBBManager; +class JidLinkManager; +class LiveRoster; +class LiveRosterItem; +class Message; +class Resource; +class ResourceList; +class Roster; +class RosterItem; +class S5BManager; +class ServerInfoManager; +class Stream; +class Task; +class TcpPortReserver; +namespace Jingle { + class Manager; + namespace S5B { class Manager; - namespace S5B { - class Manager; - } - namespace IBB { - class Manager; - } } + namespace IBB { + class Manager; + } +} } namespace XMPP { - class Client : public QObject - { - Q_OBJECT - - public: - Client(QObject *parent=nullptr); - ~Client(); - - bool isActive() const; - void connectToServer(ClientStream *s, const Jid &j, bool auth=true); - void start(const QString &host, const QString &user, const QString &pass, const QString &resource); - void close(bool fast=false); - - bool hasStream() const; - Stream & stream(); - QString streamBaseNS() const; - const LiveRoster & roster() const; - const ResourceList & resourceList() const; - bool isSessionRequired() const; - - void send(const QDomElement &); - void send(const QString &); - void clearSendQueue(); - - QString host() const; - QString user() const; - QString pass() const; - QString resource() const; - Jid jid() const; - - void setNetworkAccessManager(QNetworkAccessManager *qnam); - QNetworkAccessManager *networkAccessManager() const; - - void rosterRequest(); - void sendMessage(Message &); - void sendSubscription(const Jid &, const QString &, const QString& nick = QString()); - void setPresence(const Status &); - - void debug(const QString &); - QString genUniqueId(); - Task *rootTask(); - QDomDocument *doc() const; - - QString OSName() const; - QString OSVersion() const; - QString timeZone() const; - int timeZoneOffset() const; - bool manualTimeZoneOffset() const; - QString clientName() const; - QString clientVersion() const; - CapsSpec caps() const; - CapsSpec serverCaps() const; - - void setOSName(const QString &); - void setOSVersion(const QString &); - void setTimeZone(const QString &, int); - void setClientName(const QString &); - void setClientVersion(const QString &); - void setCaps(const CapsSpec &); - void setEncryptionHandler(EncryptionHandler *); - EncryptionHandler *encryptionHandler() const; - - void setIdentity(const DiscoItem::Identity &); - DiscoItem::Identity identity() const; - - void setFeatures(const Features& f); - const Features& features() const; - DiscoItem makeDiscoResult(const QString &node = QString()) const; - - void setTcpPortReserver(TcpPortReserver *portReserver); - TcpPortReserver *tcpPortReserver() const; - S5BManager *s5bManager() const; - IBBManager *ibbManager() const; - BoBManager *bobManager() const; - JidLinkManager *jidLinkManager() const; - CapsManager *capsManager() const; - ServerInfoManager *serverInfoManager() const; - HttpFileUploadManager *httpFileUploadManager() const; - Jingle::Manager* jingleManager() const; - Jingle::S5B::Manager *jingleS5BManager() const; - Jingle::IBB::Manager *jingleIBBManager() const; - - void setFileTransferEnabled(bool b); - FileTransferManager *fileTransferManager() const; - - QString groupChatPassword(const QString& host, const QString& room) const; - bool groupChatJoin(const QString &host, const QString &room, const QString &nick, const QString& password = QString(), int maxchars = -1, int maxstanzas = -1, int seconds = -1, const QDateTime &since = QDateTime(), const Status& = Status()); - void groupChatSetStatus(const QString &host, const QString &room, const Status &); - void groupChatChangeNick(const QString &host, const QString &room, const QString &nick, const Status &); - void groupChatLeave(const QString &host, const QString &room, const QString &statusStr = QString()); - void groupChatLeaveAll(const QString &statusStr = QString()); - QString groupChatNick(const QString &host, const QString &room) const; - - signals: - void activated(); - void disconnected(); - //void authFinished(bool, int, const QString &); - void rosterRequestFinished(bool, int, const QString &); - void rosterItemAdded(const RosterItem &); - void rosterItemUpdated(const RosterItem &); - void rosterItemRemoved(const RosterItem &); - void resourceAvailable(const Jid &, const Resource &); - void resourceUnavailable(const Jid &, const Resource &); - void presenceError(const Jid &, int, const QString &); - void subscription(const Jid &, const QString &, const QString &); - void messageReceived(const Message &); - void debugText(const QString &); - void xmlIncoming(const QString &); - void xmlOutgoing(const QString &); - void stanzaElementOutgoing(QDomElement &); - void groupChatJoined(const Jid &); - void groupChatLeft(const Jid &); - void groupChatPresence(const Jid &, const Status &); - void groupChatError(const Jid &, int, const QString &); - - void incomingJidLink(); - - void beginImportRoster(); - void endImportRoster(); - - private slots: - //void streamConnected(); - //void streamHandshaken(); - //void streamError(const StreamError &); - //void streamSSLCertificateReady(const QSSLCert &); - //void streamCloseFinished(); - void streamError(int); - void streamReadyRead(); - void streamIncomingXml(const QString &); - void streamOutgoingXml(const QString &); - - void slotRosterRequestFinished(); - - // basic daemons - void ppSubscription(const Jid &, const QString &, const QString&); - void ppPresence(const Jid &, const Status &); - void pmMessage(const Message &); - void prRoster(const Roster &); - - void s5b_incomingReady(); - void ibb_incomingReady(); - - void handleSMAckResponse(int); - void parseUnhandledStreamFeatures(); - - public: - class GroupChat; - - private: - void cleanup(); - void distribute(const QDomElement &); - void importRoster(const Roster &); - void importRosterItem(const RosterItem &); - void updateSelfPresence(const Jid &, const Status &); - void updatePresence(LiveRosterItem *, const Jid &, const Status &); - void handleIncoming(BSConnection *); - - void sendAckRequest(); - - class ClientPrivate; - ClientPrivate *d; - }; +class Client : public QObject { + Q_OBJECT + +public: + Client(QObject *parent = nullptr); + ~Client(); + + bool isActive() const; + void connectToServer(ClientStream *s, const Jid &j, bool auth = true); + void start(const QString &host, const QString &user, const QString &pass, const QString &resource); + void close(bool fast = false); + + bool hasStream() const; + Stream & stream(); + QString streamBaseNS() const; + const LiveRoster & roster() const; + const ResourceList &resourceList() const; + bool isSessionRequired() const; + + void send(const QDomElement &); + void send(const QString &); + void clearSendQueue(); + + QString host() const; + QString user() const; + QString pass() const; + QString resource() const; + Jid jid() const; + + void setNetworkAccessManager(QNetworkAccessManager *qnam); + QNetworkAccessManager *networkAccessManager() const; + + void rosterRequest(); + void sendMessage(Message &); + void sendSubscription(const Jid &, const QString &, const QString &nick = QString()); + void setPresence(const Status &); + + void debug(const QString &); + QString genUniqueId(); + Task * rootTask(); + QDomDocument *doc() const; + + QString OSName() const; + QString OSVersion() const; + QString timeZone() const; + int timeZoneOffset() const; + bool manualTimeZoneOffset() const; + QString clientName() const; + QString clientVersion() const; + CapsSpec caps() const; + CapsSpec serverCaps() const; + + void setOSName(const QString &); + void setOSVersion(const QString &); + void setTimeZone(const QString &, int); + void setClientName(const QString &); + void setClientVersion(const QString &); + void setCaps(const CapsSpec &); + void setEncryptionHandler(EncryptionHandler *); + EncryptionHandler *encryptionHandler() const; + + void setIdentity(const DiscoItem::Identity &); + DiscoItem::Identity identity() const; + + void setFeatures(const Features &f); + const Features &features() const; + DiscoItem makeDiscoResult(const QString &node = QString()) const; + + void setTcpPortReserver(TcpPortReserver *portReserver); + TcpPortReserver * tcpPortReserver() const; + S5BManager * s5bManager() const; + IBBManager * ibbManager() const; + BoBManager * bobManager() const; + JidLinkManager * jidLinkManager() const; + CapsManager * capsManager() const; + ServerInfoManager * serverInfoManager() const; + HttpFileUploadManager *httpFileUploadManager() const; + Jingle::Manager * jingleManager() const; + Jingle::S5B::Manager * jingleS5BManager() const; + Jingle::IBB::Manager * jingleIBBManager() const; + + void setFileTransferEnabled(bool b); + FileTransferManager *fileTransferManager() const; + + QString groupChatPassword(const QString &host, const QString &room) const; + bool groupChatJoin(const QString &host, const QString &room, const QString &nick, + const QString &password = QString(), int maxchars = -1, int maxstanzas = -1, int seconds = -1, + const QDateTime &since = QDateTime(), const Status & = Status()); + void groupChatSetStatus(const QString &host, const QString &room, const Status &); + void groupChatChangeNick(const QString &host, const QString &room, const QString &nick, const Status &); + void groupChatLeave(const QString &host, const QString &room, const QString &statusStr = QString()); + void groupChatLeaveAll(const QString &statusStr = QString()); + QString groupChatNick(const QString &host, const QString &room) const; + +signals: + void activated(); + void disconnected(); + // void authFinished(bool, int, const QString &); + void rosterRequestFinished(bool, int, const QString &); + void rosterItemAdded(const RosterItem &); + void rosterItemUpdated(const RosterItem &); + void rosterItemRemoved(const RosterItem &); + void resourceAvailable(const Jid &, const Resource &); + void resourceUnavailable(const Jid &, const Resource &); + void presenceError(const Jid &, int, const QString &); + void subscription(const Jid &, const QString &, const QString &); + void messageReceived(const Message &); + void debugText(const QString &); + void xmlIncoming(const QString &); + void xmlOutgoing(const QString &); + void stanzaElementOutgoing(QDomElement &); + void groupChatJoined(const Jid &); + void groupChatLeft(const Jid &); + void groupChatPresence(const Jid &, const Status &); + void groupChatError(const Jid &, int, const QString &); + + void incomingJidLink(); + + void beginImportRoster(); + void endImportRoster(); + +private slots: + // void streamConnected(); + // void streamHandshaken(); + // void streamError(const StreamError &); + // void streamSSLCertificateReady(const QSSLCert &); + // void streamCloseFinished(); + void streamError(int); + void streamReadyRead(); + void streamIncomingXml(const QString &); + void streamOutgoingXml(const QString &); + + void slotRosterRequestFinished(); + + // basic daemons + void ppSubscription(const Jid &, const QString &, const QString &); + void ppPresence(const Jid &, const Status &); + void pmMessage(const Message &); + void prRoster(const Roster &); + + void s5b_incomingReady(); + void ibb_incomingReady(); + + void handleSMAckResponse(int); + void parseUnhandledStreamFeatures(); + +public: + class GroupChat; + +private: + void cleanup(); + void distribute(const QDomElement &); + void importRoster(const Roster &); + void importRosterItem(const RosterItem &); + void updateSelfPresence(const Jid &, const Status &); + void updatePresence(LiveRosterItem *, const Jid &, const Status &); + void handleIncoming(BSConnection *); + + void sendAckRequest(); + + class ClientPrivate; + ClientPrivate *d; +}; } // namespace XMPP #endif // XMPP_CLIENT_H diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp index 4694152c..31f8b103 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.cpp @@ -31,46 +31,35 @@ using namespace XMPP; -class DiscoInfoTask::Private -{ +class DiscoInfoTask::Private { public: - bool allowCache = true; - Jid jid; - QString node; + bool allowCache = true; + Jid jid; + QString node; DiscoItem::Identity ident; - DiscoItem item; + DiscoItem item; }; -DiscoInfoTask::DiscoInfoTask(Task *parent) -: Task(parent) -{ - d = new Private; -} +DiscoInfoTask::DiscoInfoTask(Task *parent) : Task(parent) { d = new Private; } -DiscoInfoTask::~DiscoInfoTask() -{ - delete d; -} +DiscoInfoTask::~DiscoInfoTask() { delete d; } -void DiscoInfoTask::setAllowCache(bool allow) -{ - d->allowCache = allow; -} +void DiscoInfoTask::setAllowCache(bool allow) { d->allowCache = allow; } void DiscoInfoTask::get(const DiscoItem &item) { DiscoItem::Identity id; - if ( item.identities().count() == 1 ) + if (item.identities().count() == 1) id = item.identities().first(); get(item.jid(), item.node(), id); } -void DiscoInfoTask::get (const Jid &j, const QString &node, DiscoItem::Identity ident) +void DiscoInfoTask::get(const Jid &j, const QString &node, DiscoItem::Identity ident) { d->item = DiscoItem(); // clear item - d->jid = j; - d->node = node; + d->jid = j; + d->node = node; d->ident = ident; } @@ -79,27 +68,18 @@ void DiscoInfoTask::get (const Jid &j, const QString &node, DiscoItem::Identity * Is here because sometimes the responder does not include this information * in the reply. */ -const Jid& DiscoInfoTask::jid() const -{ - return d->jid; -} +const Jid &DiscoInfoTask::jid() const { return d->jid; } /** * Original requested node. * Is here because sometimes the responder does not include this information * in the reply. */ -const QString& DiscoInfoTask::node() const -{ - return d->node; -} +const QString &DiscoInfoTask::node() const { return d->node; } -const DiscoItem &DiscoInfoTask::item() const -{ - return d->item; -} +const DiscoItem &DiscoInfoTask::item() const { return d->item; } -void DiscoInfoTask::onGo () +void DiscoInfoTask::onGo() { if (d->allowCache && client()->capsManager()->isEnabled()) { d->item = client()->capsManager()->disco(d->jid); @@ -109,9 +89,9 @@ void DiscoInfoTask::onGo () } } - QDomElement iq = createIQ(doc(), "get", d->jid.full(), id()); + QDomElement iq = createIQ(doc(), "get", d->jid.full(), id()); QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#info", "query"); - if ( !d->node.isEmpty() ) + if (!d->node.isEmpty()) query.setAttribute("node", d->node); #if 0 // seems like disco#info get request was misinterpreted. xep-0030 says it has to be an EMPTY query. @@ -133,25 +113,24 @@ void DiscoInfoTask::onGo () void DiscoInfoTask::cachedReady() { - d->item.setJid( d->jid ); + d->item.setJid(d->jid); setSuccess(); } bool DiscoInfoTask::take(const QDomElement &x) { - if(!iqVerify(x, d->jid, id())) + if (!iqVerify(x, d->jid, id())) return false; - if(x.attribute("type") == "result") { + if (x.attribute("type") == "result") { d->item = DiscoItem::fromDiscoInfoResult(queryTag(x)); - d->item.setJid( d->jid ); + d->item.setJid(d->jid); if (d->allowCache && client()->capsManager()->isEnabled()) { client()->capsManager()->updateDisco(d->jid, d->item); } setSuccess(); - } - else { + } else { setError(x); } diff --git a/src/xmpp/xmpp-im/xmpp_discoinfotask.h b/src/xmpp/xmpp-im/xmpp_discoinfotask.h index 03aa8885..a5f4da11 100644 --- a/src/xmpp/xmpp-im/xmpp_discoinfotask.h +++ b/src/xmpp/xmpp-im/xmpp_discoinfotask.h @@ -26,37 +26,36 @@ class QDomElement; class QString; namespace XMPP { - class Jid; +class Jid; - class DiscoInfoTask : public Task - { - Q_OBJECT - public: - DiscoInfoTask(Task *); - ~DiscoInfoTask(); +class DiscoInfoTask : public Task { + Q_OBJECT +public: + DiscoInfoTask(Task *); + ~DiscoInfoTask(); - // Allow retreive result from cache and update cache on finish with new data - void setAllowCache(bool allow = true); + // Allow retreive result from cache and update cache on finish with new data + void setAllowCache(bool allow = true); - void get(const Jid &, const QString &node = QString(), const DiscoItem::Identity = DiscoItem::Identity()); - void get(const DiscoItem &); + void get(const Jid &, const QString &node = QString(), const DiscoItem::Identity = DiscoItem::Identity()); + void get(const DiscoItem &); - const DiscoItem &item() const; - const Jid& jid() const; - const QString& node() const; + const DiscoItem &item() const; + const Jid & jid() const; + const QString & node() const; - void onGo(); - bool take(const QDomElement &); + void onGo(); + bool take(const QDomElement &); - private slots: - void cachedReady(); +private slots: + void cachedReady(); - private: - class Private; - Private *d; - }; - // Deprecated name - typedef DiscoInfoTask JT_DiscoInfo; +private: + class Private; + Private *d; +}; +// Deprecated name +typedef DiscoInfoTask JT_DiscoInfo; } // namespace XMPP #endif // XMPP_DISCOINFOTASK_H diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.cpp b/src/xmpp/xmpp-im/xmpp_discoitem.cpp index 3006c91f..69286639 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.cpp +++ b/src/xmpp/xmpp-im/xmpp_discoitem.cpp @@ -23,93 +23,79 @@ using namespace XMPP; -class XMPP::DiscoItemPrivate : public QSharedData -{ +class XMPP::DiscoItemPrivate : public QSharedData { public: - DiscoItemPrivate() - { - action = DiscoItem::None; - } + DiscoItemPrivate() { action = DiscoItem::None; } - Jid jid; - QString name; - QString node; + Jid jid; + QString name; + QString node; DiscoItem::Action action; - Features features; + Features features; DiscoItem::Identities identities; - QList exts; + QList exts; }; -DiscoItem::DiscoItem() - : d(new DiscoItemPrivate) -{ -} +DiscoItem::DiscoItem() : d(new DiscoItemPrivate) {} -DiscoItem::DiscoItem(const DiscoItem &from) - : d(new DiscoItemPrivate) -{ - *this = from; -} +DiscoItem::DiscoItem(const DiscoItem &from) : d(new DiscoItemPrivate) { *this = from; } -DiscoItem & DiscoItem::operator= (const DiscoItem &from) +DiscoItem &DiscoItem::operator=(const DiscoItem &from) { - d->jid = from.d->jid; - d->name = from.d->name; - d->node = from.d->node; - d->action = from.d->action; - d->features = from.d->features; + d->jid = from.d->jid; + d->name = from.d->name; + d->node = from.d->node; + d->action = from.d->action; + d->features = from.d->features; d->identities = from.d->identities; - d->exts = from.d->exts; + d->exts = from.d->exts; return *this; } -DiscoItem::~DiscoItem() -{ - -} +DiscoItem::~DiscoItem() {} AgentItem DiscoItem::toAgentItem() const { AgentItem ai; - ai.setJid( jid() ); - ai.setName( name() ); + ai.setJid(jid()); + ai.setName(name()); Identity id; - if ( !identities().isEmpty() ) + if (!identities().isEmpty()) id = identities().first(); - ai.setCategory( id.category ); - ai.setType( id.type ); + ai.setCategory(id.category); + ai.setType(id.type); - ai.setFeatures( d->features ); + ai.setFeatures(d->features); return ai; } void DiscoItem::fromAgentItem(const AgentItem &ai) { - setJid( ai.jid() ); - setName( ai.name() ); + setJid(ai.jid()); + setName(ai.name()); Identity id; id.category = ai.category(); - id.type = ai.type(); - id.name = ai.name(); + id.type = ai.type(); + id.name = ai.name(); Identities idList; idList << id; - setIdentities( idList ); + setIdentities(idList); - setFeatures( ai.features() ); + setFeatures(ai.features()); } QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const { - QStringList prep; + QStringList prep; DiscoItem::Identities idents = d->identities; std::sort(idents.begin(), idents.end()); @@ -121,7 +107,7 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const std::sort(fl.begin(), fl.end()); prep += fl; - QMap forms; + QMap forms; foreach (const XData &xd, d->exts) { if (xd.registrarType().isEmpty()) { continue; @@ -133,7 +119,7 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const } foreach (const XData &xd, forms.values()) { prep << xd.registrarType(); - QMap values; + QMap values; foreach (const XData::Field &f, xd.fields()) { if (f.var() == QLatin1String("FORM_TYPE")) { continue; @@ -148,7 +134,7 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const std::sort(v.begin(), v.end()); values[f.var()] = v; } - QMap ::ConstIterator it = values.constBegin(); + QMap::ConstIterator it = values.constBegin(); for (; it != values.constEnd(); ++it) { prep += it.key(); prep += it.value(); @@ -156,7 +142,7 @@ QString DiscoItem::capsHash(QCryptographicHash::Algorithm algo) const } QByteArray ba = QString(prep.join(QLatin1String("<")) + QLatin1Char('<')).toUtf8(); - //qDebug() << "Server caps ver: " << (prep.join(QLatin1String("<")) + QLatin1Char('<')) + // qDebug() << "Server caps ver: " << (prep.join(QLatin1String("<")) + QLatin1Char('<')) // << "Hash:" << QString::fromLatin1(QCryptographicHash::hash(ba, algo).toBase64()); return QString::fromLatin1(QCryptographicHash::hash(ba, algo).toBase64()); } @@ -165,21 +151,20 @@ DiscoItem DiscoItem::fromDiscoInfoResult(const QDomElement &q) { DiscoItem item; - item.setNode( q.attribute("node") ); + item.setNode(q.attribute("node")); - QStringList features; + QStringList features; DiscoItem::Identities identities; - QList extList; + QList extList; - for(QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { + for (QDomNode n = q.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement e = n.toElement(); - if( e.isNull() ) + if (e.isNull()) continue; - if ( e.tagName() == "feature" ) { + if (e.tagName() == "feature") { features << e.attribute("var"); - } - else if ( e.tagName() == "identity" ) { + } else if (e.tagName() == "identity") { DiscoItem::Identity id; id.category = e.attribute("category"); @@ -187,25 +172,25 @@ DiscoItem DiscoItem::fromDiscoInfoResult(const QDomElement &q) id.lang = e.attribute("lang"); id.name = e.attribute("name"); - identities.append( id ); - } - else if (e.tagName() == QLatin1String("x") && e.namespaceURI() == QLatin1String("jabber:x:data")) { + identities.append(id); + } else if (e.tagName() == QLatin1String("x") && e.namespaceURI() == QLatin1String("jabber:x:data")) { XData form; form.fromXml(e); extList.append(form); } } - item.setFeatures( features ); - item.setIdentities( identities ); - item.setExtensions( extList ); + item.setFeatures(features); + item.setIdentities(identities); + item.setExtensions(extList); return item; } QDomElement DiscoItem::toDiscoInfoResult(QDomDocument *doc) const { - QDomElement q = doc->createElementNS(QLatin1String("http://jabber.org/protocol/disco#info"), QLatin1String("query")); + QDomElement q + = doc->createElementNS(QLatin1String("http://jabber.org/protocol/disco#info"), QLatin1String("query")); q.setAttribute("node", d->node); foreach (const Identity &id, d->identities) { @@ -232,78 +217,39 @@ QDomElement DiscoItem::toDiscoInfoResult(QDomDocument *doc) const return q; } -const Jid &DiscoItem::jid() const -{ - return d->jid; -} +const Jid &DiscoItem::jid() const { return d->jid; } -void DiscoItem::setJid(const Jid &j) -{ - d->jid = j; -} +void DiscoItem::setJid(const Jid &j) { d->jid = j; } -const QString &DiscoItem::name() const -{ - return d->name; -} +const QString &DiscoItem::name() const { return d->name; } -void DiscoItem::setName(const QString &n) -{ - d->name = n; -} +void DiscoItem::setName(const QString &n) { d->name = n; } -const QString &DiscoItem::node() const -{ - return d->node; -} +const QString &DiscoItem::node() const { return d->node; } -void DiscoItem::setNode(const QString &n) -{ - d->node = n; -} +void DiscoItem::setNode(const QString &n) { d->node = n; } -DiscoItem::Action DiscoItem::action() const -{ - return d->action; -} +DiscoItem::Action DiscoItem::action() const { return d->action; } -void DiscoItem::setAction(Action a) -{ - d->action = a; -} +void DiscoItem::setAction(Action a) { d->action = a; } -const Features &DiscoItem::features() const -{ - return d->features; -} +const Features &DiscoItem::features() const { return d->features; } -void DiscoItem::setFeatures(const Features &f) -{ - d->features = f; -} +void DiscoItem::setFeatures(const Features &f) { d->features = f; } -const DiscoItem::Identities &DiscoItem::identities() const -{ - return d->identities; -} +const DiscoItem::Identities &DiscoItem::identities() const { return d->identities; } void DiscoItem::setIdentities(const Identities &i) { d->identities = i; - if ( name().isEmpty() && i.count() ) - setName( i.first().name ); + if (name().isEmpty() && i.count()) + setName(i.first().name); } -const QList &DiscoItem::extensions() const -{ - return d->exts; -} +const QList &DiscoItem::extensions() const { return d->exts; } -void DiscoItem::setExtensions(const QList &extlist) -{ - d->exts = extlist; -} +void DiscoItem::setExtensions(const QList &extlist) { d->exts = extlist; } XData DiscoItem::registeredExtension(const QString &ns) const { @@ -319,9 +265,9 @@ DiscoItem::Action DiscoItem::string2action(const QString &s) { Action a; - if ( s == "update" ) + if (s == "update") a = Update; - else if ( s == "remove" ) + else if (s == "remove") a = Remove; else a = None; @@ -333,9 +279,9 @@ QString DiscoItem::action2string(const Action a) { QString s; - if ( a == Update ) + if (a == Update) s = "update"; - else if ( a == Remove ) + else if (a == Remove) s = "remove"; else s = QString(); @@ -361,6 +307,5 @@ bool XMPP::operator<(const DiscoItem::Identity &a, const DiscoItem::Identity &b) bool DiscoItem::Identity::operator==(const DiscoItem::Identity &other) const { - return category == other.category && type == other.type && - lang == other.lang && name == other.name; + return category == other.category && type == other.type && lang == other.lang && name == other.name; } diff --git a/src/xmpp/xmpp-im/xmpp_discoitem.h b/src/xmpp/xmpp-im/xmpp_discoitem.h index 051f6833..face5952 100644 --- a/src/xmpp/xmpp-im/xmpp_discoitem.h +++ b/src/xmpp/xmpp-im/xmpp_discoitem.h @@ -29,79 +29,76 @@ #include namespace XMPP { - class DiscoItemPrivate; +class DiscoItemPrivate; - class DiscoItem - { - public: - DiscoItem(); - ~DiscoItem(); +class DiscoItem { +public: + DiscoItem(); + ~DiscoItem(); - const Jid &jid() const; - const QString &node() const; - const QString &name() const; + const Jid & jid() const; + const QString &node() const; + const QString &name() const; - void setJid(const Jid &); - void setName(const QString &); - void setNode(const QString &); + void setJid(const Jid &); + void setName(const QString &); + void setNode(const QString &); - enum Action { - None = 0, - Remove, - Update - }; + enum Action { None = 0, Remove, Update }; - Action action() const; - void setAction(Action); + Action action() const; + void setAction(Action); - const Features &features() const; - void setFeatures(const Features &); + const Features &features() const; + void setFeatures(const Features &); - struct Identity - { - QString category; - QString type; - QString lang; - QString name; + struct Identity { + QString category; + QString type; + QString lang; + QString name; - inline Identity() {} - inline Identity(const QString &categoty, const QString &type, - const QString &lang = QString(), const QString &name = QString()) : - category(categoty), type(type), lang(lang), name(name) {} - bool operator==(const Identity &other) const; - }; + inline Identity() {} + inline Identity(const QString &categoty, const QString &type, const QString &lang = QString(), + const QString &name = QString()) : + category(categoty), + type(type), lang(lang), name(name) + { + } + bool operator==(const Identity &other) const; + }; - typedef QList Identities; + typedef QList Identities; - const Identities &identities() const; - void setIdentities(const Identities &); - inline void setIdentities(const Identity &id) { setIdentities(Identities() << id); } + const Identities &identities() const; + void setIdentities(const Identities &); + inline void setIdentities(const Identity &id) { setIdentities(Identities() << id); } - const QList &extensions() const; - void setExtensions(const QList &extlist); - XData registeredExtension(const QString &ns) const; + const QList &extensions() const; + void setExtensions(const QList &extlist); + XData registeredExtension(const QString &ns) const; - // some useful helper functions - static Action string2action(const QString &s); - static QString action2string(const Action a); + // some useful helper functions + static Action string2action(const QString &s); + static QString action2string(const Action a); - DiscoItem & operator= (const DiscoItem &); - DiscoItem(const DiscoItem &); + DiscoItem &operator=(const DiscoItem &); + DiscoItem(const DiscoItem &); - operator AgentItem() const { return toAgentItem(); } - AgentItem toAgentItem() const; - void fromAgentItem(const AgentItem &); + operator AgentItem() const { return toAgentItem(); } + AgentItem toAgentItem() const; + void fromAgentItem(const AgentItem &); - QString capsHash(QCryptographicHash::Algorithm algo) const; + QString capsHash(QCryptographicHash::Algorithm algo) const; - static DiscoItem fromDiscoInfoResult(const QDomElement &x); - QDomElement toDiscoInfoResult(QDomDocument *doc) const; + static DiscoItem fromDiscoInfoResult(const QDomElement &x); + QDomElement toDiscoInfoResult(QDomDocument *doc) const; - private: - QSharedDataPointer d; - }; +private: + QSharedDataPointer d; +}; - bool operator<(const DiscoItem::Identity &a, const DiscoItem::Identity &b); +bool operator<(const DiscoItem::Identity &a, const DiscoItem::Identity &b); } // namespace XMPP #endif // XMPP_DISCOITEM diff --git a/src/xmpp/xmpp-im/xmpp_encryptionhandler.h b/src/xmpp/xmpp-im/xmpp_encryptionhandler.h index 89691f34..21e86c8f 100644 --- a/src/xmpp/xmpp-im/xmpp_encryptionhandler.h +++ b/src/xmpp/xmpp-im/xmpp_encryptionhandler.h @@ -23,12 +23,11 @@ class QDomElement; namespace XMPP { - class EncryptionHandler - { - public: - virtual bool decryptMessageElement(QDomElement &) = 0; - virtual bool encryptMessageElement(QDomElement &) = 0; - }; +class EncryptionHandler { +public: + virtual bool decryptMessageElement(QDomElement &) = 0; + virtual bool encryptMessageElement(QDomElement &) = 0; +}; } // namespace XMPP -#endif //PSI_XMPP_ENCRYPTIONHANDLER_H +#endif // PSI_XMPP_ENCRYPTIONHANDLER_H diff --git a/src/xmpp/xmpp-im/xmpp_features.cpp b/src/xmpp/xmpp-im/xmpp_features.cpp index 81af7ed8..ee2853d9 100644 --- a/src/xmpp/xmpp-im/xmpp_features.cpp +++ b/src/xmpp/xmpp-im/xmpp_features.cpp @@ -29,19 +29,11 @@ using namespace XMPP; -Features::Features() -{ -} +Features::Features() {} -Features::Features(const QStringList &l) -{ - setList(l); -} +Features::Features(const QStringList &l) { setList(l); } -Features::Features(const QSet &s) -{ - setList(s); -} +Features::Features(const QSet &s) { setList(s); } Features::Features(const QString &str) { @@ -51,39 +43,19 @@ Features::Features(const QString &str) setList(l); } -Features::~Features() -{ -} +Features::~Features() {} -QStringList Features::list() const -{ - return _list.toList(); -} +QStringList Features::list() const { return _list.toList(); } -void Features::setList(const QStringList &l) -{ - _list = QSet::fromList(l); -} +void Features::setList(const QStringList &l) { _list = QSet::fromList(l); } -void Features::setList(const QSet &l) -{ - _list = l; -} +void Features::setList(const QSet &l) { _list = l; } -void Features::addFeature(const QString& s) -{ - _list += s; -} +void Features::addFeature(const QString &s) { _list += s; } -bool Features::test(const QStringList &ns) const -{ - return _list.contains(QSet::fromList(ns)); -} +bool Features::test(const QStringList &ns) const { return _list.contains(QSet::fromList(ns)); } -bool Features::test(const QSet &ns) const -{ - return _list.contains(ns); -} +bool Features::test(const QSet &ns) const { return _list.contains(ns); } #define FID_MULTICAST "http://jabber.org/protocol/address" bool Features::hasMulticast() const @@ -206,49 +178,47 @@ bool Features::hasJingleFT() const // custom Psi actions #define FID_ADD "psi:add" -class Features::FeatureName : public QObject -{ +class Features::FeatureName : public QObject { Q_OBJECT public: - FeatureName() - : QObject(QCoreApplication::instance()) + FeatureName() : QObject(QCoreApplication::instance()) { - id2s[FID_Invalid] = tr("ERROR: Incorrect usage of Features class"); - id2s[FID_None] = tr("None"); - id2s[FID_Register] = tr("Register"); - id2s[FID_Search] = tr("Search"); - id2s[FID_Groupchat] = tr("Groupchat"); - id2s[FID_Gateway] = tr("Gateway"); - id2s[FID_Disco] = tr("Service Discovery"); - id2s[FID_VCard] = tr("VCard"); - id2s[FID_AHCommand] = tr("Execute command"); - id2s[FID_QueryVersion] = tr("Query version"); - id2s[FID_MessageCarbons]= tr("Message Carbons"); + id2s[FID_Invalid] = tr("ERROR: Incorrect usage of Features class"); + id2s[FID_None] = tr("None"); + id2s[FID_Register] = tr("Register"); + id2s[FID_Search] = tr("Search"); + id2s[FID_Groupchat] = tr("Groupchat"); + id2s[FID_Gateway] = tr("Gateway"); + id2s[FID_Disco] = tr("Service Discovery"); + id2s[FID_VCard] = tr("VCard"); + id2s[FID_AHCommand] = tr("Execute command"); + id2s[FID_QueryVersion] = tr("Query version"); + id2s[FID_MessageCarbons] = tr("Message Carbons"); // custom Psi actions - id2s[FID_Add] = tr("Add to roster"); + id2s[FID_Add] = tr("Add to roster"); // compute reverse map - //QMap::Iterator it = id2s.begin(); - //for ( ; it != id2s.end(); ++it) + // QMap::Iterator it = id2s.begin(); + // for ( ; it != id2s.end(); ++it) // s2id[it.data()] = it.key(); - id2f[FID_Register] = FID_REGISTER; - id2f[FID_Search] = FID_SEARCH; - id2f[FID_Groupchat] = FID_GROUPCHAT; - id2f[FID_Gateway] = FID_GATEWAY; - id2f[FID_Disco] = FID_DISCO; - id2f[FID_VCard] = FID_VCARD; - id2f[FID_AHCommand] = FID_AHCOMMAND; - id2f[FID_QueryVersion] = FID_QUERYVERSION; - id2f[FID_MessageCarbons]= FID_MESSAGECARBONS; + id2f[FID_Register] = FID_REGISTER; + id2f[FID_Search] = FID_SEARCH; + id2f[FID_Groupchat] = FID_GROUPCHAT; + id2f[FID_Gateway] = FID_GATEWAY; + id2f[FID_Disco] = FID_DISCO; + id2f[FID_VCard] = FID_VCARD; + id2f[FID_AHCommand] = FID_AHCOMMAND; + id2f[FID_QueryVersion] = FID_QUERYVERSION; + id2f[FID_MessageCarbons] = FID_MESSAGECARBONS; // custom Psi actions - id2f[FID_Add] = FID_ADD; + id2f[FID_Add] = FID_ADD; } - //QMap s2id; + // QMap s2id; QMap id2s; QMap id2f; }; @@ -257,25 +227,25 @@ static Features::FeatureName *featureName = nullptr; long Features::id() const { - if ( _list.count() > 1 ) + if (_list.count() > 1) return FID_Invalid; - else if ( hasRegister() ) + else if (hasRegister()) return FID_Register; - else if ( hasSearch() ) + else if (hasSearch()) return FID_Search; - else if ( hasGroupchat() ) + else if (hasGroupchat()) return FID_Groupchat; - else if ( hasGateway() ) + else if (hasGateway()) return FID_Gateway; - else if ( hasDisco() ) + else if (hasDisco()) return FID_Disco; - else if ( hasVCard() ) + else if (hasVCard()) return FID_VCard; - else if ( hasCommand() ) + else if (hasCommand()) return FID_AHCommand; - else if ( test(QStringList(FID_ADD)) ) + else if (test(QStringList(FID_ADD))) return FID_Add; - else if ( hasVersion() ) + else if (hasVersion()) return FID_QueryVersion; return FID_None; @@ -289,7 +259,7 @@ long Features::id(const QString &feature) QString Features::feature(long id) { - if ( !featureName ) + if (!featureName) featureName = new FeatureName(); return featureName->id2f[id]; @@ -303,16 +273,13 @@ Features &Features::operator<<(const QString &feature) QString Features::name(long id) { - if ( !featureName ) + if (!featureName) featureName = new FeatureName(); return featureName->id2s[id]; } -QString Features::name() const -{ - return name(id()); -} +QString Features::name() const { return name(id()); } QString Features::name(const QString &feature) { diff --git a/src/xmpp/xmpp-im/xmpp_features.h b/src/xmpp/xmpp-im/xmpp_features.h index df628a14..c755ae1e 100644 --- a/src/xmpp/xmpp-im/xmpp_features.h +++ b/src/xmpp/xmpp-im/xmpp_features.h @@ -26,87 +26,85 @@ class QString; namespace XMPP { - class Features - { - public: - Features(); - Features(const QStringList &); - Features(const QSet &); - Features(const QString &); - ~Features(); - - QStringList list() const; // actual featurelist - void setList(const QStringList &); - void setList(const QSet &); - void addFeature(const QString&); - - // features - inline bool isEmpty() const { return _list.isEmpty(); } - bool hasRegister() const; - bool hasSearch() const; - bool hasMulticast() const; - bool hasGroupchat() const; - bool hasVoice() const; - bool hasDisco() const; - bool hasChatState() const; - bool hasCommand() const; - bool hasGateway() const; - bool hasVersion() const; - bool hasVCard() const; - bool hasMessageCarbons() const; - bool hasJingleFT() const; - - [[deprecated]] inline bool canRegister() const { return hasRegister(); } - [[deprecated]] inline bool canSearch() const { return hasSearch(); } - [[deprecated]] inline bool canMulticast() const { return hasMulticast(); } - [[deprecated]] inline bool canGroupchat() const { return hasGroupchat(); } - [[deprecated]] inline bool canVoice() const { return hasVoice(); } - [[deprecated]] inline bool canDisco() const { return hasDisco(); } - [[deprecated]] inline bool canChatState() const { return hasChatState(); } - [[deprecated]] inline bool canCommand() const { return hasCommand(); } - [[deprecated]] inline bool isGateway() const { return hasGateway(); } - [[deprecated]] inline bool haveVCard() const { return hasVCard(); } - [[deprecated]] inline bool canMessageCarbons() const { return hasMessageCarbons(); } - - enum FeatureID { - FID_Invalid = -1, - FID_None, - FID_Register, - FID_Search, - FID_Groupchat, - FID_Disco, - FID_Gateway, - FID_VCard, - FID_AHCommand, - FID_QueryVersion, - FID_MessageCarbons, - - // private Psi actions - FID_Add - }; - - // useful functions - inline bool test(const char *ns) const - { return test(QSet() << QLatin1String(ns)); } - bool test(const QStringList &) const; - bool test(const QSet &) const; - - QString name() const; - static QString name(long id); - static QString name(const QString &feature); - - long id() const; - static long id(const QString &feature); - static QString feature(long id); - - Features &operator<<(const QString &feature); - inline bool operator==(const Features &other) - { return _list == other._list; } - - class FeatureName; - private: - QSet _list; +class Features { +public: + Features(); + Features(const QStringList &); + Features(const QSet &); + Features(const QString &); + ~Features(); + + QStringList list() const; // actual featurelist + void setList(const QStringList &); + void setList(const QSet &); + void addFeature(const QString &); + + // features + inline bool isEmpty() const { return _list.isEmpty(); } + bool hasRegister() const; + bool hasSearch() const; + bool hasMulticast() const; + bool hasGroupchat() const; + bool hasVoice() const; + bool hasDisco() const; + bool hasChatState() const; + bool hasCommand() const; + bool hasGateway() const; + bool hasVersion() const; + bool hasVCard() const; + bool hasMessageCarbons() const; + bool hasJingleFT() const; + + [[deprecated]] inline bool canRegister() const { return hasRegister(); } + [[deprecated]] inline bool canSearch() const { return hasSearch(); } + [[deprecated]] inline bool canMulticast() const { return hasMulticast(); } + [[deprecated]] inline bool canGroupchat() const { return hasGroupchat(); } + [[deprecated]] inline bool canVoice() const { return hasVoice(); } + [[deprecated]] inline bool canDisco() const { return hasDisco(); } + [[deprecated]] inline bool canChatState() const { return hasChatState(); } + [[deprecated]] inline bool canCommand() const { return hasCommand(); } + [[deprecated]] inline bool isGateway() const { return hasGateway(); } + [[deprecated]] inline bool haveVCard() const { return hasVCard(); } + [[deprecated]] inline bool canMessageCarbons() const { return hasMessageCarbons(); } + + enum FeatureID { + FID_Invalid = -1, + FID_None, + FID_Register, + FID_Search, + FID_Groupchat, + FID_Disco, + FID_Gateway, + FID_VCard, + FID_AHCommand, + FID_QueryVersion, + FID_MessageCarbons, + + // private Psi actions + FID_Add }; + + // useful functions + inline bool test(const char *ns) const { return test(QSet() << QLatin1String(ns)); } + bool test(const QStringList &) const; + bool test(const QSet &) const; + + QString name() const; + static QString name(long id); + static QString name(const QString &feature); + + long id() const; + static long id(const QString &feature); + static QString feature(long id); + + Features & operator<<(const QString &feature); + inline bool operator==(const Features &other) { return _list == other._list; } + + class FeatureName; + +private: + QSet _list; +}; } // namespace XMPP #endif // XMPP_FEATURES_H diff --git a/src/xmpp/xmpp-im/xmpp_hash.h b/src/xmpp/xmpp-im/xmpp_hash.h index 72b17a36..8f94659a 100644 --- a/src/xmpp/xmpp-im/xmpp_hash.h +++ b/src/xmpp/xmpp-im/xmpp_hash.h @@ -44,12 +44,9 @@ class Hash { LastType = Blake2b512 }; - inline Hash(Type type = Type::Unknown) : - v_type(type) {} - inline Hash(Type type, const QByteArray &data) : - v_type(type), v_data(data) {} - inline Hash(const QStringRef &algo) : - v_type(parseType(algo)) {} + inline Hash(Type type = Type::Unknown) : v_type(type) {} + inline Hash(Type type, const QByteArray &data) : v_type(type), v_data(data) {} + inline Hash(const QStringRef &algo) : v_type(parseType(algo)) {} Hash(const QDomElement &); inline bool operator==(const Hash &other) const { return v_type == other.v_type && v_data == other.v_data; } @@ -65,9 +62,9 @@ class Hash { inline void setData(const QByteArray &d) { v_data = d; } // sets already computed hash inline QByteArray toHex() const { return v_data.toHex(); } inline QByteArray toBase64() const { return v_data.toBase64(); } - inline QString toString() const { return QString("%1+%2").arg(stringType(), QString::fromLatin1(v_data.toHex())); } - bool compute(const QByteArray &); // computes hash from passed data - bool compute(QIODevice *dev); + inline QString toString() const { return QString("%1+%2").arg(stringType(), QString::fromLatin1(v_data.toHex())); } + bool compute(const QByteArray &); // computes hash from passed data + bool compute(QIODevice *dev); QDomElement toXml(QDomDocument *doc) const; static void populateFeatures(XMPP::Features &); diff --git a/src/xmpp/xmpp-im/xmpp_htmlelement.h b/src/xmpp/xmpp-im/xmpp_htmlelement.h index 4fc42dfb..b7dbc1c5 100644 --- a/src/xmpp/xmpp-im/xmpp_htmlelement.h +++ b/src/xmpp/xmpp-im/xmpp_htmlelement.h @@ -24,24 +24,23 @@ class QString; namespace XMPP { - class HTMLElement - { - public: - HTMLElement(); - HTMLElement(const QDomElement &body); - - void setBody(const QDomElement &body); - const QDomElement& body() const; - QString toString(const QString &rootTagName = "body") const; - QString text() const; - void filterOutUnwanted(bool strict = false); - - private: - void filterOutUnwantedRecursive(QDomElement &el, bool strict); - - QDomDocument doc_; - QDomElement body_; - }; +class HTMLElement { +public: + HTMLElement(); + HTMLElement(const QDomElement &body); + + void setBody(const QDomElement &body); + const QDomElement &body() const; + QString toString(const QString &rootTagName = "body") const; + QString text() const; + void filterOutUnwanted(bool strict = false); + +private: + void filterOutUnwantedRecursive(QDomElement &el, bool strict); + + QDomDocument doc_; + QDomElement body_; +}; } // namespace XMPP #endif // XMPP_HTMLELEMENT_H diff --git a/src/xmpp/xmpp-im/xmpp_httpauthrequest.h b/src/xmpp/xmpp-im/xmpp_httpauthrequest.h index 3c9d429a..863eabce 100644 --- a/src/xmpp/xmpp-im/xmpp_httpauthrequest.h +++ b/src/xmpp/xmpp-im/xmpp_httpauthrequest.h @@ -25,31 +25,31 @@ class QDomDocument; class QDomElement; namespace XMPP { - class HttpAuthRequest - { - public: - HttpAuthRequest(const QString &m, const QString &u, const QString &i); - HttpAuthRequest(const QString &m = QString(), const QString &u = QString()); - HttpAuthRequest(const QDomElement &); - - bool isEmpty() const; - - void setMethod(const QString&); - void setUrl(const QString&); - void setId(const QString&); - QString method() const; - QString url() const; - QString id() const; - bool hasId() const; - - QDomElement toXml(QDomDocument &) const; - bool fromXml(const QDomElement &); - - static Stanza::Error denyError; - private: - QString method_, url_, id_; - bool hasId_; - }; +class HttpAuthRequest { +public: + HttpAuthRequest(const QString &m, const QString &u, const QString &i); + HttpAuthRequest(const QString &m = QString(), const QString &u = QString()); + HttpAuthRequest(const QDomElement &); + + bool isEmpty() const; + + void setMethod(const QString &); + void setUrl(const QString &); + void setId(const QString &); + QString method() const; + QString url() const; + QString id() const; + bool hasId() const; + + QDomElement toXml(QDomDocument &) const; + bool fromXml(const QDomElement &); + + static Stanza::Error denyError; + +private: + QString method_, url_, id_; + bool hasId_; +}; } // namespace XMPP #endif // XMPP_AUTHREQUEST_H diff --git a/src/xmpp/xmpp-im/xmpp_ibb.cpp b/src/xmpp/xmpp-im/xmpp_ibb.cpp index 067da527..de3777ad 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.cpp +++ b/src/xmpp/xmpp-im/xmpp_ibb.cpp @@ -25,44 +25,42 @@ #include #include -#define IBB_PACKET_DELAY 0 +#define IBB_PACKET_DELAY 0 using namespace XMPP; -static int num_conn = 0; -static int id_conn = 0; -static const char *IBB_NS = "http://jabber.org/protocol/ibb"; +static int num_conn = 0; +static int id_conn = 0; +static const char *IBB_NS = "http://jabber.org/protocol/ibb"; //---------------------------------------------------------------------------- // IBBConnection //---------------------------------------------------------------------------- -class IBBConnection::Private -{ +class IBBConnection::Private { public: Private() = default; - int state = 0; - quint16 seq = 0; - Jid peer; - QString sid; + int state = 0; + quint16 seq = 0; + Jid peer; + QString sid; IBBManager *m = nullptr; - JT_IBB *j = nullptr; - QString iq_id; - QString stanza; + JT_IBB * j = nullptr; + QString iq_id; + QString stanza; int blockSize = IBBConnection::PacketSize; - //QByteArray recvBuf, sendBuf; + // QByteArray recvBuf, sendBuf; bool closePending, closing; int id; // connection id }; -IBBConnection::IBBConnection(IBBManager *m) - : BSConnection(m) +IBBConnection::IBBConnection(IBBManager *m) : BSConnection(m) { - d = new Private; - d->m = m; - d->j = nullptr; + d = new Private; + d->m = m; + d->j = nullptr; d->blockSize = PacketSize; resetConnection(); @@ -76,18 +74,18 @@ IBBConnection::IBBConnection(IBBManager *m) void IBBConnection::resetConnection(bool clear) { d->m->unlink(this); - d->state = Idle; + d->state = Idle; d->closePending = false; - d->closing = false; - d->seq = 0; + d->closing = false; + d->seq = 0; delete d->j; d->j = nullptr; clearWriteBuffer(); - if(clear) + if (clear) clearReadBuffer(); - setOpenMode(clear || !bytesAvailable()? QIODevice::NotOpen : QIODevice::ReadOnly); + setOpenMode(clear || !bytesAvailable() ? QIODevice::NotOpen : QIODevice::ReadOnly); } IBBConnection::~IBBConnection() @@ -103,10 +101,7 @@ IBBConnection::~IBBConnection() delete d; } -void IBBConnection::setPacketSize(int blockSize) -{ - d->blockSize = blockSize; -} +void IBBConnection::setPacketSize(int blockSize) { d->blockSize = blockSize; } void IBBConnection::connectToJid(const Jid &peer, const QString &sid) { @@ -114,8 +109,8 @@ void IBBConnection::connectToJid(const Jid &peer, const QString &sid) resetConnection(true); d->state = Requesting; - d->peer = peer; - d->sid = sid; + d->peer = peer; + d->sid = sid; #ifdef IBB_DEBUG qDebug("IBBConnection[%d]: initiating request to %s", d->id, qPrintable(peer.full())); @@ -129,12 +124,11 @@ void IBBConnection::connectToJid(const Jid &peer, const QString &sid) void IBBConnection::accept() { - if(d->state != WaitingForAccept) + if (d->state != WaitingForAccept) return; #ifdef IBB_DEBUG - qDebug("IBBConnection[%d]: accepting %s [%s]", d->id, - qPrintable(d->peer.full()), qPrintable(d->sid)); + qDebug("IBBConnection[%d]: accepting %s [%s]", d->id, qPrintable(d->peer.full()), qPrintable(d->sid)); #endif d->m->doAccept(this, d->iq_id); @@ -147,10 +141,10 @@ void IBBConnection::accept() void IBBConnection::close() { - if(d->state == Idle) + if (d->state == Idle) return; - if(d->state == WaitingForAccept) { + if (d->state == WaitingForAccept) { d->m->doReject(this, d->iq_id, Stanza::Error::Forbidden, "Rejected"); resetConnection(); return; @@ -160,12 +154,12 @@ void IBBConnection::close() qDebug("IBBConnection[%d]: closing", d->id); #endif - if(d->state == Active) { + if (d->state == Active) { d->closePending = true; trySend(); // if there is data pending to be written, then pend the closing - if(bytesToWrite() > 0 || d->closing) { + if (bytesToWrite() > 0 || d->closing) { return; } } @@ -173,29 +167,17 @@ void IBBConnection::close() resetConnection(); } -int IBBConnection::state() const -{ - return d->state; -} +int IBBConnection::state() const { return d->state; } -Jid IBBConnection::peer() const -{ - return d->peer; -} +Jid IBBConnection::peer() const { return d->peer; } -QString IBBConnection::sid() const -{ - return d->sid; -} +QString IBBConnection::sid() const { return d->sid; } -BytestreamManager* IBBConnection::manager() const -{ - return d->m; -} +BytestreamManager *IBBConnection::manager() const { return d->m; } bool IBBConnection::isOpen() const { - if(d->state == Active) + if (d->state == Active) return true; else return false; @@ -203,7 +185,7 @@ bool IBBConnection::isOpen() const qint64 IBBConnection::writeData(const char *data, qint64 maxSize) { - if(d->state != Active || d->closePending || d->closing) { + if (d->state != Active || d->closePending || d->closing) { setErrorString("read only"); return 0; } @@ -213,20 +195,18 @@ qint64 IBBConnection::writeData(const char *data, qint64 maxSize) return maxSize; } -void IBBConnection::waitForAccept(const Jid &peer, const QString &iq_id, - const QString &sid, int blockSize, +void IBBConnection::waitForAccept(const Jid &peer, const QString &iq_id, const QString &sid, int blockSize, const QString &stanza) { close(); resetConnection(true); - d->state = WaitingForAccept; - d->peer = peer; - d->iq_id = iq_id; - d->sid = sid; + d->state = WaitingForAccept; + d->peer = peer; + d->iq_id = iq_id; + d->sid = sid; d->blockSize = blockSize; - d->stanza = stanza; - + d->stanza = stanza; } void IBBConnection::takeIncomingData(const IBBData &ibbData) @@ -254,41 +234,37 @@ void IBBConnection::setRemoteClosed() void IBBConnection::ibb_finished() { JT_IBB *j = d->j; - d->j = nullptr; + d->j = nullptr; - if(j->success()) { - if(j->mode() == JT_IBB::ModeRequest) { + if (j->success()) { + if (j->mode() == JT_IBB::ModeRequest) { #ifdef IBB_DEBUG - qDebug("IBBConnection[%d]: %s [%s] accepted.", d->id, - qPrintable(d->peer.full()), qPrintable(d->sid)); + qDebug("IBBConnection[%d]: %s [%s] accepted.", d->id, qPrintable(d->peer.full()), qPrintable(d->sid)); #endif d->state = Active; setOpenMode(QIODevice::ReadWrite); d->m->link(this); emit connected(); - } - else { - if(d->closing) { + } else { + if (d->closing) { resetConnection(); emit delayedCloseFinished(); } - if(bytesToWrite() || d->closePending) + if (bytesToWrite() || d->closePending) QTimer::singleShot(IBB_PACKET_DELAY, this, SLOT(trySend())); emit bytesWritten(j->bytesWritten()); // will delete this connection if no bytes left. } - } - else { - if(j->mode() == JT_IBB::ModeRequest) { + } else { + if (j->mode() == JT_IBB::ModeRequest) { #ifdef IBB_DEBUG qDebug("IBBConnection[%d]: %s refused.", d->id, qPrintable(d->peer.full())); #endif resetConnection(true); setError(ErrRequest); - } - else { + } else { resetConnection(true); setError(ErrData); } @@ -298,24 +274,22 @@ void IBBConnection::ibb_finished() void IBBConnection::trySend() { // if we already have an active task, then don't do anything - if(d->j) + if (d->j) return; QByteArray a = takeWrite(d->blockSize); - if(a.isEmpty()) { + if (a.isEmpty()) { if (!d->closePending) return; // null operation? d->closePending = false; - d->closing = true; + d->closing = true; #ifdef IBB_DEBUG qDebug("IBBConnection[%d]: closing", d->id); #endif - } - else { + } else { #ifdef IBB_DEBUG - qDebug("IBBConnection[%d]: sending [%d] bytes (%d bytes left)", - d->id, a.size(), bytesToWrite()); + qDebug("IBBConnection[%d]: sending [%d] bytes (%d bytes left)", d->id, a.size(), bytesToWrite()); #endif } @@ -323,8 +297,7 @@ void IBBConnection::trySend() connect(d->j, SIGNAL(finished()), SLOT(ibb_finished())); if (d->closing) { d->j->close(d->peer, d->sid); - } - else { + } else { d->j->sendData(d->peer, IBBData(d->sid, d->seq++, a)); } d->j->go(true); @@ -333,10 +306,10 @@ void IBBConnection::trySend() //---------------------------------------------------------------------------- // IBBData //---------------------------------------------------------------------------- -IBBData& IBBData::fromXml(const QDomElement &e) +IBBData &IBBData::fromXml(const QDomElement &e) { - sid = e.attribute("sid"); - seq = e.attribute("seq").toInt(); + sid = e.attribute("sid"); + seq = e.attribute("seq").toInt(); data = QByteArray::fromBase64(e.text().toUtf8()); return *this; } @@ -352,33 +325,27 @@ QDomElement IBBData::toXml(QDomDocument *doc) const //---------------------------------------------------------------------------- // IBBManager //---------------------------------------------------------------------------- -class IBBManager::Private -{ +class IBBManager::Private { public: Private() = default; - Client *client = nullptr; + Client * client = nullptr; IBBConnectionList activeConns; IBBConnectionList incomingConns; - JT_IBB *ibb = nullptr; + JT_IBB * ibb = nullptr; }; -IBBManager::IBBManager(Client *parent) - : BytestreamManager(parent) +IBBManager::IBBManager(Client *parent) : BytestreamManager(parent) { - d = new Private; + d = new Private; d->client = parent; d->ibb = new JT_IBB(d->client->rootTask(), true); - connect(d->ibb, - SIGNAL(incomingRequest(Jid,QString,QString,int,QString)), - SLOT(ibb_incomingRequest(Jid,QString,QString,int,QString))); - connect(d->ibb, - SIGNAL(incomingData(Jid,QString,IBBData,Stanza::Kind)), - SLOT(takeIncomingData(Jid,QString,IBBData,Stanza::Kind))); - connect(d->ibb, - SIGNAL(closeRequest(Jid,QString,QString)), - SLOT(ibb_closeRequest(Jid,QString,QString))); + connect(d->ibb, SIGNAL(incomingRequest(Jid, QString, QString, int, QString)), + SLOT(ibb_incomingRequest(Jid, QString, QString, int, QString))); + connect(d->ibb, SIGNAL(incomingData(Jid, QString, IBBData, Stanza::Kind)), + SLOT(takeIncomingData(Jid, QString, IBBData, Stanza::Kind))); + connect(d->ibb, SIGNAL(closeRequest(Jid, QString, QString)), SLOT(ibb_closeRequest(Jid, QString, QString))); } IBBManager::~IBBManager() @@ -389,28 +356,18 @@ IBBManager::~IBBManager() delete d; } -const char* IBBManager::ns() -{ - return IBB_NS; -} +const char *IBBManager::ns() { return IBB_NS; } -Client *IBBManager::client() const -{ - return d->client; -} +Client *IBBManager::client() const { return d->client; } -BSConnection *IBBManager::createConnection() -{ - return new IBBConnection(this); -} +BSConnection *IBBManager::createConnection() { return new IBBConnection(this); } IBBConnection *IBBManager::takeIncoming() { - return d->incomingConns.isEmpty()? nullptr : d->incomingConns.takeFirst(); + return d->incomingConns.isEmpty() ? nullptr : d->incomingConns.takeFirst(); } -void IBBManager::ibb_incomingRequest(const Jid &from, const QString &id, - const QString &sid, int blockSize, +void IBBManager::ibb_incomingRequest(const Jid &from, const QString &id, const QString &sid, int blockSize, const QString &stanza) { // create a "waiting" connection @@ -420,17 +377,15 @@ void IBBManager::ibb_incomingRequest(const Jid &from, const QString &id, emit incomingReady(); } -void IBBManager::takeIncomingData(const Jid &from, const QString &id, - const IBBData &data, Stanza::Kind sKind) +void IBBManager::takeIncomingData(const Jid &from, const QString &id, const IBBData &data, Stanza::Kind sKind) { IBBConnection *c = findConnection(data.sid, from); - if(!c) { + if (!c) { if (sKind == Stanza::IQ) { d->ibb->respondError(from, id, Stanza::Error::ItemNotFound, "No such stream"); } // TODO imeplement xep-0079 error processing in case of Stanza::Message - } - else { + } else { if (sKind == Stanza::IQ) { d->ibb->respondAck(from, id); } @@ -438,55 +393,40 @@ void IBBManager::takeIncomingData(const Jid &from, const QString &id, } } -void IBBManager::ibb_closeRequest(const Jid &from, const QString &id, - const QString &sid) +void IBBManager::ibb_closeRequest(const Jid &from, const QString &id, const QString &sid) { IBBConnection *c = findConnection(sid, from); - if(!c) { + if (!c) { d->ibb->respondError(from, id, Stanza::Error::ItemNotFound, "No such stream"); - } - else { + } else { d->ibb->respondAck(from, id); c->setRemoteClosed(); } } -bool IBBManager::isAcceptableSID(const XMPP::Jid &jid, const QString&sid) const +bool IBBManager::isAcceptableSID(const XMPP::Jid &jid, const QString &sid) const { return findConnection(sid, jid) == nullptr; } -const char* IBBManager::sidPrefix() const -{ - return "ibb_"; -} +const char *IBBManager::sidPrefix() const { return "ibb_"; } -void IBBManager::link(IBBConnection *c) -{ - d->activeConns.append(c); -} +void IBBManager::link(IBBConnection *c) { d->activeConns.append(c); } -void IBBManager::unlink(IBBConnection *c) -{ - d->activeConns.removeAll(c); -} +void IBBManager::unlink(IBBConnection *c) { d->activeConns.removeAll(c); } IBBConnection *IBBManager::findConnection(const QString &sid, const Jid &peer) const { - foreach(IBBConnection* c, d->activeConns) { - if(c->sid() == sid && (peer.isEmpty() || c->peer().compare(peer)) ) + foreach (IBBConnection *c, d->activeConns) { + if (c->sid() == sid && (peer.isEmpty() || c->peer().compare(peer))) return c; } return nullptr; } -void IBBManager::doAccept(IBBConnection *c, const QString &id) -{ - d->ibb->respondAck(c->peer(), id); -} +void IBBManager::doAccept(IBBConnection *c, const QString &id) { d->ibb->respondAck(c->peer(), id); } -void IBBManager::doReject(IBBConnection *c, const QString &id, - Stanza::Error::ErrorCond cond, const QString &str) +void IBBManager::doReject(IBBConnection *c, const QString &id, Stanza::Error::ErrorCond cond, const QString &str) { d->ibb->respondError(c->peer(), id, cond, str); } @@ -494,39 +434,34 @@ void IBBManager::doReject(IBBConnection *c, const QString &id, //---------------------------------------------------------------------------- // JT_IBB //---------------------------------------------------------------------------- -class JT_IBB::Private -{ +class JT_IBB::Private { public: Private() = default; QDomElement iq; - int mode = 0; - bool serve = false; - Jid to; - QString sid; - int bytesWritten = 0; + int mode = 0; + bool serve = false; + Jid to; + QString sid; + int bytesWritten = 0; }; -JT_IBB::JT_IBB(Task *parent, bool serve) -:Task(parent) +JT_IBB::JT_IBB(Task *parent, bool serve) : Task(parent) { - d = new Private; + d = new Private; d->serve = serve; } -JT_IBB::~JT_IBB() -{ - delete d; -} +JT_IBB::~JT_IBB() { delete d; } void JT_IBB::request(const Jid &to, const QString &sid, int blockSize) { d->mode = ModeRequest; QDomElement iq; - d->to = to; - iq = createIQ(doc(), "set", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS(IBB_NS, "open"); - //genUniqueKey + // genUniqueKey query.setAttribute("sid", sid); query.setAttribute("block-size", blockSize); query.setAttribute("stanza", "iq"); @@ -538,9 +473,9 @@ void JT_IBB::sendData(const Jid &to, const IBBData &ibbData) { d->mode = ModeSendData; QDomElement iq; - d->to = to; + d->to = to; d->bytesWritten = ibbData.data.size(); - iq = createIQ(doc(), "set", to.full(), id()); + iq = createIQ(doc(), "set", to.full(), id()); iq.appendChild(ibbData.toXml(doc())); d->iq = iq; } @@ -549,54 +484,45 @@ void JT_IBB::close(const Jid &to, const QString &sid) { d->mode = ModeSendData; QDomElement iq; - d->to = to; - iq = createIQ(doc(), "set", to.full(), id()); + d->to = to; + iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = iq.appendChild(doc()->createElementNS(IBB_NS, "close")).toElement(); query.setAttribute("sid", sid); d->iq = iq; } -void JT_IBB::respondError(const Jid &to, const QString &id, - Stanza::Error::ErrorCond cond, const QString &text) +void JT_IBB::respondError(const Jid &to, const QString &id, Stanza::Error::ErrorCond cond, const QString &text) { - QDomElement iq = createIQ(doc(), "error", to.full(), id); + QDomElement iq = createIQ(doc(), "error", to.full(), id); Stanza::Error error(Stanza::Error::Cancel, cond, text); iq.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS())); send(iq); } -void JT_IBB::respondAck(const Jid &to, const QString &id) -{ - send( createIQ(doc(), "result", to.full(), id) ); -} +void JT_IBB::respondAck(const Jid &to, const QString &id) { send(createIQ(doc(), "result", to.full(), id)); } -void JT_IBB::onGo() -{ - send(d->iq); -} +void JT_IBB::onGo() { send(d->iq); } bool JT_IBB::take(const QDomElement &e) { - if(d->serve) { + if (d->serve) { // must be an iq-set tag - if(e.tagName() != "iq" || e.attribute("type") != "set") + if (e.tagName() != "iq" || e.attribute("type") != "set") return false; - QString id = e.attribute("id"); - QString from = e.attribute("from"); + QString id = e.attribute("id"); + QString from = e.attribute("from"); QDomElement openEl = e.firstChildElement("open"); if (!openEl.isNull() && openEl.namespaceURI() == IBB_NS) { - emit incomingRequest(Jid(from), id, - openEl.attribute("sid"), - openEl.attribute("block-size").toInt(), - openEl.attribute("stanza")); + emit incomingRequest(Jid(from), id, openEl.attribute("sid"), openEl.attribute("block-size").toInt(), + openEl.attribute("stanza")); return true; } QDomElement dataEl = e.firstChildElement("data"); if (!dataEl.isNull() && dataEl.namespaceURI() == IBB_NS) { IBBData data; - emit incomingData(Jid(from), id, data.fromXml(dataEl), Stanza::IQ); + emit incomingData(Jid(from), id, data.fromXml(dataEl), Stanza::IQ); return true; } QDomElement closeEl = e.firstChildElement("close"); @@ -605,16 +531,14 @@ bool JT_IBB::take(const QDomElement &e) return true; } return false; - } - else { + } else { Jid from(e.attribute("from")); - if(e.attribute("id") != id() || !d->to.compare(from)) + if (e.attribute("id") != id() || !d->to.compare(from)) return false; - if(e.attribute("type") == "result") { + if (e.attribute("type") == "result") { setSuccess(); - } - else { + } else { setError(e); } @@ -622,17 +546,8 @@ bool JT_IBB::take(const QDomElement &e) } } -Jid JT_IBB::jid() const -{ - return d->to; -} +Jid JT_IBB::jid() const { return d->to; } -int JT_IBB::mode() const -{ - return d->mode; -} +int JT_IBB::mode() const { return d->mode; } -int JT_IBB::bytesWritten() const -{ - return d->bytesWritten; -} +int JT_IBB::bytesWritten() const { return d->bytesWritten; } diff --git a/src/xmpp/xmpp-im/xmpp_ibb.h b/src/xmpp/xmpp-im/xmpp_ibb.h index e12df7cc..f3c77d81 100644 --- a/src/xmpp/xmpp-im/xmpp_ibb.h +++ b/src/xmpp/xmpp-im/xmpp_ibb.h @@ -30,151 +30,133 @@ #include namespace XMPP { - class Client; - class IBBManager; - - class IBBData - { - public: - IBBData() : seq(0) {} - IBBData(const QString &sid, quint16 seq, const QByteArray &data) - : sid(sid) - , seq(seq) - , data(data) - {} - - IBBData& fromXml(const QDomElement &e); - QDomElement toXml(QDomDocument *) const; - - QString sid; - quint16 seq; - QByteArray data; - }; - - // this is an IBB connection. use it much like a qsocket - class IBBConnection : public BSConnection - { - Q_OBJECT - public: - static const int PacketSize = 4096; - - enum { ErrRequest, ErrData }; - enum { Idle, Requesting, WaitingForAccept, Active }; - IBBConnection(IBBManager *); - ~IBBConnection(); - - void setPacketSize(int blockSize = IBBConnection::PacketSize); - void connectToJid(const Jid &peer, const QString &sid); - void accept(); - void close(); - - int state() const; - Jid peer() const; - QString sid() const; - BytestreamManager* manager() const; - - bool isOpen() const; - - protected: - qint64 writeData(const char *data, qint64 maxSize); - - signals: - void connected(); - - private slots: - void ibb_finished(); - void trySend(); - - private: - class Private; - Private *d; - - void resetConnection(bool clear=false); - - friend class IBBManager; - void waitForAccept(const Jid &peer, const QString &iq_id, - const QString &sid, int blockSize, - const QString &stanza); - void takeIncomingData(const IBBData &ibbData); - void setRemoteClosed(); - }; - - typedef QList IBBConnectionList; - class IBBManager : public BytestreamManager - { - Q_OBJECT - public: - IBBManager(Client *); - ~IBBManager(); - - static const char* ns(); - Client *client() const; - - bool isAcceptableSID(const Jid &peer, const QString &sid) const; - BSConnection *createConnection(); - IBBConnection *takeIncoming(); - - public slots: - void takeIncomingData(const Jid &from, const QString &id, - const IBBData &data, Stanza::Kind); - - protected: - const char* sidPrefix() const; - - private slots: - void ibb_incomingRequest(const Jid &from, const QString &id, - const QString &sid, int blockSize, - const QString &stanza); - void ibb_closeRequest(const Jid &from, const QString &id, - const QString &sid); - - private: - class Private; - Private *d; - - friend class IBBConnection; - IBBConnection *findConnection(const QString &sid, const Jid &peer="") const; - void link(IBBConnection *); - void unlink(IBBConnection *); - void doAccept(IBBConnection *c, const QString &id); - void doReject(IBBConnection *c, const QString &id, - Stanza::Error::ErrorCond cond, const QString &); - }; - - class JT_IBB : public Task - { - Q_OBJECT - public: - enum { ModeRequest, ModeSendData }; - JT_IBB(Task *, bool serve=false); - ~JT_IBB(); - - void request(const Jid &, const QString &sid, int blockSize = IBBConnection::PacketSize); - void sendData(const Jid &, const IBBData &ibbData); - void close(const Jid &, const QString &sid); - void respondError(const Jid &, const QString &id, - Stanza::Error::ErrorCond cond, const QString &text = ""); - void respondAck(const Jid &to, const QString &id); - - void onGo(); - bool take(const QDomElement &); - - Jid jid() const; - int mode() const; - int bytesWritten() const; - - signals: - void incomingRequest(const Jid &from, const QString &id, - const QString &sid, int blockSize, +class Client; +class IBBManager; + +class IBBData { +public: + IBBData() : seq(0) {} + IBBData(const QString &sid, quint16 seq, const QByteArray &data) : sid(sid), seq(seq), data(data) {} + + IBBData & fromXml(const QDomElement &e); + QDomElement toXml(QDomDocument *) const; + + QString sid; + quint16 seq; + QByteArray data; +}; + +// this is an IBB connection. use it much like a qsocket +class IBBConnection : public BSConnection { + Q_OBJECT +public: + static const int PacketSize = 4096; + + enum { ErrRequest, ErrData }; + enum { Idle, Requesting, WaitingForAccept, Active }; + IBBConnection(IBBManager *); + ~IBBConnection(); + + void setPacketSize(int blockSize = IBBConnection::PacketSize); + void connectToJid(const Jid &peer, const QString &sid); + void accept(); + void close(); + + int state() const; + Jid peer() const; + QString sid() const; + BytestreamManager *manager() const; + + bool isOpen() const; + +protected: + qint64 writeData(const char *data, qint64 maxSize); + +signals: + void connected(); + +private slots: + void ibb_finished(); + void trySend(); + +private: + class Private; + Private *d; + + void resetConnection(bool clear = false); + + friend class IBBManager; + void waitForAccept(const Jid &peer, const QString &iq_id, const QString &sid, int blockSize, const QString &stanza); + void takeIncomingData(const IBBData &ibbData); + void setRemoteClosed(); +}; + +typedef QList IBBConnectionList; +class IBBManager : public BytestreamManager { + Q_OBJECT +public: + IBBManager(Client *); + ~IBBManager(); + + static const char *ns(); + Client * client() const; + + bool isAcceptableSID(const Jid &peer, const QString &sid) const; + BSConnection * createConnection(); + IBBConnection *takeIncoming(); + +public slots: + void takeIncomingData(const Jid &from, const QString &id, const IBBData &data, Stanza::Kind); + +protected: + const char *sidPrefix() const; + +private slots: + void ibb_incomingRequest(const Jid &from, const QString &id, const QString &sid, int blockSize, const QString &stanza); - void incomingData(const Jid &from, const QString &id, - const IBBData &data, Stanza::Kind); - void closeRequest(const Jid &from, const QString &id, const QString &sid); - - private: - class Private; - Private *d; - }; + void ibb_closeRequest(const Jid &from, const QString &id, const QString &sid); + +private: + class Private; + Private *d; + + friend class IBBConnection; + IBBConnection *findConnection(const QString &sid, const Jid &peer = "") const; + void link(IBBConnection *); + void unlink(IBBConnection *); + void doAccept(IBBConnection *c, const QString &id); + void doReject(IBBConnection *c, const QString &id, Stanza::Error::ErrorCond cond, const QString &); +}; + +class JT_IBB : public Task { + Q_OBJECT +public: + enum { ModeRequest, ModeSendData }; + JT_IBB(Task *, bool serve = false); + ~JT_IBB(); + + void request(const Jid &, const QString &sid, int blockSize = IBBConnection::PacketSize); + void sendData(const Jid &, const IBBData &ibbData); + void close(const Jid &, const QString &sid); + void respondError(const Jid &, const QString &id, Stanza::Error::ErrorCond cond, const QString &text = ""); + void respondAck(const Jid &to, const QString &id); + + void onGo(); + bool take(const QDomElement &); + + Jid jid() const; + int mode() const; + int bytesWritten() const; + +signals: + void incomingRequest(const Jid &from, const QString &id, const QString &sid, int blockSize, const QString &stanza); + void incomingData(const Jid &from, const QString &id, const IBBData &data, Stanza::Kind); + void closeRequest(const Jid &from, const QString &id, const QString &sid); + +private: + class Private; + Private *d; +}; } // namespace XMPP #endif // XMPP_IBB_H diff --git a/src/xmpp/xmpp-im/xmpp_liveroster.h b/src/xmpp/xmpp-im/xmpp_liveroster.h index 5cbfb1a8..b6f1e644 100644 --- a/src/xmpp/xmpp-im/xmpp_liveroster.h +++ b/src/xmpp/xmpp-im/xmpp_liveroster.h @@ -24,18 +24,17 @@ #include namespace XMPP { - class Jid; +class Jid; - class LiveRoster : public QList - { - public: - LiveRoster(); - ~LiveRoster(); +class LiveRoster : public QList { +public: + LiveRoster(); + ~LiveRoster(); - void flagAllForDelete(); - LiveRoster::Iterator find(const Jid &, bool compareRes=true); - LiveRoster::ConstIterator find(const Jid &, bool compareRes=true) const; - }; + void flagAllForDelete(); + LiveRoster::Iterator find(const Jid &, bool compareRes = true); + LiveRoster::ConstIterator find(const Jid &, bool compareRes = true) const; +}; } // namespace XMPP #endif // XMPP_LIVEROSTER_H diff --git a/src/xmpp/xmpp-im/xmpp_liverosteritem.h b/src/xmpp/xmpp-im/xmpp_liverosteritem.h index a9c71091..9ff16adf 100644 --- a/src/xmpp/xmpp-im/xmpp_liverosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_liverosteritem.h @@ -24,34 +24,33 @@ #include "xmpp_status.h" namespace XMPP { - class LiveRosterItem : public RosterItem - { - public: - LiveRosterItem(const Jid &j=""); - LiveRosterItem(const RosterItem &); - ~LiveRosterItem(); - LiveRosterItem& operator=(const LiveRosterItem& other) = default; - - void setRosterItem(const RosterItem &); - - ResourceList & resourceList(); - ResourceList::Iterator priority(); - - const ResourceList & resourceList() const; - ResourceList::ConstIterator priority() const; - - bool isAvailable() const; - const Status & lastUnavailableStatus() const; - bool flagForDelete() const; - - void setLastUnavailableStatus(const Status &); - void setFlagForDelete(bool); - - private: - ResourceList v_resourceList; - Status v_lastUnavailableStatus; - bool v_flagForDelete; - }; +class LiveRosterItem : public RosterItem { +public: + LiveRosterItem(const Jid &j = ""); + LiveRosterItem(const RosterItem &); + ~LiveRosterItem(); + LiveRosterItem &operator=(const LiveRosterItem &other) = default; + + void setRosterItem(const RosterItem &); + + ResourceList & resourceList(); + ResourceList::Iterator priority(); + + const ResourceList & resourceList() const; + ResourceList::ConstIterator priority() const; + + bool isAvailable() const; + const Status &lastUnavailableStatus() const; + bool flagForDelete() const; + + void setLastUnavailableStatus(const Status &); + void setFlagForDelete(bool); + +private: + ResourceList v_resourceList; + Status v_lastUnavailableStatus; + bool v_flagForDelete; +}; } // namespace XMPP #endif // XMPP_LIVEROSTERITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_message.h b/src/xmpp/xmpp-im/xmpp_message.h index bc0d407b..457c6e2a 100644 --- a/src/xmpp/xmpp-im/xmpp_message.h +++ b/src/xmpp/xmpp-im/xmpp_message.h @@ -34,210 +34,203 @@ class QDateTime; class QString; namespace XMPP { - class BoBData; - class HTMLElement; - class HttpAuthRequest; - class IBBData; - class Jid; - class PubSubItem; - class PubSubRetraction; - class XData; - - typedef QMap StringMap; - - typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent, - ComposingEvent, CancelEvent } MsgEvent; - - class Message - { - public: - enum CarbonDir : quint8 { - NoCarbon, - Received, // other party messages are sent to another own client - Sent // own messages are sent from other clients - }; - - // XEP-0334 - enum ProcessingHint { - NoPermanentStore = 1, - NoStore = 2, - NoCopy = 4, - Store = 8 - }; - Q_DECLARE_FLAGS(ProcessingHints, ProcessingHint) - - struct StanzaId { - Jid by; - QString id; - }; - - Message(); - Message(const Jid &to); - Message(const Message &from); - Message & operator=(const Message &from); - ~Message(); - bool operator ==(const Message &from) const; - inline bool isNull() const { return d == nullptr; } - - Jid to() const; - Jid from() const; - QString id() const; - QString type() const; - QString lang() const; - QString subject(const QString &lang=QString()) const; - QString subject(const QLocale &lang) const; - StringMap subjectMap() const; - QString body(const QString &lang="") const; - QString body(const QLocale &lang) const; - QString thread() const; - Stanza::Error error() const; - - void setTo(const Jid &j); - void setFrom(const Jid &j); - void setId(const QString &s); - void setType(const QString &s); - void setLang(const QString &s); - void setSubject(const QString &s, const QString &lang=""); - void setBody(const QString &s, const QString &lang=""); - void setThread(const QString &s, bool send = false); - void setError(const Stanza::Error &err); - - // XEP-0060 - QString pubsubNode() const; - QList pubsubItems() const; - QList pubsubRetractions() const; - - // XEP-0091 - QDateTime timeStamp() const; - void setTimeStamp(const QDateTime &ts, bool send = false); - - // XEP-0071 - HTMLElement html(const QString &lang="") const; - void setHTML(const HTMLElement &s, const QString &lang=""); - bool containsHTML() const; - - // XEP-0066 - UrlList urlList() const; - void urlAdd(const Url &u); - void urlsClear(); - void setUrlList(const UrlList &list); - - // XEP-0022 - QString eventId() const; - void setEventId(const QString& id); - bool containsEvents() const; - bool containsEvent(MsgEvent e) const; - void addEvent(MsgEvent e); - - // XEP-0085 - ChatState chatState() const; - void setChatState(ChatState); - - // XEP-0184 - MessageReceipt messageReceipt() const; - void setMessageReceipt(MessageReceipt); - QString messageReceiptId() const; - void setMessageReceiptId(const QString &s); - - // XEP-0027 - QString xsigned() const; - void setXSigned(const QString &s); - QString xencrypted() const; - void setXEncrypted(const QString &s); - - // XEP-0033 - AddressList addresses() const; - AddressList findAddresses(Address::Type t) const; - void addAddress(const Address &a); - void clearAddresses(); - void setAddresses(const AddressList &list); - - // XEP-144 - RosterExchangeItems rosterExchangeItems() const; - void setRosterExchangeItems(const RosterExchangeItems&); - - // XEP-172 - void setNick(const QString&); - QString nick() const; - - // XEP-0070 - void setHttpAuthRequest(const HttpAuthRequest&); - HttpAuthRequest httpAuthRequest() const; - - // XEP-0004 - void setForm(const XData&); - XData getForm() const; - - // XEP-xxxx SXE - void setSxe(const QDomElement&); - QDomElement sxe() const; - - // XEP-0231 bits of binary - void addBoBData(const BoBData &); - QList bobDataList() const; - - // XEP-0047 ibb - IBBData ibbData() const; - - // XEP-0280 Message Carbons - void setDisabledCarbons(bool disabled); - bool isDisabledCarbons() const; - void setCarbonDirection(CarbonDir); - CarbonDir carbonDirection() const; - - // XEP-0297 - void setForwardedFrom(const Jid &jid); - Jid forwardedFrom() const; - - // XEP-0308 - QString replaceId() const; - void setReplaceId(const QString& id); - - // XEP-0334 - void setProcessingHints(const ProcessingHints &hints); - ProcessingHints processingHints() const; - - // MUC - void addMUCStatus(int); - QList getMUCStatuses() const; - void addMUCInvite(const MUCInvite&); - QList mucInvites() const; - void setMUCDecline(const MUCDecline&); - MUCDecline mucDecline() const; - QString mucPassword() const; - void setMUCPassword(const QString&); - bool hasMUCUser() const; - - // XEP-0359 - StanzaId stanzaId() const; - void setStanzaId(const StanzaId &id); - QString originId() const; - void setOriginId(const QString &id); - - // XEP-0385 and XEP-0372 - QList references() const; - void addReference(const Reference &r); - void setReferences(const QList &r); - - // Obsolete invitation - QString invite() const; - void setInvite(const QString &s); - - // for compatibility. delete me later - bool spooled() const; - void setSpooled(bool); - bool wasEncrypted() const; - void setWasEncrypted(bool); - - Stanza toStanza(Stream *stream) const; - bool fromStanza(const Stanza &s); - bool fromStanza(const Stanza &s, int tzoffset); - bool fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOffset); - - private: - class Private; - QExplicitlySharedDataPointer d; +class BoBData; +class HTMLElement; +class HttpAuthRequest; +class IBBData; +class Jid; +class PubSubItem; +class PubSubRetraction; +class XData; + +typedef QMap StringMap; + +typedef enum { OfflineEvent, DeliveredEvent, DisplayedEvent, ComposingEvent, CancelEvent } MsgEvent; + +class Message { +public: + enum CarbonDir : quint8 { + NoCarbon, + Received, // other party messages are sent to another own client + Sent // own messages are sent from other clients }; + + // XEP-0334 + enum ProcessingHint { NoPermanentStore = 1, NoStore = 2, NoCopy = 4, Store = 8 }; + Q_DECLARE_FLAGS(ProcessingHints, ProcessingHint) + + struct StanzaId { + Jid by; + QString id; + }; + + Message(); + Message(const Jid &to); + Message(const Message &from); + Message &operator=(const Message &from); + ~Message(); + bool operator==(const Message &from) const; + inline bool isNull() const { return d == nullptr; } + + Jid to() const; + Jid from() const; + QString id() const; + QString type() const; + QString lang() const; + QString subject(const QString &lang = QString()) const; + QString subject(const QLocale &lang) const; + StringMap subjectMap() const; + QString body(const QString &lang = "") const; + QString body(const QLocale &lang) const; + QString thread() const; + Stanza::Error error() const; + + void setTo(const Jid &j); + void setFrom(const Jid &j); + void setId(const QString &s); + void setType(const QString &s); + void setLang(const QString &s); + void setSubject(const QString &s, const QString &lang = ""); + void setBody(const QString &s, const QString &lang = ""); + void setThread(const QString &s, bool send = false); + void setError(const Stanza::Error &err); + + // XEP-0060 + QString pubsubNode() const; + QList pubsubItems() const; + QList pubsubRetractions() const; + + // XEP-0091 + QDateTime timeStamp() const; + void setTimeStamp(const QDateTime &ts, bool send = false); + + // XEP-0071 + HTMLElement html(const QString &lang = "") const; + void setHTML(const HTMLElement &s, const QString &lang = ""); + bool containsHTML() const; + + // XEP-0066 + UrlList urlList() const; + void urlAdd(const Url &u); + void urlsClear(); + void setUrlList(const UrlList &list); + + // XEP-0022 + QString eventId() const; + void setEventId(const QString &id); + bool containsEvents() const; + bool containsEvent(MsgEvent e) const; + void addEvent(MsgEvent e); + + // XEP-0085 + ChatState chatState() const; + void setChatState(ChatState); + + // XEP-0184 + MessageReceipt messageReceipt() const; + void setMessageReceipt(MessageReceipt); + QString messageReceiptId() const; + void setMessageReceiptId(const QString &s); + + // XEP-0027 + QString xsigned() const; + void setXSigned(const QString &s); + QString xencrypted() const; + void setXEncrypted(const QString &s); + + // XEP-0033 + AddressList addresses() const; + AddressList findAddresses(Address::Type t) const; + void addAddress(const Address &a); + void clearAddresses(); + void setAddresses(const AddressList &list); + + // XEP-144 + RosterExchangeItems rosterExchangeItems() const; + void setRosterExchangeItems(const RosterExchangeItems &); + + // XEP-172 + void setNick(const QString &); + QString nick() const; + + // XEP-0070 + void setHttpAuthRequest(const HttpAuthRequest &); + HttpAuthRequest httpAuthRequest() const; + + // XEP-0004 + void setForm(const XData &); + XData getForm() const; + + // XEP-xxxx SXE + void setSxe(const QDomElement &); + QDomElement sxe() const; + + // XEP-0231 bits of binary + void addBoBData(const BoBData &); + QList bobDataList() const; + + // XEP-0047 ibb + IBBData ibbData() const; + + // XEP-0280 Message Carbons + void setDisabledCarbons(bool disabled); + bool isDisabledCarbons() const; + void setCarbonDirection(CarbonDir); + CarbonDir carbonDirection() const; + + // XEP-0297 + void setForwardedFrom(const Jid &jid); + Jid forwardedFrom() const; + + // XEP-0308 + QString replaceId() const; + void setReplaceId(const QString &id); + + // XEP-0334 + void setProcessingHints(const ProcessingHints &hints); + ProcessingHints processingHints() const; + + // MUC + void addMUCStatus(int); + QList getMUCStatuses() const; + void addMUCInvite(const MUCInvite &); + QList mucInvites() const; + void setMUCDecline(const MUCDecline &); + MUCDecline mucDecline() const; + QString mucPassword() const; + void setMUCPassword(const QString &); + bool hasMUCUser() const; + + // XEP-0359 + StanzaId stanzaId() const; + void setStanzaId(const StanzaId &id); + QString originId() const; + void setOriginId(const QString &id); + + // XEP-0385 and XEP-0372 + QList references() const; + void addReference(const Reference &r); + void setReferences(const QList &r); + + // Obsolete invitation + QString invite() const; + void setInvite(const QString &s); + + // for compatibility. delete me later + bool spooled() const; + void setSpooled(bool); + bool wasEncrypted() const; + void setWasEncrypted(bool); + + Stanza toStanza(Stream *stream) const; + bool fromStanza(const Stanza &s); + bool fromStanza(const Stanza &s, int tzoffset); + bool fromStanza(const Stanza &s, bool useTimeZoneOffset, int timeZoneOffset); + +private: + class Private; + QExplicitlySharedDataPointer d; +}; } // namespace XMPP Q_DECLARE_OPERATORS_FOR_FLAGS(XMPP::Message::ProcessingHints) diff --git a/src/xmpp/xmpp-im/xmpp_muc.h b/src/xmpp/xmpp-im/xmpp_muc.h index 7b4cfd54..770f5ff3 100644 --- a/src/xmpp/xmpp-im/xmpp_muc.h +++ b/src/xmpp/xmpp-im/xmpp_muc.h @@ -26,109 +26,105 @@ #include namespace XMPP { - class MUCItem - { - public: - enum Affiliation { UnknownAffiliation, Outcast, NoAffiliation, Member, Admin, Owner }; - enum Role { UnknownRole, NoRole, Visitor, Participant, Moderator }; - - MUCItem(Role = UnknownRole, Affiliation = UnknownAffiliation); - MUCItem(const QDomElement&); - - void setNick(const QString&); - void setJid(const Jid&); - void setAffiliation(Affiliation); - void setRole(Role); - void setActor(const Jid&); - void setReason(const QString&); - - const QString& nick() const; - const Jid& jid() const; // real jid of muc participant - Affiliation affiliation() const; - Role role() const; - const Jid& actor() const; - const QString& reason() const; - - void fromXml(const QDomElement&); - QDomElement toXml(QDomDocument&); - - bool operator==(const MUCItem& o); - - private: - QString nick_; - Jid jid_, actor_; - Affiliation affiliation_; - Role role_; - QString reason_; - }; - - class MUCInvite - { - public: - MUCInvite(); - MUCInvite(const QDomElement&); - MUCInvite(const Jid& to, const QString& reason = QString()); - - const Jid& to() const; - void setTo(const Jid&); - const Jid& from() const; - void setFrom(const Jid&); - const QString& reason() const; - void setReason(const QString&); - bool cont() const; - void setCont(bool); - - void fromXml(const QDomElement&); - QDomElement toXml(QDomDocument&) const; - bool isNull() const; - - private: - Jid to_, from_; - QString reason_, password_; - bool cont_; - }; - - class MUCDecline - { - public: - MUCDecline(); - MUCDecline(const Jid& to, const QString& reason); - MUCDecline(const QDomElement&); - - const Jid& to() const; - void setTo(const Jid&); - const Jid& from() const; - void setFrom(const Jid&); - const QString& reason() const; - void setReason(const QString&); - - void fromXml(const QDomElement&); - QDomElement toXml(QDomDocument&) const; - bool isNull() const; - - private: - Jid to_, from_; - QString reason_; - }; - - class MUCDestroy - { - public: - MUCDestroy(); - MUCDestroy(const QDomElement&); - - const Jid& jid() const; - void setJid(const Jid&); - const QString& reason() const; - void setReason(const QString&); - - void fromXml(const QDomElement&); - QDomElement toXml(QDomDocument&) const; - - private: - Jid jid_; - QString reason_; - }; +class MUCItem { +public: + enum Affiliation { UnknownAffiliation, Outcast, NoAffiliation, Member, Admin, Owner }; + enum Role { UnknownRole, NoRole, Visitor, Participant, Moderator }; + + MUCItem(Role = UnknownRole, Affiliation = UnknownAffiliation); + MUCItem(const QDomElement &); + + void setNick(const QString &); + void setJid(const Jid &); + void setAffiliation(Affiliation); + void setRole(Role); + void setActor(const Jid &); + void setReason(const QString &); + + const QString &nick() const; + const Jid & jid() const; // real jid of muc participant + Affiliation affiliation() const; + Role role() const; + const Jid & actor() const; + const QString &reason() const; + + void fromXml(const QDomElement &); + QDomElement toXml(QDomDocument &); + + bool operator==(const MUCItem &o); + +private: + QString nick_; + Jid jid_, actor_; + Affiliation affiliation_; + Role role_; + QString reason_; +}; + +class MUCInvite { +public: + MUCInvite(); + MUCInvite(const QDomElement &); + MUCInvite(const Jid &to, const QString &reason = QString()); + + const Jid & to() const; + void setTo(const Jid &); + const Jid & from() const; + void setFrom(const Jid &); + const QString &reason() const; + void setReason(const QString &); + bool cont() const; + void setCont(bool); + + void fromXml(const QDomElement &); + QDomElement toXml(QDomDocument &) const; + bool isNull() const; + +private: + Jid to_, from_; + QString reason_, password_; + bool cont_; +}; + +class MUCDecline { +public: + MUCDecline(); + MUCDecline(const Jid &to, const QString &reason); + MUCDecline(const QDomElement &); + + const Jid & to() const; + void setTo(const Jid &); + const Jid & from() const; + void setFrom(const Jid &); + const QString &reason() const; + void setReason(const QString &); + + void fromXml(const QDomElement &); + QDomElement toXml(QDomDocument &) const; + bool isNull() const; + +private: + Jid to_, from_; + QString reason_; +}; + +class MUCDestroy { +public: + MUCDestroy(); + MUCDestroy(const QDomElement &); + + const Jid & jid() const; + void setJid(const Jid &); + const QString &reason() const; + void setReason(const QString &); + + void fromXml(const QDomElement &); + QDomElement toXml(QDomDocument &) const; + +private: + Jid jid_; + QString reason_; +}; } // namespace XMPP #endif // XMPP_MUC_H diff --git a/src/xmpp/xmpp-im/xmpp_pubsubitem.h b/src/xmpp/xmpp-im/xmpp_pubsubitem.h index 3d2a6853..ca6d6de6 100644 --- a/src/xmpp/xmpp-im/xmpp_pubsubitem.h +++ b/src/xmpp/xmpp-im/xmpp_pubsubitem.h @@ -23,18 +23,17 @@ #include namespace XMPP { - class PubSubItem - { - public: - PubSubItem(); - PubSubItem(const QString& id, const QDomElement& payload); - const QString& id() const; - const QDomElement& payload() const; +class PubSubItem { +public: + PubSubItem(); + PubSubItem(const QString &id, const QDomElement &payload); + const QString & id() const; + const QDomElement &payload() const; - private: - QString id_; - QDomElement payload_; - }; +private: + QString id_; + QDomElement payload_; +}; } // namespace XMPP #endif // XMPP_PUBSUBITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_pubsubretraction.h b/src/xmpp/xmpp-im/xmpp_pubsubretraction.h index 8a0c463e..1a2023a5 100644 --- a/src/xmpp/xmpp-im/xmpp_pubsubretraction.h +++ b/src/xmpp/xmpp-im/xmpp_pubsubretraction.h @@ -23,16 +23,15 @@ #include namespace XMPP { - class PubSubRetraction - { - public: - PubSubRetraction(); - PubSubRetraction(const QString& id); - const QString& id() const; +class PubSubRetraction { +public: + PubSubRetraction(); + PubSubRetraction(const QString &id); + const QString &id() const; - private: - QString id_; - }; +private: + QString id_; +}; } // namespace XMPP #endif // XMPP_PUBSUBRETRACTION_H diff --git a/src/xmpp/xmpp-im/xmpp_receipts.h b/src/xmpp/xmpp-im/xmpp_receipts.h index 1554eb72..3220e292 100644 --- a/src/xmpp/xmpp-im/xmpp_receipts.h +++ b/src/xmpp/xmpp-im/xmpp_receipts.h @@ -21,11 +21,7 @@ #define XMPP_RECEIPTS_H namespace XMPP { - typedef enum { - ReceiptNone, - ReceiptRequest, - ReceiptReceived - } MessageReceipt; +typedef enum { ReceiptNone, ReceiptRequest, ReceiptReceived } MessageReceipt; } // namespace XMPP #endif // XMPP_RECEIPTS_H diff --git a/src/xmpp/xmpp-im/xmpp_reference.cpp b/src/xmpp/xmpp-im/xmpp_reference.cpp index d610b8b3..59a94cb5 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.cpp +++ b/src/xmpp/xmpp-im/xmpp_reference.cpp @@ -21,44 +21,32 @@ using namespace XMPP; -#define D() (d? d:(d=new Private)) +#define D() (d ? d : (d = new Private)) const QString XMPP::MEDIASHARING_NS(QStringLiteral("urn:xmpp:sims:1")); const QString XMPP::REFERENCE_NS(QStringLiteral("urn:xmpp:reference:0")); -class Reference::Private : public QSharedData -{ +class Reference::Private : public QSharedData { public: Reference::Type type; - QString uri; - QString anchor; - int begin = -1; - int end = -1; - MediaSharing mediaSharing; + QString uri; + QString anchor; + int begin = -1; + int end = -1; + MediaSharing mediaSharing; }; -Reference::Reference() -{ - -} +Reference::Reference() {} -Reference::Reference(Type type, const QString &uri) : - d(new Private) +Reference::Reference(Type type, const QString &uri) : d(new Private) { d->type = type; - d->uri = uri; -} - -Reference::~Reference() -{ - + d->uri = uri; } -Reference::Reference(const Reference &other) : - d(other.d) -{ +Reference::~Reference() {} -} +Reference::Reference(const Reference &other) : d(other.d) {} Reference &Reference::operator=(const Reference &other) { @@ -66,58 +54,34 @@ Reference &Reference::operator=(const Reference &other) return *this; } -Reference::Type Reference::type() const -{ - return d->type; -} +Reference::Type Reference::type() const { return d->type; } -const QString &Reference::uri() const -{ - return d->uri; -} +const QString &Reference::uri() const { return d->uri; } void Reference::setRange(int begin, int end) { D()->begin = begin; - d->end = end; + d->end = end; } -int Reference::begin() const -{ - return d->begin; -} +int Reference::begin() const { return d->begin; } -int Reference::end() const -{ - return d->end; -} +int Reference::end() const { return d->end; } -const QString &Reference::anchor() const -{ - return d->anchor; -} +const QString &Reference::anchor() const { return d->anchor; } -void Reference::setAnchor(const QString &anchor) -{ - D()->anchor = anchor; -} +void Reference::setAnchor(const QString &anchor) { D()->anchor = anchor; } -void Reference::setMediaSharing(const MediaSharing &ms) -{ - D()->mediaSharing = ms; -} +void Reference::setMediaSharing(const MediaSharing &ms) { D()->mediaSharing = ms; } -const MediaSharing &Reference::mediaSharing() const -{ - return d->mediaSharing; -} +const MediaSharing &Reference::mediaSharing() const { return d->mediaSharing; } bool Reference::fromXml(const QDomElement &e) { - QString type = e.attribute(QString::fromLatin1("type")); - QString uri = e.attribute(QString::fromLatin1("uri")); - QString begin = e.attribute(QString::fromLatin1("begin")); - QString end = e.attribute(QString::fromLatin1("end")); + QString type = e.attribute(QString::fromLatin1("type")); + QString uri = e.attribute(QString::fromLatin1("uri")); + QString begin = e.attribute(QString::fromLatin1("begin")); + QString end = e.attribute(QString::fromLatin1("end")); QString anchor = e.attribute(QString::fromLatin1("anchor")); if (type.isEmpty() || uri.isEmpty()) { @@ -132,12 +96,12 @@ bool Reference::fromXml(const QDomElement &e) else return false; - int beginN = -1, endN = -1; + int beginN = -1, endN = -1; bool ok; - if (!begin.isEmpty() && !(beginN = begin.toInt(&ok),ok)) + if (!begin.isEmpty() && !(beginN = begin.toInt(&ok), ok)) return false; - if (!end.isEmpty() && !(endN = end.toInt(&ok),ok)) + if (!end.isEmpty() && !(endN = end.toInt(&ok), ok)) return false; if (beginN >= 0 && endN >= 0 && endN < beginN) @@ -146,10 +110,10 @@ bool Reference::fromXml(const QDomElement &e) if ((endN >= 0 && beginN == -1) || (endN == -1 && beginN >= 0)) return false; - auto msEl = e.firstChildElement("media-sharing"); + auto msEl = e.firstChildElement("media-sharing"); MediaSharing ms; if (msEl.namespaceURI() == MEDIASHARING_NS) { - auto fileEl = msEl.firstChildElement("file"); + auto fileEl = msEl.firstChildElement("file"); auto sourcesEl = msEl.firstChildElement("sources"); if (sourcesEl.isNull() || fileEl.isNull() || fileEl.namespaceURI() != XMPP::Jingle::FileTransfer::NS) return false; @@ -172,11 +136,11 @@ bool Reference::fromXml(const QDomElement &e) return false; } - D()->type = t; - d->uri = uri; - d->begin = beginN; - d->end = endN; - d->anchor = anchor; + D()->type = t; + d->uri = uri; + d->begin = beginN; + d->end = endN; + d->anchor = anchor; d->mediaSharing = ms; return true; @@ -189,15 +153,16 @@ QDomElement Reference::toXml(QDomDocument *doc) const } auto root = doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference")); root.setAttribute(QString::fromLatin1("uri"), d->uri); - root.setAttribute(QString::fromLatin1("type"), QString(d->type == Reference::Mention? "mention": "data")); + root.setAttribute(QString::fromLatin1("type"), QString(d->type == Reference::Mention ? "mention" : "data")); if (d->mediaSharing.file.isValid() && d->mediaSharing.sources.count()) { auto msEl = doc->createElementNS(MEDIASHARING_NS, QString::fromLatin1("media-sharing")); root.appendChild(msEl); msEl.appendChild(d->mediaSharing.file.toXml(doc)); auto sourcesEl = msEl.appendChild(doc->createElement(QString::fromLatin1("sources"))).toElement(); - for (auto const &s: d->mediaSharing.sources) { - auto sEl = sourcesEl.appendChild(doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference"))).toElement(); + for (auto const &s : d->mediaSharing.sources) { + auto sEl = sourcesEl.appendChild(doc->createElementNS(REFERENCE_NS, QString::fromLatin1("reference"))) + .toElement(); sEl.setAttribute(QString::fromLatin1("uri"), s); sEl.setAttribute(QString::fromLatin1("type"), QString::fromLatin1("data")); } @@ -214,4 +179,3 @@ QDomElement Reference::toXml(QDomDocument *doc) const return root; } - diff --git a/src/xmpp/xmpp-im/xmpp_reference.h b/src/xmpp/xmpp-im/xmpp_reference.h index 9cf3e5ac..8a3aaace 100644 --- a/src/xmpp/xmpp-im/xmpp_reference.h +++ b/src/xmpp/xmpp-im/xmpp_reference.h @@ -26,54 +26,52 @@ #include namespace XMPP { - extern const QString MEDIASHARING_NS; - extern const QString REFERENCE_NS; +extern const QString MEDIASHARING_NS; +extern const QString REFERENCE_NS; - class MediaSharing - { - public: - Jingle::FileTransfer::File file; - QStringList sources; +class MediaSharing { +public: + Jingle::FileTransfer::File file; + QStringList sources; - inline bool isValid() const { return file.isValid(); } - }; + inline bool isValid() const { return file.isValid(); } +}; - class Reference - { - public: - enum Type : char { +class Reference { +public: + enum Type : char { - Mention, - Data - }; + Mention, + Data + }; - Reference(); - Reference(Type type, const QString &uri); - ~Reference(); - Reference(const Reference &other); - Reference &operator=(const Reference &other); + Reference(); + Reference(Type type, const QString &uri); + ~Reference(); + Reference(const Reference &other); + Reference &operator=(const Reference &other); - bool isValid() const { return d != nullptr; } - Type type() const; - const QString &uri() const; + bool isValid() const { return d != nullptr; } + Type type() const; + const QString &uri() const; - void setRange(int begin, int end); - int begin() const; - int end() const; + void setRange(int begin, int end); + int begin() const; + int end() const; - const QString &anchor() const; - void setAnchor(const QString &anchor); + const QString &anchor() const; + void setAnchor(const QString &anchor); - void setMediaSharing(const MediaSharing &); - const MediaSharing &mediaSharing() const; + void setMediaSharing(const MediaSharing &); + const MediaSharing &mediaSharing() const; - bool fromXml(const QDomElement &e); - QDomElement toXml(QDomDocument *) const; + bool fromXml(const QDomElement &e); + QDomElement toXml(QDomDocument *) const; - private: - class Private; - QSharedDataPointer d; - }; +private: + class Private; + QSharedDataPointer d; +}; } // namespace XMPP #endif // XMPPREFERENCE_H diff --git a/src/xmpp/xmpp-im/xmpp_resource.h b/src/xmpp/xmpp-im/xmpp_resource.h index 7fd1b6b1..10a045f4 100644 --- a/src/xmpp/xmpp-im/xmpp_resource.h +++ b/src/xmpp/xmpp-im/xmpp_resource.h @@ -24,22 +24,21 @@ #include namespace XMPP { - class Resource - { - public: - Resource(const QString &name="", const Status &s=Status()); - - const QString & name() const; - int priority() const; - const Status & status() const; - - void setName(const QString &); - void setStatus(const Status &); - - private: - QString v_name; - Status v_status; - }; +class Resource { +public: + Resource(const QString &name = "", const Status &s = Status()); + + const QString &name() const; + int priority() const; + const Status & status() const; + + void setName(const QString &); + void setStatus(const Status &); + +private: + QString v_name; + Status v_status; +}; } // namespace XMPP #endif // XMPP_RESOURCE_H diff --git a/src/xmpp/xmpp-im/xmpp_resourcelist.h b/src/xmpp/xmpp-im/xmpp_resourcelist.h index ae41bad2..93003581 100644 --- a/src/xmpp/xmpp-im/xmpp_resourcelist.h +++ b/src/xmpp/xmpp-im/xmpp_resourcelist.h @@ -26,18 +26,17 @@ class QString; namespace XMPP { - class ResourceList : public QList - { - public: - ResourceList(); - ~ResourceList(); - - ResourceList::Iterator find(const QString &); - ResourceList::Iterator priority(); - - ResourceList::ConstIterator find(const QString &) const; - ResourceList::ConstIterator priority() const; - }; +class ResourceList : public QList { +public: + ResourceList(); + ~ResourceList(); + + ResourceList::Iterator find(const QString &); + ResourceList::Iterator priority(); + + ResourceList::ConstIterator find(const QString &) const; + ResourceList::ConstIterator priority() const; +}; } // namespace XMPP #endif // XMPP_RESOURCELIST_H diff --git a/src/xmpp/xmpp-im/xmpp_roster.h b/src/xmpp/xmpp-im/xmpp_roster.h index 9572e580..669f2aff 100644 --- a/src/xmpp/xmpp-im/xmpp_roster.h +++ b/src/xmpp/xmpp-im/xmpp_roster.h @@ -27,21 +27,20 @@ class QDomDocument; class QDomElement; namespace XMPP { - class Jid; +class Jid; - class Roster : public QList - { - public: - Roster(); - ~Roster(); +class Roster : public QList { +public: + Roster(); + ~Roster(); - Roster::Iterator find(const Jid &); - Roster::ConstIterator find(const Jid &) const; + Roster::Iterator find(const Jid &); + Roster::ConstIterator find(const Jid &) const; - private: - class RosterPrivate; - RosterPrivate *d = nullptr; - }; +private: + class RosterPrivate; + RosterPrivate *d = nullptr; +}; } // namespace XMPP #endif // XMPP_ROSTER_H diff --git a/src/xmpp/xmpp-im/xmpp_rosteritem.h b/src/xmpp/xmpp-im/xmpp_rosteritem.h index 3fe1e486..e773ce33 100644 --- a/src/xmpp/xmpp-im/xmpp_rosteritem.h +++ b/src/xmpp/xmpp-im/xmpp_rosteritem.h @@ -25,58 +25,56 @@ #include namespace XMPP { - class Subscription - { - public: - enum SubType { None, To, From, Both, Remove }; +class Subscription { +public: + enum SubType { None, To, From, Both, Remove }; - Subscription(SubType type=None); + Subscription(SubType type = None); - int type() const; + int type() const; - QString toString() const; - bool fromString(const QString &); + QString toString() const; + bool fromString(const QString &); - private: - SubType value; - }; +private: + SubType value; +}; - class RosterItem - { - public: - RosterItem(const Jid &jid=""); - RosterItem(const RosterItem &item); - virtual ~RosterItem(); - RosterItem& operator=(const RosterItem& other) = default; +class RosterItem { +public: + RosterItem(const Jid &jid = ""); + RosterItem(const RosterItem &item); + virtual ~RosterItem(); + RosterItem &operator=(const RosterItem &other) = default; - const Jid & jid() const; - const QString & name() const; - const QStringList & groups() const; - const Subscription & subscription() const; - const QString & ask() const; - bool isPush() const; - bool inGroup(const QString &) const; + const Jid & jid() const; + const QString & name() const; + const QStringList & groups() const; + const Subscription &subscription() const; + const QString & ask() const; + bool isPush() const; + bool inGroup(const QString &) const; - virtual void setJid(const Jid &); - void setName(const QString &); - void setGroups(const QStringList &); - void setSubscription(const Subscription &); - void setAsk(const QString &); - void setIsPush(bool); - bool addGroup(const QString &); - bool removeGroup(const QString &); + virtual void setJid(const Jid &); + void setName(const QString &); + void setGroups(const QStringList &); + void setSubscription(const Subscription &); + void setAsk(const QString &); + void setIsPush(bool); + bool addGroup(const QString &); + bool removeGroup(const QString &); - QDomElement toXml(QDomDocument *) const; - bool fromXml(const QDomElement &); + QDomElement toXml(QDomDocument *) const; + bool fromXml(const QDomElement &); - private: - Jid v_jid; - QString v_name; - QStringList v_groups; - Subscription v_subscription; - QString v_ask; - bool v_push; - }; +private: + Jid v_jid; + QString v_name; + QStringList v_groups; + Subscription v_subscription; + QString v_ask; + bool v_push; +}; } // namespace XMPP #endif // XMPP_ROSTERITEM_H diff --git a/src/xmpp/xmpp-im/xmpp_rosterx.h b/src/xmpp/xmpp-im/xmpp_rosterx.h index 70a3f9de..98669d65 100644 --- a/src/xmpp/xmpp-im/xmpp_rosterx.h +++ b/src/xmpp/xmpp-im/xmpp_rosterx.h @@ -28,37 +28,37 @@ class QDomElement; namespace XMPP { - class Stanza; +class Stanza; - class RosterExchangeItem - { - public: - enum Action { Add, Delete, Modify }; +class RosterExchangeItem { +public: + enum Action { Add, Delete, Modify }; - RosterExchangeItem(const Jid& jid, const QString& name = "", const QStringList& groups = QStringList(), Action = Add); - RosterExchangeItem(const QDomElement&); + RosterExchangeItem(const Jid &jid, const QString &name = "", const QStringList &groups = QStringList(), + Action = Add); + RosterExchangeItem(const QDomElement &); - const Jid& jid() const; - Action action() const; - const QString& name() const; - const QStringList& groups() const; - bool isNull() const; + const Jid & jid() const; + Action action() const; + const QString & name() const; + const QStringList &groups() const; + bool isNull() const; - void setJid(const Jid&); - void setAction(Action); - void setName(const QString&); - void setGroups(const QStringList&); + void setJid(const Jid &); + void setAction(Action); + void setName(const QString &); + void setGroups(const QStringList &); - QDomElement toXml(Stanza&) const; - void fromXml(const QDomElement&); + QDomElement toXml(Stanza &) const; + void fromXml(const QDomElement &); - private: - Jid jid_; - QString name_; - QStringList groups_; - Action action_; - }; - typedef QList RosterExchangeItems; +private: + Jid jid_; + QString name_; + QStringList groups_; + Action action_; +}; +typedef QList RosterExchangeItems; } // namespace XMPP #endif // XMPP_ROSTERX_H diff --git a/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp b/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp index 72e5ee83..e9dc3589 100644 --- a/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp +++ b/src/xmpp/xmpp-im/xmpp_serverinfomanager.cpp @@ -23,14 +23,12 @@ #include "xmpp_tasks.h" namespace XMPP { -ServerInfoManager::ServerInfoManager(Client* client): - QObject(client), - _client(client), - _canMessageCarbons(false) +ServerInfoManager::ServerInfoManager(Client *client) : QObject(client), _client(client), _canMessageCarbons(false) { deinitialize(); // NOTE we can use this class for any server, but for this we shouldn't use roster signal here - connect(_client, SIGNAL(rosterRequestFinished(bool, int, const QString &)), SLOT(initialize()), Qt::QueuedConnection); + connect(_client, SIGNAL(rosterRequestFinished(bool, int, const QString &)), SLOT(initialize()), + Qt::QueuedConnection); } void ServerInfoManager::reset() @@ -59,39 +57,31 @@ void ServerInfoManager::deinitialize() emit featuresChanged(); } -const QString& ServerInfoManager::multicastService() const -{ - return _multicastService; -} +const QString &ServerInfoManager::multicastService() const { return _multicastService; } -bool ServerInfoManager::hasPEP() const -{ - return _hasPEP; -} +bool ServerInfoManager::hasPEP() const { return _hasPEP; } -bool ServerInfoManager::canMessageCarbons() const -{ - return _canMessageCarbons; -} +bool ServerInfoManager::canMessageCarbons() const { return _canMessageCarbons; } void ServerInfoManager::queryServicesList() { _servicesListState = ST_InProgress; - auto jtitems = new JT_DiscoItems(_client->rootTask()); - connect(jtitems, &JT_DiscoItems::finished, this, [=]() - { - _servicesInfo.clear(); // - if (jtitems->success()) { - _servicesListState = ST_Ready; - for (const auto &item: jtitems->items()) { - _servicesInfo.insert(item.jid().full(), {ST_NotQueried, item, QMap()}); + auto jtitems = new JT_DiscoItems(_client->rootTask()); + connect( + jtitems, &JT_DiscoItems::finished, this, + [=]() { + _servicesInfo.clear(); // + if (jtitems->success()) { + _servicesListState = ST_Ready; + for (const auto &item : jtitems->items()) { + _servicesInfo.insert(item.jid().full(), { ST_NotQueried, item, QMap() }); + } + } else { + _servicesListState = ST_Failed; } - } - else { - _servicesListState = ST_Failed; - } - checkPendingServiceQueries(); - }, Qt::QueuedConnection); + checkPendingServiceQueries(); + }, + Qt::QueuedConnection); jtitems->get(_client->jid().domain()); jtitems->go(true); } @@ -103,7 +93,7 @@ void ServerInfoManager::checkPendingServiceQueries() if (_servicesListState == ST_Failed) { const auto sqs = _serviceQueries; _serviceQueries.clear(); - for (const auto &q: sqs) { + for (const auto &q : sqs) { q.callback(QList()); } } @@ -112,13 +102,13 @@ void ServerInfoManager::checkPendingServiceQueries() // services list is ready here and we can start checking it and sending disco#info to not cached entries auto sqIt = _serviceQueries.begin(); - while(sqIt != _serviceQueries.end()) { + while (sqIt != _serviceQueries.end()) { // populate services to query for this service request if (!sqIt->servicesToQueryDefined) { sqIt->spareServicesToQuery.clear(); // grep all suitble service jids. moving forward preferred ones - QMapIterator si(_servicesInfo); + QMapIterator si(_servicesInfo); while (si.hasNext()) { si.next(); if (!sqIt->nameHint.isEmpty()) { @@ -145,33 +135,31 @@ void ServerInfoManager::checkPendingServiceQueries() // now `sqIt->servicesToQuery` definitely has something to check. maybe some info is already in cache. bool hasInProgress = false; - auto jidIt = sqIt->servicesToQuery.begin(); - //bool foundMatch = false; + auto jidIt = sqIt->servicesToQuery.begin(); + // bool foundMatch = false; while (jidIt != sqIt->servicesToQuery.end()) { auto si = _servicesInfo.find(*jidIt); // find cached service corresponding to one of matched jids if (si == _servicesInfo.end() || si->state == ST_Failed) { // the map was updated after the first service list request, or info request failed. sqIt->servicesToQuery.erase(jidIt++); continue; - } else - if (si->state == ST_Ready) { // disco info finished successfully for current jid from `servicesToQuery` + } else if (si->state + == ST_Ready) { // disco info finished successfully for current jid from `servicesToQuery` bool foundIdentity = sqIt->category.isEmpty() && sqIt->type.isEmpty(); if (!foundIdentity) { - for (auto &i: si->item.identities()) { - if ((sqIt->category.isEmpty() || sqIt->category == i.category) && - (sqIt->type.isEmpty() || sqIt->type == i.type)) - { + for (auto &i : si->item.identities()) { + if ((sqIt->category.isEmpty() || sqIt->category == i.category) + && (sqIt->type.isEmpty() || sqIt->type == i.type)) { foundIdentity = true; break; } } } - if (foundIdentity && (sqIt->features.isEmpty() || std::accumulate(sqIt->features.constBegin(), - sqIt->features.constEnd(), false, - [&si](bool a, const QSet &b) { - return a || si->item.features().test(b); - }))) - { + if (foundIdentity + && (sqIt->features.isEmpty() + || std::accumulate( + sqIt->features.constBegin(), sqIt->features.constEnd(), false, + [&si](bool a, const QSet &b) { return a || si->item.features().test(b); }))) { sqIt->result.append(si->item); if (sqIt->options & SQ_FinishOnFirstMatch) { break; @@ -185,14 +173,14 @@ void ServerInfoManager::checkPendingServiceQueries() Q_ASSERT(si->state == ST_NotQueried || si->state == ST_InProgress); hasInProgress = true; if (si->state == ST_NotQueried) { // if not queried then let's query - si->state = ST_InProgress; + si->state = ST_InProgress; auto jtinfo = new JT_DiscoInfo(_client->rootTask()); - connect(jtinfo, &DiscoInfoTask::finished, this, [this, jtinfo](){ + connect(jtinfo, &DiscoInfoTask::finished, this, [this, jtinfo]() { auto si = _servicesInfo.find(jtinfo->jid().full()); if (si != _servicesInfo.end()) { if (jtinfo->success()) { si.value().state = ST_Ready; - si.value().item = jtinfo->item(); + si.value().item = jtinfo->item(); } else { si.value().state = ST_Failed; } @@ -206,7 +194,8 @@ void ServerInfoManager::checkPendingServiceQueries() } if (sqIt->result.isEmpty() && !hasInProgress && !sqIt->spareServicesToQuery.isEmpty()) { - // we don't check sqIt->servicesToQuery.isEmpty() since it comes from other conditions (sqIt->result.isEmpty() && !hasInProgress) + // we don't check sqIt->servicesToQuery.isEmpty() since it comes from other conditions + // (sqIt->result.isEmpty() && !hasInProgress) sqIt->servicesToQuery = sqIt->spareServicesToQuery; sqIt->spareServicesToQuery.clear(); continue; // continue with the same ServiceQuery but with different jids list @@ -217,7 +206,7 @@ void ServerInfoManager::checkPendingServiceQueries() // if nothing in progress then we have full result set or nothing found even in spare list if (forceFinish || !hasInProgress) { // self explanatory auto callback = std::move(sqIt->callback); - auto result = sqIt->result; + auto result = sqIt->result; _serviceQueries.erase(sqIt++); callback(result); } else { @@ -239,8 +228,9 @@ void ServerInfoManager::appendQuery(const ServiceQuery &q) } } -void ServerInfoManager::queryServiceInfo(const QString &category, const QString &type, const QList> &features, - const QRegExp &nameHint, SQOptions options, std::function &items)> callback) +void ServerInfoManager::queryServiceInfo(const QString &category, const QString &type, + const QList> &features, const QRegExp &nameHint, + SQOptions options, std::function &items)> callback) { appendQuery(ServiceQuery(type, category, features, nameHint, options, std::move(callback))); } @@ -275,14 +265,15 @@ void ServerInfoManager::disco_finished() // Identities DiscoItem::Identities is = jt->item().identities(); - foreach(DiscoItem::Identity i, is) { + foreach (DiscoItem::Identity i, is) { if (i.category == "pubsub" && i.type == "pep") _hasPEP = true; } - for (const auto &x: jt->item().extensions()) { - if (x.type() == XData::Data_Result && x.registrarType() == QLatin1String("http://jabber.org/network/serverinfo")) { - for (const auto &f: x.fields()) { + for (const auto &x : jt->item().extensions()) { + if (x.type() == XData::Data_Result + && x.registrarType() == QLatin1String("http://jabber.org/network/serverinfo")) { + for (const auto &f : x.fields()) { if (f.type() == XData::Field::Field_ListMulti) { _extraServerInfo.insert(f.var(), f.value()); // covers XEP-0157 } diff --git a/src/xmpp/xmpp-im/xmpp_serverinfomanager.h b/src/xmpp/xmpp-im/xmpp_serverinfomanager.h index ebbaeeef..2fabf153 100644 --- a/src/xmpp/xmpp-im/xmpp_serverinfomanager.h +++ b/src/xmpp/xmpp-im/xmpp_serverinfomanager.h @@ -34,8 +34,7 @@ class Client; class Features; class Jid; -class ServerInfoManager : public QObject -{ +class ServerInfoManager : public QObject { Q_OBJECT public: enum SQOption { @@ -47,50 +46,42 @@ class ServerInfoManager : public QObject private: struct ServiceQuery { - const QString type; - const QString category; - const QList> features; - const QRegExp nameHint; - const SQOptions options; + const QString type; + const QString category; + const QList> features; + const QRegExp nameHint; + const SQOptions options; const std::function &item)> callback; - QLinkedList servicesToQuery; + QLinkedList servicesToQuery; QLinkedList spareServicesToQuery; // usually a fallback when the above is not matched - bool servicesToQueryDefined = false; - QList result; - - ServiceQuery(const QString &type, - const QString &category, - const QList> &features, - const QRegExp &nameHint, - const SQOptions &options, - const std::function &item)> &&callback - ) : - type(type), category(category), features(features), nameHint(nameHint), options(options), callback(callback) - { } + bool servicesToQueryDefined = false; + QList result; + + ServiceQuery(const QString &type, const QString &category, const QList> &features, + const QRegExp &nameHint, const SQOptions &options, + const std::function &item)> &&callback) : + type(type), + category(category), features(features), nameHint(nameHint), options(options), callback(callback) + { + } }; - enum ServicesState { - ST_NotQueried, - ST_InProgress, - ST_Ready, - ST_Failed - }; + enum ServicesState { ST_NotQueried, ST_InProgress, ST_Ready, ST_Failed }; struct ServiceInfo { - ServicesState state; - DiscoItem item; - QMap meta; + ServicesState state; + DiscoItem item; + QMap meta; }; public: + ServerInfoManager(XMPP::Client *client); - ServerInfoManager(XMPP::Client* client); - - const QString& multicastService() const; - bool hasPEP() const; - inline const Features &features() const { return _features; } - bool canMessageCarbons() const; - inline const QMap &extraServerInfo() const { return _extraServerInfo; } + const QString & multicastService() const; + bool hasPEP() const; + inline const Features & features() const { return _features; } + bool canMessageCarbons() const; + inline const QMap &extraServerInfo() const { return _extraServerInfo; } /* empty type/category/features/nameHint means it won't be checked. @@ -109,10 +100,10 @@ class ServerInfoManager : public QObject nameHint = (http\..*|) // search for service name like http.jabber.ru Result: disco info for upload.jabber.ru will be returned. */ - void queryServiceInfo(const QString &category, const QString &type, const QList> &features, - const QRegExp &nameHint, SQOptions options, - std::function &items)> callback); - void setServiceMeta(const Jid &service, const QString &key, const QVariant &value); + void queryServiceInfo(const QString &category, const QString &type, const QList> &features, + const QRegExp &nameHint, SQOptions options, + std::function &items)> callback); + void setServiceMeta(const Jid &service, const QString &key, const QVariant &value); QVariant serviceMeta(const Jid &service, const QString &key); signals: @@ -131,15 +122,16 @@ private slots: void appendQuery(const ServiceQuery &q); private: - XMPP::Client* _client = nullptr; - CapsSpec _caps; - Features _features; - QString _multicastService; - QMap _extraServerInfo; // XEP-0128, XEP-0157 + XMPP::Client * _client = nullptr; + CapsSpec _caps; + Features _features; + QString _multicastService; + QMap _extraServerInfo; // XEP-0128, XEP-0157 std::list _serviceQueries; // a storage of pending requests as result of `queryService` call - ServicesState _servicesListState = ST_NotQueried; - QMap _servicesInfo; // all the diso#info requests for services of this server jid=>(state,info) + ServicesState _servicesListState = ST_NotQueried; + QMap + _servicesInfo; // all the diso#info requests for services of this server jid=>(state,info) bool _featuresRequested; bool _hasPEP; diff --git a/src/xmpp/xmpp-im/xmpp_status.h b/src/xmpp/xmpp-im/xmpp_status.h index f3caa4a8..3208f425 100644 --- a/src/xmpp/xmpp-im/xmpp_status.h +++ b/src/xmpp/xmpp-im/xmpp_status.h @@ -68,13 +68,7 @@ class CapsSpec { class Status { public: - enum Type { Offline, - Online, - Away, - XA, - DND, - Invisible, - FFC }; + enum Type { Offline, Online, Away, XA, DND, Invisible, FFC }; Status(const QString &show = QString(), const QString &status = QString(), int priority = 0, bool available = true); Status(Type type, const QString &status = QString(), int priority = 0); diff --git a/src/xmpp/xmpp-im/xmpp_subsets.cpp b/src/xmpp/xmpp-im/xmpp_subsets.cpp index 5bdf0831..5925bbab 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.cpp +++ b/src/xmpp/xmpp-im/xmpp_subsets.cpp @@ -25,21 +25,20 @@ using namespace XMPP; static QLatin1String xmlns_ns_rsm("http://jabber.org/protocol/rsm"); -class SubsetsClientManager::Private -{ +class SubsetsClientManager::Private { public: enum QueryType { None, Count, First, Last, Next, Previous, Index }; struct { QueryType type; - int max; - int index; + int max; + int index; } query; struct { - int count; - int index; - bool first; - bool last; - int itemsCount; + int count; + int index; + bool first; + bool last; + int itemsCount; QString firstId; QString lastId; } result; @@ -47,12 +46,12 @@ class SubsetsClientManager::Private void resetResult() { - result.count = -1; - result.index = -1; - result.first = false; - result.last = false; + result.count = -1; + result.index = -1; + result.first = false; + result.last = false; result.itemsCount = 0; - valid = false; + valid = false; } QDomElement mainElement(QDomDocument *doc) @@ -86,16 +85,16 @@ class SubsetsClientManager::Private bool updateFromElement(const QDomElement &el) { - valid = true; - bool ok = false; - QDomElement e = el.firstChildElement(QLatin1String("count")); + valid = true; + bool ok = false; + QDomElement e = el.firstChildElement(QLatin1String("count")); if (!e.isNull()) result.count = tagContent(e).toInt(&ok); if (!ok || result.count < 0) result.count = -1; result.index = -1; - e = el.firstChildElement(QLatin1String("first")); + e = el.firstChildElement(QLatin1String("first")); if (!e.isNull()) { result.firstId = tagContent(e); if (result.firstId.isEmpty()) @@ -103,8 +102,7 @@ class SubsetsClientManager::Private int i = e.attribute(QLatin1String("index")).toInt(&ok); if (ok && i >= 0) result.index = i; - } - else + } else result.firstId = ""; e = el.firstChildElement(QLatin1String("last")); @@ -112,18 +110,17 @@ class SubsetsClientManager::Private result.lastId = tagContent(e); if (result.lastId.isEmpty()) valid = false; - } - else + } else result.lastId = ""; if (result.firstId.isEmpty() != result.lastId.isEmpty()) valid = false; - result.first = query.type == First || result.index == 0 || - (result.itemsCount == 0 && result.index == -1 && (query.type == Last || query.type == Previous)); - result.last = query.type == Last || - (result.index != -1 && result.count != -1 && result.count - result.itemsCount <= result.index) || - (result.itemsCount == 0 && result.index == -1 && (query.type == First || query.type == Next)); + result.first = query.type == First || result.index == 0 + || (result.itemsCount == 0 && result.index == -1 && (query.type == Last || query.type == Previous)); + result.last = query.type == Last + || (result.index != -1 && result.count != -1 && result.count - result.itemsCount <= result.index) + || (result.itemsCount == 0 && result.index == -1 && (query.type == First || query.type == Next)); if (result.firstId.isEmpty() && result.lastId.isEmpty()) { switch (query.type) { case Previous: @@ -147,10 +144,7 @@ SubsetsClientManager::SubsetsClientManager() reset(); } -SubsetsClientManager::~SubsetsClientManager() -{ - delete d; -} +SubsetsClientManager::~SubsetsClientManager() { delete d; } void SubsetsClientManager::reset() { @@ -162,30 +156,15 @@ void SubsetsClientManager::reset() d->resetResult(); } -bool SubsetsClientManager::isValid() const -{ - return d->valid; -} +bool SubsetsClientManager::isValid() const { return d->valid; } -bool SubsetsClientManager::isFirst() const -{ - return d->result.first; -} +bool SubsetsClientManager::isFirst() const { return d->result.first; } -bool SubsetsClientManager::isLast() const -{ - return d->result.last; -} +bool SubsetsClientManager::isLast() const { return d->result.last; } -int SubsetsClientManager::count() const -{ - return d->result.count; -} +int SubsetsClientManager::count() const { return d->result.count; } -void SubsetsClientManager::setMax(int max) -{ - d->query.max = max; -} +void SubsetsClientManager::setMax(int max) { d->query.max = max; } QDomElement SubsetsClientManager::findElement(const QDomElement &el, bool child) { diff --git a/src/xmpp/xmpp-im/xmpp_subsets.h b/src/xmpp/xmpp-im/xmpp_subsets.h index d1f9b8e5..4e6bbd24 100644 --- a/src/xmpp/xmpp-im/xmpp_subsets.h +++ b/src/xmpp/xmpp-im/xmpp_subsets.h @@ -23,34 +23,33 @@ #include namespace XMPP { - class SubsetsClientManager - { - public: - SubsetsClientManager(); - ~SubsetsClientManager(); - - void reset(); - bool isValid() const; - bool isFirst() const; - bool isLast() const; - int count() const; - void setMax(int max); - - void getCount(); - void getFirst(); - void getNext(); - void getLast(); - void getPrevious(); - void getByIndex(); - - static QDomElement findElement(const QDomElement &el, bool child); - bool updateFromElement(const QDomElement &el, int itemsCount); - QDomElement makeQueryElement(QDomDocument *doc) const; - - private: - class Private; - Private *d; - }; +class SubsetsClientManager { +public: + SubsetsClientManager(); + ~SubsetsClientManager(); + + void reset(); + bool isValid() const; + bool isFirst() const; + bool isLast() const; + int count() const; + void setMax(int max); + + void getCount(); + void getFirst(); + void getNext(); + void getLast(); + void getPrevious(); + void getByIndex(); + + static QDomElement findElement(const QDomElement &el, bool child); + bool updateFromElement(const QDomElement &el, int itemsCount); + QDomElement makeQueryElement(QDomDocument *doc) const; + +private: + class Private; + Private *d; +}; } // namespace XMPP #endif // XMPP_SUBSETS_H diff --git a/src/xmpp/xmpp-im/xmpp_task.cpp b/src/xmpp/xmpp-im/xmpp_task.cpp index 8b65987d..aa86cc9f 100644 --- a/src/xmpp/xmpp-im/xmpp_task.cpp +++ b/src/xmpp/xmpp-im/xmpp_task.cpp @@ -28,36 +28,33 @@ using namespace XMPP; -class Task::TaskPrivate -{ +class Task::TaskPrivate { public: TaskPrivate() = default; - QString id; - bool success = false; - int statusCode = 0; - QString statusString; + QString id; + bool success = false; + int statusCode = 0; + QString statusString; XMPP::Stanza::Error error; - Client *client = nullptr; - bool insig = false; - bool deleteme = false; - bool autoDelete = false; - bool done = false; - int timeout = 0; + Client * client = nullptr; + bool insig = false; + bool deleteme = false; + bool autoDelete = false; + bool done = false; + int timeout = 0; }; -Task::Task(Task *parent) -:QObject(parent) +Task::Task(Task *parent) : QObject(parent) { init(); d->client = parent->client(); - d->id = client()->genUniqueId(); + d->id = client()->genUniqueId(); connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected())); } -Task::Task(Client *parent, bool) -:QObject(nullptr) +Task::Task(Client *parent, bool) : QObject(nullptr) { init(); @@ -65,71 +62,38 @@ Task::Task(Client *parent, bool) connect(d->client, SIGNAL(disconnected()), SLOT(clientDisconnected())); } -Task::~Task() -{ - delete d; -} +Task::~Task() { delete d; } void Task::init() { - d = new TaskPrivate; - d->success = false; - d->insig = false; - d->deleteme = false; + d = new TaskPrivate; + d->success = false; + d->insig = false; + d->deleteme = false; d->autoDelete = false; - d->done = false; - d->timeout = DEFAULT_TIMEOUT; + d->done = false; + d->timeout = DEFAULT_TIMEOUT; } -Task *Task::parent() const -{ - return (Task *)QObject::parent(); -} +Task *Task::parent() const { return (Task *)QObject::parent(); } -Client *Task::client() const -{ - return d->client; -} +Client *Task::client() const { return d->client; } -QDomDocument *Task::doc() const -{ - return client()->doc(); -} +QDomDocument *Task::doc() const { return client()->doc(); } -QString Task::id() const -{ - return d->id; -} +QString Task::id() const { return d->id; } -bool Task::success() const -{ - return d->success; -} +bool Task::success() const { return d->success; } -int Task::statusCode() const -{ - return d->statusCode; -} +int Task::statusCode() const { return d->statusCode; } -const QString & Task::statusString() const -{ - return d->statusString; -} +const QString &Task::statusString() const { return d->statusString; } -const Stanza::Error &Task::error() const -{ - return d->error; -} +const Stanza::Error &Task::error() const { return d->error; } -void Task::setTimeout(int seconds) const -{ - d->timeout = seconds; -} +void Task::setTimeout(int seconds) const { d->timeout = seconds; } -int Task::timeout() -{ - return d->timeout; -} +int Task::timeout() { return d->timeout; } void Task::go(bool autoDelete) { @@ -140,8 +104,7 @@ void Task::go(bool autoDelete) if (autoDelete) { deleteLater(); } - } - else { + } else { onGo(); if (d->timeout) { QTimer::singleShot(d->timeout * 1000, this, SLOT(timeoutFinished())); @@ -155,13 +118,13 @@ bool Task::take(const QDomElement &x) // pass along the xml Task *t; - for(QObjectList::ConstIterator it = p.begin(); it != p.end(); ++it) { + for (QObjectList::ConstIterator it = p.begin(); it != p.end(); ++it) { QObject *obj = *it; - if(!obj->inherits("XMPP::Task")) + if (!obj->inherits("XMPP::Task")) continue; - t = static_cast(obj); - if(t->take(x)) // don't check for done here. it will hurt server tasks + t = static_cast(obj); + if (t->take(x)) // don't check for done here. it will hurt server tasks return true; } @@ -170,23 +133,21 @@ bool Task::take(const QDomElement &x) void Task::safeDelete() { - if(d->deleteme) + if (d->deleteme) return; d->deleteme = true; - if(!d->insig) + if (!d->insig) deleteLater(); } -void Task::onGo() -{ -} +void Task::onGo() {} void Task::onDisconnect() { - if(!d->done) { - d->success = false; - d->statusCode = ErrDisc; + if (!d->done) { + d->success = false; + d->statusCode = ErrDisc; d->statusString = tr("Disconnected"); // delay this so that tasks that react don't block the shutdown @@ -198,24 +159,21 @@ void Task::onDisconnect() void Task::onTimeout() { - if(!d->done) { - d->success = false; - d->statusCode = ErrTimeout; + if (!d->done) { + d->success = false; + d->statusCode = ErrTimeout; d->statusString = tr("Request timed out"); done(); } } -void Task::send(const QDomElement &x) -{ - client()->send(x); -} +void Task::send(const QDomElement &x) { client()->send(x); } void Task::setSuccess(int code, const QString &str) { - if(!d->done) { - d->success = true; - d->statusCode = code; + if (!d->done) { + d->success = true; + d->statusCode = code; d->statusString = str; done(); } @@ -223,17 +181,17 @@ void Task::setSuccess(int code, const QString &str) void Task::setError(const QDomElement &e) { - if(!d->done) { + if (!d->done) { d->success = false; QDomElement tag = e.firstChildElement("error"); - if(tag.isNull()) + if (tag.isNull()) return; XMPP::Stanza::Error err; err.fromXml(tag, d->client->streamBaseNS()); - d->error = err; - d->statusCode = err.code(); + d->error = err; + d->statusCode = err.code(); d->statusString = err.toString(); done(); } @@ -241,9 +199,9 @@ void Task::setError(const QDomElement &e) void Task::setError(int code, const QString &str) { - if(!d->done) { - d->success = false; - d->statusCode = code; + if (!d->done) { + d->success = false; + d->statusCode = code; d->statusString = str; done(); } @@ -251,25 +209,22 @@ void Task::setError(int code, const QString &str) void Task::done() { - if(d->done || d->insig) + if (d->done || d->insig) return; d->done = true; - if(d->autoDelete) + if (d->autoDelete) d->deleteme = true; d->insig = true; emit finished(); d->insig = false; - if(d->deleteme) + if (d->deleteme) deleteLater(); } -void Task::clientDisconnected() -{ - onDisconnect(); -} +void Task::clientDisconnected() { onDisconnect(); } void Task::timeoutFinished() { @@ -287,10 +242,7 @@ void Task::debug(const char *fmt, ...) debug(str); } -void Task::debug(const QString &str) -{ - client()->debug(QString("%1: ").arg(metaObject()->className()) + str); -} +void Task::debug(const QString &str) { client()->debug(QString("%1: ").arg(metaObject()->className()) + str); } /** * \brief verifiys a stanza is a IQ reply for this task @@ -304,42 +256,42 @@ void Task::debug(const QString &str) * \param id the id of the send IQ * \param xmlns the expected namespace if the reply (if non empty) * \return true if it's a valid reply -*/ + */ bool Task::iqVerify(const QDomElement &x, const Jid &to, const QString &id, const QString &xmlns) { - if(x.tagName() != QStringLiteral("iq")) + if (x.tagName() != QStringLiteral("iq")) return false; Jid from(x.attribute(QStringLiteral("from"))); - Jid local = client()->jid(); + Jid local = client()->jid(); Jid server = client()->host(); // empty 'from' ? - if(from.isEmpty()) { + if (from.isEmpty()) { // allowed if we are querying the server - if(!to.isEmpty() && !to.compare(server)) + if (!to.isEmpty() && !to.compare(server)) return false; } // from ourself? - else if(from.compare(local, false) || from.compare(local.domain(),false)) { + else if (from.compare(local, false) || from.compare(local.domain(), false)) { // allowed if we are querying ourself or the server - if(!to.isEmpty() && !to.compare(local, false) && !to.compare(server)) + if (!to.isEmpty() && !to.compare(local, false) && !to.compare(server)) return false; } // from anywhere else? else { - if(!from.compare(to)) + if (!from.compare(to)) return false; } - if(!id.isEmpty()) { - if(x.attribute(QStringLiteral("id")) != id) + if (!id.isEmpty()) { + if (x.attribute(QStringLiteral("id")) != id) return false; } - if(!xmlns.isEmpty()) { - if(queryNS(x) != xmlns) + if (!xmlns.isEmpty()) { + if (queryNS(x) != xmlns) return false; } diff --git a/src/xmpp/xmpp-im/xmpp_task.h b/src/xmpp/xmpp-im/xmpp_task.h index fcdb9533..a760892b 100644 --- a/src/xmpp/xmpp-im/xmpp_task.h +++ b/src/xmpp/xmpp-im/xmpp_task.h @@ -29,61 +29,60 @@ class QDomDocument; class QDomElement; namespace XMPP { - class Client; - class Jid; - - class Task : public QObject - { - Q_OBJECT - public: - enum { ErrDisc, ErrTimeout }; - Task(Task *parent); - Task(Client *, bool isRoot); - virtual ~Task(); - - Task *parent() const; - Client *client() const; - QDomDocument *doc() const; - QString id() const; - - bool success() const; - int statusCode() const; - const QString & statusString() const; - const Stanza::Error & error() const; - - void setTimeout(int seconds) const; - int timeout(); - - void go(bool autoDelete=false); - virtual bool take(const QDomElement &); - void safeDelete(); - - signals: - void finished(); - - protected: - virtual void onGo(); - virtual void onDisconnect(); - virtual void onTimeout(); - void send(const QDomElement &); - void setSuccess(int code=0, const QString &str=""); - void setError(const QDomElement &); - void setError(int code=0, const QString &str=""); - void debug(const char *, ...); - void debug(const QString &); - bool iqVerify(const QDomElement &x, const Jid &to, const QString &id, const QString &xmlns=""); - - private slots: - void clientDisconnected(); - void timeoutFinished(); - void done(); - - private: - void init(); - - class TaskPrivate; - TaskPrivate *d; - }; +class Client; +class Jid; + +class Task : public QObject { + Q_OBJECT +public: + enum { ErrDisc, ErrTimeout }; + Task(Task *parent); + Task(Client *, bool isRoot); + virtual ~Task(); + + Task * parent() const; + Client * client() const; + QDomDocument *doc() const; + QString id() const; + + bool success() const; + int statusCode() const; + const QString & statusString() const; + const Stanza::Error &error() const; + + void setTimeout(int seconds) const; + int timeout(); + + void go(bool autoDelete = false); + virtual bool take(const QDomElement &); + void safeDelete(); + +signals: + void finished(); + +protected: + virtual void onGo(); + virtual void onDisconnect(); + virtual void onTimeout(); + void send(const QDomElement &); + void setSuccess(int code = 0, const QString &str = ""); + void setError(const QDomElement &); + void setError(int code = 0, const QString &str = ""); + void debug(const char *, ...); + void debug(const QString &); + bool iqVerify(const QDomElement &x, const Jid &to, const QString &id, const QString &xmlns = ""); + +private slots: + void clientDisconnected(); + void timeoutFinished(); + void done(); + +private: + void init(); + + class TaskPrivate; + TaskPrivate *d; +}; } // namespace XMPP #endif // XMPP_TASK_H diff --git a/src/xmpp/xmpp-im/xmpp_tasks.cpp b/src/xmpp/xmpp-im/xmpp_tasks.cpp index 104a0de5..d0980794 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.cpp +++ b/src/xmpp/xmpp-im/xmpp_tasks.cpp @@ -93,10 +93,7 @@ static Roster xmlReadRoster(const QDomElement &q, bool push) // #include "protocol.h" -JT_Session::JT_Session(Task *parent) : - Task(parent) -{ -} +JT_Session::JT_Session(Task *parent) : Task(parent) {} void JT_Session::onGo() { @@ -139,8 +136,7 @@ class JT_Register::Private { int type; }; -JT_Register::JT_Register(Task *parent) : - Task(parent) +JT_Register::JT_Register(Task *parent) : Task(parent) { d = new Private; d->type = -1; @@ -148,10 +144,7 @@ JT_Register::JT_Register(Task *parent) : d->registered = false; } -JT_Register::~JT_Register() -{ - delete d; -} +JT_Register::~JT_Register() { delete d; } void JT_Register::reg(const QString &user, const QString &pass) { @@ -227,30 +220,15 @@ void JT_Register::setForm(const Jid &to, const XData &xdata) query.appendChild(xdata.toXml(doc(), true)); } -const Form &JT_Register::form() const -{ - return d->form; -} +const Form &JT_Register::form() const { return d->form; } -bool JT_Register::hasXData() const -{ - return d->hasXData; -} +bool JT_Register::hasXData() const { return d->hasXData; } -const XData &JT_Register::xdata() const -{ - return d->xdata; -} +const XData &JT_Register::xdata() const { return d->xdata; } -bool JT_Register::isRegistered() const -{ - return d->registered; -} +bool JT_Register::isRegistered() const { return d->registered; } -void JT_Register::onGo() -{ - send(iq); -} +void JT_Register::onGo() { send(iq); } bool JT_Register::take(const QDomElement &x) { @@ -308,8 +286,7 @@ class JT_UnRegister::Private { JT_Register *jt_reg = nullptr; }; -JT_UnRegister::JT_UnRegister(Task *parent) : - Task(parent) +JT_UnRegister::JT_UnRegister(Task *parent) : Task(parent) { d = new Private; d->jt_reg = nullptr; @@ -321,10 +298,7 @@ JT_UnRegister::~JT_UnRegister() delete d; } -void JT_UnRegister::unreg(const Jid &j) -{ - d->j = j; -} +void JT_UnRegister::unreg(const Jid &j) { d->j = j; } void JT_UnRegister::onGo() { @@ -370,22 +344,18 @@ class JT_Roster::Private { QList itemList; }; -JT_Roster::JT_Roster(Task *parent) : - Task(parent) +JT_Roster::JT_Roster(Task *parent) : Task(parent) { type = -1; d = new Private; } -JT_Roster::~JT_Roster() -{ - delete d; -} +JT_Roster::~JT_Roster() { delete d; } void JT_Roster::get() { type = 0; - //to = client()->host(); + // to = client()->host(); iq = createIQ(doc(), "get", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); @@ -394,7 +364,7 @@ void JT_Roster::get() void JT_Roster::set(const Jid &jid, const QString &name, const QStringList &groups) { type = 1; - //to = client()->host(); + // to = client()->host(); QDomElement item = doc()->createElement("item"); item.setAttribute("jid", jid.full()); if (!name.isEmpty()) @@ -407,7 +377,7 @@ void JT_Roster::set(const Jid &jid, const QString &name, const QStringList &grou void JT_Roster::remove(const Jid &jid) { type = 1; - //to = client()->host(); + // to = client()->host(); QDomElement item = doc()->createElement("item"); item.setAttribute("jid", jid.full()); item.setAttribute("subscription", "remove"); @@ -419,7 +389,7 @@ void JT_Roster::onGo() if (type == 0) send(iq); else if (type == 1) { - //to = client()->host(); + // to = client()->host(); iq = createIQ(doc(), "set", to.full(), id()); QDomElement query = doc()->createElementNS("jabber:iq:roster", "query"); iq.appendChild(query); @@ -429,10 +399,7 @@ void JT_Roster::onGo() } } -const Roster &JT_Roster::roster() const -{ - return d->roster; -} +const Roster &JT_Roster::roster() const { return d->roster; } QString JT_Roster::toString() const { @@ -508,14 +475,9 @@ bool JT_Roster::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_PushRoster //---------------------------------------------------------------------------- -JT_PushRoster::JT_PushRoster(Task *parent) : - Task(parent) -{ -} +JT_PushRoster::JT_PushRoster(Task *parent) : Task(parent) {} -JT_PushRoster::~JT_PushRoster() -{ -} +JT_PushRoster::~JT_PushRoster() {} bool JT_PushRoster::take(const QDomElement &e) { @@ -535,14 +497,9 @@ bool JT_PushRoster::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_Presence //---------------------------------------------------------------------------- -JT_Presence::JT_Presence(Task *parent) : - Task(parent) -{ -} +JT_Presence::JT_Presence(Task *parent) : Task(parent) {} -JT_Presence::~JT_Presence() -{ -} +JT_Presence::~JT_Presence() {} void JT_Presence::pres(const Status &s) { @@ -626,7 +583,9 @@ void JT_Presence::sub(const Jid &to, const QString &subType, const QString &nick tag = doc()->createElement("presence"); tag.setAttribute("to", to.full()); tag.setAttribute("type", subType); - if (!nick.isEmpty() && (subType == QLatin1String("subscribe") || subType == QLatin1String("subscribed") || subType == QLatin1String("unsubscribe") || subType == QLatin1String("unsubscribed"))) { + if (!nick.isEmpty() + && (subType == QLatin1String("subscribe") || subType == QLatin1String("subscribed") + || subType == QLatin1String("unsubscribe") || subType == QLatin1String("unsubscribed"))) { QDomElement nick_tag = textTagNS(doc(), "http://jabber.org/protocol/nick", "nick", nick); tag.appendChild(nick_tag); } @@ -650,14 +609,9 @@ void JT_Presence::onGo() //---------------------------------------------------------------------------- // JT_PushPresence //---------------------------------------------------------------------------- -JT_PushPresence::JT_PushPresence(Task *parent) : - Task(parent) -{ -} +JT_PushPresence::JT_PushPresence(Task *parent) : Task(parent) {} -JT_PushPresence::~JT_PushPresence() -{ -} +JT_PushPresence::~JT_PushPresence() {} bool JT_PushPresence::take(const QDomElement &e) { @@ -676,7 +630,8 @@ bool JT_PushPresence::take(const QDomElement &e) int code = 0; getErrorFromElement(e, client()->stream().baseNS(), &code, &str); p.setError(code, str); - } else if (type == QLatin1String("subscribe") || type == QLatin1String("subscribed") || type == QLatin1String("unsubscribe") || type == QLatin1String("unsubscribed")) { + } else if (type == QLatin1String("subscribe") || type == QLatin1String("subscribed") + || type == QLatin1String("unsubscribe") || type == QLatin1String("unsubscribed")) { QString nick; QDomElement tag = e.firstChildElement("nick"); if (!tag.isNull() && tag.namespaceURI() == "http://jabber.org/protocol/nick") { @@ -740,7 +695,8 @@ bool JT_PushPresence::take(const QDomElement &e) QDomElement t; t = i.firstChildElement("photo"); if (!t.isNull()) - p.setPhotoHash(QByteArray::fromHex(tagContent(t).toLatin1())); // if hash is empty this may mean photo removal + p.setPhotoHash( + QByteArray::fromHex(tagContent(t).toLatin1())); // if hash is empty this may mean photo removal // else vcard.hasPhotoHash() returns false and that's mean user is not yet ready to advertise his image } else if (i.tagName() == "x" && i.namespaceURI() == "http://jabber.org/protocol/muc#user") { for (QDomNode muc_n = i.firstChild(); !muc_n.isNull(); muc_n = muc_n.nextSibling()) { @@ -792,9 +748,9 @@ static QDomElement oldStyleNS(const QDomElement &e) QDomElement i; int x; - //if(noShowNS) + // if(noShowNS) i = e.ownerDocument().createElement(e.tagName()); - //else + // else // i = e.ownerDocument().createElementNS(e.namespaceURI(), e.tagName()); // copy attributes @@ -817,22 +773,19 @@ static QDomElement oldStyleNS(const QDomElement &e) return i; } -JT_Message::JT_Message(Task *parent, Message &msg) : - Task(parent), m(msg) +JT_Message::JT_Message(Task *parent, Message &msg) : Task(parent), m(msg) { if (msg.id().isEmpty()) msg.setId(id()); } -JT_Message::~JT_Message() -{ -} +JT_Message::~JT_Message() {} void JT_Message::onGo() { Stanza s = m.toStanza(&(client()->stream())); - QDomElement e = s.element(); //oldStyleNS(s.element()); + QDomElement e = s.element(); // oldStyleNS(s.element()); auto encryptionHandler = client()->encryptionHandler(); bool wasEncrypted = encryptionHandler && encryptionHandler->encryptMessageElement(e); @@ -853,17 +806,13 @@ class JT_PushMessage::Private { EncryptionHandler *m_encryptionHandler; }; -JT_PushMessage::JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler) : - Task(parent) +JT_PushMessage::JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler) : Task(parent) { d = new Private; d->m_encryptionHandler = encryptionHandler; } -JT_PushMessage::~JT_PushMessage() -{ - delete d; -} +JT_PushMessage::~JT_PushMessage() { delete d; } bool JT_PushMessage::take(const QDomElement &e) { @@ -872,7 +821,8 @@ bool JT_PushMessage::take(const QDomElement &e) QDomElement e1 = e; - bool wasEncrypted = d->m_encryptionHandler != nullptr && d->m_encryptionHandler->decryptMessageElement(e1) && !e1.isNull(); + bool wasEncrypted + = d->m_encryptionHandler != nullptr && d->m_encryptionHandler->decryptMessageElement(e1) && !e1.isNull(); if (wasEncrypted && e1.isNull()) { // The message was processed, but has to be discarded for some reason return true; @@ -912,13 +862,13 @@ bool JT_PushMessage::take(const QDomElement &e) Stanza s = client()->stream().createStanza(addCorrectNS(forward.isNull() ? e1 : forward)); if (s.isNull()) { - //printf("take: bad stanza??\n"); + // printf("take: bad stanza??\n"); return false; } Message m; if (!m.fromStanza(s, client()->manualTimeZoneOffset(), client()->timeZoneOffset())) { - //printf("bad message\n"); + // printf("bad message\n"); return false; } if (!forward.isNull()) { @@ -943,17 +893,13 @@ class JT_VCard::Private { VCard vcard; }; -JT_VCard::JT_VCard(Task *parent) : - Task(parent) +JT_VCard::JT_VCard(Task *parent) : Task(parent) { type = -1; d = new Private; } -JT_VCard::~JT_VCard() -{ - delete d; -} +JT_VCard::~JT_VCard() { delete d; } void JT_VCard::get(const Jid &_jid) { @@ -964,15 +910,9 @@ void JT_VCard::get(const Jid &_jid) d->iq.appendChild(v); } -const Jid &JT_VCard::jid() const -{ - return d->jid; -} +const Jid &JT_VCard::jid() const { return d->jid; } -const VCard &JT_VCard::vcard() const -{ - return d->vcard; -} +const VCard &JT_VCard::vcard() const { return d->vcard; } void JT_VCard::set(const VCard &card) { @@ -993,10 +933,7 @@ void JT_VCard::set(const Jid &j, const VCard &card, bool isTarget) d->iq.appendChild(card.toXml(doc())); } -void JT_VCard::onGo() -{ - send(d->iq); -} +void JT_VCard::onGo() { send(d->iq); } bool JT_VCard::take(const QDomElement &x) { @@ -1049,17 +986,13 @@ class JT_Search::Private { QList resultList; }; -JT_Search::JT_Search(Task *parent) : - Task(parent) +JT_Search::JT_Search(Task *parent) : Task(parent) { d = new Private; type = -1; } -JT_Search::~JT_Search() -{ - delete d; -} +JT_Search::~JT_Search() { delete d; } void JT_Search::get(const Jid &jid) { @@ -1105,30 +1038,15 @@ void JT_Search::set(const Jid &jid, const XData &form) query.appendChild(form.toXml(doc(), true)); } -const Form &JT_Search::form() const -{ - return d->form; -} +const Form &JT_Search::form() const { return d->form; } -const QList &JT_Search::results() const -{ - return d->resultList; -} +const QList &JT_Search::results() const { return d->resultList; } -bool JT_Search::hasXData() const -{ - return d->hasXData; -} +bool JT_Search::hasXData() const { return d->hasXData; } -const XData &JT_Search::xdata() const -{ - return d->xdata; -} +const XData &JT_Search::xdata() const { return d->xdata; } -void JT_Search::onGo() -{ - send(iq); -} +void JT_Search::onGo() { send(iq); } bool JT_Search::take(const QDomElement &x) { @@ -1207,10 +1125,7 @@ bool JT_Search::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_ClientVersion //---------------------------------------------------------------------------- -JT_ClientVersion::JT_ClientVersion(Task *parent) : - Task(parent) -{ -} +JT_ClientVersion::JT_ClientVersion(Task *parent) : Task(parent) {} void JT_ClientVersion::get(const Jid &jid) { @@ -1220,10 +1135,7 @@ void JT_ClientVersion::get(const Jid &jid) iq.appendChild(query); } -void JT_ClientVersion::onGo() -{ - send(iq); -} +void JT_ClientVersion::onGo() { send(iq); } bool JT_ClientVersion::take(const QDomElement &x) { @@ -1251,41 +1163,23 @@ bool JT_ClientVersion::take(const QDomElement &x) return true; } -const Jid &JT_ClientVersion::jid() const -{ - return j; -} +const Jid &JT_ClientVersion::jid() const { return j; } -const QString &JT_ClientVersion::name() const -{ - return v_name; -} +const QString &JT_ClientVersion::name() const { return v_name; } -const QString &JT_ClientVersion::version() const -{ - return v_ver; -} +const QString &JT_ClientVersion::version() const { return v_ver; } -const QString &JT_ClientVersion::os() const -{ - return v_os; -} +const QString &JT_ClientVersion::os() const { return v_os; } //---------------------------------------------------------------------------- // JT_EntityTime //---------------------------------------------------------------------------- -JT_EntityTime::JT_EntityTime(Task *parent) : - Task(parent) -{ -} +JT_EntityTime::JT_EntityTime(Task *parent) : Task(parent) {} /** * \brief Queried entity's JID. */ -const Jid &JT_EntityTime::jid() const -{ - return j; -} +const Jid &JT_EntityTime::jid() const { return j; } /** * \brief Prepares the task to get information from JID. @@ -1298,10 +1192,7 @@ void JT_EntityTime::get(const Jid &jid) iq.appendChild(time); } -void JT_EntityTime::onGo() -{ - send(iq); -} +void JT_EntityTime::onGo() { send(iq); } bool JT_EntityTime::take(const QDomElement &x) { @@ -1336,27 +1227,16 @@ bool JT_EntityTime::take(const QDomElement &x) return true; } -const QDateTime &JT_EntityTime::dateTime() const -{ - return utc; -} +const QDateTime &JT_EntityTime::dateTime() const { return utc; } -int JT_EntityTime::timezoneOffset() const -{ - return tzo; -} +int JT_EntityTime::timezoneOffset() const { return tzo; } //---------------------------------------------------------------------------- // JT_ServInfo //---------------------------------------------------------------------------- -JT_ServInfo::JT_ServInfo(Task *parent) : - Task(parent) -{ -} +JT_ServInfo::JT_ServInfo(Task *parent) : Task(parent) {} -JT_ServInfo::~JT_ServInfo() -{ -} +JT_ServInfo::~JT_ServInfo() {} bool JT_ServInfo::take(const QDomElement &e) { @@ -1436,11 +1316,7 @@ bool JT_ServInfo::take(const QDomElement &e) //---------------------------------------------------------------------------- // JT_Gateway //---------------------------------------------------------------------------- -JT_Gateway::JT_Gateway(Task *parent) : - Task(parent) -{ - type = -1; -} +JT_Gateway::JT_Gateway(Task *parent) : Task(parent) { type = -1; } void JT_Gateway::get(const Jid &jid) { @@ -1462,30 +1338,15 @@ void JT_Gateway::set(const Jid &jid, const QString &prompt) query.appendChild(textTag(doc(), "prompt", v_prompt)); } -void JT_Gateway::onGo() -{ - send(iq); -} +void JT_Gateway::onGo() { send(iq); } -Jid JT_Gateway::jid() const -{ - return v_jid; -} +Jid JT_Gateway::jid() const { return v_jid; } -QString JT_Gateway::desc() const -{ - return v_desc; -} +QString JT_Gateway::desc() const { return v_desc; } -QString JT_Gateway::prompt() const -{ - return v_prompt; -} +QString JT_Gateway::prompt() const { return v_prompt; } -Jid JT_Gateway::translatedJid() const -{ - return v_translatedJid; -} +Jid JT_Gateway::translatedJid() const { return v_translatedJid; } bool JT_Gateway::take(const QDomElement &x) { @@ -1540,21 +1401,11 @@ class JT_DiscoItems::Private { QDomElement subsetsEl; }; -JT_DiscoItems::JT_DiscoItems(Task *parent) : - Task(parent) -{ - d = new Private; -} +JT_DiscoItems::JT_DiscoItems(Task *parent) : Task(parent) { d = new Private; } -JT_DiscoItems::~JT_DiscoItems() -{ - delete d; -} +JT_DiscoItems::~JT_DiscoItems() { delete d; } -void JT_DiscoItems::get(const DiscoItem &item) -{ - get(item.jid(), item.node()); -} +void JT_DiscoItems::get(const DiscoItem &item) { get(item.jid(), item.node()); } void JT_DiscoItems::get(const Jid &j, const QString &node) { @@ -1575,10 +1426,7 @@ void JT_DiscoItems::get(const Jid &j, const QString &node) d->iq.appendChild(query); } -const DiscoList &JT_DiscoItems::items() const -{ - return d->items; -} +const DiscoList &JT_DiscoItems::items() const { return d->items; } void JT_DiscoItems::includeSubsetQuery(const SubsetsClientManager &subsets) { @@ -1590,10 +1438,7 @@ bool JT_DiscoItems::extractSubsetInfo(SubsetsClientManager &subsets) return d->subsetsEl.isNull() ? false : subsets.updateFromElement(d->subsetsEl, d->items.count()); } -void JT_DiscoItems::onGo() -{ - send(d->iq); -} +void JT_DiscoItems::onGo() { send(d->iq); } bool JT_DiscoItems::take(const QDomElement &x) { @@ -1642,16 +1487,9 @@ class JT_DiscoPublish::Private { DiscoList list; }; -JT_DiscoPublish::JT_DiscoPublish(Task *parent) : - Task(parent) -{ - d = new Private; -} +JT_DiscoPublish::JT_DiscoPublish(Task *parent) : Task(parent) { d = new Private; } -JT_DiscoPublish::~JT_DiscoPublish() -{ - delete d; -} +JT_DiscoPublish::~JT_DiscoPublish() { delete d; } void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) { @@ -1662,7 +1500,7 @@ void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) QDomElement query = doc()->createElementNS("http://jabber.org/protocol/disco#items", "query"); // FIXME: unsure about this - //if ( !node.isEmpty() ) + // if ( !node.isEmpty() ) // query.setAttribute("node", node); DiscoList::ConstIterator it = list.begin(); @@ -1682,10 +1520,7 @@ void JT_DiscoPublish::set(const Jid &j, const DiscoList &list) d->iq.appendChild(query); } -void JT_DiscoPublish::onGo() -{ - send(d->iq); -} +void JT_DiscoPublish::onGo() { send(d->iq); } bool JT_DiscoPublish::take(const QDomElement &x) { @@ -1704,10 +1539,7 @@ bool JT_DiscoPublish::take(const QDomElement &x) // --------------------------------------------------------- // JT_BoBServer // --------------------------------------------------------- -JT_BoBServer::JT_BoBServer(Task *parent) : - Task(parent) -{ -} +JT_BoBServer::JT_BoBServer(Task *parent) : Task(parent) {} bool JT_BoBServer::take(const QDomElement &e) { @@ -1719,10 +1551,8 @@ bool JT_BoBServer::take(const QDomElement &e) QDomElement iq; BoBData bd = client()->bobManager()->bobData(data.attribute("cid")); if (bd.isNull()) { - iq = createIQ(client()->doc(), "error", - e.attribute("from"), e.attribute("id")); - Stanza::Error error(Stanza::Error::Cancel, - Stanza::Error::ItemNotFound); + iq = createIQ(client()->doc(), "error", e.attribute("from"), e.attribute("id")); + Stanza::Error error(Stanza::Error::Cancel, Stanza::Error::ItemNotFound); iq.appendChild(error.toXml(*doc(), client()->stream().baseNS())); } else { iq = createIQ(doc(), "result", e.attribute("from"), e.attribute("id")); @@ -1747,16 +1577,9 @@ class JT_BitsOfBinary::Private { BoBData data; }; -JT_BitsOfBinary::JT_BitsOfBinary(Task *parent) : - Task(parent) -{ - d = new Private; -} +JT_BitsOfBinary::JT_BitsOfBinary(Task *parent) : Task(parent) { d = new Private; } -JT_BitsOfBinary::~JT_BitsOfBinary() -{ - delete d; -} +JT_BitsOfBinary::~JT_BitsOfBinary() { delete d; } void JT_BitsOfBinary::get(const Jid &j, const QString &cid) { @@ -1803,10 +1626,7 @@ bool JT_BitsOfBinary::take(const QDomElement &x) return true; } -BoBData &JT_BitsOfBinary::data() -{ - return d->data; -} +BoBData &JT_BitsOfBinary::data() { return d->data; } //---------------------------------------------------------------------------- // JT_PongServer @@ -1816,10 +1636,7 @@ BoBData &JT_BitsOfBinary::data() * \brief Answers XMPP Pings */ -JT_PongServer::JT_PongServer(Task *parent) : - Task(parent) -{ -} +JT_PongServer::JT_PongServer(Task *parent) : Task(parent) {} bool JT_PongServer::take(const QDomElement &e) { @@ -1844,16 +1661,9 @@ class JT_CaptchaChallenger::Private { CaptchaChallenge challenge; }; -JT_CaptchaChallenger::JT_CaptchaChallenger(Task *parent) : - Task(parent), - d(new Private) -{ -} +JT_CaptchaChallenger::JT_CaptchaChallenger(Task *parent) : Task(parent), d(new Private) {} -JT_CaptchaChallenger::~JT_CaptchaChallenger() -{ - delete d; -} +JT_CaptchaChallenger::~JT_CaptchaChallenger() { delete d; } void JT_CaptchaChallenger::set(const Jid &j, const CaptchaChallenge &c) { @@ -1894,7 +1704,8 @@ void JT_CaptchaChallenger::onGo() bool JT_CaptchaChallenger::take(const QDomElement &x) { - if (x.tagName() == "message" && x.attribute("id") == id() && Jid(x.attribute("from")) == d->j && !x.firstChildElement("error").isNull()) { + if (x.tagName() == "message" && x.attribute("id") == id() && Jid(x.attribute("from")) == d->j + && !x.firstChildElement("error").isNull()) { setError(x); return true; } @@ -1902,7 +1713,10 @@ bool JT_CaptchaChallenger::take(const QDomElement &x) XDomNodeList nl; XData xd; QString rid = x.attribute("id"); - if (rid.isEmpty() || x.tagName() != "iq" || Jid(x.attribute("from")) != d->j || x.attribute("type") != "set" || (nl = childElementsByTagNameNS(x, "urn:xmpp:captcha", "captcha")).isEmpty() || (nl = childElementsByTagNameNS(nl.item(0).toElement(), "jabber:x:data", "x")).isEmpty() || (xd.fromXml(nl.item(0).toElement()), xd.getField("challenge").value().value(0) != id())) { + if (rid.isEmpty() || x.tagName() != "iq" || Jid(x.attribute("from")) != d->j || x.attribute("type") != "set" + || (nl = childElementsByTagNameNS(x, "urn:xmpp:captcha", "captcha")).isEmpty() + || (nl = childElementsByTagNameNS(nl.item(0).toElement(), "jabber:x:data", "x")).isEmpty() + || (xd.fromXml(nl.item(0).toElement()), xd.getField("challenge").value().value(0) != id())) { return false; } @@ -1931,24 +1745,17 @@ bool JT_CaptchaChallenger::take(const QDomElement &x) //--------------------------------------------------------------------------- // JT_CaptchaSender //--------------------------------------------------------------------------- -JT_CaptchaSender::JT_CaptchaSender(Task *parent) : - Task(parent) -{ -} +JT_CaptchaSender::JT_CaptchaSender(Task *parent) : Task(parent) {} void JT_CaptchaSender::set(const Jid &j, const XData &xd) { to = j; iq = createIQ(doc(), "set", to.full(), id()); - iq.appendChild(doc()->createElementNS("urn:xmpp:captcha", "captcha")) - .appendChild(xd.toXml(doc(), true)); + iq.appendChild(doc()->createElementNS("urn:xmpp:captcha", "captcha")).appendChild(xd.toXml(doc(), true)); } -void JT_CaptchaSender::onGo() -{ - send(iq); -} +void JT_CaptchaSender::onGo() { send(iq); } bool JT_CaptchaSender::take(const QDomElement &x) { @@ -1968,10 +1775,7 @@ bool JT_CaptchaSender::take(const QDomElement &x) //---------------------------------------------------------------------------- // JT_MessageCarbons //---------------------------------------------------------------------------- -JT_MessageCarbons::JT_MessageCarbons(Task *parent) : - Task(parent) -{ -} +JT_MessageCarbons::JT_MessageCarbons(Task *parent) : Task(parent) {} void JT_MessageCarbons::enable() { diff --git a/src/xmpp/xmpp-im/xmpp_tasks.h b/src/xmpp/xmpp-im/xmpp_tasks.h index d183ff42..11f8a6b3 100644 --- a/src/xmpp/xmpp-im/xmpp_tasks.h +++ b/src/xmpp/xmpp-im/xmpp_tasks.h @@ -31,444 +31,421 @@ #include namespace XMPP { - class BoBData; - class CaptchaChallenge; - class Roster; - class Status; - - class JT_Register : public Task - { - Q_OBJECT - public: - JT_Register(Task *parent); - ~JT_Register(); - - // OLd style registration - void reg(const QString &user, const QString &pass); - - void changepw(const QString &pass); - void unreg(const Jid &j=""); - - const Form & form() const; - bool hasXData() const; - const XData& xdata() const; - bool isRegistered() const; - void getForm(const Jid &); - void setForm(const Form &); - void setForm(const Jid&, const XData &); - - void onGo(); - bool take(const QDomElement &); - - private: - QDomElement iq; - Jid to; - - class Private; - Private *d = nullptr; - }; - - class JT_UnRegister : public Task - { - Q_OBJECT - public: - JT_UnRegister(Task *parent); - ~JT_UnRegister(); - - void unreg(const Jid &); - - void onGo(); - - private slots: - void getFormFinished(); - void unregFinished(); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_Roster : public Task - { - Q_OBJECT - public: - JT_Roster(Task *parent); - ~JT_Roster(); - - void get(); - void set(const Jid &, const QString &name, const QStringList &groups); - void remove(const Jid &); - - const Roster & roster() const; - - QString toString() const; - bool fromString(const QString &); - - void onGo(); - bool take(const QDomElement &x); - - private: - int type; - QDomElement iq; - Jid to; - - class Private; - Private *d = nullptr; - }; - - class JT_PushRoster : public Task - { - Q_OBJECT - public: - JT_PushRoster(Task *parent); - ~JT_PushRoster(); - - bool take(const QDomElement &); - - signals: - void roster(const Roster &); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_Presence : public Task - { - Q_OBJECT - public: - JT_Presence(Task *parent); - ~JT_Presence(); - - void pres(const Status &); - void pres(const Jid &, const Status &); - void sub(const Jid &, const QString &subType, const QString& nick = QString()); - void probe(const Jid &to); - - void onGo(); - - private: - QDomElement tag; - int type = -1; - - class Private; - Private *d = nullptr; - }; - - class JT_PushPresence : public Task - { - Q_OBJECT - public: - JT_PushPresence(Task *parent); - ~JT_PushPresence(); - - bool take(const QDomElement &); - - signals: - void presence(const Jid &, const Status &); - void subscription(const Jid &, const QString &, const QString&); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_Session : public Task - { - public: - JT_Session(Task *parent); - void onGo(); - bool take(const QDomElement&); - }; - - class JT_Message : public Task - { - Q_OBJECT - public: - JT_Message(Task *parent, Message &); - ~JT_Message(); - - void onGo(); - - private: - Message m; - - class Private; - Private *d = nullptr; - }; - - class JT_PushMessage : public Task - { - Q_OBJECT - public: - JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler = nullptr); - ~JT_PushMessage(); - - bool take(const QDomElement &); - - signals: - void message(const Message &); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_VCard : public Task - { - Q_OBJECT - public: - JT_VCard(Task *parent); - ~JT_VCard(); - - void get(const Jid &); - void set(const VCard &); - void set(const Jid &, const VCard &, bool isTarget = false); - - const Jid & jid() const; - const VCard & vcard() const; - - void onGo(); - bool take(const QDomElement &x); - - private: - int type; - - class Private; - Private *d = nullptr; - }; - - class JT_Search : public Task - { - Q_OBJECT - public: - JT_Search(Task *parent); - ~JT_Search(); - - const Form & form() const; - const QList & results() const; - - bool hasXData() const; - const XData & xdata() const; - - void get(const Jid &); - void set(const Form &); - void set(const Jid &, const XData &); - - void onGo(); - bool take(const QDomElement &x); - - private: - QDomElement iq; - int type; - - class Private; - Private *d = nullptr; - }; - - class JT_ClientVersion : public Task - { - Q_OBJECT - public: - JT_ClientVersion(Task *); - - void get(const Jid &); - void onGo(); - bool take(const QDomElement &); - - const Jid & jid() const; - const QString & name() const; - const QString & version() const; - const QString & os() const; - - private: - QDomElement iq; - - Jid j; - QString v_name, v_ver, v_os; - }; - - class JT_EntityTime : public Task - { - public: - JT_EntityTime(Task*); - - void onGo(); - bool take(const QDomElement &); - void get(const XMPP::Jid &j); - const XMPP::Jid & jid() const; - - const QDateTime & dateTime() const; - int timezoneOffset() const; - - private: - QDomElement iq; - XMPP::Jid j; - QDateTime utc; - int tzo = 0; - }; - - class JT_ServInfo : public Task - { - Q_OBJECT - public: - JT_ServInfo(Task *); - ~JT_ServInfo(); - - bool take(const QDomElement &); - }; - - class JT_Gateway : public Task - { - Q_OBJECT - public: - JT_Gateway(Task *); - - void get(const Jid &); - void set(const Jid &, const QString &prompt); - void onGo(); - bool take(const QDomElement &); - - Jid jid() const; - - QString desc() const; - QString prompt() const; - Jid translatedJid() const; - - private: - QDomElement iq; - - int type; - Jid v_jid; - Jid v_translatedJid; - QString v_prompt, v_desc; - }; - - class JT_DiscoItems : public Task - { - Q_OBJECT - public: - JT_DiscoItems(Task *); - ~JT_DiscoItems(); - - void get(const Jid &, const QString &node = QString()); - void get(const DiscoItem &); - - const DiscoList &items() const; - - void includeSubsetQuery(const SubsetsClientManager &); - bool extractSubsetInfo(SubsetsClientManager &); - - void onGo(); - bool take(const QDomElement &); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_DiscoPublish : public Task - { - Q_OBJECT - public: - JT_DiscoPublish(Task *); - ~JT_DiscoPublish(); - - void set(const Jid &, const DiscoList &); - - void onGo(); - bool take(const QDomElement &); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_BoBServer : public Task - { - Q_OBJECT - - public: - JT_BoBServer(Task *parent); - bool take(const QDomElement &); - }; - - class JT_BitsOfBinary : public Task - { - Q_OBJECT - public: - JT_BitsOfBinary(Task *); - ~JT_BitsOfBinary(); - - void get(const Jid &, const QString &); - - void onGo(); - bool take(const QDomElement &); - BoBData &data(); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_PongServer : public Task - { - Q_OBJECT - public: - JT_PongServer(Task *); - bool take(const QDomElement &); - }; - - class JT_MessageCarbons : public Task - { - Q_OBJECT - - public: - JT_MessageCarbons(Task *parent); - void enable(); - void disable(); - - void onGo(); - bool take(const QDomElement &e); - - private: - QDomElement _iq; - }; - - class JT_CaptchaChallenger : public Task - { - Q_OBJECT - public: - const static int CaptchaValidTimeout = 120; - - JT_CaptchaChallenger(Task *); - ~JT_CaptchaChallenger(); - - void set(const Jid &, const CaptchaChallenge &); - - void onGo(); - bool take(const QDomElement &); - - private: - class Private; - Private *d = nullptr; - }; - - class JT_CaptchaSender : public Task - { - Q_OBJECT - public: - JT_CaptchaSender(Task *); - - void set(const Jid &, const XData &); - - void onGo(); - bool take(const QDomElement &); - - private: - Jid to; - QDomElement iq; - }; +class BoBData; +class CaptchaChallenge; +class Roster; +class Status; + +class JT_Register : public Task { + Q_OBJECT +public: + JT_Register(Task *parent); + ~JT_Register(); + + // OLd style registration + void reg(const QString &user, const QString &pass); + + void changepw(const QString &pass); + void unreg(const Jid &j = ""); + + const Form & form() const; + bool hasXData() const; + const XData &xdata() const; + bool isRegistered() const; + void getForm(const Jid &); + void setForm(const Form &); + void setForm(const Jid &, const XData &); + + void onGo(); + bool take(const QDomElement &); + +private: + QDomElement iq; + Jid to; + + class Private; + Private *d = nullptr; +}; + +class JT_UnRegister : public Task { + Q_OBJECT +public: + JT_UnRegister(Task *parent); + ~JT_UnRegister(); + + void unreg(const Jid &); + + void onGo(); + +private slots: + void getFormFinished(); + void unregFinished(); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_Roster : public Task { + Q_OBJECT +public: + JT_Roster(Task *parent); + ~JT_Roster(); + + void get(); + void set(const Jid &, const QString &name, const QStringList &groups); + void remove(const Jid &); + + const Roster &roster() const; + + QString toString() const; + bool fromString(const QString &); + + void onGo(); + bool take(const QDomElement &x); + +private: + int type; + QDomElement iq; + Jid to; + + class Private; + Private *d = nullptr; +}; + +class JT_PushRoster : public Task { + Q_OBJECT +public: + JT_PushRoster(Task *parent); + ~JT_PushRoster(); + + bool take(const QDomElement &); + +signals: + void roster(const Roster &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_Presence : public Task { + Q_OBJECT +public: + JT_Presence(Task *parent); + ~JT_Presence(); + + void pres(const Status &); + void pres(const Jid &, const Status &); + void sub(const Jid &, const QString &subType, const QString &nick = QString()); + void probe(const Jid &to); + + void onGo(); + +private: + QDomElement tag; + int type = -1; + + class Private; + Private *d = nullptr; +}; + +class JT_PushPresence : public Task { + Q_OBJECT +public: + JT_PushPresence(Task *parent); + ~JT_PushPresence(); + + bool take(const QDomElement &); + +signals: + void presence(const Jid &, const Status &); + void subscription(const Jid &, const QString &, const QString &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_Session : public Task { +public: + JT_Session(Task *parent); + void onGo(); + bool take(const QDomElement &); +}; + +class JT_Message : public Task { + Q_OBJECT +public: + JT_Message(Task *parent, Message &); + ~JT_Message(); + + void onGo(); + +private: + Message m; + + class Private; + Private *d = nullptr; +}; + +class JT_PushMessage : public Task { + Q_OBJECT +public: + JT_PushMessage(Task *parent, EncryptionHandler *encryptionHandler = nullptr); + ~JT_PushMessage(); + + bool take(const QDomElement &); + +signals: + void message(const Message &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_VCard : public Task { + Q_OBJECT +public: + JT_VCard(Task *parent); + ~JT_VCard(); + + void get(const Jid &); + void set(const VCard &); + void set(const Jid &, const VCard &, bool isTarget = false); + + const Jid & jid() const; + const VCard &vcard() const; + + void onGo(); + bool take(const QDomElement &x); + +private: + int type; + + class Private; + Private *d = nullptr; +}; + +class JT_Search : public Task { + Q_OBJECT +public: + JT_Search(Task *parent); + ~JT_Search(); + + const Form & form() const; + const QList &results() const; + + bool hasXData() const; + const XData &xdata() const; + + void get(const Jid &); + void set(const Form &); + void set(const Jid &, const XData &); + + void onGo(); + bool take(const QDomElement &x); + +private: + QDomElement iq; + int type; + + class Private; + Private *d = nullptr; +}; + +class JT_ClientVersion : public Task { + Q_OBJECT +public: + JT_ClientVersion(Task *); + + void get(const Jid &); + void onGo(); + bool take(const QDomElement &); + + const Jid & jid() const; + const QString &name() const; + const QString &version() const; + const QString &os() const; + +private: + QDomElement iq; + + Jid j; + QString v_name, v_ver, v_os; +}; + +class JT_EntityTime : public Task { +public: + JT_EntityTime(Task *); + + void onGo(); + bool take(const QDomElement &); + void get(const XMPP::Jid &j); + const XMPP::Jid &jid() const; + + const QDateTime &dateTime() const; + int timezoneOffset() const; + +private: + QDomElement iq; + XMPP::Jid j; + QDateTime utc; + int tzo = 0; +}; + +class JT_ServInfo : public Task { + Q_OBJECT +public: + JT_ServInfo(Task *); + ~JT_ServInfo(); + + bool take(const QDomElement &); +}; + +class JT_Gateway : public Task { + Q_OBJECT +public: + JT_Gateway(Task *); + + void get(const Jid &); + void set(const Jid &, const QString &prompt); + void onGo(); + bool take(const QDomElement &); + + Jid jid() const; + + QString desc() const; + QString prompt() const; + Jid translatedJid() const; + +private: + QDomElement iq; + + int type; + Jid v_jid; + Jid v_translatedJid; + QString v_prompt, v_desc; +}; + +class JT_DiscoItems : public Task { + Q_OBJECT +public: + JT_DiscoItems(Task *); + ~JT_DiscoItems(); + + void get(const Jid &, const QString &node = QString()); + void get(const DiscoItem &); + + const DiscoList &items() const; + + void includeSubsetQuery(const SubsetsClientManager &); + bool extractSubsetInfo(SubsetsClientManager &); + + void onGo(); + bool take(const QDomElement &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_DiscoPublish : public Task { + Q_OBJECT +public: + JT_DiscoPublish(Task *); + ~JT_DiscoPublish(); + + void set(const Jid &, const DiscoList &); + + void onGo(); + bool take(const QDomElement &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_BoBServer : public Task { + Q_OBJECT + +public: + JT_BoBServer(Task *parent); + bool take(const QDomElement &); +}; + +class JT_BitsOfBinary : public Task { + Q_OBJECT +public: + JT_BitsOfBinary(Task *); + ~JT_BitsOfBinary(); + + void get(const Jid &, const QString &); + + void onGo(); + bool take(const QDomElement &); + BoBData &data(); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_PongServer : public Task { + Q_OBJECT +public: + JT_PongServer(Task *); + bool take(const QDomElement &); +}; + +class JT_MessageCarbons : public Task { + Q_OBJECT + +public: + JT_MessageCarbons(Task *parent); + void enable(); + void disable(); + + void onGo(); + bool take(const QDomElement &e); + +private: + QDomElement _iq; +}; + +class JT_CaptchaChallenger : public Task { + Q_OBJECT +public: + const static int CaptchaValidTimeout = 120; + + JT_CaptchaChallenger(Task *); + ~JT_CaptchaChallenger(); + + void set(const Jid &, const CaptchaChallenge &); + + void onGo(); + bool take(const QDomElement &); + +private: + class Private; + Private *d = nullptr; +}; + +class JT_CaptchaSender : public Task { + Q_OBJECT +public: + JT_CaptchaSender(Task *); + + void set(const Jid &, const XData &); + + void onGo(); + bool take(const QDomElement &); + +private: + Jid to; + QDomElement iq; +}; } // namespace XMPP #endif // XMPP_TASKS_H diff --git a/src/xmpp/xmpp-im/xmpp_thumbs.h b/src/xmpp/xmpp-im/xmpp_thumbs.h index bf913c01..918aea28 100644 --- a/src/xmpp/xmpp-im/xmpp_thumbs.h +++ b/src/xmpp/xmpp-im/xmpp_thumbs.h @@ -26,27 +26,27 @@ #define XMPP_THUMBS_NS "urn:xmpp:thumbs:1" // TODO make nsdb.cpp/h with static declarations of all ns namespace XMPP { - class Thumbnail +class Thumbnail { +public: + inline Thumbnail() : width(0), height(0) {} + // data - for outgoing it's actual image data. for incoming - cid + inline Thumbnail(const QByteArray &data, const QString &mimeType = QString(), quint32 width = 0, + quint32 height = 0) : + data(data), + mimeType(mimeType), width(width), height(height) { - public: - inline Thumbnail() : width(0), height(0) {} - // data - for outgoing it's actual image data. for incoming - cid - inline Thumbnail(const QByteArray &data, - const QString &mimeType = QString(), - quint32 width = 0, quint32 height = 0) : - data(data), mimeType(mimeType), - width(width), height(height) { } - Thumbnail(const QDomElement &el); + } + Thumbnail(const QDomElement &el); - inline bool isValid() const { return uri.isValid(); } - QDomElement toXml(QDomDocument *doc) const; + inline bool isValid() const { return uri.isValid(); } + QDomElement toXml(QDomDocument *doc) const; - QUrl uri; - QByteArray data; - QString mimeType; - quint32 width; - quint32 height; - }; + QUrl uri; + QByteArray data; + QString mimeType; + quint32 width; + quint32 height; +}; } // namespace XMPP #endif // XMPP_THUMBS_H diff --git a/src/xmpp/xmpp-im/xmpp_url.h b/src/xmpp/xmpp-im/xmpp_url.h index 0f90b421..bee60f2a 100644 --- a/src/xmpp/xmpp-im/xmpp_url.h +++ b/src/xmpp/xmpp-im/xmpp_url.h @@ -22,26 +22,25 @@ class QString; namespace XMPP { - class Url - { - public: - Url(const QString &url="", const QString &desc=""); - Url(const Url &); - Url & operator=(const Url &); - ~Url(); - - QString url() const; - QString desc() const; - - void setUrl(const QString &); - void setDesc(const QString &); - - private: - class Private; - Private *d; - }; - - typedef QList UrlList; +class Url { +public: + Url(const QString &url = "", const QString &desc = ""); + Url(const Url &); + Url &operator=(const Url &); + ~Url(); + + QString url() const; + QString desc() const; + + void setUrl(const QString &); + void setDesc(const QString &); + +private: + class Private; + Private *d; +}; + +typedef QList UrlList; } // namespace XMPP #endif // XMPP_URL diff --git a/src/xmpp/xmpp-im/xmpp_vcard.cpp b/src/xmpp/xmpp-im/xmpp_vcard.cpp index d28a4c7a..cb36e270 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.cpp +++ b/src/xmpp/xmpp-im/xmpp_vcard.cpp @@ -37,24 +37,24 @@ using namespace XMLHelper; //---------------------------------------------------------------------------- QString openedImage2type(QIODevice *dev) { - QString format = QImageReader::imageFormat( dev ).toUpper(); + QString format = QImageReader::imageFormat(dev).toUpper(); // TODO: add more formats: PBM PGM PPM XBM XPM - if ( format == QLatin1String("PNG") || format == QLatin1String("PSIPNG") ) // PsiPNG in normal case + if (format == QLatin1String("PNG") || format == QLatin1String("PSIPNG")) // PsiPNG in normal case return QLatin1String("image/png"); - if ( format == QLatin1String("MNG") ) + if (format == QLatin1String("MNG")) return QLatin1String("video/x-mng"); - if ( format == QLatin1String("GIF") ) + if (format == QLatin1String("GIF")) return QLatin1String("image/gif"); - if ( format == QLatin1String("JPEG")) + if (format == QLatin1String("JPEG")) return QLatin1String("image/jpeg"); - if ( format == QLatin1String("BMP") ) + if (format == QLatin1String("BMP")) return QLatin1String("image/bmp"); - if ( format == QLatin1String("WEBP") ) + if (format == QLatin1String("WEBP")) return QLatin1String("image/webp"); - if ( format == QLatin1String("XPM") ) + if (format == QLatin1String("XPM")) return QLatin1String("image/x-xpm"); - if ( format == QLatin1String("SVG") ) + if (format == QLatin1String("SVG")) return QLatin1String("image/svg+xml"); return QString(); @@ -77,7 +77,7 @@ static QString foldString(const QString &s) QString ret; for (int i = 0; i < (int)s.length(); i++) { - if ( !(i % 75) ) + if (!(i % 75)) ret += '\n'; ret += s[i]; } @@ -85,14 +85,13 @@ static QString foldString(const QString &s) return ret; } -class VCardPrivate : public QSharedData -{ +class VCardPrivate : public QSharedData { public: VCardPrivate(); ~VCardPrivate(); // do we need copy constructor? - //VCardPrivate(const VCardPrivate &other) : + // VCardPrivate(const VCardPrivate &other) : // QSharedData(other), version(other.version), fullName(other.fullName) { qDebug("Copy VCardPrivate"); } QString version; @@ -101,411 +100,374 @@ class VCardPrivate : public QSharedData QString nickName; QByteArray photo; - QString photoURI; + QString photoURI; - QString bday; + QString bday; VCard::AddressList addressList; - VCard::LabelList labelList; - VCard::PhoneList phoneList; - VCard::EmailList emailList; - QString jid; - QString mailer; - QString timezone; - VCard::Geo geo; - QString title; - QString role; + VCard::LabelList labelList; + VCard::PhoneList phoneList; + VCard::EmailList emailList; + QString jid; + QString mailer; + QString timezone; + VCard::Geo geo; + QString title; + QString role; QByteArray logo; - QString logoURI; + QString logoURI; QSharedPointer agent; - QString agentURI; + QString agentURI; - VCard::Org org; + VCard::Org org; QStringList categories; - QString note; - QString prodId; - QString rev; - QString sortString; + QString note; + QString prodId; + QString rev; + QString sortString; QByteArray sound; - QString soundURI, soundPhonetic; + QString soundURI, soundPhonetic; - QString uid; - QString url; - QString desc; + QString uid; + QString url; + QString desc; VCard::PrivacyClass privacyClass; - QByteArray key; + QByteArray key; bool isEmpty() const; }; -VCardPrivate::VCardPrivate() -{ - privacyClass = VCard::pcNone; -} +VCardPrivate::VCardPrivate() { privacyClass = VCard::pcNone; } -VCardPrivate::~VCardPrivate() -{ - -} +VCardPrivate::~VCardPrivate() {} bool VCardPrivate::isEmpty() const { - if ( !version.isEmpty() || - !fullName.isEmpty() || - !familyName.isEmpty() || !givenName.isEmpty() || !middleName.isEmpty() || !prefixName.isEmpty() || !suffixName.isEmpty() || - !nickName.isEmpty() || - !photo.isEmpty() || !photoURI.isEmpty() || - !bday.isEmpty() || - !addressList.isEmpty() || - !labelList.isEmpty() || - !phoneList.isEmpty() || - !emailList.isEmpty() || - !jid.isEmpty() || - !mailer.isEmpty() || - !timezone.isEmpty() || - !geo.lat.isEmpty() || !geo.lon.isEmpty() || - !title.isEmpty() || - !role.isEmpty() || - !logo.isEmpty() || !logoURI.isEmpty() || - (agent && !agent->isEmpty()) || !agentURI.isEmpty() || - !org.name.isEmpty() || !org.unit.isEmpty() || - !categories.isEmpty() || - !note.isEmpty() || - !prodId.isEmpty() || - !rev.isEmpty() || - !sortString.isEmpty() || - !sound.isEmpty() || !soundURI.isEmpty() || !soundPhonetic.isEmpty() || - !uid.isEmpty() || - !url.isEmpty() || - !desc.isEmpty() || - (privacyClass != VCard::pcNone) || - !key.isEmpty() ) - { + if (!version.isEmpty() || !fullName.isEmpty() || !familyName.isEmpty() || !givenName.isEmpty() + || !middleName.isEmpty() || !prefixName.isEmpty() || !suffixName.isEmpty() || !nickName.isEmpty() + || !photo.isEmpty() || !photoURI.isEmpty() || !bday.isEmpty() || !addressList.isEmpty() || !labelList.isEmpty() + || !phoneList.isEmpty() || !emailList.isEmpty() || !jid.isEmpty() || !mailer.isEmpty() || !timezone.isEmpty() + || !geo.lat.isEmpty() || !geo.lon.isEmpty() || !title.isEmpty() || !role.isEmpty() || !logo.isEmpty() + || !logoURI.isEmpty() || (agent && !agent->isEmpty()) || !agentURI.isEmpty() || !org.name.isEmpty() + || !org.unit.isEmpty() || !categories.isEmpty() || !note.isEmpty() || !prodId.isEmpty() || !rev.isEmpty() + || !sortString.isEmpty() || !sound.isEmpty() || !soundURI.isEmpty() || !soundPhonetic.isEmpty() + || !uid.isEmpty() || !url.isEmpty() || !desc.isEmpty() || (privacyClass != VCard::pcNone) || !key.isEmpty()) { return false; } return true; } -VCard::VCard() -{ -} +VCard::VCard() {} -VCard::VCard(const VCard &from) : - d(from.d) -{ -} +VCard::VCard(const VCard &from) : d(from.d) {} -VCard & VCard::operator=(const VCard &from) +VCard &VCard::operator=(const VCard &from) { d = from.d; return *this; } -VCard::~VCard() -{ -} +VCard::~VCard() {} QDomElement VCard::toXml(QDomDocument *doc) const { QDomElement v = doc->createElementNS("vcard-temp", "vCard"); - if ( !d->version.isEmpty() ) - v.appendChild( textTag(doc, "VERSION", d->version) ); - if ( !d->fullName.isEmpty() ) - v.appendChild( textTag(doc, "FN", d->fullName) ); + if (!d->version.isEmpty()) + v.appendChild(textTag(doc, "VERSION", d->version)); + if (!d->fullName.isEmpty()) + v.appendChild(textTag(doc, "FN", d->fullName)); - if ( !d->familyName.isEmpty() || !d->givenName.isEmpty() || !d->middleName.isEmpty() || - !d->prefixName.isEmpty() || !d->suffixName.isEmpty() ) { + if (!d->familyName.isEmpty() || !d->givenName.isEmpty() || !d->middleName.isEmpty() || !d->prefixName.isEmpty() + || !d->suffixName.isEmpty()) { QDomElement w = doc->createElement("N"); - if ( !d->familyName.isEmpty() ) - w.appendChild( textTag(doc, "FAMILY", d->familyName) ); - if ( !d->givenName.isEmpty() ) - w.appendChild( textTag(doc, "GIVEN", d->givenName) ); - if ( !d->middleName.isEmpty() ) - w.appendChild( textTag(doc, "MIDDLE", d->middleName) ); - if ( !d->prefixName.isEmpty() ) - w.appendChild( textTag(doc, "PREFIX", d->prefixName) ); - if ( !d->suffixName.isEmpty() ) - w.appendChild( textTag(doc, "SUFFIX", d->suffixName) ); + if (!d->familyName.isEmpty()) + w.appendChild(textTag(doc, "FAMILY", d->familyName)); + if (!d->givenName.isEmpty()) + w.appendChild(textTag(doc, "GIVEN", d->givenName)); + if (!d->middleName.isEmpty()) + w.appendChild(textTag(doc, "MIDDLE", d->middleName)); + if (!d->prefixName.isEmpty()) + w.appendChild(textTag(doc, "PREFIX", d->prefixName)); + if (!d->suffixName.isEmpty()) + w.appendChild(textTag(doc, "SUFFIX", d->suffixName)); v.appendChild(w); } - if ( !d->nickName.isEmpty() ) - v.appendChild( textTag(doc, "NICKNAME", d->nickName) ); + if (!d->nickName.isEmpty()) + v.appendChild(textTag(doc, "NICKNAME", d->nickName)); - if ( !d->photo.isEmpty() || !d->photoURI.isEmpty() ) { + if (!d->photo.isEmpty() || !d->photoURI.isEmpty()) { QDomElement w = doc->createElement("PHOTO"); - if ( !d->photo.isEmpty() ) { - w.appendChild( textTag(doc, "TYPE", image2type(d->photo)) ); - w.appendChild( textTag(doc, "BINVAL", foldString( QCA::Base64().arrayToString(d->photo)) ) ); - } - else if ( !d->photoURI.isEmpty() ) - w.appendChild( textTag(doc, "EXTVAL", d->photoURI) ); + if (!d->photo.isEmpty()) { + w.appendChild(textTag(doc, "TYPE", image2type(d->photo))); + w.appendChild(textTag(doc, "BINVAL", foldString(QCA::Base64().arrayToString(d->photo)))); + } else if (!d->photoURI.isEmpty()) + w.appendChild(textTag(doc, "EXTVAL", d->photoURI)); v.appendChild(w); } - if ( !d->bday.isEmpty() ) - v.appendChild( textTag(doc, "BDAY", d->bday) ); + if (!d->bday.isEmpty()) + v.appendChild(textTag(doc, "BDAY", d->bday)); - if ( !d->addressList.isEmpty() ) { + if (!d->addressList.isEmpty()) { AddressList::ConstIterator it = d->addressList.constBegin(); - for ( ; it != d->addressList.end(); ++it ) { - QDomElement w = doc->createElement("ADR"); + for (; it != d->addressList.end(); ++it) { + QDomElement w = doc->createElement("ADR"); const Address &a = *it; - if ( a.home ) - w.appendChild( emptyTag(doc, "HOME") ); - if ( a.work ) - w.appendChild( emptyTag(doc, "WORK") ); - if ( a.postal ) - w.appendChild( emptyTag(doc, "POSTAL") ); - if ( a.parcel ) - w.appendChild( emptyTag(doc, "PARCEL") ); - if ( a.dom ) - w.appendChild( emptyTag(doc, "DOM") ); - if ( a.intl ) - w.appendChild( emptyTag(doc, "INTL") ); - if ( a.pref ) - w.appendChild( emptyTag(doc, "PREF") ); - - if ( !a.pobox.isEmpty() ) - w.appendChild( textTag(doc, "POBOX", a.pobox) ); - if ( !a.extaddr.isEmpty() ) - w.appendChild( textTag(doc, "EXTADR", a.extaddr) ); - if ( !a.street.isEmpty() ) - w.appendChild( textTag(doc, "STREET", a.street) ); - if ( !a.locality.isEmpty() ) - w.appendChild( textTag(doc, "LOCALITY", a.locality) ); - if ( !a.region.isEmpty() ) - w.appendChild( textTag(doc, "REGION", a.region) ); - if ( !a.pcode.isEmpty() ) - w.appendChild( textTag(doc, "PCODE", a.pcode) ); - if ( !a.country.isEmpty() ) - w.appendChild( textTag(doc, "CTRY", a.country) ); + if (a.home) + w.appendChild(emptyTag(doc, "HOME")); + if (a.work) + w.appendChild(emptyTag(doc, "WORK")); + if (a.postal) + w.appendChild(emptyTag(doc, "POSTAL")); + if (a.parcel) + w.appendChild(emptyTag(doc, "PARCEL")); + if (a.dom) + w.appendChild(emptyTag(doc, "DOM")); + if (a.intl) + w.appendChild(emptyTag(doc, "INTL")); + if (a.pref) + w.appendChild(emptyTag(doc, "PREF")); + + if (!a.pobox.isEmpty()) + w.appendChild(textTag(doc, "POBOX", a.pobox)); + if (!a.extaddr.isEmpty()) + w.appendChild(textTag(doc, "EXTADR", a.extaddr)); + if (!a.street.isEmpty()) + w.appendChild(textTag(doc, "STREET", a.street)); + if (!a.locality.isEmpty()) + w.appendChild(textTag(doc, "LOCALITY", a.locality)); + if (!a.region.isEmpty()) + w.appendChild(textTag(doc, "REGION", a.region)); + if (!a.pcode.isEmpty()) + w.appendChild(textTag(doc, "PCODE", a.pcode)); + if (!a.country.isEmpty()) + w.appendChild(textTag(doc, "CTRY", a.country)); v.appendChild(w); } } - if ( !d->labelList.isEmpty() ) { + if (!d->labelList.isEmpty()) { LabelList::ConstIterator it = d->labelList.constBegin(); - for ( ; it != d->labelList.end(); ++it ) { - QDomElement w = doc->createElement("LABEL"); + for (; it != d->labelList.end(); ++it) { + QDomElement w = doc->createElement("LABEL"); const Label &l = *it; - if ( l.home ) - w.appendChild( emptyTag(doc, "HOME") ); - if ( l.work ) - w.appendChild( emptyTag(doc, "WORK") ); - if ( l.postal ) - w.appendChild( emptyTag(doc, "POSTAL") ); - if ( l.parcel ) - w.appendChild( emptyTag(doc, "PARCEL") ); - if ( l.dom ) - w.appendChild( emptyTag(doc, "DOM") ); - if ( l.intl ) - w.appendChild( emptyTag(doc, "INTL") ); - if ( l.pref ) - w.appendChild( emptyTag(doc, "PREF") ); - - if ( !l.lines.isEmpty() ) { + if (l.home) + w.appendChild(emptyTag(doc, "HOME")); + if (l.work) + w.appendChild(emptyTag(doc, "WORK")); + if (l.postal) + w.appendChild(emptyTag(doc, "POSTAL")); + if (l.parcel) + w.appendChild(emptyTag(doc, "PARCEL")); + if (l.dom) + w.appendChild(emptyTag(doc, "DOM")); + if (l.intl) + w.appendChild(emptyTag(doc, "INTL")); + if (l.pref) + w.appendChild(emptyTag(doc, "PREF")); + + if (!l.lines.isEmpty()) { QStringList::ConstIterator it = l.lines.constBegin(); - for ( ; it != l.lines.end(); ++it ) - w.appendChild( textTag(doc, "LINE", *it) ); + for (; it != l.lines.end(); ++it) + w.appendChild(textTag(doc, "LINE", *it)); } v.appendChild(w); } } - if ( !d->phoneList.isEmpty() ) { + if (!d->phoneList.isEmpty()) { PhoneList::ConstIterator it = d->phoneList.constBegin(); - for ( ; it != d->phoneList.end(); ++it ) { - QDomElement w = doc->createElement("TEL"); + for (; it != d->phoneList.end(); ++it) { + QDomElement w = doc->createElement("TEL"); const Phone &p = *it; - if ( p.home ) - w.appendChild( emptyTag(doc, "HOME") ); - if ( p.work ) - w.appendChild( emptyTag(doc, "WORK") ); - if ( p.voice ) - w.appendChild( emptyTag(doc, "VOICE") ); - if ( p.fax ) - w.appendChild( emptyTag(doc, "FAX") ); - if ( p.pager ) - w.appendChild( emptyTag(doc, "PAGER") ); - if ( p.msg ) - w.appendChild( emptyTag(doc, "MSG") ); - if ( p.cell ) - w.appendChild( emptyTag(doc, "CELL") ); - if ( p.video ) - w.appendChild( emptyTag(doc, "VIDEO") ); - if ( p.bbs ) - w.appendChild( emptyTag(doc, "BBS") ); - if ( p.modem ) - w.appendChild( emptyTag(doc, "MODEM") ); - if ( p.isdn ) - w.appendChild( emptyTag(doc, "ISDN") ); - if ( p.pcs ) - w.appendChild( emptyTag(doc, "PCS") ); - if ( p.pref ) - w.appendChild( emptyTag(doc, "PREF") ); - - if ( !p.number.isEmpty() ) - w.appendChild( textTag(doc, "NUMBER", p.number) ); + if (p.home) + w.appendChild(emptyTag(doc, "HOME")); + if (p.work) + w.appendChild(emptyTag(doc, "WORK")); + if (p.voice) + w.appendChild(emptyTag(doc, "VOICE")); + if (p.fax) + w.appendChild(emptyTag(doc, "FAX")); + if (p.pager) + w.appendChild(emptyTag(doc, "PAGER")); + if (p.msg) + w.appendChild(emptyTag(doc, "MSG")); + if (p.cell) + w.appendChild(emptyTag(doc, "CELL")); + if (p.video) + w.appendChild(emptyTag(doc, "VIDEO")); + if (p.bbs) + w.appendChild(emptyTag(doc, "BBS")); + if (p.modem) + w.appendChild(emptyTag(doc, "MODEM")); + if (p.isdn) + w.appendChild(emptyTag(doc, "ISDN")); + if (p.pcs) + w.appendChild(emptyTag(doc, "PCS")); + if (p.pref) + w.appendChild(emptyTag(doc, "PREF")); + + if (!p.number.isEmpty()) + w.appendChild(textTag(doc, "NUMBER", p.number)); v.appendChild(w); } } - if ( !d->emailList.isEmpty() ) { + if (!d->emailList.isEmpty()) { EmailList::ConstIterator it = d->emailList.constBegin(); - for ( ; it != d->emailList.end(); ++it ) { - QDomElement w = doc->createElement("EMAIL"); + for (; it != d->emailList.end(); ++it) { + QDomElement w = doc->createElement("EMAIL"); const Email &e = *it; - if ( e.home ) - w.appendChild( emptyTag(doc, "HOME") ); - if ( e.work ) - w.appendChild( emptyTag(doc, "WORK") ); - if ( e.internet ) - w.appendChild( emptyTag(doc, "INTERNET") ); - if ( e.x400 ) - w.appendChild( emptyTag(doc, "X400") ); + if (e.home) + w.appendChild(emptyTag(doc, "HOME")); + if (e.work) + w.appendChild(emptyTag(doc, "WORK")); + if (e.internet) + w.appendChild(emptyTag(doc, "INTERNET")); + if (e.x400) + w.appendChild(emptyTag(doc, "X400")); - if ( !e.userid.isEmpty() ) - w.appendChild( textTag(doc, "USERID", e.userid) ); + if (!e.userid.isEmpty()) + w.appendChild(textTag(doc, "USERID", e.userid)); v.appendChild(w); } } - if ( !d->jid.isEmpty() ) - v.appendChild( textTag(doc, "JABBERID", d->jid) ); - if ( !d->mailer.isEmpty() ) - v.appendChild( textTag(doc, "MAILER", d->mailer) ); - if ( !d->timezone.isEmpty() ) - v.appendChild( textTag(doc, "TZ", d->timezone) ); + if (!d->jid.isEmpty()) + v.appendChild(textTag(doc, "JABBERID", d->jid)); + if (!d->mailer.isEmpty()) + v.appendChild(textTag(doc, "MAILER", d->mailer)); + if (!d->timezone.isEmpty()) + v.appendChild(textTag(doc, "TZ", d->timezone)); - if ( !d->geo.lat.isEmpty() || !d->geo.lon.isEmpty() ) { + if (!d->geo.lat.isEmpty() || !d->geo.lon.isEmpty()) { QDomElement w = doc->createElement("GEO"); - if ( !d->geo.lat.isEmpty() ) - w.appendChild( textTag(doc, "LAT", d->geo.lat) ); - if ( !d->geo.lon.isEmpty() ) - w.appendChild( textTag(doc, "LON", d->geo.lon)); + if (!d->geo.lat.isEmpty()) + w.appendChild(textTag(doc, "LAT", d->geo.lat)); + if (!d->geo.lon.isEmpty()) + w.appendChild(textTag(doc, "LON", d->geo.lon)); v.appendChild(w); } - if ( !d->title.isEmpty() ) - v.appendChild( textTag(doc, "TITLE", d->title) ); - if ( !d->role.isEmpty() ) - v.appendChild( textTag(doc, "ROLE", d->role) ); + if (!d->title.isEmpty()) + v.appendChild(textTag(doc, "TITLE", d->title)); + if (!d->role.isEmpty()) + v.appendChild(textTag(doc, "ROLE", d->role)); - if ( !d->logo.isEmpty() || !d->logoURI.isEmpty() ) { + if (!d->logo.isEmpty() || !d->logoURI.isEmpty()) { QDomElement w = doc->createElement("LOGO"); - if ( !d->logo.isEmpty() ) { - w.appendChild( textTag(doc, "TYPE", image2type(d->logo)) ); - w.appendChild( textTag(doc, "BINVAL", foldString( QCA::Base64().arrayToString(d->logo)) ) ); - } - else if ( !d->logoURI.isEmpty() ) - w.appendChild( textTag(doc, "EXTVAL", d->logoURI) ); + if (!d->logo.isEmpty()) { + w.appendChild(textTag(doc, "TYPE", image2type(d->logo))); + w.appendChild(textTag(doc, "BINVAL", foldString(QCA::Base64().arrayToString(d->logo)))); + } else if (!d->logoURI.isEmpty()) + w.appendChild(textTag(doc, "EXTVAL", d->logoURI)); v.appendChild(w); } - if ( !d->agentURI.isEmpty() || (d->agent && d->agent->isEmpty()) ) { + if (!d->agentURI.isEmpty() || (d->agent && d->agent->isEmpty())) { QDomElement w = doc->createElement("AGENT"); - if ( d->agent && !d->agent->isEmpty() ) - w.appendChild( d->agent->toXml(doc) ); - else if ( !d->agentURI.isEmpty() ) - w.appendChild( textTag(doc, "EXTVAL", d->agentURI) ); + if (d->agent && !d->agent->isEmpty()) + w.appendChild(d->agent->toXml(doc)); + else if (!d->agentURI.isEmpty()) + w.appendChild(textTag(doc, "EXTVAL", d->agentURI)); v.appendChild(w); } - if ( !d->org.name.isEmpty() || !d->org.unit.isEmpty() ) { + if (!d->org.name.isEmpty() || !d->org.unit.isEmpty()) { QDomElement w = doc->createElement("ORG"); - if ( !d->org.name.isEmpty() ) - w.appendChild( textTag(doc, "ORGNAME", d->org.name) ); + if (!d->org.name.isEmpty()) + w.appendChild(textTag(doc, "ORGNAME", d->org.name)); - if ( !d->org.unit.isEmpty() ) { + if (!d->org.unit.isEmpty()) { QStringList::ConstIterator it = d->org.unit.constBegin(); - for ( ; it != d->org.unit.end(); ++it ) - w.appendChild( textTag(doc, "ORGUNIT", *it) ); + for (; it != d->org.unit.end(); ++it) + w.appendChild(textTag(doc, "ORGUNIT", *it)); } v.appendChild(w); } - if ( !d->categories.isEmpty() ) { + if (!d->categories.isEmpty()) { QDomElement w = doc->createElement("CATEGORIES"); QStringList::ConstIterator it = d->categories.constBegin(); - for ( ; it != d->categories.end(); ++it ) - w.appendChild( textTag(doc, "KEYWORD", *it) ); + for (; it != d->categories.end(); ++it) + w.appendChild(textTag(doc, "KEYWORD", *it)); v.appendChild(w); } - if ( !d->note.isEmpty() ) - v.appendChild( textTag(doc, "NOTE", d->note) ); - if ( !d->prodId.isEmpty() ) - v.appendChild( textTag(doc, "PRODID", d->prodId) ); - if ( !d->rev.isEmpty() ) - v.appendChild( textTag(doc, "REV", d->rev) ); - if ( !d->sortString.isEmpty() ) - v.appendChild( textTag(doc, "SORT-STRING", d->sortString) ); + if (!d->note.isEmpty()) + v.appendChild(textTag(doc, "NOTE", d->note)); + if (!d->prodId.isEmpty()) + v.appendChild(textTag(doc, "PRODID", d->prodId)); + if (!d->rev.isEmpty()) + v.appendChild(textTag(doc, "REV", d->rev)); + if (!d->sortString.isEmpty()) + v.appendChild(textTag(doc, "SORT-STRING", d->sortString)); - if ( !d->sound.isEmpty() || !d->soundURI.isEmpty() || !d->soundPhonetic.isEmpty() ) { + if (!d->sound.isEmpty() || !d->soundURI.isEmpty() || !d->soundPhonetic.isEmpty()) { QDomElement w = doc->createElement("SOUND"); - if ( !d->sound.isEmpty() ) - w.appendChild( textTag(doc, "BINVAL", foldString( QCA::Base64().arrayToString(d->sound)) ) ); - else if ( !d->soundURI.isEmpty() ) - w.appendChild( textTag(doc, "EXTVAL", d->soundURI) ); - else if ( !d->soundPhonetic.isEmpty() ) - w.appendChild( textTag(doc, "PHONETIC", d->soundPhonetic) ); + if (!d->sound.isEmpty()) + w.appendChild(textTag(doc, "BINVAL", foldString(QCA::Base64().arrayToString(d->sound)))); + else if (!d->soundURI.isEmpty()) + w.appendChild(textTag(doc, "EXTVAL", d->soundURI)); + else if (!d->soundPhonetic.isEmpty()) + w.appendChild(textTag(doc, "PHONETIC", d->soundPhonetic)); v.appendChild(w); } - if ( !d->uid.isEmpty() ) - v.appendChild( textTag(doc, "UID", d->uid) ); - if ( !d->url.isEmpty() ) - v.appendChild( textTag(doc, "URL", d->url) ); - if ( !d->desc.isEmpty() ) - v.appendChild( textTag(doc, "DESC", d->desc) ); + if (!d->uid.isEmpty()) + v.appendChild(textTag(doc, "UID", d->uid)); + if (!d->url.isEmpty()) + v.appendChild(textTag(doc, "URL", d->url)); + if (!d->desc.isEmpty()) + v.appendChild(textTag(doc, "DESC", d->desc)); - if ( d->privacyClass != pcNone ) { + if (d->privacyClass != pcNone) { QDomElement w = doc->createElement("CLASS"); - if ( d->privacyClass == pcPublic ) - w.appendChild( emptyTag(doc, "PUBLIC") ); - else if ( d->privacyClass == pcPrivate ) - w.appendChild( emptyTag(doc, "PRIVATE") ); - else if ( d->privacyClass == pcConfidential ) - w.appendChild( emptyTag(doc, "CONFIDENTIAL") ); + if (d->privacyClass == pcPublic) + w.appendChild(emptyTag(doc, "PUBLIC")); + else if (d->privacyClass == pcPrivate) + w.appendChild(emptyTag(doc, "PRIVATE")); + else if (d->privacyClass == pcConfidential) + w.appendChild(emptyTag(doc, "CONFIDENTIAL")); v.appendChild(w); } - if ( !d->key.isEmpty() ) { + if (!d->key.isEmpty()) { QDomElement w = doc->createElement("KEY"); // TODO: Justin, please check out this code - w.appendChild( textTag(doc, "TYPE", "text/plain")); // FIXME - w.appendChild( textTag(doc, "CRED", QString::fromUtf8(d->key)) ); // FIXME + w.appendChild(textTag(doc, "TYPE", "text/plain")); // FIXME + w.appendChild(textTag(doc, "CRED", QString::fromUtf8(d->key))); // FIXME v.appendChild(w); } @@ -515,42 +477,41 @@ QDomElement VCard::toXml(QDomDocument *doc) const VCard VCard::fromXml(const QDomElement &q) { - if ( q.tagName().toUpper() != "VCARD" ) + if (q.tagName().toUpper() != "VCARD") return VCard(); VCard v; v.d = new VCardPrivate; QDomNode n = q.firstChild(); - for ( ; !n.isNull(); n = n.nextSibling() ) { + for (; !n.isNull(); n = n.nextSibling()) { QDomElement i = n.toElement(); - if ( i.isNull() ) + if (i.isNull()) continue; QString tag = i.tagName().toUpper(); QDomElement e; - if ( tag == "VERSION" ) + if (tag == "VERSION") v.d->version = i.text().trimmed(); - else if ( tag == "FN" ) + else if (tag == "FN") v.d->fullName = i.text().trimmed(); - else if ( tag == "N" ) { + else if (tag == "N") { v.d->familyName = subTagText(i, "FAMILY"); v.d->givenName = subTagText(i, "GIVEN"); v.d->middleName = subTagText(i, "MIDDLE"); v.d->prefixName = subTagText(i, "PREFIX"); v.d->suffixName = subTagText(i, "SUFFIX"); - } - else if ( tag == "NICKNAME" ) + } else if (tag == "NICKNAME") v.d->nickName = i.text().trimmed(); - else if ( tag == "PHOTO" ) { - v.d->photo = QCA::Base64().stringToArray(subTagText(i, "BINVAL").replace(QRegExp("[\r\n]+"),"")).toByteArray(); + else if (tag == "PHOTO") { + v.d->photo + = QCA::Base64().stringToArray(subTagText(i, "BINVAL").replace(QRegExp("[\r\n]+"), "")).toByteArray(); v.d->photoURI = subTagText(i, "EXTVAL"); - } - else if ( tag == "BDAY" ) + } else if (tag == "BDAY") v.d->bday = i.text().trimmed(); - else if ( tag == "ADR" ) { + else if (tag == "ADR") { Address a; a.home = hasSubTag(i, "HOME"); @@ -569,17 +530,16 @@ VCard VCard::fromXml(const QDomElement &q) a.pcode = subTagText(i, "PCODE"); a.country = subTagText(i, "CTRY"); - if ( a.country.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9 - if ( hasSubTag(i, "COUNTRY") ) + if (a.country.isEmpty()) // FIXME: Workaround for Psi prior to 0.9 + if (hasSubTag(i, "COUNTRY")) a.country = subTagText(i, "COUNTRY"); - if ( a.extaddr.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9 - if ( hasSubTag(i, "EXTADD") ) + if (a.extaddr.isEmpty()) // FIXME: Workaround for Psi prior to 0.9 + if (hasSubTag(i, "EXTADD")) a.extaddr = subTagText(i, "EXTADD"); - v.d->addressList.append ( a ); - } - else if ( tag == "LABEL" ) { + v.d->addressList.append(a); + } else if (tag == "LABEL") { Label l; l.home = hasSubTag(i, "HOME"); @@ -591,18 +551,17 @@ VCard VCard::fromXml(const QDomElement &q) l.pref = hasSubTag(i, "PREF"); QDomNode nn = i.firstChild(); - for ( ; !nn.isNull(); nn = nn.nextSibling() ) { + for (; !nn.isNull(); nn = nn.nextSibling()) { QDomElement ii = nn.toElement(); - if ( ii.isNull() ) + if (ii.isNull()) continue; - if ( ii.tagName().toUpper() == "LINE" ) - l.lines.append ( ii.text().trimmed() ); + if (ii.tagName().toUpper() == "LINE") + l.lines.append(ii.text().trimmed()); } - v.d->labelList.append ( l ); - } - else if ( tag == "TEL" ) { + v.d->labelList.append(l); + } else if (tag == "TEL") { Phone p; p.home = hasSubTag(i, "HOME"); @@ -621,13 +580,12 @@ VCard VCard::fromXml(const QDomElement &q) p.number = subTagText(i, "NUMBER"); - if ( p.number.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9 - if ( hasSubTag(i, "VOICE") ) + if (p.number.isEmpty()) // FIXME: Workaround for Psi prior to 0.9 + if (hasSubTag(i, "VOICE")) p.number = subTagText(i, "VOICE"); - v.d->phoneList.append ( p ); - } - else if ( tag == "EMAIL" ) { + v.d->phoneList.append(p); + } else if (tag == "EMAIL") { Email m; m.home = hasSubTag(i, "HOME"); @@ -637,106 +595,98 @@ VCard VCard::fromXml(const QDomElement &q) m.userid = subTagText(i, "USERID"); - if ( m.userid.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9 - if ( !i.text().isEmpty() ) + if (m.userid.isEmpty()) // FIXME: Workaround for Psi prior to 0.9 + if (!i.text().isEmpty()) m.userid = i.text().trimmed(); - v.d->emailList.append ( m ); - } - else if ( tag == "JABBERID" ) + v.d->emailList.append(m); + } else if (tag == "JABBERID") v.d->jid = i.text().trimmed(); - else if ( tag == "MAILER" ) + else if (tag == "MAILER") v.d->mailer = i.text().trimmed(); - else if ( tag == "TZ" ) + else if (tag == "TZ") v.d->timezone = i.text().trimmed(); - else if ( tag == "GEO" ) { + else if (tag == "GEO") { v.d->geo.lat = subTagText(i, "LAT"); v.d->geo.lon = subTagText(i, "LON"); - } - else if ( tag == "TITLE" ) + } else if (tag == "TITLE") v.d->title = i.text().trimmed(); - else if ( tag == "ROLE" ) + else if (tag == "ROLE") v.d->role = i.text().trimmed(); - else if ( tag == "LOGO" ) { - v.d->logo = QCA::Base64().stringToArray( subTagText(i, "BINVAL").replace("\n","") ).toByteArray(); + else if (tag == "LOGO") { + v.d->logo = QCA::Base64().stringToArray(subTagText(i, "BINVAL").replace("\n", "")).toByteArray(); v.d->logoURI = subTagText(i, "EXTVAL"); - } - else if ( tag == "AGENT" ) { + } else if (tag == "AGENT") { e = i.firstChildElement("VCARD"); - if ( !e.isNull() ) { + if (!e.isNull()) { VCard a; - if ( a.fromXml(e) ) { - if ( !v.d->agent ) + if (a.fromXml(e)) { + if (!v.d->agent) v.d->agent = QSharedPointer(new VCard); *(v.d->agent) = a; } } v.d->agentURI = subTagText(i, "EXTVAL"); - } - else if ( tag == "ORG" ) { + } else if (tag == "ORG") { v.d->org.name = subTagText(i, "ORGNAME"); QDomNode nn = i.firstChild(); - for ( ; !nn.isNull(); nn = nn.nextSibling() ) { + for (; !nn.isNull(); nn = nn.nextSibling()) { QDomElement ii = nn.toElement(); - if ( ii.isNull() ) + if (ii.isNull()) continue; - if ( ii.tagName().toUpper() == "ORGUNIT" ) - v.d->org.unit.append( ii.text().trimmed() ); + if (ii.tagName().toUpper() == "ORGUNIT") + v.d->org.unit.append(ii.text().trimmed()); } - } - else if ( tag == "CATEGORIES") { + } else if (tag == "CATEGORIES") { QDomNode nn = i.firstChild(); - for ( ; !nn.isNull(); nn = nn.nextSibling() ) { + for (; !nn.isNull(); nn = nn.nextSibling()) { QDomElement ee = nn.toElement(); - if ( ee.isNull() ) + if (ee.isNull()) continue; - if ( ee.tagName().toUpper() == "KEYWORD" ) + if (ee.tagName().toUpper() == "KEYWORD") v.d->categories << ee.text().trimmed(); } - } - else if ( tag == "NOTE" ) + } else if (tag == "NOTE") v.d->note = i.text().trimmed(); - else if ( tag == "PRODID" ) + else if (tag == "PRODID") v.d->prodId = i.text().trimmed(); - else if ( tag == "REV" ) + else if (tag == "REV") v.d->rev = i.text().trimmed(); - else if ( tag == "SORT-STRING" ) + else if (tag == "SORT-STRING") v.d->sortString = i.text().trimmed(); - else if ( tag == "SOUND" ) { - v.d->sound = QCA::Base64().stringToArray( subTagText(i, "BINVAL").replace("\n","") ).toByteArray(); + else if (tag == "SOUND") { + v.d->sound = QCA::Base64().stringToArray(subTagText(i, "BINVAL").replace("\n", "")).toByteArray(); v.d->soundURI = subTagText(i, "EXTVAL"); v.d->soundPhonetic = subTagText(i, "PHONETIC"); - } - else if ( tag == "UID" ) + } else if (tag == "UID") v.d->uid = i.text().trimmed(); - else if ( tag == "URL") + else if (tag == "URL") v.d->url = i.text().trimmed(); - else if ( tag == "DESC" ) + else if (tag == "DESC") v.d->desc = i.text().trimmed(); - else if ( tag == "CLASS" ) { - if ( hasSubTag(i, "PUBLIC") ) + else if (tag == "CLASS") { + if (hasSubTag(i, "PUBLIC")) v.d->privacyClass = pcPublic; - else if ( hasSubTag(i, "PRIVATE") ) + else if (hasSubTag(i, "PRIVATE")) v.d->privacyClass = pcPrivate; - else if ( hasSubTag(i, "CONFIDENTIAL") ) + else if (hasSubTag(i, "CONFIDENTIAL")) v.d->privacyClass = pcConfidential; - } - else if ( tag == "KEY" ) { + } else if (tag == "KEY") { // TODO: Justin, please check out this code - e = i.firstChildElement("TYPE"); + e = i.firstChildElement("TYPE"); QString type = "text/plain"; - if ( !e.isNull() ) + if (!e.isNull()) type = e.text().trimmed(); e = i.firstChildElement("CRED"); - if ( e.isNull() ) + if (e.isNull()) e = i.firstChildElement("BINVAL"); // case for very clever clients ;-) - if ( !e.isNull() ) + if (!e.isNull()) v.d->key = e.text().toUtf8(); // FIXME } } @@ -744,10 +694,7 @@ VCard VCard::fromXml(const QDomElement &q) return v; } -bool VCard::isEmpty() const -{ - return !d || d->isEmpty(); -} +bool VCard::isEmpty() const { return !d || d->isEmpty(); } VCard VCard::makeEmpty() { @@ -758,275 +705,118 @@ VCard VCard::makeEmpty() // Some constructors -VCard::Address::Address() -{ - home = work = postal = parcel = dom = intl = pref = false; -} +VCard::Address::Address() { home = work = postal = parcel = dom = intl = pref = false; } -VCard::Label::Label() -{ - home = work = postal = parcel = dom = intl = pref = false; -} +VCard::Label::Label() { home = work = postal = parcel = dom = intl = pref = false; } VCard::Phone::Phone() { home = work = voice = fax = pager = msg = cell = video = bbs = modem = isdn = pcs = pref = false; } -VCard::Email::Email() -{ - home = work = internet = x400 = false; -} +VCard::Email::Email() { home = work = internet = x400 = false; } -VCard::Geo::Geo() -{ -} +VCard::Geo::Geo() {} -VCard::Org::Org() -{ -} +VCard::Org::Org() {} // vCard properties... -const QString &VCard::version() const -{ - return d->version; -} +const QString &VCard::version() const { return d->version; } -void VCard::setVersion(const QString &v) -{ - d->version = v; -} +void VCard::setVersion(const QString &v) { d->version = v; } -const QString &VCard::fullName() const -{ - return d->fullName; -} +const QString &VCard::fullName() const { return d->fullName; } -void VCard::setFullName(const QString &n) -{ - d->fullName = n; -} +void VCard::setFullName(const QString &n) { d->fullName = n; } -const QString &VCard::familyName() const -{ - return d->familyName; -} +const QString &VCard::familyName() const { return d->familyName; } -void VCard::setFamilyName(const QString &n) -{ - d->familyName = n; -} +void VCard::setFamilyName(const QString &n) { d->familyName = n; } -const QString &VCard::givenName() const -{ - return d->givenName; -} +const QString &VCard::givenName() const { return d->givenName; } -void VCard::setGivenName(const QString &n) -{ - d->givenName = n; -} +void VCard::setGivenName(const QString &n) { d->givenName = n; } -const QString &VCard::middleName() const -{ - return d->middleName; -} +const QString &VCard::middleName() const { return d->middleName; } -void VCard::setMiddleName(const QString &n) -{ - d->middleName = n; -} +void VCard::setMiddleName(const QString &n) { d->middleName = n; } -const QString &VCard::prefixName() const -{ - return d->prefixName; -} +const QString &VCard::prefixName() const { return d->prefixName; } -void VCard::setPrefixName(const QString &p) -{ - d->prefixName = p; -} +void VCard::setPrefixName(const QString &p) { d->prefixName = p; } -const QString &VCard::suffixName() const -{ - return d->suffixName; -} +const QString &VCard::suffixName() const { return d->suffixName; } -void VCard::setSuffixName(const QString &s) -{ - d->suffixName = s; -} +void VCard::setSuffixName(const QString &s) { d->suffixName = s; } -const QString &VCard::nickName() const -{ - return d->nickName; -} +const QString &VCard::nickName() const { return d->nickName; } -void VCard::setNickName(const QString &n) -{ - d->nickName = n; -} +void VCard::setNickName(const QString &n) { d->nickName = n; } -const QByteArray &VCard::photo() const -{ - return d->photo; -} +const QByteArray &VCard::photo() const { return d->photo; } -void VCard::setPhoto(const QByteArray &i) -{ - d->photo = i; -} +void VCard::setPhoto(const QByteArray &i) { d->photo = i; } -const QString &VCard::photoURI() const -{ - return d->photoURI; -} +const QString &VCard::photoURI() const { return d->photoURI; } -void VCard::setPhotoURI(const QString &p) -{ - d->photoURI = p; -} +void VCard::setPhotoURI(const QString &p) { d->photoURI = p; } -const QDate VCard::bday() const -{ - return QDate::fromString(d->bday); -} +const QDate VCard::bday() const { return QDate::fromString(d->bday); } -void VCard::setBday(const QDate &date) -{ - d->bday = date.toString(); -} +void VCard::setBday(const QDate &date) { d->bday = date.toString(); } -const QString &VCard::bdayStr() const -{ - return d->bday; -} +const QString &VCard::bdayStr() const { return d->bday; } -void VCard::setBdayStr(const QString &date) -{ - d->bday = date; -} +void VCard::setBdayStr(const QString &date) { d->bday = date; } -const VCard::AddressList &VCard::addressList() const -{ - return d->addressList; -} +const VCard::AddressList &VCard::addressList() const { return d->addressList; } -void VCard::setAddressList(const VCard::AddressList &a) -{ - d->addressList = a; -} +void VCard::setAddressList(const VCard::AddressList &a) { d->addressList = a; } -const VCard::LabelList &VCard::labelList() const -{ - return d->labelList; -} +const VCard::LabelList &VCard::labelList() const { return d->labelList; } -void VCard::setLabelList(const VCard::LabelList &l) -{ - d->labelList = l; -} +void VCard::setLabelList(const VCard::LabelList &l) { d->labelList = l; } -const VCard::PhoneList &VCard::phoneList() const -{ - return d->phoneList; -} +const VCard::PhoneList &VCard::phoneList() const { return d->phoneList; } -void VCard::setPhoneList(const VCard::PhoneList &p) -{ - d->phoneList = p; -} +void VCard::setPhoneList(const VCard::PhoneList &p) { d->phoneList = p; } -const VCard::EmailList &VCard::emailList() const -{ - return d->emailList; -} +const VCard::EmailList &VCard::emailList() const { return d->emailList; } -void VCard::setEmailList(const VCard::EmailList &e) -{ - d->emailList = e; -} +void VCard::setEmailList(const VCard::EmailList &e) { d->emailList = e; } -const QString &VCard::jid() const -{ - return d->jid; -} +const QString &VCard::jid() const { return d->jid; } -void VCard::setJid(const QString &j) -{ - d->jid = j; -} +void VCard::setJid(const QString &j) { d->jid = j; } -const QString &VCard::mailer() const -{ - return d->mailer; -} +const QString &VCard::mailer() const { return d->mailer; } -void VCard::setMailer(const QString &m) -{ - d->mailer = m; -} +void VCard::setMailer(const QString &m) { d->mailer = m; } -const QString &VCard::timezone() const -{ - return d->timezone; -} +const QString &VCard::timezone() const { return d->timezone; } -void VCard::setTimezone(const QString &t) -{ - d->timezone = t; -} +void VCard::setTimezone(const QString &t) { d->timezone = t; } -const VCard::Geo &VCard::geo() const -{ - return d->geo; -} +const VCard::Geo &VCard::geo() const { return d->geo; } -void VCard::setGeo(const VCard::Geo &g) -{ - d->geo = g; -} +void VCard::setGeo(const VCard::Geo &g) { d->geo = g; } -const QString &VCard::title() const -{ - return d->title; -} +const QString &VCard::title() const { return d->title; } -void VCard::setTitle(const QString &t) -{ - d->title = t; -} +void VCard::setTitle(const QString &t) { d->title = t; } -const QString &VCard::role() const -{ - return d->role; -} +const QString &VCard::role() const { return d->role; } -void VCard::setRole(const QString &r) -{ - d->role = r; -} +void VCard::setRole(const QString &r) { d->role = r; } -const QByteArray &VCard::logo() const -{ - return d->logo; -} +const QByteArray &VCard::logo() const { return d->logo; } -void VCard::setLogo(const QByteArray &i) -{ - d->logo = i; -} +void VCard::setLogo(const QByteArray &i) { d->logo = i; } -const QString &VCard::logoURI() const -{ - return d->logoURI; -} +const QString &VCard::logoURI() const { return d->logoURI; } -void VCard::setLogoURI(const QString &l) -{ - d->logoURI = l; -} +void VCard::setLogoURI(const QString &l) { d->logoURI = l; } VCard VCard::agent() const { @@ -1038,158 +828,68 @@ VCard VCard::agent() const void VCard::setAgent(const VCard &v) { - if ( !d->agent ) + if (!d->agent) d->agent = QSharedPointer(new VCard); *(d->agent) = v; } -const QString VCard::agentURI() const -{ - return d->agentURI; -} +const QString VCard::agentURI() const { return d->agentURI; } -void VCard::setAgentURI(const QString &a) -{ - d->agentURI = a; -} +void VCard::setAgentURI(const QString &a) { d->agentURI = a; } -const VCard::Org &VCard::org() const -{ - return d->org; -} +const VCard::Org &VCard::org() const { return d->org; } -void VCard::setOrg(const VCard::Org &o) -{ - d->org = o; -} +void VCard::setOrg(const VCard::Org &o) { d->org = o; } -const QStringList &VCard::categories() const -{ - return d->categories; -} +const QStringList &VCard::categories() const { return d->categories; } -void VCard::setCategories(const QStringList &c) -{ - d->categories = c; -} +void VCard::setCategories(const QStringList &c) { d->categories = c; } -const QString &VCard::note() const -{ - return d->note; -} +const QString &VCard::note() const { return d->note; } -void VCard::setNote(const QString &n) -{ - d->note = n; -} +void VCard::setNote(const QString &n) { d->note = n; } -const QString &VCard::prodId() const -{ - return d->prodId; -} +const QString &VCard::prodId() const { return d->prodId; } -void VCard::setProdId(const QString &p) -{ - d->prodId = p; -} +void VCard::setProdId(const QString &p) { d->prodId = p; } -const QString &VCard::rev() const -{ - return d->rev; -} +const QString &VCard::rev() const { return d->rev; } -void VCard::setRev(const QString &r) -{ - d->rev = r; -} +void VCard::setRev(const QString &r) { d->rev = r; } -const QString &VCard::sortString() const -{ - return d->sortString; -} +const QString &VCard::sortString() const { return d->sortString; } -void VCard::setSortString(const QString &s) -{ - d->sortString = s; -} +void VCard::setSortString(const QString &s) { d->sortString = s; } -const QByteArray &VCard::sound() const -{ - return d->sound; -} +const QByteArray &VCard::sound() const { return d->sound; } -void VCard::setSound(const QByteArray &s) -{ - d->sound = s; -} +void VCard::setSound(const QByteArray &s) { d->sound = s; } -const QString &VCard::soundURI() const -{ - return d->soundURI; -} +const QString &VCard::soundURI() const { return d->soundURI; } -void VCard::setSoundURI(const QString &s) -{ - d->soundURI = s; -} +void VCard::setSoundURI(const QString &s) { d->soundURI = s; } -const QString &VCard::soundPhonetic() const -{ - return d->soundPhonetic; -} +const QString &VCard::soundPhonetic() const { return d->soundPhonetic; } -void VCard::setSoundPhonetic(const QString &s) -{ - d->soundPhonetic = s; -} +void VCard::setSoundPhonetic(const QString &s) { d->soundPhonetic = s; } -const QString &VCard::uid() const -{ - return d->uid; -} +const QString &VCard::uid() const { return d->uid; } -void VCard::setUid(const QString &u) -{ - d->uid = u; -} +void VCard::setUid(const QString &u) { d->uid = u; } -const QString &VCard::url() const -{ - return d->url; -} +const QString &VCard::url() const { return d->url; } -void VCard::setUrl(const QString &u) -{ - d->url = u; -} +void VCard::setUrl(const QString &u) { d->url = u; } -const QString &VCard::desc() const -{ - return d->desc; -} +const QString &VCard::desc() const { return d->desc; } -void VCard::setDesc(const QString &desc) -{ - d->desc = desc; -} +void VCard::setDesc(const QString &desc) { d->desc = desc; } -const VCard::PrivacyClass &VCard::privacyClass() const -{ - return d->privacyClass; -} +const VCard::PrivacyClass &VCard::privacyClass() const { return d->privacyClass; } -void VCard::setPrivacyClass(const VCard::PrivacyClass &c) -{ - d->privacyClass = c; -} +void VCard::setPrivacyClass(const VCard::PrivacyClass &c) { d->privacyClass = c; } -const QByteArray &VCard::key() const -{ - return d->key; -} +const QByteArray &VCard::key() const { return d->key; } -void VCard::setKey(const QByteArray &k) -{ - d->key = k; -} +void VCard::setKey(const QByteArray &k) { d->key = k; } } // namespace XMPP diff --git a/src/xmpp/xmpp-im/xmpp_vcard.h b/src/xmpp/xmpp-im/xmpp_vcard.h index 8dda52d3..5f4a7075 100644 --- a/src/xmpp/xmpp-im/xmpp_vcard.h +++ b/src/xmpp/xmpp-im/xmpp_vcard.h @@ -29,240 +29,234 @@ class QDate; namespace XMPP { - class VCardPrivate; +class VCardPrivate; - class VCard - { +class VCard { +public: + VCard(); + VCard(const VCard &); + VCard &operator=(const VCard &); + ~VCard(); + + QDomElement toXml(QDomDocument *) const; + static VCard fromXml(const QDomElement &); + bool isEmpty() const; + inline bool isNull() const { return !d; } + inline bool operator!() const { return !d; } + inline operator bool() const { return !!d; } + static VCard makeEmpty(); + + const QString &version() const; + void setVersion(const QString &); + + const QString &fullName() const; + void setFullName(const QString &); + + const QString &familyName() const; + void setFamilyName(const QString &); + + const QString &givenName() const; + void setGivenName(const QString &); + + const QString &middleName() const; + void setMiddleName(const QString &); + + const QString &prefixName() const; + void setPrefixName(const QString &); + + const QString &suffixName() const; + void setSuffixName(const QString &); + + const QString &nickName() const; + void setNickName(const QString &); + + const QByteArray &photo() const; + void setPhoto(const QByteArray &); + + const QString &photoURI() const; + void setPhotoURI(const QString &); + + const QDate bday() const; + void setBday(const QDate &); + + const QString &bdayStr() const; + void setBdayStr(const QString &); + + class Address { public: - VCard(); - VCard(const VCard &); - VCard & operator=(const VCard &); - ~VCard(); - - QDomElement toXml(QDomDocument *) const; - static VCard fromXml(const QDomElement &); - bool isEmpty() const; - inline bool isNull() const { return !d; } - inline bool operator!() const { return !d; } - inline operator bool() const { return !!d; } - static VCard makeEmpty(); - - const QString &version() const; - void setVersion(const QString &); - - const QString &fullName() const; - void setFullName(const QString &); - - const QString &familyName() const; - void setFamilyName(const QString &); - - const QString &givenName() const; - void setGivenName(const QString &); - - const QString &middleName() const; - void setMiddleName(const QString &); - - const QString &prefixName() const; - void setPrefixName(const QString &); - - const QString &suffixName() const; - void setSuffixName(const QString &); - - const QString &nickName() const; - void setNickName(const QString &); - - const QByteArray &photo() const; - void setPhoto(const QByteArray &); - - const QString &photoURI() const; - void setPhotoURI(const QString &); - - const QDate bday() const; - void setBday(const QDate &); - - const QString &bdayStr() const; - void setBdayStr(const QString &); - - class Address { - public: - Address(); - - bool home; - bool work; - bool postal; - bool parcel; - - bool dom; - bool intl; - - bool pref; - - QString pobox; - QString extaddr; - QString street; - QString locality; - QString region; - QString pcode; - QString country; - }; - typedef QList
AddressList; - const AddressList &addressList() const; - void setAddressList(const AddressList &); - - class Label { - public: - Label(); - - bool home; - bool work; - bool postal; - bool parcel; - - bool dom; - bool intl; - - bool pref; - - QStringList lines; - }; - typedef QList