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

« back to all changes in this revision

Viewing changes to cutestuff/legacy/srvresolver.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * srvresolver.cpp - class to simplify SRV lookups
 
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 "srvresolver.h"
 
22
 
 
23
#include <q3cstring.h>
 
24
#include <qtimer.h>
 
25
#include <q3dns.h>
 
26
//Added by qt3to4:
 
27
#include <QList>
 
28
#include "safedelete.h"
 
29
 
 
30
#ifndef NO_NDNS
 
31
#include "ndns.h"
 
32
#endif
 
33
 
 
34
// CS_NAMESPACE_BEGIN
 
35
 
 
36
static void sortSRVList(QList<Q3Dns::Server> &list)
 
37
{
 
38
        QList<Q3Dns::Server> tmp = list;
 
39
        list.clear();
 
40
 
 
41
        while(!tmp.isEmpty()) {
 
42
                QList<Q3Dns::Server>::Iterator p = tmp.end();
 
43
                for(QList<Q3Dns::Server>::Iterator it = tmp.begin(); it != tmp.end(); ++it) {
 
44
                        if(p == tmp.end())
 
45
                                p = it;
 
46
                        else {
 
47
                                int a = (*it).priority;
 
48
                                int b = (*p).priority;
 
49
                                int j = (*it).weight;
 
50
                                int k = (*p).weight;
 
51
                                if(a < b || (a == b && j < k))
 
52
                                        p = it;
 
53
                        }
 
54
                }
 
55
                list.append(*p);
 
56
                tmp.remove(p);
 
57
        }
 
58
}
 
59
 
 
60
class SrvResolver::Private
 
61
{
 
62
public:
 
63
        Private() {}
 
64
 
 
65
        Q3Dns *qdns;
 
66
#ifndef NO_NDNS
 
67
        NDns ndns;
 
68
#endif
 
69
 
 
70
        bool failed;
 
71
        QHostAddress resultAddress;
 
72
        Q_UINT16 resultPort;
 
73
 
 
74
        bool srvonly;
 
75
        QString srv;
 
76
        QList<Q3Dns::Server> servers;
 
77
        bool aaaa;
 
78
 
 
79
        QTimer t;
 
80
        SafeDelete sd;
 
81
};
 
82
 
 
83
SrvResolver::SrvResolver(QObject *parent)
 
84
:QObject(parent)
 
85
{
 
86
        d = new Private;
 
87
        d->qdns = 0;
 
88
 
 
89
#ifndef NO_NDNS
 
90
        connect(&d->ndns, SIGNAL(resultsReady()), SLOT(ndns_done()));
 
91
#endif
 
92
        connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout()));
 
93
        stop();
 
94
}
 
95
 
 
96
SrvResolver::~SrvResolver()
 
97
{
 
98
        stop();
 
99
        delete d;
 
100
}
 
101
 
 
102
void SrvResolver::resolve(const QString &server, const QString &type, const QString &proto)
 
103
{
 
104
        stop();
 
105
 
 
106
        d->failed = false;
 
107
        d->srvonly = false;
 
108
        d->srv = QString("_") + type + "._" + proto + '.' + server;
 
109
        d->t.start(15000, true);
 
110
        d->qdns = new Q3Dns;
 
111
        connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
 
112
        d->qdns->setRecordType(Q3Dns::Srv);
 
113
        d->qdns->setLabel(d->srv);
 
114
}
 
115
 
 
116
void SrvResolver::resolveSrvOnly(const QString &server, const QString &type, const QString &proto)
 
117
{
 
118
        stop();
 
119
 
 
120
        d->failed = false;
 
121
        d->srvonly = true;
 
122
        d->srv = QString("_") + type + "._" + proto + '.' + server;
 
123
        d->t.start(15000, true);
 
124
        d->qdns = new Q3Dns;
 
125
        connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
 
126
        d->qdns->setRecordType(Q3Dns::Srv);
 
127
        d->qdns->setLabel(d->srv);
 
128
}
 
129
 
 
130
void SrvResolver::next()
 
131
{
 
132
        if(d->servers.isEmpty())
 
133
                return;
 
134
 
 
135
        tryNext();
 
136
}
 
137
 
 
138
void SrvResolver::stop()
 
139
{
 
140
        if(d->t.isActive())
 
141
                d->t.stop();
 
142
        if(d->qdns) {
 
143
                d->qdns->disconnect(this);
 
144
                d->sd.deleteLater(d->qdns);
 
145
                d->qdns = 0;
 
146
        }
 
147
#ifndef NO_NDNS
 
148
        if(d->ndns.isBusy())
 
149
                d->ndns.stop();
 
150
#endif
 
151
        d->resultAddress = QHostAddress();
 
152
        d->resultPort = 0;
 
153
        d->servers.clear();
 
154
        d->srv = "";
 
155
        d->failed = true;
 
156
}
 
157
 
 
158
bool SrvResolver::isBusy() const
 
159
{
 
160
#ifndef NO_NDNS
 
161
        if(d->qdns || d->ndns.isBusy())
 
162
#else
 
163
        if(d->qdns)
 
164
#endif
 
165
                return true;
 
166
        else
 
167
                return false;
 
168
}
 
169
 
 
170
QList<Q3Dns::Server> SrvResolver::servers() const
 
171
{
 
172
        return d->servers;
 
173
}
 
174
 
 
175
bool SrvResolver::failed() const
 
176
{
 
177
        return d->failed;
 
178
}
 
179
 
 
180
QHostAddress SrvResolver::resultAddress() const
 
181
{
 
182
        return d->resultAddress;
 
183
}
 
184
 
 
185
Q_UINT16 SrvResolver::resultPort() const
 
186
{
 
187
        return d->resultPort;
 
188
}
 
189
 
 
190
void SrvResolver::tryNext()
 
191
{
 
192
#ifndef NO_NDNS
 
193
        d->ndns.resolve(d->servers.first().name);
 
194
#else
 
195
        d->qdns = new Q3Dns;
 
196
        connect(d->qdns, SIGNAL(resultsReady()), SLOT(ndns_done()));
 
197
        if(d->aaaa)
 
198
                d->qdns->setRecordType(Q3Dns::Aaaa); // IPv6
 
199
        else
 
200
                d->qdns->setRecordType(Q3Dns::A); // IPv4
 
201
        d->qdns->setLabel(d->servers.first().name);
 
202
#endif
 
203
}
 
204
 
 
205
void SrvResolver::qdns_done()
 
206
{
 
207
        if(!d->qdns)
 
208
                return;
 
209
 
 
210
        // apparently we sometimes get this signal even though the results aren't ready
 
211
        if(d->qdns->isWorking())
 
212
                return;
 
213
        d->t.stop();
 
214
 
 
215
        SafeDeleteLock s(&d->sd);
 
216
 
 
217
        // grab the server list and destroy the qdns object
 
218
        QList<Q3Dns::Server> list;
 
219
        if(d->qdns->recordType() == Q3Dns::Srv)
 
220
                list = d->qdns->servers();
 
221
        d->qdns->disconnect(this);
 
222
        d->sd.deleteLater(d->qdns);
 
223
        d->qdns = 0;
 
224
 
 
225
        if(list.isEmpty()) {
 
226
                stop();
 
227
                resultsReady();
 
228
                return;
 
229
        }
 
230
        sortSRVList(list);
 
231
        d->servers = list;
 
232
 
 
233
        if(d->srvonly)
 
234
                resultsReady();
 
235
        else {
 
236
                // kick it off
 
237
                d->aaaa = true;
 
238
                tryNext();
 
239
        }
 
240
}
 
241
 
 
242
void SrvResolver::ndns_done()
 
243
{
 
244
#ifndef NO_NDNS
 
245
        SafeDeleteLock s(&d->sd);
 
246
 
 
247
        QHostAddress r = d->ndns.result();
 
248
        int port = d->servers.first().port;
 
249
        d->servers.remove(d->servers.begin());
 
250
 
 
251
        if(!r.isNull()) {
 
252
                d->resultAddress = d->ndns.result();
 
253
                d->resultPort = port;
 
254
                resultsReady();
 
255
        }
 
256
        else {
 
257
                // failed?  bail if last one
 
258
                if(d->servers.isEmpty()) {
 
259
                        stop();
 
260
                        resultsReady();
 
261
                        return;
 
262
                }
 
263
 
 
264
                // otherwise try the next
 
265
                tryNext();
 
266
        }
 
267
#else
 
268
        if(!d->qdns)
 
269
                return;
 
270
 
 
271
        // apparently we sometimes get this signal even though the results aren't ready
 
272
        if(d->qdns->isWorking())
 
273
                return;
 
274
 
 
275
        SafeDeleteLock s(&d->sd);
 
276
 
 
277
        // grab the address list and destroy the qdns object
 
278
        QList<QHostAddress> list;
 
279
        if(d->qdns->recordType() == Q3Dns::A || d->qdns->recordType() == Q3Dns::Aaaa)
 
280
                list = d->qdns->addresses();
 
281
        d->qdns->disconnect(this);
 
282
        d->sd.deleteLater(d->qdns);
 
283
        d->qdns = 0;
 
284
 
 
285
        if(!list.isEmpty()) {
 
286
                int port = d->servers.first().port;
 
287
                d->servers.remove(d->servers.begin());
 
288
                d->aaaa = true;
 
289
 
 
290
                d->resultAddress = list.first();
 
291
                d->resultPort = port;
 
292
                resultsReady();
 
293
        }
 
294
        else {
 
295
                if(!d->aaaa)
 
296
                        d->servers.remove(d->servers.begin());
 
297
                d->aaaa = !d->aaaa;
 
298
 
 
299
                // failed?  bail if last one
 
300
                if(d->servers.isEmpty()) {
 
301
                        stop();
 
302
                        resultsReady();
 
303
                        return;
 
304
                }
 
305
 
 
306
                // otherwise try the next
 
307
                tryNext();
 
308
        }
 
309
#endif
 
310
}
 
311
 
 
312
void SrvResolver::t_timeout()
 
313
{
 
314
        SafeDeleteLock s(&d->sd);
 
315
 
 
316
        stop();
 
317
        resultsReady();
 
318
}
 
319
 
 
320
// CS_NAMESPACE_END