Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/connectivity_plus/connectivity_plus/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
4 changes: 2 additions & 2 deletions packages/connectivity_plus/connectivity_plus/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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/

Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.0

- Add ethernet as connectivity result.

Comment thread
mhadaily marked this conversation as resolved.
## 1.1.0

- Update connectivity plus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <flutter/event_channel.h>
Expand All @@ -10,8 +13,6 @@
#include <functional>
#include <memory>

#include "network_manager.h"

namespace {

typedef flutter::EventChannel<flutter::EncodableValue> FlEventChannel;
Expand Down Expand Up @@ -45,7 +46,7 @@ class ConnectivityStreamHandler : public FlStreamHandler {
virtual ~ConnectivityStreamHandler();

protected:
void AddConnectivityEvent(bool connected);
void AddConnectivityEvent();

std::unique_ptr<FlStreamHandlerError> OnListenInternal(
const flutter::EncodableValue* arguments,
Expand Down Expand Up @@ -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<flutter::EncodableValue>& method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> 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();
Expand All @@ -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));
}

Expand All @@ -129,16 +140,16 @@ ConnectivityStreamHandler::OnListenInternal(
std::unique_ptr<FlEventSink>&& 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<FlStreamHandlerError>(
std::to_string(manager->GetError()), "NetworkManager::StartListen",
nullptr);
}

AddConnectivityEvent(manager->IsConnected());
AddConnectivityEvent();
return nullptr;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
#ifndef NETWORK_MANAGER_H
#define NETWORK_MANAGER_H

// clang-format off
#include <winsock2.h>
// clang-format on
#include <windows.h>

#include <functional>
#include <string>

enum class ConnectivityType { None, Ethernet, WiFi };

class NetworkListener;
struct IConnectionPoint;
struct IConnectionPointContainer;
struct INetworkListManager;
struct IUnknown;

typedef std::function<void(bool)> NetworkCallback;
typedef std::function<void()> NetworkCallback;

class NetworkManager {
public:
Expand All @@ -22,7 +27,7 @@ class NetworkManager {
bool Init();
void Cleanup();

bool IsConnected();
ConnectivityType GetConnectivityType() const;

bool StartListen(NetworkCallback pCallback);
void StopListen();
Expand All @@ -31,6 +36,8 @@ class NetworkManager {
int GetError() const;

private:
std::vector<GUID> GetConnectedAdapterIds() const;

DWORD dwCookie = 0;
IUnknown *pUnknown = NULL;
INetworkListManager *pNetworkListManager = NULL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <iphlpapi.h>
#include <netlistmgr.h>
#include <ocidl.h>

#include <cassert>
#include <set>

class NetworkListener final : public INetworkListManagerEvents {
class NetworkListener final : public INetworkEvents {
public:
NetworkListener(NetworkCallback pCb) : pCallback(pCb) {}

Expand All @@ -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;
}
Expand All @@ -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:
Expand Down Expand Up @@ -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<GUID> NetworkManager::GetConnectedAdapterIds() const {
std::vector<GUID> 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<unsigned char> buffer(bufferSize);
PIP_ADAPTER_ADDRESSES addresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize);
if (rc == ERROR_BUFFER_OVERFLOW) {
buffer.resize(bufferSize);
addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(&buffer.front());
rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize);
}
return Connected == VARIANT_TRUE;

if (rc != NO_ERROR) {
return ConnectivityType::None;
}

std::vector<GUID> adapterIds = GetConnectedAdapterIds();
if (adapterIds.empty()) {
return ConnectivityType::None;
}

std::set<ConnectivityType> 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) {
Expand All @@ -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);
Expand Down