Overview

Request 272 (accepted)

No description set
Submit package home:pansenmann:branches:Multimedia / jreen to package Multimedia / jreen

jreen.spec Changed
x
 
1
@@ -1,7 +1,7 @@
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
@@ -1,89 +0,0 @@
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
@@ -1,59 +0,0 @@
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
@@ -1,113 +0,0 @@
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
@@ -1,54 +0,0 @@
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
@@ -0,0 +1,399 @@
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
@@ -0,0 +1,88 @@
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
@@ -0,0 +1,259 @@
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
@@ -0,0 +1,76 @@
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
@@ -0,0 +1,387 @@
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
@@ -0,0 +1,67 @@
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
@@ -0,0 +1,1342 @@
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
@@ -0,0 +1,189 @@
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
@@ -0,0 +1,1056 @@
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
@@ -0,0 +1,188 @@
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
@@ -0,0 +1,29 @@
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
@@ -0,0 +1,888 @@
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, &notStun, 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
@@ -0,0 +1,103 @@
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
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,75 @@
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
@@ -0,0 +1,251 @@
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
@@ -0,0 +1,78 @@
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
@@ -0,0 +1,301 @@
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
@@ -0,0 +1,88 @@
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
@@ -0,0 +1,111 @@
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
@@ -0,0 +1,69 @@
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
@@ -0,0 +1,1134 @@
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
@@ -0,0 +1,160 @@
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
@@ -0,0 +1,1455 @@
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
@@ -0,0 +1,135 @@
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
@@ -0,0 +1,300 @@
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
@@ -0,0 +1,83 @@
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
@@ -0,0 +1,733 @@
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
@@ -0,0 +1,111 @@
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
@@ -0,0 +1,745 @@
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
@@ -0,0 +1,207 @@
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
@@ -0,0 +1,738 @@
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
@@ -0,0 +1,146 @@
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
@@ -0,0 +1,101 @@
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
@@ -0,0 +1,44 @@
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
@@ -0,0 +1,1147 @@
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, &notStun))
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
@@ -0,0 +1,194 @@
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
@@ -0,0 +1,435 @@
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
@@ -0,0 +1,74 @@
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
@@ -4,13 +4,13 @@
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,9 +20,29 @@
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
@@ -42,6 +62,8 @@
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
@@ -57,15 +79,23 @@
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
@@ -159,9 +189,12 @@
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
@@ -1,8 +1,30 @@
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
@@ -32,6 +32,8 @@
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
@@ -41,6 +43,14 @@
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
@@ -33,6 +33,8 @@
2
 #include "logger.h"
3
 #include "util.h"
4
 
5
+#define NS_ROSTER QLatin1String("jabber:iq:roster")
6
+
7
 namespace Jreen
8
 {
9
 
10
@@ -55,13 +57,13 @@
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
@@ -119,7 +121,7 @@
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
@@ -141,12 +143,8 @@
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
@@ -58,7 +58,7 @@
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
@@ -137,7 +137,7 @@
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
@@ -68,7 +68,7 @@
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
@@ -32,7 +32,7 @@
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
@@ -49,7 +49,7 @@
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
@@ -0,0 +1,109 @@
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
@@ -0,0 +1,60 @@
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
@@ -0,0 +1,100 @@
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
@@ -0,0 +1,54 @@
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
@@ -29,7 +29,7 @@
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
@@ -33,8 +33,7 @@
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
@@ -72,6 +71,12 @@
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
@@ -122,9 +127,9 @@
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
@@ -32,7 +32,7 @@
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
@@ -44,6 +44,7 @@
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
@@ -0,0 +1,55 @@
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
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,96 @@
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
@@ -0,0 +1,56 @@
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
@@ -30,7 +30,7 @@
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
@@ -43,6 +43,7 @@
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
@@ -58,6 +59,11 @@
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
@@ -84,11 +90,12 @@
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
@@ -108,7 +115,7 @@
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
@@ -163,11 +170,15 @@
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
@@ -175,7 +186,7 @@
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
@@ -236,6 +247,26 @@
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
@@ -243,7 +274,6 @@
104
 
105
 void Client::setProxyFactory(QNetworkProxyFactory *factory)
106
 {
107
-   Q_D(Client);
108
    d_func()->proxyFactory.reset(factory);
109
 }
110
 
111
@@ -310,6 +340,14 @@
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
@@ -383,10 +421,11 @@
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
@@ -410,14 +449,21 @@
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
@@ -33,7 +33,7 @@
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
@@ -49,6 +49,7 @@
11
 class Disco;
12
 class MessageSessionManager;
13
 class AbstractRoster;
14
+class JingleManager;
15
 
16
 class XmlStreamHandler
17
 {
18
@@ -80,8 +81,26 @@
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
@@ -93,6 +112,9 @@
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
@@ -107,6 +129,7 @@
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
@@ -115,7 +138,8 @@
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
@@ -146,7 +170,7 @@
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
@@ -51,6 +51,7 @@
2
 #include <QNetworkProxyFactory>
3
 #include "stanza_p.h"
4
 #include "streamprocessor.h"
5
+#include "experimental/jinglemanager.h"
6
 
7
 namespace Jreen
8
 {
9
@@ -131,28 +132,32 @@
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
@@ -183,7 +188,7 @@
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
@@ -192,22 +197,25 @@
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
@@ -216,24 +224,13 @@
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
@@ -254,16 +251,16 @@
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
@@ -273,17 +270,29 @@
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
@@ -328,7 +337,7 @@
168
    }
169
    QXmlStreamWriter *writer()
170
    {
171
-       return d->writer;
172
+       return d->writer.data();
173
    }
174
    void completed(const CompletedFlags &flags)
175
    {
176
@@ -339,7 +348,7 @@
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
@@ -363,8 +372,8 @@
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
@@ -26,11 +26,139 @@
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
@@ -97,6 +225,16 @@
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
@@ -466,6 +604,14 @@
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
@@ -502,6 +648,11 @@
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
@@ -40,11 +40,61 @@
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
@@ -82,8 +132,7 @@
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
@@ -101,6 +150,9 @@
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
@@ -329,6 +381,7 @@
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
@@ -336,6 +389,7 @@
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
@@ -45,6 +45,7 @@
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
@@ -71,6 +72,7 @@
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
@@ -26,10 +26,12 @@
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
@@ -110,6 +112,86 @@
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
@@ -120,7 +202,8 @@
103
    "list-single",
104
    "text-multi",
105
    "text-private",
106
-   "text-single"
107
+   "text-single",
108
+   ""
109
 };
110
 
111
 class DataFormFieldParser : XmlStreamFactory<DataFormField>
112
@@ -155,6 +238,8 @@
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
@@ -164,6 +249,8 @@
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
@@ -173,6 +260,10 @@
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
@@ -186,6 +277,10 @@
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
@@ -219,8 +314,8 @@
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
@@ -229,6 +324,7 @@
163
        AtValue,
164
        AtOption,
165
        AtRequied,
166
+       AtMedia,
167
        AtNowhere
168
    };
169
    void clear() {
170
@@ -237,10 +333,12 @@
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
@@ -248,8 +346,9 @@
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
@@ -267,7 +366,7 @@
195
    "result"
196
 };
197
 
198
-class DataFormFactoryPrivate
199
+class JREEN_AUTOTEST_EXPORT DataFormFactoryPrivate
200
 {
201
 public:
202
    void clear()
203
@@ -320,7 +419,7 @@
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
@@ -350,10 +449,13 @@
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
@@ -376,7 +478,7 @@
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
@@ -29,8 +29,8 @@
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
@@ -28,12 +28,12 @@
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
@@ -90,7 +90,8 @@
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
@@ -29,8 +29,8 @@
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
@@ -29,9 +29,128 @@
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
@@ -50,44 +50,11 @@
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
@@ -97,60 +64,11 @@
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
@@ -70,7 +70,7 @@
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
@@ -545,6 +545,11 @@
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
@@ -583,6 +588,11 @@
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
@@ -592,6 +602,8 @@
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
@@ -157,12 +157,14 @@
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
@@ -46,7 +46,7 @@
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
@@ -68,7 +68,7 @@
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
@@ -30,7 +30,7 @@
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
@@ -59,6 +59,11 @@
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
@@ -161,6 +161,7 @@
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
@@ -68,7 +68,7 @@
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
@@ -83,6 +83,7 @@
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
@@ -95,7 +96,8 @@
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
@@ -30,7 +30,7 @@
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
@@ -46,6 +46,7 @@
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
@@ -0,0 +1,34 @@
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
@@ -0,0 +1,41 @@
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
@@ -0,0 +1,73 @@
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
@@ -0,0 +1,108 @@
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
@@ -0,0 +1,281 @@
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
@@ -0,0 +1,85 @@
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
@@ -0,0 +1,85 @@
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
@@ -0,0 +1,130 @@
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
@@ -0,0 +1,56 @@
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
@@ -0,0 +1,134 @@
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
@@ -0,0 +1,70 @@
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
@@ -0,0 +1,57 @@
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
@@ -0,0 +1,213 @@
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
@@ -0,0 +1,147 @@
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
@@ -0,0 +1,68 @@
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
@@ -0,0 +1,196 @@
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
@@ -0,0 +1,62 @@
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
@@ -0,0 +1,155 @@
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
@@ -0,0 +1,63 @@
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
@@ -0,0 +1,53 @@
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
@@ -0,0 +1,281 @@
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
@@ -0,0 +1,75 @@
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
@@ -0,0 +1,74 @@
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
@@ -0,0 +1,128 @@
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
@@ -0,0 +1,62 @@
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
@@ -0,0 +1,72 @@
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
@@ -0,0 +1,130 @@
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
@@ -0,0 +1,274 @@
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
@@ -0,0 +1,99 @@
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
@@ -0,0 +1,68 @@
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
@@ -0,0 +1,56 @@
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
@@ -0,0 +1,114 @@
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
@@ -0,0 +1,63 @@
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
@@ -34,7 +34,9 @@
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
@@ -31,7 +31,6 @@
2
 {
3
 IqFactory::IqFactory(Client *client) : StanzaFactory(client)
4
 {
5
-   m_depth = 0;
6
 }
7
 
8
 int IqFactory::stanzaType()
9
@@ -41,16 +40,15 @@
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
@@ -87,35 +85,35 @@
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
@@ -31,7 +31,7 @@
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
@@ -42,9 +42,6 @@
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
@@ -35,12 +35,22 @@
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
@@ -65,19 +65,19 @@
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
@@ -1,15 +1,15 @@
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
@@ -19,7 +19,7 @@
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
@@ -1,15 +1,15 @@
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
@@ -19,7 +19,7 @@
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
@@ -33,6 +33,13 @@
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
@@ -51,6 +51,7 @@
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
@@ -24,8 +24,10 @@
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
@@ -33,7 +35,7 @@
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
@@ -31,26 +31,16 @@
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
@@ -60,28 +50,25 @@
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
@@ -100,13 +87,20 @@
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
@@ -119,8 +113,7 @@
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
@@ -128,13 +121,15 @@
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
@@ -31,7 +31,7 @@
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
@@ -44,13 +44,7 @@
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
@@ -155,7 +155,7 @@
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
@@ -183,16 +183,19 @@
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
@@ -39,14 +39,24 @@
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
@@ -0,0 +1,30 @@
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
@@ -0,0 +1,46 @@
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
@@ -0,0 +1,106 @@
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
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,171 @@
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
@@ -0,0 +1,88 @@
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
@@ -31,7 +31,7 @@
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
@@ -199,6 +199,7 @@
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
@@ -312,9 +313,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
@@ -587,6 +588,7 @@
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
@@ -86,7 +86,7 @@
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
@@ -31,7 +31,7 @@
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
@@ -45,7 +45,7 @@
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
@@ -62,7 +62,7 @@
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
@@ -82,7 +82,7 @@
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
@@ -101,7 +101,7 @@
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
@@ -29,7 +29,7 @@
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
@@ -29,8 +29,8 @@
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
@@ -30,6 +30,8 @@
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
@@ -37,7 +39,7 @@
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
@@ -74,7 +74,45 @@
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
@@ -82,14 +120,34 @@
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
@@ -187,11 +245,6 @@
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
@@ -213,11 +266,6 @@
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
@@ -232,14 +280,11 @@
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
@@ -56,7 +56,6 @@
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
@@ -0,0 +1,56 @@
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
@@ -0,0 +1,52 @@
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
@@ -0,0 +1,141 @@
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
@@ -0,0 +1,68 @@
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
@@ -0,0 +1,56 @@
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
@@ -0,0 +1,53 @@
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
@@ -30,7 +30,7 @@
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
@@ -36,7 +36,10 @@
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
@@ -35,16 +35,7 @@
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
@@ -54,18 +45,15 @@
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
@@ -133,28 +121,29 @@
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
@@ -163,42 +152,39 @@
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
@@ -33,7 +33,7 @@
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
@@ -46,13 +46,8 @@
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
@@ -30,7 +30,7 @@
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
@@ -86,7 +86,7 @@
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
@@ -33,7 +33,7 @@
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
@@ -39,6 +39,7 @@
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
@@ -65,7 +66,7 @@
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
@@ -116,7 +117,7 @@
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
@@ -33,7 +33,7 @@
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
@@ -35,7 +35,7 @@
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
@@ -28,8 +28,8 @@
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
@@ -0,0 +1,85 @@
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
@@ -0,0 +1,57 @@
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
@@ -0,0 +1,266 @@
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
@@ -0,0 +1,118 @@
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
@@ -0,0 +1,90 @@
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
@@ -0,0 +1,39 @@
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
@@ -0,0 +1,49 @@
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
@@ -0,0 +1,159 @@
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
@@ -0,0 +1,63 @@
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
@@ -26,19 +26,22 @@
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
@@ -83,7 +86,7 @@
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
@@ -147,9 +150,9 @@
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
@@ -158,9 +161,9 @@
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
@@ -173,13 +176,17 @@
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
@@ -41,7 +41,7 @@
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
@@ -37,7 +37,7 @@
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
@@ -28,8 +28,8 @@
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
@@ -94,6 +94,11 @@
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
@@ -58,12 +58,23 @@
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
@@ -50,11 +50,48 @@
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
@@ -79,6 +116,8 @@
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
@@ -29,6 +29,7 @@
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
@@ -42,11 +43,23 @@
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
@@ -52,8 +52,10 @@
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
@@ -73,7 +75,7 @@
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
@@ -108,12 +110,18 @@
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
@@ -26,33 +26,108 @@
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
@@ -26,30 +26,36 @@
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
@@ -69,12 +69,13 @@
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
@@ -96,6 +97,6 @@
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
@@ -29,6 +29,7 @@
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
@@ -38,7 +39,7 @@
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
@@ -31,7 +31,7 @@
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
@@ -119,32 +119,25 @@
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
@@ -41,6 +41,8 @@
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
@@ -406,7 +406,7 @@
2
        str = stringstype;
3
 }
4
 
5
-class VCardFactoryPrivate
6
+class JREEN_AUTOTEST_EXPORT VCardFactoryPrivate
7
 {
8
 public:
9
    void clear();
10
@@ -447,7 +447,7 @@
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
@@ -30,7 +30,7 @@
2
 #include <QPair>
3
 
4
 namespace Jreen {
5
-class VCardFactoryPrivate;
6
+class JREEN_AUTOTEST_EXPORT VCardFactoryPrivate;
7
 
8
 class AbstractStructureParser : public XmlStreamParser
9
 {
10
@@ -97,7 +97,7 @@
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
@@ -29,7 +29,7 @@
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
@@ -27,6 +27,9 @@
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
@@ -45,7 +48,7 @@
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
@@ -90,7 +93,7 @@
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.

Request History