]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/FreeRTOS_Stream_Buffer.c
f903fadc14f57e6a4909c202b40310a79c8cf220
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-TCP / FreeRTOS_Stream_Buffer.c
1 /*\r
2  * FreeRTOS+TCP V2.0.11\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /* Standard includes. */\r
27 #include <stdint.h>\r
28 \r
29 /* FreeRTOS includes. */\r
30 #include "FreeRTOS.h"\r
31 #include "task.h"\r
32 #include "semphr.h"\r
33 \r
34 /* FreeRTOS+TCP includes. */\r
35 #include "FreeRTOS_UDP_IP.h"\r
36 #include "FreeRTOS_IP.h"\r
37 #include "FreeRTOS_Sockets.h"\r
38 #include "FreeRTOS_IP_Private.h"\r
39 \r
40 /*\r
41  * uxStreamBufferAdd( )\r
42  * Adds data to a stream buffer.  If uxOffset > 0, data will be written at\r
43  * an offset from uxHead while uxHead will not be moved yet.  This possibility\r
44  * will be used when TCP data is received while earlier data is still missing.\r
45  * If 'pucData' equals NULL, the function is called to advance 'uxHead' only.\r
46  */\r
47 size_t uxStreamBufferAdd( StreamBuffer_t *pxBuffer, size_t uxOffset, const uint8_t *pucData, size_t uxCount )\r
48 {\r
49 size_t uxSpace, uxNextHead, uxFirst;\r
50 \r
51         uxSpace = uxStreamBufferGetSpace( pxBuffer );\r
52 \r
53         /* If uxOffset > 0, items can be placed in front of uxHead */\r
54         if( uxSpace > uxOffset )\r
55         {\r
56                 uxSpace -= uxOffset;\r
57         }\r
58         else\r
59         {\r
60                 uxSpace = 0u;\r
61         }\r
62 \r
63         /* The number of bytes that can be written is the minimum of the number of\r
64         bytes requested and the number available. */\r
65         uxCount = FreeRTOS_min_uint32( uxSpace, uxCount );\r
66 \r
67         if( uxCount != 0u )\r
68         {\r
69                 uxNextHead = pxBuffer->uxHead;\r
70 \r
71                 if( uxOffset != 0u )\r
72                 {\r
73                         /* ( uxOffset > 0 ) means: write in front if the uxHead marker */\r
74                         uxNextHead += uxOffset;\r
75                         if( uxNextHead >= pxBuffer->LENGTH )\r
76                         {\r
77                                 uxNextHead -= pxBuffer->LENGTH;\r
78                         }\r
79                 }\r
80 \r
81                 if( pucData != NULL )\r
82                 {\r
83                         /* Calculate the number of bytes that can be added in the first\r
84                         write - which may be less than the total number of bytes that need\r
85                         to be added if the buffer will wrap back to the beginning. */\r
86                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextHead, uxCount );\r
87 \r
88                         /* Write as many bytes as can be written in the first write. */\r
89                         memcpy( ( void* ) ( pxBuffer->ucArray + uxNextHead ), pucData, uxFirst );\r
90 \r
91                         /* If the number of bytes written was less than the number that\r
92                         could be written in the first write... */\r
93                         if( uxCount > uxFirst )\r
94                         {\r
95                                 /* ...then write the remaining bytes to the start of the\r
96                                 buffer. */\r
97                                 memcpy( ( void * )pxBuffer->ucArray, pucData + uxFirst, uxCount - uxFirst );\r
98                         }\r
99                 }\r
100 \r
101                 if( uxOffset == 0u )\r
102                 {\r
103                         /* ( uxOffset == 0 ) means: write at uxHead position */\r
104                         uxNextHead += uxCount;\r
105                         if( uxNextHead >= pxBuffer->LENGTH )\r
106                         {\r
107                                 uxNextHead -= pxBuffer->LENGTH;\r
108                         }\r
109                         pxBuffer->uxHead = uxNextHead;\r
110                 }\r
111 \r
112                 if( xStreamBufferLessThenEqual( pxBuffer, pxBuffer->uxFront, uxNextHead ) != pdFALSE )\r
113                 {\r
114                         /* Advance the front pointer */\r
115                         pxBuffer->uxFront = uxNextHead;\r
116                 }\r
117         }\r
118 \r
119         return uxCount;\r
120 }\r
121 /*-----------------------------------------------------------*/\r
122 \r
123 /*\r
124  * uxStreamBufferGet( )\r
125  * 'uxOffset' can be used to read data located at a certain offset from 'lTail'.\r
126  * If 'pucData' equals NULL, the function is called to advance 'lTail' only.\r
127  * if 'xPeek' is pdTRUE, or if 'uxOffset' is non-zero, the 'lTail' pointer will\r
128  * not be advanced.\r
129  */\r
130 size_t uxStreamBufferGet( StreamBuffer_t *pxBuffer, size_t uxOffset, uint8_t *pucData, size_t uxMaxCount, BaseType_t xPeek )\r
131 {\r
132 size_t uxSize, uxCount, uxFirst, uxNextTail;\r
133 \r
134         /* How much data is available? */\r
135         uxSize = uxStreamBufferGetSize( pxBuffer );\r
136 \r
137         if( uxSize > uxOffset )\r
138         {\r
139                 uxSize -= uxOffset;\r
140         }\r
141         else\r
142         {\r
143                 uxSize = 0u;\r
144         }\r
145 \r
146         /* Use the minimum of the wanted bytes and the available bytes. */\r
147         uxCount = FreeRTOS_min_uint32( uxSize, uxMaxCount );\r
148 \r
149         if( uxCount > 0u )\r
150         {\r
151                 uxNextTail = pxBuffer->uxTail;\r
152 \r
153                 if( uxOffset != 0u )\r
154                 {\r
155                         uxNextTail += uxOffset;\r
156                         if( uxNextTail >= pxBuffer->LENGTH )\r
157                         {\r
158                                 uxNextTail -= pxBuffer->LENGTH;\r
159                         }\r
160                 }\r
161 \r
162                 if( pucData != NULL )\r
163                 {\r
164                         /* Calculate the number of bytes that can be read - which may be\r
165                         less than the number wanted if the data wraps around to the start of\r
166                         the buffer. */\r
167                         uxFirst = FreeRTOS_min_uint32( pxBuffer->LENGTH - uxNextTail, uxCount );\r
168 \r
169                         /* Obtain the number of bytes it is possible to obtain in the first\r
170                         read. */\r
171                         memcpy( pucData, pxBuffer->ucArray + uxNextTail, uxFirst );\r
172 \r
173                         /* If the total number of wanted bytes is greater than the number\r
174                         that could be read in the first read... */\r
175                         if( uxCount > uxFirst )\r
176                         {\r
177                                 /*...then read the remaining bytes from the start of the buffer. */\r
178                                 memcpy( pucData + uxFirst, pxBuffer->ucArray, uxCount - uxFirst );\r
179                         }\r
180                 }\r
181 \r
182                 if( ( xPeek == pdFALSE ) && ( uxOffset == 0UL ) )\r
183                 {\r
184                         /* Move the tail pointer to effecively remove the data read from\r
185                         the buffer. */\r
186                         uxNextTail += uxCount;\r
187 \r
188                         if( uxNextTail >= pxBuffer->LENGTH )\r
189                         {\r
190                                 uxNextTail -= pxBuffer->LENGTH;\r
191                         }\r
192 \r
193                         pxBuffer->uxTail = uxNextTail;\r
194                 }\r
195         }\r
196 \r
197         return uxCount;\r
198 }\r
199 \r