• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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