/* * * Copyright (c) 2020 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. */ #include "commands/clusters/SubscriptionsCommands.h" #include "commands/common/Commands.h" #include "commands/example/ExampleCredentialIssuerCommands.h" #include #include "CastingServer.h" #include "CastingUtils.h" #if defined(ENABLE_CHIP_SHELL) #include "CastingShellCommands.h" #include // nogncheck #include #endif #include "LinuxCommissionableDataProvider.h" #include "Options.h" #include #include #include #include #include using namespace chip; using chip::ArgParser::HelpOptions; using chip::ArgParser::OptionDef; using chip::ArgParser::OptionSet; #if defined(ENABLE_CHIP_SHELL) using chip::Shell::Engine; #endif CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options) { chip::Optional setupPasscode; if (options.payload.setUpPINCode != 0) { setupPasscode.SetValue(options.payload.setUpPINCode); } else if (!options.spake2pVerifier.HasValue()) { uint32_t defaultTestPasscode = 0; chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); ChipLogError(Support, "*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 " "given on command line. This is temporary and will disappear. Please update your scripts " "to explicitly configure onboarding credentials. ***", static_cast(defaultTestPasscode)); setupPasscode.SetValue(defaultTestPasscode); options.payload.setUpPINCode = defaultTestPasscode; } else { // Passcode is 0, so will be ignored, and verifier will take over. Onboarding payload // printed for debug will be invalid, but if the onboarding payload had been given // properly to the commissioner later, PASE will succeed. } // Default to minimum PBKDF iterations uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Min_PBKDF_Iterations; if (options.spake2pIterations != 0) { spake2pIterationCount = options.spake2pIterations; } ChipLogError(Support, "PASE PBKDF iterations set to %u", static_cast(spake2pIterationCount)); return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode, options.payload.discriminator.GetLongValue()); } // To hold SPAKE2+ verifier, discriminator, passcode LinuxCommissionableDataProvider gCommissionableDataProvider; // For shell and command line processing of commands ExampleCredentialIssuerCommands gCredIssuerCommands; Commands gCommands; CHIP_ERROR ProcessClusterCommand(int argc, char ** argv) { if (!CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->IsInitialized()) { CastingServer::GetInstance()->SetDefaultFabricIndex(OnConnectionSuccess, OnConnectionFailure, OnNewOrUpdatedEndpoint); } gCommands.Run(argc, argv); return CHIP_NO_ERROR; } int main(int argc, char * argv[]) { ChipLogProgress(AppServer, "chip_casting_simplified = 0"); // this file is built/run only if chip_casting_simplified = 0 VerifyOrDie(CHIP_NO_ERROR == chip::Platform::MemoryInit()); VerifyOrDie(CHIP_NO_ERROR == chip::DeviceLayer::PlatformMgr().InitChipStack()); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); std::thread shellThread([]() { Engine::Root().RunMainLoop(); }); Shell::RegisterCastingCommands(); #endif CHIP_ERROR err = CHIP_NO_ERROR; DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH); // Init the commissionable data provider based on command line options // to handle custom verifiers, discriminators, etc. err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); SuccessOrExit(err); DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider); // Initialize device attestation config SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); // Initialize device attestation verifier from a constant version { // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); } SuccessOrExit(err = CastingServer::GetInstance()->PreInit()); // Enter commissioning mode, open commissioning window static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(CHIP_NO_ERROR == initParams.InitializeStaticResourcesBeforeServerInit()); VerifyOrDie(CHIP_NO_ERROR == chip::Server::GetInstance().Init(initParams)); if (argc > 1) { ChipLogProgress(AppServer, "Command line parameters detected. Skipping auto-start."); } else if (ConnectToCachedVideoPlayer() == CHIP_NO_ERROR) { ChipLogProgress(AppServer, "Skipping commissioner discovery / User directed commissioning flow."); } else { // Send discover commissioners request SuccessOrExit(err = CastingServer::GetInstance()->DiscoverCommissioners()); // Give commissioners some time to respond and then ScheduleWork to initiate commissioning DeviceLayer::SystemLayer().StartTimer( chip::System::Clock::Milliseconds32(kCommissionerDiscoveryTimeoutInMs), [](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr); } registerClusters(gCommands, &gCredIssuerCommands); registerCommandsSubscriptions(gCommands, &gCredIssuerCommands); if (argc > 1) { // if there are command-line arguments, then automatically start server ProcessClusterCommand(argc, argv); } DeviceLayer::PlatformMgr().RunEventLoop(); exit: #if defined(ENABLE_CHIP_SHELL) shellThread.join(); #endif if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Failed to run TV Casting App: %s", ErrorStr(err)); // End the program with non zero error code to indicate an error. return 1; } return 0; }