1 /*
2 * Copyright (c) 2016, The OpenThread Authors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /**
30 * @file
31 * This file contains definitions for the CLI interpreter.
32 */
33
34 #ifndef CLI_HPP_
35 #define CLI_HPP_
36
37 #include "openthread-core-config.h"
38
39 #include "cli_config.h"
40
41 #include <stdarg.h>
42
43 #include <openthread/cli.h>
44 #include <openthread/dataset.h>
45 #include <openthread/dns_client.h>
46 #include <openthread/instance.h>
47 #include <openthread/ip6.h>
48 #include <openthread/link.h>
49 #include <openthread/logging.h>
50 #include <openthread/netdata.h>
51 #include <openthread/ping_sender.h>
52 #include <openthread/sntp.h>
53 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
54 #include <openthread/tcp.h>
55 #endif
56 #include <openthread/thread.h>
57 #include <openthread/thread_ftd.h>
58 #include <openthread/udp.h>
59
60 #include "cli/cli_commissioner.hpp"
61 #include "cli/cli_dataset.hpp"
62 #include "cli/cli_history.hpp"
63 #include "cli/cli_joiner.hpp"
64 #include "cli/cli_network_data.hpp"
65 #include "cli/cli_output.hpp"
66 #include "cli/cli_srp_client.hpp"
67 #include "cli/cli_srp_server.hpp"
68 #include "cli/cli_tcp.hpp"
69 #include "cli/cli_udp.hpp"
70 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
71 #include "cli/cli_coap.hpp"
72 #endif
73 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
74 #include "cli/cli_coap_secure.hpp"
75 #endif
76
77 #include "common/code_utils.hpp"
78 #include "common/debug.hpp"
79 #include "common/instance.hpp"
80 #include "common/type_traits.hpp"
81
82 namespace ot {
83
84 /**
85 * @namespace ot::Cli
86 *
87 * @brief
88 * This namespace contains definitions for the CLI interpreter.
89 *
90 */
91 namespace Cli {
92
93 extern "C" void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
94 extern "C" void otCliAppendResult(otError aError);
95 extern "C" void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
96 extern "C" void otCliOutputFormat(const char *aFmt, ...);
97
98 /**
99 * This class implements the CLI interpreter.
100 *
101 */
102 class Interpreter : public Output
103 {
104 #if OPENTHREAD_FTD || OPENTHREAD_MTD
105 friend class Commissioner;
106 friend class Joiner;
107 friend class NetworkData;
108 friend class SrpClient;
109 #endif
110 friend void otCliPlatLogv(otLogLevel, otLogRegion, const char *, va_list);
111 friend void otCliAppendResult(otError aError);
112 friend void otCliOutputBytes(const uint8_t *aBytes, uint8_t aLength);
113 friend void otCliOutputFormat(const char *aFmt, ...);
114
115 public:
116 typedef Utils::CmdLineParser::Arg Arg;
117
118 /**
119 * Constructor
120 *
121 * @param[in] aInstance The OpenThread instance structure.
122 * @param[in] aCallback A callback method called to process CLI output.
123 * @param[in] aContext A user context pointer.
124 */
125 explicit Interpreter(Instance *aInstance, otCliOutputCallback aCallback, void *aContext);
126
127 /**
128 * This method returns a reference to the interpreter object.
129 *
130 * @returns A reference to the interpreter object.
131 *
132 */
GetInterpreter(void)133 static Interpreter &GetInterpreter(void)
134 {
135 OT_ASSERT(sInterpreter != nullptr);
136
137 return *sInterpreter;
138 }
139
140 /**
141 * This method initializes the Console interpreter.
142 *
143 * @param[in] aInstance The OpenThread instance structure.
144 * @param[in] aCallback A pointer to a callback method.
145 * @param[in] aContext A pointer to a user context.
146 *
147 */
148 static void Initialize(otInstance *aInstance, otCliOutputCallback aCallback, void *aContext);
149
150 /**
151 * This method returns whether the interpreter is initialized.
152 *
153 * @returns Whether the interpreter is initialized.
154 *
155 */
IsInitialized(void)156 static bool IsInitialized(void) { return sInterpreter != nullptr; }
157
158 /**
159 * This method interprets a CLI command.
160 *
161 * @param[in] aBuf A pointer to a string.
162 *
163 */
164 void ProcessLine(char *aBuf);
165
166 /**
167 * This static method checks a given argument string against "enable" or "disable" commands.
168 *
169 * @param[in] aArg The argument string to parse.
170 * @param[out] aEnable Boolean variable to return outcome on success.
171 * Set to TRUE for "enable" command, and FALSE for "disable" command.
172 *
173 * @retval OT_ERROR_NONE Successfully parsed the @p aString and updated @p aEnable.
174 * @retval OT_ERROR_INVALID_COMMAND The @p aString is not "enable" or "disable" command.
175 *
176 */
177 static otError ParseEnableOrDisable(const Arg &aArg, bool &aEnable);
178
179 /**
180 * This method sets the user command table.
181 *
182 * @param[in] aCommands A pointer to an array with user commands.
183 * @param[in] aLength @p aUserCommands length.
184 * @param[in] aContext @p aUserCommands length.
185 *
186 */
187 void SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext);
188
189 static constexpr uint8_t kLinkModeStringSize = sizeof("rdn"); ///< Size of string buffer for a MLE Link Mode.
190
191 /**
192 * This method converts a given MLE Link Mode to flag string.
193 *
194 * The characters 'r', 'd', and 'n' are respectively used for `mRxOnWhenIdle`, `mDeviceType` and `mNetworkData`
195 * flags. If all flags are `false`, then "-" is returned.
196 *
197 * @param[in] aLinkMode The MLE Link Mode to convert.
198 * @param[out] aStringBuffer A reference to an string array to place the string.
199 *
200 * @returns A pointer @p aStringBuffer which contains the converted string.
201 *
202 */
203 static const char *LinkModeToString(const otLinkModeConfig &aLinkMode, char (&aStringBuffer)[kLinkModeStringSize]);
204
205 /**
206 * This method converts an IPv6 address origin `OT_ADDRESS_ORIGIN_*` value to human-readable string.
207 *
208 * @param[in] aOrigin The IPv6 address origin to convert.
209 *
210 * @returns A human-readable string representation of @p aOrigin.
211 *
212 */
213 static const char *AddressOriginToString(uint8_t aOrigin);
214
215 /**
216 * This static method parses a given argument string as a route preference comparing it against "high", "med", or
217 * "low".
218 *
219 * @param[in] aArg The argument string to parse.
220 * @param[out] aPreference Reference to a `otRoutePreference` to return the parsed preference.
221 *
222 * @retval OT_ERROR_NONE Successfully parsed @p aArg and updated @p aPreference.
223 * @retval OT_ERROR_INVALID_ARG @p aArg is not a valid preference string "high", "med", or "low".
224 *
225 */
226 static otError ParsePreference(const Arg &aArg, otRoutePreference &aPreference);
227
228 /**
229 * This static method converts a route preference value to human-readable string.
230 *
231 * @param[in] aPreference The preference value to convert (`OT_ROUTE_PREFERENCE_*` values).
232 *
233 * @returns A string representation @p aPreference.
234 *
235 */
236 static const char *PreferenceToString(signed int aPreference);
237
238 protected:
239 static Interpreter *sInterpreter;
240
241 private:
242 enum
243 {
244 kIndentSize = 4,
245 kMaxArgs = 32,
246 kMaxAutoAddresses = 8,
247 kMaxLineLength = OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH,
248 };
249
250 static constexpr uint32_t kNetworkDiagnosticTimeoutMsecs = 5000;
251 static constexpr uint32_t kLocateTimeoutMsecs = 2500;
252
253 using Command = CommandEntry<Interpreter>;
254
255 template <typename ValueType> using GetHandler = ValueType (&)(otInstance *);
256 template <typename ValueType> using SetHandler = void (&)(otInstance *, ValueType);
257 template <typename ValueType> using SetHandlerFailable = otError (&)(otInstance *, ValueType);
258
259 // Returns format string to output a `ValueType` (e.g., "%u" for `uint16_t`).
260 template <typename ValueType> static constexpr const char *FormatStringFor(void);
261
ProcessGet(Arg aArgs[],GetHandler<ValueType> aGetHandler)262 template <typename ValueType> otError ProcessGet(Arg aArgs[], GetHandler<ValueType> aGetHandler)
263 {
264 static_assert(
265 TypeTraits::IsSame<ValueType, uint8_t>::kValue || TypeTraits::IsSame<ValueType, uint16_t>::kValue ||
266 TypeTraits::IsSame<ValueType, uint32_t>::kValue || TypeTraits::IsSame<ValueType, int8_t>::kValue ||
267 TypeTraits::IsSame<ValueType, int16_t>::kValue || TypeTraits::IsSame<ValueType, int32_t>::kValue,
268 "ValueType must be an 8, 16, or 32 bit `int` or `uint` type");
269
270 otError error = OT_ERROR_NONE;
271
272 VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
273 OutputLine(FormatStringFor<ValueType>(), aGetHandler(GetInstancePtr()));
274
275 exit:
276 return error;
277 }
278
ProcessSet(Arg aArgs[],SetHandler<ValueType> aSetHandler)279 template <typename ValueType> otError ProcessSet(Arg aArgs[], SetHandler<ValueType> aSetHandler)
280 {
281 otError error;
282 ValueType value;
283
284 SuccessOrExit(error = aArgs[0].ParseAs<ValueType>(value));
285 VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
286
287 aSetHandler(GetInstancePtr(), value);
288
289 exit:
290 return error;
291 }
292
ProcessSet(Arg aArgs[],SetHandlerFailable<ValueType> aSetHandler)293 template <typename ValueType> otError ProcessSet(Arg aArgs[], SetHandlerFailable<ValueType> aSetHandler)
294 {
295 otError error;
296 ValueType value;
297
298 SuccessOrExit(error = aArgs[0].ParseAs<ValueType>(value));
299 VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
300
301 error = aSetHandler(GetInstancePtr(), value);
302
303 exit:
304 return error;
305 }
306
307 template <typename ValueType>
ProcessGetSet(Arg aArgs[],GetHandler<ValueType> aGetHandler,SetHandler<ValueType> aSetHandler)308 otError ProcessGetSet(Arg aArgs[], GetHandler<ValueType> aGetHandler, SetHandler<ValueType> aSetHandler)
309 {
310 otError error = ProcessGet(aArgs, aGetHandler);
311
312 VerifyOrExit(error != OT_ERROR_NONE);
313 error = ProcessSet(aArgs, aSetHandler);
314
315 exit:
316 return error;
317 }
318
319 template <typename ValueType>
ProcessGetSet(Arg aArgs[],GetHandler<ValueType> aGetHandler,SetHandlerFailable<ValueType> aSetHandler)320 otError ProcessGetSet(Arg aArgs[], GetHandler<ValueType> aGetHandler, SetHandlerFailable<ValueType> aSetHandler)
321 {
322 otError error = ProcessGet(aArgs, aGetHandler);
323
324 VerifyOrExit(error != OT_ERROR_NONE);
325 error = ProcessSet(aArgs, aSetHandler);
326
327 exit:
328 return error;
329 }
330
331 void OutputPrompt(void);
332 void OutputResult(otError aError);
333
334 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
335 otError ParsePingInterval(const Arg &aArg, uint32_t &aInterval);
336 #endif
337 static otError ParseJoinerDiscerner(Arg &aArg, otJoinerDiscerner &aDiscerner);
338 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
339 static otError ParsePrefix(Arg aArgs[], otBorderRouterConfig &aConfig);
340 static otError ParseRoute(Arg aArgs[], otExternalRouteConfig &aConfig);
341 #endif
342
343 otError ProcessCommand(Arg aArgs[]);
344
345 template <CommandId kCommandId> otError Process(Arg aArgs[]);
346
347 otError ProcessUserCommands(Arg aArgs[]);
348
349 #if OPENTHREAD_FTD || OPENTHREAD_MTD
350
351 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
352 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
353 otError ProcessBackboneRouterLocal(Arg aArgs[]);
354 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
355 otError ProcessBackboneRouterMgmtMlr(Arg aArgs[]);
356 void PrintMulticastListenersTable(void);
357 #endif
358 #endif
359 #endif
360
361 #if OPENTHREAD_FTD
362 void OutputEidCacheEntry(const otCacheEntryInfo &aEntry);
363 #endif
364 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
365 otError ProcessLinkMetricsQuery(Arg aArgs[]);
366 otError ProcessLinkMetricsMgmt(Arg aArgs[]);
367 otError ProcessLinkMetricsProbe(Arg aArgs[]);
368 otError ParseLinkMetricsFlags(otLinkMetrics &aLinkMetrics, const Arg &aFlags);
369 #endif
370 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
371 static void HandleLocateResult(void * aContext,
372 otError aError,
373 const otIp6Address *aMeshLocalAddress,
374 uint16_t aRloc16);
375 void HandleLocateResult(otError aError, const otIp6Address *aMeshLocalAddress, uint16_t aRloc16);
376 #endif
377 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
378 static void HandleMlrRegResult(void * aContext,
379 otError aError,
380 uint8_t aMlrStatus,
381 const otIp6Address *aFailedAddresses,
382 uint8_t aFailedAddressNum);
383 void HandleMlrRegResult(otError aError,
384 uint8_t aMlrStatus,
385 const otIp6Address *aFailedAddresses,
386 uint8_t aFailedAddressNum);
387 #endif
388 #if OPENTHREAD_CONFIG_MULTI_RADIO
389 void OutputMultiRadioInfo(const otMultiRadioNeighborInfo &aMultiRadioInfo);
390 #endif
391
392 #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
393 void PrintMacFilter(void);
394 otError ProcessMacFilterAddress(Arg aArgs[]);
395 otError ProcessMacFilterRss(Arg aArgs[]);
396 void OutputMacFilterEntry(const otMacFilterEntry &aEntry);
397 static const char *MacFilterAddressModeToString(otMacFilterAddressMode aMode);
398 #endif
399
400 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
401 static void HandlePingReply(const otPingSenderReply *aReply, void *aContext);
402 static void HandlePingStatistics(const otPingSenderStatistics *aStatistics, void *aContext);
403 #endif
404 static void HandleActiveScanResult(otActiveScanResult *aResult, void *aContext);
405 static void HandleEnergyScanResult(otEnergyScanResult *aResult, void *aContext);
406 static void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx, void *aContext);
407
408 #if OPENTHREAD_FTD || (OPENTHREAD_MTD && OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE)
409 void HandleDiagnosticGetResponse(otError aError, const otMessage *aMessage, const Ip6::MessageInfo *aMessageInfo);
410 static void HandleDiagnosticGetResponse(otError aError,
411 otMessage * aMessage,
412 const otMessageInfo *aMessageInfo,
413 void * aContext);
414
415 void OutputMode(uint8_t aIndentSize, const otLinkModeConfig &aMode);
416 void OutputConnectivity(uint8_t aIndentSize, const otNetworkDiagConnectivity &aConnectivity);
417 void OutputRoute(uint8_t aIndentSize, const otNetworkDiagRoute &aRoute);
418 void OutputRouteData(uint8_t aIndentSize, const otNetworkDiagRouteData &aRouteData);
419 void OutputLeaderData(uint8_t aIndentSize, const otLeaderData &aLeaderData);
420 void OutputNetworkDiagMacCounters(uint8_t aIndentSize, const otNetworkDiagMacCounters &aMacCounters);
421 void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
422 #endif
423
424 #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE
425 otError GetDnsConfig(Arg aArgs[], otDnsQueryConfig *&aConfig);
426 static void HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse, void *aContext);
427 void HandleDnsAddressResponse(otError aError, const otDnsAddressResponse *aResponse);
428 #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE
429 void OutputDnsServiceInfo(uint8_t aIndentSize, const otDnsServiceInfo &aServiceInfo);
430 static void HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse, void *aContext);
431 void HandleDnsBrowseResponse(otError aError, const otDnsBrowseResponse *aResponse);
432 static void HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse, void *aContext);
433 void HandleDnsServiceResponse(otError aError, const otDnsServiceResponse *aResponse);
434 #endif
435 #endif
436
437 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
438 static void HandleSntpResponse(void *aContext, uint64_t aTime, otError aResult);
439 #endif
440
441 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
442 void HandlePingReply(const otPingSenderReply *aReply);
443 void HandlePingStatistics(const otPingSenderStatistics *aStatistics);
444 #endif
445 void HandleActiveScanResult(otActiveScanResult *aResult);
446 void HandleEnergyScanResult(otEnergyScanResult *aResult);
447 void HandleLinkPcapReceive(const otRadioFrame *aFrame, bool aIsTx);
448 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
449 void HandleSntpResponse(uint64_t aTime, otError aResult);
450 #endif
451 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
452 void PrintLinkMetricsValue(const otLinkMetricsValues *aMetricsValues);
453
454 static void HandleLinkMetricsReport(const otIp6Address * aAddress,
455 const otLinkMetricsValues *aMetricsValues,
456 uint8_t aStatus,
457 void * aContext);
458
459 void HandleLinkMetricsReport(const otIp6Address * aAddress,
460 const otLinkMetricsValues *aMetricsValues,
461 uint8_t aStatus);
462
463 static void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, uint8_t aStatus, void *aContext);
464
465 void HandleLinkMetricsMgmtResponse(const otIp6Address *aAddress, uint8_t aStatus);
466
467 static void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
468 const otExtAddress * aExtAddress,
469 const otLinkMetricsValues *aMetricsValues,
470 void * aContext);
471
472 void HandleLinkMetricsEnhAckProbingIe(otShortAddress aShortAddress,
473 const otExtAddress * aExtAddress,
474 const otLinkMetricsValues *aMetricsValues);
475
476 const char *LinkMetricsStatusToStr(uint8_t aStatus);
477 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
478
479 static void HandleDetachGracefullyResult(void *aContext);
480 void HandleDetachGracefullyResult(void);
481
HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo * aInfo,void * aContext)482 static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext)
483 {
484 static_cast<Interpreter *>(aContext)->HandleDiscoveryRequest(*aInfo);
485 }
486 void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo);
487
488 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
489
490 void SetCommandTimeout(uint32_t aTimeoutMilli);
491
492 static void HandleTimer(Timer &aTimer);
493 void HandleTimer(void);
494
495 const otCliCommand *mUserCommands;
496 uint8_t mUserCommandsLength;
497 void * mUserCommandsContext;
498 bool mCommandIsPending;
499
500 TimerMilliContext mTimer;
501
502 #if OPENTHREAD_FTD || OPENTHREAD_MTD
503 #if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
504 bool mSntpQueryingInProgress;
505 #endif
506
507 Dataset mDataset;
508 NetworkData mNetworkData;
509 UdpExample mUdp;
510
511 #if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
512 TcpExample mTcp;
513 #endif
514
515 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
516 Coap mCoap;
517 #endif
518
519 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
520 CoapSecure mCoapSecure;
521 #endif
522
523 #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
524 Commissioner mCommissioner;
525 #endif
526
527 #if OPENTHREAD_CONFIG_JOINER_ENABLE
528 Joiner mJoiner;
529 #endif
530
531 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
532 SrpClient mSrpClient;
533 #endif
534
535 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
536 SrpServer mSrpServer;
537 #endif
538
539 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
540 History mHistory;
541 #endif
542 #endif // OPENTHREAD_FTD || OPENTHREAD_MTD
543
544 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
545 bool mPingIsAsync : 1;
546 #endif
547 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
548 bool mLocateInProgress : 1;
549 #endif
550 };
551
552 // Specializations of `FormatStringFor<ValueType>()`
553
FormatStringFor(void)554 template <> inline constexpr const char *Interpreter::FormatStringFor<uint8_t>(void)
555 {
556 return "%u";
557 }
558
FormatStringFor(void)559 template <> inline constexpr const char *Interpreter::FormatStringFor<uint16_t>(void)
560 {
561 return "%u";
562 }
563
FormatStringFor(void)564 template <> inline constexpr const char *Interpreter::FormatStringFor<uint32_t>(void)
565 {
566 return "%u";
567 }
568
FormatStringFor(void)569 template <> inline constexpr const char *Interpreter::FormatStringFor<int8_t>(void)
570 {
571 return "%d";
572 }
573
FormatStringFor(void)574 template <> inline constexpr const char *Interpreter::FormatStringFor<int16_t>(void)
575 {
576 return "%d";
577 }
578
FormatStringFor(void)579 template <> inline constexpr const char *Interpreter::FormatStringFor<int32_t>(void)
580 {
581 return "%d";
582 }
583
584 } // namespace Cli
585 } // namespace ot
586
587 #endif // CLI_HPP_
588