[cmd-parser] simplify ParseAsHexString() & Cli::UdpExample::ProcessSend() (#6726)

This commit enhances `CmdLineParser` methods that parse a hex string
adding a new version which allows a (longer) hex string to be parsed
in short segments sequentially. The unit test `test_cmd_line_parser`
is also updated to verify the behavior of the newly added method.

This commit also updates CLI `UdpExample` implementation to use the
new method for parsing message payload data from input hex string and
simplifies how `ProcessSend()` parses different arguments indicating
message payload options.
This commit is contained in:
Abtin Keshavarzian
2021-06-17 10:23:25 -07:00
committed by GitHub
parent d47a3fa9ad
commit e66b9a3958
5 changed files with 274 additions and 187 deletions
+82 -71
View File
@@ -114,88 +114,70 @@ otError UdpExample::ProcessOpen(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessSend(uint8_t aArgsLength, Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otError error = OT_ERROR_NONE;
otMessage * message = nullptr;
otMessageInfo messageInfo;
otMessage * message = nullptr;
uint8_t curArg = 0;
uint16_t payloadLength = 0;
PayloadType payloadType = kTypeText;
uint8_t argIndex = 0;
otMessageSettings messageSettings = {mLinkSecurityEnabled, OT_MESSAGE_PRIORITY_NORMAL};
memset(&messageInfo, 0, sizeof(messageInfo));
// Possible argument formats:
//
// send <text>
// send <type> <value>
// send <ip> <port> <text>
// send <ip> <port> <type> <value>
VerifyOrExit(aArgsLength >= 1 && aArgsLength <= 4, error = OT_ERROR_INVALID_ARGS);
if (aArgsLength > 2)
{
SuccessOrExit(error = aArgs[curArg++].ParseAsIp6Address(messageInfo.mPeerAddr));
SuccessOrExit(error = aArgs[curArg++].ParseAsUint16(messageInfo.mPeerPort));
}
if (aArgsLength == 2 || aArgsLength == 4)
{
uint8_t typePos = curArg++;
if (aArgs[typePos] == "-s")
{
payloadType = kTypeAutoSize;
SuccessOrExit(error = aArgs[curArg].ParseAsUint16(payloadLength));
}
else if (aArgs[typePos] == "-x")
{
payloadLength = aArgs[curArg].GetLength();
payloadType = kTypeHexString;
}
else if (aArgs[typePos] == "-t")
{
payloadType = kTypeText;
}
SuccessOrExit(error = aArgs[argIndex++].ParseAsIp6Address(messageInfo.mPeerAddr));
SuccessOrExit(error = aArgs[argIndex++].ParseAsUint16(messageInfo.mPeerPort));
}
message = otUdpNewMessage(mInterpreter.mInstance, &messageSettings);
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
switch (payloadType)
if (aArgs[argIndex] == "-s")
{
case kTypeText:
SuccessOrExit(error = otMessageAppend(message, aArgs[curArg].GetCString(), aArgs[curArg].GetLength()));
break;
case kTypeAutoSize:
SuccessOrExit(error = WriteCharToBuffer(message, payloadLength));
break;
case kTypeHexString:
{
uint8_t buf[50];
uint16_t bufLen;
uint16_t conversionLength = 0;
const char *hexString = aArgs[curArg].GetCString();
// Auto-generated payload with a given length
while (payloadLength > 0)
uint16_t payloadLength;
argIndex++;
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = aArgs[argIndex].ParseAsUint16(payloadLength));
SuccessOrExit(error = PrepareAutoGeneratedPayload(*message, payloadLength));
}
else if (aArgs[argIndex] == "-x")
{
// Binary hex data payload
argIndex++;
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = PrepareHexStringPaylod(*message, aArgs[argIndex].GetCString()));
}
else
{
// Text payload (same as without specifying the type)
if (aArgs[argIndex] == "-t")
{
bufLen = sizeof(buf);
SuccessOrExit(error = ParseAsHexString(hexString, bufLen, buf, Utils::CmdLineParser::kAllowTruncate));
VerifyOrExit(bufLen > 0, error = OT_ERROR_INVALID_ARGS);
conversionLength = static_cast<uint16_t>(bufLen * 2);
if ((payloadLength & 0x01) != 0)
{
conversionLength -= 1;
}
hexString += conversionLength;
payloadLength -= conversionLength;
SuccessOrExit(error = otMessageAppend(message, buf, bufLen));
argIndex++;
}
break;
}
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = otMessageAppend(message, aArgs[argIndex].GetCString(), aArgs[argIndex].GetLength()));
}
error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo);
SuccessOrExit(error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo));
message = nullptr;
exit:
if (error != OT_ERROR_NONE && message != nullptr)
if (message != nullptr)
{
otMessageFree(message);
}
@@ -219,26 +201,28 @@ otError UdpExample::ProcessLinkSecurity(uint8_t aArgsLength, Arg aArgs[])
return error;
}
otError UdpExample::WriteCharToBuffer(otMessage *aMessage, uint16_t aMessageSize)
otError UdpExample::PrepareAutoGeneratedPayload(otMessage &aMessage, uint16_t aPayloadLength)
{
otError error = OT_ERROR_NONE;
uint8_t character = 0x30; // 0
uint8_t character = '0';
for (uint16_t index = 0; index < aMessageSize; index++)
for (; aPayloadLength != 0; aPayloadLength--)
{
SuccessOrExit(error = otMessageAppend(aMessage, &character, 1));
character++;
SuccessOrExit(error = otMessageAppend(&aMessage, &character, sizeof(character)));
switch (character)
{
case 0x3A: // 9
character = 0x41; // A
case '9':
character = 'A';
break;
case 0x5B: // Z
character = 0x61; // a
case 'Z':
character = 'a';
break;
case 0x7B: // z
character = 0x30; // 0
case 'z':
character = '0';
break;
default:
character++;
break;
}
}
@@ -247,6 +231,33 @@ exit:
return error;
}
otError UdpExample::PrepareHexStringPaylod(otMessage &aMessage, const char *aHexString)
{
enum : uint8_t
{
kBufferSize = 50,
};
otError error;
uint8_t buf[kBufferSize];
uint16_t length;
bool done = false;
while (!done)
{
length = sizeof(buf);
error = Utils::CmdLineParser::ParseAsHexStringSegment(aHexString, length, buf);
VerifyOrExit((error == OT_ERROR_NONE) || (error == OT_ERROR_PENDING));
done = (error == OT_ERROR_NONE);
SuccessOrExit(error = otMessageAppend(&aMessage, buf, length));
}
exit:
return error;
}
otError UdpExample::Process(uint8_t aArgsLength, Arg aArgs[])
{
otError error = OT_ERROR_INVALID_ARGS;