1 /*
2 * FreeRTOS V202212.00
3 * Copyright (C) 2020 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 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
24 *
25 */
26
27 /*
28 * This project is a cut down version of the project described on the following
29 * link. Only the simple UDP client and server and the TCP echo clients are
30 * included in the build:
31 * https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
32 */
33
34 /* Standard includes. */
35 #include <stdio.h>
36 #include <time.h>
37 #include <unistd.h>
38
39 /* FreeRTOS includes. */
40 #include <FreeRTOS.h>
41 #include "task.h"
42
43 /* Demo application includes. */
44 #include "FreeRTOS_IP.h"
45 #include "FreeRTOS_Sockets.h"
46 /*#include "SimpleUDPClientAndServer.h" */
47 /*#include "SimpleTCPEchoServer.h" */
48 /*#include "TCPEchoClient_SingleTasks.h" */
49 /*#include "logging.h" */
50 #include "TCPEchoClient_SingleTasks.h"
51
52 /* Simple UDP client and server task parameters. */
53 #define mainSIMPLE_UDP_CLIENT_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY )
54 #define mainSIMPLE_UDP_CLIENT_SERVER_PORT ( 5005UL )
55
56 /* Echo client task parameters - used for both TCP and UDP echo clients. */
57 #define mainECHO_CLIENT_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 )
58 #define mainECHO_CLIENT_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
59
60 /* Echo server task parameters. */
61 #define mainECHO_SERVER_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 )
62 #define mainECHO_SERVER_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
63
64 /* Define a name that will be used for LLMNR and NBNS searches. */
65 #define mainHOST_NAME "RTOSDemo"
66 #define mainDEVICE_NICK_NAME "linux_demo"
67
68 /* Set the following constants to 1 or 0 to define which tasks to include and
69 * exclude:
70 *
71 * mainCREATE_TCP_ECHO_TASKS_SINGLE: When set to 1 a set of tasks are created that
72 * send TCP echo requests to the standard echo port (port 7), then wait for and
73 * verify the echo reply, from within the same task (Tx and Rx are performed in the
74 * same RTOS task). The IP address of the echo server must be configured using the
75 * configECHO_SERVER_ADDR0 to configECHO_SERVER_ADDR3 constants in
76 * FreeRTOSConfig.h.
77 *
78 */
79 #define mainCREATE_TCP_ECHO_TASKS_SINGLE 1
80 /*-----------------------------------------------------------*/
81
82 /*
83 * Just seeds the simple pseudo random number generator.
84 */
85 static void prvSRand( UBaseType_t ulSeed );
86
87 /*
88 * Miscellaneous initialisation including preparing the logging and seeding the
89 * random number generator.
90 */
91 static void prvMiscInitialisation( void );
92
93 /* The default IP and MAC address used by the demo. The address configuration
94 * defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is
95 * 1 but a DHCP server could not be contacted. See the online documentation for
96 * more information. */
97 static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };
98 static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };
99 static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };
100 static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };
101
102 /* Set the following constant to pdTRUE to log using the method indicated by the
103 * name of the constant, or pdFALSE to not log using the method indicated by the
104 * name of the constant. Options include to standard out (xLogToStdout), to a disk
105 * file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE
106 * then UDP messages are sent to the IP address configured as the echo server
107 * address (see the configECHO_SERVER_ADDR0 definitions in FreeRTOSConfig.h) and
108 * the port number set by configPRINT_PORT in FreeRTOSConfig.h. */
109 const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE;
110
111 /* Default MAC address configuration. The demo creates a virtual network
112 * connection that uses this MAC address by accessing the raw Ethernet data
113 * to and from a real network connection on the host PC. See the
114 * configNETWORK_INTERFACE_TO_USE definition for information on how to configure
115 * the real network connection to use. */
116 const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };
117
118 /* Use by the pseudo random number generator. */
119 static UBaseType_t ulNextRand;
120
121 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
122
123 /* In case multiple interfaces are used, define them statically. */
124
125 /* There is only 1 physical interface. */
126 static NetworkInterface_t xInterfaces[ 1 ];
127
128 /* It will have several end-points. */
129 static NetworkEndPoint_t xEndPoints[ 4 ];
130
131 #endif /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
132
133
134 /*-----------------------------------------------------------*/
135
main_tcp_echo_client_tasks(void)136 void main_tcp_echo_client_tasks( void )
137 {
138 BaseType_t xResult;
139 const uint32_t ulLongTime_ms = pdMS_TO_TICKS( 1000UL );
140
141 /*
142 * Instructions for using this project are provided on:
143 * https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/examples_FreeRTOS_simulator.html
144 */
145
146 /* Miscellaneous initialisation including preparing the logging and seeding
147 * the random number generator. */
148 prvMiscInitialisation();
149
150 /* Initialise the network interface.
151 *
152 ***NOTE*** Tasks that use the network are created in the network event hook
153 * when the network is connected and ready for use (see the definition of
154 * vApplicationIPNetworkEventHook() below). The address values passed in here
155 * are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1
156 * but a DHCP server cannot be contacted. */
157
158 /* Initialise the network interface.*/
159 FreeRTOS_debug_printf( ( "FreeRTOS_IPInit\r\n" ) );
160
161 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
162 extern NetworkInterface_t * pxLibslirp_FillInterfaceDescriptor( BaseType_t xEMACIndex,
163 NetworkInterface_t * pxInterface );
164 pxLibslirp_FillInterfaceDescriptor( 0, &( xInterfaces[ 0 ] ) );
165
166 /* === End-point 0 === */
167 FreeRTOS_FillEndPoint( &( xInterfaces[ 0 ] ), &( xEndPoints[ 0 ] ), ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
168 #if ( ipconfigUSE_DHCP != 0 )
169 {
170 /* End-point 0 wants to use DHCPv4. */
171 xEndPoints[ 0 ].bits.bWantDHCP = pdTRUE;
172 }
173 #endif /* ( ipconfigUSE_DHCP != 0 ) */
174
175 xResult = FreeRTOS_IPInit_Multi();
176 #else /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
177 /* Using the old /single /IPv4 library, or using backward compatible mode of the new /multi library. */
178 xResult = FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
179 #endif /* if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
180
181 configASSERT( xResult == pdTRUE );
182
183 /* Start the RTOS scheduler. */
184 FreeRTOS_debug_printf( ( "vTaskStartScheduler\n" ) );
185 vTaskStartScheduler();
186 FreeRTOS_debug_printf( ( "Should not reach this point after scheduler\n" ) );
187
188 /* If all is well, the scheduler will now be running, and the following
189 * line will never be reached. If the following line does execute, then
190 * there was insufficient FreeRTOS heap memory available for the idle and/or
191 * timer tasks to be created. See the memory management section on the
192 * FreeRTOS web site for more details (this is standard text that is not not
193 * really applicable to the Linux simulator port). */
194 for( ; ; )
195 {
196 usleep( ulLongTime_ms * 1000 );
197 }
198 }
199 /*-----------------------------------------------------------*/
200
201 /* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect
202 * events are only received if implemented in the MAC driver. */
203 /* *INDENT-OFF* */
204 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
vApplicationIPNetworkEventHook_Multi(eIPCallbackEvent_t eNetworkEvent,struct xNetworkEndPoint * pxEndPoint)205 void vApplicationIPNetworkEventHook_Multi( eIPCallbackEvent_t eNetworkEvent,
206 struct xNetworkEndPoint * pxEndPoint )
207 #else
208 void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
209 #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
210 /* *INDENT-ON* */
211 {
212 uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
213 char cBuffer[ 16 ];
214 static BaseType_t xTasksAlreadyCreated = pdFALSE;
215
216 /* If the network has just come up...*/
217 if( eNetworkEvent == eNetworkUp )
218 {
219 /* Create the tasks that use the IP stack if they have not already been
220 * created. */
221 if( xTasksAlreadyCreated == pdFALSE )
222 {
223 /* See the comments above the definitions of these pre-processor
224 * macros at the top of this file for a description of the individual
225 * demo tasks. */
226
227 #if ( mainCREATE_TCP_ECHO_TASKS_SINGLE == 1 )
228 {
229 vStartTCPEchoClientTasks_SingleTasks( mainECHO_CLIENT_TASK_STACK_SIZE, mainECHO_CLIENT_TASK_PRIORITY );
230 }
231 #endif /* mainCREATE_TCP_ECHO_TASKS_SINGLE */
232
233 xTasksAlreadyCreated = pdTRUE;
234 }
235
236 /* Print out the network configuration, which may have come from a DHCP
237 * server. */
238 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
239 FreeRTOS_GetEndPointConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress, pxNetworkEndPoints );
240 #else
241 FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );
242 #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
243 FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
244 FreeRTOS_printf( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );
245
246 FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
247 FreeRTOS_printf( ( "Subnet Mask: %s\r\n", cBuffer ) );
248
249 FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
250 FreeRTOS_printf( ( "Gateway Address: %s\r\n", cBuffer ) );
251
252 FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
253 FreeRTOS_printf( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) );
254 }
255 else
256 {
257 FreeRTOS_printf( ( "Application idle hook network down\n" ) );
258 }
259 }
260 /*-----------------------------------------------------------*/
261
uxRand(void)262 UBaseType_t uxRand( void )
263 {
264 const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
265
266 /* Utility function to generate a pseudo random number. */
267
268 ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
269 return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
270 }
271 /*-----------------------------------------------------------*/
272
prvSRand(UBaseType_t ulSeed)273 static void prvSRand( UBaseType_t ulSeed )
274 {
275 /* Utility function to seed the pseudo random number generator. */
276 ulNextRand = ulSeed;
277 }
278 /*-----------------------------------------------------------*/
279
prvMiscInitialisation(void)280 static void prvMiscInitialisation( void )
281 {
282 time_t xTimeNow;
283 uint32_t ulRandomNumbers[ 4 ];
284
285 /* Seed the random number generator. */
286 time( &xTimeNow );
287 FreeRTOS_debug_printf( ( "Seed for randomiser: %lu\n", xTimeNow ) );
288 prvSRand( ( uint32_t ) xTimeNow );
289
290 ( void ) xApplicationGetRandomNumber( &ulRandomNumbers[ 0 ] );
291 ( void ) xApplicationGetRandomNumber( &ulRandomNumbers[ 1 ] );
292 ( void ) xApplicationGetRandomNumber( &ulRandomNumbers[ 2 ] );
293 ( void ) xApplicationGetRandomNumber( &ulRandomNumbers[ 3 ] );
294
295 FreeRTOS_debug_printf( ( "Random numbers: %08X %08X %08X %08X\n",
296 ulRandomNumbers[ 0 ],
297 ulRandomNumbers[ 1 ],
298 ulRandomNumbers[ 2 ],
299 ulRandomNumbers[ 3 ] ) );
300 }
301 /*-----------------------------------------------------------*/
302
303 #if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
304
pcApplicationHostnameHook(void)305 const char * pcApplicationHostnameHook( void )
306 {
307 /* Assign the name "FreeRTOS" to this network node. This function will
308 * be called during the DHCP: the machine will be registered with an IP
309 * address plus this name. */
310 return mainHOST_NAME;
311 }
312
313 #endif
314 /*-----------------------------------------------------------*/
315
316 #if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 )
317
318 #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
xApplicationDNSQueryHook_Multi(struct xNetworkEndPoint * pxEndPoint,const char * pcName)319 BaseType_t xApplicationDNSQueryHook_Multi( struct xNetworkEndPoint * pxEndPoint,
320 const char * pcName )
321 #else
322 BaseType_t xApplicationDNSQueryHook( const char * pcName )
323 #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
324 {
325 BaseType_t xReturn;
326
327 /* Determine if a name lookup is for this node. Two names are given
328 * to this node: that returned by pcApplicationHostnameHook() and that set
329 * by mainDEVICE_NICK_NAME. */
330 if( strcasecmp( pcName, pcApplicationHostnameHook() ) == 0 )
331 {
332 xReturn = pdPASS;
333 }
334 else if( strcasecmp( pcName, mainDEVICE_NICK_NAME ) == 0 )
335 {
336 xReturn = pdPASS;
337 }
338 else
339 {
340 xReturn = pdFAIL;
341 }
342
343 return xReturn;
344 }
345
346 #endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */
347
348 /*
349 * Callback that provides the inputs necessary to generate a randomized TCP
350 * Initial Sequence Number per RFC 6528. THIS IS ONLY A DUMMY IMPLEMENTATION
351 * THAT RETURNS A PSEUDO RANDOM NUMBER SO IS NOT INTENDED FOR USE IN PRODUCTION
352 * SYSTEMS.
353 */
ulApplicationGetNextSequenceNumber(uint32_t ulSourceAddress,uint16_t usSourcePort,uint32_t ulDestinationAddress,uint16_t usDestinationPort)354 extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
355 uint16_t usSourcePort,
356 uint32_t ulDestinationAddress,
357 uint16_t usDestinationPort )
358 {
359 ( void ) ulSourceAddress;
360 ( void ) usSourcePort;
361 ( void ) ulDestinationAddress;
362 ( void ) usDestinationPort;
363
364 return uxRand();
365 }
366
367 /*
368 * Supply a random number to FreeRTOS+TCP stack.
369 * THIS IS ONLY A DUMMY IMPLEMENTATION THAT RETURNS A PSEUDO RANDOM NUMBER
370 * SO IS NOT INTENDED FOR USE IN PRODUCTION SYSTEMS.
371 */
xApplicationGetRandomNumber(uint32_t * pulNumber)372 BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
373 {
374 *( pulNumber ) = uxRand();
375 return pdTRUE;
376 }
377