Overview
Request 272 (accepted)
No description set
- Created by pansenmann over 11 years ago
- In state accepted
jreen.spec
Changed
x
1
2
# vim: set sw=4 ts=4 et nu:
3
4
Name: jreen
5
-Version: 1.0.3
6
+Version: 1.1.0
7
%define soname 1
8
Release: 0.pm.1
9
Summary: Qt Jabber/XMPP library
10
libjreen-1.0.3.tar.bz2/src/gui
Deleted
2
1
-(directory)
2
libjreen-1.0.3.tar.bz2/src/multimediadata.cpp
Deleted
91
1
2
-/****************************************************************************
3
-**
4
-** Jreen
5
-**
6
-** Copyright © 2011 Aleksey Sidorov <gorthauer87@yandex.ru>
7
-**
8
-*****************************************************************************
9
-**
10
-** $JREEN_BEGIN_LICENSE$
11
-** This program is free software: you can redistribute it and/or modify
12
-** it under the terms of the GNU General Public License as published by
13
-** the Free Software Foundation, either version 2 of the License, or
14
-** (at your option) any later version.
15
-**
16
-** This program is distributed in the hope that it will be useful,
17
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
-** See the GNU General Public License for more details.
20
-**
21
-** You should have received a copy of the GNU General Public License
22
-** along with this program. If not, see http://www.gnu.org/licenses/.
23
-** $JREEN_END_LICENSE$
24
-**
25
-****************************************************************************/
26
-
27
-#include "multimediadata.h"
28
-
29
-namespace Jreen
30
-{
31
-
32
-class MultimediaDataPrivate : public QSharedData
33
-{
34
-public:
35
- MultimediaDataPrivate() : QSharedData() {}
36
- MultimediaDataPrivate(const MultimediaDataPrivate &other) :
37
- QSharedData(other),
38
- type(other.type),
39
- data(other.data),
40
- attributes(other.attributes)
41
- {
42
- }
43
- MultimediaData::Type type;
44
- QVariantList data;
45
- QVariantMap attributes;
46
-};
47
-
48
-MultimediaData::MultimediaData(Type type,const QVariantList &data,const QVariantMap &attributes) :
49
- d_ptr(new MultimediaDataPrivate)
50
-{
51
- d_ptr->type = type;
52
- d_ptr->data = data;
53
- d_ptr->attributes = attributes;
54
-}
55
-
56
-MultimediaData::MultimediaData(const MultimediaData &other) :
57
- d_ptr(other.d_ptr)
58
-{
59
-}
60
-
61
-MultimediaData::~MultimediaData()
62
-{
63
-
64
-}
65
-
66
-MultimediaData &MultimediaData::operator =(const MultimediaData &o)
67
-{
68
- d_ptr = o.d_ptr;
69
- return *this;
70
-}
71
-
72
-QVariantMap MultimediaData::attributes() const
73
-{
74
- return d_ptr->attributes;
75
-}
76
-QVariantList MultimediaData::data() const
77
-{
78
- return d_ptr->data;
79
-}
80
-void MultimediaData::setData(const QVariantList &data)
81
-{
82
- d_ptr->data = data;
83
-}
84
-
85
-void MultimediaData::setAttributes(const QVariantMap &attributes)
86
-{
87
- d_ptr->attributes = attributes;
88
-}
89
-
90
-} // namespace Jreen
91
libjreen-1.0.3.tar.bz2/src/multimediadata.h
Deleted
61
1
2
-/****************************************************************************
3
-**
4
-** Jreen
5
-**
6
-** Copyright © 2011 Aleksey Sidorov <gorthauer87@yandex.ru>
7
-**
8
-*****************************************************************************
9
-**
10
-** $JREEN_BEGIN_LICENSE$
11
-** This program is free software: you can redistribute it and/or modify
12
-** it under the terms of the GNU General Public License as published by
13
-** the Free Software Foundation, either version 2 of the License, or
14
-** (at your option) any later version.
15
-**
16
-** This program is distributed in the hope that it will be useful,
17
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
-** See the GNU General Public License for more details.
20
-**
21
-** You should have received a copy of the GNU General Public License
22
-** along with this program. If not, see http://www.gnu.org/licenses/.
23
-** $JREEN_END_LICENSE$
24
-**
25
-****************************************************************************/
26
-
27
-#ifndef MULTIMEDIADATA_H
28
-#define MULTIMEDIADATA_H
29
-#include <QVariantMap>
30
-#include "stanzaextension.h"
31
-
32
-namespace Jreen
33
-{
34
-
35
-// XEP-0221
36
-// http://xmpp.org/extensions/xep-0221.html
37
-class MultimediaDataPrivate;
38
-class JREEN_EXPORT MultimediaData
39
-{
40
-public:
41
- enum Type
42
- {
43
- Audio,
44
- Image
45
- };
46
- MultimediaData(Type type,const QVariantList &data,const QVariantMap &attributes = QVariantMap());
47
- MultimediaData(const MultimediaData &other);
48
- ~MultimediaData();
49
- MultimediaData &operator =(const MultimediaData &o);
50
- QVariantMap attributes() const;
51
- QVariantList data() const;
52
- void setData(const QVariantList &data);
53
- void setAttributes(const QVariantMap &attributes);
54
-private:
55
- QSharedDataPointer<MultimediaDataPrivate> d_ptr;
56
- friend class MultimediaDataPrivate;
57
-};
58
-
59
-} // namespace Jreen
60
-#endif // MULTIMEDIADATA_H
61
libjreen-1.0.3.tar.bz2/src/multimediadatafactory.cpp
Deleted
115
1
2
-/****************************************************************************
3
-**
4
-** Jreen
5
-**
6
-** Copyright © 2011 Aleksey Sidorov <gorthauer87@yandex.ru>
7
-**
8
-*****************************************************************************
9
-**
10
-** $JREEN_BEGIN_LICENSE$
11
-** This program is free software: you can redistribute it and/or modify
12
-** it under the terms of the GNU General Public License as published by
13
-** the Free Software Foundation, either version 2 of the License, or
14
-** (at your option) any later version.
15
-**
16
-** This program is distributed in the hope that it will be useful,
17
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
-** See the GNU General Public License for more details.
20
-**
21
-** You should have received a copy of the GNU General Public License
22
-** along with this program. If not, see http://www.gnu.org/licenses/.
23
-** $JREEN_END_LICENSE$
24
-**
25
-****************************************************************************/
26
-
27
-#include "multimediadatafactory_p.h"
28
-#define NS_MULTIMEDIA_DATA QLatin1String("urn:xmpp:media-element")
29
-#include <QLatin1String>
30
-#include <QXmlStreamWriter>
31
-#include <QStringList>
32
-
33
-namespace Jreen {
34
-
35
-MultimediaDataFactory::MultimediaDataFactory()
36
-{
37
-}
38
-
39
-MultimediaDataFactory::~MultimediaDataFactory()
40
-{
41
-
42
-}
43
-
44
-QStringList MultimediaDataFactory::features() const
45
-{
46
- return QStringList(NS_MULTIMEDIA_DATA);
47
-}
48
-bool MultimediaDataFactory::canParse(const QStringRef &name, const QStringRef &uri,
49
- const QXmlStreamAttributes &attributes)
50
-{
51
- Q_UNUSED(attributes);
52
- return name == QLatin1String("media") && uri == NS_MULTIMEDIA_DATA;
53
-}
54
-
55
-void MultimediaDataFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
56
- const QXmlStreamAttributes &attributes)
57
-{
58
- Q_UNUSED(name);
59
- Q_UNUSED(attributes);
60
- Q_UNUSED(uri);
61
- m_depth++;
62
- if(m_depth == 1) {
63
- foreach(const QXmlStreamAttribute &attribute,attributes) {
64
- m_attributes.insert(attribute.name().toString(),
65
- attribute.value().toString());
66
- }
67
- } else if(m_depth == 2) {
68
- m_currentDataItem.clear();
69
- m_currentDataItem.insert("type",attributes.value("type").toString());
70
- }
71
-}
72
-
73
-void MultimediaDataFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
74
-{
75
- Q_UNUSED(name);
76
- Q_UNUSED(uri);
77
- if(m_depth == 2)
78
- m_data.append(m_currentDataItem);
79
- m_depth--;
80
-}
81
-
82
-void MultimediaDataFactory::handleCharacterData(const QStringRef &text)
83
-{
84
- if(m_depth == 2)
85
- m_currentDataItem.insert("uri",text.toString());
86
-}
87
-
88
-void MultimediaDataFactory::serialize(const MultimediaData &media, QXmlStreamWriter *writer)
89
-{
90
- writer->writeStartElement(QLatin1String("media"));
91
- writer->writeDefaultNamespace(NS_MULTIMEDIA_DATA);
92
-
93
- QVariantMap attributes = media.attributes();
94
- QVariantMap::const_iterator it = attributes.constBegin();
95
- while(it != attributes.constEnd()) {
96
- writer->writeAttribute(it.key(),it.value().toString());
97
- it++;
98
- }
99
- foreach(QVariant item,media.data()) {
100
- QVariantMap map = item.toMap();
101
- writer->writeStartElement(QLatin1String("uri"));
102
- writer->writeAttribute(QLatin1String("type"),map.value("type").toString());
103
- writer->writeCharacters(map.value("uri").toString());
104
- writer->writeEndElement();
105
- }
106
- writer->writeEndElement();
107
-}
108
-
109
-MultimediaData MultimediaDataFactory::create()
110
-{
111
- return MultimediaData(m_type,m_data,m_attributes);
112
-}
113
-
114
-} // namespace Jreen
115
libjreen-1.0.3.tar.bz2/src/multimediadatafactory_p.h
Deleted
56
1
2
-/****************************************************************************
3
-**
4
-** Jreen
5
-**
6
-** Copyright © 2011 Aleksey Sidorov <gorthauer87@yandex.ru>
7
-**
8
-*****************************************************************************
9
-**
10
-** $JREEN_BEGIN_LICENSE$
11
-** This program is free software: you can redistribute it and/or modify
12
-** it under the terms of the GNU General Public License as published by
13
-** the Free Software Foundation, either version 2 of the License, or
14
-** (at your option) any later version.
15
-**
16
-** This program is distributed in the hope that it will be useful,
17
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
-** See the GNU General Public License for more details.
20
-**
21
-** You should have received a copy of the GNU General Public License
22
-** along with this program. If not, see http://www.gnu.org/licenses/.
23
-** $JREEN_END_LICENSE$
24
-**
25
-****************************************************************************/
26
-
27
-#ifndef MULTIMEDIADATAFACTORY_H
28
-#define MULTIMEDIADATAFACTORY_P_H
29
-#include "multimediadata.h"
30
-
31
-namespace Jreen {
32
-
33
-class MultimediaDataFactory : public XmlStreamParser
34
-{
35
-public:
36
- MultimediaDataFactory();
37
- virtual ~MultimediaDataFactory();
38
- QStringList features() const;
39
- bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
40
- void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
41
- void handleEndElement(const QStringRef &name, const QStringRef &uri);
42
- void handleCharacterData(const QStringRef &text);
43
- void serialize(const MultimediaData &media, QXmlStreamWriter *writer);
44
- MultimediaData create();
45
-private:
46
- QVariantMap m_attributes;
47
- QVariantList m_data;
48
- QVariantMap m_currentDataItem;
49
- int m_depth;
50
- MultimediaData::Type m_type;
51
-};
52
-
53
-} // namespace Jreen
54
-
55
-#endif // MULTIMEDIADATAFACTORY_H
56
libjreen-1.1.0.tar.bz2/3rdparty/icesupport
Added
2
1
+(directory)
2
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/bsocket.cpp
Added
401
1
2
+/*
3
+ * bsocket.cpp - QSocket wrapper based on Bytestream with SRV DNS support
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#include <QTcpSocket>
23
+#include <QHostAddress>
24
+#include <QMetaType>
25
+
26
+#include "bsocket.h"
27
+
28
+//#include "safedelete.h"
29
+
30
+//#define BS_DEBUG
31
+
32
+#ifdef BS_DEBUG
33
+#include <stdio.h>
34
+#endif
35
+
36
+#define READBUFSIZE 65536
37
+
38
+// CS_NAMESPACE_BEGIN
39
+
40
+class QTcpSocketSignalRelay : public QObject
41
+{
42
+ Q_OBJECT
43
+public:
44
+ QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = 0)
45
+ :QObject(parent)
46
+ {
47
+ qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
48
+ connect(sock, SIGNAL(hostFound()), SLOT(sock_hostFound()), Qt::QueuedConnection);
49
+ connect(sock, SIGNAL(connected()), SLOT(sock_connected()), Qt::QueuedConnection);
50
+ connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()), Qt::QueuedConnection);
51
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()), Qt::QueuedConnection);
52
+ connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)), Qt::QueuedConnection);
53
+ connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)), Qt::QueuedConnection);
54
+ }
55
+
56
+signals:
57
+ void hostFound();
58
+ void connected();
59
+ void disconnected();
60
+ void readyRead();
61
+ void bytesWritten(qint64);
62
+ void error(QAbstractSocket::SocketError);
63
+
64
+public slots:
65
+ void sock_hostFound()
66
+ {
67
+ emit hostFound();
68
+ }
69
+
70
+ void sock_connected()
71
+ {
72
+ emit connected();
73
+ }
74
+
75
+ void sock_disconnected()
76
+ {
77
+ emit disconnected();
78
+ }
79
+
80
+ void sock_readyRead()
81
+ {
82
+ emit readyRead();
83
+ }
84
+
85
+ void sock_bytesWritten(qint64 x)
86
+ {
87
+ emit bytesWritten(x);
88
+ }
89
+
90
+ void sock_error(QAbstractSocket::SocketError x)
91
+ {
92
+ emit error(x);
93
+ }
94
+};
95
+
96
+class BSocket::Private
97
+{
98
+public:
99
+ Private(BSocket *_q)
100
+ {
101
+ qsock = 0;
102
+ qsock_relay = 0;
103
+ }
104
+
105
+ QTcpSocket *qsock;
106
+ QTcpSocketSignalRelay *qsock_relay;
107
+ int state;
108
+
109
+ QString host;
110
+ int port;
111
+ QHostAddress addr;
112
+ //SafeDelete sd;
113
+};
114
+
115
+BSocket::BSocket(QObject *parent)
116
+:ByteStream(parent)
117
+{
118
+ d = new Private(this);
119
+
120
+ reset();
121
+}
122
+
123
+BSocket::~BSocket()
124
+{
125
+ reset(true);
126
+ delete d;
127
+}
128
+
129
+void BSocket::reset(bool clear)
130
+{
131
+ if(d->qsock) {
132
+ delete d->qsock_relay;
133
+ d->qsock_relay = 0;
134
+
135
+ /*d->qsock->disconnect(this);
136
+
137
+ if(!clear && d->qsock->isOpen() && d->qsock->isValid()) {*/
138
+ // move remaining into the local queue
139
+ QByteArray block(d->qsock->bytesAvailable(), 0);
140
+ d->qsock->read(block.data(), block.size());
141
+ appendRead(block);
142
+ //}
143
+
144
+ //d->sd.deleteLater(d->qsock);
145
+ d->qsock->deleteLater();
146
+ d->qsock = 0;
147
+ }
148
+ else {
149
+ if(clear)
150
+ clearReadBuffer();
151
+ }
152
+
153
+ d->state = Idle;
154
+ d->addr = QHostAddress();
155
+}
156
+
157
+void BSocket::ensureSocket()
158
+{
159
+ if(!d->qsock) {
160
+ d->qsock = new QTcpSocket(this);
161
+#if QT_VERSION >= 0x030200
162
+ d->qsock->setReadBufferSize(READBUFSIZE);
163
+#endif
164
+ d->qsock_relay = new QTcpSocketSignalRelay(d->qsock, this);
165
+ connect(d->qsock_relay, SIGNAL(hostFound()), SLOT(qs_hostFound()));
166
+ connect(d->qsock_relay, SIGNAL(connected()), SLOT(qs_connected()));
167
+ connect(d->qsock_relay, SIGNAL(disconnected()), SLOT(qs_closed()));
168
+ connect(d->qsock_relay, SIGNAL(readyRead()), SLOT(qs_readyRead()));
169
+ connect(d->qsock_relay, SIGNAL(bytesWritten(qint64)), SLOT(qs_bytesWritten(qint64)));
170
+ connect(d->qsock_relay, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(qs_error(QAbstractSocket::SocketError)));
171
+ }
172
+}
173
+
174
+void BSocket::connectToHost(const QString &host, quint16 port)
175
+{
176
+ reset(true);
177
+ d->host = host;
178
+ d->port = port;
179
+ d->state = HostLookup;
180
+ do_connect();
181
+}
182
+
183
+void BSocket::connectToHost(const QHostAddress &addr, quint16 port)
184
+{
185
+ reset(true);
186
+ d->host = addr.toString();
187
+ d->addr = addr;
188
+ d->port = port;
189
+ d->state = Connecting;
190
+ do_connect();
191
+}
192
+
193
+int BSocket::socket() const
194
+{
195
+ if(d->qsock)
196
+ return d->qsock->socketDescriptor();
197
+ else
198
+ return -1;
199
+}
200
+
201
+void BSocket::setSocket(int s)
202
+{
203
+ reset(true);
204
+ ensureSocket();
205
+ d->state = Connected;
206
+ d->qsock->setSocketDescriptor(s);
207
+}
208
+
209
+int BSocket::state() const
210
+{
211
+ return d->state;
212
+}
213
+
214
+bool BSocket::isOpen() const
215
+{
216
+ if(d->state == Connected)
217
+ return true;
218
+ else
219
+ return false;
220
+}
221
+
222
+void BSocket::close()
223
+{
224
+ if(d->state == Idle)
225
+ return;
226
+
227
+ if(d->qsock) {
228
+ d->qsock->close();
229
+ d->state = Closing;
230
+ if(d->qsock->bytesToWrite() == 0)
231
+ reset();
232
+ }
233
+ else {
234
+ reset();
235
+ }
236
+}
237
+
238
+void BSocket::write(const QByteArray &a)
239
+{
240
+ if(d->state != Connected)
241
+ return;
242
+#ifdef BS_DEBUG
243
+ QString s = QString::fromUtf8(a);
244
+ fprintf(stderr, "BSocket: writing %d: {%s}\n", a.size(), s.latin1());
245
+#endif
246
+ d->qsock->write(a.data(), a.size());
247
+}
248
+
249
+QByteArray BSocket::read(int bytes)
250
+{
251
+ QByteArray block;
252
+ if(d->qsock) {
253
+ int max = bytesAvailable();
254
+ if(bytes <= 0 || bytes > max)
255
+ bytes = max;
256
+ block.resize(bytes);
257
+ d->qsock->read(block.data(), block.size());
258
+ }
259
+ else
260
+ block = ByteStream::read(bytes);
261
+
262
+#ifdef BS_DEBUG
263
+ QString s = QString::fromUtf8(block);
264
+ fprintf(stderr, "BSocket: read %d: {%s}\n", block.size(), s.latin1());
265
+#endif
266
+ return block;
267
+}
268
+
269
+int BSocket::bytesAvailable() const
270
+{
271
+ if(d->qsock)
272
+ return d->qsock->bytesAvailable();
273
+ else
274
+ return ByteStream::bytesAvailable();
275
+}
276
+
277
+int BSocket::bytesToWrite() const
278
+{
279
+ if(!d->qsock)
280
+ return 0;
281
+ return d->qsock->bytesToWrite();
282
+}
283
+
284
+QHostAddress BSocket::address() const
285
+{
286
+ if(d->qsock)
287
+ return d->qsock->localAddress();
288
+ else
289
+ return QHostAddress();
290
+}
291
+
292
+quint16 BSocket::port() const
293
+{
294
+ if(d->qsock)
295
+ return d->qsock->localPort();
296
+ else
297
+ return 0;
298
+}
299
+
300
+QHostAddress BSocket::peerAddress() const
301
+{
302
+ if(d->qsock)
303
+ return d->qsock->peerAddress();
304
+ else
305
+ return QHostAddress();
306
+}
307
+
308
+quint16 BSocket::peerPort() const
309
+{
310
+ if(d->qsock)
311
+ return d->qsock->peerPort();
312
+ else
313
+ return 0;
314
+}
315
+
316
+void BSocket::do_connect()
317
+{
318
+#ifdef BS_DEBUG
319
+ fprintf(stderr, "BSocket: Connecting to %s:%d\n", d->host.latin1(), d->port);
320
+#endif
321
+ ensureSocket();
322
+ if(!d->addr.isNull())
323
+ d->qsock->connectToHost(d->addr, d->port);
324
+ else
325
+ d->qsock->connectToHost(d->host, d->port);
326
+}
327
+
328
+void BSocket::qs_hostFound()
329
+{
330
+ //SafeDeleteLock s(&d->sd);
331
+}
332
+
333
+void BSocket::qs_connected()
334
+{
335
+ d->state = Connected;
336
+#ifdef BS_DEBUG
337
+ fprintf(stderr, "BSocket: Connected.\n");
338
+#endif
339
+ //SafeDeleteLock s(&d->sd);
340
+ connected();
341
+}
342
+
343
+void BSocket::qs_closed()
344
+{
345
+ if(d->state == Closing)
346
+ {
347
+#ifdef BS_DEBUG
348
+ fprintf(stderr, "BSocket: Delayed Close Finished.\n");
349
+#endif
350
+ //SafeDeleteLock s(&d->sd);
351
+ reset();
352
+ delayedCloseFinished();
353
+ }
354
+}
355
+
356
+void BSocket::qs_readyRead()
357
+{
358
+ //SafeDeleteLock s(&d->sd);
359
+ readyRead();
360
+}
361
+
362
+void BSocket::qs_bytesWritten(qint64 x64)
363
+{
364
+ int x = x64;
365
+#ifdef BS_DEBUG
366
+ fprintf(stderr, "BSocket: BytesWritten %d.\n", x);
367
+#endif
368
+ //SafeDeleteLock s(&d->sd);
369
+ bytesWritten(x);
370
+}
371
+
372
+void BSocket::qs_error(QAbstractSocket::SocketError x)
373
+{
374
+ if(x == QTcpSocket::RemoteHostClosedError) {
375
+#ifdef BS_DEBUG
376
+ fprintf(stderr, "BSocket: Connection Closed.\n");
377
+#endif
378
+ //SafeDeleteLock s(&d->sd);
379
+ reset();
380
+ connectionClosed();
381
+ return;
382
+ }
383
+
384
+#ifdef BS_DEBUG
385
+ fprintf(stderr, "BSocket: Error.\n");
386
+#endif
387
+ //SafeDeleteLock s(&d->sd);
388
+
389
+ reset();
390
+ if(x == QTcpSocket::ConnectionRefusedError)
391
+ error(ErrConnectionRefused);
392
+ else if(x == QTcpSocket::HostNotFoundError)
393
+ error(ErrHostNotFound);
394
+ else
395
+ error(ErrRead);
396
+}
397
+
398
+#include "bsocket.moc"
399
+
400
+// CS_NAMESPACE_END
401
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/bsocket.h
Added
90
1
2
+/*
3
+ * bsocket.h - QSocket wrapper based on Bytestream with SRV DNS support
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#ifndef CS_BSOCKET_H
23
+#define CS_BSOCKET_H
24
+
25
+#include <QAbstractSocket>
26
+
27
+#include "bytestream.h"
28
+
29
+class QString;
30
+class QObject;
31
+class QByteArray;
32
+
33
+// CS_NAMESPACE_BEGIN
34
+
35
+class BSocket : public ByteStream
36
+{
37
+ Q_OBJECT
38
+public:
39
+ enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound };
40
+ enum State { Idle, HostLookup, Connecting, Connected, Closing };
41
+ BSocket(QObject *parent=0);
42
+ ~BSocket();
43
+
44
+ void connectToHost(const QString &host, quint16 port);
45
+ void connectToHost(const QHostAddress &addr, quint16 port);
46
+ int socket() const;
47
+ void setSocket(int);
48
+ int state() const;
49
+
50
+ // from ByteStream
51
+ bool isOpen() const;
52
+ void close();
53
+ void write(const QByteArray &);
54
+ QByteArray read(int bytes=0);
55
+ int bytesAvailable() const;
56
+ int bytesToWrite() const;
57
+
58
+ // local
59
+ QHostAddress address() const;
60
+ quint16 port() const;
61
+
62
+ // remote
63
+ QHostAddress peerAddress() const;
64
+ quint16 peerPort() const;
65
+
66
+signals:
67
+ void hostFound();
68
+ void connected();
69
+
70
+private slots:
71
+ void qs_hostFound();
72
+ void qs_connected();
73
+ void qs_closed();
74
+ void qs_readyRead();
75
+ void qs_bytesWritten(qint64);
76
+ void qs_error(QAbstractSocket::SocketError);
77
+ void do_connect();
78
+
79
+private:
80
+ class Private;
81
+ Private *d;
82
+
83
+ void reset(bool clear=false);
84
+ void ensureSocket();
85
+};
86
+
87
+// CS_NAMESPACE_END
88
+
89
+#endif
90
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/bytestream.cpp
Added
261
1
2
+/*
3
+ * bytestream.cpp - base class for bytestreams
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#include "bytestream.h"
23
+#include <QByteArray>
24
+
25
+// CS_NAMESPACE_BEGIN
26
+
27
+//! \class ByteStream bytestream.h
28
+//! \brief Base class for "bytestreams"
29
+//!
30
+//! This class provides a basic framework for a "bytestream", here defined
31
+//! as a bi-directional, asynchronous pipe of data. It can be used to create
32
+//! several different kinds of bytestream-applications, such as a console or
33
+//! TCP connection, or something more abstract like a security layer or tunnel,
34
+//! all with the same interface. The provided functions make creating such
35
+//! classes simpler. ByteStream is a pure-virtual class, so you do not use it
36
+//! on its own, but instead through a subclass such as \a BSocket.
37
+//!
38
+//! The signals connectionClosed(), delayedCloseFinished(), readyRead(),
39
+//! bytesWritten(), and error() serve the exact same function as those from
40
+//! <A HREF="http://doc.trolltech.com/3.1/qsocket.html">QSocket</A>.
41
+//!
42
+//! The simplest way to create a ByteStream is to reimplement isOpen(), close(),
43
+//! and tryWrite(). Call appendRead() whenever you want to make data available for
44
+//! reading. ByteStream will take care of the buffers with regards to the caller,
45
+//! and will call tryWrite() when the write buffer gains data. It will be your
46
+//! job to call tryWrite() whenever it is acceptable to write more data to
47
+//! the underlying system.
48
+//!
49
+//! If you need more advanced control, reimplement read(), write(), bytesAvailable(),
50
+//! and/or bytesToWrite() as necessary.
51
+//!
52
+//! Use appendRead(), appendWrite(), takeRead(), and takeWrite() to modify the
53
+//! buffers. If you have more advanced requirements, the buffers can be accessed
54
+//! directly with readBuf() and writeBuf().
55
+//!
56
+//! Also available are the static convenience functions ByteStream::appendArray()
57
+//! and ByteStream::takeArray(), which make dealing with byte queues very easy.
58
+
59
+class ByteStream::Private
60
+{
61
+public:
62
+ Private() {}
63
+
64
+ QByteArray readBuf, writeBuf;
65
+};
66
+
67
+//!
68
+//! Constructs a ByteStream object with parent \a parent.
69
+ByteStream::ByteStream(QObject *parent)
70
+:QObject(parent)
71
+{
72
+ d = new Private;
73
+}
74
+
75
+//!
76
+//! Destroys the object and frees allocated resources.
77
+ByteStream::~ByteStream()
78
+{
79
+ delete d;
80
+}
81
+
82
+//!
83
+//! Returns TRUE if the stream is open, meaning that you can write to it.
84
+bool ByteStream::isOpen() const
85
+{
86
+ return false;
87
+}
88
+
89
+//!
90
+//! Closes the stream. If there is data in the write buffer then it will be
91
+//! written before actually closing the stream. Once all data has been written,
92
+//! the delayedCloseFinished() signal will be emitted.
93
+//! \sa delayedCloseFinished()
94
+void ByteStream::close()
95
+{
96
+}
97
+
98
+//!
99
+//! Writes array \a a to the stream.
100
+void ByteStream::write(const QByteArray &a)
101
+{
102
+ if(!isOpen())
103
+ return;
104
+
105
+ bool doWrite = bytesToWrite() == 0 ? true: false;
106
+ appendWrite(a);
107
+ if(doWrite)
108
+ tryWrite();
109
+}
110
+
111
+//!
112
+//! Reads bytes \a bytes of data from the stream and returns them as an array. If \a bytes is 0, then
113
+//! \a read will return all available data.
114
+QByteArray ByteStream::read(int bytes)
115
+{
116
+ return takeRead(bytes);
117
+}
118
+
119
+//!
120
+//! Returns the number of bytes available for reading.
121
+int ByteStream::bytesAvailable() const
122
+{
123
+ return d->readBuf.size();
124
+}
125
+
126
+//!
127
+//! Returns the number of bytes that are waiting to be written.
128
+int ByteStream::bytesToWrite() const
129
+{
130
+ return d->writeBuf.size();
131
+}
132
+
133
+//!
134
+//! Clears the read buffer.
135
+void ByteStream::clearReadBuffer()
136
+{
137
+ d->readBuf.resize(0);
138
+}
139
+
140
+//!
141
+//! Clears the write buffer.
142
+void ByteStream::clearWriteBuffer()
143
+{
144
+ d->writeBuf.resize(0);
145
+}
146
+
147
+//!
148
+//! Appends \a block to the end of the read buffer.
149
+void ByteStream::appendRead(const QByteArray &block)
150
+{
151
+ appendArray(&d->readBuf, block);
152
+}
153
+
154
+//!
155
+//! Appends \a block to the end of the write buffer.
156
+void ByteStream::appendWrite(const QByteArray &block)
157
+{
158
+ appendArray(&d->writeBuf, block);
159
+}
160
+
161
+//!
162
+//! Returns \a size bytes from the start of the read buffer.
163
+//! If \a size is 0, then all available data will be returned.
164
+//! If \a del is TRUE, then the bytes are also removed.
165
+QByteArray ByteStream::takeRead(int size, bool del)
166
+{
167
+ return takeArray(&d->readBuf, size, del);
168
+}
169
+
170
+//!
171
+//! Returns \a size bytes from the start of the write buffer.
172
+//! If \a size is 0, then all available data will be returned.
173
+//! If \a del is TRUE, then the bytes are also removed.
174
+QByteArray ByteStream::takeWrite(int size, bool del)
175
+{
176
+ return takeArray(&d->writeBuf, size, del);
177
+}
178
+
179
+//!
180
+//! Returns a reference to the read buffer.
181
+QByteArray & ByteStream::readBuf()
182
+{
183
+ return d->readBuf;
184
+}
185
+
186
+//!
187
+//! Returns a reference to the write buffer.
188
+QByteArray & ByteStream::writeBuf()
189
+{
190
+ return d->writeBuf;
191
+}
192
+
193
+//!
194
+//! Attempts to try and write some bytes from the write buffer, and returns the number
195
+//! successfully written or -1 on error. The default implementation returns -1.
196
+int ByteStream::tryWrite()
197
+{
198
+ return -1;
199
+}
200
+
201
+//!
202
+//! Append array \a b to the end of the array pointed to by \a a.
203
+void ByteStream::appendArray(QByteArray *a, const QByteArray &b)
204
+{
205
+ int oldsize = a->size();
206
+ a->resize(oldsize + b.size());
207
+ memcpy(a->data() + oldsize, b.data(), b.size());
208
+}
209
+
210
+//!
211
+//! Returns \a size bytes from the start of the array pointed to by \a from.
212
+//! If \a size is 0, then all available data will be returned.
213
+//! If \a del is TRUE, then the bytes are also removed.
214
+QByteArray ByteStream::takeArray(QByteArray *from, int size, bool del)
215
+{
216
+ QByteArray a;
217
+ if(size == 0) {
218
+ a = *from;
219
+ if(del)
220
+ from->resize(0);
221
+ }
222
+ else {
223
+ if(size > (int)from->size())
224
+ size = from->size();
225
+ a.resize(size);
226
+ char *r = from->data();
227
+ memcpy(a.data(), r, size);
228
+ if(del) {
229
+ int newsize = from->size()-size;
230
+ memmove(r, r+size, newsize);
231
+ from->resize(newsize);
232
+ }
233
+ }
234
+ return a;
235
+}
236
+ void connectionClosed();
237
+ void delayedCloseFinished();
238
+ void readyRead();
239
+ void bytesWritten(int);
240
+ void error(int);
241
+
242
+//! \fn void ByteStream::connectionClosed()
243
+//! This signal is emitted when the remote end of the stream closes.
244
+
245
+//! \fn void ByteStream::delayedCloseFinished()
246
+//! This signal is emitted when all pending data has been written to the stream
247
+//! after an attempt to close.
248
+
249
+//! \fn void ByteStream::readyRead()
250
+//! This signal is emitted when data is available to be read.
251
+
252
+//! \fn void ByteStream::bytesWritten(int x);
253
+//! This signal is emitted when data has been successfully written to the stream.
254
+//! \a x is the number of bytes written.
255
+
256
+//! \fn void ByteStream::error(int code)
257
+//! This signal is emitted when an error occurs in the stream. The reason for
258
+//! error is indicated by \a code.
259
+
260
+// CS_NAMESPACE_END
261
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/bytestream.h
Added
78
1
2
+/*
3
+ * bytestream.h - base class for bytestreams
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#ifndef CS_BYTESTREAM_H
23
+#define CS_BYTESTREAM_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+
28
+// CS_NAMESPACE_BEGIN
29
+
30
+// CS_EXPORT_BEGIN
31
+class ByteStream : public QObject
32
+{
33
+ Q_OBJECT
34
+public:
35
+ enum Error { ErrRead, ErrWrite, ErrCustom = 10 };
36
+ ByteStream(QObject *parent=0);
37
+ virtual ~ByteStream()=0;
38
+
39
+ virtual bool isOpen() const;
40
+ virtual void close();
41
+ virtual void write(const QByteArray &);
42
+ virtual QByteArray read(int bytes=0);
43
+ virtual int bytesAvailable() const;
44
+ virtual int bytesToWrite() const;
45
+
46
+ static void appendArray(QByteArray *a, const QByteArray &b);
47
+ static QByteArray takeArray(QByteArray *from, int size=0, bool del=true);
48
+
49
+signals:
50
+ void connectionClosed();
51
+ void delayedCloseFinished();
52
+ void readyRead();
53
+ void bytesWritten(int);
54
+ void error(int);
55
+
56
+protected:
57
+ void clearReadBuffer();
58
+ void clearWriteBuffer();
59
+ void appendRead(const QByteArray &);
60
+ void appendWrite(const QByteArray &);
61
+ QByteArray takeRead(int size=0, bool del=true);
62
+ QByteArray takeWrite(int size=0, bool del=true);
63
+ QByteArray & readBuf();
64
+ QByteArray & writeBuf();
65
+ virtual int tryWrite();
66
+
67
+private:
68
+//! \if _hide_doc_
69
+ class Private;
70
+ Private *d;
71
+//! \endif
72
+};
73
+// CS_EXPORT_END
74
+
75
+// CS_NAMESPACE_END
76
+
77
+#endif
78
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/httpconnect.cpp
Added
389
1
2
+/*
3
+ * httpconnect.cpp - HTTP "CONNECT" proxy
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#include "httpconnect.h"
23
+
24
+#include <qstringlist.h>
25
+#include <QByteArray>
26
+#include "bsocket.h"
27
+#include <QtCrypto>
28
+
29
+//#define PROX_DEBUG
30
+
31
+#ifdef PROX_DEBUG
32
+#include <stdio.h>
33
+#endif
34
+
35
+// CS_NAMESPACE_BEGIN
36
+
37
+#ifdef PROX_DEBUG
38
+QString escapeOutput(const QByteArray &in)
39
+{
40
+ QString out;
41
+ for(int n = 0; n < in.size(); ++n) {
42
+ if(inn == '\\') {
43
+ out += QString("\\\\");
44
+ }
45
+ else if(inn >= 32 && inn < 127) {
46
+ out += QChar::fromLatin1(inn);
47
+ }
48
+ else {
49
+ out += QString().sprintf("\\x%02x", (unsigned char)inn);
50
+ }
51
+ }
52
+ return out;
53
+}
54
+#endif
55
+
56
+static QString extractLine(QByteArray *buf, bool *found)
57
+{
58
+ // Scan for newline
59
+ int index = buf->indexOf ("\r\n");
60
+ if (index == -1) {
61
+ // Newline not found
62
+ if (found)
63
+ *found = false;
64
+ return "";
65
+ }
66
+ else {
67
+ // Found newline
68
+ QString s = QString::fromAscii(buf->left(index));
69
+ buf->remove(0, index + 2);
70
+
71
+ if (found)
72
+ *found = true;
73
+ return s;
74
+ }
75
+}
76
+
77
+static bool extractMainHeader(const QString &line, QString *proto, int *code, QString *msg)
78
+{
79
+ int n = line.indexOf(' ');
80
+ if(n == -1)
81
+ return false;
82
+ if(proto)
83
+ *proto = line.mid(0, n);
84
+ ++n;
85
+ int n2 = line.indexOf(' ', n);
86
+ if(n2 == -1)
87
+ return false;
88
+ if(code)
89
+ *code = line.mid(n, n2-n).toInt();
90
+ n = n2+1;
91
+ if(msg)
92
+ *msg = line.mid(n);
93
+ return true;
94
+}
95
+
96
+class HttpConnect::Private
97
+{
98
+public:
99
+ Private(HttpConnect *_q) :
100
+ sock(_q)
101
+ {
102
+ }
103
+
104
+ BSocket sock;
105
+ QString host;
106
+ int port;
107
+ QString user, pass;
108
+ QString real_host;
109
+ int real_port;
110
+
111
+ QByteArray recvBuf;
112
+
113
+ bool inHeader;
114
+ QStringList headerLines;
115
+
116
+ int toWrite;
117
+ bool active;
118
+};
119
+
120
+HttpConnect::HttpConnect(QObject *parent)
121
+:ByteStream(parent)
122
+{
123
+ d = new Private(this);
124
+ connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected()));
125
+ connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
126
+ connect(&d->sock, SIGNAL(delayedCloseFinished()), SLOT(sock_delayedCloseFinished()));
127
+ connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
128
+ connect(&d->sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
129
+ connect(&d->sock, SIGNAL(error(int)), SLOT(sock_error(int)));
130
+
131
+ reset(true);
132
+}
133
+
134
+HttpConnect::~HttpConnect()
135
+{
136
+ reset(true);
137
+ delete d;
138
+}
139
+
140
+void HttpConnect::reset(bool clear)
141
+{
142
+ if(d->sock.state() != BSocket::Idle)
143
+ d->sock.close();
144
+ if(clear) {
145
+ clearReadBuffer();
146
+ d->recvBuf.resize(0);
147
+ }
148
+ d->active = false;
149
+}
150
+
151
+void HttpConnect::setAuth(const QString &user, const QString &pass)
152
+{
153
+ d->user = user;
154
+ d->pass = pass;
155
+}
156
+
157
+void HttpConnect::connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port)
158
+{
159
+ reset(true);
160
+
161
+ d->host = proxyHost;
162
+ d->port = proxyPort;
163
+ d->real_host = host;
164
+ d->real_port = port;
165
+
166
+#ifdef PROX_DEBUG
167
+ fprintf(stderr, "HttpConnect: Connecting to %s:%d", qPrintable(proxyHost), proxyPort);
168
+ if(d->user.isEmpty())
169
+ fprintf(stderr, "\n");
170
+ else
171
+ fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass));
172
+#endif
173
+ d->sock.connectToHost(d->host, d->port);
174
+}
175
+
176
+bool HttpConnect::isOpen() const
177
+{
178
+ return d->active;
179
+}
180
+
181
+void HttpConnect::close()
182
+{
183
+ d->sock.close();
184
+ if(d->sock.bytesToWrite() == 0)
185
+ reset();
186
+}
187
+
188
+void HttpConnect::write(const QByteArray &buf)
189
+{
190
+ if(d->active)
191
+ d->sock.write(buf);
192
+}
193
+
194
+QByteArray HttpConnect::read(int bytes)
195
+{
196
+ return ByteStream::read(bytes);
197
+}
198
+
199
+int HttpConnect::bytesAvailable() const
200
+{
201
+ return ByteStream::bytesAvailable();
202
+}
203
+
204
+int HttpConnect::bytesToWrite() const
205
+{
206
+ if(d->active)
207
+ return d->sock.bytesToWrite();
208
+ else
209
+ return 0;
210
+}
211
+
212
+void HttpConnect::sock_connected()
213
+{
214
+#ifdef PROX_DEBUG
215
+ fprintf(stderr, "HttpConnect: Connected\n");
216
+#endif
217
+ d->inHeader = true;
218
+ d->headerLines.clear();
219
+
220
+ // connected, now send the request
221
+ QString s;
222
+ s += QString("CONNECT ") + d->real_host + ':' + QString::number(d->real_port) + " HTTP/1.0\r\n";
223
+ if(!d->user.isEmpty()) {
224
+ QString str = d->user + ':' + d->pass;
225
+ s += QString("Proxy-Authorization: Basic ") + QCA::Base64().encodeString(str) + "\r\n";
226
+ }
227
+ s += "Pragma: no-cache\r\n";
228
+ s += "\r\n";
229
+
230
+ QByteArray block = s.toUtf8();
231
+#ifdef PROX_DEBUG
232
+ fprintf(stderr, "HttpConnect: writing: {%s}\n", qPrintable(escapeOutput(block)));
233
+#endif
234
+ d->toWrite = block.size();
235
+ d->sock.write(block);
236
+}
237
+
238
+void HttpConnect::sock_connectionClosed()
239
+{
240
+ if(d->active) {
241
+ reset();
242
+ connectionClosed();
243
+ }
244
+ else {
245
+ error(ErrProxyNeg);
246
+ }
247
+}
248
+
249
+void HttpConnect::sock_delayedCloseFinished()
250
+{
251
+ if(d->active) {
252
+ reset();
253
+ delayedCloseFinished();
254
+ }
255
+}
256
+
257
+void HttpConnect::sock_readyRead()
258
+{
259
+ QByteArray block = d->sock.read();
260
+
261
+ if(!d->active) {
262
+ ByteStream::appendArray(&d->recvBuf, block);
263
+
264
+ if(d->inHeader) {
265
+ // grab available lines
266
+ while(1) {
267
+ bool found;
268
+ QString line = extractLine(&d->recvBuf, &found);
269
+ if(!found)
270
+ break;
271
+ if(line.isEmpty()) {
272
+ d->inHeader = false;
273
+ break;
274
+ }
275
+ d->headerLines += line;
276
+ }
277
+
278
+ // done with grabbing the header?
279
+ if(!d->inHeader) {
280
+ QString str = d->headerLines.first();
281
+ d->headerLines.takeFirst();
282
+
283
+ QString proto;
284
+ int code;
285
+ QString msg;
286
+ if(!extractMainHeader(str, &proto, &code, &msg)) {
287
+#ifdef PROX_DEBUG
288
+ fprintf(stderr, "HttpConnect: invalid header!\n");
289
+#endif
290
+ reset(true);
291
+ error(ErrProxyNeg);
292
+ return;
293
+ }
294
+ else {
295
+#ifdef PROX_DEBUG
296
+ fprintf(stderr, "HttpConnect: header proto=%s code=%d msg=%s\n", qPrintable(proto), code, qPrintable(msg));
297
+ for(QStringList::ConstIterator it = d->headerLines.begin(); it != d->headerLines.end(); ++it)
298
+ fprintf(stderr, "HttpConnect: * %s\n", qPrintable(*it));
299
+#endif
300
+ }
301
+
302
+ if(code == 200) { // OK
303
+#ifdef PROX_DEBUG
304
+ fprintf(stderr, "HttpConnect: << Success >>\n");
305
+#endif
306
+ d->active = true;
307
+ connected();
308
+
309
+ if(!d->recvBuf.isEmpty()) {
310
+ appendRead(d->recvBuf);
311
+ d->recvBuf.resize(0);
312
+ readyRead();
313
+ return;
314
+ }
315
+ }
316
+ else {
317
+ int err;
318
+ QString errStr;
319
+ if(code == 407) { // Authentication failed
320
+ err = ErrProxyAuth;
321
+ errStr = tr("Authentication failed");
322
+ }
323
+ else if(code == 404) { // Host not found
324
+ err = ErrHostNotFound;
325
+ errStr = tr("Host not found");
326
+ }
327
+ else if(code == 403) { // Access denied
328
+ err = ErrProxyNeg;
329
+ errStr = tr("Access denied");
330
+ }
331
+ else if(code == 503) { // Connection refused
332
+ err = ErrConnectionRefused;
333
+ errStr = tr("Connection refused");
334
+ }
335
+ else { // invalid reply
336
+ err = ErrProxyNeg;
337
+ errStr = tr("Invalid reply");
338
+ }
339
+
340
+#ifdef PROX_DEBUG
341
+ fprintf(stderr, "HttpConnect: << Error >> %s\n", qPrintable(errStr));
342
+#endif
343
+ reset(true);
344
+ error(err);
345
+ return;
346
+ }
347
+ }
348
+ }
349
+ }
350
+ else {
351
+ appendRead(block);
352
+ readyRead();
353
+ return;
354
+ }
355
+}
356
+
357
+void HttpConnect::sock_bytesWritten(int x)
358
+{
359
+ if(d->toWrite > 0) {
360
+ int size = x;
361
+ if(d->toWrite < x)
362
+ size = d->toWrite;
363
+ d->toWrite -= size;
364
+ x -= size;
365
+ }
366
+
367
+ if(d->active && x > 0)
368
+ bytesWritten(x);
369
+}
370
+
371
+void HttpConnect::sock_error(int x)
372
+{
373
+ if(d->active) {
374
+ reset();
375
+ error(ErrRead);
376
+ }
377
+ else {
378
+ reset(true);
379
+ if(x == BSocket::ErrHostNotFound)
380
+ error(ErrProxyConnect);
381
+ else if(x == BSocket::ErrConnectionRefused)
382
+ error(ErrProxyConnect);
383
+ else if(x == BSocket::ErrRead)
384
+ error(ErrProxyNeg);
385
+ }
386
+}
387
+
388
+// CS_NAMESPACE_END
389
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/httpconnect.h
Added
69
1
2
+/*
3
+ * httpconnect.h - HTTP "CONNECT" proxy
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#ifndef CS_HTTPCONNECT_H
23
+#define CS_HTTPCONNECT_H
24
+
25
+#include "bytestream.h"
26
+
27
+// CS_NAMESPACE_BEGIN
28
+
29
+class HttpConnect : public ByteStream
30
+{
31
+ Q_OBJECT
32
+public:
33
+ enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth };
34
+ HttpConnect(QObject *parent=0);
35
+ ~HttpConnect();
36
+
37
+ void setAuth(const QString &user, const QString &pass="");
38
+ void connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port);
39
+
40
+ // from ByteStream
41
+ bool isOpen() const;
42
+ void close();
43
+ void write(const QByteArray &);
44
+ QByteArray read(int bytes=0);
45
+ int bytesAvailable() const;
46
+ int bytesToWrite() const;
47
+
48
+signals:
49
+ void connected();
50
+
51
+private slots:
52
+ void sock_connected();
53
+ void sock_connectionClosed();
54
+ void sock_delayedCloseFinished();
55
+ void sock_readyRead();
56
+ void sock_bytesWritten(int);
57
+ void sock_error(int);
58
+
59
+private:
60
+ class Private;
61
+ Private *d;
62
+
63
+ void reset(bool clear=false);
64
+};
65
+
66
+// CS_NAMESPACE_END
67
+
68
+#endif
69
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/ice176.cpp
Added
1344
1
2
+/*
3
+ * Copyright (C) 2009,2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "ice176.h"
23
+
24
+#include <QSet>
25
+#include <QTimer>
26
+#include <QUdpSocket>
27
+#include <QtCrypto>
28
+#include "stuntransaction.h"
29
+#include "stunbinding.h"
30
+#include "stunmessage.h"
31
+#include "udpportreserver.h"
32
+#include "icelocaltransport.h"
33
+#include "iceturntransport.h"
34
+#include "icecomponent.h"
35
+
36
+namespace XMPP {
37
+
38
+enum
39
+{
40
+ Direct,
41
+ Relayed
42
+};
43
+
44
+static QChar randomPrintableChar()
45
+{
46
+ // 0-25 = a-z
47
+ // 26-51 = A-Z
48
+ // 52-61 = 0-9
49
+
50
+ uchar c = QCA::Random::randomChar() % 62;
51
+ if(c <= 25)
52
+ return 'a' + c;
53
+ else if(c <= 51)
54
+ return 'A' + (c - 26);
55
+ else
56
+ return '0' + (c - 52);
57
+}
58
+
59
+static QString randomCredential(int len)
60
+{
61
+ QString out;
62
+ for(int n = 0; n < len; ++n)
63
+ out += randomPrintableChar();
64
+ return out;
65
+}
66
+
67
+static qint64 calc_pair_priority(int a, int b)
68
+{
69
+ qint64 priority = ((qint64)1 << 32) * qMin(a, b);
70
+ priority += (qint64)2 * qMax(a, b);
71
+ if(a > b)
72
+ ++priority;
73
+ return priority;
74
+}
75
+
76
+// see if candidates are considered the same for pruning purposes
77
+static bool compare_candidates(const IceComponent::CandidateInfo &a, const IceComponent::CandidateInfo &b)
78
+{
79
+ if(a.addr == b.addr && a.componentId == b.componentId)
80
+ return true;
81
+ else
82
+ return false;
83
+}
84
+
85
+// scope values: 0 = local, 1 = link-local, 2 = private, 3 = public
86
+// FIXME: dry (this is in psi avcall also)
87
+static int getAddressScope(const QHostAddress &a)
88
+{
89
+ if(a.protocol() == QAbstractSocket::IPv6Protocol)
90
+ {
91
+ if(a == QHostAddress(QHostAddress::LocalHostIPv6))
92
+ return 0;
93
+ else if(XMPP::Ice176::isIPv6LinkLocalAddress(a))
94
+ return 1;
95
+ }
96
+ else if(a.protocol() == QAbstractSocket::IPv4Protocol)
97
+ {
98
+ quint32 v4 = a.toIPv4Address();
99
+ quint8 a0 = v4 >> 24;
100
+ quint8 a1 = (v4 >> 16) & 0xff;
101
+ if(a0 == 127)
102
+ return 0;
103
+ else if(a0 == 169 && a1 == 254)
104
+ return 1;
105
+ else if(a0 == 10)
106
+ return 2;
107
+ else if(a0 == 172 && a1 >= 16 && a1 <= 31)
108
+ return 2;
109
+ else if(a0 == 192 && a1 == 168)
110
+ return 2;
111
+ }
112
+
113
+ return 3;
114
+}
115
+
116
+class Ice176::Private : public QObject
117
+{
118
+ Q_OBJECT
119
+
120
+public:
121
+ enum State
122
+ {
123
+ Stopped,
124
+ Starting,
125
+ Started,
126
+ Stopping
127
+ };
128
+
129
+ enum CandidatePairState
130
+ {
131
+ PWaiting,
132
+ PInProgress,
133
+ PSucceeded,
134
+ PFailed,
135
+ PFrozen
136
+ };
137
+
138
+ enum CheckListState
139
+ {
140
+ LRunning,
141
+ LCompleted,
142
+ LFailed
143
+ };
144
+
145
+ class CandidatePair
146
+ {
147
+ public:
148
+ IceComponent::CandidateInfo local, remote;
149
+ bool isDefault;
150
+ bool isValid;
151
+ bool isNominated;
152
+ CandidatePairState state;
153
+
154
+ qint64 priority;
155
+ QString foundation;
156
+
157
+ StunBinding *binding;
158
+
159
+ // FIXME: this is wrong i think, it should be in LocalTransport
160
+ // or such, to multiplex ids
161
+ StunTransactionPool *pool;
162
+
163
+ CandidatePair() :
164
+ binding(0),
165
+ pool(0)
166
+ {
167
+ }
168
+ };
169
+
170
+ class CheckList
171
+ {
172
+ public:
173
+ QList<CandidatePair> pairs;
174
+ CheckListState state;
175
+ };
176
+
177
+ class Component
178
+ {
179
+ public:
180
+ int id;
181
+ IceComponent *ic;
182
+ bool localFinished;
183
+ bool stopped;
184
+ bool lowOverhead;
185
+
186
+ Component() :
187
+ localFinished(false),
188
+ stopped(false),
189
+ lowOverhead(false)
190
+ {
191
+ }
192
+ };
193
+
194
+ Ice176 *q;
195
+ Ice176::Mode mode;
196
+ State state;
197
+ TurnClient::Proxy proxy;
198
+ UdpPortReserver *portReserver;
199
+ int componentCount;
200
+ QList<Ice176::LocalAddress> localAddrs;
201
+ QList<Ice176::ExternalAddress> extAddrs;
202
+ QHostAddress stunBindAddr;
203
+ int stunBindPort;
204
+ QHostAddress stunRelayUdpAddr;
205
+ int stunRelayUdpPort;
206
+ QString stunRelayUdpUser;
207
+ QCA::SecureArray stunRelayUdpPass;
208
+ QHostAddress stunRelayTcpAddr;
209
+ int stunRelayTcpPort;
210
+ QString stunRelayTcpUser;
211
+ QCA::SecureArray stunRelayTcpPass;
212
+ QString localUser, localPass;
213
+ QString peerUser, peerPass;
214
+ QList<Component> components;
215
+ QList<IceComponent::Candidate> localCandidates;
216
+ QSet<IceTransport*> iceTransports;
217
+ CheckList checkList;
218
+ QList< QList<QByteArray> > in;
219
+ bool useLocal;
220
+ bool useStunBind;
221
+ bool useStunRelayUdp;
222
+ bool useStunRelayTcp;
223
+ bool useTrickle;
224
+ QTimer *collectTimer;
225
+
226
+ Private(Ice176 *_q) :
227
+ QObject(_q),
228
+ q(_q),
229
+ state(Stopped),
230
+ portReserver(0),
231
+ componentCount(0),
232
+ useLocal(true),
233
+ useStunBind(true),
234
+ useStunRelayUdp(true),
235
+ useStunRelayTcp(true),
236
+ useTrickle(false),
237
+ collectTimer(0)
238
+ {
239
+ }
240
+
241
+ ~Private()
242
+ {
243
+ if(collectTimer)
244
+ {
245
+ collectTimer->disconnect(this);
246
+ collectTimer->deleteLater();
247
+ }
248
+
249
+ foreach(const Component &c, components)
250
+ delete c.ic;
251
+
252
+ for(int n = 0; n < checkList.pairs.count(); ++n)
253
+ {
254
+ StunBinding *binding = checkList.pairsn.binding;
255
+ StunTransactionPool *pool = checkList.pairsn.pool;
256
+
257
+ delete binding;
258
+
259
+ if(pool)
260
+ {
261
+ pool->disconnect(this);
262
+ pool->setParent(0);
263
+ pool->deleteLater();
264
+ }
265
+ }
266
+ }
267
+
268
+ void reset()
269
+ {
270
+ // TODO
271
+ }
272
+
273
+ int findLocalAddress(const QHostAddress &addr)
274
+ {
275
+ for(int n = 0; n < localAddrs.count(); ++n)
276
+ {
277
+ if(localAddrsn.addr == addr)
278
+ return n;
279
+ }
280
+
281
+ return -1;
282
+ }
283
+
284
+ void updateLocalAddresses(const QList<LocalAddress> &addrs)
285
+ {
286
+ // for now, ignore address changes during operation
287
+ if(state != Stopped)
288
+ return;
289
+
290
+ localAddrs.clear();
291
+ foreach(const LocalAddress &la, addrs)
292
+ {
293
+ int at = findLocalAddress(la.addr);
294
+ if(at == -1)
295
+ localAddrs += la;
296
+ }
297
+ }
298
+
299
+ void updateExternalAddresses(const QList<ExternalAddress> &addrs)
300
+ {
301
+ // for now, ignore address changes during operation
302
+ if(state != Stopped)
303
+ return;
304
+
305
+ extAddrs.clear();
306
+ foreach(const ExternalAddress &ea, addrs)
307
+ {
308
+ int at = findLocalAddress(ea.base.addr);
309
+ if(at != -1)
310
+ extAddrs += ea;
311
+ }
312
+ }
313
+
314
+ void start()
315
+ {
316
+ Q_ASSERT(state == Stopped);
317
+
318
+ state = Starting;
319
+
320
+ localUser = randomCredential(4);
321
+ localPass = randomCredential(22);
322
+
323
+ QList<QUdpSocket*> socketList;
324
+ if(portReserver)
325
+ socketList = portReserver->borrowSockets(componentCount, this);
326
+
327
+ for(int n = 0; n < componentCount; ++n)
328
+ {
329
+ Component c;
330
+ c.id = n + 1;
331
+ c.ic = new IceComponent(c.id, this);
332
+ c.ic->setDebugLevel(IceComponent::DL_Info);
333
+ connect(c.ic, SIGNAL(candidateAdded(const XMPP::IceComponent::Candidate &)), SLOT(ic_candidateAdded(const XMPP::IceComponent::Candidate &)));
334
+ connect(c.ic, SIGNAL(candidateRemoved(const XMPP::IceComponent::Candidate &)), SLOT(ic_candidateRemoved(const XMPP::IceComponent::Candidate &)));
335
+ connect(c.ic, SIGNAL(localFinished()), SLOT(ic_localFinished()));
336
+ connect(c.ic, SIGNAL(stopped()), SLOT(ic_stopped()));
337
+ connect(c.ic, SIGNAL(debugLine(const QString &)), SLOT(ic_debugLine(const QString &)));
338
+
339
+ c.ic->setClientSoftwareNameAndVersion("Iris");
340
+ c.ic->setProxy(proxy);
341
+ if(portReserver)
342
+ c.ic->setPortReserver(portReserver);
343
+ c.ic->setLocalAddresses(localAddrs);
344
+ c.ic->setExternalAddresses(extAddrs);
345
+ if(!stunBindAddr.isNull())
346
+ c.ic->setStunBindService(stunBindAddr, stunBindPort);
347
+ if(!stunRelayUdpAddr.isNull())
348
+ c.ic->setStunRelayUdpService(stunRelayUdpAddr, stunRelayUdpPort, stunRelayUdpUser, stunRelayUdpPass);
349
+ if(!stunRelayTcpAddr.isNull())
350
+ c.ic->setStunRelayTcpService(stunRelayTcpAddr, stunRelayTcpPort, stunRelayTcpUser, stunRelayTcpPass);
351
+
352
+ c.ic->setUseLocal(useLocal);
353
+ c.ic->setUseStunBind(useStunBind);
354
+ c.ic->setUseStunRelayUdp(useStunRelayUdp);
355
+ c.ic->setUseStunRelayTcp(useStunRelayTcp);
356
+
357
+ // create an inbound queue for this component
358
+ in += QList<QByteArray>();
359
+
360
+ components += c;
361
+
362
+ c.ic->update(&socketList);
363
+ }
364
+
365
+ // socketList should always empty here, but might not be if
366
+ // the app provided a different address list to
367
+ // UdpPortReserver and Ice176. and that would really be
368
+ // a dumb thing to do but I'm not going to Q_ASSERT it
369
+ if(!socketList.isEmpty())
370
+ portReserver->returnSockets(socketList);
371
+ }
372
+
373
+ void stop()
374
+ {
375
+ Q_ASSERT(state == Starting || state == Started);
376
+
377
+ state = Stopping;
378
+
379
+ if(!components.isEmpty())
380
+ {
381
+ for(int n = 0; n < components.count(); ++n)
382
+ componentsn.ic->stop();
383
+ }
384
+ else
385
+ {
386
+ // TODO: hmm, is it possible to have no components?
387
+ QMetaObject::invokeMethod(this, "postStop", Qt::QueuedConnection);
388
+ }
389
+ }
390
+
391
+ void addRemoteCandidates(const QList<Candidate> &list)
392
+ {
393
+ QList<IceComponent::CandidateInfo> remoteCandidates;
394
+ foreach(const Candidate &c, list)
395
+ {
396
+ IceComponent::CandidateInfo ci;
397
+ ci.addr.addr = c.ip;
398
+ ci.addr.addr.setScopeId(QString());
399
+ ci.addr.port = c.port;
400
+ ci.type = (IceComponent::CandidateType)string_to_candidateType(c.type); // TODO: handle error
401
+ ci.componentId = c.component;
402
+ ci.priority = c.priority;
403
+ ci.foundation = c.foundation;
404
+ if(!c.rel_addr.isNull())
405
+ {
406
+ ci.base.addr = c.rel_addr;
407
+ ci.base.addr.setScopeId(QString());
408
+ ci.base.port = c.rel_port;
409
+ }
410
+ ci.network = c.network;
411
+ ci.id = c.id;
412
+ remoteCandidates += ci;
413
+ }
414
+
415
+ printf("adding %d remote candidates\n", remoteCandidates.count());
416
+
417
+ QList<CandidatePair> pairs;
418
+ foreach(const IceComponent::Candidate &cc, localCandidates)
419
+ {
420
+ const IceComponent::CandidateInfo &lc = cc.info;
421
+
422
+ foreach(const IceComponent::CandidateInfo &rc, remoteCandidates)
423
+ {
424
+ if(lc.componentId != rc.componentId)
425
+ continue;
426
+
427
+ // don't pair ipv4 with ipv6. FIXME: is this right?
428
+ if(lc.addr.addr.protocol() != rc.addr.addr.protocol())
429
+ continue;
430
+
431
+ // don't relay to localhost. turnserver
432
+ // doesn't like it. i don't know if this
433
+ // should qualify as a HACK or not.
434
+ // trying to relay to localhost is pretty
435
+ // stupid anyway
436
+ if(lc.type == IceComponent::RelayedType && getAddressScope(rc.addr.addr) == 0)
437
+ continue;
438
+
439
+ CandidatePair pair;
440
+ pair.state = PFrozen; // FIXME: setting state here may be wrong
441
+ pair.local = lc;
442
+ pair.remote = rc;
443
+ if(pair.local.addr.addr.protocol() == QAbstractSocket::IPv6Protocol && isIPv6LinkLocalAddress(pair.local.addr.addr))
444
+ pair.remote.addr.addr.setScopeId(pair.local.addr.addr.scopeId());
445
+ pair.isDefault = false;
446
+ pair.isValid = false;
447
+ pair.isNominated = false;
448
+ if(mode == Ice176::Initiator)
449
+ pair.priority = calc_pair_priority(lc.priority, rc.priority);
450
+ else
451
+ pair.priority = calc_pair_priority(rc.priority, lc.priority);
452
+ pairs += pair;
453
+ }
454
+ }
455
+
456
+ printf("%d pairs\n", pairs.count());
457
+
458
+ // combine pairs with existing, and sort
459
+ pairs = checkList.pairs + pairs;
460
+ checkList.pairs.clear();
461
+ foreach(const CandidatePair &pair, pairs)
462
+ {
463
+ int at;
464
+ for(at = 0; at < checkList.pairs.count(); ++at)
465
+ {
466
+ if(compare_pair(pair, checkList.pairsat) < 0)
467
+ break;
468
+ }
469
+
470
+ checkList.pairs.insert(at, pair);
471
+ }
472
+
473
+ // pruning
474
+
475
+ for(int n = 0; n < checkList.pairs.count(); ++n)
476
+ {
477
+ CandidatePair &pair = checkList.pairsn;
478
+ if(pair.local.type == IceComponent::ServerReflexiveType)
479
+ pair.local.addr = pair.local.base;
480
+ }
481
+
482
+ for(int n = 0; n < checkList.pairs.count(); ++n)
483
+ {
484
+ CandidatePair &pair = checkList.pairsn;
485
+ 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);
486
+
487
+ bool found = false;
488
+ for(int i = n - 1; i >= 0; --i)
489
+ {
490
+ if(compare_candidates(pair.local, checkList.pairsi.local) && compare_candidates(pair.remote, checkList.pairsi.remote))
491
+ {
492
+ found = true;
493
+ break;
494
+ }
495
+ }
496
+
497
+ if(found )
498
+ {
499
+ checkList.pairs.removeAt(n);
500
+ --n; // adjust position
501
+ }
502
+ }
503
+
504
+ // max pairs is 100 * number of components
505
+ int max_pairs = 100 * components.count();
506
+ while(checkList.pairs.count() > max_pairs)
507
+ checkList.pairs.removeLast();
508
+
509
+ printf("%d after pruning\n", checkList.pairs.count());
510
+
511
+ // set state
512
+ for(int n = 0; n < checkList.pairs.count(); ++n)
513
+ {
514
+ CandidatePair &pair = checkList.pairsn;
515
+
516
+ // only initialize the new pairs
517
+ if(pair.state != PFrozen)
518
+ continue;
519
+
520
+ pair.foundation = pair.local.foundation + pair.remote.foundation;
521
+
522
+ // FIXME: for now we just do checks to everything immediately
523
+ pair.state = PInProgress;
524
+
525
+ int at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port);
526
+ Q_ASSERT(at != -1);
527
+
528
+ IceComponent::Candidate &lc = localCandidatesat;
529
+
530
+ Component &c = componentsfindComponent(lc.info.componentId);
531
+
532
+ pair.pool = new StunTransactionPool(StunTransaction::Udp, this);
533
+ connect(pair.pool, SIGNAL(outgoingMessage(const QByteArray &, const QHostAddress &, int)), SLOT(pool_outgoingMessage(const QByteArray &, const QHostAddress &, int)));
534
+ //pair.pool->setUsername(peerUser + ':' + localUser);
535
+ //pair.pool->setPassword(peerPass.toUtf8());
536
+
537
+ pair.binding = new StunBinding(pair.pool);
538
+ connect(pair.binding, SIGNAL(success()), SLOT(binding_success()));
539
+
540
+ int prflx_priority = c.ic->peerReflexivePriority(lc.iceTransport, lc.path);
541
+ pair.binding->setPriority(prflx_priority);
542
+
543
+ if(mode == Ice176::Initiator)
544
+ {
545
+ pair.binding->setIceControlling(0);
546
+ pair.binding->setUseCandidate(true);
547
+ }
548
+ else
549
+ pair.binding->setIceControlled(0);
550
+
551
+ pair.binding->setShortTermUsername(peerUser + ':' + localUser);
552
+ pair.binding->setShortTermPassword(peerPass);
553
+
554
+ pair.binding->start();
555
+ }
556
+ }
557
+
558
+ void write(int componentIndex, const QByteArray &datagram)
559
+ {
560
+ int at = -1;
561
+ for(int n = 0; n < checkList.pairs.count(); ++n)
562
+ {
563
+ if(checkList.pairsn.local.componentId - 1 == componentIndex && checkList.pairsn.isValid)
564
+ {
565
+ at = n;
566
+ break;
567
+ }
568
+ }
569
+ if(at == -1)
570
+ return;
571
+
572
+ CandidatePair &pair = checkList.pairsat;
573
+
574
+ at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port);
575
+ if(at == -1) // FIXME: assert?
576
+ return;
577
+
578
+ IceComponent::Candidate &lc = localCandidatesat;
579
+
580
+ IceTransport *sock = lc.iceTransport;
581
+ int path = lc.path;
582
+
583
+ sock->writeDatagram(path, datagram, pair.remote.addr.addr, pair.remote.addr.port);
584
+
585
+ // DOR-SR?
586
+ QMetaObject::invokeMethod(q, "datagramsWritten", Qt::QueuedConnection, Q_ARG(int, componentIndex), Q_ARG(int, 1));
587
+ }
588
+
589
+ void flagComponentAsLowOverhead(int componentIndex)
590
+ {
591
+ // FIXME: ok to assume in order?
592
+ Component &c = componentscomponentIndex;
593
+ c.lowOverhead = true;
594
+
595
+ // FIXME: actually do something
596
+ }
597
+
598
+private:
599
+ int findComponent(const IceComponent *ic) const
600
+ {
601
+ for(int n = 0; n < components.count(); ++n)
602
+ {
603
+ if(componentsn.ic == ic)
604
+ return n;
605
+ }
606
+
607
+ return -1;
608
+ }
609
+
610
+ int findComponent(int id) const
611
+ {
612
+ for(int n = 0; n < components.count(); ++n)
613
+ {
614
+ if(componentsn.id == id)
615
+ return n;
616
+ }
617
+
618
+ return -1;
619
+ }
620
+
621
+ int findLocalCandidate(const IceTransport *iceTransport, int path) const
622
+ {
623
+ for(int n = 0; n < localCandidates.count(); ++n)
624
+ {
625
+ const IceComponent::Candidate &cc = localCandidatesn;
626
+ if(cc.iceTransport == iceTransport && cc.path == path)
627
+ return n;
628
+ }
629
+
630
+ return -1;
631
+ }
632
+
633
+ int findLocalCandidate(const QHostAddress &fromAddr, int fromPort)
634
+ {
635
+ for(int n = 0; n < localCandidates.count(); ++n)
636
+ {
637
+ const IceComponent::Candidate &cc = localCandidatesn;
638
+ if(cc.info.addr.addr == fromAddr && cc.info.addr.port == fromPort)
639
+ return n;
640
+ }
641
+
642
+ return -1;
643
+ }
644
+
645
+ static QString candidateType_to_string(IceComponent::CandidateType type)
646
+ {
647
+ QString out;
648
+ switch(type)
649
+ {
650
+ case IceComponent::HostType: out = "host"; break;
651
+ case IceComponent::PeerReflexiveType: out = "prflx"; break;
652
+ case IceComponent::ServerReflexiveType: out = "srflx"; break;
653
+ case IceComponent::RelayedType: out = "relay"; break;
654
+ default: Q_ASSERT(0);
655
+ }
656
+ return out;
657
+ }
658
+
659
+ static int string_to_candidateType(const QString &in)
660
+ {
661
+ if(in == "host")
662
+ return IceComponent::HostType;
663
+ else if(in == "prflx")
664
+ return IceComponent::PeerReflexiveType;
665
+ else if(in == "srflx")
666
+ return IceComponent::ServerReflexiveType;
667
+ else if(in == "relay")
668
+ return IceComponent::RelayedType;
669
+ else
670
+ return -1;
671
+ }
672
+
673
+ static int compare_pair(const CandidatePair &a, const CandidatePair &b)
674
+ {
675
+ // prefer remote srflx, for leap
676
+ if(a.remote.type == IceComponent::ServerReflexiveType && b.remote.type != IceComponent::ServerReflexiveType && b.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol)
677
+ return -1;
678
+ else if(b.remote.type == IceComponent::ServerReflexiveType && a.remote.type != IceComponent::ServerReflexiveType && a.remote.addr.addr.protocol() != QAbstractSocket::IPv6Protocol)
679
+ return 1;
680
+
681
+ if(a.priority > b.priority)
682
+ return -1;
683
+ else if(b.priority > a.priority)
684
+ return 1;
685
+
686
+ return 0;
687
+ }
688
+
689
+private slots:
690
+ void postStop()
691
+ {
692
+ state = Stopped;
693
+ emit q->stopped();
694
+ }
695
+
696
+ void ic_candidateAdded(const XMPP::IceComponent::Candidate &_cc)
697
+ {
698
+ IceComponent::Candidate cc = _cc;
699
+ cc.info.id = randomCredential(10); // FIXME: ensure unique
700
+ cc.info.foundation = "0"; // FIXME
701
+ // TODO
702
+ localCandidates += cc;
703
+
704
+ printf("C%d: candidate added: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), cc.info.addr.port);
705
+
706
+ if(!iceTransports.contains(cc.iceTransport))
707
+ {
708
+ connect(cc.iceTransport, SIGNAL(readyRead(int)), SLOT(it_readyRead(int)));
709
+ connect(cc.iceTransport, SIGNAL(datagramsWritten(int, int, const QHostAddress &, int)), SLOT(it_datagramsWritten(int, int, const QHostAddress &, int)));
710
+
711
+ iceTransports += cc.iceTransport;
712
+ }
713
+
714
+ if(state == Started && useTrickle)
715
+ {
716
+ QList<Ice176::Candidate> list;
717
+
718
+ Ice176::Candidate c;
719
+ c.component = cc.info.componentId;
720
+ c.foundation = cc.info.foundation;
721
+ c.generation = 0; // TODO
722
+ c.id = cc.info.id;
723
+ c.ip = cc.info.addr.addr;
724
+ c.ip.setScopeId(QString());
725
+ c.network = cc.info.network;
726
+ c.port = cc.info.addr.port;
727
+ c.priority = cc.info.priority;
728
+ c.protocol = "udp";
729
+ if(cc.info.type != IceComponent::HostType)
730
+ {
731
+ c.rel_addr = cc.info.base.addr;
732
+ c.rel_addr.setScopeId(QString());
733
+ c.rel_port = cc.info.base.port;
734
+ }
735
+ else
736
+ {
737
+ c.rel_addr = QHostAddress();
738
+ c.rel_port = -1;
739
+ }
740
+ c.rem_addr = QHostAddress();
741
+ c.rem_port = -1;
742
+ c.type = candidateType_to_string(cc.info.type);
743
+ list += c;
744
+
745
+ emit q->localCandidatesReady(list);
746
+ }
747
+ }
748
+
749
+ void ic_candidateRemoved(const XMPP::IceComponent::Candidate &cc)
750
+ {
751
+ // TODO
752
+ printf("C%d: candidate removed: %s;%d\n", cc.info.componentId, qPrintable(cc.info.addr.addr.toString()), cc.info.addr.port);
753
+
754
+ QStringList idList;
755
+ for(int n = 0; n < localCandidates.count(); ++n)
756
+ {
757
+ if(localCandidatesn.id == cc.id && localCandidatesn.info.componentId == cc.info.componentId)
758
+ {
759
+ // FIXME: this is rather ridiculous I think
760
+ idList += localCandidatesn.info.id;
761
+
762
+ localCandidates.removeAt(n);
763
+ --n; // adjust position
764
+ }
765
+ }
766
+
767
+ bool iceTransportInUse = false;
768
+ foreach(const IceComponent::Candidate &lc, localCandidates)
769
+ {
770
+ if(lc.iceTransport == cc.iceTransport)
771
+ {
772
+ iceTransportInUse = true;
773
+ break;
774
+ }
775
+ }
776
+ if(!iceTransportInUse)
777
+ {
778
+ cc.iceTransport->disconnect(this);
779
+ iceTransports.remove(cc.iceTransport);
780
+ }
781
+
782
+ for(int n = 0; n < checkList.pairs.count(); ++n)
783
+ {
784
+ if(idList.contains(checkList.pairsn.local.id))
785
+ {
786
+ StunBinding *binding = checkList.pairsn.binding;
787
+ StunTransactionPool *pool = checkList.pairsn.pool;
788
+
789
+ delete binding;
790
+
791
+ if(pool)
792
+ {
793
+ pool->disconnect(this);
794
+ pool->setParent(0);
795
+ pool->deleteLater();
796
+ }
797
+
798
+ checkList.pairs.removeAt(n);
799
+ --n; // adjust position
800
+ }
801
+ }
802
+ }
803
+
804
+ void ic_localFinished()
805
+ {
806
+ IceComponent *ic = (IceComponent *)sender();
807
+ int at = findComponent(ic);
808
+ Q_ASSERT(at != -1);
809
+
810
+ componentsat.localFinished = true;
811
+
812
+ bool allFinished = true;
813
+ foreach(const Component &c, components)
814
+ {
815
+ if(!c.localFinished)
816
+ {
817
+ allFinished = false;
818
+ break;
819
+ }
820
+ }
821
+
822
+ if(allFinished)
823
+ {
824
+ state = Started;
825
+
826
+ emit q->started();
827
+
828
+ if(!useTrickle)
829
+ {
830
+ // FIXME: there should be a way to not wait if
831
+ // we know for sure there is nothing else
832
+ // possibly coming
833
+ collectTimer = new QTimer(this);
834
+ connect(collectTimer, SIGNAL(timeout()), SLOT(collect_timeout()));
835
+ collectTimer->setSingleShot(true);
836
+ collectTimer->start(4000);
837
+ return;
838
+ }
839
+
840
+ // FIXME: DOR-SS
841
+ QList<Ice176::Candidate> list;
842
+ foreach(const IceComponent::Candidate &cc, localCandidates)
843
+ {
844
+ Ice176::Candidate c;
845
+ c.component = cc.info.componentId;
846
+ c.foundation = cc.info.foundation;
847
+ c.generation = 0; // TODO
848
+ c.id = cc.info.id;
849
+ c.ip = cc.info.addr.addr;
850
+ c.ip.setScopeId(QString());
851
+ c.network = cc.info.network;
852
+ c.port = cc.info.addr.port;
853
+ c.priority = cc.info.priority;
854
+ c.protocol = "udp";
855
+ if(cc.info.type != IceComponent::HostType)
856
+ {
857
+ c.rel_addr = cc.info.base.addr;
858
+ c.rel_addr.setScopeId(QString());
859
+ c.rel_port = cc.info.base.port;
860
+ }
861
+ else
862
+ {
863
+ c.rel_addr = QHostAddress();
864
+ c.rel_port = -1;
865
+ }
866
+ c.rem_addr = QHostAddress();
867
+ c.rem_port = -1;
868
+ c.type = candidateType_to_string(cc.info.type);
869
+ list += c;
870
+ }
871
+ if(!list.isEmpty())
872
+ emit q->localCandidatesReady(list);
873
+ }
874
+ }
875
+
876
+ void ic_stopped()
877
+ {
878
+ IceComponent *ic = (IceComponent *)sender();
879
+ int at = findComponent(ic);
880
+ Q_ASSERT(at != -1);
881
+
882
+ componentsat.stopped = true;
883
+
884
+ bool allStopped = true;
885
+ foreach(const Component &c, components)
886
+ {
887
+ if(!c.stopped)
888
+ {
889
+ allStopped = false;
890
+ break;
891
+ }
892
+ }
893
+
894
+ if(allStopped)
895
+ postStop();
896
+ }
897
+
898
+ void ic_debugLine(const QString &line)
899
+ {
900
+ IceComponent *ic = (IceComponent *)sender();
901
+ int at = findComponent(ic);
902
+ Q_ASSERT(at != -1);
903
+
904
+ // FIXME: components are always sorted?
905
+ printf("C%d: %s\n", at + 1, qPrintable(line));
906
+ }
907
+
908
+ void collect_timeout()
909
+ {
910
+ collectTimer->disconnect(this);
911
+ collectTimer->deleteLater();
912
+ collectTimer = 0;
913
+
914
+ QList<Ice176::Candidate> list;
915
+ foreach(const IceComponent::Candidate &cc, localCandidates)
916
+ {
917
+ Ice176::Candidate c;
918
+ c.component = cc.info.componentId;
919
+ c.foundation = cc.info.foundation;
920
+ c.generation = 0; // TODO
921
+ c.id = cc.info.id;
922
+ c.ip = cc.info.addr.addr;
923
+ c.ip.setScopeId(QString());
924
+ c.network = cc.info.network;
925
+ c.port = cc.info.addr.port;
926
+ c.priority = cc.info.priority;
927
+ c.protocol = "udp";
928
+ if(cc.info.type != IceComponent::HostType)
929
+ {
930
+ c.rel_addr = cc.info.base.addr;
931
+ c.rel_addr.setScopeId(QString());
932
+ c.rel_port = cc.info.base.port;
933
+ }
934
+ else
935
+ {
936
+ c.rel_addr = QHostAddress();
937
+ c.rel_port = -1;
938
+ }
939
+ c.rem_addr = QHostAddress();
940
+ c.rem_port = -1;
941
+ c.type = candidateType_to_string(cc.info.type);
942
+ list += c;
943
+ }
944
+ if(!list.isEmpty())
945
+ emit q->localCandidatesReady(list);
946
+ }
947
+
948
+ void it_readyRead(int path)
949
+ {
950
+ IceTransport *it = (IceTransport *)sender();
951
+ int at = findLocalCandidate(it, path);
952
+ Q_ASSERT(at != -1);
953
+
954
+ IceComponent::Candidate &cc = localCandidatesat;
955
+
956
+ IceTransport *sock = it;
957
+
958
+ while(sock->hasPendingDatagrams(path))
959
+ {
960
+ QHostAddress fromAddr;
961
+ int fromPort;
962
+ QByteArray buf = sock->readDatagram(path, &fromAddr, &fromPort);
963
+
964
+ //printf("port %d: received packet (%d bytes)\n", lt->sock->localPort(), buf.size());
965
+
966
+ QString requser = localUser + ':' + peerUser;
967
+ QByteArray reqkey = localPass.toUtf8();
968
+
969
+ StunMessage::ConvertResult result;
970
+ StunMessage msg = StunMessage::fromBinary(buf, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, reqkey);
971
+ if(!msg.isNull() && (msg.mclass() == StunMessage::Request || msg.mclass() == StunMessage::Indication))
972
+ {
973
+ printf("received validated request or indication from %s:%d\n", qPrintable(fromAddr.toString()), fromPort);
974
+ QString user = QString::fromUtf8(msg.attribute(0x0006)); // USERNAME
975
+ if(requser != user)
976
+ {
977
+ printf("user %s is wrong. it should be %s. skipping\n", qPrintable(user), qPrintable(requser));
978
+ continue;
979
+ }
980
+
981
+ if(msg.method() != 0x001)
982
+ {
983
+ printf("not a binding request. skipping\n");
984
+ continue;
985
+ }
986
+
987
+ StunMessage response;
988
+ response.setClass(StunMessage::SuccessResponse);
989
+ response.setMethod(0x001);
990
+ response.setId(msg.id());
991
+
992
+ quint16 port16 = fromPort;
993
+ quint32 addr4 = fromAddr.toIPv4Address();
994
+ QByteArray val(8, 0);
995
+ quint8 *p = (quint8 *)val.data();
996
+ const quint8 *magic = response.magic();
997
+ p0 = 0;
998
+ p1 = 0x01;
999
+ p2 = (port16 >> 8) & 0xff;
1000
+ p2 ^= magic0;
1001
+ p3 = port16 & 0xff;
1002
+ p3 ^= magic1;
1003
+ p4 = (addr4 >> 24) & 0xff;
1004
+ p4 ^= magic0;
1005
+ p5 = (addr4 >> 16) & 0xff;
1006
+ p5 ^= magic1;
1007
+ p6 = (addr4 >> 8) & 0xff;
1008
+ p6 ^= magic2;
1009
+ p7 = addr4 & 0xff;
1010
+ p7 ^= magic3;
1011
+
1012
+ QList<StunMessage::Attribute> list;
1013
+ StunMessage::Attribute attr;
1014
+ attr.type = 0x0020;
1015
+ attr.value = val;
1016
+ list += attr;
1017
+
1018
+ response.setAttributes(list);
1019
+
1020
+ QByteArray packet = response.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, reqkey);
1021
+ sock->writeDatagram(path, packet, fromAddr, fromPort);
1022
+ }
1023
+ else
1024
+ {
1025
+ QByteArray reskey = peerPass.toUtf8();
1026
+ StunMessage msg = StunMessage::fromBinary(buf, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, reskey);
1027
+ if(!msg.isNull() && (msg.mclass() == StunMessage::SuccessResponse || msg.mclass() == StunMessage::ErrorResponse))
1028
+ {
1029
+ printf("received validated response\n");
1030
+
1031
+ // FIXME: this is so gross and completely defeats the point of having pools
1032
+ for(int n = 0; n < checkList.pairs.count(); ++n)
1033
+ {
1034
+ CandidatePair &pair = checkList.pairsn;
1035
+ if(pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port)
1036
+ pair.pool->writeIncomingMessage(msg);
1037
+ }
1038
+ }
1039
+ else
1040
+ {
1041
+ //printf("received some non-stun or invalid stun packet\n");
1042
+
1043
+ // FIXME: i don't know if this is good enough
1044
+ if(StunMessage::isProbablyStun(buf))
1045
+ {
1046
+ printf("unexpected stun packet (loopback?), skipping.\n");
1047
+ continue;
1048
+ }
1049
+
1050
+ int at = -1;
1051
+ for(int n = 0; n < checkList.pairs.count(); ++n)
1052
+ {
1053
+ CandidatePair &pair = checkList.pairsn;
1054
+ if(pair.local.addr.addr == cc.info.addr.addr && pair.local.addr.port == cc.info.addr.port)
1055
+ {
1056
+ at = n;
1057
+ break;
1058
+ }
1059
+ }
1060
+ if(at == -1)
1061
+ {
1062
+ printf("the local transport does not seem to be associated with a candidate?!\n");
1063
+ continue;
1064
+ }
1065
+
1066
+ int componentIndex = checkList.pairsat.local.componentId - 1;
1067
+ //printf("packet is considered to be application data for component index %d\n", componentIndex);
1068
+
1069
+ // FIXME: this assumes components are ordered by id in our local arrays
1070
+ incomponentIndex += buf;
1071
+ emit q->readyRead(componentIndex);
1072
+ }
1073
+ }
1074
+ }
1075
+ }
1076
+
1077
+ void it_datagramsWritten(int path, int count, const QHostAddress &addr, int port)
1078
+ {
1079
+ // TODO
1080
+ Q_UNUSED(path);
1081
+ Q_UNUSED(count);
1082
+ Q_UNUSED(addr);
1083
+ Q_UNUSED(port);
1084
+ }
1085
+
1086
+ void pool_outgoingMessage(const QByteArray &packet, const QHostAddress &addr, int port)
1087
+ {
1088
+ Q_UNUSED(addr);
1089
+ Q_UNUSED(port);
1090
+
1091
+ StunTransactionPool *pool = (StunTransactionPool *)sender();
1092
+ int at = -1;
1093
+ for(int n = 0; n < checkList.pairs.count(); ++n)
1094
+ {
1095
+ if(checkList.pairsn.pool == pool)
1096
+ {
1097
+ at = n;
1098
+ break;
1099
+ }
1100
+ }
1101
+ if(at == -1) // FIXME: assert?
1102
+ return;
1103
+
1104
+ CandidatePair &pair = checkList.pairsat;
1105
+
1106
+ at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port);
1107
+ if(at == -1) // FIXME: assert?
1108
+ return;
1109
+
1110
+ IceComponent::Candidate &lc = localCandidatesat;
1111
+
1112
+ IceTransport *sock = lc.iceTransport;
1113
+ int path = lc.path;
1114
+
1115
+ 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);
1116
+ sock->writeDatagram(path, packet, pair.remote.addr.addr, pair.remote.addr.port);
1117
+ }
1118
+
1119
+ void binding_success()
1120
+ {
1121
+ StunBinding *binding = (StunBinding *)sender();
1122
+ int at = -1;
1123
+ for(int n = 0; n < checkList.pairs.count(); ++n)
1124
+ {
1125
+ if(checkList.pairsn.binding == binding)
1126
+ {
1127
+ at = n;
1128
+ break;
1129
+ }
1130
+ }
1131
+ if(at == -1)
1132
+ return;
1133
+
1134
+ printf("check success\n");
1135
+
1136
+ CandidatePair &pair = checkList.pairsat;
1137
+
1138
+ // TODO: if we were cool, we'd do something with the peer
1139
+ // reflexive address received
1140
+
1141
+ // TODO: we're also supposed to do triggered checks. except
1142
+ // that currently we check everything anyway so this is not
1143
+ // relevant
1144
+
1145
+ // check if there's a candidate already valid
1146
+ at = -1;
1147
+ for(int n = 0; n < checkList.pairs.count(); ++n)
1148
+ {
1149
+ if(checkList.pairsn.local.componentId == pair.local.componentId && checkList.pairsn.isValid)
1150
+ {
1151
+ at = n;
1152
+ break;
1153
+ }
1154
+ }
1155
+
1156
+ pair.isValid = true;
1157
+
1158
+ if(at == -1)
1159
+ {
1160
+ int at = findComponent(pair.local.componentId);
1161
+ Component &c = componentsat;
1162
+ if(c.lowOverhead)
1163
+ {
1164
+ printf("component is flagged for low overhead. setting up for %s;%d -> %s;%d\n",
1165
+ qPrintable(pair.local.addr.addr.toString()), pair.local.addr.port, qPrintable(pair.remote.addr.addr.toString()), pair.remote.addr.port);
1166
+ at = findLocalCandidate(pair.local.addr.addr, pair.local.addr.port);
1167
+ IceComponent::Candidate &cc = localCandidatesat;
1168
+ c.ic->flagPathAsLowOverhead(cc.id, pair.remote.addr.addr, pair.remote.addr.port);
1169
+ }
1170
+
1171
+ emit q->componentReady(pair.local.componentId - 1);
1172
+ }
1173
+ else
1174
+ {
1175
+ printf("component %d already active, not signalling\n", pair.local.componentId);
1176
+ }
1177
+ }
1178
+};
1179
+
1180
+Ice176::Ice176(QObject *parent) :
1181
+ QObject(parent)
1182
+{
1183
+ d = new Private(this);
1184
+}
1185
+
1186
+Ice176::~Ice176()
1187
+{
1188
+ delete d;
1189
+}
1190
+
1191
+void Ice176::reset()
1192
+{
1193
+ d->reset();
1194
+}
1195
+
1196
+void Ice176::setProxy(const TurnClient::Proxy &proxy)
1197
+{
1198
+ d->proxy = proxy;
1199
+}
1200
+
1201
+void Ice176::setPortReserver(UdpPortReserver *portReserver)
1202
+{
1203
+ Q_ASSERT(d->state == Private::Stopped);
1204
+
1205
+ d->portReserver = portReserver;
1206
+}
1207
+
1208
+void Ice176::setLocalAddresses(const QList<LocalAddress> &addrs)
1209
+{
1210
+ d->updateLocalAddresses(addrs);
1211
+}
1212
+
1213
+void Ice176::setExternalAddresses(const QList<ExternalAddress> &addrs)
1214
+{
1215
+ d->updateExternalAddresses(addrs);
1216
+}
1217
+
1218
+void Ice176::setStunBindService(const QHostAddress &addr, int port)
1219
+{
1220
+ d->stunBindAddr = addr;
1221
+ d->stunBindPort = port;
1222
+}
1223
+
1224
+void Ice176::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass)
1225
+{
1226
+ d->stunRelayUdpAddr = addr;
1227
+ d->stunRelayUdpPort = port;
1228
+ d->stunRelayUdpUser = user;
1229
+ d->stunRelayUdpPass = pass;
1230
+}
1231
+
1232
+void Ice176::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass)
1233
+{
1234
+ d->stunRelayTcpAddr = addr;
1235
+ d->stunRelayTcpPort = port;
1236
+ d->stunRelayTcpUser = user;
1237
+ d->stunRelayTcpPass = pass;
1238
+}
1239
+
1240
+void Ice176::setUseLocal(bool enabled)
1241
+{
1242
+ d->useLocal = enabled;
1243
+}
1244
+
1245
+void Ice176::setUseStunBind(bool enabled)
1246
+{
1247
+ d->useStunBind = enabled;
1248
+}
1249
+
1250
+void Ice176::setUseStunRelayUdp(bool enabled)
1251
+{
1252
+ d->useStunRelayUdp = enabled;
1253
+}
1254
+
1255
+void Ice176::setUseStunRelayTcp(bool enabled)
1256
+{
1257
+ d->useStunRelayTcp = enabled;
1258
+}
1259
+
1260
+void Ice176::setComponentCount(int count)
1261
+{
1262
+ Q_ASSERT(d->state == Private::Stopped);
1263
+
1264
+ d->componentCount = count;
1265
+}
1266
+
1267
+void Ice176::setLocalCandidateTrickle(bool enabled)
1268
+{
1269
+ d->useTrickle = enabled;
1270
+}
1271
+
1272
+void Ice176::start(Mode mode)
1273
+{
1274
+ d->mode = mode;
1275
+ d->start();
1276
+}
1277
+
1278
+void Ice176::stop()
1279
+{
1280
+ d->stop();
1281
+}
1282
+
1283
+QString Ice176::localUfrag() const
1284
+{
1285
+ return d->localUser;
1286
+}
1287
+
1288
+QString Ice176::localPassword() const
1289
+{
1290
+ return d->localPass;
1291
+}
1292
+
1293
+void Ice176::setPeerUfrag(const QString &ufrag)
1294
+{
1295
+ d->peerUser = ufrag;
1296
+}
1297
+
1298
+void Ice176::setPeerPassword(const QString &pass)
1299
+{
1300
+ d->peerPass = pass;
1301
+}
1302
+
1303
+void Ice176::addRemoteCandidates(const QList<Candidate> &list)
1304
+{
1305
+ d->addRemoteCandidates(list);
1306
+}
1307
+
1308
+bool Ice176::hasPendingDatagrams(int componentIndex) const
1309
+{
1310
+ return !d->incomponentIndex.isEmpty();
1311
+}
1312
+
1313
+QByteArray Ice176::readDatagram(int componentIndex)
1314
+{
1315
+ return d->incomponentIndex.takeFirst();
1316
+}
1317
+
1318
+void Ice176::writeDatagram(int componentIndex, const QByteArray &datagram)
1319
+{
1320
+ d->write(componentIndex, datagram);
1321
+}
1322
+
1323
+void Ice176::flagComponentAsLowOverhead(int componentIndex)
1324
+{
1325
+ d->flagComponentAsLowOverhead(componentIndex);
1326
+}
1327
+
1328
+bool Ice176::isIPv6LinkLocalAddress(const QHostAddress &addr)
1329
+{
1330
+ Q_ASSERT(addr.protocol() == QAbstractSocket::IPv6Protocol);
1331
+ Q_IPV6ADDR addr6 = addr.toIPv6Address();
1332
+ quint16 hi = addr60;
1333
+ hi <<= 8;
1334
+ hi += addr61;
1335
+ if((hi & 0xffc0) == 0xfe80)
1336
+ return true;
1337
+ else
1338
+ return false;
1339
+}
1340
+
1341
+}
1342
+
1343
+#include "ice176.moc"
1344
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/ice176.h
Added
191
1
2
+/*
3
+ * Copyright (C) 2009,2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef ICE176_H
23
+#define ICE176_H
24
+
25
+#include <QObject>
26
+#include <QString>
27
+#include <QHostAddress>
28
+#include "turnclient.h"
29
+
30
+namespace QCA {
31
+ class SecureArray;
32
+}
33
+
34
+namespace XMPP {
35
+
36
+class UdpPortReserver;
37
+
38
+class Ice176 : public QObject
39
+{
40
+ Q_OBJECT
41
+
42
+public:
43
+ enum Error
44
+ {
45
+ ErrorGeneric
46
+ };
47
+
48
+ enum Mode
49
+ {
50
+ Initiator,
51
+ Responder
52
+ };
53
+
54
+ class LocalAddress
55
+ {
56
+ public:
57
+ QHostAddress addr;
58
+ int network; // -1 = unknown
59
+ bool isVpn;
60
+
61
+ LocalAddress() :
62
+ network(-1),
63
+ isVpn(false)
64
+ {
65
+ }
66
+ };
67
+
68
+ class ExternalAddress
69
+ {
70
+ public:
71
+ LocalAddress base;
72
+ QHostAddress addr;
73
+ int portBase; // -1 = same as base
74
+
75
+ ExternalAddress() :
76
+ portBase(-1)
77
+ {
78
+ }
79
+ };
80
+
81
+ class Candidate
82
+ {
83
+ public:
84
+ int component;
85
+ QString foundation;
86
+ int generation;
87
+ QString id;
88
+ QHostAddress ip;
89
+ int network; // -1 = unknown
90
+ int port;
91
+ int priority;
92
+ QString protocol;
93
+ QHostAddress rel_addr;
94
+ int rel_port;
95
+ QHostAddress rem_addr;
96
+ int rem_port;
97
+ QString type;
98
+
99
+ Candidate() :
100
+ component(-1),
101
+ generation(-1),
102
+ network(-1),
103
+ port(-1),
104
+ priority(-1),
105
+ rel_port(-1),
106
+ rem_port(-1)
107
+ {
108
+ }
109
+ };
110
+
111
+ Ice176(QObject *parent = 0);
112
+ ~Ice176();
113
+
114
+ void reset();
115
+
116
+ void setProxy(const TurnClient::Proxy &proxy);
117
+
118
+ // if set, ports will be drawn from the reserver if possible, before
119
+ // binding to random ports
120
+ // note: ownership is not passed
121
+ void setPortReserver(UdpPortReserver *portReserver);
122
+
123
+ void setLocalAddresses(const QList<LocalAddress> &addrs);
124
+
125
+ // one per local address. you must set local addresses first.
126
+ void setExternalAddresses(const QList<ExternalAddress> &addrs);
127
+
128
+ void setStunBindService(const QHostAddress &addr, int port);
129
+ void setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass);
130
+ void setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass);
131
+
132
+ // these all start out enabled, but can be disabled for diagnostic
133
+ // purposes
134
+ void setUseLocal(bool enabled);
135
+ void setUseStunBind(bool enabled);
136
+ void setUseStunRelayUdp(bool enabled);
137
+ void setUseStunRelayTcp(bool enabled);
138
+
139
+ void setComponentCount(int count);
140
+ void setLocalCandidateTrickle(bool enabled); // default false
141
+
142
+ void start(Mode mode);
143
+ void stop();
144
+
145
+ QString localUfrag() const;
146
+ QString localPassword() const;
147
+
148
+ void setPeerUfrag(const QString &ufrag);
149
+ void setPeerPassword(const QString &pass);
150
+
151
+ void addRemoteCandidates(const QList<Candidate> &list);
152
+
153
+ bool hasPendingDatagrams(int componentIndex) const;
154
+ QByteArray readDatagram(int componentIndex);
155
+ void writeDatagram(int componentIndex, const QByteArray &datagram);
156
+
157
+ // this call will ensure that TURN headers are minimized on this
158
+ // component, with the drawback that packets might not be able to
159
+ // be set as non-fragmentable. use this on components that expect
160
+ // to send lots of very small packets, where header overhead is the
161
+ // most costly but also where fragmentation is impossible anyway.
162
+ // in short, use this on audio, but not on video.
163
+ void flagComponentAsLowOverhead(int componentIndex);
164
+
165
+ // FIXME: this should probably be in netinterface.h or such
166
+ static bool isIPv6LinkLocalAddress(const QHostAddress &addr);
167
+
168
+signals:
169
+ // indicates that the ice engine is started and is ready to receive
170
+ // peer creds and remote candidates
171
+ void started();
172
+
173
+ void stopped();
174
+ void error(XMPP::Ice176::Error e);
175
+
176
+ void localCandidatesReady(const QList<XMPP::Ice176::Candidate> &list);
177
+ void componentReady(int index);
178
+
179
+ void readyRead(int componentIndex);
180
+ void datagramsWritten(int componentIndex, int count);
181
+
182
+private:
183
+ class Private;
184
+ friend class Private;
185
+ Private *d;
186
+};
187
+
188
+}
189
+
190
+#endif
191
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icecomponent.cpp
Added
1058
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "icecomponent.h"
23
+
24
+#include <QUdpSocket>
25
+#include <QtCrypto>
26
+#include "objectsession.h"
27
+#include "udpportreserver.h"
28
+#include "icelocaltransport.h"
29
+#include "iceturntransport.h"
30
+
31
+namespace XMPP {
32
+
33
+static int calc_priority(int typePref, int localPref, int componentId)
34
+{
35
+ Q_ASSERT(typePref >= 0 && typePref <= 126);
36
+ Q_ASSERT(localPref >= 0 && localPref <= 65535);
37
+ Q_ASSERT(componentId >= 1 && componentId <= 256);
38
+
39
+ int priority = (1 << 24) * typePref;
40
+ priority += (1 << 8) * localPref;
41
+ priority += (256 - componentId);
42
+ return priority;
43
+}
44
+
45
+class IceComponent::Private : public QObject
46
+{
47
+ Q_OBJECT
48
+
49
+public:
50
+ class Config
51
+ {
52
+ public:
53
+ QList<Ice176::LocalAddress> localAddrs;
54
+ QList<Ice176::ExternalAddress> extAddrs;
55
+
56
+ QHostAddress stunBindAddr;
57
+ int stunBindPort;
58
+
59
+ QHostAddress stunRelayUdpAddr;
60
+ int stunRelayUdpPort;
61
+ QString stunRelayUdpUser;
62
+ QCA::SecureArray stunRelayUdpPass;
63
+
64
+ QHostAddress stunRelayTcpAddr;
65
+ int stunRelayTcpPort;
66
+ QString stunRelayTcpUser;
67
+ QCA::SecureArray stunRelayTcpPass;
68
+ };
69
+
70
+ class LocalTransport
71
+ {
72
+ public:
73
+ QUdpSocket *qsock;
74
+ bool borrowedSocket;
75
+ QHostAddress addr;
76
+ IceLocalTransport *sock;
77
+ int network;
78
+ bool isVpn;
79
+ bool started;
80
+ bool stun_started;
81
+ bool stun_finished, turn_finished;
82
+ QHostAddress extAddr;
83
+ bool ext_finished;
84
+
85
+ LocalTransport() :
86
+ qsock(0),
87
+ borrowedSocket(false),
88
+ sock(0),
89
+ network(-1),
90
+ isVpn(false),
91
+ started(false),
92
+ stun_started(false),
93
+ stun_finished(false),
94
+ turn_finished(false),
95
+ ext_finished(false)
96
+ {
97
+ }
98
+ };
99
+
100
+ IceComponent *q;
101
+ ObjectSession sess;
102
+ int id;
103
+ QString clientSoftware;
104
+ TurnClient::Proxy proxy;
105
+ UdpPortReserver *portReserver;
106
+ Config pending;
107
+ Config config;
108
+ bool stopping;
109
+ QList<LocalTransport*> localLeap;
110
+ QList<LocalTransport*> localStun;
111
+ IceTurnTransport *tt;
112
+ QList<Candidate> localCandidates;
113
+ QHash<int, QSet<TransportAddress> > channelPeers;
114
+ bool useLocal;
115
+ bool useStunBind;
116
+ bool useStunRelayUdp;
117
+ bool useStunRelayTcp;
118
+ bool local_finished;
119
+ int debugLevel;
120
+
121
+ Private(IceComponent *_q) :
122
+ QObject(_q),
123
+ q(_q),
124
+ sess(this),
125
+ portReserver(0),
126
+ stopping(false),
127
+ tt(0),
128
+ useLocal(true),
129
+ useStunBind(true),
130
+ useStunRelayUdp(true),
131
+ useStunRelayTcp(true),
132
+ local_finished(false),
133
+ debugLevel(DL_None)
134
+ {
135
+ }
136
+
137
+ ~Private()
138
+ {
139
+ QList<QUdpSocket*> socketsToReturn;
140
+
141
+ for(int n = 0; n < localLeap.count(); ++n)
142
+ {
143
+ delete localLeapn->sock;
144
+
145
+ if(localLeapn->borrowedSocket)
146
+ socketsToReturn += localLeapn->qsock;
147
+ else
148
+ localLeapn->qsock->deleteLater();
149
+ }
150
+
151
+ if(!socketsToReturn.isEmpty())
152
+ portReserver->returnSockets(socketsToReturn);
153
+
154
+ qDeleteAll(localLeap);
155
+
156
+ for(int n = 0; n < localStun.count(); ++n)
157
+ delete localStunn->sock;
158
+
159
+ qDeleteAll(localStun);
160
+
161
+ delete tt;
162
+ }
163
+
164
+ void update(QList<QUdpSocket*> *socketList)
165
+ {
166
+ Q_ASSERT(!stopping);
167
+
168
+ // for now, only allow setting localAddrs once
169
+ if(!pending.localAddrs.isEmpty() && config.localAddrs.isEmpty())
170
+ {
171
+ foreach(const Ice176::LocalAddress &la, pending.localAddrs)
172
+ {
173
+ // skip duplicate addrs
174
+ if(findLocalAddr(la.addr) != -1)
175
+ continue;
176
+
177
+ if(!useLocal)
178
+ {
179
+ // skip out, but log the address in
180
+ // case we need it for stun
181
+ config.localAddrs += la;
182
+ continue;
183
+ }
184
+
185
+ QUdpSocket *qsock = 0;
186
+ if(socketList)
187
+ qsock = takeFromSocketList(socketList, la.addr, this);
188
+
189
+ bool borrowedSocket;
190
+ if(qsock)
191
+ {
192
+ borrowedSocket = true;
193
+ }
194
+ else
195
+ {
196
+ // otherwise, bind to random
197
+ qsock = new QUdpSocket(this);
198
+ if(!qsock->bind(la.addr, 0))
199
+ {
200
+ delete qsock;
201
+ emit q->debugLine("Warning: unable to bind to random port.");
202
+ continue;
203
+ }
204
+
205
+ borrowedSocket = false;
206
+ }
207
+
208
+ int port = qsock->localPort();
209
+
210
+ config.localAddrs += la;
211
+
212
+ LocalTransport *lt = new LocalTransport;
213
+ lt->addr = la.addr;
214
+ lt->qsock = qsock;
215
+ lt->borrowedSocket = borrowedSocket;
216
+ lt->sock = new IceLocalTransport(this);
217
+ lt->sock->setDebugLevel((IceTransport::DebugLevel)debugLevel);
218
+ lt->network = la.network;
219
+ lt->isVpn = la.isVpn;
220
+ connect(lt->sock, SIGNAL(started()), SLOT(lt_started()));
221
+ connect(lt->sock, SIGNAL(stopped()), SLOT(lt_stopped()));
222
+ connect(lt->sock, SIGNAL(addressesChanged()), SLOT(lt_addressesChanged()));
223
+ connect(lt->sock, SIGNAL(error(int)), SLOT(lt_error(int)));
224
+ connect(lt->sock, SIGNAL(debugLine(const QString &)), SLOT(lt_debugLine(const QString &)));
225
+ localLeap += lt;
226
+
227
+ lt->sock->start(qsock);
228
+ emit q->debugLine(QString("starting transport ") + la.addr.toString() + ';' + QString::number(port) + " for component " + QString::number(id));
229
+ }
230
+ }
231
+
232
+ // extAddrs created on demand if present, but only once
233
+ if(!pending.extAddrs.isEmpty() && config.extAddrs.isEmpty())
234
+ {
235
+ config.extAddrs = pending.extAddrs;
236
+
237
+ bool need_doExt = false;
238
+
239
+ foreach(LocalTransport *lt, localLeap)
240
+ {
241
+ // already assigned an ext address? skip
242
+ if(!lt->extAddr.isNull())
243
+ continue;
244
+
245
+ QHostAddress laddr = lt->sock->localAddress();
246
+ int lport = lt->sock->localPort();
247
+
248
+ int at = -1;
249
+ for(int n = 0; n < config.extAddrs.count(); ++n)
250
+ {
251
+ const Ice176::ExternalAddress &ea = config.extAddrsn;
252
+ if(laddr.protocol() != QAbstractSocket::IPv6Protocol && ea.base.addr == laddr && (ea.portBase == -1 || ea.portBase == lport))
253
+ {
254
+ at = n;
255
+ break;
256
+ }
257
+ }
258
+
259
+ if(at != -1)
260
+ {
261
+ lt->extAddr = config.extAddrsat.addr;
262
+ if(lt->started)
263
+ need_doExt = true;
264
+ }
265
+ }
266
+
267
+ if(need_doExt)
268
+ sess.defer(this, "doExt");
269
+ }
270
+
271
+ // only allow setting stun stuff once
272
+ if(!pending.stunBindAddr.isNull() && config.stunBindAddr.isNull())
273
+ {
274
+ config.stunBindAddr = pending.stunBindAddr;
275
+ config.stunBindPort = pending.stunBindPort;
276
+ config.stunRelayUdpAddr = pending.stunRelayUdpAddr;
277
+ config.stunRelayUdpPort = pending.stunRelayUdpPort;
278
+ config.stunRelayUdpUser = pending.stunRelayUdpUser;
279
+ config.stunRelayUdpPass = pending.stunRelayUdpPass;
280
+ config.stunRelayTcpAddr = pending.stunRelayTcpAddr;
281
+ config.stunRelayTcpPort = pending.stunRelayTcpPort;
282
+ config.stunRelayTcpUser = pending.stunRelayTcpUser;
283
+ config.stunRelayTcpPass = pending.stunRelayTcpPass;
284
+ }
285
+
286
+ // localStun sockets created on demand if stun settings are
287
+ // present, but only once (cannot be changed, for now)
288
+ if(((useStunBind && !config.stunBindAddr.isNull()) || (useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty())) && !config.localAddrs.isEmpty() && localStun.isEmpty())
289
+ {
290
+ foreach(const Ice176::LocalAddress &la, config.localAddrs)
291
+ {
292
+ // don't setup stun ports for ipv6
293
+ if(la.addr.protocol() == QAbstractSocket::IPv6Protocol)
294
+ continue;
295
+
296
+ LocalTransport *lt = new LocalTransport;
297
+ lt->addr = la.addr;
298
+ lt->sock = new IceLocalTransport(this);
299
+ lt->sock->setDebugLevel((IceTransport::DebugLevel)debugLevel);
300
+ lt->network = la.network;
301
+ lt->isVpn = la.isVpn;
302
+ connect(lt->sock, SIGNAL(started()), SLOT(lt_started()));
303
+ connect(lt->sock, SIGNAL(stopped()), SLOT(lt_stopped()));
304
+ connect(lt->sock, SIGNAL(addressesChanged()), SLOT(lt_addressesChanged()));
305
+ connect(lt->sock, SIGNAL(error(int)), SLOT(lt_error(int)));
306
+ connect(lt->sock, SIGNAL(debugLine(const QString &)), SLOT(lt_debugLine(const QString &)));
307
+ localStun += lt;
308
+
309
+ lt->sock->setClientSoftwareNameAndVersion(clientSoftware);
310
+ lt->sock->start(la.addr);
311
+ emit q->debugLine(QString("starting transport ") + la.addr.toString() + ";(dyn)" + " for component " + QString::number(id));
312
+ }
313
+ }
314
+
315
+ if((!config.stunBindAddr.isNull() || !config.stunRelayUdpAddr.isNull()) && !localStun.isEmpty())
316
+ {
317
+ for(int n = 0; n < localStun.count(); ++n)
318
+ {
319
+ if(localStunn->started && !localStunn->stun_started)
320
+ tryStun(n);
321
+ }
322
+ }
323
+
324
+ if(useStunRelayTcp && !config.stunRelayTcpAddr.isNull() && !config.stunRelayTcpUser.isEmpty() && !tt)
325
+ {
326
+ tt = new IceTurnTransport(this);
327
+ tt->setDebugLevel((IceTransport::DebugLevel)debugLevel);
328
+ connect(tt, SIGNAL(started()), SLOT(tt_started()));
329
+ connect(tt, SIGNAL(stopped()), SLOT(tt_stopped()));
330
+ connect(tt, SIGNAL(error(int)), SLOT(tt_error(int)));
331
+ connect(tt, SIGNAL(debugLine(const QString &)), SLOT(tt_debugLine(const QString &)));
332
+ tt->setClientSoftwareNameAndVersion(clientSoftware);
333
+ tt->setProxy(proxy);
334
+ tt->setUsername(config.stunRelayTcpUser);
335
+ tt->setPassword(config.stunRelayTcpPass);
336
+ tt->start(config.stunRelayTcpAddr, config.stunRelayTcpPort);
337
+
338
+ emit q->debugLine(QString("starting TURN transport with server ") + config.stunRelayTcpAddr.toString() + ';' + QString::number(config.stunRelayTcpPort) + " for component " + QString::number(id));
339
+ }
340
+
341
+ if(localLeap.isEmpty() && localStun.isEmpty() && !local_finished)
342
+ {
343
+ local_finished = true;
344
+ sess.defer(q, "localFinished");
345
+ }
346
+ }
347
+
348
+ void stop()
349
+ {
350
+ Q_ASSERT(!stopping);
351
+
352
+ stopping = true;
353
+
354
+ // nothing to stop?
355
+ if(allStopped())
356
+ {
357
+ sess.defer(this, "postStop");
358
+ return;
359
+ }
360
+
361
+ foreach(LocalTransport *lt, localLeap)
362
+ lt->sock->stop();
363
+
364
+ foreach(LocalTransport *lt, localStun)
365
+ lt->sock->stop();
366
+
367
+ if(tt)
368
+ tt->stop();
369
+ }
370
+
371
+ int peerReflexivePriority(const IceTransport *iceTransport, int path) const
372
+ {
373
+ int addrAt = -1;
374
+ const IceLocalTransport *lt = qobject_cast<const IceLocalTransport*>(iceTransport);
375
+ if(lt)
376
+ {
377
+ bool isLocalLeap = false;
378
+ addrAt = findLocalTransport(lt, &isLocalLeap);
379
+ if(addrAt != -1 && path == 1)
380
+ {
381
+ // lower priority, but not as far as IceTurnTransport
382
+ addrAt += 512;
383
+ }
384
+ }
385
+ else if(qobject_cast<const IceTurnTransport*>(iceTransport) == tt)
386
+ {
387
+ // lower priority by making it seem like the last nic
388
+ addrAt = 1024;
389
+ }
390
+
391
+ Q_ASSERT(addrAt != -1);
392
+
393
+ return choose_default_priority(PeerReflexiveType, 65535 - addrAt, false, id);
394
+ }
395
+
396
+ void flagPathAsLowOverhead(int id, const QHostAddress &addr, int port)
397
+ {
398
+ int at = -1;
399
+ for(int n = 0; n < localCandidates.count(); ++n)
400
+ {
401
+ if(localCandidatesn.id == id)
402
+ {
403
+ at = n;
404
+ break;
405
+ }
406
+ }
407
+
408
+ Q_ASSERT(at != -1);
409
+
410
+ Candidate &c = localCandidatesat;
411
+
412
+ TransportAddress ta(addr, port);
413
+ QSet<TransportAddress> &addrs = channelPeersc.id;
414
+ if(!addrs.contains(ta))
415
+ {
416
+ addrs += ta;
417
+ c.iceTransport->addChannelPeer(ta.addr, ta.port);
418
+ }
419
+ }
420
+
421
+private:
422
+ // localPref is the priority of the network interface being used for
423
+ // this candidate. the value must be between 0-65535 and different
424
+ // interfaces must have different values. if there is only one
425
+ // interface, the value should be 65535.
426
+ static int choose_default_priority(CandidateType type, int localPref, bool isVpn, int componentId)
427
+ {
428
+ int typePref;
429
+ if(type == HostType)
430
+ {
431
+ if(isVpn)
432
+ typePref = 0;
433
+ else
434
+ typePref = 126;
435
+ }
436
+ else if(type == PeerReflexiveType)
437
+ typePref = 110;
438
+ else if(type == ServerReflexiveType)
439
+ typePref = 100;
440
+ else // RelayedType
441
+ typePref = 0;
442
+
443
+ return calc_priority(typePref, localPref, componentId);
444
+ }
445
+
446
+ static QUdpSocket *takeFromSocketList(QList<QUdpSocket*> *socketList, const QHostAddress &addr, QObject *parent = 0)
447
+ {
448
+ for(int n = 0; n < socketList->count(); ++n)
449
+ {
450
+ if((*socketList)n->localAddress() == addr)
451
+ {
452
+ QUdpSocket *sock = socketList->takeAt(n);
453
+ sock->setParent(parent);
454
+ return sock;
455
+ }
456
+ }
457
+
458
+ return 0;
459
+ }
460
+
461
+ int getId() const
462
+ {
463
+ for(int n = 0;; ++n)
464
+ {
465
+ bool found = false;
466
+ foreach(const Candidate &c, localCandidates)
467
+ {
468
+ if(c.id == n)
469
+ {
470
+ found = true;
471
+ break;
472
+ }
473
+ }
474
+
475
+ if(!found)
476
+ return n;
477
+ }
478
+ }
479
+
480
+ int findLocalAddr(const QHostAddress &addr)
481
+ {
482
+ for(int n = 0; n < config.localAddrs.count(); ++n)
483
+ {
484
+ if(config.localAddrsn.addr == addr)
485
+ return n;
486
+ }
487
+
488
+ return -1;
489
+ }
490
+
491
+ int findLocalTransport(const IceLocalTransport *sock, bool *isLocalLeap) const
492
+ {
493
+ for(int n = 0; n < localLeap.count(); ++n)
494
+ {
495
+ if(localLeapn->sock == sock)
496
+ {
497
+ *isLocalLeap = true;
498
+ return n;
499
+ }
500
+ }
501
+
502
+ for(int n = 0; n < localStun.count(); ++n)
503
+ {
504
+ if(localStunn->sock == sock)
505
+ {
506
+ *isLocalLeap = false;
507
+ return n;
508
+ }
509
+ }
510
+
511
+ return -1;
512
+ }
513
+
514
+ void tryStun(int at)
515
+ {
516
+ LocalTransport *lt = localStunat;
517
+
518
+ bool atLeastOne = false;
519
+ if(useStunBind && !config.stunBindAddr.isNull())
520
+ {
521
+ atLeastOne = true;
522
+ lt->sock->setStunBindService(config.stunBindAddr, config.stunBindPort);
523
+ }
524
+ if(useStunRelayUdp && !config.stunRelayUdpAddr.isNull() && !config.stunRelayUdpUser.isEmpty())
525
+ {
526
+ atLeastOne = true;
527
+ lt->sock->setStunRelayService(config.stunRelayUdpAddr, config.stunRelayUdpPort, config.stunRelayUdpUser, config.stunRelayUdpPass);
528
+ }
529
+
530
+ Q_ASSERT(atLeastOne);
531
+
532
+ lt->stun_started = true;
533
+ lt->sock->stunStart();
534
+ }
535
+
536
+ void ensureExt(LocalTransport *lt, int addrAt)
537
+ {
538
+ if(!lt->extAddr.isNull() && !lt->ext_finished)
539
+ {
540
+ CandidateInfo ci;
541
+ ci.addr.addr = lt->extAddr;
542
+ ci.addr.port = lt->sock->localPort();
543
+ ci.type = ServerReflexiveType;
544
+ ci.componentId = id;
545
+ ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId);
546
+ ci.base.addr = lt->sock->localAddress();
547
+ ci.base.port = lt->sock->localPort();
548
+ ci.network = lt->network;
549
+
550
+ Candidate c;
551
+ c.id = getId();
552
+ c.info = ci;
553
+ c.iceTransport = lt->sock;
554
+ c.path = 0;
555
+
556
+ localCandidates += c;
557
+ lt->ext_finished = true;
558
+
559
+ emit q->candidateAdded(c);
560
+ }
561
+ }
562
+
563
+ void removeLocalCandidates(const IceTransport *sock)
564
+ {
565
+ ObjectSessionWatcher watch(&sess);
566
+
567
+ for(int n = 0; n < localCandidates.count(); ++n)
568
+ {
569
+ Candidate &c = localCandidatesn;
570
+
571
+ if(c.iceTransport == sock)
572
+ {
573
+ Candidate tmp = localCandidates.takeAt(n);
574
+ --n; // adjust position
575
+
576
+ channelPeers.remove(tmp.id);
577
+
578
+ emit q->candidateRemoved(tmp);
579
+ if(!watch.isValid())
580
+ return;
581
+ }
582
+ }
583
+ }
584
+
585
+ bool allStopped() const
586
+ {
587
+ if(localLeap.isEmpty() && localStun.isEmpty() && !tt)
588
+ return true;
589
+ else
590
+ return false;
591
+ }
592
+
593
+ void tryStopped()
594
+ {
595
+ if(allStopped())
596
+ postStop();
597
+ }
598
+
599
+private slots:
600
+ void doExt()
601
+ {
602
+ if(stopping)
603
+ return;
604
+
605
+ ObjectSessionWatcher watch(&sess);
606
+
607
+ foreach(LocalTransport *lt, localLeap)
608
+ {
609
+ if(lt->started)
610
+ {
611
+ int addrAt = findLocalAddr(lt->addr);
612
+ Q_ASSERT(addrAt != -1);
613
+
614
+ ensureExt(lt, addrAt);
615
+ if(!watch.isValid())
616
+ return;
617
+ }
618
+ }
619
+ }
620
+
621
+ void postStop()
622
+ {
623
+ stopping = false;
624
+
625
+ emit q->stopped();
626
+ }
627
+
628
+ void lt_started()
629
+ {
630
+ IceLocalTransport *sock = (IceLocalTransport *)sender();
631
+ bool isLocalLeap = false;
632
+ int at = findLocalTransport(sock, &isLocalLeap);
633
+ Q_ASSERT(at != -1);
634
+
635
+ LocalTransport *lt;
636
+ if(isLocalLeap)
637
+ lt = localLeapat;
638
+ else
639
+ lt = localStunat;
640
+
641
+ lt->started = true;
642
+
643
+ int addrAt = findLocalAddr(lt->addr);
644
+ Q_ASSERT(addrAt != -1);
645
+
646
+ ObjectSessionWatcher watch(&sess);
647
+
648
+ if(useLocal && isLocalLeap)
649
+ {
650
+ CandidateInfo ci;
651
+ ci.addr.addr = lt->sock->localAddress();
652
+ ci.addr.port = lt->sock->localPort();
653
+ ci.type = HostType;
654
+ ci.componentId = id;
655
+ ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId);
656
+ ci.base = ci.addr;
657
+ ci.network = lt->network;
658
+
659
+ Candidate c;
660
+ c.id = getId();
661
+ c.info = ci;
662
+ c.iceTransport = sock;
663
+ c.path = 0;
664
+
665
+ localCandidates += c;
666
+
667
+ emit q->candidateAdded(c);
668
+ if(!watch.isValid())
669
+ return;
670
+
671
+ ensureExt(lt, addrAt);
672
+ if(!watch.isValid())
673
+ return;
674
+ }
675
+
676
+ if(!isLocalLeap && !lt->stun_started)
677
+ tryStun(at);
678
+
679
+ bool allFinished = true;
680
+ foreach(const LocalTransport *lt, localLeap)
681
+ {
682
+ if(!lt->started)
683
+ {
684
+ allFinished = false;
685
+ break;
686
+ }
687
+ }
688
+ if(allFinished)
689
+ {
690
+ foreach(const LocalTransport *lt, localStun)
691
+ {
692
+ if(!lt->started)
693
+ {
694
+ allFinished = false;
695
+ break;
696
+ }
697
+ }
698
+ }
699
+
700
+ if(allFinished && !local_finished)
701
+ {
702
+ local_finished = true;
703
+ emit q->localFinished();
704
+ }
705
+ }
706
+
707
+ void lt_stopped()
708
+ {
709
+ IceLocalTransport *sock = (IceLocalTransport *)sender();
710
+ bool isLocalLeap = false;
711
+ int at = findLocalTransport(sock, &isLocalLeap);
712
+ Q_ASSERT(at != -1);
713
+
714
+ LocalTransport *lt;
715
+ if(isLocalLeap)
716
+ lt = localLeapat;
717
+ else
718
+ lt = localStunat;
719
+
720
+ ObjectSessionWatcher watch(&sess);
721
+
722
+ removeLocalCandidates(lt->sock);
723
+ if(!watch.isValid())
724
+ return;
725
+
726
+ delete lt->sock;
727
+ lt->sock = 0;
728
+
729
+ if(isLocalLeap)
730
+ {
731
+ if(lt->borrowedSocket)
732
+ portReserver->returnSockets(QList<QUdpSocket*>() << lt->qsock);
733
+ else
734
+ lt->qsock->deleteLater();
735
+
736
+ delete lt;
737
+ localLeap.removeAt(at);
738
+ }
739
+ else
740
+ {
741
+ delete lt;
742
+ localStun.removeAt(at);
743
+ }
744
+
745
+ tryStopped();
746
+ }
747
+
748
+ void lt_addressesChanged()
749
+ {
750
+ IceLocalTransport *sock = (IceLocalTransport *)sender();
751
+ bool isLocalLeap = false;
752
+ int at = findLocalTransport(sock, &isLocalLeap);
753
+ Q_ASSERT(at != -1);
754
+
755
+ // leap does not use stun, so we should not get this signal
756
+ Q_ASSERT(!isLocalLeap);
757
+
758
+ LocalTransport *lt = localStunat;
759
+
760
+ int addrAt = findLocalAddr(lt->addr);
761
+ Q_ASSERT(addrAt != -1);
762
+
763
+ ObjectSessionWatcher watch(&sess);
764
+
765
+ if(useStunBind && !lt->sock->serverReflexiveAddress().isNull() && !lt->stun_finished)
766
+ {
767
+ // automatically assign ext to related leaps, if possible
768
+ foreach(LocalTransport *i, localLeap)
769
+ {
770
+ if(i->extAddr.isNull() && i->sock->localAddress() == lt->sock->localAddress())
771
+ {
772
+ i->extAddr = lt->sock->serverReflexiveAddress();
773
+ if(i->started)
774
+ {
775
+ ensureExt(i, addrAt);
776
+ if(!watch.isValid())
777
+ return;
778
+ }
779
+ }
780
+ }
781
+
782
+ CandidateInfo ci;
783
+ ci.addr.addr = lt->sock->serverReflexiveAddress();
784
+ ci.addr.port = lt->sock->serverReflexivePort();
785
+ ci.type = ServerReflexiveType;
786
+ ci.componentId = id;
787
+ ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId);
788
+ // stun is only used on non-leap sockets, but we don't
789
+ // announce non-leap local candidates, so make the
790
+ // base the same as the srflx
791
+ //ci.base.addr = lt->sock->localAddress();
792
+ //ci.base.port = lt->sock->localPort();
793
+ ci.base = ci.addr;
794
+ ci.network = lt->network;
795
+
796
+ Candidate c;
797
+ c.id = getId();
798
+ c.info = ci;
799
+ c.iceTransport = sock;
800
+ c.path = 0;
801
+
802
+ localCandidates += c;
803
+ lt->stun_finished = true;
804
+
805
+ emit q->candidateAdded(c);
806
+ if(!watch.isValid())
807
+ return;
808
+ }
809
+
810
+ if(!lt->sock->relayedAddress().isNull() && !lt->turn_finished)
811
+ {
812
+ CandidateInfo ci;
813
+ ci.addr.addr = lt->sock->relayedAddress();
814
+ ci.addr.port = lt->sock->relayedPort();
815
+ ci.type = RelayedType;
816
+ ci.componentId = id;
817
+ ci.priority = choose_default_priority(ci.type, 65535 - addrAt, lt->isVpn, ci.componentId);
818
+ ci.base.addr = lt->sock->serverReflexiveAddress();
819
+ ci.base.port = lt->sock->serverReflexivePort();
820
+ ci.network = lt->network;
821
+
822
+ Candidate c;
823
+ c.id = getId();
824
+ c.info = ci;
825
+ c.iceTransport = sock;
826
+ c.path = 1;
827
+
828
+ localCandidates += c;
829
+ lt->turn_finished = true;
830
+
831
+ emit q->candidateAdded(c);
832
+ }
833
+ }
834
+
835
+ void lt_error(int e)
836
+ {
837
+ Q_UNUSED(e);
838
+
839
+ IceLocalTransport *sock = (IceLocalTransport *)sender();
840
+ bool isLocalLeap = false;
841
+ int at = findLocalTransport(sock, &isLocalLeap);
842
+ Q_ASSERT(at != -1);
843
+
844
+ LocalTransport *lt;
845
+ if(isLocalLeap)
846
+ lt = localLeapat;
847
+ else
848
+ lt = localStunat;
849
+
850
+ ObjectSessionWatcher watch(&sess);
851
+
852
+ removeLocalCandidates(lt->sock);
853
+ if(!watch.isValid())
854
+ return;
855
+
856
+ delete lt->sock;
857
+ lt->sock = 0;
858
+
859
+ if(isLocalLeap)
860
+ {
861
+ if(lt->borrowedSocket)
862
+ portReserver->returnSockets(QList<QUdpSocket*>() << lt->qsock);
863
+ else
864
+ lt->qsock->deleteLater();
865
+
866
+ delete lt;
867
+ localLeap.removeAt(at);
868
+ }
869
+ else
870
+ {
871
+ delete lt;
872
+ localStun.removeAt(at);
873
+ }
874
+ }
875
+
876
+ void lt_debugLine(const QString &line)
877
+ {
878
+ emit q->debugLine(line);
879
+ }
880
+
881
+ void tt_started()
882
+ {
883
+ // lower priority by making it seem like the last nic
884
+ int addrAt = 1024;
885
+
886
+ CandidateInfo ci;
887
+ ci.addr.addr = tt->relayedAddress();
888
+ ci.addr.port = tt->relayedPort();
889
+ ci.type = RelayedType;
890
+ ci.componentId = id;
891
+ ci.priority = choose_default_priority(ci.type, 65535 - addrAt, false, ci.componentId);
892
+ ci.base = ci.addr;
893
+ ci.network = 0; // not relevant
894
+
895
+ Candidate c;
896
+ c.id = getId();
897
+ c.info = ci;
898
+ c.iceTransport = tt;
899
+ c.path = 0;
900
+
901
+ localCandidates += c;
902
+
903
+ emit q->candidateAdded(c);
904
+ }
905
+
906
+ void tt_stopped()
907
+ {
908
+ ObjectSessionWatcher watch(&sess);
909
+
910
+ removeLocalCandidates(tt);
911
+ if(!watch.isValid())
912
+ return;
913
+
914
+ delete tt;
915
+ tt = 0;
916
+
917
+ tryStopped();
918
+ }
919
+
920
+ void tt_error(int e)
921
+ {
922
+ Q_UNUSED(e);
923
+
924
+ ObjectSessionWatcher watch(&sess);
925
+
926
+ removeLocalCandidates(tt);
927
+ if(!watch.isValid())
928
+ return;
929
+
930
+ delete tt;
931
+ tt = 0;
932
+ }
933
+
934
+ void tt_debugLine(const QString &line)
935
+ {
936
+ emit q->debugLine(line);
937
+ }
938
+};
939
+
940
+IceComponent::IceComponent(int id, QObject *parent) :
941
+ QObject(parent)
942
+{
943
+ d = new Private(this);
944
+ d->id = id;
945
+}
946
+
947
+IceComponent::~IceComponent()
948
+{
949
+ delete d;
950
+}
951
+
952
+int IceComponent::id() const
953
+{
954
+ return d->id;
955
+}
956
+
957
+void IceComponent::setClientSoftwareNameAndVersion(const QString &str)
958
+{
959
+ d->clientSoftware = str;
960
+}
961
+
962
+void IceComponent::setProxy(const TurnClient::Proxy &proxy)
963
+{
964
+ d->proxy = proxy;
965
+}
966
+
967
+void IceComponent::setPortReserver(UdpPortReserver *portReserver)
968
+{
969
+ d->portReserver = portReserver;
970
+}
971
+
972
+void IceComponent::setLocalAddresses(const QList<Ice176::LocalAddress> &addrs)
973
+{
974
+ d->pending.localAddrs = addrs;
975
+}
976
+
977
+void IceComponent::setExternalAddresses(const QList<Ice176::ExternalAddress> &addrs)
978
+{
979
+ d->pending.extAddrs = addrs;
980
+}
981
+
982
+void IceComponent::setStunBindService(const QHostAddress &addr, int port)
983
+{
984
+ d->pending.stunBindAddr = addr;
985
+ d->pending.stunBindPort = port;
986
+}
987
+
988
+void IceComponent::setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass)
989
+{
990
+ d->pending.stunRelayUdpAddr = addr;
991
+ d->pending.stunRelayUdpPort = port;
992
+ d->pending.stunRelayUdpUser = user;
993
+ d->pending.stunRelayUdpPass = pass;
994
+}
995
+
996
+void IceComponent::setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass)
997
+{
998
+ d->pending.stunRelayTcpAddr = addr;
999
+ d->pending.stunRelayTcpPort = port;
1000
+ d->pending.stunRelayTcpUser = user;
1001
+ d->pending.stunRelayTcpPass = pass;
1002
+}
1003
+
1004
+void IceComponent::setUseLocal(bool enabled)
1005
+{
1006
+ d->useLocal = enabled;
1007
+}
1008
+
1009
+void IceComponent::setUseStunBind(bool enabled)
1010
+{
1011
+ d->useStunBind = enabled;
1012
+}
1013
+
1014
+void IceComponent::setUseStunRelayUdp(bool enabled)
1015
+{
1016
+ d->useStunRelayUdp = enabled;
1017
+}
1018
+
1019
+void IceComponent::setUseStunRelayTcp(bool enabled)
1020
+{
1021
+ d->useStunRelayTcp = enabled;
1022
+}
1023
+
1024
+void IceComponent::update(QList<QUdpSocket*> *socketList)
1025
+{
1026
+ d->update(socketList);
1027
+}
1028
+
1029
+void IceComponent::stop()
1030
+{
1031
+ d->stop();
1032
+}
1033
+
1034
+int IceComponent::peerReflexivePriority(const IceTransport *iceTransport, int path) const
1035
+{
1036
+ return d->peerReflexivePriority(iceTransport, path);
1037
+}
1038
+
1039
+void IceComponent::flagPathAsLowOverhead(int id, const QHostAddress &addr, int port)
1040
+{
1041
+ return d->flagPathAsLowOverhead(id, addr, port);
1042
+}
1043
+
1044
+void IceComponent::setDebugLevel(DebugLevel level)
1045
+{
1046
+ d->debugLevel = level;
1047
+ foreach(const Private::LocalTransport *lt, d->localLeap)
1048
+ lt->sock->setDebugLevel((IceTransport::DebugLevel)level);
1049
+ foreach(const Private::LocalTransport *lt, d->localStun)
1050
+ lt->sock->setDebugLevel((IceTransport::DebugLevel)level);
1051
+ if(d->tt)
1052
+ d->tt->setDebugLevel((IceTransport::DebugLevel)level);
1053
+}
1054
+
1055
+}
1056
+
1057
+#include "icecomponent.moc"
1058
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icecomponent.h
Added
190
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef ICECOMPONENT_H
23
+#define ICECOMPONENT_H
24
+
25
+#include <QList>
26
+#include "turnclient.h"
27
+#include "icetransport.h"
28
+#include "ice176.h"
29
+
30
+class QUdpSocket;
31
+
32
+namespace XMPP {
33
+
34
+class UdpPortReserver;
35
+
36
+class IceComponent : public QObject
37
+{
38
+ Q_OBJECT
39
+
40
+public:
41
+ enum CandidateType
42
+ {
43
+ HostType,
44
+ PeerReflexiveType,
45
+ ServerReflexiveType,
46
+ RelayedType
47
+ };
48
+
49
+ class TransportAddress
50
+ {
51
+ public:
52
+ QHostAddress addr;
53
+ int port;
54
+
55
+ TransportAddress() :
56
+ port(-1)
57
+ {
58
+ }
59
+
60
+ TransportAddress(const QHostAddress &_addr, int _port) :
61
+ addr(_addr),
62
+ port(_port)
63
+ {
64
+ }
65
+
66
+ bool operator==(const TransportAddress &other) const
67
+ {
68
+ if(addr == other.addr && port == other.port)
69
+ return true;
70
+ else
71
+ return false;
72
+ }
73
+
74
+ inline bool operator!=(const TransportAddress &other) const
75
+ {
76
+ return !operator==(other);
77
+ }
78
+ };
79
+
80
+ class CandidateInfo
81
+ {
82
+ public:
83
+ TransportAddress addr;
84
+ CandidateType type;
85
+ int priority;
86
+ QString foundation;
87
+ int componentId;
88
+ TransportAddress base;
89
+ TransportAddress related;
90
+ QString id;
91
+ int network;
92
+ };
93
+
94
+ class Candidate
95
+ {
96
+ public:
97
+ // unique across all candidates within this component
98
+ int id;
99
+
100
+ // info.id is unset, since it must be unique across all
101
+ // components and this class is only aware of itself. it
102
+ // is up to the user to create the candidate id.
103
+ // info.foundation is also unset, since awareness of all
104
+ // components and candidates is needed to calculate it.
105
+ CandidateInfo info;
106
+
107
+ // note that these may be the same for multiple candidates
108
+ IceTransport *iceTransport;
109
+ int path;
110
+ };
111
+
112
+ enum DebugLevel
113
+ {
114
+ DL_None,
115
+ DL_Info,
116
+ DL_Packet
117
+ };
118
+
119
+ IceComponent(int id, QObject *parent = 0);
120
+ ~IceComponent();
121
+
122
+ int id() const;
123
+
124
+ void setClientSoftwareNameAndVersion(const QString &str);
125
+ void setProxy(const TurnClient::Proxy &proxy);
126
+
127
+ void setPortReserver(UdpPortReserver *portReserver);
128
+
129
+ // can be set once, but later changes are ignored
130
+ void setLocalAddresses(const QList<Ice176::LocalAddress> &addrs);
131
+
132
+ // can be set once, but later changes are ignored. local addresses
133
+ // must have been set for this to work
134
+ void setExternalAddresses(const QList<Ice176::ExternalAddress> &addrs);
135
+
136
+ // can be set at any time, but only once. later changes are ignored
137
+ void setStunBindService(const QHostAddress &addr, int port);
138
+ void setStunRelayUdpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass);
139
+ void setStunRelayTcpService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass);
140
+
141
+ // these all start out enabled, but can be disabled for diagnostic
142
+ // purposes
143
+ void setUseLocal(bool enabled);
144
+ void setUseStunBind(bool enabled);
145
+ void setUseStunRelayUdp(bool enabled);
146
+ void setUseStunRelayTcp(bool enabled);
147
+
148
+ // if socketList is not null then port reserver must be set
149
+ void update(QList<QUdpSocket*> *socketList = 0);
150
+ void stop();
151
+
152
+ // prflx priority to use when replying from this transport/path
153
+ int peerReflexivePriority(const IceTransport *iceTransport, int path) const;
154
+
155
+ void flagPathAsLowOverhead(int id, const QHostAddress &addr, int port);
156
+
157
+ void setDebugLevel(DebugLevel level);
158
+
159
+signals:
160
+ // this is emitted in the same pass of the eventloop that a
161
+ // transport/path becomes ready
162
+ void candidateAdded(const XMPP::IceComponent::Candidate &c);
163
+
164
+ // this is emitted just before a transport/path will be deleted
165
+ void candidateRemoved(const XMPP::IceComponent::Candidate &c);
166
+
167
+ // indicates all the initial HostType candidates have been pushed.
168
+ // note that it is possible there are no HostType candidates.
169
+ void localFinished();
170
+
171
+ void stopped();
172
+
173
+ // reports debug of iceTransports as well. not DOR-SS/DS safe
174
+ void debugLine(const QString &line);
175
+
176
+private:
177
+ class Private;
178
+ friend class Private;
179
+ Private *d;
180
+};
181
+
182
+inline uint qHash(const XMPP::IceComponent::TransportAddress &key)
183
+{
184
+ return ::qHash(key.addr) ^ ::qHash(key.port);
185
+}
186
+
187
+}
188
+
189
+#endif
190
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icecomponent_p.h
Added
31
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef ICECOMPONENT_P_H
28
+#define ICECOMPONENT_P_H
29
+
30
+#endif // ICECOMPONENT_P_H
31
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icelocaltransport.cpp
Added
890
1
2
+/*
3
+ * Copyright (C) 2009,2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "icelocaltransport.h"
23
+
24
+#include <QHostAddress>
25
+#include <QUdpSocket>
26
+#include <QtCrypto>
27
+#include "objectsession.h"
28
+#include "stunmessage.h"
29
+#include "stuntransaction.h"
30
+#include "stunbinding.h"
31
+#include "stunallocate.h"
32
+#include "turnclient.h"
33
+
34
+// don't queue more incoming packets than this per transmit path
35
+#define MAX_PACKET_QUEUE 64
36
+
37
+namespace XMPP {
38
+
39
+enum
40
+{
41
+ Direct,
42
+ Relayed
43
+};
44
+
45
+//----------------------------------------------------------------------------
46
+// SafeUdpSocket
47
+//----------------------------------------------------------------------------
48
+// DOR-safe wrapper for QUdpSocket
49
+class SafeUdpSocket : public QObject
50
+{
51
+ Q_OBJECT
52
+
53
+private:
54
+ ObjectSession sess;
55
+ QUdpSocket *sock;
56
+ int writtenCount;
57
+
58
+public:
59
+ SafeUdpSocket(QUdpSocket *_sock, QObject *parent = 0) :
60
+ QObject(parent),
61
+ sess(this),
62
+ sock(_sock)
63
+ {
64
+ sock->setParent(this);
65
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
66
+ connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
67
+
68
+ writtenCount = 0;
69
+ }
70
+
71
+ ~SafeUdpSocket()
72
+ {
73
+ if(sock)
74
+ {
75
+ QUdpSocket *out = release();
76
+ out->deleteLater();
77
+ }
78
+ }
79
+
80
+ QUdpSocket *release()
81
+ {
82
+ sock->disconnect(this);
83
+ sock->setParent(0);
84
+ QUdpSocket *out = sock;
85
+ sock = 0;
86
+ return out;
87
+ }
88
+
89
+ QHostAddress localAddress() const
90
+ {
91
+ return sock->localAddress();
92
+ }
93
+
94
+ quint16 localPort() const
95
+ {
96
+ return sock->localPort();
97
+ }
98
+
99
+ bool hasPendingDatagrams() const
100
+ {
101
+ return sock->hasPendingDatagrams();
102
+ }
103
+
104
+ QByteArray readDatagram(QHostAddress *address = 0, quint16 *port = 0)
105
+ {
106
+ if(!sock->hasPendingDatagrams())
107
+ return QByteArray();
108
+
109
+ QByteArray buf;
110
+ buf.resize(sock->pendingDatagramSize());
111
+ sock->readDatagram(buf.data(), buf.size(), address, port);
112
+ return buf;
113
+ }
114
+
115
+ void writeDatagram(const QByteArray &buf, const QHostAddress &address, quint16 port)
116
+ {
117
+ sock->writeDatagram(buf, address, port);
118
+ }
119
+
120
+signals:
121
+ void readyRead();
122
+ void datagramsWritten(int count);
123
+
124
+private slots:
125
+ void sock_readyRead()
126
+ {
127
+ emit readyRead();
128
+ }
129
+
130
+ void sock_bytesWritten(qint64 bytes)
131
+ {
132
+ Q_UNUSED(bytes);
133
+
134
+ ++writtenCount;
135
+ sess.deferExclusive(this, "processWritten");
136
+ }
137
+
138
+ void processWritten()
139
+ {
140
+ int count = writtenCount;
141
+ writtenCount = 0;
142
+
143
+ emit datagramsWritten(count);
144
+ }
145
+};
146
+
147
+//----------------------------------------------------------------------------
148
+// IceLocalTransport
149
+//----------------------------------------------------------------------------
150
+class IceLocalTransport::Private : public QObject
151
+{
152
+ Q_OBJECT
153
+
154
+public:
155
+ class WriteItem
156
+ {
157
+ public:
158
+ enum Type
159
+ {
160
+ Direct,
161
+ Pool,
162
+ Turn
163
+ };
164
+
165
+ Type type;
166
+ QHostAddress addr;
167
+ int port;
168
+ };
169
+
170
+ class Written
171
+ {
172
+ public:
173
+ QHostAddress addr;
174
+ int port;
175
+ int count;
176
+ };
177
+
178
+ class Datagram
179
+ {
180
+ public:
181
+ QHostAddress addr;
182
+ int port;
183
+ QByteArray buf;
184
+ };
185
+
186
+ IceLocalTransport *q;
187
+ ObjectSession sess;
188
+ QUdpSocket *extSock;
189
+ SafeUdpSocket *sock;
190
+ StunTransactionPool *pool;
191
+ StunBinding *stunBinding;
192
+ TurnClient *turn;
193
+ bool turnActivated;
194
+ QHostAddress addr;
195
+ int port;
196
+ QHostAddress refAddr;
197
+ int refPort;
198
+ QHostAddress relAddr;
199
+ int relPort;
200
+ QHostAddress stunBindAddr;
201
+ int stunBindPort;
202
+ QHostAddress stunRelayAddr;
203
+ int stunRelayPort;
204
+ QString stunUser;
205
+ QCA::SecureArray stunPass;
206
+ QString clientSoftware;
207
+ QList<Datagram> in;
208
+ QList<Datagram> inRelayed;
209
+ QList<WriteItem> pendingWrites;
210
+ int retryCount;
211
+ bool stopping;
212
+ int debugLevel;
213
+
214
+ Private(IceLocalTransport *_q) :
215
+ QObject(_q),
216
+ q(_q),
217
+ sess(this),
218
+ extSock(0),
219
+ sock(0),
220
+ pool(0),
221
+ stunBinding(0),
222
+ turn(0),
223
+ turnActivated(false),
224
+ port(-1),
225
+ refPort(-1),
226
+ relPort(-1),
227
+ retryCount(0),
228
+ stopping(false),
229
+ debugLevel(IceTransport::DL_None)
230
+ {
231
+ }
232
+
233
+ ~Private()
234
+ {
235
+ reset();
236
+ }
237
+
238
+ void reset()
239
+ {
240
+ sess.reset();
241
+
242
+ delete stunBinding;
243
+ stunBinding = 0;
244
+
245
+ delete turn;
246
+ turn = 0;
247
+ turnActivated = false;
248
+
249
+ if(sock)
250
+ {
251
+ if(extSock)
252
+ {
253
+ sock->release();
254
+ extSock = 0;
255
+ }
256
+
257
+ delete sock;
258
+ sock = 0;
259
+ }
260
+
261
+ addr = QHostAddress();
262
+ port = -1;
263
+
264
+ refAddr = QHostAddress();
265
+ refPort = -1;
266
+
267
+ relAddr = QHostAddress();
268
+ relPort = -1;
269
+
270
+ in.clear();
271
+ inRelayed.clear();
272
+ pendingWrites.clear();
273
+
274
+ retryCount = 0;
275
+ stopping = false;
276
+ }
277
+
278
+ void start()
279
+ {
280
+ Q_ASSERT(!sock);
281
+
282
+ sess.defer(this, "postStart");
283
+ }
284
+
285
+ void stop()
286
+ {
287
+ Q_ASSERT(sock);
288
+ Q_ASSERT(!stopping);
289
+
290
+ stopping = true;
291
+
292
+ if(turn)
293
+ turn->close();
294
+ else
295
+ sess.defer(this, "postStop");
296
+ }
297
+
298
+ void stunStart()
299
+ {
300
+ Q_ASSERT(!pool);
301
+
302
+ pool = new StunTransactionPool(StunTransaction::Udp, this);
303
+ pool->setDebugLevel((StunTransactionPool::DebugLevel)debugLevel);
304
+ connect(pool, SIGNAL(outgoingMessage(const QByteArray &, const QHostAddress &, int)), SLOT(pool_outgoingMessage(const QByteArray &, const QHostAddress &, int)));
305
+ connect(pool, SIGNAL(needAuthParams()), SLOT(pool_needAuthParams()));
306
+ connect(pool, SIGNAL(debugLine(const QString &)), SLOT(pool_debugLine(const QString &)));
307
+
308
+ pool->setLongTermAuthEnabled(true);
309
+ if(!stunUser.isEmpty())
310
+ {
311
+ pool->setUsername(stunUser);
312
+ pool->setPassword(stunPass);
313
+ }
314
+
315
+ if(!stunBindAddr.isNull())
316
+ {
317
+ stunBinding = new StunBinding(pool);
318
+ connect(stunBinding, SIGNAL(success()), SLOT(binding_success()));
319
+ connect(stunBinding, SIGNAL(error(XMPP::StunBinding::Error)), SLOT(binding_error(XMPP::StunBinding::Error)));
320
+ stunBinding->start(stunBindAddr, stunBindPort);
321
+ }
322
+
323
+ if(!stunRelayAddr.isNull())
324
+ {
325
+ do_turn();
326
+ }
327
+ }
328
+
329
+ void do_turn()
330
+ {
331
+ turn = new TurnClient(this);
332
+ turn->setDebugLevel((TurnClient::DebugLevel)debugLevel);
333
+ connect(turn, SIGNAL(connected()), SLOT(turn_connected()));
334
+ connect(turn, SIGNAL(tlsHandshaken()), SLOT(turn_tlsHandshaken()));
335
+ connect(turn, SIGNAL(closed()), SLOT(turn_closed()));
336
+ connect(turn, SIGNAL(activated()), SLOT(turn_activated()));
337
+ connect(turn, SIGNAL(packetsWritten(int, const QHostAddress &, int)), SLOT(turn_packetsWritten(int, const QHostAddress &, int)));
338
+ connect(turn, SIGNAL(error(XMPP::TurnClient::Error)), SLOT(turn_error(XMPP::TurnClient::Error)));
339
+ connect(turn, SIGNAL(outgoingDatagram(const QByteArray &)), SLOT(turn_outgoingDatagram(const QByteArray &)));
340
+ connect(turn, SIGNAL(debugLine(const QString &)), SLOT(turn_debugLine(const QString &)));
341
+
342
+ turn->setClientSoftwareNameAndVersion(clientSoftware);
343
+
344
+ turn->connectToHost(pool, stunRelayAddr, stunRelayPort);
345
+ }
346
+
347
+private:
348
+ // note: emits signal on error
349
+ QUdpSocket *createSocket()
350
+ {
351
+ QUdpSocket *qsock = new QUdpSocket(this);
352
+ if(!qsock->bind(addr, 0))
353
+ {
354
+ delete qsock;
355
+ emit q->error(IceLocalTransport::ErrorBind);
356
+ return 0;
357
+ }
358
+
359
+ return qsock;
360
+ }
361
+
362
+ void prepareSocket()
363
+ {
364
+ addr = sock->localAddress();
365
+ port = sock->localPort();
366
+
367
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
368
+ connect(sock, SIGNAL(datagramsWritten(int)), SLOT(sock_datagramsWritten(int)));
369
+ }
370
+
371
+ // return true if we are retrying, false if we should error out
372
+ bool handleRetry()
373
+ {
374
+ // don't allow retrying if activated or stopping)
375
+ if(turnActivated || stopping)
376
+ return false;
377
+
378
+ ++retryCount;
379
+ if(retryCount < 3)
380
+ {
381
+ if(debugLevel >= IceTransport::DL_Info)
382
+ emit q->debugLine("retrying...");
383
+
384
+ delete sock;
385
+ sock = 0;
386
+
387
+ // to receive this error, it is a Relay, so change
388
+ // the mode
389
+ //stunType = IceLocalTransport::Relay;
390
+
391
+ QUdpSocket *qsock = createSocket();
392
+ if(!qsock)
393
+ {
394
+ // signal emitted in this case. bail.
395
+ // (return true so caller takes no action)
396
+ return true;
397
+ }
398
+
399
+ sock = new SafeUdpSocket(qsock, this);
400
+
401
+ prepareSocket();
402
+
403
+ refAddr = QHostAddress();
404
+ refPort = -1;
405
+
406
+ relAddr = QHostAddress();
407
+ relPort = -1;
408
+
409
+ do_turn();
410
+
411
+ // tell the world that our local address probably
412
+ // changed, and that we lost our reflexive address
413
+ emit q->addressesChanged();
414
+ return true;
415
+ }
416
+
417
+ return false;
418
+ }
419
+
420
+ // return true if data packet, false if pool or nothing
421
+ bool processIncomingStun(const QByteArray &buf, const QHostAddress &fromAddr, int fromPort, Datagram *dg)
422
+ {
423
+ QByteArray data;
424
+ QHostAddress dataAddr;
425
+ int dataPort;
426
+
427
+ bool notStun;
428
+ if(!pool->writeIncomingMessage(buf, ¬Stun, fromAddr, fromPort) && turn)
429
+ {
430
+ data = turn->processIncomingDatagram(buf, notStun, &dataAddr, &dataPort);
431
+ if(!data.isNull())
432
+ {
433
+ dg->addr = dataAddr;
434
+ dg->port = dataPort;
435
+ dg->buf = data;
436
+ return true;
437
+ }
438
+ else
439
+ {
440
+ if(debugLevel >= IceTransport::DL_Packet)
441
+ emit q->debugLine("Warning: server responded with what doesn't seem to be a STUN or data packet, skipping.");
442
+ }
443
+ }
444
+
445
+ return false;
446
+ }
447
+
448
+private slots:
449
+ void postStart()
450
+ {
451
+ if(stopping)
452
+ return;
453
+
454
+ if(extSock)
455
+ {
456
+ sock = new SafeUdpSocket(extSock, this);
457
+ }
458
+ else
459
+ {
460
+ QUdpSocket *qsock = createSocket();
461
+ if(!qsock)
462
+ {
463
+ // signal emitted in this case. bail
464
+ return;
465
+ }
466
+
467
+ sock = new SafeUdpSocket(qsock, this);
468
+ }
469
+
470
+ prepareSocket();
471
+
472
+ emit q->started();
473
+ }
474
+
475
+ void postStop()
476
+ {
477
+ reset();
478
+ emit q->stopped();
479
+ }
480
+
481
+ void sock_readyRead()
482
+ {
483
+ ObjectSessionWatcher watch(&sess);
484
+
485
+ QList<Datagram> dreads;
486
+ QList<Datagram> rreads;
487
+
488
+ while(sock->hasPendingDatagrams())
489
+ {
490
+ QHostAddress from;
491
+ quint16 fromPort;
492
+
493
+ Datagram dg;
494
+
495
+ QByteArray buf = sock->readDatagram(&from, &fromPort);
496
+ if((from == stunBindAddr && fromPort == stunBindPort) || (from == stunRelayAddr && fromPort == stunRelayPort))
497
+ {
498
+ bool haveData = processIncomingStun(buf, from, fromPort, &dg);
499
+
500
+ // processIncomingStun could cause signals to
501
+ // emit. for example, stopped()
502
+ if(!watch.isValid())
503
+ return;
504
+
505
+ if(haveData)
506
+ rreads += dg;
507
+ }
508
+ else
509
+ {
510
+ dg.addr = from;
511
+ dg.port = fromPort;
512
+ dg.buf = buf;
513
+ dreads += dg;
514
+ }
515
+ }
516
+
517
+ if(dreads.count() > 0)
518
+ {
519
+ in += dreads;
520
+ emit q->readyRead(Direct);
521
+ if(!watch.isValid())
522
+ return;
523
+ }
524
+
525
+ if(rreads.count() > 0)
526
+ {
527
+ inRelayed += rreads;
528
+ emit q->readyRead(Relayed);
529
+ }
530
+ }
531
+
532
+ void sock_datagramsWritten(int count)
533
+ {
534
+ QList<Written> dwrites;
535
+ int twrites = 0;
536
+
537
+ while(count > 0)
538
+ {
539
+ Q_ASSERT(!pendingWrites.isEmpty());
540
+ WriteItem wi = pendingWrites.takeFirst();
541
+ --count;
542
+
543
+ if(wi.type == WriteItem::Direct)
544
+ {
545
+ int at = -1;
546
+ for(int n = 0; n < dwrites.count(); ++n)
547
+ {
548
+ if(dwritesn.addr == wi.addr && dwritesn.port == wi.port)
549
+ {
550
+ at = n;
551
+ break;
552
+ }
553
+ }
554
+
555
+ if(at != -1)
556
+ {
557
+ ++dwritesat.count;
558
+ }
559
+ else
560
+ {
561
+ Written wr;
562
+ wr.addr = wi.addr;
563
+ wr.port = wi.port;
564
+ wr.count = 1;
565
+ dwrites += wr;
566
+ }
567
+ }
568
+ else if(wi.type == WriteItem::Turn)
569
+ ++twrites;
570
+ }
571
+
572
+ if(dwrites.isEmpty() && twrites == 0)
573
+ return;
574
+
575
+ ObjectSessionWatcher watch(&sess);
576
+
577
+ if(!dwrites.isEmpty())
578
+ {
579
+ foreach(const Written &wr, dwrites)
580
+ {
581
+ emit q->datagramsWritten(Direct, wr.count, wr.addr, wr.port);
582
+ if(!watch.isValid())
583
+ return;
584
+ }
585
+ }
586
+
587
+ if(twrites > 0)
588
+ {
589
+ // note: this will invoke turn_packetsWritten()
590
+ turn->outgoingDatagramsWritten(twrites);
591
+ }
592
+ }
593
+
594
+ void pool_outgoingMessage(const QByteArray &packet, const QHostAddress &toAddress, int toPort)
595
+ {
596
+ // warning: read StunTransactionPool docs before modifying
597
+ // this function
598
+
599
+ WriteItem wi;
600
+ wi.type = WriteItem::Pool;
601
+ pendingWrites += wi;
602
+ sock->writeDatagram(packet, toAddress, toPort);
603
+ }
604
+
605
+ void pool_needAuthParams()
606
+ {
607
+ // we can get this signal if the user did not provide
608
+ // creds to us. however, since this class doesn't support
609
+ // prompting just continue on as if we had a blank
610
+ // user/pass
611
+ pool->continueAfterParams();
612
+ }
613
+
614
+ void pool_debugLine(const QString &line)
615
+ {
616
+ emit q->debugLine(line);
617
+ }
618
+
619
+ void binding_success()
620
+ {
621
+ refAddr = stunBinding->reflexiveAddress();
622
+ refPort = stunBinding->reflexivePort();
623
+
624
+ delete stunBinding;
625
+ stunBinding = 0;
626
+
627
+ emit q->addressesChanged();
628
+ }
629
+
630
+ void binding_error(XMPP::StunBinding::Error e)
631
+ {
632
+ Q_UNUSED(e);
633
+
634
+ delete stunBinding;
635
+ stunBinding = 0;
636
+
637
+ // don't report any error
638
+ //if(stunType == IceLocalTransport::Basic || (stunType == IceLocalTransport::Auto && !turn))
639
+ // emit q->addressesChanged();
640
+ }
641
+
642
+ void turn_connected()
643
+ {
644
+ if(debugLevel >= IceTransport::DL_Info)
645
+ emit q->debugLine("turn_connected");
646
+ }
647
+
648
+ void turn_tlsHandshaken()
649
+ {
650
+ if(debugLevel >= IceTransport::DL_Info)
651
+ emit q->debugLine("turn_tlsHandshaken");
652
+ }
653
+
654
+ void turn_closed()
655
+ {
656
+ if(debugLevel >= IceTransport::DL_Info)
657
+ emit q->debugLine("turn_closed");
658
+
659
+ delete turn;
660
+ turn = 0;
661
+ turnActivated = false;
662
+
663
+ postStop();
664
+ }
665
+
666
+ void turn_activated()
667
+ {
668
+ StunAllocate *allocate = turn->stunAllocate();
669
+
670
+ // take reflexive address from TURN only if we are not using a
671
+ // separate STUN server
672
+ if(stunBindAddr.isNull() || stunBindAddr == stunRelayAddr)
673
+ {
674
+ refAddr = allocate->reflexiveAddress();
675
+ refPort = allocate->reflexivePort();
676
+ }
677
+
678
+ if(debugLevel >= IceTransport::DL_Info)
679
+ emit q->debugLine(QString("Server says we are ") + allocate->reflexiveAddress().toString() + ';' + QString::number(allocate->reflexivePort()));
680
+
681
+ relAddr = allocate->relayedAddress();
682
+ relPort = allocate->relayedPort();
683
+ if(debugLevel >= IceTransport::DL_Info)
684
+ emit q->debugLine(QString("Server relays via ") + relAddr.toString() + ';' + QString::number(relPort));
685
+
686
+ turnActivated = true;
687
+
688
+ emit q->addressesChanged();
689
+ }
690
+
691
+ void turn_packetsWritten(int count, const QHostAddress &addr, int port)
692
+ {
693
+ emit q->datagramsWritten(Relayed, count, addr, port);
694
+ }
695
+
696
+ void turn_error(XMPP::TurnClient::Error e)
697
+ {
698
+ if(debugLevel >= IceTransport::DL_Info)
699
+ emit q->debugLine(QString("turn_error: ") + turn->errorString());
700
+
701
+ delete turn;
702
+ turn = 0;
703
+ bool wasActivated = turnActivated;
704
+ turnActivated = false;
705
+
706
+ if(e == TurnClient::ErrorMismatch)
707
+ {
708
+ if(!extSock && handleRetry())
709
+ return;
710
+ }
711
+
712
+ // this means our relay died on us. in the future we might
713
+ // consider reporting this
714
+ if(wasActivated)
715
+ return;
716
+
717
+ // don't report any error
718
+ //if(stunType == IceLocalTransport::Relay || (stunType == IceLocalTransport::Auto && !stunBinding))
719
+ // emit q->addressesChanged();
720
+ }
721
+
722
+ void turn_outgoingDatagram(const QByteArray &buf)
723
+ {
724
+ WriteItem wi;
725
+ wi.type = WriteItem::Turn;
726
+ pendingWrites += wi;
727
+ sock->writeDatagram(buf, stunRelayAddr, stunRelayPort);
728
+ }
729
+
730
+ void turn_debugLine(const QString &line)
731
+ {
732
+ emit q->debugLine(line);
733
+ }
734
+};
735
+
736
+IceLocalTransport::IceLocalTransport(QObject *parent) :
737
+ IceTransport(parent)
738
+{
739
+ d = new Private(this);
740
+}
741
+
742
+IceLocalTransport::~IceLocalTransport()
743
+{
744
+ delete d;
745
+}
746
+
747
+void IceLocalTransport::setClientSoftwareNameAndVersion(const QString &str)
748
+{
749
+ d->clientSoftware = str;
750
+}
751
+
752
+void IceLocalTransport::start(QUdpSocket *sock)
753
+{
754
+ d->extSock = sock;
755
+ d->start();
756
+}
757
+
758
+void IceLocalTransport::start(const QHostAddress &addr)
759
+{
760
+ d->addr = addr;
761
+ d->start();
762
+}
763
+
764
+void IceLocalTransport::stop()
765
+{
766
+ d->stop();
767
+}
768
+
769
+void IceLocalTransport::setStunBindService(const QHostAddress &addr, int port)
770
+{
771
+ d->stunBindAddr = addr;
772
+ d->stunBindPort = port;
773
+}
774
+
775
+void IceLocalTransport::setStunRelayService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass)
776
+{
777
+ d->stunRelayAddr = addr;
778
+ d->stunRelayPort = port;
779
+ d->stunUser = user;
780
+ d->stunPass = pass;
781
+}
782
+
783
+void IceLocalTransport::stunStart()
784
+{
785
+ d->stunStart();
786
+}
787
+
788
+QHostAddress IceLocalTransport::localAddress() const
789
+{
790
+ return d->addr;
791
+}
792
+
793
+int IceLocalTransport::localPort() const
794
+{
795
+ return d->port;
796
+}
797
+
798
+QHostAddress IceLocalTransport::serverReflexiveAddress() const
799
+{
800
+ return d->refAddr;
801
+}
802
+
803
+int IceLocalTransport::serverReflexivePort() const
804
+{
805
+ return d->refPort;
806
+}
807
+
808
+QHostAddress IceLocalTransport::relayedAddress() const
809
+{
810
+ return d->relAddr;
811
+}
812
+
813
+int IceLocalTransport::relayedPort() const
814
+{
815
+ return d->relPort;
816
+}
817
+
818
+void IceLocalTransport::addChannelPeer(const QHostAddress &addr, int port)
819
+{
820
+ if(d->turn)
821
+ d->turn->addChannelPeer(addr, port);
822
+}
823
+
824
+bool IceLocalTransport::hasPendingDatagrams(int path) const
825
+{
826
+ if(path == Direct)
827
+ return !d->in.isEmpty();
828
+ else if(path == Relayed)
829
+ return !d->inRelayed.isEmpty();
830
+ else
831
+ {
832
+ Q_ASSERT(0);
833
+ return false;
834
+ }
835
+}
836
+
837
+QByteArray IceLocalTransport::readDatagram(int path, QHostAddress *addr, int *port)
838
+{
839
+ QList<Private::Datagram> *in = 0;
840
+ if(path == Direct)
841
+ in = &d->in;
842
+ else if(path == Relayed)
843
+ in = &d->inRelayed;
844
+ else
845
+ Q_ASSERT(0);
846
+
847
+ if(!in->isEmpty())
848
+ {
849
+ Private::Datagram datagram = in->takeFirst();
850
+ *addr = datagram.addr;
851
+ *port = datagram.port;
852
+ return datagram.buf;
853
+ }
854
+ else
855
+ return QByteArray();
856
+}
857
+
858
+void IceLocalTransport::writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port)
859
+{
860
+ if(path == Direct)
861
+ {
862
+ Private::WriteItem wi;
863
+ wi.type = Private::WriteItem::Direct;
864
+ wi.addr = addr;
865
+ wi.port = port;
866
+ d->pendingWrites += wi;
867
+ d->sock->writeDatagram(buf, addr, port);
868
+ }
869
+ else if(path == Relayed)
870
+ {
871
+ if(d->turn && d->turnActivated)
872
+ d->turn->write(buf, addr, port);
873
+ }
874
+ else
875
+ Q_ASSERT(0);
876
+}
877
+
878
+void IceLocalTransport::setDebugLevel(DebugLevel level)
879
+{
880
+ d->debugLevel = level;
881
+ if(d->pool)
882
+ d->pool->setDebugLevel((StunTransactionPool::DebugLevel)level);
883
+ if(d->turn)
884
+ d->turn->setDebugLevel((TurnClient::DebugLevel)level);
885
+}
886
+
887
+}
888
+
889
+#include "icelocaltransport.moc"
890
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icelocaltransport.h
Added
105
1
2
+/*
3
+ * Copyright (C) 2009,2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef ICELOCALTRANSPORT_H
23
+#define ICELOCALTRANSPORT_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+#include "icetransport.h"
28
+
29
+class QHostAddress;
30
+class QUdpSocket;
31
+
32
+namespace QCA {
33
+ class SecureArray;
34
+}
35
+
36
+namespace XMPP {
37
+
38
+// this class manages a single port on a single interface, including the
39
+// relationship with an associated STUN/TURN server. if TURN is used, this
40
+// class offers two paths (0=direct and 1=relayed), otherwise it offers
41
+// just one path (0=direct)
42
+class IceLocalTransport : public IceTransport
43
+{
44
+ Q_OBJECT
45
+
46
+public:
47
+ enum Error
48
+ {
49
+ ErrorBind = ErrorCustom
50
+ };
51
+
52
+ IceLocalTransport(QObject *parent = 0);
53
+ ~IceLocalTransport();
54
+
55
+ void setClientSoftwareNameAndVersion(const QString &str);
56
+
57
+ // passed socket must already be bind()'ed, don't support
58
+ // ErrorMismatch retries
59
+ void start(QUdpSocket *sock);
60
+
61
+ // bind to this address on a random port, do support ErrorMismatch
62
+ // retries
63
+ void start(const QHostAddress &addr);
64
+
65
+ void setStunBindService(const QHostAddress &addr, int port);
66
+ void setStunRelayService(const QHostAddress &addr, int port, const QString &user, const QCA::SecureArray &pass);
67
+
68
+ // obtain relay / reflexive
69
+ void stunStart();
70
+
71
+ QHostAddress localAddress() const;
72
+ int localPort() const;
73
+
74
+ QHostAddress serverReflexiveAddress() const;
75
+ int serverReflexivePort() const;
76
+
77
+ QHostAddress relayedAddress() const;
78
+ int relayedPort() const;
79
+
80
+ // reimplemented
81
+ virtual void stop();
82
+ virtual bool hasPendingDatagrams(int path) const;
83
+ virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port);
84
+ virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port);
85
+ virtual void addChannelPeer(const QHostAddress &addr, int port);
86
+ virtual void setDebugLevel(DebugLevel level);
87
+
88
+signals:
89
+ // may be emitted multiple times.
90
+ // if handling internal ErrorMismatch, then local address may change
91
+ // and server reflexive address may disappear.
92
+ // if start(QUdpSocket*) was used, then ErrorMismatch is not handled,
93
+ // and this signal will only be emitted to add addresses
94
+ void addressesChanged();
95
+
96
+private:
97
+ class Private;
98
+ friend class Private;
99
+ Private *d;
100
+};
101
+
102
+}
103
+
104
+#endif
105
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icetransport.cpp
Added
36
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "icetransport.h"
23
+
24
+namespace XMPP {
25
+
26
+IceTransport::IceTransport(QObject *parent) :
27
+ QObject(parent)
28
+{
29
+}
30
+
31
+IceTransport::~IceTransport()
32
+{
33
+}
34
+
35
+}
36
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/icetransport.h
Added
77
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef ICETRANSPORT_H
23
+#define ICETRANSPORT_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+
28
+class QHostAddress;
29
+
30
+namespace XMPP {
31
+
32
+class IceTransport : public QObject
33
+{
34
+ Q_OBJECT
35
+
36
+public:
37
+ enum Error
38
+ {
39
+ ErrorGeneric,
40
+ ErrorCustom
41
+ };
42
+
43
+ enum DebugLevel
44
+ {
45
+ DL_None,
46
+ DL_Info,
47
+ DL_Packet
48
+ };
49
+
50
+ IceTransport(QObject *parent = 0);
51
+ ~IceTransport();
52
+
53
+ virtual void stop() = 0;
54
+
55
+ virtual bool hasPendingDatagrams(int path) const = 0;
56
+ virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port) = 0;
57
+ virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port) = 0;
58
+ virtual void addChannelPeer(const QHostAddress &addr, int port) = 0;
59
+
60
+ virtual void setDebugLevel(DebugLevel level) = 0;
61
+
62
+signals:
63
+ void started();
64
+ void stopped();
65
+ void error(int e);
66
+
67
+ void readyRead(int path);
68
+ void datagramsWritten(int path, int count, const QHostAddress &addr, int port);
69
+
70
+ // not DOR-SS/DS safe
71
+ void debugLine(const QString &str);
72
+};
73
+
74
+}
75
+
76
+#endif
77
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/iceturntransport.cpp
Added
253
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "iceturntransport.h"
23
+
24
+#include <QtCrypto>
25
+#include "stunallocate.h"
26
+
27
+namespace XMPP {
28
+
29
+class IceTurnTransport::Private : public QObject
30
+{
31
+ Q_OBJECT
32
+
33
+public:
34
+ IceTurnTransport *q;
35
+ int mode;
36
+ QHostAddress serverAddr;
37
+ int serverPort;
38
+ QString relayUser;
39
+ QCA::SecureArray relayPass;
40
+ QHostAddress relayAddr;
41
+ int relayPort;
42
+ TurnClient turn;
43
+ int turnErrorCode;
44
+ int debugLevel;
45
+
46
+ Private(IceTurnTransport *_q) :
47
+ QObject(_q),
48
+ q(_q),
49
+ turn(this),
50
+ debugLevel(IceTransport::DL_None)
51
+ {
52
+ connect(&turn, SIGNAL(connected()), SLOT(turn_connected()));
53
+ connect(&turn, SIGNAL(tlsHandshaken()), SLOT(turn_tlsHandshaken()));
54
+ connect(&turn, SIGNAL(closed()), SLOT(turn_closed()));
55
+ connect(&turn, SIGNAL(needAuthParams()), SLOT(turn_needAuthParams()));
56
+ connect(&turn, SIGNAL(retrying()), SLOT(turn_retrying()));
57
+ connect(&turn, SIGNAL(activated()), SLOT(turn_activated()));
58
+ connect(&turn, SIGNAL(readyRead()), SLOT(turn_readyRead()));
59
+ connect(&turn, SIGNAL(packetsWritten(int, const QHostAddress &, int)), SLOT(turn_packetsWritten(int, const QHostAddress &, int)));
60
+ connect(&turn, SIGNAL(error(XMPP::TurnClient::Error)), SLOT(turn_error(XMPP::TurnClient::Error)));
61
+ connect(&turn, SIGNAL(debugLine(const QString &)), SLOT(turn_debugLine(const QString &)));
62
+ }
63
+
64
+ void start()
65
+ {
66
+ turn.setUsername(relayUser);
67
+ turn.setPassword(relayPass);
68
+ turn.connectToHost(serverAddr, serverPort, (TurnClient::Mode)mode);
69
+ }
70
+
71
+ void stop()
72
+ {
73
+ turn.close();
74
+ }
75
+
76
+private slots:
77
+ void turn_connected()
78
+ {
79
+ if(debugLevel >= IceTransport::DL_Info)
80
+ emit q->debugLine("turn_connected");
81
+ }
82
+
83
+ void turn_tlsHandshaken()
84
+ {
85
+ if(debugLevel >= IceTransport::DL_Info)
86
+ emit q->debugLine("turn_tlsHandshaken");
87
+ }
88
+
89
+ void turn_closed()
90
+ {
91
+ if(debugLevel >= IceTransport::DL_Info)
92
+ emit q->debugLine("turn_closed");
93
+
94
+ emit q->stopped();
95
+ }
96
+
97
+ void turn_needAuthParams()
98
+ {
99
+ // we can get this signal if the user did not provide
100
+ // creds to us. however, since this class doesn't support
101
+ // prompting just continue on as if we had a blank
102
+ // user/pass
103
+ turn.continueAfterParams();
104
+ }
105
+
106
+ void turn_retrying()
107
+ {
108
+ if(debugLevel >= IceTransport::DL_Info)
109
+ emit q->debugLine("turn_retrying");
110
+ }
111
+
112
+ void turn_activated()
113
+ {
114
+ StunAllocate *allocate = turn.stunAllocate();
115
+
116
+ QHostAddress saddr = allocate->reflexiveAddress();
117
+ quint16 sport = allocate->reflexivePort();
118
+ if(debugLevel >= IceTransport::DL_Info)
119
+ emit q->debugLine(QString("Server says we are ") + saddr.toString() + ';' + QString::number(sport));
120
+ saddr = allocate->relayedAddress();
121
+ sport = allocate->relayedPort();
122
+ if(debugLevel >= IceTransport::DL_Info)
123
+ emit q->debugLine(QString("Server relays via ") + saddr.toString() + ';' + QString::number(sport));
124
+
125
+ relayAddr = saddr;
126
+ relayPort = sport;
127
+
128
+ emit q->started();
129
+ }
130
+
131
+ void turn_readyRead()
132
+ {
133
+ emit q->readyRead(0);
134
+ }
135
+
136
+ void turn_packetsWritten(int count, const QHostAddress &addr, int port)
137
+ {
138
+ emit q->datagramsWritten(0, count, addr, port);
139
+ }
140
+
141
+ void turn_error(XMPP::TurnClient::Error e)
142
+ {
143
+ if(debugLevel >= IceTransport::DL_Info)
144
+ emit q->debugLine(QString("turn_error: ") + turn.errorString());
145
+
146
+ turnErrorCode = e;
147
+ emit q->error(IceTurnTransport::ErrorTurn);
148
+ }
149
+
150
+ void turn_debugLine(const QString &line)
151
+ {
152
+ emit q->debugLine(line);
153
+ }
154
+};
155
+
156
+IceTurnTransport::IceTurnTransport(QObject *parent) :
157
+ IceTransport(parent)
158
+{
159
+ d = new Private(this);
160
+}
161
+
162
+IceTurnTransport::~IceTurnTransport()
163
+{
164
+ delete d;
165
+}
166
+
167
+void IceTurnTransport::setClientSoftwareNameAndVersion(const QString &str)
168
+{
169
+ d->turn.setClientSoftwareNameAndVersion(str);
170
+}
171
+
172
+void IceTurnTransport::setUsername(const QString &user)
173
+{
174
+ d->relayUser = user;
175
+}
176
+
177
+void IceTurnTransport::setPassword(const QCA::SecureArray &pass)
178
+{
179
+ d->relayPass = pass;
180
+}
181
+
182
+void IceTurnTransport::setProxy(const TurnClient::Proxy &proxy)
183
+{
184
+ d->turn.setProxy(proxy);
185
+}
186
+
187
+void IceTurnTransport::start(const QHostAddress &addr, int port, TurnClient::Mode mode)
188
+{
189
+ d->serverAddr = addr;
190
+ d->serverPort = port;
191
+ d->mode = mode;
192
+ d->start();
193
+}
194
+
195
+QHostAddress IceTurnTransport::relayedAddress() const
196
+{
197
+ return d->relayAddr;
198
+}
199
+
200
+int IceTurnTransport::relayedPort() const
201
+{
202
+ return d->relayPort;
203
+}
204
+
205
+void IceTurnTransport::addChannelPeer(const QHostAddress &addr, int port)
206
+{
207
+ d->turn.addChannelPeer(addr, port);
208
+}
209
+
210
+TurnClient::Error IceTurnTransport::turnErrorCode() const
211
+{
212
+ return (TurnClient::Error)d->turnErrorCode;
213
+}
214
+
215
+void IceTurnTransport::stop()
216
+{
217
+ d->stop();
218
+}
219
+
220
+bool IceTurnTransport::hasPendingDatagrams(int path) const
221
+{
222
+ Q_ASSERT(path == 0);
223
+ Q_UNUSED(path);
224
+
225
+ return (d->turn.packetsToRead() > 0 ? true : false);
226
+}
227
+
228
+QByteArray IceTurnTransport::readDatagram(int path, QHostAddress *addr, int *port)
229
+{
230
+ Q_ASSERT(path == 0);
231
+ Q_UNUSED(path);
232
+
233
+ return d->turn.read(addr, port);
234
+}
235
+
236
+void IceTurnTransport::writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port)
237
+{
238
+ Q_ASSERT(path == 0);
239
+ Q_UNUSED(path);
240
+
241
+ d->turn.write(buf, addr, port);
242
+}
243
+
244
+void IceTurnTransport::setDebugLevel(DebugLevel level)
245
+{
246
+ d->debugLevel = level;
247
+ d->turn.setDebugLevel((TurnClient::DebugLevel)level);
248
+}
249
+
250
+}
251
+
252
+#include "iceturntransport.moc"
253
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/iceturntransport.h
Added
80
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef ICETURNTRANSPORT_H
23
+#define ICETURNTRANSPORT_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+#include <QHostAddress>
28
+#include "turnclient.h"
29
+#include "icetransport.h"
30
+
31
+namespace XMPP {
32
+
33
+// for the turn transport, only path 0 is used
34
+
35
+class IceTurnTransport : public IceTransport
36
+{
37
+ Q_OBJECT
38
+
39
+public:
40
+ enum Error
41
+ {
42
+ ErrorTurn = ErrorCustom
43
+ };
44
+
45
+ IceTurnTransport(QObject *parent = 0);
46
+ ~IceTurnTransport();
47
+
48
+ void setClientSoftwareNameAndVersion(const QString &str);
49
+
50
+ // set these before calling start()
51
+ void setUsername(const QString &user);
52
+ void setPassword(const QCA::SecureArray &pass);
53
+
54
+ void setProxy(const TurnClient::Proxy &proxy);
55
+
56
+ void start(const QHostAddress &addr, int port, TurnClient::Mode mode = TurnClient::PlainMode);
57
+
58
+ QHostAddress relayedAddress() const;
59
+ int relayedPort() const;
60
+
61
+ TurnClient::Error turnErrorCode() const;
62
+
63
+ // reimplemented
64
+ virtual void stop();
65
+ virtual bool hasPendingDatagrams(int path) const;
66
+ virtual QByteArray readDatagram(int path, QHostAddress *addr, int *port);
67
+ virtual void writeDatagram(int path, const QByteArray &buf, const QHostAddress &addr, int port);
68
+ virtual void addChannelPeer(const QHostAddress &addr, int port);
69
+ virtual void setDebugLevel(DebugLevel level);
70
+
71
+private:
72
+ class Private;
73
+ friend class Private;
74
+ Private *d;
75
+};
76
+
77
+}
78
+
79
+#endif
80
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/objectsession.cpp
Added
303
1
2
+/*
3
+ * Copyright (C) 2008 Justin Karneges
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+#include "objectsession.h"
22
+
23
+#include <QList>
24
+#include <QByteArray>
25
+#include <QMetaObject>
26
+#include <QMetaType>
27
+#include <QTimer>
28
+
29
+namespace XMPP {
30
+
31
+class ObjectSessionWatcherPrivate
32
+{
33
+public:
34
+ ObjectSession *sess;
35
+};
36
+
37
+class ObjectSessionPrivate : public QObject
38
+{
39
+ Q_OBJECT
40
+
41
+public:
42
+ ObjectSession *q;
43
+
44
+ class MethodCall
45
+ {
46
+ public:
47
+ QObject *obj;
48
+ QByteArray method;
49
+ class Argument
50
+ {
51
+ public:
52
+ int type;
53
+ void *data;
54
+ };
55
+ QList<Argument> args;
56
+
57
+ MethodCall(QObject *_obj, const char *_method) :
58
+ obj(_obj),
59
+ method(_method)
60
+ {
61
+ }
62
+
63
+ ~MethodCall()
64
+ {
65
+ clearArgs();
66
+ }
67
+
68
+ void clearArgs()
69
+ {
70
+ for(int n = 0; n < args.count(); ++n)
71
+ QMetaType::destroy(argsn.type, argsn.data);
72
+ args.clear();
73
+ }
74
+
75
+ bool setArgs(QGenericArgument val0 = QGenericArgument(),
76
+ QGenericArgument val1 = QGenericArgument(),
77
+ QGenericArgument val2 = QGenericArgument(),
78
+ QGenericArgument val3 = QGenericArgument(),
79
+ QGenericArgument val4 = QGenericArgument(),
80
+ QGenericArgument val5 = QGenericArgument(),
81
+ QGenericArgument val6 = QGenericArgument(),
82
+ QGenericArgument val7 = QGenericArgument(),
83
+ QGenericArgument val8 = QGenericArgument(),
84
+ QGenericArgument val9 = QGenericArgument())
85
+ {
86
+ const char *arg_name =
87
+ {
88
+ val0.name(), val1.name(), val2.name(),
89
+ val3.name(), val4.name(), val5.name(),
90
+ val6.name(), val7.name(), val8.name(),
91
+ val9.name()
92
+ };
93
+
94
+ void *arg_data =
95
+ {
96
+ val0.data(), val1.data(), val2.data(),
97
+ val3.data(), val4.data(), val5.data(),
98
+ val6.data(), val7.data(), val8.data(),
99
+ val9.data()
100
+ };
101
+
102
+ clearArgs();
103
+
104
+ for(int n = 0; n < 10; ++n)
105
+ {
106
+ if(arg_namen == 0)
107
+ break;
108
+
109
+ Argument arg;
110
+ arg.type = QMetaType::type(arg_namen);
111
+ if(!arg.type)
112
+ {
113
+ clearArgs();
114
+ return false;
115
+ }
116
+
117
+ arg.data = QMetaType::construct(arg.type, arg_datan);
118
+ args += arg;
119
+ }
120
+
121
+ return true;
122
+ }
123
+ };
124
+
125
+ QList<MethodCall*> pendingCalls;
126
+ QTimer *callTrigger;
127
+ bool paused;
128
+ QList<ObjectSessionWatcherPrivate*> watchers;
129
+
130
+ ObjectSessionPrivate(ObjectSession *_q) :
131
+ QObject(_q),
132
+ q(_q),
133
+ paused(false)
134
+ {
135
+ callTrigger = new QTimer(this);
136
+ connect(callTrigger, SIGNAL(timeout()), SLOT(doCall()));
137
+ callTrigger->setSingleShot(true);
138
+ }
139
+
140
+ ~ObjectSessionPrivate()
141
+ {
142
+ invalidateWatchers();
143
+
144
+ callTrigger->disconnect(this);
145
+ callTrigger->setParent(0);
146
+ callTrigger->deleteLater();
147
+ }
148
+
149
+ void addPendingCall(MethodCall *call)
150
+ {
151
+ pendingCalls += call;
152
+ if(!paused && !callTrigger->isActive())
153
+ callTrigger->start();
154
+ }
155
+
156
+ bool havePendingCall(QObject *obj, const char *method) const
157
+ {
158
+ foreach(const MethodCall *call, pendingCalls)
159
+ {
160
+ if(call->obj == obj && qstrcmp(call->method.data(), method) == 0)
161
+ return true;
162
+ }
163
+ return false;
164
+ }
165
+
166
+ void invalidateWatchers()
167
+ {
168
+ for(int n = 0; n < watchers.count(); ++n)
169
+ watchersn->sess = 0;
170
+ watchers.clear();
171
+ }
172
+
173
+private slots:
174
+ void doCall()
175
+ {
176
+ MethodCall *call = pendingCalls.takeFirst();
177
+ if(!pendingCalls.isEmpty())
178
+ callTrigger->start();
179
+
180
+ Q_ASSERT(call->args.count() <= 10);
181
+
182
+ QGenericArgument arg10;
183
+ for(int n = 0; n < call->args.count(); ++n)
184
+ argn = QGenericArgument(QMetaType::typeName(call->argsn.type), call->argsn.data);
185
+
186
+ bool ok;
187
+ ok = QMetaObject::invokeMethod(call->obj, call->method.data(),
188
+ Qt::DirectConnection,
189
+ arg0, arg1, arg2, arg3, arg4,
190
+ arg5, arg6, arg7, arg8, arg9);
191
+ Q_ASSERT(ok);
192
+
193
+ delete call;
194
+ }
195
+};
196
+
197
+ObjectSessionWatcher::ObjectSessionWatcher(ObjectSession *sess)
198
+{
199
+ d = new ObjectSessionWatcherPrivate;
200
+ d->sess = sess;
201
+ if(d->sess)
202
+ d->sess->d->watchers += d;
203
+}
204
+
205
+ObjectSessionWatcher::~ObjectSessionWatcher()
206
+{
207
+ if(d->sess)
208
+ d->sess->d->watchers.removeAll(d);
209
+ delete d;
210
+}
211
+
212
+bool ObjectSessionWatcher::isValid() const
213
+{
214
+ if(d->sess)
215
+ return true;
216
+ else
217
+ return false;
218
+}
219
+
220
+
221
+ObjectSession::ObjectSession(QObject *parent) :
222
+ QObject(parent)
223
+{
224
+ d = new ObjectSessionPrivate(this);
225
+}
226
+
227
+ObjectSession::~ObjectSession()
228
+{
229
+ delete d;
230
+}
231
+
232
+void ObjectSession::reset()
233
+{
234
+ d->invalidateWatchers();
235
+ if(d->callTrigger->isActive())
236
+ d->callTrigger->stop();
237
+ d->pendingCalls.clear();
238
+}
239
+
240
+bool ObjectSession::isDeferred(QObject *obj, const char *method)
241
+{
242
+ return d->havePendingCall(obj, method);
243
+}
244
+
245
+void ObjectSession::defer(QObject *obj, const char *method,
246
+ QGenericArgument val0,
247
+ QGenericArgument val1,
248
+ QGenericArgument val2,
249
+ QGenericArgument val3,
250
+ QGenericArgument val4,
251
+ QGenericArgument val5,
252
+ QGenericArgument val6,
253
+ QGenericArgument val7,
254
+ QGenericArgument val8,
255
+ QGenericArgument val9)
256
+{
257
+ ObjectSessionPrivate::MethodCall *call = new ObjectSessionPrivate::MethodCall(obj, method);
258
+ call->setArgs(val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
259
+ d->addPendingCall(call);
260
+}
261
+
262
+void ObjectSession::deferExclusive(QObject *obj, const char *method,
263
+ QGenericArgument val0,
264
+ QGenericArgument val1,
265
+ QGenericArgument val2,
266
+ QGenericArgument val3,
267
+ QGenericArgument val4,
268
+ QGenericArgument val5,
269
+ QGenericArgument val6,
270
+ QGenericArgument val7,
271
+ QGenericArgument val8,
272
+ QGenericArgument val9)
273
+{
274
+ if(d->havePendingCall(obj, method))
275
+ return;
276
+
277
+ ObjectSessionPrivate::MethodCall *call = new ObjectSessionPrivate::MethodCall(obj, method);
278
+ call->setArgs(val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
279
+ d->addPendingCall(call);
280
+}
281
+
282
+void ObjectSession::pause()
283
+{
284
+ Q_ASSERT(!d->paused);
285
+
286
+ if(d->callTrigger->isActive())
287
+ d->callTrigger->stop();
288
+ d->paused = true;
289
+}
290
+
291
+void ObjectSession::resume()
292
+{
293
+ Q_ASSERT(d->paused);
294
+
295
+ d->paused = false;
296
+ if(!d->pendingCalls.isEmpty())
297
+ d->callTrigger->start();
298
+}
299
+
300
+}
301
+
302
+#include "objectsession.moc"
303
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/objectsession.h
Added
90
1
2
+/*
3
+ * Copyright (C) 2008 Justin Karneges
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ *
19
+ */
20
+
21
+#ifndef OBJECTSESSION_H
22
+#define OBJECTSESSION_H
23
+
24
+#include <QObject>
25
+
26
+namespace XMPP {
27
+
28
+class ObjectSessionPrivate;
29
+class ObjectSessionWatcherPrivate;
30
+
31
+class ObjectSession : public QObject
32
+{
33
+ Q_OBJECT
34
+
35
+public:
36
+ ObjectSession(QObject *parent = 0);
37
+ ~ObjectSession();
38
+
39
+ // clear all deferred requests, invalidate watchers
40
+ void reset();
41
+
42
+ bool isDeferred(QObject *obj, const char *method);
43
+ void defer(QObject *obj, const char *method,
44
+ QGenericArgument val0 = QGenericArgument(),
45
+ QGenericArgument val1 = QGenericArgument(),
46
+ QGenericArgument val2 = QGenericArgument(),
47
+ QGenericArgument val3 = QGenericArgument(),
48
+ QGenericArgument val4 = QGenericArgument(),
49
+ QGenericArgument val5 = QGenericArgument(),
50
+ QGenericArgument val6 = QGenericArgument(),
51
+ QGenericArgument val7 = QGenericArgument(),
52
+ QGenericArgument val8 = QGenericArgument(),
53
+ QGenericArgument val9 = QGenericArgument());
54
+ void deferExclusive(QObject *obj, const char *method,
55
+ QGenericArgument val0 = QGenericArgument(),
56
+ QGenericArgument val1 = QGenericArgument(),
57
+ QGenericArgument val2 = QGenericArgument(),
58
+ QGenericArgument val3 = QGenericArgument(),
59
+ QGenericArgument val4 = QGenericArgument(),
60
+ QGenericArgument val5 = QGenericArgument(),
61
+ QGenericArgument val6 = QGenericArgument(),
62
+ QGenericArgument val7 = QGenericArgument(),
63
+ QGenericArgument val8 = QGenericArgument(),
64
+ QGenericArgument val9 = QGenericArgument());
65
+
66
+ void pause();
67
+ void resume();
68
+
69
+private:
70
+ friend class ObjectSessionWatcher;
71
+ ObjectSessionPrivate *d;
72
+};
73
+
74
+class ObjectSessionWatcher
75
+{
76
+public:
77
+ ObjectSessionWatcher(ObjectSession *sess);
78
+ ~ObjectSessionWatcher();
79
+
80
+ bool isValid() const;
81
+
82
+private:
83
+ friend class ObjectSessionPrivate;
84
+ ObjectSessionWatcherPrivate *d;
85
+};
86
+
87
+}
88
+
89
+#endif
90
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/servsock.cpp
Added
113
1
2
+/*
3
+ * servsock.cpp - simple wrapper to QServerSocket
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#include "servsock.h"
23
+
24
+// CS_NAMESPACE_BEGIN
25
+
26
+//----------------------------------------------------------------------------
27
+// ServSock
28
+//----------------------------------------------------------------------------
29
+class ServSock::Private
30
+{
31
+public:
32
+ Private() {}
33
+
34
+ ServSockSignal *serv;
35
+};
36
+
37
+ServSock::ServSock(QObject *parent)
38
+:QObject(parent)
39
+{
40
+ d = new Private;
41
+ d->serv = 0;
42
+}
43
+
44
+ServSock::~ServSock()
45
+{
46
+ stop();
47
+ delete d;
48
+}
49
+
50
+bool ServSock::isActive() const
51
+{
52
+ return (d->serv ? true: false);
53
+}
54
+
55
+bool ServSock::listen(quint16 port)
56
+{
57
+ stop();
58
+
59
+ d->serv = new ServSockSignal(this);
60
+ if(!d->serv->listen(QHostAddress::Any, port)) {
61
+ delete d->serv;
62
+ d->serv = 0;
63
+ return false;
64
+ }
65
+ connect(d->serv, SIGNAL(connectionReady(int)), SLOT(sss_connectionReady(int)));
66
+
67
+ return true;
68
+}
69
+
70
+void ServSock::stop()
71
+{
72
+ delete d->serv;
73
+ d->serv = 0;
74
+}
75
+
76
+int ServSock::port() const
77
+{
78
+ if(d->serv)
79
+ return d->serv->serverPort();
80
+ else
81
+ return -1;
82
+}
83
+
84
+QHostAddress ServSock::address() const
85
+{
86
+ if(d->serv)
87
+ return d->serv->serverAddress();
88
+ else
89
+ return QHostAddress();
90
+}
91
+
92
+void ServSock::sss_connectionReady(int s)
93
+{
94
+ connectionReady(s);
95
+}
96
+
97
+
98
+//----------------------------------------------------------------------------
99
+// ServSockSignal
100
+//----------------------------------------------------------------------------
101
+ServSockSignal::ServSockSignal(QObject *parent)
102
+:QTcpServer(parent)
103
+{
104
+ setMaxPendingConnections(16);
105
+}
106
+
107
+void ServSockSignal::incomingConnection(int socketDescriptor)
108
+{
109
+ connectionReady(socketDescriptor);
110
+}
111
+
112
+// CS_NAMESPACE_END
113
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/servsock.h
Added
71
1
2
+/*
3
+ * servsock.h - simple wrapper to QServerSocket
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#ifndef CS_SERVSOCK_H
23
+#define CS_SERVSOCK_H
24
+
25
+#include <QtCore>
26
+#include <QtNetwork>
27
+
28
+// CS_NAMESPACE_BEGIN
29
+
30
+class ServSock : public QObject
31
+{
32
+ Q_OBJECT
33
+public:
34
+ ServSock(QObject *parent=0);
35
+ ~ServSock();
36
+
37
+ bool isActive() const;
38
+ bool listen(quint16 port);
39
+ void stop();
40
+ int port() const;
41
+ QHostAddress address() const;
42
+
43
+signals:
44
+ void connectionReady(int);
45
+
46
+private slots:
47
+ void sss_connectionReady(int);
48
+
49
+private:
50
+ class Private;
51
+ Private *d;
52
+};
53
+
54
+class ServSockSignal : public QTcpServer
55
+{
56
+ Q_OBJECT
57
+public:
58
+ ServSockSignal(QObject *parent = 0);
59
+
60
+signals:
61
+ void connectionReady(int);
62
+
63
+protected:
64
+ // reimplemented
65
+ void incomingConnection(int socketDescriptor);
66
+};
67
+
68
+// CS_NAMESPACE_END
69
+
70
+#endif
71
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/socks.cpp
Added
1136
1
2
+/*
3
+ * socks.cpp - SOCKS5 TCP proxy client/server
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#include "socks.h"
23
+
24
+#include <qhostaddress.h>
25
+#include <qstringlist.h>
26
+#include <qtimer.h>
27
+#include <qpointer.h>
28
+#include <qsocketnotifier.h>
29
+#include <QByteArray>
30
+
31
+#ifdef Q_OS_UNIX
32
+#include <sys/types.h>
33
+#include <netinet/in.h>
34
+#endif
35
+
36
+#ifdef Q_OS_WIN32
37
+#include <windows.h>
38
+#endif
39
+
40
+#ifdef Q_OS_UNIX
41
+#include <unistd.h>
42
+#include <fcntl.h>
43
+#endif
44
+
45
+#include "servsock.h"
46
+#include "bsocket.h"
47
+
48
+//#define PROX_DEBUG
49
+
50
+#ifdef PROX_DEBUG
51
+#include <stdio.h>
52
+#endif
53
+
54
+// CS_NAMESPACE_BEGIN
55
+
56
+//----------------------------------------------------------------------------
57
+// SocksUDP
58
+//----------------------------------------------------------------------------
59
+
60
+class SocksUDP::Private
61
+{
62
+public:
63
+ QUdpSocket *sd;
64
+ SocksClient *sc;
65
+ QHostAddress routeAddr;
66
+ int routePort;
67
+ QString host;
68
+ int port;
69
+};
70
+
71
+SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort)
72
+:QObject(sc)
73
+{
74
+ d = new Private;
75
+ d->sc = sc;
76
+ d->sd = new QUdpSocket(this);
77
+ connect(d->sd, SIGNAL(readyRead()), SLOT(sd_readyRead()));
78
+ d->host = host;
79
+ d->port = port;
80
+ d->routeAddr = routeAddr;
81
+ d->routePort = routePort;
82
+}
83
+
84
+SocksUDP::~SocksUDP()
85
+{
86
+ delete d->sd;
87
+ delete d;
88
+}
89
+
90
+void SocksUDP::change(const QString &host, int port)
91
+{
92
+ d->host = host;
93
+ d->port = port;
94
+}
95
+
96
+void SocksUDP::write(const QByteArray &data)
97
+{
98
+ d->sd->writeDatagram(data.data(), data.size(), d->routeAddr, d->routePort);
99
+}
100
+
101
+void SocksUDP::sd_activated()
102
+{
103
+ while (d->sd->hasPendingDatagrams()) {
104
+ QByteArray datagram;
105
+ datagram.resize(d->sd->pendingDatagramSize());
106
+ d->sd->readDatagram(datagram.data(), datagram.size());
107
+ packetReady(datagram);
108
+ }
109
+}
110
+
111
+//----------------------------------------------------------------------------
112
+// SocksClient
113
+//----------------------------------------------------------------------------
114
+#define REQ_CONNECT 0x01
115
+#define REQ_BIND 0x02
116
+#define REQ_UDPASSOCIATE 0x03
117
+
118
+#define RET_SUCCESS 0x00
119
+#define RET_UNREACHABLE 0x04
120
+#define RET_CONNREFUSED 0x05
121
+
122
+// spc = socks packet client
123
+// sps = socks packet server
124
+// SPCS = socks packet client struct
125
+// SPSS = socks packet server struct
126
+
127
+// Version
128
+static QByteArray spc_set_version()
129
+{
130
+ QByteArray ver;
131
+ ver.resize(4);
132
+ ver0 = 0x05; // socks version 5
133
+ ver1 = 0x02; // number of methods
134
+ ver2 = 0x00; // no-auth
135
+ ver3 = 0x02; // username
136
+ return ver;
137
+}
138
+
139
+static QByteArray sps_set_version(int method)
140
+{
141
+ QByteArray ver;
142
+ ver.resize(2);
143
+ ver0 = 0x05;
144
+ ver1 = method;
145
+ return ver;
146
+}
147
+
148
+struct SPCS_VERSION
149
+{
150
+ unsigned char version;
151
+ QByteArray methodList;
152
+};
153
+
154
+static int spc_get_version(QByteArray *from, SPCS_VERSION *s)
155
+{
156
+ if(from->size() < 1)
157
+ return 0;
158
+ if(from->at(0) != 0x05) // only SOCKS5 supported
159
+ return -1;
160
+ if(from->size() < 2)
161
+ return 0;
162
+ unsigned char mlen = from->at(1);
163
+ int num = mlen;
164
+ if(num > 16) // who the heck has over 16 auth methods??
165
+ return -1;
166
+ if(from->size() < 2 + num)
167
+ return 0;
168
+ QByteArray a = ByteStream::takeArray(from, 2+num);
169
+ s->version = a0;
170
+ s->methodList.resize(num);
171
+ memcpy(s->methodList.data(), a.data() + 2, num);
172
+ return 1;
173
+}
174
+
175
+struct SPSS_VERSION
176
+{
177
+ unsigned char version;
178
+ unsigned char method;
179
+};
180
+
181
+static int sps_get_version(QByteArray *from, SPSS_VERSION *s)
182
+{
183
+ if(from->size() < 2)
184
+ return 0;
185
+ QByteArray a = ByteStream::takeArray(from, 2);
186
+ s->version = a0;
187
+ s->method = a1;
188
+ return 1;
189
+}
190
+
191
+// authUsername
192
+static QByteArray spc_set_authUsername(const QByteArray &user, const QByteArray &pass)
193
+{
194
+ int len1 = user.length();
195
+ int len2 = pass.length();
196
+ if(len1 > 255)
197
+ len1 = 255;
198
+ if(len2 > 255)
199
+ len2 = 255;
200
+ QByteArray a;
201
+ a.resize(1+1+len1+1+len2);
202
+ a0 = 0x01; // username auth version 1
203
+ a1 = len1;
204
+ memcpy(a.data() + 2, user.data(), len1);
205
+ a2+len1 = len2;
206
+ memcpy(a.data() + 3 + len1, pass.data(), len2);
207
+ return a;
208
+}
209
+
210
+static QByteArray sps_set_authUsername(bool success)
211
+{
212
+ QByteArray a;
213
+ a.resize(2);
214
+ a0 = 0x01;
215
+ a1 = success ? 0x00 : 0xff;
216
+ return a;
217
+}
218
+
219
+struct SPCS_AUTHUSERNAME
220
+{
221
+ QString user, pass;
222
+};
223
+
224
+static int spc_get_authUsername(QByteArray *from, SPCS_AUTHUSERNAME *s)
225
+{
226
+ if(from->size() < 1)
227
+ return 0;
228
+ unsigned char ver = from->at(0);
229
+ if(ver != 0x01)
230
+ return -1;
231
+ if(from->size() < 2)
232
+ return 0;
233
+ unsigned char ulen = from->at(1);
234
+ if((int)from->size() < ulen + 3)
235
+ return 0;
236
+ unsigned char plen = from->at(ulen+2);
237
+ if((int)from->size() < ulen + plen + 3)
238
+ return 0;
239
+ QByteArray a = ByteStream::takeArray(from, ulen + plen + 3);
240
+
241
+ QByteArray user, pass;
242
+ user.resize(ulen);
243
+ pass.resize(plen);
244
+ memcpy(user.data(), a.data()+2, ulen);
245
+ memcpy(pass.data(), a.data()+ulen+3, plen);
246
+ s->user = QString::fromUtf8(user);
247
+ s->pass = QString::fromUtf8(pass);
248
+ return 1;
249
+}
250
+
251
+struct SPSS_AUTHUSERNAME
252
+{
253
+ unsigned char version;
254
+ bool success;
255
+};
256
+
257
+static int sps_get_authUsername(QByteArray *from, SPSS_AUTHUSERNAME *s)
258
+{
259
+ if(from->size() < 2)
260
+ return 0;
261
+ QByteArray a = ByteStream::takeArray(from, 2);
262
+ s->version = a0;
263
+ s->success = ((char) a1 == 0 ? true: false);
264
+ return 1;
265
+}
266
+
267
+// connectRequest
268
+static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1)
269
+{
270
+ int at = 0;
271
+ QByteArray a;
272
+ a.resize(4);
273
+ aat++ = 0x05; // socks version 5
274
+ aat++ = cmd1;
275
+ aat++ = 0x00; // reserved
276
+ if(addr.protocol() == QAbstractSocket::IPv4Protocol || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
277
+ aat++ = 0x01; // address type = ipv4
278
+ quint32 ip4 = htonl(addr.toIPv4Address());
279
+ a.resize(at+4);
280
+ memcpy(a.data() + at, &ip4, 4);
281
+ at += 4;
282
+ }
283
+ else {
284
+ aat++ = 0x04;
285
+ quint8 a616;
286
+ QStringList s6 = addr.toString().split(':');
287
+ int at = 0;
288
+ quint16 c;
289
+ bool ok;
290
+ for(QStringList::ConstIterator it = s6.begin(); it != s6.end(); ++it) {
291
+ c = (*it).toInt(&ok, 16);
292
+ a6at++ = (c >> 8);
293
+ a6at++ = c & 0xff;
294
+ }
295
+ a.resize(at+16);
296
+ memcpy(a.data() + at, a6, 16);
297
+ at += 16;
298
+ }
299
+
300
+ // port
301
+ a.resize(at+2);
302
+ unsigned short p = htons(port);
303
+ memcpy(a.data() + at, &p, 2);
304
+
305
+ return a;
306
+}
307
+
308
+static QByteArray sp_set_request(const QString &host, quint16 port, unsigned char cmd1)
309
+{
310
+ // detect for IP addresses
311
+ QHostAddress addr;
312
+ if(addr.setAddress(host))
313
+ return sp_set_request(addr, port, cmd1);
314
+
315
+ QByteArray h = host.toUtf8();
316
+ h.truncate(255);
317
+ h = QString::fromUtf8(h).toUtf8(); // delete any partial characters?
318
+ int hlen = h.length();
319
+
320
+ int at = 0;
321
+ QByteArray a;
322
+ a.resize(4);
323
+ aat++ = 0x05; // socks version 5
324
+ aat++ = cmd1;
325
+ aat++ = 0x00; // reserved
326
+ aat++ = 0x03; // address type = domain
327
+
328
+ // host
329
+ a.resize(at+hlen+1);
330
+ aat++ = hlen;
331
+ memcpy(a.data() + at, h.data(), hlen);
332
+ at += hlen;
333
+
334
+ // port
335
+ a.resize(at+2);
336
+ unsigned short p = htons(port);
337
+ memcpy(a.data() + at, &p, 2);
338
+
339
+ return a;
340
+}
341
+
342
+struct SPS_CONNREQ
343
+{
344
+ unsigned char version;
345
+ unsigned char cmd;
346
+ int address_type;
347
+ QString host;
348
+ QHostAddress addr;
349
+ quint16 port;
350
+};
351
+
352
+static int sp_get_request(QByteArray *from, SPS_CONNREQ *s)
353
+{
354
+ int full_len = 4;
355
+ if((int)from->size() < full_len)
356
+ return 0;
357
+
358
+ QString host;
359
+ QHostAddress addr;
360
+ unsigned char atype = from->at(3);
361
+
362
+ if(atype == 0x01) {
363
+ full_len += 4;
364
+ if((int)from->size() < full_len)
365
+ return 0;
366
+ quint32 ip4;
367
+ memcpy(&ip4, from->data() + 4, 4);
368
+ addr.setAddress(ntohl(ip4));
369
+ }
370
+ else if(atype == 0x03) {
371
+ ++full_len;
372
+ if((int)from->size() < full_len)
373
+ return 0;
374
+ unsigned char host_len = from->at(4);
375
+ full_len += host_len;
376
+ if((int)from->size() < full_len)
377
+ return 0;
378
+ QByteArray cs;
379
+ cs.resize(host_len);
380
+ memcpy(cs.data(), from->data() + 5, host_len);
381
+ host = QString::fromLatin1(cs);
382
+ }
383
+ else if(atype == 0x04) {
384
+ full_len += 16;
385
+ if((int)from->size() < full_len)
386
+ return 0;
387
+ quint8 a616;
388
+ memcpy(a6, from->data() + 4, 16);
389
+ addr.setAddress(a6);
390
+ }
391
+
392
+ full_len += 2;
393
+ if((int)from->size() < full_len)
394
+ return 0;
395
+
396
+ QByteArray a = ByteStream::takeArray(from, full_len);
397
+
398
+ quint16 p;
399
+ memcpy(&p, a.data() + full_len - 2, 2);
400
+
401
+ s->version = a0;
402
+ s->cmd = a1;
403
+ s->address_type = atype;
404
+ s->host = host;
405
+ s->addr = addr;
406
+ s->port = ntohs(p);
407
+
408
+ return 1;
409
+}
410
+
411
+enum { StepVersion, StepAuth, StepRequest };
412
+
413
+class SocksClient::Private
414
+{
415
+public:
416
+ Private(SocksClient *_q) :
417
+ sock(_q)
418
+ {
419
+ }
420
+
421
+ BSocket sock;
422
+ QString host;
423
+ int port;
424
+ QString user, pass;
425
+ QString real_host;
426
+ int real_port;
427
+
428
+ QByteArray recvBuf;
429
+ bool active;
430
+ int step;
431
+ int authMethod;
432
+ bool incoming, waiting;
433
+
434
+ QString rhost;
435
+ int rport;
436
+
437
+ int pending;
438
+
439
+ bool udp;
440
+ QString udpAddr;
441
+ int udpPort;
442
+};
443
+
444
+SocksClient::SocksClient(QObject *parent)
445
+:ByteStream(parent)
446
+{
447
+ init();
448
+
449
+ d->incoming = false;
450
+}
451
+
452
+SocksClient::SocksClient(int s, QObject *parent)
453
+:ByteStream(parent)
454
+{
455
+ init();
456
+
457
+ d->incoming = true;
458
+ d->waiting = true;
459
+ d->sock.setSocket(s);
460
+}
461
+
462
+void SocksClient::init()
463
+{
464
+ d = new Private(this);
465
+ connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected()));
466
+ connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
467
+ connect(&d->sock, SIGNAL(delayedCloseFinished()), SLOT(sock_delayedCloseFinished()));
468
+ connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
469
+ connect(&d->sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
470
+ connect(&d->sock, SIGNAL(error(int)), SLOT(sock_error(int)));
471
+
472
+ reset(true);
473
+}
474
+
475
+SocksClient::~SocksClient()
476
+{
477
+ reset(true);
478
+ delete d;
479
+}
480
+
481
+void SocksClient::reset(bool clear)
482
+{
483
+ if(d->sock.state() != BSocket::Idle)
484
+ d->sock.close();
485
+ if(clear)
486
+ clearReadBuffer();
487
+ d->recvBuf.resize(0);
488
+ d->active = false;
489
+ d->waiting = false;
490
+ d->udp = false;
491
+ d->pending = 0;
492
+}
493
+
494
+bool SocksClient::isIncoming() const
495
+{
496
+ return d->incoming;
497
+}
498
+
499
+void SocksClient::setAuth(const QString &user, const QString &pass)
500
+{
501
+ d->user = user;
502
+ d->pass = pass;
503
+}
504
+
505
+void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode)
506
+{
507
+ reset(true);
508
+
509
+ d->host = proxyHost;
510
+ d->port = proxyPort;
511
+ d->real_host = host;
512
+ d->real_port = port;
513
+ d->udp = udpMode;
514
+
515
+#ifdef PROX_DEBUG
516
+ fprintf(stderr, "SocksClient: Connecting to %s:%d", qPrintable(proxyHost), proxyPort);
517
+ if(d->user.isEmpty())
518
+ fprintf(stderr, "\n");
519
+ else
520
+ fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass));
521
+#endif
522
+ d->sock.connectToHost(d->host, d->port);
523
+}
524
+
525
+bool SocksClient::isOpen() const
526
+{
527
+ return d->active;
528
+}
529
+
530
+void SocksClient::close()
531
+{
532
+ d->sock.close();
533
+ if(d->sock.bytesToWrite() == 0)
534
+ reset();
535
+}
536
+
537
+void SocksClient::writeData(const QByteArray &buf)
538
+{
539
+#ifdef PROX_DEBUG
540
+ // show hex
541
+ fprintf(stderr, "SocksClient: client write { ");
542
+ for(int n = 0; n < (int)buf.size(); ++n)
543
+ fprintf(stderr, "%02X ", (unsigned char)bufn);
544
+ fprintf(stderr, " } \n");
545
+#endif
546
+ d->pending += buf.size();
547
+ d->sock.write(buf);
548
+}
549
+
550
+void SocksClient::write(const QByteArray &buf)
551
+{
552
+ if(d->active && !d->udp)
553
+ d->sock.write(buf);
554
+}
555
+
556
+QByteArray SocksClient::read(int bytes)
557
+{
558
+ return ByteStream::read(bytes);
559
+}
560
+
561
+int SocksClient::bytesAvailable() const
562
+{
563
+ return ByteStream::bytesAvailable();
564
+}
565
+
566
+int SocksClient::bytesToWrite() const
567
+{
568
+ if(d->active)
569
+ return d->sock.bytesToWrite();
570
+ else
571
+ return 0;
572
+}
573
+
574
+void SocksClient::sock_connected()
575
+{
576
+#ifdef PROX_DEBUG
577
+ fprintf(stderr, "SocksClient: Connected\n");
578
+#endif
579
+
580
+ d->step = StepVersion;
581
+ writeData(spc_set_version());
582
+}
583
+
584
+void SocksClient::sock_connectionClosed()
585
+{
586
+ if(d->active) {
587
+ reset();
588
+ connectionClosed();
589
+ }
590
+ else {
591
+ error(ErrProxyNeg);
592
+ }
593
+}
594
+
595
+void SocksClient::sock_delayedCloseFinished()
596
+{
597
+ if(d->active) {
598
+ reset();
599
+ delayedCloseFinished();
600
+ }
601
+}
602
+
603
+void SocksClient::sock_readyRead()
604
+{
605
+ QByteArray block = d->sock.read();
606
+
607
+ if(!d->active) {
608
+ if(d->incoming)
609
+ processIncoming(block);
610
+ else
611
+ processOutgoing(block);
612
+ }
613
+ else {
614
+ if(!d->udp) {
615
+ appendRead(block);
616
+ readyRead();
617
+ }
618
+ }
619
+}
620
+
621
+void SocksClient::processOutgoing(const QByteArray &block)
622
+{
623
+#ifdef PROX_DEBUG
624
+ // show hex
625
+ fprintf(stderr, "SocksClient: client recv { ");
626
+ for(int n = 0; n < (int)block.size(); ++n)
627
+ fprintf(stderr, "%02X ", (unsigned char)blockn);
628
+ fprintf(stderr, " } \n");
629
+#endif
630
+ ByteStream::appendArray(&d->recvBuf, block);
631
+
632
+ if(d->step == StepVersion) {
633
+ SPSS_VERSION s;
634
+ int r = sps_get_version(&d->recvBuf, &s);
635
+ if(r == -1) {
636
+ reset(true);
637
+ error(ErrProxyNeg);
638
+ return;
639
+ }
640
+ else if(r == 1) {
641
+ if(s.version != 0x05 || s.method == 0xff) {
642
+#ifdef PROX_DEBUG
643
+ fprintf(stderr, "SocksClient: Method selection failed\n");
644
+#endif
645
+ reset(true);
646
+ error(ErrProxyNeg);
647
+ return;
648
+ }
649
+
650
+ QString str;
651
+ if(s.method == 0x00) {
652
+ str = "None";
653
+ d->authMethod = AuthNone;
654
+ }
655
+ else if(s.method == 0x02) {
656
+ str = "Username/Password";
657
+ d->authMethod = AuthUsername;
658
+ }
659
+ else {
660
+#ifdef PROX_DEBUG
661
+ fprintf(stderr, "SocksClient: Server wants to use unknown method '%02x'\n", s.method);
662
+#endif
663
+ reset(true);
664
+ error(ErrProxyNeg);
665
+ return;
666
+ }
667
+
668
+ if(d->authMethod == AuthNone) {
669
+ // no auth, go straight to the request
670
+ do_request();
671
+ }
672
+ else if(d->authMethod == AuthUsername) {
673
+ d->step = StepAuth;
674
+#ifdef PROX_DEBUG
675
+ fprintf(stderr, "SocksClient: Authenticating Username ...\n");
676
+#endif
677
+ writeData(spc_set_authUsername(d->user.toLatin1(), d->pass.toLatin1()));
678
+ }
679
+ }
680
+ }
681
+ if(d->step == StepAuth) {
682
+ if(d->authMethod == AuthUsername) {
683
+ SPSS_AUTHUSERNAME s;
684
+ int r = sps_get_authUsername(&d->recvBuf, &s);
685
+ if(r == -1) {
686
+ reset(true);
687
+ error(ErrProxyNeg);
688
+ return;
689
+ }
690
+ else if(r == 1) {
691
+ if(s.version != 0x01) {
692
+ reset(true);
693
+ error(ErrProxyNeg);
694
+ return;
695
+ }
696
+ if(!s.success) {
697
+ reset(true);
698
+ error(ErrProxyAuth);
699
+ return;
700
+ }
701
+
702
+ do_request();
703
+ }
704
+ }
705
+ }
706
+ else if(d->step == StepRequest) {
707
+ SPS_CONNREQ s;
708
+ int r = sp_get_request(&d->recvBuf, &s);
709
+ if(r == -1) {
710
+ reset(true);
711
+ error(ErrProxyNeg);
712
+ return;
713
+ }
714
+ else if(r == 1) {
715
+ if(s.cmd != RET_SUCCESS) {
716
+#ifdef PROX_DEBUG
717
+ fprintf(stderr, "SocksClient: client << Error >> %02x\n", s.cmd);
718
+#endif
719
+ reset(true);
720
+ if(s.cmd == RET_UNREACHABLE)
721
+ error(ErrHostNotFound);
722
+ else if(s.cmd == RET_CONNREFUSED)
723
+ error(ErrConnectionRefused);
724
+ else
725
+ error(ErrProxyNeg);
726
+ return;
727
+ }
728
+
729
+#ifdef PROX_DEBUG
730
+ fprintf(stderr, "SocksClient: client << Success >>\n");
731
+#endif
732
+ if(d->udp) {
733
+ if(s.address_type == 0x03)
734
+ d->udpAddr = s.host;
735
+ else
736
+ d->udpAddr = s.addr.toString();
737
+ d->udpPort = s.port;
738
+ }
739
+
740
+ d->active = true;
741
+
742
+ QPointer<QObject> self = this;
743
+ connected();
744
+ if(!self)
745
+ return;
746
+
747
+ if(!d->recvBuf.isEmpty()) {
748
+ appendRead(d->recvBuf);
749
+ d->recvBuf.resize(0);
750
+ readyRead();
751
+ }
752
+ }
753
+ }
754
+}
755
+
756
+void SocksClient::do_request()
757
+{
758
+#ifdef PROX_DEBUG
759
+ fprintf(stderr, "SocksClient: Requesting ...\n");
760
+#endif
761
+ d->step = StepRequest;
762
+ int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT;
763
+ QByteArray buf;
764
+ if(!d->real_host.isEmpty())
765
+ buf = sp_set_request(d->real_host, d->real_port, cmd);
766
+ else
767
+ buf = sp_set_request(QHostAddress(), 0, cmd);
768
+ writeData(buf);
769
+}
770
+
771
+void SocksClient::sock_bytesWritten(int x)
772
+{
773
+ int bytes = x;
774
+ if(d->pending >= bytes) {
775
+ d->pending -= bytes;
776
+ bytes = 0;
777
+ }
778
+ else {
779
+ bytes -= d->pending;
780
+ d->pending = 0;
781
+ }
782
+ if(bytes > 0)
783
+ bytesWritten(bytes);
784
+}
785
+
786
+void SocksClient::sock_error(int x)
787
+{
788
+ if(d->active) {
789
+ reset();
790
+ error(ErrRead);
791
+ }
792
+ else {
793
+ reset(true);
794
+ if(x == BSocket::ErrHostNotFound)
795
+ error(ErrProxyConnect);
796
+ else if(x == BSocket::ErrConnectionRefused)
797
+ error(ErrProxyConnect);
798
+ else if(x == BSocket::ErrRead)
799
+ error(ErrProxyNeg);
800
+ }
801
+}
802
+
803
+void SocksClient::serve()
804
+{
805
+ d->waiting = false;
806
+ d->step = StepVersion;
807
+ continueIncoming();
808
+}
809
+
810
+void SocksClient::processIncoming(const QByteArray &block)
811
+{
812
+#ifdef PROX_DEBUG
813
+ // show hex
814
+ fprintf(stderr, "SocksClient: server recv { ");
815
+ for(int n = 0; n < (int)block.size(); ++n)
816
+ fprintf(stderr, "%02X ", (unsigned char)blockn);
817
+ fprintf(stderr, " } \n");
818
+#endif
819
+ ByteStream::appendArray(&d->recvBuf, block);
820
+
821
+ if(!d->waiting)
822
+ continueIncoming();
823
+}
824
+
825
+void SocksClient::continueIncoming()
826
+{
827
+ if(d->recvBuf.isEmpty())
828
+ return;
829
+
830
+ if(d->step == StepVersion) {
831
+ SPCS_VERSION s;
832
+ int r = spc_get_version(&d->recvBuf, &s);
833
+ if(r == -1) {
834
+ reset(true);
835
+ error(ErrProxyNeg);
836
+ return;
837
+ }
838
+ else if(r == 1) {
839
+ if(s.version != 0x05) {
840
+ reset(true);
841
+ error(ErrProxyNeg);
842
+ return;
843
+ }
844
+
845
+ int methods = 0;
846
+ for(int n = 0; n < (int)s.methodList.size(); ++n) {
847
+ unsigned char c = s.methodListn;
848
+ if(c == 0x00)
849
+ methods |= AuthNone;
850
+ else if(c == 0x02)
851
+ methods |= AuthUsername;
852
+ }
853
+ d->waiting = true;
854
+ incomingMethods(methods);
855
+ }
856
+ }
857
+ else if(d->step == StepAuth) {
858
+ SPCS_AUTHUSERNAME s;
859
+ int r = spc_get_authUsername(&d->recvBuf, &s);
860
+ if(r == -1) {
861
+ reset(true);
862
+ error(ErrProxyNeg);
863
+ return;
864
+ }
865
+ else if(r == 1) {
866
+ d->waiting = true;
867
+ incomingAuth(s.user, s.pass);
868
+ }
869
+ }
870
+ else if(d->step == StepRequest) {
871
+ SPS_CONNREQ s;
872
+ int r = sp_get_request(&d->recvBuf, &s);
873
+ if(r == -1) {
874
+ reset(true);
875
+ error(ErrProxyNeg);
876
+ return;
877
+ }
878
+ else if(r == 1) {
879
+ d->waiting = true;
880
+ if(s.cmd == REQ_CONNECT) {
881
+ if(!s.host.isEmpty())
882
+ d->rhost = s.host;
883
+ else
884
+ d->rhost = s.addr.toString();
885
+ d->rport = s.port;
886
+ incomingConnectRequest(d->rhost, d->rport);
887
+ }
888
+ else if(s.cmd == REQ_UDPASSOCIATE) {
889
+ incomingUDPAssociateRequest();
890
+ }
891
+ else {
892
+ requestDeny();
893
+ return;
894
+ }
895
+ }
896
+ }
897
+}
898
+
899
+void SocksClient::chooseMethod(int method)
900
+{
901
+ if(d->step != StepVersion || !d->waiting)
902
+ return;
903
+
904
+ unsigned char c;
905
+ if(method == AuthNone) {
906
+ d->step = StepRequest;
907
+ c = 0x00;
908
+ }
909
+ else {
910
+ d->step = StepAuth;
911
+ c = 0x02;
912
+ }
913
+
914
+ // version response
915
+ d->waiting = false;
916
+ writeData(sps_set_version(c));
917
+ continueIncoming();
918
+}
919
+
920
+void SocksClient::authGrant(bool b)
921
+{
922
+ if(d->step != StepAuth || !d->waiting)
923
+ return;
924
+
925
+ if(b)
926
+ d->step = StepRequest;
927
+
928
+ // auth response
929
+ d->waiting = false;
930
+ writeData(sps_set_authUsername(b));
931
+ if(!b) {
932
+ reset(true);
933
+ return;
934
+ }
935
+ continueIncoming();
936
+}
937
+
938
+void SocksClient::requestDeny()
939
+{
940
+ if(d->step != StepRequest || !d->waiting)
941
+ return;
942
+
943
+ // response
944
+ d->waiting = false;
945
+ writeData(sp_set_request(d->rhost, d->rport, RET_UNREACHABLE));
946
+ reset(true);
947
+}
948
+
949
+void SocksClient::grantConnect()
950
+{
951
+ if(d->step != StepRequest || !d->waiting)
952
+ return;
953
+
954
+ // response
955
+ d->waiting = false;
956
+ writeData(sp_set_request(d->rhost, d->rport, RET_SUCCESS));
957
+ d->active = true;
958
+#ifdef PROX_DEBUG
959
+ fprintf(stderr, "SocksClient: server << Success >>\n");
960
+#endif
961
+
962
+ if(!d->recvBuf.isEmpty()) {
963
+ appendRead(d->recvBuf);
964
+ d->recvBuf.resize(0);
965
+ readyRead();
966
+ }
967
+}
968
+
969
+void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort)
970
+{
971
+ if(d->step != StepRequest || !d->waiting)
972
+ return;
973
+
974
+ // response
975
+ d->waiting = false;
976
+ writeData(sp_set_request(relayHost, relayPort, RET_SUCCESS));
977
+ d->udp = true;
978
+ d->active = true;
979
+#ifdef PROX_DEBUG
980
+ fprintf(stderr, "SocksClient: server << Success >>\n");
981
+#endif
982
+
983
+ if(!d->recvBuf.isEmpty())
984
+ d->recvBuf.resize(0);
985
+}
986
+
987
+QHostAddress SocksClient::peerAddress() const
988
+{
989
+ return d->sock.peerAddress();
990
+}
991
+
992
+quint16 SocksClient::peerPort() const
993
+{
994
+ return d->sock.peerPort();
995
+}
996
+
997
+QString SocksClient::udpAddress() const
998
+{
999
+ return d->udpAddr;
1000
+}
1001
+
1002
+quint16 SocksClient::udpPort() const
1003
+{
1004
+ return d->udpPort;
1005
+}
1006
+
1007
+SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort)
1008
+{
1009
+ return new SocksUDP(this, host, port, routeAddr, routePort);
1010
+}
1011
+
1012
+//----------------------------------------------------------------------------
1013
+// SocksServer
1014
+//----------------------------------------------------------------------------
1015
+class SocksServer::Private
1016
+{
1017
+public:
1018
+ Private(SocksServer *_q) :
1019
+ serv(_q)
1020
+ {
1021
+ }
1022
+
1023
+ ServSock serv;
1024
+ QList<SocksClient*> incomingConns;
1025
+ QUdpSocket *sd;
1026
+};
1027
+
1028
+SocksServer::SocksServer(QObject *parent)
1029
+:QObject(parent)
1030
+{
1031
+ d = new Private(this);
1032
+ d->sd = 0;
1033
+ connect(&d->serv, SIGNAL(connectionReady(int)), SLOT(connectionReady(int)));
1034
+}
1035
+
1036
+SocksServer::~SocksServer()
1037
+{
1038
+ stop();
1039
+ while (d->incomingConns.count()) {
1040
+ delete d->incomingConns.takeFirst();
1041
+ }
1042
+ delete d;
1043
+}
1044
+
1045
+bool SocksServer::isActive() const
1046
+{
1047
+ return d->serv.isActive();
1048
+}
1049
+
1050
+bool SocksServer::listen(quint16 port, bool udp)
1051
+{
1052
+ stop();
1053
+ if(!d->serv.listen(port))
1054
+ return false;
1055
+ if(udp) {
1056
+ d->sd = new QUdpSocket(this);
1057
+ if(!d->sd->bind(QHostAddress::LocalHost, port)) {
1058
+ delete d->sd;
1059
+ d->sd = 0;
1060
+ d->serv.stop();
1061
+ return false;
1062
+ }
1063
+ connect(d->sd, SIGNAL(readyRead()), SLOT(sd_activated()));
1064
+ }
1065
+ return true;
1066
+}
1067
+
1068
+void SocksServer::stop()
1069
+{
1070
+ delete d->sd;
1071
+ d->sd = 0;
1072
+ d->serv.stop();
1073
+}
1074
+
1075
+int SocksServer::port() const
1076
+{
1077
+ return d->serv.port();
1078
+}
1079
+
1080
+QHostAddress SocksServer::address() const
1081
+{
1082
+ return d->serv.address();
1083
+}
1084
+
1085
+SocksClient *SocksServer::takeIncoming()
1086
+{
1087
+ if(d->incomingConns.isEmpty())
1088
+ return 0;
1089
+
1090
+ SocksClient *c = d->incomingConns.takeFirst();
1091
+
1092
+ // we don't care about errors anymore
1093
+ disconnect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
1094
+
1095
+ // don't serve the connection until the event loop, to give the caller a chance to map signals
1096
+ QTimer::singleShot(0, c, SLOT(serve()));
1097
+
1098
+ return c;
1099
+}
1100
+
1101
+void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data)
1102
+{
1103
+ if(d->sd) {
1104
+ d->sd->writeDatagram(data.data(), data.size(), addr, port);
1105
+ }
1106
+}
1107
+
1108
+void SocksServer::connectionReady(int s)
1109
+{
1110
+ SocksClient *c = new SocksClient(s, this);
1111
+ connect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
1112
+ d->incomingConns.append(c);
1113
+ incomingReady();
1114
+}
1115
+
1116
+void SocksServer::connectionError()
1117
+{
1118
+ SocksClient *c = (SocksClient *)sender();
1119
+ d->incomingConns.removeAll(c);
1120
+ c->deleteLater();
1121
+}
1122
+
1123
+void SocksServer::sd_activated()
1124
+{
1125
+ while (d->sd->hasPendingDatagrams()) {
1126
+ QByteArray datagram;
1127
+ QHostAddress sender;
1128
+ quint16 senderPort;
1129
+ datagram.resize(d->sd->pendingDatagramSize());
1130
+ d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
1131
+ incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram);
1132
+ }
1133
+}
1134
+
1135
+// CS_NAMESPACE_END
1136
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/socks.h
Added
162
1
2
+/*
3
+ * socks.h - SOCKS5 TCP proxy client/server
4
+ * Copyright (C) 2003 Justin Karneges
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ *
20
+ */
21
+
22
+#ifndef CS_SOCKS_H
23
+#define CS_SOCKS_H
24
+
25
+#include "bytestream.h"
26
+
27
+// CS_NAMESPACE_BEGIN
28
+
29
+class QHostAddress;
30
+class SocksClient;
31
+class SocksServer;
32
+
33
+class SocksUDP : public QObject
34
+{
35
+ Q_OBJECT
36
+public:
37
+ ~SocksUDP();
38
+
39
+ void change(const QString &host, int port);
40
+ void write(const QByteArray &data);
41
+
42
+signals:
43
+ void packetReady(const QByteArray &data);
44
+
45
+private slots:
46
+ void sd_activated();
47
+
48
+private:
49
+ class Private;
50
+ Private *d;
51
+
52
+ friend class SocksClient;
53
+ SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort);
54
+};
55
+
56
+class SocksClient : public ByteStream
57
+{
58
+ Q_OBJECT
59
+public:
60
+ enum Error { ErrConnectionRefused = ErrCustom, ErrHostNotFound, ErrProxyConnect, ErrProxyNeg, ErrProxyAuth };
61
+ enum Method { AuthNone=0x0001, AuthUsername=0x0002 };
62
+ enum Request { ReqConnect, ReqUDPAssociate };
63
+ SocksClient(QObject *parent=0);
64
+ SocksClient(int, QObject *parent=0);
65
+ ~SocksClient();
66
+
67
+ bool isIncoming() const;
68
+
69
+ // outgoing
70
+ void setAuth(const QString &user, const QString &pass="");
71
+ void connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode=false);
72
+
73
+ // incoming
74
+ void chooseMethod(int);
75
+ void authGrant(bool);
76
+ void requestDeny();
77
+ void grantConnect();
78
+ void grantUDPAssociate(const QString &relayHost, int relayPort);
79
+
80
+ // from ByteStream
81
+ bool isOpen() const;
82
+ void close();
83
+ void write(const QByteArray &);
84
+ QByteArray read(int bytes=0);
85
+ int bytesAvailable() const;
86
+ int bytesToWrite() const;
87
+
88
+ // remote address
89
+ QHostAddress peerAddress() const;
90
+ quint16 peerPort() const;
91
+
92
+ // udp
93
+ QString udpAddress() const;
94
+ quint16 udpPort() const;
95
+ SocksUDP *createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort);
96
+
97
+signals:
98
+ // outgoing
99
+ void connected();
100
+
101
+ // incoming
102
+ void incomingMethods(int);
103
+ void incomingAuth(const QString &user, const QString &pass);
104
+ void incomingConnectRequest(const QString &host, int port);
105
+ void incomingUDPAssociateRequest();
106
+
107
+private slots:
108
+ void sock_connected();
109
+ void sock_connectionClosed();
110
+ void sock_delayedCloseFinished();
111
+ void sock_readyRead();
112
+ void sock_bytesWritten(int);
113
+ void sock_error(int);
114
+ void serve();
115
+
116
+private:
117
+ class Private;
118
+ Private *d;
119
+
120
+ void init();
121
+ void reset(bool clear=false);
122
+ void do_request();
123
+ void processOutgoing(const QByteArray &);
124
+ void processIncoming(const QByteArray &);
125
+ void continueIncoming();
126
+ void writeData(const QByteArray &a);
127
+};
128
+
129
+class SocksServer : public QObject
130
+{
131
+ Q_OBJECT
132
+public:
133
+ SocksServer(QObject *parent=0);
134
+ ~SocksServer();
135
+
136
+ bool isActive() const;
137
+ bool listen(quint16 port, bool udp=false);
138
+ void stop();
139
+ int port() const;
140
+ QHostAddress address() const;
141
+ SocksClient *takeIncoming();
142
+
143
+ void writeUDP(const QHostAddress &addr, int port, const QByteArray &data);
144
+
145
+signals:
146
+ void incomingReady();
147
+ void incomingUDP(const QString &host, int port, const QHostAddress &addr, int sourcePort, const QByteArray &data);
148
+
149
+private slots:
150
+ void connectionReady(int);
151
+ void connectionError();
152
+ void sd_activated();
153
+
154
+private:
155
+ class Private;
156
+ Private *d;
157
+};
158
+
159
+// CS_NAMESPACE_END
160
+
161
+#endif
162
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunallocate.cpp
Added
1457
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stunallocate.h"
23
+
24
+#include <QMetaType>
25
+#include <QHostAddress>
26
+#include <QTimer>
27
+#include <QtCrypto>
28
+#include "objectsession.h"
29
+#include "stunutil.h"
30
+#include "stunmessage.h"
31
+#include "stuntypes.h"
32
+#include "stuntransaction.h"
33
+
34
+// permissions last 5 minutes, update them every 4 minutes
35
+#define PERM_INTERVAL (4 * 60 * 1000)
36
+
37
+// channels last 10 minutes, update them every 9 minutes
38
+#define CHAN_INTERVAL (9 * 60 * 1000)
39
+
40
+namespace XMPP {
41
+
42
+void releaseAndDeleteLater(QObject *owner, QObject *obj)
43
+{
44
+ obj->disconnect(owner);
45
+ obj->setParent(0);
46
+ obj->deleteLater();
47
+}
48
+
49
+// return size of channelData packet, or -1
50
+static int check_channelData(const quint8 *data, int size)
51
+{
52
+ // top two bits are never zero for ChannelData
53
+ if((data0 & 0xc0) == 0)
54
+ return -1;
55
+
56
+ if(size < 4)
57
+ return -1;
58
+
59
+ quint16 len = StunUtil::read16(data + 2);
60
+ if(size - 4 < (int)len)
61
+ return -1;
62
+
63
+ // data from a stream must be 4 byte aligned
64
+ int plen = len;
65
+ int remainder = plen % 4;
66
+ if(remainder != 0)
67
+ plen += (4 - remainder);
68
+
69
+ int need = plen + 4;
70
+ if(size < need)
71
+ return -1;
72
+
73
+ return need;
74
+}
75
+
76
+class StunAllocatePermission : public QObject
77
+{
78
+ Q_OBJECT
79
+
80
+public:
81
+ QTimer *timer;
82
+ StunTransactionPool *pool;
83
+ StunTransaction *trans;
84
+ QHostAddress stunAddr;
85
+ int stunPort;
86
+ QHostAddress addr;
87
+ bool active;
88
+
89
+ enum Error
90
+ {
91
+ ErrorGeneric,
92
+ ErrorProtocol,
93
+ ErrorCapacity,
94
+ ErrorForbidden,
95
+ ErrorRejected,
96
+ ErrorTimeout
97
+ };
98
+
99
+ StunAllocatePermission(StunTransactionPool *_pool, const QHostAddress &_addr) :
100
+ QObject(_pool),
101
+ pool(_pool),
102
+ trans(0),
103
+ addr(_addr),
104
+ active(false)
105
+ {
106
+ timer = new QTimer(this);
107
+ connect(timer, SIGNAL(timeout()), SLOT(timer_timeout()));
108
+ timer->setSingleShot(true);
109
+ timer->setInterval(PERM_INTERVAL);
110
+ }
111
+
112
+ ~StunAllocatePermission()
113
+ {
114
+ cleanup();
115
+
116
+ releaseAndDeleteLater(this, timer);
117
+ }
118
+
119
+ void start(const QHostAddress &_addr, int _port)
120
+ {
121
+ Q_ASSERT(!active);
122
+
123
+ stunAddr = _addr;
124
+ stunPort = _port;
125
+
126
+ doTransaction();
127
+ }
128
+
129
+ static StunAllocate::Error errorToStunAllocateError(Error e)
130
+ {
131
+ switch(e)
132
+ {
133
+ case ErrorProtocol:
134
+ return StunAllocate::ErrorProtocol;
135
+ case ErrorCapacity:
136
+ return StunAllocate::ErrorCapacity;
137
+ case ErrorForbidden:
138
+ case ErrorRejected:
139
+ return StunAllocate::ErrorRejected;
140
+ case ErrorTimeout:
141
+ return StunAllocate::ErrorTimeout;
142
+ default:
143
+ return StunAllocate::ErrorGeneric;
144
+ }
145
+ }
146
+
147
+signals:
148
+ void ready();
149
+ void error(XMPP::StunAllocatePermission::Error e, const QString &reason);
150
+
151
+private:
152
+ void cleanup()
153
+ {
154
+ delete trans;
155
+ trans = 0;
156
+
157
+ timer->stop();
158
+
159
+ active = false;
160
+ }
161
+
162
+ void doTransaction()
163
+ {
164
+ Q_ASSERT(!trans);
165
+ trans = new StunTransaction(this);
166
+ connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
167
+ connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
168
+ connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
169
+ trans->start(pool, stunAddr, stunPort);
170
+ }
171
+
172
+ void restartTimer()
173
+ {
174
+ timer->start();
175
+ }
176
+
177
+private slots:
178
+ void trans_createMessage(const QByteArray &transactionId)
179
+ {
180
+ // CreatePermission
181
+ StunMessage message;
182
+ message.setMethod(StunTypes::CreatePermission);
183
+ message.setId((const quint8 *)transactionId.data());
184
+
185
+ QList<StunMessage::Attribute> list;
186
+
187
+ // we only do one address per permission request, because
188
+ // otherwise if we receive an error it would be ambiguous
189
+ // as to which address the error applies to
190
+
191
+ {
192
+ StunMessage::Attribute a;
193
+ a.type = StunTypes::XOR_PEER_ADDRESS;
194
+ a.value = StunTypes::createXorPeerAddress(addr, 0, message.magic(), message.id());
195
+ list += a;
196
+ }
197
+
198
+ message.setAttributes(list);
199
+
200
+ trans->setMessage(message);
201
+ }
202
+
203
+ void trans_finished(const XMPP::StunMessage &response)
204
+ {
205
+ delete trans;
206
+ trans = 0;
207
+
208
+ bool err = false;
209
+ int code;
210
+ QString reason;
211
+ if(response.mclass() == StunMessage::ErrorResponse)
212
+ {
213
+ if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason))
214
+ {
215
+ cleanup();
216
+ emit error(ErrorProtocol, "Unable to parse ERROR-CODE in error response.");
217
+ return;
218
+ }
219
+
220
+ err = true;
221
+ }
222
+
223
+ if(err)
224
+ {
225
+ cleanup();
226
+
227
+ if(code == StunTypes::InsufficientCapacity)
228
+ emit error(ErrorCapacity, reason);
229
+ else if(code == StunTypes::Forbidden)
230
+ emit error(ErrorForbidden, reason);
231
+ else
232
+ emit error(ErrorRejected, reason);
233
+
234
+ return;
235
+ }
236
+
237
+ restartTimer();
238
+
239
+ if(!active)
240
+ {
241
+ active = true;
242
+ emit ready();
243
+ }
244
+ }
245
+
246
+ void trans_error(XMPP::StunTransaction::Error e)
247
+ {
248
+ cleanup();
249
+
250
+ if(e == XMPP::StunTransaction::ErrorTimeout)
251
+ emit error(ErrorTimeout, "Request timed out.");
252
+ else
253
+ emit error(ErrorGeneric, "Generic transaction error.");
254
+ }
255
+
256
+ void timer_timeout()
257
+ {
258
+ doTransaction();
259
+ }
260
+};
261
+
262
+class StunAllocateChannel : public QObject
263
+{
264
+ Q_OBJECT
265
+
266
+public:
267
+ QTimer *timer;
268
+ StunTransactionPool *pool;
269
+ StunTransaction *trans;
270
+ QHostAddress stunAddr;
271
+ int stunPort;
272
+ int channelId;
273
+ QHostAddress addr;
274
+ int port;
275
+ bool active;
276
+
277
+ enum Error
278
+ {
279
+ ErrorGeneric,
280
+ ErrorProtocol,
281
+ ErrorCapacity,
282
+ ErrorForbidden,
283
+ ErrorRejected,
284
+ ErrorTimeout
285
+ };
286
+
287
+ StunAllocateChannel(StunTransactionPool *_pool, int _channelId, const QHostAddress &_addr, int _port) :
288
+ QObject(_pool),
289
+ pool(_pool),
290
+ trans(0),
291
+ channelId(_channelId),
292
+ addr(_addr),
293
+ port(_port),
294
+ active(false)
295
+ {
296
+ timer = new QTimer(this);
297
+ connect(timer, SIGNAL(timeout()), SLOT(timer_timeout()));
298
+ timer->setSingleShot(true);
299
+ timer->setInterval(CHAN_INTERVAL);
300
+ }
301
+
302
+ ~StunAllocateChannel()
303
+ {
304
+ cleanup();
305
+
306
+ releaseAndDeleteLater(this, timer);
307
+ }
308
+
309
+ void start(const QHostAddress &_addr, int _port)
310
+ {
311
+ Q_ASSERT(!active);
312
+
313
+ stunAddr = _addr;
314
+ stunPort = _port;
315
+
316
+ doTransaction();
317
+ }
318
+
319
+ static StunAllocate::Error errorToStunAllocateError(Error e)
320
+ {
321
+ switch(e)
322
+ {
323
+ case ErrorProtocol:
324
+ return StunAllocate::ErrorProtocol;
325
+ case ErrorCapacity:
326
+ return StunAllocate::ErrorCapacity;
327
+ case ErrorForbidden:
328
+ case ErrorRejected:
329
+ return StunAllocate::ErrorRejected;
330
+ case ErrorTimeout:
331
+ return StunAllocate::ErrorTimeout;
332
+ default:
333
+ return StunAllocate::ErrorGeneric;
334
+ }
335
+ }
336
+
337
+signals:
338
+ void ready();
339
+ void error(XMPP::StunAllocateChannel::Error e, const QString &reason);
340
+
341
+private:
342
+ void cleanup()
343
+ {
344
+ delete trans;
345
+ trans = 0;
346
+
347
+ timer->stop();
348
+
349
+ channelId = -1;
350
+ active = false;
351
+ }
352
+
353
+ void doTransaction()
354
+ {
355
+ Q_ASSERT(!trans);
356
+ trans = new StunTransaction(this);
357
+ connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
358
+ connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
359
+ connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
360
+ trans->start(pool, stunAddr, stunPort);
361
+ }
362
+
363
+ void restartTimer()
364
+ {
365
+ timer->start();
366
+ }
367
+
368
+private slots:
369
+ void trans_createMessage(const QByteArray &transactionId)
370
+ {
371
+ // ChannelBind
372
+ StunMessage message;
373
+ message.setMethod(StunTypes::ChannelBind);
374
+ message.setId((const quint8 *)transactionId.data());
375
+
376
+ QList<StunMessage::Attribute> list;
377
+
378
+ {
379
+ StunMessage::Attribute a;
380
+ a.type = StunTypes::CHANNEL_NUMBER;
381
+ a.value = StunTypes::createChannelNumber(channelId);
382
+ list += a;
383
+ }
384
+
385
+ {
386
+ StunMessage::Attribute a;
387
+ a.type = StunTypes::XOR_PEER_ADDRESS;
388
+ a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id());
389
+ list += a;
390
+ }
391
+
392
+ message.setAttributes(list);
393
+
394
+ trans->setMessage(message);
395
+ }
396
+
397
+ void trans_finished(const XMPP::StunMessage &response)
398
+ {
399
+ delete trans;
400
+ trans = 0;
401
+
402
+ bool err = false;
403
+ int code;
404
+ QString reason;
405
+ if(response.mclass() == StunMessage::ErrorResponse)
406
+ {
407
+ if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason))
408
+ {
409
+ cleanup();
410
+ emit error(ErrorProtocol, "Unable to parse ERROR-CODE in error response.");
411
+ return;
412
+ }
413
+
414
+ err = true;
415
+ }
416
+
417
+ if(err)
418
+ {
419
+ cleanup();
420
+
421
+ if(code == StunTypes::InsufficientCapacity)
422
+ emit error(ErrorCapacity, reason);
423
+ else if(code == StunTypes::Forbidden)
424
+ emit error(ErrorForbidden, reason);
425
+ else
426
+ emit error(ErrorRejected, reason);
427
+
428
+ return;
429
+ }
430
+
431
+ restartTimer();
432
+
433
+ if(!active)
434
+ {
435
+ active = true;
436
+ emit ready();
437
+ }
438
+ }
439
+
440
+ void trans_error(XMPP::StunTransaction::Error e)
441
+ {
442
+ cleanup();
443
+
444
+ if(e == XMPP::StunTransaction::ErrorTimeout)
445
+ emit error(ErrorTimeout, "Request timed out.");
446
+ else
447
+ emit error(ErrorGeneric, "Generic transaction error.");
448
+ }
449
+
450
+ void timer_timeout()
451
+ {
452
+ doTransaction();
453
+ }
454
+};
455
+
456
+class StunAllocate::Private : public QObject
457
+{
458
+ Q_OBJECT
459
+
460
+public:
461
+ enum DontFragmentState
462
+ {
463
+ DF_Unknown,
464
+ DF_Supported,
465
+ DF_Unsupported
466
+ };
467
+
468
+ enum State
469
+ {
470
+ Stopped,
471
+ Starting,
472
+ Started,
473
+ Refreshing,
474
+ Stopping,
475
+ Erroring // like stopping, but emits error when finished
476
+ };
477
+
478
+ StunAllocate *q;
479
+ ObjectSession sess;
480
+ StunTransactionPool *pool;
481
+ StunTransaction *trans;
482
+ QHostAddress stunAddr;
483
+ int stunPort;
484
+ State state;
485
+ QString errorString;
486
+ DontFragmentState dfState;
487
+ QString clientSoftware, serverSoftware;
488
+ QHostAddress reflexiveAddress, relayedAddress;
489
+ int reflexivePort, relayedPort;
490
+ StunMessage msg;
491
+ int allocateLifetime;
492
+ QTimer *allocateRefreshTimer;
493
+ QList<StunAllocatePermission*> perms;
494
+ QList<StunAllocateChannel*> channels;
495
+ QList<QHostAddress> permsOut;
496
+ QList<StunAllocate::Channel> channelsOut;
497
+ int erroringCode;
498
+ QString erroringString;
499
+
500
+ Private(StunAllocate *_q) :
501
+ QObject(_q),
502
+ q(_q),
503
+ sess(this),
504
+ pool(0),
505
+ trans(0),
506
+ state(Stopped),
507
+ dfState(DF_Unknown),
508
+ erroringCode(-1)
509
+ {
510
+ allocateRefreshTimer = new QTimer(this);
511
+ connect(allocateRefreshTimer, SIGNAL(timeout()), SLOT(refresh()));
512
+ allocateRefreshTimer->setSingleShot(true);
513
+ }
514
+
515
+ ~Private()
516
+ {
517
+ cleanup();
518
+
519
+ releaseAndDeleteLater(this, allocateRefreshTimer);
520
+ }
521
+
522
+ void start(const QHostAddress &_addr = QHostAddress(), int _port = -1)
523
+ {
524
+ Q_ASSERT(state == Stopped);
525
+
526
+ stunAddr = _addr;
527
+ stunPort = _port;
528
+
529
+ state = Starting;
530
+ doTransaction();
531
+ }
532
+
533
+ void stop()
534
+ {
535
+ // erroring already? no need to do anything
536
+ if(state == Erroring)
537
+ return;
538
+
539
+ Q_ASSERT(state == Started);
540
+
541
+ cleanupTasks();
542
+ state = Stopping;
543
+ doTransaction();
544
+ }
545
+
546
+ void stopWithError(int code, const QString &str)
547
+ {
548
+ Q_ASSERT(state == Started);
549
+
550
+ cleanupTasks();
551
+ erroringCode = code;
552
+ erroringString = str;
553
+ state = Erroring;
554
+ doTransaction();
555
+ }
556
+
557
+ void setPermissions(const QList<QHostAddress> &newPerms)
558
+ {
559
+ // if currently erroring out, skip
560
+ if(state == Erroring)
561
+ return;
562
+
563
+ Q_ASSERT(state == Started);
564
+
565
+ int freeCount = 0;
566
+
567
+ // removed?
568
+ for(int n = 0; n < perms.count(); ++n)
569
+ {
570
+ bool found = false;
571
+ for(int k = 0; k < newPerms.count(); ++k)
572
+ {
573
+ if(newPermsk == permsn->addr)
574
+ {
575
+ found = true;
576
+ break;
577
+ }
578
+ }
579
+
580
+ if(!found)
581
+ {
582
+ // delete related channels
583
+ for(int j = 0; j < channels.count(); ++j)
584
+ {
585
+ if(channelsj->addr == permsn->addr)
586
+ {
587
+ delete channelsj;
588
+ channels.removeAt(j);
589
+ --j; // adjust position
590
+ }
591
+ }
592
+
593
+ ++freeCount;
594
+
595
+ delete permsn;
596
+ perms.removeAt(n);
597
+ --n; // adjust position
598
+ }
599
+ }
600
+
601
+ if(freeCount > 0)
602
+ {
603
+ // removals count as a change, so emit the signal
604
+ sess.deferExclusive(q, "permissionsChanged");
605
+
606
+ // wake up inactive perms now that we've freed space
607
+ for(int n = 0; n < perms.count(); ++n)
608
+ {
609
+ if(!permsn->active)
610
+ permsn->start(stunAddr, stunPort);
611
+ }
612
+ }
613
+
614
+ // added?
615
+ for(int n = 0; n < newPerms.count(); ++n)
616
+ {
617
+ bool found = false;
618
+ for(int k = 0; k < perms.count(); ++k)
619
+ {
620
+ if(permsk->addr == newPermsn)
621
+ {
622
+ found = true;
623
+ break;
624
+ }
625
+ }
626
+
627
+ if(!found)
628
+ {
629
+ StunAllocatePermission *perm = new StunAllocatePermission(pool, newPermsn);
630
+ connect(perm, SIGNAL(ready()), SLOT(perm_ready()));
631
+ connect(perm, SIGNAL(error(XMPP::StunAllocatePermission::Error, const QString &)), SLOT(perm_error(XMPP::StunAllocatePermission::Error, const QString &)));
632
+ perms += perm;
633
+ perm->start(stunAddr, stunPort);
634
+ }
635
+ }
636
+ }
637
+
638
+ void setChannels(const QList<StunAllocate::Channel> &newChannels)
639
+ {
640
+ // if currently erroring out, skip
641
+ if(state == Erroring)
642
+ return;
643
+
644
+ Q_ASSERT(state == Started);
645
+
646
+ int freeCount = 0;
647
+
648
+ // removed?
649
+ for(int n = 0; n < channels.count(); ++n)
650
+ {
651
+ bool found = false;
652
+ for(int k = 0; k < newChannels.count(); ++k)
653
+ {
654
+ if(newChannelsk.address == channelsn->addr && newChannelsk.port == channelsn->port)
655
+ {
656
+ found = true;
657
+ break;
658
+ }
659
+ }
660
+
661
+ if(!found)
662
+ {
663
+ ++freeCount;
664
+
665
+ delete channelsn;
666
+ channels.removeAt(n);
667
+ --n; // adjust position
668
+ }
669
+ }
670
+
671
+ if(freeCount > 0)
672
+ {
673
+ // removals count as a change, so emit the signal
674
+ sess.deferExclusive(q, "channelsChanged");
675
+
676
+ // wake up inactive channels now that we've freed space
677
+ for(int n = 0; n < channels.count(); ++n)
678
+ {
679
+ if(!channelsn->active)
680
+ {
681
+ int channelId = getFreeChannelNumber();
682
+
683
+ // out of channels? give up
684
+ if(channelId == -1)
685
+ break;
686
+
687
+ channelsn->channelId = channelId;
688
+ channelsn->start(stunAddr, stunPort);
689
+ }
690
+ }
691
+ }
692
+
693
+ // added?
694
+ for(int n = 0; n < newChannels.count(); ++n)
695
+ {
696
+ bool found = false;
697
+ for(int k = 0; k < channels.count(); ++k)
698
+ {
699
+ if(channelsk->addr == newChannelsn.address && channelsk->port == newChannelsn.port)
700
+ {
701
+ found = true;
702
+ break;
703
+ }
704
+ }
705
+
706
+ if(!found)
707
+ {
708
+ // look up the permission for this channel
709
+ int at = -1;
710
+ for(int k = 0; k < perms.count(); ++k)
711
+ {
712
+ if(permsk->addr == newChannelsn.address)
713
+ {
714
+ at = k;
715
+ break;
716
+ }
717
+ }
718
+
719
+ // only install a channel if we have a permission
720
+ if(at != -1)
721
+ {
722
+ int channelId = getFreeChannelNumber();
723
+
724
+ StunAllocateChannel *channel = new StunAllocateChannel(pool, channelId, newChannelsn.address, newChannelsn.port);
725
+ connect(channel, SIGNAL(ready()), SLOT(channel_ready()));
726
+ connect(channel, SIGNAL(error(XMPP::StunAllocateChannel::Error, const QString &)), SLOT(channel_error(XMPP::StunAllocateChannel::Error, const QString &)));
727
+ channels += channel;
728
+
729
+ if(channelId != -1)
730
+ channel->start(stunAddr, stunPort);
731
+ }
732
+ }
733
+ }
734
+ }
735
+
736
+ int getFreeChannelNumber()
737
+ {
738
+ for(int tryId = 0x4000; tryId <= 0x7fff; ++tryId)
739
+ {
740
+ bool found = false;
741
+ for(int n = 0; n < channels.count(); ++n)
742
+ {
743
+ if(channelsn->channelId == tryId)
744
+ {
745
+ found = true;
746
+ break;
747
+ }
748
+ }
749
+
750
+ if(!found)
751
+ return tryId;
752
+ }
753
+
754
+ return -1;
755
+ }
756
+
757
+ int getChannel(const QHostAddress &addr, int port)
758
+ {
759
+ for(int n = 0; n < channels.count(); ++n)
760
+ {
761
+ if(channelsn->active && channelsn->addr == addr && channelsn->port == port)
762
+ return channelsn->channelId;
763
+ }
764
+
765
+ return -1;
766
+ }
767
+
768
+ // note that this function works even for inactive channels, so that
769
+ // incoming traffic that is received out-of-order with a
770
+ // ChannelBind success response is still processable
771
+ bool getAddressPort(int channelId, QHostAddress *addr, int *port)
772
+ {
773
+ for(int n = 0; n < channels.count(); ++n)
774
+ {
775
+ if(channelsn->channelId == channelId)
776
+ {
777
+ *addr = channelsn->addr;
778
+ *port = channelsn->port;
779
+ return true;
780
+ }
781
+ }
782
+
783
+ return false;
784
+ }
785
+
786
+private:
787
+ void cleanup()
788
+ {
789
+ sess.reset();
790
+
791
+ cleanupTasks();
792
+
793
+ erroringCode = -1;
794
+ erroringString.clear();
795
+
796
+ state = Stopped;
797
+ }
798
+
799
+ // stop refreshing, permissions, and channelbinds
800
+ void cleanupTasks()
801
+ {
802
+ delete trans;
803
+ trans = 0;
804
+
805
+ allocateRefreshTimer->stop();
806
+
807
+ qDeleteAll(channels);
808
+ channels.clear();
809
+ channelsOut.clear();
810
+
811
+ qDeleteAll(perms);
812
+ perms.clear();
813
+ permsOut.clear();
814
+ }
815
+
816
+ void doTransaction()
817
+ {
818
+ Q_ASSERT(!trans);
819
+ trans = new StunTransaction(this);
820
+ connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
821
+ connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
822
+ connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
823
+ trans->start(pool, stunAddr, stunPort);
824
+ }
825
+
826
+ void restartRefreshTimer()
827
+ {
828
+ // refresh 1 minute shy of the lifetime
829
+ allocateRefreshTimer->start((allocateLifetime - 60) * 1000);
830
+ }
831
+
832
+ bool updatePermsOut()
833
+ {
834
+ QList<QHostAddress> newList;
835
+
836
+ for(int n = 0; n < perms.count(); ++n)
837
+ {
838
+ if(permsn->active)
839
+ newList += permsn->addr;
840
+ }
841
+
842
+ if(newList == permsOut)
843
+ return false;
844
+
845
+ permsOut = newList;
846
+ return true;
847
+ }
848
+
849
+ bool updateChannelsOut()
850
+ {
851
+ QList<StunAllocate::Channel> newList;
852
+
853
+ for(int n = 0; n < channels.count(); ++n)
854
+ {
855
+ if(channelsn->active)
856
+ newList += StunAllocate::Channel(channelsn->addr, channelsn->port);
857
+ }
858
+
859
+ if(newList == channelsOut)
860
+ return false;
861
+
862
+ channelsOut = newList;
863
+ return true;
864
+ }
865
+
866
+private slots:
867
+ void refresh()
868
+ {
869
+ Q_ASSERT(state == Started);
870
+
871
+ state = Refreshing;
872
+ doTransaction();
873
+ }
874
+
875
+ void trans_createMessage(const QByteArray &transactionId)
876
+ {
877
+ if(state == Starting)
878
+ {
879
+ // send Allocate request
880
+ StunMessage message;
881
+ message.setMethod(StunTypes::Allocate);
882
+ message.setId((const quint8 *)transactionId.data());
883
+
884
+ QList<StunMessage::Attribute> list;
885
+
886
+ if(!clientSoftware.isEmpty())
887
+ {
888
+ StunMessage::Attribute a;
889
+ a.type = StunTypes::SOFTWARE;
890
+ a.value = StunTypes::createSoftware(clientSoftware);
891
+ list += a;
892
+ }
893
+
894
+ {
895
+ StunMessage::Attribute a;
896
+ a.type = StunTypes::LIFETIME;
897
+ a.value = StunTypes::createLifetime(3600);
898
+ list += a;
899
+ }
900
+
901
+ {
902
+ StunMessage::Attribute a;
903
+ a.type = StunTypes::REQUESTED_TRANSPORT;
904
+ a.value = StunTypes::createRequestedTransport(17); // 17=UDP
905
+ list += a;
906
+ }
907
+
908
+ if(dfState == DF_Unknown)
909
+ {
910
+ StunMessage::Attribute a;
911
+ a.type = StunTypes::DONT_FRAGMENT;
912
+ list += a;
913
+ }
914
+
915
+ message.setAttributes(list);
916
+
917
+ trans->setMessage(message);
918
+ }
919
+ else if(state == Stopping || state == Erroring)
920
+ {
921
+ StunMessage message;
922
+ message.setMethod(StunTypes::Refresh);
923
+ message.setId((const quint8 *)transactionId.data());
924
+
925
+ QList<StunMessage::Attribute> list;
926
+
927
+ {
928
+ StunMessage::Attribute a;
929
+ a.type = StunTypes::LIFETIME;
930
+ a.value = StunTypes::createLifetime(0);
931
+ list += a;
932
+ }
933
+
934
+ message.setAttributes(list);
935
+
936
+ trans->setMessage(message);
937
+ }
938
+ else if(state == Refreshing)
939
+ {
940
+ StunMessage message;
941
+ message.setMethod(StunTypes::Refresh);
942
+ message.setId((const quint8 *)transactionId.data());
943
+
944
+ QList<StunMessage::Attribute> list;
945
+
946
+ {
947
+ StunMessage::Attribute a;
948
+ a.type = StunTypes::LIFETIME;
949
+ a.value = StunTypes::createLifetime(3600);
950
+ list += a;
951
+ }
952
+
953
+ message.setAttributes(list);
954
+
955
+ trans->setMessage(message);
956
+ }
957
+ }
958
+
959
+ void trans_finished(const XMPP::StunMessage &response)
960
+ {
961
+ delete trans;
962
+ trans = 0;
963
+
964
+ bool error = false;
965
+ int code;
966
+ QString reason;
967
+ if(response.mclass() == StunMessage::ErrorResponse)
968
+ {
969
+ if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason))
970
+ {
971
+ cleanup();
972
+ errorString = "Unable to parse ERROR-CODE in error response.";
973
+ emit q->error(StunAllocate::ErrorProtocol);
974
+ return;
975
+ }
976
+
977
+ error = true;
978
+ }
979
+
980
+ if(state == Starting)
981
+ {
982
+ if(error)
983
+ {
984
+ if(code == StunTypes::UnknownAttribute)
985
+ {
986
+ QList<quint16> typeList;
987
+ if(!StunTypes::parseUnknownAttributes(response.attribute(StunTypes::UNKNOWN_ATTRIBUTES), &typeList))
988
+ {
989
+ cleanup();
990
+ errorString = "Unable to parse UNKNOWN-ATTRIBUTES in 420 (Unknown Attribute) error response.";
991
+ emit q->error(StunAllocate::ErrorProtocol);
992
+ return;
993
+ }
994
+
995
+ if(typeList.contains(StunTypes::DONT_FRAGMENT))
996
+ {
997
+ dfState = DF_Unsupported;
998
+
999
+ // stay in same state, try again
1000
+ doTransaction();
1001
+ }
1002
+ else
1003
+ {
1004
+ cleanup();
1005
+ errorString = reason;
1006
+ emit q->error(StunAllocate::ErrorGeneric);
1007
+ }
1008
+
1009
+ return;
1010
+ }
1011
+ else if(code == StunTypes::AllocationMismatch)
1012
+ {
1013
+ cleanup();
1014
+ errorString = "437 (Allocation Mismatch).";
1015
+ emit q->error(StunAllocate::ErrorMismatch);
1016
+ return;
1017
+ }
1018
+ else if(code == StunTypes::InsufficientCapacity)
1019
+ {
1020
+ cleanup();
1021
+ errorString = reason;
1022
+ emit q->error(StunAllocate::ErrorCapacity);
1023
+ return;
1024
+ }
1025
+ else if(code == StunTypes::Unauthorized)
1026
+ {
1027
+ cleanup();
1028
+ errorString = "Unauthorized";
1029
+ emit q->error(StunAllocate::ErrorAuth);
1030
+ return;
1031
+ }
1032
+ else
1033
+ {
1034
+ cleanup();
1035
+ errorString = reason;
1036
+ emit q->error(StunAllocate::ErrorGeneric);
1037
+ return;
1038
+ }
1039
+ }
1040
+
1041
+ quint32 lifetime;
1042
+ if(!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime))
1043
+ {
1044
+ cleanup();
1045
+ errorString = "Unable to parse LIFETIME.";
1046
+ emit q->error(StunAllocate::ErrorProtocol);
1047
+ return;
1048
+ }
1049
+
1050
+ QHostAddress raddr;
1051
+ quint16 rport;
1052
+ if(!StunTypes::parseXorRelayedAddress(response.attribute(StunTypes::XOR_RELAYED_ADDRESS), response.magic(), response.id(), &raddr, &rport))
1053
+ {
1054
+ cleanup();
1055
+ errorString = "Unable to parse XOR-RELAYED-ADDRESS.";
1056
+ emit q->error(StunAllocate::ErrorProtocol);
1057
+ return;
1058
+ }
1059
+
1060
+ QHostAddress saddr;
1061
+ quint16 sport;
1062
+ if(!StunTypes::parseXorMappedAddress(response.attribute(StunTypes::XOR_MAPPED_ADDRESS), response.magic(), response.id(), &saddr, &sport))
1063
+ {
1064
+ cleanup();
1065
+ errorString = "Unable to parse XOR-MAPPED-ADDRESS.";
1066
+ emit q->error(StunAllocate::ErrorProtocol);
1067
+ return;
1068
+ }
1069
+
1070
+ if(lifetime < 120)
1071
+ {
1072
+ state = Started; // stopWithError requires this
1073
+ stopWithError(StunAllocate::ErrorProtocol,
1074
+ "LIFETIME is less than two minutes. That is ridiculous.");
1075
+ return;
1076
+ }
1077
+
1078
+ QString str;
1079
+ if(StunTypes::parseSoftware(response.attribute(StunTypes::SOFTWARE), &str))
1080
+ {
1081
+ serverSoftware = str;
1082
+ }
1083
+
1084
+ allocateLifetime = lifetime;
1085
+ relayedAddress = raddr;
1086
+ relayedPort = rport;
1087
+ reflexiveAddress = saddr;
1088
+ reflexivePort = sport;
1089
+
1090
+ if(dfState == DF_Unknown)
1091
+ dfState = DF_Supported;
1092
+
1093
+ state = Started;
1094
+ restartRefreshTimer();
1095
+
1096
+ emit q->started();
1097
+ }
1098
+ else if(state == Stopping || state == Erroring)
1099
+ {
1100
+ if(error)
1101
+ {
1102
+ // AllocationMismatch on session cancel doesn't count as an error
1103
+ if(code != StunTypes::AllocationMismatch)
1104
+ {
1105
+ cleanup();
1106
+ errorString = reason;
1107
+ emit q->error(StunAllocate::ErrorGeneric);
1108
+ return;
1109
+ }
1110
+ }
1111
+
1112
+ if(state == Stopping)
1113
+ {
1114
+ // cleanup will set the state to Stopped
1115
+ cleanup();
1116
+ emit q->stopped();
1117
+ }
1118
+ else // Erroring
1119
+ {
1120
+ int code = erroringCode;
1121
+ QString str = erroringString;
1122
+
1123
+ // cleanup will set the state to Stopped
1124
+ cleanup();
1125
+ errorString = str;
1126
+ emit q->error((StunAllocate::Error)code);
1127
+ }
1128
+ }
1129
+ else if(state == Refreshing)
1130
+ {
1131
+ if(error)
1132
+ {
1133
+ cleanup();
1134
+ errorString = reason;
1135
+ emit q->error(StunAllocate::ErrorRejected);
1136
+ return;
1137
+ }
1138
+
1139
+ quint32 lifetime;
1140
+ if(!StunTypes::parseLifetime(response.attribute(StunTypes::LIFETIME), &lifetime))
1141
+ {
1142
+ cleanup();
1143
+ errorString = "Unable to parse LIFETIME.";
1144
+ emit q->error(StunAllocate::ErrorProtocol);
1145
+ return;
1146
+ }
1147
+
1148
+ allocateLifetime = lifetime;
1149
+
1150
+ state = Started;
1151
+ restartRefreshTimer();
1152
+ }
1153
+ }
1154
+
1155
+ void perm_ready()
1156
+ {
1157
+ if(updatePermsOut())
1158
+ emit q->permissionsChanged();
1159
+ }
1160
+
1161
+ void perm_error(XMPP::StunAllocatePermission::Error e, const QString &reason)
1162
+ {
1163
+ if(e == StunAllocatePermission::ErrorCapacity)
1164
+ {
1165
+ // if we aren't allowed to make anymore permissions,
1166
+ // don't consider this an error. the perm stays
1167
+ // in the list inactive. we'll try it again if
1168
+ // any perms get removed.
1169
+ return;
1170
+ }
1171
+ else if(e == StunAllocatePermission::ErrorForbidden)
1172
+ {
1173
+ // silently discard the permission request
1174
+ StunAllocatePermission *perm = (StunAllocatePermission *)sender();
1175
+ QHostAddress addr = perm->addr;
1176
+ delete perm;
1177
+ perms.removeAll(perm);
1178
+ emit q->debugLine(QString("Warning: permission forbidden to %1").arg(addr.toString()));
1179
+ return;
1180
+ }
1181
+
1182
+ cleanup();
1183
+ errorString = reason;
1184
+ emit q->error(StunAllocatePermission::errorToStunAllocateError(e));
1185
+ }
1186
+
1187
+ void channel_ready()
1188
+ {
1189
+ if(updateChannelsOut())
1190
+ emit q->channelsChanged();
1191
+ }
1192
+
1193
+ void channel_error(XMPP::StunAllocateChannel::Error e, const QString &reason)
1194
+ {
1195
+ if(e == StunAllocateChannel::ErrorCapacity)
1196
+ {
1197
+ // if we aren't allowed to make anymore channels,
1198
+ // don't consider this an error. the channel stays
1199
+ // in the list inactive. we'll try it again if
1200
+ // any channels get removed.
1201
+ return;
1202
+ }
1203
+
1204
+ cleanup();
1205
+ errorString = reason;
1206
+ emit q->error(StunAllocateChannel::errorToStunAllocateError(e));
1207
+ }
1208
+
1209
+ void trans_error(XMPP::StunTransaction::Error e)
1210
+ {
1211
+ delete trans;
1212
+ trans = 0;
1213
+
1214
+ cleanup();
1215
+
1216
+ if(e == StunTransaction::ErrorTimeout)
1217
+ {
1218
+ errorString = "Request timed out.";
1219
+ emit q->error(StunAllocate::ErrorTimeout);
1220
+ }
1221
+ else
1222
+ {
1223
+ errorString = "Generic transaction error.";
1224
+ emit q->error(StunAllocate::ErrorGeneric);
1225
+ }
1226
+ }
1227
+};
1228
+
1229
+StunAllocate::StunAllocate(StunTransactionPool *pool) :
1230
+ QObject(pool)
1231
+{
1232
+ d = new Private(this);
1233
+ d->pool = pool;
1234
+}
1235
+
1236
+StunAllocate::~StunAllocate()
1237
+{
1238
+ delete d;
1239
+}
1240
+
1241
+void StunAllocate::setClientSoftwareNameAndVersion(const QString &str)
1242
+{
1243
+ d->clientSoftware = str;
1244
+}
1245
+
1246
+void StunAllocate::start()
1247
+{
1248
+ d->start();
1249
+}
1250
+
1251
+void StunAllocate::start(const QHostAddress &addr, int port)
1252
+{
1253
+ d->start(addr, port);
1254
+}
1255
+
1256
+void StunAllocate::stop()
1257
+{
1258
+ d->stop();
1259
+}
1260
+
1261
+QString StunAllocate::serverSoftwareNameAndVersion() const
1262
+{
1263
+ return d->serverSoftware;
1264
+}
1265
+
1266
+QHostAddress StunAllocate::reflexiveAddress() const
1267
+{
1268
+ return d->reflexiveAddress;
1269
+}
1270
+
1271
+int StunAllocate::reflexivePort() const
1272
+{
1273
+ return d->reflexivePort;
1274
+}
1275
+
1276
+QHostAddress StunAllocate::relayedAddress() const
1277
+{
1278
+ return d->relayedAddress;
1279
+}
1280
+
1281
+int StunAllocate::relayedPort() const
1282
+{
1283
+ return d->relayedPort;
1284
+}
1285
+
1286
+QList<QHostAddress> StunAllocate::permissions() const
1287
+{
1288
+ return d->permsOut;
1289
+}
1290
+
1291
+void StunAllocate::setPermissions(const QList<QHostAddress> &perms)
1292
+{
1293
+ d->setPermissions(perms);
1294
+}
1295
+
1296
+QList<StunAllocate::Channel> StunAllocate::channels() const
1297
+{
1298
+ return d->channelsOut;
1299
+}
1300
+
1301
+void StunAllocate::setChannels(const QList<Channel> &channels)
1302
+{
1303
+ d->setChannels(channels);
1304
+}
1305
+
1306
+int StunAllocate::packetHeaderOverhead(const QHostAddress &addr, int port) const
1307
+{
1308
+ int channelId = d->getChannel(addr, port);
1309
+
1310
+ if(channelId != -1)
1311
+ {
1312
+ // overhead of ChannelData
1313
+ if(d->pool->mode() == StunTransaction::Udp)
1314
+ return 4;
1315
+ else // Tcp
1316
+ return 4 + 3; // add 3 for potential padding
1317
+ }
1318
+ else
1319
+ {
1320
+ // we add 3 for potential padding
1321
+ if(d->dfState == StunAllocate::Private::DF_Supported)
1322
+ {
1323
+ // overhead of STUN-based data, with DONT_FRAGMENT
1324
+ return 40 + 3;
1325
+ }
1326
+ else
1327
+ {
1328
+ // overhead of STUN-based data, without DONT-FRAGMENT
1329
+ return 36 + 3;
1330
+ }
1331
+ }
1332
+
1333
+ return -1;
1334
+}
1335
+
1336
+QByteArray StunAllocate::encode(const QByteArray &datagram, const QHostAddress &addr, int port)
1337
+{
1338
+ int channelId = d->getChannel(addr, port);
1339
+
1340
+ if(channelId != -1)
1341
+ {
1342
+ if(datagram.size() > 65535)
1343
+ return QByteArray();
1344
+
1345
+ quint16 num = channelId;
1346
+ quint16 len = datagram.size();
1347
+
1348
+ int plen = len;
1349
+
1350
+ // in tcp mode, round to up to nearest 4 bytes
1351
+ if(d->pool->mode() == StunTransaction::Tcp)
1352
+ {
1353
+ int remainder = plen % 4;
1354
+ if(remainder != 0)
1355
+ plen += (4 - remainder);
1356
+ }
1357
+
1358
+ QByteArray out(4 + plen, 0);
1359
+ StunUtil::write16((quint8 *)out.data(), num);
1360
+ StunUtil::write16((quint8 *)out.data() + 2, len);
1361
+ memcpy(out.data() + 4, datagram.data(), datagram.size());
1362
+
1363
+ return out;
1364
+ }
1365
+ else
1366
+ {
1367
+ StunMessage message;
1368
+ message.setClass(StunMessage::Indication);
1369
+ message.setMethod(StunTypes::Send);
1370
+ QByteArray id = d->pool->generateId();
1371
+ message.setId((const quint8 *)id.data());
1372
+
1373
+ QList<StunMessage::Attribute> list;
1374
+
1375
+ {
1376
+ StunMessage::Attribute a;
1377
+ a.type = StunTypes::XOR_PEER_ADDRESS;
1378
+ a.value = StunTypes::createXorPeerAddress(addr, port, message.magic(), message.id());
1379
+ list += a;
1380
+ }
1381
+
1382
+ if(d->dfState == StunAllocate::Private::DF_Supported)
1383
+ {
1384
+ StunMessage::Attribute a;
1385
+ a.type = StunTypes::DONT_FRAGMENT;
1386
+ list += a;
1387
+ }
1388
+
1389
+ {
1390
+ StunMessage::Attribute a;
1391
+ a.type = StunTypes::DATA;
1392
+ a.value = datagram;
1393
+ list += a;
1394
+ }
1395
+
1396
+ message.setAttributes(list);
1397
+
1398
+ return message.toBinary();
1399
+ }
1400
+}
1401
+
1402
+QByteArray StunAllocate::decode(const QByteArray &encoded, QHostAddress *addr, int *port)
1403
+{
1404
+ if(encoded.size() < 4)
1405
+ return QByteArray();
1406
+
1407
+ quint16 num = StunUtil::read16((const quint8 *)encoded.data());
1408
+ quint16 len = StunUtil::read16((const quint8 *)encoded.data() + 2);
1409
+ if(encoded.size() - 4 < (int)len)
1410
+ return QByteArray();
1411
+
1412
+ if(!d->getAddressPort(num, addr, port))
1413
+ return QByteArray();
1414
+
1415
+ return encoded.mid(4, len);
1416
+}
1417
+
1418
+QByteArray StunAllocate::decode(const StunMessage &encoded, QHostAddress *addr, int *port)
1419
+{
1420
+ QHostAddress paddr;
1421
+ quint16 pport;
1422
+
1423
+ if(!StunTypes::parseXorPeerAddress(encoded.attribute(StunTypes::XOR_PEER_ADDRESS), encoded.magic(), encoded.id(), &paddr, &pport))
1424
+ return QByteArray();
1425
+
1426
+ QByteArray data = encoded.attribute(StunTypes::DATA);
1427
+ if(data.isNull())
1428
+ return QByteArray();
1429
+
1430
+ *addr = paddr;
1431
+ *port = pport;
1432
+ return data;
1433
+}
1434
+
1435
+QString StunAllocate::errorString() const
1436
+{
1437
+ return d->errorString;
1438
+}
1439
+
1440
+bool StunAllocate::containsChannelData(const quint8 *data, int size)
1441
+{
1442
+ return (check_channelData(data, size) != -1 ? true : false);
1443
+}
1444
+
1445
+QByteArray StunAllocate::readChannelData(const quint8 *data, int size)
1446
+{
1447
+ int len = check_channelData(data, size);
1448
+ if(len != -1)
1449
+ return QByteArray((const char *)data, len);
1450
+ else
1451
+ return QByteArray();
1452
+}
1453
+
1454
+}
1455
+
1456
+#include "stunallocate.moc"
1457
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunallocate.h
Added
137
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNALLOCATE_H
23
+#define STUNALLOCATE_H
24
+
25
+#include <QObject>
26
+#include <QList>
27
+#include <QHostAddress>
28
+
29
+class QByteArray;
30
+
31
+namespace XMPP {
32
+
33
+class StunMessage;
34
+class StunTransactionPool;
35
+
36
+class StunAllocate : public QObject
37
+{
38
+ Q_OBJECT
39
+
40
+public:
41
+ enum Error
42
+ {
43
+ ErrorGeneric,
44
+ ErrorTimeout,
45
+ ErrorAuth,
46
+ ErrorRejected,
47
+ ErrorProtocol,
48
+ ErrorCapacity,
49
+ ErrorMismatch
50
+ };
51
+
52
+ class Channel
53
+ {
54
+ public:
55
+ QHostAddress address;
56
+ int port;
57
+
58
+ Channel(const QHostAddress &_address, int _port) :
59
+ address(_address),
60
+ port(_port)
61
+ {
62
+ }
63
+
64
+ inline bool operator==(const Channel &other)
65
+ {
66
+ if(address == other.address && port == other.port)
67
+ return true;
68
+ else
69
+ return false;
70
+ }
71
+
72
+ inline bool operator!=(const Channel &other)
73
+ {
74
+ return !operator==(other);
75
+ }
76
+ };
77
+
78
+ StunAllocate(StunTransactionPool *pool);
79
+ ~StunAllocate();
80
+
81
+ void setClientSoftwareNameAndVersion(const QString &str);
82
+
83
+ void start();
84
+ void start(const QHostAddress &addr, int port); // use addr association
85
+ void stop();
86
+
87
+ QString serverSoftwareNameAndVersion() const;
88
+
89
+ QHostAddress reflexiveAddress() const;
90
+ int reflexivePort() const;
91
+
92
+ QHostAddress relayedAddress() const;
93
+ int relayedPort() const;
94
+
95
+ QList<QHostAddress> permissions() const;
96
+ void setPermissions(const QList<QHostAddress> &perms);
97
+
98
+ QList<Channel> channels() const;
99
+ void setChannels(const QList<Channel> &channels);
100
+
101
+ int packetHeaderOverhead(const QHostAddress &addr, int port) const;
102
+
103
+ QByteArray encode(const QByteArray &datagram, const QHostAddress &addr, int port);
104
+ QByteArray decode(const QByteArray &encoded, QHostAddress *addr = 0, int *port = 0);
105
+ QByteArray decode(const StunMessage &encoded, QHostAddress *addr = 0, int *port = 0);
106
+
107
+ QString errorString() const;
108
+
109
+ static bool containsChannelData(const quint8 *data, int size);
110
+ static QByteArray readChannelData(const quint8 *data, int size);
111
+
112
+signals:
113
+ void started();
114
+ void stopped();
115
+ void error(XMPP::StunAllocate::Error e);
116
+
117
+ // emitted after calling setPermissions()
118
+ void permissionsChanged();
119
+
120
+ // emitted after calling setChannels()
121
+ void channelsChanged();
122
+
123
+ // not DOR-SS/DS safe
124
+ void debugLine(const QString &line);
125
+
126
+private:
127
+ Q_DISABLE_COPY(StunAllocate)
128
+
129
+ class Private;
130
+ friend class Private;
131
+ Private *d;
132
+};
133
+
134
+}
135
+
136
+#endif
137
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunbinding.cpp
Added
302
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stunbinding.h"
23
+
24
+#include <QHostAddress>
25
+#include "stunmessage.h"
26
+#include "stuntypes.h"
27
+#include "stuntransaction.h"
28
+
29
+namespace XMPP {
30
+
31
+class StunBinding::Private : public QObject
32
+{
33
+ Q_OBJECT
34
+
35
+public:
36
+ StunBinding *q;
37
+ StunTransactionPool *pool;
38
+ StunTransaction *trans;
39
+ QHostAddress stunAddr;
40
+ int stunPort;
41
+ QHostAddress addr;
42
+ int port;
43
+ QString errorString;
44
+ bool use_extPriority, use_extIceControlling, use_extIceControlled;
45
+ quint32 extPriority;
46
+ bool extUseCandidate;
47
+ quint64 extIceControlling, extIceControlled;
48
+ QString stuser, stpass;
49
+ bool fpRequired;
50
+
51
+ Private(StunBinding *_q) :
52
+ QObject(_q),
53
+ q(_q),
54
+ pool(0),
55
+ trans(0),
56
+ use_extPriority(false),
57
+ use_extIceControlling(false),
58
+ use_extIceControlled(false),
59
+ extUseCandidate(false),
60
+ fpRequired(false)
61
+ {
62
+ }
63
+
64
+ ~Private()
65
+ {
66
+ delete trans;
67
+ }
68
+
69
+ void start(const QHostAddress &_addr = QHostAddress(), int _port = -1)
70
+ {
71
+ Q_ASSERT(!trans);
72
+
73
+ stunAddr = _addr;
74
+ stunPort = _port;
75
+
76
+ trans = new StunTransaction(this);
77
+ connect(trans, SIGNAL(createMessage(const QByteArray &)), SLOT(trans_createMessage(const QByteArray &)));
78
+ connect(trans, SIGNAL(finished(const XMPP::StunMessage &)), SLOT(trans_finished(const XMPP::StunMessage &)));
79
+ connect(trans, SIGNAL(error(XMPP::StunTransaction::Error)), SLOT(trans_error(XMPP::StunTransaction::Error)));
80
+
81
+ if(!stuser.isEmpty())
82
+ {
83
+ trans->setShortTermUsername(stuser);
84
+ trans->setShortTermPassword(stpass);
85
+ }
86
+
87
+ trans->setFingerprintRequired(fpRequired);
88
+
89
+ trans->start(pool, stunAddr, stunPort);
90
+ }
91
+
92
+private slots:
93
+ void trans_createMessage(const QByteArray &transactionId)
94
+ {
95
+ StunMessage message;
96
+ message.setMethod(StunTypes::Binding);
97
+ message.setId((const quint8 *)transactionId.data());
98
+
99
+ QList<StunMessage::Attribute> list;
100
+
101
+ if(use_extPriority)
102
+ {
103
+ StunMessage::Attribute a;
104
+ a.type = StunTypes::PRIORITY;
105
+ a.value = StunTypes::createPriority(extPriority);
106
+ list += a;
107
+ }
108
+
109
+ if(extUseCandidate)
110
+ {
111
+ StunMessage::Attribute a;
112
+ a.type = StunTypes::USE_CANDIDATE;
113
+ list += a;
114
+ }
115
+
116
+ if(use_extIceControlling)
117
+ {
118
+ StunMessage::Attribute a;
119
+ a.type = StunTypes::ICE_CONTROLLING;
120
+ a.value = StunTypes::createIceControlling(extIceControlling);
121
+ list += a;
122
+ }
123
+
124
+ if(use_extIceControlled)
125
+ {
126
+ StunMessage::Attribute a;
127
+ a.type = StunTypes::ICE_CONTROLLED;
128
+ a.value = StunTypes::createIceControlled(extIceControlled);
129
+ list += a;
130
+ }
131
+
132
+ message.setAttributes(list);
133
+
134
+ trans->setMessage(message);
135
+ }
136
+
137
+ void trans_finished(const XMPP::StunMessage &response)
138
+ {
139
+ delete trans;
140
+ trans = 0;
141
+
142
+ bool error = false;
143
+ int code;
144
+ QString reason;
145
+ if(response.mclass() == StunMessage::ErrorResponse)
146
+ {
147
+ if(!StunTypes::parseErrorCode(response.attribute(StunTypes::ERROR_CODE), &code, &reason))
148
+ {
149
+ errorString = "Unable to parse ERROR-CODE in error response.";
150
+ emit q->error(StunBinding::ErrorProtocol);
151
+ return;
152
+ }
153
+
154
+ error = true;
155
+ }
156
+
157
+ if(error)
158
+ {
159
+ errorString = reason;
160
+ if(code == StunTypes::RoleConflict)
161
+ emit q->error(StunBinding::ErrorConflict);
162
+ else
163
+ emit q->error(StunBinding::ErrorRejected);
164
+ return;
165
+ }
166
+
167
+ QHostAddress saddr;
168
+ quint16 sport = 0;
169
+
170
+ QByteArray val;
171
+ val = response.attribute(StunTypes::XOR_MAPPED_ADDRESS);
172
+ if(!val.isNull())
173
+ {
174
+ if(!StunTypes::parseXorMappedAddress(val, response.magic(), response.id(), &saddr, &sport))
175
+ {
176
+ errorString = "Unable to parse XOR-MAPPED-ADDRESS response.";
177
+ emit q->error(StunBinding::ErrorProtocol);
178
+ return;
179
+ }
180
+ }
181
+ else
182
+ {
183
+ val = response.attribute(StunTypes::MAPPED_ADDRESS);
184
+ if(!val.isNull())
185
+ {
186
+ if(!StunTypes::parseMappedAddress(val, &saddr, &sport))
187
+ {
188
+ errorString = "Unable to parse MAPPED-ADDRESS response.";
189
+ emit q->error(StunBinding::ErrorProtocol);
190
+ return;
191
+ }
192
+ }
193
+ else
194
+ {
195
+ errorString = "Response does not contain XOR-MAPPED-ADDRESS or MAPPED-ADDRESS.";
196
+ emit q->error(StunBinding::ErrorProtocol);
197
+ return;
198
+ }
199
+ }
200
+
201
+ addr = saddr;
202
+ port = sport;
203
+ emit q->success();
204
+ }
205
+
206
+ void trans_error(XMPP::StunTransaction::Error e)
207
+ {
208
+ delete trans;
209
+ trans = 0;
210
+
211
+ if(e == StunTransaction::ErrorTimeout)
212
+ {
213
+ errorString = "Request timed out.";
214
+ emit q->error(StunBinding::ErrorTimeout);
215
+ }
216
+ else
217
+ {
218
+ errorString = "Generic transaction error.";
219
+ emit q->error(StunBinding::ErrorGeneric);
220
+ }
221
+ }
222
+};
223
+
224
+StunBinding::StunBinding(StunTransactionPool *pool) :
225
+ QObject(pool)
226
+{
227
+ d = new Private(this);
228
+ d->pool = pool;
229
+}
230
+
231
+StunBinding::~StunBinding()
232
+{
233
+ delete d;
234
+}
235
+
236
+void StunBinding::setPriority(quint32 i)
237
+{
238
+ d->use_extPriority = true;
239
+ d->extPriority = i;
240
+}
241
+
242
+void StunBinding::setUseCandidate(bool enabled)
243
+{
244
+ d->extUseCandidate = enabled;
245
+}
246
+
247
+void StunBinding::setIceControlling(quint64 i)
248
+{
249
+ d->use_extIceControlling = true;
250
+ d->extIceControlling = i;
251
+}
252
+
253
+void StunBinding::setIceControlled(quint64 i)
254
+{
255
+ d->use_extIceControlled = true;
256
+ d->extIceControlled = i;
257
+}
258
+
259
+void StunBinding::setShortTermUsername(const QString &username)
260
+{
261
+ d->stuser = username;
262
+}
263
+
264
+void StunBinding::setShortTermPassword(const QString &password)
265
+{
266
+ d->stpass = password;
267
+}
268
+
269
+void StunBinding::setFingerprintRequired(bool enabled)
270
+{
271
+ d->fpRequired = enabled;
272
+}
273
+
274
+void StunBinding::start()
275
+{
276
+ d->start();
277
+}
278
+
279
+void StunBinding::start(const QHostAddress &addr, int port)
280
+{
281
+ d->start(addr, port);
282
+}
283
+
284
+QHostAddress StunBinding::reflexiveAddress() const
285
+{
286
+ return d->addr;
287
+}
288
+
289
+int StunBinding::reflexivePort() const
290
+{
291
+ return d->port;
292
+}
293
+
294
+QString StunBinding::errorString() const
295
+{
296
+ return d->errorString;
297
+}
298
+
299
+}
300
+
301
+#include "stunbinding.moc"
302
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunbinding.h
Added
85
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNBINDING_H
23
+#define STUNBINDING_H
24
+
25
+#include <QObject>
26
+
27
+class QHostAddress;
28
+
29
+namespace XMPP {
30
+
31
+class StunTransactionPool;
32
+
33
+class StunBinding : public QObject
34
+{
35
+ Q_OBJECT
36
+
37
+public:
38
+ enum Error
39
+ {
40
+ ErrorGeneric,
41
+ ErrorTimeout,
42
+ ErrorRejected,
43
+ ErrorProtocol,
44
+ ErrorConflict
45
+ };
46
+
47
+ StunBinding(StunTransactionPool *pool);
48
+ ~StunBinding();
49
+
50
+ // for ICE-use only
51
+ void setPriority(quint32 i);
52
+ void setUseCandidate(bool enabled);
53
+ void setIceControlling(quint64 i);
54
+ void setIceControlled(quint64 i);
55
+
56
+ void setShortTermUsername(const QString &username);
57
+ void setShortTermPassword(const QString &password);
58
+
59
+ void setFingerprintRequired(bool enabled);
60
+
61
+ void start();
62
+ void start(const QHostAddress &addr, int port); // use addr association
63
+
64
+ QHostAddress reflexiveAddress() const;
65
+ int reflexivePort() const;
66
+
67
+ // non-translatable diagnostic string for convenience
68
+ QString errorString() const;
69
+
70
+signals:
71
+ void success();
72
+ void error(XMPP::StunBinding::Error e);
73
+
74
+private:
75
+ Q_DISABLE_COPY(StunBinding)
76
+
77
+ class Private;
78
+ friend class Private;
79
+ Private *d;
80
+};
81
+
82
+}
83
+
84
+#endif
85
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunmessage.cpp
Added
735
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stunmessage.h"
23
+
24
+#include <QSharedData>
25
+#include <QtCrypto>
26
+#include "stunutil.h"
27
+
28
+#define ENSURE_D { if(!d) d = new Private; }
29
+
30
+namespace XMPP {
31
+
32
+using namespace StunUtil;
33
+
34
+// some attribute types we need to explicitly support
35
+enum
36
+{
37
+ AttribMessageIntegrity = 0x0008,
38
+ AttribFingerprint = 0x8028
39
+};
40
+
41
+// adapted from public domain source by Ross Williams and Eric Durbin
42
+unsigned long crctable256 =
43
+{
44
+ 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
45
+ 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
46
+ 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
47
+ 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
48
+ 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
49
+ 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
50
+ 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
51
+ 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
52
+ 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
53
+ 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
54
+ 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
55
+ 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
56
+ 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
57
+ 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
58
+ 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
59
+ 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
60
+ 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
61
+ 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
62
+ 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
63
+ 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
64
+ 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
65
+ 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
66
+ 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
67
+ 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
68
+ 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
69
+ 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
70
+ 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
71
+ 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
72
+ 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
73
+ 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
74
+ 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
75
+ 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
76
+ 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
77
+ 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
78
+ 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
79
+ 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
80
+ 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
81
+ 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
82
+ 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
83
+ 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
84
+ 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
85
+ 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
86
+ 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
87
+ 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
88
+ 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
89
+ 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
90
+ 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
91
+ 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
92
+ 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
93
+ 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
94
+ 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
95
+ 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
96
+ 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
97
+ 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
98
+ 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
99
+ 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
100
+ 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
101
+ 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
102
+ 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
103
+ 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
104
+ 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
105
+ 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
106
+ 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
107
+ 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
108
+};
109
+
110
+class Crc32
111
+{
112
+private:
113
+ quint32 result;
114
+
115
+public:
116
+ Crc32()
117
+ {
118
+ clear();
119
+ }
120
+
121
+ void clear()
122
+ {
123
+ result = 0xffffffff;
124
+ }
125
+
126
+ void update(const QByteArray &in)
127
+ {
128
+ for(int n = 0; n < in.size(); ++n)
129
+ result = (result >> 8) ^ (crctable(result & 0xff) ^ (quint8)inn);
130
+ }
131
+
132
+ quint32 final()
133
+ {
134
+ return result ^= 0xffffffff;
135
+ }
136
+
137
+ static quint32 process(const QByteArray &in)
138
+ {
139
+ Crc32 c;
140
+ c.update(in);
141
+ return c.final();
142
+ }
143
+};
144
+
145
+static quint8 magic_cookie4 = { 0x21, 0x12, 0xA4, 0x42 };
146
+
147
+// do 3-field check of stun packet
148
+// returns length of packet not counting the header, or -1 on error
149
+static int check_and_get_length(const QByteArray &buf)
150
+{
151
+ // stun packets are at least 20 bytes
152
+ if(buf.size() < 20)
153
+ return -1;
154
+
155
+ // minimal 3-field check
156
+
157
+ // top 2 bits of packet must be 0
158
+ if(buf0 & 0xC0)
159
+ return -1;
160
+
161
+ const quint8 *p = (const quint8 *)buf.data();
162
+ quint16 mlen = read16(p + 2);
163
+
164
+ // bottom 2 bits of message length field must be 0
165
+ if(mlen & 0x03)
166
+ return -1;
167
+
168
+ // (also, the message length should be a reasonable size)
169
+ if(mlen + 20 > buf.size())
170
+ return -1;
171
+
172
+ // magic cookie must be set
173
+ if(memcmp(p + 4, magic_cookie, 4) != 0)
174
+ return -1;
175
+
176
+ return mlen;
177
+}
178
+
179
+#define ATTRIBUTE_AREA_START 20
180
+#define ATTRIBUTE_AREA_MAX 65535
181
+#define ATTRIBUTE_VALUE_MAX 65531
182
+
183
+// note: because the attribute area of the packet has a maximum size of
184
+// 2^16-1, and each attribute itself has a 4 byte header, it follows that
185
+// the maximum size of an attribute's value is 2^16-5. this means that,
186
+// even if padded with up to 3 bytes, the physical size of an attribute's
187
+// value will not overflow a 16-bit unsigned integer.
188
+static quint16 round_up_length(quint16 in)
189
+{
190
+ Q_ASSERT(in <= ATTRIBUTE_VALUE_MAX);
191
+ quint16 out = in;
192
+ quint16 remainder = out % 4;
193
+ if(remainder != 0)
194
+ out += (4 - remainder);
195
+ return out;
196
+}
197
+
198
+// buf = entire stun packet
199
+// offset = byte index of current attribute (first is offset=20)
200
+// type = take attribute type
201
+// len = take attribute value length (value is at offset + 4)
202
+// returns offset of next attribute, -1 if no more
203
+static int get_attribute_props(const QByteArray &buf, int offset, quint16 *type, int *len)
204
+{
205
+ Q_ASSERT(offset >= ATTRIBUTE_AREA_START);
206
+
207
+ const quint8 *p = (const quint8 *)buf.data();
208
+
209
+ // need at least 4 bytes for an attribute
210
+ if(offset + 4 > buf.size())
211
+ return -1;
212
+
213
+ quint16 _type = read16(p + offset);
214
+ offset += 2;
215
+ quint16 _alen = read16(p + offset);
216
+ offset += 2;
217
+
218
+ // get physical length. stun attributes are 4-byte aligned, and may
219
+ // contain 0-3 bytes of padding.
220
+ quint16 plen = round_up_length(_alen);
221
+ if(offset + plen > buf.size())
222
+ return -1;
223
+
224
+ *type = _type;
225
+ *len = _alen;
226
+ return offset + plen;
227
+}
228
+
229
+// buf = entire stun packet
230
+// type = attribute type to find
231
+// len = take attribute value length (value is at offset + 4)
232
+// next = take offset of next attribute
233
+// returns offset of found attribute, -1 if not found
234
+static int find_attribute(const QByteArray &buf, quint16 type, int *len, int *next = 0)
235
+{
236
+ int at = ATTRIBUTE_AREA_START;
237
+ quint16 _type;
238
+ int _len;
239
+ int _next;
240
+
241
+ while(1)
242
+ {
243
+ _next = get_attribute_props(buf, at, &_type, &_len);
244
+ if(_next == -1)
245
+ break;
246
+ if(_type == type)
247
+ {
248
+ *len = _len;
249
+ if(next)
250
+ *next = _next;
251
+ return at;
252
+ }
253
+ at = _next;
254
+ }
255
+
256
+ return -1;
257
+}
258
+
259
+// buf = stun packet to append attribute to
260
+// type = type of attribute
261
+// len = length of value
262
+// returns offset of new attribute, or -1 if it can't fit
263
+// note: attribute value is located at offset + 4 and is uninitialized
264
+// note: padding following attribute is zeroed out
265
+static int append_attribute_uninitialized(QByteArray *buf, quint16 type, int len)
266
+{
267
+ if(len > ATTRIBUTE_VALUE_MAX)
268
+ return -1;
269
+
270
+ quint16 alen = (quint16)len;
271
+ quint16 plen = round_up_length(alen);
272
+
273
+ if((buf->size() - ATTRIBUTE_AREA_START) + 4 + plen > ATTRIBUTE_AREA_MAX)
274
+ return -1;
275
+
276
+ int at = buf->size();
277
+ buf->resize(buf->size() + 4 + plen);
278
+ quint8 *p = (quint8 *)buf->data();
279
+
280
+ write16(p + at, type);
281
+ write16(p + at + 2, alen);
282
+
283
+ // padding
284
+ for(int n = 0; n < plen - alen; ++n)
285
+ pat + alen + n = 0;
286
+
287
+ return at;
288
+}
289
+
290
+static quint32 fingerprint_calc(const quint8 *buf, int size)
291
+{
292
+ QByteArray region = QByteArray::fromRawData((const char *)buf, size);
293
+ return Crc32::process(region) ^ 0x5354554e;
294
+}
295
+
296
+static QByteArray message_integrity_calc(const quint8 *buf, int size, const QByteArray &key)
297
+{
298
+ QCA::MessageAuthenticationCode hmac("hmac(sha1)", key);
299
+ QByteArray region = QByteArray::fromRawData((const char *)buf, size);
300
+ QByteArray result = hmac.process(region).toByteArray();
301
+ Q_ASSERT(result.size() == 20);
302
+ return result;
303
+}
304
+
305
+// look for fingerprint attribute and confirm it
306
+// buf = entire stun packet
307
+// returns true if fingerprint attribute exists and is correct
308
+static bool fingerprint_check(const QByteArray &buf)
309
+{
310
+ int at, len;
311
+ at = find_attribute(buf, AttribFingerprint, &len);
312
+ if(at == -1 || len != 4) // value must be 4 bytes
313
+ return false;
314
+
315
+ const quint8 *p = (const quint8 *)buf.data();
316
+ quint32 fpval = read32(p + at + 4);
317
+ quint32 fpcalc = fingerprint_calc(p, at);
318
+ if(fpval == fpcalc)
319
+ return true;
320
+ else
321
+ return false;
322
+}
323
+
324
+// copy the input buffer and prepare for message integrity checking. the
325
+// packet is truncated after the message-integrity attribute (since nothing
326
+// after it is protected), and the packet length is adjusted in the header
327
+// accordingly.
328
+// buf = input stun packet
329
+// out = take output stun packet
330
+// offset = take offset of message-integrity attribute
331
+// returns true if message-integrity attribute exists and packet is prepared
332
+// note: message-integrity value is at offset + 4 and is exactly 20 bytes
333
+static bool message_integrity_prep(const QByteArray &buf, QByteArray *out, int *offset)
334
+{
335
+ int at, len, next;
336
+ at = find_attribute(buf, AttribMessageIntegrity, &len, &next);
337
+ if(at == -1 || len != 20) // value must be 20 bytes
338
+ return false;
339
+
340
+ // prepare new attribute area size
341
+ int i = next - ATTRIBUTE_AREA_START;
342
+
343
+ // new value must be divisible by 4
344
+ if(i % 4 != 0)
345
+ return false;
346
+
347
+ // copy truncated packet
348
+ *out = buf.mid(0, next);
349
+
350
+ // set new length in header
351
+ quint16 newlen = (quint16)i;
352
+ write16((quint8 *)out->data() + 2, newlen);
353
+
354
+ *offset = at;
355
+ return true;
356
+}
357
+
358
+// confirm message integrity
359
+// buf = prepared stun packet (from message_integrity_prep())
360
+// offset = offset of message-integrity attribute
361
+// key = the HMAC key
362
+// returns true if correct
363
+static bool message_integrity_check(const QByteArray &buf, int offset, const QByteArray &key)
364
+{
365
+ QByteArray mival = QByteArray::fromRawData(buf.data() + offset + 4, 20);
366
+ QByteArray micalc = message_integrity_calc((const quint8 *)buf.data(), offset, key);
367
+ if(mival == micalc)
368
+ return true;
369
+ else
370
+ return false;
371
+}
372
+
373
+class StunMessage::Private : public QSharedData
374
+{
375
+public:
376
+ StunMessage::Class mclass;
377
+ quint16 method;
378
+ quint8 magic4;
379
+ quint8 id12;
380
+ QList<Attribute> attribs;
381
+
382
+ Private()
383
+ {
384
+ mclass = (StunMessage::Class)-1;
385
+ method = 0;
386
+ memcpy(magic, magic_cookie, 4);
387
+ memset(id, 0, 12);
388
+ }
389
+};
390
+
391
+StunMessage::StunMessage() :
392
+ d(0)
393
+{
394
+}
395
+
396
+StunMessage::StunMessage(const StunMessage &from) :
397
+ d(from.d)
398
+{
399
+}
400
+
401
+StunMessage::~StunMessage()
402
+{
403
+}
404
+
405
+StunMessage & StunMessage::operator=(const StunMessage &from)
406
+{
407
+ d = from.d;
408
+ return *this;
409
+}
410
+
411
+bool StunMessage::isNull() const
412
+{
413
+ return (d ? false : true);
414
+}
415
+
416
+StunMessage::Class StunMessage::mclass() const
417
+{
418
+ Q_ASSERT(d);
419
+ return d->mclass;
420
+}
421
+
422
+quint16 StunMessage::method() const
423
+{
424
+ Q_ASSERT(d);
425
+ return d->method;
426
+}
427
+
428
+const quint8 *StunMessage::magic() const
429
+{
430
+ Q_ASSERT(d);
431
+ return d->magic;
432
+}
433
+
434
+const quint8 *StunMessage::id() const
435
+{
436
+ Q_ASSERT(d);
437
+ return d->id;
438
+}
439
+
440
+QList<StunMessage::Attribute> StunMessage::attributes() const
441
+{
442
+ Q_ASSERT(d);
443
+ return d->attribs;
444
+}
445
+
446
+QByteArray StunMessage::attribute(quint16 type) const
447
+{
448
+ Q_ASSERT(d);
449
+
450
+ foreach(const Attribute &i, d->attribs)
451
+ {
452
+ if(i.type == type)
453
+ return i.value;
454
+ }
455
+ return QByteArray();
456
+}
457
+
458
+void StunMessage::setClass(Class mclass)
459
+{
460
+ ENSURE_D
461
+ d->mclass = mclass;
462
+}
463
+
464
+void StunMessage::setMethod(quint16 method)
465
+{
466
+ ENSURE_D
467
+ d->method = method;
468
+}
469
+
470
+void StunMessage::setMagic(const quint8 *magic)
471
+{
472
+ ENSURE_D
473
+ memcpy(d->magic, magic, 4);
474
+}
475
+
476
+void StunMessage::setId(const quint8 *id)
477
+{
478
+ ENSURE_D
479
+ memcpy(d->id, id, 12);
480
+}
481
+
482
+void StunMessage::setAttributes(const QList<Attribute> &attribs)
483
+{
484
+ ENSURE_D
485
+ d->attribs = attribs;
486
+}
487
+
488
+QByteArray StunMessage::toBinary(int validationFlags, const QByteArray &key) const
489
+{
490
+ Q_ASSERT(d);
491
+
492
+ // header
493
+ QByteArray buf(20, 0);
494
+ quint8 *p = (quint8 *)buf.data();
495
+
496
+ quint8 classbits = 0;
497
+ if(d->mclass == Request)
498
+ classbits = 0; // 00
499
+ else if(d->mclass == Indication)
500
+ classbits = 1; // 01
501
+ else if(d->mclass == SuccessResponse)
502
+ classbits = 2; // 10
503
+ else if(d->mclass == ErrorResponse)
504
+ classbits = 3; // 11
505
+ else
506
+ Q_ASSERT(0);
507
+
508
+ // method bits are split into 3 sections
509
+ quint16 m1, m2, m3;
510
+ m1 = d->method & 0x0f80; // M7-11
511
+ m1 <<= 2;
512
+ m2 = d->method & 0x0070; // M4-6
513
+ m2 <<= 1;
514
+ m3 = d->method & 0x000f; // M0-3
515
+
516
+ // class bits are split into 2 sections
517
+ quint16 c1, c2;
518
+ c1 = classbits & 0x02; // C1
519
+ c1 <<= 7;
520
+ c2 = classbits & 0x01; // C0
521
+ c2 <<= 4;
522
+
523
+ quint16 type = m1 | m2 | m3 | c1 | c2;
524
+ write16(p, type);
525
+ write16(p + 2, 0);
526
+ memcpy(p + 4, d->magic, 4);
527
+ memcpy(p + 8, d->id, 12);
528
+
529
+ foreach(const Attribute &i, d->attribs)
530
+ {
531
+ int at = append_attribute_uninitialized(&buf, i.type, i.value.size());
532
+ if(at == -1)
533
+ return QByteArray();
534
+
535
+ p = (quint8 *)buf.data(); // follow the resize
536
+
537
+ memcpy(buf.data() + at + 4, i.value.data(), i.value.size());
538
+ }
539
+
540
+ // set attribute area size
541
+ write16(p + 2, buf.size() - ATTRIBUTE_AREA_START);
542
+
543
+ if(validationFlags & MessageIntegrity)
544
+ {
545
+ quint16 alen = 20; // size of hmac(sha1)
546
+ int at = append_attribute_uninitialized(&buf, AttribMessageIntegrity, alen);
547
+ if(at == -1)
548
+ return QByteArray();
549
+
550
+ p = (quint8 *)buf.data(); // follow the resize
551
+
552
+ // set attribute area size to include the new attribute
553
+ write16(p + 2, buf.size() - ATTRIBUTE_AREA_START);
554
+
555
+ // now calculate the hash and fill in the value
556
+ QByteArray result = message_integrity_calc(p, at, key);
557
+ Q_ASSERT(result.size() == alen);
558
+ memcpy(p + at + 4, result.data(), alen);
559
+ }
560
+
561
+ if(validationFlags & Fingerprint)
562
+ {
563
+ quint16 alen = 4; // size of crc32
564
+ int at = append_attribute_uninitialized(&buf, AttribFingerprint, alen);
565
+ if(at == -1)
566
+ return QByteArray();
567
+
568
+ p = (quint8 *)buf.data(); // follow the resize
569
+
570
+ // set attribute area size to include the new attribute
571
+ write16(p + 2, buf.size() - ATTRIBUTE_AREA_START);
572
+
573
+ // now calculate the fingerprint and fill in the value
574
+ quint32 fpcalc = fingerprint_calc(p, at);
575
+ write32(p + at + 4, fpcalc);
576
+ }
577
+
578
+ return buf;
579
+}
580
+
581
+StunMessage StunMessage::fromBinary(const QByteArray &a, ConvertResult *result, int validationFlags, const QByteArray &key)
582
+{
583
+ int mlen = check_and_get_length(a);
584
+ if(mlen == -1)
585
+ {
586
+ if(result)
587
+ *result = ErrorFormat;
588
+ return StunMessage();
589
+ }
590
+
591
+ if(validationFlags & Fingerprint)
592
+ {
593
+ if(!fingerprint_check(a))
594
+ {
595
+ if(result)
596
+ *result = ErrorFingerprint;
597
+ return StunMessage();
598
+ }
599
+ }
600
+
601
+ QByteArray in;
602
+
603
+ if(validationFlags & MessageIntegrity)
604
+ {
605
+ int offset;
606
+ if(!message_integrity_prep(a, &in, &offset))
607
+ {
608
+ if(result)
609
+ *result = ErrorMessageIntegrity;
610
+ return StunMessage();
611
+ }
612
+
613
+ if(!message_integrity_check(in, offset, key))
614
+ {
615
+ if(result)
616
+ *result = ErrorMessageIntegrity;
617
+ return StunMessage();
618
+ }
619
+ }
620
+ else
621
+ in = a;
622
+
623
+ // all validating complete, now just parse the packet
624
+
625
+ const quint8 *p = (const quint8 *)in.data();
626
+
627
+ // method bits are split into 3 sections
628
+ quint16 m1, m2, m3;
629
+ m1 = p0 & 0x3e; // M7-11
630
+ m1 <<= 6;
631
+ m2 = p1 & 0xe0; // M4-6
632
+ m2 >>= 1;
633
+ m3 = p1 & 0x0f; // M0-3
634
+
635
+ // class bits are split into 2 sections
636
+ quint8 c1, c2;
637
+ c1 = p0 & 0x01; // C1
638
+ c1 <<= 1;
639
+ c2 = p1 & 0x10; // C0
640
+ c2 >>= 4;
641
+
642
+ quint16 method = m1 | m2 | m3;
643
+ quint8 classbits = c1 | c2;
644
+
645
+ Class mclass;
646
+ if(classbits == 0) // 00
647
+ mclass = Request;
648
+ else if(classbits == 1) // 01
649
+ mclass = Indication;
650
+ else if(classbits == 2) // 10
651
+ mclass = SuccessResponse;
652
+ else // 11
653
+ mclass = ErrorResponse;
654
+
655
+ StunMessage out;
656
+ out.setClass(mclass);
657
+ out.setMethod(method);
658
+ out.setMagic(p + 4);
659
+ out.setId(p + 8);
660
+
661
+ QList<Attribute> list;
662
+ int at = ATTRIBUTE_AREA_START;
663
+ while(1)
664
+ {
665
+ quint16 type;
666
+ int len;
667
+ int next;
668
+
669
+ next = get_attribute_props(in, at, &type, &len);
670
+ if(next == -1)
671
+ break;
672
+
673
+ Attribute attrib;
674
+ attrib.type = type;
675
+ attrib.value = in.mid(at + 4, len);
676
+ list += attrib;
677
+
678
+ at = next;
679
+ }
680
+ out.setAttributes(list);
681
+
682
+ if(result)
683
+ *result = ConvertGood;
684
+ return out;
685
+}
686
+
687
+bool StunMessage::isProbablyStun(const QByteArray &a)
688
+{
689
+ return (check_and_get_length(a) != -1 ? true : false);
690
+}
691
+
692
+StunMessage::Class StunMessage::extractClass(const QByteArray &in)
693
+{
694
+ const quint8 *p = (const quint8 *)in.data();
695
+
696
+ // class bits are split into 2 sections
697
+ quint8 c1, c2;
698
+ c1 = p0 & 0x01; // C1
699
+ c1 <<= 1;
700
+ c2 = p1 & 0x10; // C0
701
+ c2 >>= 4;
702
+
703
+ quint8 classbits = c1 | c2;
704
+
705
+ Class mclass;
706
+ if(classbits == 0) // 00
707
+ mclass = Request;
708
+ else if(classbits == 1) // 01
709
+ mclass = Indication;
710
+ else if(classbits == 2) // 10
711
+ mclass = SuccessResponse;
712
+ else // 11
713
+ mclass = ErrorResponse;
714
+
715
+ return mclass;
716
+}
717
+
718
+bool StunMessage::containsStun(const quint8 *data, int size)
719
+{
720
+ // check_and_get_length does a full packet check so it works even on a stream
721
+ return (check_and_get_length(QByteArray::fromRawData((const char *)data, size)) != -1 ? true : false);
722
+}
723
+
724
+QByteArray StunMessage::readStun(const quint8 *data, int size)
725
+{
726
+ QByteArray in = QByteArray::fromRawData((const char *)data, size);
727
+ int mlen = check_and_get_length(in);
728
+ if(mlen != -1)
729
+ return QByteArray((const char *)data, mlen + 20);
730
+ else
731
+ return QByteArray();
732
+}
733
+
734
+}
735
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunmessage.h
Added
113
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNMESSAGE_H
23
+#define STUNMESSAGE_H
24
+
25
+#include <QByteArray>
26
+#include <QList>
27
+#include <QSharedDataPointer>
28
+
29
+namespace XMPP {
30
+
31
+class StunMessage
32
+{
33
+public:
34
+ enum Class
35
+ {
36
+ Request,
37
+ SuccessResponse,
38
+ ErrorResponse,
39
+ Indication
40
+ };
41
+
42
+ enum ValidationFlags
43
+ {
44
+ Fingerprint = 0x01,
45
+
46
+ // you must have the hmac(sha1) algorithm in QCA to use
47
+ MessageIntegrity = 0x02
48
+ };
49
+
50
+ enum ConvertResult
51
+ {
52
+ ConvertGood,
53
+ ErrorFormat,
54
+ ErrorFingerprint,
55
+ ErrorMessageIntegrity,
56
+ ErrorConvertUnknown = 64
57
+ };
58
+
59
+ class Attribute
60
+ {
61
+ public:
62
+ quint16 type;
63
+ QByteArray value;
64
+ };
65
+
66
+ StunMessage();
67
+ StunMessage(const StunMessage &from);
68
+ ~StunMessage();
69
+ StunMessage & operator=(const StunMessage &from);
70
+
71
+ bool isNull() const;
72
+ Class mclass() const;
73
+ quint16 method() const;
74
+ const quint8 *magic() const; // 4 bytes
75
+ const quint8 *id() const; // 12 bytes
76
+ QList<Attribute> attributes() const;
77
+
78
+ // returns the first instance or null
79
+ QByteArray attribute(quint16 type) const;
80
+
81
+ void setClass(Class mclass);
82
+ void setMethod(quint16 method);
83
+ void setMagic(const quint8 *magic); // 4 bytes
84
+ void setId(const quint8 *id); // 12 bytes
85
+ void setAttributes(const QList<Attribute> &attribs);
86
+
87
+ QByteArray toBinary(int validationFlags = 0, const QByteArray &key = QByteArray()) const;
88
+ static StunMessage fromBinary(const QByteArray &a, ConvertResult *result = 0, int validationFlags = 0, const QByteArray &key = QByteArray());
89
+
90
+ // minimal 3-field check
91
+ static bool isProbablyStun(const QByteArray &a);
92
+
93
+ // extract out the class value from a raw packet. assumes that 'a' has
94
+ // already passed isProbablyStun()
95
+ static Class extractClass(const QByteArray &a);
96
+
97
+ // examine raw data, such as from a stream, to see if it contains a
98
+ // stun packet
99
+ static bool containsStun(const quint8 *data, int size);
100
+
101
+ // try to read a stun packet from the raw data, else return null.
102
+ // a successful result can be passed to fromBinary()
103
+ static QByteArray readStun(const quint8 *data, int size);
104
+
105
+private:
106
+ class Private;
107
+ QSharedDataPointer<Private> d;
108
+};
109
+
110
+}
111
+
112
+#endif
113
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stuntransaction.cpp
Added
747
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stuntransaction.h"
23
+
24
+#include <QHash>
25
+#include <QMetaType>
26
+#include <QTime>
27
+#include <QTimer>
28
+#include <QtCrypto>
29
+#include "stunutil.h"
30
+#include "stunmessage.h"
31
+#include "stuntypes.h"
32
+
33
+Q_DECLARE_METATYPE(XMPP::StunTransaction::Error)
34
+
35
+namespace XMPP {
36
+
37
+// parse a stun message, optionally performing validity checks. the
38
+// StunMessage class itself provides parsing with validity or parsing
39
+// without validity, but it does not provide a way to do both together,
40
+// so we attempt to do that here.
41
+// TODO: consider moving this code into StunMessage
42
+static StunMessage parse_stun_message(const QByteArray &packet, int *validationFlags, const QByteArray &key)
43
+{
44
+ // ideally we shouldn't fully parse the packet more than once. the
45
+ // integrity checks performed by fromBinary do not require fully
46
+ // parsing the packet, so we should be able to avoid most redundant
47
+ // processing. fromBinary checks the fingerprint first, and we
48
+ // can use that knowledge to avoid duplicating integrity checks.
49
+ int flags = 0;
50
+ StunMessage::ConvertResult result;
51
+ StunMessage msg = StunMessage::fromBinary(packet, &result, StunMessage::MessageIntegrity | StunMessage::Fingerprint, key);
52
+ if(result == StunMessage::ErrorFingerprint)
53
+ {
54
+ // if fingerprint fails, then it is the only thing that was
55
+ // performed and we can skip it now.
56
+ msg = StunMessage::fromBinary(packet, &result, StunMessage::MessageIntegrity, key);
57
+ if(result == StunMessage::ErrorMessageIntegrity)
58
+ {
59
+ // if message-integrity fails, then it is the only
60
+ // thing that was performed and we can skip it now
61
+ msg = StunMessage::fromBinary(packet, &result);
62
+ if(result == StunMessage::ConvertGood)
63
+ flags = 0;
64
+ else
65
+ return msg; // null
66
+ }
67
+ else if(result == StunMessage::ConvertGood)
68
+ flags = StunMessage::MessageIntegrity;
69
+ else
70
+ return msg; // null
71
+ }
72
+ else if(result == StunMessage::ErrorMessageIntegrity)
73
+ {
74
+ // fingerprint succeeded, but message-integrity failed. parse
75
+ // without validation now (to skip redundant
76
+ // fingerprint/message-integrity checks), and assume correct
77
+ // fingerprint
78
+ msg = StunMessage::fromBinary(packet, &result);
79
+ if(result == StunMessage::ConvertGood)
80
+ flags = StunMessage::Fingerprint;
81
+ else
82
+ return msg; // null
83
+ }
84
+ else if(result == StunMessage::ConvertGood)
85
+ flags = StunMessage::MessageIntegrity | StunMessage::Fingerprint;
86
+ else
87
+ return msg; // null
88
+
89
+ *validationFlags = flags;
90
+ return msg;
91
+}
92
+
93
+class StunTransactionPoolPrivate : public QObject
94
+{
95
+ Q_OBJECT
96
+
97
+public:
98
+ StunTransactionPool *q;
99
+ StunTransaction::Mode mode;
100
+ QSet<StunTransaction*> transactions;
101
+ QHash<StunTransaction*,QByteArray> transToId;
102
+ QHash<QByteArray,StunTransaction*> idToTrans;
103
+ bool useLongTermAuth;
104
+ bool needLongTermAuth;
105
+ bool triedLongTermAuth;
106
+ QString user;
107
+ QCA::SecureArray pass;
108
+ QString realm;
109
+ QString nonce;
110
+ int debugLevel;
111
+
112
+ StunTransactionPoolPrivate(StunTransactionPool *_q) :
113
+ QObject(_q),
114
+ q(_q),
115
+ useLongTermAuth(false),
116
+ needLongTermAuth(false),
117
+ triedLongTermAuth(false),
118
+ debugLevel(StunTransactionPool::DL_None)
119
+ {
120
+ }
121
+
122
+ QByteArray generateId() const;
123
+ void insert(StunTransaction *trans);
124
+ void remove(StunTransaction *trans);
125
+ void transmit(StunTransaction *trans);
126
+};
127
+
128
+//----------------------------------------------------------------------------
129
+// StunTransaction
130
+//----------------------------------------------------------------------------
131
+class StunTransactionPrivate : public QObject
132
+{
133
+ Q_OBJECT
134
+
135
+public:
136
+ StunTransaction *q;
137
+
138
+ StunTransactionPool *pool;
139
+ bool active;
140
+ StunTransaction::Mode mode;
141
+ StunMessage origMessage;
142
+ QByteArray id;
143
+ QByteArray packet;
144
+ QHostAddress to_addr;
145
+ int to_port;
146
+
147
+ int rto, rc, rm, ti;
148
+ int tries;
149
+ int last_interval;
150
+ QTimer *t;
151
+
152
+ QString stuser;
153
+ QString stpass;
154
+ bool fpRequired;
155
+ QByteArray key;
156
+ QTime time;
157
+
158
+ StunTransactionPrivate(StunTransaction *_q) :
159
+ QObject(_q),
160
+ q(_q),
161
+ pool(0),
162
+ fpRequired(false)
163
+ {
164
+ qRegisterMetaType<StunTransaction::Error>();
165
+
166
+ active = false;
167
+
168
+ t = new QTimer(this);
169
+ connect(t, SIGNAL(timeout()), SLOT(t_timeout()));
170
+ t->setSingleShot(true);
171
+
172
+ // defaults from RFC 5389
173
+ rto = 500;
174
+ rc = 7;
175
+ rm = 16;
176
+ ti = 39500;
177
+ }
178
+
179
+ ~StunTransactionPrivate()
180
+ {
181
+ if(pool)
182
+ pool->d->remove(q);
183
+
184
+ t->disconnect(this);
185
+ t->setParent(0);
186
+ t->deleteLater();
187
+ }
188
+
189
+ void start(StunTransactionPool *_pool, const QHostAddress &toAddress, int toPort)
190
+ {
191
+ pool = _pool;
192
+ mode = pool->d->mode;
193
+ to_addr = toAddress;
194
+ to_port = toPort;
195
+
196
+ tryRequest();
197
+ }
198
+
199
+ void setMessage(const StunMessage &request)
200
+ {
201
+ origMessage = request;
202
+ }
203
+
204
+ void retry()
205
+ {
206
+ Q_ASSERT(!active);
207
+ pool->d->remove(q);
208
+
209
+ tryRequest();
210
+ }
211
+
212
+ void tryRequest()
213
+ {
214
+ emit q->createMessage(pool->d->generateId());
215
+
216
+ if(origMessage.isNull())
217
+ {
218
+ // since a transaction is not cancelable nor reusable,
219
+ // there's no DOR-SR issue here
220
+ QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection,
221
+ Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric));
222
+ return;
223
+ }
224
+
225
+ StunMessage out = origMessage;
226
+
227
+ out.setClass(StunMessage::Request);
228
+ id = QByteArray((const char *)out.id(), 12);
229
+
230
+ if(!stuser.isEmpty())
231
+ {
232
+ QList<StunMessage::Attribute> list = out.attributes();
233
+ StunMessage::Attribute attr;
234
+ attr.type = StunTypes::USERNAME;
235
+ attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(stuser.toUtf8()).toByteArray()));
236
+ list += attr;
237
+ out.setAttributes(list);
238
+
239
+ key = StunUtil::saslPrep(stpass.toUtf8()).toByteArray();
240
+ }
241
+ else if(!pool->d->nonce.isEmpty())
242
+ {
243
+ QList<StunMessage::Attribute> list = out.attributes();
244
+ {
245
+ StunMessage::Attribute attr;
246
+ attr.type = StunTypes::USERNAME;
247
+ attr.value = StunTypes::createUsername(QString::fromUtf8(StunUtil::saslPrep(pool->d->user.toUtf8()).toByteArray()));
248
+ list += attr;
249
+ }
250
+ {
251
+ StunMessage::Attribute attr;
252
+ attr.type = StunTypes::REALM;
253
+ attr.value = StunTypes::createRealm(pool->d->realm);
254
+ list += attr;
255
+ }
256
+ {
257
+ StunMessage::Attribute attr;
258
+ attr.type = StunTypes::NONCE;
259
+ attr.value = StunTypes::createNonce(pool->d->nonce);
260
+ list += attr;
261
+ }
262
+ out.setAttributes(list);
263
+
264
+ QCA::SecureArray buf;
265
+ buf += StunUtil::saslPrep(pool->d->user.toUtf8());
266
+ buf += QByteArray(1, ':');
267
+ buf += StunUtil::saslPrep(pool->d->realm.toUtf8());
268
+ buf += QByteArray(1, ':');
269
+ buf += StunUtil::saslPrep(pool->d->pass);
270
+
271
+ key = QCA::Hash("md5").process(buf).toByteArray();
272
+ }
273
+
274
+ if(!key.isEmpty())
275
+ packet = out.toBinary(StunMessage::MessageIntegrity | StunMessage::Fingerprint, key);
276
+ else
277
+ packet = out.toBinary(StunMessage::Fingerprint);
278
+
279
+ if(packet.isEmpty())
280
+ {
281
+ // since a transaction is not cancelable nor reusable,
282
+ // there's no DOR-SR issue here
283
+ QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection,
284
+ Q_ARG(XMPP::StunTransaction::Error, StunTransaction::ErrorGeneric));
285
+ return;
286
+ }
287
+
288
+ active = true;
289
+ tries = 1; // we transmit immediately here, so count it
290
+
291
+ if(mode == StunTransaction::Udp)
292
+ {
293
+ last_interval = rm * rto;
294
+ t->start(rto);
295
+ rto *= 2;
296
+ }
297
+ else if(mode == StunTransaction::Tcp)
298
+ {
299
+ t->start(ti);
300
+ }
301
+ else
302
+ Q_ASSERT(0);
303
+
304
+ time.start();
305
+ pool->d->insert(q);
306
+ transmit();
307
+ }
308
+
309
+private slots:
310
+ void t_timeout()
311
+ {
312
+ if(mode == StunTransaction::Tcp || tries == rc)
313
+ {
314
+ pool->d->remove(q);
315
+ emit q->error(StunTransaction::ErrorTimeout);
316
+ return;
317
+ }
318
+
319
+ ++tries;
320
+ if(tries == rc)
321
+ {
322
+ t->start(last_interval);
323
+ }
324
+ else
325
+ {
326
+ t->start(rto);
327
+ rto *= 2;
328
+ }
329
+
330
+ transmit();
331
+ }
332
+
333
+private:
334
+ void transmit()
335
+ {
336
+ if(pool->d->debugLevel >= StunTransactionPool::DL_Packet)
337
+ {
338
+ QString str = QString("STUN SEND: elapsed=") + QString::number(time.elapsed());
339
+ if(!to_addr.isNull())
340
+ str += QString(" to=(") + to_addr.toString() + ';' + QString::number(to_port) + ')';
341
+ emit pool->debugLine(str);
342
+
343
+ StunMessage msg = StunMessage::fromBinary(packet);
344
+ emit pool->debugLine(StunTypes::print_packet_str(msg));
345
+ }
346
+
347
+ pool->d->transmit(q);
348
+ }
349
+
350
+ bool checkActiveAndFrom(const QHostAddress &from_addr, int from_port)
351
+ {
352
+ if(!active)
353
+ return false;
354
+
355
+ if(!to_addr.isNull() && (to_addr != from_addr || to_port != from_port))
356
+ return false;
357
+
358
+ return true;
359
+ }
360
+
361
+ void processIncoming(const StunMessage &msg, bool authed)
362
+ {
363
+ active = false;
364
+ t->stop();
365
+
366
+ if(pool->d->debugLevel >= StunTransactionPool::DL_Packet)
367
+ emit pool->debugLine(QString("matched incoming response to existing request. elapsed=") + QString::number(time.elapsed()));
368
+
369
+ // will be set to true when receiving an Unauthorized error
370
+ bool unauthError = false;
371
+
372
+ if(msg.mclass() == StunMessage::ErrorResponse && pool->d->useLongTermAuth)
373
+ {
374
+ // we'll handle certain error codes at this layer
375
+ int code;
376
+ QString reason;
377
+ if(StunTypes::parseErrorCode(msg.attribute(StunTypes::ERROR_CODE), &code, &reason))
378
+ {
379
+ if(code == StunTypes::Unauthorized)
380
+ unauthError = true;
381
+
382
+ if(unauthError && !pool->d->triedLongTermAuth)
383
+ {
384
+ QString realm;
385
+ QString nonce;
386
+ if(StunTypes::parseRealm(msg.attribute(StunTypes::REALM), &realm) &&
387
+ StunTypes::parseRealm(msg.attribute(StunTypes::NONCE), &nonce))
388
+ {
389
+ // always set these to the latest received values,
390
+ // which will be used for all transactions
391
+ // once creds are provided.
392
+ if(pool->d->realm.isEmpty())
393
+ pool->d->realm = realm;
394
+ pool->d->nonce = nonce;
395
+
396
+ if(!pool->d->needLongTermAuth)
397
+ {
398
+ if(!pool->d->user.isEmpty())
399
+ {
400
+ // creds already set? use them
401
+ pool->d->triedLongTermAuth = true;
402
+ retry();
403
+ }
404
+ else
405
+ {
406
+ // else ask the user
407
+ pool->d->needLongTermAuth = true;
408
+ emit pool->needAuthParams();
409
+ }
410
+ }
411
+ return;
412
+ }
413
+ }
414
+ else if(code == StunTypes::StaleNonce && pool->d->triedLongTermAuth)
415
+ {
416
+ QString nonce;
417
+ if(StunTypes::parseNonce(msg.attribute(StunTypes::NONCE), &nonce) && nonce != pool->d->nonce)
418
+ {
419
+ pool->d->nonce = nonce;
420
+ retry();
421
+ return;
422
+ }
423
+ }
424
+ }
425
+ }
426
+
427
+ // require message integrity when auth is used
428
+ if(!unauthError && (!stuser.isEmpty() || pool->d->triedLongTermAuth) && !authed)
429
+ return;
430
+
431
+ pool->d->remove(q);
432
+ emit q->finished(msg);
433
+ }
434
+
435
+public:
436
+ bool writeIncomingMessage(const StunMessage &msg, const QHostAddress &from_addr, int from_port)
437
+ {
438
+ if(!checkActiveAndFrom(from_addr, from_port))
439
+ return false;
440
+
441
+ // if a StunMessage is passed directly to us then we assume
442
+ // the user has authenticated the message as necessary
443
+ processIncoming(msg, true);
444
+ return true;
445
+ }
446
+
447
+ bool writeIncomingMessage(const QByteArray &packet, bool *notStun, const QHostAddress &from_addr, int from_port)
448
+ {
449
+ if(!checkActiveAndFrom(from_addr, from_port))
450
+ {
451
+ // could be STUN, don't really know for sure
452
+ *notStun = false;
453
+ return false;
454
+ }
455
+
456
+ int validationFlags = 0;
457
+ StunMessage msg = parse_stun_message(packet, &validationFlags, key);
458
+ if(msg.isNull())
459
+ {
460
+ // packet doesn't parse at all, surely not STUN
461
+ *notStun = true;
462
+ return false;
463
+ }
464
+
465
+ if(fpRequired && !(validationFlags & StunMessage::Fingerprint))
466
+ {
467
+ // fingerprint failed when required. consider the
468
+ // packet to be surely not STUN
469
+ *notStun = true;
470
+ return false;
471
+ }
472
+
473
+ processIncoming(msg, (validationFlags & StunMessage::MessageIntegrity) ? true : false);
474
+ return true;
475
+ }
476
+
477
+public slots:
478
+ void continueAfterParams()
479
+ {
480
+ retry();
481
+ }
482
+};
483
+
484
+StunTransaction::StunTransaction(QObject *parent) :
485
+ QObject(parent)
486
+{
487
+ d = new StunTransactionPrivate(this);
488
+}
489
+
490
+StunTransaction::~StunTransaction()
491
+{
492
+ delete d;
493
+}
494
+
495
+void StunTransaction::start(StunTransactionPool *pool, const QHostAddress &toAddress, int toPort)
496
+{
497
+ Q_ASSERT(!d->active);
498
+ d->start(pool, toAddress, toPort);
499
+}
500
+
501
+void StunTransaction::setMessage(const StunMessage &request)
502
+{
503
+ d->setMessage(request);
504
+}
505
+
506
+void StunTransaction::setRTO(int i)
507
+{
508
+ Q_ASSERT(!d->active);
509
+ d->rto = i;
510
+}
511
+
512
+void StunTransaction::setRc(int i)
513
+{
514
+ Q_ASSERT(!d->active);
515
+ d->rc = i;
516
+}
517
+
518
+void StunTransaction::setRm(int i)
519
+{
520
+ Q_ASSERT(!d->active);
521
+ d->rm = i;
522
+}
523
+
524
+void StunTransaction::setTi(int i)
525
+{
526
+ Q_ASSERT(!d->active);
527
+ d->ti = i;
528
+}
529
+
530
+void StunTransaction::setShortTermUsername(const QString &username)
531
+{
532
+ d->stuser = username;
533
+}
534
+
535
+void StunTransaction::setShortTermPassword(const QString &password)
536
+{
537
+ d->stpass = password;
538
+}
539
+
540
+void StunTransaction::setFingerprintRequired(bool enabled)
541
+{
542
+ d->fpRequired = enabled;
543
+}
544
+
545
+//----------------------------------------------------------------------------
546
+// StunTransactionPool
547
+//----------------------------------------------------------------------------
548
+QByteArray StunTransactionPoolPrivate::generateId() const
549
+{
550
+ QByteArray id;
551
+
552
+ do
553
+ {
554
+ id = QCA::Random::randomArray(12).toByteArray();
555
+ } while(idToTrans.contains(id));
556
+
557
+ return id;
558
+}
559
+
560
+void StunTransactionPoolPrivate::insert(StunTransaction *trans)
561
+{
562
+ Q_ASSERT(!trans->d->id.isEmpty());
563
+
564
+ transactions.insert(trans);
565
+ QByteArray id = trans->d->id;
566
+ transToId.insert(trans, id);
567
+ idToTrans.insert(id, trans);
568
+}
569
+
570
+void StunTransactionPoolPrivate::remove(StunTransaction *trans)
571
+{
572
+ if(transactions.contains(trans))
573
+ {
574
+ transactions.remove(trans);
575
+ QByteArray id = transToId.value(trans);
576
+ transToId.remove(trans);
577
+ idToTrans.remove(id);
578
+ }
579
+}
580
+
581
+void StunTransactionPoolPrivate::transmit(StunTransaction *trans)
582
+{
583
+ emit q->outgoingMessage(trans->d->packet, trans->d->to_addr, trans->d->to_port);
584
+}
585
+
586
+StunTransactionPool::StunTransactionPool(StunTransaction::Mode mode, QObject *parent) :
587
+ QObject(parent)
588
+{
589
+ d = new StunTransactionPoolPrivate(this);
590
+ d->mode = mode;
591
+}
592
+
593
+StunTransactionPool::~StunTransactionPool()
594
+{
595
+ delete d;
596
+}
597
+
598
+StunTransaction::Mode StunTransactionPool::mode() const
599
+{
600
+ return d->mode;
601
+}
602
+
603
+bool StunTransactionPool::writeIncomingMessage(const StunMessage &msg, const QHostAddress &addr, int port)
604
+{
605
+ if(d->debugLevel >= DL_Packet)
606
+ {
607
+ QString str = "STUN RECV";
608
+ if(!addr.isNull())
609
+ str += QString(" from=(") + addr.toString() + ';' + QString::number(port) + ')';
610
+ emit debugLine(str);
611
+ emit debugLine(StunTypes::print_packet_str(msg));
612
+ }
613
+
614
+ QByteArray id = QByteArray::fromRawData((const char *)msg.id(), 12);
615
+ StunMessage::Class mclass = msg.mclass();
616
+
617
+ if(mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse)
618
+ return false;
619
+
620
+ StunTransaction *trans = d->idToTrans.value(id);
621
+ if(!trans)
622
+ return false;
623
+
624
+ return trans->d->writeIncomingMessage(msg, addr, port);
625
+}
626
+
627
+bool StunTransactionPool::writeIncomingMessage(const QByteArray &packet, bool *notStun, const QHostAddress &addr, int port)
628
+{
629
+ if(!StunMessage::isProbablyStun(packet))
630
+ {
631
+ // basic stun check failed? surely not STUN
632
+ if(notStun)
633
+ *notStun = true;
634
+ return false;
635
+ }
636
+
637
+ if(d->debugLevel >= DL_Packet)
638
+ {
639
+ StunMessage msg = StunMessage::fromBinary(packet);
640
+ QString str = "STUN RECV";
641
+ if(!addr.isNull())
642
+ str += QString(" from=(") + addr.toString() + ';' + QString::number(port) + ')';
643
+ emit debugLine(str);
644
+ emit debugLine(StunTypes::print_packet_str(msg));
645
+ }
646
+
647
+ // isProbablyStun ensures the packet is 20 bytes long, so we can safely
648
+ // safely extract out the transaction id from the raw packet
649
+ QByteArray id = QByteArray((const char *)packet.data() + 8, 12);
650
+
651
+ StunMessage::Class mclass = StunMessage::extractClass(packet);
652
+
653
+ if(mclass != StunMessage::SuccessResponse && mclass != StunMessage::ErrorResponse)
654
+ {
655
+ // could be STUN, don't really know for sure
656
+ if(notStun)
657
+ *notStun = false;
658
+ return false;
659
+ }
660
+
661
+ StunTransaction *trans = d->idToTrans.value(id);
662
+ if(!trans)
663
+ {
664
+ // could be STUN, don't really know for sure
665
+ if(notStun)
666
+ *notStun = false;
667
+ return false;
668
+ }
669
+
670
+ bool _notStun = false;
671
+ bool ret = trans->d->writeIncomingMessage(packet, &_notStun, addr, port);
672
+ if(!ret && notStun)
673
+ *notStun = _notStun;
674
+ return ret;
675
+}
676
+
677
+void StunTransactionPool::setLongTermAuthEnabled(bool enabled)
678
+{
679
+ d->useLongTermAuth = enabled;
680
+}
681
+
682
+QString StunTransactionPool::realm() const
683
+{
684
+ return d->realm;
685
+}
686
+
687
+void StunTransactionPool::setUsername(const QString &username)
688
+{
689
+ d->user = username;
690
+}
691
+
692
+void StunTransactionPool::setPassword(const QCA::SecureArray &password)
693
+{
694
+ d->pass = password;
695
+}
696
+
697
+void StunTransactionPool::setRealm(const QString &realm)
698
+{
699
+ d->realm = realm;
700
+}
701
+
702
+void StunTransactionPool::continueAfterParams()
703
+{
704
+ if(d->debugLevel >= DL_Info)
705
+ {
706
+ emit debugLine("continue after params:");
707
+ emit debugLine(QString(" U=%1").arg(d->user));
708
+ emit debugLine(QString(" P=%1").arg(d->pass.data()));
709
+ emit debugLine(QString(" R=%1").arg(d->realm));
710
+ emit debugLine(QString(" N=%1").arg(d->nonce));
711
+ }
712
+
713
+ Q_ASSERT(d->useLongTermAuth);
714
+ Q_ASSERT(d->needLongTermAuth);
715
+ Q_ASSERT(!d->triedLongTermAuth);
716
+
717
+ d->needLongTermAuth = false;
718
+ d->triedLongTermAuth = true;
719
+
720
+ foreach(StunTransaction *trans, d->transactions)
721
+ {
722
+ // the only reason an inactive transaction would be in the
723
+ // list is if it is waiting for an auth retry
724
+ if(!trans->d->active)
725
+ {
726
+ // use queued call to prevent all sorts of DOR-SS
727
+ // nastiness
728
+ QMetaObject::invokeMethod(trans->d, "continueAfterParams",
729
+ Qt::QueuedConnection);
730
+ }
731
+ }
732
+}
733
+
734
+QByteArray StunTransactionPool::generateId() const
735
+{
736
+ return d->generateId();
737
+}
738
+
739
+void StunTransactionPool::setDebugLevel(DebugLevel level)
740
+{
741
+ d->debugLevel = level;
742
+}
743
+
744
+}
745
+
746
+#include "stuntransaction.moc"
747
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stuntransaction.h
Added
209
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNTRANSACTION_H
23
+#define STUNTRANSACTION_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+#include <QHostAddress>
28
+
29
+namespace QCA {
30
+ class SecureArray;
31
+}
32
+
33
+namespace XMPP {
34
+
35
+class StunMessage;
36
+
37
+class StunTransactionPrivate;
38
+class StunTransactionPool;
39
+class StunTransactionPoolPrivate;
40
+
41
+// Notes:
42
+//
43
+// - we allow multiple simultaneous requests. no serializing or waiting, at
44
+// least not at the transaction layer.
45
+// - requests may require authentication. the protocol flow for STUN is that
46
+// you first try a request without providing credentials, and if
47
+// authentication is needed then an error is returned. the request must be
48
+// tried again with credentials provided for it to succeed. note that the
49
+// error response contains a nonce value that must be passed back in the
50
+// second request, and so the first request cannot be skipped.
51
+// - it is possible to provide credentials in advance, so that the user is not
52
+// asked for them dynamically. however, the protocol flow remains the same
53
+// either way (i.e. request w/o creds, error, request with creds).
54
+// - the user is only asked for credentials once ever. if two requests require
55
+// authentication, the user is asked only once and both requests will be
56
+// retried once the creds are provided. if an authentication error is
57
+// received after providing creds, then the transaction will fail. this
58
+// means the user only has one chance to get the creds right, and creds
59
+// cannot change during a session. in the event of failure due to wrong or
60
+// changed creds, the pool will need to be recreated in order to try new
61
+// creds.
62
+// - if short term or long term auth is used, then the request is authenticated
63
+// and the response is required to be authenticated.
64
+
65
+class StunTransaction : public QObject
66
+{
67
+ Q_OBJECT
68
+
69
+public:
70
+ enum Mode
71
+ {
72
+ Udp, // handle retransmissions
73
+ Tcp // send once
74
+ };
75
+
76
+ enum Error
77
+ {
78
+ ErrorGeneric,
79
+ ErrorTimeout
80
+ };
81
+
82
+ StunTransaction(QObject *parent = 0);
83
+ ~StunTransaction();
84
+
85
+ // toAddress/toPort are optional, to associate this request to a
86
+ // specific endpoint
87
+ // note: not DOR-DS safe. this function will cause the pool's
88
+ // outgoingMessage() signal to be emitted.
89
+ void start(StunTransactionPool *pool, const QHostAddress &toAddress = QHostAddress(), int toPort = -1);
90
+
91
+ // pass message with class unset. use transaction id from the
92
+ // createMessage signal.
93
+ void setMessage(const StunMessage &request);
94
+
95
+ // transmission/timeout parameters, from RFC 5389. by default,
96
+ // they are set to the recommended values from the RFC.
97
+ void setRTO(int i);
98
+ void setRc(int i);
99
+ void setRm(int i);
100
+ void setTi(int i);
101
+
102
+ void setShortTermUsername(const QString &username);
103
+ void setShortTermPassword(const QString &password);
104
+
105
+ // fingerprint is always provided in outbound requests, but ignored
106
+ // on responses. if this flag is set, then responses will be
107
+ // required to provide a fingerprint.
108
+ void setFingerprintRequired(bool enabled);
109
+
110
+signals:
111
+ // you must use a direct connection with this signal and call
112
+ // setMessage() in the slot. this signal may occur many times
113
+ // before the StunTransaction completes, and you must recreate the
114
+ // message every time using the new transactionId.
115
+ void createMessage(const QByteArray &transactionId);
116
+
117
+ void finished(const XMPP::StunMessage &response);
118
+ void error(XMPP::StunTransaction::Error error);
119
+
120
+private:
121
+ Q_DISABLE_COPY(StunTransaction)
122
+
123
+ friend class StunTransactionPool;
124
+ friend class StunTransactionPoolPrivate;
125
+
126
+ friend class StunTransactionPrivate;
127
+ StunTransactionPrivate *d;
128
+};
129
+
130
+// keep track of many open transactions. note that retransmit() may be
131
+// emitted as a direct result of calling certain member functions of this
132
+// class as well as any other class that might use it (such as StunBinding).
133
+// so, be careful with what you do in your retransmit slot.
134
+class StunTransactionPool : public QObject
135
+{
136
+ Q_OBJECT
137
+
138
+public:
139
+ enum DebugLevel
140
+ {
141
+ DL_None,
142
+ DL_Info,
143
+ DL_Packet
144
+ };
145
+
146
+ StunTransactionPool(StunTransaction::Mode mode, QObject *parent = 0);
147
+ ~StunTransactionPool();
148
+
149
+ StunTransaction::Mode mode() const;
150
+
151
+ // note: the writeIncomingMessage functions are not DOR-DS safe. they
152
+ // may cause a transaction to emit finished() or error() signals.
153
+
154
+ // returns true if the message is owned by the pool, else false.
155
+ bool writeIncomingMessage(const StunMessage &msg, const QHostAddress &addr = QHostAddress(), int port = -1);
156
+
157
+ // returns true if the packet is surely a STUN message and owned by the
158
+ // pool, else false. a packet must be owned by the pool to be
159
+ // considered surely a STUN message. if false, the packet may or may
160
+ // not be a STUN message. *notStun will be set to true if the packet
161
+ // is surely not STUN, or set to false if it is unclear whether the
162
+ // packet is STUN or not.
163
+ bool writeIncomingMessage(const QByteArray &packet, bool *notStun = 0, const QHostAddress &addr = QHostAddress(), int port = -1);
164
+
165
+ void setLongTermAuthEnabled(bool enabled);
166
+
167
+ QString realm() const;
168
+ void setUsername(const QString &username);
169
+ void setPassword(const QCA::SecureArray &password);
170
+ void setRealm(const QString &realm);
171
+ void continueAfterParams();
172
+
173
+ // for use with stun indications
174
+ QByteArray generateId() const;
175
+
176
+ void setDebugLevel(DebugLevel level); // default DL_None
177
+
178
+signals:
179
+ // note: not DOR-SS safe. writeIncomingMessage() must not be called
180
+ // during this signal.
181
+ //
182
+ // why do we need this restriction? long explanation: since
183
+ // outgoingMessage() can be emitted as a result of calling a
184
+ // transaction's start(), and calling writeIncomingMessage() could
185
+ // result in a transaction completing, then calling
186
+ // writeIncomingMessage() during outgoingMessage() could cause
187
+ // a transaction's finished() or error() signals to emit during
188
+ // start(), which would violate DOR-DS.
189
+ void outgoingMessage(const QByteArray &packet, const QHostAddress &addr, int port);
190
+
191
+ void needAuthParams();
192
+
193
+ // not DOR-SS/DS safe
194
+ void debugLine(const QString &line);
195
+
196
+private:
197
+ Q_DISABLE_COPY(StunTransactionPool)
198
+
199
+ friend class StunTransaction;
200
+ friend class StunTransactionPrivate;
201
+
202
+ friend class StunTransactionPoolPrivate;
203
+ StunTransactionPoolPrivate *d;
204
+};
205
+
206
+}
207
+
208
+#endif
209
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stuntypes.cpp
Added
740
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stuntypes.h"
23
+
24
+#include <stdio.h>
25
+#include <QtCrypto>
26
+#include "stunutil.h"
27
+
28
+#define STRING_MAX_CHARS 127
29
+#define STRING_MAX_BYTES 763
30
+
31
+namespace XMPP {
32
+
33
+using namespace StunUtil;
34
+
35
+namespace StunTypes {
36
+
37
+static void xorIPv4(QByteArray *in, const quint8 *magic)
38
+{
39
+ quint8 *p = (quint8 *)in->data();
40
+ p2 ^= magic0;
41
+ p3 ^= magic1;
42
+ for(int n = 0; n < 4; ++n)
43
+ pn + 4 ^= magicn;
44
+}
45
+
46
+static void xorIPv6(QByteArray *in, const quint8 *magic, const quint8 *id)
47
+{
48
+ quint8 *p = (quint8 *)in->data();
49
+ p2 ^= magic0;
50
+ p3 ^= magic1;
51
+ for(int n = 0; n < 4; ++n)
52
+ pn + 4 ^= magicn;
53
+ for(int n = 0; n < 12; ++n)
54
+ pn + 8 ^= idn;
55
+}
56
+
57
+static bool validateString(const QByteArray &in, QString *out)
58
+{
59
+ if(in.size() <= STRING_MAX_BYTES)
60
+ {
61
+ QString s = QString::fromUtf8(in);
62
+ if(s.length() <= STRING_MAX_CHARS)
63
+ {
64
+ *out = s;
65
+ return true;
66
+ }
67
+ }
68
+
69
+ return false;
70
+}
71
+
72
+QByteArray createMappedAddress(const QHostAddress &addr, quint16 port)
73
+{
74
+ QByteArray out;
75
+
76
+ if(addr.protocol() == QAbstractSocket::IPv6Protocol)
77
+ {
78
+ out = QByteArray(20, 0);
79
+ out1 = 0x02; // IPv6
80
+ Q_IPV6ADDR addr6 = addr.toIPv6Address();
81
+ memcpy(out.data() + 4, addr6.c, 16);
82
+ }
83
+ else if(addr.protocol() == QAbstractSocket::IPv4Protocol)
84
+ {
85
+ out = QByteArray(8, 0);
86
+ out1 = 0x01; // IPv4
87
+ write32((quint8 *)out.data() + 4, addr.toIPv4Address());
88
+ }
89
+ else
90
+ Q_ASSERT(0);
91
+
92
+ write16((quint8 *)out.data() + 2, port);
93
+ return out;
94
+}
95
+
96
+QByteArray createUsername(const QString &username)
97
+{
98
+ return username.left(STRING_MAX_CHARS).toUtf8();
99
+}
100
+
101
+QByteArray createErrorCode(int code, const QString &reason)
102
+{
103
+ QByteArray out(4, 0);
104
+
105
+ int ih = code / 100;
106
+ int il = code % 100;
107
+ ih &= 0x07; // keep only lower 3 bits
108
+
109
+ unsigned char ch = (unsigned char)ih;
110
+ unsigned char cl = (unsigned char)il;
111
+ out2 = ch;
112
+ out3 = cl;
113
+ out += reason.left(STRING_MAX_CHARS).toUtf8();
114
+ return out;
115
+}
116
+
117
+QByteArray createUnknownAttributes(const QList<quint16> &typeList)
118
+{
119
+ if(typeList.isEmpty())
120
+ return QByteArray();
121
+
122
+ QByteArray out(typeList.count() * 2, 0);
123
+ for(int n = 0; n < typeList.count(); ++n)
124
+ write16((quint8 *)out.data() + (n * 2), typeListn);
125
+ return out;
126
+}
127
+
128
+QByteArray createRealm(const QString &realm)
129
+{
130
+ return realm.left(STRING_MAX_CHARS).toUtf8();
131
+}
132
+
133
+QByteArray createNonce(const QString &nonce)
134
+{
135
+ return nonce.left(STRING_MAX_CHARS).toUtf8();
136
+}
137
+
138
+QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id)
139
+{
140
+ QByteArray out = createMappedAddress(addr, port);
141
+ if(addr.protocol() == QAbstractSocket::IPv6Protocol)
142
+ xorIPv6(&out, magic, id);
143
+ else // IPv4
144
+ xorIPv4(&out, magic);
145
+ return out;
146
+}
147
+
148
+QByteArray createChannelNumber(quint16 i)
149
+{
150
+ QByteArray val(4, 0);
151
+ write16((quint8 *)val.data(), i);
152
+ // bytes 2-3 are zeroed out
153
+ return val;
154
+}
155
+
156
+QByteArray createLifetime(quint32 i)
157
+{
158
+ QByteArray val(4, 0);
159
+ write32((quint8 *)val.data(), i);
160
+ return val;
161
+}
162
+
163
+QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id)
164
+{
165
+ return createXorMappedAddress(addr, port, magic, id);
166
+}
167
+
168
+QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id)
169
+{
170
+ return createXorMappedAddress(addr, port, magic, id);
171
+}
172
+
173
+QByteArray createEvenPort(bool reserve)
174
+{
175
+ QByteArray val(1, 0);
176
+ unsigned char c = 0;
177
+ if(reserve)
178
+ c |= 0x80; // set high bit
179
+ val0 = c;
180
+ return val;
181
+}
182
+
183
+QByteArray createRequestedTransport(quint8 proto)
184
+{
185
+ QByteArray val(4, 0);
186
+ val0 = proto;
187
+ // bytes 1-3 are zeroed out
188
+ return val;
189
+}
190
+
191
+QByteArray createReservationToken(const QByteArray &token)
192
+{
193
+ Q_ASSERT(token.size() == 8);
194
+ return token;
195
+}
196
+
197
+QByteArray createPriority(quint32 i)
198
+{
199
+ QByteArray val(4, 0);
200
+ write32((quint8 *)val.data(), i);
201
+ return val;
202
+}
203
+
204
+QByteArray createSoftware(const QString &str)
205
+{
206
+ return str.left(STRING_MAX_CHARS).toUtf8();
207
+}
208
+
209
+QByteArray createAlternateServer(const QHostAddress &addr, quint16 port)
210
+{
211
+ return createMappedAddress(addr, port);
212
+}
213
+
214
+QByteArray createIceControlled(quint64 i)
215
+{
216
+ QByteArray val(8, 0);
217
+ write64((quint8 *)val.data(), i);
218
+ return val;
219
+}
220
+
221
+QByteArray createIceControlling(quint64 i)
222
+{
223
+ QByteArray val(8, 0);
224
+ write64((quint8 *)val.data(), i);
225
+ return val;
226
+}
227
+
228
+bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port)
229
+{
230
+ if(val1 == 0x02 && val.size() == 20) // IPv6
231
+ {
232
+ *port = read16((const quint8 *)val.data() + 2);
233
+ QByteArray buf = val.mid(4);
234
+ *addr = QHostAddress((quint8 *)buf.data());
235
+ return true;
236
+ }
237
+ else if(val1 == 0x01 && val.size() == 8) // IPv4
238
+ {
239
+ *port = read16((const quint8 *)val.data() + 2);
240
+ *addr = QHostAddress(read32((const quint8 *)val.data() + 4));
241
+ return true;
242
+ }
243
+ else
244
+ return false;
245
+}
246
+
247
+bool parseUsername(const QByteArray &val, QString *username)
248
+{
249
+ return validateString(val, username);
250
+}
251
+
252
+bool parseErrorCode(const QByteArray &val, int *code, QString *reason)
253
+{
254
+ if(val.size() < 4)
255
+ return false;
256
+
257
+ unsigned char ch = (unsigned char)val2;
258
+ unsigned char cl = (unsigned char)val3;
259
+ int ih = ch & 0x07; // lower 3 bits
260
+ int x = ih * 100 + (int)cl;
261
+
262
+ QString str;
263
+ if(validateString(val.mid(4), &str))
264
+ {
265
+ *code = x;
266
+ *reason = str;
267
+ return true;
268
+ }
269
+
270
+ return false;
271
+}
272
+
273
+bool parseUnknownAttributes(const QByteArray &val, QList<quint16> *typeList)
274
+{
275
+ if(val.size() % 2 != 0)
276
+ return false;
277
+
278
+ typeList->clear();
279
+ int count = val.size() / 2;
280
+ for(int n = 0; n < count; ++n)
281
+ typeList->append(read16((const quint8 *)val.data() + (n * 2)));
282
+ return true;
283
+}
284
+
285
+bool parseRealm(const QByteArray &val, QString *realm)
286
+{
287
+ return validateString(val, realm);
288
+}
289
+
290
+bool parseNonce(const QByteArray &val, QString *nonce)
291
+{
292
+ return validateString(val, nonce);
293
+}
294
+
295
+bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port)
296
+{
297
+ if(val.size() < 4)
298
+ return false;
299
+
300
+ QByteArray buf;
301
+ if(val1 == 0x02 && val.size() == 20) // IPv6
302
+ {
303
+ buf = val;
304
+ xorIPv6(&buf, magic, id);
305
+ }
306
+ else if(val1 == 0x01 && val.size() == 8) // IPv4
307
+ {
308
+ buf = val;
309
+ xorIPv4(&buf, magic);
310
+ }
311
+ else
312
+ return false;
313
+
314
+ return parseMappedAddress(buf, addr, port);
315
+}
316
+
317
+bool parseChannelNumber(const QByteArray &val, quint16 *i)
318
+{
319
+ if(val.size() != 4)
320
+ return false;
321
+
322
+ const quint8 *p = (const quint8 *)val.data();
323
+ *i = read16(p);
324
+ return true;
325
+}
326
+
327
+bool parseLifetime(const QByteArray &val, quint32 *i)
328
+{
329
+ if(val.size() != 4)
330
+ return false;
331
+
332
+ const quint8 *p = (const quint8 *)val.data();
333
+ *i = read32(p);
334
+ return true;
335
+}
336
+
337
+bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port)
338
+{
339
+ return parseXorMappedAddress(val, magic, id, addr, port);
340
+}
341
+
342
+bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port)
343
+{
344
+ return parseXorMappedAddress(val, magic, id, addr, port);
345
+}
346
+
347
+bool parseEvenPort(const QByteArray &val, bool *reserve)
348
+{
349
+ if(val.size() != 1)
350
+ return false;
351
+
352
+ unsigned char c = val0;
353
+ if(c & 0x80)
354
+ *reserve = true;
355
+ else
356
+ *reserve = false;
357
+
358
+ return true;
359
+}
360
+
361
+bool parseRequestedTransport(const QByteArray &val, quint8 *proto)
362
+{
363
+ if(val.size() != 4)
364
+ return false;
365
+
366
+ *proto = val0;
367
+ return true;
368
+}
369
+
370
+bool parseReservationToken(const QByteArray &val, QByteArray *token)
371
+{
372
+ if(val.size() != 8)
373
+ return false;
374
+
375
+ *token = val;
376
+ return true;
377
+}
378
+
379
+bool parsePriority(const QByteArray &val, quint32 *i)
380
+{
381
+ if(val.size() != 4)
382
+ return false;
383
+
384
+ const quint8 *p = (const quint8 *)val.data();
385
+ *i = read32(p);
386
+ return true;
387
+}
388
+
389
+bool parseSoftware(const QByteArray &val, QString *str)
390
+{
391
+ *str = QString::fromUtf8(val);
392
+ return true;
393
+}
394
+
395
+bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port)
396
+{
397
+ return parseMappedAddress(val, addr, port);
398
+}
399
+
400
+bool parseIceControlled(const QByteArray &val, quint64 *i)
401
+{
402
+ if(val.size() != 8)
403
+ return false;
404
+
405
+ const quint8 *p = (const quint8 *)val.data();
406
+ *i = read64(p);
407
+ return true;
408
+}
409
+
410
+bool parseIceControlling(const QByteArray &val, quint64 *i)
411
+{
412
+ if(val.size() != 8)
413
+ return false;
414
+
415
+ const quint8 *p = (const quint8 *)val.data();
416
+ *i = read64(p);
417
+ return true;
418
+}
419
+
420
+#define METHOD_ENTRY(x) \
421
+ { x, #x }
422
+
423
+struct MethodEntry
424
+{
425
+ Method method;
426
+ const char *str;
427
+} method_table =
428
+{
429
+ METHOD_ENTRY(Binding),
430
+ METHOD_ENTRY(Allocate),
431
+ METHOD_ENTRY(Refresh),
432
+ METHOD_ENTRY(Send),
433
+ METHOD_ENTRY(Data),
434
+ METHOD_ENTRY(CreatePermission),
435
+ METHOD_ENTRY(ChannelBind),
436
+ { (Method)-1, 0 }
437
+};
438
+
439
+QString methodToString(int method)
440
+{
441
+ for(int n = 0; method_tablen.str; ++n)
442
+ {
443
+ if(method_tablen.method == (Method)method)
444
+ return QString::fromLatin1(method_tablen.str);
445
+ }
446
+
447
+ return QString();
448
+}
449
+
450
+#define ATTRIB_ENTRY(x) \
451
+ { x, #x }
452
+
453
+struct AttribEntry
454
+{
455
+ Attribute type;
456
+ const char *str;
457
+} attrib_table =
458
+{
459
+ ATTRIB_ENTRY(MAPPED_ADDRESS),
460
+ ATTRIB_ENTRY(USERNAME),
461
+ ATTRIB_ENTRY(MESSAGE_INTEGRITY),
462
+ ATTRIB_ENTRY(ERROR_CODE),
463
+ ATTRIB_ENTRY(UNKNOWN_ATTRIBUTES),
464
+ ATTRIB_ENTRY(REALM),
465
+ ATTRIB_ENTRY(NONCE),
466
+ ATTRIB_ENTRY(XOR_MAPPED_ADDRESS),
467
+ ATTRIB_ENTRY(CHANNEL_NUMBER),
468
+ ATTRIB_ENTRY(LIFETIME),
469
+ ATTRIB_ENTRY(XOR_PEER_ADDRESS),
470
+ ATTRIB_ENTRY(DATA),
471
+ ATTRIB_ENTRY(XOR_RELAYED_ADDRESS),
472
+ ATTRIB_ENTRY(EVEN_PORT),
473
+ ATTRIB_ENTRY(REQUESTED_TRANSPORT),
474
+ ATTRIB_ENTRY(DONT_FRAGMENT),
475
+ ATTRIB_ENTRY(RESERVATION_TOKEN),
476
+ ATTRIB_ENTRY(PRIORITY),
477
+ ATTRIB_ENTRY(USE_CANDIDATE),
478
+ ATTRIB_ENTRY(SOFTWARE),
479
+ ATTRIB_ENTRY(ALTERNATE_SERVER),
480
+ ATTRIB_ENTRY(FINGERPRINT),
481
+ ATTRIB_ENTRY(ICE_CONTROLLED),
482
+ ATTRIB_ENTRY(ICE_CONTROLLING),
483
+ { (Attribute)-1, 0 }
484
+};
485
+
486
+QString attributeTypeToString(int type)
487
+{
488
+ for(int n = 0; attrib_tablen.str; ++n)
489
+ {
490
+ if(attrib_tablen.type == (Attribute)type)
491
+ {
492
+ QString name = QString::fromLatin1(attrib_tablen.str);
493
+ name.replace('_', '-');
494
+ return name;
495
+ }
496
+ }
497
+
498
+ return QString();
499
+}
500
+
501
+static QString quoted(const QString &in)
502
+{
503
+ return QString("\"") + in + '\"';
504
+}
505
+
506
+QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id)
507
+{
508
+ switch((Attribute)type)
509
+ {
510
+ case MAPPED_ADDRESS:
511
+ {
512
+ QHostAddress addr;
513
+ quint16 port;
514
+ if(parseMappedAddress(val, &addr, &port))
515
+ return addr.toString() + ';' + QString::number(port);
516
+ break;
517
+ }
518
+ case USERNAME:
519
+ {
520
+ QString str;
521
+ if(parseUsername(val, &str))
522
+ return quoted(str);
523
+ break;
524
+ }
525
+ case MESSAGE_INTEGRITY:
526
+ {
527
+ return QCA::arrayToHex(val);
528
+ }
529
+ case ERROR_CODE:
530
+ {
531
+ int code;
532
+ QString reason;
533
+ if(parseErrorCode(val, &code, &reason))
534
+ {
535
+ QString out = QString::number(code);
536
+ if(!reason.isEmpty())
537
+ out += QString(", ") + quoted(reason);
538
+ return out;
539
+ }
540
+ break;
541
+ }
542
+ case UNKNOWN_ATTRIBUTES:
543
+ {
544
+ QList<quint16> typeList;
545
+ if(parseUnknownAttributes(val, &typeList))
546
+ {
547
+ if(!typeList.isEmpty())
548
+ {
549
+ QStringList strList;
550
+ foreach(quint16 i, typeList)
551
+ strList += QString().sprintf("0x%04x", i);
552
+ return strList.join(", ");
553
+ }
554
+ else
555
+ return "(None)";
556
+ }
557
+ break;
558
+ }
559
+ case REALM:
560
+ {
561
+ QString str;
562
+ if(parseRealm(val, &str))
563
+ return quoted(str);
564
+ break;
565
+ }
566
+ case NONCE:
567
+ {
568
+ QString str;
569
+ if(parseNonce(val, &str))
570
+ return quoted(str);
571
+ break;
572
+ }
573
+ case XOR_MAPPED_ADDRESS:
574
+ {
575
+ QHostAddress addr;
576
+ quint16 port;
577
+ if(parseXorMappedAddress(val, magic, id, &addr, &port))
578
+ return addr.toString() + ';' + QString::number(port);
579
+ break;
580
+ }
581
+ case CHANNEL_NUMBER:
582
+ {
583
+ quint16 i;
584
+ if(parseChannelNumber(val, &i))
585
+ return QString().sprintf("0x%04x", (int)i);
586
+ break;
587
+ }
588
+ case LIFETIME:
589
+ {
590
+ quint32 i;
591
+ if(parseLifetime(val, &i))
592
+ return QString::number(i);
593
+ break;
594
+ }
595
+ case XOR_PEER_ADDRESS:
596
+ {
597
+ return attributeValueToString(XOR_MAPPED_ADDRESS, val, magic, id);
598
+ }
599
+ case DATA:
600
+ {
601
+ return QString("len=%1, ").arg(val.size()) + QCA::arrayToHex(val);
602
+ }
603
+ case XOR_RELAYED_ADDRESS:
604
+ {
605
+ return attributeValueToString(XOR_MAPPED_ADDRESS, val, magic, id);
606
+ }
607
+ case EVEN_PORT:
608
+ {
609
+ bool reserve;
610
+ if(parseEvenPort(val, &reserve))
611
+ return QString("reserve=") + (reserve ? "true" : "false");
612
+ break;
613
+ }
614
+ case REQUESTED_TRANSPORT:
615
+ {
616
+ quint8 proto;
617
+ if(parseRequestedTransport(val, &proto))
618
+ {
619
+ QString str = QString::number((int)proto);
620
+ if(proto == 17) // UDP
621
+ str += " (UDP)";
622
+ else
623
+ str += " (Unknown)";
624
+ return str;
625
+ }
626
+ break;
627
+ }
628
+ case DONT_FRAGMENT:
629
+ {
630
+ return QString("");
631
+ }
632
+ case RESERVATION_TOKEN:
633
+ {
634
+ QByteArray token;
635
+ if(parseReservationToken(val, &token))
636
+ return QCA::arrayToHex(token);
637
+ break;
638
+ }
639
+ case PRIORITY:
640
+ {
641
+ quint32 i;
642
+ if(parsePriority(val, &i))
643
+ return QString::number(i);
644
+ break;
645
+ }
646
+ case USE_CANDIDATE:
647
+ {
648
+ return QString("");
649
+ }
650
+ case SOFTWARE:
651
+ {
652
+ QString out;
653
+ if(parseSoftware(val, &out))
654
+ return quoted(out);
655
+ break;
656
+ }
657
+ case ALTERNATE_SERVER:
658
+ {
659
+ return attributeValueToString(MAPPED_ADDRESS, val, magic, id);
660
+ }
661
+ case FINGERPRINT:
662
+ {
663
+ return QCA::arrayToHex(val);
664
+ }
665
+ case ICE_CONTROLLED:
666
+ {
667
+ quint64 i;
668
+ if(parseIceControlled(val, &i))
669
+ return QString::number(i);
670
+ break;
671
+ }
672
+ case ICE_CONTROLLING:
673
+ {
674
+ quint64 i;
675
+ if(parseIceControlling(val, &i))
676
+ return QString::number(i);
677
+ break;
678
+ }
679
+ }
680
+
681
+ return QString();
682
+}
683
+
684
+QString print_packet_str(const StunMessage &message)
685
+{
686
+ QString out;
687
+
688
+ QString mclass;
689
+ if(message.mclass() == StunMessage::Request)
690
+ mclass = "Request";
691
+ else if(message.mclass() == StunMessage::SuccessResponse)
692
+ mclass = "Response (Success)";
693
+ else if(message.mclass() == StunMessage::ErrorResponse)
694
+ mclass = "Response (Error)";
695
+ else if(message.mclass() == StunMessage::Indication)
696
+ mclass = "Indication";
697
+ else
698
+ Q_ASSERT(0);
699
+
700
+ out += QString("Class: %1\n").arg(mclass);
701
+ out += QString("Method: %1\n").arg(methodToString(message.method()));
702
+ out += QString("Transaction id: %1\n").arg(QCA::arrayToHex(QByteArray((const char *)message.id(), 12)));
703
+ out += "Attributes:";
704
+ QList<StunMessage::Attribute> attribs = message.attributes();
705
+ if(!attribs.isEmpty())
706
+ {
707
+ foreach(const StunMessage::Attribute &a, attribs)
708
+ {
709
+ out += '\n';
710
+
711
+ QString name = attributeTypeToString(a.type);
712
+ if(!name.isNull())
713
+ {
714
+ QString val = attributeValueToString(a.type, a.value, message.magic(), message.id());
715
+ if(val.isNull())
716
+ val = QString("Unable to parse %1 bytes").arg(a.value.size());
717
+
718
+ out += QString(" %1").arg(name);
719
+ if(!val.isEmpty())
720
+ out += QString(" = %1").arg(val);
721
+ }
722
+ else
723
+ out += QString().sprintf(" Unknown attribute (0x%04x) of %d bytes", a.type, a.value.size());
724
+ }
725
+ }
726
+ else
727
+ out += "\n (None)";
728
+
729
+ return out;
730
+}
731
+
732
+void print_packet(const StunMessage &message)
733
+{
734
+ printf("%s\n", qPrintable(print_packet_str(message)));
735
+}
736
+
737
+}
738
+
739
+}
740
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stuntypes.h
Added
148
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNTYPES_H
23
+#define STUNTYPES_H
24
+
25
+#include <QString>
26
+#include <QByteArray>
27
+#include <QList>
28
+#include <QHostAddress>
29
+#include "stunmessage.h"
30
+
31
+namespace XMPP {
32
+
33
+namespace StunTypes {
34
+
35
+enum Method
36
+{
37
+ Binding = 0x001,
38
+ Allocate = 0x003,
39
+ Refresh = 0x004,
40
+ Send = 0x006,
41
+ Data = 0x007,
42
+ CreatePermission = 0x008,
43
+ ChannelBind = 0x009
44
+};
45
+
46
+enum Attribute
47
+{
48
+ MAPPED_ADDRESS = 0x0001,
49
+ USERNAME = 0x0006,
50
+ MESSAGE_INTEGRITY = 0x0008,
51
+ ERROR_CODE = 0x0009,
52
+ UNKNOWN_ATTRIBUTES = 0x000a,
53
+ REALM = 0x0014,
54
+ NONCE = 0x0015,
55
+ XOR_MAPPED_ADDRESS = 0x0020,
56
+ CHANNEL_NUMBER = 0x000c,
57
+ LIFETIME = 0x000d,
58
+ XOR_PEER_ADDRESS = 0x0012,
59
+ DATA = 0x0013,
60
+ XOR_RELAYED_ADDRESS = 0x0016,
61
+ EVEN_PORT = 0x0018,
62
+ REQUESTED_TRANSPORT = 0x0019,
63
+ DONT_FRAGMENT = 0x001a,
64
+ RESERVATION_TOKEN = 0x0022,
65
+
66
+ PRIORITY = 0x0024,
67
+ USE_CANDIDATE = 0x0025,
68
+
69
+ SOFTWARE = 0x8022,
70
+ ALTERNATE_SERVER = 0x8023,
71
+ FINGERPRINT = 0x8028,
72
+
73
+ ICE_CONTROLLED = 0x8029,
74
+ ICE_CONTROLLING = 0x802a
75
+};
76
+
77
+enum Error
78
+{
79
+ TryAlternate = 300,
80
+ BadRequest = 400,
81
+ Unauthorized = 401,
82
+ UnknownAttribute = 420,
83
+ StaleNonce = 438,
84
+ ServerError = 500,
85
+
86
+ Forbidden = 403,
87
+ AllocationMismatch = 437,
88
+ WrongCredentials = 441,
89
+ UnsupportedTransportProtocol = 442,
90
+ AllocationQuotaReached = 486,
91
+ InsufficientCapacity = 508,
92
+
93
+ RoleConflict = 487
94
+};
95
+
96
+QByteArray createMappedAddress(const QHostAddress &addr, quint16 port);
97
+QByteArray createUsername(const QString &username);
98
+QByteArray createErrorCode(int code, const QString &reason);
99
+QByteArray createUnknownAttributes(const QList<quint16> &typeList);
100
+QByteArray createRealm(const QString &realm);
101
+QByteArray createNonce(const QString &nonce);
102
+QByteArray createXorMappedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id);
103
+QByteArray createChannelNumber(quint16 i);
104
+QByteArray createLifetime(quint32 i);
105
+QByteArray createXorPeerAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id);
106
+QByteArray createXorRelayedAddress(const QHostAddress &addr, quint16 port, const quint8 *magic, const quint8 *id);
107
+QByteArray createEvenPort(bool reserve);
108
+QByteArray createRequestedTransport(quint8 proto);
109
+QByteArray createReservationToken(const QByteArray &token);
110
+QByteArray createPriority(quint32 i);
111
+QByteArray createSoftware(const QString &str);
112
+QByteArray createAlternateServer(const QHostAddress &addr, quint16 port);
113
+QByteArray createIceControlled(quint64 i);
114
+QByteArray createIceControlling(quint64 i);
115
+
116
+bool parseMappedAddress(const QByteArray &val, QHostAddress *addr, quint16 *port);
117
+bool parseUsername(const QByteArray &val, QString *username);
118
+bool parseErrorCode(const QByteArray &val, int *code, QString *reason);
119
+bool parseUnknownAttributes(const QByteArray &val, QList<quint16> *typeList);
120
+bool parseRealm(const QByteArray &val, QString *realm);
121
+bool parseNonce(const QByteArray &val, QString *nonce);
122
+bool parseXorMappedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port);
123
+bool parseChannelNumber(const QByteArray &val, quint16 *i);
124
+bool parseLifetime(const QByteArray &val, quint32 *i);
125
+bool parseXorPeerAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port);
126
+bool parseXorRelayedAddress(const QByteArray &val, const quint8 *magic, const quint8 *id, QHostAddress *addr, quint16 *port);
127
+bool parseEvenPort(const QByteArray &val, bool *reserve);
128
+bool parseRequestedTransport(const QByteArray &val, quint8 *proto);
129
+bool parseReservationToken(const QByteArray &val, QByteArray *token);
130
+bool parsePriority(const QByteArray &val, quint32 *i);
131
+bool parseSoftware(const QByteArray &val, QString *str);
132
+bool parseAlternateServer(const QByteArray &val, QHostAddress *addr, quint16 *port);
133
+bool parseIceControlled(const QByteArray &val, quint64 *i);
134
+bool parseIceControlling(const QByteArray &val, quint64 *i);
135
+
136
+QString methodToString(int method);
137
+QString attributeTypeToString(int type);
138
+QString attributeValueToString(int type, const QByteArray &val, const quint8 *magic, const quint8 *id);
139
+
140
+QString print_packet_str(const StunMessage &message);
141
+void print_packet(const StunMessage &message);
142
+
143
+}
144
+
145
+}
146
+
147
+#endif
148
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunutil.cpp
Added
103
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "stunutil.h"
23
+
24
+namespace XMPP {
25
+
26
+namespace StunUtil {
27
+
28
+quint16 read16(const quint8 *in)
29
+{
30
+ quint16 out = in0;
31
+ out <<= 8;
32
+ out += in1;
33
+ return out;
34
+}
35
+
36
+quint32 read32(const quint8 *in)
37
+{
38
+ quint32 out = in0;
39
+ out <<= 8;
40
+ out += in1;
41
+ out <<= 8;
42
+ out += in2;
43
+ out <<= 8;
44
+ out += in3;
45
+ return out;
46
+}
47
+
48
+quint64 read64(const quint8 *in)
49
+{
50
+ quint64 out = in0;
51
+ out <<= 8;
52
+ out += in1;
53
+ out <<= 8;
54
+ out += in2;
55
+ out <<= 8;
56
+ out += in3;
57
+ out <<= 8;
58
+ out += in4;
59
+ out <<= 8;
60
+ out += in5;
61
+ out <<= 8;
62
+ out += in6;
63
+ out <<= 8;
64
+ out += in7;
65
+ return out;
66
+}
67
+
68
+void write16(quint8 *out, quint16 i)
69
+{
70
+ out0 = (i >> 8) & 0xff;
71
+ out1 = i & 0xff;
72
+}
73
+
74
+void write32(quint8 *out, quint32 i)
75
+{
76
+ out0 = (i >> 24) & 0xff;
77
+ out1 = (i >> 16) & 0xff;
78
+ out2 = (i >> 8) & 0xff;
79
+ out3 = i & 0xff;
80
+}
81
+
82
+void write64(quint8 *out, quint64 i)
83
+{
84
+ out0 = (i >> 56) & 0xff;
85
+ out1 = (i >> 48) & 0xff;
86
+ out2 = (i >> 40) & 0xff;
87
+ out3 = (i >> 32) & 0xff;
88
+ out4 = (i >> 24) & 0xff;
89
+ out5 = (i >> 16) & 0xff;
90
+ out6 = (i >> 8) & 0xff;
91
+ out7 = i & 0xff;
92
+}
93
+
94
+QCA::SecureArray saslPrep(const QCA::SecureArray &in)
95
+{
96
+ // TODO
97
+ return in;
98
+}
99
+
100
+}
101
+
102
+}
103
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/stunutil.h
Added
46
1
2
+/*
3
+ * Copyright (C) 2009 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef STUNUTIL_H
23
+#define STUNUTIL_H
24
+
25
+#include <QtCrypto>
26
+
27
+namespace XMPP {
28
+
29
+namespace StunUtil {
30
+
31
+quint16 read16(const quint8 *in);
32
+quint32 read32(const quint8 *in);
33
+quint64 read64(const quint8 *in);
34
+
35
+void write16(quint8 *out, quint16 i);
36
+void write32(quint8 *out, quint32 i);
37
+void write64(quint8 *out, quint64 i);
38
+
39
+QCA::SecureArray saslPrep(const QCA::SecureArray &in);
40
+
41
+}
42
+
43
+}
44
+
45
+#endif
46
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/turnclient.cpp
Added
1149
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "turnclient.h"
23
+
24
+#include <QtCrypto>
25
+#include "stuntypes.h"
26
+#include "stunmessage.h"
27
+#include "stuntransaction.h"
28
+#include "stunallocate.h"
29
+#include "objectsession.h"
30
+#include "bytestream.h"
31
+#include "bsocket.h"
32
+#include "httpconnect.h"
33
+#include "socks.h"
34
+
35
+namespace XMPP {
36
+
37
+//----------------------------------------------------------------------------
38
+// TurnClient::Proxy
39
+//----------------------------------------------------------------------------
40
+TurnClient::Proxy::Proxy()
41
+{
42
+ t = None;
43
+}
44
+
45
+TurnClient::Proxy::~Proxy()
46
+{
47
+}
48
+
49
+int TurnClient::Proxy::type() const
50
+{
51
+ return t;
52
+}
53
+
54
+QString TurnClient::Proxy::host() const
55
+{
56
+ return v_host;
57
+}
58
+
59
+quint16 TurnClient::Proxy::port() const
60
+{
61
+ return v_port;
62
+}
63
+
64
+QString TurnClient::Proxy::user() const
65
+{
66
+ return v_user;
67
+}
68
+
69
+QString TurnClient::Proxy::pass() const
70
+{
71
+ return v_pass;
72
+}
73
+
74
+void TurnClient::Proxy::setHttpConnect(const QString &host, quint16 port)
75
+{
76
+ t = HttpConnect;
77
+ v_host = host;
78
+ v_port = port;
79
+}
80
+
81
+void TurnClient::Proxy::setSocks(const QString &host, quint16 port)
82
+{
83
+ t = Socks;
84
+ v_host = host;
85
+ v_port = port;
86
+}
87
+
88
+void TurnClient::Proxy::setUserPass(const QString &user, const QString &pass)
89
+{
90
+ v_user = user;
91
+ v_pass = pass;
92
+}
93
+
94
+//----------------------------------------------------------------------------
95
+// TurnClient
96
+//----------------------------------------------------------------------------
97
+class TurnClient::Private : public QObject
98
+{
99
+ Q_OBJECT
100
+
101
+public:
102
+ TurnClient *q;
103
+ Proxy proxy;
104
+ QString clientSoftware;
105
+ TurnClient::Mode mode;
106
+ QHostAddress serverAddr;
107
+ int serverPort;
108
+ ObjectSession sess;
109
+ ByteStream *bs;
110
+ QCA::TLS *tls;
111
+ bool tlsHandshaken;
112
+ QByteArray inStream;
113
+ bool udp;
114
+ StunTransactionPool *pool;
115
+ StunAllocate *allocate;
116
+ bool allocateStarted;
117
+ QString user;
118
+ QCA::SecureArray pass;
119
+ QString realm;
120
+ int retryCount;
121
+ QString errorString;
122
+ int debugLevel;
123
+
124
+ class WriteItem
125
+ {
126
+ public:
127
+ enum Type
128
+ {
129
+ Data,
130
+ Other
131
+ };
132
+
133
+ Type type;
134
+ int size;
135
+ QHostAddress addr;
136
+ int port;
137
+
138
+ WriteItem(int _size) :
139
+ type(Other),
140
+ size(_size),
141
+ port(-1)
142
+ {
143
+ }
144
+
145
+ WriteItem(int _size, const QHostAddress &_addr, int _port) :
146
+ type(Data),
147
+ size(_size),
148
+ addr(_addr),
149
+ port(_port)
150
+ {
151
+ }
152
+ };
153
+
154
+ QList<WriteItem> writeItems;
155
+ int writtenBytes;
156
+ bool stopping;
157
+
158
+ class Packet
159
+ {
160
+ public:
161
+ QHostAddress addr;
162
+ int port;
163
+ QByteArray data;
164
+
165
+ // for outbound
166
+ bool requireChannel;
167
+
168
+ Packet() :
169
+ port(-1),
170
+ requireChannel(false)
171
+ {
172
+ }
173
+ };
174
+
175
+ QList<Packet> in;
176
+ QList<Packet> outPending;
177
+ int outPendingWrite;
178
+ QList<QHostAddress> desiredPerms;
179
+ QList<StunAllocate::Channel> pendingChannels, desiredChannels;
180
+
181
+ class Written
182
+ {
183
+ public:
184
+ QHostAddress addr;
185
+ int port;
186
+ int count;
187
+ };
188
+
189
+ Private(TurnClient *_q) :
190
+ QObject(_q),
191
+ q(_q),
192
+ sess(this),
193
+ bs(0),
194
+ tls(0),
195
+ udp(false),
196
+ pool(0),
197
+ allocate(0),
198
+ retryCount(0),
199
+ debugLevel(TurnClient::DL_None),
200
+ writtenBytes(0),
201
+ stopping(false),
202
+ outPendingWrite(0)
203
+ {
204
+ }
205
+
206
+ ~Private()
207
+ {
208
+ cleanup();
209
+ }
210
+
211
+ void cleanup()
212
+ {
213
+ delete allocate;
214
+ allocate = 0;
215
+
216
+ // in udp mode, we don't own the pool
217
+ if(!udp)
218
+ delete pool;
219
+ pool = 0;
220
+
221
+ delete tls;
222
+ tls = 0;
223
+
224
+ delete bs;
225
+ bs = 0;
226
+
227
+ udp = false;
228
+
229
+ sess.reset();
230
+
231
+ inStream.clear();
232
+ retryCount = 0;
233
+ writeItems.clear();
234
+ writtenBytes = 0;
235
+ stopping = false;
236
+ outPending.clear();
237
+ outPendingWrite = 0;
238
+ desiredPerms.clear();
239
+ pendingChannels.clear();
240
+ desiredChannels.clear();
241
+ }
242
+
243
+ void do_connect()
244
+ {
245
+ if(udp)
246
+ {
247
+ after_connected();
248
+ return;
249
+ }
250
+
251
+ if(proxy.type() == Proxy::HttpConnect)
252
+ {
253
+ HttpConnect *s = new HttpConnect(this);
254
+ bs = s;
255
+ connect(s, SIGNAL(connected()), SLOT(bs_connected()));
256
+ connect(s, SIGNAL(error(int)), SLOT(bs_error(int)));
257
+ if(!proxy.user().isEmpty())
258
+ s->setAuth(proxy.user(), proxy.pass());
259
+ s->connectToHost(proxy.host(), proxy.port(), serverAddr.toString(), serverPort);
260
+ }
261
+ else if(proxy.type() == Proxy::Socks)
262
+ {
263
+ SocksClient *s = new SocksClient(this);
264
+ bs = s;
265
+ connect(s, SIGNAL(connected()), SLOT(bs_connected()));
266
+ connect(s, SIGNAL(error(int)), SLOT(bs_error(int)));
267
+ if(!proxy.user().isEmpty())
268
+ s->setAuth(proxy.user(), proxy.pass());
269
+ s->connectToHost(proxy.host(), proxy.port(), serverAddr.toString(), serverPort);
270
+ }
271
+ else
272
+ {
273
+ BSocket *s = new BSocket(this);
274
+ bs = s;
275
+ connect(s, SIGNAL(connected()), SLOT(bs_connected()));
276
+ connect(s, SIGNAL(error(int)), SLOT(bs_error(int)));
277
+ s->connectToHost(serverAddr.toString(), serverPort);
278
+ }
279
+
280
+ connect(bs, SIGNAL(connectionClosed()), SLOT(bs_connectionClosed()));
281
+ connect(bs, SIGNAL(delayedCloseFinished()), SLOT(bs_delayedCloseFinished()));
282
+ connect(bs, SIGNAL(readyRead()), SLOT(bs_readyRead()));
283
+ connect(bs, SIGNAL(bytesWritten(int)), SLOT(bs_bytesWritten(int)));
284
+ }
285
+
286
+ void do_close()
287
+ {
288
+ stopping = true;
289
+
290
+ if(allocate && allocateStarted)
291
+ {
292
+ if(debugLevel >= TurnClient::DL_Info)
293
+ emit q->debugLine("Deallocating...");
294
+ allocate->stop();
295
+ }
296
+ else
297
+ {
298
+ delete allocate;
299
+ allocate = 0;
300
+
301
+ // in udp mode, we don't own the pool
302
+ if(!udp)
303
+ delete pool;
304
+ pool = 0;
305
+
306
+ if(udp)
307
+ sess.defer(q, "closed");
308
+ else
309
+ do_transport_close();
310
+ }
311
+ }
312
+
313
+ void do_transport_close()
314
+ {
315
+ if(tls && tlsHandshaken)
316
+ {
317
+ tls->close();
318
+ }
319
+ else
320
+ {
321
+ delete tls;
322
+ tls = 0;
323
+
324
+ do_sock_close();
325
+ }
326
+ }
327
+
328
+ void do_sock_close()
329
+ {
330
+ bool waitForSignal = false;
331
+ if(bs->bytesToWrite() > 0)
332
+ waitForSignal = true;
333
+
334
+ bs->close();
335
+ if(!waitForSignal)
336
+ {
337
+ cleanup();
338
+ sess.defer(q, "closed");
339
+ }
340
+ }
341
+
342
+ void after_connected()
343
+ {
344
+ // when retrying, pool will be non-null because we reuse it
345
+ if(!udp && !pool)
346
+ {
347
+ pool = new StunTransactionPool(StunTransaction::Tcp, this);
348
+ pool->setDebugLevel((StunTransactionPool::DebugLevel)debugLevel);
349
+ connect(pool, SIGNAL(outgoingMessage(const QByteArray &, const QHostAddress &, int)), SLOT(pool_outgoingMessage(const QByteArray &, const QHostAddress &, int)));
350
+ connect(pool, SIGNAL(needAuthParams()), SLOT(pool_needAuthParams()));
351
+ connect(pool, SIGNAL(debugLine(const QString &)), SLOT(pool_debugLine(const QString &)));
352
+
353
+ pool->setLongTermAuthEnabled(true);
354
+ if(!user.isEmpty())
355
+ {
356
+ pool->setUsername(user);
357
+ pool->setPassword(pass);
358
+ if(!realm.isEmpty())
359
+ pool->setRealm(realm);
360
+ }
361
+ }
362
+
363
+ allocate = new StunAllocate(pool);
364
+ connect(allocate, SIGNAL(started()), SLOT(allocate_started()));
365
+ connect(allocate, SIGNAL(stopped()), SLOT(allocate_stopped()));
366
+ connect(allocate, SIGNAL(error(XMPP::StunAllocate::Error)), SLOT(allocate_error(XMPP::StunAllocate::Error)));
367
+ connect(allocate, SIGNAL(permissionsChanged()), SLOT(allocate_permissionsChanged()));
368
+ connect(allocate, SIGNAL(channelsChanged()), SLOT(allocate_channelsChanged()));
369
+ connect(allocate, SIGNAL(debugLine(const QString &)), SLOT(allocate_debugLine(const QString &)));
370
+
371
+ allocate->setClientSoftwareNameAndVersion(clientSoftware);
372
+
373
+ allocateStarted = false;
374
+ if(debugLevel >= TurnClient::DL_Info)
375
+ emit q->debugLine("Allocating...");
376
+ // only use addr association in udp mode
377
+ if(udp)
378
+ allocate->start(serverAddr, serverPort);
379
+ else
380
+ allocate->start();
381
+ }
382
+
383
+ void processStream(const QByteArray &in)
384
+ {
385
+ inStream += in;
386
+
387
+ ObjectSessionWatcher watch(&sess);
388
+ while(1)
389
+ {
390
+ QByteArray packet;
391
+
392
+ // try to extract ChannelData or a STUN message from
393
+ // the stream
394
+ packet = StunAllocate::readChannelData((const quint8 *)inStream.data(), inStream.size());
395
+ if(packet.isNull())
396
+ {
397
+ packet = StunMessage::readStun((const quint8 *)inStream.data(), inStream.size());
398
+ if(packet.isNull())
399
+ break;
400
+ }
401
+
402
+ inStream = inStream.mid(packet.size());
403
+
404
+ // processDatagram may cause the session to be reset
405
+ // or the object to be deleted
406
+ processDatagram(packet);
407
+ if(!watch.isValid())
408
+ break;
409
+ }
410
+ }
411
+
412
+ void processDatagram(const QByteArray &buf)
413
+ {
414
+ bool notStun;
415
+ if(!pool->writeIncomingMessage(buf, ¬Stun))
416
+ {
417
+ QByteArray data;
418
+ QHostAddress fromAddr;
419
+ int fromPort;
420
+
421
+ data = processNonPoolPacket(buf, notStun, &fromAddr, &fromPort);
422
+ if(!data.isNull())
423
+ processDataPacket(data, fromAddr, fromPort);
424
+ }
425
+ }
426
+
427
+ QByteArray processNonPoolPacket(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port)
428
+ {
429
+ if(notStun)
430
+ {
431
+ // not stun? maybe it is a data packet
432
+ QByteArray data = allocate->decode(buf, addr, port);
433
+ if(!data.isNull())
434
+ {
435
+ if(debugLevel >= TurnClient::DL_Packet)
436
+ emit q->debugLine("Received ChannelData-based data packet");
437
+ return data;
438
+ }
439
+ }
440
+ else
441
+ {
442
+ // packet might be stun not owned by pool.
443
+ // let's see
444
+ StunMessage message = StunMessage::fromBinary(buf);
445
+ if(!message.isNull())
446
+ {
447
+ QByteArray data = allocate->decode(message, addr, port);
448
+
449
+ if(!data.isNull())
450
+ {
451
+ if(debugLevel >= TurnClient::DL_Packet)
452
+ emit q->debugLine("Received STUN-based data packet");
453
+ return data;
454
+ }
455
+ else
456
+ {
457
+ if(debugLevel >= TurnClient::DL_Packet)
458
+ emit q->debugLine("Warning: server responded with an unexpected STUN packet, skipping.");
459
+ }
460
+
461
+ return QByteArray();
462
+ }
463
+ }
464
+
465
+ if(debugLevel >= TurnClient::DL_Packet)
466
+ emit q->debugLine("Warning: server responded with what doesn't seem to be a STUN or data packet, skipping.");
467
+ return QByteArray();
468
+ }
469
+
470
+ void processDataPacket(const QByteArray &buf, const QHostAddress &addr, int port)
471
+ {
472
+ Packet p;
473
+ p.addr = addr;
474
+ p.port = port;
475
+ p.data = buf;
476
+ in += p;
477
+
478
+ emit q->readyRead();
479
+ }
480
+
481
+ void writeOrQueue(const QByteArray &buf, const QHostAddress &addr, int port)
482
+ {
483
+ Q_ASSERT(allocateStarted);
484
+
485
+ StunAllocate::Channel c(addr, port);
486
+ bool writeImmediately = false;
487
+ bool requireChannel = pendingChannels.contains(c) || desiredChannels.contains(c);
488
+
489
+ QList<QHostAddress> actualPerms = allocate->permissions();
490
+ if(actualPerms.contains(addr))
491
+ {
492
+ if(requireChannel)
493
+ {
494
+ QList<StunAllocate::Channel> actualChannels = allocate->channels();
495
+ if(actualChannels.contains(c))
496
+ writeImmediately = true;
497
+ }
498
+ else
499
+ writeImmediately = true;
500
+ }
501
+
502
+ if(writeImmediately)
503
+ {
504
+ write(buf, addr, port);
505
+ }
506
+ else
507
+ {
508
+ Packet p;
509
+ p.addr = addr;
510
+ p.port = port;
511
+ p.data = buf;
512
+ p.requireChannel = requireChannel;
513
+ outPending += p;
514
+
515
+ ensurePermission(addr);
516
+ }
517
+ }
518
+
519
+ void tryWriteQueued()
520
+ {
521
+ QList<QHostAddress> actualPerms = allocate->permissions();
522
+ QList<StunAllocate::Channel> actualChannels = allocate->channels();
523
+ for(int n = 0; n < outPending.count(); ++n)
524
+ {
525
+ const Packet &p = outPendingn;
526
+ if(actualPerms.contains(p.addr))
527
+ {
528
+ StunAllocate::Channel c(p.addr, p.port);
529
+ if(!p.requireChannel || actualChannels.contains(c))
530
+ {
531
+ Packet po = outPendingn;
532
+ outPending.removeAt(n);
533
+ --n; // adjust position
534
+
535
+ write(po.data, po.addr, po.port);
536
+ }
537
+ }
538
+ }
539
+ }
540
+
541
+ void tryChannelQueued()
542
+ {
543
+ if(!pendingChannels.isEmpty())
544
+ {
545
+ QList<QHostAddress> actualPerms = allocate->permissions();
546
+ QList<StunAllocate::Channel> list;
547
+ for(int n = 0; n < pendingChannels.count(); ++n)
548
+ {
549
+ if(actualPerms.contains(pendingChannelsn.address))
550
+ {
551
+ list += pendingChannelsn;
552
+ pendingChannels.removeAt(n);
553
+ --n; // adjust position
554
+ }
555
+ }
556
+
557
+ if(!list.isEmpty())
558
+ ensureChannels(list);
559
+ }
560
+ }
561
+
562
+ void write(const QByteArray &buf, const QHostAddress &addr, int port)
563
+ {
564
+ QByteArray packet = allocate->encode(buf, addr, port);
565
+
566
+ if(debugLevel >= TurnClient::DL_Packet)
567
+ {
568
+ StunMessage msg = StunMessage::fromBinary(packet);
569
+ if(!msg.isNull())
570
+ {
571
+ emit q->debugLine("STUN SEND");
572
+ emit q->debugLine(StunTypes::print_packet_str(msg));
573
+ }
574
+ else
575
+ emit q->debugLine("Sending ChannelData-based data packet");
576
+ }
577
+
578
+ writeItems += WriteItem(packet.size(), addr, port);
579
+ ++outPendingWrite;
580
+ if(udp)
581
+ {
582
+ emit q->outgoingDatagram(packet);
583
+ }
584
+ else
585
+ {
586
+ if(tls)
587
+ tls->write(packet);
588
+ else
589
+ bs->write(packet);
590
+ }
591
+ }
592
+
593
+ void ensurePermission(const QHostAddress &addr)
594
+ {
595
+ if(!desiredPerms.contains(addr))
596
+ {
597
+ if(debugLevel >= TurnClient::DL_Info)
598
+ emit q->debugLine(QString("Setting permission for peer address %1").arg(addr.toString()));
599
+
600
+ desiredPerms += addr;
601
+ allocate->setPermissions(desiredPerms);
602
+ }
603
+ }
604
+
605
+ // assumes we have perms for all input already
606
+ void ensureChannels(const QList<StunAllocate::Channel> &channels)
607
+ {
608
+ bool changed = false;
609
+ foreach(const StunAllocate::Channel &c, channels)
610
+ {
611
+ if(!desiredChannels.contains(c))
612
+ {
613
+ if(debugLevel >= TurnClient::DL_Info)
614
+ emit q->debugLine(QString("Setting channel for peer address/port %1;%2").arg(c.address.toString()).arg(c.port));
615
+
616
+ desiredChannels += c;
617
+ changed = true;
618
+ }
619
+ }
620
+
621
+ if(changed)
622
+ allocate->setChannels(desiredChannels);
623
+ }
624
+
625
+ void addChannelPeer(const QHostAddress &addr, int port)
626
+ {
627
+ ensurePermission(addr);
628
+
629
+ StunAllocate::Channel c(addr, port);
630
+ if(!pendingChannels.contains(c) && !desiredChannels.contains(c))
631
+ {
632
+ pendingChannels += c;
633
+
634
+ tryChannelQueued();
635
+ }
636
+ }
637
+
638
+ void udp_datagramsWritten(int count)
639
+ {
640
+ QList<Written> writtenDests;
641
+
642
+ while(count > 0)
643
+ {
644
+ Q_ASSERT(!writeItems.isEmpty());
645
+ WriteItem wi = writeItems.takeFirst();
646
+ --count;
647
+
648
+ if(wi.type == WriteItem::Data)
649
+ {
650
+ int at = -1;
651
+ for(int n = 0; n < writtenDests.count(); ++n)
652
+ {
653
+ if(writtenDestsn.addr == wi.addr && writtenDestsn.port == wi.port)
654
+ {
655
+ at = n;
656
+ break;
657
+ }
658
+ }
659
+
660
+ if(at != -1)
661
+ {
662
+ ++writtenDestsat.count;
663
+ }
664
+ else
665
+ {
666
+ Written wr;
667
+ wr.addr = wi.addr;
668
+ wr.port = wi.port;
669
+ wr.count = 1;
670
+ writtenDests += wr;
671
+ }
672
+ }
673
+ }
674
+
675
+ emitPacketsWritten(writtenDests);
676
+ }
677
+
678
+ void emitPacketsWritten(const QList<Written> &writtenDests)
679
+ {
680
+ ObjectSessionWatcher watch(&sess);
681
+ foreach(const Written &wr, writtenDests)
682
+ {
683
+ emit q->packetsWritten(wr.count, wr.addr, wr.port);
684
+ if(!watch.isValid())
685
+ return;
686
+ }
687
+ }
688
+
689
+ // return true if we are retrying, false if we should error out
690
+ bool handleRetry()
691
+ {
692
+ ++retryCount;
693
+ if(retryCount < 3 && !stopping)
694
+ {
695
+ if(debugLevel >= TurnClient::DL_Info)
696
+ emit q->debugLine("retrying...");
697
+
698
+ // start completely over, but retain the same pool
699
+ // so the user isn't asked to auth again
700
+
701
+ int tmp_retryCount = retryCount;
702
+ StunTransactionPool *tmp_pool = pool;
703
+ pool = 0;
704
+
705
+ cleanup();
706
+
707
+ retryCount = tmp_retryCount;
708
+ pool = tmp_pool;
709
+
710
+ do_connect();
711
+ return true;
712
+ }
713
+
714
+ return false;
715
+ }
716
+
717
+private slots:
718
+ void bs_connected()
719
+ {
720
+ ObjectSessionWatcher watch(&sess);
721
+ emit q->connected();
722
+ if(!watch.isValid())
723
+ return;
724
+
725
+ if(mode == TurnClient::TlsMode)
726
+ {
727
+ tls = new QCA::TLS(this);
728
+ connect(tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
729
+ connect(tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
730
+ connect(tls, SIGNAL(readyReadOutgoing()), SLOT(tls_readyReadOutgoing()));
731
+ connect(tls, SIGNAL(error()), SLOT(tls_error()));
732
+ tlsHandshaken = false;
733
+ if(debugLevel >= TurnClient::DL_Info)
734
+ emit q->debugLine("TLS handshaking...");
735
+ tls->startClient();
736
+ }
737
+ else
738
+ after_connected();
739
+ }
740
+
741
+ void bs_connectionClosed()
742
+ {
743
+ cleanup();
744
+ errorString = "Server unexpectedly disconnected.";
745
+ emit q->error(TurnClient::ErrorStream);
746
+ }
747
+
748
+ void bs_delayedCloseFinished()
749
+ {
750
+ cleanup();
751
+ emit q->closed();
752
+ }
753
+
754
+ void bs_readyRead()
755
+ {
756
+ QByteArray buf = bs->read();
757
+
758
+ if(tls)
759
+ tls->writeIncoming(buf);
760
+ else
761
+ processStream(buf);
762
+ }
763
+
764
+ void bs_bytesWritten(int written)
765
+ {
766
+ if(tls)
767
+ {
768
+ // convertBytesWritten() is unsafe to call unless
769
+ // the TLS handshake is completed
770
+ if(!tlsHandshaken)
771
+ return;
772
+
773
+ written = tls->convertBytesWritten(written);
774
+ }
775
+
776
+ writtenBytes += written;
777
+
778
+ QList<Written> writtenDests;
779
+
780
+ while(writtenBytes > 0)
781
+ {
782
+ Q_ASSERT(!writeItems.isEmpty());
783
+ if(writtenBytes < writeItems.first().size)
784
+ break;
785
+
786
+ WriteItem wi = writeItems.takeFirst();
787
+ writtenBytes -= wi.size;
788
+
789
+ if(wi.type == WriteItem::Data)
790
+ {
791
+ int at = -1;
792
+ for(int n = 0; n < writtenDests.count(); ++n)
793
+ {
794
+ if(writtenDestsn.addr == wi.addr && writtenDestsn.port == wi.port)
795
+ {
796
+ at = n;
797
+ break;
798
+ }
799
+ }
800
+
801
+ if(at != -1)
802
+ {
803
+ ++writtenDestsat.count;
804
+ }
805
+ else
806
+ {
807
+ Written wr;
808
+ wr.addr = wi.addr;
809
+ wr.port = wi.port;
810
+ wr.count = 1;
811
+ writtenDests += wr;
812
+ }
813
+ }
814
+ }
815
+
816
+ emitPacketsWritten(writtenDests);
817
+ }
818
+
819
+ void bs_error(int e)
820
+ {
821
+ TurnClient::Error te;
822
+ if(qobject_cast<HttpConnect*>(bs))
823
+ {
824
+ if(e == HttpConnect::ErrConnectionRefused)
825
+ te = TurnClient::ErrorConnect;
826
+ else if(e == HttpConnect::ErrHostNotFound)
827
+ te = TurnClient::ErrorHostNotFound;
828
+ else if(e == HttpConnect::ErrProxyConnect)
829
+ te = TurnClient::ErrorProxyConnect;
830
+ else if(e == HttpConnect::ErrProxyNeg)
831
+ te = TurnClient::ErrorProxyNeg;
832
+ else if(e == HttpConnect::ErrProxyAuth)
833
+ te = TurnClient::ErrorProxyAuth;
834
+ else
835
+ te = TurnClient::ErrorStream;
836
+ }
837
+ else if(qobject_cast<SocksClient*>(bs))
838
+ {
839
+ if(e == SocksClient::ErrConnectionRefused)
840
+ te = TurnClient::ErrorConnect;
841
+ else if(e == SocksClient::ErrHostNotFound)
842
+ te = TurnClient::ErrorHostNotFound;
843
+ else if(e == SocksClient::ErrProxyConnect)
844
+ te = TurnClient::ErrorProxyConnect;
845
+ else if(e == SocksClient::ErrProxyNeg)
846
+ te = TurnClient::ErrorProxyNeg;
847
+ else if(e == SocksClient::ErrProxyAuth)
848
+ te = TurnClient::ErrorProxyAuth;
849
+ else
850
+ te = TurnClient::ErrorStream;
851
+ }
852
+ else
853
+ {
854
+ if(e == BSocket::ErrConnectionRefused)
855
+ te = TurnClient::ErrorConnect;
856
+ else if(e == BSocket::ErrHostNotFound)
857
+ te = TurnClient::ErrorHostNotFound;
858
+ else
859
+ te = TurnClient::ErrorStream;
860
+ }
861
+
862
+ cleanup();
863
+ errorString = "Transport error.";
864
+ emit q->error(te);
865
+ }
866
+
867
+ void tls_handshaken()
868
+ {
869
+ tlsHandshaken = true;
870
+
871
+ ObjectSessionWatcher watch(&sess);
872
+ emit q->tlsHandshaken();
873
+ if(!watch.isValid())
874
+ return;
875
+
876
+ tls->continueAfterStep();
877
+ after_connected();
878
+ }
879
+
880
+ void tls_readyRead()
881
+ {
882
+ processStream(tls->read());
883
+ }
884
+
885
+ void tls_readyReadOutgoing()
886
+ {
887
+ bs->write(tls->readOutgoing());
888
+ }
889
+
890
+ void tls_closed()
891
+ {
892
+ delete tls;
893
+ tls = 0;
894
+
895
+ do_sock_close();
896
+ }
897
+
898
+ void tls_error()
899
+ {
900
+ cleanup();
901
+ errorString = "TLS error.";
902
+ emit q->error(TurnClient::ErrorTls);
903
+ }
904
+
905
+ void pool_outgoingMessage(const QByteArray &packet, const QHostAddress &toAddress, int toPort)
906
+ {
907
+ // we aren't using IP-associated transactions
908
+ Q_UNUSED(toAddress);
909
+ Q_UNUSED(toPort);
910
+
911
+ writeItems += WriteItem(packet.size());
912
+
913
+ if(tls)
914
+ tls->write(packet);
915
+ else
916
+ bs->write(packet);
917
+ }
918
+
919
+ void pool_needAuthParams()
920
+ {
921
+ emit q->needAuthParams();
922
+ }
923
+
924
+ void pool_debugLine(const QString &line)
925
+ {
926
+ emit q->debugLine(line);
927
+ }
928
+
929
+ void allocate_started()
930
+ {
931
+ allocateStarted = true;
932
+ if(debugLevel >= TurnClient::DL_Info)
933
+ emit q->debugLine("Allocate started");
934
+
935
+ emit q->activated();
936
+ }
937
+
938
+ void allocate_stopped()
939
+ {
940
+ delete allocate;
941
+ allocate = 0;
942
+
943
+ // in udp mode, we don't own the pool
944
+ if(!udp)
945
+ delete pool;
946
+ pool = 0;
947
+
948
+ if(udp)
949
+ emit q->closed();
950
+ else
951
+ do_transport_close();
952
+ }
953
+
954
+ void allocate_error(XMPP::StunAllocate::Error e)
955
+ {
956
+ QString str = allocate->errorString();
957
+
958
+ TurnClient::Error te;
959
+ if(e == StunAllocate::ErrorAuth)
960
+ te = TurnClient::ErrorAuth;
961
+ else if(e == StunAllocate::ErrorRejected)
962
+ te = TurnClient::ErrorRejected;
963
+ else if(e == StunAllocate::ErrorProtocol)
964
+ te = TurnClient::ErrorProtocol;
965
+ else if(e == StunAllocate::ErrorCapacity)
966
+ te = TurnClient::ErrorCapacity;
967
+ else if(e == StunAllocate::ErrorMismatch)
968
+ {
969
+ if(!udp && handleRetry())
970
+ return;
971
+
972
+ te = TurnClient::ErrorMismatch;
973
+ }
974
+ else
975
+ te = TurnClient::ErrorGeneric;
976
+
977
+ cleanup();
978
+ errorString = str;
979
+ emit q->error(te);
980
+ }
981
+
982
+ void allocate_permissionsChanged()
983
+ {
984
+ if(debugLevel >= TurnClient::DL_Info)
985
+ emit q->debugLine("PermissionsChanged");
986
+
987
+ tryChannelQueued();
988
+ tryWriteQueued();
989
+ }
990
+
991
+ void allocate_channelsChanged()
992
+ {
993
+ if(debugLevel >= TurnClient::DL_Info)
994
+ emit q->debugLine("ChannelsChanged");
995
+
996
+ tryWriteQueued();
997
+ }
998
+
999
+ void allocate_debugLine(const QString &line)
1000
+ {
1001
+ emit q->debugLine(line);
1002
+ }
1003
+};
1004
+
1005
+TurnClient::TurnClient(QObject *parent) :
1006
+ QObject(parent)
1007
+{
1008
+ d = new Private(this);
1009
+}
1010
+
1011
+TurnClient::~TurnClient()
1012
+{
1013
+ delete d;
1014
+}
1015
+
1016
+void TurnClient::setProxy(const Proxy &proxy)
1017
+{
1018
+ d->proxy = proxy;
1019
+}
1020
+
1021
+void TurnClient::setClientSoftwareNameAndVersion(const QString &str)
1022
+{
1023
+ d->clientSoftware = str;
1024
+}
1025
+
1026
+void TurnClient::connectToHost(StunTransactionPool *pool, const QHostAddress &addr, int port)
1027
+{
1028
+ d->serverAddr = addr;
1029
+ d->serverPort = port;
1030
+ d->udp = true;
1031
+ d->pool = pool;
1032
+ d->in.clear();
1033
+ d->do_connect();
1034
+}
1035
+
1036
+void TurnClient::connectToHost(const QHostAddress &addr, int port, Mode mode)
1037
+{
1038
+ d->serverAddr = addr;
1039
+ d->serverPort = port;
1040
+ d->udp = false;
1041
+ d->mode = mode;
1042
+ d->in.clear();
1043
+ d->do_connect();
1044
+}
1045
+
1046
+QByteArray TurnClient::processIncomingDatagram(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port)
1047
+{
1048
+ return d->processNonPoolPacket(buf, notStun, addr, port);
1049
+}
1050
+
1051
+void TurnClient::outgoingDatagramsWritten(int count)
1052
+{
1053
+ d->udp_datagramsWritten(count);
1054
+}
1055
+
1056
+QString TurnClient::realm() const
1057
+{
1058
+ if(d->pool)
1059
+ return d->pool->realm();
1060
+ else
1061
+ return d->realm;
1062
+}
1063
+
1064
+void TurnClient::setUsername(const QString &username)
1065
+{
1066
+ d->user = username;
1067
+ if(d->pool)
1068
+ d->pool->setUsername(d->user);
1069
+}
1070
+
1071
+void TurnClient::setPassword(const QCA::SecureArray &password)
1072
+{
1073
+ d->pass = password;
1074
+ if(d->pool)
1075
+ d->pool->setPassword(d->pass);
1076
+}
1077
+
1078
+void TurnClient::setRealm(const QString &realm)
1079
+{
1080
+ d->realm = realm;
1081
+ if(d->pool)
1082
+ d->pool->setRealm(d->realm);
1083
+}
1084
+
1085
+void TurnClient::continueAfterParams()
1086
+{
1087
+ Q_ASSERT(d->pool);
1088
+ d->pool->continueAfterParams();
1089
+}
1090
+
1091
+void TurnClient::close()
1092
+{
1093
+ d->do_close();
1094
+}
1095
+
1096
+StunAllocate *TurnClient::stunAllocate()
1097
+{
1098
+ return d->allocate;
1099
+}
1100
+
1101
+void TurnClient::addChannelPeer(const QHostAddress &addr, int port)
1102
+{
1103
+ d->addChannelPeer(addr, port);
1104
+}
1105
+
1106
+int TurnClient::packetsToRead() const
1107
+{
1108
+ return d->in.count();
1109
+}
1110
+
1111
+int TurnClient::packetsToWrite() const
1112
+{
1113
+ return d->outPending.count() + d->outPendingWrite;
1114
+}
1115
+
1116
+QByteArray TurnClient::read(QHostAddress *addr, int *port)
1117
+{
1118
+ if(!d->in.isEmpty())
1119
+ {
1120
+ Private::Packet p = d->in.takeFirst();
1121
+ *addr = p.addr;
1122
+ *port = p.port;
1123
+ return p.data;
1124
+ }
1125
+ else
1126
+ return QByteArray();
1127
+}
1128
+
1129
+void TurnClient::write(const QByteArray &buf, const QHostAddress &addr, int port)
1130
+{
1131
+ d->writeOrQueue(buf, addr, port);
1132
+}
1133
+
1134
+QString TurnClient::errorString() const
1135
+{
1136
+ return d->errorString;
1137
+}
1138
+
1139
+void TurnClient::setDebugLevel(DebugLevel level)
1140
+{
1141
+ d->debugLevel = level;
1142
+ if(d->pool)
1143
+ d->pool->setDebugLevel((StunTransactionPool::DebugLevel)level);
1144
+}
1145
+
1146
+}
1147
+
1148
+#include "turnclient.moc"
1149
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/turnclient.h
Added
196
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef TURNCLIENT_H
23
+#define TURNCLIENT_H
24
+
25
+#include <QObject>
26
+#include <QByteArray>
27
+#include <QString>
28
+#include <QHostAddress>
29
+
30
+namespace QCA {
31
+ class SecureArray;
32
+}
33
+
34
+namespace XMPP {
35
+
36
+class StunTransactionPool;
37
+class StunAllocate;
38
+
39
+class TurnClient : public QObject
40
+{
41
+ Q_OBJECT
42
+
43
+public:
44
+ enum Error
45
+ {
46
+ ErrorGeneric,
47
+ ErrorHostNotFound,
48
+ ErrorConnect,
49
+
50
+ // stream error or stream unexpectedly disconnected by peer
51
+ ErrorStream,
52
+
53
+ ErrorProxyConnect,
54
+ ErrorProxyNeg,
55
+ ErrorProxyAuth,
56
+ ErrorTls,
57
+ ErrorAuth,
58
+ ErrorRejected,
59
+ ErrorProtocol,
60
+ ErrorCapacity,
61
+
62
+ // according to the TURN spec, a client should try three times
63
+ // to correct a mismatch error before giving up. this class
64
+ // will perform the retries internally, and ErrorMismatch is
65
+ // only emitted when it has given up. note that if this
66
+ // happens, the TURN spec says you should not connect to the
67
+ // TURN server again for at least 2 minutes.
68
+ // note: in UDP mode, this class does not perform retries and
69
+ // will emit this error immediately.
70
+ ErrorMismatch
71
+ };
72
+
73
+ enum Mode
74
+ {
75
+ PlainMode,
76
+ TlsMode
77
+ };
78
+
79
+ enum DebugLevel
80
+ {
81
+ DL_None,
82
+ DL_Info,
83
+ DL_Packet
84
+ };
85
+
86
+ // adapted from XMPP::AdvancedConnector
87
+ class Proxy
88
+ {
89
+ public:
90
+ enum
91
+ {
92
+ None,
93
+ HttpConnect,
94
+ Socks
95
+ };
96
+
97
+ Proxy();
98
+ ~Proxy();
99
+
100
+ int type() const;
101
+ QString host() const;
102
+ quint16 port() const;
103
+ QString user() const;
104
+ QString pass() const;
105
+
106
+ void setHttpConnect(const QString &host, quint16 port);
107
+ void setSocks(const QString &host, quint16 port);
108
+ void setUserPass(const QString &user, const QString &pass);
109
+
110
+ private:
111
+ int t;
112
+ QString v_host;
113
+ quint16 v_port;
114
+ QString v_user, v_pass;
115
+ };
116
+
117
+ TurnClient(QObject *parent = 0);
118
+ ~TurnClient();
119
+
120
+ void setProxy(const Proxy &proxy);
121
+ void setClientSoftwareNameAndVersion(const QString &str);
122
+
123
+ // for UDP. does not take ownership of the pool. stun transaction
124
+ // I/O occurs through the pool. transfer of data packets occurs
125
+ // via processIncomingDatagram(), outgoingDatagram(), and
126
+ // outgoingDatagramsWritten(). authentication happens through the
127
+ // pool and not through this class. the turn addr/port is optional,
128
+ // and used only for addr association with the pool
129
+ void connectToHost(StunTransactionPool *pool, const QHostAddress &addr = QHostAddress(), int port = -1);
130
+
131
+ // for TCP and TCP-TLS
132
+ void connectToHost(const QHostAddress &addr, int port, Mode mode = PlainMode);
133
+
134
+ // for UDP, use this function to process incoming packets instead of
135
+ // read().
136
+ QByteArray processIncomingDatagram(const QByteArray &buf, bool notStun, QHostAddress *addr, int *port);
137
+
138
+ // call after writing datagrams from outgoingDatagram. not DOR-DS safe
139
+ void outgoingDatagramsWritten(int count);
140
+
141
+ QString realm() const;
142
+ void setUsername(const QString &username);
143
+ void setPassword(const QCA::SecureArray &password);
144
+ void setRealm(const QString &realm);
145
+ void continueAfterParams();
146
+
147
+ void close();
148
+
149
+ StunAllocate *stunAllocate();
150
+
151
+ void addChannelPeer(const QHostAddress &addr, int port);
152
+
153
+ int packetsToRead() const;
154
+ int packetsToWrite() const;
155
+
156
+ // TCP mode only
157
+ QByteArray read(QHostAddress *addr, int *port);
158
+
159
+ // for UDP, this call may emit outgoingDatagram() immediately (not
160
+ // DOR-DS safe)
161
+ void write(const QByteArray &buf, const QHostAddress &addr, int port);
162
+
163
+ QString errorString() const;
164
+
165
+ void setDebugLevel(DebugLevel level); // default DL_None
166
+
167
+signals:
168
+ void connected(); // tcp connected
169
+ void tlsHandshaken();
170
+ void closed();
171
+ void needAuthParams();
172
+ void retrying(); // mismatch error received, starting all over
173
+ void activated(); // ready for read/write
174
+
175
+ // TCP mode only
176
+ void readyRead();
177
+
178
+ void packetsWritten(int count, const QHostAddress &addr, int port);
179
+ void error(XMPP::TurnClient::Error e);
180
+
181
+ // data packets to be sent to the TURN server, UDP mode only
182
+ void outgoingDatagram(const QByteArray &buf);
183
+
184
+ // not DOR-SS/DS safe
185
+ void debugLine(const QString &line);
186
+
187
+private:
188
+ class Private;
189
+ friend class Private;
190
+ Private *d;
191
+};
192
+
193
+}
194
+
195
+#endif
196
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/udpportreserver.cpp
Added
437
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#include "udpportreserver.h"
23
+
24
+#include <QUdpSocket>
25
+
26
+namespace XMPP {
27
+
28
+class UdpPortReserver::Private : public QObject
29
+{
30
+ Q_OBJECT
31
+
32
+public:
33
+ class Item
34
+ {
35
+ public:
36
+ int port; // port to reserve
37
+ bool lent;
38
+
39
+ // list of sockets for this port, one socket per address.
40
+ // note that we may have sockets bound for addresses
41
+ // we no longer care about, if we are currently lending
42
+ // them out
43
+ QList<QUdpSocket*> sockList;
44
+
45
+ // keep track of which addresses we lent out
46
+ QList<QHostAddress> lentAddrs;
47
+
48
+ Item() :
49
+ port(-1),
50
+ lent(false)
51
+ {
52
+ }
53
+
54
+ bool haveAddress(const QHostAddress &addr) const
55
+ {
56
+ foreach(const QUdpSocket *sock, sockList)
57
+ {
58
+ if(sock->localAddress() == addr)
59
+ return true;
60
+ }
61
+
62
+ return false;
63
+ }
64
+ };
65
+
66
+ UdpPortReserver *q;
67
+ QList<QHostAddress> addrs;
68
+ QList<int> ports; // sorted
69
+ QList<Item> items; // in order sorted by port
70
+
71
+ Private(UdpPortReserver *_q) :
72
+ QObject(_q),
73
+ q(_q)
74
+ {
75
+ }
76
+
77
+ ~Private()
78
+ {
79
+ bool lendingAny = false;
80
+ foreach(const Item &i, items)
81
+ {
82
+ if(i.lent)
83
+ {
84
+ lendingAny = true;
85
+ break;
86
+ }
87
+ }
88
+
89
+ Q_ASSERT(!lendingAny);
90
+
91
+ foreach(const Item &i, items)
92
+ {
93
+ foreach(QUdpSocket *sock, i.sockList)
94
+ sock->deleteLater();
95
+ }
96
+ }
97
+
98
+ void updateAddresses(const QList<QHostAddress> &newAddrs)
99
+ {
100
+ addrs = newAddrs;
101
+
102
+ tryBind();
103
+ tryCleanup();
104
+ }
105
+
106
+ void updatePorts(const QList<int> &newPorts)
107
+ {
108
+ QList<int> added;
109
+ foreach(int x, newPorts)
110
+ {
111
+ bool found = false;
112
+ foreach(const Item &i, items)
113
+ {
114
+ if(i.port == x)
115
+ {
116
+ found = true;
117
+ break;
118
+ }
119
+ }
120
+
121
+ if(!found)
122
+ added += x;
123
+ }
124
+
125
+ ports = newPorts;
126
+
127
+ // keep ports in sorted order
128
+ qSort(ports);
129
+
130
+ foreach(int x, added)
131
+ {
132
+ int insert_before = items.count();
133
+ for(int n = 0; n < items.count(); ++n)
134
+ {
135
+ if(x < itemsn.port)
136
+ {
137
+ insert_before = n;
138
+ break;
139
+ }
140
+ }
141
+
142
+ Item i;
143
+ i.port = x;
144
+ items.insert(insert_before, i);
145
+ }
146
+
147
+ tryBind();
148
+ tryCleanup();
149
+ }
150
+
151
+ bool reservedAll() const
152
+ {
153
+ bool ok = true;
154
+ foreach(const Item &i, items)
155
+ {
156
+ // skip ports we don't care about
157
+ if(!ports.contains(i.port))
158
+ continue;
159
+
160
+ if(!isReserved(i))
161
+ {
162
+ ok = false;
163
+ break;
164
+ }
165
+ }
166
+
167
+ return ok;
168
+ }
169
+
170
+ QList<QUdpSocket*> borrowSockets(int portCount, QObject *parent)
171
+ {
172
+ Q_ASSERT(portCount > 0);
173
+
174
+ QList<QUdpSocket*> out;
175
+
176
+ if(portCount > 1)
177
+ {
178
+ // first try to see if we can find something all in a
179
+ // row, starting with best alignment to worst
180
+ for(int align = portCount; align >= 2; align /= 2)
181
+ {
182
+ int at = findConsecutive(portCount, align);
183
+ if(at != -1)
184
+ {
185
+ for(int n = 0; n < portCount; ++n)
186
+ out += lendItem(&itemsat + n, parent);
187
+
188
+ break;
189
+ }
190
+ }
191
+
192
+ if(out.isEmpty())
193
+ {
194
+ // otherwise, try splitting them up into
195
+ // smaller consecutive chunks
196
+ int chunks2;
197
+ chunks0 = portCount / 2 + (portCount % 2);
198
+ chunks1 = portCount / 2;
199
+ for(int n = 0; n < 2; ++n)
200
+ out += borrowSockets(chunksn, parent);
201
+ }
202
+ }
203
+ else
204
+ {
205
+ // take the next available port
206
+ int at = findConsecutive(1, 1);
207
+ if(at != -1)
208
+ out += lendItem(&itemsat, parent);
209
+ }
210
+
211
+ return out;
212
+ }
213
+
214
+ void returnSockets(const QList<QUdpSocket*> &sockList)
215
+ {
216
+ foreach(QUdpSocket *sock, sockList)
217
+ {
218
+ int at = -1;
219
+ for(int n = 0; n < items.count(); ++n)
220
+ {
221
+ if(itemsn.sockList.contains(sock))
222
+ {
223
+ at = n;
224
+ break;
225
+ }
226
+ }
227
+
228
+ Q_ASSERT(at != -1);
229
+
230
+ Item &i = itemsat;
231
+
232
+ QHostAddress a = sock->localAddress();
233
+
234
+ Q_ASSERT(i.lent);
235
+ Q_ASSERT(i.lentAddrs.contains(a));
236
+
237
+ sock->setParent(q);
238
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
239
+
240
+ i.lentAddrs.removeAll(a);
241
+ if(i.lentAddrs.isEmpty())
242
+ i.lent = false;
243
+ }
244
+
245
+ tryCleanup();
246
+ }
247
+
248
+private slots:
249
+ void sock_readyRead()
250
+ {
251
+ QUdpSocket *sock = (QUdpSocket *)sender();
252
+
253
+ // eat all packets
254
+ while(sock->hasPendingDatagrams())
255
+ sock->readDatagram(0, 0);
256
+ }
257
+
258
+private:
259
+ void tryBind()
260
+ {
261
+ for(int n = 0; n < items.count(); ++n)
262
+ {
263
+ Item &i = itemsn;
264
+
265
+ // skip ports we don't care about
266
+ if(!ports.contains(i.port))
267
+ continue;
268
+
269
+ QList<QHostAddress> neededAddrs;
270
+ foreach(const QHostAddress &a, addrs)
271
+ {
272
+ if(!i.haveAddress(a))
273
+ neededAddrs += a;
274
+ }
275
+
276
+ foreach(const QHostAddress &a, neededAddrs)
277
+ {
278
+ QUdpSocket *sock = new QUdpSocket(q);
279
+
280
+ if(!sock->bind(a, i.port))
281
+ {
282
+ delete sock;
283
+ continue;
284
+ }
285
+
286
+ connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
287
+
288
+ i.sockList += sock;
289
+ }
290
+ }
291
+ }
292
+
293
+ void tryCleanup()
294
+ {
295
+ for(int n = 0; n < items.count(); ++n)
296
+ {
297
+ Item &i = itemsn;
298
+
299
+ // don't care about this port anymore?
300
+ if(!i.lent && !ports.contains(i.port))
301
+ {
302
+ foreach(QUdpSocket *sock, i.sockList)
303
+ sock->deleteLater();
304
+
305
+ items.removeAt(n);
306
+ --n; // adjust position
307
+ continue;
308
+ }
309
+
310
+ // any addresses we don't care about?
311
+ for(int k = 0; k < i.sockList.count(); ++k)
312
+ {
313
+ QUdpSocket *sock = i.sockListk;
314
+
315
+ QHostAddress a = sock->localAddress();
316
+
317
+ if(!addrs.contains(a) && !i.lentAddrs.contains(a))
318
+ {
319
+ sock->deleteLater();
320
+ i.sockList.removeAt(k);
321
+ --k; // adjust position
322
+ continue;
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ bool isReserved(const Item &i) const
329
+ {
330
+ // must have desired addrs to consider a port reserved
331
+ if(addrs.isEmpty())
332
+ return false;
333
+
334
+ foreach(const QHostAddress &a, addrs)
335
+ {
336
+ if(!i.haveAddress(a))
337
+ return false;
338
+ }
339
+
340
+ return true;
341
+ }
342
+
343
+ bool isConsecutive(int at, int count) const
344
+ {
345
+ if(at + count > items.count())
346
+ return false;
347
+
348
+ for(int n = 0; n < count; ++n)
349
+ {
350
+ const Item &i = itemsat + n;
351
+
352
+ if(i.lent || !isReserved(i))
353
+ return false;
354
+
355
+ if(n > 0 && (i.port != itemsat + n - 1.port + 1))
356
+ return false;
357
+ }
358
+
359
+ return true;
360
+ }
361
+
362
+ int findConsecutive(int count, int align) const
363
+ {
364
+ for(int n = 0; n < items.count(); n += align)
365
+ {
366
+ if(isConsecutive(n, count))
367
+ return n;
368
+ }
369
+
370
+ return -1;
371
+ }
372
+
373
+ QList<QUdpSocket*> lendItem(Item *i, QObject *parent)
374
+ {
375
+ QList<QUdpSocket*> out;
376
+
377
+ i->lent = true;
378
+ foreach(QUdpSocket *sock, i->sockList)
379
+ {
380
+ i->lentAddrs += sock->localAddress();
381
+ sock->disconnect(this);
382
+ sock->setParent(parent);
383
+ out += sock;
384
+ }
385
+
386
+ return out;
387
+ }
388
+};
389
+
390
+UdpPortReserver::UdpPortReserver(QObject *parent) :
391
+ QObject(parent)
392
+{
393
+ d = new Private(this);
394
+}
395
+
396
+UdpPortReserver::~UdpPortReserver()
397
+{
398
+ delete d;
399
+}
400
+
401
+void UdpPortReserver::setAddresses(const QList<QHostAddress> &addrs)
402
+{
403
+ d->updateAddresses(addrs);
404
+}
405
+
406
+void UdpPortReserver::setPorts(int start, int len)
407
+{
408
+ QList<int> ports;
409
+ for(int n = 0; n < len; ++n)
410
+ ports += start + n;
411
+ setPorts(ports);
412
+}
413
+
414
+void UdpPortReserver::setPorts(const QList<int> &ports)
415
+{
416
+ d->updatePorts(ports);
417
+}
418
+
419
+bool UdpPortReserver::reservedAll() const
420
+{
421
+ return d->reservedAll();
422
+}
423
+
424
+QList<QUdpSocket*> UdpPortReserver::borrowSockets(int portCount, QObject *parent)
425
+{
426
+ return d->borrowSockets(portCount, parent);
427
+}
428
+
429
+void UdpPortReserver::returnSockets(const QList<QUdpSocket*> &sockList)
430
+{
431
+ d->returnSockets(sockList);
432
+}
433
+
434
+}
435
+
436
+#include "udpportreserver.moc"
437
libjreen-1.1.0.tar.bz2/3rdparty/icesupport/udpportreserver.h
Added
76
1
2
+/*
3
+ * Copyright (C) 2010 Barracuda Networks, Inc.
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with this library; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ * 02110-1301 USA
19
+ *
20
+ */
21
+
22
+#ifndef UDPPORTRESERVER_H
23
+#define UDPPORTRESERVER_H
24
+
25
+#include <QObject>
26
+#include <QList>
27
+
28
+class QHostAddress;
29
+class QUdpSocket;
30
+
31
+namespace XMPP {
32
+
33
+// call both setAddresses() and setPorts() at least once for socket
34
+// reservations to occur. at any time you can update the list of addresses
35
+// (interfaces) and ports to reserve. note that the port must be available
36
+// on all addresses in order for it to get reserved.
37
+// note: you must return all sockets back to this class before destructing
38
+class UdpPortReserver : public QObject
39
+{
40
+ Q_OBJECT
41
+
42
+public:
43
+ UdpPortReserver(QObject *parent = 0);
44
+ ~UdpPortReserver();
45
+
46
+ void setAddresses(const QList<QHostAddress> &addrs);
47
+ void setPorts(int start, int len);
48
+ void setPorts(const QList<int> &ports);
49
+
50
+ // return true if all ports got reserved, false if only some
51
+ // or none got reserved
52
+ bool reservedAll() const;
53
+
54
+ // may return less than asked for, if we had less reserved ports
55
+ // left. some attempt is made to return aligned or consecutive port
56
+ // values, but this is just a best effort and not a guarantee. if
57
+ // not all ports were able to be reserved earlier, then this call
58
+ // may attempt to reserve those ports again. the sockets in the
59
+ // returned list are ordered by port (in ascending order) and then
60
+ // by address (in the order provided). since all addresses must be
61
+ // able to bind to a port for it to be considered reserved, this
62
+ // function always returns a list with a size that is a multiple of
63
+ // the number of addresses.
64
+ QList<QUdpSocket*> borrowSockets(int portCount, QObject *parent = 0);
65
+
66
+ void returnSockets(const QList<QUdpSocket*> &sockList);
67
+
68
+private:
69
+ class Private;
70
+ Private *d;
71
+};
72
+
73
+}
74
+
75
+#endif
76
libjreen-1.0.3.tar.bz2/CMakeLists.txt -> libjreen-1.1.0.tar.bz2/CMakeLists.txt
Changed
104
1
2
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
3
4
set(CMAKE_JREEN_VERSION_MAJOR 1 CACHE INT "Major Jreen version number" FORCE)
5
-set(CMAKE_JREEN_VERSION_MINOR 0 CACHE INT "Minor Jreen version number" FORCE)
6
-set(CMAKE_JREEN_VERSION_PATCH 3 CACHE INT "Release Jreen version number" FORCE)
7
+set(CMAKE_JREEN_VERSION_MINOR 1 CACHE INT "Minor Jreen version number" FORCE)
8
+set(CMAKE_JREEN_VERSION_PATCH 0 CACHE INT "Release Jreen version number" FORCE)
9
set(CMAKE_JREEN_VERSION_STRING "${CMAKE_JREEN_VERSION_MAJOR}.${CMAKE_JREEN_VERSION_MINOR}.${CMAKE_JREEN_VERSION_PATCH}" CACHE STRING "Jreen version string" FORCE)
10
11
# Search for source and headers in source directory (non-recursive)
12
-FILE(GLOB SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
13
-FILE(GLOB HDR "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
14
+FILE(GLOB_RECURSE SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
15
+FILE(GLOB_RECURSE HDR "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
16
17
# Require QT 4.6
18
SET(QT_MIN_VERSION "4.6.0")
19
20
INCLUDE(${QT_USE_FILE})
21
INCLUDE(jreenMacros)
22
FIND_PACKAGE(QCA2 REQUIRED)
23
-#FIND_PACKAGE(ZLIB REQUIRED)
24
-FIND_PACKAGE(LibIDN)
25
26
+if( JREEN_BUILD_INTERNAL )
27
+ add_definitions( "-DJ_BUILD_INTERNAL" )
28
+endif()
29
+FIND_PACKAGE(PkgConfig)
30
+
31
+#pkg_search_module(NICE nice)
32
+#if(NOT NICE_FOUND)
33
+# message(STATUS "Could not find nice library.")
34
+#else(NOT NICE_FOUND)
35
+# message(STATUS "Nice library is found.")
36
+# include_directories(${NICE_INCLUDE_DIRS})
37
+# ADD_DEFINITIONS("-DJREEN_HAVE_NICE=1")
38
+#endif(NOT NICE_FOUND)
39
+
40
+pkg_search_module(SPEEX speex)
41
+if(NOT SPEEX_FOUND)
42
+ message(STATUS "Could not find speex library.")
43
+else(NOT SPEEX_FOUND)
44
+ message(STATUS "Speex library is found.")
45
+ include_directories(${SPEEX_INCLUDE_DIRS})
46
+ ADD_DEFINITIONS("-DJREEN_HAVE_SPEEX=1")
47
+endif(NOT SPEEX_FOUND)
48
49
# FindZLIB is broken on Ubuntu, so find the library using pkg-config
50
if(LINUX)
51
52
if(NOT ZLIB_LIBRARIES)
53
message(SEND_ERROR "Could not find zlib library.")
54
endif(NOT ZLIB_LIBRARIES)
55
+
56
+
57
else()
58
find_package(ZLIB REQUIRED)
59
endif()
60
61
${QCA2_INCLUDE_DIR}
62
${ZLIB_INCLUDE_DIR}
63
)
64
-IF(LIBIDN_FOUND)
65
- INCLUDE_DIRECTORIES(${LIBIDN_INCLUDE_DIR})
66
- ADD_DEFINITIONS("-DHAVE_IDN=1")
67
-ENDIF(LIBIDN_FOUND)
68
69
LIST(APPEND SRC ${3RD_PARTY_SRC_C})
70
LIST(APPEND SRC ${3RD_PARTY_SRC})
71
LIST(APPEND HDR ${3RD_PARTY_HDR})
72
73
+# Ice support
74
+option(JREEN_USE_IRISICE "Use ICE from IRIS" OFF)
75
+if (JREEN_USE_IRISICE)
76
+ file(GLOB_RECURSE ICESUPPORT_SRC "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/icesupport/*.cpp")
77
+ file(GLOB_RECURSE ICESUPPORT_SRC_C "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/icesupport/*.c")
78
+ file(GLOB_RECURSE ICESUPPORT_HDR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/icesupport/*.h")
79
+ list(APPEND SRC ${ICESUPPORT_SRC})
80
+ list(APPEND SRC ${ICESUPPORT_SRC_C})
81
+ list(APPEND HDR ${ICESUPPORT_HDR})
82
+ add_definitions("-DHAVE_IRISICE")
83
+endif()
84
+
85
option(JREEN_USE_SIMPLESASL "Use SimpleSASL" ON)
86
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/simplesasl")
87
set(JREEN_USE_SIMPLESASL OFF)
88
89
IF(WIN32)
90
LIST(APPEND EXTRA_LIBS ws2_32)
91
ENDIF()
92
-IF(LIBIDN_FOUND)
93
- LIST(APPEND EXTRA_LIBS ${LIBIDN_LIBRARIES})
94
-ENDIF(LIBIDN_FOUND)
95
+#IF(NICE_FOUND)
96
+# LIST(APPEND EXTRA_LIBS ${NICE_LIBRARIES})
97
+#ENDIF(NICE_FOUND)
98
+IF(SPEEX_FOUND)
99
+ LIST(APPEND EXTRA_LIBS ${SPEEX_LIBRARIES})
100
+ENDIF(SPEEX_FOUND)
101
102
# Link with Qt
103
#IF(SYMBIAN)
104
libjreen-1.0.3.tar.bz2/ChangeLog -> libjreen-1.1.0.tar.bz2/ChangeLog
Changed
34
1
2
-Version 1.0.3
3
+Version 1.1.0
4
+ * Added PGP payloads
5
+ * Added support for Message Forwarding
6
+ * Added MetaContacts support
7
+ * Added experimental Jingle support
8
+ * Fixed authorization with SCRAM-SHA1
9
+ * Fixed sending of IQ's on connect
10
+
11
+Version 1.0.6:
12
+ * Fixed parsing of PubSub payload
13
+ * Fixed serializing of PubSub payload
14
+
15
+Version 1.0.5:
16
+ * Fixed parsing of message's thread attribute
17
+
18
+Version 1.0.4:
19
+ * Added support for in-band registration
20
+ * Added ability to force/deny compression/encryption
21
+ * Added CAPTCHA support
22
+ * Fixed IQ requests to yourself
23
+ * Fixed handling of messages' types in MessageSession
24
+
25
+Version 1.0.3:
26
* Added Logger implementation
27
* Fixed QJDns initialization issue
28
29
-Version 1.0.2
30
+Version 1.0.2:
31
* Added support for ProxyFactory
32
* Added immunity to invalid stanzas
33
* Added localization support for incoming stanzas
34
libjreen-1.0.3.tar.bz2/cmake/jreenMacros.cmake -> libjreen-1.1.0.tar.bz2/cmake/jreenMacros.cmake
Changed
25
1
2
SET(_header ${_abs_PATH}/${_basename}.cpp)
3
FILE(READ ${_header} _contents)
4
STRING(REGEX MATCHALL "# *include +\">moc_^ +\\.cpp\">" _match "${_contents}")
5
+ STRING(REGEX MATCHALL "# *include +^ +\\.moc\">" _match2 "${_contents}")
6
+ STRING(REGEX MATCHALL "Q_OBJECT" _match3 "${_contents}")
7
IF(_match)
8
SET(_HAS_MOC true)
9
FOREACH (_current_MOC_INC ${_match})
10
11
MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc})
12
ENDFOREACH (_current_MOC_INC)
13
ENDIF()
14
+ IF(_match2)
15
+ FOREACH (_current_MOC_INC ${_match2})
16
+ STRING(REGEX MATCH "^ <\"+\\.moc" _current_MOC "${_current_MOC_INC}")
17
+ SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC})
18
+ QT4_CREATE_MOC_COMMAND(${_header} ${_moc} "${_moc_INCS}" "")
19
+ MACRO_ADD_FILE_DEPENDENCIES(${_header} ${_moc})
20
+ ENDFOREACH (_current_MOC_INC)
21
+ ENDIF()
22
ENDIF()
23
IF(NOT _HAS_MOC)
24
FILE(READ ${_abs_FILE} _contents)
25
libjreen-1.1.0.tar.bz2/deffered
Added
2
1
+(directory)
2
libjreen-1.1.0.tar.bz2/deffered/gui
Added
2
1
+(directory)
2
libjreen-1.1.0.tar.bz2/deffered/gui/jidedit.cpp
Changed
2
1
(renamed from src/gui/jidedit.cpp)
2
libjreen-1.1.0.tar.bz2/deffered/gui/jidedit.h
Changed
2
1
(renamed from src/gui/jidedit.h)
2
libjreen-1.1.0.tar.bz2/deffered/gui/jidedit_p.h
Changed
2
1
(renamed from src/gui/jidedit_p.h)
2
libjreen-1.1.0.tar.bz2/deffered/gui/xmlconsole.cpp
Changed
2
1
(renamed from src/gui/xmlconsole.cpp)
2
libjreen-1.1.0.tar.bz2/deffered/gui/xmlconsole.h
Changed
2
1
(renamed from src/gui/xmlconsole.h)
2
libjreen-1.1.0.tar.bz2/deffered/gui/xmlconsole.ui
Changed
2
1
(renamed from src/gui/xmlconsole.ui)
2
libjreen-1.0.3.tar.bz2/src/abstractroster.cpp -> libjreen-1.1.0.tar.bz2/src/abstractroster.cpp
Changed
49
1
2
#include "logger.h"
3
#include "util.h"
4
5
+#define NS_ROSTER QLatin1String("jabber:iq:roster")
6
+
7
namespace Jreen
8
{
9
10
11
12
QStringList AbstractRosterQueryFactory::features() const
13
{
14
- return QStringList(QLatin1String("jabber:iq:roster"));
15
+ return QStringList(NS_ROSTER);
16
}
17
18
bool AbstractRosterQueryFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
19
{
20
Q_UNUSED(attributes);
21
- return name == QLatin1String("query") && uri == QLatin1String("jabber:iq:roster");
22
+ return name == QLatin1String("query") && uri == NS_ROSTER;
23
}
24
25
void AbstractRosterQueryFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
26
27
if (!query)
28
return;
29
writer->writeStartElement(QLatin1String("query"));
30
- writer->writeDefaultNamespace(QLatin1String("jabber:iq:roster"));
31
+ writer->writeDefaultNamespace(NS_ROSTER);
32
if (query->items().isEmpty())
33
writer->writeAttribute(QLatin1String("ver"), query->ver());
34
foreach (const RosterItem::Ptr &item, query->items()) {
35
36
return Payload::Ptr(new AbstractRosterQuery(m_items, m_ver));
37
}
38
39
-static const QStringList roster_subscriptions = QStringList()
40
-<< QLatin1String("from") << QLatin1String("to")
41
-<< QLatin1String("both") << QLatin1String("remove");
42
-
43
RosterItem::RosterItem(const QString &jid, const QString &name,
44
- const QStringList &groups, SubscriptionType s10n)
45
+ const QStringList &groups, SubscriptionType s10n)
46
: d_ptr(new RosterItemPrivate)
47
{
48
Q_D(RosterItem);
49
libjreen-1.0.3.tar.bz2/src/abstractroster.h -> libjreen-1.1.0.tar.bz2/src/abstractroster.h
Changed
19
1
2
class RosterItemPrivate;
3
class AbstractRosterQuery;
4
5
-class ItemFactory : public XmlStreamFactory<RosterItem>
6
+class JREEN_AUTOTEST_EXPORT ItemFactory : public XmlStreamFactory<RosterItem>
7
{
8
public:
9
};
10
11
virtual void onLoaded(const QList<QSharedPointer<RosterItem> > &items);
12
QScopedPointer<AbstractRosterPrivate> d_ptr;
13
friend class AbstractRosterQuery;
14
- friend class AbstractRosterQueryFactory;
15
+ friend class JREEN_AUTOTEST_EXPORT AbstractRosterQueryFactory;
16
friend class RosterItem;
17
};
18
19
libjreen-1.0.3.tar.bz2/src/abstractroster_p.h -> libjreen-1.1.0.tar.bz2/src/abstractroster_p.h
Changed
10
1
2
QString m_ver;
3
};
4
5
-class AbstractRosterQueryFactory : public PayloadFactory<AbstractRosterQuery>
6
+class JREEN_AUTOTEST_EXPORT AbstractRosterQueryFactory : public PayloadFactory<AbstractRosterQuery>
7
{
8
public:
9
AbstractRosterQueryFactory(AbstractRoster *roster);
10
libjreen-1.0.3.tar.bz2/src/activityfactory_p.h -> libjreen-1.1.0.tar.bz2/src/activityfactory_p.h
Changed
10
1
2
3
namespace Jreen {
4
5
-class ActivityFactory : public PayloadFactory<Activity>
6
+class JREEN_AUTOTEST_EXPORT ActivityFactory : public PayloadFactory<Activity>
7
{
8
public:
9
ActivityFactory();
10
libjreen-1.0.3.tar.bz2/src/bindfeature.cpp -> libjreen-1.1.0.tar.bz2/src/bindfeature.cpp
Changed
10
1
2
bool m_bind;
3
};
4
5
-class BindQueryFactory : public PayloadFactory<BindQuery>
6
+class JREEN_AUTOTEST_EXPORT BindQueryFactory : public PayloadFactory<BindQuery>
7
{
8
public:
9
BindQueryFactory() : m_bind(true), m_depth(0), m_state(AtStart) {}
10
libjreen-1.1.0.tar.bz2/src/bitsofbinary.cpp
Added
111
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "bitsofbinary.h"
28
+#include <QCryptographicHash>
29
+#include <QUrl>
30
+
31
+namespace Jreen
32
+{
33
+
34
+class BitsOfBinaryPrivate
35
+{
36
+public:
37
+ mutable QUrl cid;
38
+ qint64 maximumAge;
39
+ QByteArray data;
40
+ QString type;
41
+};
42
+
43
+BitsOfBinary::BitsOfBinary(const QByteArray &data, qint64 age) : d_ptr(new BitsOfBinaryPrivate)
44
+{
45
+ Q_D(BitsOfBinary);
46
+ d->maximumAge = age;
47
+ d->data = data;
48
+}
49
+
50
+BitsOfBinary::BitsOfBinary(const QUrl &cid)
51
+{
52
+ Q_D(BitsOfBinary);
53
+ d->maximumAge = -1;
54
+ d->cid = cid;
55
+}
56
+
57
+BitsOfBinary::~BitsOfBinary()
58
+{
59
+}
60
+
61
+QUrl BitsOfBinary::cid() const
62
+{
63
+ Q_D(const BitsOfBinary);
64
+ if (!d->data.isEmpty() && d->cid.isEmpty()) {
65
+ QString cid = QLatin1String("sha1+");
66
+ QCryptographicHash hash(QCryptographicHash::Sha1);
67
+ hash.addData(d->data);
68
+ cid += hash.result().toHex();
69
+ cid += QLatin1String("@bob.xmpp.org");
70
+ d->cid = QUrl(cid);
71
+ }
72
+ return d->cid;
73
+}
74
+
75
+void BitsOfBinary::setCid(const QUrl &cid)
76
+{
77
+ d_func()->cid = cid;
78
+}
79
+
80
+qint64 BitsOfBinary::maximumAge() const
81
+{
82
+ return d_func()->maximumAge;
83
+}
84
+
85
+void BitsOfBinary::setMaximumAge(qint64 age)
86
+{
87
+ d_func()->maximumAge = age;
88
+}
89
+
90
+QString BitsOfBinary::type() const
91
+{
92
+ return d_func()->type;
93
+}
94
+
95
+void BitsOfBinary::setType(const QString &type)
96
+{
97
+ d_func()->type = type;
98
+}
99
+
100
+QByteArray BitsOfBinary::data() const
101
+{
102
+ return d_func()->data;
103
+}
104
+
105
+void BitsOfBinary::setData(const QByteArray &data)
106
+{
107
+ d_func()->data = data;
108
+}
109
+
110
+} // namespace Jreen
111
libjreen-1.1.0.tar.bz2/src/bitsofbinary.h
Added
62
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_BITSOFBINARY_H
28
+#define JREEN_BITSOFBINARY_H
29
+
30
+#include "stanzaextension.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class BitsOfBinaryPrivate;
36
+
37
+class JREEN_EXPORT BitsOfBinary : public Jreen::Payload
38
+{
39
+ J_PAYLOAD(Jreen::BitsOfBinary)
40
+ Q_DECLARE_PRIVATE(BitsOfBinary)
41
+public:
42
+ BitsOfBinary(const QByteArray &data = QByteArray(), qint64 age = -1);
43
+ BitsOfBinary(const QUrl &cid);
44
+ ~BitsOfBinary();
45
+
46
+ QUrl cid() const;
47
+ void setCid(const QUrl &cid);
48
+ qint64 maximumAge() const;
49
+ void setMaximumAge(qint64 age);
50
+ QString type() const;
51
+ void setType(const QString &type);
52
+ QByteArray data() const;
53
+ void setData(const QByteArray &data);
54
+
55
+private:
56
+ QScopedPointer<BitsOfBinaryPrivate> d_ptr;
57
+};
58
+
59
+} // namespace Jreen
60
+
61
+#endif // JREEN_BITSOFBINARY_H
62
libjreen-1.1.0.tar.bz2/src/bitsofbinaryfactory.cpp
Added
102
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "bitsofbinaryfactory_p.h"
28
+#include <QUrl>
29
+#include <QStringList>
30
+
31
+namespace Jreen
32
+{
33
+
34
+#define NS_BOB QLatin1String("urn:xmpp:bob")
35
+
36
+BitsOfBinaryFactory::BitsOfBinaryFactory() : m_depth(0)
37
+{
38
+}
39
+
40
+QStringList BitsOfBinaryFactory::features() const
41
+{
42
+ return QStringList();
43
+}
44
+
45
+bool BitsOfBinaryFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
46
+{
47
+ Q_UNUSED(attributes);
48
+ m_depth = 0;
49
+ return name == QLatin1String("data") && uri == NS_BOB;
50
+}
51
+
52
+void BitsOfBinaryFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
53
+{
54
+ Q_UNUSED(name);
55
+ Q_UNUSED(uri);
56
+ ++m_depth;
57
+
58
+ if (m_depth == 1) {
59
+ m_query.reset(new BitsOfBinary);
60
+ m_query->setCid(QUrl(attributes.value(QLatin1String("cid")).toString()));
61
+ QStringRef maxAgeString = attributes.value(QLatin1String("max-age"));
62
+ bool ok = true;
63
+ qint64 maxAge = maxAgeString.toString().toInt(&ok);
64
+ m_query->setMaximumAge(ok ? maxAge : -1);
65
+ m_query->setType(attributes.value(QLatin1String("type")).toString());
66
+ }
67
+}
68
+
69
+void BitsOfBinaryFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
70
+{
71
+ Q_UNUSED(name);
72
+ Q_UNUSED(uri);
73
+ --m_depth;
74
+}
75
+
76
+void BitsOfBinaryFactory::handleCharacterData(const QStringRef &text)
77
+{
78
+ if (m_depth == 1)
79
+ m_query->setData(QByteArray::fromBase64(text.toString().toLatin1()));
80
+}
81
+
82
+void BitsOfBinaryFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
83
+{
84
+ BitsOfBinary *query = payload_cast<BitsOfBinary*>(extension);
85
+ writer->writeStartElement(QLatin1String("data"));
86
+ writer->writeAttribute(QLatin1String("cid"), query->cid().toString());
87
+ if (!query->type().isEmpty())
88
+ writer->writeAttribute(QLatin1String("type"), query->type());
89
+ if (query->maximumAge() >= 0)
90
+ writer->writeAttribute(QLatin1String("max-age"), QString::number(query->maximumAge()));
91
+ writer->writeDefaultNamespace(NS_BOB);
92
+ writer->writeCharacters(QLatin1String(query->data().toBase64()));
93
+ writer->writeEndElement();
94
+}
95
+
96
+Payload::Ptr BitsOfBinaryFactory::createPayload()
97
+{
98
+ return Payload::Ptr(m_query.take());
99
+}
100
+
101
+} // namespace Jreen
102
libjreen-1.1.0.tar.bz2/src/bitsofbinaryfactory_p.h
Added
56
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_BITSOFBINARYFACTORY_P_H
28
+#define JREEN_BITSOFBINARYFACTORY_P_H
29
+
30
+#include "bitsofbinary.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class JREEN_AUTOTEST_EXPORT BitsOfBinaryFactory : public Jreen::PayloadFactory<BitsOfBinary>
36
+{
37
+public:
38
+ BitsOfBinaryFactory();
39
+
40
+ QStringList features() const;
41
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
42
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
43
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
44
+ void handleCharacterData(const QStringRef &text);
45
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
46
+ Payload::Ptr createPayload();
47
+
48
+private:
49
+ int m_depth;
50
+ QScopedPointer<BitsOfBinary> m_query;
51
+};
52
+
53
+} // namespace Jreen
54
+
55
+#endif // JREEN_BITSOFBINARYFACTORY_P_H
56
libjreen-1.0.3.tar.bz2/src/bookmarkfactory_p.h -> libjreen-1.1.0.tar.bz2/src/bookmarkfactory_p.h
Changed
10
1
2
3
namespace Jreen {
4
5
-class BookmarkFactory : public PayloadFactory<Bookmark>
6
+class JREEN_AUTOTEST_EXPORT BookmarkFactory : public PayloadFactory<Bookmark>
7
{
8
public:
9
BookmarkFactory();
10
libjreen-1.0.3.tar.bz2/src/capabilitiesfactory.cpp -> libjreen-1.1.0.tar.bz2/src/capabilitiesfactory.cpp
Changed
37
1
2
3
namespace Jreen {
4
5
-
6
-QString CapabilitesFactory::hashValue(Disco *disco)
7
+QString CapabilitesFactory::verificationValue(Jreen::Disco *disco)
8
{
9
QString s;
10
QStringList sl;
11
12
s.append(value).append(QLatin1Char('<'));
13
}
14
}
15
+ return s;
16
+}
17
+
18
+QString CapabilitesFactory::hashValue(Disco *disco)
19
+{
20
+ const QString s = verificationValue(disco);
21
return QString::fromLatin1(QCryptographicHash::hash(s.toUtf8(), QCryptographicHash::Sha1).toBase64());
22
}
23
24
25
QString ver = caps->ver().isEmpty() ? hashValue(m_disco) : caps->ver();
26
writer->writeStartElement(QLatin1String("c"));
27
writer->writeDefaultNamespace(NS_CAPS);
28
- writer->writeAttribute(QLatin1String("hash"),QLatin1String("sha-1"));
29
- writer->writeAttribute(QLatin1String("ver"),ver);
30
- writer->writeAttribute(QLatin1String("node"),caps->node());
31
+ writer->writeAttribute(QLatin1String("hash"), QLatin1String("sha-1"));
32
+ writer->writeAttribute(QLatin1String("ver"), ver);
33
+ writer->writeAttribute(QLatin1String("node"), caps->node());
34
writer->writeEndElement();
35
}
36
37
libjreen-1.0.3.tar.bz2/src/capabilitiesfactory_p.h -> libjreen-1.1.0.tar.bz2/src/capabilitiesfactory_p.h
Changed
18
1
2
namespace Jreen {
3
4
class Disco;
5
-class CapabilitesFactory : public PayloadFactory<Capabilities>
6
+class JREEN_AUTOTEST_EXPORT CapabilitesFactory : public PayloadFactory<Capabilities>
7
{
8
public:
9
CapabilitesFactory(Disco *disco);
10
11
void handleCharacterData(const QStringRef &text);
12
void serialize(Payload *extension, QXmlStreamWriter *writer);
13
Payload::Ptr createPayload();
14
+ static QString verificationValue(Disco *disco);
15
static QString hashValue(Disco *disco);
16
private:
17
Disco *m_disco;
18
libjreen-1.1.0.tar.bz2/src/captcha.cpp
Added
57
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "captcha.h"
28
+
29
+namespace Jreen {
30
+
31
+class CaptchaPrivate
32
+{
33
+public:
34
+ DataForm::Ptr form;
35
+};
36
+
37
+Captcha::Captcha(DataForm::Ptr form) : d_ptr(new CaptchaPrivate)
38
+{
39
+ d_func()->form = form;
40
+}
41
+
42
+Captcha::~Captcha()
43
+{
44
+}
45
+
46
+DataForm::Ptr Captcha::form() const
47
+{
48
+ return d_func()->form;
49
+}
50
+
51
+void Captcha::setForm(const DataForm::Ptr &form)
52
+{
53
+ d_func()->form = form;
54
+}
55
+
56
+} // namespace Jreen
57
libjreen-1.1.0.tar.bz2/src/captcha.h
Added
54
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_CAPTCHA_H
28
+#define JREEN_CAPTCHA_H
29
+
30
+#include "dataform.h"
31
+
32
+namespace Jreen {
33
+
34
+class CaptchaPrivate;
35
+
36
+class JREEN_EXPORT Captcha : public Payload
37
+{
38
+ J_PAYLOAD(Jreen::Captcha)
39
+ Q_DECLARE_PRIVATE(Captcha)
40
+public:
41
+ Captcha(DataForm::Ptr form = DataForm::Ptr());
42
+ ~Captcha();
43
+
44
+ DataForm::Ptr form() const;
45
+ void setForm(const DataForm::Ptr &form);
46
+
47
+private:
48
+ QScopedPointer<CaptchaPrivate> d_ptr;
49
+};
50
+
51
+} // namespace Jreen
52
+
53
+#endif // JREEN_CAPTCHA_H
54
libjreen-1.1.0.tar.bz2/src/captchafactory.cpp
Added
98
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "captchafactory_p.h"
28
+
29
+#define NS_CAPTCHA QLatin1String("urn:xmpp:captcha")
30
+
31
+namespace Jreen {
32
+
33
+CaptchaFactory::CaptchaFactory() : m_depth(0), m_atFactory(0)
34
+{
35
+}
36
+
37
+QStringList CaptchaFactory::features() const
38
+{
39
+ return QStringList();
40
+}
41
+
42
+bool CaptchaFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
43
+{
44
+ Q_UNUSED(attributes);
45
+ return name == QLatin1String("captcha") && uri == NS_CAPTCHA;
46
+}
47
+
48
+void CaptchaFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
49
+{
50
+ ++m_depth;
51
+
52
+ if (m_depth == 1)
53
+ m_captcha.reset(new Captcha);
54
+ else if (m_depth == 2 && m_factory.canParse(name, uri, attributes))
55
+ m_atFactory = true;
56
+
57
+ if (m_atFactory)
58
+ m_factory.handleStartElement(name, uri, attributes);
59
+}
60
+
61
+void CaptchaFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
62
+{
63
+ if (m_atFactory) {
64
+ m_factory.handleEndElement(name, uri);
65
+ if (m_depth == 2) {
66
+ DataForm::Ptr form = m_factory.createPayload().staticCast<DataForm>();
67
+ if (form->typeName() == NS_CAPTCHA)
68
+ m_captcha->setForm(form);
69
+ m_atFactory = false;
70
+ }
71
+ }
72
+
73
+ --m_depth;
74
+}
75
+
76
+void CaptchaFactory::handleCharacterData(const QStringRef &text)
77
+{
78
+ if (m_atFactory)
79
+ m_factory.handleCharacterData(text);
80
+}
81
+
82
+void CaptchaFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
83
+{
84
+ Captcha *captcha = payload_cast<Captcha*>(extension);
85
+ writer->writeStartElement(QLatin1String("captcha"));
86
+ writer->writeDefaultNamespace(NS_CAPTCHA);
87
+ if (captcha->form())
88
+ m_factory.serialize(captcha->form().data(), writer);
89
+ writer->writeEndElement();
90
+}
91
+
92
+Payload::Ptr CaptchaFactory::createPayload()
93
+{
94
+ return Payload::Ptr(m_captcha.take());
95
+}
96
+
97
+} // namespace Jreen
98
libjreen-1.1.0.tar.bz2/src/captchafactory_p.h
Added
58
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_CAPTCHAFACTORY_P_H
28
+#define JREEN_CAPTCHAFACTORY_P_H
29
+
30
+#include "captcha.h"
31
+#include "dataformfactory_p.h"
32
+
33
+namespace Jreen {
34
+
35
+class JREEN_AUTOTEST_EXPORT CaptchaFactory : public PayloadFactory<Captcha>
36
+{
37
+public:
38
+ CaptchaFactory();
39
+
40
+ QStringList features() const;
41
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
42
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
43
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
44
+ void handleCharacterData(const QStringRef &text);
45
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
46
+ Payload::Ptr createPayload();
47
+
48
+private:
49
+ int m_depth : 31;
50
+ int m_atFactory : 1;
51
+ DataFormFactory m_factory;
52
+ QScopedPointer<Captcha> m_captcha;
53
+};
54
+
55
+} // namespace Jreen
56
+
57
+#endif // JREEN_CAPTCHAFACTORY_P_H
58
libjreen-1.0.3.tar.bz2/src/chatstatefactory_p.h -> libjreen-1.1.0.tar.bz2/src/chatstatefactory_p.h
Changed
10
1
2
3
namespace Jreen {
4
5
-class ChatStateFactory : public PayloadFactory<ChatState>
6
+class JREEN_AUTOTEST_EXPORT ChatStateFactory : public PayloadFactory<ChatState>
7
{
8
public:
9
ChatStateFactory();
10
libjreen-1.0.3.tar.bz2/src/client.cpp -> libjreen-1.1.0.tar.bz2/src/client.cpp
Changed
166
1
2
#include "pubsubmanager_p.h"
3
#include "tunefactory_p.h"
4
#include "bookmarkfactory_p.h"
5
+#include "metacontactsfactory_p.h"
6
#include "privacyqueryfactory_p.h"
7
#include "delayeddeliveryfactory_p.h"
8
#include "receiptfactory_p.h"
9
10
#include "chatstatefactory_p.h"
11
#include "capabilitiesfactory_p.h"
12
#include "errorfactory_p.h"
13
+#include "registrationqueryfactory_p.h"
14
+#include "bitsofbinaryfactory_p.h"
15
+#include "captchafactory_p.h"
16
+#include "pgpfactory_p.h"
17
+#include "forwardedfactory_p.h"
18
19
// Features
20
#include "nonsaslauth_p.h"
21
22
int type = StanzaPrivate::get(*stanza)->type;
23
if (type == StanzaPrivate::StanzaIq) {
24
QSharedPointer<IQ> iq = stanza.staticCast<IQ>();
25
- IQReply *reply = iqTracks.take(stanza->id());
26
- if (reply) {
27
- emit reply->received(*iq);
28
- reply->deleteLater();
29
- } else {
30
+ if (iq->subtype() == IQ::Result || iq->subtype() == IQ::Error) {
31
+ if (IQReply *reply = iqTracks.take(stanza->id())) {
32
+ emit reply->received(*iq);
33
+ reply->deleteLater();
34
+ }
35
+ } else if (iq->subtype() == IQ::Get || iq->subtype() == IQ::Set) {
36
bool ok = iq->from().isDomain()
37
|| !roster
38
|| rooms.contains(iq->from().bare())
39
40
return;
41
}
42
q_ptr->handleIQ(*iq);
43
- if (!iq->accepted() && (iq->subtype() == IQ::Set || iq->subtype() == IQ::Get)) {
44
+ if (!iq->accepted()) {
45
IQ error(IQ::Error, iq->from(), iq->id());
46
error.addExtension(new Error(Error::Cancel, Error::ServiceUnavailable));
47
send(error);
48
49
q_ptr->registerPayload(new MUCRoomOwnerQueryFactory);
50
q_ptr->registerPayload(new EntityTimeFactory);
51
q_ptr->registerPayload(new BookmarkFactory);
52
+ q_ptr->registerPayload(new MetaContactsFactory);
53
q_ptr->registerPayload(new PrivateXmlQueryFactory(q_ptr));
54
q_ptr->registerPayload(new PrivacyQueryFactory);
55
-// client->registerPayload(new PubSub::EventFactory);
56
-// client->registerPayload(new PubSub::PublishFacatory);
57
- //client->registerPayload(new PrivateXml::QueryFactory);
58
+ q_ptr->registerPayload(new RegistrationQueryFactory);
59
+ q_ptr->registerPayload(new BitsOfBinaryFactory);
60
+ q_ptr->registerPayload(new CaptchaFactory);
61
+ q_ptr->registerPayload(new PGPSignedFactory);
62
+ q_ptr->registerPayload(new PGPEncryptedFactory);
63
+ q_ptr->registerPayload(new ForwardedFactory(q_ptr));
64
65
q_ptr->registerStreamFeature(new NonSaslAuth);
66
q_ptr->registerStreamFeature(new SASLFeature);
67
68
q_ptr->registerStreamFeature(new BindFeature);
69
q_ptr->registerStreamFeature(new SessionFeature);
70
q_ptr->registerStreamFeature(new ZLibCompressionFeature);
71
- presence.addExtension(new Capabilities(QString(), QLatin1String("http://qutim.org/jreen/")));
72
+ presence.addExtension(new Capabilities(QString(), QLatin1String("http://qutim.org/jreen")));
73
}
74
75
Client::Client(const JID &jid, const QString &password, int port)
76
77
d->proxy = proxy;
78
}
79
80
+void Client::setFeatureConfig(Client::Feature feature, Client::FeatureConfig config)
81
+{
82
+ Q_D(Client);
83
+ if (feature < 0 || feature >= d->configs.size())
84
+ return;
85
+ d->configsfeature = config;
86
+}
87
+
88
+Client::FeatureConfig Client::featureConfig(Client::Feature feature) const
89
+{
90
+ Q_D(const Client);
91
+ return d->configs.value(feature, Auto);
92
+}
93
+
94
+bool Client::isFeatureActivated(Client::Feature feature) const
95
+{
96
+ Q_D(const Client);
97
+ return (d->usedFeatures & (1 << feature));
98
+}
99
+
100
QNetworkProxy Client::proxy() const
101
{
102
return d_func()->proxy;
103
104
105
void Client::setProxyFactory(QNetworkProxyFactory *factory)
106
{
107
- Q_D(Client);
108
d_func()->proxyFactory.reset(factory);
109
}
110
111
112
return d_func()->roster;
113
}
114
115
+JingleManager *Client::jingleManager()
116
+{
117
+ Q_D(Client);
118
+ if (!d->jingleManager)
119
+ d->jingleManager.reset(new JingleManager(this));
120
+ return d->jingleManager.data();
121
+}
122
+
123
void Client::send(const Stanza &stanza)
124
{
125
Q_D(Client);
126
127
delete d->conn;
128
d->conn = conn;
129
d->streamProcessor = qobject_cast<StreamProcessor*>(conn);
130
- d->device->setDevice(conn);
131
+ d->bufferedDevice->setDevice(conn);
132
// connect(conn, SIGNAL(readyRead()), impl, SLOT(newData()));
133
connect(conn, SIGNAL(connected()), this, SLOT(_q_connected()));
134
- connect(conn, SIGNAL(disconnected()), this, SLOT(_q_disconnected()));
135
+ connect(conn, SIGNAL(stateChanged(Jreen::Connection::SocketState)),
136
+ this, SLOT(_q_stateChanged(Jreen::Connection::SocketState)));
137
}
138
139
Connection *Client::connection() const
140
141
return a->type() == b->type() ? a->priority() > b->priority() : a->type() < b->type();
142
}
143
144
-void Client::registerStreamFeature(StreamFeature *stream_feature)
145
+void Client::registerStreamFeature(StreamFeature *streamFeature)
146
{
147
Q_D(Client);
148
- if(!stream_feature)
149
+ if(!streamFeature)
150
return;
151
d->features.insert(qLowerBound(d->features.begin(), d->features.end(),
152
- stream_feature, featureLessThan), stream_feature);
153
- stream_feature->setStreamInfo(d->stream_info);
154
+ streamFeature, featureLessThan), streamFeature);
155
+ streamFeature->setStreamInfo(d->stream_info);
156
+}
157
+
158
+void Client::removeStreamFeature(StreamFeature *streamFeature)
159
+{
160
+ Q_D(Client);
161
+ d->features.removeAll(streamFeature);
162
+ streamFeature->setStreamInfo(0);
163
}
164
165
void Client::setPingInterval(int interval)
166
libjreen-1.0.3.tar.bz2/src/client.h -> libjreen-1.1.0.tar.bz2/src/client.h
Changed
83
1
2
#include "presence.h"
3
#include "disco.h"
4
5
-class QNetworkProxyFactory;
6
+class JREEN_AUTOTEST_EXPORT QNetworkProxyFactory;
7
class QNetworkProxy;
8
9
namespace Jreen
10
11
class Disco;
12
class MessageSessionManager;
13
class AbstractRoster;
14
+class JingleManager;
15
16
class XmlStreamHandler
17
{
18
19
InternalServerError,
20
SystemShutdown,
21
Conflict,
22
- Unknown
23
+ Unknown,
24
+ NoCompressionSupport,
25
+ NoEncryptionSupport,
26
+ NoAuthorizationSupport,
27
+ NoSupportedFeature
28
};
29
+
30
+ enum Feature {
31
+ InvalidFeature = -1,
32
+ Compression = 0,
33
+ Encryption,
34
+ Authorization
35
+ };
36
+
37
+ enum FeatureConfig {
38
+ Force,
39
+ Disable,
40
+ Auto
41
+ };
42
+
43
Client(const JID &jid, const QString &password = QString(), int port = -1);
44
Client();
45
virtual ~Client();
46
47
void setResource(const QString &resource);
48
void setPort(int port);
49
void setProxy(const QNetworkProxy &proxy);
50
+ void setFeatureConfig(Feature feature, FeatureConfig config);
51
+ FeatureConfig featureConfig(Feature feature) const;
52
+ bool isFeatureActivated(Feature feature) const;
53
QNetworkProxy proxy() const;
54
void setProxyFactory(QNetworkProxyFactory *factory);
55
QNetworkProxyFactory *proxyFactory() const;
56
57
Disco *disco();
58
MessageSessionManager *messageSessionManager();
59
AbstractRoster *roster();
60
+ JingleManager *jingleManager();
61
bool isConnected() const;
62
void send(const Stanza &stanza);
63
void send(const Presence &pres);
64
65
void setConnection(Connection *conn);
66
Connection *connection() const;
67
void registerPayload(AbstractPayloadFactory *factory);
68
- void registerStreamFeature(StreamFeature *stream_feature);
69
+ void registerStreamFeature(StreamFeature *streamFeature);
70
+ void removeStreamFeature(StreamFeature *streamFeature);
71
public slots:
72
void setPresence();
73
void setPresence(Jreen::Presence::Type type, const QString &text = QString(), int priority = -129);
74
75
Q_PRIVATE_SLOT(d_func(), void _q_read_more())
76
Q_PRIVATE_SLOT(d_func(), void _q_send_header())
77
Q_PRIVATE_SLOT(d_func(), void _q_connected())
78
- Q_PRIVATE_SLOT(d_func(), void _q_disconnected())
79
+ Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(Jreen::Connection::SocketState))
80
};
81
82
}
83
libjreen-1.0.3.tar.bz2/src/client_p.h -> libjreen-1.1.0.tar.bz2/src/client_p.h
Changed
196
1
2
#include <QNetworkProxyFactory>
3
#include "stanza_p.h"
4
#include "streamprocessor.h"
5
+#include "experimental/jinglemanager.h"
6
7
namespace Jreen
8
{
9
10
roster = 0;
11
authorized = false;
12
isConnected = false;
13
- device = new BufferedDataStream(&streamHandlers);
14
- device->open(QIODevice::ReadWrite);
15
- q->connect(device, SIGNAL(readyRead()), q, SLOT(_q_new_data()));
16
+ bufferedDevice.reset(new BufferedDataStream(&streamHandlers));
17
+ bufferedDevice->open(QIODevice::ReadWrite);
18
+ q->connect(bufferedDevice.data(), SIGNAL(readyRead()), q, SLOT(_q_new_data()));
19
+ configs.append(Client::Auto);
20
+ configs.append(Client::Auto);
21
+ configs.append(Client::Force);
22
+ usedFeatures = 0;
23
}
24
void init();
25
void send(const Stanza &stanza)
26
{
27
- if(stanza.from().full().isEmpty()) {
28
+ if(isConnected && stanza.from().full().isEmpty()) {
29
const StanzaPrivate *p = StanzaPrivate::get(stanza);
30
const_cast<StanzaPrivate*>(p)->from = jid;
31
}
32
foreach (StanzaFactory *factory, stanzas) {
33
if (factory->stanzaType() == StanzaPrivate::get(stanza)->type) {
34
- factory->serialize(const_cast<Stanza*>(&stanza), writer);
35
+ factory->serialize(const_cast<Stanza*>(&stanza), writer.data());
36
break;
37
}
38
}
39
}
40
void send(const QString &data)
41
{
42
- if(conn && device->isOpen())
43
- device->write(data.toUtf8());
44
+ if(conn && bufferedDevice->isOpen())
45
+ bufferedDevice->write(data.toUtf8());
46
}
47
void processStreamFeature(StreamFeature *stream_feature)
48
{
49
50
int current_id;
51
Parser *parser;
52
Connection *conn;
53
- DataStream *device;
54
+ QScopedPointer<BufferedDataStream> bufferedDevice;
55
StreamProcessor *streamProcessor;
56
QList<DataStream*> devices;
57
bool authorized;
58
59
Disco *disco;
60
StreamFeature *current_stream_feature;
61
QHash<QString, IQReply*> iqTracks;
62
- QXmlStreamWriter *writer;
63
+ QScopedPointer<QXmlStreamWriter> writer;
64
+ QVector<Client::FeatureConfig> configs;
65
+ int usedFeatures;
66
QList<StanzaFactory*> stanzas;
67
QList<StreamFeature*> features;
68
QSet<QString> serverFeatures;
69
Jreen::Disco::IdentityList serverIdentities;
70
- QMap<QString, MUCRoomPrivate*> rooms;
71
+ QHash<QString, MUCRoomPrivate*> rooms;
72
PayloadFactoryMap factories;
73
- QMultiMap<QString, AbstractPayloadFactory*> factoriesByUri;
74
+ QMultiHash<QString, AbstractPayloadFactory*> factoriesByUri;
75
MessageSessionManager *messageSessionManager;
76
AbstractRoster *roster;
77
+ QScopedPointer<JingleManager> jingleManager;
78
int depth;
79
IQReply *createIQReply() { return new IQReply(q_func()); }
80
void _q_iq_received(const Jreen::IQ &iq, int context);
81
void _q_new_data()
82
{
83
- QByteArray data = device->read(qMax(Q_INT64_C(0xffff), device->bytesAvailable())); // device->readAll();
84
+ QByteArray data = bufferedDevice->read(qMax(Q_INT64_C(0xffff), bufferedDevice->bytesAvailable())); // device->readAll();
85
// Logger::debug() << "-" << data.size() << data;
86
parser->appendData(data);
87
// parser->appendData(data);
88
89
void _q_read_more();
90
void _q_send_header()
91
{
92
- delete writer;
93
foreach (XmlStreamHandler *handler, streamHandlers)
94
handler->handleStreamBegin();
95
if (streamProcessor) {
96
- writer = new QXmlStreamWriter(device);
97
-// QByteArray data;
98
-// QBuffer buffer(&data);
99
-// buffer.open(QIODevice::WriteOnly);
100
-// streamProcessor->restartStream();
101
-// writer = new QXmlStreamWriter(&buffer);
102
-// writer->writeStartDocument(QLatin1String("1.0"));
103
-// writer->writeStartElement(QLatin1String("stream:stream"));
104
-// writer->writeDefaultNamespace(QLatin1String("jabber:client"));
105
-// writer->writeCharacters(QString());
106
-// writer->setDevice(device);
107
+ writer.reset(new QXmlStreamWriter(bufferedDevice.data()));
108
return;
109
}
110
- writer = new QXmlStreamWriter(device);
111
+ writer.reset(new QXmlStreamWriter(bufferedDevice.data()));
112
writer->writeStartDocument(QLatin1String("1.0"));
113
writer->writeStartElement(QLatin1String("stream:stream"));
114
writer->writeAttribute(QLatin1String("to"), jid.domain());
115
116
117
void _q_connected()
118
{
119
- writer = 0;
120
+ writer.reset();
121
depth = 0;
122
parser->reset();
123
_q_send_header();
124
- isConnected = true;
125
}
126
void _q_disconnected()
127
{
128
pingTimer.stop();
129
isConnected = false;
130
+ usedFeatures = 0;
131
foreach (XmlStreamHandler *handler, streamHandlers)
132
handler->handleStreamEnd();
133
authorized = false;
134
135
foreach (DataStream *dataStream, devices)
136
dataStream->deleteLater();
137
devices.clear();
138
- device->setDevice(conn);
139
+ bufferedDevice->setDevice(conn);
140
QHash<QString, IQReply*>::iterator it = iqTracks.begin();
141
for (; it != iqTracks.end(); ++it)
142
it.value()->deleteLater();
143
iqTracks.clear();
144
}
145
- inline void emitAuthorized() { q_ptr->handleAuthorized(); }
146
+ void _q_stateChanged(Connection::SocketState state)
147
+ {
148
+ if (state == Connection::UnconnectedState)
149
+ _q_disconnected();
150
+ }
151
+
152
+ inline void emitAuthorized() { authorized = true; q_ptr->handleAuthorized(); }
153
inline void emitConnected() { isConnected = true; q_ptr->handleConnect(); }
154
inline void emitDisconnected(Client::DisconnectReason reason)
155
{
156
- emit q_func()->disconnected(reason);
157
+ Q_Q(Client);
158
+ writer->writeEndElement();
159
+ q->blockSignals(true);
160
+ conn->close();
161
+ _q_disconnected();
162
+ q->blockSignals(false);
163
+ emit q->disconnected(reason);
164
}
165
};
166
167
168
}
169
QXmlStreamWriter *writer()
170
{
171
- return d->writer;
172
+ return d->writer.data();
173
}
174
void completed(const CompletedFlags &flags)
175
{
176
177
if(flags & Authorized)
178
d->emitAuthorized();
179
if (flags & ResendHeader) {
180
- d->device->readAll();
181
+ d->bufferedDevice->readAll();
182
d->_q_send_header();
183
if (d->streamProcessor)
184
d->streamProcessor->restartStream();
185
186
void addDataStream(DataStream *dataStream)
187
{
188
d->devices.append(dataStream);
189
- dataStream->setDevice(d->device->device());
190
- d->device->setDevice(dataStream);
191
+ dataStream->setDevice(d->bufferedDevice->device());
192
+ d->bufferedDevice->setDevice(dataStream);
193
// QObject::disconnect(m_client_private->device, 0, m_client_private, 0);
194
// m_client_private->device = dataStream;
195
dataStream->open(QIODevice::ReadWrite);
196
libjreen-1.0.3.tar.bz2/src/dataform.cpp -> libjreen-1.1.0.tar.bz2/src/dataform.cpp
Changed
185
1
2
3
#include "dataform_p.h"
4
#include "jstrings.h"
5
+#include "stanza.h"
6
+#include "bitsofbinary.h"
7
#include <QStringList>
8
+#include <QSize>
9
+#include <QUrl>
10
11
namespace Jreen
12
{
13
14
+class DataFormMedia::UriPrivate : public QSharedData
15
+{
16
+public:
17
+ UriPrivate() {}
18
+ UriPrivate(const UriPrivate &o) : QSharedData(o), url(o.url), type(o.type) {}
19
+
20
+ QUrl url;
21
+ QString type;
22
+};
23
+
24
+DataFormMedia::Uri::Uri() : d(new UriPrivate)
25
+{
26
+}
27
+
28
+DataFormMedia::Uri::Uri(const QUrl &url, const QString &type) : d(new UriPrivate)
29
+{
30
+ d->url = url;
31
+ d->type = type;
32
+}
33
+
34
+DataFormMedia::Uri::Uri(const DataFormMedia::Uri &o) : d(o.d)
35
+{
36
+}
37
+
38
+DataFormMedia::Uri &DataFormMedia::Uri::operator =(const DataFormMedia::Uri &o)
39
+{
40
+ d = o.d;
41
+ return *this;
42
+}
43
+
44
+DataFormMedia::Uri::~Uri()
45
+{
46
+}
47
+
48
+bool DataFormMedia::Uri::operator ==(const DataFormMedia::Uri &o) const
49
+{
50
+ return d->type == o.d->type && d->url == o.d->url;
51
+}
52
+
53
+QUrl DataFormMedia::Uri::url() const
54
+{
55
+ return d->url;
56
+}
57
+
58
+void DataFormMedia::Uri::setUrl(const QUrl &url)
59
+{
60
+ d->url = url;
61
+}
62
+
63
+QString DataFormMedia::Uri::type() const
64
+{
65
+ return d->type;
66
+}
67
+
68
+void DataFormMedia::Uri::setType(const QString &type)
69
+{
70
+ d->type = type;
71
+}
72
+
73
+class DataFormMediaPrivate
74
+{
75
+public:
76
+ QSize size;
77
+ QList<DataFormMedia::Uri> uries;
78
+};
79
+
80
+DataFormMedia::DataFormMedia() : d_ptr(new DataFormMediaPrivate)
81
+{
82
+}
83
+
84
+DataFormMedia::~DataFormMedia()
85
+{
86
+}
87
+
88
+void DataFormMedia::appendUri(const DataFormMedia::Uri &uri)
89
+{
90
+ d_func()->uries.append(uri);
91
+}
92
+
93
+void DataFormMedia::appendUri(const QUrl &url, const QString &type)
94
+{
95
+ d_func()->uries.append(Uri(url, type));
96
+}
97
+
98
+void DataFormMedia::setUries(const QList<DataFormMedia::Uri> &uries)
99
+{
100
+ d_func()->uries = uries;
101
+}
102
+
103
+QList<DataFormMedia::Uri> DataFormMedia::uries() const
104
+{
105
+ return d_func()->uries;
106
+}
107
+
108
+QSize DataFormMedia::size() const
109
+{
110
+ return d_func()->size;
111
+}
112
+
113
+void DataFormMedia::setSize(const QSize &size)
114
+{
115
+ d_func()->size = size;
116
+}
117
+
118
+int DataFormMedia::width() const
119
+{
120
+ return d_func()->size.width();
121
+}
122
+
123
+void DataFormMedia::setWidth(int width)
124
+{
125
+ d_func()->size.setWidth(width);
126
+}
127
+
128
+int DataFormMedia::height() const
129
+{
130
+ return d_func()->size.height();
131
+}
132
+
133
+void DataFormMedia::setHeight(int height)
134
+{
135
+ d_func()->size.setHeight(height);
136
+}
137
+
138
DataFormField::DataFormField(Type type, const QString &var, const QString &label) : d_ptr(new DataFormFieldPrivate)
139
{
140
d_ptr->type = type;
141
142
d_ptr->desc = desc;
143
}
144
145
+DataFormMedia::Ptr DataFormField::media() const
146
+{
147
+ return d_ptr->media;
148
+}
149
+
150
+void DataFormField::setMedia(const DataFormMedia::Ptr &media)
151
+{
152
+ d_ptr->media = media;
153
+}
154
+
155
void DataFormField::setValues(const QStringList &values)
156
{
157
d_ptr->values = values;
158
159
d->title = title;
160
}
161
162
+DataForm::DataForm(DataForm::Type type, const QString &title, const QString &instructions) : DataFormFieldContainer(*new DataFormPrivate)
163
+{
164
+ Q_D(DataForm);
165
+ d->type = type;
166
+ d->title = title;
167
+ d->instructions = instructions;
168
+}
169
+
170
DataForm::~DataForm()
171
{
172
}
173
174
return d_func()->title;
175
}
176
177
+QString DataForm::instructions() const
178
+{
179
+ return d_func()->instructions;
180
+}
181
+
182
QList<DataFormItem::Ptr> DataForm::items() const
183
{
184
return d_func()->items;
185
libjreen-1.0.3.tar.bz2/src/dataform.h -> libjreen-1.1.0.tar.bz2/src/dataform.h
Changed
99
1
2
// http://xmpp.org/extensions/xep-0004.html
3
4
class DataFormFieldPrivate;
5
+class DataFormMediaPrivate;
6
+class Stanza;
7
+
8
+class JREEN_EXPORT DataFormMedia
9
+{
10
+ Q_DECLARE_PRIVATE(DataFormMedia)
11
+public:
12
+ typedef QSharedPointer<DataFormMedia> Ptr;
13
+
14
+ class UriPrivate;
15
+ class JREEN_EXPORT Uri
16
+ {
17
+ public:
18
+ Uri();
19
+ Uri(const QUrl &url, const QString &type);
20
+ Uri(const Uri &o);
21
+ Uri &operator =(const Uri &o);
22
+ ~Uri();
23
+
24
+ bool operator==(const Uri &o) const;
25
+
26
+ QUrl url() const;
27
+ void setUrl(const QUrl &url);
28
+ QString type() const;
29
+ void setType(const QString &type);
30
+ private:
31
+ QSharedDataPointer<UriPrivate> d;
32
+ };
33
+
34
+ DataFormMedia();
35
+ ~DataFormMedia();
36
+
37
+ void appendUri(const Uri &uri);
38
+ void appendUri(const QUrl &url, const QString &type);
39
+ void setUries(const QList<Uri> &uries);
40
+ QList<Uri> uries() const;
41
+
42
+ QSize size() const;
43
+ void setSize(const QSize &size);
44
+ int width() const;
45
+ void setWidth(int width);
46
+ int height() const;
47
+ void setHeight(int height);
48
+
49
+private:
50
+ Q_DISABLE_COPY(DataFormMedia)
51
+ QScopedPointer<DataFormMediaPrivate> d_ptr;
52
+};
53
+
54
class JREEN_EXPORT DataFormField
55
{
56
public:
57
enum Type
58
{
59
+ Invalid = -1,
60
Boolean, /**< The field enables an entity to gather or provide an either-or
61
* choice between two options. The default value is "false". */
62
Fixed, /**< The field is intended for data description (e.g., human-readable
63
64
* line or word of text, which may be shown in an interface.
65
* This field type is the default and MUST be assumed if a form-submitting
66
* entity receives a field type it does not understand. */
67
- None,
68
- Invalid
69
+ None
70
};
71
72
DataFormField(Type type = Invalid, const QString &var = QString(), const QString &label = QString());
73
74
QString description() const;
75
void setDescription(const QString &desc);
76
77
+ DataFormMedia::Ptr media() const;
78
+ void setMedia(const DataFormMedia::Ptr &media);
79
+
80
void setValues(const QStringList &values);
81
QStringList values() const;
82
void setValue(const QString &value);
83
84
Invalid
85
};
86
DataForm(Type type = Submit, const QString &title = QString());
87
+ DataForm(Type type, const QString &title, const QString &instructions);
88
virtual ~DataForm();
89
90
Type type() const;
91
92
QString typeName() const;
93
void setTypeName(const QString &type);
94
QString title() const;
95
+ QString instructions() const;
96
QList<DataFormItem::Ptr> items() const;
97
DataFormReported::Ptr reported() const;
98
};
99
libjreen-1.0.3.tar.bz2/src/dataform_p.h -> libjreen-1.1.0.tar.bz2/src/dataform_p.h
Changed
17
1
2
QStringList values;
3
bool required;
4
QList<QPair<QString,QString> > options;
5
+ DataFormMedia::Ptr media;
6
7
static DataFormFieldPrivate *get(DataFormField *field) { return field->d_ptr.data(); }
8
private:
9
10
{
11
public:
12
QString title;
13
+ QString instructions;
14
DataFormReported::Ptr reported;
15
QList<DataFormItem::Ptr> items;
16
DataForm::Type type;
17
libjreen-1.0.3.tar.bz2/src/dataformfactory.cpp -> libjreen-1.1.0.tar.bz2/src/dataformfactory.cpp
Changed
235
1
2
#include "dataformfactory_p.h"
3
#include "jstrings.h"
4
#include <QXmlStreamWriter>
5
+#include <QSize>
6
+#include <QUrl>
7
#include "util.h"
8
-#include "multimediadatafactory_p.h"
9
#include "logger.h"
10
#define NS_DATAFORM QLatin1String("jabber:x:data")
11
+#define NS_MEDIA QLatin1String("urn:xmpp:media-element")
12
13
namespace Jreen {
14
15
16
QString m_value;
17
};
18
19
+class DataFormMediaParser : public XmlStreamFactory<DataFormMedia>
20
+{
21
+public:
22
+ DataFormMediaParser() : m_depth(0), m_state(AtNowhere)
23
+ {
24
+ }
25
+
26
+ virtual ~DataFormMediaParser()
27
+ {
28
+ }
29
+
30
+ virtual bool canParse(const QStringRef &name, const QStringRef &uri,
31
+ const QXmlStreamAttributes &attributes)
32
+ {
33
+ Q_UNUSED(attributes);
34
+ return name == QLatin1String("media") && uri == NS_MEDIA;
35
+ }
36
+ virtual void handleStartElement(const QStringRef &name, const QStringRef &uri,
37
+ const QXmlStreamAttributes &attributes)
38
+ {
39
+ Q_UNUSED(name);
40
+ Q_UNUSED(uri);
41
+ m_depth++;
42
+
43
+ if(m_depth == 1) {
44
+ m_state = AtNowhere;
45
+ m_media = DataFormMedia::Ptr::create();
46
+ } else if (m_depth == 2 && name == QLatin1String("uri")) {
47
+ m_state = AtUri;
48
+ m_uriType = attributes.value(QLatin1String("type")).toString();
49
+ }
50
+ }
51
+ virtual void handleEndElement(const QStringRef &name, const QStringRef &uri)
52
+ {
53
+ Q_UNUSED(name);
54
+ Q_UNUSED(uri);
55
+ if (m_depth == 2)
56
+ m_state = AtNowhere;
57
+ m_depth--;
58
+ }
59
+ virtual void handleCharacterData(const QStringRef &text)
60
+ {
61
+ if(m_depth == 2 && m_state == AtUri) {
62
+ m_media->appendUri(text.toString(), m_uriType);
63
+ }
64
+ }
65
+ virtual void serialize(DataFormMedia *media, QXmlStreamWriter *writer)
66
+ {
67
+ writer->writeStartElement(QLatin1String("media"));
68
+ const QSize size = media->size();
69
+ if (size.width() >= 0)
70
+ writer->writeAttribute(QLatin1String("width"), QString::number(size.width()));
71
+ if (size.height() >= 0)
72
+ writer->writeAttribute(QLatin1String("height"), QString::number(size.height()));
73
+ writer->writeDefaultNamespace(NS_MEDIA);
74
+ foreach (const DataFormMedia::Uri &uri, media->uries()) {
75
+ writer->writeStartElement(QLatin1String("uri"));
76
+ writer->writeAttribute(QLatin1String("type"), uri.type());
77
+ writer->writeCharacters(uri.url().toString());
78
+ writer->writeEndElement();
79
+ }
80
+ writer->writeEndElement();
81
+ }
82
+ DataFormMedia::Ptr create()
83
+ {
84
+ DataFormMedia::Ptr result;
85
+ qSwap(result, m_media);
86
+ return result;
87
+ }
88
+
89
+private:
90
+ int m_depth;
91
+ enum State {
92
+ AtNowhere,
93
+ AtUri
94
+ } m_state;
95
+ QString m_uriType;
96
+ DataFormMedia::Ptr m_media;
97
+};
98
+
99
static const char* datafield_types = {
100
"boolean",
101
"fixed",
102
103
"list-single",
104
"text-multi",
105
"text-private",
106
- "text-single"
107
+ "text-single",
108
+ ""
109
};
110
111
class DataFormFieldParser : XmlStreamFactory<DataFormField>
112
113
m_state = AtValue;
114
} else if(m_optionParser.canParse(name,uri,attributes)) {
115
m_state = AtOption;
116
+ } else if (m_mediaParser.canParse(name, uri, attributes)) {
117
+ m_state = AtMedia;
118
} else if(name == QLatin1String("required")) {
119
m_state = AtRequied;
120
m_required = true;
121
122
}
123
if(m_state == AtOption)
124
m_optionParser.handleStartElement(name,uri,attributes);
125
+ else if(m_state == AtMedia)
126
+ m_mediaParser.handleStartElement(name, uri, attributes);
127
}
128
virtual void handleEndElement(const QStringRef &name, const QStringRef &uri)
129
{
130
131
Logger::debug() << m_optionParser.create();
132
m_options.append(m_optionParser.create());
133
}
134
+ } else if(m_state == AtMedia) {
135
+ m_mediaParser.handleEndElement(name, uri);
136
+ if(m_depth == 2)
137
+ m_media = m_mediaParser.create();
138
}
139
if (m_depth <= 2)
140
m_state = AtNowhere;
141
142
break;
143
case AtOption:
144
m_optionParser.handleCharacterData(text);
145
+ break;
146
+ case AtMedia:
147
+ m_mediaParser.handleCharacterData(text);
148
+ break;
149
default:
150
break;
151
}
152
153
d->label = m_label;
154
d->type = m_type;
155
d->options = m_options;
156
-// Logger::debug() << m_label << m_var << field.var() << field.label() << d->var << d->label;
157
d->required = m_required;
158
+ d->media = m_media;
159
clear();
160
return field;
161
}
162
163
AtValue,
164
AtOption,
165
AtRequied,
166
+ AtMedia,
167
AtNowhere
168
};
169
void clear() {
170
171
m_label.clear();
172
m_var.clear();
173
m_values.clear();
174
+ m_media.clear();
175
m_required = false;
176
m_state = AtNowhere;
177
}
178
State m_state;
179
+// QScopedPointer<DataFormFieldPrivate> m_form;
180
int m_depth;
181
DataFormField::Type m_type;
182
QString m_label;
183
184
QStringList m_values;
185
QList<QPair<QString, QString> > m_options;
186
bool m_required;
187
+ DataFormMedia::Ptr m_media;
188
DataFormOptionParser m_optionParser;
189
- MultimediaDataFactory m_multimediaDataFactory;
190
+ DataFormMediaParser m_mediaParser;
191
};
192
193
enum DataFormState { AtNowhere, AtTitle, AtInstruction, AtField };
194
195
"result"
196
};
197
198
-class DataFormFactoryPrivate
199
+class JREEN_AUTOTEST_EXPORT DataFormFactoryPrivate
200
{
201
public:
202
void clear()
203
204
d->state = AtField;
205
else if(name == QLatin1String("title"))
206
d->state = AtTitle;
207
- else if(name == QLatin1String("instruction"))
208
+ else if(name == QLatin1String("instructions"))
209
d->state = AtInstruction;
210
else
211
d->state = AtNowhere;
212
213
switch(d->state) {
214
case AtTitle:
215
d->title = text.toString();
216
+ break;
217
case AtInstruction:
218
d->instruction = text.toString();
219
+ break;
220
case AtField:
221
d->fieldParser.handleCharacterData(text);
222
+ break;
223
default:
224
break;
225
}
226
227
Payload::Ptr DataFormFactory::createPayload()
228
{
229
Q_D(DataFormFactory);
230
- DataForm *form = new DataForm(d->formType,d->title);
231
+ DataForm *form = new DataForm(d->formType, d->title, d->instruction);
232
form->setFields(d->fields);
233
d->clear();
234
return Payload::Ptr(form);
235
libjreen-1.0.3.tar.bz2/src/dataformfactory_p.h -> libjreen-1.1.0.tar.bz2/src/dataformfactory_p.h
Changed
12
1
2
3
namespace Jreen {
4
5
-class DataFormFactoryPrivate;
6
-class DataFormFactory : public PayloadFactory<DataForm>
7
+class JREEN_AUTOTEST_EXPORT DataFormFactoryPrivate;
8
+class JREEN_AUTOTEST_EXPORT DataFormFactory : public PayloadFactory<DataForm>
9
{
10
Q_DECLARE_PRIVATE(DataFormFactory)
11
public:
12
libjreen-1.0.3.tar.bz2/src/delayeddeliveryfactory.cpp -> libjreen-1.1.0.tar.bz2/src/delayeddeliveryfactory.cpp
Changed
27
1
2
#include "util.h"
3
4
5
-#define NS_DELAY "urn:xmpp:delay"
6
-#define NS_DELAY_DEPRECATED "jabber:x:delay"
7
+#define NS_DELAY QLatin1String("urn:xmpp:delay")
8
+#define NS_DELAY_DEPRECATED QLatin1String("jabber:x:delay")
9
10
namespace Jreen {
11
12
-class DelayedDeliveryFactoryPrivate
13
+class JREEN_AUTOTEST_EXPORT DelayedDeliveryFactoryPrivate
14
{
15
public:
16
JID from;
17
18
writer->writeStartElement(QLatin1String("delay"));
19
writer->writeAttribute(QLatin1String("stamp"), Util::toStamp(delivery->dateTime()));
20
writer->writeDefaultNamespace(NS_DELAY);
21
- writer->writeAttribute(QLatin1String("from"), delivery->from());
22
+ if (delivery->from().isValid())
23
+ writer->writeAttribute(QLatin1String("from"), delivery->from());
24
writer->writeCharacters(delivery->reason());
25
writer->writeEndElement();
26
}
27
libjreen-1.0.3.tar.bz2/src/delayeddeliveryfactory_p.h -> libjreen-1.1.0.tar.bz2/src/delayeddeliveryfactory_p.h
Changed
12
1
2
namespace Jreen
3
{
4
5
-class DelayedDeliveryFactoryPrivate;
6
-class DelayedDeliveryFactory : public PayloadFactory<DelayedDelivery>
7
+class JREEN_AUTOTEST_EXPORT DelayedDeliveryFactoryPrivate;
8
+class JREEN_AUTOTEST_EXPORT DelayedDeliveryFactory : public PayloadFactory<DelayedDelivery>
9
{
10
Q_DECLARE_PRIVATE(DelayedDeliveryFactory)
11
public:
12
libjreen-1.0.3.tar.bz2/src/directconnection.cpp -> libjreen-1.1.0.tar.bz2/src/directconnection.cpp
Changed
130
1
2
#include <QSslConfiguration>
3
#include <QSsl>
4
5
+#ifdef Q_OS_LINUX
6
+# include <sys/types.h>
7
+# include <sys/socket.h>
8
+# include <netinet/in.h>
9
+# include <netinet/tcp.h>
10
+#endif
11
+
12
namespace Jreen
13
{
14
15
+DirectConnectionPrivate::DirectConnectionPrivate(const QString &hn, int p, DirectConnection *par)
16
+ : host_name(hn), port(p), dns_lookup_id(-1), parent(par)
17
+{
18
+ do_lookup = p < 0 || !QUrl(host_name).isValid();
19
+ socket_state = QAbstractSocket::UnconnectedState;
20
+ socket_error = QAbstractSocket::UnknownSocketError;
21
+}
22
+
23
+void DirectConnectionPrivate::connectSocket()
24
+{
25
+ if (qobject_cast<QSslSocket*>(socket)) {
26
+ connect(socket, SIGNAL(encrypted()), parent, SIGNAL(connected()));
27
+ } else {
28
+ connect(socket, SIGNAL(connected()), parent, SIGNAL(connected()));
29
+ }
30
+ connect(socket, SIGNAL(disconnected()), parent, SIGNAL(disconnected()));
31
+ connect(socket, SIGNAL(readyRead()), parent, SIGNAL(readyRead()));
32
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
33
+ this, SLOT(stateChanged(QAbstractSocket::SocketState)));
34
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
35
+ this, SLOT(error(QAbstractSocket::SocketError)));
36
+ connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
37
+ parent, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
38
+}
39
+
40
+void DirectConnectionPrivate::doLookup()
41
+{
42
+ Logger::debug() << "doLookup";
43
+ emit stateChanged(QAbstractSocket::HostLookupState);
44
+
45
+ if (SJDns::instance().isValid())
46
+ SJDns::instance().doLookup(host_name, this, SLOT(lookupResultsReady()));
47
+ else
48
+ emit stateChanged(QAbstractSocket::UnconnectedState);
49
+}
50
+
51
+void DirectConnectionPrivate::lookupResultsReady()
52
+{
53
+ const QJDns::Response *response = SJDns::instance().servers(host_name);
54
+ dns_records.clear();
55
+ if (!response || !response->answerRecords.size()) {
56
+ Record record;
57
+ record.host = host_name;
58
+ dns_records << record;
59
+ } else {
60
+ foreach(const QJDns::Record &qrecord, response->answerRecords) {
61
+ Record record;
62
+ record.host = QUrl::fromAce(qrecord.name);
63
+ // may be it's a reason of connection problems of some users
64
+ if (record.host.endsWith(QLatin1Char('.')))
65
+ record.host.chop(1);
66
+ record.port = qrecord.port;
67
+ record.weight = qrecord.weight;
68
+ record.priority = qrecord.priority;
69
+ dns_records << record;
70
+ }
71
+ }
72
+ Record &record = dns_records0;
73
+ Logger::debug() << "use:" << record.host << record.port;
74
+ socket->connectToHost(record.host, record.port);
75
+}
76
+
77
+void DirectConnectionPrivate::stateChanged(QAbstractSocket::SocketState ss)
78
+{
79
+ Logger::debug() << ss;
80
+ if(socket_state == ss)
81
+ return;
82
+
83
+ switch(ss) {
84
+ case QAbstractSocket::ConnectedState: {
85
+#ifdef Q_OS_LINUX
86
+ if (qobject_cast<QTcpSocket*>(socket)) {
87
+ int fd = socket->socketDescriptor();
88
+ Q_ASSERT(fd != -1);
89
+ Logger::debug() << "Trying to set KeepAlive attributes to socket descriptor" << fd;
90
+ if (fd != -1) {
91
+ socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
92
+ int enableKeepAlive = 1;
93
+ Logger::debug() << setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &enableKeepAlive, sizeof(enableKeepAlive));
94
+
95
+ int maxIdle = 15; // seconds
96
+ Logger::debug() << setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &maxIdle, sizeof(maxIdle));
97
+
98
+ int count = 3; // send up to 3 keepalive packets out, then disconnect if no response
99
+ Logger::debug() << setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &count, sizeof(count));
100
+
101
+ int interval = 2; // send a keepalive packet out every 2 seconds (after the idle period)
102
+ Logger::debug() << setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
103
+ }
104
+ }
105
+#endif
106
+ socket_state = QAbstractSocket::ListeningState;
107
+ parent->open();
108
+ return;
109
+ }
110
+ case QAbstractSocket::ClosingState:
111
+ parent->close();
112
+ break;
113
+ default:
114
+ break;
115
+ }
116
+
117
+ socket_state = ss;
118
+ emit parent->stateChanged(static_cast<Connection::SocketState>(ss));
119
+}
120
+
121
+void DirectConnectionPrivate::error(QAbstractSocket::SocketError se)
122
+{
123
+ socket_error = se;
124
+ emit parent->error(static_cast<Connection::SocketError>(se));
125
+}
126
+
127
DirectConnection::DirectConnection(QAbstractSocket *socket, const QString &host_name, qint16 port)
128
: d_ptr(new DirectConnectionPrivate(host_name, port, this))
129
{
130
libjreen-1.0.3.tar.bz2/src/directconnection_p.h -> libjreen-1.1.0.tar.bz2/src/directconnection_p.h
Changed
116
1
2
int weight;
3
int priority;
4
};
5
- DirectConnectionPrivate(const QString &hn, int p, DirectConnection *par)
6
- : host_name(hn), port(p), dns_lookup_id(-1), parent(par)
7
- {
8
- do_lookup = p < 0 || !QUrl(host_name).isValid();
9
- socket_state = QAbstractSocket::UnconnectedState;
10
- socket_error = QAbstractSocket::UnknownSocketError;
11
- }
12
- void connectSocket()
13
- {
14
-// QNetworkProxy proxy;
15
-// proxy.setType(QNetworkProxy::HttpProxy);
16
-// proxy.setHostName("proxy.istu.ru");
17
-// proxy.setPort(8080);
18
-// socket->setProxy(proxy);
19
- if (qobject_cast<QSslSocket*>(socket)) {
20
- connect(socket, SIGNAL(encrypted()), parent, SIGNAL(connected()));
21
- } else {
22
- connect(socket, SIGNAL(connected()), parent, SIGNAL(connected()));
23
- }
24
- connect(socket, SIGNAL(disconnected()), parent, SIGNAL(disconnected()));
25
- connect(socket, SIGNAL(readyRead()), parent, SIGNAL(readyRead()));
26
- connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
27
- this, SLOT(stateChanged(QAbstractSocket::SocketState)));
28
- connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
29
- this, SLOT(error(QAbstractSocket::SocketError)));
30
- connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
31
- parent, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
32
- }
33
- void doLookup()
34
- {
35
- Logger::debug() << "doLookup";
36
- emit stateChanged(QAbstractSocket::HostLookupState);
37
-
38
- if (SJDns::instance().isValid())
39
- SJDns::instance().doLookup(host_name, this, SLOT(lookupResultsReady()));
40
- else
41
- emit stateChanged(QAbstractSocket::UnconnectedState);
42
- }
43
+
44
+ DirectConnectionPrivate(const QString &hn, int p, DirectConnection *par);
45
+ void connectSocket();
46
+ void doLookup();
47
+
48
QAbstractSocket *socket;
49
QString host_name;
50
int port;
51
52
int dns_lookup_id;
53
QList<Record> dns_records;
54
DirectConnection *parent;
55
+
56
public slots:
57
- void lookupResultsReady()
58
- {
59
- const QJDns::Response *response = SJDns::instance().servers(host_name);
60
- dns_records.clear();
61
- if(!response || !response->answerRecords.size()) {
62
- Record record;
63
- record.host = host_name;
64
- dns_records << record;
65
- }
66
- else {
67
- foreach(const QJDns::Record &qrecord, response->answerRecords) {
68
- Record record;
69
- record.host = QUrl::fromAce(qrecord.name);
70
- // may be it's a reason of connection problems of some users
71
- if (record.host.endsWith(QLatin1Char('.')))
72
- record.host.chop(1);
73
- record.port = qrecord.port;
74
- record.weight = qrecord.weight;
75
- record.priority = qrecord.priority;
76
- dns_records << record;
77
- }
78
- }
79
- Record &record = dns_records0;
80
- Logger::debug() << "use:" << record.host << record.port;
81
- socket->connectToHost(record.host, record.port);
82
- }
83
- void stateChanged(QAbstractSocket::SocketState ss)
84
- {
85
- Logger::debug() << ss;
86
- if(socket_state == ss)
87
- return;
88
-
89
- switch(ss) {
90
- case QAbstractSocket::ConnectedState: {
91
- socket_state = QAbstractSocket::ListeningState;
92
- parent->open();
93
- return;
94
- }
95
- case QAbstractSocket::ClosingState:
96
- parent->close();
97
- break;
98
- default:
99
- break;
100
- }
101
-
102
- socket_state = ss;
103
- emit parent->stateChanged(static_cast<Connection::SocketState>(ss));
104
- }
105
- void error(QAbstractSocket::SocketError se)
106
- {
107
- socket_error = se;
108
- emit parent->error(static_cast<Connection::SocketError>(se));
109
- }
110
+ void lookupResultsReady();
111
+ void stateChanged(QAbstractSocket::SocketState ss);
112
+ void error(QAbstractSocket::SocketError se);
113
};
114
115
}
116
libjreen-1.0.3.tar.bz2/src/disco.cpp -> libjreen-1.1.0.tar.bz2/src/disco.cpp
Changed
43
1
2
Disco::Identity identity(attributes.value(QLatin1String("category")).toString(),
3
attributes.value(QLatin1String("type")).toString(),
4
attributes.value(QLatin1String("name")).toString(),
5
- attributes.value(QLatin1String("lang")).toString());
6
+ attributes.value(QLatin1String("xml:lang")).toString());
7
m_identities.append(identity);
8
} else if (name == QLatin1String("feature")) {
9
m_features.insert(attributes.value(QLatin1String("var")).toString());
10
11
d_func()->identities.append(identity);
12
}
13
14
+void Disco::addIdentity(const QString &category, const QString &type, const QString &name, const QString &lang)
15
+{
16
+ d_func()->identities.append(Identity(category, type, name, lang));
17
+}
18
+
19
const QSet<QString> &Disco::features() const
20
{
21
Q_D(const Disco);
22
23
24
void Disco::setSoftwareVersion(const QString &name, const QString &version, const QString &os)
25
{
26
+ setSoftwareVersion(name, version, os, QString());
27
+}
28
+
29
+void Disco::setSoftwareVersion(const QString &name, const QString &version, const QString &os, const QString &osVersion)
30
+{
31
Q_D(Disco);
32
d->software_name = name;
33
d->software_version = version;
34
35
form->appendField(DataFormFieldHidden(QLatin1String("FORM_TYPE"), QLatin1String("urn:xmpp:dataforms:softwareinfo")));
36
form->appendField(DataFormFieldNone(QLatin1String("ip_version"), QStringList() << QLatin1String("ipv4") << QLatin1String("ipv6")));
37
form->appendField(DataFormFieldNone(QLatin1String("os"), QStringList(os)));
38
+ if (!osVersion.isEmpty())
39
+ form->appendField(DataFormFieldNone(QLatin1String("os_version"), QStringList(osVersion)));
40
form->appendField(DataFormFieldNone(QLatin1String("software"), QStringList(name)));
41
form->appendField(DataFormFieldNone(QLatin1String("software_version"), QStringList(version)));
42
d->form = form;
43
libjreen-1.0.3.tar.bz2/src/disco.h -> libjreen-1.1.0.tar.bz2/src/disco.h
Changed
16
1
2
DiscoReply *requestItems(const Item &item);
3
4
void addIdentity(const Identity &identity);
5
+ void addIdentity(const QString &category, const QString &type, const QString &name, const QString &lang = QString());
6
const IdentityList &identities() const;
7
IdentityList &identities();
8
const QSet<QString> &features() const;
9
QSet<QString> &features();
10
void addFeature(const QString &feature);
11
void setSoftwareVersion(const QString &name, const QString &version, const QString &os = QString());
12
+ void setSoftwareVersion(const QString &name, const QString &version, const QString &os, const QString &osVersion);
13
const DataForm *form() const;
14
void setForm(DataForm *form);
15
16
libjreen-1.0.3.tar.bz2/src/disco_p.h -> libjreen-1.1.0.tar.bz2/src/disco_p.h
Changed
19
1
2
static DiscoPrivate *get(Disco *disco) { return disco->d_func(); }
3
};
4
5
-class DiscoInfoFactory : public PayloadFactory<Disco::Info>
6
+class JREEN_AUTOTEST_EXPORT DiscoInfoFactory : public PayloadFactory<Disco::Info>
7
{
8
public:
9
DiscoInfoFactory();
10
11
bool m_hasDataForm;
12
};
13
14
-class DiscoItemsFactory : public PayloadFactory<Disco::Items>
15
+class JREEN_AUTOTEST_EXPORT DiscoItemsFactory : public PayloadFactory<Disco::Items>
16
{
17
public:
18
DiscoItemsFactory();
19
libjreen-1.0.3.tar.bz2/src/entitytimefactory_p.h -> libjreen-1.1.0.tar.bz2/src/entitytimefactory_p.h
Changed
10
1
2
3
namespace Jreen
4
{
5
- class EntityTimeFactory : public PayloadFactory<EntityTime>
6
+ class JREEN_AUTOTEST_EXPORT EntityTimeFactory : public PayloadFactory<EntityTime>
7
{
8
public:
9
EntityTimeFactory();
10
libjreen-1.0.3.tar.bz2/src/error.cpp -> libjreen-1.1.0.tar.bz2/src/error.cpp
Changed
13
1
2
return d_func()->type;
3
}
4
5
+QString Error::text(const QString &lang) const
6
+{
7
+ return d_func()->text.value(lang);
8
+}
9
+
10
Error::Condition Error::condition() const
11
{
12
return d_func()->condition;
13
libjreen-1.0.3.tar.bz2/src/error.h -> libjreen-1.1.0.tar.bz2/src/error.h
Changed
9
1
2
~Error();
3
4
Type type() const;
5
+ QString text(const QString &lang = QString()) const;
6
Condition condition() const;
7
QString conditionText() const;
8
private:
9
libjreen-1.0.3.tar.bz2/src/errorfactory.cpp -> libjreen-1.1.0.tar.bz2/src/errorfactory.cpp
Changed
28
1
2
3
Payload::Ptr ErrorFactory::createPayload()
4
{
5
- return Payload::Ptr(new Error(m_type,m_condition));
6
+ return Payload::Ptr(new Error(m_type, m_condition, LangMap(m_text)));
7
}
8
9
QStringList ErrorFactory::features() const
10
11
if (m_depth == 1) {
12
QStringRef subtype = attributes.value(QLatin1String("type"));
13
m_type = strToEnum<Error::Type>(subtype,error_types);
14
+ m_text.clear();
15
} else if(m_depth == 2) {
16
if(name == QLatin1String("text"))
17
m_state = AtText;
18
19
20
void ErrorFactory::handleCharacterData(const QStringRef& text)
21
{
22
- Q_UNUSED(text);
23
+ if (m_state == AtText)
24
+ m_text = text.toString();
25
}
26
void ErrorFactory::handleEndElement(const QStringRef& name, const QStringRef& uri)
27
{
28
libjreen-1.0.3.tar.bz2/src/errorfactory_p.h -> libjreen-1.1.0.tar.bz2/src/errorfactory_p.h
Changed
18
1
2
3
namespace Jreen {
4
5
-class ErrorFactory : public PayloadFactory<Error>
6
+class JREEN_AUTOTEST_EXPORT ErrorFactory : public PayloadFactory<Error>
7
{
8
public:
9
ErrorFactory();
10
11
enum State {AtCondition,AtText};
12
State m_state;
13
int m_depth;
14
+ QString m_text;
15
Error::Type m_type;
16
Error::Condition m_condition;
17
};
18
libjreen-1.1.0.tar.bz2/src/experimental
Added
2
1
+(directory)
2
libjreen-1.1.0.tar.bz2/src/experimental/iristransport.cpp
Added
36
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "iristransport.h"
28
+
29
+namespace Jreen
30
+{
31
+namespace JingleIce
32
+{
33
+
34
+} // namespace JingleIce
35
+} // namespace Jreen
36
libjreen-1.1.0.tar.bz2/src/experimental/iristransport.h
Added
43
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_JINGLEICE_IRISTRANSPORT_H
28
+#define JREEN_JINGLEICE_IRISTRANSPORT_H
29
+
30
+#include "jingletransport.h"
31
+#include "3rdparty/icesupport/ice176.h"
32
+#include "3rdparty/icesupport/udpportreserver.h"
33
+
34
+namespace Jreen
35
+{
36
+namespace JingleIce
37
+{
38
+
39
+} // namespace JingleIce
40
+} // namespace Jreen
41
+
42
+#endif // JREEN_JINGLEICE_IRISTRANSPORT_H
43
libjreen-1.1.0.tar.bz2/src/experimental/jingle.cpp
Added
75
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingle_p.h"
28
+#include "jinglesession_p.h"
29
+#include "../iqreply.h"
30
+
31
+namespace Jreen
32
+{
33
+
34
+Jingle::Jingle() : action(Jingle::SessionInitiate)
35
+{
36
+}
37
+
38
+Jingle::Ptr Jingle::create(JingleSession *session, Action action)
39
+{
40
+ Jingle::Ptr jingle = Jingle::Ptr::create();
41
+ JingleSessionPrivate *d = JingleSessionPrivate::get(session);
42
+ jingle->initiator = d->client->jid();
43
+// jingle->responder = d->other;
44
+ if (d->incoming)
45
+ qSwap(jingle->initiator, jingle->responder);
46
+ jingle->action = action;
47
+ jingle->sid = d->sid;
48
+ return jingle;
49
+}
50
+
51
+IQReply *Jingle::send(JingleSession *session, Action action, const QList<Content> &contents)
52
+{
53
+ JingleSessionPrivate *d = JingleSessionPrivate::get(session);
54
+ Jingle::Ptr jingle = create(session, action);
55
+ jingle->contents = contents;
56
+ IQ iq(IQ::Set, d->other);
57
+ iq.addExtension(jingle);
58
+ return d->client->send(iq);
59
+}
60
+
61
+IQReply *Jingle::send(JingleSession *session, Action action, const Content &content)
62
+{
63
+ return send(session, action, QList<Content>() << content);
64
+}
65
+
66
+IQReply *Jingle::send(JingleSession *session, Action action, JingleContent *contentObject)
67
+{
68
+ JingleSessionPrivate *d = JingleSessionPrivate::get(session);
69
+ JingleSessionContent *content = d->findContent(contentObject);
70
+ Q_ASSERT(content);
71
+ return send(session, action, *content);
72
+}
73
+
74
+}
75
libjreen-1.1.0.tar.bz2/src/experimental/jingle_p.h
Added
110
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLE_H
28
+#define JINGLE_H
29
+
30
+#include "../stanzaextension.h"
31
+#include "../jid.h"
32
+#include "jingletransport.h"
33
+#include "jinglecontent.h"
34
+
35
+namespace Jreen
36
+{
37
+
38
+class IQReply;
39
+
40
+class Jingle : public Payload
41
+{
42
+ J_PAYLOAD(Jreen::Jingle)
43
+public:
44
+ enum Action {
45
+ ContentAccept,
46
+ ContentAdd,
47
+ ContentModify,
48
+ ContentReject,
49
+ ContentRemove,
50
+ DescriptionInfo,
51
+ SecurityInfo,
52
+ SessionAccept,
53
+ SessionInfo,
54
+ SessionInitiate,
55
+ SessionTerminate,
56
+ TransportAccept,
57
+ TransportInfo,
58
+ TransportReject,
59
+ TransportReplace
60
+ };
61
+
62
+ enum CreatorType {
63
+ Invalid = -1,
64
+ None = 0,
65
+ Initiator = 1,
66
+ Responder = 2,
67
+ Both = Initiator | Responder
68
+ };
69
+
70
+ typedef QFlags<CreatorType> SendersType;
71
+
72
+ struct Content
73
+ {
74
+ Content() : creator(Initiator), senders(Both) {}
75
+ QString name;
76
+ CreatorType creator;
77
+ SendersType senders;
78
+ JingleDescription::Ptr description;
79
+ QList<JingleTransportInfo::Ptr> transports;
80
+ };
81
+
82
+ Jingle();
83
+
84
+ static Jingle::Ptr create(JingleSession *session, Action action);
85
+ static IQReply *send(JingleSession *session, Action action, const QList<Content> &contents = QList<Content>());
86
+ template <typename T>
87
+ static IQReply *send(JingleSession *session, Action action, const QList<T> &list)
88
+ {
89
+ QList<Content> contents;
90
+ for (int i = 0; i < list.size(); ++i)
91
+ contents << listi;
92
+ return send(session, action, contents);
93
+ }
94
+
95
+ static IQReply *send(JingleSession *session, Action action, const Content &content);
96
+ static IQReply *send(JingleSession *session, Action action, JingleContent *content);
97
+
98
+ JID initiator;
99
+ JID responder;
100
+ QString sid;
101
+ Action action;
102
+ QList<Content> contents;
103
+};
104
+
105
+}
106
+
107
+Q_DECLARE_OPERATORS_FOR_FLAGS(Jreen::Jingle::SendersType)
108
+
109
+#endif // JINGLE_H
110
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiocontent.cpp
Added
283
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingleaudiocontent_p.h"
28
+#include "jinglespeexcodec_p.h"
29
+#include <QSet>
30
+#include <QtEndian>
31
+#include <QDateTime>
32
+#include <QDebug>
33
+#include <qmath.h>
34
+
35
+namespace Jreen
36
+{
37
+
38
+enum { JingleRTP = 0, JingleRTCP = 1 };
39
+
40
+class JingleRtpHeader
41
+{
42
+public:
43
+ JingleRtpHeader() : begin(2 << 6), pt(0), sq(0), ts(0), ssrc(0) {}
44
+ JingleRtpHeader(const char * &data, int &len);
45
+ enum { Version = 2 };
46
+
47
+ bool isValid() const { return version() == 2; }
48
+ quint8 version() const { return begin >> 6; }
49
+ bool hasPadding() const { return begin & (1 << 5); }
50
+ bool hasExtension() const { return begin & (1 << 4); }
51
+ quint8 csrcCount() const { return begin & 0x7; }
52
+ bool hasMarker() const { return begin & (1 << 7); }
53
+ quint8 payloadType() const { return pt /*& 0xef*/ ; }
54
+ void setPayloadType(quint8 type) { /* pt &= ~0xef; pt |= type;*/ pt = type; }
55
+ quint16 sequence() const { return sq; }
56
+ void setSequence(quint16 seq) { sq = seq; }
57
+ quint32 timestamp() const { return ts; }
58
+ void setTimestamp(quint32 timest) { ts = timest; }
59
+ quint32 synchronizationSource() const { return ssrc; }
60
+ QByteArray data() const;
61
+
62
+private:
63
+ quint8 begin;
64
+ quint8 pt;
65
+ quint16 sq;
66
+ quint32 ts;
67
+ quint32 ssrc;
68
+};
69
+
70
+JingleRtpHeader::JingleRtpHeader(const char * &xdata, int &len)
71
+{
72
+ const uchar * &udata = reinterpret_cast<const uchar * &>(xdata);
73
+ const uchar *start = udata;
74
+ begin = udata0;
75
+ pt = udata1;
76
+ sq = qFromBigEndian<quint16>(udata + 2);
77
+ ts = qFromBigEndian<quint32>(udata + 4);
78
+ ssrc = qFromBigEndian<quint32>(udata + 4);
79
+ udata += 12;
80
+ udata += csrcCount() * 4;
81
+ len -= (udata - start);
82
+}
83
+
84
+QByteArray JingleRtpHeader::data() const
85
+{
86
+ QByteArray result(1 + 1 + 2 + 4 + 4, Qt::Uninitialized);
87
+ uchar *d = reinterpret_cast<uchar*>(result.data());
88
+ d0 = begin;
89
+ d1 = pt;
90
+ qToBigEndian(sq, d + 2);
91
+ qToBigEndian(ts, d + 4);
92
+ qToBigEndian(ssrc, d + 8);
93
+ return result;
94
+}
95
+
96
+JingleAudioDevice::JingleAudioDevice(JingleAudioContentPrivate *content)
97
+ : m_content(content)
98
+{
99
+}
100
+
101
+JingleAudioDevice::~JingleAudioDevice()
102
+{
103
+}
104
+
105
+bool JingleAudioDevice::open(OpenMode mode)
106
+{
107
+ Q_UNUSED(mode);
108
+ return QIODevice::open(QIODevice::ReadWrite | QIODevice::Unbuffered);
109
+}
110
+
111
+void JingleAudioDevice::close()
112
+{
113
+ m_buffer.clear();
114
+ m_outputBuffer.clear();
115
+ QIODevice::close();
116
+}
117
+
118
+bool JingleAudioDevice::isSequential() const
119
+{
120
+ return true;
121
+}
122
+
123
+qint64 JingleAudioDevice::bytesAvailable() const
124
+{
125
+ return m_outputBuffer.size();
126
+}
127
+
128
+void JingleAudioDevice::appendData(const QByteArray &data)
129
+{
130
+ m_outputBuffer.append(data);
131
+ if (m_outputBuffer.size() > (8 * 320))
132
+ m_outputBuffer.remove(0, m_outputBuffer.size() - 8 * 320);
133
+ emit readyRead();
134
+}
135
+
136
+qint64 JingleAudioDevice::readData(char *data, qint64 maxSize)
137
+{
138
+ qMemSet(data, 0, maxSize);
139
+ qint64 size = qMin<qint64>(m_outputBuffer.size(), maxSize);
140
+ qMemCopy(data, m_outputBuffer.data(), size);
141
+ m_outputBuffer.remove(0, size);
142
+ return maxSize;
143
+}
144
+
145
+qint64 JingleAudioDevice::writeData(const char *data, qint64 len)
146
+{
147
+ m_buffer.append(data, len);
148
+ const JingleAudioPayload &payload = m_content->payloads.first();
149
+ JingleAudioCodec *codec = m_content->codecs.value(payload.id());
150
+ // We use only two-byte integers right now
151
+ const int frameSize = codec->frameSize() * 2;
152
+ int offset = 0;
153
+ while (m_buffer.size() - offset >= frameSize) {
154
+ m_content->send(payload.id(), codec->encodeFrame(m_buffer.data() + offset, frameSize));
155
+ offset += frameSize;
156
+ }
157
+ m_buffer.remove(0, offset);
158
+ return len;
159
+}
160
+
161
+static inline void init_factories(QList<JingleAudioCodecFactory*> &factories)
162
+{
163
+ Q_UNUSED(factories);
164
+#ifdef JREEN_HAVE_SPEEX
165
+ factories << new JingleSpeexCodecFactory;
166
+#endif
167
+}
168
+
169
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QList<JingleAudioCodecFactory*>, factories, init_factories(*x))
170
+
171
+JingleAudioContent::JingleAudioContent(JingleSession *session)
172
+ : JingleContent(session, *new JingleAudioContentPrivate(this))
173
+{
174
+ Q_D(JingleAudioContent);
175
+ d->device.reset(new JingleAudioDevice(d));
176
+ setComponentCount(2);
177
+}
178
+
179
+JingleAudioContent::~JingleAudioContent()
180
+{
181
+ qDeleteAll(d_func()->codecs);
182
+}
183
+
184
+JingleAudioPayload JingleAudioContent::currentPayload() const
185
+{
186
+ return d_func()->payloads.value(0);
187
+}
188
+
189
+int JingleAudioContent::currentPayloadFrameSize() const
190
+{
191
+ Q_D(const JingleAudioContent);
192
+ int id = d->payloads.value(0).id();
193
+ JingleAudioCodec *codec = d->codecs.value(id);
194
+ return codec ? codec->frameSize() : -1;
195
+}
196
+
197
+QIODevice *JingleAudioContent::audioDevice() const
198
+{
199
+ return d_func()->device.data();
200
+}
201
+
202
+JingleDescription::Ptr JingleAudioContent::defaultDescription()
203
+{
204
+ JingleAudioDescription::Ptr info = JingleAudioDescription::Ptr::create();
205
+ foreach (JingleAudioCodecFactory *factory, *factories())
206
+ info->payloads << factory->supportedPayloads();
207
+ return info;
208
+}
209
+
210
+JingleDescription::Ptr JingleAudioContent::handleDescription(const JingleDescription::Ptr &description)
211
+{
212
+ Q_D(JingleAudioContent);
213
+ JingleAudioDescription::Ptr info = description.staticCast<JingleAudioDescription>();
214
+ QSet<int> payloads;
215
+ foreach (JingleAudioCodecFactory *factory, *factories()) {
216
+ for (int i = 0; i < info->payloads.size(); ++i) {
217
+ if (payloads.contains(i))
218
+ continue;
219
+ const JingleAudioPayload &payload = info->payloads.at(i);
220
+ if (factory->supportsPayload(payload)) {
221
+ d->payloads << payload;
222
+ JingleAudioCodec *codec = factory->createCodec(payload);
223
+ d->codecs.insert(payload.id(), codec);
224
+ payloads.insert(i);
225
+ }
226
+ }
227
+ }
228
+ if (d->payloads.isEmpty())
229
+ return JingleDescription::Ptr();
230
+ JingleAudioDescription::Ptr result = JingleAudioDescription::Ptr::create();
231
+ result->payloads = d->payloads;
232
+ if (!d->payloads.isEmpty())
233
+ emit payloadChoosed(d->payloads.value(0));
234
+ return result;
235
+}
236
+
237
+void JingleAudioContent::registerCodec(JingleAudioCodecFactory *factory)
238
+{
239
+ factories()->append(factory);
240
+}
241
+
242
+void JingleAudioContentPrivate::_q_stateChanged(Jreen::JingleTransport::State newState)
243
+{
244
+ if (newState == JingleTransport::Connected)
245
+ device->open(QIODevice::ReadWrite);
246
+ JingleContentPrivate::_q_stateChanged(newState);
247
+}
248
+
249
+void JingleAudioContentPrivate::send(int payload, const QByteArray &data)
250
+{
251
+ JingleRtpHeader header;
252
+ header.setSequence(sequence++);
253
+ header.setTimestamp(QDateTime::currentDateTime().toTime_t());
254
+ header.setPayloadType(payload);
255
+ QByteArray result = header.data();
256
+ result += data;
257
+ q_func()->send(JingleRTP, result);
258
+}
259
+
260
+void JingleAudioContent::receive(int component, const QByteArray &receivedData)
261
+{
262
+ if (component == JingleRTCP) {
263
+ qDebug() << Q_FUNC_INFO << receivedData.toHex();
264
+ }
265
+ if (component != JingleRTP)
266
+ return;
267
+ Q_D(JingleAudioContent);
268
+ const char *data = receivedData.constData();
269
+ int size = receivedData.size();
270
+ JingleRtpHeader header(data, size);
271
+ if (!header.isValid())
272
+ return;
273
+ JingleAudioCodec *codec = d->codecs.value(header.payloadType());
274
+ if (!codec)
275
+ return;
276
+ QByteArray audio = codec->decodeFrame(data, size);
277
+ d->device->appendData(audio);
278
+}
279
+
280
+}
281
+
282
+#include "moc_jingleaudiocontent.cpp"
283
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiocontent.h
Added
87
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEAUDIOCONTENT_H
28
+#define JINGLEAUDIOCONTENT_H
29
+
30
+#include "jinglecontent.h"
31
+#include "jingleaudiopayload.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleAudioContentPrivate;
37
+class JingleAudioCodecFactory;
38
+
39
+class JREEN_EXPORT JingleAudioContent : public JingleContent
40
+{
41
+ Q_OBJECT
42
+ Q_DECLARE_PRIVATE(JingleAudioContent)
43
+public:
44
+ JingleAudioContent(JingleSession *session);
45
+ ~JingleAudioContent();
46
+
47
+ JingleAudioPayload currentPayload() const;
48
+ int currentPayloadFrameSize() const;
49
+ QIODevice *audioDevice() const;
50
+
51
+ virtual JingleDescription::Ptr defaultDescription();
52
+ virtual JingleDescription::Ptr handleDescription(const JingleDescription::Ptr &description);
53
+
54
+ static void registerCodec(JingleAudioCodecFactory *factory);
55
+
56
+protected:
57
+ virtual void receive(int component, const QByteArray &data);
58
+
59
+signals:
60
+ void payloadChoosed(const Jreen::JingleAudioPayload &payload);
61
+};
62
+
63
+class JREEN_EXPORT JingleAudioCodec
64
+{
65
+public:
66
+ virtual ~JingleAudioCodec() {}
67
+
68
+ virtual int frameSize() const = 0;
69
+ virtual QByteArray encodeFrame(const char *data, int size) = 0;
70
+ virtual QByteArray decodeFrame(const char *data, int size) = 0;
71
+};
72
+
73
+class JREEN_EXPORT JingleAudioCodecFactory
74
+{
75
+public:
76
+ virtual ~JingleAudioCodecFactory() {}
77
+ virtual QList<JingleAudioPayload> supportedPayloads() = 0;
78
+ virtual bool supportsPayload(const JingleAudioPayload &payload) = 0;
79
+ virtual JingleAudioCodec *createCodec(const JingleAudioPayload &payload) = 0;
80
+};
81
+
82
+}
83
+
84
+Q_DECLARE_INTERFACE(Jreen::JingleAudioCodecFactory, "org.qutim.Jreen.Jingle.AudioCodecFactory")
85
+
86
+#endif // JINGLEAUDIOCONTENT_H
87
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiocontent_p.h
Added
87
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEAUDIOCONTENT_P_H
28
+#define JINGLEAUDIOCONTENT_P_H
29
+
30
+#include "jingleaudiocontent.h"
31
+#include "jingleaudiopayload_p.h"
32
+#include "jinglecontent_p.h"
33
+
34
+namespace Jreen
35
+{
36
+
37
+class JingleAudioDevice : public QIODevice
38
+{
39
+public:
40
+ JingleAudioDevice(JingleAudioContentPrivate *content);
41
+ ~JingleAudioDevice();
42
+
43
+ virtual bool open(OpenMode mode);
44
+ virtual void close();
45
+ bool isSequential() const;
46
+ qint64 bytesAvailable() const;
47
+ void appendData(const QByteArray &data);
48
+
49
+protected:
50
+ virtual qint64 readData(char *data, qint64 len);
51
+ virtual qint64 writeData(const char *data, qint64 len);
52
+
53
+private:
54
+ JingleAudioContentPrivate *m_content;
55
+ QByteArray m_buffer;
56
+ QByteArray m_outputBuffer;
57
+};
58
+
59
+class JingleAudioContentPrivate : public JingleContentPrivate
60
+{
61
+ Q_DECLARE_PUBLIC(JingleAudioContent)
62
+public:
63
+ JingleAudioContentPrivate(JingleAudioContent *q)
64
+ : JingleContentPrivate(q), sequence(qrand()), lastSequence(0) {}
65
+
66
+ quint16 sequence;
67
+ quint16 lastSequence;
68
+ QScopedPointer<JingleAudioDevice> device;
69
+ QList<JingleAudioPayload> payloads;
70
+ QMap<int, JingleAudioCodec*> codecs;
71
+
72
+ void _q_stateChanged(Jreen::JingleTransport::State);
73
+ void send(int payload, const QByteArray &data);
74
+ static JingleAudioContentPrivate *get(JingleAudioContent *q) { return q->d_func(); }
75
+};
76
+
77
+class JingleAudioDescription : public JingleDescription
78
+{
79
+ J_PAYLOAD(Jreen::JingleAudioDescription)
80
+public:
81
+ QList<JingleAudioPayload> payloads;
82
+};
83
+
84
+}
85
+
86
+#endif // JINGLEAUDIOCONTENT_P_H
87
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiocontentfactory.cpp
Added
132
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingleaudiocontentfactory_p.h"
28
+
29
+#define NS_RTP QLatin1String("urn:xmpp:jingle:apps:rtp:1")
30
+#define NS_RTP_AUDIO QLatin1String("urn:xmpp:jingle:apps:rtp:audio")
31
+
32
+namespace Jreen
33
+{
34
+
35
+JingleAudioContentFactory::JingleAudioContentFactory()
36
+ : JingleContentFactory<JingleAudioDescription>(NS_RTP, QLatin1String("audio")), m_state(AtRoot), m_depth(0)
37
+{
38
+}
39
+
40
+JingleContent *JingleAudioContentFactory::createObject(JingleSession *session)
41
+{
42
+ return new JingleAudioContent(session);
43
+}
44
+
45
+QStringList JingleAudioContentFactory::features() const
46
+{
47
+ return QStringList(m_elementUri)
48
+ << NS_RTP_AUDIO;
49
+}
50
+
51
+void JingleAudioContentFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
52
+{
53
+ Q_UNUSED(name);
54
+ Q_UNUSED(uri);
55
+ m_depth++;
56
+ if (m_depth == 1) {
57
+ m_info = JingleAudioDescription::Ptr::create();
58
+ } if (m_depth == 2 && name == QLatin1String("payload-type")) {
59
+ m_state = AtPayload;
60
+ m_payload.reset(new JingleAudioPayload);
61
+ m_payload->setId(attributes.value(QLatin1String("id")).toString().toInt());
62
+ m_payload->setChannelCount(attributes.value(QLatin1String("channels")).toString().toInt());
63
+ m_payload->setClockRate(attributes.value(QLatin1String("clockrate")).toString().toInt());
64
+ m_payload->setName(attributes.value(QLatin1String("name")).toString());
65
+ m_payload->setMaximumPacketTime(attributes.value(QLatin1String("maxptime")).toString().toInt());
66
+ m_payload->setPacketTime(attributes.value(QLatin1String("ptime")).toString().toInt());
67
+ } else if (m_depth == 3 && name == QLatin1String("parameter")) {
68
+ m_payload->setParameter(attributes.value(QLatin1String("name")).toString(),
69
+ attributes.value(QLatin1String("value")).toString());
70
+ }
71
+}
72
+
73
+void JingleAudioContentFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
74
+{
75
+ Q_UNUSED(name);
76
+ Q_UNUSED(uri);
77
+ if (m_state == AtPayload && m_depth == 2) {
78
+ m_state = AtRoot;
79
+ m_info->payloads << *m_payload;
80
+ m_payload.reset();
81
+ }
82
+ m_depth--;
83
+}
84
+
85
+void JingleAudioContentFactory::handleCharacterData(const QStringRef &text)
86
+{
87
+ Q_UNUSED(text);
88
+}
89
+
90
+void JingleAudioContentFactory::serialize(Payload *obj, QXmlStreamWriter *writer)
91
+{
92
+ JingleAudioDescription *info = se_cast<JingleAudioDescription*>(obj);
93
+ Q_ASSERT(info);
94
+
95
+ writer->writeStartElement(QLatin1String("description"));
96
+ writer->writeDefaultNamespace(m_elementUri);
97
+ writer->writeAttribute(QLatin1String("media"), m_media);
98
+ foreach (const JingleAudioPayload &payload, info->payloads) {
99
+ const JingleAudioPayloadData *d = JingleAudioPayloadData::get(payload);
100
+ writer->writeStartElement(QLatin1String("payload-type"));
101
+ writer->writeAttribute(QLatin1String("id"), QString::number(d->id));
102
+ if (d->channelCount > 0)
103
+ writer->writeAttribute(QLatin1String("channels"), QString::number(d->channelCount));
104
+ if (d->clockRate > 0)
105
+ writer->writeAttribute(QLatin1String("clockrate"), QString::number(d->clockRate));
106
+ if (!d->name.isEmpty())
107
+ writer->writeAttribute(QLatin1String("name"), d->name);
108
+ if (d->maxmimumPacketTime > 0)
109
+ writer->writeAttribute(QLatin1String("maxptime"), QString::number(d->maxmimumPacketTime));
110
+ if (d->packetTime > 0)
111
+ writer->writeAttribute(QLatin1String("ptime"), QString::number(d->packetTime));
112
+ QMapIterator<QString, QString> it(d->parameters);
113
+ while (it.hasNext()) {
114
+ it.next();
115
+ writer->writeEmptyElement(QLatin1String("parameter"));
116
+ writer->writeAttribute(QLatin1String("name"), it.key());
117
+ writer->writeAttribute(QLatin1String("value"), it.value());
118
+ }
119
+ writer->writeEndElement();
120
+ }
121
+ writer->writeEndElement();
122
+}
123
+
124
+Payload::Ptr JingleAudioContentFactory::createPayload()
125
+{
126
+ Payload::Ptr result = m_info;
127
+ m_info.clear();
128
+ return result;
129
+}
130
+
131
+}
132
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiocontentfactory_p.h
Added
58
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEAUDIOCONTENTFACTORY_P_H
28
+#define JINGLEAUDIOCONTENTFACTORY_P_H
29
+
30
+#include "jingleaudiocontent_p.h"
31
+#include "jingleaudiopayload.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleAudioContentFactory : public JingleContentFactory<JingleAudioDescription>
37
+{
38
+public:
39
+ JingleAudioContentFactory();
40
+
41
+ virtual JingleContent *createObject(JingleSession *session);
42
+ virtual QStringList features() const;
43
+ virtual void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
44
+ virtual void handleEndElement(const QStringRef &name, const QStringRef &uri);
45
+ virtual void handleCharacterData(const QStringRef &text);
46
+ virtual void serialize(Payload *obj, QXmlStreamWriter *writer);
47
+ virtual Payload::Ptr createPayload();
48
+private:
49
+ enum State { AtRoot, AtPayload } m_state;
50
+ int m_depth;
51
+ JingleAudioDescription::Ptr m_info;
52
+ QScopedPointer<JingleAudioPayload> m_payload;
53
+};
54
+
55
+}
56
+
57
+#endif // JINGLEAUDIOCONTENTFACTORY_P_H
58
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiopayload.cpp
Added
136
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingleaudiopayload_p.h"
28
+
29
+namespace Jreen
30
+{
31
+
32
+Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<JingleAudioPayloadData>, nullData, (new JingleAudioPayloadData))
33
+
34
+JingleAudioPayload::JingleAudioPayload() : d(*nullData())
35
+{
36
+}
37
+
38
+JingleAudioPayload::JingleAudioPayload(const JingleAudioPayload &o) : d(o.d)
39
+{
40
+}
41
+
42
+JingleAudioPayload &JingleAudioPayload::operator =(const JingleAudioPayload &o)
43
+{
44
+ d = o.d;
45
+ return *this;
46
+}
47
+
48
+JingleAudioPayload::~JingleAudioPayload()
49
+{
50
+}
51
+
52
+bool JingleAudioPayload::operator ==(const JingleAudioPayload &o)
53
+{
54
+ return (o.id() < 96 && d->id == o.id())
55
+ || (d->channelCount == o.channelCount()
56
+ && d->clockRate == o.clockRate()
57
+ && d->name == o.name());
58
+}
59
+
60
+bool JingleAudioPayload::operator !=(const JingleAudioPayload &o)
61
+{
62
+ return !operator ==(o);
63
+}
64
+
65
+int JingleAudioPayload::channelCount() const
66
+{
67
+ return d->channelCount;
68
+}
69
+
70
+void JingleAudioPayload::setChannelCount(int channelCount)
71
+{
72
+ d->channelCount = (channelCount <= 0 ? 1 : channelCount);
73
+}
74
+
75
+int JingleAudioPayload::clockRate() const
76
+{
77
+ return d->clockRate;
78
+}
79
+
80
+void JingleAudioPayload::setClockRate(int clockRate)
81
+{
82
+ d->clockRate = (clockRate <= 0 ? -1 : clockRate);
83
+}
84
+
85
+int JingleAudioPayload::id() const
86
+{
87
+ return d->id;
88
+}
89
+
90
+void JingleAudioPayload::setId(int id)
91
+{
92
+ d->id = id;
93
+}
94
+
95
+int JingleAudioPayload::maximumPacketTime() const
96
+{
97
+ return d->maxmimumPacketTime;
98
+}
99
+
100
+void JingleAudioPayload::setMaximumPacketTime(int maximumPacketTime)
101
+{
102
+ d->maxmimumPacketTime = (maximumPacketTime <= 0 ? -1 : maximumPacketTime);
103
+}
104
+
105
+QString JingleAudioPayload::name() const
106
+{
107
+ return d->name;
108
+}
109
+
110
+void JingleAudioPayload::setName(const QString &name)
111
+{
112
+ d->name = name;
113
+}
114
+
115
+int JingleAudioPayload::packetTime() const
116
+{
117
+ return d->packetTime;
118
+}
119
+
120
+void JingleAudioPayload::setPacketTime(int packetTime)
121
+{
122
+ d->packetTime = (packetTime <= 0 ? -1 : packetTime);
123
+}
124
+
125
+QString JingleAudioPayload::parameter(const QString &name) const
126
+{
127
+ return d->parameters.value(name);
128
+}
129
+
130
+void JingleAudioPayload::setParameter(const QString &name, const QString &value)
131
+{
132
+ d->parameters.insert(name, value);
133
+}
134
+
135
+}
136
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiopayload.h
Added
72
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEAUDIOPAYLOAD_H
28
+#define JINGLEAUDIOPAYLOAD_H
29
+
30
+#include "../jreen.h"
31
+#include <QSharedDataPointer>
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleAudioPayloadData;
37
+
38
+class JREEN_EXPORT JingleAudioPayload
39
+{
40
+public:
41
+ JingleAudioPayload();
42
+ JingleAudioPayload(const JingleAudioPayload &o);
43
+ JingleAudioPayload &operator =(const JingleAudioPayload &o);
44
+ ~JingleAudioPayload();
45
+
46
+ bool operator ==(const JingleAudioPayload &o);
47
+ bool operator !=(const JingleAudioPayload &o);
48
+
49
+ int channelCount() const;
50
+ void setChannelCount(int channelCount);
51
+ int clockRate() const;
52
+ void setClockRate(int clockRate);
53
+ int id() const;
54
+ void setId(int id);
55
+ int maximumPacketTime() const;
56
+ void setMaximumPacketTime(int maximumPacketTime);
57
+ QString name() const;
58
+ void setName(const QString &name);
59
+ int packetTime() const;
60
+ void setPacketTime(int packetTime);
61
+ QString parameter(const QString &name) const;
62
+ void setParameter(const QString &name, const QString &value);
63
+
64
+private:
65
+ QSharedDataPointer<JingleAudioPayloadData> d;
66
+ friend class JingleAudioPayloadData;
67
+};
68
+
69
+}
70
+
71
+#endif // JINGLEAUDIOPAYLOAD_H
72
libjreen-1.1.0.tar.bz2/src/experimental/jingleaudiopayload_p.h
Added
59
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEAUDIOPAYLOAD_P_H
28
+#define JINGLEAUDIOPAYLOAD_P_H
29
+
30
+#include "jingleaudiopayload.h"
31
+#include <QMap>
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleAudioPayloadData : public QSharedData
37
+{
38
+public:
39
+ JingleAudioPayloadData()
40
+ : channelCount(1), clockRate(-1), id(-1), maxmimumPacketTime(-1), packetTime(-1) {}
41
+ JingleAudioPayloadData(const JingleAudioPayloadData &o)
42
+ : QSharedData(o), channelCount(o.channelCount), clockRate(o.clockRate), id(o.id),
43
+ maxmimumPacketTime(o.maxmimumPacketTime), packetTime(o.packetTime),
44
+ name(o.name), parameters(o.parameters) {}
45
+ int channelCount;
46
+ int clockRate;
47
+ int id;
48
+ int maxmimumPacketTime;
49
+ int packetTime;
50
+ QString name;
51
+ QMap<QString, QString> parameters;
52
+
53
+ static const JingleAudioPayloadData *get(const JingleAudioPayload &p) { return p.d.constData(); }
54
+};
55
+
56
+}
57
+
58
+#endif // JINGLEAUDIOPAYLOAD_P_H
59
libjreen-1.1.0.tar.bz2/src/experimental/jinglecontent.cpp
Added
215
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jinglecontent_p.h"
28
+#include "jingletransport.h"
29
+#include "jinglesession_p.h"
30
+#include <QDebug>
31
+
32
+namespace Jreen
33
+{
34
+
35
+void JingleContentPrivate::_q_received(int component, const QByteArray &data)
36
+{
37
+ q_func()->receive(component, data);
38
+}
39
+
40
+void JingleContentPrivate::_q_stateChanged(Jreen::JingleTransport::State newState)
41
+{
42
+ state = static_cast<JingleContent::State>(newState);
43
+ emit q_func()->stateChanged(state);
44
+}
45
+
46
+void JingleContentPrivate::_q_localInfoReady(const Jreen::JingleTransportInfo::Ptr &)
47
+{
48
+ if (needTransports > 0) {
49
+ needTransports--;
50
+ if (needTransports == 0) {
51
+ JingleSessionPrivate *sessionD = JingleSessionPrivate::get(session);
52
+ sessionD->onTransportsReady(q_func(), transports);
53
+ }
54
+ } else {
55
+ canAccept = 1;
56
+ transportInfos.clear();
57
+ transport = qobject_cast<JingleTransport*>(q_func()->sender());
58
+ Q_ASSERT(transport);
59
+ transports << transport;
60
+ accept();
61
+ }
62
+}
63
+
64
+void JingleContentPrivate::_q_tryStateChanged(Jreen::JingleTransport::State state)
65
+{
66
+ if (state == JingleTransport::Failed) {
67
+ JingleTransport *transport = qobject_cast<JingleTransport*>(q_func()->sender());
68
+ Q_ASSERT(transport);
69
+ delete transport;
70
+ tryNextTransport();
71
+ }
72
+}
73
+
74
+void JingleContentPrivate::setTransport(JingleTransport *trueTransport)
75
+{
76
+ transport = trueTransport;
77
+ qDebug() << Q_FUNC_INFO << transport;
78
+ QObject::connect(transport, SIGNAL(received(int,QByteArray)),
79
+ q_func(), SLOT(_q_received(int,QByteArray)));
80
+ QObject::connect(transport, SIGNAL(stateChanged(Jreen::JingleTransport::State)),
81
+ q_func(), SLOT(_q_stateChanged(Jreen::JingleTransport::State)));
82
+}
83
+
84
+void JingleContentPrivate::initiateTransports()
85
+{
86
+ JingleSessionPrivate *sessionD = JingleSessionPrivate::get(session);
87
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(sessionD->client->jingleManager());
88
+ foreach (AbstractJingleTransportFactory *factory, manager->transports) {
89
+ JingleTransport *transport = factory->createObject(q_func());
90
+ if (transport->localInfo().isNull()) {
91
+ QObject::connect(transport, SIGNAL(localInfoReady(Jreen::JingleTransportInfo::Ptr)),
92
+ q_func(), SLOT(_q_localInfoReady(Jreen::JingleTransportInfo::Ptr)));
93
+ needTransports++;
94
+ }
95
+ transports << transport;
96
+ }
97
+}
98
+
99
+void JingleContentPrivate::accept()
100
+{
101
+ if (needAccept || !canAccept)
102
+ return;
103
+ JingleSessionPrivate *sessionD = JingleSessionPrivate::get(session);
104
+ sessionD->onTransportsReady(q_func(), transports);
105
+}
106
+
107
+void JingleContentPrivate::decline()
108
+{
109
+ IQReply *reply = Jingle::send(session, Jingle::ContentReject, q_func());
110
+ Q_UNUSED(reply);
111
+}
112
+
113
+void JingleContentPrivate::tryNextTransport()
114
+{
115
+ JingleSessionPrivate *sessionD = JingleSessionPrivate::get(session);
116
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(sessionD->client->jingleManager());
117
+ JingleTransport *transport = 0;
118
+ JingleTransportInfo::Ptr info;
119
+ while (!transport && !transportInfos.isEmpty()) {
120
+ info = transportInfos.takeFirst();
121
+ transport = manager->transport(info, q_func());
122
+ }
123
+ if (!transport) {
124
+ q_func()->decline();
125
+ return;
126
+ }
127
+ transport->setRemoteInfo(info, false);
128
+ QObject::connect(transport, SIGNAL(localInfoReady(Jreen::JingleTransportInfo::Ptr)),
129
+ q_func(), SLOT(_q_localInfoReady(Jreen::JingleTransportInfo::Ptr)));
130
+ QObject::connect(transport, SIGNAL(stateChanged(Jreen::JingleTransport::State)),
131
+ q_func(), SLOT(_q_stateChanged(Jreen::JingleTransport::State)));
132
+}
133
+
134
+void JingleContentPrivate::initiateTransports(const QList<JingleTransportInfo::Ptr> &transportInfosOther)
135
+{
136
+ transportInfos = transportInfosOther;
137
+ tryNextTransport();
138
+}
139
+
140
+JingleContent::JingleContent(JingleSession *session)
141
+ : QObject(session), d_ptr(new JingleContentPrivate(this))
142
+{
143
+ Q_D(JingleContent);
144
+ d->session = session;
145
+}
146
+
147
+JingleContent::JingleContent(JingleSession *session, JingleContentPrivate &p)
148
+ : QObject(session), d_ptr(&p)
149
+{
150
+ Q_D(JingleContent);
151
+ d->session = session;
152
+}
153
+
154
+JingleContent::~JingleContent()
155
+{
156
+}
157
+
158
+JingleSession *JingleContent::session() const
159
+{
160
+ return d_func()->session;
161
+}
162
+
163
+JingleContent::State JingleContent::state() const
164
+{
165
+ return d_func()->state;
166
+}
167
+
168
+bool JingleContent::isAcceptable() const
169
+{
170
+ return d_func()->needAccept;
171
+}
172
+
173
+void JingleContent::accept()
174
+{
175
+ Q_D(JingleContent);
176
+ d->needAccept = false;
177
+ d->accept();
178
+}
179
+
180
+void JingleContent::decline()
181
+{
182
+ Q_D(JingleContent);
183
+ if (d->needAccept) {
184
+ d->needAccept = false;
185
+ IQReply *reply = Jingle::send(d->session, Jingle::ContentReject, this);
186
+ Q_UNUSED(reply);
187
+ }
188
+}
189
+
190
+int JingleContent::componentCount() const
191
+{
192
+ return d_func()->componentCount;
193
+}
194
+
195
+void JingleContent::setComponentCount(int count)
196
+{
197
+ d_func()->componentCount = count;
198
+}
199
+
200
+void JingleContent::send(int component, const QByteArray &data)
201
+{
202
+ Q_D(JingleContent);
203
+ if (d->transport)
204
+ d->transport->send(component, data);
205
+}
206
+
207
+void JingleContent::send(int component, const char *data, int size)
208
+{
209
+ send(component, QByteArray(data, size));
210
+}
211
+
212
+}
213
+
214
+#include "moc_jinglecontent.cpp"
215
libjreen-1.1.0.tar.bz2/src/experimental/jinglecontent.h
Added
149
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLECONTENT_H
28
+#define JINGLECONTENT_H
29
+
30
+#include "../stanzaextension.h"
31
+#include "jingletransport.h"
32
+#include <QStringList>
33
+
34
+namespace Jreen
35
+{
36
+
37
+class JingleSession;
38
+class JingleContentPrivate;
39
+
40
+typedef Payload JingleDescription;
41
+
42
+class JREEN_EXPORT JingleContent : public QObject
43
+{
44
+ Q_OBJECT
45
+ Q_DECLARE_PRIVATE(JingleContent)
46
+ Q_PROPERTY(Jreen::JingleContent::State state READ state NOTIFY stateChanged)
47
+public:
48
+ enum State {
49
+ Disconnected,
50
+ Gathering,
51
+ Connecting,
52
+ Connected,
53
+ Failed
54
+ };
55
+
56
+ JingleContent(JingleSession *session);
57
+ ~JingleContent();
58
+
59
+ JingleSession *session() const;
60
+ int componentCount() const;
61
+ virtual JingleDescription::Ptr defaultDescription() = 0;
62
+ virtual JingleDescription::Ptr handleDescription(const JingleDescription::Ptr &description) = 0;
63
+ State state() const;
64
+ bool isAcceptable() const;
65
+ void accept();
66
+ void decline();
67
+
68
+signals:
69
+ void stateChanged(Jreen::JingleContent::State);
70
+
71
+protected:
72
+ JingleContent(JingleSession *session, JingleContentPrivate &p);
73
+ void setComponentCount(int count);
74
+ void send(int component, const QByteArray &data);
75
+ void send(int component, const char *data, int size);
76
+ virtual void receive(int component, const QByteArray &data) = 0;
77
+ Q_PRIVATE_SLOT(d_func(), void _q_received(int, const QByteArray &))
78
+ Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(Jreen::JingleTransport::State))
79
+ Q_PRIVATE_SLOT(d_func(), void _q_localInfoReady(const Jreen::JingleTransportInfo::Ptr &))
80
+
81
+ QScopedPointer<JingleContentPrivate> d_ptr;
82
+};
83
+
84
+class JREEN_EXPORT AbstractJingleContentFactory : public AbstractPayloadFactory
85
+{
86
+public:
87
+ inline JingleDescription::Ptr createDescription() { return createPayload(); }
88
+ virtual QString media() const = 0;
89
+ virtual JingleContent *createObject(JingleSession *session) = 0;
90
+};
91
+
92
+template <typename Extension>
93
+class JingleContentFactory : public AbstractJingleContentFactory
94
+{
95
+public:
96
+ JingleContentFactory(const QString &uri, const QString &media = QString());
97
+ virtual ~JingleContentFactory();
98
+
99
+ virtual QString media() const;
100
+ virtual int payloadType() const;
101
+ virtual QStringList features() const;
102
+ virtual bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
103
+
104
+protected:
105
+ const QString m_elementUri;
106
+ const QString m_media;
107
+};
108
+
109
+template <typename Extension>
110
+Q_INLINE_TEMPLATE JingleContentFactory<Extension>::JingleContentFactory(const QString &uri, const QString &media)
111
+ : m_elementUri(uri), m_media(media)
112
+{
113
+}
114
+
115
+template <typename Extension>
116
+Q_INLINE_TEMPLATE JingleContentFactory<Extension>::~JingleContentFactory()
117
+{
118
+}
119
+
120
+template <typename Extension>
121
+Q_INLINE_TEMPLATE QString JingleContentFactory<Extension>::media() const
122
+{
123
+ return m_media;
124
+}
125
+
126
+template <typename Extension>
127
+Q_INLINE_TEMPLATE int JingleContentFactory<Extension>::payloadType() const
128
+{
129
+ return Extension::staticPayloadType();
130
+}
131
+
132
+template <typename Extension>
133
+Q_INLINE_TEMPLATE QStringList JingleContentFactory<Extension>::features() const
134
+{
135
+ return QStringList(m_elementUri);
136
+}
137
+
138
+template <typename Extension>
139
+Q_INLINE_TEMPLATE bool JingleContentFactory<Extension>::canParse(const QStringRef &name, const QStringRef &uri,
140
+ const QXmlStreamAttributes &attributes)
141
+{
142
+ return name == QLatin1String("description") && uri == m_elementUri
143
+ && (m_media.isEmpty() || attributes.value(QLatin1String("media")) == m_media);
144
+}
145
+
146
+}
147
+
148
+#endif // JINGLECONTENT_H
149
libjreen-1.1.0.tar.bz2/src/experimental/jinglecontent_p.h
Added
70
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLECONTENT_P_H
28
+#define JINGLECONTENT_P_H
29
+
30
+#include "jinglecontent.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class JingleContentPrivate
36
+{
37
+ Q_DECLARE_PUBLIC(JingleContent)
38
+public:
39
+ JingleContentPrivate(JingleContent *q)
40
+ : q_ptr(q), transport(0), componentCount(1), needTransports(0),
41
+ needAccept(0), canAccept(0), state(JingleContent::Gathering) {}
42
+
43
+ JingleContent *q_ptr;
44
+ JingleSession *session;
45
+ JingleTransport *transport;
46
+ int componentCount : 14;
47
+ int needTransports : 14;
48
+ int needAccept : 1;
49
+ int canAccept : 1;
50
+ JingleContent::State state;
51
+ QList<JingleTransport*> transports;
52
+ QList<JingleTransportInfo::Ptr> transportInfos;
53
+
54
+ void _q_received(int component, const QByteArray &data);
55
+ virtual void _q_stateChanged(Jreen::JingleTransport::State);
56
+ void _q_localInfoReady(const Jreen::JingleTransportInfo::Ptr &);
57
+ void _q_tryStateChanged(Jreen::JingleTransport::State state);
58
+ void setTransport(JingleTransport *trueTransport);
59
+ void initiateTransports();
60
+ void tryNextTransport();
61
+ void initiateTransports(const QList<JingleTransportInfo::Ptr> &transportInfos);
62
+ void accept();
63
+ void decline();
64
+ static JingleContentPrivate *get(JingleContent *q) { return q->d_func(); }
65
+};
66
+
67
+}
68
+
69
+#endif // JINGLECONTENT_P_H
70
libjreen-1.1.0.tar.bz2/src/experimental/jinglefactory.cpp
Added
198
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jinglefactory_p.h"
28
+#include "../jstrings.h"
29
+#include "../client_p.h"
30
+
31
+#define NS_JINGLE QLatin1String("urn:xmpp:jingle:1")
32
+#define NS_JINGLE_RTP QLatin1String("urn:xmpp:jingle:apps:rtp:1")
33
+
34
+namespace Jreen
35
+{
36
+
37
+static const char *actions = {
38
+ "content-accept",
39
+ "content-add",
40
+ "content-modify",
41
+ "content-reject",
42
+ "content-remove",
43
+ "description-info",
44
+ "security-info",
45
+ "session-accept",
46
+ "session-info",
47
+ "session-initiate",
48
+ "session-terminate",
49
+ "transport-accept",
50
+ "transport-info",
51
+ "transport-reject",
52
+ "transport-replace"
53
+};
54
+
55
+static const char *senders = {
56
+ "none",
57
+ "initiator",
58
+ "responder",
59
+ "both"
60
+};
61
+
62
+JingleFactory::JingleFactory(Client *client)
63
+ : m_client(ClientPrivate::get(client)), m_state(AtRoot), m_depth(0), m_factory(0)
64
+{
65
+}
66
+
67
+bool JingleFactory::checkSupport(const QSet<QString> &features)
68
+{
69
+ return features.contains(NS_JINGLE) && features.contains(NS_JINGLE_RTP);
70
+}
71
+
72
+QStringList JingleFactory::features() const
73
+{
74
+ return QStringList(NS_JINGLE) << NS_JINGLE_RTP;
75
+}
76
+
77
+bool JingleFactory::canParse(const QStringRef &name, const QStringRef &uri,
78
+ const QXmlStreamAttributes &attributes)
79
+{
80
+ Q_UNUSED(attributes);
81
+ return name == QLatin1String("jingle") && uri == NS_JINGLE;
82
+}
83
+
84
+void JingleFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
85
+ const QXmlStreamAttributes &attributes)
86
+{
87
+ Q_UNUSED(uri);
88
+ ++m_depth;
89
+ if (m_depth == 1) {
90
+ m_state = AtRoot;
91
+ m_jingle = Jingle::Ptr::create();
92
+ m_jingle->initiator = attributes.value(QLatin1String("initiator")).toString();
93
+ m_jingle->sid = attributes.value(QLatin1String("sid")).toString();
94
+ m_jingle->action = strToEnum<Jingle::Action>(attributes.value(QLatin1String("action")), actions);
95
+ } else if (m_depth == 2 && m_state == AtRoot && name == QLatin1String("content")) {
96
+ m_state = AtContent;
97
+ m_content.reset(new Jingle::Content);
98
+ m_content->name = attributes.value(QLatin1String("name")).toString();
99
+ m_content->senders = strToEnum<Jingle::SendersType>(attributes.value(QLatin1String("senders")), senders);
100
+ m_content->creator = strToEnum<Jingle::CreatorType>(attributes.value(QLatin1String("creator")), senders);
101
+ if (m_content->senders == Jingle::Invalid)
102
+ m_content->senders = Jingle::Both;
103
+ } else if (m_depth == 3 && m_state == AtContent) {
104
+ foreach (m_factory, m_client->factoriesByUri.values(uri.toString())) {
105
+ qDebug() << uri << Payload::payloadName(m_factory->payloadType())
106
+ << m_factory->canParse(name, uri, attributes);
107
+ if (m_factory->canParse(name, uri, attributes))
108
+ break;
109
+ else
110
+ m_factory = 0;
111
+ }
112
+ if (m_factory && name == QLatin1String("transport"))
113
+ m_state = AtTransport;
114
+ else if (m_factory && name == QLatin1String("description"))
115
+ m_state = AtDescription;
116
+ else
117
+ m_factory = 0;
118
+ qDebug() << name << uri << m_factory;
119
+ }
120
+ if (m_factory)
121
+ m_factory->handleStartElement(name, uri, attributes);
122
+}
123
+
124
+void JingleFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
125
+{
126
+ if (m_factory) {
127
+ m_factory->handleEndElement(name, uri);
128
+ if (m_depth == 3) {
129
+ if (m_state == AtTransport)
130
+ m_content->transports << m_factory->createPayload();
131
+ else if (m_state == AtDescription)
132
+ m_content->description = m_factory->createPayload();
133
+ else
134
+ Q_ASSERT(!"Unknown state with existen factory");
135
+ m_factory = 0;
136
+ m_state = AtContent;
137
+ }
138
+ } else if (m_depth == 2 && m_state == AtContent) {
139
+ m_jingle->contents << *m_content;
140
+ m_content.reset();
141
+ m_state = AtRoot;
142
+ }
143
+
144
+ --m_depth;
145
+}
146
+
147
+void JingleFactory::handleCharacterData(const QStringRef &text)
148
+{
149
+ if (m_factory)
150
+ m_factory->handleCharacterData(text);
151
+}
152
+
153
+void JingleFactory::serialize(Payload *obj, QXmlStreamWriter *writer)
154
+{
155
+ Jingle *jingle = se_cast<Jingle*>(obj);
156
+ if (!jingle) return;
157
+ writer->writeStartElement(QLatin1String("jingle"));
158
+ writer->writeDefaultNamespace(NS_JINGLE);
159
+ writer->writeAttribute(QLatin1String("action"), enumToStr(jingle->action, actions));
160
+ if (jingle->initiator.isValid())
161
+ writer->writeAttribute(QLatin1String("initiator"), jingle->initiator);
162
+ if (jingle->responder.isValid())
163
+ writer->writeAttribute(QLatin1String("responder"), jingle->responder);
164
+ writer->writeAttribute(QLatin1String("sid"), jingle->sid);
165
+ for (int i = 0; i < jingle->contents.size(); ++i) {
166
+ const Jingle::Content &content = jingle->contents.at(i);
167
+ writer->writeStartElement(QLatin1String("content"));
168
+ writer->writeAttribute(QLatin1String("creator"), enumToStr(content.creator, senders));
169
+ writer->writeAttribute(QLatin1String("senders"), enumToStr(content.senders, senders));
170
+ writer->writeAttribute(QLatin1String("name"), content.name);
171
+ AbstractPayloadFactory *factory = 0;
172
+ if (content.description) {
173
+ factory = m_client->factories.value(content.description->payloadType());
174
+ if (factory)
175
+ factory->serialize(content.description.data(), writer);
176
+ } else {
177
+ qDebug("No description");
178
+ }
179
+ for (int j = 0; j < content.transports.size(); ++j) {
180
+ Payload *payload = content.transports.at(j).data();
181
+ factory = m_client->factories.value(payload->payloadType());
182
+ if (factory)
183
+ factory->serialize(payload, writer);
184
+ }
185
+ writer->writeEndElement();
186
+ }
187
+ writer->writeEndElement();
188
+}
189
+
190
+Payload::Ptr JingleFactory::createPayload()
191
+{
192
+ Payload::Ptr result = m_jingle;
193
+ m_jingle.clear();
194
+ return result;
195
+}
196
+
197
+}
198
libjreen-1.1.0.tar.bz2/src/experimental/jinglefactory_p.h
Added
64
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEFACTORY_P_H
28
+#define JINGLEFACTORY_P_H
29
+
30
+#include "jingle_p.h"
31
+#include "../client_p.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleFactory : public PayloadFactory<Jingle>
37
+{
38
+public:
39
+ JingleFactory(Client *client);
40
+
41
+ static bool checkSupport(const QSet<QString> &features);
42
+ virtual QStringList features() const;
43
+ virtual bool canParse(const QStringRef &name, const QStringRef &uri,
44
+ const QXmlStreamAttributes &attributes);
45
+ virtual void handleStartElement(const QStringRef &name, const QStringRef &uri,
46
+ const QXmlStreamAttributes &attributes);
47
+ virtual void handleEndElement(const QStringRef &name, const QStringRef &uri);
48
+ virtual void handleCharacterData(const QStringRef &text);
49
+ virtual void serialize(Payload *obj, QXmlStreamWriter *writer);
50
+ virtual Payload::Ptr createPayload();
51
+
52
+private:
53
+ ClientPrivate *m_client;
54
+ enum State { AtRoot, AtContent, AtTransport, AtDescription, AtReason } m_state;
55
+ int m_depth;
56
+ Jingle::Ptr m_jingle;
57
+ AbstractPayloadFactory *m_factory;
58
+ QScopedPointer<Jingle::Content> m_content;
59
+};
60
+
61
+}
62
+
63
+#endif // JINGLEFACTORY_P_H
64
libjreen-1.1.0.tar.bz2/src/experimental/jinglemanager.cpp
Added
157
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jinglemanager_p.h"
28
+#include "../client.h"
29
+#include "jinglesession_p.h"
30
+#include "jingletransportice_p.h"
31
+#include "jingleaudiocontentfactory_p.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+JingleContent *JingleManagerPrivate::content(const QString &name, JingleSession *session)
37
+{
38
+ for (int i = 0; i < descriptions.size(); ++i) {
39
+ if (descriptions.at(i)->media() == name)
40
+ return descriptions.at(i)->createObject(session);
41
+ }
42
+ return 0;
43
+}
44
+
45
+JingleContent *JingleManagerPrivate::content(const JingleDescription::Ptr &description, JingleSession *session)
46
+{
47
+ for (int i = 0; i < descriptions.size(); ++i) {
48
+ if (descriptions.at(i)->payloadType() == description->payloadType())
49
+ return descriptions.at(i)->createObject(session);
50
+ }
51
+ return 0;
52
+}
53
+
54
+JingleTransport *JingleManagerPrivate::transport(const JingleTransportInfo::Ptr &info, JingleContent *content)
55
+{
56
+ for (int i = 0; i < transports.size(); ++i) {
57
+ if (transports.at(i)->payloadType() == info->payloadType())
58
+ return transports.at(i)->createObject(content);
59
+ }
60
+ return 0;
61
+}
62
+
63
+void JingleManagerPrivate::_q_iqReceived(const Jreen::IQ &iq)
64
+{
65
+ Jingle::Ptr jingle = iq.payload<Jingle>();
66
+ if (!jingle)
67
+ return;
68
+ qDebug() << Q_FUNC_INFO;
69
+ iq.accept();
70
+ JingleSession *session = sessions.value(jingle->sid);
71
+ if (session) {
72
+ JingleSessionPrivate::get(session)->handle(jingle);
73
+ } else if (jingle->action == Jingle::SessionInitiate) {
74
+ new JingleSession(jingle, client);
75
+ } else {
76
+ IQ error(IQ::Error, iq.from(), iq.id());
77
+ Jingle::Ptr result = Jingle::Ptr::create();
78
+ result->sid = jingle->sid;
79
+ result->initiator = jingle->initiator;
80
+ result->action = Jingle::SessionTerminate;
81
+ // TODO: Add reason
82
+ client->send(error);
83
+ return;
84
+ }
85
+ IQ reply(IQ::Result, iq.from());
86
+ client->send(reply);
87
+}
88
+
89
+JingleManager::JingleManager(Client *client)
90
+ : QObject(client), d_ptr(new JingleManagerPrivate)
91
+{
92
+ Q_D(JingleManager);
93
+ d->client = client;
94
+#ifdef HAVE_IRISICE
95
+ d->transports << new JingleIce::TransportFactory;
96
+#endif
97
+ d->descriptions << new JingleAudioContentFactory;
98
+ client->registerPayload(new JingleFactory(client));
99
+ foreach (AbstractPayloadFactory *factory, d->transports)
100
+ client->registerPayload(factory);
101
+ foreach (AbstractPayloadFactory *factory, d->descriptions)
102
+ client->registerPayload(factory);
103
+ connect(d->client, SIGNAL(iqReceived(Jreen::IQ)),
104
+ SLOT(_q_iqReceived(Jreen::IQ)));
105
+}
106
+
107
+JingleManager::~JingleManager()
108
+{
109
+}
110
+
111
+static inline bool set_contains_list(const QSet<QString> &features, const QStringList &list)
112
+{
113
+ bool ok = true;
114
+ for (int i = 0; ok && i < list.size(); ++i)
115
+ ok &= features.contains(list.at(i));
116
+ return ok;
117
+}
118
+
119
+bool JingleManager::checkSupport(const QSet<QString> &features)
120
+{
121
+ Q_D(JingleManager);
122
+ bool ok = JingleFactory::checkSupport(features);
123
+ if (!ok) return false;
124
+ ok = false;
125
+ for (int i = 0; !ok && i < d->transports.size(); ++i)
126
+ ok |= set_contains_list(features, d->transports.at(i)->features());
127
+ if (!ok) return false;
128
+ ok = false;
129
+ for (int i = 0; !ok && i < d->descriptions.size(); ++i)
130
+ ok |= set_contains_list(features, d->descriptions.at(i)->features());
131
+ return ok;
132
+}
133
+
134
+bool JingleManager::hasSession(const JID &responder)
135
+{
136
+ return d_func()->sessionsByJid.contains(responder);
137
+}
138
+
139
+JingleSession *JingleManager::createSession(const JID &responder, const QStringList &contents)
140
+{
141
+ Q_D(JingleManager);
142
+ if (JingleSession *session = d->sessionsByJid.value(responder))
143
+ return session;
144
+ JingleSession *session = new JingleSession(responder, contents, d->client);
145
+ emit sessionCreated(session);
146
+ return session;
147
+}
148
+
149
+JingleSession *JingleManager::session(const JID &jid) const
150
+{
151
+ return d_func()->sessionsByJid.value(jid);
152
+}
153
+
154
+}
155
+
156
+#include "moc_jinglemanager.cpp"
157
libjreen-1.1.0.tar.bz2/src/experimental/jinglemanager.h
Added
65
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEMANAGER_H
28
+#define JINGLEMANAGER_H
29
+
30
+#include "../iq.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class Client;
36
+class JingleSession;
37
+class JingleManagerPrivate;
38
+
39
+class JREEN_EXPORT JingleManager : public QObject
40
+{
41
+ Q_OBJECT
42
+ Q_DECLARE_PRIVATE(JingleManager)
43
+public:
44
+ ~JingleManager();
45
+
46
+ bool checkSupport(const QSet<QString> &features);
47
+ bool hasSession(const JID &responder);
48
+ JingleSession *createSession(const JID &responder, const QStringList &contents = QStringList());
49
+ JingleSession *session(const JID &jid) const;
50
+
51
+signals:
52
+ void sessionCreated(Jreen::JingleSession *session);
53
+ void sessionTerminated(Jreen::JingleSession *session);
54
+
55
+protected:
56
+ JingleManager(Client *client);
57
+ friend class Client;
58
+ QScopedPointer<JingleManagerPrivate> d_ptr;
59
+ Q_PRIVATE_SLOT(d_func(), void _q_iqReceived(const Jreen::IQ &))
60
+};
61
+
62
+}
63
+
64
+#endif // JINGLEMANAGER_H
65
libjreen-1.1.0.tar.bz2/src/experimental/jinglemanager_p.h
Added
55
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEMANAGER_P_H
28
+#define JINGLEMANAGER_P_H
29
+
30
+#include "jinglemanager.h"
31
+#include "jinglefactory_p.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleManagerPrivate
37
+{
38
+public:
39
+ Client *client;
40
+ QList<AbstractJingleTransportFactory*> transports;
41
+ QList<AbstractJingleContentFactory*> descriptions;
42
+ QHash<QString, JingleSession*> sessions;
43
+ QHash<JID, JingleSession*> sessionsByJid;
44
+
45
+ JingleContent *content(const QString &name, JingleSession *session);
46
+ JingleContent *content(const JingleDescription::Ptr &decription, JingleSession *session);
47
+ JingleTransport *transport(const JingleTransportInfo::Ptr &info, JingleContent *content);
48
+ void _q_iqReceived(const Jreen::IQ &iq);
49
+ static JingleManagerPrivate *get(JingleManager *q) { return q->d_func(); }
50
+};
51
+
52
+}
53
+
54
+#endif // JINGLEMANAGER_P_H
55
libjreen-1.1.0.tar.bz2/src/experimental/jinglesession.cpp
Added
283
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jinglesession_p.h"
28
+#include "../client.h"
29
+#include "../util.h"
30
+
31
+namespace Jreen
32
+{
33
+
34
+JingleSessionContent *JingleSessionPrivate::findContent(const QString &name)
35
+{
36
+ for (int i = 0; i < contents.size(); ++i) {
37
+ if (contents.at(i).name == name)
38
+ return &contentsi;
39
+ }
40
+ return 0;
41
+}
42
+
43
+JingleSessionContent *JingleSessionPrivate::findContent(JingleContent *content)
44
+{
45
+ for (int i = 0; i < contents.size(); ++i) {
46
+ if (contentsi.contentObject == content)
47
+ return &contentsi;
48
+ }
49
+ return 0;
50
+}
51
+
52
+void JingleSessionPrivate::handle(const Jingle::Ptr &jingle)
53
+{
54
+ qDebug() << Q_FUNC_INFO;
55
+ if (jingle->action == Jingle::SessionAccept) {
56
+ foreach (const Jingle::Content &remoteContent, jingle->contents) {
57
+ JingleSessionContent *content = findContent(remoteContent.name);
58
+ if (!content) {
59
+ qWarning("Unknown content with name %s", qPrintable(content->name));
60
+ continue;
61
+ }
62
+ if (!remoteContent.description) {
63
+ qWarning("Unknown content description with name %s", qPrintable(content->name));
64
+ continue;
65
+ }
66
+ content->contentObject->handleDescription(remoteContent.description);
67
+ if (remoteContent.transports.size() != 1) {
68
+ qWarning("Content %s has %d transports", qPrintable(content->name),
69
+ remoteContent.transports.size());
70
+ }
71
+ if (!remoteContent.transports.value(0)) {
72
+ qCritical("Content %s has no transports", qPrintable(content->name));
73
+ continue;
74
+ }
75
+ JingleContentPrivate *p = JingleContentPrivate::get(content->contentObject);
76
+ const JingleTransportInfo::Ptr &transportInfo = remoteContent.transports.at(0);
77
+ for (int i = content->transports.size() - 1; i >= 0; --i) {
78
+ if (content->transportsi->payloadType() != transportInfo->payloadType()) {
79
+ content->transports.removeAt(i);
80
+ delete p->transports.takeAt(i);
81
+ }
82
+ }
83
+ if (p->transports.isEmpty()) {
84
+ qCritical("Content %s has no needed transport", qPrintable(content->name));
85
+ continue;
86
+ }
87
+ p->setTransport(p->transports.first());
88
+ p->transport->setRemoteInfo(transportInfo, true);
89
+ }
90
+ } else if (jingle->action == Jingle::SessionTerminate) {
91
+ emit q_func()->terminated();
92
+ } else if (jingle->action == Jingle::ContentAdd) {
93
+ foreach (const Jingle::Content &remoteContent, jingle->contents) {
94
+ if (!remoteContent.description || remoteContent.transports.isEmpty()) {
95
+ Jingle::send(q_func(), Jingle::ContentReject, remoteContent);
96
+ continue;
97
+ }
98
+ JingleSessionContent content = remoteContent;
99
+ content.creator = Jingle::Initiator;
100
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(client->jingleManager());
101
+ content.contentObject = manager->content(remoteContent.description, q_func());
102
+ if (!content.contentObject) {
103
+ Jingle::send(q_func(), Jingle::ContentReject, remoteContent);
104
+ continue;
105
+ }
106
+ content.description = content.contentObject->handleDescription(remoteContent.description);
107
+ if (!content.description) {
108
+ content.description = content.contentObject->defaultDescription();
109
+ Jingle::send(q_func(), Jingle::ContentReject, content);
110
+ continue;
111
+ }
112
+ JingleContentPrivate *contentD = JingleContentPrivate::get(content.contentObject);
113
+ contentD->needAccept = 1;
114
+ contents << content;
115
+ JingleContentPrivate::get(content.contentObject)->initiateTransports(content.transports);
116
+ emit q_func()->contentAdded(content.contentObject);
117
+ }
118
+ }
119
+}
120
+
121
+void JingleSessionPrivate::accept(const JingleSessionContent &content)
122
+{
123
+ IQReply *reply = Jingle::send(q_func(), Jingle::ContentAccept, content);
124
+ Q_UNUSED(reply);
125
+}
126
+
127
+void JingleSessionPrivate::add(const JingleSessionContent &content)
128
+{
129
+ IQReply *reply = Jingle::send(q_func(), Jingle::ContentAdd, content);
130
+ Q_UNUSED(reply);
131
+}
132
+
133
+void JingleSessionPrivate::onTransportsReady(JingleContent *content, const QList<JingleTransport*> &transports)
134
+{
135
+ for (int i = 0; i < contents.size(); ++i) {
136
+ if (contents.at(i).contentObject != content)
137
+ continue;
138
+ JingleSessionContent &sessionContent = contentsi;
139
+ for (int j = 0; j < transports.size(); ++j)
140
+ sessionContent.transports << transportsj->localInfo();
141
+ if (initiating) {
142
+ needMore--;
143
+ if (needMore == 0)
144
+ q_func()->initiate();
145
+ } else {
146
+ JingleContentPrivate *p = JingleContentPrivate::get(content);
147
+ if (p->canAccept)
148
+ accept(sessionContent);
149
+ else
150
+ add(sessionContent);
151
+ }
152
+ }
153
+}
154
+
155
+JingleSession::JingleSession(const JID &responder, const QStringList &contents, Client *client)
156
+ : QObject(client->jingleManager()), d_ptr(new JingleSessionPrivate)
157
+{
158
+ Q_D(JingleSession);
159
+ d->q_ptr = this;
160
+ d->incoming = 0;
161
+ d->client = client;
162
+ d->other = responder;
163
+ d->sid = Util::randomStringHash(16);
164
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(client->jingleManager());
165
+ manager->sessions.insert(d->sid, this);
166
+ manager->sessionsByJid.insert(responder, this);
167
+ for (int i = 0; i < contents.size(); ++i)
168
+ addContent(contents.at(i));
169
+ if (d->needMore == 0 && d->contents.size() > 0)
170
+ initiate();
171
+}
172
+
173
+JingleSession::JingleSession(const Payload::Ptr &payload, Client *client)
174
+ : QObject(client->jingleManager()), d_ptr(new JingleSessionPrivate)
175
+{
176
+ Q_D(JingleSession);
177
+ Q_ASSERT(se_cast<Jingle*>(payload.data()));
178
+ d->client = client;
179
+ d->initiating = 0;
180
+ Jingle::Ptr jingle = payload.staticCast<Jingle>();
181
+ d->other = jingle->initiator;
182
+ d->sid = jingle->sid;
183
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(client->jingleManager());
184
+ manager->sessions.insert(d->sid, this);
185
+ manager->sessionsByJid.insert(jingle->initiator, this);
186
+}
187
+
188
+void JingleSession::initiate()
189
+{
190
+ Q_D(JingleSession);
191
+ IQReply *reply = Jingle::send(this, Jingle::SessionInitiate, d->contents);
192
+ Q_UNUSED(reply);
193
+}
194
+
195
+void JingleSession::terminate()
196
+{
197
+ IQReply *reply = Jingle::send(this, Jingle::SessionTerminate);
198
+ connect(reply, SIGNAL(received(Jreen::IQ)), SIGNAL(terminated()));
199
+}
200
+
201
+bool JingleSession::isIncoming() const
202
+{
203
+ return d_func()->incoming;
204
+}
205
+
206
+JID JingleSession::jid() const
207
+{
208
+ return d_func()->other;
209
+}
210
+
211
+JingleContent *JingleSession::content(const QString &id) const
212
+{
213
+ Q_D(const JingleSession);
214
+ for (int i = 0; i < d->contents.size(); ++i) {
215
+ if (d->contents.at(i).name == id)
216
+ return d->contents.at(i).contentObject;
217
+ }
218
+ return 0;
219
+}
220
+
221
+QStringList JingleSession::contents() const
222
+{
223
+ Q_D(const JingleSession);
224
+ QStringList result;
225
+ for (int i = 0; i < d->contents.size(); ++i)
226
+ result << d->contents.at(i).name;
227
+ return result;
228
+}
229
+
230
+JingleSession::~JingleSession()
231
+{
232
+ Q_D(JingleSession);
233
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(d->client->jingleManager());
234
+ manager->sessions.remove(d->sid);
235
+ manager->sessionsByJid.remove(d->other);
236
+}
237
+
238
+bool JingleSession::addContent(const QString &media, const QString &id)
239
+{
240
+ Q_D(JingleSession);
241
+ JingleManagerPrivate *manager = JingleManagerPrivate::get(d->client->jingleManager());
242
+ JingleSessionContent content;
243
+ content.creator = Jingle::Initiator;
244
+ content.contentObject = manager->content(media, this);
245
+ if (!content.contentObject) {
246
+ qWarning("Unknown content %s", qPrintable(media));
247
+ return false;
248
+ }
249
+ content.description = content.contentObject->defaultDescription();
250
+ content.name = id.isEmpty() ? Util::randomStringHash(8) : id;
251
+ JingleContentPrivate *contentD = JingleContentPrivate::get(content.contentObject);
252
+ contentD->initiateTransports();
253
+ d->contents << content;
254
+ if (d->initiating)
255
+ d->needMore++;
256
+ emit contentAdded(content.contentObject);
257
+ return true;
258
+}
259
+
260
+void JingleSession::accept()
261
+{
262
+ Q_D(JingleSession);
263
+ for (int i = 0; i < d->contents.size(); ++i) {
264
+ JingleContentPrivate *content = JingleContentPrivate::get(d->contents.at(i).contentObject);
265
+ if (content->needAccept)
266
+ content->accept();
267
+ }
268
+}
269
+
270
+void JingleSession::decline()
271
+{
272
+ Q_D(JingleSession);
273
+ for (int i = 0; i < d->contents.size(); ++i) {
274
+ JingleContentPrivate *content = JingleContentPrivate::get(d->contents.at(i).contentObject);
275
+ if (content->needAccept)
276
+ content->decline();
277
+ }
278
+}
279
+
280
+}
281
+
282
+#include "moc_jinglesession.cpp"
283
libjreen-1.1.0.tar.bz2/src/experimental/jinglesession.h
Added
77
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLESESSION_H
28
+#define JINGLESESSION_H
29
+
30
+#include "jinglecontent.h"
31
+#include "../stanzaextension.h"
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleManager;
37
+class JingleManagerPrivate;
38
+class JingleSessionPrivate;
39
+class Client;
40
+class JID;
41
+
42
+class JREEN_EXPORT JingleSession : public QObject
43
+{
44
+ Q_OBJECT
45
+ Q_DECLARE_PRIVATE(JingleSession)
46
+public:
47
+// enum State { };
48
+
49
+ ~JingleSession();
50
+
51
+ bool addContent(const QString &content, const QString &id = QString());
52
+ void initiate();
53
+ void terminate();
54
+ void accept();
55
+ void decline();
56
+ bool isIncoming() const;
57
+ JID jid() const;
58
+ JingleContent *content(const QString &id) const;
59
+ QStringList contents() const;
60
+
61
+signals:
62
+ void contentAdded(Jreen::JingleContent *content);
63
+ void contentRemoved(Jreen::JingleContent *content);
64
+ void terminated();
65
+
66
+protected:
67
+ JingleSession(const JID &responder, const QStringList &contents, Client *client);
68
+ JingleSession(const Payload::Ptr &payload, Client *client);
69
+ friend class JingleManager;
70
+ friend class JingleManagerPrivate;
71
+ QScopedPointer<JingleSessionPrivate> d_ptr;
72
+};
73
+
74
+}
75
+
76
+#endif // JINGLESESSION_H
77
libjreen-1.1.0.tar.bz2/src/experimental/jinglesession_p.h
Added
76
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLESESSION_P_H
28
+#define JINGLESESSION_P_H
29
+
30
+#include "jinglesession.h"
31
+#include "jinglemanager_p.h"
32
+#include "jingle_p.h"
33
+#include "jinglecontent_p.h"
34
+
35
+namespace Jreen
36
+{
37
+
38
+class JingleSessionContent : public Jingle::Content
39
+{
40
+public:
41
+ JingleSessionContent() : contentObject(0), initiating(0) {}
42
+ JingleSessionContent(const Content &o) : Content(o), contentObject(0), initiating(0) {}
43
+ JingleSessionContent(const JingleSessionContent &o)
44
+ : Content(o), contentObject(o.contentObject), initiating(o.initiating) {}
45
+
46
+ JingleContent *contentObject;
47
+ int initiating : 1;
48
+};
49
+
50
+class JingleSessionPrivate
51
+{
52
+public:
53
+ Q_DECLARE_PUBLIC(JingleSession);
54
+ JingleSessionPrivate() : needMore(0), incoming(1), initiating(1) {}
55
+ JingleSession *q_ptr;
56
+ Client *client;
57
+ JID other;
58
+ QString sid;
59
+ QList<JingleSessionContent> contents;
60
+ int needMore : 30;
61
+ int incoming : 1;
62
+ int initiating : 1;
63
+
64
+ JingleSessionContent *findContent(const QString &name);
65
+ JingleSessionContent *findContent(JingleContent *content);
66
+ void handle(const Jingle::Ptr &jingle);
67
+ void accept(const JingleSessionContent &content);
68
+ void add(const JingleSessionContent &content);
69
+ void onTransportsReady(JingleContent *content, const QList<JingleTransport*> &transports);
70
+ static JingleSessionPrivate *get(JingleSession *q) { return q->d_func(); }
71
+};
72
+
73
+}
74
+
75
+#endif // JINGLESESSION_P_H
76
libjreen-1.1.0.tar.bz2/src/experimental/jinglespeexcodec.cpp
Added
130
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jinglespeexcodec_p.h"
28
+
29
+#ifdef JREEN_HAVE_SPEEX
30
+
31
+namespace Jreen
32
+{
33
+
34
+JingleSpeexCodec::JingleSpeexCodec(const JingleAudioPayload &payload)
35
+{
36
+ const SpeexMode *mode = 0;
37
+ switch (payload.clockRate()) {
38
+ case 32000:
39
+ mode = &speex_uwb_mode;
40
+ break;
41
+ case 16000:
42
+ mode = &speex_wb_mode;
43
+ break;
44
+ default:
45
+ Q_ASSERT(!"Unknown clockrate");
46
+ // fall through
47
+ // break;
48
+ case 8000:
49
+ mode = &speex_nb_mode;
50
+ break;
51
+ }
52
+
53
+ speex_bits_init(&m_bits);
54
+ m_encodingState = speex_encoder_init(mode);
55
+ speex_encoder_ctl(m_encodingState, SPEEX_GET_FRAME_SIZE, &m_frameSize);
56
+ m_decodingState = speex_decoder_init(mode);
57
+ speex_decoder_ctl(m_decodingState, SPEEX_GET_FRAME_SIZE, &m_frameSize);
58
+
59
+ QString quality = payload.parameter(QLatin1String("quality"));
60
+ if (!quality.isEmpty()) {
61
+ int value = quality.toInt();
62
+ speex_encoder_ctl(m_encodingState, SPEEX_SET_QUALITY, &value);
63
+ }
64
+}
65
+
66
+JingleSpeexCodec::~JingleSpeexCodec()
67
+{
68
+ speex_bits_destroy(&m_bits);
69
+ speex_encoder_destroy(m_encodingState);
70
+ speex_decoder_destroy(m_decodingState);
71
+}
72
+
73
+int JingleSpeexCodec::frameSize() const
74
+{
75
+ return m_frameSize;
76
+}
77
+
78
+QByteArray JingleSpeexCodec::encodeFrame(const char *data, int size)
79
+{
80
+ Q_ASSERT(size == m_frameSize * 2);
81
+ spx_int16_t *inputFrame = reinterpret_cast<spx_int16_t*>(const_cast<char*>(data));
82
+ speex_bits_reset(&m_bits);
83
+ speex_encode_int(m_encodingState, inputFrame, &m_bits);
84
+ QByteArray frame(speex_bits_nbytes(&m_bits), Qt::Uninitialized);
85
+ int frameSize = speex_bits_write(&m_bits, frame.data(), frame.size());
86
+ Q_ASSERT(frameSize == frame.size());
87
+ return frame;
88
+}
89
+
90
+QByteArray JingleSpeexCodec::decodeFrame(const char *data, int size)
91
+{
92
+ speex_bits_read_from(&m_bits, const_cast<char *>(data), size);
93
+ QByteArray output(m_frameSize * 2, Qt::Uninitialized);
94
+ spx_int16_t *outputFrame = reinterpret_cast<spx_int16_t*>(output.data());
95
+ speex_decode_int(m_decodingState, &m_bits, outputFrame);
96
+ return output;
97
+}
98
+
99
+QList<JingleAudioPayload> JingleSpeexCodecFactory::supportedPayloads()
100
+{
101
+ QList<JingleAudioPayload> result;
102
+ JingleAudioPayload payload;
103
+ payload.setId(97);
104
+ payload.setName(QLatin1String("speex"));
105
+ payload.setClockRate(8000);
106
+ result << payload;
107
+// payload.setId(96);
108
+// payload.setClockRate(16000);
109
+// result << payload;
110
+// payload.setId(98);
111
+// payload.setClockRate(32000);
112
+// result << payload;
113
+ return result;
114
+}
115
+
116
+bool JingleSpeexCodecFactory::supportsPayload(const JingleAudioPayload &payload)
117
+{
118
+ return !payload.name().compare(QLatin1String("speex"), Qt::CaseInsensitive)
119
+ && payload.clockRate() == 8000;
120
+}
121
+
122
+JingleAudioCodec *JingleSpeexCodecFactory::createCodec(const JingleAudioPayload &payload)
123
+{
124
+ return new JingleSpeexCodec(payload);
125
+}
126
+
127
+}
128
+
129
+#endif
130
libjreen-1.1.0.tar.bz2/src/experimental/jinglespeexcodec_p.h
Added
64
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#if !defined(JINGLESPEEXCODEC_P_H) && defined(JREEN_HAVE_SPEEX)
28
+#define JINGLESPEEXCODEC_P_H
29
+
30
+#include "jingleaudiocontent.h"
31
+#include <speex/speex.h>
32
+
33
+namespace Jreen
34
+{
35
+
36
+class JingleSpeexCodec : public JingleAudioCodec
37
+{
38
+public:
39
+ JingleSpeexCodec(const JingleAudioPayload &payload);
40
+ ~JingleSpeexCodec();
41
+
42
+ virtual int frameSize() const;
43
+ virtual QByteArray encodeFrame(const char *data, int size);
44
+ virtual QByteArray decodeFrame(const char *data, int size);
45
+
46
+private:
47
+ SpeexBits m_bits;
48
+ void *m_decodingState;
49
+ void *m_encodingState;
50
+ int m_frameSize;
51
+};
52
+
53
+class JingleSpeexCodecFactory : public JingleAudioCodecFactory
54
+{
55
+public:
56
+ virtual QList<JingleAudioPayload> supportedPayloads();
57
+ virtual bool supportsPayload(const JingleAudioPayload &payload);
58
+ virtual JingleAudioCodec *createCodec(const JingleAudioPayload &payload);
59
+};
60
+
61
+}
62
+
63
+#endif // JINGLESPEEXCODEC_P_H
64
libjreen-1.1.0.tar.bz2/src/experimental/jingletransport.cpp
Added
74
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingletransport.h"
28
+#include "jinglesession.h"
29
+
30
+namespace Jreen
31
+{
32
+
33
+class JingleTransportPrivate
34
+{
35
+public:
36
+ JingleTransportInfo::Ptr localInfo;
37
+ JingleTransport::State state;
38
+};
39
+
40
+JingleTransport::JingleTransport(JingleContent *content)
41
+ : QObject(content), d_ptr(new JingleTransportPrivate)
42
+{
43
+ Q_D(JingleTransport);
44
+ d->state = Gathering;
45
+}
46
+
47
+JingleTransport::~JingleTransport()
48
+{
49
+}
50
+
51
+JingleTransport::State JingleTransport::state() const
52
+{
53
+ return d_func()->state;
54
+}
55
+
56
+JingleTransportInfo::Ptr JingleTransport::localInfo() const
57
+{
58
+ return d_func()->localInfo;
59
+}
60
+
61
+void JingleTransport::setState(JingleTransport::State state)
62
+{
63
+ d_func()->state = state;
64
+ emit stateChanged(state);
65
+}
66
+
67
+void JingleTransport::setLocalInfo(const JingleTransportInfo::Ptr &info)
68
+{
69
+ d_func()->localInfo = info;
70
+ emit localInfoReady(info);
71
+}
72
+
73
+}
74
libjreen-1.1.0.tar.bz2/src/experimental/jingletransport.h
Added
132
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLETRANSPORT_H
28
+#define JINGLETRANSPORT_H
29
+
30
+#include "jinglemanager.h"
31
+#include "../stanzaextension.h"
32
+#include <QSharedPointer>
33
+
34
+namespace Jreen
35
+{
36
+
37
+class JingleTransportPrivate;
38
+class JingleContent;
39
+typedef Payload JingleTransportInfo;
40
+
41
+class JingleTransport : public QObject
42
+{
43
+ Q_OBJECT
44
+ Q_DECLARE_PRIVATE(JingleTransport)
45
+ Q_PROPERTY(Jreen::JingleTransport::State state READ state NOTIFY stateChanged)
46
+public:
47
+ enum State {
48
+ Disconnected,
49
+ Gathering,
50
+ Connecting,
51
+ Connected,
52
+ Failed
53
+ };
54
+ typedef QSharedPointer<JingleTransport> Ptr;
55
+
56
+ JingleTransport(JingleContent *content);
57
+ virtual ~JingleTransport();
58
+
59
+ State state() const;
60
+ virtual void send(int component, const QByteArray &data) = 0;
61
+ JingleTransportInfo::Ptr localInfo() const;
62
+ virtual void setRemoteInfo(const JingleTransportInfo::Ptr &info, bool final) = 0;
63
+
64
+protected:
65
+ void setState(State state);
66
+ void setLocalInfo(const JingleTransportInfo::Ptr &info);
67
+
68
+signals:
69
+ void received(int component, const QByteArray &data);
70
+ void localInfoReady(const Jreen::JingleTransportInfo::Ptr &info);
71
+ void stateChanged(Jreen::JingleTransport::State);
72
+
73
+private:
74
+ QScopedPointer<JingleTransportPrivate> d_ptr;
75
+};
76
+
77
+class AbstractJingleTransportFactory : public AbstractPayloadFactory
78
+{
79
+public:
80
+ inline JingleTransportInfo::Ptr createInfo() { return createPayload(); }
81
+ virtual JingleTransport *createObject(JingleContent *content) = 0;
82
+};
83
+
84
+template <typename Extension>
85
+class JingleTransportFactory : public AbstractJingleTransportFactory
86
+{
87
+public:
88
+ JingleTransportFactory(const QString &uri);
89
+ virtual ~JingleTransportFactory();
90
+
91
+ virtual int payloadType() const;
92
+ virtual QStringList features() const;
93
+ virtual bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
94
+
95
+protected:
96
+ const QString m_elementUri;
97
+};
98
+
99
+template <typename Extension>
100
+Q_INLINE_TEMPLATE JingleTransportFactory<Extension>::JingleTransportFactory(const QString &uri)
101
+ : m_elementUri(uri)
102
+{
103
+}
104
+
105
+template <typename Extension>
106
+Q_INLINE_TEMPLATE JingleTransportFactory<Extension>::~JingleTransportFactory()
107
+{
108
+}
109
+
110
+template <typename Extension>
111
+Q_INLINE_TEMPLATE int JingleTransportFactory<Extension>::payloadType() const
112
+{
113
+ return Extension::staticPayloadType();
114
+}
115
+
116
+template <typename Extension>
117
+Q_INLINE_TEMPLATE QStringList JingleTransportFactory<Extension>::features() const
118
+{
119
+ return QStringList(m_elementUri);
120
+}
121
+
122
+template <typename Extension>
123
+Q_INLINE_TEMPLATE bool JingleTransportFactory<Extension>::canParse(const QStringRef &name, const QStringRef &uri,
124
+ const QXmlStreamAttributes &)
125
+{
126
+ return name == QLatin1String("transport") && uri == m_elementUri;
127
+}
128
+
129
+}
130
+
131
+#endif // JINGLETRANSPORT_H
132
libjreen-1.1.0.tar.bz2/src/experimental/jingletransportice.cpp
Added
276
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "jingletransportice_p.h"
28
+
29
+#ifdef HAVE_IRISICE
30
+
31
+#include <QHostAddress>
32
+#include <QNetworkInterface>
33
+#include "jinglecontent.h"
34
+#include "jinglesession.h"
35
+#include "../jstrings.h"
36
+#include "../util.h"
37
+
38
+#define NS_ICE_UDP QLatin1String("urn:xmpp:jingle:transports:ice-udp:1")
39
+
40
+namespace Jreen
41
+{
42
+namespace JingleIce
43
+{
44
+
45
+static inline int addressPriority(const QHostAddress &address)
46
+{
47
+ if (address.protocol() == QAbstractSocket::IPv6Protocol) {
48
+ if (address == QHostAddress(QHostAddress::LocalHostIPv6))
49
+ return 0;
50
+ if (XMPP::Ice176::isIPv6LinkLocalAddress(address))
51
+ return 1;
52
+ } else if (address.protocol() == QAbstractSocket::IPv4Protocol) {
53
+ quint32 v4 = address.toIPv4Address();
54
+ quint8 a0 = v4 >> 24;
55
+ quint8 a1 = (v4 >> 16) & 0xff;
56
+ if(a0 == 127)
57
+ return 0;
58
+ else if(a0 == 169 && a1 == 254)
59
+ return 1;
60
+ else if(a0 == 10)
61
+ return 2;
62
+ else if(a0 == 172 && a1 >= 16 && a1 <= 31)
63
+ return 2;
64
+ else if(a0 == 192 && a1 == 168)
65
+ return 2;
66
+ }
67
+ return 3;
68
+}
69
+
70
+static inline bool addressLessThen(const QHostAddress &a, const QHostAddress &b)
71
+{
72
+ int cmp = addressPriority(a) - addressPriority(b);
73
+ if (cmp != 0)
74
+ return cmp < 0;
75
+ return a.protocol() == QAbstractSocket::IPv6Protocol
76
+ && b.protocol() != QAbstractSocket::IPv6Protocol;
77
+}
78
+
79
+Transport::Transport(JingleContent *content)
80
+ : JingleTransport(content)
81
+{
82
+ QList<QHostAddress> addresses;
83
+ foreach (const QNetworkInterface &networkInterface, QNetworkInterface::allInterfaces()) {
84
+ if (networkInterface.flags() & QNetworkInterface::IsLoopBack)
85
+ continue;
86
+ foreach (const QNetworkAddressEntry &addressEntry, networkInterface.addressEntries()) {
87
+ QHostAddress address = addressEntry.ip();
88
+ if(address.protocol() == QAbstractSocket::IPv6Protocol && XMPP::Ice176::isIPv6LinkLocalAddress(address))
89
+ address.setScopeId(networkInterface.name());
90
+ addresses << address;
91
+ }
92
+ }
93
+ qSort(addresses.begin(), addresses.end(), addressLessThen);
94
+ QList<XMPP::Ice176::LocalAddress> localAddresses;
95
+ foreach (const QHostAddress &address, addresses) {
96
+ XMPP::Ice176::LocalAddress localAddress;
97
+ localAddress.addr = address;
98
+ localAddresses << localAddress;
99
+ }
100
+
101
+ m_ice = new XMPP::Ice176(this);
102
+ m_ice->setComponentCount(content->componentCount());
103
+ for (int i = 0; i < content->componentCount(); ++i)
104
+ m_ready.insert(i);
105
+ m_ice->setLocalCandidateTrickle(true);
106
+ m_ice->setLocalAddresses(localAddresses);
107
+ m_portReserver = new XMPP::UdpPortReserver(m_ice);
108
+ m_portReserver->setAddresses(addresses);
109
+ m_portReserver->setPorts(qrand() & 0xffff, 4);
110
+ m_ice->setPortReserver(m_portReserver);
111
+
112
+ connect(m_ice, SIGNAL(started()), SLOT(onIceStarted()));
113
+ connect(m_ice, SIGNAL(error(XMPP::Ice176::Error)), SLOT(onIceError(XMPP::Ice176::Error)));
114
+ connect(m_ice, SIGNAL(localCandidatesReady(const QList<XMPP::Ice176::Candidate> &)), SLOT(onIceLocalCandidatesReady(const QList<XMPP::Ice176::Candidate> &)));
115
+ connect(m_ice, SIGNAL(componentReady(int)), SLOT(onIceComponentReady(int)), Qt::QueuedConnection); // signal is not DOR-SS
116
+ connect(m_ice, SIGNAL(readyRead(int)), SLOT(onIceReadyRead(int)));
117
+
118
+ m_ice->start(content->isAcceptable() ? XMPP::Ice176::Responder : XMPP::Ice176::Initiator);
119
+}
120
+
121
+Transport::~Transport()
122
+{
123
+}
124
+
125
+void Transport::send(int component, const QByteArray &data)
126
+{
127
+ m_ice->writeDatagram(component, data);
128
+}
129
+
130
+void Transport::setRemoteInfo(const JingleTransportInfo::Ptr &genericInfo, bool final)
131
+{
132
+ Q_UNUSED(final);
133
+ qDebug() << Q_FUNC_INFO;
134
+ TransportInfo::Ptr info = genericInfo.staticCast<TransportInfo>();
135
+ if (!info->ufrag.isEmpty())
136
+ m_ice->setPeerUfrag(info->ufrag);
137
+ if (!info->pwd.isEmpty())
138
+ m_ice->setPeerPassword(info->pwd);
139
+ m_ice->addRemoteCandidates(info->candidates);
140
+ setState(Connecting);
141
+}
142
+
143
+void Transport::onIceStarted()
144
+{
145
+ qDebug() << Q_FUNC_INFO;
146
+}
147
+
148
+void Transport::onIceError(XMPP::Ice176::Error error)
149
+{
150
+ qDebug() << Q_FUNC_INFO << error;
151
+ setState(Failed);
152
+}
153
+
154
+void Transport::onIceLocalCandidatesReady(const QList<XMPP::Ice176::Candidate> &candidates)
155
+{
156
+ qDebug() << Q_FUNC_INFO;
157
+ TransportInfo::Ptr info = TransportInfo::Ptr::create();
158
+ info->candidates = candidates;
159
+ info->ufrag = m_ice->localUfrag();
160
+ info->pwd = m_ice->localPassword();
161
+ setLocalInfo(info);
162
+}
163
+
164
+void Transport::onIceComponentReady(int component)
165
+{
166
+ m_ready.remove(component);
167
+ qDebug() << Q_FUNC_INFO << component;
168
+ if (m_ready.isEmpty())
169
+ setState(Connected);
170
+}
171
+
172
+void Transport::onIceReadyRead(int component)
173
+{
174
+ while (m_ice->hasPendingDatagrams(component)) {
175
+ emit received(component, m_ice->readDatagram(component));
176
+ }
177
+}
178
+
179
+TransportFactory::TransportFactory()
180
+ : JingleTransportFactory<TransportInfo>(NS_ICE_UDP), m_depth(0)
181
+{
182
+}
183
+
184
+JingleTransport *TransportFactory::createObject(JingleContent *content)
185
+{
186
+ return new Transport(content);
187
+}
188
+
189
+void TransportFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attr)
190
+{
191
+ Q_UNUSED(uri);
192
+ m_depth++;
193
+ if (m_depth == 1) {
194
+ m_info = TransportInfo::Ptr::create();
195
+ m_info->pwd = attr.value(QLatin1String("pwd")).toString();
196
+ m_info->ufrag = attr.value(QLatin1String("ufrag")).toString();
197
+ } else if (m_depth == 2 && name == QLatin1String("candidate")) {
198
+ m_info->candidates << Candidate();
199
+ Candidate &cand = m_info->candidates.last();
200
+ cand.type = attr.value(QLatin1String("type")).toString();
201
+ cand.ip = QHostAddress(attr.value(QLatin1String("ip")).toString());
202
+ cand.port = attr.value(QLatin1String("port")).toString().toInt();
203
+ cand.network = attr.value(QLatin1String("network")).toString().toInt();
204
+ cand.component = attr.value(QLatin1String("component")).toString().toInt();
205
+ cand.priority = attr.value(QLatin1String("priority")).toString().toInt();
206
+ cand.protocol = attr.value(QLatin1String("protocol")).toString();
207
+ cand.foundation = attr.value(QLatin1String("foundation")).toString();
208
+ cand.rel_addr = QHostAddress(attr.value(QLatin1String("rel-addr")).toString());
209
+ cand.rel_port = attr.value(QLatin1String("rel-port")).toString().toInt();
210
+ cand.generation = attr.value(QLatin1String("generation")).toString().toInt();
211
+ cand.id = attr.value(QLatin1String("id")).toString();
212
+ }
213
+}
214
+
215
+void TransportFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
216
+{
217
+ Q_UNUSED(name);
218
+ Q_UNUSED(uri);
219
+ m_depth--;
220
+}
221
+
222
+void TransportFactory::handleCharacterData(const QStringRef &text)
223
+{
224
+ Q_UNUSED(text);
225
+}
226
+
227
+void TransportFactory::serialize(Payload *obj, QXmlStreamWriter *writer)
228
+{
229
+ TransportInfo *info = se_cast<TransportInfo*>(obj);
230
+ Q_ASSERT(info);
231
+ writer->writeStartElement(QLatin1String("transport"));
232
+ writer->writeDefaultNamespace(m_elementUri);
233
+ if (!info->pwd.isEmpty())
234
+ writer->writeAttribute(QLatin1String("pwd"), info->pwd);
235
+ if (!info->ufrag.isEmpty())
236
+ writer->writeAttribute(QLatin1String("ufrag"), info->ufrag);
237
+ for (int i = 0; i < info->candidates.size(); ++i) {
238
+ const Candidate &c = info->candidates.at(i);
239
+ writer->writeEmptyElement(QLatin1String("candidate"));
240
+ writer->writeAttribute(QLatin1String("component"), QString::number(c.component));
241
+ writer->writeAttribute(QLatin1String("foundation"), c.foundation);
242
+ writer->writeAttribute(QLatin1String("generation"), QString::number(c.generation));
243
+ if(!c.id.isEmpty())
244
+ writer->writeAttribute(QLatin1String("id"), c.id);
245
+ writer->writeAttribute(QLatin1String("ip"), c.ip.toString());
246
+ if(c.network != -1)
247
+ writer->writeAttribute(QLatin1String("network"), QString::number(c.network));
248
+ else // weird?
249
+ writer->writeAttribute(QLatin1String("network"), QString::number(0));
250
+ writer->writeAttribute(QLatin1String("port"), QString::number(c.port));
251
+ writer->writeAttribute(QLatin1String("priority"), QString::number(c.priority));
252
+ writer->writeAttribute(QLatin1String("protocol"), c.protocol);
253
+ if(!c.rel_addr.isNull())
254
+ writer->writeAttribute(QLatin1String("rel-addr"), c.rel_addr.toString());
255
+ if(c.rel_port != -1)
256
+ writer->writeAttribute(QLatin1String("rel-port"), QString::number(c.rel_port));
257
+ writer->writeAttribute("type", c.type);
258
+ }
259
+ writer->writeEndElement();
260
+}
261
+
262
+Payload::Ptr TransportFactory::createPayload()
263
+{
264
+ qDebug() << Q_FUNC_INFO << m_info->pwd << m_info->ufrag;
265
+ qDebug() << Q_FUNC_INFO << m_info->candidates.size();
266
+ Payload::Ptr result = m_info;
267
+ m_info.clear();
268
+ return result;
269
+}
270
+
271
+}
272
+
273
+}
274
+
275
+#endif
276
libjreen-1.1.0.tar.bz2/src/experimental/jingletransportice_p.h
Added
101
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JINGLEICE_H
28
+#define JINGLEICE_H
29
+
30
+#include "jingletransport.h"
31
+
32
+#ifdef HAVE_IRISICE
33
+
34
+#include <QList>
35
+#include "3rdparty/icesupport/ice176.h"
36
+#include "3rdparty/icesupport/udpportreserver.h"
37
+//#include <nice.h>
38
+
39
+namespace Jreen
40
+{
41
+namespace JingleIce
42
+{
43
+
44
+class Transport : public JingleTransport
45
+{
46
+ Q_OBJECT
47
+public:
48
+ Transport(JingleContent *content);
49
+ ~Transport();
50
+
51
+ virtual void send(int component, const QByteArray &data);
52
+ virtual void setRemoteInfo(const JingleTransportInfo::Ptr &info, bool final);
53
+
54
+private slots:
55
+ void onIceStarted();
56
+ void onIceError(XMPP::Ice176::Error error);
57
+ void onIceLocalCandidatesReady(const QList<XMPP::Ice176::Candidate> &candidates);
58
+ void onIceComponentReady(int component);
59
+ void onIceReadyRead(int);
60
+
61
+private:
62
+ XMPP::Ice176 *m_ice;
63
+ XMPP::UdpPortReserver *m_portReserver;
64
+ QSet<int> m_ready;
65
+};
66
+
67
+typedef XMPP::Ice176::Candidate Candidate;
68
+
69
+class TransportInfo : public JingleTransportInfo
70
+{
71
+ J_PAYLOAD(Jreen::JingleIce::TransportInfo)
72
+public:
73
+ QList<Candidate> candidates;
74
+ QString pwd;
75
+ QString ufrag;
76
+};
77
+
78
+class TransportFactory : public JingleTransportFactory<TransportInfo>
79
+{
80
+public:
81
+ TransportFactory();
82
+
83
+ virtual JingleTransport *createObject(JingleContent *content);
84
+ virtual void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
85
+ virtual void handleEndElement(const QStringRef &name, const QStringRef &uri);
86
+ virtual void handleCharacterData(const QStringRef &text);
87
+ virtual void serialize(Payload *obj, QXmlStreamWriter *writer);
88
+ virtual Payload::Ptr createPayload();
89
+
90
+private:
91
+ int m_depth;
92
+ TransportInfo::Ptr m_info;
93
+};
94
+
95
+}
96
+}
97
+
98
+#endif // HAVE_IRISICE
99
+
100
+#endif // JINGLEICE_H
101
libjreen-1.1.0.tar.bz2/src/forwarded.cpp
Added
70
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "forwarded.h"
28
+
29
+namespace Jreen
30
+{
31
+
32
+class ForwardedPrivate
33
+{
34
+public:
35
+ ForwardedPrivate(const Message &m, const DelayedDelivery::Ptr &t)
36
+ : message(m), time(t) {}
37
+ Message message;
38
+ DelayedDelivery::Ptr time;
39
+};
40
+
41
+Forwarded::Forwarded(const Message &message, const DelayedDelivery::Ptr &time)
42
+ : d_ptr(new ForwardedPrivate(message, time))
43
+{
44
+}
45
+
46
+Forwarded::~Forwarded()
47
+{
48
+}
49
+
50
+Message Forwarded::message() const
51
+{
52
+ return d_func()->message;
53
+}
54
+
55
+void Forwarded::setMessage(const Message &message)
56
+{
57
+ d_func()->message = message;
58
+}
59
+
60
+DelayedDelivery::Ptr Forwarded::time() const
61
+{
62
+ return d_func()->time;
63
+}
64
+
65
+void Forwarded::setTime(const DelayedDelivery::Ptr &time)
66
+{
67
+ d_func()->time = time;
68
+}
69
+} // namespace Jreen
70
libjreen-1.1.0.tar.bz2/src/forwarded.h
Added
58
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_FORWARDED_H
28
+#define JREEN_FORWARDED_H
29
+
30
+#include "message.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class ForwardedPrivate;
36
+
37
+class JREEN_EXPORT Forwarded : public Payload
38
+{
39
+ J_PAYLOAD(Jreen::Forwarded)
40
+ Q_DECLARE_PRIVATE(Forwarded)
41
+public:
42
+ Forwarded(const Message &message = Message(), const DelayedDelivery::Ptr &time = DelayedDelivery::Ptr());
43
+ ~Forwarded();
44
+
45
+ Message message() const;
46
+ void setMessage(const Message &message);
47
+
48
+ DelayedDelivery::Ptr time() const;
49
+ void setTime(const DelayedDelivery::Ptr &time);
50
+
51
+private:
52
+ QScopedPointer<ForwardedPrivate> d_ptr;
53
+};
54
+
55
+} // namespace Jreen
56
+
57
+#endif // JREEN_FORWARDED_H
58
libjreen-1.1.0.tar.bz2/src/forwardedfactory.cpp
Added
116
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "forwardedfactory_p.h"
28
+
29
+#define NS_FORWARDED QLatin1String("urn:xmpp:forward:0")
30
+
31
+namespace Jreen
32
+{
33
+
34
+ForwardedFactory::ForwardedFactory(Client *client)
35
+ : m_messageFactory(client)
36
+{
37
+ m_depth = 0;
38
+ m_state = AtUnknown;
39
+}
40
+
41
+QStringList ForwardedFactory::features() const
42
+{
43
+ return QStringList(NS_FORWARDED);
44
+}
45
+
46
+bool ForwardedFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
47
+{
48
+ Q_UNUSED(attributes);
49
+ return name == QLatin1String("forwarded") && uri == NS_FORWARDED;
50
+}
51
+
52
+void ForwardedFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
53
+{
54
+ ++m_depth;
55
+ if (m_depth == 1) {
56
+ m_forwarded.reset(new Forwarded);
57
+ } else if (m_depth == 2) {
58
+ if (m_delayedFactory.canParse(name, uri, attributes))
59
+ m_state = AtDelayed;
60
+ else if (m_messageFactory.canParse(name, uri, attributes))
61
+ m_state = AtMessage;
62
+ else
63
+ m_state = AtUnknown;
64
+ }
65
+ if (m_state == AtDelayed)
66
+ m_delayedFactory.handleStartElement(name, uri, attributes);
67
+ else if (m_state == AtMessage)
68
+ m_messageFactory.handleStartElement(name, uri, attributes);
69
+}
70
+
71
+void ForwardedFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
72
+{
73
+ if (m_state == AtDelayed)
74
+ m_delayedFactory.handleEndElement(name, uri);
75
+ else if (m_state == AtMessage)
76
+ m_messageFactory.handleEndElement(name, uri);
77
+
78
+ if (m_depth == 2) {
79
+ if (m_state == AtDelayed) {
80
+ m_forwarded->setTime(m_delayedFactory.createPayload().staticCast<DelayedDelivery>());
81
+ } else if (m_state == AtMessage) {
82
+ Stanza::Ptr message = m_messageFactory.createStanza();
83
+ m_forwarded->setMessage(*message.staticCast<Message>().data());
84
+ }
85
+ m_state = AtUnknown;
86
+ }
87
+ --m_depth;
88
+}
89
+
90
+void ForwardedFactory::handleCharacterData(const QStringRef &text)
91
+{
92
+ if (m_state == AtDelayed)
93
+ m_delayedFactory.handleCharacterData(text);
94
+ else if (m_state == AtMessage)
95
+ m_messageFactory.handleCharacterData(text);
96
+}
97
+
98
+void ForwardedFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
99
+{
100
+ Forwarded *forwarded = payload_cast<Forwarded*>(extension);
101
+ writer->writeStartElement(QLatin1String("forwarded"));
102
+ writer->writeDefaultNamespace(NS_FORWARDED);
103
+ if (forwarded->time())
104
+ m_delayedFactory.serialize(forwarded->time().data(), writer);
105
+ Message message = forwarded->message();
106
+ m_messageFactory.serialize(&message, writer);
107
+ writer->writeEndElement();
108
+}
109
+
110
+Payload::Ptr ForwardedFactory::createPayload()
111
+{
112
+ return Payload::Ptr(m_forwarded.take());
113
+}
114
+
115
+} // namespace Jreen
116
libjreen-1.1.0.tar.bz2/src/forwardedfactory_p.h
Added
65
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_FORWARDEDFACTORY_P_H
28
+#define JREEN_FORWARDEDFACTORY_P_H
29
+
30
+#include "forwarded.h"
31
+#include "messagefactory_p.h"
32
+#include "delayeddeliveryfactory_p.h"
33
+
34
+namespace Jreen
35
+{
36
+
37
+class JREEN_AUTOTEST_EXPORT ForwardedFactory : public PayloadFactory<Forwarded>
38
+{
39
+public:
40
+ ForwardedFactory(Client *client);
41
+
42
+ QStringList features() const;
43
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
44
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
45
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
46
+ void handleCharacterData(const QStringRef &text);
47
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
48
+ Payload::Ptr createPayload();
49
+
50
+private:
51
+ enum State {
52
+ AtUnknown,
53
+ AtDelayed,
54
+ AtMessage
55
+ } m_state;
56
+ int m_depth;
57
+ MessageFactory m_messageFactory;
58
+ DelayedDeliveryFactory m_delayedFactory;
59
+ QScopedPointer<Forwarded> m_forwarded;
60
+};
61
+
62
+} // namespace Jreen
63
+
64
+#endif // JREEN_FORWARDEDFACTORY_P_H
65
libjreen-1.0.3.tar.bz2/src/iq_p.h -> libjreen-1.1.0.tar.bz2/src/iq_p.h
Changed
12
1
2
class IQPrivate : public StanzaPrivate
3
{
4
public:
5
- IQPrivate() : StanzaPrivate(StanzaIq), accepted(false), connection(false) {}
6
+ IQPrivate()
7
+ : StanzaPrivate(StanzaIq), subtype(IQ::Invalid),
8
+ accepted(false), connection(false) {}
9
IQ::Type subtype;
10
mutable bool accepted;
11
bool connection;
12
libjreen-1.0.3.tar.bz2/src/iqfactory.cpp -> libjreen-1.1.0.tar.bz2/src/iqfactory.cpp
Changed
78
1
2
{
3
IqFactory::IqFactory(Client *client) : StanzaFactory(client)
4
{
5
- m_depth = 0;
6
}
7
8
int IqFactory::stanzaType()
9
10
11
Stanza::Ptr IqFactory::createStanza()
12
{
13
- IQPrivate *p = new IQPrivate;
14
- p->from = m_from;
15
- p->to = m_to;
16
- p->id = m_id;
17
- p->subtype = m_type;
18
- return Stanza::Ptr(new IQ(*p));
19
+ return Stanza::Ptr(new IQ(*static_cast<IQPrivate*>(m_stanza.take())));
20
}
21
22
void IqFactory::serialize(Stanza *stanza, QXmlStreamWriter *writer)
23
{
24
+ if (!StanzaPrivate::get(*stanza)->tokens.isEmpty()) {
25
+ StanzaFactory::serialize(stanza, writer);
26
+ return;
27
+ }
28
IQ *iq = static_cast<IQ*>(stanza);
29
if (iq->subtype() == IQ::Invalid)
30
return;
31
32
33
void IqFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
34
{
35
- Q_UNUSED(name);
36
- Q_UNUSED(uri);
37
m_depth++;
38
+ if (m_depth == 1)
39
+ m_stanza.reset(new IQPrivate);
40
+ StanzaFactory::handleStartElement(name, uri, attributes);
41
if (m_depth == 1) {
42
- parseAttributes(attributes);
43
+ IQPrivate *p = static_cast<IQPrivate*>(m_stanza.data());
44
QStringRef type = attributes.value(QLatin1String("type"));
45
if (type == QLatin1String("get"))
46
- m_type = IQ::Get;
47
+ p->subtype = IQ::Get;
48
else if (type == QLatin1String("set"))
49
- m_type = IQ::Set;
50
+ p->subtype = IQ::Set;
51
else if (type == QLatin1String("result"))
52
- m_type = IQ::Result;
53
+ p->subtype = IQ::Result;
54
else if (type == QLatin1String("error"))
55
- m_type = IQ::Error;
56
+ p->subtype = IQ::Error;
57
else
58
- m_type = IQ::Invalid;
59
+ p->subtype = IQ::Invalid;
60
}
61
}
62
63
void IqFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
64
{
65
+ StanzaFactory::handleEndElement(name, uri);
66
m_depth--;
67
- Q_UNUSED(name);
68
- Q_UNUSED(uri);
69
}
70
71
void IqFactory::handleCharacterData(const QStringRef &name)
72
{
73
- Q_UNUSED(name);
74
+ StanzaFactory::handleCharacterData(name);
75
}
76
77
}
78
libjreen-1.0.3.tar.bz2/src/iqfactory_p.h -> libjreen-1.1.0.tar.bz2/src/iqfactory_p.h
Changed
20
1
2
3
namespace Jreen
4
{
5
-class IqFactory : public StanzaFactory
6
+class JREEN_AUTOTEST_EXPORT IqFactory : public StanzaFactory
7
{
8
public:
9
IqFactory(Client *client);
10
11
void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
12
void handleEndElement(const QStringRef &name, const QStringRef &uri);
13
void handleCharacterData(const QStringRef &name);
14
-private:
15
- int m_depth;
16
- IQ::Type m_type;
17
};
18
}
19
20
libjreen-1.0.3.tar.bz2/src/jreen.h -> libjreen-1.1.0.tar.bz2/src/jreen.h
Changed
24
1
2
# include <QtCore/QXmlStreamWriter> //needed on OS X (10.5) for QXmlStreamWriter typedef
3
4
# ifndef J_BUILD_STATIC
5
+# ifdef J_BUILD_INTERNAL
6
+# ifdef J_BUILD_LIBRARY
7
+# define JREEN_AUTOTEST_EXPORT Q_DECL_EXPORT
8
+# else
9
+# define JREEN_AUTOTEST_EXPORT Q_DECL_IMPORT
10
+# endif
11
+# endif
12
# ifdef J_BUILD_LIBRARY
13
# define JREEN_EXPORT Q_DECL_EXPORT
14
# else
15
# define JREEN_EXPORT Q_DECL_IMPORT
16
# endif
17
# endif
18
+# ifndef JREEN_AUTOTEST_EXPORT
19
+# define JREEN_AUTOTEST_EXPORT
20
+# endif
21
# ifndef JREEN_EXPORT
22
# define JREEN_EXPORT
23
# endif
24
libjreen-1.0.3.tar.bz2/src/jstrings.h -> libjreen-1.1.0.tar.bz2/src/jstrings.h
Changed
28
1
2
return -1;
3
}
4
5
-template<typename T, int N, typename X>
6
-Q_INLINE_TEMPLATE int strToFlag(const T &str, const char *(&strings)N)
7
+template<typename X, typename T, int N>
8
+Q_INLINE_TEMPLATE X strToFlag(const T &str, const char *(&strings)N)
9
{
10
return static_cast<X>(strToFlag(str,strings));
11
}
12
13
template<int N>
14
-Q_INLINE_TEMPLATE QString flagToStr(int i, const char *(&strings)N)
15
+Q_INLINE_TEMPLATE QString flagToStr(uint i, const char *(&strings)N)
16
{
17
- int n=1;
18
- while(n < i)
19
- n <<= 1;
20
- if(n<0 || n>=N)
21
+ uint n = 1;
22
+ while ((1 << n) < i && n < N)
23
+ ++n;
24
+ if (n >= N)
25
return QString();
26
return QLatin1String(stringsn);
27
}
28
libjreen-1.0.3.tar.bz2/src/logger.cpp -> libjreen-1.1.0.tar.bz2/src/logger.cpp
Changed
29
1
2
/****************************************************************************
3
**
4
-** qutIM - instant messenger
5
+** Jreen
6
**
7
** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
8
**
9
*****************************************************************************
10
**
11
-** $QUTIM_BEGIN_LICENSE$
12
+** $JREEN_BEGIN_LICENSE$
13
** This program is free software: you can redistribute it and/or modify
14
** it under the terms of the GNU General Public License as published by
15
-** the Free Software Foundation, either version 3 of the License, or
16
+** the Free Software Foundation, either version 2 of the License, or
17
** (at your option) any later version.
18
**
19
** This program is distributed in the hope that it will be useful,
20
21
**
22
** You should have received a copy of the GNU General Public License
23
** along with this program. If not, see http://www.gnu.org/licenses/.
24
-** $QUTIM_END_LICENSE$
25
+** $JREEN_END_LICENSE$
26
**
27
****************************************************************************/
28
29
libjreen-1.0.3.tar.bz2/src/logger.h -> libjreen-1.1.0.tar.bz2/src/logger.h
Changed
29
1
2
/****************************************************************************
3
**
4
-** qutIM - instant messenger
5
+** Jreen
6
**
7
** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
8
**
9
*****************************************************************************
10
**
11
-** $QUTIM_BEGIN_LICENSE$
12
+** $JREEN_BEGIN_LICENSE$
13
** This program is free software: you can redistribute it and/or modify
14
** it under the terms of the GNU General Public License as published by
15
-** the Free Software Foundation, either version 3 of the License, or
16
+** the Free Software Foundation, either version 2 of the License, or
17
** (at your option) any later version.
18
**
19
** This program is distributed in the hope that it will be useful,
20
21
**
22
** You should have received a copy of the GNU General Public License
23
** along with this program. If not, see http://www.gnu.org/licenses/.
24
-** $QUTIM_END_LICENSE$
25
+** $JREEN_END_LICENSE$
26
**
27
****************************************************************************/
28
29
libjreen-1.0.3.tar.bz2/src/message.cpp -> libjreen-1.1.0.tar.bz2/src/message.cpp
Changed
15
1
2
namespace Jreen
3
{
4
5
+Message::Message(Message::Type type)
6
+ : Stanza(*new MessagePrivate)
7
+{
8
+ Q_D(Message);
9
+ d->subtype = type;
10
+}
11
+
12
Message::Message(Type type, const JID& to, const QString &body, const QString &subject, const QString &thread, const QString &xmllang)
13
: Stanza(*new MessagePrivate)
14
{
15
libjreen-1.0.3.tar.bz2/src/message.h -> libjreen-1.1.0.tar.bz2/src/message.h
Changed
9
1
2
Normal, /**< A normal message. */
3
Invalid /**< The message stanza is invalid. */
4
};
5
+ Message(Type type = Invalid);
6
Message(Type type, const JID& to, const QString &body = QString(), const QString &subject = QString(),
7
const QString &thread = QString(), const QString &xmllang = QString());
8
Message(MessagePrivate &p);
9
libjreen-1.0.3.tar.bz2/src/message_p.h -> libjreen-1.1.0.tar.bz2/src/message_p.h
Changed
21
1
2
****************************************************************************/
3
#ifndef MESSAGE_P_H
4
#define MESSAGE_P_H
5
+
6
#include "stanza_p.h"
7
#include "langmap.h"
8
+#include "message.h"
9
10
namespace Jreen
11
{
12
13
class MessagePrivate : public StanzaPrivate
14
{
15
public:
16
- MessagePrivate() : StanzaPrivate(StanzaMessage) {}
17
+ MessagePrivate() : StanzaPrivate(StanzaMessage), subtype(Message::Normal) {}
18
Message::Type subtype;
19
LangMap body;
20
LangMap subject;
21
libjreen-1.0.3.tar.bz2/src/messagefactory.cpp -> libjreen-1.1.0.tar.bz2/src/messagefactory.cpp
Changed
125
1
2
namespace Jreen {
3
4
static const char *message_types = {
5
- "chat",
6
- "error",
7
- "groupchat",
8
- "headline"
9
+ "chat",
10
+ "error",
11
+ "groupchat",
12
+ "headline",
13
+ "normal"
14
};
15
16
MessageFactory::MessageFactory(Client *client) :
17
- StanzaFactory(client),
18
- m_depth(0)
19
+ StanzaFactory(client), m_state(AtMessage)
20
{
21
- clear();
22
-}
23
-
24
-void MessageFactory::clear()
25
-{
26
- m_body.clear();
27
- m_subject.clear();
28
- m_thread.clear();
29
- m_subtype = Message::Normal;
30
- m_state = AtMessage;
31
}
32
33
int MessageFactory::stanzaType()
34
35
36
Stanza::Ptr MessageFactory::createStanza()
37
{
38
- MessagePrivate *p = new MessagePrivate;
39
- p->from = m_from;
40
- p->to = m_to;
41
- p->id = m_id;
42
- p->body = m_body;
43
- p->subject = m_subject;
44
- p->subtype = m_subtype;
45
- p->thread = m_thread.toString();
46
- return Stanza::Ptr(new Message(*p));
47
+ return Stanza::Ptr(new Message(*static_cast<MessagePrivate*>(m_stanza.take())));
48
}
49
50
void MessageFactory::serialize(Stanza *stanza, QXmlStreamWriter *writer)
51
{
52
+ if (!StanzaPrivate::get(*stanza)->tokens.isEmpty()) {
53
+ StanzaFactory::serialize(stanza, writer);
54
+ return;
55
+ }
56
Message *message = static_cast<Message*>(stanza);
57
if (message->subtype() == Message::Invalid)
58
return;
59
60
- QString subtype = enumToStr(message->subtype(),message_types);
61
+ QLatin1String subtype = enumToStr(message->subtype(),message_types);
62
63
writer->writeStartElement(QLatin1String("message"));
64
writeAttributes(stanza, writer);
65
- writer->writeAttribute(QLatin1String("type"),subtype);
66
+ if (subtype != QLatin1String(""))
67
+ writer->writeAttribute(QLatin1String("type"), subtype);
68
writeLangMap(QLatin1String("subject"),message->subject(),writer);
69
writeLangMap(QLatin1String("body"),message->body(),writer);
70
if(!message->thread().isEmpty())
71
72
void MessageFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
73
const QXmlStreamAttributes &attributes)
74
{
75
- Q_UNUSED(uri);
76
m_depth++;
77
+ if (m_depth == 1)
78
+ m_stanza.reset(new MessagePrivate);
79
+ StanzaFactory::handleStartElement(name, uri, attributes);
80
if (m_depth == 1) {
81
- clear();
82
- parseAttributes(attributes);
83
+ m_state = AtMessage;
84
+ MessagePrivate *p = static_cast<MessagePrivate*>(m_stanza.data());
85
QStringRef subtype = attributes.value(QLatin1String("type"));
86
- m_subtype = strToEnum<Message::Type>(subtype,message_types);
87
+ if (subtype.isEmpty())
88
+ p->subtype = Message::Normal;
89
+ else
90
+ p->subtype = strToEnum<Message::Type>(subtype, message_types);
91
+ if (p->subtype < 0)
92
+ p->subtype = Message::Invalid;
93
} else if(m_depth == 2) {
94
if(name == QLatin1String("body"))
95
m_state = AtBody;
96
97
98
void MessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
99
{
100
- Q_UNUSED(name);
101
- Q_UNUSED(uri);
102
+ StanzaFactory::handleEndElement(name, uri);
103
if (m_depth == 2)
104
m_state = AtMessage;
105
m_depth--;
106
107
108
void MessageFactory::handleCharacterData(const QStringRef &name)
109
{
110
+ StanzaFactory::handleCharacterData(name);
111
if(m_depth == 2) {
112
+ MessagePrivate *p = static_cast<MessagePrivate*>(m_stanza.data());
113
if(m_state == AtBody)
114
- m_body = name.toString();
115
+ p->body = name.toString();
116
else if(m_state == AtSubject)
117
- m_subject = name.toString();
118
+ p->subject = name.toString();
119
else if(m_state == AtThread)
120
- m_thread = name;
121
+ p->thread = name.toString();
122
}
123
}
124
125
libjreen-1.0.3.tar.bz2/src/messagefactory_p.h -> libjreen-1.1.0.tar.bz2/src/messagefactory_p.h
Changed
24
1
2
3
namespace Jreen
4
{
5
-class MessageFactory : public StanzaFactory
6
+class JREEN_AUTOTEST_EXPORT MessageFactory : public StanzaFactory
7
{
8
public:
9
enum State { AtMessage, AtBody, AtSubject,AtThread };
10
11
void handleEndElement(const QStringRef &name, const QStringRef &uri);
12
void handleCharacterData(const QStringRef &name);
13
private:
14
- void clear();
15
- int m_depth;
16
- Message::Type m_subtype;
17
- LangMap m_body;
18
- LangMap m_subject;
19
State m_state;
20
- QStringRef m_thread;
21
};
22
23
} // namespace Jreen
24
libjreen-1.0.3.tar.bz2/src/messagesession.cpp -> libjreen-1.1.0.tar.bz2/src/messagesession.cpp
Changed
33
1
2
{
3
Q_D(MessageSessionManager);
4
d->client = client;
5
- d->sessionHandlers.resize(Message::Invalid);
6
+ d->sessionHandlers.resize(Message::Invalid + 1);
7
qsrand(QDateTime::currentDateTime().toTime_t());
8
connect(client, SIGNAL(messageReceived(Jreen::Message)),
9
this, SLOT(handleMessage(Jreen::Message)));
10
11
12
void MessageSessionManager::registerMessageSessionHandler(MessageSessionHandler *handler, QList<Message::Type> types)
13
{
14
- for(int i = 0; i < types.size(); i++)
15
- d_func()->sessionHandlersi = handler;
16
+ for (int i = 0; i < types.size(); i++) {
17
+ Q_ASSERT(types.at(i) >= 0 && types.at(i) <= Message::Invalid);
18
+ d_func()->sessionHandlerstypes.at(i) = handler;
19
+ }
20
}
21
22
void MessageSessionManager::removeMessageSessionHandler(MessageSessionHandler *handler)
23
{
24
Q_D(MessageSessionManager);
25
- for(int i = 0; i < d->sessionHandlers.size(); i++)
26
+ for (int i = 0; i < d->sessionHandlers.size(); i++) {
27
if(d->sessionHandlersi == handler)
28
d->sessionHandlersi = 0;
29
+ }
30
}
31
32
MessageSession *MessageSessionManager::session(const JID &jid, Message::Type type, bool create)
33
libjreen-1.0.3.tar.bz2/src/messagesession.h -> libjreen-1.1.0.tar.bz2/src/messagesession.h
Changed
32
1
2
class MessageSessionManager;
3
class Client;
4
5
-#define J_MESSAGE_FILTER \
6
- public: \
7
- static const Jreen::MessageFilterMeta &meta() \
8
+#define J_MESSAGE_FILTER(Class) \
9
+ public: \
10
+ typedef QSharedPointer<Class> Ptr; \
11
+ static int staticFilterType() \
12
{ \
13
- static Jreen::MessageFilterMeta staticFilterMeta; \
14
- return staticFilterMeta; \
15
+ static QBasicAtomicInt filterType = Q_BASIC_ATOMIC_INITIALIZER(0); \
16
+ if (!filterType) { \
17
+ filterType = Jreen::Payload::registerPayloadType( #Class ); \
18
+ Class *useFullNameWithNamespaces = reinterpret_cast< ::Class* >(0); \
19
+ Q_UNUSED(useFullNameWithNamespaces); \
20
+ } \
21
+ return filterType; \
22
+ } \
23
+ virtual int filterType() const \
24
+ { \
25
+ Q_UNUSED(static_cast<const ::Class*>(this)); \
26
+ return staticFilterType(); \
27
} \
28
- virtual int filterType() const { return meta().type; } \
29
private:
30
31
struct MessageFilterMeta
32
libjreen-1.1.0.tar.bz2/src/metacontacts.cpp
Added
32
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "metacontacts_p.h"
28
+
29
+namespace Jreen {
30
+
31
+} // namespace Jreen
32
libjreen-1.1.0.tar.bz2/src/metacontacts_p.h
Added
48
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_METACONTACTS_P_H
28
+#define JREEN_METACONTACTS_P_H
29
+
30
+#include "metacontactstorage.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class JREEN_AUTOTEST_EXPORT MetaContacts : public Payload
36
+{
37
+ J_PAYLOAD(Jreen::MetaContacts)
38
+public:
39
+ MetaContacts(MetaContactStorage::ItemList items) : items(items) {}
40
+ MetaContacts() {}
41
+
42
+ MetaContactStorage::ItemList items;
43
+};
44
+
45
+} // namespace Jreen
46
+
47
+#endif // JREEN_METACONTACTS_P_H
48
libjreen-1.1.0.tar.bz2/src/metacontactsfactory.cpp
Added
108
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "metacontactsfactory_p.h"
28
+#include <QStringList>
29
+#define NS_METACONTACTS QLatin1String("storage:metacontacts")
30
+
31
+namespace Jreen {
32
+
33
+MetaContactsFactory::MetaContactsFactory()
34
+{
35
+ m_depth = 0;
36
+}
37
+
38
+MetaContactsFactory::~MetaContactsFactory()
39
+{
40
+}
41
+
42
+QStringList MetaContactsFactory::features() const
43
+{
44
+ return QStringList(NS_METACONTACTS);
45
+}
46
+
47
+bool MetaContactsFactory::canParse(const QStringRef &name, const QStringRef &uri,
48
+ const QXmlStreamAttributes &attributes)
49
+{
50
+ Q_UNUSED(attributes);
51
+ return name == QLatin1String("storage") && uri == NS_METACONTACTS;
52
+}
53
+
54
+void MetaContactsFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
55
+ const QXmlStreamAttributes &attributes)
56
+{
57
+ Q_UNUSED(uri);
58
+ m_depth++;
59
+ if(m_depth == 1) {
60
+ m_metacontacts.reset(new MetaContacts);
61
+ } else if (m_depth == 2 && name == QLatin1String("meta")) {
62
+ Jreen::MetaContactStorage::Item item;
63
+ item.setJID(attributes.value(QLatin1String("jid")).toString());
64
+ item.setTag(attributes.value(QLatin1String("tag")).toString());
65
+ QString orderStr = attributes.value(QLatin1String("order")).toString();
66
+ bool ok = true;
67
+ uint order = orderStr.toUInt(&ok);
68
+ if (ok)
69
+ item.setOrder(order);
70
+ m_metacontacts->items << item;
71
+ }
72
+}
73
+
74
+void MetaContactsFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
75
+{
76
+ Q_UNUSED(name);
77
+ Q_UNUSED(uri);
78
+ m_depth--;
79
+}
80
+
81
+void MetaContactsFactory::handleCharacterData(const QStringRef &text)
82
+{
83
+ Q_UNUSED(text);
84
+}
85
+
86
+void MetaContactsFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
87
+{
88
+ MetaContacts *metacontacts = se_cast<MetaContacts*>(extension);
89
+ writer->writeStartElement(QLatin1String("storage"));
90
+ writer->writeDefaultNamespace(NS_METACONTACTS);
91
+ foreach (const MetaContactStorage::Item &item, metacontacts->items) {
92
+ writer->writeStartElement(QLatin1String("meta"));
93
+ writer->writeAttribute(QLatin1String("jid"), item.jid().full());
94
+ writer->writeAttribute(QLatin1String("tag"), item.tag());
95
+ if (item.hasOrder())
96
+ writer->writeAttribute(QLatin1String("order"), QString::number(item.order()));
97
+ writer->writeEndElement();
98
+ }
99
+ writer->writeEndElement();
100
+}
101
+
102
+Payload::Ptr MetaContactsFactory::createPayload()
103
+{
104
+ return Payload::Ptr(m_metacontacts.take());
105
+}
106
+
107
+} // namespace Jreen
108
libjreen-1.1.0.tar.bz2/src/metacontactsfactory_p.h
Added
54
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_METACONTACTSFACTORY_P_H
28
+#define JREEN_METACONTACTSFACTORY_P_H
29
+
30
+#include "metacontacts_p.h"
31
+
32
+namespace Jreen {
33
+
34
+class JREEN_AUTOTEST_EXPORT MetaContactsFactory : public PayloadFactory<MetaContacts>
35
+{
36
+public:
37
+ MetaContactsFactory();
38
+ ~MetaContactsFactory();
39
+ QStringList features() const;
40
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
41
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
42
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
43
+ void handleCharacterData(const QStringRef &text);
44
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
45
+ Payload::Ptr createPayload();
46
+private:
47
+ int m_depth;
48
+ QScopedPointer<MetaContacts> m_metacontacts;
49
+};
50
+
51
+} // namespace Jreen
52
+
53
+#endif // JREEN_METACONTACTSFACTORY_P_H
54
libjreen-1.1.0.tar.bz2/src/metacontactstorage.cpp
Added
173
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "metacontactstorage.h"
28
+#include "metacontacts_p.h"
29
+#include "logger.h"
30
+#include "client.h"
31
+
32
+namespace Jreen {
33
+
34
+class MetaContactStorage::ItemData : public QSharedData
35
+{
36
+public:
37
+ ItemData() : order(-1) {}
38
+ ItemData(const ItemData &o)
39
+ : QSharedData(o), jid(o.jid), tag(o.tag), order(o.order) {}
40
+
41
+ JID jid;
42
+ QString tag;
43
+ qint64 order;
44
+};
45
+
46
+MetaContactStorage::Item::Item() : d(new ItemData)
47
+{
48
+}
49
+
50
+MetaContactStorage::Item::Item(const JID &jid, const QString &tag) : d(new MetaContactStorage::ItemData)
51
+{
52
+ d->jid = jid;
53
+ d->tag = tag;
54
+}
55
+
56
+MetaContactStorage::Item::Item(const JID &jid, const QString &tag, uint order) : d(new MetaContactStorage::ItemData)
57
+{
58
+ d->jid = jid;
59
+ d->tag = tag;
60
+ d->order = order;
61
+}
62
+
63
+MetaContactStorage::Item::Item(const MetaContactStorage::Item &item) : d(item.d)
64
+{
65
+}
66
+
67
+MetaContactStorage::Item &MetaContactStorage::Item::operator =(const MetaContactStorage::Item &item)
68
+{
69
+ d = item.d;
70
+ return *this;
71
+}
72
+
73
+MetaContactStorage::Item::~Item()
74
+{
75
+}
76
+
77
+JID MetaContactStorage::Item::jid() const
78
+{
79
+ return d->jid;
80
+}
81
+
82
+void MetaContactStorage::Item::setJID(const JID &jid)
83
+{
84
+ d->jid = jid;
85
+}
86
+
87
+QString MetaContactStorage::Item::tag() const
88
+{
89
+ return d->tag;
90
+}
91
+
92
+void MetaContactStorage::Item::setTag(const QString &tag)
93
+{
94
+ d->tag = tag;
95
+}
96
+
97
+uint MetaContactStorage::Item::order() const
98
+{
99
+ return uint(d->order);
100
+}
101
+
102
+bool MetaContactStorage::Item::hasOrder() const
103
+{
104
+ return d->order >= 0;
105
+}
106
+
107
+void MetaContactStorage::Item::clearOrder()
108
+{
109
+ d->order = -1;
110
+}
111
+
112
+void MetaContactStorage::Item::setOrder(uint order)
113
+{
114
+ d->order = order;
115
+}
116
+
117
+class MetaContactStoragePrivate
118
+{
119
+public:
120
+ Client *client;
121
+ QWeakPointer<PrivateXml> privateXml;
122
+};
123
+
124
+MetaContactStorage::MetaContactStorage(Client *client) :
125
+ QObject(client), d_ptr(new MetaContactStoragePrivate)
126
+{
127
+ Q_D(MetaContactStorage);
128
+ d->client = client;
129
+}
130
+
131
+MetaContactStorage::~MetaContactStorage()
132
+{
133
+}
134
+
135
+void MetaContactStorage::setPrivateXml(PrivateXml *privateXml)
136
+{
137
+ d_func()->privateXml = privateXml;
138
+}
139
+
140
+void MetaContactStorage::requestMetaContacts()
141
+{
142
+ Q_D(MetaContactStorage);
143
+ if (!d->privateXml)
144
+ return;
145
+ d->privateXml.data()->request(QLatin1String("storage"), QLatin1String("storage:metacontacts"), this,
146
+ SLOT(onResultReady(Jreen::Payload::Ptr,Jreen::PrivateXml::Result,Jreen::Error::Ptr)));
147
+}
148
+
149
+void MetaContactStorage::storeMetaContacts(const MetaContactStorage::ItemList &items)
150
+{
151
+ Q_D(MetaContactStorage);
152
+ if (!d->privateXml)
153
+ return;
154
+ d->privateXml.data()->store(MetaContacts::Ptr(new MetaContacts(items)), this,
155
+ SLOT(onResultReady(Jreen::Payload::Ptr,Jreen::PrivateXml::Result,Jreen::Error::Ptr)));
156
+}
157
+
158
+void MetaContactStorage::onResultReady(const Payload::Ptr &payload, PrivateXml::Result result, const Error::Ptr &error)
159
+{
160
+ Q_UNUSED(error);
161
+ Logger::debug() << "onResultReady";
162
+ if(result == PrivateXml::RequestOk) {
163
+ MetaContacts *metacontacts = payload_cast<MetaContacts*>(payload.data());
164
+ Logger::debug() << "received metacontacts" << metacontacts << payload.data();
165
+ if (metacontacts)
166
+ emit metaContactsReceived(metacontacts->items);
167
+ else
168
+ emit metaContactsReceived(ItemList());
169
+ }
170
+}
171
+
172
+} // namespace Jreen
173
libjreen-1.1.0.tar.bz2/src/metacontactstorage.h
Added
90
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_METACONTACTSTORAGE_H
28
+#define JREEN_METACONTACTSTORAGE_H
29
+
30
+#include "jid.h"
31
+#include "privatexml.h"
32
+#include "error.h"
33
+
34
+namespace Jreen
35
+{
36
+
37
+class MetaContactStoragePrivate;
38
+
39
+class JREEN_EXPORT MetaContactStorage : public QObject
40
+{
41
+ Q_OBJECT
42
+ Q_DECLARE_PRIVATE(MetaContactStorage)
43
+public:
44
+ class ItemData;
45
+ class Item
46
+ {
47
+ public:
48
+ Item();
49
+ Item(const JID &jid, const QString &tag);
50
+ Item(const JID &jid, const QString &tag, uint order);
51
+ Item(const Item &item);
52
+ Item &operator =(const Item &item);
53
+ ~Item();
54
+
55
+ JID jid() const;
56
+ void setJID(const JID &jid);
57
+ QString tag() const;
58
+ void setTag(const QString &tag);
59
+ uint order() const;
60
+ bool hasOrder() const;
61
+ void clearOrder();
62
+ void setOrder(uint order);
63
+
64
+ private:
65
+ QSharedDataPointer<ItemData> d;
66
+ };
67
+ typedef QList<Item> ItemList;
68
+
69
+ MetaContactStorage(Client *client);
70
+ ~MetaContactStorage();
71
+
72
+ void setPrivateXml(PrivateXml *privateXml);
73
+
74
+ void requestMetaContacts();
75
+ void storeMetaContacts(const ItemList &items);
76
+
77
+signals:
78
+ void metaContactsReceived(const Jreen::MetaContactStorage::ItemList &items);
79
+
80
+private slots:
81
+ void onResultReady(const Jreen::Payload::Ptr &,Jreen::PrivateXml::Result,const Jreen::Error::Ptr &);
82
+
83
+private:
84
+ QScopedPointer<MetaContactStoragePrivate> d_ptr;
85
+};
86
+
87
+} // namespace Jreen
88
+
89
+#endif // JREEN_METACONTACTSTORAGE_H
90
libjreen-1.0.3.tar.bz2/src/moodfactory_p.h -> libjreen-1.1.0.tar.bz2/src/moodfactory_p.h
Changed
10
1
2
3
namespace Jreen {
4
5
-class MoodFactory : public PayloadFactory<Mood>
6
+class JREEN_AUTOTEST_EXPORT MoodFactory : public PayloadFactory<Mood>
7
{
8
public:
9
MoodFactory();
10
libjreen-1.0.3.tar.bz2/src/mucroom.cpp -> libjreen-1.1.0.tar.bz2/src/mucroom.cpp
Changed
30
1
2
Q_Q(MUCRoom);
3
Logger::debug() << "handle presence" << pres.from();
4
if (Error::Ptr e = pres.payload<Error>()) {
5
+ startedJoining = false;
6
emit q->error(e);
7
return;
8
}
9
10
void MUCRoom::join(Presence::Type type, const QString &message, int priority)
11
{
12
Q_D(MUCRoom);
13
- if (!isJoined()) {
14
- d->startedJoining = true;
15
- }
16
+ if (d->startedJoining)
17
+ return;
18
+ d->startedJoining = true;
19
Presence pres(type, d->jid, message, priority);
20
MUCRoomQuery *query = new MUCRoomQuery(d->password);
21
query->setMaxChars(d->maxChars);
22
23
void MUCRoom::onDisconnected()
24
{
25
Q_D(MUCRoom);
26
+ d->startedJoining = false;
27
if (d->currentPresence.subtype() != Presence::Unavailable) {
28
d->participantsHash.clear();
29
d->isJoined = false;
30
libjreen-1.0.3.tar.bz2/src/mucroom_p.h -> libjreen-1.1.0.tar.bz2/src/mucroom_p.h
Changed
10
1
2
int m_maxStanzas;
3
int m_seconds;
4
QDateTime m_since;
5
- friend class MUCRoomQueryFactory;
6
+ friend class JREEN_AUTOTEST_EXPORT MUCRoomQueryFactory;
7
};
8
9
class MUCRoomItem
10
libjreen-1.0.3.tar.bz2/src/mucroomfactory_p.h -> libjreen-1.1.0.tar.bz2/src/mucroomfactory_p.h
Changed
46
1
2
3
namespace Jreen
4
{
5
-class MUCRoomQueryFactory : public PayloadFactory<MUCRoomQuery>
6
+class JREEN_AUTOTEST_EXPORT MUCRoomQueryFactory : public PayloadFactory<MUCRoomQuery>
7
{
8
public:
9
MUCRoomQueryFactory();
10
11
Payload::Ptr createPayload();
12
};
13
14
-class MUCRoomItemFactory : public XmlStreamFactory<MUCRoomItem>
15
+class JREEN_AUTOTEST_EXPORT MUCRoomItemFactory : public XmlStreamFactory<MUCRoomItem>
16
{
17
public:
18
MUCRoomItemFactory();
19
20
QScopedPointer<MUCRoomItem> m_item;
21
};
22
23
-class MUCRoomUserQueryFactory : public PayloadFactory<MUCRoomUserQuery>
24
+class JREEN_AUTOTEST_EXPORT MUCRoomUserQueryFactory : public PayloadFactory<MUCRoomUserQuery>
25
{
26
public:
27
MUCRoomUserQueryFactory();
28
29
State m_state;
30
};
31
32
-class MUCRoomAdminQueryFactory : public PayloadFactory<MUCRoomAdminQuery>
33
+class JREEN_AUTOTEST_EXPORT MUCRoomAdminQueryFactory : public PayloadFactory<MUCRoomAdminQuery>
34
{
35
public:
36
MUCRoomAdminQueryFactory();
37
38
QScopedPointer<MUCRoomAdminQuery> m_query;
39
};
40
41
-class MUCRoomOwnerQueryFactory : public PayloadFactory<MUCRoomOwnerQuery>
42
+class JREEN_AUTOTEST_EXPORT MUCRoomOwnerQueryFactory : public PayloadFactory<MUCRoomOwnerQuery>
43
{
44
public:
45
MUCRoomOwnerQueryFactory();
46
libjreen-1.0.3.tar.bz2/src/nicknamefactory.cpp -> libjreen-1.1.0.tar.bz2/src/nicknamefactory.cpp
Changed
10
1
2
3
namespace Jreen {
4
5
-class NicknameFactoryPrivate
6
+class JREEN_AUTOTEST_EXPORT NicknameFactoryPrivate
7
{
8
public:
9
QString nickname;
10
libjreen-1.0.3.tar.bz2/src/nicknamefactory_p.h -> libjreen-1.1.0.tar.bz2/src/nicknamefactory_p.h
Changed
12
1
2
3
namespace Jreen {
4
5
-class NicknameFactoryPrivate;
6
-class NicknameFactory : public PayloadFactory<Nickname>
7
+class JREEN_AUTOTEST_EXPORT NicknameFactoryPrivate;
8
+class JREEN_AUTOTEST_EXPORT NicknameFactory : public PayloadFactory<Nickname>
9
{
10
Q_DECLARE_PRIVATE(NicknameFactory)
11
public:
12
libjreen-1.0.3.tar.bz2/src/nonsaslauth.cpp -> libjreen-1.1.0.tar.bz2/src/nonsaslauth.cpp
Changed
19
1
2
#include "client.h"
3
#include "jstrings.h"
4
5
+#define NS_IQ_AUTH QLatin1String("http://jabber.org/features/iq-auth")
6
+
7
namespace Jreen
8
{
9
10
11
{
12
Q_UNUSED(uri);
13
Q_UNUSED(attributes);
14
- return name == QLatin1String("auth") && uri == QLatin1String("http://jabber.org/features/iq-auth");
15
+ return name == QLatin1String("auth") && uri == NS_IQ_AUTH;
16
}
17
18
void NonSaslAuth::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
19
libjreen-1.0.3.tar.bz2/src/parser.cpp -> libjreen-1.1.0.tar.bz2/src/parser.cpp
Changed
126
1
2
d->parsers.clear();
3
foreach (StreamFeature *feature, d->client->features)
4
feature->reset();
5
- d->extensions.clear();
6
+}
7
+
8
+static Client::Feature convertToFeature(int type)
9
+{
10
+ switch (type) {
11
+ case StreamFeature::CompressionLayer:
12
+ return Client::Compression;
13
+ case StreamFeature::SecurityLayer:
14
+ return Client::Encryption;
15
+ case StreamFeature::SASL:
16
+ case StreamFeature::SimpleAuthorization:
17
+ return Client::Authorization;
18
+ default:
19
+ return Client::InvalidFeature;
20
+ }
21
+}
22
+
23
+static Client::DisconnectReason convertToReason(Client::Feature feature)
24
+{
25
+ switch (feature) {
26
+ case Client::Encryption:
27
+ return Client::NoEncryptionSupport;
28
+ case Client::Compression:
29
+ return Client::NoCompressionSupport;
30
+ case Client::Authorization:
31
+ return Client::NoAuthorizationSupport;
32
+ default:
33
+ return Client::NoSupportedFeature;
34
+ }
35
+}
36
+
37
+static bool checkFeature(ClientPrivate *client, Client::Feature feature)
38
+{
39
+ if (client->configsfeature == Client::Force
40
+ && !(client->usedFeatures & (1 << feature))) {
41
+ client->emitDisconnected(convertToReason(feature));
42
+ return false;
43
+ }
44
+ return true;
45
}
46
47
void Parser::activateFeature()
48
49
Q_D(Parser);
50
int i = d->client->features.indexOf(d->client->current_stream_feature) + 1;
51
d->client->current_stream_feature = 0;
52
+ bool foundAny = false;
53
for (; i < d->client->features.size(); i++) {
54
StreamFeature *feature = d->client->features.at(i);
55
- if (feature->isActivatable()) {
56
- d->client->current_stream_feature = feature;
57
- feature->activate();
58
- break;
59
+ if (!feature->isActivatable())
60
+ continue;
61
+ Client::Feature clientFeature = convertToFeature(feature->type());
62
+ Client::FeatureConfig config = d->client->configs.value(clientFeature, Client::Auto);
63
+ if (config == Client::Disable)
64
+ continue;
65
+ if (clientFeature == Client::InvalidFeature
66
+ && (!checkFeature(d->client, Client::Encryption)
67
+ || !checkFeature(d->client, Client::Compression)
68
+ || !checkFeature(d->client, Client::Authorization))) {
69
+ return;
70
+ }
71
+ if (clientFeature == Client::Authorization
72
+ && !checkFeature(d->client, Client::Encryption)) {
73
+ return;
74
}
75
+ d->client->current_stream_feature = feature;
76
+ foundAny = true;
77
+ feature->activate();
78
+ if (clientFeature != Client::InvalidFeature)
79
+ d->client->usedFeatures |= (1 << clientFeature);
80
+ break;
81
}
82
+ if (!foundAny)
83
+ d->client->emitDisconnected(Client::NoSupportedFeature);
84
}
85
86
#define XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
87
88
if (feature->canParse(name, uri, attributes))
89
d->parsers.append(feature);
90
}
91
- } else if (d->state == ReadStanza && d->depth == 2) {
92
- foreach (AbstractPayloadFactory *factory, d->client->factories) {
93
- if (factory->canParse(name, uri, attributes))
94
- d->parsers.append(factory);
95
- }
96
}
97
foreach (XmlStreamParser *parser, d->parsers)
98
parser->handleStartElement(name, uri, attributes);
99
100
for (int i = 0; i < d->parsers.size(); i++) {
101
XmlStreamParser *parser = d->parsers.at(i);
102
parser->handleEndElement(name, uri);
103
- if (d->depth == 2 && d->state == ReadStanza && i > d->parsersCount.at(1)) {
104
- Payload::Ptr se;
105
- se = static_cast<AbstractPayloadFactory*>(parser)->createPayload();
106
- d->extensions.append(se);
107
- }
108
}
109
#ifdef PARSER_DEBUG_SPEED
110
d->parsingTime += counter.elapsed();
111
112
} else if (d->state == ReadStanza) {
113
StanzaFactory *factory = static_cast<StanzaFactory*>(d->parsers.top());
114
Stanza::Ptr stanza = factory->createStanza();
115
- foreach (const Payload::Ptr &se, d->extensions)
116
- stanza->addExtension(se);
117
#ifdef PARSER_DEBUG_SPEED
118
d->parsingTime += counter.elapsed();
119
counter.restart();
120
#endif
121
d->client->handleStanza(stanza);
122
- d->extensions.clear();
123
#ifdef PARSER_DEBUG_SPEED
124
d->stanzaLogicTimefactory->stanzaType() += counter.elapsed();
125
#endif
126
libjreen-1.0.3.tar.bz2/src/parser_p.h -> libjreen-1.1.0.tar.bz2/src/parser_p.h
Changed
9
1
2
Parser::State state;
3
QStack<XmlStreamParser*> parsers;
4
QStack<int> parsersCount;
5
- QList<Payload::Ptr> extensions;
6
QByteArray buffer;
7
int depth;
8
bool atParsing;
9
libjreen-1.1.0.tar.bz2/src/pgpencrypted.cpp
Added
58
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "pgpencrypted.h"
28
+
29
+namespace Jreen
30
+{
31
+
32
+class PGPEncryptedPrivate
33
+{
34
+public:
35
+ QString encryptedText;
36
+};
37
+
38
+PGPEncrypted::PGPEncrypted(const QString &encryptedText) : d_ptr(new PGPEncryptedPrivate)
39
+{
40
+ d_func()->encryptedText = encryptedText;
41
+}
42
+
43
+PGPEncrypted::~PGPEncrypted()
44
+{
45
+}
46
+
47
+QString PGPEncrypted::encryptedText() const
48
+{
49
+ return d_func()->encryptedText;
50
+}
51
+
52
+void PGPEncrypted::setEncryptedText(const QString &encryptedText)
53
+{
54
+ d_func()->encryptedText = encryptedText;
55
+}
56
+
57
+} // namespace Jreen
58
libjreen-1.1.0.tar.bz2/src/pgpencrypted.h
Added
54
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_PGPENCRYPTED_H
28
+#define JREEN_PGPENCRYPTED_H
29
+
30
+#include "stanzaextension.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class PGPEncryptedPrivate;
36
+
37
+class JREEN_EXPORT PGPEncrypted : public Payload
38
+{
39
+ J_PAYLOAD(Jreen::PGPEncrypted)
40
+ Q_DECLARE_PRIVATE(PGPEncrypted)
41
+public:
42
+ PGPEncrypted(const QString &encryptedText = QString());
43
+ ~PGPEncrypted();
44
+
45
+ QString encryptedText() const;
46
+ void setEncryptedText(const QString &encryptedText);
47
+
48
+private:
49
+ QScopedPointer<PGPEncryptedPrivate> d_ptr;
50
+};
51
+} // namespace Jreen
52
+
53
+#endif // JREEN_PGPENCRYPTED_H
54
libjreen-1.1.0.tar.bz2/src/pgpfactory.cpp
Added
143
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "pgpfactory_p.h"
28
+#include <QStringList>
29
+
30
+#define NS_SIGNED QLatin1String("jabber:x:signed")
31
+#define NS_ENCRYPTED QLatin1String("jabber:x:encrypted")
32
+
33
+namespace Jreen
34
+{
35
+
36
+PGPSignedFactory::PGPSignedFactory() : m_depth(0)
37
+{
38
+}
39
+
40
+QStringList PGPSignedFactory::features() const
41
+{
42
+ return QStringList(NS_SIGNED);
43
+}
44
+
45
+bool PGPSignedFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
46
+{
47
+ Q_UNUSED(attributes);
48
+ return name == QLatin1String("x") && uri == NS_SIGNED;
49
+}
50
+
51
+void PGPSignedFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
52
+{
53
+ Q_UNUSED(name);
54
+ Q_UNUSED(uri);
55
+ Q_UNUSED(attributes);
56
+ m_depth++;
57
+ if (m_depth == 1)
58
+ m_query.reset(new PGPSigned);
59
+}
60
+
61
+void PGPSignedFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
62
+{
63
+ Q_UNUSED(name);
64
+ Q_UNUSED(uri);
65
+ --m_depth;
66
+}
67
+
68
+void PGPSignedFactory::handleCharacterData(const QStringRef &text)
69
+{
70
+ Q_UNUSED(text);
71
+ if (m_depth == 1)
72
+ m_query->setSignature(text.toString());
73
+}
74
+
75
+void PGPSignedFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
76
+{
77
+ PGPSigned *query = payload_cast<PGPSigned*>(extension);
78
+ writer->writeStartElement(QLatin1String("x"));
79
+ writer->writeDefaultNamespace(NS_SIGNED);
80
+ writer->writeCharacters(query->signature());
81
+ writer->writeEndElement();
82
+}
83
+
84
+Payload::Ptr PGPSignedFactory::createPayload()
85
+{
86
+ return Payload::Ptr(m_query.take());
87
+}
88
+
89
+PGPEncryptedFactory::PGPEncryptedFactory() : m_depth(0)
90
+{
91
+}
92
+
93
+QStringList PGPEncryptedFactory::features() const
94
+{
95
+ return QStringList(NS_ENCRYPTED);
96
+}
97
+
98
+bool PGPEncryptedFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
99
+{
100
+ Q_UNUSED(attributes);
101
+ return name == QLatin1String("x") && uri == NS_ENCRYPTED;
102
+}
103
+
104
+void PGPEncryptedFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
105
+{
106
+ Q_UNUSED(name);
107
+ Q_UNUSED(uri);
108
+ Q_UNUSED(attributes);
109
+ m_depth++;
110
+ if (m_depth == 1)
111
+ m_query.reset(new PGPEncrypted);
112
+}
113
+
114
+void PGPEncryptedFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
115
+{
116
+ Q_UNUSED(name);
117
+ Q_UNUSED(uri);
118
+ --m_depth;
119
+}
120
+
121
+void PGPEncryptedFactory::handleCharacterData(const QStringRef &text)
122
+{
123
+ Q_UNUSED(text);
124
+ if (m_depth == 1)
125
+ m_query->setEncryptedText(text.toString());
126
+}
127
+
128
+void PGPEncryptedFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
129
+{
130
+ PGPEncrypted *query = payload_cast<PGPEncrypted*>(extension);
131
+ writer->writeStartElement(QLatin1String("x"));
132
+ writer->writeDefaultNamespace(NS_ENCRYPTED);
133
+ writer->writeCharacters(query->encryptedText());
134
+ writer->writeEndElement();
135
+}
136
+
137
+Payload::Ptr PGPEncryptedFactory::createPayload()
138
+{
139
+ return Payload::Ptr(m_query.take());
140
+}
141
+
142
+} // namespace Jreen
143
libjreen-1.1.0.tar.bz2/src/pgpfactory_p.h
Added
70
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_PGPFACTORY_H
28
+#define JREEN_PGPFACTORY_H
29
+
30
+#include "pgpsigned.h"
31
+#include "pgpencrypted.h"
32
+
33
+namespace Jreen {
34
+
35
+class JREEN_AUTOTEST_EXPORT PGPSignedFactory : public PayloadFactory<PGPSigned>
36
+{
37
+public:
38
+ PGPSignedFactory();
39
+ QStringList features() const;
40
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
41
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
42
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
43
+ void handleCharacterData(const QStringRef &text);
44
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
45
+ Payload::Ptr createPayload();
46
+private:
47
+ int m_depth;
48
+ QScopedPointer<PGPSigned> m_query;
49
+};
50
+
51
+class JREEN_AUTOTEST_EXPORT PGPEncryptedFactory : public PayloadFactory<PGPEncrypted>
52
+{
53
+public:
54
+ PGPEncryptedFactory();
55
+ QStringList features() const;
56
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
57
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
58
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
59
+ void handleCharacterData(const QStringRef &text);
60
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
61
+ Payload::Ptr createPayload();
62
+private:
63
+ int m_depth;
64
+ QScopedPointer<PGPEncrypted> m_query;
65
+};
66
+
67
+} // namespace Jreen
68
+
69
+#endif // JREEN_PGPFACTORY_H
70
libjreen-1.1.0.tar.bz2/src/pgpsigned.cpp
Added
58
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "pgpsigned.h"
28
+
29
+namespace Jreen
30
+{
31
+
32
+class PGPSignedPrivate
33
+{
34
+public:
35
+ QString signature;
36
+};
37
+
38
+PGPSigned::PGPSigned(const QString &signature) : d_ptr(new PGPSignedPrivate)
39
+{
40
+ d_func()->signature = signature;
41
+}
42
+
43
+PGPSigned::~PGPSigned()
44
+{
45
+}
46
+
47
+QString PGPSigned::signature() const
48
+{
49
+ return d_func()->signature;
50
+}
51
+
52
+void PGPSigned::setSignature(const QString &signature)
53
+{
54
+ d_func()->signature = signature;
55
+}
56
+
57
+} // namespace Jreen
58
libjreen-1.1.0.tar.bz2/src/pgpsigned.h
Added
55
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_PGPSIGNED_H
28
+#define JREEN_PGPSIGNED_H
29
+
30
+#include "stanzaextension.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class PGPSignedPrivate;
36
+
37
+class JREEN_EXPORT PGPSigned : public Payload
38
+{
39
+ J_PAYLOAD(Jreen::PGPSigned)
40
+ Q_DECLARE_PRIVATE(PGPSigned)
41
+public:
42
+ PGPSigned(const QString &signature = QString());
43
+ ~PGPSigned();
44
+
45
+ QString signature() const;
46
+ void setSignature(const QString &signature);
47
+
48
+private:
49
+ QScopedPointer<PGPSignedPrivate> d_ptr;
50
+};
51
+
52
+} // namespace Jreen
53
+
54
+#endif // JREEN_PGPSIGNED_H
55
libjreen-1.0.3.tar.bz2/src/pingfactory_p.h -> libjreen-1.1.0.tar.bz2/src/pingfactory_p.h
Changed
10
1
2
namespace Jreen {
3
4
//overkill
5
-class PingFactory : public PayloadFactory<Ping>
6
+class JREEN_AUTOTEST_EXPORT PingFactory : public PayloadFactory<Ping>
7
{
8
public:
9
PingFactory();
10
libjreen-1.0.3.tar.bz2/src/presence_p.h -> libjreen-1.1.0.tar.bz2/src/presence_p.h
Changed
13
1
2
class PresencePrivate : public StanzaPrivate
3
{
4
public:
5
- PresencePrivate() : StanzaPrivate(StanzaPresence) {}
6
+ PresencePrivate()
7
+ : StanzaPrivate(StanzaPresence),
8
+ subtype(Presence::Available),
9
+ priority(0) {}
10
Presence::Type subtype;
11
LangMap status;
12
int priority;
13
libjreen-1.0.3.tar.bz2/src/presencefactory.cpp -> libjreen-1.1.0.tar.bz2/src/presencefactory.cpp
Changed
137
1
2
3
PresenceFactory::PresenceFactory(Client *client) : StanzaFactory(client)
4
{
5
- m_depth = 0;
6
m_state = AtNowhere;
7
- clear();
8
-}
9
-
10
-void PresenceFactory::clear()
11
-{
12
- m_status.clear();
13
- m_priority = 0;
14
- m_subtype = Presence::Available;
15
}
16
17
int PresenceFactory::stanzaType()
18
19
20
Stanza::Ptr PresenceFactory::createStanza()
21
{
22
- PresencePrivate *p = new PresencePrivate;
23
- p->from = m_from;
24
- p->to = m_to;
25
- p->id = m_id;
26
- p->subtype = m_subtype;
27
- p->status = m_status;
28
- p->priority = m_priority;
29
- return Stanza::Ptr(new Presence(*p));
30
+ return Stanza::Ptr(new Presence(*static_cast<PresencePrivate*>(m_stanza.take())));
31
}
32
33
void PresenceFactory::serialize(Stanza *stanza, QXmlStreamWriter *writer)
34
{
35
+ if (!StanzaPrivate::get(*stanza)->tokens.isEmpty()) {
36
+ StanzaFactory::serialize(stanza, writer);
37
+ return;
38
+ }
39
Presence *presence = static_cast<Presence*>(stanza);
40
if(presence->subtype() == Presence::Invalid)
41
return;
42
43
44
void PresenceFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
45
{
46
- Q_UNUSED(uri);
47
m_depth++;
48
+ if (m_depth == 1)
49
+ m_stanza.reset(new PresencePrivate);
50
+ StanzaFactory::handleStartElement(name, uri, attributes);
51
+ PresencePrivate *p = static_cast<PresencePrivate*>(m_stanza.data());
52
if (m_depth == 1) {
53
- clear();
54
- parseAttributes(attributes);
55
QStringRef type = attributes.value(QLatin1String("type"));
56
if (type == QLatin1String("unavailable"))
57
- m_subtype = Presence::Unavailable;
58
+ p->subtype = Presence::Unavailable;
59
else if (type == QLatin1String("probe"))
60
- m_subtype = Presence::Probe;
61
+ p->subtype = Presence::Probe;
62
else if (type == QLatin1String("subscribe"))
63
- m_subtype = Presence::Subscribe;
64
+ p->subtype = Presence::Subscribe;
65
else if (type == QLatin1String("unsubscribe"))
66
- m_subtype = Presence::Unsubscribe;
67
+ p->subtype = Presence::Unsubscribe;
68
else if (type == QLatin1String("subscribed"))
69
- m_subtype = Presence::Subscribe;
70
+ p->subtype = Presence::Subscribe;
71
else if (type == QLatin1String("unsubscribed"))
72
- m_subtype = Presence::Unsubscribe;
73
+ p->subtype = Presence::Unsubscribe;
74
else if (type == QLatin1String("error"))
75
- m_subtype = Presence::Error;
76
+ p->subtype = Presence::Error;
77
else
78
- m_subtype = Presence::Available;
79
+ p->subtype = Presence::Available;
80
} else if(m_depth == 2) {
81
if(name == QLatin1String("show"))
82
m_state = AtShow;
83
84
}
85
else if(name == QLatin1String("status")) {
86
m_state = AtStatus;
87
- m_xmllang = attributes.value(QLatin1String("xml:lang"));
88
+ m_xmllang = attributes.value(QLatin1String("xml:lang")).toString();
89
}
90
}
91
}
92
93
void PresenceFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
94
{
95
+ StanzaFactory::handleEndElement(name, uri);
96
if (m_depth == 2)
97
m_state = AtNowhere;
98
m_depth--;
99
- Q_UNUSED(name);
100
- Q_UNUSED(uri);
101
}
102
103
void PresenceFactory::handleCharacterData(const QStringRef &text)
104
{
105
+ StanzaFactory::handleCharacterData(text);
106
if(m_depth == 2) {
107
+ PresencePrivate *p = static_cast<PresencePrivate*>(m_stanza.data());
108
if(m_state == AtShow) {
109
-/* if(text == QLatin1String("available"))
110
- m_type = Presence::Available;
111
- else if(text == QLatin1String("unavailable"))
112
- m_type = Presence::Unavailable;
113
- else */if(text == QLatin1String("away"))
114
- m_subtype = Presence::Away;
115
+ if(text == QLatin1String("away"))
116
+ p->subtype = Presence::Away;
117
else if(text == QLatin1String("chat"))
118
- m_subtype = Presence::Chat;
119
+ p->subtype = Presence::Chat;
120
else if(text == QLatin1String("dnd"))
121
- m_subtype = Presence::DND;
122
+ p->subtype = Presence::DND;
123
else if(text == QLatin1String("xa"))
124
- m_subtype = Presence::XA;
125
+ p->subtype = Presence::XA;
126
}
127
else if(m_state == AtPriority) {
128
- m_priority = text.toString().toInt();
129
+ p->priority = text.toString().toInt();
130
}
131
else if(m_state == AtStatus) {
132
- m_statusm_xmllang.toString() = text.toString();
133
+ p->statusm_xmllang = text.toString();
134
}
135
}
136
}
137
libjreen-1.0.3.tar.bz2/src/presencefactory_p.h -> libjreen-1.1.0.tar.bz2/src/presencefactory_p.h
Changed
25
1
2
3
namespace Jreen
4
{
5
-class PresenceFactory : public StanzaFactory
6
+class JREEN_AUTOTEST_EXPORT PresenceFactory : public StanzaFactory
7
{
8
public:
9
enum State { AtNowhere, AtShow, AtStatus,AtPriority };
10
11
void handleEndElement(const QStringRef &name, const QStringRef &uri);
12
void handleCharacterData(const QStringRef &name);
13
private:
14
- void clear();
15
- int m_depth;
16
- Presence::Type m_subtype;
17
- int m_priority;
18
- LangMap m_status;
19
State m_state;
20
- QStringRef m_xmllang;
21
+ QString m_xmllang;
22
};
23
}
24
25
libjreen-1.0.3.tar.bz2/src/privacyqueryfactory_p.h -> libjreen-1.1.0.tar.bz2/src/privacyqueryfactory_p.h
Changed
10
1
2
3
namespace Jreen
4
{
5
-class PrivacyQueryFactory : public PayloadFactory<PrivacyQuery>
6
+class JREEN_AUTOTEST_EXPORT PrivacyQueryFactory : public PayloadFactory<PrivacyQuery>
7
{
8
public:
9
PrivacyQueryFactory();
10
libjreen-1.0.3.tar.bz2/src/privatexml_p.h -> libjreen-1.1.0.tar.bz2/src/privatexml_p.h
Changed
10
1
2
Type m_type;
3
};
4
5
-class PrivateXmlQueryFactory : public PayloadFactory<PrivateXmlQuery>
6
+class JREEN_AUTOTEST_EXPORT PrivateXmlQueryFactory : public PayloadFactory<PrivateXmlQuery>
7
{
8
public:
9
PrivateXmlQueryFactory(Client *client);
10
libjreen-1.0.3.tar.bz2/src/pubsubeventfactory_p.h -> libjreen-1.1.0.tar.bz2/src/pubsubeventfactory_p.h
Changed
10
1
2
{
3
namespace PubSub
4
{
5
-class EventFactory : public PayloadFactory<Event>
6
+class JREEN_AUTOTEST_EXPORT EventFactory : public PayloadFactory<Event>
7
{
8
public:
9
EventFactory(QList<AbstractPayloadFactory*> &factories);
10
libjreen-1.0.3.tar.bz2/src/pubsubpublishfactory.cpp -> libjreen-1.1.0.tar.bz2/src/pubsubpublishfactory.cpp
Changed
27
1
2
PublishFactory::PublishFactory(QList<AbstractPayloadFactory*> &factories) : m_factories(factories)
3
{
4
m_depth = 0;
5
+ m_factory = 0;
6
m_state = AtNowhere;
7
}
8
9
10
if (m_depth == 1) {
11
m_publish.reset(new Publish);
12
} if (m_depth == 2 && name == QLatin1String("publish")) {
13
- findFactory(attributes.value(QLatin1String("node")));
14
+ m_factory = findFactory(attributes.value(QLatin1String("node")));
15
m_state = m_factory ? AtPublish : AtNowhere;
16
} else if (m_depth == 3 && m_state == AtPublish && name == QLatin1String("item")) {
17
m_state = AtItem;
18
19
Logger::warning() << "Invalid stanza extension at PubSub::Publish";
20
return;
21
}
22
- writer->writeStartElement(QLatin1String("pusbsub"));
23
+ writer->writeStartElement(QLatin1String("pubsub"));
24
writer->writeDefaultNamespace(NS_PUBSUB);
25
writer->writeStartElement(QLatin1String("publish"));
26
writer->writeAttribute(QLatin1String("node"), node);
27
libjreen-1.0.3.tar.bz2/src/pubsubpublishfactory_p.h -> libjreen-1.1.0.tar.bz2/src/pubsubpublishfactory_p.h
Changed
10
1
2
{
3
namespace PubSub
4
{
5
-class PublishFactory : public PayloadFactory<Publish>
6
+class JREEN_AUTOTEST_EXPORT PublishFactory : public PayloadFactory<Publish>
7
{
8
public:
9
PublishFactory(QList<AbstractPayloadFactory*> &factories);
10
libjreen-1.0.3.tar.bz2/src/receiptfactory.cpp -> libjreen-1.1.0.tar.bz2/src/receiptfactory.cpp
Changed
10
1
2
3
static const char *receipt_strings = {"request","received"};
4
5
-class ReceiptFactoryPrivate
6
+class JREEN_AUTOTEST_EXPORT ReceiptFactoryPrivate
7
{
8
public:
9
Receipt::Type type;
10
libjreen-1.0.3.tar.bz2/src/receiptfactory_p.h -> libjreen-1.1.0.tar.bz2/src/receiptfactory_p.h
Changed
12
1
2
3
namespace Jreen {
4
5
-class ReceiptFactoryPrivate;
6
-class ReceiptFactory : public PayloadFactory<Receipt>
7
+class JREEN_AUTOTEST_EXPORT ReceiptFactoryPrivate;
8
+class JREEN_AUTOTEST_EXPORT ReceiptFactory : public PayloadFactory<Receipt>
9
{
10
Q_DECLARE_PRIVATE(ReceiptFactory)
11
public:
12
libjreen-1.1.0.tar.bz2/src/registrationfeature.cpp
Added
87
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "registrationfeature_p.h"
28
+#include "registrationmanager_p.h"
29
+
30
+namespace Jreen
31
+{
32
+
33
+#define NS_REGISTER QLatin1String("http://jabber.org/features/iq-register")
34
+
35
+RegistrationFeature::RegistrationFeature(RegistrationManager *manager)
36
+ : StreamFeature(RegistrationRequest), m_manager(manager), m_activatable(false)
37
+{
38
+}
39
+
40
+int RegistrationFeature::priority()
41
+{
42
+ return 10;
43
+}
44
+
45
+bool RegistrationFeature::isActivatable()
46
+{
47
+ return m_activatable;
48
+}
49
+
50
+bool RegistrationFeature::activate()
51
+{
52
+ RegistrationManagerPrivate::get(m_manager)->handleConnection();
53
+ return true;
54
+}
55
+
56
+void RegistrationFeature::reset()
57
+{
58
+ m_activatable = false;
59
+}
60
+
61
+bool RegistrationFeature::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
62
+{
63
+ Q_UNUSED(attributes);
64
+ return name == QLatin1String("register") && uri == NS_REGISTER;
65
+}
66
+
67
+void RegistrationFeature::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
68
+{
69
+ Q_UNUSED(uri);
70
+ Q_UNUSED(attributes);
71
+ if (name == QLatin1String("register"))
72
+ m_activatable = true;
73
+}
74
+
75
+void RegistrationFeature::handleEndElement(const QStringRef &name, const QStringRef &uri)
76
+{
77
+ Q_UNUSED(name);
78
+ Q_UNUSED(uri);
79
+}
80
+
81
+void RegistrationFeature::handleCharacterData(const QStringRef &text)
82
+{
83
+ Q_UNUSED(text);
84
+}
85
+
86
+} // namespace Jreen
87
libjreen-1.1.0.tar.bz2/src/registrationfeature_p.h
Added
59
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_REGISTRATIONFEATURE_P_H
28
+#define JREEN_REGISTRATIONFEATURE_P_H
29
+
30
+#include "streamfeature_p.h"
31
+
32
+namespace Jreen
33
+{
34
+
35
+class RegistrationManager;
36
+
37
+class RegistrationFeature : public StreamFeature
38
+{
39
+public:
40
+ RegistrationFeature(RegistrationManager *manager);
41
+
42
+ virtual int priority();
43
+ virtual bool isActivatable();
44
+ virtual bool activate();
45
+ virtual void reset();
46
+ virtual bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
47
+ virtual void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
48
+ virtual void handleEndElement(const QStringRef &name, const QStringRef &uri);
49
+ virtual void handleCharacterData(const QStringRef &text);
50
+
51
+private:
52
+ RegistrationManager *m_manager;
53
+ bool m_activatable;
54
+};
55
+
56
+} // namespace Jreen
57
+
58
+#endif // JREEN_REGISTRATIONFEATURE_P_H
59
libjreen-1.1.0.tar.bz2/src/registrationmanager.cpp
Added
268
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "registrationmanager_p.h"
28
+#include "registrationquery_p.h"
29
+#include "registrationfeature_p.h"
30
+#include "iqreply.h"
31
+#include "iq_p.h"
32
+#include "logger.h"
33
+#include <QCoreApplication>
34
+#include <QTimer>
35
+
36
+namespace Jreen
37
+{
38
+
39
+RegistrationData::RegistrationData() : d(new RegistrationDataPrivate)
40
+{
41
+}
42
+
43
+RegistrationData::RegistrationData(const RegistrationData &data) : d(data.d)
44
+{
45
+}
46
+
47
+RegistrationData::RegistrationData(const QSharedDataPointer<RegistrationDataPrivate> &data) : d(data)
48
+{
49
+}
50
+
51
+RegistrationData &RegistrationData::operator =(const RegistrationData &data)
52
+{
53
+ d = data.d;
54
+ return *this;
55
+}
56
+
57
+RegistrationData::~RegistrationData()
58
+{
59
+}
60
+
61
+DataForm::Ptr RegistrationData::form() const
62
+{
63
+ return d->form;
64
+}
65
+
66
+void RegistrationData::setForm(const DataForm::Ptr &form)
67
+{
68
+ d->form = form;
69
+}
70
+
71
+bool RegistrationData::hasForm() const
72
+{
73
+ return !d->form.isNull();
74
+}
75
+
76
+QString RegistrationData::instructions() const
77
+{
78
+ return d->instructions;
79
+}
80
+
81
+QString RegistrationData::fieldValue(FieldType type) const
82
+{
83
+ return d->values.value(type);
84
+}
85
+
86
+// It's not good time for localization support yet
87
+
88
+//const char *registrationTranslations = {
89
+// QT_TRANSLATE_NOOP("Jreen", "Username"),
90
+// QT_TRANSLATE_NOOP("Jreen", "Familiar name of the user"),
91
+// QT_TRANSLATE_NOOP("Jreen", "Password"),
92
+// QT_TRANSLATE_NOOP("Jreen", "Full name"),
93
+// QT_TRANSLATE_NOOP("Jreen", "Given name"),
94
+// QT_TRANSLATE_NOOP("Jreen", "Family name"),
95
+// QT_TRANSLATE_NOOP("Jreen", "Email"),
96
+// QT_TRANSLATE_NOOP("Jreen", "Street"),
97
+// QT_TRANSLATE_NOOP("Jreen", "Locality"),
98
+// QT_TRANSLATE_NOOP("Jreen", "Region"),
99
+// QT_TRANSLATE_NOOP("Jreen", "Postal code"),
100
+// QT_TRANSLATE_NOOP("Jreen", "Phone number"),
101
+// QT_TRANSLATE_NOOP("Jreen", "Web page url"),
102
+// QT_TRANSLATE_NOOP("Jreen", "Birth date")
103
+//};
104
+
105
+//QString RegistrationData::fieldText(RegistrationData::FieldType type) const
106
+//{
107
+// size_t count = sizeof(registrationTranslations) / sizeof(registrationTranslations0);
108
+// if (type >= 0 && type < count)
109
+// return QCoreApplication::translate("Jreen", registrationTranslationstype);
110
+// return QString();
111
+//}
112
+
113
+bool RegistrationData::hasField(RegistrationData::FieldType type) const
114
+{
115
+ return (d->valuesFlags & (1 << type));
116
+}
117
+
118
+bool RegistrationData::hasFields() const
119
+{
120
+ return d->valuesFlags != 0;
121
+}
122
+
123
+void RegistrationData::setFieldValue(RegistrationData::FieldType type, const QString &value)
124
+{
125
+ if (d->values.size() <= type) {
126
+ Logger::warning() << "Unkown RegistrationData::ValueType:" << type;
127
+ return;
128
+ }
129
+ d->valuesFlags |= (1 << type);
130
+ d->valuestype = value;
131
+}
132
+
133
+QList<BitsOfBinary::Ptr> RegistrationData::bitsOfBinaries() const
134
+{
135
+ return d->bobs;
136
+}
137
+
138
+void RegistrationManagerPrivate::requestInfo()
139
+{
140
+ ConnectionIQ iq(IQ::Get, service);
141
+ iq.addPayload(new RegistrationQuery);
142
+ sendIQ(iq, SLOT(_q_form_received(Jreen::IQ)));
143
+}
144
+
145
+void RegistrationManagerPrivate::handleConnection()
146
+{
147
+ waitingForConnection = false;
148
+ while (!iqs.isEmpty()) {
149
+ QPair<IQ, QByteArray> iq = iqs.takeFirst();
150
+ sendIQ(iq.first, iq.second);
151
+ }
152
+ if (!fieldsReceived)
153
+ requestInfo();
154
+}
155
+
156
+void RegistrationManagerPrivate::sendIQ(const IQ &iq, const char *slot)
157
+{
158
+ Q_Q(RegistrationManager);
159
+ if (waitingForConnection) {
160
+ iqs << qMakePair(iq, QByteArray(slot));
161
+ } else {
162
+ IQReply *reply = client->send(iq);
163
+ QObject::connect(reply, SIGNAL(received(Jreen::IQ)),
164
+ q, slot);
165
+ }
166
+}
167
+
168
+void RegistrationManagerPrivate::_q_form_received(const Jreen::IQ &iq)
169
+{
170
+ Q_Q(RegistrationManager);
171
+ fieldsReceived = true;
172
+ if (RegistrationQuery::Ptr query = iq.payload<RegistrationQuery>())
173
+ emit q->formReceived(RegistrationData(query->data));
174
+ else
175
+ emit q->error(iq.error());
176
+}
177
+
178
+void RegistrationManagerPrivate::_q_result_received(const Jreen::IQ &iq)
179
+{
180
+ Q_Q(RegistrationManager);
181
+ if (iq.error()) {
182
+ emit q->error(iq.error());
183
+ } else {
184
+ QObject::disconnect(client, 0, q, 0);
185
+ for (int i = 0; i < configs.size(); ++i) {
186
+ Client::Feature feature = static_cast<Client::Feature>(i);
187
+ client->setFeatureConfig(feature, configsi);
188
+ }
189
+ if (feature) {
190
+ client->removeStreamFeature(feature);
191
+ delete feature;
192
+ feature = 0;
193
+ }
194
+ emit q->success();
195
+ }
196
+}
197
+
198
+void RegistrationManagerPrivate::_q_on_disconnect(Client::DisconnectReason reason)
199
+{
200
+ Q_Q(RegistrationManager);
201
+ waitingForConnection = true;
202
+ if (reason == Client::NoSupportedFeature
203
+ || reason == Client::NoEncryptionSupport
204
+ || reason == Client::NoCompressionSupport
205
+ || reason == Client::NoAuthorizationSupport) {
206
+ emit q->unsupported();
207
+ } else {
208
+ QTimer::singleShot(0, client, SLOT(connectToServer()));
209
+ }
210
+}
211
+
212
+RegistrationManager::RegistrationManager(const JID &service, Client *client)
213
+ : QObject(client), d_ptr(new RegistrationManagerPrivate(this))
214
+{
215
+ Q_D(RegistrationManager);
216
+ d->service = service;
217
+ d->client = client;
218
+ d->feature = 0;
219
+}
220
+
221
+RegistrationManager::~RegistrationManager()
222
+{
223
+}
224
+
225
+void RegistrationManager::registerAtServer()
226
+{
227
+ Q_D(RegistrationManager);
228
+ d->fieldsReceived = false;
229
+ d->waitingForConnection = true;
230
+ d->feature = new RegistrationFeature(this);
231
+ connect(d->client, SIGNAL(disconnected(Jreen::Client::DisconnectReason)),
232
+ SLOT(_q_on_disconnect(Jreen::Client::DisconnectReason)));
233
+ d->client->setJID(d->service);
234
+ d->client->registerStreamFeature(d->feature);
235
+ d->configs.resize(3);
236
+ for (int i = 0; i < 3; ++i) {
237
+ Client::Feature feature = static_cast<Client::Feature>(i);
238
+ d->configsi = d->client->featureConfig(feature);
239
+ }
240
+ d->client->setFeatureConfig(Client::Authorization, Client::Disable);
241
+ d->client->connectToServer();
242
+}
243
+
244
+void RegistrationManager::registerAtService()
245
+{
246
+ Q_D(RegistrationManager);
247
+ d->waitingForConnection = false;
248
+ d->requestInfo();
249
+}
250
+
251
+void RegistrationManager::fetchFields()
252
+{
253
+ Q_D(RegistrationManager);
254
+ d->requestInfo();
255
+}
256
+
257
+void RegistrationManager::send(const Jreen::RegistrationData &data)
258
+{
259
+ Q_D(RegistrationManager);
260
+ ConnectionIQ iq(IQ::Set, d->service);
261
+ iq.addPayload(new RegistrationQuery(data));
262
+ d->sendIQ(iq, SLOT(_q_result_received(Jreen::IQ)));
263
+}
264
+
265
+}
266
+
267
+#include "moc_registrationmanager.cpp"
268
libjreen-1.1.0.tar.bz2/src/registrationmanager.h
Added
120
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef REGISTRATIONMANAGER_H
28
+#define REGISTRATIONMANAGER_H
29
+
30
+#include "dataform.h"
31
+#include "error.h"
32
+#include "bitsofbinary.h"
33
+#include "iq.h"
34
+
35
+namespace Jreen
36
+{
37
+
38
+class RegistrationManager;
39
+class RegistrationManagerPrivate;
40
+class RegistrationDataPrivate;
41
+
42
+class JREEN_EXPORT RegistrationData
43
+{
44
+public:
45
+ enum FieldType {
46
+ UsernameField,
47
+ NickField,
48
+ PasswordField,
49
+ FullNameField,
50
+ FirstNameField,
51
+ LastNameField,
52
+ EmailField,
53
+ AddressField,
54
+ CityField,
55
+ StateField,
56
+ ZipField,
57
+ PhoneField,
58
+ UrlField,
59
+ DateField,
60
+// MiscField,
61
+// TextField,
62
+// KeyField,
63
+ LastFieldType = DateField
64
+ };
65
+
66
+ RegistrationData();
67
+ RegistrationData(const RegistrationData &data);
68
+ RegistrationData &operator =(const RegistrationData &data);
69
+ ~RegistrationData();
70
+
71
+ DataForm::Ptr form() const;
72
+ void setForm(const DataForm::Ptr &form);
73
+ bool hasForm() const;
74
+ QString instructions() const;
75
+ QString fieldValue(FieldType type) const;
76
+ bool hasField(FieldType type) const;
77
+ bool hasFields() const;
78
+ void setFieldValue(FieldType type, const QString &value);
79
+ QList<Jreen::BitsOfBinary::Ptr> bitsOfBinaries() const;
80
+
81
+private:
82
+ RegistrationData(const QSharedDataPointer<RegistrationDataPrivate> &data);
83
+
84
+ friend class RegistrationManager;
85
+ friend class RegistrationManagerPrivate;
86
+ friend class RegistrationDataPrivate;
87
+ QSharedDataPointer<RegistrationDataPrivate> d;
88
+};
89
+
90
+class JREEN_EXPORT RegistrationManager : public QObject
91
+{
92
+ Q_OBJECT
93
+ Q_DECLARE_PRIVATE(RegistrationManager)
94
+public:
95
+ RegistrationManager(const JID &service, Client *client);
96
+ ~RegistrationManager();
97
+
98
+signals:
99
+ void formReceived(const Jreen::RegistrationData &data);
100
+ void error(const Jreen::Error::Ptr &error);
101
+ void success();
102
+ void unsupported();
103
+
104
+public slots:
105
+ void registerAtServer();
106
+ void registerAtService();
107
+ void fetchFields();
108
+ void send(const Jreen::RegistrationData &data);
109
+
110
+private:
111
+ Q_PRIVATE_SLOT(d_func(), void _q_form_received(const Jreen::IQ &iq))
112
+ Q_PRIVATE_SLOT(d_func(), void _q_result_received(const Jreen::IQ &iq))
113
+ Q_PRIVATE_SLOT(d_func(), void _q_on_disconnect(Jreen::Client::DisconnectReason))
114
+ QScopedPointer<RegistrationManagerPrivate> d_ptr;
115
+};
116
+
117
+}
118
+
119
+#endif // REGISTRATIONMANAGER_H
120
libjreen-1.1.0.tar.bz2/src/registrationmanager_p.h
Added
92
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef REGISTRATIONMANAGER_P_H
28
+#define REGISTRATIONMANAGER_P_H
29
+
30
+#include "registrationmanager.h"
31
+#include "client.h"
32
+#include <QQueue>
33
+
34
+namespace Jreen
35
+{
36
+
37
+class RegistrationFeature;
38
+class RegistrationQuery;
39
+
40
+class RegistrationDataPrivate : public QSharedData
41
+{
42
+public:
43
+ typedef QSharedDataPointer<RegistrationDataPrivate> Ptr;
44
+
45
+ enum Flag {
46
+ Registered = 0x01,
47
+ Remove = 0x02
48
+ };
49
+ Q_DECLARE_FLAGS(Flags, Flag)
50
+
51
+ RegistrationDataPrivate() : valuesFlags(0) { values.resize(RegistrationData::LastFieldType + 1); }
52
+ RegistrationDataPrivate(const RegistrationDataPrivate &o)
53
+ : QSharedData(o), form(o.form), flags(o.flags), instructions(o.instructions),
54
+ valuesFlags(o.valuesFlags), values(o.values), bobs(o.bobs) {}
55
+ static Ptr get(const RegistrationData &data) { return data.d; }
56
+
57
+ DataForm::Ptr form;
58
+ Flags flags;
59
+ QString instructions;
60
+ int valuesFlags;
61
+ QVector<QString> values;
62
+ QList<BitsOfBinary::Ptr> bobs;
63
+};
64
+
65
+class RegistrationManagerPrivate
66
+{
67
+ Q_DECLARE_PUBLIC(RegistrationManager)
68
+public:
69
+ RegistrationManagerPrivate(RegistrationManager *q) : q_ptr(q), fieldsReceived(false), waitingForConnection(true) {}
70
+
71
+ static RegistrationManagerPrivate *get(RegistrationManager *manager) { return manager->d_func(); }
72
+ void requestInfo();
73
+ void handleConnection();
74
+ void sendIQ(const Jreen::IQ &iq, const char *slot);
75
+ void _q_form_received(const Jreen::IQ &iq);
76
+ void _q_result_received(const Jreen::IQ &iq);
77
+ void _q_on_disconnect(Jreen::Client::DisconnectReason reason);
78
+
79
+ RegistrationManager *q_ptr;
80
+ Client *client;
81
+ RegistrationFeature *feature;
82
+ bool fieldsReceived;
83
+ bool waitingForConnection;
84
+ QQueue<QPair<Jreen::IQ, QByteArray> > iqs;
85
+ QVector<Client::FeatureConfig> configs;
86
+ JID service;
87
+};
88
+
89
+}
90
+
91
+#endif // REGISTRATIONMANAGER_P_H
92
libjreen-1.1.0.tar.bz2/src/registrationquery.cpp
Added
41
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "registrationquery_p.h"
28
+#include "registrationmanager_p.h"
29
+
30
+namespace Jreen {
31
+
32
+RegistrationQuery::RegistrationQuery() : data(new RegistrationDataPrivate)
33
+{
34
+}
35
+
36
+RegistrationQuery::RegistrationQuery(const RegistrationData &d) : data(RegistrationDataPrivate::get(d))
37
+{
38
+}
39
+
40
+} // namespace Jreen
41
libjreen-1.1.0.tar.bz2/src/registrationquery_p.h
Added
51
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_REGISTRATIONQUERY_P_H
28
+#define JREEN_REGISTRATIONQUERY_P_H
29
+
30
+#include "stanzaextension.h"
31
+#include "dataform.h"
32
+#include "registrationmanager_p.h"
33
+
34
+namespace Jreen {
35
+
36
+class RegistrationData;
37
+
38
+class RegistrationQuery : public Payload
39
+{
40
+ J_PAYLOAD(Jreen::RegistrationQuery)
41
+public:
42
+ RegistrationQuery();
43
+ RegistrationQuery(const RegistrationData &data);
44
+
45
+ RegistrationDataPrivate::Ptr data;
46
+};
47
+
48
+} // namespace Jreen
49
+
50
+#endif // JREEN_REGISTRATIONQUERY_P_H
51
libjreen-1.1.0.tar.bz2/src/registrationqueryfactory.cpp
Added
161
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#include "registrationqueryfactory_p.h"
28
+#include "jstrings.h"
29
+
30
+#define NS_REGISTER QLatin1String("jabber:iq:register")
31
+
32
+namespace Jreen
33
+{
34
+
35
+const char *emptyNames = {
36
+ "registered",
37
+ "remove"
38
+};
39
+
40
+const char *valueNames = {
41
+ "username",
42
+ "nick",
43
+ "password",
44
+ "name",
45
+ "first",
46
+ "last",
47
+ "email",
48
+ "address",
49
+ "city",
50
+ "state",
51
+ "zip",
52
+ "phone",
53
+ "url",
54
+ "date"
55
+ "misc",
56
+ "text",
57
+ "key"
58
+};
59
+
60
+
61
+RegistrationQueryFactory::RegistrationQueryFactory() : m_state(Nowhere), m_depth(0)
62
+{
63
+}
64
+
65
+QStringList RegistrationQueryFactory::features() const
66
+{
67
+ return QStringList(); // << NS_REGISTER;
68
+}
69
+
70
+bool RegistrationQueryFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
71
+{
72
+ Q_UNUSED(attributes);
73
+ m_state = Nowhere;
74
+ m_depth = 0;
75
+ m_query.reset(new RegistrationQuery);
76
+ return name == QLatin1String("query") && uri == NS_REGISTER;
77
+}
78
+
79
+void RegistrationQueryFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
80
+{
81
+ ++m_depth;
82
+ if (m_depth == 2) {
83
+ if (m_formFactory.canParse(name, uri, attributes)) {
84
+ m_state = AtForm;
85
+ } else if (m_bobFactory.canParse(name, uri, attributes)) {
86
+ m_state = AtBob;
87
+ } else if (name == QLatin1String("instructions")) {
88
+ m_state = AtInstructions;
89
+ } else {
90
+ RegistrationDataPrivate::Flag flag = strToFlag<RegistrationDataPrivate::Flag>(name, emptyNames);
91
+ if (flag != -1) {
92
+ m_query->data->flags |= flag;
93
+ return;
94
+ }
95
+ int index = strToEnum(name, valueNames);
96
+ if (index != -1) {
97
+ m_query->data->valuesFlags |= (1 << index);
98
+ m_state = static_cast<State>(AtValue + index);
99
+ return;
100
+ }
101
+ }
102
+ }
103
+ if (m_state == AtForm)
104
+ m_formFactory.handleStartElement(name, uri, attributes);
105
+ else if (m_state == AtBob)
106
+ m_bobFactory.handleStartElement(name, uri, attributes);
107
+}
108
+
109
+void RegistrationQueryFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
110
+{
111
+ if (m_state == AtForm)
112
+ m_formFactory.handleEndElement(name, uri);
113
+ else if (m_state == AtBob)
114
+ m_bobFactory.handleEndElement(name, uri);
115
+ if (m_depth == 2) {
116
+ if (m_state == AtForm)
117
+ m_query->data->form = m_formFactory.createPayload().staticCast<DataForm>();
118
+ else if (m_state == AtBob)
119
+ m_query->data->bobs << m_bobFactory.createPayload().staticCast<BitsOfBinary>();
120
+ m_state = Nowhere;
121
+ }
122
+ --m_depth;
123
+}
124
+
125
+void RegistrationQueryFactory::handleCharacterData(const QStringRef &text)
126
+{
127
+ if (m_state == AtForm)
128
+ m_formFactory.handleCharacterData(text);
129
+ else if (m_state == AtBob)
130
+ m_bobFactory.handleCharacterData(text);
131
+ else if (m_state == AtInstructions)
132
+ m_query->data->instructions = text.toString();
133
+ else if (m_state >= AtValue)
134
+ m_query->data->valuesm_state - AtValue = text.toString();
135
+}
136
+
137
+void RegistrationQueryFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
138
+{
139
+ RegistrationQuery *query = se_cast<RegistrationQuery*>(extension);
140
+ writer->writeStartElement(QLatin1String("query"));
141
+ writer->writeDefaultNamespace(NS_REGISTER);
142
+ for (uint i = 0; i < sizeof(emptyNames) / sizeof(emptyNames0); ++i) {
143
+ if (query->data->flags & (1 << i))
144
+ writer->writeEmptyElement(QLatin1String(emptyNamesi));
145
+ }
146
+ for (int i = 0; i < query->data->values.size(); ++i) {
147
+ if (query->data->valuesFlags & (1 << i))
148
+ writer->writeTextElement(QLatin1String(valueNamesi), query->data->valuesi);
149
+ }
150
+ if (query->data->form)
151
+ m_formFactory.serialize(query->data->form.data(), writer);
152
+ writer->writeEndElement();
153
+}
154
+
155
+Payload::Ptr RegistrationQueryFactory::createPayload()
156
+{
157
+ return Payload::Ptr(m_query.take());
158
+}
159
+
160
+} // namespace Jreen
161
libjreen-1.1.0.tar.bz2/src/registrationqueryfactory_p.h
Added
65
1
2
+/****************************************************************************
3
+**
4
+** Jreen
5
+**
6
+** Copyright © 2012 Ruslan Nigmatullin <euroelessar@yandex.ru>
7
+**
8
+*****************************************************************************
9
+**
10
+** $JREEN_BEGIN_LICENSE$
11
+** This program is free software: you can redistribute it and/or modify
12
+** it under the terms of the GNU General Public License as published by
13
+** the Free Software Foundation, either version 2 of the License, or
14
+** (at your option) any later version.
15
+**
16
+** This program is distributed in the hope that it will be useful,
17
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
+** See the GNU General Public License for more details.
20
+**
21
+** You should have received a copy of the GNU General Public License
22
+** along with this program. If not, see http://www.gnu.org/licenses/.
23
+** $JREEN_END_LICENSE$
24
+**
25
+****************************************************************************/
26
+
27
+#ifndef JREEN_REGISTRATIONQUERYFACTORY_P_H
28
+#define JREEN_REGISTRATIONQUERYFACTORY_P_H
29
+
30
+#include "registrationquery_p.h"
31
+#include "dataformfactory_p.h"
32
+#include "bitsofbinaryfactory_p.h"
33
+
34
+namespace Jreen
35
+{
36
+
37
+class JREEN_AUTOTEST_EXPORT RegistrationQueryFactory : public PayloadFactory<RegistrationQuery>
38
+{
39
+public:
40
+ RegistrationQueryFactory();
41
+ QStringList features() const;
42
+ bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
43
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
44
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
45
+ void handleCharacterData(const QStringRef &text);
46
+ void serialize(Payload *extension, QXmlStreamWriter *writer);
47
+ Payload::Ptr createPayload();
48
+private:
49
+ enum State {
50
+ Nowhere,
51
+ AtForm,
52
+ AtBob,
53
+ AtInstructions,
54
+ AtValue
55
+ } m_state;
56
+ int m_depth;
57
+ DataFormFactory m_formFactory;
58
+ BitsOfBinaryFactory m_bobFactory;
59
+ QScopedPointer<RegistrationQuery> m_query;
60
+};
61
+
62
+} // namespace Jreen
63
+
64
+#endif // JREEN_REGISTRATIONQUERYFACTORY_P_H
65
libjreen-1.0.3.tar.bz2/src/saslfeature.cpp -> libjreen-1.1.0.tar.bz2/src/saslfeature.cpp
Changed
78
1
2
#include "saslfeature_p.h"
3
#include "client_p.h"
4
#include <QUrl>
5
+#include <QCoreApplication>
6
#include "logger.h"
7
8
#ifdef HAVE_SIMPLESASL
9
# include "../3rdparty/simplesasl/simplesasl.h"
10
#endif
11
12
+#define NS_SASL QLatin1String("urn:ietf:params:xml:ns:xmpp-sasl")
13
+
14
namespace Jreen
15
{
16
17
SASLFeature::SASLFeature() : StreamFeature(SASL)
18
{
19
QCA::init();
20
- QCA::setAppName("qutim");
21
+ QCA::setAppName(QCoreApplication::applicationName());
22
m_depth = 0;
23
m_isSupported = QCA::isSupported("sasl");
24
#ifdef HAVE_SIMPLESASL
25
26
return false;
27
Q_UNUSED(name);
28
Q_UNUSED(attributes);
29
- return uri == QLatin1String("urn:ietf:params:xml:ns:xmpp-sasl");
30
+ return uri == NS_SASL;
31
}
32
33
void SASLFeature::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
34
35
36
void SASLFeature::onClientStarted(bool init, const QByteArray &data)
37
{
38
- QXmlStreamWriter *writer = ClientPrivate::get(m_client)->writer;
39
+ QXmlStreamWriter *writer = m_info->writer();
40
writer->writeStartElement(QLatin1String("auth"));
41
- writer->writeDefaultNamespace(QLatin1String("urn:ietf:params:xml:ns:xmpp-sasl"));
42
+ writer->writeDefaultNamespace(NS_SASL);
43
writer->writeAttribute(QLatin1String("mechanism"), m_sasl->mechanism());
44
if (init)
45
writer->writeCharacters(QString::fromLatin1(data.toBase64()));
46
47
48
void SASLFeature::onNextStep(const QByteArray &data)
49
{
50
- QXmlStreamWriter *writer = ClientPrivate::get(m_client)->writer;
51
+ QXmlStreamWriter *writer = m_info->writer();
52
writer->writeStartElement(QLatin1String("response"));
53
- writer->writeDefaultNamespace(QLatin1String("urn:ietf:params:xml:ns:xmpp-sasl"));
54
+ writer->writeDefaultNamespace(NS_SASL);
55
writer->writeCharacters(QString::fromLatin1(data.toBase64()));
56
writer->writeEndElement();
57
}
58
59
m_sasl->setUsername(m_info->jid().node());
60
if (params.canSendRealm())
61
m_sasl->setRealm(m_info->jid().domain());
62
- if (params.canSendAuthzid() && m_info->jid().domain() != QLatin1String("chat.facebook.com"))
63
- m_sasl->setAuthzid(m_info->jid().bare());
64
+ // ???
65
+ // Why SASL tells me that I can send Authzid?
66
+ /*if (params.canSendAuthzid() && m_info->jid().domain() != QLatin1String("chat.facebook.com"))
67
+ m_sasl->setAuthzid(m_info->jid().bare());*/
68
m_sasl->continueAfterParams();
69
}
70
71
void SASLFeature::onAuthCheck(const QString &user, const QString &authzid)
72
{
73
+ Q_UNUSED(user);
74
+ Q_UNUSED(authzid);
75
m_sasl->continueAfterAuthCheck();
76
}
77
78
libjreen-1.0.3.tar.bz2/src/sessionfeature.cpp -> libjreen-1.1.0.tar.bz2/src/sessionfeature.cpp
Changed
10
1
2
SessionQuery() {}
3
};
4
5
-class SessionQueryFactory : public PayloadFactory<SessionQuery>
6
+class JREEN_AUTOTEST_EXPORT SessionQueryFactory : public PayloadFactory<SessionQuery>
7
{
8
public:
9
SessionQueryFactory() {}
10
libjreen-1.0.3.tar.bz2/src/softwareversionfactory.cpp -> libjreen-1.1.0.tar.bz2/src/softwareversionfactory.cpp
Changed
10
1
2
3
static const char *query_strings = {"name","version","os"};
4
5
-class SoftwareVersionFactoryPrivate
6
+class JREEN_AUTOTEST_EXPORT SoftwareVersionFactoryPrivate
7
{
8
public:
9
int depth;
10
libjreen-1.0.3.tar.bz2/src/softwareversionfactory_p.h -> libjreen-1.1.0.tar.bz2/src/softwareversionfactory_p.h
Changed
12
1
2
3
namespace Jreen {
4
5
-class SoftwareVersionFactoryPrivate;
6
-class SoftwareVersionFactory : public PayloadFactory<SoftwareVersion>
7
+class JREEN_AUTOTEST_EXPORT SoftwareVersionFactoryPrivate;
8
+class JREEN_AUTOTEST_EXPORT SoftwareVersionFactory : public PayloadFactory<SoftwareVersion>
9
{
10
Q_DECLARE_PRIVATE(SoftwareVersionFactory)
11
public:
12
libjreen-1.0.3.tar.bz2/src/stanza.cpp -> libjreen-1.1.0.tar.bz2/src/stanza.cpp
Changed
13
1
2
d_ptr->extensions.clear();
3
}
4
5
+void Stanza::removePayload(int id)
6
+{
7
+ d_ptr->extensions.remove(id);
8
+}
9
+
10
Error::Ptr Stanza::error() const
11
{
12
return payload<Error>();
13
libjreen-1.0.3.tar.bz2/src/stanza.h -> libjreen-1.1.0.tar.bz2/src/stanza.h
Changed
27
1
2
{ addExtension(Payload::Ptr(se)); }
3
PayloadList payloads() const;
4
template< class T >
5
+ QList<typename T::Ptr> payloads() const
6
+ {
7
+ QList<typename T::Ptr> list;
8
+ foreach (const Payload::Ptr &payload, payloads().values(T::staticPayloadType()))
9
+ list << payload.staticCast<T>();
10
+ return list;
11
+ }
12
+ template< class T >
13
inline const QSharedPointer<T> payload() const
14
- { return qSharedPointerCast<T>(payloads().value(reinterpret_cast<T*>(0)->staticPayloadType())); }
15
+ { return qSharedPointerCast<T>(payloads().value(T::staticPayloadType())); }
16
template< class T >
17
inline bool containsPayload() const
18
- { return payloads().contains(reinterpret_cast<T*>(0)->staticPayloadType()); }
19
+ { return payloads().contains(T::staticPayloadType()); }
20
void removePayloads();
21
+ template< class T >
22
+ inline void removePayload() { removePayload(T::staticPayloadType()); }
23
+ void removePayload(int id);
24
Error::Ptr error() const;
25
protected:
26
Stanza(StanzaPrivate &);
27
libjreen-1.0.3.tar.bz2/src/stanza_p.h -> libjreen-1.1.0.tar.bz2/src/stanza_p.h
Changed
59
1
2
StanzaMessage,
3
StanzaSubscription
4
};
5
+ struct Token
6
+ {
7
+ enum Type {
8
+ StartElement,
9
+ EndElement,
10
+ Characters
11
+ };
12
+ Token(Type t) : type(t) {}
13
+
14
+ Type type;
15
+ };
16
+
17
+ struct StartToken : public Token
18
+ {
19
+ StartToken() : Token(StartElement) {}
20
+
21
+ QStringRef name;
22
+ QStringRef uri;
23
+ QXmlStreamAttributes attributes;
24
+ };
25
+
26
+ struct EndToken : public Token
27
+ {
28
+ EndToken() : Token(EndElement) {}
29
+ };
30
+
31
+ struct CharactersToken : public Token
32
+ {
33
+ CharactersToken() : Token(Characters) {}
34
+
35
+ QStringRef text;
36
+ };
37
38
StanzaPrivate(Type t) : type(t)
39
{
40
ref = 1;
41
}
42
+ ~StanzaPrivate()
43
+ {
44
+ qDeleteAll(tokens);
45
+ }
46
+
47
void addExtensions(QXmlStreamWriter *writer) const
48
{
49
Q_UNUSED(writer);
50
51
JID to;
52
QString id;
53
PayloadList extensions;
54
+ QList<Token*> tokens;
55
+ QString buffer;
56
};
57
58
}
59
libjreen-1.0.3.tar.bz2/src/stanzaextension.cpp -> libjreen-1.1.0.tar.bz2/src/stanzaextension.cpp
Changed
35
1
2
{
3
typedef QHash<QByteArray, int> ByteArrayHash;
4
Q_GLOBAL_STATIC(ByteArrayHash, seClassHash)
5
+Q_GLOBAL_STATIC(QVector<QByteArray>, seClassVector)
6
7
Payload::Payload()
8
{
9
10
{
11
QByteArray t = type;
12
int id = seClassHash()->value(t, seClassHash()->size());
13
- if (id == seClassHash()->size())
14
- seClassHash()->insert(t, id);
15
+ if (id == seClassHash()->size()) {
16
+ ByteArrayHash::Iterator it = seClassHash()->insert(t, id);
17
+ seClassVector()->append(it.key());
18
+ }
19
return id;
20
}
21
22
+const char *Payload::payloadName(int type)
23
+{
24
+ return seClassVector()->value(type).constData();
25
+}
26
+
27
+const char *Payload::payloadName() const
28
+{
29
+ return payloadName(payloadType());
30
+}
31
+
32
AbstractPayloadFactory::AbstractPayloadFactory()
33
{
34
}
35
libjreen-1.0.3.tar.bz2/src/stanzaextension.h -> libjreen-1.1.0.tar.bz2/src/stanzaextension.h
Changed
41
1
2
virtual ~Payload();
3
4
static int registerPayloadType(const char *type);
5
+ static const char *payloadName(int type);
6
7
virtual int payloadType() const = 0;
8
+ const char *payloadName() const;
9
};
10
11
typedef QMultiMap<int, Payload::Ptr> PayloadList;
12
13
typedef QMap<int, AbstractPayloadFactory*> PayloadFactoryMap;
14
15
template <typename Extension>
16
-class PayloadFactory : public AbstractPayloadFactory
17
+class JREEN_AUTOTEST_EXPORT PayloadFactory : public AbstractPayloadFactory
18
{
19
Q_DISABLE_COPY(PayloadFactory)
20
public:
21
22
}
23
24
template <typename T>
25
-Q_INLINE_TEMPLATE T se_cast(Payload *se)
26
+Q_INLINE_TEMPLATE T payload_cast(Payload *se)
27
{
28
if (se && reinterpret_cast<T>(0)->staticPayloadType() == se->payloadType())
29
return static_cast<T>(se);
30
return 0;
31
}
32
+
33
+template <typename T>
34
+Q_INLINE_TEMPLATE T se_cast(Payload *se)
35
+{
36
+ return payload_cast<T>(se);
37
+}
38
}
39
40
#define J_PAYLOAD(Class) \
41
libjreen-1.0.3.tar.bz2/src/stanzafactory.cpp -> libjreen-1.1.0.tar.bz2/src/stanzafactory.cpp
Changed
121
1
2
#include "stanzafactory_p.h"
3
#include "client_p.h"
4
#include "logger.h"
5
+#include <QStack>
6
7
namespace Jreen
8
{
9
StanzaFactory::StanzaFactory(Client *client) : m_client(client)
10
{
11
+ m_depth = 0;
12
}
13
14
StanzaFactory::~StanzaFactory()
15
{
16
}
17
18
-void StanzaFactory::parseAttributes(const QXmlStreamAttributes &attributes)
19
+void StanzaFactory::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
20
{
21
- m_from = attributes.value(QLatin1String("from")).toString();
22
- m_to = attributes.value(QLatin1String("to")).toString();
23
- m_id = attributes.value(QLatin1String("id")).toString();
24
+ while (!m_stanza->tokens.isEmpty() && m_stanza->tokens.last()->type == StanzaPrivate::Token::Characters)
25
+ delete m_stanza->tokens.takeLast();
26
+ StanzaPrivate::StartToken *token = new StanzaPrivate::StartToken;
27
+ token->name = name.appendTo(&m_stanza->buffer);
28
+ token->uri = uri.appendTo(&m_stanza->buffer);
29
+ token->attributes = attributes;
30
+ m_stanza->tokens << token;
31
+
32
+ if (m_depth == 1) {
33
+ m_stanza->from = attributes.value(QLatin1String("from")).toString();
34
+ m_stanza->to = attributes.value(QLatin1String("to")).toString();
35
+ m_stanza->id = attributes.value(QLatin1String("id")).toString();
36
+ } else if (m_depth == 2) {
37
+ foreach (AbstractPayloadFactory *factory, ClientPrivate::get(m_client)->factories) {
38
+ if (factory->canParse(name, uri, attributes))
39
+ m_parsers.append(factory);
40
+ }
41
+ }
42
+ for (int i = 0; i < m_parsers.size(); i++)
43
+ m_parsers.at(i)->handleStartElement(name, uri, attributes);
44
+}
45
+
46
+void StanzaFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
47
+{
48
+ for (int i = 0; i < m_parsers.size(); i++)
49
+ m_parsers.at(i)->handleEndElement(name, uri);
50
+ m_stanza->tokens << new StanzaPrivate::EndToken;
51
+ if (m_depth == 2) {
52
+ for (int i = 0; i < m_parsers.size(); i++) {
53
+ AbstractPayloadFactory *parser = static_cast<AbstractPayloadFactory*>(m_parsers.at(i));
54
+ Payload::Ptr payload = parser->createPayload();
55
+ if (payload.isNull())
56
+ qFatal("Payload is null from %s", Payload::payloadName(parser->payloadType()));
57
+ m_stanza->extensions.insert(payload->payloadType(), payload);
58
+ }
59
+ m_parsers.clear();
60
+ }
61
+}
62
+
63
+void StanzaFactory::handleCharacterData(const QStringRef &text)
64
+{
65
+ for (int i = 0; i < m_parsers.size(); i++)
66
+ m_parsers.at(i)->handleCharacterData(text);
67
+ if (!m_stanza->tokens.isEmpty() && m_stanza->tokens.last()->type == StanzaPrivate::Token::EndElement)
68
+ return;
69
+ StanzaPrivate::CharactersToken *token = new StanzaPrivate::CharactersToken;
70
+ token->text = text.appendTo(&m_stanza->buffer);
71
+ m_stanza->tokens << token;
72
+}
73
+
74
+void StanzaFactory::serialize(Stanza *stanza, QXmlStreamWriter *writer)
75
+{
76
+ StanzaPrivate *p = StanzaPrivate::get(*stanza);
77
+ QString namespaceUri = QLatin1String("jabber:client");
78
+ QStack<QStringRef> uries;
79
+ for (int i = 0; i < p->tokens.size(); ++i) {
80
+ StanzaPrivate::Token * const token = p->tokens.at(i);
81
+ if (token->type == StanzaPrivate::Token::StartElement) {
82
+ StanzaPrivate::StartToken * const startToken = static_cast<StanzaPrivate::StartToken*>(token);
83
+ writer->writeStartElement(startToken->name.toString());
84
+ QStringRef currentUri = (i == 0) ? QStringRef(&namespaceUri) : startToken->uri;
85
+ if (uries.isEmpty() || uries.top() != currentUri)
86
+ writer->writeDefaultNamespace(startToken->uri.toString());
87
+ uries.push(currentUri);
88
+ writer->writeAttributes(startToken->attributes);
89
+ } else if (token->type == StanzaPrivate::Token::Characters) {
90
+ StanzaPrivate::CharactersToken * const charachtersToken = static_cast<StanzaPrivate::CharactersToken*>(token);
91
+ writer->writeCharacters(charachtersToken->text.toString());
92
+ } else if (token->type == StanzaPrivate::Token::EndElement) {
93
+ writer->writeEndElement();
94
+ uries.pop();
95
+ } else {
96
+ Q_ASSERT(!"Unknown token type");
97
+ }
98
+ }
99
}
100
101
void StanzaFactory::writeAttributes(Stanza *stanza, QXmlStreamWriter *writer)
102
{
103
- if(stanza->from().isValid())
104
- writer->writeAttribute(QLatin1String("from"), stanza->from());
105
- if(stanza->to().isValid())
106
- writer->writeAttribute(QLatin1String("to"), stanza->to());
107
- if(!stanza->id().isEmpty())
108
- writer->writeAttribute(QLatin1String("id"), stanza->id());
109
- writer->writeAttribute(QLatin1String("xmlns"), QLatin1String("jabber:client"));
110
+ StanzaPrivate *p = StanzaPrivate::get(*stanza);
111
+ if (p->from.isValid())
112
+ writer->writeAttribute(QLatin1String("from"), p->from);
113
+ if (p->to.isValid())
114
+ writer->writeAttribute(QLatin1String("to"), p->to);
115
+ if (!p->id.isEmpty())
116
+ writer->writeAttribute(QLatin1String("id"), p->id);
117
+ writer->writeDefaultNamespace(QLatin1String("jabber:client"));
118
}
119
120
void StanzaFactory::writePayloads(Stanza *stanza, QXmlStreamWriter *writer)
121
libjreen-1.0.3.tar.bz2/src/stanzafactory_p.h -> libjreen-1.1.0.tar.bz2/src/stanzafactory_p.h
Changed
44
1
2
#ifndef STANZAFACTORY_H
3
#define STANZAFACTORY_H
4
5
-#include "stanza.h"
6
+#include "stanza_p.h"
7
#include "langmap.h"
8
#include <QXmlStreamAttributes>
9
+#include <QStack>
10
11
namespace Jreen
12
{
13
14
-class StanzaFactory : public XmlStreamFactory<Stanza>
15
+class JREEN_AUTOTEST_EXPORT StanzaFactory : public XmlStreamFactory<Stanza>
16
{
17
public:
18
StanzaFactory(Client *client);
19
virtual ~StanzaFactory();
20
+
21
+ void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
22
+ void handleEndElement(const QStringRef &name, const QStringRef &uri);
23
+ void handleCharacterData(const QStringRef &name);
24
+
25
virtual int stanzaType() = 0;
26
virtual Stanza::Ptr createStanza() = 0;
27
+ void serialize(Stanza *stanza, QXmlStreamWriter *writer);
28
protected:
29
- void parseAttributes(const QXmlStreamAttributes &attributes);
30
void writeAttributes(Stanza *stanza, QXmlStreamWriter *writer);
31
void writePayloads(Stanza *stanza, QXmlStreamWriter *writer);
32
void writeEscapedString(const QString &str, QXmlStreamWriter *writer);
33
void writeLangMap(const QString &tag, const LangMap &map,QXmlStreamWriter *writer); //may be move to XmlStreamFactory?
34
- JID m_from;
35
- JID m_to;
36
- QString m_id;
37
+ int m_depth;
38
+ QScopedPointer<StanzaPrivate> m_stanza;
39
Client *m_client;
40
+ QStack<XmlStreamParser*> m_parsers;
41
};
42
}
43
44
libjreen-1.0.3.tar.bz2/src/streamfeature_p.h -> libjreen-1.1.0.tar.bz2/src/streamfeature_p.h
Changed
29
1
2
public:
3
enum Type
4
{
5
- SecurityLayer,
6
- CompressionLayer,
7
- SASL,
8
- SimpleAuthorization,
9
- Custom,
10
- Invalid
11
+ SecurityLayer = 0,
12
+ CompressionLayer = 0x10,
13
+ RegistrationRequest = 0x20,
14
+ SASL = 0x100,
15
+ SimpleAuthorization = 0x1000,
16
+ Custom = 0x10000,
17
+ Invalid = -1
18
};
19
StreamFeature(Type type) : m_info(0), m_client(0), m_type(type) {}
20
virtual ~StreamFeature() {}
21
22
}
23
24
Q_DECLARE_OPERATORS_FOR_FLAGS(Jreen::StreamInfo::CompletedFlags)
25
-Q_DECLARE_INTERFACE(Jreen::StreamFeature,"org.qutim.JReen.StreamFeature");
26
+Q_DECLARE_INTERFACE(Jreen::StreamFeature, "org.qutim.Jreen.StreamFeature")
27
28
#endif // STREAMFEATURE_H
29
libjreen-1.0.3.tar.bz2/src/tlsfeature.cpp -> libjreen-1.1.0.tar.bz2/src/tlsfeature.cpp
Changed
18
1
2
#include "client.h"
3
#include <QXmlStreamWriter>
4
#include "logger.h"
5
+#include <QCoreApplication>
6
7
#define NS_TLS QLatin1String("urn:ietf:params:xml:ns:xmpp-tls")
8
9
10
TLSFeature::TLSFeature() : StreamFeature(SecurityLayer)
11
{
12
QCA::init();
13
- QCA::setAppName("qutim");
14
+ QCA::setAppName(QCoreApplication::applicationName());
15
m_required = false;
16
m_available = false;
17
m_hasTls = QCA::isSupported("tls");
18
libjreen-1.0.3.tar.bz2/src/tunefactory_p.h -> libjreen-1.1.0.tar.bz2/src/tunefactory_p.h
Changed
10
1
2
3
namespace Jreen
4
{
5
- class TuneFactory : public PayloadFactory<Tune>
6
+ class JREEN_AUTOTEST_EXPORT TuneFactory : public PayloadFactory<Tune>
7
{
8
public:
9
TuneFactory();
10
libjreen-1.0.3.tar.bz2/src/util.cpp -> libjreen-1.1.0.tar.bz2/src/util.cpp
Changed
49
1
2
return date_time.toUTC().toString(FULLZ_STAMP_STR);
3
}
4
5
-QByteArray Util::randomHash( /*const JID &jid*/ )
6
+QByteArray Util::randomHash()
7
{
8
-// Holy shit...
9
-// QCryptographicHash hash(QCryptographicHash::Sha1);
10
-// qptrdiff temp = QDateTime::currentDateTime().toTime_t();
11
-// QByteArray data;
12
-// data.append(jid.full().toUtf8());
13
-// data.append('\0');
14
-// for(uint i = 0; i < sizeof(qptrdiff); i++, temp /= 0x100)
15
-// data.append(temp % 0x100);
16
-// data.append('\0');
17
-// temp = reinterpret_cast<qptrdiff>(&jid);
18
-// for(uint i = 0; i < sizeof(qptrdiff); i++, temp /= 0x100)
19
-// data.append(temp % 0x100);
20
-// hash.addData(data);
21
-// data.append('\0');
22
-// temp = qrand();
23
-// for(uint i = 0; i < sizeof(qptrdiff); i++, temp /= 0x100)
24
-// data.append(temp % 0x100);
25
-// hash.addData(data);
26
-// return QLatin1String(hash.result().toHex());
27
-// Nobody whould find a differ
28
qint32 buf5;
29
for (int i = 0; i < 5; i++)
30
bufi = qrand();
31
- return QByteArray(reinterpret_cast<char*>(buf), sizeof(buf)).toHex();
32
+ return QByteArray::fromRawData(reinterpret_cast<char*>(buf), sizeof(buf)).toHex();
33
+}
34
+
35
+QString Util::randomStringHash(int length)
36
+{
37
+ QString str(length, Qt::Uninitialized);
38
+ for (int i = 0; i < length; ++i) {
39
+ int c = qrand() % (10 + 26);
40
+ if (c < 10)
41
+ stri = QLatin1Char('0' + c);
42
+ else
43
+ stri = QLatin1Char('a' + c - 10);
44
+ }
45
+ return str;
46
}
47
48
}
49
libjreen-1.0.3.tar.bz2/src/util.h -> libjreen-1.1.0.tar.bz2/src/util.h
Changed
10
1
2
JREEN_EXPORT QString toStamp(const QDate &date);
3
JREEN_EXPORT QString toStamp(const QDateTime &date_time);
4
JREEN_EXPORT QByteArray randomHash();
5
+JREEN_EXPORT QString randomStringHash(int len);
6
+
7
inline int log2(register uint n)
8
{
9
register int pos = 0;
10
libjreen-1.0.3.tar.bz2/src/vcardfactory.cpp -> libjreen-1.1.0.tar.bz2/src/vcardfactory.cpp
Changed
19
1
2
str = stringstype;
3
}
4
5
-class VCardFactoryPrivate
6
+class JREEN_AUTOTEST_EXPORT VCardFactoryPrivate
7
{
8
public:
9
void clear();
10
11
Payload::Ptr VCardFactory::createPayload()
12
{
13
Q_D(VCardFactory);
14
- return Payload::Ptr(d->vcard ? new VCard(*d->vcard.take()) : 0); //here is segfault
15
+ return Payload::Ptr(new VCard(*d->vcard.take()));
16
}
17
18
QStringList VCardFactory::features() const
19
libjreen-1.0.3.tar.bz2/src/vcardfactory_p.h -> libjreen-1.1.0.tar.bz2/src/vcardfactory_p.h
Changed
19
1
2
#include <QPair>
3
4
namespace Jreen {
5
-class VCardFactoryPrivate;
6
+class JREEN_AUTOTEST_EXPORT VCardFactoryPrivate;
7
8
class AbstractStructureParser : public XmlStreamParser
9
{
10
11
TPrivate m_data;
12
};
13
14
-class VCardFactory : public PayloadFactory<VCard>
15
+class JREEN_AUTOTEST_EXPORT VCardFactory : public PayloadFactory<VCard>
16
{
17
Q_DECLARE_PRIVATE(VCardFactory)
18
public:
19
libjreen-1.0.3.tar.bz2/src/vcardupdatefactory_p.h -> libjreen-1.1.0.tar.bz2/src/vcardupdatefactory_p.h
Changed
10
1
2
3
namespace Jreen {
4
5
-class VCardUpdateFactory : public PayloadFactory<VCardUpdate>
6
+class JREEN_AUTOTEST_EXPORT VCardUpdateFactory : public PayloadFactory<VCardUpdate>
7
{
8
public:
9
VCardUpdateFactory();
10
libjreen-1.0.3.tar.bz2/src/zlibcompressionfeature.cpp -> libjreen-1.1.0.tar.bz2/src/zlibcompressionfeature.cpp
Changed
29
1
2
#include "zlibdatastream_p.h"
3
#include <QXmlStreamWriter>
4
5
+#define NS_COMPRESS_FEATURE QLatin1String("http://jabber.org/features/compress")
6
+#define NS_COMPRESS_PROTOCOL QLatin1String("http://jabber.org/protocol/compress")
7
+
8
namespace Jreen
9
{
10
ZLibCompressionFeature::ZLibCompressionFeature() : StreamFeature(CompressionLayer)
11
12
{
13
Q_UNUSED(name);
14
Q_UNUSED(attributes);
15
- return uri == QLatin1String("http://jabber.org/features/compress") || uri == QLatin1String("http://jabber.org/protocol/compress");
16
+ return uri == NS_COMPRESS_FEATURE || uri == NS_COMPRESS_PROTOCOL;
17
}
18
19
void ZLibCompressionFeature::handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
20
21
{
22
QXmlStreamWriter *writer = m_info->writer();
23
writer->writeStartElement(QLatin1String("compress"));
24
- writer->writeDefaultNamespace(QLatin1String("http://jabber.org/protocol/compress"));
25
+ writer->writeDefaultNamespace(NS_COMPRESS_PROTOCOL);
26
writer->writeTextElement(QLatin1String("method"), QLatin1String("zlib"));
27
writer->writeEndElement();
28
return true;
29
Refresh
The project this package belongs to currently has no build targets defined.
Refresh
The project this package belongs to currently has no build targets defined.
Login required, please
login
or
signup
in order to comment