/src/connectedhomeip/examples/common/tracing/decoder/bdx/Decoder.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2022 Project CHIP Authors |
3 | | * All rights reserved. |
4 | | * |
5 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | | * you may not use this file except in compliance with the License. |
7 | | * You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | * |
17 | | */ |
18 | | |
19 | | #include "Decoder.h" |
20 | | |
21 | | #include "../logging/Log.h" |
22 | | |
23 | | #include <lib/core/CHIPSafeCasts.h> |
24 | | #include <protocols/bdx/BdxMessages.h> |
25 | | |
26 | | namespace { |
27 | | constexpr char kProtocolName[] = "Bulk Data Exchange"; |
28 | | |
29 | | constexpr char kUnknown[] = "Unknown"; |
30 | | constexpr char kSendInit[] = "Send Init"; |
31 | | constexpr char kSendAccept[] = "Send Accept"; |
32 | | constexpr char kReceiveInit[] = "Receive Init"; |
33 | | constexpr char kReceiveAccept[] = "Receive Accept"; |
34 | | constexpr char kBlockQuery[] = "Block Query"; |
35 | | constexpr char kBlock[] = "Block"; |
36 | | constexpr char kBlockEOF[] = "Block End Of File"; |
37 | | constexpr char kBlockAck[] = "Block Ack"; |
38 | | constexpr char kBlockAckEOF[] = "Block Ack End Of File"; |
39 | | constexpr char kBlockQueryWithSkip[] = "Block Query With Skip"; |
40 | | |
41 | | constexpr char kDataHeader[] = "Data"; |
42 | | } // namespace |
43 | | |
44 | | using MessageType = chip::bdx::MessageType; |
45 | | using RangeControlFlags = chip::bdx::RangeControlFlags; |
46 | | using TransferControlFlags = chip::bdx::TransferControlFlags; |
47 | | |
48 | | namespace chip { |
49 | | namespace trace { |
50 | | namespace bdx { |
51 | | |
52 | | using namespace logging; |
53 | | |
54 | | CHIP_ERROR DecodeTransferInit(System::PacketBufferHandle msgData); |
55 | | CHIP_ERROR DecodeSendAccept(System::PacketBufferHandle msgData); |
56 | | CHIP_ERROR DecodeReceiveAccept(System::PacketBufferHandle msgData); |
57 | | CHIP_ERROR DecodeBlockCounter(System::PacketBufferHandle msgData); |
58 | | CHIP_ERROR DecodeDataBlock(System::PacketBufferHandle msgData); |
59 | | CHIP_ERROR DecodeBlockQueryWithSkip(System::PacketBufferHandle msgData); |
60 | | void DecodeAndPrintTransferControl(const char * header, BitFlags<TransferControlFlags> & flags); |
61 | | void DecodeAndPrintRangeControl(const char * header, BitFlags<RangeControlFlags> & flags); |
62 | | void DecodeAndPrintMetadata(const ByteSpan & data); |
63 | | |
64 | | const char * ToProtocolName() |
65 | 0 | { |
66 | 0 | return kProtocolName; |
67 | 0 | } |
68 | | |
69 | | const char * ToProtocolMessageTypeName(uint8_t protocolCode) |
70 | 0 | { |
71 | 0 | switch (protocolCode) |
72 | 0 | { |
73 | 0 | case to_underlying(MessageType::SendInit): |
74 | 0 | return kSendInit; |
75 | 0 | case to_underlying(MessageType::SendAccept): |
76 | 0 | return kSendAccept; |
77 | 0 | case to_underlying(MessageType::ReceiveInit): |
78 | 0 | return kReceiveInit; |
79 | 0 | case to_underlying(MessageType::ReceiveAccept): |
80 | 0 | return kReceiveAccept; |
81 | 0 | case to_underlying(MessageType::BlockQuery): |
82 | 0 | return kBlockQuery; |
83 | 0 | case to_underlying(MessageType::Block): |
84 | 0 | return kBlock; |
85 | 0 | case to_underlying(MessageType::BlockEOF): |
86 | 0 | return kBlockEOF; |
87 | 0 | case to_underlying(MessageType::BlockAck): |
88 | 0 | return kBlockAck; |
89 | 0 | case to_underlying(MessageType::BlockAckEOF): |
90 | 0 | return kBlockAckEOF; |
91 | 0 | case to_underlying(MessageType::BlockQueryWithSkip): |
92 | 0 | return kBlockQueryWithSkip; |
93 | 0 | } |
94 | | |
95 | 0 | return kUnknown; |
96 | 0 | } |
97 | | |
98 | | CHIP_ERROR LogAsProtocolMessage(uint8_t protocolCode, const uint8_t * data, size_t len) |
99 | 0 | { |
100 | 0 | auto msgData = System::PacketBufferHandle::NewWithData(data, len); |
101 | |
|
102 | 0 | switch (protocolCode) |
103 | 0 | { |
104 | 0 | case to_underlying(MessageType::SendInit): |
105 | 0 | return DecodeTransferInit(std::move(msgData)); |
106 | 0 | case to_underlying(MessageType::SendAccept): |
107 | 0 | return DecodeSendAccept(std::move(msgData)); |
108 | 0 | case to_underlying(MessageType::ReceiveInit): |
109 | 0 | return DecodeTransferInit(std::move(msgData)); |
110 | 0 | case to_underlying(MessageType::ReceiveAccept): |
111 | 0 | return DecodeReceiveAccept(std::move(msgData)); |
112 | 0 | case to_underlying(MessageType::BlockQuery): |
113 | 0 | return DecodeBlockCounter(std::move(msgData)); |
114 | 0 | case to_underlying(MessageType::Block): |
115 | 0 | return DecodeDataBlock(std::move(msgData)); |
116 | 0 | case to_underlying(MessageType::BlockEOF): |
117 | 0 | return DecodeDataBlock(std::move(msgData)); |
118 | 0 | case to_underlying(MessageType::BlockAck): |
119 | 0 | return DecodeBlockCounter(std::move(msgData)); |
120 | 0 | case to_underlying(MessageType::BlockAckEOF): |
121 | 0 | return DecodeBlockCounter(std::move(msgData)); |
122 | 0 | case to_underlying(MessageType::BlockQueryWithSkip): |
123 | 0 | return DecodeBlockQueryWithSkip(std::move(msgData)); |
124 | 0 | } |
125 | | |
126 | 0 | return CHIP_ERROR_NOT_IMPLEMENTED; |
127 | 0 | } |
128 | | |
129 | | CHIP_ERROR DecodeTransferInit(System::PacketBufferHandle msgData) |
130 | 0 | { |
131 | 0 | auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength()); |
132 | |
|
133 | 0 | chip::bdx::TransferInit msg; |
134 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
135 | | |
136 | 0 | auto ptc = msg.TransferCtlOptions; |
137 | 0 | auto rc = msg.mRangeCtlFlags; |
138 | 0 | auto pmbs = msg.MaxBlockSize; |
139 | 0 | auto startofs = msg.StartOffset; |
140 | 0 | auto len = msg.MaxLength; |
141 | 0 | auto fdl = msg.FileDesLength; |
142 | 0 | auto fd = CharSpan(Uint8::to_const_char(msg.FileDesignator), msg.FileDesLength); |
143 | 0 | auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength); |
144 | |
|
145 | 0 | DecodeAndPrintTransferControl("Proposed Transfer Control", ptc); |
146 | 0 | DecodeAndPrintRangeControl("Range Control", rc); |
147 | 0 | Log("Proposed Max Block Size", pmbs); |
148 | |
|
149 | 0 | if (rc.Has(RangeControlFlags::kStartOffset)) |
150 | 0 | { |
151 | 0 | LogAsHex("Start Offset", startofs); |
152 | 0 | } |
153 | |
|
154 | 0 | if (rc.Has(RangeControlFlags::kDefLen)) |
155 | 0 | { |
156 | 0 | LogAsHex("Proposed Max Length", len); |
157 | 0 | } |
158 | |
|
159 | 0 | Log("File Designator Length", fdl); |
160 | 0 | Log("File Designator", fd); |
161 | 0 | DecodeAndPrintMetadata(mdata); |
162 | |
|
163 | 0 | return CHIP_NO_ERROR; |
164 | 0 | } |
165 | | |
166 | | CHIP_ERROR DecodeSendAccept(System::PacketBufferHandle msgData) |
167 | 0 | { |
168 | 0 | auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength()); |
169 | |
|
170 | 0 | chip::bdx::SendAccept msg; |
171 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
172 | | |
173 | 0 | auto tc = msg.TransferCtlFlags; |
174 | 0 | auto mbs = msg.MaxBlockSize; |
175 | 0 | auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength); |
176 | |
|
177 | 0 | DecodeAndPrintTransferControl("Transfer Control", tc); |
178 | 0 | Log("Max Block Size", mbs); |
179 | 0 | DecodeAndPrintMetadata(mdata); |
180 | |
|
181 | 0 | return CHIP_NO_ERROR; |
182 | 0 | } |
183 | | |
184 | | CHIP_ERROR DecodeReceiveAccept(System::PacketBufferHandle msgData) |
185 | 0 | { |
186 | 0 | auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength()); |
187 | |
|
188 | 0 | chip::bdx::ReceiveAccept msg; |
189 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
190 | | |
191 | 0 | auto tc = msg.TransferCtlFlags; |
192 | 0 | auto rc = msg.mRangeCtlFlags; |
193 | 0 | auto mbs = msg.MaxBlockSize; |
194 | 0 | auto len = msg.Length; |
195 | 0 | auto mdata = ByteSpan(msg.Metadata, msg.MetadataLength); |
196 | |
|
197 | 0 | DecodeAndPrintTransferControl("Transfer Control", tc); |
198 | 0 | DecodeAndPrintRangeControl("Range Control", rc); |
199 | 0 | Log("Max Block Size", mbs); |
200 | |
|
201 | 0 | if (rc.Has(RangeControlFlags::kDefLen)) |
202 | 0 | { |
203 | 0 | LogAsHex("Length", len); |
204 | 0 | } |
205 | |
|
206 | 0 | DecodeAndPrintMetadata(mdata); |
207 | |
|
208 | 0 | return CHIP_NO_ERROR; |
209 | 0 | } |
210 | | |
211 | | CHIP_ERROR DecodeBlockCounter(System::PacketBufferHandle msgData) |
212 | 0 | { |
213 | 0 | auto scopedIndent = ScopedLogIndent(kDataHeader); |
214 | |
|
215 | 0 | chip::bdx::CounterMessage msg; |
216 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
217 | | |
218 | 0 | Log("BlockCounter", msg.BlockCounter); |
219 | |
|
220 | 0 | return CHIP_NO_ERROR; |
221 | 0 | } |
222 | | |
223 | | CHIP_ERROR DecodeDataBlock(System::PacketBufferHandle msgData) |
224 | 0 | { |
225 | 0 | auto scopedIndent = ScopedLogIndentWithSize(kDataHeader, msgData->DataLength()); |
226 | |
|
227 | 0 | chip::bdx::DataBlock msg; |
228 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
229 | | |
230 | 0 | Log("BlockCounter", msg.BlockCounter); |
231 | |
|
232 | 0 | auto data = ByteSpan(msg.Data, msg.DataLength); |
233 | 0 | Log("Data", data); |
234 | |
|
235 | 0 | return CHIP_NO_ERROR; |
236 | 0 | } |
237 | | |
238 | | CHIP_ERROR DecodeBlockQueryWithSkip(System::PacketBufferHandle msgData) |
239 | 0 | { |
240 | 0 | auto scopedIndent = ScopedLogIndent(kDataHeader); |
241 | |
|
242 | 0 | chip::bdx::BlockQueryWithSkip msg; |
243 | 0 | ReturnErrorOnFailure(msg.Parse(msgData.Retain())); |
244 | | |
245 | 0 | Log("BlockCounter", msg.BlockCounter); |
246 | 0 | LogAsHex("BytesToSkip", msg.BytesToSkip); |
247 | |
|
248 | 0 | return CHIP_NO_ERROR; |
249 | 0 | } |
250 | | |
251 | | void DecodeAndPrintTransferControl(const char * header, BitFlags<TransferControlFlags> & flags) |
252 | 0 | { |
253 | 0 | auto scopedIndent = ScopedLogIndentWithFlags(header, flags.Raw()); |
254 | |
|
255 | 0 | if (flags.Has(TransferControlFlags::kSenderDrive)) |
256 | 0 | { |
257 | 0 | Log("SenderDrive"); |
258 | 0 | } |
259 | |
|
260 | 0 | if (flags.Has(TransferControlFlags::kReceiverDrive)) |
261 | 0 | { |
262 | 0 | Log("ReceivedDrive"); |
263 | 0 | } |
264 | |
|
265 | 0 | if (flags.Has(TransferControlFlags::kAsync)) |
266 | 0 | { |
267 | 0 | Log("Async"); |
268 | 0 | } |
269 | 0 | } |
270 | | |
271 | | void DecodeAndPrintRangeControl(const char * header, BitFlags<RangeControlFlags> & flags) |
272 | 0 | { |
273 | 0 | auto scopedIndent = ScopedLogIndentWithFlags(header, flags.Raw()); |
274 | |
|
275 | 0 | if (flags.Has(chip::bdx::RangeControlFlags::kDefLen)) |
276 | 0 | { |
277 | 0 | Log("DefLen"); |
278 | 0 | } |
279 | |
|
280 | 0 | if (flags.Has(RangeControlFlags::kStartOffset)) |
281 | 0 | { |
282 | 0 | Log("StartOffset"); |
283 | 0 | } |
284 | |
|
285 | 0 | if (flags.Has(RangeControlFlags::kWiderange)) |
286 | 0 | { |
287 | 0 | Log("Widerange"); |
288 | 0 | } |
289 | 0 | } |
290 | | |
291 | | void DecodeAndPrintMetadata(const ByteSpan & data) |
292 | 0 | { |
293 | 0 | if (data.size()) |
294 | 0 | { |
295 | | // TODO Make metadata decoding prettier. |
296 | 0 | Log("HasMetadata"); |
297 | 0 | } |
298 | 0 | } |
299 | | |
300 | | } // namespace bdx |
301 | | } // namespace trace |
302 | | } // namespace chip |