From 3c5c13c639b15b97a4baf681ae124917c334bab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 7 Oct 2021 13:40:01 +0200 Subject: QNI: Windows: support transportMedium Brings support for transportMedium to NetworkListManager backend. Which, with this patch, also uses winrt API because there is no equivalent API available in NLM. This API is so much nicer than NLM... Task-number: QTBUG-91023 Change-Id: I360a3a197caa2aa4848c8f768aea6a09a68b0ed5 Reviewed-by: Qt CI Bot Reviewed-by: Oliver Wolff --- .../networklistmanager/CMakeLists.txt | 5 ++ .../qnetworklistmanagerevents.cpp | 72 ++++++++++++++++++++++ .../networklistmanager/qnetworklistmanagerevents.h | 17 +++++ ...networklistmanagernetworkinformationbackend.cpp | 9 ++- 4 files changed, 102 insertions(+), 1 deletion(-) (limited to 'src/plugins/networkinformation') diff --git a/src/plugins/networkinformation/networklistmanager/CMakeLists.txt b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt index b5cf60b62c..d927d4af60 100644 --- a/src/plugins/networkinformation/networklistmanager/CMakeLists.txt +++ b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt @@ -10,6 +10,11 @@ qt_internal_add_plugin(QNLMNIPlugin Qt::NetworkPrivate ) +qt_internal_extend_target(QNLMNIPlugin CONDITION WIN32 AND MSVC AND NOT CLANG + LIBRARIES + runtimeobject +) + # Don't repeat the target name in AUTOGEN_BUILD_DIR to work around issues with overlong paths. set_property(TARGET QNLMNIPlugin PROPERTY AUTOGEN_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/autogen") diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp index bac5c1f339..dcc1439482 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp @@ -39,6 +39,19 @@ #include "qnetworklistmanagerevents.h" +#ifdef SUPPORTS_WINRT +#include +// Workaround for Windows SDK bug. +// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 +namespace winrt::impl +{ + template + auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); +} + +#include +#endif + QT_BEGIN_NAMESPACE namespace { @@ -121,6 +134,19 @@ bool QNetworkListManagerEvents::start() qCWarning(lcNetInfoNLM) << "Could not get connectivity:" << errorStringFromHResult(hr); else emit connectivityChanged(connectivity); + +#ifdef SUPPORTS_WINRT + using namespace winrt::Windows::Networking::Connectivity; + // Register for changes in the network and store a token to unregister later: + token = NetworkInformation::NetworkStatusChanged( + [this](const winrt::Windows::Foundation::IInspectable sender) { + Q_UNUSED(sender); + emit transportMediumChanged(getTransportMedium()); + }); + // Emit initial state + emit transportMediumChanged(getTransportMedium()); +#endif + return true; } @@ -134,6 +160,13 @@ bool QNetworkListManagerEvents::stop() return false; } cookie = 0; + +#ifdef SUPPORTS_WINRT + using namespace winrt::Windows::Networking::Connectivity; + // Pass the token we stored earlier to unregister: + NetworkInformation::NetworkStatusChanged(token); + token = {}; +#endif return true; } @@ -175,4 +208,43 @@ bool QNetworkListManagerEvents::checkBehindCaptivePortal() return false; } +// NB: this isn't part of "network list manager", but sadly NLM doesn't have an +// equivalent API (at least not that I've found...)! +QNetworkInformation::TransportMedium QNetworkListManagerEvents::getTransportMedium() +{ +#ifdef SUPPORTS_WINRT + using namespace winrt::Windows::Networking::Connectivity; + ConnectionProfile profile = NetworkInformation::GetInternetConnectionProfile(); + if (profile == nullptr) + return QNetworkInformation::TransportMedium::Unknown; + + if (profile.IsWwanConnectionProfile()) + return QNetworkInformation::TransportMedium::Cellular; + if (profile.IsWlanConnectionProfile()) + return QNetworkInformation::TransportMedium::WiFi; + + NetworkAdapter adapter = profile.NetworkAdapter(); + if (adapter == nullptr) + return QNetworkInformation::TransportMedium::Unknown; + + // Note: Bluetooth is given an iana iftype of 6, which is the same as Ethernet. + // In Windows itself there is clearly a distinction between a Bluetooth PAN + // and an Ethernet LAN, though it is not clear how they make this distinction. + auto fromIanaId = [](quint32 ianaId) -> QNetworkInformation::TransportMedium { + // https://www.iana.org/assignments/ianaiftype-mib/ianaiftype-mib + switch (ianaId) { + case 6: + return QNetworkInformation::TransportMedium::Ethernet; + case 71: // Should be handled before entering this lambda + return QNetworkInformation::TransportMedium::WiFi; + } + return QNetworkInformation::TransportMedium::Unknown; + }; + + return fromIanaId(adapter.IanaInterfaceType()); +#else + return QNetworkInformation::TransportMedium::Unknown; +#endif +} + QT_END_NAMESPACE diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h index 60a2367e4f..8618a09a84 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h @@ -39,6 +39,8 @@ #include +#include + #include #include #include @@ -49,6 +51,14 @@ #include #include +#if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) +#define SUPPORTS_WINRT 1 +#endif + +#ifdef SUPPORTS_WINRT +#include +#endif + using namespace Microsoft::WRL; QT_BEGIN_NAMESPACE @@ -88,11 +98,18 @@ public: signals: void connectivityChanged(NLM_CONNECTIVITY); + void transportMediumChanged(QNetworkInformation::TransportMedium); private: + [[nodiscard]] QNetworkInformation::TransportMedium getTransportMedium(); + ComPtr networkListManager = nullptr; ComPtr connectionPoint = nullptr; +#ifdef SUPPORTS_WINRT + winrt::event_token token; +#endif + QAtomicInteger ref = 0; DWORD cookie = 0; }; diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp index 73952b3395..e8b36be02e 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp @@ -99,7 +99,11 @@ public: static QNetworkInformation::Features featuresSupportedStatic() { return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability - | QNetworkInformation::Feature::CaptivePortal); + | QNetworkInformation::Feature::CaptivePortal +#ifdef SUPPORTS_WINRT + | QNetworkInformation::Feature::TransportMedium +#endif + ); } [[nodiscard]] bool start(); @@ -158,6 +162,9 @@ QNetworkListManagerNetworkInformationBackend::QNetworkListManagerNetworkInformat managerEvents = new QNetworkListManagerEvents(); connect(managerEvents.Get(), &QNetworkListManagerEvents::connectivityChanged, this, &QNetworkListManagerNetworkInformationBackend::setConnectivity); + + connect(managerEvents.Get(), &QNetworkListManagerEvents::transportMediumChanged, this, + &QNetworkListManagerNetworkInformationBackend::setTransportMedium); } QNetworkListManagerNetworkInformationBackend::~QNetworkListManagerNetworkInformationBackend() -- cgit v1.2.3