blob: 268b4c78be7ef1b47a2f19d5cc4a13bb41c9beee [file] [log] [blame]
/*
* 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.
*
*/
#include "Decoder.h"
#include "../logging/Log.h"
#include <lib/core/CHIPSafeCasts.h>
#include <protocols/bdx/BdxMessages.h>
namespace {
constexpr char kProtocolName[] = "Bulk Data Exchange";
constexpr char kUnknown[] = "Unknown";
constexpr char kSendInit[] = "Send Init";
constexpr char kSendAccept[] = "Send Accept";
constexpr char kReceiveInit[] = "Receive Init";
constexpr char kReceiveAccept[] = "Receive Accept";
constexpr char kBlockQuery[] = "Block Query";
constexpr char kBlock[] = "Block";
constexpr char kBlockEOF[] = "Block End Of File";
constexpr char kBlockAck[] = "Block Ack";
constexpr char kBlockAckEOF[] = "Block Ack End Of File";
constexpr char kBlockQueryWithSkip[] = "Block Query With Skip";
constexpr char kDataHeader[] = "Data";
} // namespace
using MessageType = chip::bdx::MessageType;
using RangeControlFlags = chip::bdx::RangeControlFlags;
using TransferControlFlags = chip::bdx::TransferControlFlags;
namespace chip {
namespace trace {
namespace bdx {
using namespace logging;
CHIP_ERROR DecodeTransferInit(System::PacketBufferHandle msgData);
CHIP_ERROR DecodeSendAccept(System::PacketBufferHandle msgData);
CHIP_ERROR DecodeReceiveAccept(System::PacketBufferHandle msgData);
CHIP_ERROR DecodeBlockCounter(System::PacketBufferHandle msgData);
CHIP_ERROR DecodeDataBlock(System::PacketBufferHandle msgData);
CHIP_ERROR DecodeBlockQueryWithSkip(System::PacketBufferHandle msgData);
void DecodeAndPrintTransferControl(const char * header, BitFlags<TransferControlFlags> & flags);
void DecodeAndPrintRangeControl(const char * header, BitFlags<RangeControlFlags> & flags);
void DecodeAndPrintMetadata(const ByteSpan & data);
const char * ToProtocolName()
{
return kProtocolName;
}
const char * ToProtocolMessageTypeName(uint8_t protocolCode)
{
switch (protocolCode)
{
case to_underlying(MessageType::SendInit):
return kSendInit;
case to_underlying(MessageType::SendAccept):
return kSendAccept;
case to_underlying(MessageType::ReceiveInit):
return kReceiveInit;
case to_underlying(MessageType::ReceiveAccept):
return kReceiveAccept;
case to_underlying(MessageType::BlockQuery):
return kBlockQuery;
case to_underlying(MessageType::Block):
return kBlock;
case to_underlying(MessageType::BlockEOF):
return kBlockEOF;
case to_underlying(MessageType::BlockAck):
return kBlockAck;
case to_underlying(MessageType::BlockAckEOF):
return kBlockAckEOF;
case to_underlying(MessageType::BlockQueryWithSkip):
return kBlockQueryWithSkip;
}
return kUnknown;
}
CHIP_ERROR LogAsProtocolMessage(uint8_t protocolCode, const uint8_t * data, size_t len)
{
auto msgData = System::PacketBufferHandle::NewWithData(data, len);
switch (protocolCode)
{
case to_underlying(MessageType::SendInit):
return DecodeTransferInit(std::move(msgData));
case to_underlying(MessageType::SendAccept):
return DecodeSendAccept(std::move(msgData));
case to_underlying(MessageType::ReceiveInit):
return DecodeTransferInit(std::move(msgData));
case to_underlying(MessageType::ReceiveAccept):
return DecodeReceiveAccept(std::move(msgData));
case to_underlying(MessageType::BlockQuery):
return DecodeBlockCounter(std::move(msgData));
case to_underlying(MessageType::Block):
return DecodeDataBlock(std::move(msgData));
case to_underlying(MessageType::BlockEOF):
return DecodeDataBlock(std::move(msgData));
case to_underlying(MessageType::BlockAck):
return DecodeBlockCounter(std::move(msgData));
case to_underlying(MessageType::BlockAckEOF):
return DecodeBlockCounter(std::move(msgData));
case to_underlying(MessageType::BlockQueryWithSkip):
return DecodeBlockQueryWithSkip(std::move(msgData));
}
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR DecodeTransferInit(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength());
chip::bdx::TransferInit msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
auto ptc = msg.TransferCtlOptions;
auto rc = msg.mRangeCtlFlags;
auto pmbs = msg.MaxBlockSize;
auto startofs = msg.StartOffset;
auto len = msg.MaxLength;
auto fdl = msg.FileDesLength;
auto fd = CharSpan(Uint8::to_const_char(msg.FileDesignator), msg.FileDesLength);
auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength);
DecodeAndPrintTransferControl("Proposed Transfer Control", ptc);
DecodeAndPrintRangeControl("Range Control", rc);
Log("Proposed Max Block Size", pmbs);
if (rc.Has(RangeControlFlags::kStartOffset))
{
LogAsHex("Start Offset", startofs);
}
if (rc.Has(RangeControlFlags::kDefLen))
{
LogAsHex("Proposed Max Length", len);
}
Log("File Designator Length", fdl);
Log("File Designator", fd);
DecodeAndPrintMetadata(mdata);
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodeSendAccept(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength());
chip::bdx::SendAccept msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
auto tc = msg.TransferCtlFlags;
auto mbs = msg.MaxBlockSize;
auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength);
DecodeAndPrintTransferControl("Transfer Control", tc);
Log("Max Block Size", mbs);
DecodeAndPrintMetadata(mdata);
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodeReceiveAccept(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength());
chip::bdx::ReceiveAccept msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
auto tc = msg.TransferCtlFlags;
auto rc = msg.mRangeCtlFlags;
auto mbs = msg.MaxBlockSize;
auto len = msg.Length;
auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength);
DecodeAndPrintTransferControl("Transfer Control", tc);
DecodeAndPrintRangeControl("Range Control", rc);
Log("Max Block Size", mbs);
if (rc.Has(RangeControlFlags::kDefLen))
{
LogAsHex("Length", len);
}
DecodeAndPrintMetadata(mdata);
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodeBlockCounter(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndent(kDataHeader);
chip::bdx::CounterMessage msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
Log("BlockCounter", msg.BlockCounter);
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodeDataBlock(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength());
chip::bdx::DataBlock msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
Log("BlockCounter", msg.BlockCounter);
auto data = ByteSpan(msg.Data, msg.DataLength);
Log("Data", data);
return CHIP_NO_ERROR;
}
CHIP_ERROR DecodeBlockQueryWithSkip(System::PacketBufferHandle msgData)
{
auto scopedIndent = ScopedLogIndent(kDataHeader);
chip::bdx::BlockQueryWithSkip msg;
ReturnErrorOnFailure(msg.Parse(msgData.Retain()));
Log("BlockCounter", msg.BlockCounter);
LogAsHex("BytesToSkip", msg.BytesToSkip);
return CHIP_NO_ERROR;
}
void DecodeAndPrintTransferControl(const char * header, BitFlags<TransferControlFlags> & flags)
{
auto scopedIndent = ScopedLogIndentWithFlags(header, flags.Raw());
if (flags.Has(TransferControlFlags::kSenderDrive))
{
Log("SenderDrive");
}
if (flags.Has(TransferControlFlags::kReceiverDrive))
{
Log("ReceivedDrive");
}
if (flags.Has(TransferControlFlags::kAsync))
{
Log("Async");
}
}
void DecodeAndPrintRangeControl(const char * header, BitFlags<RangeControlFlags> & flags)
{
auto scopedIndent = ScopedLogIndentWithFlags(header, flags.Raw());
if (flags.Has(chip::bdx::RangeControlFlags::kDefLen))
{
Log("DefLen");
}
if (flags.Has(RangeControlFlags::kStartOffset))
{
Log("StartOffset");
}
if (flags.Has(RangeControlFlags::kWiderange))
{
Log("Widerange");
}
}
void DecodeAndPrintMetadata(const ByteSpan & data)
{
if (data.size())
{
// TODO Make metadata decoding prettier.
Log("HasMetadata");
}
}
} // namespace bdx
} // namespace trace
} // namespace chip