Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file defines structures and utility methods for working with BDX
22 : * messages, mainly for writing to and reading from PacketBuffers.
23 : */
24 :
25 : #pragma once
26 :
27 : #include <lib/support/BitFlags.h>
28 : #include <lib/support/BufferWriter.h>
29 : #include <lib/support/CodeUtils.h>
30 : #include <protocols/Protocols.h>
31 : #include <protocols/bdx/StatusCode.h>
32 : #include <system/SystemPacketBuffer.h>
33 :
34 : namespace chip {
35 : namespace bdx {
36 :
37 : inline constexpr uint16_t kMaxFileDesignatorLen = 0xFF;
38 :
39 : inline constexpr char kProtocolName[] = "BDX";
40 :
41 : enum class MessageType : uint8_t
42 : {
43 : SendInit = 0x01,
44 : SendAccept = 0x02,
45 : ReceiveInit = 0x04,
46 : ReceiveAccept = 0x05,
47 : BlockQuery = 0x10,
48 : Block = 0x11,
49 : BlockEOF = 0x12,
50 : BlockAck = 0x13,
51 : BlockAckEOF = 0x14,
52 : BlockQueryWithSkip = 0x15,
53 : };
54 :
55 : enum class TransferControlFlags : uint8_t
56 : {
57 : // first 4 bits reserved for version
58 : kSenderDrive = (1U << 4),
59 : kReceiverDrive = (1U << 5),
60 : kAsync = (1U << 6),
61 : };
62 :
63 : enum class RangeControlFlags : uint8_t
64 : {
65 : kDefLen = (1U),
66 : kStartOffset = (1U << 1),
67 : kWiderange = (1U << 4),
68 : };
69 :
70 : /**
71 : * @brief
72 : * Interface for defining methods that apply to all BDX messages.
73 : */
74 : struct BdxMessage
75 : {
76 : /**
77 : * @brief
78 : * Parse data from an PacketBuffer into a BdxMessage struct.
79 : *
80 : * Note that this may store pointers that point into the passed PacketBuffer,
81 : * so it is essential that the underlying PacketBuffer is not modified until after this
82 : * struct is no longer needed.
83 : *
84 : * @param[in] aBuffer A PacketBufferHandle with a reference to the PacketBuffer containing the data.
85 : *
86 : * @return CHIP_ERROR Return an error if the message format is invalid and/or can't be parsed
87 : */
88 : CHECK_RETURN_VALUE
89 : virtual CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) = 0;
90 :
91 : /**
92 : * @brief
93 : * Write the message fields to a buffer using the provided BufferWriter.
94 : *
95 : * It is up to the caller to use BufferWriter::Fit() to verify that the write was
96 : * successful. This method will also not check for correctness or completeness for
97 : * any of the fields - it is the caller's responsibility to ensure that the fields
98 : * align with BDX specifications.
99 : *
100 : * @param aBuffer A BufferWriter object that will be used to write the message
101 : */
102 : virtual Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const = 0;
103 :
104 : /**
105 : * @brief
106 : * Returns the size of buffer needed to write the message.
107 : */
108 : virtual size_t MessageSize() const = 0;
109 :
110 : #if CHIP_AUTOMATION_LOGGING
111 : /**
112 : * @brief
113 : * Log all parameters for this message.
114 : */
115 : virtual void LogMessage(bdx::MessageType messageType) const = 0;
116 : #endif // CHIP_AUTOMATION_LOGGING
117 :
118 82 : virtual ~BdxMessage() = default;
119 : };
120 :
121 : /*
122 : * A structure for representing a SendInit or ReceiveInit message (both contain
123 : * identical parameters).
124 : */
125 : struct TransferInit : public BdxMessage
126 : {
127 : bool operator==(const TransferInit &) const;
128 :
129 : // Proposed Transfer Control (required)
130 : BitFlags<TransferControlFlags> TransferCtlOptions;
131 : uint8_t Version = 0; ///< The highest version supported by the sender
132 :
133 : // Range Control
134 : BitFlags<RangeControlFlags> mRangeCtlFlags;
135 :
136 : // All required
137 : uint16_t MaxBlockSize = 0; ///< Proposed max block size to use in transfer
138 : uint64_t StartOffset = 0; ///< Proposed start offset of data. 0 for no offset
139 : uint64_t MaxLength = 0; ///< Proposed max length of data in transfer, 0 for indefinite
140 :
141 : // File designator (required) and additional metadata (optional, TLV format)
142 : // WARNING: there is no guarantee at any point that these pointers will point to valid memory. The Buffer field should be used
143 : // to hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
144 : const uint8_t * FileDesignator = nullptr;
145 : uint16_t FileDesLength = 0; ///< Length of file designator string (not including null-terminator)
146 : const uint8_t * Metadata = nullptr;
147 : size_t MetadataLength = 0;
148 :
149 : // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
150 : System::PacketBufferHandle Buffer;
151 :
152 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
153 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
154 : size_t MessageSize() const override;
155 : #if CHIP_AUTOMATION_LOGGING
156 : void LogMessage(bdx::MessageType messageType) const override;
157 : #endif // CHIP_AUTOMATION_LOGGING
158 : };
159 :
160 : using SendInit = TransferInit;
161 : using ReceiveInit = TransferInit;
162 :
163 : /*
164 : * A structure for representing a SendAccept message.
165 : */
166 : struct SendAccept : public BdxMessage
167 : {
168 : bool operator==(const SendAccept &) const;
169 :
170 : // Transfer Control (required, only one should be set)
171 : BitFlags<TransferControlFlags> TransferCtlFlags;
172 :
173 : uint8_t Version = 0; ///< The agreed upon version for the transfer (required)
174 : uint16_t MaxBlockSize = 0; ///< Chosen max block size to use in transfer (required)
175 :
176 : // Additional metadata (optional, TLV format)
177 : // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
178 : // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
179 : const uint8_t * Metadata = nullptr;
180 : size_t MetadataLength = 0;
181 :
182 : // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
183 : System::PacketBufferHandle Buffer;
184 :
185 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
186 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
187 : size_t MessageSize() const override;
188 : #if CHIP_AUTOMATION_LOGGING
189 : void LogMessage(bdx::MessageType messageType) const override;
190 : #endif // CHIP_AUTOMATION_LOGGING
191 : };
192 :
193 : /**
194 : * A structure for representing ReceiveAccept messages.
195 : */
196 : struct ReceiveAccept : public BdxMessage
197 : {
198 : bool operator==(const ReceiveAccept &) const;
199 :
200 : // Transfer Control (required, only one should be set)
201 : BitFlags<TransferControlFlags> TransferCtlFlags;
202 :
203 : // Range Control
204 : BitFlags<RangeControlFlags> mRangeCtlFlags;
205 :
206 : // All required
207 : uint8_t Version = 0; ///< The agreed upon version for the transfer
208 : uint16_t MaxBlockSize = 0; ///< Chosen max block size to use in transfer
209 : uint64_t StartOffset = 0; ///< Chosen start offset of data. 0 for no offset.
210 : uint64_t Length = 0; ///< Length of transfer. 0 if length is indefinite.
211 :
212 : // Additional metadata (optional, TLV format)
213 : // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
214 : // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
215 : const uint8_t * Metadata = nullptr;
216 : size_t MetadataLength = 0;
217 :
218 : // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
219 : System::PacketBufferHandle Buffer;
220 :
221 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
222 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
223 : size_t MessageSize() const override;
224 : #if CHIP_AUTOMATION_LOGGING
225 : void LogMessage(bdx::MessageType messageType) const override;
226 : #endif // CHIP_AUTOMATION_LOGGING
227 : };
228 :
229 : /**
230 : * A struct for representing messages contiaining just a counter field. Can be used to
231 : * represent BlockQuery, BlockAck, and BlockAckEOF.
232 : */
233 : struct CounterMessage : public BdxMessage
234 : {
235 : bool operator==(const CounterMessage &) const;
236 :
237 : uint32_t BlockCounter = 0;
238 :
239 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
240 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
241 : size_t MessageSize() const override;
242 : #if CHIP_AUTOMATION_LOGGING
243 : void LogMessage(bdx::MessageType messageType) const override;
244 : #endif // CHIP_AUTOMATION_LOGGING
245 : };
246 :
247 : using BlockQuery = CounterMessage;
248 : using BlockAck = CounterMessage;
249 : using BlockAckEOF = CounterMessage;
250 :
251 : /**
252 : * A struct that represents a message containing actual data (Block, BlockEOF).
253 : */
254 : struct DataBlock : public BdxMessage
255 : {
256 : bool operator==(const DataBlock &) const;
257 :
258 : uint32_t BlockCounter = 0;
259 :
260 : // WARNING: there is no guarantee at any point that this pointer will point to valid memory. The Buffer field should be used to
261 : // hold a reference to the PacketBuffer containing the data in order to ensure the data is not freed.
262 : const uint8_t * Data = nullptr;
263 : size_t DataLength = 0;
264 :
265 : // Retain ownership of the packet buffer so that the FileDesignator and Metadata pointers remain valid.
266 : System::PacketBufferHandle Buffer;
267 :
268 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
269 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
270 : size_t MessageSize() const override;
271 : #if CHIP_AUTOMATION_LOGGING
272 : void LogMessage(bdx::MessageType messageType) const override;
273 : #endif // CHIP_AUTOMATION_LOGGING
274 : };
275 :
276 : using Block = DataBlock;
277 : using BlockEOF = DataBlock;
278 :
279 : struct BlockQueryWithSkip : public BdxMessage
280 : {
281 : bool operator==(const BlockQueryWithSkip &) const;
282 :
283 : uint32_t BlockCounter = 0;
284 : uint64_t BytesToSkip = 0;
285 :
286 : CHIP_ERROR Parse(System::PacketBufferHandle aBuffer) override;
287 : Encoding::LittleEndian::BufferWriter & WriteToBuffer(Encoding::LittleEndian::BufferWriter & aBuffer) const override;
288 : size_t MessageSize() const override;
289 : #if CHIP_AUTOMATION_LOGGING
290 : void LogMessage(bdx::MessageType messageType) const override;
291 : #endif // CHIP_AUTOMATION_LOGGING
292 : };
293 :
294 : } // namespace bdx
295 :
296 : namespace Protocols {
297 : template <>
298 : struct MessageTypeTraits<bdx::MessageType>
299 : {
300 41 : static constexpr const Protocols::Id & ProtocolId() { return BDX::Id; }
301 :
302 16 : static auto GetTypeToNameTable()
303 : {
304 : static const std::array<MessageTypeNameLookup, 10> typeToNameTable = {
305 : {
306 : { bdx::MessageType::SendInit, "SendInit" },
307 : { bdx::MessageType::SendAccept, "SendAccept" },
308 : { bdx::MessageType::ReceiveInit, "ReceiveInit" },
309 : { bdx::MessageType::ReceiveAccept, "ReceiveAccept" },
310 : { bdx::MessageType::BlockQuery, "BlockQuery" },
311 : { bdx::MessageType::Block, "Block" },
312 : { bdx::MessageType::BlockEOF, "BlockEOF" },
313 : { bdx::MessageType::BlockAck, "BlockAck" },
314 : { bdx::MessageType::BlockAckEOF, "BlockAckEOF" },
315 : { bdx::MessageType::BlockQueryWithSkip, "BlockQueryWithSkip" },
316 : },
317 : };
318 :
319 16 : return &typeToNameTable;
320 : }
321 : };
322 : } // namespace Protocols
323 :
324 : } // namespace chip
|