24 #include <QtCore/QString>
25 #include <QtCore/QHash>
26 #include <QtCore/QCache>
27 #include <QtCore/QMetaType>
28 #include <QtCore/QTime>
29 #include <QtCore/QTimer>
30 #include <QtCore/QList>
31 #include <QtCore/QPair>
32 #include <QtCore/QThread>
33 #include <QtCore/QFutureWatcher>
34 #include <QtCore/QSemaphore>
35 #include <QtCore/QSharedPointer>
36 #include <QtCore/QtConcurrentRun>
37 #include <QtNetwork/QHostInfo>
41 # include <QtCore/QFileInfo>
42 # include <netinet/in.h>
43 # include <arpa/nameser.h>
45 # ifndef _PATH_RESCONF
46 # define _PATH_RESCONF "/etc/resolv.conf"
56 class HostInfoAgentPrivate :
public QObject
60 HostInfoAgentPrivate(
int cacheSize = 100);
61 virtual ~HostInfoAgentPrivate() {};
66 void setTTL(
int _ttl) { ttl = _ttl; }
68 void queryFinished(
const QHostInfo&);
74 QCache<QString, QPair<QHostInfo, QTime> > dnsCache;
75 time_t resolvConfMTime;
79 class HostInfoAgentPrivate::Result :
public QObject
83 void result(QHostInfo);
85 friend class HostInfoAgentPrivate;
88 class HostInfoAgentPrivate::Query :
public QObject
92 Query(): m_watcher(), m_hostName()
94 connect(&m_watcher, SIGNAL(finished()),
this, SLOT(relayFinished()));
96 void start(
const QString& hostName)
98 m_hostName = hostName;
100 m_watcher.setFuture(future);
107 void result(QHostInfo);
111 emit result(m_watcher.result());
114 QFutureWatcher<QHostInfo> m_watcher;
118 class NameLookupThreadRequest
121 NameLookupThreadRequest(
const QString& hostName) : m_hostName(hostName)
125 QSemaphore *semaphore()
130 QHostInfo result()
const
135 void setResult(
const QHostInfo& hostInfo)
137 m_hostInfo = hostInfo;
150 void setLookupId(
int id)
156 Q_DISABLE_COPY(NameLookupThreadRequest)
158 QSemaphore m_semaphore;
159 QHostInfo m_hostInfo;
163 class NameLookUpThreadWorker :
public QObject
167 void lookupHost(
const QSharedPointer<NameLookupThreadRequest>& request)
169 const QString hostName = request->hostName();
171 request->setLookupId(lookupId);
172 m_lookups.insert(lookupId, request);
175 void abortLookup(
const QSharedPointer<NameLookupThreadRequest>& request)
177 QHostInfo::abortHostLookup(request->lookupId());
178 m_lookups.remove(request->lookupId());
181 void lookupFinished(
const QHostInfo &hostInfo)
184 if (it != m_lookups.end()) {
185 (*it)->setResult(hostInfo);
186 (*it)->semaphore()->release();
195 class NameLookUpThread :
public QThread
199 NameLookUpThread () : m_worker(0)
201 qRegisterMetaType< QSharedPointer<NameLookupThreadRequest> > (
"QSharedPointer<NameLookupThreadRequest>");
211 NameLookUpThreadWorker *worker()
216 QSemaphore *semaphore()
223 NameLookUpThreadWorker worker;
225 m_semaphore.release();
230 NameLookUpThreadWorker *m_worker;
231 QSemaphore m_semaphore;
238 K_GLOBAL_STATIC(NameLookUpThread, nameLookUpThread)
243 hostInfoAgentPrivate->lookupHost(hostName, receiver, member);
249 QHostAddress address (hostName);
251 if (!address.isNull()) {
253 addressList << address;
254 hostInfo.setAddresses(addressList);
260 if (!hostInfo.hostName().isEmpty() && hostInfo.error() == QHostInfo::NoError) {
265 QSharedPointer<NameLookupThreadRequest> request = QSharedPointer<NameLookupThreadRequest>(
new NameLookupThreadRequest(hostName));
266 nameLookUpThread->semaphore()->acquire();
267 nameLookUpThread->semaphore()->release();
268 QMetaObject::invokeMethod(nameLookUpThread->worker(),
"lookupHost", Qt::QueuedConnection, Q_ARG(QSharedPointer<NameLookupThreadRequest>, request));
269 if (request->semaphore()->tryAcquire(1, timeout)) {
270 hostInfo = request->result();
271 if (!hostInfo.hostName().isEmpty() && hostInfo.error() == QHostInfo::NoError) {
275 QMetaObject::invokeMethod(nameLookUpThread->worker(),
"abortLookup", Qt::QueuedConnection, Q_ARG(QSharedPointer<NameLookupThreadRequest>, request));
284 return hostInfoAgentPrivate->lookupCachedHostInfoFor(hostName);
289 hostInfoAgentPrivate->cacheLookup(info);
294 hostInfoAgentPrivate->lookupHost(hostName, 0, 0);
299 hostInfoAgentPrivate->setCacheSize(s);
304 hostInfoAgentPrivate->setTTL(ttl);
307 HostInfoAgentPrivate::HostInfoAgentPrivate(
int cacheSize)
315 QObject* receiver,
const char* member)
319 time_t currentMTime = resolvConf.lastModified().toTime_t();
320 if (resolvConf.exists() && currentMTime != resolvConfMTime) {
323 resolvConfMTime = currentMTime;
329 if (QTime::currentTime() <= info->second.addSecs(ttl)) {
332 QObject::connect(&result, SIGNAL(result(QHostInfo)),receiver, member);
333 emit result.result(info->first);
337 dnsCache.remove(hostName);
340 if (Query* query = openQueries.value(hostName)) {
342 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
347 Query* query =
new Query();
348 openQueries.insert(hostName, query);
349 connect(query, SIGNAL(result(QHostInfo)),
this, SLOT(queryFinished(QHostInfo)));
351 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
353 query->start(hostName);
359 if (info && info->second.addSecs(ttl) >= QTime::currentTime())
367 if (info.hostName().isEmpty())
370 if (info.error() != QHostInfo::NoError)
376 void HostInfoAgentPrivate::queryFinished(
const QHostInfo& info)
378 Query* query =
static_cast<Query*
>(sender());
379 openQueries.remove(query->hostName());
380 if (info.error() == QHostInfo::NoError) {
381 dnsCache.insert(query->hostName(),
384 query->deleteLater();
387 #include "hostinfo.moc"
#define K_GLOBAL_STATIC(TYPE, NAME)
void lookupHost(const QString &hostName, QObject *receiver, const char *member)
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
void cacheLookup(const QHostInfo &info)
QHostInfo lookupCachedHostInfoFor(const QString &hostName)
KAction * quit(const QObject *recvr, const char *slot, QObject *parent)
void prefetchHost(const QString &hostName)
static int dummyHostInfoMetaType