From bb3f54cab3cb1d8f5d051f617f807534dcc7bf42 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Wed, 4 Sep 2024 16:58:54 -0700 Subject: [PATCH] Fix iOS app crash due to null cpp cluster --- .../MatterTvCastingBridge/MCEndpoint.mm | 72 ++++++++++++++----- ...ionBasicReadVendorIDExampleViewModel.swift | 2 +- ...entLauncherLaunchURLExampleViewModel.swift | 2 +- ...scribeToCurrentStateExampleViewModel.swift | 2 +- .../tv-casting-common/core/BaseCluster.h | 20 +++++- .../tv-casting-common/core/CastingPlayer.cpp | 1 + .../tv-casting-common/core/CastingPlayer.h | 5 -- .../tv-casting-common/core/Endpoint.cpp | 4 +- .../tv-casting-common/core/Endpoint.h | 3 + .../support/CastingStore.cpp | 14 +++- .../support/EndpointListLoader.cpp | 9 ++- 11 files changed, 102 insertions(+), 32 deletions(-) diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm index 24b5c8639aa6e2..5b26e1575e6177 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCEndpoint.mm @@ -90,27 +90,67 @@ - (MCCastingPlayer * _Nonnull)castingPlayer - (MCCluster * _Nullable)clusterForType:(MCEndpointClusterType)type { switch (type) { - case MCEndpointClusterTypeApplicationBasic: - return [[MCApplicationBasicCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; - - case MCEndpointClusterTypeApplicationLauncher: - return [[MCApplicationLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; - - case MCEndpointClusterTypeContentLauncher: - return [[MCContentLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeApplicationBasic: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeApplicationBasic, GetCluster() returned nullptr"); + return nil; + } + return [[MCApplicationBasicCluster alloc] initWithCppCluster:cppCluster]; + } - case MCEndpointClusterTypeKeypadInput: - return [[MCKeypadInputCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeApplicationLauncher: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeApplicationLauncher GetCluster() returned nullptr"); + return nil; + } + return [[MCApplicationLauncherCluster alloc] initWithCppCluster:cppCluster]; + } - case MCEndpointClusterTypeMediaPlayback: - return [[MCMediaPlaybackCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeContentLauncher: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeContentLauncher GetCluster() returned nullptr"); + return nil; + } + return [[MCContentLauncherCluster alloc] initWithCppCluster:cppCluster]; + } - case MCEndpointClusterTypeOnOff: - return [[MCOnOffCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeKeypadInput: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeKeypadInput GetCluster() returned nullptr"); + return nil; + } + return [[MCKeypadInputCluster alloc] initWithCppCluster:cppCluster]; + } - case MCEndpointClusterTypeTargetNavigator: - return [[MCTargetNavigatorCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster()]; + case MCEndpointClusterTypeMediaPlayback: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeMediaPlayback GetCluster() returned nullptr"); + return nil; + } + return [[MCMediaPlaybackCluster alloc] initWithCppCluster:cppCluster]; + } + case MCEndpointClusterTypeOnOff: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeOnOff GetCluster() returned nullptr"); + return nil; + } + return [[MCOnOffCluster alloc] initWithCppCluster:cppCluster]; + } + case MCEndpointClusterTypeTargetNavigator: { + auto cppCluster = _cppEndpoint->GetCluster(); + if (cppCluster == nullptr) { + ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeTargetNavigator GetCluster() returned nullptr"); + return nil; + } + return [[MCTargetNavigatorCluster alloc] initWithCppCluster:cppCluster]; + } default: ChipLogError(AppServer, "MCEndpointClusterType not found"); break; diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift index a95580f5aaf7cd..3efed6baa1289a 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCApplicationBasicReadVendorIDExampleViewModel.swift @@ -47,7 +47,7 @@ class MCApplicationBasicReadVendorIDExampleViewModel: ObservableObject { // validate that the selected endpoint supports the ApplicationBasic cluster if(!endpoint.hasCluster(MCEndpointClusterTypeApplicationBasic)) { - self.Log.error("No ApplicationBasic cluster supporting endpoint found") + self.Log.error("MCApplicationBasicReadVendorIDExampleViewModel.read() No ApplicationBasic cluster supporting endpoint found") DispatchQueue.main.async { self.status = "No ApplicationBasic cluster supporting endpoint found" diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift index aaf18375bb2c82..7f337ed473eb94 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCContentLauncherLaunchURLExampleViewModel.swift @@ -47,7 +47,7 @@ class MCContentLauncherLaunchURLExampleViewModel: ObservableObject { // validate that the selected endpoint supports the ContentLauncher cluster if(!endpoint.hasCluster(MCEndpointClusterTypeContentLauncher)) { - self.Log.error("No ContentLauncher cluster supporting endpoint found") + self.Log.error("MCContentLauncherLaunchURLExampleViewModel.invokeCommand() No ContentLauncher cluster supporting endpoint found") DispatchQueue.main.async { self.status = "No ContentLauncher cluster supporting endpoint found" diff --git a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift index 7a4752431e1846..e699240c49af6c 100644 --- a/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift +++ b/examples/tv-casting-app/darwin/TvCasting/TvCasting/MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.swift @@ -47,7 +47,7 @@ class MCMediaPlaybackSubscribeToCurrentStateExampleViewModel: ObservableObject { // validate that the selected endpoint supports the MediaPlayback cluster if(!endpoint.hasCluster(MCEndpointClusterTypeMediaPlayback)) { - self.Log.error("No MediaPlayback cluster supporting endpoint found") + self.Log.error("MCMediaPlaybackSubscribeToCurrentStateExampleViewModel.subscribe() No MediaPlayback cluster supporting endpoint found") DispatchQueue.main.async { self.status = "No MediaPlayback cluster supporting endpoint found" diff --git a/examples/tv-casting-app/tv-casting-common/core/BaseCluster.h b/examples/tv-casting-app/tv-casting-common/core/BaseCluster.h index e98f690cee0087..059bb55ad19800 100644 --- a/examples/tv-casting-app/tv-casting-common/core/BaseCluster.h +++ b/examples/tv-casting-app/tv-casting-common/core/BaseCluster.h @@ -58,12 +58,28 @@ class BaseCluster /** * @return Pointer to the Attribute registered in this cluster, corresponding to attributeId */ - void * GetAttribute(const chip::AttributeId attributeId) { return mAttributes[attributeId]; } + void * GetAttribute(const chip::AttributeId attributeId) + { + if (mAttributes.empty()) + { + ChipLogError(AppServer, "BaseCluster::GetAttribute() mAttributes is empty"); + return nullptr; + } + return mAttributes[attributeId]; + } /** * @return Pointer to the Command registered in this cluster, corresponding to commandId */ - void * GetCommand(const chip::CommandId commandId) { return mCommands[commandId]; } + void * GetCommand(const chip::CommandId commandId) + { + if (mCommands.empty()) + { + ChipLogError(AppServer, "BaseCluster::GetCommand() mCommands is empty"); + return nullptr; + } + return mCommands[commandId]; + } protected: /** diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index a833507cb6e3ae..83fc6b4b563a9e 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -109,6 +109,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectionCallbacks connectionCa // found the CastingPlayer in cache if (it != cachedCastingPlayers.end()) { + ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() found this CastingPlayer in app cache"); unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it); if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.getTargetAppInfoList())) { diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h index b8119f13fa1863..b2422b43f5dee6 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -102,16 +102,11 @@ class CastingPlayer : public std::enable_shared_from_this */ static CastingPlayer * GetTargetCastingPlayer() { - ChipLogProgress(AppServer, "CastingPlayer::GetTargetCastingPlayer() called"); std::shared_ptr sharedPtr = mTargetCastingPlayer.lock(); CastingPlayer * rawPtr = nullptr; if (sharedPtr) { rawPtr = sharedPtr.get(); - ChipLogProgress( - AppServer, - "CastingPlayer::GetTargetCastingPlayer() Got rawPtr from mTargetCastingPlayer, sharedPtr reference count: %lu", - sharedPtr.use_count()); sharedPtr.reset(); } else diff --git a/examples/tv-casting-app/tv-casting-common/core/Endpoint.cpp b/examples/tv-casting-app/tv-casting-common/core/Endpoint.cpp index d2fb12e48daf68..25b9e2850edb56 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Endpoint.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/Endpoint.cpp @@ -28,6 +28,7 @@ void Endpoint::RegisterClusters(std::vector clusters) { for (chip::ClusterId clusterId : clusters) { + ChipLogProgress(AppServer, "Endpoint::RegisterClusters() Registering clusterId %d for endpointId %d", clusterId, GetId()); switch (clusterId) { case chip::app::Clusters::ApplicationBasic::Id: @@ -67,7 +68,8 @@ void Endpoint::RegisterClusters(std::vector clusters) break; default: - ChipLogProgress(AppServer, "Skipping registration of clusterId %d for endpointId %d", clusterId, GetId()); + ChipLogProgress(AppServer, "Endpoint::RegisterClusters() Skipping registration of clusterId %d for endpointId %d", + clusterId, GetId()); break; } } diff --git a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h index fc18267cf466be..734f1e3d5ae140 100644 --- a/examples/tv-casting-app/tv-casting-common/core/Endpoint.h +++ b/examples/tv-casting-app/tv-casting-common/core/Endpoint.h @@ -105,6 +105,7 @@ class Endpoint : public std::enable_shared_from_this */ std::vector GetServerList() { + ChipLogProgress(AppServer, "Endpoint::GetServerList() mClusters.size(): %d", static_cast(mClusters.size())); std::vector serverList; for (auto const & cluster : mClusters) { @@ -122,6 +123,7 @@ class Endpoint : public std::enable_shared_from_this template void RegisterCluster(const chip::ClusterId clusterId) { + ChipLogProgress(AppServer, "Endpoint::RegisterCluster() Registering clusterId %d for endpointId %d", clusterId, GetId()); static_assert(std::is_base_of::value, "T must be derived from BaseCluster"); auto cluster = std::make_shared(shared_from_this()); cluster->SetUp(); @@ -135,6 +137,7 @@ class Endpoint : public std::enable_shared_from_this memory::Strong GetCluster() { static_assert(std::is_base_of::value, "T must be derived from BaseCluster"); + ChipLogProgress(AppServer, "Endpoint::GetCluster() mClusters.size(): %d", static_cast(mClusters.size())); for (const auto & pair : mClusters) { auto cluster = std::dynamic_pointer_cast(pair.second); diff --git a/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp b/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp index 2e8561d2e5aab1..93bd00616dac6c 100644 --- a/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp +++ b/examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp @@ -427,9 +427,14 @@ std::vector CastingStore::ReadAll() for (auto & endpointAttributes : endpointAttributesList) { std::shared_ptr endpoint(new core::Endpoint(castingPlayer, endpointAttributes)); + ChipLogProgress(AppServer, "CastingStore::ReadAll() endpointServerListMap[endpointAttributes.mId].size(): %d", + static_cast(endpointServerListMap[endpointAttributes.mId].size())); endpoint->RegisterClusters(endpointServerListMap[endpointAttributes.mId]); castingPlayer->RegisterEndpoint(endpoint); + ChipLogProgress(AppServer, "CastingStore::ReadAll() Registered endpointID: %d", endpoint->GetId()); } + ChipLogProgress(AppServer, "CastingStore::ReadAll() Created CastingPlayer with deviceName: %s", + castingPlayer->GetDeviceName()); castingPlayers.push_back(*castingPlayer); continue; } @@ -453,7 +458,7 @@ std::vector CastingStore::ReadAll() CHIP_ERROR CastingStore::WriteAll(std::vector castingPlayers) { - ChipLogProgress(AppServer, "CastingStore::WriteAll called"); + ChipLogProgress(AppServer, "CastingStore::WriteAll() called"); chip::TLV::TLVWriter tlvWriter; uint8_t castingStoreData[kCastingStoreDataMaxBytes]; @@ -470,6 +475,7 @@ CHIP_ERROR CastingStore::WriteAll(std::vector castingPlayer for (auto & castingPlayer : castingPlayers) { + ChipLogProgress(AppServer, "CastingStore::WriteAll() writing castingPlayer:"); chip::TLV::TLVType castingPlayerContainerType; // CastingPlayer container starts ReturnErrorOnFailure( @@ -502,6 +508,8 @@ CHIP_ERROR CastingStore::WriteAll(std::vector castingPlayer std::vector> endpoints = core::CastingPlayer::GetTargetCastingPlayer()->GetEndpoints(); for (auto & endpoint : endpoints) { + ChipLogProgress(AppServer, "CastingStore::WriteAll() writing CastingPlayer Endpoint with endpointId: %d", + endpoint->GetId()); chip::TLV::TLVType endpointContainerType; // Endpoint container starts ReturnErrorOnFailure( @@ -539,8 +547,10 @@ CHIP_ERROR CastingStore::WriteAll(std::vector castingPlayer ReturnErrorOnFailure(tlvWriter.StartContainer(chip::TLV::ContextTag(kCastingPlayerEndpointServerListContainerTag), chip::TLV::kTLVType_Structure, serverListContainerType)); std::vector serverList = endpoint->GetServerList(); + ChipLogProgress(AppServer, "CastingStore::WriteAll() writing CastingPlayer Endpoint ServerList:"); for (chip::ClusterId clusterId : serverList) { + ChipLogProgress(AppServer, "CastingStore::WriteAll() clusterId: %d", clusterId); ReturnErrorOnFailure(tlvWriter.Put(chip::TLV::ContextTag(kCastingPlayerEndpointServerClusterIdTag), clusterId)); } // ServerList container ends @@ -562,7 +572,7 @@ CHIP_ERROR CastingStore::WriteAll(std::vector castingPlayer ReturnErrorOnFailure(tlvWriter.Finalize()); ChipLogProgress(AppServer, - "CastingStore::WriteAll TLV(CastingStoreData).LengthWritten: %d bytes, CastingPlayers size: %lu " + "CastingStore::WriteAll() TLV(CastingStoreData).LengthWritten: %d bytes, CastingPlayers size: %lu " "and version: %d", tlvWriter.GetLengthWritten(), static_cast(castingPlayers.size()), kCurrentCastingStoreDataVersion); diff --git a/examples/tv-casting-app/tv-casting-common/support/EndpointListLoader.cpp b/examples/tv-casting-app/tv-casting-common/support/EndpointListLoader.cpp index a7bbfb78d6ad3a..7d32456ad534fc 100644 --- a/examples/tv-casting-app/tv-casting-common/support/EndpointListLoader.cpp +++ b/examples/tv-casting-app/tv-casting-common/support/EndpointListLoader.cpp @@ -90,7 +90,8 @@ CHIP_ERROR EndpointListLoader::Load() if (binding.type == MATTER_UNICAST_BINDING && CastingPlayer::GetTargetCastingPlayer()->GetNodeId() == binding.nodeId) { // if we discovered a new Endpoint from the bindings, read its EndpointAttributes - chip::EndpointId endpointId = binding.remote; + chip::EndpointId endpointId = binding.remote; + ChipLogProgress(AppServer, "EndpointListLoader::Load() Found new endpointId: %d", endpointId); std::vector> endpoints = CastingPlayer::GetTargetCastingPlayer()->GetEndpoints(); if (std::find_if(endpoints.begin(), endpoints.end(), [&endpointId](const memory::Strong & endpoint) { return endpoint->GetId() == endpointId; @@ -128,17 +129,19 @@ void EndpointListLoader::Complete() if (mPendingAttributeReads == 0) { - ChipLogProgress(AppServer, "EndpointListLoader::Complete Loading %lu endpoint(s)", mNewEndpointsToLoad); + ChipLogProgress(AppServer, "EndpointListLoader::Complete() Loading %lu endpoint(s)", mNewEndpointsToLoad); for (unsigned long i = 0; i < mNewEndpointsToLoad; i++) { EndpointAttributes endpointAttributes = mEndpointAttributesList[i]; std::shared_ptr endpoint = std::make_shared(CastingPlayer::GetTargetCastingPlayer(), endpointAttributes); + ChipLogProgress(AppServer, "EndpointListLoader::Complete() mEndpointServerLists[i].size: %lu ", + mEndpointServerLists[i].size()); endpoint->RegisterClusters(mEndpointServerLists[i]); CastingPlayer::GetTargetCastingPlayer()->RegisterEndpoint(endpoint); } - ChipLogProgress(AppServer, "EndpointListLoader::Complete finished Loading %lu endpoints", mNewEndpointsToLoad); + ChipLogProgress(AppServer, "EndpointListLoader::Complete() Finished Loading %lu endpoints", mNewEndpointsToLoad); // TODO cleanup // delete mEndpointAttributesList;