From 5b788dc53d6bb2c2157376bc09185dda8bc4533b Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 12 Apr 2024 08:12:48 +0200 Subject: [PATCH] [nrfconnect] Implemented WiFiNetworkDiagnostics events generation * Added generation of optional events from WiFiNetworkDiagnostics cluster. * Improved handler methods to validate the input data size --- src/platform/nrfconnect/wifi/WiFiManager.cpp | 109 ++++++++++++++++++- src/platform/nrfconnect/wifi/WiFiManager.h | 13 ++- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/src/platform/nrfconnect/wifi/WiFiManager.cpp b/src/platform/nrfconnect/wifi/WiFiManager.cpp index 6e3ff8e473ea13..d5783fa060c558 100644 --- a/src/platform/nrfconnect/wifi/WiFiManager.cpp +++ b/src/platform/nrfconnect/wifi/WiFiManager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -151,7 +152,7 @@ void WiFiManager::WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mg Platform::UniquePtr eventData(new uint8_t[cb->info_length]); VerifyOrReturn(eventData); memcpy(eventData.get(), cb->info, cb->info_length); - sEventHandlerMap[mgmtEvent](std::move(eventData)); + sEventHandlerMap[mgmtEvent](std::move(eventData), cb->info_length); } } @@ -292,8 +293,11 @@ CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const return CHIP_NO_ERROR; } -void WiFiManager::ScanResultHandler(Platform::UniquePtr data) +void WiFiManager::ScanResultHandler(Platform::UniquePtr data, size_t length) { + // Validate that input data size matches the expected one. + VerifyOrReturn(length == sizeof(wifi_scan_result)); + // Contrary to other handlers, offload accumulating of the scan results from the CHIP thread to the caller's thread const wifi_scan_result * scanResult = reinterpret_cast(data.get()); @@ -337,8 +341,11 @@ void WiFiManager::ScanResultHandler(Platform::UniquePtr data) } } -void WiFiManager::ScanDoneHandler(Platform::UniquePtr data) +void WiFiManager::ScanDoneHandler(Platform::UniquePtr data, size_t length) { + // Validate that input data size matches the expected one. + VerifyOrReturn(length == sizeof(wifi_status)); + CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { Platform::UniquePtr safePtr(capturedData); uint8_t * rawData = safePtr.get(); @@ -416,8 +423,13 @@ void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param) } } -void WiFiManager::ConnectHandler(Platform::UniquePtr data) +void WiFiManager::ConnectHandler(Platform::UniquePtr data, size_t length) { + using app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum; + + // Validate that input data size matches the expected one. + VerifyOrReturn(length == sizeof(wifi_status)); + CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { Platform::UniquePtr safePtr(capturedData); uint8_t * rawData = safePtr.get(); @@ -432,6 +444,32 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data) { Instance().mHandling.mOnConnectionDone(connStatus); } + + WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); + if (delegate) + { + uint16_t reason = Instance().GetLastDisconnectReason(); + uint8_t associationFailureCause; + + switch (connStatus) + { + case WIFI_STATUS_CONN_WRONG_PASSWORD: + associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAuthenticationFailed); + break; + case WIFI_STATUS_CONN_FAIL: + case WIFI_STATUS_CONN_TIMEOUT: + associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAssociationFailed); + break; + case WIFI_STATUS_CONN_AP_NOT_FOUND: + associationFailureCause = to_underlying(AssociationFailureCauseEnum::kSsidNotFound); + break; + default: + associationFailureCause = to_underlying(AssociationFailureCauseEnum::kUnknown); + break; + } + + delegate->OnAssociationFailureDetected(associationFailureCause, reason); + } } else // The connection has been established successfully. { @@ -457,6 +495,13 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data) { ChipLogError(DeviceLayer, "Cannot post event [error: %s]", ErrorStr(error)); } + + WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); + if (delegate) + { + delegate->OnConnectionStatusChanged( + to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected)); + } } // cleanup the provisioning data as it is configured per each connect request Instance().ClearStationProvisioningData(); @@ -469,13 +514,55 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr data) } } -void WiFiManager::DisconnectHandler(Platform::UniquePtr) +void WiFiManager::DisconnectHandler(Platform::UniquePtr data, size_t length) { - SystemLayer().ScheduleLambda([] { + // Validate that input data size matches the expected one. + VerifyOrReturn(length == sizeof(wifi_status)); + + CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] { + Platform::UniquePtr safePtr(capturedData); + uint8_t * rawData = safePtr.get(); + const wifi_status * status = reinterpret_cast(rawData); + uint16_t reason; + + switch (status->disconn_reason) + { + case WIFI_REASON_DISCONN_UNSPECIFIED: + reason = WLAN_REASON_UNSPECIFIED; + break; + case WIFI_REASON_DISCONN_USER_REQUEST: + reason = WLAN_REASON_DEAUTH_LEAVING; + break; + case WIFI_REASON_DISCONN_AP_LEAVING: + reason = WLAN_REASON_DEAUTH_LEAVING; + break; + case WIFI_REASON_DISCONN_INACTIVITY: + reason = WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY; + break; + default: + reason = WLAN_REASON_UNSPECIFIED; + break; + } + Instance().SetLastDisconnectReason(reason); + ChipLogProgress(DeviceLayer, "WiFi station disconnected"); Instance().mWiFiState = WIFI_STATE_DISCONNECTED; Instance().PostConnectivityStatusChange(kConnectivity_Lost); + + WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate(); + if (delegate) + { + delegate->OnConnectionStatusChanged( + to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected)); + delegate->OnDisconnectionDetected(reason); + } }); + + if (CHIP_NO_ERROR == err) + { + // the ownership has been transferred to the worker thread - release the buffer + data.release(); + } } void WiFiManager::IPv6AddressChangeHandler(const void * data) @@ -586,5 +673,15 @@ CHIP_ERROR WiFiManager::SetLowPowerMode(bool onoff) return CHIP_NO_ERROR; } +void WiFiManager::SetLastDisconnectReason(uint16_t reason) +{ + mLastDisconnectedReason = reason; +} + +uint16_t WiFiManager::GetLastDisconnectReason() +{ + return mLastDisconnectedReason; +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nrfconnect/wifi/WiFiManager.h b/src/platform/nrfconnect/wifi/WiFiManager.h index 2694b050cec4ac..a4e3a8afb39256 100644 --- a/src/platform/nrfconnect/wifi/WiFiManager.h +++ b/src/platform/nrfconnect/wifi/WiFiManager.h @@ -179,9 +179,11 @@ class WiFiManager CHIP_ERROR GetNetworkStatistics(NetworkStatistics & stats) const; void AbortConnectionRecovery(); CHIP_ERROR SetLowPowerMode(bool onoff); + void SetLastDisconnectReason(uint16_t reason); + uint16_t GetLastDisconnectReason(); private: - using NetEventHandler = void (*)(Platform::UniquePtr); + using NetEventHandler = void (*)(Platform::UniquePtr, size_t); struct ConnectionParams { @@ -197,10 +199,10 @@ class WiFiManager // Event handling static void WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface); static void IPv6MgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface); - static void ScanResultHandler(Platform::UniquePtr data); - static void ScanDoneHandler(Platform::UniquePtr data); - static void ConnectHandler(Platform::UniquePtr data); - static void DisconnectHandler(Platform::UniquePtr data); + static void ScanResultHandler(Platform::UniquePtr data, size_t length); + static void ScanDoneHandler(Platform::UniquePtr data, size_t length); + static void ConnectHandler(Platform::UniquePtr data, size_t length); + static void DisconnectHandler(Platform::UniquePtr data, size_t length); static void PostConnectivityStatusChange(ConnectivityChange changeType); static void SendRouterSolicitation(System::Layer * layer, void * param); static void IPv6AddressChangeHandler(const void * data); @@ -234,6 +236,7 @@ class WiFiManager uint32_t mConnectionRecoveryCounter{ 0 }; uint32_t mConnectionRecoveryTimeMs{ kConnectionRecoveryMinIntervalMs }; bool mApplicationDisconnectRequested{ false }; + uint16_t mLastDisconnectedReason = WLAN_REASON_UNSPECIFIED; static const Map sStatusMap; static const Map sEventHandlerMap;