diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 15b1b3351..44561fc5b 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -89,8 +89,17 @@ using ot::Encoding::BigEndian::HostSwap16; using ot::Encoding::BigEndian::HostSwap32; -namespace ot { +using ot::Utils::CmdLineParser::ParseAsBool; +using ot::Utils::CmdLineParser::ParseAsHexString; +using ot::Utils::CmdLineParser::ParseAsInt8; +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsIp6Prefix; +using ot::Utils::CmdLineParser::ParseAsUint16; +using ot::Utils::CmdLineParser::ParseAsUint32; +using ot::Utils::CmdLineParser::ParseAsUint64; +using ot::Utils::CmdLineParser::ParseAsUint8; +namespace ot { namespace Cli { constexpr Interpreter::Command Interpreter::sCommands[]; @@ -146,67 +155,6 @@ Interpreter::Interpreter(Instance *aInstance) #endif } -int Interpreter::Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength, bool aAllowTruncate) -{ - size_t hexLength = strlen(aHex); - const char *hexEnd = aHex + hexLength; - uint8_t * cur = aBin; - uint8_t numChars = hexLength & 1; - uint8_t byte = 0; - int len = 0; - int rval; - - if (!aAllowTruncate) - { - VerifyOrExit((hexLength + 1) / 2 <= aBinLength, rval = -1); - } - - while (aHex < hexEnd) - { - if ('A' <= *aHex && *aHex <= 'F') - { - byte |= 10 + (*aHex - 'A'); - } - else if ('a' <= *aHex && *aHex <= 'f') - { - byte |= 10 + (*aHex - 'a'); - } - else if ('0' <= *aHex && *aHex <= '9') - { - byte |= *aHex - '0'; - } - else - { - ExitNow(rval = -1); - } - - aHex++; - numChars++; - - if (numChars >= 2) - { - numChars = 0; - *cur++ = byte; - byte = 0; - len++; - - if (len == aBinLength) - { - ExitNow(rval = len); - } - } - else - { - byte <<= 4; - } - } - - rval = len; - -exit: - return rval; -} - void Interpreter::OutputResult(otError aError) { switch (aError) @@ -239,59 +187,17 @@ int Interpreter::OutputIp6Address(const otIp6Address &aAddress) HostSwap16(aAddress.mFields.m16[5]), HostSwap16(aAddress.mFields.m16[6]), HostSwap16(aAddress.mFields.m16[7])); } -otError Interpreter::ParseLong(char *aString, long &aLong) -{ - char *endptr; - aLong = strtol(aString, &endptr, 0); - return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS; -} - -otError Interpreter::ParseUnsignedLong(char *aString, unsigned long &aUnsignedLong) -{ - char *endptr; - aUnsignedLong = strtoul(aString, &endptr, 0); - return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS; -} - otError Interpreter::ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aDiscerner) { - otError error = OT_ERROR_NONE; - char * separator = strstr(aString, "/"); - unsigned long length; + otError error = OT_ERROR_NONE; + char * separator = strstr(aString, "/"); VerifyOrExit(separator != nullptr, error = OT_ERROR_NOT_FOUND); - SuccessOrExit(error = ParseUnsignedLong(separator + 1, length)); - VerifyOrExit(length > 0 && length <= 64, error = OT_ERROR_INVALID_ARGS); - - { - char * end; - unsigned long long value = strtoull(aString, &end, 0); - aDiscerner.mValue = value; - VerifyOrExit(end == separator, error = OT_ERROR_INVALID_ARGS); - } - - aDiscerner.mLength = static_cast(length); - -exit: - return error; -} - -otError Interpreter::ParseIp6Prefix(char *aString, otIp6Prefix &aPrefix) -{ - otError error = OT_ERROR_NONE; - char * prefixLengthStr; - unsigned long length; - - prefixLengthStr = strchr(aString, '/'); - VerifyOrExit(prefixLengthStr != nullptr, error = OT_ERROR_INVALID_ARGS); - - *prefixLengthStr++ = '\0'; - - SuccessOrExit(error = otIp6AddressFromString(aString, &aPrefix.mPrefix)); - - SuccessOrExit(error = ParseUnsignedLong(prefixLengthStr, length)); - aPrefix.mLength = static_cast(length); + SuccessOrExit(error = ParseAsUint8(separator + 1, aDiscerner.mLength)); + VerifyOrExit(aDiscerner.mLength > 0 && aDiscerner.mLength <= 64, error = OT_ERROR_INVALID_ARGS); + *separator = '\0'; + error = ParseAsUint64(aString, aDiscerner.mValue); exit: return error; @@ -391,7 +297,7 @@ otError Interpreter::ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]) #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE if (strcmp(aArgs[0], "mgmt") == 0) { - unsigned long value; + uint8_t status; VerifyOrExit(aArgsLength >= 2, error = OT_ERROR_INVALID_COMMAND); @@ -402,16 +308,15 @@ otError Interpreter::ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit((aArgsLength == 3 || aArgsLength == 4), error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseUnsignedLong(aArgs[2], value)); + SuccessOrExit(error = ParseAsUint8(aArgs[2], status)); if (aArgsLength == 4) { - VerifyOrExit(Hex2Bin(aArgs[3], iid.mFields.m8, sizeof(iid)) == sizeof(iid), - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[3], iid.mFields.m8)); mlIid = &iid; } - otBackboneRouterConfigNextDuaRegistrationResponse(mInstance, mlIid, static_cast(value)); + otBackboneRouterConfigNextDuaRegistrationResponse(mInstance, mlIid, status); ExitNow(); } else if (strcmp(aArgs[1], "mlr") == 0) @@ -452,17 +357,16 @@ otError Interpreter::ProcessBackboneRouterMgmtMlr(uint8_t aArgsLength, char **aA } else if (!strcmp(aArgs[1], "add")) { - otIp6Address address; - unsigned long value; - uint32_t timeout = 0; + otIp6Address address; + uint32_t timeout = 0; VerifyOrExit(aArgsLength == 3 || aArgsLength == 4, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[2], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[2], address)); + if (aArgsLength == 4) { - SuccessOrExit(error = ParseUnsignedLong(aArgs[3], value)); - timeout = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[3], timeout)); } error = otBackboneRouterMulticastListenerAdd(mInstance, &address, timeout); @@ -470,12 +374,12 @@ otError Interpreter::ProcessBackboneRouterMgmtMlr(uint8_t aArgsLength, char **aA } else if (!strcmp(aArgs[0], "response")) { - unsigned long value; + uint8_t status; VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); + SuccessOrExit(error = ParseAsUint8(aArgs[1], status)); - otBackboneRouterConfigNextMulticastListenerRegistrationResponse(mInstance, static_cast(value)); + otBackboneRouterConfigNextMulticastListenerRegistrationResponse(mInstance, status); } else { @@ -504,7 +408,6 @@ otError Interpreter::ProcessBackboneRouterLocal(uint8_t aArgsLength, char *aArgs { otError error = OT_ERROR_NONE; otBackboneRouterConfig config; - unsigned long value; if (strcmp(aArgs[0], "disable") == 0) { @@ -522,8 +425,10 @@ otError Interpreter::ProcessBackboneRouterLocal(uint8_t aArgsLength, char *aArgs } else if (aArgsLength == 2) { - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - otBackboneRouterSetRegistrationJitter(mInstance, static_cast(value)); + uint8_t jitter; + + SuccessOrExit(error = ParseAsUint8(aArgs[1], jitter)); + otBackboneRouterSetRegistrationJitter(mInstance, jitter); } } else if (strcmp(aArgs[0], "register") == 0) @@ -564,18 +469,15 @@ otError Interpreter::ProcessBackboneRouterLocal(uint8_t aArgsLength, char *aArgs if (strcmp(aArgs[argCur], "seqno") == 0) { - SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); - config.mSequenceNumber = static_cast(value); + SuccessOrExit(error = ParseAsUint8(aArgs[++argCur], config.mSequenceNumber)); } else if (strcmp(aArgs[argCur], "delay") == 0) { - SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); - config.mReregistrationDelay = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[++argCur], config.mReregistrationDelay)); } else if (strcmp(aArgs[argCur], "timeout") == 0) { - SuccessOrExit(error = ParseUnsignedLong(aArgs[++argCur], value)); - config.mMlrTimeout = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[++argCur], config.mMlrTimeout)); } else { @@ -642,9 +544,7 @@ otError Interpreter::ProcessDua(uint8_t aArgsLength, char *aArgs[]) { otIp6InterfaceIdentifier iid; - VerifyOrExit(Hex2Bin(aArgs[1], iid.mFields.m8, sizeof(otIp6InterfaceIdentifier)) == - sizeof(otIp6InterfaceIdentifier), - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[1], iid.mFields.m8)); SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, &iid)); } break; @@ -687,20 +587,17 @@ otError Interpreter::ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]) otError Interpreter::ProcessCcaThreshold(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; + int8_t cca; if (aArgsLength == 0) { - int8_t cca; - SuccessOrExit(error = otPlatRadioGetCcaEnergyDetectThreshold(mInstance, &cca)); OutputLine("%d dBm", cca); } else { - long value; - - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otPlatRadioSetCcaEnergyDetectThreshold(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsInt8(aArgs[0], cca)); + SuccessOrExit(error = otPlatRadioSetCcaEnergyDetectThreshold(mInstance, cca)); } exit: @@ -710,7 +607,7 @@ exit: otError Interpreter::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; + uint8_t channel; if (aArgsLength == 0) { @@ -741,7 +638,7 @@ otError Interpreter::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) OutputLine("count: %u", otChannelMonitorGetSampleCount(mInstance)); OutputLine("occupancies:"); - for (uint8_t channel = 0; channel < channelNum; channel++) + for (channel = 0; channel < channelNum; channel++) { uint32_t occupancy = 0; @@ -795,46 +692,58 @@ otError Interpreter::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) else if (strcmp(aArgs[1], "change") == 0) { VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - otChannelManagerRequestChannelChange(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[2], channel)); + otChannelManagerRequestChannelChange(mInstance, channel); } #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE else if (strcmp(aArgs[1], "select") == 0) { + bool enable; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - error = otChannelManagerRequestChannelSelect(mInstance, (value != 0) ? true : false); + SuccessOrExit(error = ParseAsBool(aArgs[2], enable)); + error = otChannelManagerRequestChannelSelect(mInstance, enable); } #endif else if (strcmp(aArgs[1], "auto") == 0) { + bool enable; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - otChannelManagerSetAutoChannelSelectionEnabled(mInstance, (value != 0) ? true : false); + SuccessOrExit(error = ParseAsBool(aArgs[2], enable)); + otChannelManagerSetAutoChannelSelectionEnabled(mInstance, enable); } else if (strcmp(aArgs[1], "delay") == 0) { + uint8_t delay; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - error = otChannelManagerSetDelay(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[2], delay)); + error = otChannelManagerSetDelay(mInstance, delay); } else if (strcmp(aArgs[1], "interval") == 0) { + uint32_t interval; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - error = otChannelManagerSetAutoChannelSelectionInterval(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint32(aArgs[2], interval)); + error = otChannelManagerSetAutoChannelSelectionInterval(mInstance, interval); } else if (strcmp(aArgs[1], "supported") == 0) { + uint32_t mask; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - otChannelManagerSetSupportedChannels(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint32(aArgs[2], mask)); + otChannelManagerSetSupportedChannels(mInstance, mask); } else if (strcmp(aArgs[1], "favored") == 0) { + uint32_t mask; + VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - otChannelManagerSetFavoredChannels(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint32(aArgs[2], mask)); + otChannelManagerSetFavoredChannels(mInstance, mask); } else { @@ -844,8 +753,8 @@ otError Interpreter::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) #endif // OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - error = otLinkSetChannel(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[0], channel)); + error = otLinkSetChannel(mInstance, channel); } exit: @@ -857,7 +766,7 @@ otError Interpreter::ProcessChild(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; otChildInfo childInfo; - long value; + uint16_t childId; bool isTable; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); @@ -908,8 +817,8 @@ otError Interpreter::ProcessChild(uint8_t aArgsLength, char *aArgs[]) ExitNow(); } - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otThreadGetChildInfoById(mInstance, static_cast(value), &childInfo)); + SuccessOrExit(error = ParseAsUint16(aArgs[0], childId)); + SuccessOrExit(error = otThreadGetChildInfoById(mInstance, childId, &childInfo)); OutputLine("Child ID: %d", childInfo.mChildId); OutputLine("Rloc: %04x", childInfo.mRloc16); @@ -991,9 +900,9 @@ otError Interpreter::ProcessChildIp(uint8_t aArgsLength, char *aArgs[]) #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE else if (aArgsLength == 2) { - unsigned long value; - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - SuccessOrExit(error = otThreadSetMaxChildIpAddresses(mInstance, static_cast(value))); + uint8_t maxIpAddresses; + SuccessOrExit(error = ParseAsUint8(aArgs[1], maxIpAddresses)); + SuccessOrExit(error = otThreadSetMaxChildIpAddresses(mInstance, maxIpAddresses)); } #endif else @@ -1015,7 +924,6 @@ exit: otError Interpreter::ProcessChildMax(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -1023,8 +931,10 @@ otError Interpreter::ProcessChildMax(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otThreadSetMaxAllowedChildren(mInstance, static_cast(value))); + uint16_t maxChildren; + + SuccessOrExit(error = ParseAsUint16(aArgs[0], maxChildren)); + SuccessOrExit(error = otThreadSetMaxAllowedChildren(mInstance, maxChildren)); } exit: @@ -1035,7 +945,6 @@ exit: otError Interpreter::ProcessChildTimeout(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -1043,8 +952,10 @@ otError Interpreter::ProcessChildTimeout(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - otThreadSetChildTimeout(mInstance, static_cast(value)); + uint32_t timeout; + + SuccessOrExit(error = ParseAsUint32(aArgs[0], timeout)); + otThreadSetChildTimeout(mInstance, timeout); } exit: @@ -1124,7 +1035,6 @@ exit: otError Interpreter::ProcessContextIdReuseDelay(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -1132,8 +1042,10 @@ otError Interpreter::ProcessContextIdReuseDelay(uint8_t aArgsLength, char *aArgs } else { - SuccessOrExit(ParseLong(aArgs[0], value)); - otThreadSetContextIdReuseDelay(mInstance, static_cast(value)); + uint32_t delay; + + SuccessOrExit(error = ParseAsUint32(aArgs[0], delay)); + otThreadSetContextIdReuseDelay(mInstance, delay); } exit: @@ -1232,7 +1144,7 @@ exit: } #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -otError Interpreter::ProcessCsl(uint8_t aArgsLength, char *argv[]) +otError Interpreter::ProcessCsl(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_INVALID_ARGS; @@ -1246,21 +1158,26 @@ otError Interpreter::ProcessCsl(uint8_t aArgsLength, char *argv[]) } else if (aArgsLength == 2) { - long value; + if (strcmp(aArgs[0], "channel") == 0) + { + uint8_t channel; - SuccessOrExit(error = ParseLong(argv[1], value)); + SuccessOrExit(error = ParseAsUint8(aArgs[1], channel)); + SuccessOrExit(error = otLinkCslSetChannel(mInstance, channel)); + } + else if (strcmp(aArgs[0], "period") == 0) + { + uint16_t period; - if (strcmp(argv[0], "channel") == 0) - { - SuccessOrExit(error = otLinkCslSetChannel(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsUint16(aArgs[1], period)); + SuccessOrExit(error = otLinkCslSetPeriod(mInstance, period)); } - else if (strcmp(argv[0], "period") == 0) + else if (strcmp(aArgs[0], "timeout") == 0) { - SuccessOrExit(error = otLinkCslSetPeriod(mInstance, static_cast(value))); - } - else if (strcmp(argv[0], "timeout") == 0) - { - SuccessOrExit(error = otLinkCslSetTimeout(mInstance, static_cast(value))); + uint32_t timeout; + + SuccessOrExit(error = ParseAsUint32(aArgs[1], timeout)); + SuccessOrExit(error = otLinkCslSetTimeout(mInstance, timeout)); } } @@ -1280,9 +1197,9 @@ otError Interpreter::ProcessDelayTimerMin(uint8_t aArgsLength, char *aArgs[]) } else if (aArgsLength == 1) { - unsigned long value; - SuccessOrExit(error = ParseUnsignedLong(aArgs[0], value)); - SuccessOrExit(error = otDatasetSetDelayTimerMinimal(mInstance, static_cast(value * 1000))); + uint32_t delay; + SuccessOrExit(error = ParseAsUint32(aArgs[0], delay)); + SuccessOrExit(error = otDatasetSetDelayTimerMinimal(mInstance, static_cast(delay * 1000))); } else { @@ -1298,14 +1215,14 @@ otError Interpreter::ProcessDiscover(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; uint32_t scanChannels = 0; - long value; if (aArgsLength > 0) { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - VerifyOrExit((0 <= value) && (value < static_cast(sizeof(scanChannels) * CHAR_BIT)), - error = OT_ERROR_INVALID_ARGS); - scanChannels = 1 << value; + uint8_t channel; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], channel)); + VerifyOrExit(channel < sizeof(scanChannels) * CHAR_BIT, error = OT_ERROR_INVALID_ARGS); + scanChannels = 1 << channel; } SuccessOrExit(error = otThreadDiscover(mInstance, scanChannels, OT_PANID_BROADCAST, false, false, @@ -1323,7 +1240,7 @@ exit: otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long port = OT_DNS_DEFAULT_SERVER_PORT; + uint16_t port = OT_DNS_DEFAULT_SERVER_PORT; Ip6::MessageInfo messageInfo; otDnsQuery query; @@ -1339,7 +1256,7 @@ otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 2) { - SuccessOrExit(error = messageInfo.GetPeerAddr().FromString(aArgs[2])); + SuccessOrExit(error = ParseAsIp6Address(aArgs[2], messageInfo.GetPeerAddr())); } else { @@ -1349,10 +1266,10 @@ otError Interpreter::ProcessDns(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 3) { - SuccessOrExit(error = ParseLong(aArgs[3], port)); + SuccessOrExit(error = ParseAsUint16(aArgs[3], port)); } - messageInfo.SetPeerPort(static_cast(port)); + messageInfo.SetPeerPort(port); query.mHostname = mResolvingHostname; query.mMessageInfo = static_cast(&messageInfo); @@ -1457,10 +1374,7 @@ otError Interpreter::ProcessExtAddress(uint8_t aArgsLength, char *aArgs[]) { otExtAddress extAddress; - memset(&extAddress, 0, sizeof(extAddress)); - VerifyOrExit(Hex2Bin(aArgs[0], extAddress.m8, sizeof(extAddress.m8)) == sizeof(extAddress.m8), - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[0], extAddress.m8)); error = otLinkSetExtendedAddress(mInstance, &extAddress); } @@ -1495,9 +1409,9 @@ otError Interpreter::ProcessLog(uint8_t aArgsLength, char *aArgs[]) #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE else if (aArgsLength == 2) { - long level; + uint8_t level; - SuccessOrExit(error = ParseLong(aArgs[1], level)); + SuccessOrExit(error = ParseAsUint8(aArgs[1], level)); SuccessOrExit(error = otLoggingSetLevel(static_cast(level))); } #endif @@ -1536,9 +1450,7 @@ otError Interpreter::ProcessExtPanId(uint8_t aArgsLength, char *aArgs[]) { otExtendedPanId extPanId; - VerifyOrExit(Hex2Bin(aArgs[0], extPanId.m8, sizeof(extPanId)) == sizeof(extPanId), - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[0], extPanId.m8)); error = otThreadSetExtendedPanId(mInstance, &extPanId); } @@ -1570,12 +1482,9 @@ otError Interpreter::ProcessFake(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength == 4, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &destination)); - SuccessOrExit(error = otIp6AddressFromString(aArgs[2], &target)); - VerifyOrExit(Hex2Bin(aArgs[3], mlIid.mFields.m8, sizeof(otIp6InterfaceIdentifier)) == - sizeof(otIp6InterfaceIdentifier), - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsIp6Address(aArgs[1], destination)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[2], target)); + SuccessOrExit(error = ParseAsHexString(aArgs[3], mlIid.mFields.m8)); otThreadSendAddressNotification(mInstance, &destination, &target, &mlIid); } exit: @@ -1622,7 +1531,7 @@ otError Interpreter::ProcessIpAddrAdd(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &aAddress.mAddress)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], aAddress.mAddress)); aAddress.mPrefixLength = 64; aAddress.mPreferred = true; aAddress.mValid = true; @@ -1640,7 +1549,7 @@ otError Interpreter::ProcessIpAddrDel(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], address)); error = otIp6RemoveUnicastAddress(mInstance, &address); exit: @@ -1703,7 +1612,7 @@ otError Interpreter::ProcessIpMulticastAddrAdd(uint8_t aArgsLength, char *aArgs[ VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], address)); error = otIp6SubscribeMulticastAddress(mInstance, &address); exit: @@ -1717,7 +1626,7 @@ otError Interpreter::ProcessIpMulticastAddrDel(uint8_t aArgsLength, char *aArgs[ VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], address)); error = otIp6UnsubscribeMulticastAddress(mInstance, &address); exit: @@ -1798,7 +1707,6 @@ exit: otError Interpreter::ProcessKeySequence(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; VerifyOrExit(aArgsLength == 1 || aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); @@ -1810,8 +1718,10 @@ otError Interpreter::ProcessKeySequence(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[1], value)); - otThreadSetKeySequenceCounter(mInstance, static_cast(value)); + uint32_t counter; + + SuccessOrExit(error = ParseAsUint32(aArgs[1], counter)); + otThreadSetKeySequenceCounter(mInstance, counter); } } else if (strcmp(aArgs[0], "guardtime") == 0) @@ -1822,8 +1732,10 @@ otError Interpreter::ProcessKeySequence(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[1], value)); - otThreadSetKeySwitchGuardTime(mInstance, static_cast(value)); + uint32_t guardTime; + + SuccessOrExit(error = ParseAsUint32(aArgs[1], guardTime)); + otThreadSetKeySwitchGuardTime(mInstance, guardTime); } } else @@ -1858,8 +1770,7 @@ exit: #if OPENTHREAD_FTD otError Interpreter::ProcessLeaderPartitionId(uint8_t aArgsLength, char *aArgs[]) { - otError error = OT_ERROR_NONE; - unsigned long value; + otError error = OT_ERROR_NONE; if (aArgsLength == 0) { @@ -1867,8 +1778,10 @@ otError Interpreter::ProcessLeaderPartitionId(uint8_t aArgsLength, char *aArgs[] } else { - SuccessOrExit(error = ParseUnsignedLong(aArgs[0], value)); - otThreadSetLocalLeaderPartitionId(mInstance, static_cast(value)); + uint32_t partitionId; + + SuccessOrExit(error = ParseAsUint32(aArgs[0], partitionId)); + otThreadSetLocalLeaderPartitionId(mInstance, partitionId); } exit: @@ -1878,7 +1791,6 @@ exit: otError Interpreter::ProcessLeaderWeight(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -1886,8 +1798,10 @@ otError Interpreter::ProcessLeaderWeight(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - otThreadSetLocalLeaderWeight(mInstance, static_cast(value)); + uint8_t weight; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], weight)); + otThreadSetLocalLeaderWeight(mInstance, weight); } exit: @@ -1957,7 +1871,7 @@ otError Interpreter::ProcessLinkMetricsQuery(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength >= 2, OT_NOOP); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], address)); memset(&linkMetrics, 0, sizeof(otLinkMetrics)); @@ -2016,7 +1930,7 @@ otError Interpreter::ProcessPskc(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength == 1) { - VerifyOrExit(Hex2Bin(aArgs[0], pskc.m8, sizeof(pskc)) == sizeof(pskc), error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[0], pskc.m8)); } else if (!strcmp(aArgs[0], "-p")) { @@ -2050,7 +1964,7 @@ otError Interpreter::ProcessMasterKey(uint8_t aArgsLength, char *aArgs[]) { otMasterKey key; - VerifyOrExit(Hex2Bin(aArgs[0], key.m8, sizeof(key.m8)) == OT_MASTER_KEY_SIZE, error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[0], key.m8)); SuccessOrExit(error = otThreadSetMasterKey(mInstance, &key)); } @@ -2091,7 +2005,7 @@ otError Interpreter::ProcessMlrReg(uint8_t aArgsLength, char *aArgs[]) for (i = 0; i < aArgsLength && i < kIPv6AddressesNumMax; i++) { - if (otIp6AddressFromString(aArgs[i], &addresses[i]) != OT_ERROR_NONE) + if (ParseAsIp6Address(aArgs[i], addresses[i]) != OT_ERROR_NONE) { break; } @@ -2102,11 +2016,7 @@ otError Interpreter::ProcessMlrReg(uint8_t aArgsLength, char *aArgs[]) if (i == aArgsLength - 1) { // Parse the last argument as a timeout in seconds - unsigned long value; - - SuccessOrExit(error = ParseUnsignedLong(aArgs[i], value)); - - timeout = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[i], timeout)); } SuccessOrExit(error = otIp6RegisterMulticastListeners(mInstance, addresses, i, @@ -2377,15 +2287,14 @@ otError Interpreter::ProcessService(uint8_t aArgsLength, char *aArgs[]) } else { - long enterpriseNumber; - int length; + uint16_t length; VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[1], enterpriseNumber)); - cfg.mEnterpriseNumber = static_cast(enterpriseNumber); + SuccessOrExit(error = ParseAsUint32(aArgs[1], cfg.mEnterpriseNumber)); - length = Hex2Bin(aArgs[2], cfg.mServiceData, sizeof(cfg.mServiceData)); + length = sizeof(cfg.mServiceData); + SuccessOrExit(error = ParseAsHexString(aArgs[2], length, cfg.mServiceData)); VerifyOrExit(length > 0, error = OT_ERROR_INVALID_ARGS); cfg.mServiceDataLength = static_cast(length); @@ -2393,7 +2302,8 @@ otError Interpreter::ProcessService(uint8_t aArgsLength, char *aArgs[]) { VerifyOrExit(aArgsLength > 3, error = OT_ERROR_INVALID_ARGS); - length = Hex2Bin(aArgs[3], cfg.mServerConfig.mServerData, sizeof(cfg.mServerConfig.mServerData)); + length = sizeof(cfg.mServerConfig.mServerData); + SuccessOrExit(error = ParseAsHexString(aArgs[3], length, cfg.mServerConfig.mServerData)); VerifyOrExit(length > 0, error = OT_ERROR_INVALID_ARGS); cfg.mServerConfig.mServerDataLength = static_cast(length); @@ -2421,7 +2331,6 @@ otError Interpreter::ProcessNetworkData(uint8_t aArgsLength, char *aArgs[]) otError Interpreter::ProcessNetworkIdTimeout(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -2429,8 +2338,10 @@ otError Interpreter::ProcessNetworkIdTimeout(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - otThreadSetNetworkIdTimeout(mInstance, static_cast(value)); + uint8_t timeout; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], timeout)); + otThreadSetNetworkIdTimeout(mInstance, timeout); } exit: @@ -2459,7 +2370,6 @@ exit: otError Interpreter::ProcessNetworkTime(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -2493,11 +2403,14 @@ otError Interpreter::ProcessNetworkTime(uint8_t aArgsLength, char *aArgs[]) } else if (aArgsLength == 2) { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otNetworkTimeSetSyncPeriod(mInstance, static_cast(value))); + uint16_t period; + uint16_t xtalThreshold; - SuccessOrExit(error = ParseLong(aArgs[1], value)); - SuccessOrExit(error = otNetworkTimeSetXtalThreshold(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsUint16(aArgs[0], period)); + ; + SuccessOrExit(error = ParseAsUint16(aArgs[1], xtalThreshold)); + SuccessOrExit(error = otNetworkTimeSetSyncPeriod(mInstance, period)); + SuccessOrExit(error = otNetworkTimeSetXtalThreshold(mInstance, xtalThreshold)); } else { @@ -2512,7 +2425,6 @@ exit: otError Interpreter::ProcessPanId(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -2520,8 +2432,10 @@ otError Interpreter::ProcessPanId(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - error = otLinkSetPanId(mInstance, static_cast(value)); + uint16_t panId; + + SuccessOrExit(error = ParseAsUint16(aArgs[0], panId)); + error = otLinkSetPanId(mInstance, panId); } exit: @@ -2553,7 +2467,6 @@ exit: otError Interpreter::ProcessParentPriority(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -2561,8 +2474,10 @@ otError Interpreter::ProcessParentPriority(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - error = otThreadSetParentPriority(mInstance, static_cast(value)); + int8_t priority; + + SuccessOrExit(error = ParseAsInt8(aArgs[0], priority)); + error = otThreadSetParentPriority(mInstance, priority); } exit: @@ -2613,7 +2528,6 @@ otError Interpreter::ProcessPing(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; uint8_t index = 1; - long value; uint32_t interval; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); @@ -2628,7 +2542,7 @@ otError Interpreter::ProcessPing(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(!mPingTimer.IsRunning(), error = OT_ERROR_BUSY); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &mPingDestAddress)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], mPingDestAddress)); mPingLength = kDefaultPingLength; mPingCount = kDefaultPingCount; @@ -2641,13 +2555,11 @@ otError Interpreter::ProcessPing(uint8_t aArgsLength, char *aArgs[]) switch (index) { case 1: - SuccessOrExit(error = ParseLong(aArgs[index], value)); - mPingLength = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], mPingLength)); break; case 2: - SuccessOrExit(error = ParseLong(aArgs[index], value)); - mPingCount = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], mPingCount)); break; case 3: @@ -2657,9 +2569,7 @@ otError Interpreter::ProcessPing(uint8_t aArgsLength, char *aArgs[]) break; case 4: - SuccessOrExit(error = ParseLong(aArgs[index], value)); - VerifyOrExit(0 <= value && value <= 255, error = OT_ERROR_INVALID_ARGS); - mPingHopLimit = static_cast(value); + SuccessOrExit(error = ParseAsUint8(aArgs[index], mPingHopLimit)); mPingAllowZeroHopLimit = (mPingHopLimit == 0); break; @@ -2726,7 +2636,6 @@ exit: otError Interpreter::ProcessPollPeriod(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -2734,8 +2643,10 @@ otError Interpreter::ProcessPollPeriod(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - error = otLinkSetPollPeriod(mInstance, static_cast(value)); + uint32_t pollPeriod; + + SuccessOrExit(error = ParseAsUint32(aArgs[0], pollPeriod)); + error = otLinkSetPollPeriod(mInstance, pollPeriod); } exit: @@ -2863,7 +2774,7 @@ otError Interpreter::ProcessPrefixAdd(uint8_t aArgsLength, char *aArgs[]) memset(&config, 0, sizeof(otBorderRouterConfig)); - SuccessOrExit(error = ParseIp6Prefix(aArgs[argcur], config.mPrefix)); + SuccessOrExit(error = ParseAsIp6Prefix(aArgs[argcur], config.mPrefix)); argcur++; for (; argcur < aArgsLength; argcur++) @@ -2943,7 +2854,7 @@ otError Interpreter::ProcessPrefixRemove(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseIp6Prefix(aArgs[0], prefix)); + SuccessOrExit(error = ParseAsIp6Prefix(aArgs[0], prefix)); error = otBorderRouterRemoveOnMeshPrefix(mInstance, &prefix); @@ -3004,12 +2915,12 @@ exit: #if OPENTHREAD_FTD otError Interpreter::ProcessPreferRouterId(uint8_t aArgsLength, char *aArgs[]) { - otError error = OT_ERROR_NONE; - unsigned long value; + otError error = OT_ERROR_NONE; + uint8_t routerId; VerifyOrExit(aArgsLength == 1, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseUnsignedLong(aArgs[0], value)); - error = otThreadSetPreferredRouterId(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[0], routerId)); + error = otThreadSetPreferredRouterId(mInstance, routerId); exit: return error; @@ -3041,12 +2952,12 @@ exit: otError Interpreter::ProcessReleaseRouterId(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; + uint8_t routerId; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otThreadReleaseRouterId(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsUint8(aArgs[0], routerId)); + SuccessOrExit(error = otThreadReleaseRouterId(mInstance, routerId)); exit: return error; @@ -3084,7 +2995,7 @@ otError Interpreter::ProcessRouteAdd(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseIp6Prefix(aArgs[argcur], config.mPrefix)); + SuccessOrExit(error = ParseAsIp6Prefix(aArgs[argcur], config.mPrefix)); argcur++; for (; argcur < aArgsLength; argcur++) @@ -3124,7 +3035,7 @@ otError Interpreter::ProcessRouteRemove(uint8_t aArgsLength, char *aArgs[]) VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseIp6Prefix(aArgs[0], prefix)); + SuccessOrExit(error = ParseAsIp6Prefix(aArgs[0], prefix)); error = otBorderRouterRemoveRoute(mInstance, &prefix); @@ -3176,7 +3087,7 @@ otError Interpreter::ProcessRouter(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; otRouterInfo routerInfo; - long value; + uint16_t routerId; bool isTable; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); @@ -3225,8 +3136,8 @@ otError Interpreter::ProcessRouter(uint8_t aArgsLength, char *aArgs[]) ExitNow(); } - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otThreadGetRouterInfo(mInstance, static_cast(value), &routerInfo)); + SuccessOrExit(error = ParseAsUint16(aArgs[0], routerId)); + SuccessOrExit(error = otThreadGetRouterInfo(mInstance, routerId, &routerInfo)); OutputLine("Alloc: %d", routerInfo.mAllocated); @@ -3256,7 +3167,6 @@ exit: otError Interpreter::ProcessRouterDowngradeThreshold(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -3264,8 +3174,10 @@ otError Interpreter::ProcessRouterDowngradeThreshold(uint8_t aArgsLength, char * } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - otThreadSetRouterDowngradeThreshold(mInstance, static_cast(value)); + uint8_t threshold; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], threshold)); + otThreadSetRouterDowngradeThreshold(mInstance, threshold); } exit: @@ -3307,7 +3219,6 @@ exit: otError Interpreter::ProcessRouterSelectionJitter(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -3315,9 +3226,10 @@ otError Interpreter::ProcessRouterSelectionJitter(uint8_t aArgsLength, char *aAr } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - VerifyOrExit(0 < value && value < 256, error = OT_ERROR_INVALID_ARGS); - otThreadSetRouterSelectionJitter(mInstance, static_cast(value)); + uint8_t jitter; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], jitter)); + otThreadSetRouterSelectionJitter(mInstance, jitter); } exit: @@ -3327,7 +3239,6 @@ exit: otError Interpreter::ProcessRouterUpgradeThreshold(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -3335,8 +3246,10 @@ otError Interpreter::ProcessRouterUpgradeThreshold(uint8_t aArgsLength, char *aA } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - otThreadSetRouterUpgradeThreshold(mInstance, static_cast(value)); + uint8_t threshold; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], threshold)); + otThreadSetRouterUpgradeThreshold(mInstance, threshold); } exit: @@ -3350,7 +3263,6 @@ otError Interpreter::ProcessScan(uint8_t aArgsLength, char *aArgs[]) uint32_t scanChannels = 0; uint16_t scanDuration = 0; bool energyScan = false; - long value; if (aArgsLength > 0) { @@ -3360,16 +3272,16 @@ otError Interpreter::ProcessScan(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 1) { - SuccessOrExit(error = ParseLong(aArgs[1], value)); - scanDuration = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[1], scanDuration)); } } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - VerifyOrExit((0 <= value) && (value < static_cast(sizeof(scanChannels) * CHAR_BIT)), - error = OT_ERROR_INVALID_ARGS); - scanChannels = 1 << value; + uint8_t channel; + + SuccessOrExit(error = ParseAsUint8(aArgs[0], channel)); + VerifyOrExit(channel < sizeof(scanChannels) * CHAR_BIT, error = OT_ERROR_INVALID_ARGS); + scanChannels = 1 << channel; } } @@ -3465,7 +3377,7 @@ otError Interpreter::ProcessSingleton(uint8_t aArgsLength, char *aArgs[]) otError Interpreter::ProcessSntp(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long port = OT_SNTP_DEFAULT_SERVER_PORT; + uint16_t port = OT_SNTP_DEFAULT_SERVER_PORT; Ip6::MessageInfo messageInfo; otSntpQuery query; @@ -3477,7 +3389,7 @@ otError Interpreter::ProcessSntp(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 1) { - SuccessOrExit(error = messageInfo.GetPeerAddr().FromString(aArgs[1])); + SuccessOrExit(error = ParseAsIp6Address(aArgs[1], messageInfo.GetPeerAddr())); } else { @@ -3487,10 +3399,10 @@ otError Interpreter::ProcessSntp(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 2) { - SuccessOrExit(error = ParseLong(aArgs[2], port)); + SuccessOrExit(error = ParseAsUint16(aArgs[2], port)); } - messageInfo.SetPeerPort(static_cast(port)); + messageInfo.SetPeerPort(port); query.mMessageInfo = static_cast(&messageInfo); @@ -3635,20 +3547,17 @@ otError Interpreter::ProcessDataset(uint8_t aArgsLength, char *aArgs[]) otError Interpreter::ProcessTxPower(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; + int8_t power; if (aArgsLength == 0) { - int8_t power; - SuccessOrExit(error = otPlatRadioGetTransmitPower(mInstance, &power)); OutputLine("%d dBm", power); } else { - long value; - - SuccessOrExit(error = ParseLong(aArgs[0], value)); - SuccessOrExit(error = otPlatRadioSetTransmitPower(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsInt8(aArgs[0], power)); + SuccessOrExit(error = otPlatRadioSetTransmitPower(mInstance, power)); } exit: @@ -3668,12 +3577,11 @@ otError Interpreter::ProcessUnsecurePort(uint8_t aArgsLength, char *aArgs[]) if (strcmp(aArgs[0], "add") == 0) { - unsigned long value; + uint16_t port; VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - VerifyOrExit(value <= 0xffff, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsUint16(aArgs[1], port)); + SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, port)); } else if (strcmp(aArgs[0], "remove") == 0) { @@ -3685,11 +3593,10 @@ otError Interpreter::ProcessUnsecurePort(uint8_t aArgsLength, char *aArgs[]) } else { - unsigned long value; + uint16_t port; - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - VerifyOrExit(value <= 0xffff, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6RemoveUnsecurePort(mInstance, static_cast(value))); + SuccessOrExit(error = ParseAsUint16(aArgs[1], port)); + SuccessOrExit(error = otIp6RemoveUnsecurePort(mInstance, port)); } } else if (strcmp(aArgs[0], "get") == 0) @@ -3759,7 +3666,6 @@ otError Interpreter::ProcessJoiner(uint8_t aArgsLength, char *aArgs[]) otError Interpreter::ProcessJoinerPort(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; if (aArgsLength == 0) { @@ -3767,8 +3673,10 @@ otError Interpreter::ProcessJoinerPort(uint8_t aArgsLength, char *aArgs[]) } else { - SuccessOrExit(error = ParseLong(aArgs[0], value)); - error = otThreadSetJoinerUdpPort(mInstance, static_cast(value)); + uint16_t port; + + SuccessOrExit(error = ParseAsUint16(aArgs[0], port)); + error = otThreadSetJoinerUdpPort(mInstance, port); } exit: @@ -3870,7 +3778,6 @@ otError Interpreter::ProcessMacFilterAddress(uint8_t aArgsLength, char *aArgs[]) otMacFilterEntry entry; otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT; otMacFilterAddressMode mode = otLinkFilterGetAddressMode(mInstance); - long value; if (aArgsLength == 0) { @@ -3920,27 +3827,24 @@ otError Interpreter::ProcessMacFilterAddress(uint8_t aArgsLength, char *aArgs[]) else if (strcmp(aArgs[0], "add") == 0) { VerifyOrExit(aArgsLength >= 2, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit(Hex2Bin(aArgs[1], extAddr.m8, OT_EXT_ADDRESS_SIZE) == OT_EXT_ADDRESS_SIZE, - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddr.m8)); error = otLinkFilterAddAddress(mInstance, &extAddr); VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY, OT_NOOP); if (aArgsLength > 2) { - int8_t rss = 0; + int8_t rss; + VerifyOrExit(aArgsLength == 3, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - rss = static_cast(value); + SuccessOrExit(error = ParseAsInt8(aArgs[2], rss)); SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, &extAddr, rss)); } } else if (strcmp(aArgs[0], "remove") == 0) { VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit(Hex2Bin(aArgs[1], extAddr.m8, OT_EXT_ADDRESS_SIZE) == OT_EXT_ADDRESS_SIZE, - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddr.m8)); otLinkFilterRemoveAddress(mInstance, &extAddr); } else if (strcmp(aArgs[0], "clear") == 0) @@ -3964,7 +3868,6 @@ otError Interpreter::ProcessMacFilterRss(uint8_t aArgsLength, char *aArgs[]) otMacFilterEntry entry; otMacFilterIterator iterator = OT_MAC_FILTER_ITERATOR_INIT; otExtAddress extAddr; - long value; int8_t rss; if (aArgsLength == 0) @@ -3997,12 +3900,13 @@ otError Interpreter::ProcessMacFilterRss(uint8_t aArgsLength, char *aArgs[]) { if (strcmp(aArgs[0], "add-lqi") == 0) { - uint8_t linkquality = 0; + uint8_t linkQuality; + VerifyOrExit(aArgsLength == 3, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - linkquality = static_cast(value); - VerifyOrExit(linkquality <= 3, error = OT_ERROR_INVALID_ARGS); - rss = otLinkConvertLinkQualityToRss(mInstance, linkquality); + + SuccessOrExit(error = ParseAsUint8(aArgs[2], linkQuality)); + VerifyOrExit(linkQuality <= 3, error = OT_ERROR_INVALID_ARGS); + rss = otLinkConvertLinkQualityToRss(mInstance, linkQuality); if (strcmp(aArgs[1], "*") == 0) { @@ -4010,17 +3914,14 @@ otError Interpreter::ProcessMacFilterRss(uint8_t aArgsLength, char *aArgs[]) } else { - VerifyOrExit(Hex2Bin(aArgs[1], extAddr.m8, OT_EXT_ADDRESS_SIZE) == OT_EXT_ADDRESS_SIZE, - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddr.m8)); SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, &extAddr, rss)); } } else if (strcmp(aArgs[0], "add") == 0) { VerifyOrExit(aArgsLength == 3, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = ParseLong(aArgs[2], value)); - rss = static_cast(value); + SuccessOrExit(error = ParseAsInt8(aArgs[2], rss)); if (strcmp(aArgs[1], "*") == 0) { @@ -4028,9 +3929,7 @@ otError Interpreter::ProcessMacFilterRss(uint8_t aArgsLength, char *aArgs[]) } else { - VerifyOrExit(Hex2Bin(aArgs[1], extAddr.m8, OT_EXT_ADDRESS_SIZE) == OT_EXT_ADDRESS_SIZE, - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddr.m8)); SuccessOrExit(error = otLinkFilterAddRssIn(mInstance, &extAddr, rss)); } } @@ -4044,9 +3943,7 @@ otError Interpreter::ProcessMacFilterRss(uint8_t aArgsLength, char *aArgs[]) } else { - VerifyOrExit(Hex2Bin(aArgs[1], extAddr.m8, OT_EXT_ADDRESS_SIZE) == OT_EXT_ADDRESS_SIZE, - error = OT_ERROR_INVALID_ARGS); - + SuccessOrExit(error = ParseAsHexString(aArgs[1], extAddr.m8)); otLinkFilterRemoveRssIn(mInstance, &extAddr); } } @@ -4099,12 +3996,10 @@ otError Interpreter::ProcessMacRetries(uint8_t aArgsLength, char *aArgs[]) } else { - unsigned long value; + uint8_t retries; - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - VerifyOrExit(value <= 0xff, error = OT_ERROR_INVALID_ARGS); - - otLinkSetMaxFrameRetriesDirect(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[1], retries)); + otLinkSetMaxFrameRetriesDirect(mInstance, retries); } } #if OPENTHREAD_FTD @@ -4116,12 +4011,10 @@ otError Interpreter::ProcessMacRetries(uint8_t aArgsLength, char *aArgs[]) } else { - unsigned long value; + uint8_t retries; - SuccessOrExit(error = ParseUnsignedLong(aArgs[1], value)); - VerifyOrExit(value <= 0xff, error = OT_ERROR_INVALID_ARGS); - - otLinkSetMaxFrameRetriesIndirect(mInstance, static_cast(value)); + SuccessOrExit(error = ParseAsUint8(aArgs[1], retries)); + otLinkSetMaxFrameRetriesIndirect(mInstance, retries); } } #endif @@ -4207,15 +4100,13 @@ otError Interpreter::ProcessNetworkDiagnostic(uint8_t aArgsLength, char *aArgs[] // Include operation, address and type tlv list. VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[1], address)); argsIndex = 2; while (argsIndex < aArgsLength && count < sizeof(tlvTypes)) { - long value; - SuccessOrExit(error = ParseLong(aArgs[argsIndex++], value)); - tlvTypes[count++] = static_cast(value); + SuccessOrExit(error = ParseAsUint8(aArgs[argsIndex++], tlvTypes[count++])); } if (strcmp(aArgs[0], "get") == 0) diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 7ad064ee3..5b060df07 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -126,44 +126,6 @@ public: */ void ProcessLine(char *aBuf, uint16_t aBufLength); - /** - * This method parses an ASCII string as a long. - * - * @param[in] aString A pointer to the ASCII string. - * @param[out] aLong A reference to where the parsed long is placed. - * - * @retval OT_ERROR_NONE Successfully parsed the ASCII string. - * @retval OT_ERROR_INVALID_ARGS @p aString is not a valid long integer. - * - */ - static otError ParseLong(char *aString, long &aLong); - - /** - * This method parses an ASCII string as an unsigned long. - * - * @param[in] aString A pointer to the ASCII string. - * @param[out] aUnsignedLong A reference to where the parsed unsigned long is placed. - * - * @retval OT_ERROR_NONE Successfully parsed the ASCII string. - * @retval OT_ERROR_INVALID_ARGS @p aString is not a valid unsigned long integer. - * - */ - static otError ParseUnsignedLong(char *aString, unsigned long &aUnsignedLong); - - /** - * This method converts a hex string to binary. - * - * @param[in] aHex A pointer to the hex string. - * @param[out] aBin A pointer to where the binary representation is placed. - * @param[in] aBinLength Maximum length of the binary representation. - * @param[in] aAllowTruncate TRUE if @p aBinLength may be less than what is required - * to convert @p aHex to binary representation, FALSE otherwise. - * - * @returns The number of bytes in the binary representation, or -1 if @p aHex is not a valid hex string - * - */ - static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength, bool aAllowTruncate = false); - /** * This method delivers raw characters to the client. * @@ -296,7 +258,6 @@ private: otError ParsePingInterval(const char *aString, uint32_t &aInterval); static otError ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aJoinerDiscerner); - static otError ParseIp6Prefix(char *aString, otIp6Prefix &aPrefix); otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]); otError ProcessCcaThreshold(uint8_t aArgsLength, char *aArgs[]); @@ -343,7 +304,7 @@ private: otError ProcessContextIdReuseDelay(uint8_t aArgsLength, char *aArgs[]); #endif otError ProcessCounters(uint8_t aArgsLength, char *aArgs[]); - otError ProcessCsl(uint8_t aArgsLength, char *argv[]); + otError ProcessCsl(uint8_t aArgsLength, char *aArgs[]); #if OPENTHREAD_FTD otError ProcessDelayTimerMin(uint8_t aArgsLength, char *aArgs[]); #endif diff --git a/src/cli/cli_coap.cpp b/src/cli/cli_coap.cpp index e7c668774..d10617593 100644 --- a/src/cli/cli_coap.cpp +++ b/src/cli/cli_coap.cpp @@ -39,6 +39,11 @@ #include "cli/cli.hpp" #include "coap/coap_message.hpp" +#include "utils/parse_cmdline.hpp" + +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsUint32; +using ot::Utils::CmdLineParser::ParseAsUint8; namespace ot { namespace Cli { @@ -298,24 +303,12 @@ otError Coap::ProcessParameters(uint8_t aArgsLength, char *aArgs[]) } else { - unsigned long value; - VerifyOrExit(aArgsLength >= 6, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[2], value)); - txParameters->mAckTimeout = static_cast(value); - - SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[3], value)); - VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS); - txParameters->mAckRandomFactorNumerator = static_cast(value); - - SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[4], value)); - VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS); - txParameters->mAckRandomFactorDenominator = static_cast(value); - - SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[5], value)); - VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS); - txParameters->mMaxRetransmit = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[2], txParameters->mAckTimeout)); + SuccessOrExit(error = ParseAsUint8(aArgs[3], txParameters->mAckRandomFactorNumerator)); + SuccessOrExit(error = ParseAsUint8(aArgs[4], txParameters->mAckRandomFactorDenominator)); + SuccessOrExit(error = ParseAsUint8(aArgs[5], txParameters->mMaxRetransmit)); VerifyOrExit(txParameters->mAckRandomFactorNumerator > txParameters->mAckRandomFactorDenominator, error = OT_ERROR_INVALID_ARGS); @@ -391,7 +384,7 @@ otError Coap::ProcessRequest(uint8_t aArgsLength, char *aArgs[]) // Destination IPv6 address if (aArgsLength > 1) { - SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &coapDestinationIp)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[1], coapDestinationIp)); } else { diff --git a/src/cli/cli_coap_secure.cpp b/src/cli/cli_coap_secure.cpp index 7caa20e76..0f60e7251 100644 --- a/src/cli/cli_coap_secure.cpp +++ b/src/cli/cli_coap_secure.cpp @@ -39,9 +39,14 @@ #include #include "cli/cli.hpp" +#include "utils/parse_cmdline.hpp" + // header for place your x509 certificate and private key #include "x509_cert_key.hpp" +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsUint16; + namespace ot { namespace Cli { @@ -234,7 +239,7 @@ otError CoapSecure::ProcessRequest(uint8_t aArgsLength, char *aArgs[]) // Destination IPv6 address if (aArgsLength > 1) { - error = otIp6AddressFromString(aArgs[1], &coapDestinationIp); + error = ParseAsIp6Address(aArgs[1], coapDestinationIp); } else { @@ -322,17 +327,13 @@ otError CoapSecure::ProcessConnect(uint8_t aArgsLength, char *aArgs[]) // Destination IPv6 address memset(&sockaddr, 0, sizeof(sockaddr)); - SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &sockaddr.mAddress)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[1], sockaddr.mAddress)); sockaddr.mPort = OT_DEFAULT_COAP_SECURE_PORT; // check for port specification if (aArgsLength > 2) { - long value; - - error = Interpreter::ParseLong(aArgs[2], value); - SuccessOrExit(error); - sockaddr.mPort = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[2], sockaddr.mPort)); } SuccessOrExit(error = otCoapSecureConnect(mInterpreter.mInstance, &sockaddr, &CoapSecure::HandleConnected, this)); diff --git a/src/cli/cli_commissioner.cpp b/src/cli/cli_commissioner.cpp index 59725a69f..14b28f1b6 100644 --- a/src/cli/cli_commissioner.cpp +++ b/src/cli/cli_commissioner.cpp @@ -34,6 +34,13 @@ #include "cli_commissioner.hpp" #include "cli/cli.hpp" +#include "utils/parse_cmdline.hpp" + +using ot::Utils::CmdLineParser::ParseAsHexString; +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsUint16; +using ot::Utils::CmdLineParser::ParseAsUint32; +using ot::Utils::CmdLineParser::ParseAsUint8; #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD @@ -58,21 +65,19 @@ otError Commissioner::ProcessHelp(uint8_t aArgsLength, char *aArgs[]) otError Commissioner::ProcessAnnounce(uint8_t aArgsLength, char *aArgs[]) { otError error; - long mask; - long count; - long period; + uint32_t mask; + uint8_t count; + uint16_t period; otIp6Address address; VerifyOrExit(aArgsLength > 4, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], mask)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], count)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[3], period)); - SuccessOrExit(error = otIp6AddressFromString(aArgs[4], &address)); + SuccessOrExit(error = ParseAsUint32(aArgs[1], mask)); + SuccessOrExit(error = ParseAsUint8(aArgs[2], count)); + SuccessOrExit(error = ParseAsUint16(aArgs[3], period)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[4], address)); - SuccessOrExit(error = otCommissionerAnnounceBegin(mInterpreter.mInstance, static_cast(mask), - static_cast(count), static_cast(period), - &address)); + SuccessOrExit(error = otCommissionerAnnounceBegin(mInterpreter.mInstance, mask, count, period, &address)); exit: return error; @@ -81,23 +86,21 @@ exit: otError Commissioner::ProcessEnergy(uint8_t aArgsLength, char *aArgs[]) { otError error; - long mask; - long count; - long period; - long scanDuration; + uint32_t mask; + uint8_t count; + uint16_t period; + uint16_t scanDuration; otIp6Address address; VerifyOrExit(aArgsLength > 5, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], mask)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], count)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[3], period)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[4], scanDuration)); - SuccessOrExit(error = otIp6AddressFromString(aArgs[5], &address)); + SuccessOrExit(error = ParseAsUint32(aArgs[1], mask)); + SuccessOrExit(error = ParseAsUint8(aArgs[2], count)); + SuccessOrExit(error = ParseAsUint16(aArgs[3], period)); + SuccessOrExit(error = ParseAsUint16(aArgs[4], scanDuration)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[5], address)); - SuccessOrExit(error = otCommissionerEnergyScan(mInterpreter.mInstance, static_cast(mask), - static_cast(count), static_cast(period), - static_cast(scanDuration), &address, + SuccessOrExit(error = otCommissionerEnergyScan(mInterpreter.mInstance, mask, count, period, scanDuration, &address, &Commissioner::HandleEnergyReport, this)); exit: @@ -121,8 +124,7 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[]) } else if ((error = Interpreter::ParseJoinerDiscerner(aArgs[2], discerner)) == OT_ERROR_NOT_FOUND) { - VerifyOrExit(Interpreter::Hex2Bin(aArgs[2], addr.m8, sizeof(addr)) == sizeof(addr), - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[2], addr.m8)); addrPtr = &addr; } else if (error != OT_ERROR_NONE) @@ -134,22 +136,21 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[]) { VerifyOrExit(aArgsLength > 3, error = OT_ERROR_INVALID_ARGS); // Timeout parameter is optional - if not specified, use default value. - unsigned long timeout = kDefaultJoinerTimeout; + uint32_t timeout = kDefaultJoinerTimeout; if (aArgsLength > 4) { - SuccessOrExit(error = Interpreter::ParseUnsignedLong(aArgs[4], timeout)); + SuccessOrExit(error = ParseAsUint32(aArgs[4], timeout)); } if (discerner.mLength) { - SuccessOrExit(error = otCommissionerAddJoinerWithDiscerner(mInterpreter.mInstance, &discerner, aArgs[3], - static_cast(timeout))); + SuccessOrExit( + error = otCommissionerAddJoinerWithDiscerner(mInterpreter.mInstance, &discerner, aArgs[3], timeout)); } else { - SuccessOrExit(error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3], - static_cast(timeout))); + SuccessOrExit(error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3], timeout)); } } else if (strcmp(aArgs[1], "remove") == 0) @@ -174,10 +175,9 @@ exit: otError Commissioner::ProcessMgmtGet(uint8_t aArgsLength, char *aArgs[]) { - otError error; + otError error = OT_ERROR_NONE; uint8_t tlvs[32]; - long value; - int length = 0; + uint8_t length = 0; for (uint8_t index = 1; index < aArgsLength; index++) { @@ -201,13 +201,12 @@ otError Commissioner::ProcessMgmtGet(uint8_t aArgsLength, char *aArgs[]) } else if (strcmp(aArgs[index], "-x") == 0) { + uint16_t readLength; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); - value = static_cast(strlen(aArgs[index]) + 1) / 2; - VerifyOrExit(static_cast(value) <= (sizeof(tlvs) - static_cast(length)), - error = OT_ERROR_NO_BUFS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs + length, static_cast(value)) == value, - error = OT_ERROR_INVALID_ARGS); - length += value; + readLength = static_cast(sizeof(tlvs) - length); + SuccessOrExit(error = ParseAsHexString(aArgs[index], readLength, tlvs + length)); + length += static_cast(readLength); } else { @@ -226,8 +225,7 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[]) otError error; otCommissioningDataset dataset; uint8_t tlvs[32]; - long value; - int length = 0; + uint8_t tlvsLength = 0; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); @@ -235,48 +233,42 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[]) for (uint8_t index = 1; index < aArgsLength; index++) { - VerifyOrExit(static_cast(length) < sizeof(tlvs), error = OT_ERROR_NO_BUFS); - if (strcmp(aArgs[index], "locator") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mIsLocatorSet = true; - SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value)); - dataset.mLocator = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mLocator)); } else if (strcmp(aArgs[index], "sessionid") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mIsSessionIdSet = true; - SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value)); - dataset.mSessionId = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mSessionId)); } else if (strcmp(aArgs[index], "steeringdata") == 0) { + uint16_t length; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mIsSteeringDataSet = true; - length = static_cast((strlen(aArgs[index]) + 1) / 2); - VerifyOrExit(static_cast(length) <= OT_STEERING_DATA_MAX_LENGTH, error = OT_ERROR_NO_BUFS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], dataset.mSteeringData.m8, static_cast(length)) == - length, - error = OT_ERROR_INVALID_ARGS); + length = sizeof(dataset.mSteeringData.m8); + SuccessOrExit(error = ParseAsHexString(aArgs[index], length, dataset.mSteeringData.m8)); dataset.mSteeringData.mLength = static_cast(length); - length = 0; } else if (strcmp(aArgs[index], "joinerudpport") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mIsJoinerUdpPortSet = true; - SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value)); - dataset.mJoinerUdpPort = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mJoinerUdpPort)); } else if (strcmp(aArgs[index], "-x") == 0) { + uint16_t length; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); - length = static_cast((strlen(aArgs[index]) + 1) / 2); - VerifyOrExit(static_cast(length) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs, static_cast(length)) == length, - error = OT_ERROR_INVALID_ARGS); + length = sizeof(tlvs); + SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs)); + tlvsLength = static_cast(length); } else { @@ -284,8 +276,7 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[]) } } - SuccessOrExit(error = - otCommissionerSendMgmtSet(mInterpreter.mInstance, &dataset, tlvs, static_cast(length))); + SuccessOrExit(error = otCommissionerSendMgmtSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength)); exit: return error; @@ -294,18 +285,17 @@ exit: otError Commissioner::ProcessPanId(uint8_t aArgsLength, char *aArgs[]) { otError error; - long panid; - long mask; + uint16_t panId; + uint32_t mask; otIp6Address address; VerifyOrExit(aArgsLength > 3, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], panid)); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], mask)); - SuccessOrExit(error = otIp6AddressFromString(aArgs[3], &address)); + SuccessOrExit(error = ParseAsUint16(aArgs[1], panId)); + SuccessOrExit(error = ParseAsUint32(aArgs[2], mask)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[3], address)); - SuccessOrExit(error = otCommissionerPanIdQuery(mInterpreter.mInstance, static_cast(panid), - static_cast(mask), &address, + SuccessOrExit(error = otCommissionerPanIdQuery(mInterpreter.mInstance, panId, mask, &address, &Commissioner::HandlePanIdConflict, this)); exit: diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 1196adcad..514ab0730 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -40,6 +40,14 @@ #include #include "cli/cli.hpp" +#include "utils/parse_cmdline.hpp" + +using ot::Utils::CmdLineParser::ParseAsHexString; +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsUint16; +using ot::Utils::CmdLineParser::ParseAsUint32; +using ot::Utils::CmdLineParser::ParseAsUint64; +using ot::Utils::CmdLineParser::ParseAsUint8; namespace ot { namespace Cli { @@ -284,10 +292,7 @@ otError Dataset::ProcessActiveTimestamp(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mActiveTimestamp = static_cast(value); + SuccessOrExit(error = ParseAsUint64(aArgs[0], sDataset.mActiveTimestamp)); sDataset.mComponents.mIsActiveTimestampPresent = true; } @@ -308,10 +313,7 @@ otError Dataset::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mChannel = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mChannel)); sDataset.mComponents.mIsChannelPresent = true; } @@ -332,10 +334,7 @@ otError Dataset::ProcessChannelMask(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mChannelMask = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[0], sDataset.mChannelMask)); sDataset.mComponents.mIsChannelMaskPresent = true; } @@ -388,10 +387,7 @@ otError Dataset::ProcessDelay(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mDelay = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[0], sDataset.mDelay)); sDataset.mComponents.mIsDelayPresent = true; } @@ -413,12 +409,7 @@ otError Dataset::ProcessExtPanId(uint8_t aArgsLength, char *aArgs[]) } else { - uint8_t extPanId[OT_EXT_PAN_ID_SIZE]; - - VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], extPanId, sizeof(extPanId)) == sizeof(extPanId), - error = OT_ERROR_INVALID_ARGS); - - memcpy(sDataset.mExtendedPanId.m8, extPanId, sizeof(sDataset.mExtendedPanId)); + SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mExtendedPanId.m8)); sDataset.mComponents.mIsExtendedPanIdPresent = true; } @@ -440,12 +431,7 @@ otError Dataset::ProcessMasterKey(uint8_t aArgsLength, char *aArgs[]) } else { - uint8_t key[OT_MASTER_KEY_SIZE]; - - VerifyOrExit((Interpreter::Hex2Bin(aArgs[0], key, sizeof(key))) == OT_MASTER_KEY_SIZE, - error = OT_ERROR_INVALID_ARGS); - - memcpy(sDataset.mMasterKey.m8, key, sizeof(sDataset.mMasterKey)); + SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mMasterKey.m8)); sDataset.mComponents.mIsMasterKeyPresent = true; } @@ -473,7 +459,7 @@ otError Dataset::ProcessMeshLocalPrefix(uint8_t aArgsLength, char *aArgs[]) { otIp6Address prefix; - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &prefix)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], prefix)); memcpy(sDataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(sDataset.mMeshLocalPrefix.m8)); sDataset.mComponents.mIsMeshLocalPrefixPresent = true; @@ -523,10 +509,7 @@ otError Dataset::ProcessPanId(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mPanId = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mPanId)); sDataset.mComponents.mIsPanIdPresent = true; } @@ -547,10 +530,7 @@ otError Dataset::ProcessPendingTimestamp(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mPendingTimestamp = static_cast(value); + SuccessOrExit(error = ParseAsUint64(aArgs[0], sDataset.mPendingTimestamp)); sDataset.mComponents.mIsPendingTimestampPresent = true; } @@ -563,9 +543,7 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[]) otError error = OT_ERROR_NONE; otOperationalDataset dataset; uint8_t tlvs[128]; - long value; - int length = 0; - otIp6Address prefix; + uint8_t tlvsLength = 0; VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); @@ -577,85 +555,77 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[]) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsActiveTimestampPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mActiveTimestamp = static_cast(value); + SuccessOrExit(error = ParseAsUint64(aArgs[index], dataset.mActiveTimestamp)); } else if (strcmp(aArgs[index], "pendingtimestamp") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsPendingTimestampPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mPendingTimestamp = static_cast(value); + SuccessOrExit(error = ParseAsUint64(aArgs[index], dataset.mPendingTimestamp)); } else if (strcmp(aArgs[index], "masterkey") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsMasterKeyPresent = true; - VerifyOrExit((length = Interpreter::Hex2Bin(aArgs[index], dataset.mMasterKey.m8, - sizeof(dataset.mMasterKey.m8))) == OT_MASTER_KEY_SIZE, - error = OT_ERROR_INVALID_ARGS); - length = 0; + SuccessOrExit(error = ParseAsHexString(aArgs[index], dataset.mMasterKey.m8)); } else if (strcmp(aArgs[index], "networkname") == 0) { + size_t length; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsNetworkNamePresent = true; - VerifyOrExit((length = static_cast(strlen(aArgs[index]))) <= OT_NETWORK_NAME_MAX_SIZE, - error = OT_ERROR_INVALID_ARGS); + VerifyOrExit((length = strlen(aArgs[index])) <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); memset(&dataset.mNetworkName, 0, sizeof(sDataset.mNetworkName)); - memcpy(dataset.mNetworkName.m8, aArgs[index], static_cast(length)); - length = 0; + memcpy(dataset.mNetworkName.m8, aArgs[index], length); } else if (strcmp(aArgs[index], "extpanid") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsExtendedPanIdPresent = true; - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], dataset.mExtendedPanId.m8, - sizeof(dataset.mExtendedPanId.m8)) == sizeof(dataset.mExtendedPanId.m8), - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[index], dataset.mExtendedPanId.m8)); } else if (strcmp(aArgs[index], "localprefix") == 0) { + otIp6Address prefix; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsMeshLocalPrefixPresent = true; - SuccessOrExit(error = otIp6AddressFromString(aArgs[index], &prefix)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[index], prefix)); memcpy(dataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(dataset.mMeshLocalPrefix.m8)); } else if (strcmp(aArgs[index], "delaytimer") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsDelayPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mDelay = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[index], dataset.mDelay)); } else if (strcmp(aArgs[index], "panid") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsPanIdPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mPanId = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mPanId)); } else if (strcmp(aArgs[index], "channel") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsChannelPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mChannel = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mChannel)); } else if (strcmp(aArgs[index], "channelmask") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); dataset.mComponents.mIsChannelMaskPresent = true; - SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value)); - dataset.mChannelMask = static_cast(value); + SuccessOrExit(error = ParseAsUint32(aArgs[index], dataset.mChannelMask)); } else if (strcmp(aArgs[index], "-x") == 0) { + uint16_t length; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); - length = static_cast((strlen(aArgs[index]) + 1) / 2); - VerifyOrExit(static_cast(length) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs, static_cast(length)) == length, - error = OT_ERROR_INVALID_ARGS); + length = sizeof(tlvs); + SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs)); + tlvsLength = static_cast(length); } else { @@ -665,13 +635,11 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[]) if (strcmp(aArgs[0], "active") == 0) { - SuccessOrExit( - error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, static_cast(length))); + SuccessOrExit(error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength)); } else if (strcmp(aArgs[0], "pending") == 0) { - SuccessOrExit( - error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, static_cast(length))); + SuccessOrExit(error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength)); } else { @@ -687,8 +655,7 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[]) otError error = OT_ERROR_NONE; otOperationalDatasetComponents datasetComponents; uint8_t tlvs[32]; - long value; - int length = 0; + uint8_t tlvsLength = 0; bool destAddrSpecified = false; otIp6Address address; @@ -698,8 +665,6 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[]) for (uint8_t index = 1; index < aArgsLength; index++) { - VerifyOrExit(static_cast(length) < sizeof(tlvs), error = OT_ERROR_NO_BUFS); - if (strcmp(aArgs[index], "activetimestamp") == 0) { datasetComponents.mIsActiveTimestampPresent = true; @@ -738,18 +703,17 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[]) } else if (strcmp(aArgs[index], "-x") == 0) { + uint16_t length; + VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); - value = static_cast(strlen(aArgs[index]) + 1) / 2; - VerifyOrExit(static_cast(value) <= (sizeof(tlvs) - static_cast(length)), - error = OT_ERROR_NO_BUFS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs + length, static_cast(value)) == value, - error = OT_ERROR_INVALID_ARGS); - length += value; + length = sizeof(tlvs); + SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs)); + tlvsLength = static_cast(length); } else if (strcmp(aArgs[index], "address") == 0) { VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[index], &address)); + SuccessOrExit(error = ParseAsIp6Address(aArgs[index], address)); destAddrSpecified = true; } else @@ -760,14 +724,12 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[]) if (strcmp(aArgs[0], "active") == 0) { - SuccessOrExit(error = otDatasetSendMgmtActiveGet(mInterpreter.mInstance, &datasetComponents, tlvs, - static_cast(length), + SuccessOrExit(error = otDatasetSendMgmtActiveGet(mInterpreter.mInstance, &datasetComponents, tlvs, tlvsLength, destAddrSpecified ? &address : nullptr)); } else if (strcmp(aArgs[0], "pending") == 0) { - SuccessOrExit(error = otDatasetSendMgmtPendingGet(mInterpreter.mInstance, &datasetComponents, tlvs, - static_cast(length), + SuccessOrExit(error = otDatasetSendMgmtPendingGet(mInterpreter.mInstance, &datasetComponents, tlvs, tlvsLength, destAddrSpecified ? &address : nullptr)); } else @@ -793,9 +755,7 @@ otError Dataset::ProcessPskc(uint8_t aArgsLength, char *aArgs[]) } else if (aArgsLength == 1) { - VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], sDataset.mPskc.m8, sizeof(sDataset.mPskc)) == - sizeof(sDataset.mPskc), - error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mPskc.m8)); } #if OPENTHREAD_FTD else if (aArgsLength == 2 && !strcmp(aArgs[0], "-p")) @@ -862,11 +822,8 @@ otError Dataset::ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[]) } else { - long value; - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mSecurityPolicy.mRotationTime = static_cast(value); - sDataset.mSecurityPolicy.mFlags = 0; + SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mSecurityPolicy.mRotationTime)); + sDataset.mSecurityPolicy.mFlags = 0; if (aArgsLength > 1) { @@ -911,13 +868,12 @@ otError Dataset::ProcessSet(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; otOperationalDatasetTlvs dataset; - int tlvsLength; + uint16_t tlvsLength; VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - tlvsLength = Interpreter::Hex2Bin(aArgs[1], dataset.mTlvs, sizeof(dataset.mTlvs)); - VerifyOrExit((0 <= tlvsLength) && (static_cast(tlvsLength) <= sizeof(dataset.mTlvs)), - error = OT_ERROR_INVALID_ARGS); + tlvsLength = sizeof(dataset.mTlvs); + SuccessOrExit(error = ParseAsHexString(aArgs[1], tlvsLength, dataset.mTlvs)); dataset.mLength = static_cast(tlvsLength); if (strcmp(aArgs[0], "active") == 0) diff --git a/src/cli/cli_joiner.cpp b/src/cli/cli_joiner.cpp index 4720bfe99..0e634b8cd 100644 --- a/src/cli/cli_joiner.cpp +++ b/src/cli/cli_joiner.cpp @@ -36,6 +36,7 @@ #include #include "cli/cli.hpp" +#include "utils/parse_cmdline.hpp" #if OPENTHREAD_CONFIG_JOINER_ENABLE diff --git a/src/cli/cli_network_data.cpp b/src/cli/cli_network_data.cpp index 01622f7b3..f251c804a 100644 --- a/src/cli/cli_network_data.cpp +++ b/src/cli/cli_network_data.cpp @@ -38,8 +38,10 @@ #include "cli/cli.hpp" #include "common/encoding.hpp" +#include "utils/parse_cmdline.hpp" using ot::Encoding::BigEndian::HostSwap16; +using ot::Utils::CmdLineParser::ParseAsHexString; namespace ot { namespace Cli { @@ -212,7 +214,7 @@ otError NetworkData::ProcessSteeringData(uint8_t aArgsLength, char *aArgs[]) if (error == OT_ERROR_NOT_FOUND) { - VerifyOrExit(Interpreter::Hex2Bin(aArgs[1], addr.m8, sizeof(addr)) == sizeof(addr), OT_NOOP); + SuccessOrExit(error = ParseAsHexString(aArgs[1], addr.m8)); } else if (error != OT_ERROR_NONE) { diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp index fd4f819fd..90badb433 100644 --- a/src/cli/cli_udp.cpp +++ b/src/cli/cli_udp.cpp @@ -38,9 +38,14 @@ #include "cli/cli.hpp" #include "common/encoding.hpp" +#include "utils/parse_cmdline.hpp" using ot::Encoding::BigEndian::HostSwap16; +using ot::Utils::CmdLineParser::ParseAsHexString; +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsUint16; + namespace ot { namespace Cli { @@ -70,19 +75,11 @@ otError UdpExample::ProcessBind(uint8_t aArgsLength, char *aArgs[]) { otError error; otSockAddr sockaddr; - long value; VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - memset(&sockaddr, 0, sizeof(sockaddr)); - - error = otIp6AddressFromString(aArgs[0], &sockaddr.mAddress); - SuccessOrExit(error); - - error = Interpreter::ParseLong(aArgs[1], value); - SuccessOrExit(error); - - sockaddr.mPort = static_cast(value); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], sockaddr.mAddress)); + SuccessOrExit(error = ParseAsUint16(aArgs[1], sockaddr.mPort)); error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr); @@ -94,19 +91,11 @@ otError UdpExample::ProcessConnect(uint8_t aArgsLength, char *aArgs[]) { otError error; otSockAddr sockaddr; - long value; VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS); - memset(&sockaddr, 0, sizeof(sockaddr)); - - error = otIp6AddressFromString(aArgs[0], &sockaddr.mAddress); - SuccessOrExit(error); - - error = Interpreter::ParseLong(aArgs[1], value); - SuccessOrExit(error); - - sockaddr.mPort = static_cast(value); + SuccessOrExit(error = ParseAsIp6Address(aArgs[0], sockaddr.mAddress)); + SuccessOrExit(error = ParseAsUint16(aArgs[1], sockaddr.mPort)); error = otUdpConnect(mInterpreter.mInstance, &mSocket, &sockaddr); @@ -146,14 +135,8 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[]) if (aArgsLength > 2) { - long value; - error = otIp6AddressFromString(aArgs[curArg++], &messageInfo.mPeerAddr); - SuccessOrExit(error); - - error = Interpreter::ParseLong(aArgs[curArg++], value); - SuccessOrExit(error); - - messageInfo.mPeerPort = static_cast(value); + SuccessOrExit(error = ParseAsIp6Address(aArgs[curArg++], messageInfo.mPeerAddr)); + SuccessOrExit(error = ParseAsUint16(aArgs[curArg++], messageInfo.mPeerPort)); } if (aArgsLength == 2 || aArgsLength == 4) @@ -162,10 +145,8 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[]) if (strcmp(aArgs[typePos], "-s") == 0) { - unsigned long value; payloadType = kTypeAutoSize; - SuccessOrExit(error = Interpreter::ParseUnsignedLong(aArgs[curArg], value)); - payloadLength = static_cast(value); + SuccessOrExit(error = ParseAsUint16(aArgs[curArg], payloadLength)); } else if (strcmp(aArgs[typePos], "-x") == 0) { @@ -192,14 +173,14 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[]) case kTypeHexString: { uint8_t buf[50]; - int16_t bufLen; + uint16_t bufLen; uint16_t conversionLength = 0; const char *hexString = aArgs[curArg]; while (payloadLength > 0) { - bufLen = static_cast(Interpreter::Hex2Bin(hexString, buf, sizeof(buf), true)); - + bufLen = sizeof(buf); + SuccessOrExit(error = ParseAsHexString(hexString, bufLen, buf, Utils::CmdLineParser::kAllowTruncate)); VerifyOrExit(bufLen > 0, error = OT_ERROR_INVALID_ARGS); conversionLength = static_cast(bufLen * 2); @@ -211,7 +192,7 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[]) hexString += conversionLength; payloadLength -= conversionLength; - SuccessOrExit(error = otMessageAppend(message, buf, static_cast(bufLen))); + SuccessOrExit(error = otMessageAppend(message, buf, bufLen)); } break; } diff --git a/src/core/utils/parse_cmdline.cpp b/src/core/utils/parse_cmdline.cpp index d65bc4797..0c84fac6f 100644 --- a/src/core/utils/parse_cmdline.cpp +++ b/src/core/utils/parse_cmdline.cpp @@ -31,14 +31,17 @@ * This file implements the command line parser. */ -#include - #include "parse_cmdline.hpp" +#include +#include + #include "common/code_utils.hpp" +#include "net/ip6_address.hpp" namespace ot { namespace Utils { +namespace CmdLineParser { static bool IsSeparator(char aChar) { @@ -50,7 +53,38 @@ static bool IsEscapable(char aChar) return IsSeparator(aChar) || (aChar == '\\'); } -otError CmdLineParser::ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax) +static otError ParseDigit(char aDigitChar, uint8_t &aValue) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(('0' <= aDigitChar) && (aDigitChar <= '9'), error = OT_ERROR_INVALID_ARGS); + aValue = static_cast(aDigitChar - '0'); + +exit: + return error; +} + +static otError ParseHexDigit(char aHexChar, uint8_t &aValue) +{ + otError error = OT_ERROR_NONE; + + if (('A' <= aHexChar) && (aHexChar <= 'F')) + { + ExitNow(aValue = static_cast(aHexChar - 'A' + 10)); + } + + if (('a' <= aHexChar) && (aHexChar <= 'f')) + { + ExitNow(aValue = static_cast(aHexChar - 'a' + 10)); + } + + error = ParseDigit(aHexChar, aValue); + +exit: + return error; +} + +otError ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax) { otError error = OT_ERROR_NONE; char * cmd; @@ -80,5 +114,229 @@ exit: return error; } +template otError ParseUint(const char *aString, UintType &aUint) +{ + otError error; + uint64_t value; + + SuccessOrExit(error = ParseAsUint64(aString, value)); + + VerifyOrExit(value <= std::numeric_limits::max(), error = OT_ERROR_INVALID_ARGS); + aUint = static_cast(value); + +exit: + return error; +} + +otError ParseAsUint8(const char *aString, uint8_t &aUint8) +{ + return ParseUint(aString, aUint8); +} + +otError ParseAsUint16(const char *aString, uint16_t &aUint16) +{ + return ParseUint(aString, aUint16); +} + +otError ParseAsUint32(const char *aString, uint32_t &aUint32) +{ + return ParseUint(aString, aUint32); +} + +otError ParseAsUint64(const char *aString, uint64_t &aUint64) +{ + otError error = OT_ERROR_NONE; + uint64_t value = 0; + const char *cur = aString; + bool isHex = false; + + enum : uint64_t + { + kMaxHexBeforeOveflow = (0xffffffffffffffffULL / 16), + kMaxDecBeforeOverlow = (0xffffffffffffffffULL / 10), + }; + + if (cur[0] == '0' && (cur[1] == 'x' || cur[1] == 'X')) + { + cur += 2; + isHex = true; + } + + do + { + uint8_t digit; + uint64_t newValue; + + SuccessOrExit(error = isHex ? ParseHexDigit(*cur, digit) : ParseDigit(*cur, digit)); + VerifyOrExit(value <= (isHex ? kMaxHexBeforeOveflow : kMaxDecBeforeOverlow), error = OT_ERROR_INVALID_ARGS); + value = isHex ? (value << 4) : (value * 10); + newValue = value + digit; + VerifyOrExit(newValue >= value, error = OT_ERROR_INVALID_ARGS); + value = newValue; + cur++; + } while (*cur != '\0'); + + aUint64 = value; + +exit: + return error; +} + +template otError ParseInt(const char *aString, IntType &aInt) +{ + otError error; + int32_t value; + + SuccessOrExit(error = ParseAsInt32(aString, value)); + + VerifyOrExit((std::numeric_limits::min() <= value) && (value <= std::numeric_limits::max()), + error = OT_ERROR_INVALID_ARGS); + aInt = static_cast(value); + +exit: + return error; +} + +otError ParseAsInt8(const char *aString, int8_t &aInt8) +{ + return ParseInt(aString, aInt8); +} + +otError ParseAsInt16(const char *aString, int16_t &aInt16) +{ + return ParseInt(aString, aInt16); +} + +otError ParseAsInt32(const char *aString, int32_t &aInt32) +{ + otError error; + uint64_t value; + bool isNegavtive = false; + + if (*aString == '-') + { + aString++; + isNegavtive = true; + } + else if (*aString == '+') + { + aString++; + } + + SuccessOrExit(error = ParseAsUint64(aString, value)); + VerifyOrExit(value <= (isNegavtive + ? static_cast(-static_cast(std::numeric_limits::min())) + : static_cast(std::numeric_limits::max())), + error = OT_ERROR_INVALID_ARGS); + aInt32 = isNegavtive ? -static_cast(value) : static_cast(value); + +exit: + return error; +} + +otError ParseAsBool(const char *aString, bool &aBool) +{ + otError error; + uint32_t value; + + SuccessOrExit(error = ParseAsUint32(aString, value)); + aBool = (value != 0); + +exit: + return error; +} +#if OPENTHREAD_FTD || OPENTHREAD_MTD + +otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix) +{ + enum : uint8_t + { + kMaxIp6AddressStringSize = 45, + }; + + otError error = OT_ERROR_INVALID_ARGS; + char string[kMaxIp6AddressStringSize]; + const char *prefixLengthStr; + + prefixLengthStr = strchr(aString, '/'); + VerifyOrExit(prefixLengthStr != nullptr, OT_NOOP); + + VerifyOrExit(prefixLengthStr - aString < static_cast(sizeof(string)), OT_NOOP); + + memcpy(string, aString, static_cast(prefixLengthStr - aString)); + string[prefixLengthStr - aString] = '\0'; + + SuccessOrExit(static_cast(aPrefix.mPrefix).FromString(string)); + error = ParseAsUint8(prefixLengthStr + 1, aPrefix.mLength); + +exit: + return error; +} +#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD + +otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize) +{ + otError error; + uint16_t readSize = aSize; + + SuccessOrExit(error = ParseAsHexString(aString, readSize, aBuffer, kDisallowTruncate)); + VerifyOrExit(readSize == aSize, error = OT_ERROR_INVALID_ARGS); + +exit: + return error; +} + +otError ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode) +{ + otError error = OT_ERROR_NONE; + uint8_t byte = 0; + uint16_t readBytes = 0; + const char *hex = aString; + size_t hexLength = strlen(aString); + uint8_t numChars; + + if (aMode == kDisallowTruncate) + { + VerifyOrExit((hexLength + 1) / 2 <= aSize, error = OT_ERROR_INVALID_ARGS); + } + + // Handle the case where number of chars in hex string is odd. + numChars = hexLength & 1; + + while (*hex != '\0') + { + uint8_t digit; + + SuccessOrExit(error = ParseHexDigit(*hex, digit)); + byte |= digit; + + hex++; + numChars++; + + if (numChars >= 2) + { + numChars = 0; + *aBuffer++ = byte; + byte = 0; + readBytes++; + + if (readBytes == aSize) + { + ExitNow(); + } + } + else + { + byte <<= 4; + } + } + + aSize = readBytes; + +exit: + return error; +} + +} // namespace CmdLineParser } // namespace Utils } // namespace ot diff --git a/src/core/utils/parse_cmdline.hpp b/src/core/utils/parse_cmdline.hpp index 670ccd9da..6c3facde3 100644 --- a/src/core/utils/parse_cmdline.hpp +++ b/src/core/utils/parse_cmdline.hpp @@ -35,10 +35,13 @@ #define PARSE_CMD_LINE_HPP_ #include + #include +#include namespace ot { namespace Utils { +namespace CmdLineParser { /** * @addtogroup utils-parse-cmd-line @@ -50,32 +53,242 @@ namespace Utils { */ /** - * This class implements the command line parser. + * This enumeration type represents the parse mode value used as a parameter in `ParseAsHexString()`. * */ -class CmdLineParser +enum HexStringParseMode : uint8_t { -public: - /** - * This function parses the command line. - * - * Note: this method may change the input @p aString, it will put a '\0' by the end of each argument, - * and @p aArgs will point to the arguments in the input @p aString. Backslash ('\') can be used - * to escape separators (' ', '\t', '\r', '\n') and the backslash itself. - * - * @param[in] aString A null-terminated input string. - * @param[out] aArgsLength The argument counter of the command line. - * @param[out] aArgs The argument vector of the command line. - * @param[in] aArgsLengthMax The maximum argument counter. - * - */ - static otError ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax); + kDisallowTruncate, // Disallow truncation of hex string. + kAllowTruncate, // Allow truncation of hex string. }; +/** + * This function parses a given command line string and breaks it into an argument list. + * + * Note: this method may change the input @p aCommandString, it will put a '\0' by the end of each argument, + * and @p aArgs will point to the arguments in the input @p aCommandString. Backslash ('\') can be used + * to escape separators (' ', '\t', '\r', '\n') and the backslash itself. + * + * @param[in] aCommandString A null-terminated input string. + * @param[out] aArgsLength The argument counter of the command line. + * @param[out] aArgs The argument vector of the command line. + * @param[in] aArgsLengthMax The maximum argument counter. + * + */ +otError ParseCmd(char *aCommandString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax); + +/** + * This function parses a string as a `uint8_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). + * + * @param[in] aString The string to parse. + * @param[out] aUint8 A reference to an `uint8_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsUint8(const char *aString, uint8_t &aUint8); + +/** + * This function parses a string as a `uint16_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). + * + * @param[in] aString The string to parse. + * @param[out] aUint16 A reference to an `uint16_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsUint16(const char *aString, uint16_t &aUint16); + +/** + * This function parses a string as a `uint32_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). + * + * @param[in] aString The string to parse. + * @param[out] aUint32 A reference to an `uint32_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsUint32(const char *aString, uint32_t &aUint32); + +/** + * This function parses a string as a `uint64_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). + * + * @param[in] aString The string to parse. + * @param[out] aUint64 A reference to an `uint64_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsUint64(const char *aString, uint64_t &aUint64); + +/** + * This function parses a string as a `int8_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with + * `+`/`-` sign. + * + * @param[in] aString The string to parse. + * @param[out] aInt8 A reference to an `int8_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsInt8(const char *aString, int8_t &aInt8); + +/** + * This function parses a string as a `int16_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with + * `+`/`-` sign. + * + * @param[in] aString The string to parse. + * @param[out] aInt16 A reference to an `int16_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsInt16(const char *aString, int16_t &aInt16); + +/** + * This function parses a string as a `int32_t` value. + * + * The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with + * `+`/`-` sign. + * + * @param[in] aString The string to parse. + * @param[out] aInt32 A reference to an `int32_t` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range). + * + */ +otError ParseAsInt32(const char *aString, int32_t &aInt32); + +/** + * This function parses a string as a `bool` value. + * + * Zero value is treated as `false, non-zero value as `true`. + * + * @param[in] aString The string to parse. + * @param[out] aBool A reference to a `bool` variable to output the parsed value. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid number. + * + */ +otError ParseAsBool(const char *aString, bool &aBool); + +#if OPENTHREAD_FTD || OPENTHREAD_MTD +/** + * This function parses a string as an IPv6 address. + * + * + * @param[in] aString The string to parse. + * @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 address. + * + */ +inline otError ParseAsIp6Address(const char *aString, otIp6Address &aAddress) +{ + return otIp6AddressFromString(aString, &aAddress); +} + +/** + * This function parses a string as an IPv6 prefix. + * + * The string is parsed as `{IPv6Address}/{PrefixLength}`. + * + * @param[in] aString The string to parse. + * @param[out] aPrefix A reference to an `otIp6Prefix` to output the parsed IPv6 prefix. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 prefix + * + */ +otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix); +#endif // OPENTHREAD_FTD || OPENTHREAD_MTD + +/** + * This function parses a hex string into a byte array of fixed expected size. + * + * This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p aSize bytes (after parsing). If + * there are fewer or more bytes in hex string that @p aSize, the parsed bytes (up to @p aSize) are copied into the + * `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned. + * + * @param[in] aString The string to parse. + * @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence. + * @param[in] aSize The expected size of byte sequence (number of bytes after parsing). + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes. + * + */ +otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize); + +/** + * This template function parses a hex string into a a given fixed size array. + * + * This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p kBufferSize bytes (after parsing). + * If there are fewer or more bytes in hex string that @p kBufferSize, the parsed bytes (up to @p kBufferSize) are + * copied into the `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned. + * + * @tparam kBufferSize The byte array size (number of bytes). + * + * @param[in] aString The string to parse. + * @param[out] aBuffer A reference to a byte array to output the parsed byte sequence. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes. + * + */ +template static otError ParseAsHexString(const char *aString, uint8_t (&aBuffer)[kBufferSize]) +{ + return ParseAsHexString(aString, aBuffer, kBufferSize); +} + +/** + * This function parses a hex string into a byte array. + * + * If @p aMode disallows truncation (`kDisallowTruncate`), this function verifies that parses hex string bytes fit in + * @p aBuffer with its given size in @aSize. Otherwise when @p aMode allows truncation, extra bytes after @p aSize bytes + * are ignored. + * + * @param[in] aString The string to parse. + * @param[inout] aSize On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer). + * On exit provides number of bytes parsed and copied into @p aBuffer + * @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence. + * @param[in] aMode Indicates parsing mode whether to allow truncation or not. + * + * @retval OT_ERROR_NONE The string was parsed successfully. + * @retval OT_ERROR_INVALID_ARGS The string does not contain valid format or too many bytes (if truncation not allowed) + * + */ +otError ParseAsHexString(const char * aString, + uint16_t & aSize, + uint8_t * aBuffer, + HexStringParseMode aMode = kDisallowTruncate); + /** * @} */ +} // namespace CmdLineParser } // namespace Utils } // namespace ot diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index bd4e248e5..58b406a26 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -139,6 +139,28 @@ target_link_libraries(test-child-table add_test(NAME test-child-table COMMAND test-child-table) +add_executable(test-cmd-line-parser + ${COMMON_SOURCES} + test_cmd_line_parser.cpp +) + +target_include_directories(test-cmd-line-parser + PRIVATE + ${COMMON_INCLUDES} +) + +target_compile_options(test-cmd-line-parser + PRIVATE + ${COMMON_COMPILE_OPTIONS} +) + +target_link_libraries(test-cmd-line-parser + PRIVATE + ${COMMON_LIBS} +) + +add_test(NAME test-cmd-line-parser COMMAND test-cmd-line-parser) + add_executable(test-flash ${COMMON_SOURCES} test_flash.cpp @@ -608,6 +630,7 @@ set_target_properties( test-checksum test-child test-child-table + test-cmd-line-parser test-flash test-heap test-hmac-sha256 diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 4c1971ed4..1e4a26872 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -110,6 +110,7 @@ check_PROGRAMS += \ test-checksum \ test-child \ test-child-table \ + test-cmd-line-parser \ test-flash \ test-heap \ test-hmac-sha256 \ @@ -183,6 +184,9 @@ test_child_SOURCES = $(COMMON_SOURCES) test_child.cpp test_child_table_LDADD = $(COMMON_LDADD) test_child_table_SOURCES = $(COMMON_SOURCES) test_child_table.cpp +test_cmd_line_parser_LDADD = $(COMMON_LDADD) +test_cmd_line_parser_SOURCES = $(COMMON_SOURCES) test_cmd_line_parser.cpp + test_flash_LDADD = $(COMMON_LDADD) test_flash_SOURCES = $(COMMON_SOURCES) test_flash.cpp diff --git a/tests/unit/test_cmd_line_parser.cpp b/tests/unit/test_cmd_line_parser.cpp new file mode 100644 index 000000000..59339e209 --- /dev/null +++ b/tests/unit/test_cmd_line_parser.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "test_platform.h" + +#include + +#include "common/instance.hpp" +#include "utils/parse_cmdline.hpp" + +#include "test_util.h" + +using ot::Utils::CmdLineParser::ParseAsBool; +using ot::Utils::CmdLineParser::ParseAsHexString; +using ot::Utils::CmdLineParser::ParseAsInt16; +using ot::Utils::CmdLineParser::ParseAsInt32; +using ot::Utils::CmdLineParser::ParseAsInt8; +using ot::Utils::CmdLineParser::ParseAsIp6Address; +using ot::Utils::CmdLineParser::ParseAsIp6Prefix; +using ot::Utils::CmdLineParser::ParseAsUint16; +using ot::Utils::CmdLineParser::ParseAsUint32; +using ot::Utils::CmdLineParser::ParseAsUint64; +using ot::Utils::CmdLineParser::ParseAsUint8; + +template struct TestCase +{ + const char *mString; + otError mError; + ValueType mValue; +}; + +template +void VerifyParser(const TestCase *aTestCases, const char *aParserName, const char *aPrintFormat) +{ + const TestCase *testCase = aTestCases; + ValueType value; + otError error; + + printf("----------------------------------------------------------\n"); + + while (true) + { + printf("%s(\"%s\") -> ", aParserName, testCase->mString); + + if (testCase->mError != OT_ERROR_NONE) + { + printf("error:%s", otThreadErrorToString(testCase->mError)); + } + else + { + printf(aPrintFormat, testCase->mValue); + } + + printf("\n"); + + error = Parser(testCase->mString, value); + + VerifyOrQuit(error == testCase->mError, "Parser did not return the expected error"); + + if (error == OT_ERROR_NONE) + { + VerifyOrQuit(value == testCase->mValue, "Parser failed"); + } + + if (testCase->mString[0] == '\0') + { + break; + } + + testCase++; + } +} + +void TestParsingInts(void) +{ + TestCase kBoolTestCases[] = { + {"0", OT_ERROR_NONE, false}, // Zero as false value + {"1", OT_ERROR_NONE, true}, // Non-zero as true value + {"0x0", OT_ERROR_NONE, false}, // Zero as false value + {"0x1", OT_ERROR_NONE, true}, // Non-zero (in hex) as true value + {"10", OT_ERROR_NONE, true}, // Non-zero as true value + {"a", OT_ERROR_INVALID_ARGS, false}, // Error case: Incorrect char + {"-1", OT_ERROR_INVALID_ARGS, false}, // Error case: Negative value + {"", OT_ERROR_INVALID_ARGS, false}, // Empty string indicate end of the list + }; + + TestCase kUint8TestCases[] = { + {"0", OT_ERROR_NONE, 0}, + {"1", OT_ERROR_NONE, 1}, + {"74", OT_ERROR_NONE, 74}, + {"255", OT_ERROR_NONE, 255}, // Max `uint8` value (decimal format) + {"0xa", OT_ERROR_NONE, 0xa}, + {"0x04", OT_ERROR_NONE, 4}, + {"0x7e", OT_ERROR_NONE, 0x7e}, + {"0xcd", OT_ERROR_NONE, 0xcd}, + {"0x0", OT_ERROR_NONE, 0}, + {"0xff", OT_ERROR_NONE, 0xff}, // Max `uint8` value (hex format) + {"0x0000ff", OT_ERROR_NONE, 0xff}, // Hex format (extra zeros) + {"0xB", OT_ERROR_NONE, 0xb}, + {"0X04", OT_ERROR_NONE, 4}, + {"0X7E", OT_ERROR_NONE, 0x7e}, + {"0XCD", OT_ERROR_NONE, 0xcd}, + {"0X0", OT_ERROR_NONE, 0}, + {"0XFF", OT_ERROR_NONE, 0xff}, + {"00", OT_ERROR_NONE, 0}, + {"-5", OT_ERROR_INVALID_ARGS, 0}, // Error case: Negative value. + {"0y", OT_ERROR_INVALID_ARGS, 0}, // Error case: Incorrect prefix. + {"0x7g", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char. + {"0xaaa", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out or range. + {"256", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1) + {"12e", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra char. + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list + }; + + TestCase kUint16TestCases[] = { + {"0", OT_ERROR_NONE, 0}, + {"1245", OT_ERROR_NONE, 1245}, + {"0xa", OT_ERROR_NONE, 0xa}, + {"0xab7d", OT_ERROR_NONE, 0xab7d}, + {"0X1AE", OT_ERROR_NONE, 0x1ae}, + {"0X7E", OT_ERROR_NONE, 0x7e}, + {"65535", OT_ERROR_NONE, 65535}, // Max `uint16` value (decimal format) + {"0xffff", OT_ERROR_NONE, 0xffff}, // Max `uint16` value (hex format) + {"-1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Negative value + {"0y", OT_ERROR_INVALID_ARGS, 0}, // Error case: Incorrect prefix + {"0xq", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char. + {"0x12345", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range. + {"65536", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1) + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list + }; + + TestCase kUint32TestCases[] = { + {"0", OT_ERROR_NONE, 0}, + {"1234567", OT_ERROR_NONE, 1234567}, + {"0xc", OT_ERROR_NONE, 0xc}, + {"0x01234567", OT_ERROR_NONE, 0x1234567}, + {"0XABCDEF09", OT_ERROR_NONE, 0xabcdef09}, + {"0X54321", OT_ERROR_NONE, 0x54321}, + {"4294967295", OT_ERROR_NONE, 4294967295}, // Max `uint32` value (decimal format) + {"0xffffffff", OT_ERROR_NONE, 0xffffffff}, // Max `uint32` value (hex format) + {"-1", OT_ERROR_INVALID_ARGS, 0}, + {"0y", OT_ERROR_INVALID_ARGS, 0}, + {"0x1234zz", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char + {"0x123456789", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range + {"4294967296", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1) + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list. + }; + + TestCase kUint64TestCases[] = { + {"0", OT_ERROR_NONE, 0}, + {"123456789087654321", OT_ERROR_NONE, 123456789087654321}, + {"0xb", OT_ERROR_NONE, 0xb}, + {"0x1234567890acbdef", OT_ERROR_NONE, 0x1234567890acbdef}, + {"0XFEDCBA9876543210", OT_ERROR_NONE, 0xfedcba9876543210}, + {"0xffffffffffffffff", OT_ERROR_NONE, 0xffffffffffffffff}, // Max `uint64` value (hex format) + {"18446744073709551615", OT_ERROR_NONE, 18446744073709551615ull}, // Max `uint64` value (decimal format) + {"-1", OT_ERROR_INVALID_ARGS, 0}, + {"0x1234567890acbdef0", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range + {"18446744073709551616", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out or range (max value + 1) + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list. + }; + + TestCase kInt8TestCases[] = { + {"0", OT_ERROR_NONE, 0}, + {"-1", OT_ERROR_NONE, -1}, + {"+74", OT_ERROR_NONE, 74}, + {"-0x12", OT_ERROR_NONE, -0x12}, + {"-0XB", OT_ERROR_NONE, -11}, + {"127", OT_ERROR_NONE, 127}, // Max `int8` value + {"-128", OT_ERROR_NONE, -128}, // Min `int8` value + {"128", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1) + {"-129", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min value - 1) + {"--1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign + {"+-2", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign + {"++1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list. + }; + + TestCase kInt16TestCases[] = { + {"-1", OT_ERROR_NONE, -1}, + {"+0x1234", OT_ERROR_NONE, 0x1234}, + {"-0X6E8", OT_ERROR_NONE, -0x6E8}, + {"32767", OT_ERROR_NONE, 32767}, // Max `int16` value + {"0X7FFF", OT_ERROR_NONE, 0x7fff}, // Max `int16` value (hex value) + {"-32768", OT_ERROR_NONE, -32768}, // Min `int16` value + {"-0x8000", OT_ERROR_NONE, -0x8000}, // Min `int16` value (hex value) + {"32768", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1) + {"0X8000", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1) + {"-32769", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1) + {"-0x8001", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1) + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list. + }; + + TestCase kInt32TestCases[] = { + {"-256", OT_ERROR_NONE, -256}, + {"+0x12345678", OT_ERROR_NONE, 0x12345678}, + {"-0X6677aB", OT_ERROR_NONE, -0X6677aB}, + {"2147483647", OT_ERROR_NONE, 2147483647}, + {"0x7fffFFFF", OT_ERROR_NONE, 0x7fffffff}, // Max `int32` value + {"-2147483648", OT_ERROR_NONE, -2147483648}, // Min `int32` value + {"2147483648", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1) + {"0X80000000", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1) + {"-2147483649", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1) + {"-0x80000001", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1) + {"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list + }; + + VerifyParser(kBoolTestCases, "ParseAsBool", "%d"); + VerifyParser(kUint8TestCases, "ParseAsUint8", "0x%02x"); + VerifyParser(kUint16TestCases, "ParseAsUint16", "0x%04x"); + VerifyParser(kUint32TestCases, "ParseAsUint32", "0x%08x"); + VerifyParser(kUint64TestCases, "ParseAsUint64", "0x%016llx"); + VerifyParser(kInt8TestCases, "ParseAsInt8", "%d"); + VerifyParser(kInt16TestCases, "ParseAsInt16", "%d"); + VerifyParser(kInt32TestCases, "ParseAsInt32", "%d"); +} + +void TestParsingHexStrings(void) +{ + const char kHexString[] = "DeadBeefCafeBabe"; + const uint8_t kParsedArray[] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe}; + + uint8_t buffer[sizeof(kParsedArray)]; + uint8_t buf3[3]; + uint16_t len; + + // Verify `ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)` + + buffer[0] = 0xff; + SuccessOrQuit(ParseAsHexString("0", buffer, 1), "ParseAsHexString() failed"); + VerifyOrQuit(buffer[0] == 0, "ParseAsHexString() parsed incorrectly"); + + buffer[0] = 0; + SuccessOrQuit(ParseAsHexString("7e", buffer, 1), "ParseAsHexString() failed"); + VerifyOrQuit(buffer[0] == 0x7e, "ParseAsHexString() parsed incorrectly"); + + VerifyOrQuit(ParseAsHexString("123", buffer, 1) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + SuccessOrQuit(ParseAsHexString("123", buffer, 2), "ParseAsHexString() failed"); + VerifyOrQuit(buffer[0] == 1 && buffer[1] == 0x23, "ParseAsHexString() parsed incorrectly"); + + VerifyOrQuit(ParseAsHexString("123x", buffer, 2) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + VerifyOrQuit(ParseAsHexString(" 123", buffer, 2) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + + // Verify `ParseAsHexString()` + + VerifyOrQuit(ParseAsHexString("1122", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + VerifyOrQuit(ParseAsHexString("1122334", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + VerifyOrQuit(ParseAsHexString("11223344", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input"); + SuccessOrQuit(ParseAsHexString("abbade", buf3), "ParseAsHexString() failed"); + VerifyOrQuit(buf3[0] == 0xab && buf3[1] == 0xba && buf3[2] == 0xde, "ParseAsHexString() parsed incorrectly"); + + SuccessOrQuit(ParseAsHexString(kHexString, buffer), "ParseAsHexString failed"); + VerifyOrQuit(memcmp(buffer, kParsedArray, sizeof(buffer)) == 0, "ParseAsHexString() parsed incorrectly"); + + // Verify truncation + + len = sizeof(buffer); + + SuccessOrQuit(ParseAsHexString(kHexString, len, buffer), "ParseAsHexString failed"); + VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly"); + VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly"); + + SuccessOrQuit(ParseAsHexString(kHexString + 1, len, buffer), "ParseAsHexString failed"); + VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly"); + VerifyOrQuit(memcmp(buffer + 1, kParsedArray + 1, len - 1) == 0, "ParseAsHexString() parsed incorrectly"); + VerifyOrQuit(buffer[0] = 0xe, "ParseAsHexString() parsed incorrectly"); + + SuccessOrQuit(ParseAsHexString(kHexString + 2, len, buffer), "ParseAsHexString failed"); + VerifyOrQuit(len == sizeof(kParsedArray) - 1, "ParseAsHexString() parsed incorrectly"); + VerifyOrQuit(memcmp(buffer, kParsedArray + 1, len) == 0, "ParseAsHexString() parsed incorrectly"); + + len = sizeof(buffer) - 1; + VerifyOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kDisallowTruncate) != + OT_ERROR_NONE, + "ParseAsHexString passed with bad input"); + len = sizeof(buffer) - 1; + SuccessOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kAllowTruncate), + "ParseAsHexString failed"); + VerifyOrQuit(len == sizeof(buffer) - 1, "ParseAsHexString() parsed incorrectly"); + VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly"); +} + +int main(void) +{ + TestParsingInts(); + TestParsingHexStrings(); + + printf("All tests passed\n"); + return 0; +}