1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QHOSTINFO_P_H
5#define QHOSTINFO_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of the QHostInfo class. This header file may change from
13// version to version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtNetwork/private/qtnetworkglobal_p.h>
19#include "QtCore/qcoreapplication.h"
20#include "private/qcoreapplication_p.h"
21#include "private/qmetaobject_p.h"
22#include "QtNetwork/qhostinfo.h"
23#include "QtCore/qmutex.h"
24#include "QtCore/qwaitcondition.h"
25#include "QtCore/qobject.h"
26#include "QtCore/qpointer.h"
27#include "QtCore/qthread.h"
28#if QT_CONFIG(thread)
29#include "QtCore/qthreadpool.h"
30#endif
31#include "QtCore/qrunnable.h"
32#include "QtCore/qlist.h"
33#include "QtCore/qqueue.h"
34#include <QElapsedTimer>
35#include <QCache>
36
37#include <atomic>
38
39QT_BEGIN_NAMESPACE
40
41
42class QHostInfoResult : public QObject
43{
44 Q_OBJECT
45public:
46 explicit QHostInfoResult(const QObject *receiver, QtPrivate::SlotObjUniquePtr slot);
47 ~QHostInfoResult() override;
48
49 void postResultsReady(const QHostInfo &info);
50
51Q_SIGNALS:
52 void resultsReady(const QHostInfo &info);
53
54protected:
55 bool event(QEvent *event) override;
56
57private:
58 QHostInfoResult(const QHostInfoResult *other)
59 : receiver(other->receiver), slotObj{copy(other: other->slotObj)},
60 withContextObject(other->withContextObject)
61 {
62 // cleanup if the application terminates before results are delivered
63 connect(sender: QCoreApplication::instance(), signal: &QCoreApplication::aboutToQuit,
64 context: this, slot: &QObject::deleteLater);
65 // maintain thread affinity
66 moveToThread(thread: other->thread());
67 }
68
69 QPointer<const QObject> receiver = nullptr;
70 QtPrivate::SlotObjUniquePtr slotObj;
71 const bool withContextObject = false;
72};
73
74class QHostInfoAgent
75{
76public:
77 static QHostInfo fromName(const QString &hostName);
78 static QHostInfo lookup(const QString &hostName);
79 static QHostInfo reverseLookup(const QHostAddress &address);
80};
81
82class QHostInfoPrivate
83{
84public:
85 inline QHostInfoPrivate()
86 : err(QHostInfo::NoError),
87 errorStr(QLatin1StringView(QT_TRANSLATE_NOOP("QHostInfo", "Unknown error"))),
88 lookupId(0)
89 {
90 }
91 static int lookupHostImpl(const QString &name,
92 const QObject *receiver,
93 QtPrivate::QSlotObjectBase *slotObj,
94 const char *member);
95
96 QHostInfo::HostInfoError err;
97 QString errorStr;
98 QList<QHostAddress> addrs;
99 QString hostName;
100 int lookupId;
101};
102
103// These functions are outside of the QHostInfo class and strictly internal.
104// Do NOT use them outside of QAbstractSocket.
105QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id);
106void Q_AUTOTEST_EXPORT qt_qhostinfo_clear_cache();
107void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e);
108void Q_AUTOTEST_EXPORT qt_qhostinfo_cache_inject(const QString &hostname, const QHostInfo &resolution);
109
110class QHostInfoCache
111{
112public:
113 QHostInfoCache();
114 const int max_age; // seconds
115
116 QHostInfo get(const QString &name, bool *valid);
117 void put(const QString &name, const QHostInfo &info);
118 void clear();
119
120 bool isEnabled() { return enabled.load(m: std::memory_order_relaxed); }
121 // this function is currently only used for the auto tests
122 // and not usable by public API
123 void setEnabled(bool e) { enabled.store(i: e, m: std::memory_order_relaxed); }
124private:
125 std::atomic<bool> enabled;
126 struct QHostInfoCacheElement {
127 QHostInfo info;
128 QElapsedTimer age;
129 };
130 QCache<QString,QHostInfoCacheElement> cache;
131 QMutex mutex;
132};
133
134// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
135
136class QHostInfoRunnable : public QRunnable
137{
138public:
139 explicit QHostInfoRunnable(const QString &hn, int i, const QObject *receiver,
140 QtPrivate::SlotObjUniquePtr slotObj);
141 ~QHostInfoRunnable() override;
142
143 void run() override;
144
145 QString toBeLookedUp;
146 int id;
147 QHostInfoResult resultEmitter;
148};
149
150
151class QHostInfoLookupManager
152{
153public:
154 QHostInfoLookupManager();
155 ~QHostInfoLookupManager();
156
157 void clear();
158
159 // called from QHostInfo
160 void scheduleLookup(QHostInfoRunnable *r);
161 void abortLookup(int id);
162
163 // called from QHostInfoRunnable
164 void lookupFinished(QHostInfoRunnable *r);
165 bool wasAborted(int id);
166
167 QHostInfoCache cache;
168
169 friend class QHostInfoRunnable;
170protected:
171#if QT_CONFIG(thread)
172 QList<QHostInfoRunnable*> currentLookups; // in progress
173 QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
174#endif
175 QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
176 QList<QHostInfoRunnable*> finishedLookups; // recently finished
177 QList<int> abortedLookups; // ids of aborted lookups
178
179#if QT_CONFIG(thread)
180 QThreadPool threadPool;
181#endif
182 QMutex mutex;
183
184 bool wasDeleted;
185
186private:
187 void rescheduleWithMutexHeld();
188};
189
190QT_END_NAMESPACE
191
192#endif // QHOSTINFO_P_H
193

source code of qtbase/src/network/kernel/qhostinfo_p.h