diff --git a/packages/connectivity_plus/connectivity_plus/CHANGELOG.md b/packages/connectivity_plus/connectivity_plus/CHANGELOG.md index 14062c8f11..4b00567916 100644 --- a/packages/connectivity_plus/connectivity_plus/CHANGELOG.md +++ b/packages/connectivity_plus/connectivity_plus/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.0 + +- Add ethernet as connectivity result. Supported on Android, iOS, Windows, Linux, macOS, and Web + ## 1.2.0 - migrate integration_test to flutter sdk diff --git a/packages/connectivity_plus/connectivity_plus/pubspec.yaml b/packages/connectivity_plus/connectivity_plus/pubspec.yaml index 1dda54e660..4efaedbd69 100644 --- a/packages/connectivity_plus/connectivity_plus/pubspec.yaml +++ b/packages/connectivity_plus/connectivity_plus/pubspec.yaml @@ -1,6 +1,6 @@ name: connectivity_plus description: Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS. -version: 1.2.0 +version: 1.3.0 homepage: https://plus.fluttercommunity.dev/ repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/ @@ -33,7 +33,7 @@ dependencies: connectivity_plus_linux: ^1.1.0 connectivity_plus_macos: ^1.1.0 connectivity_plus_web: ^1.1.0 - connectivity_plus_windows: ^1.1.0 + connectivity_plus_windows: ^1.2.0 dev_dependencies: flutter_test: diff --git a/packages/connectivity_plus/connectivity_plus_windows/CHANGELOG.md b/packages/connectivity_plus/connectivity_plus_windows/CHANGELOG.md index 80d068e176..796d7b516c 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/CHANGELOG.md +++ b/packages/connectivity_plus/connectivity_plus_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0 + +- Add ethernet as connectivity result. + ## 1.1.0 - Update connectivity plus diff --git a/packages/connectivity_plus/connectivity_plus_windows/pubspec.yaml b/packages/connectivity_plus/connectivity_plus_windows/pubspec.yaml index 52e61ded49..f40bbccd8d 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/pubspec.yaml +++ b/packages/connectivity_plus/connectivity_plus_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: connectivity_plus_windows description: Windows implementation of the connectivity_plus plugin homepage: https://plus.fluttercommunity.dev/ repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/ -version: 1.1.0 +version: 1.2.0 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/packages/connectivity_plus/connectivity_plus_windows/windows/CMakeLists.txt b/packages/connectivity_plus/connectivity_plus_windows/windows/CMakeLists.txt index 450daaad4d..7ee88e4f4c 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/windows/CMakeLists.txt +++ b/packages/connectivity_plus/connectivity_plus_windows/windows/CMakeLists.txt @@ -16,7 +16,11 @@ set_target_properties(${PLUGIN_NAME} PROPERTIES target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) +target_link_libraries(${PLUGIN_NAME} PRIVATE + flutter + flutter_wrapper_plugin + iphlpapi +) # List of absolute paths to libraries that should be bundled with the plugin set(connectivity_plus_windows_bundled_libraries diff --git a/packages/connectivity_plus/connectivity_plus_windows/windows/connectivity_plus_windows_plugin.cpp b/packages/connectivity_plus/connectivity_plus_windows/windows/connectivity_plus_windows_plugin.cpp index b538830294..2286f919e7 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/windows/connectivity_plus_windows_plugin.cpp +++ b/packages/connectivity_plus/connectivity_plus_windows/windows/connectivity_plus_windows_plugin.cpp @@ -1,3 +1,6 @@ +// clang-format off +#include "include/connectivity_plus_windows/network_manager.h" +// clang-format on #include "include/connectivity_plus_windows/connectivity_plus_windows_plugin.h" #include @@ -10,8 +13,6 @@ #include #include -#include "network_manager.h" - namespace { typedef flutter::EventChannel FlEventChannel; @@ -45,7 +46,7 @@ class ConnectivityStreamHandler : public FlStreamHandler { virtual ~ConnectivityStreamHandler(); protected: - void AddConnectivityEvent(bool connected); + void AddConnectivityEvent(); std::unique_ptr OnListenInternal( const flutter::EncodableValue* arguments, @@ -97,15 +98,24 @@ void ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( registrar->AddPlugin(std::move(plugin)); } -static std::string ConnectivityToString(bool isConnected) { - return isConnected ? "wifi" : "none"; +static std::string ConnectivityToString(ConnectivityType connectivityType) { + switch (connectivityType) { + case ConnectivityType::WiFi: + return "wifi"; + case ConnectivityType::Ethernet: + return "ethernet"; + case ConnectivityType::None: + default: + return "none"; + } } void ConnectivityPlusWindowsPlugin::HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { if (method_call.method_name().compare("check") == 0) { - std::string connectivity = ConnectivityToString(manager->IsConnected()); + std::string connectivity = + ConnectivityToString(manager->GetConnectivityType()); result->Success(flutter::EncodableValue(connectivity)); } else { result->NotImplemented(); @@ -118,8 +128,9 @@ ConnectivityStreamHandler::ConnectivityStreamHandler( ConnectivityStreamHandler::~ConnectivityStreamHandler() {} -void ConnectivityStreamHandler::AddConnectivityEvent(bool connected) { - std::string connectivity = ConnectivityToString(connected); +void ConnectivityStreamHandler::AddConnectivityEvent() { + std::string connectivity = + ConnectivityToString(manager->GetConnectivityType()); sink->Success(flutter::EncodableValue(connectivity)); } @@ -129,8 +140,8 @@ ConnectivityStreamHandler::OnListenInternal( std::unique_ptr&& events) { sink = std::move(events); - auto callback = std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, - this, std::placeholders::_1); + auto callback = + std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, this); if (!manager->StartListen(callback)) { return std::make_unique( @@ -138,7 +149,7 @@ ConnectivityStreamHandler::OnListenInternal( nullptr); } - AddConnectivityEvent(manager->IsConnected()); + AddConnectivityEvent(); return nullptr; } diff --git a/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.h b/packages/connectivity_plus/connectivity_plus_windows/windows/include/connectivity_plus_windows/network_manager.h similarity index 73% rename from packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.h rename to packages/connectivity_plus/connectivity_plus_windows/windows/include/connectivity_plus_windows/network_manager.h index 00a946f6c8..ea179b74a3 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.h +++ b/packages/connectivity_plus/connectivity_plus_windows/windows/include/connectivity_plus_windows/network_manager.h @@ -1,18 +1,23 @@ #ifndef NETWORK_MANAGER_H #define NETWORK_MANAGER_H +// clang-format off +#include +// clang-format on #include #include #include +enum class ConnectivityType { None, Ethernet, WiFi }; + class NetworkListener; struct IConnectionPoint; struct IConnectionPointContainer; struct INetworkListManager; struct IUnknown; -typedef std::function NetworkCallback; +typedef std::function NetworkCallback; class NetworkManager { public: @@ -22,7 +27,7 @@ class NetworkManager { bool Init(); void Cleanup(); - bool IsConnected(); + ConnectivityType GetConnectivityType() const; bool StartListen(NetworkCallback pCallback); void StopListen(); @@ -31,6 +36,8 @@ class NetworkManager { int GetError() const; private: + std::vector GetConnectedAdapterIds() const; + DWORD dwCookie = 0; IUnknown *pUnknown = NULL; INetworkListManager *pNetworkListManager = NULL; diff --git a/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.cpp b/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.cpp index 6ca79c8fff..97054a4a44 100644 --- a/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.cpp +++ b/packages/connectivity_plus/connectivity_plus_windows/windows/network_manager.cpp @@ -9,14 +9,16 @@ * See full license text in LICENSE file at top of project tree */ -#include "network_manager.h" +#include "include/connectivity_plus_windows/network_manager.h" +#include #include #include #include +#include -class NetworkListener final : public INetworkListManagerEvents { +class NetworkListener final : public INetworkEvents { public: NetworkListener(NetworkCallback pCb) : pCallback(pCb) {} @@ -26,8 +28,8 @@ class NetworkListener final : public INetworkListManagerEvents { HRESULT hr = S_OK; if (IsEqualIID(riid, IID_IUnknown)) { *ppvObject = (IUnknown *)this; - } else if (IsEqualIID(riid, IID_INetworkListManagerEvents)) { - *ppvObject = (INetworkListManagerEvents *)this; + } else if (IsEqualIID(riid, IID_INetworkEvents)) { + *ppvObject = (INetworkEvents *)this; } else { hr = E_NOINTERFACE; } @@ -44,16 +46,27 @@ class NetworkListener final : public INetworkListManagerEvents { return lAddend; } + HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) { return S_OK; } + HRESULT STDMETHODCALLTYPE - ConnectivityChanged(NLM_CONNECTIVITY fConnectivity) { - Callback(fConnectivity & - (NLM_CONNECTIVITY_IPV4_INTERNET | NLM_CONNECTIVITY_IPV6_INTERNET)); + NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) { + Callback(); return S_OK; } - void Callback(bool bConnected) { + HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) { + if (flags & NLM_NETWORK_PROPERTY_CHANGE_CONNECTION) { + Callback(); + } + return S_OK; + } + + void Callback() { assert(pCallback); - pCallback(bConnected); + pCallback(); } private: @@ -94,13 +107,96 @@ void NetworkManager::Cleanup() { CoUninitialize(); } -bool NetworkManager::IsConnected() { - VARIANT_BOOL Connected = VARIANT_FALSE; - HRESULT hr = pNetworkListManager->get_IsConnectedToInternet(&Connected); - if (FAILED(hr)) { - return false; +std::vector NetworkManager::GetConnectedAdapterIds() const { + std::vector adapterIds; + + IEnumNetworkConnections *connections = NULL; + HRESULT hr = pNetworkListManager->GetNetworkConnections(&connections); + if (hr == S_OK) { + while (true) { + INetworkConnection *connection = NULL; + hr = connections->Next(1, &connection, NULL); + if (hr != S_OK) { + break; + } + + VARIANT_BOOL isConnected = VARIANT_FALSE; + hr = connection->get_IsConnectedToInternet(&isConnected); + if (hr == S_OK && isConnected == VARIANT_TRUE) { + GUID guid; + hr = connection->GetAdapterId(&guid); + if (hr == S_OK) { + adapterIds.push_back(std::move(guid)); + } + } + connection->Release(); + } + connections->Release(); + } + + return adapterIds; +} + +ConnectivityType NetworkManager::GetConnectivityType() const { + ULONG bufferSize = 15 * 1024; + ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + std::vector buffer(bufferSize); + PIP_ADAPTER_ADDRESSES addresses = + reinterpret_cast(&buffer.front()); + DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + if (rc == ERROR_BUFFER_OVERFLOW) { + buffer.resize(bufferSize); + addresses = reinterpret_cast(&buffer.front()); + rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); } - return Connected == VARIANT_TRUE; + + if (rc != NO_ERROR) { + return ConnectivityType::None; + } + + std::vector adapterIds = GetConnectedAdapterIds(); + if (adapterIds.empty()) { + return ConnectivityType::None; + } + + std::set connectivities; + for (; addresses != NULL; addresses = addresses->Next) { + NET_LUID luid; + rc = ConvertInterfaceIndexToLuid(addresses->IfIndex, &luid); + if (rc != NO_ERROR) { + continue; + } + + GUID guid; + rc = ConvertInterfaceLuidToGuid(&luid, &guid); + if (rc != NO_ERROR) { + continue; + } + + if (std::find(adapterIds.begin(), adapterIds.end(), guid) != + adapterIds.end()) { + switch (addresses->IfType) { + case IF_TYPE_ETHERNET_CSMACD: + connectivities.insert(ConnectivityType::Ethernet); + break; + default: + connectivities.insert(ConnectivityType::WiFi); + break; + } + } + } + + if (connectivities.find(ConnectivityType::WiFi) != connectivities.end()) { + return ConnectivityType::WiFi; + } + + if (connectivities.find(ConnectivityType::Ethernet) != connectivities.end()) { + return ConnectivityType::Ethernet; + } + + return ConnectivityType::None; } bool NetworkManager::StartListen(NetworkCallback pCallback) { @@ -111,8 +207,7 @@ bool NetworkManager::StartListen(NetworkCallback pCallback) { HRESULT hr = pNetworkListManager->QueryInterface( IID_IConnectionPointContainer, (void **)&pCPContainer); if (SUCCEEDED(hr)) { - hr = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, - &pConnectPoint); + hr = pCPContainer->FindConnectionPoint(IID_INetworkEvents, &pConnectPoint); if (SUCCEEDED(hr)) { pListener = new NetworkListener(pCallback); hr = pConnectPoint->Advise((IUnknown *)pListener, &dwCookie);