• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
hostinfo.cpp
Go to the documentation of this file.
1/*
2Copyright 2008 Roland Harnau <tau@gmx.eu>
3
4This library is free software; you can redistribute it and/or
5modify it under the terms of the GNU Lesser General Public
6License as published by the Free Software Foundation; either
7version 2.1 of the License, or (at your option) version 3, or any
8later version accepted by the membership of KDE e.V. (or its
9successor approved by the membership of KDE e.V.), which shall
10act as a proxy defined in Section 6 of version 3 of the license.
11
12This library is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public
18License along with this library. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "hostinfo_p.h"
22
23#include <kglobal.h>
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>
38#include "kdebug.h"
39
40#ifdef Q_OS_UNIX
41# include <QtCore/QFileInfo>
42# include <netinet/in.h>
43# include <arpa/nameser.h>
44# include <resolv.h> // for _PATH_RESCONF
45# ifndef _PATH_RESCONF
46# define _PATH_RESCONF "/etc/resolv.conf"
47# endif
48#endif
49
50#define TTL 300
51
52static int dummyHostInfoMetaType = qRegisterMetaType<QHostInfo>("QHostInfo");
53
54namespace KIO
55{
56 class HostInfoAgentPrivate : public QObject
57 {
58 Q_OBJECT
59 public:
60 HostInfoAgentPrivate(int cacheSize = 100);
61 virtual ~HostInfoAgentPrivate() {};
62 void lookupHost(const QString& hostName, QObject* receiver, const char* member);
63 QHostInfo lookupCachedHostInfoFor(const QString& hostName);
64 void cacheLookup(const QHostInfo&);
65 void setCacheSize(int s) { dnsCache.setMaxCost(s); }
66 void setTTL(int _ttl) { ttl = _ttl; }
67 private slots:
68 void queryFinished(const QHostInfo&);
69 private:
70 class Result;
71 class Query;
72
73 QHash<QString, Query*> openQueries;
74 QCache<QString, QPair<QHostInfo, QTime> > dnsCache;
75 time_t resolvConfMTime;
76 int ttl;
77 };
78
79 class HostInfoAgentPrivate::Result : public QObject
80 {
81 Q_OBJECT
82 signals:
83 void result(QHostInfo);
84 private:
85 friend class HostInfoAgentPrivate;
86 };
87
88 class HostInfoAgentPrivate::Query : public QObject
89 {
90 Q_OBJECT
91 public:
92 Query(): m_watcher(), m_hostName()
93 {
94 connect(&m_watcher, SIGNAL(finished()), this, SLOT(relayFinished()));
95 }
96 void start(const QString& hostName)
97 {
98 m_hostName = hostName;
99 QFuture<QHostInfo> future = QtConcurrent::run(&QHostInfo::fromName, hostName);
100 m_watcher.setFuture(future);
101 }
102 QString hostName() const
103 {
104 return m_hostName;
105 }
106 signals:
107 void result(QHostInfo);
108 private slots:
109 void relayFinished()
110 {
111 emit result(m_watcher.result());
112 }
113 private:
114 QFutureWatcher<QHostInfo> m_watcher;
115 QString m_hostName;
116 };
117
118 class NameLookupThreadRequest
119 {
120 public:
121 NameLookupThreadRequest(const QString& hostName) : m_hostName(hostName)
122 {
123 }
124
125 QSemaphore *semaphore()
126 {
127 return &m_semaphore;
128 }
129
130 QHostInfo result() const
131 {
132 return m_hostInfo;
133 }
134
135 void setResult(const QHostInfo& hostInfo)
136 {
137 m_hostInfo = hostInfo;
138 }
139
140 QString hostName() const
141 {
142 return m_hostName;
143 }
144
145 int lookupId() const
146 {
147 return m_lookupId;
148 }
149
150 void setLookupId(int id)
151 {
152 m_lookupId = id;
153 }
154
155 private:
156 Q_DISABLE_COPY(NameLookupThreadRequest)
157 QString m_hostName;
158 QSemaphore m_semaphore;
159 QHostInfo m_hostInfo;
160 int m_lookupId;
161 };
162
163 class NameLookUpThreadWorker : public QObject
164 {
165 Q_OBJECT
166 public slots:
167 void lookupHost(const QSharedPointer<NameLookupThreadRequest>& request)
168 {
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);
173 }
174
175 void abortLookup(const QSharedPointer<NameLookupThreadRequest>& request)
176 {
177 QHostInfo::abortHostLookup(request->lookupId());
178 m_lookups.remove(request->lookupId());
179 }
180
181 void lookupFinished(const QHostInfo &hostInfo)
182 {
183 QMap<int, QSharedPointer<NameLookupThreadRequest> >::iterator it = m_lookups.find(hostInfo.lookupId());
184 if (it != m_lookups.end()) {
185 (*it)->setResult(hostInfo);
186 (*it)->semaphore()->release();
187 m_lookups.erase(it);
188 }
189 }
190
191 private:
192 QMap<int, QSharedPointer<NameLookupThreadRequest> > m_lookups;
193 };
194
195 class NameLookUpThread : public QThread
196 {
197 Q_OBJECT
198 public:
199 NameLookUpThread () : m_worker(0)
200 {
201 qRegisterMetaType< QSharedPointer<NameLookupThreadRequest> > ("QSharedPointer<NameLookupThreadRequest>");
202 start();
203 }
204
205 ~NameLookUpThread ()
206 {
207 quit();
208 wait();
209 }
210
211 NameLookUpThreadWorker *worker()
212 {
213 return m_worker;
214 }
215
216 QSemaphore *semaphore()
217 {
218 return &m_semaphore;
219 }
220
221 void run()
222 {
223 NameLookUpThreadWorker worker;
224 m_worker = &worker;
225 m_semaphore.release();
226 exec();
227 }
228
229 private:
230 NameLookUpThreadWorker *m_worker;
231 QSemaphore m_semaphore;
232 };
233}
234
235using namespace KIO;
236
237K_GLOBAL_STATIC(HostInfoAgentPrivate, hostInfoAgentPrivate)
238K_GLOBAL_STATIC(NameLookUpThread, nameLookUpThread)
239
240void HostInfo::lookupHost(const QString& hostName, QObject* receiver,
241 const char* member)
242{
243 hostInfoAgentPrivate->lookupHost(hostName, receiver, member);
244}
245
246QHostInfo HostInfo::lookupHost(const QString& hostName, unsigned long timeout)
247{
248 // Do not perform a reverse lookup here...
249 QHostAddress address (hostName);
250 QHostInfo hostInfo;
251 if (!address.isNull()) {
252 QList<QHostAddress> addressList;
253 addressList << address;
254 hostInfo.setAddresses(addressList);
255 return hostInfo;
256 }
257
258 // Look up the name in the KIO/KHTML DNS cache...
259 hostInfo = HostInfo::lookupCachedHostInfoFor(hostName);
260 if (!hostInfo.hostName().isEmpty() && hostInfo.error() == QHostInfo::NoError) {
261 return hostInfo;
262 }
263
264 // Failing all of the above, do the lookup...
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) {
272 HostInfo::cacheLookup(hostInfo); // cache the look up...
273 }
274 } else {
275 QMetaObject::invokeMethod(nameLookUpThread->worker(), "abortLookup", Qt::QueuedConnection, Q_ARG(QSharedPointer<NameLookupThreadRequest>, request));
276 }
277
278 //kDebug(7022) << "Name look up succeeded for" << hostName;
279 return hostInfo;
280}
281
282QHostInfo HostInfo::lookupCachedHostInfoFor(const QString& hostName)
283{
284 return hostInfoAgentPrivate->lookupCachedHostInfoFor(hostName);
285}
286
287void HostInfo::cacheLookup(const QHostInfo& info)
288{
289 hostInfoAgentPrivate->cacheLookup(info);
290}
291
292void HostInfo::prefetchHost(const QString& hostName)
293{
294 hostInfoAgentPrivate->lookupHost(hostName, 0, 0);
295}
296
297void HostInfo::setCacheSize(int s)
298{
299 hostInfoAgentPrivate->setCacheSize(s);
300}
301
302void HostInfo::setTTL(int ttl)
303{
304 hostInfoAgentPrivate->setTTL(ttl);
305}
306
307HostInfoAgentPrivate::HostInfoAgentPrivate(int cacheSize)
308 : openQueries(),
309 dnsCache(cacheSize),
310 resolvConfMTime(0),
311 ttl(TTL)
312{}
313
314void HostInfoAgentPrivate::lookupHost(const QString& hostName,
315 QObject* receiver, const char* member)
316{
317#ifdef _PATH_RESCONF
318 QFileInfo resolvConf(QFile::decodeName(_PATH_RESCONF));
319 time_t currentMTime = resolvConf.lastModified().toTime_t();
320 if (resolvConf.exists() && currentMTime != resolvConfMTime) {
321 // /etc/resolv.conf has been modified
322 // clear our cache
323 resolvConfMTime = currentMTime;
324 dnsCache.clear();
325 }
326#endif
327
328 if (QPair<QHostInfo, QTime>* info = dnsCache.object(hostName)) {
329 if (QTime::currentTime() <= info->second.addSecs(ttl)) {
330 Result result;
331 if (receiver) {
332 QObject::connect(&result, SIGNAL(result(QHostInfo)),receiver, member);
333 emit result.result(info->first);
334 }
335 return;
336 }
337 dnsCache.remove(hostName);
338 }
339
340 if (Query* query = openQueries.value(hostName)) {
341 if (receiver) {
342 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
343 }
344 return;
345 }
346
347 Query* query = new Query();
348 openQueries.insert(hostName, query);
349 connect(query, SIGNAL(result(QHostInfo)), this, SLOT(queryFinished(QHostInfo)));
350 if (receiver) {
351 connect(query, SIGNAL(result(QHostInfo)), receiver, member);
352 }
353 query->start(hostName);
354}
355
356QHostInfo HostInfoAgentPrivate::lookupCachedHostInfoFor(const QString& hostName)
357{
358 QPair<QHostInfo, QTime>* info = dnsCache.object(hostName);
359 if (info && info->second.addSecs(ttl) >= QTime::currentTime())
360 return info->first;
361
362 return QHostInfo();
363}
364
365void HostInfoAgentPrivate::cacheLookup(const QHostInfo& info)
366{
367 if (info.hostName().isEmpty())
368 return;
369
370 if (info.error() != QHostInfo::NoError)
371 return;
372
373 dnsCache.insert(info.hostName(), new QPair<QHostInfo, QTime>(info, QTime::currentTime()));
374}
375
376void HostInfoAgentPrivate::queryFinished(const QHostInfo& info)
377{
378 Query* query = static_cast<Query* >(sender());
379 openQueries.remove(query->hostName());
380 if (info.error() == QHostInfo::NoError) {
381 dnsCache.insert(query->hostName(),
382 new QPair<QHostInfo, QTime>(info, QTime::currentTime()));
383 }
384 query->deleteLater();
385}
386
387#include "hostinfo.moc"
QHash
QList
QMap
QObject
QPair
QThread
K_GLOBAL_STATIC
#define K_GLOBAL_STATIC(TYPE, NAME)
dummyHostInfoMetaType
static int dummyHostInfoMetaType
Definition: hostinfo.cpp:52
TTL
#define TTL
Definition: hostinfo.cpp:50
_PATH_RESCONF
#define _PATH_RESCONF
Definition: hostinfo.cpp:46
hostinfo_p.h
kdebug.h
kglobal.h
timeout
int timeout
KDesktopFileActions::run
bool run(const KUrl &_url, bool _is_local)
Invokes the default action for the desktop entry.
Definition: kdesktopfileactions.cpp:54
KIO::HostInfo::setCacheSize
void setCacheSize(int s)
Definition: hostinfo.cpp:297
KIO::HostInfo::lookupCachedHostInfoFor
QHostInfo lookupCachedHostInfoFor(const QString &hostName)
Definition: hostinfo.cpp:282
KIO::HostInfo::prefetchHost
void prefetchHost(const QString &hostName)
Definition: hostinfo.cpp:292
KIO::HostInfo::cacheLookup
void cacheLookup(const QHostInfo &info)
Definition: hostinfo.cpp:287
KIO::HostInfo::lookupHost
void lookupHost(const QString &hostName, QObject *receiver, const char *member)
Definition: hostinfo.cpp:240
KIO::HostInfo::setTTL
void setTTL(int ttl)
Definition: hostinfo.cpp:302
KIO
A namespace for KIO globals.
Definition: kbookmarkmenu.h:55
quit
KAction * quit(const QObject *recvr, const char *slot, QObject *parent)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal