]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator/DemoTasks/SimpleClientAndServer.c
Update version number to 8.1.1 for patch release that re-enables mutexes to be given...
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_UDP_and_CLI_Windows_Simulator / DemoTasks / SimpleClientAndServer.c
1 /*\r
2     FreeRTOS V8.1.1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS provides completely free yet professionally developed,    *\r
10      *    robust, strictly quality controlled, supported, and cross          *\r
11      *    platform software that has become a de facto standard.             *\r
12      *                                                                       *\r
13      *    Help yourself get started quickly and support the FreeRTOS         *\r
14      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
15      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \r
23     FreeRTOS is free software; you can redistribute it and/or modify it under\r
24     the terms of the GNU General Public License (version 2) as published by the\r
25     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
26 \r
27     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
28     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
29     >>!   obliged to provide the source code for proprietary components     !<<\r
30     >>!   outside of the FreeRTOS kernel.                                   !<<\r
31 \r
32     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
33     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
34     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
35     link: http://www.freertos.org/a00114.html\r
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \r
51     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
52     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
53     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
54 \r
55     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
56     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
57     licenses offer ticketed support, indemnification and middleware.\r
58 \r
59     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
60     engineered and independently SIL3 certified version for use in safety and\r
61     mission critical applications that require provable dependability.\r
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 /*\r
67  * Creates two transmitting tasks and two receiving tasks.  The transmitting\r
68  * tasks send values that are received by the receiving tasks.  One set of tasks\r
69  * uses the standard API.  The other set of tasks uses the zero copy API.\r
70  */\r
71 \r
72 /* Standard includes. */\r
73 #include <stdint.h>\r
74 #include <stdio.h>\r
75 \r
76 /* FreeRTOS includes. */\r
77 #include "FreeRTOS.h"\r
78 #include "task.h"\r
79 \r
80 /* FreeRTOS+UDP includes. */\r
81 #include "FreeRTOS_UDP_IP.h"\r
82 #include "FreeRTOS_Sockets.h"\r
83 \r
84 #define simpTINY_DELAY  ( ( TickType_t ) 2 )\r
85 \r
86 /*\r
87  * Uses a socket to send data without using the zero copy option.\r
88  * prvSimpleServerTask() will receive the data.\r
89  */\r
90 static void prvSimpleClientTask( void *pvParameters );\r
91 \r
92 /*\r
93  * Uses a socket to receive the data sent by the prvSimpleClientTask() task.\r
94  * Does not use the zero copy option.\r
95  */\r
96 static void prvSimpleServerTask( void *pvParameters );\r
97 \r
98 /*\r
99  * Uses a socket to send data using the zero copy option.\r
100  * prvSimpleZeroCopyServerTask() will receive the data.\r
101  */\r
102 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters );\r
103 \r
104 /*\r
105  * Uses a socket to receive the data sent by the prvSimpleZeroCopyUDPClientTask()\r
106  * task.  Uses the zero copy option.\r
107  */\r
108 static void prvSimpleZeroCopyServerTask( void *pvParameters );\r
109 \r
110 /*-----------------------------------------------------------*/\r
111 \r
112 void vStartSimpleUDPClientServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )\r
113 {\r
114         /* Create the client and server tasks that do not use the zero copy\r
115         interface. */\r
116         xTaskCreate( prvSimpleClientTask, "SimpCpyClnt", usStackSize, ( void * ) ulPort, uxPriority, NULL );\r
117         xTaskCreate( prvSimpleServerTask, "SimpCpySrv", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );\r
118 \r
119         /* Create the client and server tasks that do use the zero copy interface. */\r
120         xTaskCreate( prvSimpleZeroCopyUDPClientTask, "SimpZCpyClnt", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority, NULL );\r
121         xTaskCreate( prvSimpleZeroCopyServerTask, "SimpZCpySrv", usStackSize, ( void * ) ( ulPort + 1 ), uxPriority + 1, NULL );\r
122 }\r
123 /*-----------------------------------------------------------*/\r
124 \r
125 static void prvSimpleClientTask( void *pvParameters )\r
126 {\r
127 xSocket_t xClientSocket;\r
128 struct freertos_sockaddr xDestinationAddress;\r
129 char cString[ 50 ];\r
130 BaseType_t lReturned;\r
131 uint32_t ulCount = 0UL, ulIPAddress;\r
132 const uint32_t ulLoopsPerSocket = 10UL;\r
133 const TickType_t x150ms = 150UL / portTICK_RATE_MS;\r
134 \r
135         /* Remove compiler warning about unused parameters. */\r
136         ( void ) pvParameters;\r
137 \r
138         /* It is assumed that this task is not created until the network is up,\r
139         so the IP address can be obtained immediately.  store the IP address being\r
140         used in ulIPAddress.  This is done so the socket can send to a different\r
141         port on the same IP address. */\r
142         FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
143 \r
144         /* This test sends to itself, so data sent from here is received by a server\r
145         socket on the same IP address.  Setup the freertos_sockaddr structure with\r
146         this nodes IP address, and the port number being sent to.  The strange\r
147         casting is to try and remove compiler warnings on 32 bit machines. */\r
148         xDestinationAddress.sin_addr = ulIPAddress;\r
149         xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
150         xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );\r
151 \r
152         for( ;; )\r
153         {\r
154                 /* Create the socket. */\r
155                 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
156                 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );\r
157 \r
158                 /* The count is used to differentiate between different messages sent to\r
159                 the server, and to break out of the do while loop below. */\r
160                 ulCount = 0UL;\r
161 \r
162                 do\r
163                 {\r
164                         /* Create the string that is sent to the server. */\r
165                         sprintf( cString, "Server received (not zero copy): Message number %lu\r\n", ulCount );\r
166 \r
167                         /* Send the string to the socket.  ulFlags is set to 0, so the zero\r
168                         copy option is not selected.  That means the data from cString[] is\r
169                         copied into a network buffer inside FreeRTOS_sendto(), and cString[]\r
170                         can be reused as soon as FreeRTOS_sendto() has returned. */\r
171                         lReturned = FreeRTOS_sendto( xClientSocket, ( void * ) cString, strlen( cString ), 0, &xDestinationAddress, sizeof( xDestinationAddress ) );\r
172 \r
173                         ulCount++;\r
174 \r
175                 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );\r
176 \r
177                 FreeRTOS_closesocket( xClientSocket );\r
178 \r
179                 /* A short delay to prevent the messages printed by the server task\r
180                 scrolling off the screen too quickly, and to prevent reduce the network\r
181                 loading. */\r
182                 vTaskDelay( x150ms );\r
183         }\r
184 }\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 static void prvSimpleServerTask( void *pvParameters )\r
188 {\r
189 long lBytes;\r
190 char cReceivedString[ 60 ];\r
191 struct freertos_sockaddr xClient, xBindAddress;\r
192 uint32_t xClientLength = sizeof( xClient );\r
193 xSocket_t xListeningSocket;\r
194 \r
195         /* Just to prevent compiler warnings. */\r
196         ( void ) pvParameters;\r
197 \r
198         /* Attempt to open the socket. */\r
199         xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
200         configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );\r
201 \r
202         /* This test receives data sent from a different port on the same IP\r
203         address.  Configure the freertos_sockaddr structure with the address being\r
204         bound to.  The strange casting is to try and remove     compiler warnings on 32\r
205         bit machines.  Note that this task is only created after the network is up,\r
206         so the IP address is valid here. */\r
207         xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
208         xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );\r
209 \r
210         /* Bind the socket to the port that the client task will send to. */\r
211         FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );\r
212 \r
213         for( ;; )\r
214         {\r
215                 /* Zero out the receive array so there is NULL at the end of the string\r
216                 when it is printed out. */\r
217                 memset( cReceivedString, 0x00, sizeof( cReceivedString ) );\r
218 \r
219                 /* Receive data on the socket.  ulFlags is zero, so the zero copy option\r
220                 is not set and the received data is copied into the buffer pointed to by\r
221                 cReceivedString.  By default the block time is portMAX_DELAY.\r
222                 xClientLength is not actually used by FreeRTOS_recvfrom(), but is set\r
223                 appropriately in case future versions do use it. */\r
224                 lBytes = FreeRTOS_recvfrom( xListeningSocket, cReceivedString, sizeof( cReceivedString ), 0, &xClient, &xClientLength );\r
225 \r
226                 /* Print the received characters. */\r
227                 if( lBytes > 0 )\r
228                 {\r
229                         vOutputString( cReceivedString );\r
230                 }\r
231 \r
232                 /* Error check. */\r
233                 configASSERT( lBytes == ( BaseType_t ) strlen( cReceivedString ) );\r
234         }\r
235 }\r
236 /*-----------------------------------------------------------*/\r
237 \r
238 static void prvSimpleZeroCopyUDPClientTask( void *pvParameters )\r
239 {\r
240 xSocket_t xClientSocket;\r
241 uint8_t *pucUDPPayloadBuffer;\r
242 struct freertos_sockaddr xDestinationAddress;\r
243 BaseType_t lReturned;\r
244 uint32_t ulCount = 0UL, ulIPAddress;\r
245 const uint32_t ulLoopsPerSocket = 10UL;\r
246 const char *pcStringToSend = "Server received (using zero copy): Message number ";\r
247 const TickType_t x150ms = 150UL / portTICK_RATE_MS;\r
248 /* 15 is added to ensure the number, \r\n and terminating zero fit. */\r
249 const size_t xStringLength = strlen( pcStringToSend ) + 15;\r
250 \r
251         /* Remove compiler warning about unused parameters. */\r
252         ( void ) pvParameters;\r
253 \r
254         /* It is assumed that this task is not created until the network is up,\r
255         so the IP address can be obtained immediately.  store the IP address being\r
256         used in ulIPAddress.  This is done so the socket can send to a different\r
257         port on the same IP address. */\r
258         FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
259 \r
260         /* This test sends to itself, so data sent from here is received by a server\r
261         socket on the same IP address.  Setup the freertos_sockaddr structure with\r
262         this nodes IP address, and the port number being sent to.  The strange\r
263         casting is to try and remove compiler warnings on 32 bit machines. */\r
264         xDestinationAddress.sin_addr = ulIPAddress;\r
265         xDestinationAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
266         xDestinationAddress.sin_port = FreeRTOS_htons( xDestinationAddress.sin_port );\r
267 \r
268         for( ;; )\r
269         {\r
270                 /* Create the socket. */\r
271                 xClientSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
272                 configASSERT( xClientSocket != FREERTOS_INVALID_SOCKET );\r
273 \r
274                 /* The count is used to differentiate between different messages sent to\r
275                 the server, and to break out of the do while loop below. */\r
276                 ulCount = 0UL;\r
277 \r
278                 do\r
279                 {\r
280                         /* This task is going to send using the zero copy interface.  The\r
281                         data being sent is therefore written directly into a buffer that is\r
282                         passed into, rather than copied into, the FreeRTOS_sendto()\r
283                         function.\r
284 \r
285                         First obtain a buffer of adequate length from the IP stack into which\r
286                         the string will be written.  Although a max delay is used, the actual\r
287                         delay will be capped to ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence\r
288                         the do while loop is used to ensure a buffer is obtained. */\r
289                         do\r
290                         {\r
291                         } while( ( pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xStringLength, portMAX_DELAY ) ) == NULL );\r
292 \r
293                         /* A buffer was successfully obtained.  Create the string that is\r
294                         sent to the server.  First the string is filled with zeros as this will\r
295                         effectively be the null terminator when the string is received at the other\r
296                         end.  Note that the string is being written directly into the buffer\r
297                         obtained from the IP stack above. */\r
298                         memset( ( void * ) pucUDPPayloadBuffer, 0x00, xStringLength );\r
299                         sprintf( ( char * ) pucUDPPayloadBuffer, "%s%lu\r\n", pcStringToSend, ulCount );\r
300 \r
301                         /* Pass the buffer into the send function.  ulFlags has the\r
302                         FREERTOS_ZERO_COPY bit set so the IP stack will take control of the\r
303                         buffer rather than copy data out of the buffer. */\r
304                         lReturned = FreeRTOS_sendto( xClientSocket,                             /* The socket being sent to. */\r
305                                                                                 ( void * ) pucUDPPayloadBuffer, /* A pointer to the the data being sent. */\r
306                                                                                 strlen( ( const char * ) pucUDPPayloadBuffer ) + 1, /* The length of the data being sent - including the string's null terminator. */\r
307                                                                                 FREERTOS_ZERO_COPY,                     /* ulFlags with the FREERTOS_ZERO_COPY bit set. */\r
308                                                                                 &xDestinationAddress,                   /* Where the data is being sent. */\r
309                                                                                 sizeof( xDestinationAddress ) );\r
310 \r
311                         if( lReturned == 0 )\r
312                         {\r
313                                 /* The send operation failed, so this task is still responsible\r
314                                 for the buffer obtained from the IP stack.  To ensure the buffer\r
315                                 is not lost it must either be used again, or, as in this case,\r
316                                 returned to the IP stack using FreeRTOS_ReleaseUDPPayloadBuffer().\r
317                                 pucUDPPayloadBuffer can be safely re-used after this call. */\r
318                                 FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );\r
319                         }\r
320                         else\r
321                         {\r
322                                 /* The send was successful so the IP stack is now managing the\r
323                                 buffer pointed to by pucUDPPayloadBuffer, and the IP stack will\r
324                                 return the buffer once it has been sent.  pucUDPPayloadBuffer can\r
325                                 be safely re-used. */\r
326                         }\r
327 \r
328                         ulCount++;\r
329 \r
330                 } while( ( lReturned != FREERTOS_SOCKET_ERROR ) && ( ulCount < ulLoopsPerSocket ) );\r
331 \r
332                 FreeRTOS_closesocket( xClientSocket );\r
333 \r
334                 /* A short delay to prevent the messages scrolling off the screen too\r
335                 quickly. */\r
336                 vTaskDelay( x150ms );\r
337         }\r
338 }\r
339 /*-----------------------------------------------------------*/\r
340 \r
341 static void prvSimpleZeroCopyServerTask( void *pvParameters )\r
342 {\r
343 int32_t lBytes;\r
344 uint8_t *pucUDPPayloadBuffer;\r
345 struct freertos_sockaddr xClient, xBindAddress;\r
346 uint32_t xClientLength = sizeof( xClient ), ulIPAddress;\r
347 xSocket_t xListeningSocket;\r
348 \r
349         /* Just to prevent compiler warnings. */\r
350         ( void ) pvParameters;\r
351 \r
352         /* Attempt to open the socket. */\r
353         xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );\r
354         configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );\r
355 \r
356         /* This test receives data sent from a different port on the same IP address.\r
357         Obtain the nodes IP address.  Configure the freertos_sockaddr structure with\r
358         the address being bound to.  The strange casting is to try and remove\r
359         compiler warnings on 32 bit machines.  Note that this task is only created\r
360         after the network is up, so the IP address is valid here. */\r
361         FreeRTOS_GetAddressConfiguration( &ulIPAddress, NULL, NULL, NULL );\r
362         xBindAddress.sin_addr = ulIPAddress;\r
363         xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;\r
364         xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );\r
365 \r
366         /* Bind the socket to the port that the client task will send to. */\r
367         FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );\r
368 \r
369         for( ;; )\r
370         {\r
371                 /* Receive data on the socket.  ulFlags has the zero copy bit set\r
372                 (FREERTOS_ZERO_COPY) indicating to the stack that a reference to the\r
373                 received data should be passed out to this task using the second\r
374                 parameter to the FreeRTOS_recvfrom() call.  When this is done the\r
375                 IP stack is no longer responsible for releasing the buffer, and\r
376                 the task *must* return the buffer to the stack when it is no longer\r
377                 needed.  By default the block time is portMAX_DELAY. */\r
378                 lBytes = FreeRTOS_recvfrom( xListeningSocket, ( void * ) &pucUDPPayloadBuffer, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength );\r
379 \r
380                 /* It is expected to receive one more byte than the string length as\r
381                 the NULL terminator is also transmitted. */\r
382                 configASSERT( lBytes == ( ( BaseType_t ) strlen( ( const char * ) pucUDPPayloadBuffer ) + 1 ) );\r
383 \r
384                 /* Print the received characters. */\r
385                 if( lBytes > 0 )\r
386                 {\r
387                         vOutputString( ( char * ) pucUDPPayloadBuffer );\r
388                 }\r
389 \r
390                 if( lBytes >= 0 )\r
391                 {\r
392                         /* The buffer *must* be freed once it is no longer needed. */\r
393                         FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );\r
394                 }\r
395         }\r
396 }\r
397 \r