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"
26
#include"safedelete.h"
34
static void sortSRVList(QValueList<QDns::Server> &list)
36
QValueList<QDns::Server> tmp = list;
39
while(!tmp.isEmpty()) {
40
QValueList<QDns::Server>::Iterator p = tmp.end();
41
for(QValueList<QDns::Server>::Iterator it = tmp.begin(); it != tmp.end(); ++it) {
45
int a = (*it).priority;
46
int b = (*p).priority;
49
if(a < b || (a == b && j < k))
58
class SrvResolver::Private
69
QHostAddress resultAddress;
74
QValueList<QDns::Server> servers;
81
SrvResolver::SrvResolver(QObject *parent)
88
connect(&d->ndns, SIGNAL(resultsReady()), SLOT(ndns_done()));
90
connect(&d->t, SIGNAL(timeout()), SLOT(t_timeout()));
94
SrvResolver::~SrvResolver()
100
void SrvResolver::resolve(const QString &server, const QString &type, const QString &proto)
106
d->srv = QString("_") + type + "._" + proto + '.' + server;
107
d->t.start(15000, true);
109
connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
110
d->qdns->setRecordType(QDns::Srv);
111
d->qdns->setLabel(d->srv);
114
void SrvResolver::resolveSrvOnly(const QString &server, const QString &type, const QString &proto)
120
d->srv = QString("_") + type + "._" + proto + '.' + server;
121
d->t.start(15000, true);
123
connect(d->qdns, SIGNAL(resultsReady()), SLOT(qdns_done()));
124
d->qdns->setRecordType(QDns::Srv);
125
d->qdns->setLabel(d->srv);
128
void SrvResolver::next()
130
if(d->servers.isEmpty())
136
void SrvResolver::stop()
141
d->qdns->disconnect(this);
142
d->sd.deleteLater(d->qdns);
149
d->resultAddress = QHostAddress();
156
bool SrvResolver::isBusy() const
159
if(d->qdns || d->ndns.isBusy())
168
QValueList<QDns::Server> SrvResolver::servers() const
173
bool SrvResolver::failed() const
178
QHostAddress SrvResolver::resultAddress() const
180
return d->resultAddress;
183
Q_UINT16 SrvResolver::resultPort() const
185
return d->resultPort;
188
void SrvResolver::tryNext()
191
d->ndns.resolve(d->servers.first().name);
194
connect(d->qdns, SIGNAL(resultsReady()), SLOT(ndns_done()));
196
d->qdns->setRecordType(QDns::Aaaa); // IPv6
198
d->qdns->setRecordType(QDns::A); // IPv4
199
d->qdns->setLabel(d->servers.first().name);
203
void SrvResolver::qdns_done()
208
// apparently we sometimes get this signal even though the results aren't ready
209
if(d->qdns->isWorking())
213
SafeDeleteLock s(&d->sd);
215
// grab the server list and destroy the qdns object
216
QValueList<QDns::Server> list;
217
if(d->qdns->recordType() == QDns::Srv)
218
list = d->qdns->servers();
219
d->qdns->disconnect(this);
220
d->sd.deleteLater(d->qdns);
240
void SrvResolver::ndns_done()
243
SafeDeleteLock s(&d->sd);
245
uint r = d->ndns.result();
246
int port = d->servers.first().port;
247
d->servers.remove(d->servers.begin());
250
d->resultAddress = QHostAddress(d->ndns.result());
251
d->resultPort = port;
255
// failed? bail if last one
256
if(d->servers.isEmpty()) {
262
// otherwise try the next
269
// apparently we sometimes get this signal even though the results aren't ready
270
if(d->qdns->isWorking())
273
SafeDeleteLock s(&d->sd);
275
// grab the address list and destroy the qdns object
276
QValueList<QHostAddress> list;
277
if(d->qdns->recordType() == QDns::A || d->qdns->recordType() == QDns::Aaaa)
278
list = d->qdns->addresses();
279
d->qdns->disconnect(this);
280
d->sd.deleteLater(d->qdns);
283
if(!list.isEmpty()) {
284
int port = d->servers.first().port;
285
d->servers.remove(d->servers.begin());
288
d->resultAddress = list.first();
289
d->resultPort = port;
294
d->servers.remove(d->servers.begin());
297
// failed? bail if last one
298
if(d->servers.isEmpty()) {
304
// otherwise try the next
310
void SrvResolver::t_timeout()
312
SafeDeleteLock s(&d->sd);