@@ -461,9 +461,7 @@ CHIP_ERROR ConfigureState(chip::FabricIndex fabricIndex, chip::NodeId nodeId)
461461 CHIP_ERROR err = mSystemLayer ->StartTimer (kBdxInitReceivedTimeout , HandleBdxInitReceivedTimeoutExpired, this );
462462 LogErrorOnFailure (err);
463463
464- // The caller of this method maps CHIP_ERROR to specific BDX Status Codes (see GetBdxStatusCodeFromChipError)
465- // and those are used by the BDX session to prepare the status report.
466- VerifyOrReturnError (err == CHIP_NO_ERROR, CHIP_ERROR_INCORRECT_STATE);
464+ ReturnErrorOnFailure (err);
467465
468466 mFabricIndex .SetValue (fabricIndex);
469467 mNodeId .SetValue (nodeId);
@@ -615,7 +613,7 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath
615613 auto * commandParams = [[MTROTASoftwareUpdateProviderClusterQueryImageParams alloc ] init ];
616614 CHIP_ERROR err = ConvertToQueryImageParams (commandData, commandParams);
617615 if (err != CHIP_NO_ERROR) {
618- commandObj->AddStatus (commandPath, Protocols::InteractionModel::Status::InvalidCommand );
616+ commandObj->AddStatus (commandPath, StatusIB (err). mStatus );
619617 return ;
620618 }
621619
@@ -635,64 +633,83 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath
635633 ChipLogDetail (Controller, " QueryImage: application responded with: %s" ,
636634 [[data description ] cStringUsingEncoding: NSUTF8StringEncoding]);
637635
638- Commands::QueryImageResponse::Type response;
639- ConvertFromQueryImageResponseParms (data, response);
640-
641636 auto hasUpdate = [data.status isEqual: @(MTROtaSoftwareUpdateProviderOTAQueryStatusUpdateAvailable)];
642637 auto isBDXProtocolSupported = [commandParams.protocolsSupported
643638 containsObject: @(MTROtaSoftwareUpdateProviderOTADownloadProtocolBDXSynchronous)];
644639
645- if (hasUpdate && isBDXProtocolSupported) {
646- auto fabricIndex = handler->GetSubjectDescriptor ().fabricIndex ;
647- auto nodeId = handler->GetSubjectDescriptor ().subject ;
648- CHIP_ERROR err = gOtaSender .PrepareForTransfer (fabricIndex, nodeId);
649- if (CHIP_NO_ERROR != err) {
650- LogErrorOnFailure (err);
651- if (err == CHIP_ERROR_BUSY) {
652- Commands::QueryImageResponse::Type busyResponse;
653- busyResponse.status = static_cast <OTAQueryStatus>(MTROTASoftwareUpdateProviderOTAQueryStatusBusy);
654- busyResponse.delayedActionTime .SetValue (response.delayedActionTime .ValueOr (kDelayedActionTimeSeconds ));
655- handler->AddResponse (cachedCommandPath, busyResponse);
656- handle.Release ();
657- return ;
658- }
659- handler->AddStatus (cachedCommandPath, Protocols::InteractionModel::Status::Failure);
660- handle.Release ();
661- gOtaSender .ResetState ();
662- return ;
663- }
664- auto targetNodeId
665- = handler->GetExchangeContext ()->GetSessionHandle ()->AsSecureSession ()->GetLocalScopedNodeId ();
640+ // The logic we are following here is if none of the protocols supported by the requestor are supported by us, we
641+ // can't transfer the image even if we had an image available and we would return a Protocol Not Supported status.
642+ // Assumption here is the requestor would send us a list of all the protocols it supports. If one/more of the
643+ // protocols supported by the requestor are supported by us, we check if an image is not available due to various
644+ // reasons - image not available, delegate reporting busy, we will respond with the status in the delegate response.
645+ // If update is available, we try to prepare for transfer and build the uri in the response with a status of Image
646+ // Available
647+
648+ // If the protocol requested is not supported, return status - Protocol Not Supported
649+ if (!isBDXProtocolSupported) {
650+ Commands::QueryImageResponse::Type response;
651+ response.status
652+ = static_cast <OTAQueryStatus>(MTROTASoftwareUpdateProviderOTAQueryStatusDownloadProtocolNotSupported);
653+ handler->AddResponse (cachedCommandPath, response);
654+ handle.Release ();
655+ return ;
656+ }
666657
667- char uriBuffer[kMaxBDXURILen ];
668- MutableCharSpan uri (uriBuffer);
669- err = bdx::MakeURI (targetNodeId.GetNodeId (), AsCharSpan (data.imageURI ), uri);
670- if (CHIP_NO_ERROR != err) {
671- LogErrorOnFailure (err);
672- handler->AddStatus (cachedCommandPath, Protocols::InteractionModel::Status::Failure);
658+ Commands::QueryImageResponse::Type delegateResponse;
659+ ConvertFromQueryImageResponseParams (data, delegateResponse);
660+
661+ // If update is not available, return the delegate response
662+ if (!hasUpdate) {
663+ handler->AddResponse (cachedCommandPath, delegateResponse);
664+ handle.Release ();
665+ return ;
666+ }
667+
668+ // If there is an update available, try to prepare for a transfer.
669+ auto fabricIndex = handler->GetSubjectDescriptor ().fabricIndex ;
670+ auto nodeId = handler->GetSubjectDescriptor ().subject ;
671+ CHIP_ERROR err = gOtaSender .PrepareForTransfer (fabricIndex, nodeId);
672+ if (CHIP_NO_ERROR != err) {
673+
674+ // Handle busy error separately as we have a query image response status that maps to busy
675+ if (err == CHIP_ERROR_BUSY) {
676+ ChipLogError (
677+ Controller, " Responding with Busy due to being in the middle of handling another BDX transfer" );
678+ Commands::QueryImageResponse::Type response;
679+ response.status = static_cast <OTAQueryStatus>(MTROTASoftwareUpdateProviderOTAQueryStatusBusy);
680+ response.delayedActionTime .SetValue (delegateResponse.delayedActionTime .ValueOr (kDelayedActionTimeSeconds ));
681+ handler->AddResponse (cachedCommandPath, response);
673682 handle.Release ();
674- gOtaSender .ResetState ();
683+ // We do not reset state when we get the busy error because that means we are locked in a BDX transfer
684+ // session with another requestor when we get this query image request. We do not want to interrupt the
685+ // ongoing transfer instead just respond to the second requestor with a busy status and a delayedActionTime
686+ // in which the requestor can retry.
675687 return ;
676688 }
677-
678- response.imageURI .SetValue (uri);
679- handler->AddResponse (cachedCommandPath, response);
689+ LogErrorOnFailure (err);
690+ handler->AddStatus (cachedCommandPath, StatusIB (err).mStatus );
680691 handle.Release ();
692+ // We need to reset state here to clean up any initialization we might have done including starting the BDX
693+ // timeout timer while preparing for transfer if any failure occurs afterwards.
694+ gOtaSender .ResetState ();
681695 return ;
682696 }
683- if (!hasUpdate) {
684- // Send whatever error response our delegate decided on.
685- handler->AddResponse (cachedCommandPath, response);
686- } else {
687- // We must have isBDXProtocolSupported false. Send the corresponding error status.
688- Commands::QueryImageResponse::Type protocolNotSupportedResponse;
689- protocolNotSupportedResponse.status
690- = static_cast <OTAQueryStatus>(MTROTASoftwareUpdateProviderOTAQueryStatusDownloadProtocolNotSupported);
691- handler->AddResponse (cachedCommandPath, protocolNotSupportedResponse);
697+ auto targetNodeId = handler->GetExchangeContext ()->GetSessionHandle ()->AsSecureSession ()->GetLocalScopedNodeId ();
698+
699+ char uriBuffer[kMaxBDXURILen ];
700+ MutableCharSpan uri (uriBuffer);
701+ err = bdx::MakeURI (targetNodeId.GetNodeId (), AsCharSpan (data.imageURI ), uri);
702+ if (CHIP_NO_ERROR != err) {
703+ LogErrorOnFailure (err);
704+ handler->AddStatus (cachedCommandPath, StatusIB (err).mStatus );
705+ handle.Release ();
706+ gOtaSender .ResetState ();
707+ return ;
692708 }
709+ delegateResponse.imageURI .SetValue (uri);
710+ handler->AddResponse (cachedCommandPath, delegateResponse);
693711 handle.Release ();
694712 }
695-
696713 errorHandler: ^(NSError *) {
697714 // Not much we can do here
698715 }];
@@ -867,7 +884,7 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath
867884 return CHIP_NO_ERROR;
868885}
869886
870- void MTROTAProviderDelegateBridge::ConvertFromQueryImageResponseParms (
887+ void MTROTAProviderDelegateBridge::ConvertFromQueryImageResponseParams (
871888 const MTROTASoftwareUpdateProviderClusterQueryImageResponseParams * responseParams,
872889 Commands::QueryImageResponse::Type & response)
873890{
0 commit comments