1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-19 12:21:52 +02:00

Integrate qjdns/jdnsshared, make a shared library, and do some implementation

This commit is contained in:
Jeff Mitchell
2011-02-09 22:59:08 -05:00
parent 6c89dc4152
commit 2d11571812
27 changed files with 1357 additions and 1550 deletions

View File

@@ -258,6 +258,7 @@ set( libHeaders
playlist/dynamic/widgets/MiscControlWidgets.h
playlist/dynamic/widgets/CollapsibleControls.h
utils/tomahawkutils.h
utils/querylabel.h
utils/elidedlabel.h
utils/animatedcounterlabel.h
@@ -296,6 +297,9 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
../../qxt/qxtweb-standalone/qxtweb
../../rtaudio
../../alsa-playback
../../thirdparty/jdns
../../thirdparty/jdns/jdns
../../thirdparty/jdns/jdnsshared
playlist
)
@@ -359,7 +363,7 @@ target_link_libraries( tomahawklib
vorbisfile
ogg
FLAC++
jdns
tomahawk_jdns
clucene
)

View File

@@ -16,8 +16,11 @@
#ifdef Q_WS_MAC
#include <Carbon/Carbon.h>
#include <sys/sysctl.h>
#include <thirdparty/jdns/qjdns.h>
#endif
#include <qjdns.h>
#include <jdnsshared.h>
namespace TomahawkUtils
{
@@ -305,4 +308,62 @@ setProxy( QNetworkProxy* proxy )
s_proxy = proxy;
}
///////////////// DNSResolver /////////////////
static DNSResolver* s_dnsResolver = 0;
DNSResolver*
dnsResolver()
{
if( !s_dnsResolver )
s_dnsResolver = new DNSResolver();
return s_dnsResolver;
}
DNSResolver::DNSResolver()
{
m_dnsShared = new JDnsShared(JDnsShared::UnicastInternet);
m_dnsShared->addInterface(QHostAddress::Any);
m_dnsShared->addInterface(QHostAddress::AnyIPv6);
m_dnsSharedRequest = new JDnsSharedRequest(m_dnsShared);
}
void
DNSResolver::resolve( QString &host, QString &type )
{
connect(m_dnsSharedRequest, SIGNAL(resultsReady()), SLOT(resultsReady()));
if( type == "SRV" )
{
// For the moment, assume we are looking for XMPP...
m_dnsSharedRequest->query( "_xmpp-client._tcp." + host.toUtf8(), QJDns::Srv );
}
else
{
QString badResult( "NONE" );
emit result( badResult );
}
}
void
DNSResolver::resultsReady()
{
if( m_dnsSharedRequest->success() )
{
QList<QJDns::Record> results = m_dnsSharedRequest->results();
foreach( QJDns::Record r, results )
{
if( r.type == QJDns::Srv )
{
QString foundResult( r.name );
emit result( foundResult );
return;
}
}
}
QString badResult( "NONE" );
emit result( badResult );
}
} // ns

View File

@@ -2,6 +2,7 @@
#define TOMAHAWKUTILS_H
#include "dllmacro.h"
#include <QObject>
#define RESPATH ":/data/"
@@ -12,8 +13,31 @@ class QPixmap;
class QNetworkAccessManager;
class QNetworkProxy;
class JDnsShared;
class JDnsSharedRequest;
namespace TomahawkUtils
{
class DLLEXPORT DNSResolver : public QObject
{
Q_OBJECT
public:
explicit DNSResolver();
~DNSResolver() {}
void resolve( QString &host, QString &type );
signals:
void result( QString &result );
public slots:
void resultsReady();
private:
JDnsShared* m_dnsShared;
JDnsSharedRequest* m_dnsSharedRequest;
};
DLLEXPORT QDir appConfigDir();
DLLEXPORT QDir appDataDir();
@@ -28,6 +52,8 @@ namespace TomahawkUtils
DLLEXPORT void setNam( QNetworkAccessManager* nam );
DLLEXPORT void setProxy( QNetworkProxy* proxy );
DLLEXPORT DNSResolver* dnsResolver();
}
#endif // TOMAHAWKUTILS_H

View File

@@ -6,39 +6,46 @@ SET(CMAKE_VERBOSE_MAKEFILE ON)
SET( QT_USE_QTNETWORK TRUE )
INCLUDE( ${QT_USE_FILE} )
add_definitions( ${QT_DEFINITIONS} )
add_definitions( -DQT_SHARED )
if(WIN32)
SET(PLATFORM_SPECIFIC_LIBS "ws2_32.dll" "advapi32.dll" )
set(PLATFORM_SPECIFIC_LIBS "ws2_32.dll" "advapi32.dll" )
endif(WIN32)
set(JDNS_SOURCES
jdns_util.c
jdns_packet.c
jdns_mdnsd.c
jdns_sys.c
jdns.c
qjdns_sock.cpp
qjdns.cpp
set(TOMAHAWK_JDNS_SOURCES
jdns/jdns_util.c
jdns/jdns_packet.c
jdns/jdns_mdnsd.c
jdns/jdns_sys.c
jdns/jdns.c
jdns/qjdns_sock.cpp
jdns/qjdns.cpp
jdnsshared/jdnsshared.cpp
)
set(JDNS_HEADERS
qjdns.h
set(TOMAHAWK_JDNS_HEADERS
jdns/qjdns.h
jdns/qjdns_helpers.h
jdnsshared/jdnsshared.h
jdnsshared/jdnsshared_helpers.h
)
include_directories(
.
${QT_INCLUDE_DIR}
${QT_INCLUDES}
jdns
)
qt4_wrap_cpp( JDNS_MOC ${JDNS_HEADERS} )
qt4_wrap_cpp( TOMAHAWK_JDNS_MOC ${TOMAHAWK_JDNS_HEADERS} )
if(WIN32)
ADD_LIBRARY(jdns SHARED ${JDNS_SOURCES} ${JDNS_MOC})
else()
ADD_LIBRARY(jdns STATIC ${JDNS_SOURCES} ${JDNS_MOC})
endif()
ADD_LIBRARY(tomahawk_jdns SHARED ${TOMAHAWK_JDNS_SOURCES} ${TOMAHAWK_JDNS_MOC})
target_link_libraries(jdns
target_link_libraries(tomahawk_jdns
${QT_LIBRARIES}
)
INSTALL(TARGETS jdns ARCHIVE DESTINATION lib)
SET_TARGET_PROPERTIES( tomahawk_jdns PROPERTIES DEFINE_SYMBOL MAKE_JDNS_LIB )
INSTALL(TARGETS tomahawk_jdns DESTINATION lib)

638
thirdparty/jdns/jdns/qjdns.cpp vendored Normal file
View File

@@ -0,0 +1,638 @@
/*
* Copyright (C) 2005-2008 Justin Karneges
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "qjdns.h"
#include <time.h>
#include "qjdns_sock.h"
#include "qjdns_helpers.h"
#include "jdns.h"
// for fprintf
#include <stdio.h>
//----------------------------------------------------------------------------
// QJDns::NameServer
//----------------------------------------------------------------------------
QJDns::NameServer::NameServer()
{
port = JDNS_UNICAST_PORT;
}
//----------------------------------------------------------------------------
// QJDns::Record
//----------------------------------------------------------------------------
QJDns::Record::Record()
{
ttl = 0;
type = -1;
haveKnown = false;
}
bool QJDns::Record::verify() const
{
jdns_rr_t *rr = export_record(*this);
int ok = jdns_rr_verify(rr);
jdns_rr_delete(rr);
return (ok ? true : false);
}
//----------------------------------------------------------------------------
// QJDns
//----------------------------------------------------------------------------
QJDns::Private::Private(QJDns *_q) :
QObject(_q),
q(_q),
stepTrigger(this),
debugTrigger(this),
stepTimeout(this),
pErrors(0),
pPublished(0),
pResponses(0)
{
sess = 0;
shutting_down = false;
new_debug_strings = false;
pending = 0;
connect(&stepTrigger, SIGNAL(timeout()), SLOT(doNextStepSlot()));
stepTrigger.setSingleShot(true);
connect(&debugTrigger, SIGNAL(timeout()), SLOT(doDebug()));
debugTrigger.setSingleShot(true);
connect(&stepTimeout, SIGNAL(timeout()), SLOT(st_timeout()));
stepTimeout.setSingleShot(true);
my_srand();
clock.start();
}
QJDns::Private::~Private()
{
cleanup();
}
void QJDns::Private::cleanup()
{
if(sess)
{
jdns_session_delete(sess);
sess = 0;
}
shutting_down = false;
pending = 0;
// it is safe to delete the QUdpSocket objects here without
// deleteLater, since this code path never occurs when
// a signal from those objects is on the stack
qDeleteAll(socketForHandle);
socketForHandle.clear();
handleForSocket.clear();
stepTrigger.stop();
stepTimeout.stop();
need_handle = 0;
}
bool QJDns::Private::init(QJDns::Mode _mode, const QHostAddress &address)
{
mode = _mode;
jdns_callbacks_t callbacks;
callbacks.app = this;
callbacks.time_now = cb_time_now;
callbacks.rand_int = cb_rand_int;
callbacks.debug_line = cb_debug_line;
callbacks.udp_bind = cb_udp_bind;
callbacks.udp_unbind = cb_udp_unbind;
callbacks.udp_read = cb_udp_read;
callbacks.udp_write = cb_udp_write;
sess = jdns_session_new(&callbacks);
jdns_set_hold_ids_enabled(sess, 1);
next_handle = 1;
need_handle = false;
int ret;
jdns_address_t *baddr = qt2addr(address);
if(mode == Unicast)
{
ret = jdns_init_unicast(sess, baddr, 0);
}
else
{
jdns_address_t *maddr;
if(address.protocol() == QAbstractSocket::IPv6Protocol)
maddr = jdns_address_multicast6_new();
else
maddr = jdns_address_multicast4_new();
ret = jdns_init_multicast(sess, baddr, JDNS_MULTICAST_PORT, maddr);
jdns_address_delete(maddr);
}
jdns_address_delete(baddr);
if(!ret)
{
jdns_session_delete(sess);
sess = 0;
return false;
}
return true;
}
void QJDns::Private::setNameServers(const QList<NameServer> &nslist)
{
jdns_nameserverlist_t *addrs = jdns_nameserverlist_new();
for(int n = 0; n < nslist.count(); ++n)
{
jdns_address_t *addr = qt2addr(nslist[n].address);
jdns_nameserverlist_append(addrs, addr, nslist[n].port);
jdns_address_delete(addr);
}
jdns_set_nameservers(sess, addrs);
jdns_nameserverlist_delete(addrs);
}
void QJDns::Private::process()
{
if(!stepTrigger.isActive())
{
stepTimeout.stop();
stepTrigger.start();
}
}
void QJDns::Private::processDebug()
{
new_debug_strings = true;
if(!debugTrigger.isActive())
debugTrigger.start();
}
void QJDns::Private::doNextStep()
{
if(shutting_down && complete_shutdown)
{
cleanup();
emit q->shutdownFinished();
return;
}
QPointer<QObject> self = this;
int ret = jdns_step(sess);
QList<LateError> errors;
QList<int> published;
QList<LateResponse> responses;
bool finish_shutdown = false;
pErrors = &errors;
pPublished = &published;
pResponses = &responses;
while(1)
{
jdns_event_t *e = jdns_next_event(sess);
if(!e)
break;
if(e->type == JDNS_EVENT_SHUTDOWN)
{
finish_shutdown = true;
}
else if(e->type == JDNS_EVENT_PUBLISH)
{
if(e->status != JDNS_STATUS_SUCCESS)
{
QJDns::Error error;
if(e->status == JDNS_STATUS_CONFLICT)
error = QJDns::ErrorConflict;
else
error = QJDns::ErrorGeneric;
LateError le;
le.source_type = 1;
le.id = e->id;
le.error = error;
errors += le;
}
else
{
published += e->id;
}
}
else if(e->type == JDNS_EVENT_RESPONSE)
{
if(e->status != JDNS_STATUS_SUCCESS)
{
QJDns::Error error;
if(e->status == JDNS_STATUS_NXDOMAIN)
error = QJDns::ErrorNXDomain;
else if(e->status == JDNS_STATUS_TIMEOUT)
error = QJDns::ErrorTimeout;
else
error = QJDns::ErrorGeneric;
LateError le;
le.source_type = 0;
le.id = e->id;
le.error = error;
errors += le;
}
else
{
QJDns::Response out_response;
for(int n = 0; n < e->response->answerCount; ++n)
out_response.answerRecords += import_record(e->response->answerRecords[n]);
LateResponse lr;
lr.id = e->id;
lr.response = out_response;
if(mode == Unicast)
lr.do_cancel = true;
else
lr.do_cancel = false;
responses += lr;
}
}
jdns_event_delete(e);
}
if(ret & JDNS_STEP_TIMER)
stepTimeout.start(jdns_next_timer(sess));
else
stepTimeout.stop();
need_handle = (ret & JDNS_STEP_HANDLE);
// read the lists safely enough so that items can be deleted
// behind our back
while(!errors.isEmpty())
{
LateError i = errors.takeFirst();
if(i.source_type == 0)
jdns_cancel_query(sess, i.id);
else
jdns_cancel_publish(sess, i.id);
emit q->error(i.id, i.error);
if(!self)
return;
}
while(!published.isEmpty())
{
int i = published.takeFirst();
emit q->published(i);
if(!self)
return;
}
while(!responses.isEmpty())
{
LateResponse i = responses.takeFirst();
if(i.do_cancel)
jdns_cancel_query(sess, i.id);
emit q->resultsReady(i.id, i.response);
if(!self)
return;
}
if(finish_shutdown)
{
// if we have pending udp packets to write, stick around
if(pending > 0)
{
pending_wait = true;
}
else
{
complete_shutdown = true;
process();
}
}
pErrors = 0;
pPublished = 0;
pResponses = 0;
}
void QJDns::Private::removeCancelled(int id)
{
if(pErrors)
{
for(int n = 0; n < pErrors->count(); ++n)
{
if(pErrors->at(n).id == id)
{
pErrors->removeAt(n);
--n; // adjust position
}
}
}
if(pPublished)
{
for(int n = 0; n < pPublished->count(); ++n)
{
if(pPublished->at(n) == id)
{
pPublished->removeAt(n);
--n; // adjust position
}
}
}
if(pResponses)
{
for(int n = 0; n < pResponses->count(); ++n)
{
if(pResponses->at(n).id == id)
{
pResponses->removeAt(n);
--n; // adjust position
}
}
}
}
void QJDns::Private::udp_readyRead()
{
QUdpSocket *sock = (QUdpSocket *)sender();
int handle = handleForSocket.value(sock);
if(need_handle)
{
jdns_set_handle_readable(sess, handle);
process();
}
else
{
// eat packet
QByteArray buf(4096, 0);
QHostAddress from_addr;
quint16 from_port;
sock->readDatagram(buf.data(), buf.size(), &from_addr, &from_port);
}
}
void QJDns::Private::udp_bytesWritten(qint64)
{
if(pending > 0)
{
--pending;
if(shutting_down && pending_wait && pending == 0)
{
pending_wait = false;
complete_shutdown = true;
process();
}
}
}
void QJDns::Private::st_timeout()
{
doNextStep();
}
void QJDns::Private::doNextStepSlot()
{
doNextStep();
}
void QJDns::Private::doDebug()
{
if(new_debug_strings)
{
new_debug_strings = false;
if(!debug_strings.isEmpty())
emit q->debugLinesReady();
}
}
QJDns::QJDns(QObject *parent)
:QObject(parent)
{
d = new Private(this);
}
QJDns::~QJDns()
{
delete d;
}
bool QJDns::init(Mode mode, const QHostAddress &address)
{
return d->init(mode, address);
}
void QJDns::shutdown()
{
d->shutting_down = true;
d->pending_wait = false;
d->complete_shutdown = false;
jdns_shutdown(d->sess);
d->process();
}
QStringList QJDns::debugLines()
{
QStringList tmp = d->debug_strings;
d->debug_strings.clear();
return tmp;
}
QJDns::SystemInfo QJDns::systemInfo()
{
SystemInfo out;
jdns_dnsparams_t *params = jdns_system_dnsparams();
for(int n = 0; n < params->nameservers->count; ++n)
{
NameServer ns;
ns.address = addr2qt(params->nameservers->item[n]->address);
out.nameServers += ns;
}
for(int n = 0; n < params->domains->count; ++n)
out.domains += str2qt(params->domains->item[n]);
for(int n = 0; n < params->hosts->count; ++n)
{
DnsHost h;
h.name = str2qt(params->hosts->item[n]->name);
h.address = addr2qt(params->hosts->item[n]->address);
out.hosts += h;
}
jdns_dnsparams_delete(params);
return out;
}
#define PROBE_BASE 20000
#define PROBE_RANGE 100
QHostAddress QJDns::detectPrimaryMulticast(const QHostAddress &address)
{
my_srand();
QUdpSocket *sock = new QUdpSocket;
QUdpSocket::BindMode mode;
mode |= QUdpSocket::ShareAddress;
mode |= QUdpSocket::ReuseAddressHint;
int port = -1;
for(int n = 0; n < PROBE_RANGE; ++n)
{
if(sock->bind(address, PROBE_BASE + n, mode))
{
port = PROBE_BASE + n;
break;
}
}
if(port == -1)
{
delete sock;
return QHostAddress();
}
jdns_address_t *a;
if(address.protocol() == QAbstractSocket::IPv6Protocol)
a = jdns_address_multicast6_new();
else
a = jdns_address_multicast4_new();
QHostAddress maddr = addr2qt(a);
jdns_address_delete(a);
if(address.protocol() == QAbstractSocket::IPv6Protocol)
{
int x;
if(!qjdns_sock_setMulticast6(sock->socketDescriptor(), maddr.toIPv6Address().c, &x))
{
delete sock;
return QHostAddress();
}
qjdns_sock_setTTL6(sock->socketDescriptor(), 0);
}
else
{
int x;
if(!qjdns_sock_setMulticast4(sock->socketDescriptor(), maddr.toIPv4Address(), &x))
{
delete sock;
return QHostAddress();
}
qjdns_sock_setTTL4(sock->socketDescriptor(), 0);
}
QHostAddress result;
QByteArray out(128, 0);
for(int n = 0; n < out.size(); ++n)
out[n] = rand();
if(sock->writeDatagram(out.data(), out.size(), maddr, port) == -1)
{
delete sock;
return QHostAddress();
}
while(1)
{
if(!sock->waitForReadyRead(1000))
{
fprintf(stderr, "QJDns::detectPrimaryMulticast: timeout while checking %s\n", qPrintable(address.toString()));
delete sock;
return QHostAddress();
}
QByteArray in(128, 0);
QHostAddress from_addr;
quint16 from_port;
int ret = sock->readDatagram(in.data(), in.size(), &from_addr, &from_port);
if(ret == -1)
{
delete sock;
return QHostAddress();
}
if(from_port != port)
continue;
in.resize(ret);
if(in != out)
continue;
result = from_addr;
break;
}
delete sock;
return result;
}
void QJDns::setNameServers(const QList<NameServer> &list)
{
d->setNameServers(list);
}
int QJDns::queryStart(const QByteArray &name, int type)
{
int id = jdns_query(d->sess, (const unsigned char *)name.data(), type);
d->process();
return id;
}
void QJDns::queryCancel(int id)
{
jdns_cancel_query(d->sess, id);
d->removeCancelled(id);
d->process();
}
int QJDns::publishStart(PublishMode m, const Record &record)
{
jdns_rr_t *rr = export_record(record);
int pubmode;
if(m == QJDns::Unique)
pubmode = JDNS_PUBLISH_UNIQUE;
else
pubmode = JDNS_PUBLISH_SHARED;
int id = jdns_publish(d->sess, pubmode, rr);
jdns_rr_delete(rr);
d->process();
return id;
}
void QJDns::publishUpdate(int id, const Record &record)
{
jdns_rr_t *rr = export_record(record);
jdns_update_publish(d->sess, id, rr);
jdns_rr_delete(rr);
d->process();
}
void QJDns::publishCancel(int id)
{
jdns_cancel_publish(d->sess, id);
d->removeCancelled(id);
d->process();
}
//#include "qjdns.moc"

17
thirdparty/jdns/jdns_export.h vendored Normal file
View File

@@ -0,0 +1,17 @@
#ifndef JDNS_EXPORT_H
#define JDNS_EXPORT_H
#include <QtCore/QtGlobal>
#ifdef Q_WS_WIN
# if defined(MAKE_JDNS_LIB)
# define JDNS_EXPORT Q_DECL_EXPORT
# else
# define JDNS_EXPORT Q_DECL_IMPORT
# endif
#else
# define JDNS_EXPORT Q_DECL_EXPORT
#endif
#endif

View File

@@ -34,71 +34,18 @@
// on each interface. We don't do anything about this.
#include "jdnsshared.h"
namespace {
#include "jdns_export.h"
#include "jdnsshared_helpers.h"
// safeobj stuff, from qca
void releaseAndDeleteLater(QObject *owner, QObject *obj)
{
obj->disconnect(owner);
obj->setParent(0);
obj->deleteLater();
}
class SafeTimer : public QObject
{
Q_OBJECT
public:
SafeTimer(QObject *parent = 0) :
QObject(parent)
{
t = new QTimer(this);
connect(t, SIGNAL(timeout()), SIGNAL(timeout()));
}
~SafeTimer()
{
releaseAndDeleteLater(this, t);
}
int interval() const { return t->interval(); }
bool isActive() const { return t->isActive(); }
bool isSingleShot() const { return t->isSingleShot(); }
void setInterval(int msec) { t->setInterval(msec); }
void setSingleShot(bool singleShot) { t->setSingleShot(singleShot); }
int timerId() const { return t->timerId(); }
public slots:
void start(int msec) { t->start(msec); }
void start() { t->start(); }
void stop() { t->stop(); }
signals:
void timeout();
private:
QTimer *t;
};
// for caching system info
class SystemInfoCache
{
public:
QJDns::SystemInfo info;
QTime time;
};
}
Q_GLOBAL_STATIC(QMutex, jdnsshared_mutex)
Q_GLOBAL_STATIC(SystemInfoCache, jdnsshared_infocache)
static QJDns::SystemInfo get_sys_info()
{
QMutexLocker locker(jdnsshared_mutex());
SystemInfoCache *c = jdnsshared_infocache();
SystemInfoCache *c = jdnsshared_infocache();
// cache info for 1/2 second, enough to prevent re-reading of sys
// info 20 times because of all the different resolves
@@ -193,42 +140,6 @@ static QByteArray makeReverseName(const QHostAddress &addr)
return out;
}
//----------------------------------------------------------------------------
// Handle
//----------------------------------------------------------------------------
namespace {
// QJDns uses integer handle ids, but they are only unique within
// the relevant QJDns instance. Since we want our handles to be
// unique across all instances, we'll make an instance/id pair.
class Handle
{
public:
QJDns *jdns;
int id;
Handle() : jdns(0), id(-1)
{
}
Handle(QJDns *_jdns, int _id) : jdns(_jdns), id(_id)
{
}
bool operator==(const Handle &a) const
{
if(a.jdns == jdns && a.id == id)
return true;
return false;
}
bool operator!=(const Handle &a) const
{
return !(operator==(a));
}
};
// adapted from qHash<QPair>
static inline uint qHash(const Handle &key)
{
@@ -237,166 +148,122 @@ static inline uint qHash(const Handle &key)
return ((h1 << 16) | (h1 >> 16)) ^ h2;
}
JDnsShutdownAgent::JDnsShutdownAgent()
: QObject()
{
}
//----------------------------------------------------------------------------
// JDnsShutdown
//----------------------------------------------------------------------------
namespace {
class JDnsShutdownAgent : public QObject
void JDnsShutdownAgent::start()
{
Q_OBJECT
public:
void start()
{
QMetaObject::invokeMethod(this, "started", Qt::QueuedConnection);
}
signals:
void started();
};
class JDnsShutdownWorker : public QObject
{
Q_OBJECT
public:
QList<JDnsShared*> list;
JDnsShutdownWorker(const QList<JDnsShared*> &_list) : QObject(0), list(_list)
{
foreach(JDnsShared *i, list)
{
connect(i, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
i->shutdown(); // MUST support DOR-DS, and it does
}
}
signals:
void finished();
private slots:
void jdns_shutdownFinished()
{
JDnsShared *i = (JDnsShared *)sender();
list.removeAll(i);
delete i;
if(list.isEmpty())
emit finished();
}
};
class JDnsShutdown : public QThread
{
Q_OBJECT
public:
QMutex m;
QWaitCondition w;
QList<JDnsShared*> list;
JDnsShutdownAgent *agent;
JDnsShutdownWorker *worker;
int phase;
void waitForShutdown(const QList<JDnsShared*> &_list)
{
list = _list;
phase = 0;
m.lock();
start();
w.wait(&m);
foreach(JDnsShared *i, list)
{
i->setParent(0);
i->moveToThread(this);
}
phase = 1;
agent->start();
wait();
}
protected:
virtual void run()
{
m.lock();
agent = new JDnsShutdownAgent;
connect(agent, SIGNAL(started()), SLOT(agent_started()), Qt::DirectConnection);
agent->start();
exec();
delete agent;
}
private slots:
void agent_started()
{
if(phase == 0)
{
w.wakeOne();
m.unlock();
}
else
{
worker = new JDnsShutdownWorker(list);
connect(worker, SIGNAL(finished()), SLOT(worker_finished()), Qt::DirectConnection);
}
}
void worker_finished()
{
delete worker;
worker = 0;
quit();
}
};
QMetaObject::invokeMethod(this, "started", Qt::QueuedConnection);
}
//----------------------------------------------------------------------------
// JDnsSharedDebug
//----------------------------------------------------------------------------
class JDnsSharedDebugPrivate : public QObject
JDnsShutdownWorker::JDnsShutdownWorker(const QList<JDnsShared*> &_list) : QObject(0), list(_list)
{
Q_OBJECT
public:
JDnsSharedDebug *q;
QMutex m;
QStringList lines;
bool dirty;
JDnsSharedDebugPrivate(JDnsSharedDebug *_q) : QObject(_q), q(_q)
foreach(JDnsShared *i, list)
{
dirty = false;
connect(i, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
i->shutdown(); // MUST support DOR-DS, and it does
}
}
void JDnsShutdownWorker::jdns_shutdownFinished()
{
JDnsShared *i = (JDnsShared *)sender();
list.removeAll(i);
delete i;
if(list.isEmpty())
emit finished();
}
JDnsShutdown::JDnsShutdown()
: QThread()
{
}
void JDnsShutdown::waitForShutdown(const QList<JDnsShared*> &_list)
{
list = _list;
phase = 0;
m.lock();
start();
w.wait(&m);
foreach(JDnsShared *i, list)
{
i->setParent(0);
i->moveToThread(this);
}
void addDebug(const QString &name, const QStringList &_lines)
phase = 1;
agent->start();
wait();
}
void JDnsShutdown::run()
{
m.lock();
agent = new JDnsShutdownAgent;
connect(agent, SIGNAL(started()), SLOT(agent_started()), Qt::DirectConnection);
agent->start();
exec();
delete agent;
}
void JDnsShutdown::agent_started()
{
if(phase == 0)
{
if(!_lines.isEmpty())
w.wakeOne();
m.unlock();
}
else
{
worker = new JDnsShutdownWorker(list);
connect(worker, SIGNAL(finished()), SLOT(worker_finished()), Qt::DirectConnection);
}
}
void JDnsShutdown::worker_finished()
{
delete worker;
worker = 0;
quit();
}
JDnsSharedDebugPrivate::JDnsSharedDebugPrivate(JDnsSharedDebug *_q)
: QObject(_q), q(_q)
{
dirty = false;
}
void JDnsSharedDebugPrivate::addDebug(const QString &name, const QStringList &_lines)
{
if(!_lines.isEmpty())
{
QMutexLocker locker(&m);
for(int n = 0; n < _lines.count(); ++n)
lines += name + ": " + _lines[n];
if(!dirty)
{
QMutexLocker locker(&m);
for(int n = 0; n < _lines.count(); ++n)
lines += name + ": " + _lines[n];
if(!dirty)
{
dirty = true;
QMetaObject::invokeMethod(this, "doUpdate", Qt::QueuedConnection);
}
dirty = true;
QMetaObject::invokeMethod(this, "doUpdate", Qt::QueuedConnection);
}
}
}
private slots:
void doUpdate()
void JDnsSharedDebugPrivate::doUpdate()
{
{
{
QMutexLocker locker(&m);
if(!dirty)
return;
}
emit q->readyRead();
QMutexLocker locker(&m);
if(!dirty)
return;
}
};
emit q->readyRead();
}
JDnsSharedDebug::JDnsSharedDebug(QObject *parent)
:QObject(parent)
@@ -418,281 +285,195 @@ QStringList JDnsSharedDebug::readDebugLines()
return tmplines;
}
//----------------------------------------------------------------------------
// JDnsSharedRequest
//----------------------------------------------------------------------------
class JDnsSharedPrivate : public QObject
JDnsSharedPrivate::JDnsSharedPrivate(JDnsShared *_q)
: QObject(_q), q(_q)
{
Q_OBJECT
public:
class Instance
{
public:
QJDns *jdns;
QHostAddress addr;
int index;
}
Instance() : jdns(0)
JDnsSharedRequest *JDnsSharedPrivate::findRequest(QJDns *jdns, int id) const
{
Handle h(jdns, id);
return requestForHandle.value(h);
}
void JDnsSharedPrivate::jdns_link(QJDns *jdns)
{
connect(jdns, SIGNAL(resultsReady(int, const QJDns::Response &)), SLOT(jdns_resultsReady(int, const QJDns::Response &)));
connect(jdns, SIGNAL(published(int)), SLOT(jdns_published(int)));
connect(jdns, SIGNAL(error(int, QJDns::Error)), SLOT(jdns_error(int, QJDns::Error)));
connect(jdns, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
connect(jdns, SIGNAL(debugLinesReady()), SLOT(jdns_debugLinesReady()));
}
int JDnsSharedPrivate::getNewIndex() const
{
// find lowest unused value
for(int n = 0;; ++n)
{
bool found = false;
foreach(Instance *i, instances)
{
}
};
enum PreprocessMode
{
None, // don't muck with anything
FillInAddress, // for A/AAAA
FillInPtrOwner6, // for PTR, IPv6
FillInPtrOwner4, // for PTR, IPv4
};
JDnsShared *q;
JDnsShared::Mode mode;
bool shutting_down;
JDnsSharedDebug *db;
QString dbname;
QList<Instance*> instances;
QHash<QJDns*,Instance*> instanceForQJDns;
QSet<JDnsSharedRequest*> requests;
QHash<Handle,JDnsSharedRequest*> requestForHandle;
JDnsSharedPrivate(JDnsShared *_q) : QObject(_q), q(_q)
{
}
JDnsSharedRequest *findRequest(QJDns *jdns, int id) const
{
Handle h(jdns, id);
return requestForHandle.value(h);
}
void jdns_link(QJDns *jdns)
{
connect(jdns, SIGNAL(resultsReady(int, const QJDns::Response &)), SLOT(jdns_resultsReady(int, const QJDns::Response &)));
connect(jdns, SIGNAL(published(int)), SLOT(jdns_published(int)));
connect(jdns, SIGNAL(error(int, QJDns::Error)), SLOT(jdns_error(int, QJDns::Error)));
connect(jdns, SIGNAL(shutdownFinished()), SLOT(jdns_shutdownFinished()));
connect(jdns, SIGNAL(debugLinesReady()), SLOT(jdns_debugLinesReady()));
}
int getNewIndex() const
{
// find lowest unused value
for(int n = 0;; ++n)
{
bool found = false;
foreach(Instance *i, instances)
if(i->index == n)
{
if(i->index == n)
{
found = true;
break;
}
found = true;
break;
}
if(!found)
return n;
}
if(!found)
return n;
}
}
void JDnsSharedPrivate::addDebug(int index, const QString &line)
{
if(db)
db->d->addDebug(dbname + QString::number(index), QStringList() << line);
}
void JDnsSharedPrivate::doDebug(QJDns *jdns, int index)
{
QStringList lines = jdns->debugLines();
if(db)
db->d->addDebug(dbname + QString::number(index), lines);
}
JDnsSharedPrivate::PreprocessMode JDnsSharedPrivate::determinePpMode(const QJDns::Record &in)
{
// Note: since our implementation only allows 1 ipv4 and 1 ipv6
// interface to exist, it is safe to publish both kinds of
// records on both interfaces, with the same values. For
// example, an A record can be published on both interfaces,
// with the value set to the ipv4 interface. If we supported
// multiple ipv4 interfaces, then this wouldn't work, because
// we wouldn't know which value to use for the A record when
// publishing on the ipv6 interface.
// publishing our own IP address? null address means the user
// wants us to fill in the blank with our address.
if((in.type == QJDns::Aaaa || in.type == QJDns::A) && in.address.isNull())
{
return FillInAddress;
}
// publishing our own reverse lookup? partial owner means
// user wants us to fill in the rest.
else if(in.type == QJDns::Ptr && in.owner == ".ip6.arpa.")
{
return FillInPtrOwner6;
}
else if(in.type == QJDns::Ptr && in.owner == ".in-addr.arpa.")
{
return FillInPtrOwner4;
}
void addDebug(int index, const QString &line)
return None;
}
QJDns::Record JDnsSharedPrivate::manipulateRecord(const QJDns::Record &in, PreprocessMode ppmode, bool *modified)
{
if(ppmode == FillInAddress)
{
if(db)
db->d->addDebug(dbname + QString::number(index), QStringList() << line);
}
QJDns::Record out = in;
void doDebug(QJDns *jdns, int index)
{
QStringList lines = jdns->debugLines();
if(db)
db->d->addDebug(dbname + QString::number(index), lines);
}
PreprocessMode determinePpMode(const QJDns::Record &in)
{
// Note: since our implementation only allows 1 ipv4 and 1 ipv6
// interface to exist, it is safe to publish both kinds of
// records on both interfaces, with the same values. For
// example, an A record can be published on both interfaces,
// with the value set to the ipv4 interface. If we supported
// multiple ipv4 interfaces, then this wouldn't work, because
// we wouldn't know which value to use for the A record when
// publishing on the ipv6 interface.
// publishing our own IP address? null address means the user
// wants us to fill in the blank with our address.
if((in.type == QJDns::Aaaa || in.type == QJDns::A) && in.address.isNull())
if(in.type == QJDns::Aaaa)
{
return FillInAddress;
}
// publishing our own reverse lookup? partial owner means
// user wants us to fill in the rest.
else if(in.type == QJDns::Ptr && in.owner == ".ip6.arpa.")
{
return FillInPtrOwner6;
}
else if(in.type == QJDns::Ptr && in.owner == ".in-addr.arpa.")
{
return FillInPtrOwner4;
}
return None;
}
QJDns::Record manipulateRecord(const QJDns::Record &in, PreprocessMode ppmode, bool *modified = 0)
{
if(ppmode == FillInAddress)
{
QJDns::Record out = in;
if(in.type == QJDns::Aaaa)
{
// are we operating on ipv6?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
{
if(modified && !(out.address == i->addr))
*modified = true;
out.address = i->addr;
break;
}
}
}
else // A
{
// are we operating on ipv4?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv4Protocol)
{
if(modified && !(out.address == i->addr))
*modified = true;
out.address = i->addr;
break;
}
}
}
return out;
}
else if(ppmode == FillInPtrOwner6)
{
QJDns::Record out = in;
// are we operating on ipv6?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
{
QByteArray newOwner = makeReverseName(i->addr);
if(modified && !(out.owner == newOwner))
if(modified && !(out.address == i->addr))
*modified = true;
out.owner = newOwner;
out.address = i->addr;
break;
}
}
return out;
}
else if(ppmode == FillInPtrOwner4)
else // A
{
QJDns::Record out = in;
// are we operating on ipv4?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv4Protocol)
{
QByteArray newOwner = makeReverseName(i->addr);
if(modified && !(out.owner == newOwner))
if(modified && !(out.address == i->addr))
*modified = true;
out.owner = newOwner;
out.address = i->addr;
break;
}
}
return out;
}
if(modified)
*modified = false;
return in;
return out;
}
bool addInterface(const QHostAddress &addr);
void removeInterface(const QHostAddress &addr);
void queryStart(JDnsSharedRequest *obj, const QByteArray &name, int qType);
void queryCancel(JDnsSharedRequest *obj);
void publishStart(JDnsSharedRequest *obj, QJDns::PublishMode m, const QJDns::Record &record);
void publishUpdate(JDnsSharedRequest *obj, const QJDns::Record &record);
void publishCancel(JDnsSharedRequest *obj);
public slots:
void late_shutdown()
else if(ppmode == FillInPtrOwner6)
{
shutting_down = false;
emit q->shutdownFinished();
QJDns::Record out = in;
// are we operating on ipv6?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv6Protocol)
{
QByteArray newOwner = makeReverseName(i->addr);
if(modified && !(out.owner == newOwner))
*modified = true;
out.owner = newOwner;
break;
}
}
return out;
}
else if(ppmode == FillInPtrOwner4)
{
QJDns::Record out = in;
// are we operating on ipv4?
foreach(Instance *i, instances)
{
if(i->addr.protocol() == QAbstractSocket::IPv4Protocol)
{
QByteArray newOwner = makeReverseName(i->addr);
if(modified && !(out.owner == newOwner))
*modified = true;
out.owner = newOwner;
break;
}
}
return out;
}
private slots:
void jdns_resultsReady(int id, const QJDns::Response &results);
void jdns_published(int id);
void jdns_error(int id, QJDns::Error e);
void jdns_shutdownFinished();
void jdns_debugLinesReady();
};
if(modified)
*modified = false;
return in;
}
class JDnsSharedRequestPrivate : public QObject
void JDnsSharedPrivate::late_shutdown()
{
Q_OBJECT
public:
JDnsSharedRequest *q;
JDnsSharedPrivate *jsp;
shutting_down = false;
emit q->shutdownFinished();
}
// current action
JDnsSharedRequest::Type type;
QByteArray name;
int qType;
QJDns::PublishMode pubmode;
JDnsSharedPrivate::PreprocessMode ppmode;
QJDns::Record pubrecord;
JDnsSharedRequestPrivate::JDnsSharedRequestPrivate(JDnsSharedRequest *_q)
: QObject(_q), q(_q), lateTimer(this)
{
connect(&lateTimer, SIGNAL(timeout()), SLOT(lateTimer_timeout()));
}
// a single request might have to perform multiple QJDns operations
QList<Handle> handles;
void JDnsSharedRequestPrivate::resetSession()
{
name = QByteArray();
pubrecord = QJDns::Record();
handles.clear();
published.clear();
queryCache.clear();
}
// keep a list of handles that successfully publish
QList<Handle> published;
// use to weed out dups for multicast
QList<QJDns::Record> queryCache;
bool success;
JDnsSharedRequest::Error error;
QList<QJDns::Record> results;
SafeTimer lateTimer;
JDnsSharedRequestPrivate(JDnsSharedRequest *_q) : QObject(_q), q(_q), lateTimer(this)
{
connect(&lateTimer, SIGNAL(timeout()), SLOT(lateTimer_timeout()));
}
void resetSession()
{
name = QByteArray();
pubrecord = QJDns::Record();
handles.clear();
published.clear();
queryCache.clear();
}
private slots:
void lateTimer_timeout()
{
emit q->resultsReady();
}
};
void JDnsSharedRequestPrivate::lateTimer_timeout()
{
emit q->resultsReady();
}
JDnsSharedRequest::JDnsSharedRequest(JDnsShared *jdnsShared, QObject *parent)
:QObject(parent)
@@ -816,7 +597,7 @@ QList<QByteArray> JDnsShared::domains()
void JDnsShared::waitForShutdown(const QList<JDnsShared*> &instances)
{
JDnsShutdown s;
JDnsShutdown s;
s.waitForShutdown(instances);
}
@@ -920,7 +701,7 @@ bool JDnsSharedPrivate::addInterface(const QHostAddress &addr)
{
if(obj->d->type == JDnsSharedRequest::Query)
{
Handle h(i->jdns, i->jdns->queryStart(obj->d->name, obj->d->qType));
Handle h(i->jdns, i->jdns->queryStart(obj->d->name, obj->d->qType));
obj->d->handles += h;
requestForHandle.insert(h, obj);
}
@@ -936,7 +717,7 @@ bool JDnsSharedPrivate::addInterface(const QHostAddress &addr)
}
// publish the record on the new interface
Handle h(i->jdns, i->jdns->publishStart(obj->d->pubmode, obj->d->pubrecord));
Handle h(i->jdns, i->jdns->publishStart(obj->d->pubmode, obj->d->pubrecord));
obj->d->handles += h;
requestForHandle.insert(h, obj);
}
@@ -970,7 +751,7 @@ void JDnsSharedPrivate::removeInterface(const QHostAddress &addr)
{
for(int n = 0; n < obj->d->handles.count(); ++n)
{
Handle h = obj->d->handles[n];
Handle h = obj->d->handles[n];
if(h.jdns == i->jdns)
{
// see above, no need to cancel the operation
@@ -985,7 +766,7 @@ void JDnsSharedPrivate::removeInterface(const QHostAddress &addr)
{
for(int n = 0; n < obj->d->published.count(); ++n)
{
Handle h = obj->d->published[n];
Handle h = obj->d->published[n];
if(h.jdns == i->jdns)
{
obj->d->published.removeAt(n);
@@ -1135,7 +916,7 @@ void JDnsSharedPrivate::queryStart(JDnsSharedRequest *obj, const QByteArray &nam
// query on all jdns instances
foreach(Instance *i, instances)
{
Handle h(i->jdns, i->jdns->queryStart(name, qType));
Handle h(i->jdns, i->jdns->queryStart(name, qType));
obj->d->handles += h;
// keep track of this handle for this request
@@ -1181,7 +962,7 @@ void JDnsSharedPrivate::publishStart(JDnsSharedRequest *obj, QJDns::PublishMode
// attempt to publish on all jdns instances
foreach(JDnsSharedPrivate::Instance *i, instances)
{
Handle h(i->jdns, i->jdns->publishStart(m, obj->d->pubrecord));
Handle h(i->jdns, i->jdns->publishStart(m, obj->d->pubrecord));
obj->d->handles += h;
// keep track of this handle for this request
@@ -1232,7 +1013,7 @@ void JDnsSharedPrivate::jdns_resultsReady(int id, const QJDns::Response &results
// only one response, so "cancel" it
for(int n = 0; n < obj->d->handles.count(); ++n)
{
Handle h = obj->d->handles[n];
Handle h = obj->d->handles[n];
if(h.jdns == jdns && h.id == id)
{
obj->d->handles.removeAt(n);
@@ -1306,10 +1087,10 @@ void JDnsSharedPrivate::jdns_published(int id)
Q_ASSERT(obj);
// find handle
Handle handle;
Handle handle;
for(int n = 0; n < obj->d->handles.count(); ++n)
{
Handle h = obj->d->handles[n];
Handle h = obj->d->handles[n];
if(h.jdns == jdns && h.id == id)
{
handle = h;
@@ -1342,7 +1123,7 @@ void JDnsSharedPrivate::jdns_error(int id, QJDns::Error e)
// "cancel" it
for(int n = 0; n < obj->d->handles.count(); ++n)
{
Handle h = obj->d->handles[n];
Handle h = obj->d->handles[n];
if(h.jdns == jdns && h.id == id)
{
obj->d->handles.removeAt(n);
@@ -1416,5 +1197,3 @@ void JDnsSharedPrivate::jdns_debugLinesReady()
doDebug(jdns, instanceForQJDns.value(jdns)->index);
}
#include "jdnsshared.moc"

View File

@@ -73,7 +73,7 @@ public:
/**
\brief Destroys the object
*/
~JDnsSharedDebug();
virtual ~JDnsSharedDebug();
/**
\brief Read the available debug information

View File

@@ -0,0 +1,322 @@
/*
* Copyright (C) 2006-2008 Justin Karneges
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
// Note: JDnsShared supports multiple interfaces for multicast, but only one
// for IPv4 and one for IPv6. Sharing multiple interfaces of the same IP
// version for multicast is unfortunately not possible without reworking
// the jdns subsystem.
//
// The reason for this limitation is that in order to do multi-interface
// multicast, you have to do a single bind to Any, and then use special
// functions to determine which interface a packet came from and to
// specify which interface a packet should go out on. Again this is just
// not possible with the current system and the assumptions made by jdns.
// Note: When quering against multiple interfaces with multicast, it is
// possible that different answers for a unique record may be reported
// on each interface. We don't do anything about this.
#include "jdnsshared.h"
#include "jdns_export.h"
// safeobj stuff, from qca
class JDNS_EXPORT JDnsSharedSafeTimer : public QObject
{
Q_OBJECT
public:
void JDnsSharedReleaseAndDeleteLater(QObject *owner, QObject *obj)
{
obj->disconnect(owner);
obj->setParent(0);
obj->deleteLater();
}
JDnsSharedSafeTimer(QObject *parent = 0) :
QObject(parent)
{
t = new QTimer(this);
connect(t, SIGNAL(timeout()), SIGNAL(timeout()));
}
~JDnsSharedSafeTimer()
{
JDnsSharedReleaseAndDeleteLater(this, t);
}
int interval() const { return t->interval(); }
bool isActive() const { return t->isActive(); }
bool isSingleShot() const { return t->isSingleShot(); }
void setInterval(int msec) { t->setInterval(msec); }
void setSingleShot(bool singleShot) { t->setSingleShot(singleShot); }
int timerId() const { return t->timerId(); }
public slots:
void start(int msec) { t->start(msec); }
void start() { t->start(); }
void stop() { t->stop(); }
signals:
void timeout();
private:
QTimer *t;
};
// for caching system info
class SystemInfoCache
{
public:
QJDns::SystemInfo info;
QTime time;
};
//----------------------------------------------------------------------------
// Handle
//----------------------------------------------------------------------------
// QJDns uses integer handle ids, but they are only unique within
// the relevant QJDns instance. Since we want our handles to be
// unique across all instances, we'll make an instance/id pair.
class Handle
{
public:
QJDns *jdns;
int id;
Handle() : jdns(0), id(-1)
{
}
Handle(QJDns *_jdns, int _id) : jdns(_jdns), id(_id)
{
}
~Handle() {}
bool operator==(const Handle &a) const
{
if(a.jdns == jdns && a.id == id)
return true;
return false;
}
bool operator!=(const Handle &a) const
{
return !(operator==(a));
}
};
//----------------------------------------------------------------------------
// JDnsShutdown
//----------------------------------------------------------------------------
class JDnsShutdownAgent : public QObject
{
Q_OBJECT
public:
JDnsShutdownAgent();
~JDnsShutdownAgent() {}
void start();
signals:
void started();
};
class JDnsShutdownWorker : public QObject
{
Q_OBJECT
public:
QList<JDnsShared*> list;
JDnsShutdownWorker(const QList<JDnsShared*> &_list);
virtual ~JDnsShutdownWorker() {}
signals:
void finished();
private slots:
void jdns_shutdownFinished();
};
class JDnsShutdown : public QThread
{
Q_OBJECT
public:
QMutex m;
QWaitCondition w;
QList<JDnsShared*> list;
JDnsShutdownAgent *agent;
JDnsShutdownWorker *worker;
int phase;
JDnsShutdown();
~JDnsShutdown() {}
void waitForShutdown(const QList<JDnsShared*> &_list);
protected:
virtual void run();
private slots:
void agent_started();
void worker_finished();
};
//----------------------------------------------------------------------------
// JDnsSharedDebug
//----------------------------------------------------------------------------
class JDnsSharedDebugPrivate : public QObject
{
Q_OBJECT
public:
JDnsSharedDebug *q;
QMutex m;
QStringList lines;
bool dirty;
JDnsSharedDebugPrivate(JDnsSharedDebug *_q);
~JDnsSharedDebugPrivate() {}
void addDebug(const QString &name, const QStringList &_lines);
private slots:
void doUpdate();
};
//----------------------------------------------------------------------------
// JDnsSharedRequest
//----------------------------------------------------------------------------
class JDnsSharedPrivate : public QObject
{
Q_OBJECT
public:
class Instance
{
public:
QJDns *jdns;
QHostAddress addr;
int index;
Instance() : jdns(0)
{
}
};
enum PreprocessMode
{
None, // don't muck with anything
FillInAddress, // for A/AAAA
FillInPtrOwner6, // for PTR, IPv6
FillInPtrOwner4, // for PTR, IPv4
};
JDnsShared *q;
JDnsShared::Mode mode;
bool shutting_down;
JDnsSharedDebug *db;
QString dbname;
QList<Instance*> instances;
QHash<QJDns*,Instance*> instanceForQJDns;
QSet<JDnsSharedRequest*> requests;
QHash<Handle,JDnsSharedRequest*> requestForHandle;
JDnsSharedPrivate(JDnsShared *_q);
~JDnsSharedPrivate() {}
JDnsSharedRequest *findRequest(QJDns *jdns, int id) const;
void jdns_link(QJDns *jdns);
int getNewIndex() const;
void addDebug(int index, const QString &line);
void doDebug(QJDns *jdns, int index);
PreprocessMode determinePpMode(const QJDns::Record &in);
QJDns::Record manipulateRecord(const QJDns::Record &in, PreprocessMode ppmode, bool *modified = 0);
bool addInterface(const QHostAddress &addr);
void removeInterface(const QHostAddress &addr);
void queryStart(JDnsSharedRequest *obj, const QByteArray &name, int qType);
void queryCancel(JDnsSharedRequest *obj);
void publishStart(JDnsSharedRequest *obj, QJDns::PublishMode m, const QJDns::Record &record);
void publishUpdate(JDnsSharedRequest *obj, const QJDns::Record &record);
void publishCancel(JDnsSharedRequest *obj);
public slots:
void late_shutdown();
private slots:
void jdns_resultsReady(int id, const QJDns::Response &results);
void jdns_published(int id);
void jdns_error(int id, QJDns::Error e);
void jdns_shutdownFinished();
void jdns_debugLinesReady();
};
class JDnsSharedRequestPrivate : public QObject
{
Q_OBJECT
public:
JDnsSharedRequest *q;
JDnsSharedPrivate *jsp;
// current action
JDnsSharedRequest::Type type;
QByteArray name;
int qType;
QJDns::PublishMode pubmode;
JDnsSharedPrivate::PreprocessMode ppmode;
QJDns::Record pubrecord;
// a single request might have to perform multiple QJDns operations
QList<Handle> handles;
// keep a list of handles that successfully publish
QList<Handle> published;
// use to weed out dups for multicast
QList<QJDns::Record> queryCache;
bool success;
JDnsSharedRequest::Error error;
QList<QJDns::Record> results;
JDnsSharedSafeTimer lateTimer;
JDnsSharedRequestPrivate(JDnsSharedRequest *_q);
~JDnsSharedRequestPrivate() {};
void resetSession();
private slots:
void lateTimer_timeout();
};

File diff suppressed because it is too large Load Diff