1 /*
2 * FreeRTOS+TCP V2.3.1
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * http://aws.amazon.com/freertos
23 * http://www.FreeRTOS.org
24 */
25
26 /**
27 * @file FreeRTOS_BitConfig.c
28 * @brief Some functions that help when analysing a binary stream of information.
29 * It offers an alternative to using packet structs with unaligned data members.
30 */
31
32 /* Standard includes. */
33 #include <stdint.h>
34
35 /* FreeRTOS includes. */
36 #include "FreeRTOS.h"
37 #include "task.h"
38 #include "semphr.h"
39
40 /* FreeRTOS+TCP includes. */
41 #include "FreeRTOS_IP.h"
42 #include "FreeRTOS_UDP_IP.h"
43 #include "FreeRTOS_Sockets.h"
44 #include "FreeRTOS_BitConfig.h"
45
46 /*-----------------------------------------------------------*/
47
48 /**
49 * @brief Initialise a bit-config struct.
50 *
51 * @param[in] pxConfig The structure containing a copy of the bits.
52 * @param[in] pucData Not NULL if a bit-stream must be analysed, otherwise NULL.
53 * @param[in] uxSize The length of the binary data stream.
54 *
55 * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
56 */
xBitConfig_init(BitConfig_t * pxConfig,const uint8_t * pucData,size_t uxSize)57 BaseType_t xBitConfig_init( BitConfig_t * pxConfig,
58 const uint8_t * pucData,
59 size_t uxSize )
60 {
61 BaseType_t xResult = pdFALSE;
62
63 ( void ) memset( ( void * ) pxConfig, 0, sizeof( *pxConfig ) );
64 pxConfig->ucContents = ( uint8_t * ) pvPortMalloc( uxSize );
65
66 if( pxConfig->ucContents != NULL )
67 {
68 pxConfig->uxSize = uxSize;
69
70 if( pucData != NULL )
71 {
72 ( void ) memcpy( pxConfig->ucContents, pucData, uxSize );
73 }
74 else
75 {
76 ( void ) memset( pxConfig->ucContents, 0, uxSize );
77 }
78
79 xResult = pdTRUE;
80 }
81 else
82 {
83 pxConfig->xHasError = pdTRUE;
84 }
85
86 return xResult;
87 }
88 /*-----------------------------------------------------------*/
89
90 /**
91 * @brief Read from a bit-config struct.
92 *
93 * @param[in] pxConfig The structure containing a copy of the bits.
94 * @param[in] pucData Not NULL if a bit-stream must be analysed, otherwise NULL.
95 * @param[in] uxSize The length of the binary data stream.
96 *
97 * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
98 */
xBitConfig_read_uc(BitConfig_t * pxConfig,uint8_t * pucData,size_t uxSize)99 BaseType_t xBitConfig_read_uc( BitConfig_t * pxConfig,
100 uint8_t * pucData,
101 size_t uxSize )
102 {
103 BaseType_t xResult = pdFALSE;
104 const size_t uxNeeded = uxSize;
105
106 if( pxConfig->xHasError == pdFALSE )
107 {
108 if( ( pxConfig->uxIndex + uxNeeded ) <= pxConfig->uxSize )
109 {
110 if( pucData != NULL )
111 {
112 ( void ) memcpy( pucData, &( pxConfig->ucContents[ pxConfig->uxIndex ] ), uxNeeded );
113 }
114 else
115 {
116 /* Caller just wants to skip some bytes. */
117 }
118
119 pxConfig->uxIndex += uxNeeded;
120 xResult = pdTRUE;
121 }
122 else
123 {
124 pxConfig->xHasError = pdTRUE;
125 }
126 }
127
128 return xResult;
129 }
130 /*-----------------------------------------------------------*/
131
132 /**
133 * @brief Peek the last byte from a bit-config struct.
134 *
135 * @param[in] pxConfig The structure containing a copy of the bits.
136 * @param[in] pucData The buffer to stored peeked data.
137 * @param[in] uxSize The length of the binary data stream.
138 *
139 * @return pdTRUE if the malloc was OK, otherwise pdFALSE.
140 */
pucBitConfig_peek_last_index_uc(BitConfig_t * pxConfig,uint8_t * pucData,size_t uxSize)141 BaseType_t pucBitConfig_peek_last_index_uc( BitConfig_t * pxConfig,
142 uint8_t * pucData,
143 size_t uxSize )
144 {
145 BaseType_t xResult = pdFALSE;
146 const size_t uxNeeded = uxSize;
147
148 if( pxConfig->xHasError == pdFALSE )
149 {
150 if( ( pxConfig->uxIndex >= uxNeeded ) && ( pucData != NULL ) )
151 {
152 ( void ) memcpy( pucData, &( pxConfig->ucContents[ pxConfig->uxIndex - uxNeeded ] ), uxNeeded );
153
154 xResult = pdTRUE;
155 }
156 else
157 {
158 /* Not support to peek length larger than write. */
159 pxConfig->xHasError = pdTRUE;
160 }
161 }
162
163 return xResult;
164 }
165
166 /**
167 * @brief Read a byte from the bit stream.
168 *
169 * @param[in] pxConfig The structure containing a copy of the bits.
170 *
171 * @return A byte value. When there was not enough data, xHasError will be set.
172 */
ucBitConfig_read_8(BitConfig_t * pxConfig)173 uint8_t ucBitConfig_read_8( BitConfig_t * pxConfig )
174 {
175 uint8_t ucResult = 0xffU;
176 const size_t uxNeeded = sizeof ucResult;
177 uint8_t pucData[ sizeof ucResult ];
178
179 if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
180 {
181 ucResult = pucData[ 0 ];
182 }
183
184 return ucResult;
185 }
186 /*-----------------------------------------------------------*/
187
188 /**
189 * @brief Read 2 bytes from the bit stream.
190 *
191 * @param[in] pxConfig The structure containing a copy of the bits.
192 *
193 * @return A 16-bit value. When there was not enough data, xHasError will be set.
194 */
usBitConfig_read_16(BitConfig_t * pxConfig)195 uint16_t usBitConfig_read_16( BitConfig_t * pxConfig )
196 {
197 uint16_t usResult = 0xffffU;
198 const size_t uxNeeded = sizeof usResult;
199 uint8_t pucData[ sizeof usResult ];
200
201 if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
202 {
203 usResult = ( uint16_t ) ( ( ( ( uint16_t ) pucData[ 0 ] ) << 8 ) |
204 ( ( ( uint16_t ) pucData[ 1 ] ) ) );
205 }
206
207 return usResult;
208 }
209 /*-----------------------------------------------------------*/
210
211 /**
212 * @brief Read 4 bytes from the bit stream.
213 *
214 * @param[in] pxConfig The structure containing a copy of the bits.
215 *
216 * @return A 32-bit value. When there was not enough data, xHasError will be set.
217 */
ulBitConfig_read_32(BitConfig_t * pxConfig)218 uint32_t ulBitConfig_read_32( BitConfig_t * pxConfig )
219 {
220 uint32_t ulResult = 0xffffffffU;
221 const size_t uxNeeded = sizeof ulResult;
222 uint8_t pucData[ sizeof ulResult ];
223
224 if( xBitConfig_read_uc( pxConfig, pucData, uxNeeded ) != pdFALSE )
225 {
226 ulResult = ( ( ( uint32_t ) pucData[ 0 ] ) << 24 ) |
227 ( ( ( uint32_t ) pucData[ 1 ] ) << 16 ) |
228 ( ( ( uint32_t ) pucData[ 2 ] ) << 8 ) |
229 ( ( ( uint32_t ) pucData[ 3 ] ) );
230 }
231
232 return ulResult;
233 }
234 /*-----------------------------------------------------------*/
235
236 /**
237 * @brief Read any number bytes from the bit stream.
238 *
239 * @param[in] pxConfig The structure containing a copy of the bit stream.
240 * @param[in] pucData The binary data to be written.
241 * @param[in] uxSize The number of bytes to be written.
242 *
243 * There is no return value. If the operation has failed,
244 * the field xHasError will be set.
245 */
vBitConfig_write_uc(BitConfig_t * pxConfig,const uint8_t * pucData,size_t uxSize)246 void vBitConfig_write_uc( BitConfig_t * pxConfig,
247 const uint8_t * pucData,
248 size_t uxSize )
249 {
250 const size_t uxNeeded = uxSize;
251
252 if( pxConfig->xHasError == pdFALSE )
253 {
254 if( pxConfig->uxIndex <= ( pxConfig->uxSize - uxNeeded ) )
255 {
256 uint8_t * pucDestination = &( pxConfig->ucContents[ pxConfig->uxIndex ] );
257 ( void ) memcpy( pucDestination, pucData, uxNeeded );
258 pxConfig->uxIndex += uxNeeded;
259 }
260 else
261 {
262 pxConfig->xHasError = pdTRUE;
263 }
264 }
265 }
266 /*-----------------------------------------------------------*/
267
268 /**
269 * @brief Write a byte to the bit stream.
270 *
271 * @param[in] pxConfig The structure containing a copy of the bits.
272 * @param[in] ucValue The byte to be written.
273 *
274 * There is no return value. If the operation has failed,
275 * the field xHasError will be set.
276 */
vBitConfig_write_8(BitConfig_t * pxConfig,uint8_t ucValue)277 void vBitConfig_write_8( BitConfig_t * pxConfig,
278 uint8_t ucValue )
279 {
280 const size_t uxNeeded = sizeof ucValue;
281
282 vBitConfig_write_uc( pxConfig, &( ucValue ), uxNeeded );
283 }
284 /*-----------------------------------------------------------*/
285
286 /**
287 * @brief Write a short word to the bit stream.
288 *
289 * @param[in] pxConfig The structure containing a copy of the bits.
290 * @param[in] usValue The 16-bit value to be written.
291 *
292 * There is no return value. If the operation has failed,
293 * the field xHasError will be set.
294 */
vBitConfig_write_16(BitConfig_t * pxConfig,uint16_t usValue)295 void vBitConfig_write_16( BitConfig_t * pxConfig,
296 uint16_t usValue )
297 {
298 const size_t uxNeeded = sizeof usValue;
299 uint8_t pucData[ sizeof usValue ];
300
301 pucData[ 0 ] = ( uint8_t ) ( ( usValue >> 8 ) & 0xFFU );
302 pucData[ 1 ] = ( uint8_t ) ( usValue & 0xFFU );
303 vBitConfig_write_uc( pxConfig, pucData, uxNeeded );
304 }
305 /*-----------------------------------------------------------*/
306
307 /**
308 * @brief Write a 32-bit word to the bit stream.
309 *
310 * @param[in] pxConfig The structure containing a copy of the bits.
311 * @param[in] ulValue The 32-bit value to be written.
312 *
313 * There is no return value. If the operation has failed,
314 * the field xHasError will be set.
315 */
vBitConfig_write_32(BitConfig_t * pxConfig,uint32_t ulValue)316 void vBitConfig_write_32( BitConfig_t * pxConfig,
317 uint32_t ulValue )
318 {
319 const size_t uxNeeded = sizeof ulValue;
320 uint8_t pucData[ sizeof ulValue ];
321
322 pucData[ 0 ] = ( uint8_t ) ( ( ulValue >> 24 ) & 0xFFU );
323 pucData[ 1 ] = ( uint8_t ) ( ( ulValue >> 16 ) & 0xFFU );
324 pucData[ 2 ] = ( uint8_t ) ( ( ulValue >> 8 ) & 0xFFU );
325 pucData[ 3 ] = ( uint8_t ) ( ulValue & 0xFFU );
326
327 vBitConfig_write_uc( pxConfig, pucData, uxNeeded );
328 }
329 /*-----------------------------------------------------------*/
330
331 /**
332 * @brief Deallocate ( release ) the buffer, and clear the bit stream structure.
333 * Note that the struct must have be initialised before calling this function.
334 *
335 * @param[in] pxConfig The structure containing a copy of the bits.
336 *
337 */
vBitConfig_release(BitConfig_t * pxConfig)338 void vBitConfig_release( BitConfig_t * pxConfig )
339 {
340 if( pxConfig != NULL )
341 {
342 if( pxConfig->ucContents != NULL )
343 {
344 vPortFree( pxConfig->ucContents );
345 }
346
347 ( void ) memset( pxConfig, 0, sizeof( BitConfig_t ) );
348 }
349 else
350 {
351 /* Nothing to free */
352 }
353 }
354 /*-----------------------------------------------------------*/
355