blob: f58251bff48dd0972a473e127feb9a89ad5dc12f [file] [log] [blame]
/*
* Copyright (c) 2022 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
#import <Matter/Matter.h>
#include <commands/common/Command.h>
#include <commands/common/CredentialIssuerCommands.h>
#include <map>
#include <set>
#include <string>
#include "../provider/OTAProviderDelegate.h"
inline constexpr char kIdentityAlpha[] = "alpha";
inline constexpr char kIdentityBeta[] = "beta";
inline constexpr char kIdentityGamma[] = "gamma";
class CHIPCommandBridge : public Command {
public:
CHIPCommandBridge(const char * commandName, const char * helpText = nullptr)
: Command(commandName, helpText)
{
AddArgument("commissioner-name", &mCommissionerName);
AddArgument("commissioner-nodeId", 0, UINT64_MAX, &mCommissionerNodeId,
"Sets the commissioner node ID of the given "
"commissioner-name. Interactive mode will only set a single commissioner on the inital command. "
"The commissioner node ID will be persisted until a different one is specified.");
AddArgument("commissioner-shared-storage", 0, 1, &mCommissionerSharedStorage,
"Use a shared storage instance instead of individual storage for each commissioner. Default is true.");
AddArgument("paa-trust-store-path", &mPaaTrustStorePath,
"Path to directory holding PAA certificate information. Can be absolute or relative to the current working "
"directory.");
AddArgument(
"storage-directory", &mStorageDirectory, "This option does nothing. It is here for API compatibility with chip-tool.");
AddArgument("commissioner-vendor-id", 0, UINT16_MAX, &mCommissionerVendorId,
"The vendor id to use for darwin-framework-tool. If not provided, chip::VendorId::TestVendor1 (65521, 0xFFF1) will be "
"used.");
}
/////////// Command Interface /////////
CHIP_ERROR Run() override;
// Will convert error to a CHIP_ERROR and call SetCommandExitStatus with the
// result. If a log string is provided, will log that plus the string
// representation of the CHIP_ERROR.
void SetCommandExitStatus(NSError * error, const char * logString = nullptr);
void SetCommandExitStatus(CHIP_ERROR status)
{
mCommandExitStatus = status;
StopWaiting();
}
static OTAProviderDelegate * mOTADelegate;
protected:
// Will be called in a setting in which it's safe to touch the CHIP
// stack. The rules for Run() are as follows:
//
// 1) If error is returned, Run() must not call SetCommandExitStatus.
// 2) If success is returned Run() must either have called
// SetCommandExitStatus() or scheduled async work that will do that.
virtual CHIP_ERROR RunCommand() = 0;
// Get the wait duration, in seconds, before the command times out.
virtual chip::System::Clock::Timeout GetWaitDuration() const = 0;
// Shut down the command, in case any work needs to be done after the event
// loop has been stopped.
virtual void Shutdown() {}
void SetIdentity(const char * identity);
// This method returns the commissioner instance to be used for running the command.
MTRDeviceController * CurrentCommissioner();
NSNumber * CurrentCommissionerFabricId();
MTRDeviceController * GetCommissioner(const char * identity);
// Returns the MTRBaseDevice for the specified node ID.
// Will utilize an existing PASE connection if the device is being commissioned.
MTRBaseDevice * BaseDeviceWithNodeId(chip::NodeId nodeId);
// Will log the given string and given error (as progress if success, error
// if failure).
void LogNSError(const char * logString, NSError * error);
// Clean up any resources allocated by the command. Some commands may hold
// on to resources after Shutdown(), but Cleanup() will guarantee those are
// cleaned up.
virtual void Cleanup() {}
// If true, skip calling Cleanup() when in interactive mode, so the command
// can keep doing work as needed. Cleanup() will be called when quitting
// interactive mode. This method will be called before Shutdown, so it can
// use member values that Shutdown will normally reset.
virtual bool DeferInteractiveCleanup() { return NO; }
// Execute any deferred cleanups. Used when exiting interactive mode.
void ExecuteDeferredCleanups();
static std::set<CHIPCommandBridge *> sDeferredCleanups;
void StopCommissioners();
void RestartCommissioners();
private:
CHIP_ERROR InitializeCommissioner(
std::string key, chip::FabricId fabricId, const chip::Credentials::AttestationTrustStore * trustStore);
void ShutdownCommissioner();
uint16_t CurrentCommissionerIndex();
CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL;
CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds);
void StopWaiting();
CHIP_ERROR MaybeSetUpStack();
CHIP_ERROR SetUpStackWithSharedStorage(NSArray<NSData *> * productAttestationAuthorityCertificates);
CHIP_ERROR SetUpStackWithPerControllerStorage(NSArray<NSData *> * productAttestationAuthorityCertificates);
void MaybeTearDownStack();
CHIP_ERROR GetPAACertsFromFolder(NSArray<NSData *> * __autoreleasing * paaCertsResult);
// Our three controllers: alpha, beta, gamma.
static std::map<std::string, MTRDeviceController *> mControllers;
// The current controller; the one the current command should be using.
MTRDeviceController * mCurrentController;
static bool sUseSharedStorage;
chip::Optional<bool> mCommissionerSharedStorage;
std::condition_variable cvWaitingForResponse;
std::mutex cvWaitingForResponseMutex;
chip::Optional<char *> mCommissionerName;
chip::Optional<uint64_t> mCommissionerNodeId;
bool mWaitingForResponse { true };
static dispatch_queue_t mOTAProviderCallbackQueue;
chip::Optional<char *> mPaaTrustStorePath;
chip::Optional<chip::VendorId> mCommissionerVendorId;
std::string mCurrentIdentity;
};