forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCHIPCommand.h
270 lines (227 loc) · 12.2 KB
/
CHIPCommand.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
* Copyright (c) 2021 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
#ifdef CONFIG_USE_LOCAL_STORAGE
#include <controller/ExamplePersistentStorage.h>
#endif // CONFIG_USE_LOCAL_STORAGE
#include "Command.h"
#include "BDXDiagnosticLogsServerDelegate.h"
#include <TracingCommandLineArgument.h>
#include <app/icd/client/CheckInHandler.h>
#include <app/icd/client/DefaultICDClientStorage.h>
#include <commands/common/ChipToolCheckInDelegate.h>
#include <commands/common/CredentialIssuerCommands.h>
#include <commands/example/ExampleCredentialIssuerCommands.h>
#include <credentials/GroupDataProviderImpl.h>
#include <credentials/PersistentStorageOpCertStore.h>
#include <crypto/PersistentStorageOperationalKeystore.h>
#include <crypto/RawKeySessionKeystore.h>
#include <string>
inline constexpr char kIdentityAlpha[] = "alpha";
inline constexpr char kIdentityBeta[] = "beta";
inline constexpr char kIdentityGamma[] = "gamma";
// The null fabric commissioner is a commissioner that isn't on a fabric.
// This is a legal configuration in which the commissioner delegates
// operational communication and invocation of the commssioning complete
// command to a separate on-fabric administrator node.
//
// The null-fabric-commissioner identity is provided here to demonstrate the
// commissioner portion of such an architecture. The null-fabric-commissioner
// can carry a commissioning flow up until the point of operational channel
// (CASE) communcation.
inline constexpr char kIdentityNull[] = "null-fabric-commissioner";
class CHIPCommand : public Command
{
public:
using ChipDeviceCommissioner = ::chip::Controller::DeviceCommissioner;
using ChipDeviceController = ::chip::Controller::DeviceController;
using IPAddress = ::chip::Inet::IPAddress;
using NodeId = ::chip::NodeId;
using PeerId = ::chip::PeerId;
using PeerAddress = ::chip::Transport::PeerAddress;
static constexpr uint16_t kMaxGroupsPerFabric = 50;
static constexpr uint16_t kMaxGroupKeysPerFabric = 25;
CHIPCommand(const char * commandName, CredentialIssuerCommands * credIssuerCmds, const char * helpText = nullptr) :
Command(commandName, helpText), mCredIssuerCmds(credIssuerCmds)
{
AddArgument("paa-trust-store-path", &mPaaTrustStorePath,
"Path to directory holding PAA certificate information. Can be absolute or relative to the current working "
"directory.");
AddArgument("cd-trust-store-path", &mCDTrustStorePath,
"Path to directory holding CD certificate information. Can be absolute or relative to the current working "
"directory.");
AddArgument("commissioner-name", &mCommissionerName,
"Name of fabric to use. Valid values are \"alpha\", \"beta\", \"gamma\", and integers greater than or equal to "
"4. The default if not specified is \"alpha\".");
AddArgument("commissioner-nodeid", 0, UINT64_MAX, &mCommissionerNodeId,
"The node id to use for chip-tool. If not provided, kTestControllerNodeId (112233, 0x1B669) will be used.");
AddArgument("use-max-sized-certs", 0, 1, &mUseMaxSizedCerts,
"Maximize the size of operational certificates. If not provided or 0 (\"false\"), normally sized operational "
"certificates are generated.");
AddArgument("only-allow-trusted-cd-keys", 0, 1, &mOnlyAllowTrustedCdKeys,
"Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD "
"verifying keys are allowed. If 1 (\"true\"), test keys are disallowed.");
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
AddArgument("trace_file", &mTraceFile);
AddArgument("trace_log", 0, 1, &mTraceLog);
AddArgument("trace_decode", 0, 1, &mTraceDecode);
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
AddArgument("trace-to", &mTraceTo, "Trace destinations, comma-separated (" SUPPORTED_COMMAND_LINE_TRACING_TARGETS ")");
AddArgument("ble-adapter", 0, UINT16_MAX, &mBleAdapterId);
AddArgument("storage-directory", &mStorageDirectory,
"Directory to place chip-tool's storage files in. Defaults to $TMPDIR, with fallback to /tmp");
AddArgument(
"commissioner-vendor-id", 0, UINT16_MAX, &mCommissionerVendorId,
"The vendor id to use for chip-tool. If not provided, chip::VendorId::TestVendor1 (65521, 0xFFF1) will be used.");
}
/////////// Command Interface /////////
CHIP_ERROR Run() override;
void SetCommandExitStatus(CHIP_ERROR status)
{
mCommandExitStatus = status;
// In interactive mode the stack is not shut down once a command is ended.
// That means calling `ErrorStr(err)` from the main thread when command
// completion is signaled may race since `ErrorStr` uses a static sErrorStr
// buffer for computing the error string. Call it here instead.
if (IsInteractive() && CHIP_NO_ERROR != status)
{
ChipLogError(chipTool, "Run command failure: %s", chip::ErrorStr(status));
}
StopWaiting();
}
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. After a Shutdown call the command object is ready
// to be used for another command invocation.
virtual void Shutdown() { ResetArguments(); }
// 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 false; }
// If true, the controller will be created with server capabilities enabled,
// such as advertising operational nodes over DNS-SD and accepting incoming
// CASE sessions.
virtual bool NeedsOperationalAdvertising() { return mAdvertiseOperational; }
// Execute any deferred cleanups. Used when exiting interactive mode.
static void ExecuteDeferredCleanups(intptr_t ignored);
#ifdef CONFIG_USE_LOCAL_STORAGE
PersistentStorage mDefaultStorage;
// TODO: It's pretty weird that we re-init mCommissionerStorage for every
// identity without shutting it down or something in between...
PersistentStorage mCommissionerStorage;
#endif // CONFIG_USE_LOCAL_STORAGE
chip::PersistentStorageOperationalKeystore mOperationalKeystore;
chip::Credentials::PersistentStorageOpCertStore mOpCertStore;
static chip::Crypto::RawKeySessionKeystore sSessionKeystore;
static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
static chip::app::DefaultICDClientStorage sICDClientStorage;
static ChipToolCheckInDelegate sCheckInDelegate;
static chip::app::CheckInHandler sCheckInHandler;
CredentialIssuerCommands * mCredIssuerCmds;
std::string GetIdentity();
CHIP_ERROR GetIdentityNodeId(std::string identity, chip::NodeId * nodeId);
CHIP_ERROR GetIdentityRootCertificate(std::string identity, chip::ByteSpan & span);
void SetIdentity(const char * name);
// This method returns the commissioner instance to be used for running the command.
// The default commissioner instance name is "alpha", but it can be overridden by passing
// --identity "instance name" when running a command.
ChipDeviceCommissioner & CurrentCommissioner();
ChipDeviceCommissioner & GetCommissioner(std::string identity);
static void RegisterOnCheckInCompleteCallback(CheckInCompleteCallback * handler);
static void UnregisterOnCheckInCompleteCallback(CheckInCompleteCallback * handler);
private:
CHIP_ERROR MaybeSetUpStack();
void MaybeTearDownStack();
CHIP_ERROR EnsureCommissionerForIdentity(std::string identity);
// Commissioners are keyed by name and local node id.
struct CommissionerIdentity
{
bool operator<(const CommissionerIdentity & other) const
{
return mName < other.mName || (mName == other.mName && mLocalNodeId < other.mLocalNodeId);
}
std::string mName;
chip::NodeId mLocalNodeId;
uint8_t mRCAC[chip::Controller::kMaxCHIPDERCertLength] = {};
uint8_t mICAC[chip::Controller::kMaxCHIPDERCertLength] = {};
uint8_t mNOC[chip::Controller::kMaxCHIPDERCertLength] = {};
size_t mRCACLen;
size_t mICACLen;
size_t mNOCLen;
};
// InitializeCommissioner uses various members, so can't be static. This is
// obviously a little odd, since the commissioners are then shared across
// multiple commands in interactive mode...
CHIP_ERROR InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId);
void ShutdownCommissioner(const CommissionerIdentity & key);
chip::FabricId CurrentCommissionerId();
static std::map<CommissionerIdentity, std::unique_ptr<ChipDeviceCommissioner>> mCommissioners;
static std::set<CHIPCommand *> sDeferredCleanups;
chip::Optional<char *> mCommissionerName;
chip::Optional<chip::NodeId> mCommissionerNodeId;
chip::Optional<chip::VendorId> mCommissionerVendorId;
chip::Optional<uint16_t> mBleAdapterId;
chip::Optional<char *> mPaaTrustStorePath;
chip::Optional<char *> mCDTrustStorePath;
chip::Optional<bool> mUseMaxSizedCerts;
chip::Optional<bool> mOnlyAllowTrustedCdKeys;
// Cached trust store so commands other than the original startup command
// can spin up commissioners as needed.
static const chip::Credentials::AttestationTrustStore * sTrustStore;
static void RunQueuedCommand(intptr_t commandArg);
typedef decltype(RunQueuedCommand) MatterWorkCallback;
static void RunCommandCleanup(intptr_t commandArg);
// Do cleanup after a commmand is done running. Must happen with the
// Matter stack locked.
void CleanupAfterRun();
// Run the given callback on the Matter thread. Return whether we managed
// to successfully dispatch it to the Matter thread. If we did, *timedOut
// will be set to whether we timed out or whether our mWaitingForResponse
// got set to false by the callback itself.
CHIP_ERROR RunOnMatterQueue(MatterWorkCallback callback, chip::System::Clock::Timeout timeout, bool * timedOut);
CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL;
CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds);
void StopWaiting();
#if CONFIG_USE_SEPARATE_EVENTLOOP
std::condition_variable cvWaitingForResponse;
std::mutex cvWaitingForResponseMutex;
bool mWaitingForResponse{ true };
#endif // CONFIG_USE_SEPARATE_EVENTLOOP
void StartTracing();
void StopTracing();
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
chip::Optional<char *> mTraceFile;
chip::Optional<bool> mTraceLog;
chip::Optional<bool> mTraceDecode;
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
chip::CommandLineApp::TracingSetup mTracingSetup;
chip::Optional<std::vector<std::string>> mTraceTo;
};