]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
Added +TCP code to main repo.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_Stream_Buffer.c
1 /*\r
2  * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd.\r
3  * Authors include Hein Tibosch and Richard Barry\r
4  *\r
5  *******************************************************************************\r
6  ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
7  ***                                                                         ***\r
8  ***                                                                         ***\r
9  ***   FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP     ***\r
10  ***   demos have a dependency on FreeRTOS+FAT, which is only in the Labs    ***\r
11  ***   download):                                                            ***\r
12  ***                                                                         ***\r
13  ***   FreeRTOS+TCP is functional and has been used in commercial products   ***\r
14  ***   for some time.  Be aware however that we are still refining its       ***\r
15  ***   design, the source code does not yet quite conform to the strict      ***\r
16  ***   coding and style standards mandated by Real Time Engineers ltd., and  ***\r
17  ***   the documentation and testing is not necessarily complete.            ***\r
18  ***                                                                         ***\r
19  ***   PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE    ***\r
20  ***   URL: http://www.FreeRTOS.org/contact  Active early adopters may, at   ***\r
21  ***   the sole discretion of Real Time Engineers Ltd., be offered versions  ***\r
22  ***   under a license other than that described below.                      ***\r
23  ***                                                                         ***\r
24  ***                                                                         ***\r
25  ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ***\r
26  *******************************************************************************\r
27  *\r
28  * FreeRTOS+TCP can be used under two different free open source licenses.  The\r
29  * license that applies is dependent on the processor on which FreeRTOS+TCP is\r
30  * executed, as follows:\r
31  *\r
32  * If FreeRTOS+TCP is executed on one of the processors listed under the Special\r
33  * License Arrangements heading of the FreeRTOS+TCP license information web\r
34  * page, then it can be used under the terms of the FreeRTOS Open Source\r
35  * License.  If FreeRTOS+TCP is used on any other processor, then it can be used\r
36  * under the terms of the GNU General Public License V2.  Links to the relevant\r
37  * licenses follow:\r
38  *\r
39  * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license\r
40  * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license\r
41  * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt\r
42  *\r
43  * FreeRTOS+TCP is distributed in the hope that it will be useful.  You cannot\r
44  * use FreeRTOS+TCP unless you agree that you use the software 'as is'.\r
45  * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied\r
46  * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
47  * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
48  * implied, expressed, or statutory.\r
49  *\r
50  * 1 tab == 4 spaces!\r
51  *\r
52  * http://www.FreeRTOS.org\r
53  * http://www.FreeRTOS.org/plus\r
54  * http://www.FreeRTOS.org/labs\r
55  *\r
56  */\r
57 \r
58 /* Standard includes. */\r
59 #include <stdint.h>\r
60 \r
61 /* FreeRTOS includes. */\r
62 #include "FreeRTOS.h"\r
63 #include "task.h"\r
64 #include "semphr.h"\r
65 \r
66 /* FreeRTOS+TCP includes. */\r
67 #include "FreeRTOS_UDP_IP.h"\r
68 #include "FreeRTOS_IP.h"\r
69 #include "FreeRTOS_Sockets.h"\r
70 #include "FreeRTOS_IP_Private.h"\r
71 \r
72 /*\r
73  * uxStreamBufferAdd( )\r
74  * Adds data to a stream buffer.  If uxOffset > 0, data will be written at\r
75  * an offset from uxHead while uxHead will not be moved yet.  This possibility\r
76  * will be used when TCP data is received while earlier data is still missing.\r
77  * If 'pucData' equals NULL, the function is called to advance 'uxHead' only.\r
78  */\r
79 size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )\r
80 {\r
81 size_t uxSpace, uxNextHead, uxFirst;\r
82 \r
83         uxSpace = uxStreamBufferGetSpace( pxBuffer );\r
84 \r
85         /* If uxOffset > 0, items can be placed in front of uxHead */\r
86         if( uxSpace > uxOffset )\r
87         {\r
88                 uxSpace -= uxOffset;\r
89         }\r
90         else\r
91         {\r
92                 uxSpace = 0u;\r
93         }\r
94 \r
95         /* The number of bytes that can be written is the minimum of the number of\r
96         bytes requested and the number available. */\r
97         uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );\r
98 \r
99         if( uxCount != 0u )\r
100         {\r
101                 uxNextHead = pxBuffer->uxHead;\r
102 \r
103                 if( uxOffset != 0u )\r
104                 {\r
105                         /* ( uxOffset > 0 ) means: write in front if the uxHead marker */\r
106                         uxNextHead += uxOffset;\r
107                         if( uxNextHead >= pxBuffer->LENGTH )\r
108                         {\r
109                                 uxNextHead -= pxBuffer->LENGTH;\r
110                         }\r
111                 }\r
112 \r
113                 if( pucData != NULL )\r
114                 {\r
115                         /* Calculate the number of bytes that can be added in the first\r
116                         write - which may be less than the total number of bytes that need\r
117                         to be added if the buffer will wrap back to the beginning. */\r
118                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );\r
119 \r
120                         /* Write as many bytes as can be written in the first write. */\r
121                         memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );\r
122 \r
123                         /* If the number of bytes written was less than the number that\r
124                         could be written in the first write... */\r
125                         if( uxCount > uxFirst )\r
126                         {\r
127                                 /* ...then write the remaining bytes to the start of the\r
128                                 buffer. */\r
129                                 memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );\r
130                         }\r
131                 }\r
132 \r
133                 if( uxOffset == 0u )\r
134                 {\r
135                         /* ( uxOffset == 0 ) means: write at uxHead position */\r
136                         uxNextHead += uxCount;\r
137                         if( uxNextHead >= pxBuffer->LENGTH )\r
138                         {\r
139                                 uxNextHead -= pxBuffer->LENGTH;\r
140                         }\r
141                         pxBuffer->uxHead = uxNextHead;\r
142                 }\r
143 \r
144                 if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )\r
145                 {\r
146                         /* Advance the front pointer */\r
147                         pxBuffer->uxFront = uxNextHead;\r
148                 }\r
149         }\r
150 \r
151         return uxCount;\r
152 }\r
153 /*-----------------------------------------------------------*/\r
154 \r
155 /*\r
156  * uxStreamBufferGet( )\r
157  * 'uxOffset' can be used to read data located at a certain offset from 'lTail'.\r
158  * If 'pucData' equals NULL, the function is called to advance 'lTail' only.\r
159  * if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will\r
160  * not be advanced.\r
161  */\r
162 size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )\r
163 {\r
164 size_t uxSize, uxCount, uxFirst, uxNextTail;\r
165 \r
166         /* How much data is available? */\r
167         uxSize = uxStreamBufferGetSize( pxBuffer );\r
168 \r
169         if( uxSize > uxOffset )\r
170         {\r
171                 uxSize -= uxOffset;\r
172         }\r
173         else\r
174         {\r
175                 uxSize = 0u;\r
176         }\r
177 \r
178         /* Use the minimum of the wanted bytes and the available bytes. */\r
179         uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );\r
180 \r
181         if( uxCount > 0u )\r
182         {\r
183                 uxNextTail = pxBuffer->uxTail;\r
184 \r
185                 if( uxOffset != 0u )\r
186                 {\r
187                         uxNextTail += uxOffset;\r
188                         if( uxNextTail >= pxBuffer->LENGTH )\r
189                         {\r
190                                 uxNextTail -= pxBuffer->LENGTH;\r
191                         }\r
192                 }\r
193 \r
194                 if( pucData != NULL )\r
195                 {\r
196                         /* Calculate the number of bytes that can be read - which may be\r
197                         less than the number wanted if the data wraps around to the start of\r
198                         the buffer. */\r
199                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );\r
200 \r
201                         /* Obtain the number of bytes it is possible to obtain in the first\r
202                         read. */\r
203                         memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );\r
204 \r
205                         /* If the total number of wanted bytes is greater than the number\r
206                         that could be read in the first read... */\r
207                         if( uxCount > uxFirst )\r
208                         {\r
209                                 /*...then read the remaining bytes from the start of the buffer. */\r
210                                 memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );\r
211                         }\r
212                 }\r
213 \r
214                 if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )\r
215                 {\r
216                         /* Move the tail pointer to effecively remove the data read from\r
217                         the buffer. */\r
218                         uxNextTail += uxCount;\r
219 \r
220                         if( uxNextTail >= pxBuffer->LENGTH )\r
221                         {\r
222                                 uxNextTail -= pxBuffer->LENGTH;\r
223                         }\r
224 \r
225                         pxBuffer->uxTail = uxNextTail;\r
226                 }\r
227         }\r
228 \r
229         return uxCount;\r
230 }\r
231 \r