~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/src/xmpp/cutestuff/bsocket.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * bsocket.cpp - QSocket wrapper based on Bytestream with SRV DNS support
 
3
 * Copyright (C) 2003  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 <QTcpSocket>
 
22
#include <QHostAddress>
 
23
#include <QMetaType>
 
24
 
 
25
#include "bsocket.h"
 
26
 
 
27
//#include "safedelete.h"
 
28
#include "ndns.h"
 
29
#include "srvresolver.h"
 
30
 
 
31
//#define BS_DEBUG
 
32
 
 
33
#ifdef BS_DEBUG
 
34
#include <stdio.h>
 
35
#endif
 
36
 
 
37
#define READBUFSIZE 65536
 
38
 
 
39
// CS_NAMESPACE_BEGIN
 
40
 
 
41
class QTcpSocketSignalRelay : public QObject
 
42
{
 
43
        Q_OBJECT
 
44
public:
 
45
        QTcpSocketSignalRelay(QTcpSocket *sock, QObject *parent = 0)
 
46
        :QObject(parent)
 
47
        {
 
48
                qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
 
49
                connect(sock, SIGNAL(hostFound()), SLOT(sock_hostFound()), Qt::QueuedConnection);
 
50
                connect(sock, SIGNAL(connected()), SLOT(sock_connected()), Qt::QueuedConnection);
 
51
                connect(sock, SIGNAL(disconnected()), SLOT(sock_disconnected()), Qt::QueuedConnection);
 
52
                connect(sock, SIGNAL(readyRead()), SLOT(sock_readyRead()), Qt::QueuedConnection);
 
53
                connect(sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)), Qt::QueuedConnection);
 
54
                connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(sock_error(QAbstractSocket::SocketError)), Qt::QueuedConnection);
 
55
        }
 
56
 
 
57
signals:
 
58
        void hostFound();
 
59
        void connected();
 
60
        void disconnected();
 
61
        void readyRead();
 
62
        void bytesWritten(qint64);
 
63
        void error(QAbstractSocket::SocketError);
 
64
 
 
65
public slots:
 
66
        void sock_hostFound()
 
67
        {
 
68
                emit hostFound();
 
69
        }
 
70
 
 
71
        void sock_connected()
 
72
        {
 
73
                emit connected();
 
74
        }
 
75
 
 
76
        void sock_disconnected()
 
77
        {
 
78
                emit disconnected();
 
79
        }
 
80
 
 
81
        void sock_readyRead()
 
82
        {
 
83
                emit readyRead();
 
84
        }
 
85
 
 
86
        void sock_bytesWritten(qint64 x)
 
87
        {
 
88
                emit bytesWritten(x);
 
89
        }
 
90
 
 
91
        void sock_error(QAbstractSocket::SocketError x)
 
92
        {
 
93
                emit error(x);
 
94
        }
 
95
};
 
96
 
 
97
class BSocket::Private
 
98
{
 
99
public:
 
100
        Private()
 
101
        {
 
102
                qsock = 0;
 
103
                qsock_relay = 0;
 
104
        }
 
105
 
 
106
        QTcpSocket *qsock;
 
107
        QTcpSocketSignalRelay *qsock_relay;
 
108
        int state;
 
109
 
 
110
        NDns ndns;
 
111
        SrvResolver srv;
 
112
        QString host;
 
113
        int port;
 
114
        //SafeDelete sd;
 
115
};
 
116
 
 
117
BSocket::BSocket(QObject *parent)
 
118
:ByteStream(parent)
 
119
{
 
120
        d = new Private;
 
121
        connect(&d->ndns, SIGNAL(resultsReady()), SLOT(ndns_done()));
 
122
        connect(&d->srv, SIGNAL(resultsReady()), SLOT(srv_done()));
 
123
 
 
124
        reset();
 
125
}
 
126
 
 
127
BSocket::~BSocket()
 
128
{
 
129
        reset(true);
 
130
        delete d;
 
131
}
 
132
 
 
133
void BSocket::reset(bool clear)
 
134
{
 
135
        if(d->qsock) {
 
136
                delete d->qsock_relay;
 
137
                d->qsock_relay = 0;
 
138
 
 
139
                /*d->qsock->disconnect(this);
 
140
 
 
141
                if(!clear && d->qsock->isOpen() && d->qsock->isValid()) {*/
 
142
                        // move remaining into the local queue
 
143
                        QByteArray block(d->qsock->bytesAvailable(), 0);
 
144
                        d->qsock->read(block.data(), block.size());
 
145
                        appendRead(block);
 
146
                //}
 
147
 
 
148
                //d->sd.deleteLater(d->qsock);
 
149
    d->qsock->deleteLater();
 
150
                d->qsock = 0;
 
151
        }
 
152
        else {
 
153
                if(clear)
 
154
                        clearReadBuffer();
 
155
        }
 
156
 
 
157
        if(d->srv.isBusy())
 
158
                d->srv.stop();
 
159
        if(d->ndns.isBusy())
 
160
                d->ndns.stop();
 
161
        d->state = Idle;
 
162
}
 
163
 
 
164
void BSocket::ensureSocket()
 
165
{
 
166
        if(!d->qsock) {
 
167
                d->qsock = new QTcpSocket;
 
168
#if QT_VERSION >= 0x030200
 
169
                d->qsock->setReadBufferSize(READBUFSIZE);
 
170
#endif
 
171
                d->qsock_relay = new QTcpSocketSignalRelay(d->qsock);
 
172
                connect(d->qsock_relay, SIGNAL(hostFound()), SLOT(qs_hostFound()));
 
173
                connect(d->qsock_relay, SIGNAL(connected()), SLOT(qs_connected()));
 
174
                connect(d->qsock_relay, SIGNAL(disconnected()), SLOT(qs_closed()));
 
175
                connect(d->qsock_relay, SIGNAL(readyRead()), SLOT(qs_readyRead()));
 
176
                connect(d->qsock_relay, SIGNAL(bytesWritten(qint64)), SLOT(qs_bytesWritten(qint64)));
 
177
                connect(d->qsock_relay, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(qs_error(QAbstractSocket::SocketError)));
 
178
        }
 
179
}
 
180
 
 
181
void BSocket::connectToHost(const QString &host, quint16 port)
 
182
{
 
183
        reset(true);
 
184
        d->host = host;
 
185
        d->port = port;
 
186
        d->state = HostLookup;
 
187
        d->ndns.resolve(d->host);
 
188
}
 
189
 
 
190
void BSocket::connectToServer(const QString &srv, const QString &type)
 
191
{
 
192
        reset(true);
 
193
        d->state = HostLookup;
 
194
        d->srv.resolve(srv, type, "tcp");
 
195
}
 
196
 
 
197
int BSocket::socket() const
 
198
{
 
199
        if(d->qsock)
 
200
                return d->qsock->socketDescriptor();
 
201
        else
 
202
                return -1;
 
203
}
 
204
 
 
205
void BSocket::setSocket(int s)
 
206
{
 
207
        reset(true);
 
208
        ensureSocket();
 
209
        d->state = Connected;
 
210
        d->qsock->setSocketDescriptor(s);
 
211
}
 
212
 
 
213
int BSocket::state() const
 
214
{
 
215
        return d->state;
 
216
}
 
217
 
 
218
bool BSocket::isOpen() const
 
219
{
 
220
        if(d->state == Connected)
 
221
                return true;
 
222
        else
 
223
                return false;
 
224
}
 
225
 
 
226
void BSocket::close()
 
227
{
 
228
        if(d->state == Idle)
 
229
                return;
 
230
 
 
231
        if(d->qsock) {
 
232
                d->qsock->close();
 
233
                d->state = Closing;
 
234
                if(d->qsock->bytesToWrite() == 0)
 
235
                        reset();
 
236
        }
 
237
        else {
 
238
                reset();
 
239
        }
 
240
}
 
241
 
 
242
void BSocket::write(const QByteArray &a)
 
243
{
 
244
        if(d->state != Connected)
 
245
                return;
 
246
#ifdef BS_DEBUG
 
247
        QString s = QString::fromUtf8(a);
 
248
        fprintf(stderr, "BSocket: writing [%d]: {%s}\n", a.size(), s.latin1());
 
249
#endif
 
250
        d->qsock->write(a.data(), a.size());
 
251
}
 
252
 
 
253
QByteArray BSocket::read(int bytes)
 
254
{
 
255
        QByteArray block;
 
256
        if(d->qsock) {
 
257
                int max = bytesAvailable();
 
258
                if(bytes <= 0 || bytes > max)
 
259
                        bytes = max;
 
260
                block.resize(bytes);
 
261
                d->qsock->read(block.data(), block.size());
 
262
        }
 
263
        else
 
264
                block = ByteStream::read(bytes);
 
265
 
 
266
#ifdef BS_DEBUG
 
267
        QString s = QString::fromUtf8(block);
 
268
        fprintf(stderr, "BSocket: read [%d]: {%s}\n", block.size(), s.latin1());
 
269
#endif
 
270
        return block;
 
271
}
 
272
 
 
273
int BSocket::bytesAvailable() const
 
274
{
 
275
        if(d->qsock)
 
276
                return d->qsock->bytesAvailable();
 
277
        else
 
278
                return ByteStream::bytesAvailable();
 
279
}
 
280
 
 
281
int BSocket::bytesToWrite() const
 
282
{
 
283
        if(!d->qsock)
 
284
                return 0;
 
285
        return d->qsock->bytesToWrite();
 
286
}
 
287
 
 
288
QHostAddress BSocket::address() const
 
289
{
 
290
        if(d->qsock)
 
291
                return d->qsock->localAddress();
 
292
        else
 
293
                return QHostAddress();
 
294
}
 
295
 
 
296
quint16 BSocket::port() const
 
297
{
 
298
        if(d->qsock)
 
299
                return d->qsock->localPort();
 
300
        else
 
301
                return 0;
 
302
}
 
303
 
 
304
QHostAddress BSocket::peerAddress() const
 
305
{
 
306
        if(d->qsock)
 
307
                return d->qsock->peerAddress();
 
308
        else
 
309
                return QHostAddress();
 
310
}
 
311
 
 
312
quint16 BSocket::peerPort() const
 
313
{
 
314
        if(d->qsock)
 
315
                return d->qsock->peerPort();
 
316
        else
 
317
                return 0;
 
318
}
 
319
 
 
320
void BSocket::srv_done()
 
321
{
 
322
        if(d->srv.failed()) {
 
323
#ifdef BS_DEBUG
 
324
                fprintf(stderr, "BSocket: Error resolving hostname.\n");
 
325
#endif
 
326
                error(ErrHostNotFound);
 
327
                return;
 
328
        }
 
329
 
 
330
        d->host = d->srv.resultAddress().toString();
 
331
        d->port = d->srv.resultPort();
 
332
        do_connect();
 
333
        //QTimer::singleShot(0, this, SLOT(do_connect()));
 
334
        //hostFound();
 
335
}
 
336
 
 
337
void BSocket::ndns_done()
 
338
{
 
339
        if(!d->ndns.result().isNull()) {
 
340
                d->host = d->ndns.resultString();
 
341
                d->state = Connecting;
 
342
                do_connect();
 
343
                //QTimer::singleShot(0, this, SLOT(do_connect()));
 
344
                //hostFound();
 
345
        }
 
346
        else {
 
347
#ifdef BS_DEBUG
 
348
                fprintf(stderr, "BSocket: Error resolving hostname.\n");
 
349
#endif
 
350
                error(ErrHostNotFound);
 
351
        }
 
352
}
 
353
 
 
354
void BSocket::do_connect()
 
355
{
 
356
#ifdef BS_DEBUG
 
357
        fprintf(stderr, "BSocket: Connecting to %s:%d\n", d->host.latin1(), d->port);
 
358
#endif
 
359
        ensureSocket();
 
360
        d->qsock->connectToHost(d->host, d->port);
 
361
}
 
362
 
 
363
void BSocket::qs_hostFound()
 
364
{
 
365
        //SafeDeleteLock s(&d->sd);
 
366
}
 
367
 
 
368
void BSocket::qs_connected()
 
369
{
 
370
        d->state = Connected;
 
371
#ifdef BS_DEBUG
 
372
        fprintf(stderr, "BSocket: Connected.\n");
 
373
#endif
 
374
        //SafeDeleteLock s(&d->sd);
 
375
        connected();
 
376
}
 
377
 
 
378
void BSocket::qs_closed()
 
379
{
 
380
        if(d->state == Closing)
 
381
        {
 
382
#ifdef BS_DEBUG
 
383
                fprintf(stderr, "BSocket: Delayed Close Finished.\n");
 
384
#endif
 
385
                //SafeDeleteLock s(&d->sd);
 
386
                reset();
 
387
                delayedCloseFinished();
 
388
        }
 
389
}
 
390
 
 
391
void BSocket::qs_readyRead()
 
392
{
 
393
        //SafeDeleteLock s(&d->sd);
 
394
        readyRead();
 
395
}
 
396
 
 
397
void BSocket::qs_bytesWritten(qint64 x64)
 
398
{
 
399
        int x = x64;
 
400
#ifdef BS_DEBUG
 
401
        fprintf(stderr, "BSocket: BytesWritten [%d].\n", x);
 
402
#endif
 
403
        //SafeDeleteLock s(&d->sd);
 
404
        bytesWritten(x);
 
405
}
 
406
 
 
407
void BSocket::qs_error(QAbstractSocket::SocketError x)
 
408
{
 
409
        if(x == QTcpSocket::RemoteHostClosedError) {
 
410
#ifdef BS_DEBUG
 
411
                fprintf(stderr, "BSocket: Connection Closed.\n");
 
412
#endif
 
413
                //SafeDeleteLock s(&d->sd);
 
414
                reset();
 
415
                connectionClosed();
 
416
                return;
 
417
        }
 
418
 
 
419
#ifdef BS_DEBUG
 
420
        fprintf(stderr, "BSocket: Error.\n");
 
421
#endif
 
422
        //SafeDeleteLock s(&d->sd);
 
423
 
 
424
        // connection error during SRV host connect?  try next
 
425
        if(d->state == HostLookup && (x == QTcpSocket::ConnectionRefusedError || x == QTcpSocket::HostNotFoundError)) {
 
426
                d->srv.next();
 
427
                return;
 
428
        }
 
429
 
 
430
        reset();
 
431
        if(x == QTcpSocket::ConnectionRefusedError)
 
432
                error(ErrConnectionRefused);
 
433
        else if(x == QTcpSocket::HostNotFoundError)
 
434
                error(ErrHostNotFound);
 
435
        else
 
436
                error(ErrRead);
 
437
}
 
438
 
 
439
#include "bsocket.moc"
 
440
 
 
441
// CS_NAMESPACE_END