2
* Copyright (C) 2009 Barracuda Networks, Inc.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
#include "stuntransaction.h"
28
#include "stunmessage.h"
30
Q_DECLARE_METATYPE(XMPP::StunTransaction::Error)
34
//----------------------------------------------------------------------------
36
//----------------------------------------------------------------------------
37
class StunTransaction::Private : public QObject
44
StunTransaction::Mode mode;
55
Private(StunTransaction *_q) :
59
qRegisterMetaType<StunTransaction::Error>();
64
connect(t, SIGNAL(timeout()), SLOT(t_timeout()));
65
t->setSingleShot(true);
67
// defaults from RFC 5389
81
void start(StunTransaction::Mode _mode, const StunMessage &msg, const QString &_stuser, const QString &stpass)
85
StunMessage out = msg;
87
id = QByteArray((const char *)msg.id(), 12);
92
QList<StunMessage::Attribute> list = out.attributes();
93
StunMessage::Attribute attr;
94
attr.type = 0x0006; // USERNAME
95
attr.value = stuser.toUtf8();
97
out.setAttributes(list);
99
key = stpass.toUtf8();
100
// FIXME: why also fingerprint? this is such a mess
101
packet = out.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, key);
104
packet = out.toBinary();
107
// since a transaction is not cancelable nor reusable,
108
// there's no DOR-SR issue here
109
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection,
110
Q_ARG(XMPP::StunTransaction::Error, ErrorGeneric));
115
tries = 1; // assume the user does its job
117
if(mode == StunTransaction::Udp)
119
last_interval = rm * rto;
123
else if(mode == StunTransaction::Tcp)
131
//printf("send: %d\n", time.elapsed());
137
if(mode == StunTransaction::Tcp || tries == rc)
139
emit q->error(StunTransaction::ErrorTimeout);
146
t->start(last_interval);
154
//printf("send: %d\n", time.elapsed());
155
emit q->retransmit();
159
bool processIncoming(const StunMessage &msg)
164
if(msg.mclass() != StunMessage::SuccessResponse && msg.mclass() != StunMessage::ErrorResponse)
167
if(memcmp(msg.id(), id.data(), 12) != 0)
172
emit q->finished(msg);
177
StunTransaction::StunTransaction(QObject *parent) :
180
d = new Private(this);
183
StunTransaction::~StunTransaction()
188
void StunTransaction::start(Mode mode, const StunMessage &msg, const QString &stuser, const QString &stpass)
190
Q_ASSERT(!d->active);
191
d->start(mode, msg, stuser, stpass);
194
QByteArray StunTransaction::transactionId() const
199
QByteArray StunTransaction::packet() const
204
void StunTransaction::setRTO(int i)
206
Q_ASSERT(!d->active);
210
void StunTransaction::setRc(int i)
212
Q_ASSERT(!d->active);
216
void StunTransaction::setRm(int i)
218
Q_ASSERT(!d->active);
222
void StunTransaction::setTi(int i)
224
Q_ASSERT(!d->active);
228
bool StunTransaction::writeIncomingMessage(const StunMessage &msg)
230
return d->processIncoming(msg);
233
//----------------------------------------------------------------------------
234
// StunTransactionPool
235
//----------------------------------------------------------------------------
236
class StunTransactionPool::Private : public QObject
241
StunTransactionPool *q;
242
StunTransaction::Mode mode;
243
QHash<StunTransaction*,QByteArray> transToId;
244
QHash<QByteArray,StunTransaction*> idToTrans;
245
bool shortTermCredentials;
246
QString username, password;
248
Private(StunTransactionPool *_q) :
251
shortTermCredentials(false)
255
void insert(StunTransaction *trans)
257
connect(trans, SIGNAL(retransmit()), this, SLOT(trans_retransmit()));
259
QByteArray id = trans->transactionId();
260
transToId.insert(trans, id);
261
idToTrans.insert(id, trans);
263
// send the first transmit attempt
264
emit q->retransmit(trans);
267
void remove(StunTransaction *trans)
269
disconnect(trans, SIGNAL(retransmit()), this, SLOT(trans_retransmit()));
271
QByteArray id = transToId.value(trans);
272
transToId.remove(trans);
273
idToTrans.remove(id);
277
void trans_retransmit()
279
StunTransaction *trans = (StunTransaction *)sender();
280
emit q->retransmit(trans);
284
StunTransactionPool::StunTransactionPool(StunTransaction::Mode mode, QObject *parent) :
287
d = new Private(this);
291
StunTransactionPool::~StunTransactionPool()
296
StunTransaction::Mode StunTransactionPool::mode() const
301
QByteArray StunTransactionPool::generateId() const
307
id = QCA::Random::randomArray(12).toByteArray();
308
} while(d->idToTrans.contains(id));
313
void StunTransactionPool::insert(StunTransaction *trans)
315
Q_ASSERT(!trans->transactionId().isEmpty());
319
void StunTransactionPool::remove(StunTransaction *trans)
324
bool StunTransactionPool::writeIncomingMessage(const StunMessage &msg)
326
if(msg.mclass() != StunMessage::SuccessResponse && msg.mclass() != StunMessage::ErrorResponse)
329
StunTransaction *trans = d->idToTrans.value(QByteArray::fromRawData((const char *)msg.id(), 12));
333
return trans->writeIncomingMessage(msg);
336
QString StunTransactionPool::realm() const
342
void StunTransactionPool::setUsername(const QString &username)
344
d->username = username;
347
void StunTransactionPool::setPassword(const QCA::SecureArray &password)
350
d->password = QString::fromUtf8(password.toByteArray());
353
void StunTransactionPool::setRealm(const QString &realm)
359
void StunTransactionPool::setShortTermCredentialsEnabled(bool enabled)
361
d->shortTermCredentials = enabled;
364
void StunTransactionPool::continueAfterParams()
369
QString StunTransactionPool::username() const
374
QString StunTransactionPool::password() const
381
#include "stuntransaction.moc"