Coverage Report

Created: 2026-05-31 06:50

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