From 49d2d0505eb916045fe6170ca901efb82fb629f3 Mon Sep 17 00:00:00 2001 From: Kristijan Mitrikjeski Date: Mon, 22 Apr 2024 20:12:50 +0200 Subject: [PATCH] Resolve issue with the connection status observer Implemented initialisation of the connection status observer during the tunnel connection process, thereby resolving the issue where tunnel connection status changes were not being detected. --- example/windows/CMakeLists.txt | 9 ++++++- example/windows/runner/flutter_window.cpp | 10 ++++++++ example/windows/runner/main.cpp | 2 +- example/windows/runner/utils.cpp | 9 ++++--- windows/connection_status_observer.cpp | 30 +++++++++++++---------- windows/connection_status_observer.h | 3 ++- windows/wireguard_dart_plugin.cpp | 2 ++ 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/example/windows/CMakeLists.txt b/example/windows/CMakeLists.txt index b92cdde..77f4b20 100644 --- a/example/windows/CMakeLists.txt +++ b/example/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "wireguard_dart_example") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") + # Generated plugin build rules, which manage building the plugins and adding # them to the application. include(flutter/generated_plugins.cmake) @@ -86,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) COMPONENT Runtime) endif() +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + # Fully re-copy the assets directory on each build to avoid having stale files # from a previous install. set(FLUTTER_ASSET_DIR_NAME "flutter_assets") diff --git a/example/windows/runner/flutter_window.cpp b/example/windows/runner/flutter_window.cpp index b43b909..955ee30 100644 --- a/example/windows/runner/flutter_window.cpp +++ b/example/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + return true; } diff --git a/example/windows/runner/main.cpp b/example/windows/runner/main.cpp index 41b8125..c52cee8 100644 --- a/example/windows/runner/main.cpp +++ b/example/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"wireguard_dart_example", origin, size)) { + if (!window.Create(L"wireguard_dart_example", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/example/windows/runner/utils.cpp b/example/windows/runner/utils.cpp index f5bf9fa..b2b0873 100644 --- a/example/windows/runner/utils.cpp +++ b/example/windows/runner/utils.cpp @@ -47,16 +47,17 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { } int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { + if (target_length <= 0 || target_length > utf8_string.max_size()) { return utf8_string; } utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/windows/connection_status_observer.cpp b/windows/connection_status_observer.cpp index 08f0970..a2ce11f 100644 --- a/windows/connection_status_observer.cpp +++ b/windows/connection_status_observer.cpp @@ -6,7 +6,6 @@ #include #include "connection_status.h" - namespace wireguard_dart { ConnectionStatusObserver::ConnectionStatusObserver() {} @@ -17,7 +16,22 @@ void ConnectionStatusObserver::StartObserving(std::wstring service_name) { if (m_running.load() == true) { return; } - watch_thread = std::thread(&ConnectionStatusObserver::StartObservingThreadProc, this, service_name); + if (service_name.size() > 0) { + m_service_name = service_name; + } + SC_HANDLE service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (service_manager == NULL) { + return; + } + SC_HANDLE service = OpenService(service_manager, &m_service_name[0], SERVICE_QUERY_STATUS | SERVICE_INTERROGATE); + if (service != NULL) { + m_running.store(true); + watch_thread = std::thread(&ConnectionStatusObserver::StartObservingThreadProc, this, service_manager, service); + } else { + CloseServiceHandle(service_manager); + m_running.store(false); + return; + } } void ConnectionStatusObserver::StopObserving() { m_watch_thread_stop.store(true); } @@ -29,17 +43,7 @@ void ConnectionStatusObserver::Shutdown() { } } -void ConnectionStatusObserver::StartObservingThreadProc(std::wstring service_name) { - m_running.store(true); - SC_HANDLE service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (service_manager == NULL) { - return; - } - SC_HANDLE service = OpenService(service_manager, &service_name[0], SERVICE_QUERY_STATUS | SERVICE_INTERROGATE); - if (service == NULL) { - CloseServiceHandle(service_manager); - return; - } +void ConnectionStatusObserver::StartObservingThreadProc(SC_HANDLE service_manager, SC_HANDLE service) { SERVICE_NOTIFY s_notify = {0}; s_notify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; s_notify.pfnNotifyCallback = &ServiceNotifyCallback; diff --git a/windows/connection_status_observer.h b/windows/connection_status_observer.h index 98894dc..09f8242 100644 --- a/windows/connection_status_observer.h +++ b/windows/connection_status_observer.h @@ -27,12 +27,13 @@ class ConnectionStatusObserver : public flutter::StreamHandler> sink_; PSC_NOTIFICATION_REGISTRATION subscription_; - void StartObservingThreadProc(std::wstring service_name); + void StartObservingThreadProc(SC_HANDLE service_manager, SC_HANDLE service); void Shutdown(); std::thread watch_thread; std::atomic_bool m_watch_thread_stop; std::atomic_bool m_running; + std::wstring m_service_name; }; } // namespace wireguard_dart diff --git a/windows/wireguard_dart_plugin.cpp b/windows/wireguard_dart_plugin.cpp index f53ed1f..705a96c 100644 --- a/windows/wireguard_dart_plugin.cpp +++ b/windows/wireguard_dart_plugin.cpp @@ -143,12 +143,14 @@ void WireguardDartPlugin::HandleMethodCall(const flutter::MethodCallError(std::string(e.what())); return; } + this->connection_status_observer_.get()->StartObserving(L""); try { tunnel_service->Start(); } catch (std::exception &e) { result->Error(std::string(e.what())); return; } + result->Success(); return; }