aboutsummaryrefslogtreecommitdiff
path: root/src/base/QXmppStun.cpp
diff options
context:
space:
mode:
authorJeremy Lainé <jeremy.laine@m4x.org>2015-09-03 11:03:18 +0200
committerJeremy Lainé <jeremy.laine@m4x.org>2015-09-03 11:10:11 +0200
commit1d828207bbab3b53ec251ac311d761a99e8977e5 (patch)
treecf5db603955197bab97255cba7766b410e69626f /src/base/QXmppStun.cpp
parenteea8f8509e4262d084e072e1bee2268ad384ec06 (diff)
downloadqxmpp-1d828207bbab3b53ec251ac311d761a99e8977e5.tar.gz
Add QXmppIceConnection::gatheringState property
Diffstat (limited to 'src/base/QXmppStun.cpp')
-rw-r--r--src/base/QXmppStun.cpp77
1 files changed, 76 insertions, 1 deletions
diff --git a/src/base/QXmppStun.cpp b/src/base/QXmppStun.cpp
index 18a3342d..86d4004a 100644
--- a/src/base/QXmppStun.cpp
+++ b/src/base/QXmppStun.cpp
@@ -42,6 +42,12 @@ static const quint16 STUN_HEADER = 20;
static const quint8 STUN_IPV4 = 0x01;
static const quint8 STUN_IPV6 = 0x02;
+static const char* gathering_states[] = {
+ "new",
+ "gathering",
+ "complete"
+};
+
static const char* pair_states[] = {
"frozen",
"waiting",
@@ -1761,6 +1767,8 @@ public:
const QXmppIcePrivate* const config;
CandidatePair *fallbackPair;
+ QXmppIceConnection::GatheringState gatheringState;
+
QList<QXmppJingleCandidate> localCandidates;
quint32 peerReflexivePriority;
@@ -1786,6 +1794,7 @@ QXmppIceComponentPrivate::QXmppIceComponentPrivate(int component_, QXmppIcePriva
, component(component_)
, config(config_)
, fallbackPair(0)
+ , gatheringState(QXmppIceConnection::NewGatheringState)
, peerReflexivePriority(0)
, timer(0)
, turnAllocation(0)
@@ -1909,6 +1918,8 @@ void QXmppIceComponentPrivate::setSockets(QList<QUdpSocket*> sockets)
transports << turnAllocation;
turnAllocation->connectToHost();
}
+
+ q->updateGatheringState();
}
void QXmppIceComponentPrivate::setTurnServer(const QHostAddress &host, quint16 port)
@@ -1965,6 +1976,9 @@ QXmppIceComponent::QXmppIceComponent(int component, QXmppIcePrivate *config, QOb
check = connect(d->turnAllocation, SIGNAL(datagramReceived(QByteArray,QHostAddress,quint16)),
this, SLOT(handleDatagram(QByteArray,QHostAddress,quint16)));
Q_ASSERT(check);
+ check = connect(d->turnAllocation, SIGNAL(disconnected()),
+ this, SLOT(updateGatheringState()));
+ Q_ASSERT(check);
// calculate peer-reflexive candidate priority
// see RFC 5245 - 7.1.2.1. PRIORITY and USE-CANDIDATE
@@ -2313,6 +2327,7 @@ void QXmppIceComponent::transactionFinished()
transaction->response().errorPhrase));
}
d->stunTransactions.remove(transaction);
+ updateGatheringState();
return;
}
}
@@ -2328,6 +2343,7 @@ void QXmppIceComponent::turnConnected()
d->localCandidates << candidate;
emit localCandidatesChanged();
+ updateGatheringState();
}
static QList<QUdpSocket*> reservePort(const QList<QHostAddress> &addresses, quint16 port, QObject *parent)
@@ -2443,6 +2459,23 @@ qint64 QXmppIceComponent::sendDatagram(const QByteArray &datagram)
return pair->transport->writeDatagram(datagram, pair->remote.host(), pair->remote.port());
}
+void QXmppIceComponent::updateGatheringState()
+{
+ QXmppIceConnection::GatheringState newGatheringState;
+ if (d->transports.isEmpty())
+ newGatheringState = QXmppIceConnection::NewGatheringState;
+ else if (!d->stunTransactions.isEmpty()
+ || d->turnAllocation->state() == QXmppTurnAllocation::ConnectingState)
+ newGatheringState = QXmppIceConnection::BusyGatheringState;
+ else
+ newGatheringState = QXmppIceConnection::CompleteGatheringState;
+
+ if (newGatheringState != d->gatheringState) {
+ d->gatheringState = newGatheringState;
+ emit gatheringStateChanged();
+ }
+}
+
void QXmppIceComponent::writeStun(const QXmppStunMessage &message)
{
QXmppStunTransaction *transaction = qobject_cast<QXmppStunTransaction*>(sender());
@@ -2476,6 +2509,8 @@ public:
QMap<int, QXmppIceComponent*> components;
QTimer *connectTimer;
+ QXmppIceConnection::GatheringState gatheringState;
+
QHostAddress turnHost;
quint16 turnPort;
QString turnUser;
@@ -2483,7 +2518,8 @@ public:
};
QXmppIceConnectionPrivate::QXmppIceConnectionPrivate()
- : turnPort(0)
+ : gatheringState(QXmppIceConnection::NewGatheringState)
+ , turnPort(0)
{
}
@@ -2549,6 +2585,10 @@ void QXmppIceConnection::addComponent(int component)
this, SLOT(slotConnected()));
Q_ASSERT(check);
+ check = connect(socket, SIGNAL(gatheringStateChanged()),
+ this, SLOT(slotGatheringStateChanged()));
+ Q_ASSERT(check);
+
d->components[component] = socket;
}
@@ -2622,6 +2662,14 @@ bool QXmppIceConnection::isConnected() const
return true;
}
+/// Returns the ICE gathering state, that is the discovery of
+/// local candidates.
+
+QXmppIceConnection::GatheringState QXmppIceConnection::gatheringState() const
+{
+ return d->gatheringState;
+}
+
/// Sets whether the local party has the ICE controlling role.
///
/// \a note This must be called only once, immediately after creating
@@ -2740,6 +2788,33 @@ void QXmppIceConnection::slotConnected()
emit connected();
}
+void QXmppIceConnection::slotGatheringStateChanged()
+{
+ GatheringState newGatheringState;
+ bool allComplete = true;
+ bool allNew = true;
+ foreach (QXmppIceComponent *socket, d->components.values()) {
+ if (socket->d->gatheringState != CompleteGatheringState)
+ allComplete = false;
+ if (socket->d->gatheringState != NewGatheringState)
+ allNew = false;
+ }
+ if (allNew)
+ newGatheringState = NewGatheringState;
+ else if (allComplete)
+ newGatheringState = CompleteGatheringState;
+ else
+ newGatheringState = BusyGatheringState;
+
+ if (newGatheringState != d->gatheringState) {
+ info(QString("ICE gathering state changed from '%1' to '%2'").arg(
+ gathering_states[d->gatheringState],
+ gathering_states[newGatheringState]));
+ d->gatheringState = newGatheringState;
+ emit gatheringStateChanged();
+ }
+}
+
void QXmppIceConnection::slotTimeout()
{
warning(QString("ICE negotiation timed out"));