Skip to content

Commit

Permalink
Fix iOS app crash due to null cpp cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
pgregorr-amazon committed Sep 4, 2024
1 parent 3a7ddbe commit bb3f54c
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,27 +90,67 @@ - (MCCastingPlayer * _Nonnull)castingPlayer
- (MCCluster * _Nullable)clusterForType:(MCEndpointClusterType)type
{
switch (type) {
case MCEndpointClusterTypeApplicationBasic:
return [[MCApplicationBasicCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster<matter::casting::clusters::application_basic::ApplicationBasicCluster>()];

case MCEndpointClusterTypeApplicationLauncher:
return [[MCApplicationLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster<matter::casting::clusters::application_launcher::ApplicationLauncherCluster>()];

case MCEndpointClusterTypeContentLauncher:
return [[MCContentLauncherCluster alloc] initWithCppCluster:_cppEndpoint->GetCluster<matter::casting::clusters::content_launcher::ContentLauncherCluster>()];
case MCEndpointClusterTypeApplicationBasic: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::application_basic::ApplicationBasicCluster>();
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<matter::casting::clusters::keypad_input::KeypadInputCluster>()];
case MCEndpointClusterTypeApplicationLauncher: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::application_launcher::ApplicationLauncherCluster>();
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<matter::casting::clusters::media_playback::MediaPlaybackCluster>()];
case MCEndpointClusterTypeContentLauncher: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::content_launcher::ContentLauncherCluster>();
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<matter::casting::clusters::on_off::OnOffCluster>()];
case MCEndpointClusterTypeKeypadInput: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::keypad_input::KeypadInputCluster>();
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<matter::casting::clusters::target_navigator::TargetNavigatorCluster>()];
case MCEndpointClusterTypeMediaPlayback: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::media_playback::MediaPlaybackCluster>();
if (cppCluster == nullptr) {
ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeMediaPlayback GetCluster() returned nullptr");
return nil;
}
return [[MCMediaPlaybackCluster alloc] initWithCppCluster:cppCluster];
}

case MCEndpointClusterTypeOnOff: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::on_off::OnOffCluster>();
if (cppCluster == nullptr) {
ChipLogError(AppServer, "MCEndpoint::clusterForType() MCEndpointClusterTypeOnOff GetCluster() returned nullptr");
return nil;
}
return [[MCOnOffCluster alloc] initWithCppCluster:cppCluster];
}
case MCEndpointClusterTypeTargetNavigator: {
auto cppCluster = _cppEndpoint->GetCluster<matter::casting::clusters::target_navigator::TargetNavigatorCluster>();
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
20 changes: 18 additions & 2 deletions examples/tv-casting-app/tv-casting-common/core/BaseCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,11 @@ class CastingPlayer : public std::enable_shared_from_this<CastingPlayer>
*/
static CastingPlayer * GetTargetCastingPlayer()
{
ChipLogProgress(AppServer, "CastingPlayer::GetTargetCastingPlayer() called");
std::shared_ptr<CastingPlayer> 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
Expand Down
4 changes: 3 additions & 1 deletion examples/tv-casting-app/tv-casting-common/core/Endpoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void Endpoint::RegisterClusters(std::vector<chip::ClusterId> 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:
Expand Down Expand Up @@ -67,7 +68,8 @@ void Endpoint::RegisterClusters(std::vector<chip::ClusterId> 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;
}
}
Expand Down
3 changes: 3 additions & 0 deletions examples/tv-casting-app/tv-casting-common/core/Endpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ class Endpoint : public std::enable_shared_from_this<Endpoint>
*/
std::vector<chip::ClusterId> GetServerList()
{
ChipLogProgress(AppServer, "Endpoint::GetServerList() mClusters.size(): %d", static_cast<int>(mClusters.size()));
std::vector<chip::ClusterId> serverList;
for (auto const & cluster : mClusters)
{
Expand All @@ -122,6 +123,7 @@ class Endpoint : public std::enable_shared_from_this<Endpoint>
template <typename T>
void RegisterCluster(const chip::ClusterId clusterId)
{
ChipLogProgress(AppServer, "Endpoint::RegisterCluster() Registering clusterId %d for endpointId %d", clusterId, GetId());
static_assert(std::is_base_of<BaseCluster, T>::value, "T must be derived from BaseCluster");
auto cluster = std::make_shared<T>(shared_from_this());
cluster->SetUp();
Expand All @@ -135,6 +137,7 @@ class Endpoint : public std::enable_shared_from_this<Endpoint>
memory::Strong<T> GetCluster()
{
static_assert(std::is_base_of<BaseCluster, T>::value, "T must be derived from BaseCluster");
ChipLogProgress(AppServer, "Endpoint::GetCluster() mClusters.size(): %d", static_cast<int>(mClusters.size()));
for (const auto & pair : mClusters)
{
auto cluster = std::dynamic_pointer_cast<T>(pair.second);
Expand Down
14 changes: 12 additions & 2 deletions examples/tv-casting-app/tv-casting-common/support/CastingStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,14 @@ std::vector<core::CastingPlayer> CastingStore::ReadAll()
for (auto & endpointAttributes : endpointAttributesList)
{
std::shared_ptr<core::Endpoint> endpoint(new core::Endpoint(castingPlayer, endpointAttributes));
ChipLogProgress(AppServer, "CastingStore::ReadAll() endpointServerListMap[endpointAttributes.mId].size(): %d",
static_cast<int>(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;
}
Expand All @@ -453,7 +458,7 @@ std::vector<core::CastingPlayer> CastingStore::ReadAll()

CHIP_ERROR CastingStore::WriteAll(std::vector<core::CastingPlayer> castingPlayers)
{
ChipLogProgress(AppServer, "CastingStore::WriteAll called");
ChipLogProgress(AppServer, "CastingStore::WriteAll() called");

chip::TLV::TLVWriter tlvWriter;
uint8_t castingStoreData[kCastingStoreDataMaxBytes];
Expand All @@ -470,6 +475,7 @@ CHIP_ERROR CastingStore::WriteAll(std::vector<core::CastingPlayer> castingPlayer

for (auto & castingPlayer : castingPlayers)
{
ChipLogProgress(AppServer, "CastingStore::WriteAll() writing castingPlayer:");
chip::TLV::TLVType castingPlayerContainerType;
// CastingPlayer container starts
ReturnErrorOnFailure(
Expand Down Expand Up @@ -502,6 +508,8 @@ CHIP_ERROR CastingStore::WriteAll(std::vector<core::CastingPlayer> castingPlayer
std::vector<memory::Strong<core::Endpoint>> 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(
Expand Down Expand Up @@ -539,8 +547,10 @@ CHIP_ERROR CastingStore::WriteAll(std::vector<core::CastingPlayer> castingPlayer
ReturnErrorOnFailure(tlvWriter.StartContainer(chip::TLV::ContextTag(kCastingPlayerEndpointServerListContainerTag),
chip::TLV::kTLVType_Structure, serverListContainerType));
std::vector<chip::ClusterId> 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
Expand All @@ -562,7 +572,7 @@ CHIP_ERROR CastingStore::WriteAll(std::vector<core::CastingPlayer> 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<unsigned long>(castingPlayers.size()),
kCurrentCastingStoreDataVersion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<memory::Strong<Endpoint>> endpoints = CastingPlayer::GetTargetCastingPlayer()->GetEndpoints();
if (std::find_if(endpoints.begin(), endpoints.end(), [&endpointId](const memory::Strong<Endpoint> & endpoint) {
return endpoint->GetId() == endpointId;
Expand Down Expand Up @@ -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> endpoint =
std::make_shared<Endpoint>(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;
Expand Down

0 comments on commit bb3f54c

Please sign in to comment.