5#include <QtNetwork/private/qnetworkinformation_p.h>
7#include <QtCore/qglobal.h>
8#include <QtCore/private/qobject_p.h>
9#include <QtCore/qmutex.h>
11#include <Network/Network.h>
14Q_DECLARE_LOGGING_CATEGORY(lcNetInfoSCR)
15Q_LOGGING_CATEGORY(lcNetInfoSCR,
"qt.network.info.applenetworkinfo");
19class ReachabilityDispatchQueue
22 ReachabilityDispatchQueue()
24 queue = dispatch_queue_create(
"qt-network-reachability-queue",
nullptr);
26 qCWarning(lcNetInfoSCR,
"Failed to create a dispatch queue for reachability probes");
29 ~ReachabilityDispatchQueue()
32 dispatch_release(queue);
35 dispatch_queue_t data()
const
41 dispatch_queue_t queue =
nullptr;
43 Q_DISABLE_COPY_MOVE(ReachabilityDispatchQueue)
46dispatch_queue_t qt_reachability_queue()
48 static const ReachabilityDispatchQueue reachabilityQueue;
49 return reachabilityQueue.data();
56 return QString::fromUtf16(QNetworkInformationBackend::PluginNames
57 [QNetworkInformationBackend::PluginNamesAppleIndex]);
78 return featuresSupportedStatic();
83 return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability
84 | QNetworkInformation::Feature::TransportMedium);
94 bool startMonitoring();
95 void stopMonitoring();
96 void updateState(nw_path_t state);
100 struct QueueCallbackData
104 } *callbackData =
nullptr;
106 nw_path_monitor_t monitor =
nullptr;
113 Q_PLUGIN_METADATA(IID QNetworkInformationBackendFactory_iid)
121 return QAppleNetworkInformationBackend::featuresSupportedStatic();
125 QNetworkInformation::Features requiredFeatures)
const override
127 if ((requiredFeatures & featuresSupported()) != requiredFeatures)
148 setReachability(isOnline ? QNetworkInformation::Reachability::Online
149 : QNetworkInformation::Reachability::Disconnected);
155 if (reachability() == QNetworkInformation::Reachability::Disconnected) {
156 setTransportMedium(QNetworkInformation::TransportMedium::Unknown);
159 case QAppleNetworkInformationBackend::InterfaceType::Ethernet:
160 setTransportMedium(QNetworkInformation::TransportMedium::Ethernet);
162 case QAppleNetworkInformationBackend::InterfaceType::Cellular:
163 setTransportMedium(QNetworkInformation::TransportMedium::Cellular);
165 case QAppleNetworkInformationBackend::InterfaceType::WiFi:
166 setTransportMedium(QNetworkInformation::TransportMedium::WiFi);
168 case QAppleNetworkInformationBackend::InterfaceType::Unknown:
169 setTransportMedium(QNetworkInformation::TransportMedium::Unknown);
177 return status == nw_path_status_satisfied;
182 Q_ASSERT(!monitor && !callbackData);
184 monitor = nw_path_monitor_create();
185 if (monitor ==
nullptr) {
186 qCWarning(lcNetInfoSCR,
"Failed to create a path monitor, cannot determine current reachability.");
190 auto queue = qt_reachability_queue();
192 qCWarning(lcNetInfoSCR,
"Failed to create a dispatch queue to schedule a probe on");
198 callbackData =
new QueueCallbackData;
199 auto *data = callbackData;
200 callbackData->backend =
this;
202 nw_path_monitor_set_update_handler(monitor, [data](nw_path_t path){
203 const QMutexLocker lock(&data->monitorMutex);
205 data->backend->updateState(path);
210 nw_path_monitor_set_cancel_handler(monitor, [data]{
214 nw_path_monitor_set_queue(monitor, queue);
215 nw_path_monitor_start(monitor);
221 Q_ASSERT(callbackData && monitor);
223 const QMutexLocker lock(&callbackData->monitorMutex);
224 callbackData->backend =
nullptr;
225 callbackData =
nullptr;
227 nw_path_monitor_cancel(monitor);
234 Q_ASSERT(callbackData);
241 const bool wasReachable = isReachable();
242 const QAppleNetworkInformationBackend::InterfaceType hadInterfaceType = interface;
243 const nw_path_status_t previousStatus = status;
245 status = nw_path_get_status(state);
246 if (wasReachable != isReachable() || previousStatus == nw_path_status_invalid)
247 reachabilityChanged(isReachable());
249 nw_path_enumerate_interfaces(state, ^(nw_interface_t nwInterface) {
250 if (nw_path_uses_interface_type(state, nw_interface_get_type(nwInterface))) {
251 const nw_interface_type_t type = nw_interface_get_type(nwInterface);
254 case nw_interface_type_wifi:
255 interface = QAppleNetworkInformationBackend::InterfaceType::WiFi;
257 case nw_interface_type_cellular:
258 interface = QAppleNetworkInformationBackend::InterfaceType::Cellular;
260 case nw_interface_type_wired:
261 interface = QAppleNetworkInformationBackend::InterfaceType::Ethernet;
264 interface = QAppleNetworkInformationBackend::InterfaceType::Unknown;
274 if (hadInterfaceType != interface)
275 interfaceTypeChanged(interface);
280#include "qapplenetworkinformationbackend.moc"