Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnetconmonitor_darwin.mm
Go to the documentation of this file.
1// Copyright (C) 2019 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#include "private/qnetconmonitor_p.h"
6
7#include "private/qobject_p.h"
8
9#include <Network/Network.h>
10
11#include <QtCore/qreadwritelock.h>
12
14
15Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor");
16
17namespace {
18
19class ReachabilityDispatchQueue
20{
21public:
22 ReachabilityDispatchQueue()
23 {
24 queue = dispatch_queue_create("qt-network-reachability-queue", nullptr);
25 if (!queue)
26 qCWarning(lcNetMon, "Failed to create a dispatch queue for reachability probes");
27 }
28
29 ~ReachabilityDispatchQueue()
30 {
31 if (queue)
32 dispatch_release(queue);
33 }
34
35 dispatch_queue_t data() const
36 {
37 return queue;
38 }
39
40private:
41 dispatch_queue_t queue = nullptr;
42
43 Q_DISABLE_COPY_MOVE(ReachabilityDispatchQueue)
44};
45
46dispatch_queue_t qt_reachability_queue()
47{
48 static const ReachabilityDispatchQueue reachabilityQueue;
49 return reachabilityQueue.data();
50}
51
52} // unnamed namespace
53
74
76{
77 QReadLocker lock(&monitorLock);
78 if (monitor == nullptr)
79 return;
80
81 // To be executed only on the reachability queue.
82 Q_Q(QNetworkConnectionMonitor);
83
84 // NETMONTODO: for now, 'online' for us means nw_path_status_satisfied
85 // is set. There are more possible flags that require more tests/some special
86 // setup. So in future this part and related can change/be extended.
87 const bool wasReachable = isReachable();
88 const QNetworkConnectionMonitor::InterfaceType hadInterfaceType = interface;
89 const nw_path_status_t previousStatus = status;
90
91 status = nw_path_get_status(state);
92 if (wasReachable != isReachable() || previousStatus == nw_path_status_invalid)
93 emit q->reachabilityChanged(isReachable());
94
95 nw_path_enumerate_interfaces(state, ^(nw_interface_t nwInterface) {
96 if (nw_path_uses_interface_type(state, nw_interface_get_type(nwInterface))) {
97 const nw_interface_type_t type = nw_interface_get_type(nwInterface);
98
99 switch (type) {
100 case nw_interface_type_wifi:
101 interface = QNetworkConnectionMonitor::InterfaceType::WiFi;
102 break;
103 case nw_interface_type_cellular:
104 interface = QNetworkConnectionMonitor::InterfaceType::Cellular;
105 break;
106 case nw_interface_type_wired:
107 interface = QNetworkConnectionMonitor::InterfaceType::Ethernet;
108 break;
109 default:
110 interface = QNetworkConnectionMonitor::InterfaceType::Unknown;
111 break;
112 }
113
114 return false;
115 }
116
117 return true;
118 });
119
120 if (hadInterfaceType != interface)
121 emit q->interfaceTypeChanged(interface);
122}
123
125{
127 status = nw_path_status_invalid;
128}
129
131{
132 return status == nw_path_status_satisfied;
133}
134
139
141{
142 QWriteLocker lock(&monitorLock);
143 monitor = nw_path_monitor_create();
144 if (monitor == nullptr) {
145 qCWarning(lcNetMon, "Failed to create a path monitor, cannot determine current reachability.");
146 return false;
147 }
148
149 nw_path_monitor_set_update_handler(monitor, [this](nw_path_t path){
150 updateState(path);
151 });
152
153 auto queue = qt_reachability_queue();
154 if (!queue) {
155 qCWarning(lcNetMon, "Failed to create a dispatch queue to schedule a probe on");
156 nw_release(monitor);
157 monitor = nullptr;
158 return false;
159 }
160
161 nw_path_monitor_set_queue(monitor, queue);
162 nw_path_monitor_start(monitor);
163 return true;
164}
165
167{
168 QWriteLocker lock(&monitorLock);
169 if (monitor != nullptr) {
170 nw_path_monitor_cancel(monitor);
171 nw_release(monitor);
172 monitor = nullptr;
173 }
174}
175
176void QNetworkConnectionMonitor::stopMonitoring()
177{
178 Q_D(QNetworkConnectionMonitor);
179 d->stopMonitoring();
180}
181
183{
184 QReadLocker lock(&monitorLock);
185 return monitor != nullptr;
186}
187
188QNetworkConnectionMonitor::QNetworkConnectionMonitor()
189 : QObject(*new QNetworkConnectionMonitorPrivate)
190{
191}
192
193QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &/*local*/, const QHostAddress &/*remote*/)
194 : QNetworkConnectionMonitor()
195{
196}
197
198QNetworkConnectionMonitor::~QNetworkConnectionMonitor()
199{
200 Q_D(QNetworkConnectionMonitor);
201 d->reset();
202}
203
204bool QNetworkConnectionMonitor::setTargets(const QHostAddress &/*local*/, const QHostAddress &/*remote*/)
205{
206 return false;
207}
208
209bool QNetworkConnectionMonitor::startMonitoring()
210{
211 Q_D(QNetworkConnectionMonitor);
212
213 if (d->isMonitoring()) {
214 qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first");
215 return false;
216 }
217
218 return d->startMonitoring();
219}
220
221bool QNetworkConnectionMonitor::isReachable()
222{
223 Q_D(QNetworkConnectionMonitor);
224
225 if (isMonitoring()) {
226 qCWarning(lcNetMon, "Calling isReachable() is unsafe after the monitoring started");
227 return false;
228 }
229
230 return d->isReachable();
231}
232
233QNetworkConnectionMonitor::InterfaceType QNetworkConnectionMonitor::getInterfaceType() const
234{
235 Q_D(const QNetworkConnectionMonitor);
236
237 if (d->isMonitoring()) {
238 qCWarning(lcNetMon, "Calling getInterfaceType() is unsafe after the monitoring started");
239 return QNetworkConnectionMonitor::InterfaceType::Unknown;
240 }
241
242 return d->getInterfaceType();
243}
244
245bool QNetworkConnectionMonitor::isEnabled()
246{
247 return true;
248}
249
250bool QNetworkConnectionMonitor::isMonitoring() const
251{
252 Q_D(const QNetworkConnectionMonitor);
253 return d->isMonitoring();
254}
255
256QT_END_NAMESPACE
QNetworkConnectionMonitor::InterfaceType getInterfaceType() const
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")