summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c')
-rw-r--r--FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c b/FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c
new file mode 100644
index 000000000..286c1b127
--- /dev/null
+++ b/FreeRTOS-Labs/Demo/Common/FreeRTOS_Plus_UDP_Demos/EchoClients/TwoEchoClients.c
@@ -0,0 +1,359 @@
+/*
+ * FreeRTOS Kernel V10.0.1
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+/******************************************************************************
+ *
+ * See the following web page for essential TwoEchoClient.c usage and
+ * configuration details:
+ * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Common_Echo_Clients.shtml
+ *
+ ******************************************************************************/
+
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* FreeRTOS+UDP includes. */
+#include "FreeRTOS_UDP_IP.h"
+#include "FreeRTOS_Sockets.h"
+
+/* Small delay used between attempts to obtain a zero copy buffer. */
+#define echoTINY_DELAY ( ( TickType_t ) 2 )
+
+/* The echo tasks create a socket, send out a number of echo requests
+(listening for each echo reply), then close the socket again before
+starting over. This delay is used between each iteration to ensure the
+network does not get too congested. */
+#define echoLOOP_DELAY ( ( TickType_t ) 250 / portTICK_RATE_MS )
+
+#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
+ /* When the trace recorder code is included user events are generated to
+ mark the sending and receiving of the echoed data (only in the zero copy
+ task. */
+ #define echoMARK_SEND_IN_TRACE_BUFFER( x ) vTraceUserEvent( x )
+ traceLabel xZeroCopySendEvent, xZeroCopyReceiveEvent;
+
+#else
+ /* When the trace recorder code is not included just #define away the call
+ to post the user event. */
+ #define echoMARK_SEND_IN_TRACE_BUFFER( x )
+ #define xZeroCopySendEvent 0
+ #define xZeroCopyReceiveEvent 0
+#endif
+
+/* The echo server is assumed to be on port 7, which is the standard echo
+protocol port. */
+#define echoECHO_PORT ( 7 )
+
+/*
+ * Uses a socket to send data to, then receive data from, the standard echo
+ * port number 7. prvEchoClientTask() uses the standard interface.
+ * prvZeroCopyEchoClientTask() uses the zero copy interface.
+ */
+static void prvEchoClientTask( void *pvParameters );
+static void prvZeroCopyEchoClientTask( void *pvParameters );
+
+/* The receive timeout is set shorter when the windows simulator is used
+because simulated time is slower than real time. */
+#ifdef _WINDOWS_
+ const TickType_t xReceiveTimeOut = 50 / portTICK_RATE_MS;
+#else
+ const TickType_t xReceiveTimeOut = 500 / portTICK_RATE_MS;
+#endif
+
+/*-----------------------------------------------------------*/
+
+void vStartEchoClientTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
+{
+ /* Create the echo client task that does not use the zero copy interface. */
+ xTaskCreate( prvEchoClientTask, /* The function that implements the task. */
+ "Echo0", /* Just a text name for the task to aid debugging. */
+ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
+ NULL, /* The task parameter, not used in this case. */
+ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
+ NULL ); /* The task handle is not used. */
+
+ /* Create the echo client task that does use the zero copy interface. */
+ xTaskCreate( prvZeroCopyEchoClientTask, /* The function that implements the task. */
+ "Echo1", /* Just a text name for the task to aid debugging. */
+ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
+ NULL, /* The task parameter, not used in this case. */
+ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
+ NULL ); /* The task handle is not used. */
+}
+/*-----------------------------------------------------------*/
+
+static void prvEchoClientTask( void *pvParameters )
+{
+xSocket_t xSocket;
+struct freertos_sockaddr xEchoServerAddress;
+char cTxString[ 25 ], cRxString[ 25 ]; /* Make sure the stack is large enough to hold these. Turn on stack overflow checking during debug to be sure. */
+int32_t lLoopCount = 0UL;
+const int32_t lMaxLoopCount = 50;
+volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
+uint32_t xAddressLength = sizeof( xEchoServerAddress );
+
+ /* Remove compiler warning about unused parameters. */
+ ( void ) pvParameters;
+
+ /* Echo requests are sent to the echo server. The address of the echo
+ server is configured by the constants configECHO_SERVER_ADDR0 to
+ configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
+ xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
+ xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
+ configECHO_SERVER_ADDR1,
+ configECHO_SERVER_ADDR2,
+ configECHO_SERVER_ADDR3 );
+
+ for( ;; )
+ {
+ /* Create a socket. */
+ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
+ configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
+
+ /* Set a time out so a missing reply does not cause the task to block
+ indefinitely. */
+ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
+
+ /* Send a number of echo requests. */
+ for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
+ {
+ /* Create the string that is sent to the echo server. */
+ sprintf( cTxString, "Message number %u\r\n", ( unsigned int ) ulTxCount );
+
+ /* Send the string to the socket. ulFlags is set to 0, so the zero
+ copy interface is not used. That means the data from cTxString is
+ copied into a network buffer inside FreeRTOS_sendto(), and cTxString
+ can be reused as soon as FreeRTOS_sendto() has returned. 1 is added
+ to ensure the NULL string terminator is sent as part of the message. */
+ FreeRTOS_sendto( xSocket, /* The socket being sent to. */
+ ( void * ) cTxString, /* The data being sent. */
+ strlen( cTxString ) + 1,/* The length of the data being sent. */
+ 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
+ &xEchoServerAddress, /* The destination address. */
+ sizeof( xEchoServerAddress ) );
+
+ /* Keep a count of how many echo requests have been transmitted so
+ it can be compared to the number of echo replies received. It would
+ be expected to loose at least one to an ARP message the first time
+ the connection is created. */
+ ulTxCount++;
+
+ /* Receive data echoed back to the socket. ulFlags is zero, so the
+ zero copy option is not being used and the received data will be
+ copied into the buffer pointed to by cRxString. xAddressLength is
+ not actually used (at the time of writing this comment, anyway) by
+ FreeRTOS_recvfrom(), but is set appropriately in case future
+ versions do use it. */
+ memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) );
+ FreeRTOS_recvfrom( xSocket, /* The socket being received from. */
+ cRxString, /* The buffer into which the received data will be written. */
+ sizeof( cRxString ), /* The size of the buffer provided to receive the data. */
+ 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
+ &xEchoServerAddress, /* The address from where the data was sent (the source address). */
+ &xAddressLength );
+
+ /* Compare the transmitted string to the received string. */
+ if( strcmp( cRxString, cTxString ) == 0 )
+ {
+ /* The echo reply was received without error. */
+ ulRxCount++;
+ }
+ };
+
+ /* Pause for a short while to ensure the network is not too
+ congested. */
+ vTaskDelay( echoLOOP_DELAY );
+
+ /* Close this socket before looping back to create another. */
+ FreeRTOS_closesocket( xSocket );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvZeroCopyEchoClientTask( void *pvParameters )
+{
+xSocket_t xSocket;
+struct freertos_sockaddr xEchoServerAddress;
+static char cTxString[ 40 ];
+int32_t lLoopCount = 0UL;
+volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
+uint32_t xAddressLength = sizeof( xEchoServerAddress );
+int32_t lReturned;
+uint8_t *pucUDPPayloadBuffer;
+
+const int32_t lMaxLoopCount = 50;
+const char * const pcStringToSend = "Zero copy message number";
+/* The buffer is large enough to hold the string, a number, and the string terminator. */
+const size_t xBufferLength = strlen( pcStringToSend ) + 15;
+
+ #if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
+ {
+ /* When the trace recorder code is included user events are generated to
+ mark the sending and receiving of the echoed data (only in the zero copy
+ task). */
+ xZeroCopySendEvent = xTraceOpenLabel( "ZeroCopyTx" );
+ xZeroCopyReceiveEvent = xTraceOpenLabel( "ZeroCopyRx" );
+ }
+ #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS */
+
+ /* Remove compiler warning about unused parameters. */
+ ( void ) pvParameters;
+
+ /* Delay for a little while to ensure the task is out of synch with the
+ other echo task implemented above. */
+ vTaskDelay( echoLOOP_DELAY >> 1 );
+
+ /* Echo requests are sent to the echo server. The address of the echo
+ server is configured by the constants configECHO_SERVER_ADDR0 to
+ configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
+ xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
+ xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
+ configECHO_SERVER_ADDR1,
+ configECHO_SERVER_ADDR2,
+ configECHO_SERVER_ADDR3 );
+
+ for( ;; )
+ {
+ /* Create a socket. */
+ xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
+ configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
+
+ /* Set a time out so a missing reply does not cause the task to block
+ indefinitely. */
+ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
+
+ /* Send a number of echo requests. */
+ for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
+ {
+ /* This task is going to send using the zero copy interface. The
+ data being sent is therefore written directly into a buffer that is
+ passed by reference into the FreeRTOS_sendto() function. First
+ obtain a buffer of adequate size from the IP stack. Although a max
+ delay is used, the actual delay will be capped to
+ ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the test to ensure a buffer
+ was actually obtained. */
+ pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xBufferLength, portMAX_DELAY );
+
+ if( pucUDPPayloadBuffer != NULL )
+ {
+ /* A buffer was successfully obtained. Create the string that is
+ sent to the echo server. Note the string is written directly
+ into the buffer obtained from the IP stack. */
+ sprintf( ( char * ) pucUDPPayloadBuffer, "%s %u\r\n", "Zero copy message number", ( unsigned int ) ulTxCount );
+
+ /* Also copy the string into a local buffer so it can be compared
+ with the string that is later received back from the echo server. */
+ strcpy( cTxString, ( char * ) pucUDPPayloadBuffer );
+
+ /* Pass the buffer into the send function. ulFlags has the
+ FREERTOS_ZERO_COPY bit set so the IP stack will take control of
+ the buffer, rather than copy data out of the buffer. */
+ echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopySendEvent );
+ lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */
+ ( void * ) pucUDPPayloadBuffer, /* The buffer being passed into the IP stack. */
+ strlen( cTxString ) + 1, /* The length of the data being sent. Plus 1 to ensure the null terminator is part of the data. */
+ FREERTOS_ZERO_COPY, /* ulFlags with the zero copy bit is set. */
+ &xEchoServerAddress, /* Where the data is being sent. */
+ sizeof( xEchoServerAddress ) );
+
+ if( lReturned == 0 )
+ {
+ /* The send operation failed, so this task is still
+ responsible for the buffer obtained from the IP stack. To
+ ensure the buffer is not lost it must either be used again,
+ or, as in this case, returned to the IP stack using
+ FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can
+ be safely re-used to receive from the socket below once the
+ buffer has been returned to the stack. */
+ FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
+ }
+ else
+ {
+ /* The send was successful so the IP stack is now managing
+ the buffer pointed to by pucUDPPayloadBuffer, and the IP
+ stack will return the buffer once it has been sent.
+ pucUDPPayloadBuffer can be safely re-used to receive from
+ the socket below. */
+ }
+
+ /* Keep a count of how many echo requests have been transmitted
+ so it can be compared to the number of echo replies received.
+ It would be expected to loose at least one to an ARP message the
+ first time the connection is created. */
+ ulTxCount++;
+
+ /* Receive data on the socket. ulFlags has the zero copy bit set
+ (FREERTOS_ZERO_COPY) indicating to the stack that a reference to
+ the received data should be passed out to this task using the
+ second parameter to the FreeRTOS_recvfrom() call. When this is
+ done the IP stack is no longer responsible for releasing the
+ buffer, and the task *must* return the buffer to the stack when
+ it is no longer needed. By default the receive block time is
+ portMAX_DELAY. */
+ echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopyReceiveEvent );
+ lReturned = FreeRTOS_recvfrom( xSocket, /* The socket to receive from. */
+ ( void * ) &pucUDPPayloadBuffer, /* pucUDPPayloadBuffer will be set to point to the buffer that already contains the received data. */
+ 0, /* Ignored because the zero copy interface is being used. */
+ FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
+ &xEchoServerAddress, /* The address from which the data was sent. */
+ &xAddressLength );
+
+ if( lReturned > 0 )
+ {
+ /* Compare the string sent to the echo server with the string
+ received back from the echo server. */
+ if( strcmp( ( char * ) pucUDPPayloadBuffer, cTxString ) == 0 )
+ {
+ /* The strings matched. */
+ ulRxCount++;
+ }
+
+ /* The buffer that contains the data passed out of the stack
+ *must* be returned to the stack. */
+ FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
+ }
+ }
+ }
+
+ /* Pause for a short while to ensure the network is not too
+ congested. */
+ vTaskDelay( echoLOOP_DELAY );
+
+ /* Close this socket before looping back to create another. */
+ FreeRTOS_closesocket( xSocket );
+ }
+}
+/*-----------------------------------------------------------*/
+