2
* Copyright (C) 2006,2007 Justin Karneges
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
// Note: JDnsShared supports multiple interfaces for multicast, but only one
22
// for IPv4 and one for IPv6. Sharing multiple interfaces of the same IP
23
// version for multicast is unfortunately not possible without reworking
24
// the jdns subsystem.
26
// The reason for this limitation is that in order to do multi-interface
27
// multicast, you have to do a single bind to Any, and then use special
28
// functions to determine which interface a packet came from and to
29
// specify which interface a packet should go out on. Again this is just
30
// not possible with the current system and the assumptions made by jdns.
32
// Note: When quering against multiple interfaces with multicast, it is
33
// possible that different answers for a unique record may be reported
34
// on each interface. We don't do anything about this.
36
#include "jdnsshared.h"
43
QJDns::SystemInfo info;
49
Q_GLOBAL_STATIC(QMutex, jdnsshared_mutex)
50
Q_GLOBAL_STATIC(SystemInfoCache, jdnsshared_infocache)
52
static QJDns::SystemInfo get_sys_info()
54
QMutexLocker locker(jdnsshared_mutex());
55
SystemInfoCache *c = jdnsshared_infocache();
57
// cache info for 1/2 second, enough to prevent re-reading of sys
58
// info 20 times because of all the different resolves
59
if(c->time.isNull() || c->time.elapsed() >= 500)
61
c->info = QJDns::systemInfo();
68
static bool domainCompare(const QByteArray &a, const QByteArray &b)
70
return (qstricmp(a.data(), b.data()) == 0) ? true: false;
73
// adapted from jdns_mdnsd.c, _a_match()
74
static bool matchRecordExceptTtl(const QJDns::Record &a, const QJDns::Record &b)
76
if(a.type != b.type || !domainCompare(a.owner, b.owner))
79
if(a.type == QJDns::Srv)
81
if(domainCompare(a.name, b.name)
83
&& a.priority == b.priority
84
&& a.weight == b.weight)
89
else if(a.type == QJDns::Ptr || a.type == QJDns::Ns || a.type == QJDns::Cname)
91
if(domainCompare(a.name, b.name))
94
else if(a.rdata == b.rdata)
100
//----------------------------------------------------------------------------
102
//----------------------------------------------------------------------------
106
// QJDns uses integer handle ids, but they are only unique within
107
// the relevant QJDns instance. Since we want our handles to be
108
// unique across all instances, we'll make an instance/id pair.
115
Handle() : jdns(0), id(-1)
119
Handle(QJDns *_jdns, int _id) : jdns(_jdns), id(_id)
123
bool operator==(const Handle &a) const
125
if(a.jdns == jdns && a.id == id)
130
bool operator!=(const Handle &a) const
132
return !(operator==(a));
138
inline uint qHash(const Handle &key)
140
return ((uint)key.jdns) ^ key.id;
143
//----------------------------------------------------------------------------
145
//----------------------------------------------------------------------------
148
class JDnsShutdownAgent : public QObject
154
QMetaObject::invokeMethod(this, "started", Qt::QueuedConnection);
161
class JDnsShutdown : public QThread
167
QList<JDnsShared*> list;
168
JDnsShutdownAgent *agent;
171
void waitForShutdown(const QList<JDnsShared*> _list)
180
foreach(JDnsShared *i, list)
183
i->moveToThread(this);
195
agent = new JDnsShutdownAgent;
196
connect(agent, SIGNAL(started()), SLOT(agent_started()), Qt::DirectConnection);
212
foreach(JDnsShared *i, list)
214
connect(i, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()), Qt::DirectConnection);
220
void jdns_shutdownFinished()
222
JDnsShared *i = (JDnsShared *)sender();
232
//----------------------------------------------------------------------------
234
//----------------------------------------------------------------------------
235
class JDnsSharedDebugPrivate : public QObject
244
JDnsSharedDebugPrivate(JDnsSharedDebug *_q) : QObject(_q), q(_q)
249
void addDebug(const QString &name, const QStringList &_lines)
251
if(!_lines.isEmpty())
253
QMutexLocker locker(&m);
254
for(int n = 0; n < _lines.count(); ++n)
255
lines += name + ": " + _lines[n];
259
QMetaObject::invokeMethod(this, "doUpdate", Qt::QueuedConnection);
268
QMutexLocker locker(&m);
276
JDnsSharedDebug::JDnsSharedDebug(QObject *parent)
279
d = new JDnsSharedDebugPrivate(this);
282
JDnsSharedDebug::~JDnsSharedDebug()
287
QStringList JDnsSharedDebug::readDebugLines()
289
QMutexLocker locker(&d->m);
290
QStringList tmplines = d->lines;
296
//----------------------------------------------------------------------------
298
//----------------------------------------------------------------------------
299
class JDnsSharedPrivate : public QObject
316
JDnsShared::Mode mode;
321
QList<Instance*> instances;
322
QHash<QJDns*,Instance*> instanceForQJDns;
324
QSet<JDnsSharedRequest*> requests;
325
QHash<Handle,JDnsSharedRequest*> requestForHandle;
327
JDnsSharedPrivate(JDnsShared *_q) : QObject(_q), q(_q)
331
JDnsSharedRequest *findRequest(QJDns *jdns, int id) const
334
return requestForHandle.value(h);
337
void jdns_link(QJDns *jdns)
339
connect(jdns, SIGNAL(resultsReady(int, const QJDns::Response &)), SLOT(jdns_resultsReady(int, const QJDns::Response &)));
340
connect(jdns, SIGNAL(published(int)), SLOT(jdns_published(int)));
341
connect(jdns, SIGNAL(error(int, QJDns::Error)), SLOT(jdns_error(int, QJDns::Error)));
342
connect(jdns, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
343
connect(jdns, SIGNAL(debugLinesReady()), SLOT(jdns_debugLinesReady()));
346
int getNewIndex() const
348
// find lowest unused value
352
foreach(Instance *i, instances)
365
void addDebug(int index, const QString &line)
368
db->d->addDebug(dbname + QString::number(index), QStringList() << line);
371
void doDebug(QJDns *jdns, int index)
373
QStringList lines = jdns->debugLines();
375
db->d->addDebug(dbname + QString::number(index), lines);
378
QJDns::Record manipulateRecord(const QJDns::Record &in)
380
// Note: since our implementation only allows 1 ipv4 and 1 ipv6
381
// interface to exist, it is safe to publish both kinds of
382
// records on both interfaces, with the same values. For
383
// example, an A record can be published on both interfaces,
384
// with the value set to the ipv4 interface. If we supported
385
// multiple ipv4 interfaces, then this wouldn't work, because
386
// we wouldn't know which value to use for the A record when
387
// publishing on the ipv6 interface.
389
// publishing our own IP address? null address means the user
390
// wants us to fill in the blank with our address.
391
if((in.type == QJDns::Aaaa || in.type == QJDns::A) && in.address.isNull())
393
QJDns::Record out = in;
394
if(in.type == QJDns::Aaaa)
396
// are we operating on ipv6?
397
foreach(Instance *i, instances)
399
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
401
out.address = i->addr;
408
// are we operating on ipv4?
409
foreach(Instance *i, instances)
411
if(i->addr.protocol() == QAbstractSocket::IPv4Protocol)
413
out.address = i->addr;
423
bool addInterface(const QHostAddress &addr);
424
void removeInterface(const QHostAddress &addr);
426
void queryStart(JDnsSharedRequest *obj, const QByteArray &name, int qType);
427
void queryCancel(JDnsSharedRequest *obj);
428
void publishStart(JDnsSharedRequest *obj, QJDns::PublishMode m, const QJDns::Record &record);
429
void publishUpdate(JDnsSharedRequest *obj, const QJDns::Record &record);
430
void publishCancel(JDnsSharedRequest *obj);
435
shutting_down = false;
436
emit q->shutdownFinished();
440
void jdns_resultsReady(int id, const QJDns::Response &results);
441
void jdns_published(int id);
442
void jdns_error(int id, QJDns::Error e);
443
void jdns_shutdownFinished();
444
void jdns_debugLinesReady();
447
class JDnsSharedRequestPrivate : public QObject
451
JDnsSharedRequest *q;
452
JDnsSharedPrivate *jsp;
455
JDnsSharedRequest::Type type;
458
QJDns::PublishMode pubmode;
459
QJDns::Record pubrecord;
461
// a single request might have to perform multiple QJDns operations
462
QList<Handle> handles;
464
// keep a list of handles that successfully publish
465
QList<Handle> published;
467
// use to weed out dups for multicast
468
QList<QJDns::Record> queryCache;
471
JDnsSharedRequest::Error error;
472
QList<QJDns::Record> results;
475
JDnsSharedRequestPrivate(JDnsSharedRequest *_q) : QObject(_q), q(_q), lateTimer(this)
477
connect(&lateTimer, SIGNAL(timeout()), SLOT(lateTimer_timeout()));
483
pubrecord = QJDns::Record();
490
void lateTimer_timeout()
492
emit q->resultsReady();
496
JDnsSharedRequest::JDnsSharedRequest(JDnsShared *jdnsShared, QObject *parent)
499
d = new JDnsSharedRequestPrivate(this);
500
d->jsp = jdnsShared->d;
503
JDnsSharedRequest::~JDnsSharedRequest()
509
JDnsSharedRequest::Type JDnsSharedRequest::type()
514
void JDnsSharedRequest::query(const QByteArray &name, int type)
517
d->jsp->queryStart(this, name, type);
520
void JDnsSharedRequest::publish(QJDns::PublishMode m, const QJDns::Record &record)
523
d->jsp->publishStart(this, m, record);
526
void JDnsSharedRequest::publishUpdate(const QJDns::Record &record)
528
// only allowed to update if we have an active publish
529
if(!d->handles.isEmpty() && d->type == Publish)
530
d->jsp->publishUpdate(this, record);
533
void JDnsSharedRequest::cancel()
536
if(!d->handles.isEmpty())
539
d->jsp->queryCancel(this);
541
d->jsp->publishCancel(this);
546
bool JDnsSharedRequest::success() const
551
JDnsSharedRequest::Error JDnsSharedRequest::error() const
556
QList<QJDns::Record> JDnsSharedRequest::results() const
561
//----------------------------------------------------------------------------
563
//----------------------------------------------------------------------------
564
JDnsShared::JDnsShared(Mode mode, QObject *parent)
567
d = new JDnsSharedPrivate(this);
569
d->shutting_down = false;
573
JDnsShared::~JDnsShared()
575
foreach(JDnsSharedPrivate::Instance *i, d->instances)
583
void JDnsShared::setDebug(JDnsSharedDebug *db, const QString &name)
589
bool JDnsShared::addInterface(const QHostAddress &addr)
591
return d->addInterface(addr);
594
void JDnsShared::removeInterface(const QHostAddress &addr)
596
d->removeInterface(addr);
599
void JDnsShared::shutdown()
601
d->shutting_down = true;
602
if(!d->instances.isEmpty())
604
foreach(JDnsSharedPrivate::Instance *i, d->instances)
608
QMetaObject::invokeMethod(d, "late_shutdown", Qt::QueuedConnection);
611
QList<QByteArray> JDnsShared::domains()
613
return get_sys_info().domains;
616
void JDnsShared::waitForShutdown(const QList<JDnsShared*> instances)
619
s.waitForShutdown(instances);
622
bool JDnsSharedPrivate::addInterface(const QHostAddress &addr)
627
// make sure we don't have this one already
628
foreach(Instance *i, instances)
634
int index = getNewIndex();
635
addDebug(index, QString("attempting to use interface %1").arg(addr.toString()));
639
if(mode == JDnsShared::UnicastInternet || mode == JDnsShared::UnicastLocal)
641
jdns = new QJDns(this);
643
if(!jdns->init(QJDns::Unicast, addr))
645
doDebug(jdns, index);
650
if(mode == JDnsShared::UnicastLocal)
652
QJDns::NameServer host;
653
host.address = QHostAddress("224.0.0.251");
655
jdns->setNameServers(QList<QJDns::NameServer>() << host);
660
// only one multicast interface allowed per IP protocol version.
661
// this is because we bind to INADDR_ANY.
663
bool have_v6 = false;
664
bool have_v4 = false;
665
foreach(Instance *i, instances)
667
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
673
bool is_v6 = (addr.protocol() == QAbstractSocket::IPv6Protocol) ? true : false;
677
addDebug(index, "already have an ipv6 interface");
681
if(!is_v6 && have_v4)
683
addDebug(index, "already have an ipv4 interface");
687
QHostAddress actualBindAddress;
689
actualBindAddress = QHostAddress::AnyIPv6;
691
actualBindAddress = QHostAddress::Any;
693
jdns = new QJDns(this);
695
if(!jdns->init(QJDns::Multicast, actualBindAddress))
697
doDebug(jdns, index);
703
Instance *i = new Instance;
708
instanceForQJDns.insert(i->jdns, i);
710
addDebug(index, "interface ready");
712
if(mode == JDnsShared::Multicast)
714
// extend active requests to this interface
715
foreach(JDnsSharedRequest *obj, requests)
717
if(obj->d->type == JDnsSharedRequest::Query)
719
Handle h(i->jdns, i->jdns->queryStart(obj->d->name, obj->d->qType));
720
obj->d->handles += h;
721
requestForHandle.insert(h, obj);
725
Handle h(i->jdns, i->jdns->publishStart(obj->d->pubmode, obj->d->pubrecord));
726
obj->d->handles += h;
727
requestForHandle.insert(h, obj);
735
void JDnsSharedPrivate::removeInterface(const QHostAddress &addr)
738
for(int n = 0; n < instances.count(); ++n)
740
if(instances[n]->addr == addr)
749
int index = i->index;
751
// we don't cancel operations or shutdown jdns, we simply
752
// delete our references. this is because if the interface
753
// is gone, then we have nothing to send on anyway.
755
foreach(JDnsSharedRequest *obj, requests)
757
for(int n = 0; n < obj->d->handles.count(); ++n)
759
Handle h = obj->d->handles[n];
760
if(h.jdns == i->jdns)
762
// see above, no need to cancel the operation
763
obj->d->handles.removeAt(n);
764
requestForHandle.remove(h);
769
// remove published reference
770
if(obj->d->type == JDnsSharedRequest::Publish)
772
for(int n = 0; n < obj->d->published.count(); ++n)
774
Handle h = obj->d->published[n];
775
if(h.jdns == i->jdns)
777
obj->d->published.removeAt(n);
784
// see above, no need to shutdown jdns
785
instanceForQJDns.remove(i->jdns);
786
instances.removeAll(i);
790
// if that was the last interface to be removed, then there should
791
// be no more handles left. let's take action with these
792
// handleless requests.
793
foreach(JDnsSharedRequest *obj, requests)
795
if(obj->d->handles.isEmpty())
797
if(mode == JDnsShared::UnicastInternet || mode == JDnsShared::UnicastLocal)
799
// for unicast, we'll invalidate with ErrorNoNet
800
obj->d->success = false;
801
obj->d->error = JDnsSharedRequest::ErrorNoNet;
802
obj->d->lateTimer.start();
806
// for multicast, we'll keep all requests alive.
807
// activity will resume when an interface is
813
addDebug(index, QString("removing from %1").arg(addr.toString()));
816
void JDnsSharedPrivate::queryStart(JDnsSharedRequest *obj, const QByteArray &name, int qType)
818
obj->d->type = JDnsSharedRequest::Query;
819
obj->d->success = false;
820
obj->d->results.clear();
822
obj->d->qType = qType;
824
// is the input an IP address and the qType is an address record?
825
if(qType == QJDns::Aaaa || qType == QJDns::A)
828
if(addr.setAddress(QString::fromLocal8Bit(name)))
830
if(qType == QJDns::Aaaa && addr.protocol() == QAbstractSocket::IPv6Protocol)
834
rec.type = QJDns::Aaaa;
836
rec.haveKnown = true;
838
obj->d->success = true;
839
obj->d->results = QList<QJDns::Record>() << rec;
840
obj->d->lateTimer.start();
843
else if(qType == QJDns::A && addr.protocol() == QAbstractSocket::IPv4Protocol)
849
rec.haveKnown = true;
851
obj->d->success = true;
852
obj->d->results = QList<QJDns::Record>() << rec;
853
obj->d->lateTimer.start();
859
QJDns::SystemInfo sysInfo = get_sys_info();
861
// is the input name a known host and the qType is an address record?
862
if(qType == QJDns::Aaaa || qType == QJDns::A)
864
QByteArray lname = name.toLower();
865
QList<QJDns::DnsHost> known = sysInfo.hosts;
866
foreach(QJDns::DnsHost host, known)
868
if(((qType == QJDns::Aaaa && host.address.protocol() == QAbstractSocket::IPv6Protocol)
869
|| (qType == QJDns::A && host.address.protocol() == QAbstractSocket::IPv4Protocol))
870
&& host.name.toLower() == lname)
876
rec.haveKnown = true;
877
rec.address = host.address;
878
obj->d->success = true;
879
obj->d->results = QList<QJDns::Record>() << rec;
880
obj->d->lateTimer.start();
886
// if we have no QJDns instances to operate on, then error
887
if(instances.isEmpty())
889
obj->d->error = JDnsSharedRequest::ErrorNoNet;
890
obj->d->lateTimer.start();
894
if(mode == JDnsShared::UnicastInternet)
896
// get latest nameservers, split into ipv6/v4, apply to jdns instances
897
QList<QJDns::NameServer> ns_v6;
898
QList<QJDns::NameServer> ns_v4;
900
QList<QJDns::NameServer> nameServers = sysInfo.nameServers;
901
foreach(QJDns::NameServer ns, nameServers)
903
if(ns.address.protocol() == QAbstractSocket::IPv6Protocol)
909
foreach(Instance *i, instances)
911
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
912
i->jdns->setNameServers(ns_v6);
914
i->jdns->setNameServers(ns_v4);
918
// keep track of this request
921
// query on all jdns instances
922
foreach(Instance *i, instances)
924
Handle h(i->jdns, i->jdns->queryStart(name, qType));
925
obj->d->handles += h;
927
// keep track of this handle for this request
928
requestForHandle.insert(h, obj);
932
void JDnsSharedPrivate::queryCancel(JDnsSharedRequest *obj)
934
if(!requests.contains(obj))
937
foreach(Handle h, obj->d->handles)
939
h.jdns->queryCancel(h.id);
940
requestForHandle.remove(h);
943
obj->d->handles.clear();
944
requests.remove(obj);
947
void JDnsSharedPrivate::publishStart(JDnsSharedRequest *obj, QJDns::PublishMode m, const QJDns::Record &record)
949
obj->d->type = JDnsSharedRequest::Publish;
950
obj->d->success = false;
951
obj->d->results.clear();
953
obj->d->pubrecord = manipulateRecord(record);
955
// if we have no QJDns instances to operate on, then error
956
if(instances.isEmpty())
958
obj->d->error = JDnsSharedRequest::ErrorNoNet;
959
obj->d->lateTimer.start();
963
// keep track of this request
966
// attempt to publish on all jdns instances
967
foreach(JDnsSharedPrivate::Instance *i, instances)
969
Handle h(i->jdns, i->jdns->publishStart(m, obj->d->pubrecord));
970
obj->d->handles += h;
972
// keep track of this handle for this request
973
requestForHandle.insert(h, obj);
977
void JDnsSharedPrivate::publishUpdate(JDnsSharedRequest *obj, const QJDns::Record &record)
979
if(!requests.contains(obj))
982
obj->d->pubrecord = manipulateRecord(record);
984
// publish update on all handles for this request
985
foreach(Handle h, obj->d->handles)
986
h.jdns->publishUpdate(h.id, obj->d->pubrecord);
989
void JDnsSharedPrivate::publishCancel(JDnsSharedRequest *obj)
991
if(!requests.contains(obj))
994
foreach(Handle h, obj->d->handles)
996
h.jdns->publishCancel(h.id);
997
requestForHandle.remove(h);
1000
obj->d->handles.clear();
1001
obj->d->published.clear();
1002
requests.remove(obj);
1005
void JDnsSharedPrivate::jdns_resultsReady(int id, const QJDns::Response &results)
1007
QJDns *jdns = (QJDns *)sender();
1008
JDnsSharedRequest *obj = findRequest(jdns, id);
1010
obj->d->success = true;
1011
obj->d->results = results.answerRecords;
1013
if(mode == JDnsShared::UnicastInternet || mode == JDnsShared::UnicastLocal)
1015
// only one response, so "cancel" it
1016
for(int n = 0; n < obj->d->handles.count(); ++n)
1018
Handle h = obj->d->handles[n];
1019
if(h.jdns == jdns && h.id == id)
1021
obj->d->handles.removeAt(n);
1022
requestForHandle.remove(h);
1027
// cancel related handles
1028
foreach(Handle h, obj->d->handles)
1030
h.jdns->queryCancel(h.id);
1031
requestForHandle.remove(h);
1034
obj->d->handles.clear();
1035
requests.remove(obj);
1039
// check our cache to see how we should report these results
1040
for(int n = 0; n < obj->d->results.count(); ++n)
1042
QJDns::Record &r = obj->d->results[n];
1044
// do we have this answer already in our cache?
1045
QJDns::Record *c = 0;
1047
for(int k = 0; k < obj->d->queryCache.count(); ++k)
1049
QJDns::Record &tmp = obj->d->queryCache[k];
1050
if(matchRecordExceptTtl(r, tmp))
1058
// don't report duplicates or unknown removals
1059
if((c && r.ttl != 0) || (!c && r.ttl == 0))
1061
obj->d->results.removeAt(n);
1062
--n; // adjust position
1066
// if we have it, and it is removed, remove from cache
1069
obj->d->queryCache.removeAt(c_at);
1071
// otherwise, if we don't have it, add it to the cache
1074
obj->d->queryCache += r;
1078
if(obj->d->results.isEmpty())
1082
emit obj->resultsReady();
1085
void JDnsSharedPrivate::jdns_published(int id)
1087
QJDns *jdns = (QJDns *)sender();
1088
JDnsSharedRequest *obj = findRequest(jdns, id);
1092
for(int n = 0; n < obj->d->handles.count(); ++n)
1094
Handle h = obj->d->handles[n];
1095
if(h.jdns == jdns && h.id == id)
1102
obj->d->published += handle;
1104
// if this publish has already been considered successful, then
1105
// a publish has succeeded on a new interface and there's no
1106
// need to report success for this request again
1110
// all handles published?
1111
if(obj->d->published.count() == obj->d->handles.count())
1113
obj->d->success = true;
1114
emit obj->resultsReady();
1118
void JDnsSharedPrivate::jdns_error(int id, QJDns::Error e)
1120
QJDns *jdns = (QJDns *)sender();
1121
JDnsSharedRequest *obj = findRequest(jdns, id);
1124
for(int n = 0; n < obj->d->handles.count(); ++n)
1126
Handle h = obj->d->handles[n];
1127
if(h.jdns == jdns && h.id == id)
1129
obj->d->handles.removeAt(n);
1130
requestForHandle.remove(h);
1135
if(obj->d->type == JDnsSharedRequest::Query)
1137
// ignore the error if it is not the last error
1138
if(!obj->d->handles.isEmpty())
1141
requests.remove(obj);
1143
obj->d->success = false;
1144
JDnsSharedRequest::Error x = JDnsSharedRequest::ErrorGeneric;
1145
if(e == QJDns::ErrorNXDomain)
1146
x = JDnsSharedRequest::ErrorNXDomain;
1147
else if(e == QJDns::ErrorTimeout)
1148
x = JDnsSharedRequest::ErrorTimeout;
1149
else // ErrorGeneric
1150
x = JDnsSharedRequest::ErrorGeneric;
1152
emit obj->resultsReady();
1156
// cancel related handles
1157
foreach(Handle h, obj->d->handles)
1159
h.jdns->publishCancel(h.id);
1160
requestForHandle.remove(h);
1163
obj->d->handles.clear();
1164
obj->d->published.clear();
1165
requests.remove(obj);
1167
obj->d->success = false;
1168
JDnsSharedRequest::Error x = JDnsSharedRequest::ErrorGeneric;
1169
if(e == QJDns::ErrorConflict)
1170
x = JDnsSharedRequest::ErrorConflict;
1171
else // ErrorGeneric
1172
x = JDnsSharedRequest::ErrorGeneric;
1174
emit obj->resultsReady();
1178
void JDnsSharedPrivate::jdns_shutdownFinished()
1180
QJDns *jdns = (QJDns *)sender();
1182
addDebug(instanceForQJDns.value(jdns)->index, "jdns_shutdownFinished, removing interface");
1184
Instance *instance = instanceForQJDns.value(jdns);
1185
delete instance->jdns;
1187
instanceForQJDns.remove(jdns);
1188
instances.removeAll(instance);
1190
if(instances.isEmpty())
1194
void JDnsSharedPrivate::jdns_debugLinesReady()
1196
QJDns *jdns = (QJDns *)sender();
1198
doDebug(jdns, instanceForQJDns.value(jdns)->index);
1201
#include "jdnsshared.moc"