Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chip-tool] Add support for hex:/str: prefixed OCTET_STRING for compl… #23967

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions examples/chip-tool/commands/clusters/ComplexArgument.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
*
*/

/**
* This file allocate/free memory using the chip platform abstractions
* (Platform::MemoryCalloc and Platform::MemoryFree) for hosting a subset of the
* data model internal types until they are consumed by the DataModel::Encode machinery:
* - chip::app:DataModel::List<T>
* - chip::ByteSpan
* - chip::CharSpan
*
* Memory allocation happens during the 'Setup' phase, while memory deallocation happens
* during the 'Finalize' phase.
*
* The 'Finalize' phase during the destructor phase, and if needed, 'Finalize' will call
* the 'Finalize' phase of its descendant.
*/

#pragma once

#include <app-common/zap-generated/cluster-objects.h>
Expand Down Expand Up @@ -173,17 +188,44 @@ class ComplexArgumentParser
return CHIP_ERROR_INVALID_ARGUMENT;
}

if (strlen(value.asCString()) % 2 != 0)
auto str = value.asString();
auto size = str.size();
uint8_t * buffer = nullptr;

if (IsStrString(str.c_str()))
{
ChipLogError(chipTool, "Error while encoding %s as an octet string: Odd number of characters.", label);
return CHIP_ERROR_INVALID_STRING_LENGTH;
// Skip the prefix
str.erase(0, kStrStringPrefixLen);
size = str.size();

buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size, sizeof(uint8_t)));
memcpy(buffer, str.c_str(), size);
}
else
{
if (IsHexString(str.c_str()))
{
// Skip the prefix
str.erase(0, kHexStringPrefixLen);
size = str.size();
}

if (size % 2 != 0)
{
ChipLogError(chipTool, "Error while encoding %s as a hex string: Odd number of characters.", label);
return CHIP_ERROR_INVALID_STRING_LENGTH;
}

size_t size = strlen(value.asCString());
auto buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size / 2, sizeof(uint8_t)));
size_t octetCount = chip::Encoding::HexToBytes(value.asCString(), size, buffer, size / 2);
buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(size / 2, sizeof(uint8_t)));
size = chip::Encoding::HexToBytes(str.c_str(), size, buffer, size / 2);
if (size == 0)
{
ChipLogError(chipTool, "Error while encoding %s as a hex string.", label);
return CHIP_ERROR_INTERNAL;
}
}

request = chip::ByteSpan(buffer, octetCount);
request = chip::ByteSpan(buffer, size);
return CHIP_NO_ERROR;
}

Expand Down
2 changes: 2 additions & 0 deletions examples/chip-tool/commands/clusters/JsonParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#pragma once

#include "../common/CustomStringPrefix.h"

#include <json/json.h>
#include <lib/core/Optional.h>

Expand Down
20 changes: 10 additions & 10 deletions examples/chip-tool/commands/common/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/

#include "Command.h"
#include "CustomStringPrefix.h"
#include "platform/PlatformManager.h"

#include <functional>
#include <netdb.h>
Expand Down Expand Up @@ -362,10 +364,9 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
// We support two ways to pass an octet string argument. If it happens
// to be all-ASCII, you can just pass it in. Otherwise you can pass in
// "hex:" followed by the hex-encoded bytes.
size_t argLen = strlen(argValue);
static constexpr char hexPrefix[] = "hex:";
constexpr size_t prefixLen = ArraySize(hexPrefix) - 1; // Don't count the null
if (strncmp(argValue, hexPrefix, prefixLen) == 0)
size_t argLen = strlen(argValue);

if (IsHexString(argValue))
{
// Hex-encoded. Decode it into a temporary buffer first, so if we
// run into errors we can do correct "argument is not valid" logging
Expand All @@ -381,7 +382,8 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
return false;
}

size_t octetCount = chip::Encoding::HexToBytes(argValue + prefixLen, argLen - prefixLen, buffer.Get(), argLen);
size_t octetCount =
chip::Encoding::HexToBytes(argValue + kHexStringPrefixLen, argLen - kHexStringPrefixLen, buffer.Get(), argLen);
if (octetCount == 0)
{
return false;
Expand All @@ -393,13 +395,11 @@ bool Command::InitArgument(size_t argIndex, char * argValue)
}

// Just ASCII. Check for the "str:" prefix.
static constexpr char strPrefix[] = "str:";
constexpr size_t strPrefixLen = ArraySize(strPrefix) - 1; // Don't count the null
if (strncmp(argValue, strPrefix, strPrefixLen) == 0)
if (IsStrString(argValue))
{
// Skip the prefix
argValue += strPrefixLen;
argLen -= strPrefixLen;
argValue += kStrStringPrefixLen;
argLen -= kStrStringPrefixLen;
}
*value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen);
return true;
Expand Down
35 changes: 35 additions & 0 deletions examples/chip-tool/commands/common/CustomStringPrefix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

static constexpr char kHexStringPrefix[] = "hex:";
constexpr size_t kHexStringPrefixLen = ArraySize(kHexStringPrefix) - 1; // Don't count the null

static constexpr char kStrStringPrefix[] = "str:";
constexpr size_t kStrStringPrefixLen = ArraySize(kStrStringPrefix) - 1; // Don't count the null

inline bool IsHexString(const char * str)
{
return strncmp(str, kHexStringPrefix, kHexStringPrefixLen) == 0;
}

inline bool IsStrString(const char * str)
{
return strncmp(str, kStrStringPrefix, kStrStringPrefixLen) == 0;
}