Skip to content

Commit

Permalink
enable content app platform on android (#17302)
Browse files Browse the repository at this point in the history
* enable content app platform on android

* Fix CI

* Fix CI

* fix restyle

* address comments

* add casting init shell command
  • Loading branch information
chrisdecenzo authored Apr 19, 2022
1 parent a3f636d commit 8793870
Show file tree
Hide file tree
Showing 29 changed files with 1,510 additions and 477 deletions.
324 changes: 3 additions & 321 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <platform/TestOnlyCommissionableDataProvider.h>

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
#include "CommissionerMain.h"
#include <ControllerShellCommands.h>
#include <controller/CHIPDeviceControllerFactory.h>
#include <controller/ExampleOperationalCredentialsIssuer.h>
Expand Down Expand Up @@ -388,326 +389,6 @@ int ChipLinuxAppInit(int argc, char ** argv, OptionSet * customOptions)
return 0;
}

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE

using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::Transport;
using namespace ::chip::Credentials;
using namespace ::chip::DeviceLayer;
using namespace ::chip::Messaging;
using namespace ::chip::Controller;

class MyServerStorageDelegate : public PersistentStorageDelegate
{
CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
{
ChipLogProgress(AppServer, "Retrieving value from server storage.");
size_t bytesRead = 0;
CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead);

if (err == CHIP_NO_ERROR)
{
ChipLogProgress(AppServer, "Retrieved value from server storage.");
}
size = static_cast<uint16_t>(bytesRead);
return err;
}

CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
{
ChipLogProgress(AppServer, "Stored value in server storage");
return PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
}

CHIP_ERROR SyncDeleteKeyValue(const char * key) override
{
ChipLogProgress(AppServer, "Delete value in server storage");
return PersistedStorage::KeyValueStoreMgr().Delete(key);
}
};

class MyCommissionerCallback : public CommissionerCallback
{
void ReadyForCommissioning(uint32_t pincode, uint16_t longDiscriminator, PeerAddress peerAddress) override
{
CommissionerPairOnNetwork(pincode, longDiscriminator, peerAddress);
}
};

DeviceCommissioner gCommissioner;
CommissionerDiscoveryController gCommissionerDiscoveryController;
MyCommissionerCallback gCommissionerCallback;
MyServerStorageDelegate gServerStorage;
ExampleOperationalCredentialsIssuer gOpCredsIssuer;
NodeId gLocalId = kMaxOperationalNodeId;
Credentials::GroupDataProviderImpl gGroupDataProvider;

CHIP_ERROR InitCommissioner()
{
Controller::FactoryInitParams factoryParams;
Controller::SetupParams params;

// use a different listen port for the commissioner than the default used by chip-tool.
factoryParams.listenPort = LinuxDeviceOptions::GetInstance().securedCommissionerPort + 10;
factoryParams.fabricIndependentStorage = &gServerStorage;

gGroupDataProvider.SetStorageDelegate(&gServerStorage);
ReturnErrorOnFailure(gGroupDataProvider.Init());
factoryParams.groupDataProvider = &gGroupDataProvider;

params.operationalCredentialsDelegate = &gOpCredsIssuer;

ReturnErrorOnFailure(gOpCredsIssuer.Initialize(gServerStorage));

// No need to explicitly set the UDC port since we will use default
ReturnErrorOnFailure(gCommissioner.SetUdcListenPort(LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort));

// Initialize device attestation verifier
// TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
const Credentials::AttestationTrustStore * testingRootStore = Credentials::GetTestAttestationTrustStore();
SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));

Platform::ScopedMemoryBuffer<uint8_t> noc;
VerifyOrReturnError(noc.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);

Platform::ScopedMemoryBuffer<uint8_t> icac;
VerifyOrReturnError(icac.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
MutableByteSpan icacSpan(icac.Get(), Controller::kMaxCHIPDERCertLength);

Platform::ScopedMemoryBuffer<uint8_t> rcac;
VerifyOrReturnError(rcac.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength);

Crypto::P256Keypair ephemeralKey;
ReturnErrorOnFailure(ephemeralKey.Initialize());

ReturnErrorOnFailure(gOpCredsIssuer.GenerateNOCChainAfterValidation(gLocalId, /* fabricId = */ 1, chip::kUndefinedCATs,
ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan));

params.operationalKeypair = &ephemeralKey;
params.controllerRCAC = rcacSpan;
params.controllerICAC = icacSpan;
params.controllerNOC = nocSpan;

auto & factory = Controller::DeviceControllerFactory::GetInstance();
ReturnErrorOnFailure(factory.Init(factoryParams));
ReturnErrorOnFailure(factory.SetupCommissioner(params, gCommissioner));

chip::FabricInfo * fabricInfo = gCommissioner.GetFabricInfo();
VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INTERNAL);

uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
MutableByteSpan compressedFabricIdSpan(compressedFabricId);
ReturnErrorOnFailure(fabricInfo->GetCompressedId(compressedFabricIdSpan));
ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:",
static_cast<unsigned>(fabricInfo->GetFabricIndex()));
ChipLogByteSpan(Support, compressedFabricIdSpan);

// TODO: Once ExampleOperationalCredentialsIssuer has support, set default IPK on it as well so
// that commissioned devices get the IPK set from real values rather than "test-only" internal hookups.
ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
ReturnLogErrorOnFailure(chip::Credentials::SetSingleIpkEpochKey(&gGroupDataProvider, fabricInfo->GetFabricIndex(), defaultIpk,
compressedFabricIdSpan));

gCommissionerDiscoveryController.SetUserDirectedCommissioningServer(gCommissioner.GetUserDirectedCommissioningServer());
gCommissionerDiscoveryController.SetCommissionerCallback(&gCommissionerCallback);

return CHIP_NO_ERROR;
}

CHIP_ERROR ShutdownCommissioner()
{
UserDirectedCommissioningServer * udcServer = gCommissioner.GetUserDirectedCommissioningServer();
if (udcServer != nullptr)
{
udcServer->SetUserConfirmationProvider(nullptr);
}

gCommissioner.Shutdown();
return CHIP_NO_ERROR;
}

class PairingCommand : public Controller::DevicePairingDelegate
{
public:
PairingCommand() :
mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this){};

/////////// DevicePairingDelegate Interface /////////
void OnStatusUpdate(Controller::DevicePairingDelegate::Status status) override;
void OnPairingComplete(CHIP_ERROR error) override;
void OnPairingDeleted(CHIP_ERROR error) override;
void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override;

CHIP_ERROR UpdateNetworkAddress();

private:
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
static void OnDeviceConnectedFn(void * context, chip::OperationalDeviceProxy * device);
static void OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR error);

chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
};

PairingCommand gPairingCommand;
NodeId gRemoteId = kTestDeviceNodeId;

CHIP_ERROR PairingCommand::UpdateNetworkAddress()
{
ChipLogProgress(AppServer, "Mdns: Updating NodeId: %" PRIx64 " ...", gRemoteId);
return gCommissioner.UpdateDevice(gRemoteId);
}

void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status)
{
switch (status)
{
case DevicePairingDelegate::Status::SecurePairingSuccess:
ChipLogProgress(AppServer, "Secure Pairing Success");
break;
case DevicePairingDelegate::Status::SecurePairingFailed:
ChipLogError(AppServer, "Secure Pairing Failed");
break;
}
}

void PairingCommand::OnPairingComplete(CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR)
{
ChipLogProgress(AppServer, "Pairing Success");
}
else
{
ChipLogProgress(AppServer, "Pairing Failure: %s", ErrorStr(err));
// For some devices, it may take more time to appear on the network and become discoverable
// over DNS-SD, so don't give up on failure and restart the address update. Note that this
// will not be repeated endlessly as each chip-tool command has a timeout (in the case of
// the `pairing` command it equals 120s).
// UpdateNetworkAddress();
}
}

void PairingCommand::OnPairingDeleted(CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR)
{
ChipLogProgress(AppServer, "Pairing Deleted Success");
}
else
{
ChipLogProgress(AppServer, "Pairing Deleted Failure: %s", ErrorStr(err));
}
}

void PairingCommand::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR)
{
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ChipLogProgress(AppServer, "Device commissioning completed with success - getting OperationalDeviceProxy");

gCommissioner.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
#else // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ChipLogProgress(AppServer, "Device commissioning completed with success");
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
}
else
{
ChipLogProgress(AppServer, "Device commissioning Failure: %s", ErrorStr(err));
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
if (cdc != nullptr)
{
cdc->CommissioningFailed(err);
}
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
}
}

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

void PairingCommand::OnDeviceConnectedFn(void * context, chip::OperationalDeviceProxy * device)
{
ChipLogProgress(Controller, "OnDeviceConnectedFn");
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();

if (device == nullptr)
{
ChipLogProgress(AppServer, "No OperationalDeviceProxy returned from OnDeviceConnectedFn");
if (cdc != nullptr)
{
cdc->CommissioningFailed(CHIP_ERROR_INCORRECT_STATE);
}
return;
}

if (cdc != nullptr)
{
// TODO: get from DAC!
UDCClientState * udc = cdc->GetUDCClientState();
uint16_t vendorId = (udc == nullptr ? 0 : udc->GetVendorId());
uint16_t productId = (udc == nullptr ? 0 : udc->GetProductId());
cdc->CommissioningSucceeded(vendorId, productId, gRemoteId, device);
}
}

void PairingCommand::OnDeviceConnectionFailureFn(void * context, PeerId peerId, CHIP_ERROR err)
{
ChipLogProgress(Controller, "OnDeviceConnectionFailureFn - attempt to get OperationalDeviceProxy failed");
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
{
cdc->CommissioningFailed(err);
}
}

#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, Transport::PeerAddress address)
{
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(pincode).SetDiscriminator(disc).SetPeerAddress(address);

gCommissioner.RegisterPairingDelegate(&gPairingCommand);
gCommissioner.PairDevice(gRemoteId, params);

return CHIP_NO_ERROR;
}

CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index)
{
UDCClientState * state = gCommissioner.GetUserDirectedCommissioningServer()->GetUDCClients().GetUDCClientState(index);
if (state == nullptr)
{
ChipLogProgress(AppServer, "udc client[%ld] null \r\n", index);
return CHIP_ERROR_KEY_NOT_FOUND;
}
else
{
Transport::PeerAddress peerAddress = state->GetPeerAddress();

state->SetUDCClientProcessingState(UDCClientProcessingState::kCommissioningNode);

return CommissionerPairOnNetwork(pincode, state->GetLongDiscriminator(), peerAddress);
}
}

DeviceCommissioner * GetDeviceCommissioner()
{
return &gCommissioner;
}

CommissionerDiscoveryController * GetCommissionerDiscoveryController()
{
return &gCommissionerDiscoveryController;
}

#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE

void ChipLinuxAppMainLoop(DeviceAttestationCredentialsProvider * dacProvider)
{
static chip::CommonCaseDeviceServerInitParams initParams;
Expand Down Expand Up @@ -745,7 +426,8 @@ void ChipLinuxAppMainLoop(DeviceAttestationCredentialsProvider * dacProvider)

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
ChipLogProgress(AppServer, "Starting commissioner");
VerifyOrReturn(InitCommissioner() == CHIP_NO_ERROR);
VerifyOrReturn(InitCommissioner(LinuxDeviceOptions::GetInstance().securedCommissionerPort + 10,
LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort) == CHIP_NO_ERROR);
ChipLogProgress(AppServer, "Started commissioner");
#if defined(ENABLE_CHIP_SHELL)
Shell::RegisterControllerCommands();
Expand Down
33 changes: 33 additions & 0 deletions examples/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ source_set("app-main") {
"AppMain.h",
"CommissioneeShellCommands.cpp",
"CommissioneeShellCommands.h",
"CommissionerMain.cpp",
"CommissionerMain.h",
"ControllerShellCommands.cpp",
"ControllerShellCommands.h",
"LinuxCommissionableDataProvider.cpp",
Expand Down Expand Up @@ -60,3 +62,34 @@ source_set("app-main") {

public_configs = [ ":app-main-config" ]
}

source_set("commissioner-main") {
defines = []
sources = [
"CommissionerMain.cpp",
"CommissionerMain.h",
]

defines = []

if (chip_enable_pw_rpc) {
defines += [ "PW_RPC_ENABLED" ]
}
if (chip_build_libshell) {
defines += [ "ENABLE_CHIP_SHELL" ]
}

public_deps = [
"${chip_root}/src/app/server",
"${chip_root}/src/credentials:default_attestation_verifier",
"${chip_root}/src/lib",
"${chip_root}/src/lib/shell",
"${chip_root}/src/lib/shell:shell_core",
]

if (chip_enable_transport_trace) {
public_deps += [ "${chip_root}/examples/common/tracing:trace_handlers" ]
}

public_configs = [ ":app-main-config" ]
}
Loading

0 comments on commit 8793870

Please sign in to comment.