1 /*
2  *  Copyright (c) 2022, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *  This file defines OpenThread `FrameBuilder` class.
32  */
33 
34 #ifndef FRAME_BUILDER_HPP_
35 #define FRAME_BUILDER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "common/error.hpp"
40 #include "common/type_traits.hpp"
41 #include "mac/mac_types.hpp"
42 
43 namespace ot {
44 class Message;
45 
46 /**
47  * The `FrameBuilder` can be used to construct frame content in a given data buffer.
48  *
49  */
50 class FrameBuilder
51 {
52 public:
53     /**
54      * This method initializes the `FrameBuilder` to use a given buffer.
55      *
56      * `FrameBuilder` MUST be initialized before its other methods are used.
57      *
58      * @param[in] aBuffer   A pointer to a buffer.
59      * @param[in] aLength   The data length (number of bytes in @p aBuffer).
60      *
61      */
62     void Init(void *aBuffer, uint16_t aLength);
63 
64     /**
65      * This method returns a pointer to the start of `FrameBuilder` buffer.
66      *
67      * @returns A pointer to the frame buffer.
68      *
69      */
GetBytes(void) const70     const uint8_t *GetBytes(void) const { return mBuffer; }
71 
72     /**
73      * This method returns the current length of frame (number of bytes appended so far).
74      *
75      * @returns The current frame length.
76      *
77      */
GetLength(void) const78     uint16_t GetLength(void) const { return mLength; }
79 
80     /**
81      * This method returns the maximum length of the frame.
82      *
83      * @returns The maximum frame length (max number of bytes in the frame buffer).
84      *
85      */
GetMaxLength(void) const86     uint16_t GetMaxLength(void) const { return mMaxLength; }
87 
88     /**
89      * This method sets the maximum length of the frame.
90      *
91      * This method does not perform any checks on the new given length. The caller MUST ensure that the specified max
92      * length is valid for the frame buffer.
93      *
94      * @param[in] aLength  The maximum frame length.
95      *
96      */
SetMaxLength(uint16_t aLength)97     void SetMaxLength(uint16_t aLength) { mMaxLength = aLength; }
98 
99     /**
100      * This method returns the remaining length (number of bytes that can be appended) in the frame.
101      *
102      * @returns The remaining length.
103      *
104      */
GetRemainingLength(void) const105     uint16_t GetRemainingLength(void) const { return mMaxLength - mLength; }
106 
107     /**
108      * This method indicates whether or not there are enough bytes remaining in the `FrameBuilder` buffer to append a
109      * given number of bytes.
110      *
111      * @param[in] aLength   The append length.
112      *
113      * @retval TRUE   There are enough remaining bytes to append @p aLength bytes.
114      * @retval FALSE  There are not enough remaining bytes to append @p aLength bytes.
115      *
116      */
CanAppend(uint16_t aLength) const117     bool CanAppend(uint16_t aLength) const { return (static_cast<uint32_t>(mLength) + aLength) <= mMaxLength; }
118 
119     /**
120      * This method appends an `uint8_t` value to the `FrameBuilder`.
121      *
122      * @param[in] aUint8     The `uint8_t` value to append.
123      *
124      * @retval kErrorNone    Successfully appended the value.
125      * @retval kErrorNoBufs  Insufficient available buffers.
126      *
127      */
128     Error AppendUint8(uint8_t aUint8);
129 
130     /**
131      * This method appends an `uint16_t` value assuming big endian encoding to the `FrameBuilder`.
132      *
133      * @param[in] aUint16    The `uint16_t` value to append.
134      *
135      * @retval kErrorNone    Successfully appended the value.
136      * @retval kErrorNoBufs  Insufficient available buffers.
137      *
138      */
139     Error AppendBigEndianUint16(uint16_t aUint16);
140 
141     /**
142      * This method appends an `uint32_t` value assuming big endian encoding to the `FrameBuilder`.
143      *
144      * @param[in] aUint32    The `uint32_t` value to append.
145      *
146      * @retval kErrorNone    Successfully appended the value.
147      * @retval kErrorNoBufs  Insufficient available buffers.
148      *
149      */
150     Error AppendBigEndianUint32(uint32_t aUint32);
151 
152     /**
153      * This method appends an `uint16_t` value assuming little endian encoding to the `FrameBuilder`.
154      *
155      * @param[in] aUint16    The `uint16_t` value to append.
156      *
157      * @retval kErrorNone    Successfully appended the value.
158      * @retval kErrorNoBufs  Insufficient available buffers.
159      *
160      */
161     Error AppendLittleEndianUint16(uint16_t aUint16);
162 
163     /**
164      * This method appends an `uint32_t` value assuming little endian encoding to the `FrameBuilder`.
165      *
166      * @param[in] aUint32    The `uint32_t` value to append.
167      *
168      * @retval kErrorNone    Successfully appended the value.
169      * @retval kErrorNoBufs  Insufficient available buffers.
170      *
171      */
172     Error AppendLittleEndianUint32(uint32_t aUint32);
173 
174     /**
175      * This method appends bytes from a given buffer to the `FrameBuilder`.
176      *
177      * @param[in] aBuffer    A pointer to a data bytes to append.
178      * @param[in] aLength    Number of bytes in @p aBuffer.
179      *
180      * @retval kErrorNone    Successfully appended the bytes.
181      * @retval kErrorNoBufs  Insufficient available buffers.
182      *
183      */
184     Error AppendBytes(const void *aBuffer, uint16_t aLength);
185 
186     /**
187      * This method appends a given `Mac::Address` to the `FrameBuilder`.
188      *
189      * @param[in] aMacAddress  A `Mac::Address` to append.
190      *
191      * @retval kErrorNone    Successfully appended the address.
192      * @retval kErrorNoBufs  Insufficient available buffers.
193      *
194      */
195     Error AppendMacAddress(const Mac::Address &aMacAddress);
196 
197 #if OPENTHREAD_FTD || OPENTHREAD_MTD
198     /**
199      * This method appends bytes read from a given message to the `FrameBuilder`.
200      *
201      * @param[in] aMessage   The message to read the bytes from.
202      * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
203      * @param[in] aLength    Number of bytes to read from @p aMessage and append.
204      *
205      * @retval kErrorNone    Successfully appended the bytes.
206      * @retval kErrorNoBufs  Insufficient available buffers to append the requested @p aLength bytes.
207      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
208      *
209      */
210     Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
211 #endif
212 
213     /**
214      * This method appends an object to the `FrameBuilder`.
215      *
216      * @tparam    ObjectType  The object type to append.
217      *
218      * @param[in] aObject     A reference to the object to append.
219      *
220      * @retval kErrorNone    Successfully appended the object.
221      * @retval kErrorNoBufs  Insufficient available buffers to append @p aObject.
222      *
223      */
Append(const ObjectType & aObject)224     template <typename ObjectType> Error Append(const ObjectType &aObject)
225     {
226         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
227 
228         return AppendBytes(&aObject, sizeof(ObjectType));
229     }
230 
231     /**
232      * This method writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content.
233      *
234      * This method does not perform any bound checks. The caller MUST ensure that the given data length fits within the
235      * previously appended content. Otherwise the behavior of this method is undefined.
236      *
237      * @param[in] aOffset    The offset to begin writing.
238      * @param[in] aBuffer    A pointer to a data buffer to write.
239      * @param[in] aLength    Number of bytes in @p aBuffer.
240      *
241      */
242     void WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength);
243 
244     /**
245      * This methods writes an object to the `FrameBuilder` at a given offset overwriting previously appended content.
246      *
247      * This method does not perform any bound checks. The caller MUST ensure the given data length fits within the
248      * previously appended content. Otherwise the behavior of this method is undefined.
249      *
250      * @tparam     ObjectType   The object type to write.
251      *
252      * @param[in]  aOffset      The offset to begin writing.
253      * @param[in]  aObject      A reference to the object to write.
254      *
255      */
Write(uint16_t aOffset,const ObjectType & aObject)256     template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
257     {
258         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
259 
260         WriteBytes(aOffset, &aObject, sizeof(ObjectType));
261     }
262 
263     /**
264      * This method inserts bytes in `FrameBuilder` at a given offset, moving previous content forward.
265      *
266      * The caller MUST ensure that @p aOffset is within the current frame length (from 0 up to and including
267      * `GetLength()`). Otherwise the behavior of this method is undefined.
268      *
269      * @param[in] aOffset   The offset to insert bytes.
270      * @param[in] aBuffer   A pointer to a data buffer to insert.
271      * @param[in] aLength   Number of bytes in @p aBuffer.
272      *
273      * @retval kErrorNone    Successfully inserted the bytes.
274      * @retval kErrorNoBufs  Insufficient available buffers to insert the bytes.
275      *
276      */
277     Error InsertBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength);
278 
279     /**
280      * This method inserts an object in `FrameBuilder` at a given offset, moving previous content forward.
281      *
282      * The caller MUST ensure that @p aOffset is within the current frame length (from 0 up to and including
283      * `GetLength()`). Otherwise the behavior of this method is undefined.
284      *
285      * @tparam     ObjectType   The object type to insert.
286      *
287      * @param[in]  aOffset      The offset to insert bytes.
288      * @param[in]  aObject      A reference to the object to insert.
289      *
290      * @retval kErrorNone       Successfully inserted the bytes.
291      * @retval kErrorNoBufs     Insufficient available buffers to insert the bytes.
292      *
293      */
Insert(uint16_t aOffset,const ObjectType & aObject)294     template <typename ObjectType> Error Insert(uint16_t aOffset, const ObjectType &aObject)
295     {
296         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
297 
298         return InsertBytes(aOffset, &aObject, sizeof(ObjectType));
299     }
300 
301     /**
302      * This method removes a given number of bytes in `FrameBuilder` at a given offset, moving existing content
303      * after removed bytes backward.
304      *
305      * This method does not perform any bound checks. The caller MUST ensure that the given length and offset fits
306      * within the previously appended content. Otherwise the behavior of this method is undefined.
307      *
308      * @param[in] aOffset   The offset to remove bytes from.
309      * @param[in] aLength   The number of bytes to remove.
310      *
311      */
312     void RemoveBytes(uint16_t aOffset, uint16_t aLength);
313 
314 private:
315     uint8_t *mBuffer;
316     uint16_t mLength;
317     uint16_t mMaxLength;
318 };
319 
320 } // namespace ot
321 
322 #endif // FRAME_BUILDER_HPP_
323