From 4d51e003c2d79d30b9e7f07908b59f96455f773e Mon Sep 17 00:00:00 2001 From: Damian Krolik Date: Fri, 27 Jan 2023 23:24:36 +0100 Subject: [PATCH] [icd] Defer subscription resumption On some platforms, DNS-SD initialization is asynchronous and any attempt to communicate with a peer node before that is completed must fail. Introduce kServerReady event that is emitted when all async initialization tasks are completed (currently, only DNS-SD) and resume persistent subscriptions in response to that event. --- src/app/server/Server.cpp | 55 ++++++++++++++++++++++++-- src/app/server/Server.h | 5 +++ src/include/platform/CHIPDeviceEvent.h | 9 +++++ src/lib/dnssd/BUILD.gn | 16 ++++++++ 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index d7f76abe19a0aa..f068d32d009800 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -28,6 +28,7 @@ #if CONFIG_NETWORK_LAYER_BLE #include #endif +#include #include #include #include @@ -353,12 +354,18 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) } } -#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS - ResumeSubscriptions(); -#endif - + PlatformMgr().AddEventHandler(OnPlatformEventWrapper, 0); PlatformMgr().HandleServerStarted(); +#if CHIP_DNSSD_PLATFORM + // Platform DNS-SD implementation uses kPlatformDnssdInitialized event to signal that it's ready. + mIsDnssdReady = false; +#else + // Minimal mDNS implementation is initialized synchronously so mark it as ready. + mIsDnssdReady = true; + CheckServerReadyEvent(); +#endif + exit: if (err != CHIP_NO_ERROR) { @@ -372,6 +379,45 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) return err; } +void Server::OnPlatformEvent(const DeviceLayer::ChipDeviceEvent & event) +{ + switch (event.Type) + { + case DeviceEventType::kServerReady: +#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS + ResumeSubscriptions(); +#endif + break; +#if CHIP_DNSSD_PLATFORM + case DeviceEventType::kDnssdPlatformInitialized: + if (!mIsDnssdReady) + { + mIsDnssdReady = true; + CheckServerReadyEvent(); + } + break; +#endif + default: + break; + } +} + +void Server::CheckServerReadyEvent() +{ + // Check if all asynchronously initialized components (currently, only DNS-SD) are ready, and + // emit the 'server ready' event if so. + if (mIsDnssdReady) + { + ChipDeviceEvent event = { .Type = DeviceEventType::kServerReady }; + PlatformMgr().PostEventOrDie(&event); + } +} + +void Server::OnPlatformEventWrapper(const DeviceLayer::ChipDeviceEvent * event, intptr_t) +{ + Server::GetInstance().OnPlatformEvent(*event); +} + void Server::RejoinExistingMulticastGroups() { ChipLogProgress(AppServer, "Joining Multicast groups"); @@ -423,6 +469,7 @@ void Server::ScheduleFactoryReset() void Server::Shutdown() { + PlatformMgr().RemoveEventHandler(OnPlatformEventWrapper, 0); mCASEServer.Shutdown(); mCASESessionManager.Shutdown(); app::DnssdServer::Instance().SetCommissioningModeProvider(nullptr); diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 6fcf79f01bf2af..70b877a0338ec4 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -377,6 +377,10 @@ class Server static Server sServer; void InitFailSafe(); + void OnPlatformEvent(const DeviceLayer::ChipDeviceEvent & event); + void CheckServerReadyEvent(); + + static void OnPlatformEventWrapper(const DeviceLayer::ChipDeviceEvent * event, intptr_t); #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS /** @@ -561,6 +565,7 @@ class Server uint16_t mOperationalServicePort; uint16_t mUserDirectedCommissioningPort; Inet::InterfaceId mInterfaceId; + bool mIsDnssdReady = false; }; } // namespace chip diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index 4d3e8353e85e13..dd597b63b2a867 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -225,6 +225,15 @@ enum PublicEventTypes * Signals that the state of the OTA engine changed. */ kOtaStateChanged, + + /** + * Server initialization has completed. + * + * Signals that all server components have been initialized and the node is ready to establish + * connections with other nodes. This event can be used to trigger on-boot actions that require + * sending messages to other nodes. + */ + kServerReady, }; /** diff --git a/src/lib/dnssd/BUILD.gn b/src/lib/dnssd/BUILD.gn index e723dd54466600..712aa24c15d90e 100644 --- a/src/lib/dnssd/BUILD.gn +++ b/src/lib/dnssd/BUILD.gn @@ -14,14 +14,30 @@ import("//build_overrides/chip.gni") import("//build_overrides/nlunit_test.gni") + +import("${chip_root}/build/chip/buildconfig_header.gni") import("${chip_root}/src/platform/device.gni") source_set("platform_header") { sources = [ "platform/Dnssd.h" ] } +buildconfig_header("dnssd_buildconfig") { + header = "DnssdBuildConfig.h" + header_dir = "dnssd" + + chip_dnssd_minimal = chip_mdns == "minimal" + chip_dnssd_platform = chip_mdns == "platform" + + defines = [ + "CHIP_DNSSD_MINIMAL=${chip_dnssd_minimal}", + "CHIP_DNSSD_PLATFORM=${chip_dnssd_platform}", + ] +} + static_library("dnssd") { public_deps = [ + ":dnssd_buildconfig", ":platform_header", "${chip_root}/src/crypto", "${chip_root}/src/lib/core",