• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/message.hpp"
41 #include "common/type_traits.hpp"
42 
43 namespace ot {
44 
45 /**
46  * The `FrameBuilder` can be used to construct frame content in a given data buffer.
47  *
48  */
49 class FrameBuilder
50 {
51 public:
52     /**
53      * This method initializes the `FrameBuilder` to use a given buffer.
54      *
55      * `FrameBuilder` MUST be initialized before its other methods are used.
56      *
57      * @param[in] aBuffer   A pointer to a buffer.
58      * @param[in] aLength   The data length (number of bytes in @p aBuffer).
59      *
60      */
61     void Init(void *aBuffer, uint16_t aLength);
62 
63     /**
64      * This method returns a pointer to the start of `FrameBuilder` buffer.
65      *
66      * @returns A pointer to the frame buffer.
67      *
68      */
GetBytes(void) const69     const uint8_t *GetBytes(void) const { return mBuffer; }
70 
71     /**
72      * This method returns the current length of frame (number of bytes appended so far).
73      *
74      * @returns The current frame length.
75      *
76      */
GetLength(void) const77     uint16_t GetLength(void) const { return mLength; }
78 
79     /**
80      * This method returns the maximum length of frame.
81      *
82      * @returns The maximum frame length (max number of bytes in the frame buffer).
83      *
84      */
GetMaxLength(void) const85     uint16_t GetMaxLength(void) const { return mMaxLength; }
86 
87     /**
88      * This method indicates whether or not there are enough bytes remaining in the `FrameBuilder` buffer to append a
89      * given number of bytes.
90      *
91      * @param[in] aLength   The append length.
92      *
93      * @retval TRUE   There are enough remaining bytes to append @p aLength bytes.
94      * @retval FALSE  There are not enough remaining bytes to append @p aLength bytes.
95      *
96      */
CanAppend(uint16_t aLength) const97     bool CanAppend(uint16_t aLength) const { return (static_cast<uint32_t>(mLength) + aLength) <= mMaxLength; }
98 
99     /**
100      * This method appends an `uint8_t` value to the `FrameBuilder`.
101      *
102      * @param[in] aUint8     The `uint8_t` value to append.
103      *
104      * @retval kErrorNone    Successfully appended the value.
105      * @retval kErrorNoBufs  Insufficient available buffers.
106      *
107      */
108     Error AppendUint8(uint8_t aUint8);
109 
110     /**
111      * This method appends an `uint16_t` value assuming big endian encoding to the `FrameBuilder`.
112      *
113      * @param[in] aUint16    The `uint16_t` value to append.
114      *
115      * @retval kErrorNone    Successfully appended the value.
116      * @retval kErrorNoBufs  Insufficient available buffers.
117      *
118      */
119     Error AppendBigEndianUint16(uint16_t aUint16);
120 
121     /**
122      * This method appends an `uint32_t` value assuming big endian encoding to the `FrameBuilder`.
123      *
124      * @param[in] aUint32    The `uint32_t` value to append.
125      *
126      * @retval kErrorNone    Successfully appended the value.
127      * @retval kErrorNoBufs  Insufficient available buffers.
128      *
129      */
130     Error AppendBigEndianUint32(uint32_t aUint32);
131 
132     /**
133      * This method appends an `uint16_t` value assuming little endian encoding to the `FrameBuilder`.
134      *
135      * @param[in] aUint16    The `uint16_t` value to append.
136      *
137      * @retval kErrorNone    Successfully appended the value.
138      * @retval kErrorNoBufs  Insufficient available buffers.
139      *
140      */
141     Error AppendLittleEndianUint16(uint16_t aUint16);
142 
143     /**
144      * This method appends an `uint32_t` value assuming little endian encoding to the `FrameBuilder`.
145      *
146      * @param[in] aUint32    The `uint32_t` value to append.
147      *
148      * @retval kErrorNone    Successfully appended the value.
149      * @retval kErrorNoBufs  Insufficient available buffers.
150      *
151      */
152     Error AppendLittleEndianUint32(uint32_t aUint32);
153 
154     /**
155      * This method appends bytes from a given buffer to the `FrameBuilder`.
156      *
157      * @param[in] aBuffer    A pointer to a data bytes to append.
158      * @param[in] aLength    Number of bytes in @p aBuffer.
159      *
160      * @retval kErrorNone    Successfully appended the bytes.
161      * @retval kErrorNoBufs  Insufficient available buffers.
162      *
163      */
164     Error AppendBytes(const void *aBuffer, uint16_t aLength);
165 
166     /**
167      * This method appends bytes read from a given message to the `FrameBuilder`.
168      *
169      * @param[in] aMessage   The message to read the bytes from.
170      * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
171      * @param[in] aLength    Number of bytes to read from @p aMessage and append.
172      *
173      * @retval kErrorNone    Successfully appended the bytes.
174      * @retval kErrorNoBufs  Insufficient available buffers to append the requested @p aLength bytes.
175      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
176      *
177      */
178     Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
179 
180     /**
181      * This method appends an object to the `FrameBuilder`.
182      *
183      * @tparam    ObjectType  The object type to append.
184      *
185      * @param[in] aObject     A reference to the object to append.
186      *
187      * @retval kErrorNone    Successfully appended the object.
188      * @retval kErrorNoBufs  Insufficient available buffers to append @p aObject.
189      *
190      */
Append(const ObjectType & aObject)191     template <typename ObjectType> Error Append(const ObjectType &aObject)
192     {
193         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
194 
195         return AppendBytes(&aObject, sizeof(ObjectType));
196     }
197 
198     /**
199      * This method writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content.
200      *
201      * This method does not perform any bound checks. The caller MUST ensure that the given data length fits within the
202      * previously appended content. Otherwise the behavior of this method is undefined.
203      *
204      * @param[in] aOffset    The offset to begin writing.
205      * @param[in] aBuffer    A pointer to a data buffer to write.
206      * @param[in] aLength    Number of bytes in @p aBuffer.
207      *
208      */
209     void WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength);
210 
211     /**
212      * This methods writes an object to the `FrameBuilder` at a given offset overwriting previously appended content.
213      *
214      * This method does not perform any bound checks. The caller MUST ensure the given data length fits within the
215      * previously appended content. Otherwise the behavior of this method is undefined.
216      *
217      * @tparam     ObjectType   The object type to write.
218      *
219      * @param[in]  aOffset      The offset to begin writing.
220      * @param[in]  aObject      A reference to the object to write.
221      *
222      */
Write(uint16_t aOffset,const ObjectType & aObject)223     template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
224     {
225         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
226 
227         WriteBytes(aOffset, &aObject, sizeof(ObjectType));
228     }
229 
230 private:
231     uint8_t *mBuffer;
232     uint16_t mLength;
233     uint16_t mMaxLength;
234 };
235 
236 } // namespace ot
237 
238 #endif // FRAME_BUILDER_HPP_
239