summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/kernel/qnetconmonitor_darwin.mm39
-rw-r--r--src/network/kernel/qnetconmonitor_p.h10
-rw-r--r--src/plugins/networkinformation/scnetworkreachability/qscnetworkreachabilitynetworkinformationbackend.mm48
3 files changed, 95 insertions, 2 deletions
diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm
index 42540c38ee..a899d3b98d 100644
--- a/src/network/kernel/qnetconmonitor_darwin.mm
+++ b/src/network/kernel/qnetconmonitor_darwin.mm
@@ -124,6 +124,9 @@ public:
void updateState(SCNetworkReachabilityFlags newState);
void reset();
bool isReachable() const;
+#ifdef QT_PLATFORM_UIKIT
+ bool isWwan() const;
+#endif
static void probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info);
@@ -139,9 +142,19 @@ void QNetworkConnectionMonitorPrivate::updateState(SCNetworkReachabilityFlags ne
// is set. There are more possible flags that require more tests/some special
// setup. So in future this part and related can change/be extended.
const bool wasReachable = isReachable();
+
+#ifdef QT_PLATFORM_UIKIT
+ const bool hadWwan = isWwan();
+#endif
+
state = newState;
if (wasReachable != isReachable())
emit q->reachabilityChanged(isReachable());
+
+#ifdef QT_PLATFORM_UIKIT
+ if (hadWwan != isWwan())
+ emit q->isWwanChanged(isWwan());
+#endif
}
void QNetworkConnectionMonitorPrivate::reset()
@@ -160,6 +173,13 @@ bool QNetworkConnectionMonitorPrivate::isReachable() const
return !!(state & kSCNetworkReachabilityFlagsReachable);
}
+#ifdef QT_PLATFORM_UIKIT // The IsWWAN flag is not available on macOS
+bool QNetworkConnectionMonitorPrivate::isWwan() const
+{
+ return !!(state & kSCNetworkReachabilityFlagsIsWWAN);
+}
+#endif
+
void QNetworkConnectionMonitorPrivate::probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info)
{
// To be executed only on the reachability queue.
@@ -301,6 +321,25 @@ bool QNetworkConnectionMonitor::isReachable()
return d->isReachable();
}
+#ifdef QT_PLATFORM_UIKIT
+bool QNetworkConnectionMonitor::isWwan() const
+{
+ Q_D(const QNetworkConnectionMonitor);
+
+ if (isMonitoring()) {
+ qCWarning(lcNetMon, "Calling isReachable() is unsafe after the monitoring started");
+ return false;
+ }
+
+ if (!d->probe) {
+ qCWarning(lcNetMon, "Reachability is unknown, set the target first");
+ return false;
+ }
+
+ return d->isWwan();
+}
+#endif
+
bool QNetworkConnectionMonitor::isEnabled()
{
return true;
diff --git a/src/network/kernel/qnetconmonitor_p.h b/src/network/kernel/qnetconmonitor_p.h
index c6d44ae559..99acbf4dea 100644
--- a/src/network/kernel/qnetconmonitor_p.h
+++ b/src/network/kernel/qnetconmonitor_p.h
@@ -73,7 +73,11 @@ public:
bool setTargets(const QHostAddress &local, const QHostAddress &remote);
bool isReachable();
- // Important: on Darwin you should not call isReachable() after
+#ifdef QT_PLATFORM_UIKIT
+ bool isWwan() const;
+#endif
+
+ // Important: on Darwin you should not call isReachable/isWwan() after
// startMonitoring(), you have to listen to reachabilityChanged()
// signal instead.
bool startMonitoring();
@@ -87,6 +91,10 @@ Q_SIGNALS:
// callback is coming on a special dispatch queue.
void reachabilityChanged(bool isOnline);
+#ifdef QT_PLATFORM_UIKIT
+ void isWwanChanged(bool isWwan);
+#endif
+
private:
Q_DECLARE_PRIVATE(QNetworkConnectionMonitor)
Q_DISABLE_COPY_MOVE(QNetworkConnectionMonitor)
diff --git a/src/plugins/networkinformation/scnetworkreachability/qscnetworkreachabilitynetworkinformationbackend.mm b/src/plugins/networkinformation/scnetworkreachability/qscnetworkreachabilitynetworkinformationbackend.mm
index 1da671e549..272327f7da 100644
--- a/src/plugins/networkinformation/scnetworkreachability/qscnetworkreachabilitynetworkinformationbackend.mm
+++ b/src/plugins/networkinformation/scnetworkreachability/qscnetworkreachabilitynetworkinformationbackend.mm
@@ -69,12 +69,20 @@ public:
static QNetworkInformation::Features featuresSupportedStatic()
{
- return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability);
+ return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability
+#ifdef QT_PLATFORM_UIKIT
+ | QNetworkInformation::Feature::TransportMedium
+#endif
+ );
}
private Q_SLOTS:
void reachabilityChanged(bool isOnline);
+#ifdef QT_PLATFORM_UIKIT
+ void isWwanChanged(bool isOnline);
+#endif
+
private:
Q_DISABLE_COPY_MOVE(QSCNetworkReachabilityNetworkInformationBackend);
@@ -110,10 +118,16 @@ private:
QSCNetworkReachabilityNetworkInformationBackend::QSCNetworkReachabilityNetworkInformationBackend()
{
bool isOnline = false;
+#ifdef QT_PLATFORM_UIKIT
+ bool isWwan = false;
+#endif
if (ipv4Probe.setTargets(QHostAddress::AnyIPv4, {})) {
// We manage to create SCNetworkReachabilityRef for IPv4, let's
// read the last known state then!
isOnline |= ipv4Probe.isReachable();
+#ifdef QT_PLATFORM_UIKIT
+ isWwan |= ipv4Probe.isWwan();
+#endif
ipv4Probe.startMonitoring();
}
@@ -121,9 +135,15 @@ QSCNetworkReachabilityNetworkInformationBackend::QSCNetworkReachabilityNetworkIn
// We manage to create SCNetworkReachability ref for IPv6, let's
// read the last known state then!
isOnline |= ipv6Probe.isReachable();
+#ifdef QT_PLATFORM_UIKIT
+ isWwan |= ipv6Probe.isWwan();
+#endif
ipv6Probe.startMonitoring();
}
reachabilityChanged(isOnline);
+#ifdef QT_PLATFORM_UIKIT
+ isWwanChanged(isWwan);
+#endif
connect(&ipv4Probe, &QNetworkConnectionMonitor::reachabilityChanged, this,
&QSCNetworkReachabilityNetworkInformationBackend::reachabilityChanged,
@@ -131,6 +151,15 @@ QSCNetworkReachabilityNetworkInformationBackend::QSCNetworkReachabilityNetworkIn
connect(&ipv6Probe, &QNetworkConnectionMonitor::reachabilityChanged, this,
&QSCNetworkReachabilityNetworkInformationBackend::reachabilityChanged,
Qt::QueuedConnection);
+
+#ifdef QT_PLATFORM_UIKIT
+ connect(&ipv4Probe, &QNetworkConnectionMonitor::isWwanChanged, this,
+ &QSCNetworkReachabilityNetworkInformationBackend::isWwanChanged,
+ Qt::QueuedConnection);
+ connect(&ipv6Probe, &QNetworkConnectionMonitor::isWwanChanged, this,
+ &QSCNetworkReachabilityNetworkInformationBackend::isWwanChanged,
+ Qt::QueuedConnection);
+#endif
}
QSCNetworkReachabilityNetworkInformationBackend::~QSCNetworkReachabilityNetworkInformationBackend()
@@ -143,6 +172,23 @@ void QSCNetworkReachabilityNetworkInformationBackend::reachabilityChanged(bool i
: QNetworkInformation::Reachability::Disconnected);
}
+#ifdef QT_PLATFORM_UIKIT
+void QSCNetworkReachabilityNetworkInformationBackend::isWwanChanged(bool isWwan)
+{
+ // The reachability API from Apple only has one entry regarding transport medium: "IsWWAN"[0].
+ // This is _serviceable_ on iOS where the only other credible options are "WLAN" or
+ // "Disconnected". But on macOS you could be connected by Ethernet as well, so how would that be
+ // reported? It doesn't matter anyway since "IsWWAN" is not available on macOS.
+ // [0]: https://developer.apple.com/documentation/systemconfiguration/scnetworkreachabilityflags/kscnetworkreachabilityflagsiswwan?language=objc
+ if (reachability() == QNetworkInformation::Reachability::Disconnected) {
+ setTransportMedium(QNetworkInformation::TransportMedium::Unknown);
+ } else {
+ setTransportMedium(isWwan ? QNetworkInformation::TransportMedium::Cellular
+ : QNetworkInformation::TransportMedium::WiFi);
+ }
+}
+#endif
+
QT_END_NAMESPACE
#include "qscnetworkreachabilitynetworkinformationbackend.moc"