/* * 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 #include 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 & flags); void DecodeAndPrintRangeControl(const char * header, BitFlags & 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 & 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 & 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