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>
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;
99 QFuture<QHostInfo> future = QtConcurrent::run(&QHostInfo::fromName, hostName);
100 m_watcher.setFuture(future);
102 QString hostName()
const
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;
140 QString hostName()
const
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();
170 const int lookupId = QHostInfo::lookupHost(hostName,
this, SLOT(lookupFinished(QHostInfo)));
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;
240void HostInfo::lookupHost(const QString& hostName,
QObject* receiver,
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);
307HostInfoAgentPrivate::HostInfoAgentPrivate(
int cacheSize)
314void HostInfoAgentPrivate::lookupHost(
const QString& hostName,
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);
356QHostInfo HostInfoAgentPrivate::lookupCachedHostInfoFor(
const QString& hostName)
359 if (info && info->second.addSecs(ttl) >= QTime::currentTime())
365void HostInfoAgentPrivate::cacheLookup(
const QHostInfo& info)
367 if (info.hostName().isEmpty())
370 if (info.error() != QHostInfo::NoError)
376void 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)
static int dummyHostInfoMetaType
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
QHostInfo lookupCachedHostInfoFor(const QString &hostName)
void prefetchHost(const QString &hostName)
void cacheLookup(const QHostInfo &info)
void lookupHost(const QString &hostName, QObject *receiver, const char *member)
A namespace for KIO globals.
KAction * quit(const QObject *recvr, const char *slot, QObject *parent)