KIO
hostinfo.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2008 Roland Harnau <tau@gmx.eu> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2.1 of the License, or (at your option) version 3, or any 00008 later version accepted by the membership of KDE e.V. (or its 00009 successor approved by the membership of KDE e.V.), which shall 00010 act as a proxy defined in Section 6 of version 3 of the license. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library. If not, see <http://www.gnu.org/licenses/>. 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> // for _PATH_RESCONF 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 // /etc/resolv.conf has been modified 00150 // clear our cache 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"
KDE 4.6 API Reference