KIO
hostinfo.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "hostinfo_p.h"
00022
00023 #include <kglobal.h>
00024 #include <QtCore/QString>
00025 #include <QtCore/QHash>
00026 #include <QtCore/QCache>
00027 #include <QtCore/QTime>
00028 #include <QtCore/QList>
00029 #include <QtCore/QPair>
00030 #include <QtCore/QFutureWatcher>
00031 #include <QtCore/QtConcurrentRun>
00032 #include <QtNetwork/QHostInfo>
00033 #include "kdebug.h"
00034
00035 #ifdef Q_OS_UNIX
00036 # include <QtCore/QFileInfo>
00037 # include <netinet/in.h>
00038 # include <arpa/nameser.h>
00039 # include <resolv.h>
00040 # ifndef _PATH_RESCONF
00041 # define _PATH_RESCONF "/etc/resolv.conf"
00042 # endif
00043 #endif
00044
00045 #define TTL 300
00046
00047 namespace KIO
00048 {
00049 class HostInfoAgentPrivate : public QObject
00050 {
00051 Q_OBJECT
00052 public:
00053 HostInfoAgentPrivate(int cacheSize = 100);
00054 virtual ~HostInfoAgentPrivate() {};
00055 void lookupHost(const QString& hostName, QObject* receiver, const char* member);
00056 void setCacheSize(int s) { dnsCache.setMaxCost(s); }
00057 void setTTL(int _ttl) { ttl = _ttl; }
00058 private slots:
00059 void queryFinished(const QHostInfo&);
00060 private:
00061 class Result;
00062 class Query;
00063
00064 QHash<QString, Query*> openQueries;
00065 QCache<QString, QPair<QHostInfo, QTime> > dnsCache;
00066 time_t resolvConfMTime;
00067 int ttl;
00068 };
00069
00070 class HostInfoAgentPrivate::Result : public QObject
00071 {
00072 Q_OBJECT
00073 signals:
00074 void result(QHostInfo);
00075 private:
00076 friend class HostInfoAgentPrivate;
00077 };
00078
00079 class HostInfoAgentPrivate::Query : public QObject
00080 {
00081 Q_OBJECT
00082 public:
00083 Query(): m_watcher(), m_hostName()
00084 {
00085 connect(&m_watcher, SIGNAL(finished()), this, SLOT(relayFinished()));
00086 }
00087 void start(const QString& hostName)
00088 {
00089 m_hostName = hostName;
00090 QFuture<QHostInfo> future = QtConcurrent::run(&QHostInfo::fromName, hostName);
00091 m_watcher.setFuture(future);
00092 }
00093 QString hostName() const
00094 {
00095 return m_hostName;
00096 }
00097 signals:
00098 void result(QHostInfo);
00099 private slots:
00100 void relayFinished()
00101 {
00102 emit result(m_watcher.result());
00103 }
00104 private:
00105 QFutureWatcher<QHostInfo> m_watcher;
00106 QString m_hostName;
00107 };
00108 }
00109
00110 using namespace KIO;
00111
00112 K_GLOBAL_STATIC(HostInfoAgentPrivate, hostInfoAgentPrivate)
00113
00114 void HostInfo::lookupHost(const QString& hostName, QObject* receiver,
00115 const char* member)
00116 {
00117 hostInfoAgentPrivate->lookupHost(hostName, receiver, member);
00118 }
00119
00120 void HostInfo::prefetchHost(const QString& hostName)
00121 {
00122 hostInfoAgentPrivate->lookupHost(hostName, 0, 0);
00123 }
00124
00125 void HostInfo::setCacheSize(int s)
00126 {
00127 hostInfoAgentPrivate->setCacheSize(s);
00128 }
00129
00130 void HostInfo::setTTL(int ttl)
00131 {
00132 hostInfoAgentPrivate->setTTL(ttl);
00133 }
00134
00135 HostInfoAgentPrivate::HostInfoAgentPrivate(int cacheSize)
00136 : openQueries(),
00137 dnsCache(cacheSize),
00138 resolvConfMTime(0),
00139 ttl(TTL)
00140 {}
00141
00142 void HostInfoAgentPrivate::lookupHost(const QString& hostName,
00143 QObject* receiver, const char* member)
00144 {
00145 #ifdef _PATH_RESCONF
00146 QFileInfo resolvConf(QFile::decodeName(_PATH_RESCONF));
00147 time_t currentMTime = resolvConf.lastModified().toTime_t();
00148 if (resolvConf.exists() && currentMTime != resolvConfMTime) {
00149
00150
00151 resolvConfMTime = currentMTime;
00152 dnsCache.clear();
00153 }
00154 #endif
00155
00156 if (QPair<QHostInfo, QTime>* info = dnsCache.object(hostName)) {
00157 if (QTime::currentTime() <= info->second.addSecs(ttl)) {
00158 Result result;
00159 if (receiver) {
00160 QObject::connect(&result, SIGNAL(result(QHostInfo)),receiver, member);
00161 emit result.result(info->first);
00162 }
00163 return;
00164 }
00165 dnsCache.remove(hostName);
00166 }
00167
00168 if (Query* query = openQueries.value(hostName)) {
00169 if (receiver) {
00170 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
00171 }
00172 return;
00173 }
00174
00175 Query* query = new Query();
00176 openQueries.insert(hostName, query);
00177 connect(query, SIGNAL(result(QHostInfo)), this, SLOT(queryFinished(QHostInfo)));
00178 if (receiver) {
00179 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
00180 }
00181 query->start(hostName);
00182 }
00183
00184 void HostInfoAgentPrivate::queryFinished(const QHostInfo& info)
00185 {
00186 Query* query = static_cast<Query* >(sender());
00187 openQueries.remove(query->hostName());
00188 if (info.error() == QHostInfo::NoError) {
00189 dnsCache.insert(query->hostName(),
00190 new QPair<QHostInfo, QTime>(info, QTime::currentTime()));
00191 }
00192 query->deleteLater();
00193 }
00194
00195 #include "hostinfo.moc"