2
* srvresolver.cpp - class to simplify SRV lookups
3
* Copyright (C) 2003 Justin Karneges
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.
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.
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
21
#include "srvresolver.h"
23
#include <q3cstring.h>
28
#include "safedelete.h"
36
static void sortSRVList(QList<Q3Dns::Server> &list)
38
QList<Q3Dns::Server> tmp = list;
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) {
47
int a = (*it).priority;
48
int b = (*p).priority;
51
if(a < b || (a == b && j < k))
60
class SrvResolver::Private
71
QHostAddress resultAddress;
76
QList<Q3Dns::Server> servers;
83
SrvResolver::SrvResolver(QObject *parent)
90
connect(&d->ndns, SIGNAL(resultsReady()), SLOT(ndns_done()));
92
connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout()));
96
SrvResolver::~SrvResolver()
102
void SrvResolver::resolve(const QString &server, const QString &type, const QString &proto)
108
d->srv = QString("_") + type + "._" + proto + '.' + server;
109
d->t.start(15000, true);
111
connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
112
d->qdns->setRecordType(Q3Dns::Srv);
113
d->qdns->setLabel(d->srv);
116
void SrvResolver::resolveSrvOnly(const QString &server, const QString &type, const QString &proto)
122
d->srv = QString("_") + type + "._" + proto + '.' + server;
123
d->t.start(15000, true);
125
connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
126
d->qdns->setRecordType(Q3Dns::Srv);
127
d->qdns->setLabel(d->srv);
130
void SrvResolver::next()
132
if(d->servers.isEmpty())
138
void SrvResolver::stop()
143
d->qdns->disconnect(this);
144
d->sd.deleteLater(d->qdns);
151
d->resultAddress = QHostAddress();
158
bool SrvResolver::isBusy() const
161
if(d->qdns || d->ndns.isBusy())
170
QList<Q3Dns::Server> SrvResolver::servers() const
175
bool SrvResolver::failed() const
180
QHostAddress SrvResolver::resultAddress() const
182
return d->resultAddress;
185
Q_UINT16 SrvResolver::resultPort() const
187
return d->resultPort;
190
void SrvResolver::tryNext()
193
d->ndns.resolve(d->servers.first().name);
196
connect(d->qdns, SIGNAL(resultsReady()), SLOT(ndns_done()));
198
d->qdns->setRecordType(Q3Dns::Aaaa); // IPv6
200
d->qdns->setRecordType(Q3Dns::A); // IPv4
201
d->qdns->setLabel(d->servers.first().name);
205
void SrvResolver::qdns_done()
210
// apparently we sometimes get this signal even though the results aren't ready
211
if(d->qdns->isWorking())
215
SafeDeleteLock s(&d->sd);
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);
242
void SrvResolver::ndns_done()
245
SafeDeleteLock s(&d->sd);
247
QHostAddress r = d->ndns.result();
248
int port = d->servers.first().port;
249
d->servers.remove(d->servers.begin());
252
d->resultAddress = d->ndns.result();
253
d->resultPort = port;
257
// failed? bail if last one
258
if(d->servers.isEmpty()) {
264
// otherwise try the next
271
// apparently we sometimes get this signal even though the results aren't ready
272
if(d->qdns->isWorking())
275
SafeDeleteLock s(&d->sd);
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);
285
if(!list.isEmpty()) {
286
int port = d->servers.first().port;
287
d->servers.remove(d->servers.begin());
290
d->resultAddress = list.first();
291
d->resultPort = port;
296
d->servers.remove(d->servers.begin());
299
// failed? bail if last one
300
if(d->servers.isEmpty()) {
306
// otherwise try the next
312
void SrvResolver::t_timeout()
314
SafeDeleteLock s(&d->sd);