diff --git a/examples/ota-provider-app/esp32/main/BdxOtaSender.cpp b/examples/ota-provider-app/esp32/main/BdxOtaSender.cpp index d4ca1a3de1ce79..fea60d46990cec 100644 --- a/examples/ota-provider-app/esp32/main/BdxOtaSender.cpp +++ b/examples/ota-provider-app/esp32/main/BdxOtaSender.cpp @@ -28,6 +28,32 @@ using chip::bdx::StatusCode; using chip::bdx::TransferControlFlags; using chip::bdx::TransferSession; +CHIP_ERROR BdxOtaSender::InitializeTransfer(chip::FabricIndex fabricIndex, chip::NodeId nodeId) +{ + if (mInitialized) + { + // Reset stale connection from the Same Node if exists + if ((mFabricIndex.HasValue() && mFabricIndex.Value() == fabricIndex) && (mNodeId.HasValue() && mNodeId.Value() == nodeId)) + { + Reset(); + } + // Prevent a new node connection since another is active + else if ((mFabricIndex.HasValue() && mFabricIndex.Value() != fabricIndex) || + (mNodeId.HasValue() && mNodeId.Value() != nodeId)) + { + return CHIP_ERROR_BUSY; + } + else + { + return CHIP_ERROR_INTERNAL; + } + } + mFabricIndex.SetValue(fabricIndex); + mNodeId.SetValue(nodeId); + mInitialized = true; + return CHIP_NO_ERROR; +} + void BdxOtaSender::SetCallbacks(BdxOtaSenderCallbacks callbacks) { mOnBlockQueryCallback = callbacks.onBlockQuery; @@ -174,11 +200,16 @@ void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & ev void BdxOtaSender::Reset() { + mFabricIndex.ClearValue(); + mNodeId.ClearValue(); mTransfer.Reset(); if (mExchangeCtx != nullptr) { mExchangeCtx->Close(); + mExchangeCtx = nullptr; } + + mInitialized = false; mNumBytesSent = 0; } diff --git a/examples/ota-provider-app/esp32/main/include/ota-provider-common/BdxOtaSender.h b/examples/ota-provider-app/esp32/main/include/ota-provider-common/BdxOtaSender.h index 4940d676dedd58..5e7ffaf091572a 100644 --- a/examples/ota-provider-app/esp32/main/include/ota-provider-common/BdxOtaSender.h +++ b/examples/ota-provider-app/esp32/main/include/ota-provider-common/BdxOtaSender.h @@ -71,6 +71,9 @@ struct BdxOtaSenderCallbacks class BdxOtaSender : public chip::bdx::Responder { public: + // Initializes BDX transfer-related metadata. Should always be called first. + CHIP_ERROR InitializeTransfer(chip::FabricIndex fabricIndex, chip::NodeId nodeId); + void SetCallbacks(BdxOtaSenderCallbacks callbacks); /** @@ -97,6 +100,12 @@ class BdxOtaSender : public chip::bdx::Responder uint32_t mNumBytesSent = 0; + bool mInitialized = false; + + chip::Optional mFabricIndex; + + chip::Optional mNodeId; + chip::Callback::Callback * mOnBlockQueryCallback = nullptr; chip::Callback::Callback * mOnTransferCompleteCallback = nullptr; chip::Callback::Callback * mOnTransferFailedCallback = nullptr; diff --git a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp index bd89f71eb2bf9b..1af2ea3dd690d2 100644 --- a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp +++ b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp @@ -35,6 +35,32 @@ BdxOtaSender::BdxOtaSender() memset(mFileDesignator, 0, chip::bdx::kMaxFileDesignatorLen); } +CHIP_ERROR BdxOtaSender::InitializeTransfer(chip::FabricIndex fabricIndex, chip::NodeId nodeId) +{ + if (mInitialized) + { + // Reset stale connection from the Same Node if exists + if ((mFabricIndex.HasValue() && mFabricIndex.Value() == fabricIndex) && (mNodeId.HasValue() && mNodeId.Value() == nodeId)) + { + Reset(); + } + // Prevent a new node connection since another is active + else if ((mFabricIndex.HasValue() && mFabricIndex.Value() != fabricIndex) || + (mNodeId.HasValue() && mNodeId.Value() != nodeId)) + { + return CHIP_ERROR_BUSY; + } + else + { + return CHIP_ERROR_INTERNAL; + } + } + mFabricIndex.SetValue(fabricIndex); + mNodeId.SetValue(nodeId); + mInitialized = true; + return CHIP_NO_ERROR; +} + void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & event) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -152,12 +178,16 @@ void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & ev void BdxOtaSender::Reset() { + mFabricIndex.ClearValue(); + mNodeId.ClearValue(); mTransfer.Reset(); if (mExchangeCtx != nullptr) { mExchangeCtx->Close(); + mExchangeCtx = nullptr; } + mInitialized = false; mNumBytesSent = 0; memset(mFileDesignator, 0, chip::bdx::kMaxFileDesignatorLen); } diff --git a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.h b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.h index 49da42aeff7827..6cc303486ed891 100644 --- a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.h +++ b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.h @@ -25,6 +25,9 @@ class BdxOtaSender : public chip::bdx::Responder public: BdxOtaSender(); + // Initializes BDX transfer-related metadata. Should always be called first. + CHIP_ERROR InitializeTransfer(chip::FabricIndex fabricIndex, chip::NodeId nodeId); + private: // Inherited from bdx::TransferFacilitator void HandleTransferSessionOutput(chip::bdx::TransferSession::OutputEvent & event) override; @@ -35,4 +38,10 @@ class BdxOtaSender : public chip::bdx::Responder char mFileDesignator[chip::bdx::kMaxFileDesignatorLen]; uint32_t mNumBytesSent = 0; + + bool mInitialized = false; + + chip::Optional mFabricIndex; + + chip::Optional mNodeId; }; diff --git a/examples/ota-provider-app/ota-provider-common/OTAProviderExample.cpp b/examples/ota-provider-app/ota-provider-common/OTAProviderExample.cpp index a85b7918c90442..2b85058257ff4d 100644 --- a/examples/ota-provider-app/ota-provider-common/OTAProviderExample.cpp +++ b/examples/ota-provider-app/ota-provider-common/OTAProviderExample.cpp @@ -270,18 +270,27 @@ EmberAfStatus OTAProviderExample::HandleQueryImage(chip::app::CommandHandler * c // Initialize the transfer session in prepartion for a BDX transfer BitFlags bdxFlags; bdxFlags.Set(TransferControlFlags::kReceiverDrive); - CHIP_ERROR err = mBdxOtaSender.PrepareForTransfer(&chip::DeviceLayer::SystemLayer(), chip::bdx::TransferRole::kSender, - bdxFlags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollFreq); - if (err != CHIP_NO_ERROR) + if (mBdxOtaSender.InitializeTransfer(commandObj->GetSubjectDescriptor().fabricIndex, + commandObj->GetSubjectDescriptor().subject) == CHIP_NO_ERROR) { - ChipLogError(BDX, "Failed to initialize BDX transfer session: %s", chip::ErrorStr(err)); - return EMBER_ZCL_STATUS_FAILURE; - } + CHIP_ERROR err = mBdxOtaSender.PrepareForTransfer(&chip::DeviceLayer::SystemLayer(), chip::bdx::TransferRole::kSender, + bdxFlags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollFreq); + if (err != CHIP_NO_ERROR) + { + ChipLogError(BDX, "Failed to initialize BDX transfer session: %s", chip::ErrorStr(err)); + return EMBER_ZCL_STATUS_FAILURE; + } - response.imageURI.Emplace(chip::CharSpan::fromCharString(uriBuf)); - response.softwareVersion.Emplace(newSoftwareVersion); - response.softwareVersionString.Emplace(chip::CharSpan::fromCharString(newSoftwareVersionString)); - response.updateToken.Emplace(chip::ByteSpan(updateToken)); + response.imageURI.Emplace(chip::CharSpan::fromCharString(uriBuf)); + response.softwareVersion.Emplace(newSoftwareVersion); + response.softwareVersionString.Emplace(chip::CharSpan::fromCharString(newSoftwareVersionString)); + response.updateToken.Emplace(chip::ByteSpan(updateToken)); + } + else + { + // Another BDX transfer in progress + queryStatus = OTAQueryStatus::kBusy; + } } response.status = queryStatus; diff --git a/src/lib/core/CHIPError.cpp b/src/lib/core/CHIPError.cpp index fb630d73e4578a..2f999000ab4443 100644 --- a/src/lib/core/CHIPError.cpp +++ b/src/lib/core/CHIPError.cpp @@ -695,6 +695,9 @@ bool FormatCHIPError(char * buf, uint16_t bufSize, CHIP_ERROR err) case CHIP_ERROR_IM_MALFORMED_TIMED_REQUEST_MESSAGE.AsInteger(): desc = "Malformed Interaction Model Timed Request Message"; break; + case CHIP_ERROR_BUSY.AsInteger(): + desc = "The Resource is busy and cannot process the request"; + break; } #endif // !CHIP_CONFIG_SHORT_ERROR_STR diff --git a/src/lib/core/CHIPError.h b/src/lib/core/CHIPError.h index c55fd3935527e5..f8c3458caade7b 100644 --- a/src/lib/core/CHIPError.h +++ b/src/lib/core/CHIPError.h @@ -2400,6 +2400,15 @@ using CHIP_ERROR = ::chip::ChipError; */ #define CHIP_ERROR_INVALID_FILE_IDENTIFIER CHIP_CORE_ERROR(0xda) +/** + * @def CHIP_ERROR_BUSY + * + * @brief + * The Resource is busy and cannot process the request. Trying again might work. + */ +#define CHIP_ERROR_BUSY CHIP_CORE_ERROR(0xdb) + + /** * @} */