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