Skip to content

Commit

Permalink
Add AsyncFacilitator to enable an async, event-driven, non-polling me…
Browse files Browse the repository at this point in the history
…chanism for facilitating BDX transfers

- Currently BDX transfers can only use the TransferFacilitator which polls the BDXTransferSession with a poll
  interval that adds unneccessary delays and is not the ideal approach to handle BDX transfers

- Add support for an AsyncTrasferFacilitator that uses a non-polling, event-driven mechanism based on BDX messages
  received over the exchange context and gets the next output event from the transfer session to drive the BDX
  transfer

- Add support for an AsyncResponder that uses the AsyncTrasferFacilitator and enables a provider delegate to
  handle BDX transfers

- Modify the darwin OTA provider code to use the AsyncResponder

- Add support for handling multiple OTA requests to the ota provider by creating an MTROTAImageTransferHandler
  object that handles a BDX transfer session independently from a singleton unsolicited BDX message handler that
  is created by the MTROTAProviderDelegateBridge.

- Support only one BDX transfer session and return busy to any query images coming from other nodes for now to
  match the test expectations (to be removed once tests for multiple OTA are in place)
  • Loading branch information
nivi-apple committed Sep 21, 2023
1 parent cd41f0b commit 73c6d9a
Show file tree
Hide file tree
Showing 13 changed files with 996 additions and 508 deletions.
16 changes: 7 additions & 9 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ @interface MTRDeviceControllerFactory ()
@property (atomic, readonly) dispatch_queue_t chipWorkQueue;
@property (readonly) DeviceControllerFactory * controllerFactory;
@property (readonly) PersistentStorageDelegate * persistentStorageDelegate;

// This is the OTA provider cluster delegate that would handle the requests to the OTA provider cluster
// itself like QueryImage, HandleUpdate and NotifyUpdateApplied. All BDX related handlers will be
// not handled here since each BDX session will have its own delegate to handle all BDX messages
// for that session.
@property (readonly) MTROTAProviderDelegateBridge * otaProviderDelegateBridge;
@property (readonly) Crypto::RawKeySessionKeystore * sessionKeystore;
// We use TestPersistentStorageDelegate just to get an in-memory store to back
Expand Down Expand Up @@ -138,6 +143,7 @@ - (BOOL)findMatchingFabric:(FabricTable &)fabricTable
fabric:(const FabricInfo * _Nullable * _Nonnull)fabric;

- (MTRDeviceController * _Nullable)maybeInitializeOTAProvider:(MTRDeviceController * _Nonnull)controller;

@end

@interface MTRDeviceControllerFactoryParams ()
Expand Down Expand Up @@ -901,7 +907,7 @@ - (MTRDeviceController * _Nullable)maybeInitializeOTAProvider:(MTRDeviceControll
__block CHIP_ERROR err;
dispatch_sync(_chipWorkQueue, ^{
auto systemState = _controllerFactory->GetSystemState();
err = _otaProviderDelegateBridge->Init(systemState->SystemLayer(), systemState->ExchangeMgr());
err = _otaProviderDelegateBridge->Init(systemState->ExchangeMgr());
});
if (CHIP_NO_ERROR != err) {
MTR_LOG_ERROR("Failed to init provider delegate bridge: %" CHIP_ERROR_FORMAT, err.Format());
Expand Down Expand Up @@ -975,10 +981,6 @@ - (void)controllerShuttingDown:(MTRDeviceController *)controller
// down most of the world.
DeviceLayer::PlatformMgrImpl().StopEventLoopTask();

if (_otaProviderDelegateBridge) {
_otaProviderDelegateBridge->Shutdown();
}

sharedCleanupBlock();

// Now that our per-controller storage for the controller being shut
Expand All @@ -999,10 +1001,6 @@ - (void)controllerShuttingDown:(MTRDeviceController *)controller
} else {
// Do the controller shutdown on the Matter work queue.
dispatch_sync(_chipWorkQueue, ^{
if (_otaProviderDelegateBridge) {
_otaProviderDelegateBridge->ControllerShuttingDown(controller);
}

sharedCleanupBlock();

// Now that our per-controller storage for the controller being shut
Expand Down
73 changes: 73 additions & 0 deletions src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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.
*/

#import <Matter/MTROTAProviderDelegate.h>

#include <protocols/bdx/AsyncTransferFacilitator.h>

NS_ASSUME_NONNULL_BEGIN

/**
* This class inherits from the AsyncResponder class and handles the BDX messages for a BDX transfer session.
* It overrides the HandleAsyncTransferSessionOutput virtual method and provides an implementation for it.
*
* For each BDX transfer, we will have an instance of MTROTAImageTransferHandler.
*/
class MTROTAImageTransferHandler : public chip::bdx::AsyncResponder
{
public:
MTROTAImageTransferHandler();
~MTROTAImageTransferHandler();

void HandleAsyncTransferSessionOutput(chip::bdx::TransferSession::OutputEvent & event) override;

private:
CHIP_ERROR PrepareForTransfer(chip::Messaging::ExchangeContext * exchangeCtx, chip::FabricIndex fabricIndex,
chip::NodeId nodeId);

void ResetState();

CHIP_ERROR ConfigureState(chip::FabricIndex fabricIndex, chip::NodeId nodeId);

static void HandleBdxInitReceivedTimeoutExpired(chip::System::Layer * systemLayer, void * state);

CHIP_ERROR OnMessageToSend(chip::bdx::TransferSession::OutputEvent & event);

CHIP_ERROR OnTransferSessionBegin(chip::bdx::TransferSession::OutputEvent & event);

CHIP_ERROR OnTransferSessionEnd(chip::bdx::TransferSession::OutputEvent & event);

CHIP_ERROR OnBlockQuery(chip::bdx::TransferSession::OutputEvent & event);

// Inherited from ExchangeContext
CHIP_ERROR OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader,
chip::System::PacketBufferHandle && payload) override;

// The fabric index of the peer node.
chip::Optional<chip::FabricIndex> mFabricIndex;

// The node id of the peer node.
chip::Optional<chip::NodeId> mNodeId;

// The OTA provider delegate used by the controller.
id<MTROTAProviderDelegate> mDelegate = nil;

// The OTA provider delegate queue used by the controller.
dispatch_queue_t mDelegateNotificationQueue = nil;
};

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 73c6d9a

Please sign in to comment.