From a94d74e28d54668a8b5509a37dfb9afda477a890 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Thu, 2 May 2024 17:06:45 -0700 Subject: [PATCH 1/7] Linux tv-casting-app v1.3 IdentificationDeclaration message --- .../jni/cpp/core/MatterCastingPlayer-JNI.cpp | 5 +- .../MatterTvCastingBridge/MCCastingPlayer.mm | 3 +- .../linux/simple-app-helper.cpp | 21 ++-- .../tv-casting-common/core/CastingApp.cpp | 3 + .../tv-casting-common/core/CastingPlayer.cpp | 68 +++++++++---- .../tv-casting-common/core/CastingPlayer.h | 98 +++++++++++++++++-- src/app/server/Server.cpp | 2 +- .../UserDirectedCommissioningServer.cpp | 1 + 8 files changed, 165 insertions(+), 36 deletions(-) diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp index caa64b4ac8d717..2ec5f64c2867d8 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp @@ -80,6 +80,9 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) MatterCastingPlayerJNIMgr().mConnectionSuccessHandler.SetUp(env, jSuccessCallback); MatterCastingPlayerJNIMgr().mConnectionFailureHandler.SetUp(env, jFailureCallback); + + // TODO: In the following PRs. Removed desiredEndpointFilter to fix Android app build issue. Replace desiredEndpointFilter with + // optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter. castingPlayer->VerifyOrEstablishConnection( [](CHIP_ERROR err, CastingPlayer * playerPtr) { ChipLogProgress(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() ConnectCallback called"); @@ -96,7 +99,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) MatterCastingPlayerJNIMgr().mConnectionFailureHandler.Handle(err); } }, - static_cast(commissioningWindowTimeoutSec), desiredEndpointFilter); + static_cast(commissioningWindowTimeoutSec)); return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR); } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index b69bbfb99f9bd7..1e96e45e7bfa1f 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -58,13 +58,14 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError cppDesiredEndpointFilter.productId = desiredEndpointFilter.productId; } + // TODO: In the following PRs. Removed desiredEndpointFilter to fix iOS app build issue. Replace desiredEndpointFilter with optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter. _cppCastingPlayer->VerifyOrEstablishConnection( [completion](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { dispatch_queue_t clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; dispatch_async(clientQueue, ^{ completion(err == CHIP_NO_ERROR ? nil : [MCErrorUtils NSErrorFromChipError:err]); }); - }, timeout, cppDesiredEndpointFilter); + }, timeout); }); } diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index de8c255366cd37..ff64d34f8299a4 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -170,10 +170,12 @@ void ConnectionHandler(CHIP_ERROR err, matter::casting::core::CastingPlayer * ca { VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogProgress(AppServer, - "ConnectionHandler: Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT, + "ConnectionHandler(): Failed to connect to CastingPlayer(ID: %s) with err %" CHIP_ERROR_FORMAT, castingPlayer->GetId(), err.Format())); - ChipLogProgress(AppServer, "ConnectionHandler: Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId()); + ChipLogProgress(AppServer, "ConnectionHandler(): Successfully connected to CastingPlayer(ID: %s)", castingPlayer->GetId()); + ChipLogProgress(AppServer, "ConnectionHandler(): Triggering demo interactions with CastingPlayer(ID: %s)", + castingPlayer->GetId()); std::vector> endpoints = castingPlayer->GetEndpoints(); // Find the desired Endpoint and auto-trigger some Matter Casting demo interactions @@ -230,7 +232,7 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) } if (strcmp(argv[0], "request") == 0) { - ChipLogProgress(AppServer, "request"); + ChipLogProgress(AppServer, "CommandHandler() request"); if (argc < 2) { return PrintAllCommands(); @@ -243,10 +245,17 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) ChipLogError(AppServer, "Invalid casting player index provided: %lu", index)); std::shared_ptr targetCastingPlayer = castingPlayers.at(index); - matter::casting::core::EndpointFilter desiredEndpointFilter; - desiredEndpointFilter.vendorId = kDesiredEndpointVendorId; + matter::casting::core::IdentificationDeclarationOptions idOptions; + idOptions.mNumTargetAppInfos = 1; + idOptions.mTargetAppInfos[0].vendorId = kDesiredEndpointVendorId; + // Attempt Commissioner-Generated Passcode commissioning flow only if the CastingPlayer indicates support for it. + if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode()) + { + idOptions.mCommissionerPasscode = true; + } + targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler, matter::casting::core::kCommissioningWindowTimeoutSec, - desiredEndpointFilter); + idOptions); return CHIP_NO_ERROR; } if (strcmp(argv[0], "print-bindings") == 0) diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index f7865910832ec9..c274edd016ed07 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -100,6 +100,9 @@ CHIP_ERROR CastingApp::Start() // reconnect (or verify connection) to the CastingPlayer that the app was connected to before being stopped, if any if (CastingPlayer::GetTargetCastingPlayer() != nullptr) { + ChipLogProgress( + Discovery, + "CastingApp::Start() calling VerifyOrEstablishConnection() to reconnect (or verify connection) to a CastingPlayer"); CastingPlayer::GetTargetCastingPlayer()->VerifyOrEstablishConnection( [](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { if (err != CHIP_NO_ERROR) 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 c9f938dbc695c7..7acf147c8c5764 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -30,7 +30,7 @@ namespace core { CastingPlayer * CastingPlayer::mTargetCastingPlayer = nullptr; void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec, - EndpointFilter desiredEndpointFilter) + IdentificationDeclarationOptions idOptions) { ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() called"); @@ -46,16 +46,19 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns ChipLogError( AppServer, "CastingPlayer::VerifyOrEstablishConnection() called while already connecting/connected to this CastingPlayer")); - mConnectionState = CASTING_PLAYER_CONNECTING; - mOnCompleted = onCompleted; - mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec; - mTargetCastingPlayer = this; + mConnectionState = CASTING_PLAYER_CONNECTING; + mOnCompleted = onCompleted; + mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec; + mTargetCastingPlayer = this; + mIdOptions = idOptions; + mUdcCommissionerPasscodeEnabled = idOptions.mCommissionerPasscode; // If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present // in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any, - // as per desiredEndpointFilter, simply Find or Re-establish the CASE session and return early + // as per IdentificationDeclarationOptions.mTargetAppInfos, simply Find or Re-establish the CASE session and return early. if (cachedCastingPlayers.size() != 0) { + ChipLogProgress(AppServer, "CastingPlayer::VerifyOrEstablishConnection() Re-establishing CASE with cached CastingPlayer"); it = std::find_if(cachedCastingPlayers.begin(), cachedCastingPlayers.end(), [this](const core::CastingPlayer & castingPlayerParam) { return castingPlayerParam == *this; }); @@ -63,7 +66,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns if (it != cachedCastingPlayers.end()) { unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it); - if (ContainsDesiredEndpoint(&cachedCastingPlayers[index], desiredEndpointFilter)) + if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.mTargetAppInfos, idOptions.mNumTargetAppInfos)) { ChipLogProgress( AppServer, @@ -163,14 +166,39 @@ void CastingPlayer::RegisterEndpoint(const memory::Strong endpoint) #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() { + ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() creating IdentificationDeclaration message"); chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest(); VerifyOrReturnValue(ipAddressToUse != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(AppServer, "No IP Address found to send UDC request to")); ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true)); - // TODO: expose options to the higher layer chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + for (size_t i = 0; i < mIdOptions.mNumTargetAppInfos; i++) + { + id.AddTargetAppInfo(mIdOptions.mTargetAppInfos[i]); + } + id.SetNoPasscode(mIdOptions.mNoPasscode); + id.SetCdUponPasscodeDialog(mIdOptions.mCdUponPasscodeDialog); + id.SetCancelPasscode(mIdOptions.mCancelPasscode); + + ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() mUdcCommissionerPasscodeEnabled: %s", + mUdcCommissionerPasscodeEnabled ? "true" : "false"); + if (mUdcCommissionerPasscodeEnabled) + { + id.SetCommissionerPasscode(true); + if (mUdcCommissionerPasscodeReady) + { + id.SetCommissionerPasscodeReady(true); + mUdcCommissionerPasscodeReady = false; + } + } + + // TODO: In the following PRs. Implement handler for CommissionerDeclaration messages and expose messages to higher layers for + // Linux, Android and iOS. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( + mCommissionerDeclarationHandler); + ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); @@ -216,21 +244,27 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC connectionContext->mOnConnectionFailureCallback); } -bool CastingPlayer::ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter) +bool CastingPlayer::ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps, + uint8_t numTargetApps) { std::vector> cachedEndpoints = cachedCastingPlayer->GetEndpoints(); - for (const auto & cachedEndpoint : cachedEndpoints) + for (size_t i = 0; i < numTargetApps; i++) { - bool match = true; - match = match && (desiredEndpointFilter.vendorId == 0 || cachedEndpoint->GetVendorId() == desiredEndpointFilter.vendorId); - match = - match && (desiredEndpointFilter.productId == 0 || cachedEndpoint->GetProductId() == desiredEndpointFilter.productId); - // TODO: check deviceTypeList - if (match) + for (const auto & cachedEndpoint : cachedEndpoints) { - return true; + bool match = true; + match = match && (desiredTargetApps[i].vendorId == 0 || cachedEndpoint->GetVendorId() == desiredTargetApps[i].vendorId); + match = + match && (desiredTargetApps[i].productId == 0 || cachedEndpoint->GetProductId() == desiredTargetApps[i].productId); + if (match) + { + ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer found"); + return true; + } } } + ChipLogProgress(AppServer, "CastingPlayer::ContainsDesiredTargetApp() matching cached CastingPlayer not found"); return false; } 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 783d50f60af390..65176a62034d08 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -69,6 +69,65 @@ class CastingPlayerAttributes chip::FabricIndex fabricIndex = 0; }; +/** + * This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the + * Commissioner. The options specify information relating to the requested UDC commissioning session. + */ +class IdentificationDeclarationOptions +{ +public: + constexpr static size_t kMaxTargetAppInfos = 10; + uint8_t mNumTargetAppInfos = 0; // The number of TargetAppInfos included. + /** + * Feature: Target Content Application + * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication. + * Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the + * desired TargetApp is not found in the on-device CastingStore. + */ + chip::Protocols::UserDirectedCommissioning::TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos]; + + /** + * Feature: Target Content Application + * Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message + * if a commissioning Passcode is needed. + */ + bool mNoPasscode = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the + * Commissioner has been shown to the user. + */ + bool mCdUponPasscodeDialog = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning. + */ + bool mCommissionerPasscode = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready + * for commissioning. + */ + bool mCommissionerPasscodeReady = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to indicate when the Commissionee user has decided to exit the commissioning process. + */ + bool mCancelPasscode = false; +}; + +// TODO: In the following PRs. This is work in progress. Break out to a seperate cpp file. +class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler +{ +public: + void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, + chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override + { + ChipLogProgress(AppServer, "CastingPlayer::CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called"); + cd.DebugLog(); + } +}; + class Endpoint; /** @@ -93,7 +152,11 @@ using ConnectCallback = std::function; class CastingPlayer : public std::enable_shared_from_this { public: - CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; } + CastingPlayer(CastingPlayerAttributes playerAttributes) + { + mAttributes = playerAttributes; + mCommissionerDeclarationHandler = new CommissionerDeclarationHandler(); + } /** * @brief Get the CastingPlayer object targeted currently (may not be connected) @@ -123,13 +186,15 @@ class CastingPlayer : public std::enable_shared_from_this * For failure - called back with an error and nullptr. * @param commissioningWindowTimeoutSec (Optional) time (in sec) to keep the commissioning window open, if commissioning is * required. Needs to be >= kCommissioningWindowTimeoutSec. - * @param desiredEndpointFilter (Optional) Attributes (such as VendorId) describing an Endpoint that the client wants to - * interact with after commissioning. If this value is passed in, the VerifyOrEstablishConnection will force User Directed - * Commissioning, in case the desired Endpoint is not found in the on device CastingStore. + * @param idOptions (Optional) Parameters in the IdentificationDeclaration message sent by the Commissionee to the Commissioner. + * These parameters specify the information relating to the requested commissioning session. + * Furthermore, attributes (such as VendorId) describe the TargetApp that the client wants to interact with after commissioning. + * If this value is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the desired + * TargetApp is not found in the on-device CastingStore. */ void VerifyOrEstablishConnection(ConnectCallback onCompleted, unsigned long long int commissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec, - EndpointFilter desiredEndpointFilter = EndpointFilter()); + IdentificationDeclarationOptions idOptions = IdentificationDeclarationOptions()); /** * @brief Sets the internal connection state of this CastingPlayer to "disconnected" @@ -197,6 +262,17 @@ class CastingPlayer : public std::enable_shared_from_this std::vector> mEndpoints; ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED; CastingPlayerAttributes mAttributes; + IdentificationDeclarationOptions mIdOptions; + /** + * Flag to indicate whether or not the Commissionee (tv-casting-app) is enabled for the Commissioner-Generated Passcode flow. + */ + bool mUdcCommissionerPasscodeEnabled = false; + /** + * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready + * for commissioning. + */ + bool mUdcCommissionerPasscodeReady = false; + CommissionerDeclarationHandler * mCommissionerDeclarationHandler; static CastingPlayer * mTargetCastingPlayer; unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; ConnectCallback mOnCompleted = {}; @@ -217,12 +293,14 @@ class CastingPlayer : public std::enable_shared_from_this #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT /** - * @brief Checks if the cachedCastingPlayer contains an Endpoint that matches the description of the desiredEndpointFilter - * - * @return true - cachedCastingPlayer contains at least one endpoint that matches all the (non-default) values in - * desiredEndpointFilter, false otherwise + * @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list. + * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values as described in the + * desiredTargetApps list, false otherwise. + * @param numTargetApps Specifies the number of TargetAppInfos passed in the desiredTargetApps array. */ - bool ContainsDesiredEndpoint(core::CastingPlayer * cachedCastingPlayer, EndpointFilter desiredEndpointFilter); + bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps, + uint8_t numTargetApps); // ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with // and connect to a CastingPlayer diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 1ad98d271262da..ad085d52be8a22 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -621,7 +621,7 @@ void Server::Shutdown() CHIP_ERROR Server::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner, Protocols::UserDirectedCommissioning::IdentificationDeclaration & id) { - ChipLogDetail(AppServer, "SendUserDirectedCommissioningRequest2"); + ChipLogDetail(AppServer, "Server::SendUserDirectedCommissioningRequest()"); CHIP_ERROR err; diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp index a06bffcec62b3a..fb31049d1d99a9 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp @@ -367,6 +367,7 @@ CHIP_ERROR IdentificationDeclaration::ReadPayload(uint8_t * udcPayload, size_t p { ChipLogProgress(AppServer, "TLV end of array"); ReturnErrorOnFailure(reader.ExitContainer(listContainerType)); + err = CHIP_NO_ERROR; } } break; From 2f039ede3bff7b22e92deceb9e69ebcee47c26fc Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Fri, 3 May 2024 16:49:21 -0700 Subject: [PATCH 2/7] Addressed comments by sharadb-amazon --- .../jni/cpp/core/MatterCastingPlayer-JNI.cpp | 22 +++-- .../MatterTvCastingBridge/MCCastingPlayer.mm | 18 +++- .../linux/simple-app-helper.cpp | 35 +++++-- .../tv-casting-app/linux/simple-app-helper.h | 1 + .../tv-casting-common/core/CastingPlayer.cpp | 42 +++++---- .../tv-casting-common/core/CastingPlayer.h | 81 +++-------------- .../core/CommissionerDeclarationHandler.h | 41 +++++++++ .../core/IdentificationDeclarationOptions.h | 91 +++++++++++++++++++ 8 files changed, 228 insertions(+), 103 deletions(-) create mode 100644 examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h create mode 100644 examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp index 2ec5f64c2867d8..9275f4d2f4ff91 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp @@ -53,9 +53,14 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) CastingPlayer * castingPlayer = support::convertCastingPlayerFromJavaToCpp(thiz); VerifyOrReturnValue(castingPlayer != nullptr, support::convertMatterErrorFromCppToJava(CHIP_ERROR_INVALID_ARGUMENT)); + matter::casting::core::IdentificationDeclarationOptions idOptions; + + // TODO: In the following PRs. Replace EndpointFilter Java class with IdentificationDeclarationOptions Java class. matter::casting::core::EndpointFilter desiredEndpointFilter; if (desiredEndpointFilterJavaObject != nullptr) { + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + // Convert the EndpointFilter Java class to a C++ EndpointFilter jclass endpointFilterJavaClass = env->GetObjectClass(desiredEndpointFilterJavaObject); jfieldID vendorIdFieldId = env->GetFieldID(endpointFilterJavaClass, "vendorId", "Ljava/lang/Integer;"); @@ -66,23 +71,26 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) // "Ljava/util/List;"); // Value of 0 means unspecified - desiredEndpointFilter.vendorId = vendorIdIntegerObject != nullptr + targetAppInfo.vendorId = vendorIdIntegerObject != nullptr ? static_cast(env->CallIntMethod( vendorIdIntegerObject, env->GetMethodID(env->GetObjectClass(vendorIdIntegerObject), "intValue", "()I"))) : 0; - desiredEndpointFilter.productId = productIdIntegerObject != nullptr + targetAppInfo.productId = productIdIntegerObject != nullptr ? static_cast(env->CallIntMethod( productIdIntegerObject, env->GetMethodID(env->GetObjectClass(productIdIntegerObject), "intValue", "()I"))) : 0; - // TODO: In following PRs. Translate the Java requiredDeviceTypes list to a C++ requiredDeviceTypes vector. For now we're - // passing an empty list of DeviceTypeStruct. + + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); + } } MatterCastingPlayerJNIMgr().mConnectionSuccessHandler.SetUp(env, jSuccessCallback); MatterCastingPlayerJNIMgr().mConnectionFailureHandler.SetUp(env, jFailureCallback); - // TODO: In the following PRs. Removed desiredEndpointFilter to fix Android app build issue. Replace desiredEndpointFilter with - // optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter. + // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter. castingPlayer->VerifyOrEstablishConnection( [](CHIP_ERROR err, CastingPlayer * playerPtr) { ChipLogProgress(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() ConnectCallback called"); @@ -99,7 +107,7 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) MatterCastingPlayerJNIMgr().mConnectionFailureHandler.Handle(err); } }, - static_cast(commissioningWindowTimeoutSec)); + static_cast(commissioningWindowTimeoutSec), idOptions); return support::convertMatterErrorFromCppToJava(CHIP_NO_ERROR); } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index 1e96e45e7bfa1f..69a31a9ec4340c 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -52,20 +52,30 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError dispatch_queue_t workQueue = [[MCCastingApp getSharedInstance] getWorkQueue]; dispatch_sync(workQueue, ^{ + matter::casting::core::IdentificationDeclarationOptions idOptions; + + // TODO: In the following PRs. Replace EndpointFilter objC class with IdentificationDeclarationOptions objC class. __block matter::casting::core::EndpointFilter cppDesiredEndpointFilter; if (desiredEndpointFilter != nil) { - cppDesiredEndpointFilter.vendorId = desiredEndpointFilter.vendorId; - cppDesiredEndpointFilter.productId = desiredEndpointFilter.productId; + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + targetAppInfo.vendorId = desiredEndpointFilter.vendorId; + targetAppInfo.productId = desiredEndpointFilter.productId; + + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "MCCastingPlayer.verifyOrEstablishConnectionWithCompletionBlock failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); + } } - // TODO: In the following PRs. Removed desiredEndpointFilter to fix iOS app build issue. Replace desiredEndpointFilter with optional IdentificationDeclarationOptions. Add optional CommissionerDeclarationHandler callback parameter. + // TODO: In the following PRs. Add optional CommissionerDeclarationHandler callback parameter. _cppCastingPlayer->VerifyOrEstablishConnection( [completion](CHIP_ERROR err, matter::casting::core::CastingPlayer * castingPlayer) { dispatch_queue_t clientQueue = [[MCCastingApp getSharedInstance] getClientQueue]; dispatch_async(clientQueue, ^{ completion(err == CHIP_NO_ERROR ? nil : [MCErrorUtils NSErrorFromChipError:err]); }); - }, timeout); + }, timeout, idOptions); }); } diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index ff64d34f8299a4..7a752818890dad 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -49,8 +49,10 @@ void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::StrongStartDiscovery(kTargetPlayerDeviceType); } if (strcmp(argv[0], "stop-discovery") == 0) { - ChipLogProgress(AppServer, "stop-discovery"); + ChipLogProgress(AppServer, "CommandHandler() stop-discovery"); return matter::casting::core::CastingPlayerDiscovery::GetInstance()->StopDiscovery(); } if (strcmp(argv[0], "request") == 0) @@ -246,12 +248,27 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) std::shared_ptr targetCastingPlayer = castingPlayers.at(index); matter::casting::core::IdentificationDeclarationOptions idOptions; - idOptions.mNumTargetAppInfos = 1; - idOptions.mTargetAppInfos[0].vendorId = kDesiredEndpointVendorId; - // Attempt Commissioner-Generated Passcode commissioning flow only if the CastingPlayer indicates support for it. - if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode()) + if (argc == 3) { - idOptions.mCommissionerPasscode = true; + if (strcmp(argv[2], "cgp") == 0) + { + // Attempt Commissioner-Generated Passcode (cgp) commissioning flow only if the CastingPlayer indicates support for it. + if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode()) + { + ChipLogProgress(AppServer, "CommandHandler() request %lu cgp. Attempting the Commissioner-Generated Passcode commissioning flow", index); + idOptions.mCommissionerPasscode = true; + } else + { + ChipLogError(AppServer, "CommandHandler() request %lu cgp. Selected CastingPLayer does not support the Commissioner-Generated Passcode commissioning flow", index); + } + } + } + chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; + targetAppInfo.vendorId = kDesiredEndpointVendorId; + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + if (result != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); } targetCastingPlayer->VerifyOrEstablishConnection(ConnectionHandler, matter::casting::core::kCommissioningWindowTimeoutSec, @@ -291,6 +308,8 @@ CHIP_ERROR PrintAllCommands() streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n"); streamer_printf( sout, " request Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n"); + streamer_printf( + sout, " request cgp Request connecting to discovered Casting Player with [index] using the Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n"); streamer_printf(sout, "\r\n"); return CHIP_NO_ERROR; diff --git a/examples/tv-casting-app/linux/simple-app-helper.h b/examples/tv-casting-app/linux/simple-app-helper.h index b1dbbe60cf04b3..f8826b5dfe021f 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.h +++ b/examples/tv-casting-app/linux/simple-app-helper.h @@ -20,6 +20,7 @@ #include "core/CastingPlayer.h" #include "core/CastingPlayerDiscovery.h" +#include "core/IdentificationDeclarationOptions.h" #include "core/Types.h" #include 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 7acf147c8c5764..61adb629d93cc1 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -66,7 +66,7 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns if (it != cachedCastingPlayers.end()) { unsigned index = (unsigned int) std::distance(cachedCastingPlayers.begin(), it); - if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.mTargetAppInfos, idOptions.mNumTargetAppInfos)) + if (ContainsDesiredTargetApp(&cachedCastingPlayers[index], idOptions.getTargetAppInfoList())) { ChipLogProgress( AppServer, @@ -166,17 +166,35 @@ void CastingPlayer::RegisterEndpoint(const memory::Strong endpoint) #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() { - ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() creating IdentificationDeclaration message"); + ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest()"); chip::Inet::IPAddress * ipAddressToUse = GetIpAddressForUDCRequest(); VerifyOrReturnValue(ipAddressToUse != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(AppServer, "No IP Address found to send UDC request to")); ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true)); + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id = buildIdentificationDeclarationMessage(); + + // TODO: In the following PRs. Implement handler for CommissionerDeclaration messages and expose messages to higher layers for + // Linux, Android and iOS. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( + mCommissionerDeclarationHandler); + + ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( + chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); + + return CHIP_NO_ERROR; +} + +chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration CastingPlayer::buildIdentificationDeclarationMessage() +{ + ChipLogProgress(AppServer, "CastingPlayer::buildIdentificationDeclarationMessage() building IdentificationDeclaration message"); chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; - for (size_t i = 0; i < mIdOptions.mNumTargetAppInfos; i++) + + std::vector mTargetAppInfos = mIdOptions.getTargetAppInfoList(); + for (size_t i = 0; i < mTargetAppInfos.size(); i++) { - id.AddTargetAppInfo(mIdOptions.mTargetAppInfos[i]); + id.AddTargetAppInfo(mTargetAppInfos[i]); } id.SetNoPasscode(mIdOptions.mNoPasscode); id.SetCdUponPasscodeDialog(mIdOptions.mCdUponPasscodeDialog); @@ -194,15 +212,7 @@ CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() } } - // TODO: In the following PRs. Implement handler for CommissionerDeclaration messages and expose messages to higher layers for - // Linux, Android and iOS. - chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( - mCommissionerDeclarationHandler); - - ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( - chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); - - return CHIP_NO_ERROR; + return id; } chip::Inet::IPAddress * CastingPlayer::GetIpAddressForUDCRequest() @@ -244,12 +254,10 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC connectionContext->mOnConnectionFailureCallback); } -bool CastingPlayer::ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, - chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps, - uint8_t numTargetApps) +bool CastingPlayer::ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, std::vector desiredTargetApps) { std::vector> cachedEndpoints = cachedCastingPlayer->GetEndpoints(); - for (size_t i = 0; i < numTargetApps; i++) + for (size_t i = 0; i < desiredTargetApps.size(); i++) { for (const auto & cachedEndpoint : cachedEndpoints) { 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 65176a62034d08..954eee930ebc47 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -18,7 +18,9 @@ #pragma once +#include "CommissionerDeclarationHandler.h" #include "Endpoint.h" +#include "IdentificationDeclarationOptions.h" #include "Types.h" #include "support/ChipDeviceEventHandler.h" #include "support/EndpointListLoader.h" @@ -69,65 +71,6 @@ class CastingPlayerAttributes chip::FabricIndex fabricIndex = 0; }; -/** - * This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the - * Commissioner. The options specify information relating to the requested UDC commissioning session. - */ -class IdentificationDeclarationOptions -{ -public: - constexpr static size_t kMaxTargetAppInfos = 10; - uint8_t mNumTargetAppInfos = 0; // The number of TargetAppInfos included. - /** - * Feature: Target Content Application - * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication. - * Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the - * desired TargetApp is not found in the on-device CastingStore. - */ - chip::Protocols::UserDirectedCommissioning::TargetAppInfo mTargetAppInfos[kMaxTargetAppInfos]; - - /** - * Feature: Target Content Application - * Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message - * if a commissioning Passcode is needed. - */ - bool mNoPasscode = false; - /** - * Feature: Coordinate Passcode Dialogs - * Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the - * Commissioner has been shown to the user. - */ - bool mCdUponPasscodeDialog = false; - /** - * Feature: Commissioner-Generated Passcode - * Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning. - */ - bool mCommissionerPasscode = false; - /** - * Feature: Commissioner-Generated Passcode - * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready - * for commissioning. - */ - bool mCommissionerPasscodeReady = false; - /** - * Feature: Coordinate Passcode Dialogs - * Flag to indicate when the Commissionee user has decided to exit the commissioning process. - */ - bool mCancelPasscode = false; -}; - -// TODO: In the following PRs. This is work in progress. Break out to a seperate cpp file. -class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler -{ -public: - void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, - chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override - { - ChipLogProgress(AppServer, "CastingPlayer::CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called"); - cd.DebugLog(); - } -}; - class Endpoint; /** @@ -155,7 +98,10 @@ class CastingPlayer : public std::enable_shared_from_this CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; - mCommissionerDeclarationHandler = new CommissionerDeclarationHandler(); + } + ~CastingPlayer() + { + delete mCommissionerDeclarationHandler; } /** @@ -272,7 +218,7 @@ class CastingPlayer : public std::enable_shared_from_this * for commissioning. */ bool mUdcCommissionerPasscodeReady = false; - CommissionerDeclarationHandler * mCommissionerDeclarationHandler; + CommissionerDeclarationHandler * mCommissionerDeclarationHandler = new CommissionerDeclarationHandler(); static CastingPlayer * mTargetCastingPlayer; unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; ConnectCallback mOnCompleted = {}; @@ -283,6 +229,11 @@ class CastingPlayer : public std::enable_shared_from_this */ CHIP_ERROR SendUserDirectedCommissioningRequest(); + /** + * @brief Builds an IdentificationDeclaration message to be sent to this CastingPlayer + */ + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration buildIdentificationDeclarationMessage(); + /** * @brief Selects an IP Address to send the UDC request to. * Prioritizes IPV4 addresses over IPV6. @@ -294,13 +245,9 @@ class CastingPlayer : public std::enable_shared_from_this /** * @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list. - * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values as described in the - * desiredTargetApps list, false otherwise. - * @param numTargetApps Specifies the number of TargetAppInfos passed in the desiredTargetApps array. + * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values for vendorID and productID as described in the desiredTargetApps list, false otherwise. */ - bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, - chip::Protocols::UserDirectedCommissioning::TargetAppInfo * desiredTargetApps, - uint8_t numTargetApps); + bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, std::vector desiredTargetApps); // ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with // and connect to a CastingPlayer diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h new file mode 100644 index 00000000000000..6c387c2354828b --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Types.h" + +namespace matter { +namespace casting { +namespace core { + +// TODO: In the following PRs. This is work in progress, call higer levels with the CommissionerDeclaration info. +class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler +{ +public: + void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, + chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override + { + ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called"); + cd.DebugLog(); + } +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h new file mode 100644 index 00000000000000..0c520d27a8e782 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Types.h" +#include + +namespace matter { +namespace casting { +namespace core { + +/** + * This class contains the optional parameters used in the IdentificationDeclaration Message, sent by the Commissionee to the + * Commissioner. The options specify information relating to the requested UDC commissioning session. + */ +class IdentificationDeclarationOptions +{ +public: + /** + * Feature: Target Content Application + * Flag to instruct the Commissioner not to display a Passcode input dialog, and instead send a CommissionerDeclaration message + * if a commissioning Passcode is needed. + */ + bool mNoPasscode = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to instruct the Commissioner to send a CommissionerDeclaration message when the Passcode input dialog on the + * Commissioner has been shown to the user. + */ + bool mCdUponPasscodeDialog = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to instruct the Commissioner to use the Commissioner-generated Passcode for commissioning. + */ + bool mCommissionerPasscode = false; + /** + * Feature: Commissioner-Generated Passcode + * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready + * for commissioning. + */ + bool mCommissionerPasscodeReady = false; + /** + * Feature: Coordinate Passcode Dialogs + * Flag to indicate when the Commissionee user has decided to exit the commissioning process. + */ + bool mCancelPasscode = false; + + CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo& targetAppInfo) { + if (mTargetAppInfos.size() >= kMaxTargetAppInfos) + { + ChipLogError(AppServer, "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %zu", kMaxTargetAppInfos); + return CHIP_ERROR_NO_MEMORY; + } + + mTargetAppInfos.push_back(targetAppInfo); + return CHIP_NO_ERROR; + } + + std::vector getTargetAppInfoList() const { return mTargetAppInfos; } + +private: + // TVs can handle the memory impact of supporting a larger list. See examples/tv-app/tv-common/include/CHIPProjectAppConfig.h + constexpr static size_t kMaxTargetAppInfos = 10; + /** + * Feature: Target Content Application + * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication. + * Also, if TargetAppInfo is passed in, VerifyOrEstablishConnection() will force User Directed Commissioning, in case the + * desired TargetApp is not found in the on-device CastingStore. + */ + std::vector mTargetAppInfos; +}; + +}; // namespace core +}; // namespace casting +}; // namespace matter From e1d72de5292c84fe4b336567c520bb11084c8aea Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Fri, 3 May 2024 16:55:36 -0700 Subject: [PATCH 3/7] Fixing style issues --- .../jni/cpp/core/MatterCastingPlayer-JNI.cpp | 4 +++- .../MatterTvCastingBridge/MCCastingPlayer.mm | 3 +-- .../linux/simple-app-helper.cpp | 23 +++++++++++++------ .../tv-casting-common/core/CastingPlayer.cpp | 4 +++- .../tv-casting-common/core/CastingPlayer.h | 18 ++++++--------- .../core/IdentificationDeclarationOptions.h | 7 ++++-- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp index 9275f4d2f4ff91..1c4a949c9f7cc5 100644 --- a/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp +++ b/examples/tv-casting-app/android/App/app/src/main/jni/cpp/core/MatterCastingPlayer-JNI.cpp @@ -83,7 +83,9 @@ JNI_METHOD(jobject, verifyOrEstablishConnection) CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); if (result != CHIP_NO_ERROR) { - ChipLogError(AppServer, "MatterCastingPlayer-JNI::verifyOrEstablishConnection() failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); + ChipLogError(AppServer, + "MatterCastingPlayer-JNI::verifyOrEstablishConnection() failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, + result.Format()); } } diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm index 69a31a9ec4340c..3bc72235a86c72 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCastingPlayer.mm @@ -62,8 +62,7 @@ - (void)verifyOrEstablishConnectionWithCompletionBlock:(void (^_Nonnull)(NSError targetAppInfo.productId = desiredEndpointFilter.productId; CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); - if (result != CHIP_NO_ERROR) - { + if (result != CHIP_NO_ERROR) { ChipLogError(AppServer, "MCCastingPlayer.verifyOrEstablishConnectionWithCompletionBlock failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); } } diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index 7a752818890dad..c76a21b21f8d61 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -252,20 +252,28 @@ CHIP_ERROR CommandHandler(int argc, char ** argv) { if (strcmp(argv[2], "cgp") == 0) { - // Attempt Commissioner-Generated Passcode (cgp) commissioning flow only if the CastingPlayer indicates support for it. + // Attempt Commissioner-Generated Passcode (cgp) commissioning flow only if the CastingPlayer indicates support for + // it. if (targetCastingPlayer->GetSupportsCommissionerGeneratedPasscode()) { - ChipLogProgress(AppServer, "CommandHandler() request %lu cgp. Attempting the Commissioner-Generated Passcode commissioning flow", index); + ChipLogProgress( + AppServer, + "CommandHandler() request %lu cgp. Attempting the Commissioner-Generated Passcode commissioning flow", + index); idOptions.mCommissionerPasscode = true; - } else + } + else { - ChipLogError(AppServer, "CommandHandler() request %lu cgp. Selected CastingPLayer does not support the Commissioner-Generated Passcode commissioning flow", index); + ChipLogError(AppServer, + "CommandHandler() request %lu cgp. Selected CastingPLayer does not support the " + "Commissioner-Generated Passcode commissioning flow", + index); } } } chip::Protocols::UserDirectedCommissioning::TargetAppInfo targetAppInfo; targetAppInfo.vendorId = kDesiredEndpointVendorId; - CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); + CHIP_ERROR result = idOptions.addTargetAppInfo(targetAppInfo); if (result != CHIP_NO_ERROR) { ChipLogError(AppServer, "CommandHandler() request, failed to add targetAppInfo: %" CHIP_ERROR_FORMAT, result.Format()); @@ -308,8 +316,9 @@ CHIP_ERROR PrintAllCommands() streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n"); streamer_printf( sout, " request Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n"); - streamer_printf( - sout, " request cgp Request connecting to discovered Casting Player with [index] using the Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n"); + streamer_printf(sout, + " request cgp Request connecting to discovered Casting Player with [index] using the " + "Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n"); streamer_printf(sout, "\r\n"); return CHIP_NO_ERROR; 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 61adb629d93cc1..3e7f1bd7dda964 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -254,7 +254,9 @@ void CastingPlayer::FindOrEstablishSession(void * clientContext, chip::OnDeviceC connectionContext->mOnConnectionFailureCallback); } -bool CastingPlayer::ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, std::vector desiredTargetApps) +bool CastingPlayer::ContainsDesiredTargetApp( + core::CastingPlayer * cachedCastingPlayer, + std::vector desiredTargetApps) { std::vector> cachedEndpoints = cachedCastingPlayer->GetEndpoints(); for (size_t i = 0; i < desiredTargetApps.size(); i++) 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 954eee930ebc47..370dde12178626 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -95,14 +95,8 @@ using ConnectCallback = std::function; class CastingPlayer : public std::enable_shared_from_this { public: - CastingPlayer(CastingPlayerAttributes playerAttributes) - { - mAttributes = playerAttributes; - } - ~CastingPlayer() - { - delete mCommissionerDeclarationHandler; - } + CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; } + ~CastingPlayer() { delete mCommissionerDeclarationHandler; } /** * @brief Get the CastingPlayer object targeted currently (may not be connected) @@ -217,7 +211,7 @@ class CastingPlayer : public std::enable_shared_from_this * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready * for commissioning. */ - bool mUdcCommissionerPasscodeReady = false; + bool mUdcCommissionerPasscodeReady = false; CommissionerDeclarationHandler * mCommissionerDeclarationHandler = new CommissionerDeclarationHandler(); static CastingPlayer * mTargetCastingPlayer; unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; @@ -245,9 +239,11 @@ class CastingPlayer : public std::enable_shared_from_this /** * @brief Checks if the cachedCastingPlayer contains at least one Endpoint/TargetApp described in the desiredTargetApps list. - * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values for vendorID and productID as described in the desiredTargetApps list, false otherwise. + * @return true - cachedCastingPlayer contains at least one endpoints with matching (non-default) values for vendorID and + * productID as described in the desiredTargetApps list, false otherwise. */ - bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, std::vector desiredTargetApps); + bool ContainsDesiredTargetApp(core::CastingPlayer * cachedCastingPlayer, + std::vector desiredTargetApps); // ChipDeviceEventHandler handles chip::DeviceLayer::ChipDeviceEvent events and helps the CastingPlayer class commission with // and connect to a CastingPlayer diff --git a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h index 0c520d27a8e782..e4c5f1c2a537b5 100644 --- a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h +++ b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h @@ -61,10 +61,13 @@ class IdentificationDeclarationOptions */ bool mCancelPasscode = false; - CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo& targetAppInfo) { + CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo & targetAppInfo) + { if (mTargetAppInfos.size() >= kMaxTargetAppInfos) { - ChipLogError(AppServer, "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %zu", kMaxTargetAppInfos); + ChipLogError(AppServer, + "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %zu", + kMaxTargetAppInfos); return CHIP_ERROR_NO_MEMORY; } From a5e0a6e87354833ff67ed6658dccaa03ef30cdf9 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Mon, 6 May 2024 17:48:31 -0700 Subject: [PATCH 4/7] Addressed comments by sharadb-amazon - 2nd review --- .../casting/DiscoveryExampleFragment.java | 5 +- .../linux/simple-app-helper.cpp | 9 ++-- .../tv-casting-app/tv-casting-common/BUILD.gn | 1 + .../tv-casting-common/core/CastingApp.cpp | 7 +++ .../tv-casting-common/core/CastingPlayer.cpp | 47 +++--------------- .../tv-casting-common/core/CastingPlayer.h | 16 ------ .../core/CommissionerDeclarationHandler.cpp | 49 +++++++++++++++++++ .../core/CommissionerDeclarationHandler.h | 21 +++++--- .../core/IdentificationDeclarationOptions.h | 42 ++++++++++++++-- .../include/CHIPProjectAppConfig.h | 4 ++ .../tv-casting-common/support/AppParameters.h | 1 + .../UserDirectedCommissioning.h | 6 +++ 12 files changed, 134 insertions(+), 74 deletions(-) create mode 100644 examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp diff --git a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java index a706780c5be3b4..65d670584971aa 100644 --- a/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java +++ b/examples/tv-casting-app/android/App/app/src/main/java/com/matter/casting/DiscoveryExampleFragment.java @@ -327,8 +327,9 @@ public View getView(int i, View view, ViewGroup viewGroup) { TAG, "OnClickListener.onClick() called for CastingPlayer with deviceId: " + castingPlayer.getDeviceId()); - DiscoveryExampleFragment.Callback callback1 = (DiscoveryExampleFragment.Callback) context; - callback1.handleConnectionButtonClicked(castingPlayer); + DiscoveryExampleFragment.Callback onClickCallback = + (DiscoveryExampleFragment.Callback) context; + onClickCallback.handleConnectionButtonClicked(castingPlayer); }; playerDescription.setOnClickListener(clickListener); return view; diff --git a/examples/tv-casting-app/linux/simple-app-helper.cpp b/examples/tv-casting-app/linux/simple-app-helper.cpp index c76a21b21f8d61..ceb66233a7bc6d 100644 --- a/examples/tv-casting-app/linux/simple-app-helper.cpp +++ b/examples/tv-casting-app/linux/simple-app-helper.cpp @@ -51,8 +51,8 @@ void DiscoveryDelegateImpl::HandleOnAdded(matter::casting::memory::Strong Delete a fabric from the casting client's fabric store. Usage: cast delete-fabric 1\r\n"); streamer_printf(sout, " discover Discover Casting Players. Usage: cast discover\r\n"); streamer_printf(sout, " stop-discovery Stop Discovery of Casting Players. Usage: cast stop-discovery\r\n"); - streamer_printf( - sout, " request Request connecting to discovered Casting Player with [index]. Usage: cast request 0\r\n"); + streamer_printf(sout, + " request Request connecting to discovered Casting Player with [index] using the " + "Commissionee-Generated Passcode commissioning flow. Usage: cast request 0\r\n"); streamer_printf(sout, " request cgp Request connecting to discovered Casting Player with [index] using the " "Commissioner-Generated Passcode commissioning flow. Usage: cast request 0 cgp\r\n"); diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index 72f14fb7bffeee..a58d272abe88bf 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -106,6 +106,7 @@ chip_data_model("tv-casting-common") { "core/CastingPlayerDiscovery.cpp", "core/CastingPlayerDiscovery.h", "core/Command.h", + "core/CommissionerDeclarationHandler.cpp", "core/Endpoint.cpp", "core/Endpoint.h", "core/Types.h", diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index c274edd016ed07..3f0aabc2b0ec87 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -18,6 +18,7 @@ #include "CastingApp.h" +#include "CommissionerDeclarationHandler.h" #include "support/CastingStore.h" #include "support/ChipDeviceEventHandler.h" @@ -117,6 +118,10 @@ CHIP_ERROR CastingApp::Start() }); } + // Set a handler for Commissioner's CommissionerDeclaration messages. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( + CommissionerDeclarationHandler::GetInstance()); + return CHIP_NO_ERROR; } @@ -153,6 +158,8 @@ CHIP_ERROR CastingApp::Stop() mState = CASTING_APP_NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->RemoveCommissionerDeclarationHandler(); + return CHIP_NO_ERROR; } 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 3e7f1bd7dda964..0f455d6b4c9a44 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -46,12 +46,11 @@ void CastingPlayer::VerifyOrEstablishConnection(ConnectCallback onCompleted, uns ChipLogError( AppServer, "CastingPlayer::VerifyOrEstablishConnection() called while already connecting/connected to this CastingPlayer")); - mConnectionState = CASTING_PLAYER_CONNECTING; - mOnCompleted = onCompleted; - mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec; - mTargetCastingPlayer = this; - mIdOptions = idOptions; - mUdcCommissionerPasscodeEnabled = idOptions.mCommissionerPasscode; + mConnectionState = CASTING_PLAYER_CONNECTING; + mOnCompleted = onCompleted; + mCommissioningWindowTimeoutSec = commissioningWindowTimeoutSec; + mTargetCastingPlayer = this; + mIdOptions = idOptions; // If *this* CastingPlayer was previously connected to, its nodeId, fabricIndex and other attributes should be present // in the CastingStore cache. If that is the case, AND, the cached data contains the endpoint desired by the client, if any, @@ -173,12 +172,7 @@ CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true)); - chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id = buildIdentificationDeclarationMessage(); - - // TODO: In the following PRs. Implement handler for CommissionerDeclaration messages and expose messages to higher layers for - // Linux, Android and iOS. - chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( - mCommissionerDeclarationHandler); + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id = mIdOptions.buildIdentificationDeclarationMessage(); ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); @@ -186,35 +180,6 @@ CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() return CHIP_NO_ERROR; } -chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration CastingPlayer::buildIdentificationDeclarationMessage() -{ - ChipLogProgress(AppServer, "CastingPlayer::buildIdentificationDeclarationMessage() building IdentificationDeclaration message"); - chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; - - std::vector mTargetAppInfos = mIdOptions.getTargetAppInfoList(); - for (size_t i = 0; i < mTargetAppInfos.size(); i++) - { - id.AddTargetAppInfo(mTargetAppInfos[i]); - } - id.SetNoPasscode(mIdOptions.mNoPasscode); - id.SetCdUponPasscodeDialog(mIdOptions.mCdUponPasscodeDialog); - id.SetCancelPasscode(mIdOptions.mCancelPasscode); - - ChipLogProgress(AppServer, "CastingPlayer::SendUserDirectedCommissioningRequest() mUdcCommissionerPasscodeEnabled: %s", - mUdcCommissionerPasscodeEnabled ? "true" : "false"); - if (mUdcCommissionerPasscodeEnabled) - { - id.SetCommissionerPasscode(true); - if (mUdcCommissionerPasscodeReady) - { - id.SetCommissionerPasscodeReady(true); - mUdcCommissionerPasscodeReady = false; - } - } - - return id; -} - chip::Inet::IPAddress * CastingPlayer::GetIpAddressForUDCRequest() { size_t ipIndexToUse = 0; 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 370dde12178626..2748eafc22cc7e 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.h @@ -96,7 +96,6 @@ class CastingPlayer : public std::enable_shared_from_this { public: CastingPlayer(CastingPlayerAttributes playerAttributes) { mAttributes = playerAttributes; } - ~CastingPlayer() { delete mCommissionerDeclarationHandler; } /** * @brief Get the CastingPlayer object targeted currently (may not be connected) @@ -203,16 +202,6 @@ class CastingPlayer : public std::enable_shared_from_this ConnectionState mConnectionState = CASTING_PLAYER_NOT_CONNECTED; CastingPlayerAttributes mAttributes; IdentificationDeclarationOptions mIdOptions; - /** - * Flag to indicate whether or not the Commissionee (tv-casting-app) is enabled for the Commissioner-Generated Passcode flow. - */ - bool mUdcCommissionerPasscodeEnabled = false; - /** - * Flag to indicate whether or not the Commissionee has obtained the Commissioner Passcode from the user and is therefore ready - * for commissioning. - */ - bool mUdcCommissionerPasscodeReady = false; - CommissionerDeclarationHandler * mCommissionerDeclarationHandler = new CommissionerDeclarationHandler(); static CastingPlayer * mTargetCastingPlayer; unsigned long long int mCommissioningWindowTimeoutSec = kCommissioningWindowTimeoutSec; ConnectCallback mOnCompleted = {}; @@ -223,11 +212,6 @@ class CastingPlayer : public std::enable_shared_from_this */ CHIP_ERROR SendUserDirectedCommissioningRequest(); - /** - * @brief Builds an IdentificationDeclaration message to be sent to this CastingPlayer - */ - chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration buildIdentificationDeclarationMessage(); - /** * @brief Selects an IP Address to send the UDC request to. * Prioritizes IPV4 addresses over IPV6. diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp new file mode 100644 index 00000000000000..f92f4d483b227c --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp @@ -0,0 +1,49 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CommissionerDeclarationHandler.h" + +#include "Types.h" + +namespace matter { +namespace casting { +namespace core { + +CommissionerDeclarationHandler * CommissionerDeclarationHandler::sCommissionerDeclarationHandler_ = nullptr; + +CommissionerDeclarationHandler * CommissionerDeclarationHandler::GetInstance() +{ + if (sCommissionerDeclarationHandler_ == nullptr) + { + sCommissionerDeclarationHandler_ = new CommissionerDeclarationHandler(); + } + return sCommissionerDeclarationHandler_; +} + +// TODO: In the following PRs. Implement setHandler() for CommissionerDeclaration messages and expose messages to higher layers for +// Linux, Android and iOS. +void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, + chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) +{ + ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called TODO: handle message"); + cd.DebugLog(); +} + +}; // namespace core +}; // namespace casting +}; // namespace matter diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h index 6c387c2354828b..445b1d6667c7cf 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h @@ -24,16 +24,25 @@ namespace matter { namespace casting { namespace core { -// TODO: In the following PRs. This is work in progress, call higer levels with the CommissionerDeclaration info. +/** + * @brief React to the Commissioner's CommissionerDeclaration messages with this singleton. This is the common handler across Linux, + * Android and iOS. + */ class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler { public: + CommissionerDeclarationHandler(const CommissionerDeclarationHandler &) = delete; + void operator=(const CommissionerDeclarationHandler &) = delete; + + static CommissionerDeclarationHandler * GetInstance(); + void OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, - chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override - { - ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called"); - cd.DebugLog(); - } + chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) override; + +private: + static CommissionerDeclarationHandler * sCommissionerDeclarationHandler_; + CommissionerDeclarationHandler() {} + ~CommissionerDeclarationHandler() {} }; }; // namespace core diff --git a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h index e4c5f1c2a537b5..af1ae2aaa79d62 100644 --- a/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h +++ b/examples/tv-casting-app/tv-casting-common/core/IdentificationDeclarationOptions.h @@ -63,11 +63,11 @@ class IdentificationDeclarationOptions CHIP_ERROR addTargetAppInfo(const chip::Protocols::UserDirectedCommissioning::TargetAppInfo & targetAppInfo) { - if (mTargetAppInfos.size() >= kMaxTargetAppInfos) + if (mTargetAppInfos.size() >= CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS) { ChipLogError(AppServer, - "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %zu", - kMaxTargetAppInfos); + "IdentificationDeclarationOptions::addTargetAppInfo() failed to add TargetAppInfo, max vector size is %d", + CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS); return CHIP_ERROR_NO_MEMORY; } @@ -77,9 +77,41 @@ class IdentificationDeclarationOptions std::vector getTargetAppInfoList() const { return mTargetAppInfos; } + /** + * @brief Builds an IdentificationDeclaration message to be sent to a CastingPlayer, given the options state specified in this + * object. + */ + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration buildIdentificationDeclarationMessage() + { + ChipLogProgress(AppServer, "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage()"); + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + + std::vector targetAppInfos = getTargetAppInfoList(); + for (size_t i = 0; i < targetAppInfos.size(); i++) + { + id.AddTargetAppInfo(targetAppInfos[i]); + } + id.SetNoPasscode(mNoPasscode); + id.SetCdUponPasscodeDialog(mCdUponPasscodeDialog); + id.SetCancelPasscode(mCancelPasscode); + + ChipLogProgress(AppServer, + "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscode: %s", + mCommissionerPasscode ? "true" : "false"); + id.SetCommissionerPasscode(mCommissionerPasscode); + + ChipLogProgress(AppServer, + "IdentificationDeclarationOptions::buildIdentificationDeclarationMessage() mCommissionerPasscodeReady: %s", + mCommissionerPasscodeReady ? "true" : "false"); + if (mCommissionerPasscodeReady) + { + id.SetCommissionerPasscodeReady(true); + mCommissionerPasscodeReady = false; + } + return id; + } + private: - // TVs can handle the memory impact of supporting a larger list. See examples/tv-app/tv-common/include/CHIPProjectAppConfig.h - constexpr static size_t kMaxTargetAppInfos = 10; /** * Feature: Target Content Application * The set of content app Vendor IDs (and optionally, Product IDs) that can be used for authentication. diff --git a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h index 74926b00489703..f5887bc3828b08 100644 --- a/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h +++ b/examples/tv-casting-app/tv-casting-common/include/CHIPProjectAppConfig.h @@ -53,6 +53,10 @@ #define CHIP_DEVICE_CONFIG_ENABLE_PAIRING_AUTOSTART 0 +// TVs can handle the memory impact of supporting a larger list of target apps. See +// examples/tv-app/tv-common/include/CHIPProjectAppConfig.h +#define CHIP_DEVICE_CONFIG_UDC_MAX_TARGET_APPS 10 + // For casting, we need to allow more ACL entries, and more complex entries #define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_TARGETS_PER_ENTRY 20 #define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_SUBJECTS_PER_ENTRY 20 diff --git a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h index 9539a2919a81f5..080011f8953c37 100644 --- a/examples/tv-casting-app/tv-casting-common/support/AppParameters.h +++ b/examples/tv-casting-app/tv-casting-common/support/AppParameters.h @@ -42,6 +42,7 @@ class AppParameters chip::Credentials::DeviceAttestationCredentialsProvider * deviceAttestationCredentialsProvider, chip::Credentials::DeviceAttestationVerifier * deviceAttestationVerifier, ServerInitParamsProvider * serverInitParamsProvider) + // TODO: In the following PRs. Add CommissionerDeclarationHandler. { VerifyOrReturnError(commissionableDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(deviceAttestationCredentialsProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h index 7a496e5a2f0a33..2e381662404447 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h @@ -538,6 +538,12 @@ class DLL_EXPORT UserDirectedCommissioningClient : public TransportMgrDelegate mCommissionerDeclarationHandler = commissionerDeclarationHandler; } + /** + * Remove the previously set Commissioner Declaration UDC request listener. + * + */ + void RemoveCommissionerDeclarationHandler() { mCommissionerDeclarationHandler = nullptr; } + private: void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf, Transport::MessageTransportContext * ctxt = nullptr) override; From 908203d9f7f1aba09476df671748fae807cd2018 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Mon, 6 May 2024 17:53:21 -0700 Subject: [PATCH 5/7] Fixing style issue in CommissionerDeclarationHandler.cpp --- .../tv-casting-common/core/CommissionerDeclarationHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp index f92f4d483b227c..1bedc6ce316a39 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.cpp @@ -37,8 +37,8 @@ CommissionerDeclarationHandler * CommissionerDeclarationHandler::GetInstance() // TODO: In the following PRs. Implement setHandler() for CommissionerDeclaration messages and expose messages to higher layers for // Linux, Android and iOS. -void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage(const chip::Transport::PeerAddress & source, - chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) +void CommissionerDeclarationHandler::OnCommissionerDeclarationMessage( + const chip::Transport::PeerAddress & source, chip::Protocols::UserDirectedCommissioning::CommissionerDeclaration cd) { ChipLogProgress(AppServer, "CommissionerDeclarationHandler::OnCommissionerDeclarationMessage() called TODO: handle message"); cd.DebugLog(); From c965cde9b9b53b67e599648028dcf027069c33ef Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Tue, 7 May 2024 09:32:21 -0700 Subject: [PATCH 6/7] Addressed comments by sharadb-amazon - 3nd review --- .../tv-casting-common/core/CastingApp.cpp | 13 +++++++------ .../core/CommissionerDeclarationHandler.h | 3 +-- .../UserDirectedCommissioning.h | 6 ------ 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index 3f0aabc2b0ec87..a8199d496a0cde 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -118,10 +118,6 @@ CHIP_ERROR CastingApp::Start() }); } - // Set a handler for Commissioner's CommissionerDeclaration messages. - chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( - CommissionerDeclarationHandler::GetInstance()); - return CHIP_NO_ERROR; } @@ -144,6 +140,10 @@ CHIP_ERROR CastingApp::PostStartRegistrations() // Register DeviceEvent Handler ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0)); + // Set a handler for Commissioner's CommissionerDeclaration messages. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( + CommissionerDeclarationHandler::GetInstance()); + mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING return CHIP_NO_ERROR; } @@ -153,13 +153,14 @@ CHIP_ERROR CastingApp::Stop() ChipLogProgress(Discovery, "CastingApp::Stop() called"); VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE); + // Remove the handler previously set for Commissioner's CommissionerDeclaration messages. + chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr); + // Shutdown the Matter server chip::Server::GetInstance().Shutdown(); mState = CASTING_APP_NOT_RUNNING; // CastingApp stopped successfully, set state to NOT_RUNNING - chip::Server::GetInstance().GetUserDirectedCommissioningClient()->RemoveCommissionerDeclarationHandler(); - return CHIP_NO_ERROR; } diff --git a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h index 445b1d6667c7cf..e84ca59a59e23d 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h +++ b/examples/tv-casting-app/tv-casting-common/core/CommissionerDeclarationHandler.h @@ -25,8 +25,7 @@ namespace casting { namespace core { /** - * @brief React to the Commissioner's CommissionerDeclaration messages with this singleton. This is the common handler across Linux, - * Android and iOS. + * @brief React to the Commissioner's CommissionerDeclaration messages with this singleton. */ class CommissionerDeclarationHandler : public chip::Protocols::UserDirectedCommissioning::CommissionerDeclarationHandler { diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h index 2e381662404447..7a496e5a2f0a33 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h @@ -538,12 +538,6 @@ class DLL_EXPORT UserDirectedCommissioningClient : public TransportMgrDelegate mCommissionerDeclarationHandler = commissionerDeclarationHandler; } - /** - * Remove the previously set Commissioner Declaration UDC request listener. - * - */ - void RemoveCommissionerDeclarationHandler() { mCommissionerDeclarationHandler = nullptr; } - private: void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf, Transport::MessageTransportContext * ctxt = nullptr) override; From 2a8c8e7cb347b4b558541c6e6a8eba09c77a4a86 Mon Sep 17 00:00:00 2001 From: Philip Gregor Date: Tue, 7 May 2024 10:45:25 -0700 Subject: [PATCH 7/7] Fixing Darwin CI build issue --- examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp index a8199d496a0cde..7e000134190daf 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingApp.cpp @@ -140,9 +140,11 @@ CHIP_ERROR CastingApp::PostStartRegistrations() // Register DeviceEvent Handler ReturnErrorOnFailure(chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(ChipDeviceEventHandler::Handle, 0)); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Set a handler for Commissioner's CommissionerDeclaration messages. chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler( CommissionerDeclarationHandler::GetInstance()); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT mState = CASTING_APP_RUNNING; // CastingApp started successfully, set state to RUNNING return CHIP_NO_ERROR; @@ -153,8 +155,10 @@ CHIP_ERROR CastingApp::Stop() ChipLogProgress(Discovery, "CastingApp::Stop() called"); VerifyOrReturnError(mState == CASTING_APP_RUNNING, CHIP_ERROR_INCORRECT_STATE); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Remove the handler previously set for Commissioner's CommissionerDeclaration messages. chip::Server::GetInstance().GetUserDirectedCommissioningClient()->SetCommissionerDeclarationHandler(nullptr); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // Shutdown the Matter server chip::Server::GetInstance().Shutdown();