]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
commit 9f316c246baafa15c542a5aea81a94f26e3d6507
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_Stream_Buffer.c
1 /*
2  * FreeRTOS+TCP V2.2.1
3  * Copyright (C) 2017 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 /* Standard includes. */
27 #include <stdint.h>
28
29 /* FreeRTOS includes. */
30 #include "FreeRTOS.h"
31 #include "task.h"
32 #include "semphr.h"
33
34 /* FreeRTOS+TCP includes. */
35 #include "FreeRTOS_UDP_IP.h"
36 #include "FreeRTOS_IP.h"
37 #include "FreeRTOS_Sockets.h"
38 #include "FreeRTOS_IP_Private.h"
39
40 /*
41  * uxStreamBufferAdd( )
42  * Adds data to a stream buffer.  If uxOffset > 0, data will be written at
43  * an offset from uxHead while uxHead will not be moved yet.  This possibility
44  * will be used when TCP data is received while earlier data is still missing.
45  * If 'pucData' equals NULL, the function is called to advance 'uxHead' only.
46  */
47 size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )
48 {
49 size_t uxSpace, uxNextHead, uxFirst;
50
51         uxSpace = uxStreamBufferGetSpace( pxBuffer );
52
53         /* If uxOffset > 0, items can be placed in front of uxHead */
54         if( uxSpace > uxOffset )
55         {
56                 uxSpace -= uxOffset;
57         }
58         else
59         {
60                 uxSpace = 0u;
61         }
62
63         /* The number of bytes that can be written is the minimum of the number of
64         bytes requested and the number available. */
65         uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );
66
67         if( uxCount != 0u )
68         {
69                 uxNextHead = pxBuffer->uxHead;
70
71                 if( uxOffset != 0u )
72                 {
73                         /* ( uxOffset > 0 ) means: write in front if the uxHead marker */
74                         uxNextHead += uxOffset;
75                         if( uxNextHead >= pxBuffer->LENGTH )
76                         {
77                                 uxNextHead -= pxBuffer->LENGTH;
78                         }
79                 }
80
81                 if( pucData != NULL )
82                 {
83                         /* Calculate the number of bytes that can be added in the first
84                         write - which may be less than the total number of bytes that need
85                         to be added if the buffer will wrap back to the beginning. */
86                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );
87
88                         /* Write as many bytes as can be written in the first write. */
89                         memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );
90
91                         /* If the number of bytes written was less than the number that
92                         could be written in the first write... */
93                         if( uxCount > uxFirst )
94                         {
95                                 /* ...then write the remaining bytes to the start of the
96                                 buffer. */
97                                 memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );
98                         }
99                 }
100
101                 if( uxOffset == 0u )
102                 {
103                         /* ( uxOffset == 0 ) means: write at uxHead position */
104                         uxNextHead += uxCount;
105                         if( uxNextHead >= pxBuffer->LENGTH )
106                         {
107                                 uxNextHead -= pxBuffer->LENGTH;
108                         }
109                         pxBuffer->uxHead = uxNextHead;
110                 }
111
112                 if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )
113                 {
114                         /* Advance the front pointer */
115                         pxBuffer->uxFront = uxNextHead;
116                 }
117         }
118
119         return uxCount;
120 }
121 /*-----------------------------------------------------------*/
122
123 /*
124  * uxStreamBufferGet( )
125  * 'uxOffset' can be used to read data located at a certain offset from 'lTail'.
126  * If 'pucData' equals NULL, the function is called to advance 'lTail' only.
127  * if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will
128  * not be advanced.
129  */
130 size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )
131 {
132 size_t uxSize, uxCount, uxFirst, uxNextTail;
133
134         /* How much data is available? */
135         uxSize = uxStreamBufferGetSize( pxBuffer );
136
137         if( uxSize > uxOffset )
138         {
139                 uxSize -= uxOffset;
140         }
141         else
142         {
143                 uxSize = 0u;
144         }
145
146         /* Use the minimum of the wanted bytes and the available bytes. */
147         uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );
148
149         if( uxCount > 0u )
150         {
151                 uxNextTail = pxBuffer->uxTail;
152
153                 if( uxOffset != 0u )
154                 {
155                         uxNextTail += uxOffset;
156                         if( uxNextTail >= pxBuffer->LENGTH )
157                         {
158                                 uxNextTail -= pxBuffer->LENGTH;
159                         }
160                 }
161
162                 if( pucData != NULL )
163                 {
164                         /* Calculate the number of bytes that can be read - which may be
165                         less than the number wanted if the data wraps around to the start of
166                         the buffer. */
167                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );
168
169                         /* Obtain the number of bytes it is possible to obtain in the first
170                         read. */
171                         memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );
172
173                         /* If the total number of wanted bytes is greater than the number
174                         that could be read in the first read... */
175                         if( uxCount > uxFirst )
176                         {
177                                 /*...then read the remaining bytes from the start of the buffer. */
178                                 memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );
179                         }
180                 }
181
182                 if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )
183                 {
184                         /* Move the tail pointer to effecively remove the data read from
185                         the buffer. */
186                         uxNextTail += uxCount;
187
188                         if( uxNextTail >= pxBuffer->LENGTH )
189                         {
190                                 uxNextTail -= pxBuffer->LENGTH;
191                         }
192
193                         pxBuffer->uxTail = uxNextTail;
194                 }
195         }
196
197         return uxCount;
198 }
199