summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c')
-rw-r--r--FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c b/FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c
new file mode 100644
index 000000000..2a2c704d7
--- /dev/null
+++ b/FreeRTOS/Demo/Posix_GCC/src/SimpleTCPEchoServer.c
@@ -0,0 +1,288 @@
+/*
+ FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+/*
+ * FreeRTOS tasks are used with FreeRTOS+TCP to create a TCP echo server on the
+ * standard echo port number (7).
+ *
+ * See the following web page for essential demo usage and configuration
+ * details:
+ * http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Echo_Server.html
+ */
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+
+/* Remove the whole file if FreeRTOSIPConfig.h is set to exclude TCP. */
+#if( ipconfigUSE_TCP == 1 )
+
+/* The maximum time to wait for a closing socket to close. */
+#define tcpechoSHUTDOWN_DELAY ( pdMS_TO_TICKS( 5000 ) )
+
+/* The standard echo port number. */
+#define tcpechoPORT_NUMBER 7
+
+/* If ipconfigUSE_TCP_WIN is 1 then the Tx sockets will use a buffer size set by
+ipconfigTCP_TX_BUFFER_LENGTH, and the Tx window size will be
+configECHO_SERVER_TX_WINDOW_SIZE times the buffer size. Note
+ipconfigTCP_TX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP
+stack constant, whereas configECHO_SERVER_TX_WINDOW_SIZE is set in
+FreeRTOSConfig.h as it is a demo application constant. */
+#ifndef configECHO_SERVER_TX_WINDOW_SIZE
+ #define configECHO_SERVER_TX_WINDOW_SIZE 2
+#endif
+
+/* If ipconfigUSE_TCP_WIN is 1 then the Rx sockets will use a buffer size set by
+ipconfigTCP_RX_BUFFER_LENGTH, and the Rx window size will be
+configECHO_SERVER_RX_WINDOW_SIZE times the buffer size. Note
+ipconfigTCP_RX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP
+stack constant, whereas configECHO_SERVER_RX_WINDOW_SIZE is set in
+FreeRTOSConfig.h as it is a demo application constant. */
+#ifndef configECHO_SERVER_RX_WINDOW_SIZE
+ #define configECHO_SERVER_RX_WINDOW_SIZE 2
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Uses FreeRTOS+TCP to listen for incoming echo connections, creating a task
+ * to handle each connection.
+ */
+static void prvConnectionListeningTask( void *pvParameters );
+
+/*
+ * Created by the connection listening task to handle a single connection.
+ */
+static void prvServerConnectionInstance( void *pvParameters );
+
+/*-----------------------------------------------------------*/
+
+/* Stores the stack size passed into vStartSimpleTCPServerTasks() so it can be
+reused when the server listening task creates tasks to handle connections. */
+static uint16_t usUsedStackSize = 0;
+
+/*-----------------------------------------------------------*/
+
+void vStartSimpleTCPServerTasks( uint16_t usStackSize, UBaseType_t uxPriority )
+{
+ /* Create the TCP echo server. */
+ xTaskCreate( prvConnectionListeningTask, "ServerListener", usStackSize, NULL, uxPriority + 1, NULL );
+
+ /* Remember the requested stack size so it can be re-used by the server
+ listening task when it creates tasks to handle connections. */
+ usUsedStackSize = usStackSize;
+}
+/*-----------------------------------------------------------*/
+
+static void prvConnectionListeningTask( void *pvParameters )
+{
+struct freertos_sockaddr xClient, xBindAddress;
+Socket_t xListeningSocket, xConnectedSocket;
+socklen_t xSize = sizeof( xClient );
+static const TickType_t xReceiveTimeOut = portMAX_DELAY;
+const BaseType_t xBacklog = 20;
+
+#if( ipconfigUSE_TCP_WIN == 1 )
+ WinProperties_t xWinProps;
+
+ /* Fill in the buffer and window sizes that will be used by the socket. */
+ xWinProps.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH;
+ xWinProps.lTxWinSize = configECHO_SERVER_TX_WINDOW_SIZE;
+ xWinProps.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH;
+ xWinProps.lRxWinSize = configECHO_SERVER_RX_WINDOW_SIZE;
+#endif /* ipconfigUSE_TCP_WIN */
+
+ /* Just to prevent compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Attempt to open the socket. */
+ xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
+ configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
+
+ /* Set a time out so accept() will just wait for a connection. */
+ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
+
+ /* Set the window and buffer sizes. */
+ #if( ipconfigUSE_TCP_WIN == 1 )
+ {
+ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
+ }
+ #endif /* ipconfigUSE_TCP_WIN */
+
+ /* Bind the socket to the port that the client task will send to, then
+ listen for incoming connections. */
+ xBindAddress.sin_port = tcpechoPORT_NUMBER;
+ xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
+ FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
+ FreeRTOS_listen( xListeningSocket, xBacklog );
+
+ for( ;; )
+ {
+ /* Wait for a client to connect. */
+ xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
+ configASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );
+
+ /* Spawn a task to handle the connection. */
+ xTaskCreate( prvServerConnectionInstance, "EchoServer", usUsedStackSize, ( void * ) xConnectedSocket, tskIDLE_PRIORITY, NULL );
+ }
+}
+/*-----------------------------------------------------------*/
+
+static void prvServerConnectionInstance( void *pvParameters )
+{
+int32_t lBytes, lSent, lTotalSent;
+Socket_t xConnectedSocket;
+static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
+static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 5000 );
+TickType_t xTimeOnShutdown;
+uint8_t *pucRxBuffer;
+
+ xConnectedSocket = ( Socket_t ) pvParameters;
+
+ /* Attempt to create the buffer used to receive the string to be echoed
+ back. This could be avoided using a zero copy interface that just returned
+ the same buffer. */
+ pucRxBuffer = ( uint8_t * ) pvPortMalloc( ipconfigTCP_MSS );
+
+ if( pucRxBuffer != NULL )
+ {
+ FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
+ FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) );
+
+ for( ;; )
+ {
+ /* Zero out the receive array so there is NULL at the end of the string
+ when it is printed out. */
+ memset( pucRxBuffer, 0x00, ipconfigTCP_MSS );
+
+ /* Receive data on the socket. */
+ lBytes = FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 );
+
+ /* If data was received, echo it back. */
+ if( lBytes >= 0 )
+ {
+ lSent = 0;
+ lTotalSent = 0;
+
+ /* Call send() until all the data has been sent. */
+ while( ( lSent >= 0 ) && ( lTotalSent < lBytes ) )
+ {
+ lSent = FreeRTOS_send( xConnectedSocket, pucRxBuffer, lBytes - lTotalSent, 0 );
+ lTotalSent += lSent;
+ }
+
+ if( lSent < 0 )
+ {
+ /* Socket closed? */
+ break;
+ }
+ }
+ else
+ {
+ /* Socket closed? */
+ break;
+ }
+ }
+ }
+
+ /* Initiate a shutdown in case it has not already been initiated. */
+ FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
+
+ /* Wait for the shutdown to take effect, indicated by FreeRTOS_recv()
+ returning an error. */
+ xTimeOnShutdown = xTaskGetTickCount();
+ do
+ {
+ if( FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 ) < 0 )
+ {
+ break;
+ }
+ } while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY );
+
+ /* Finished with the socket, buffer, the task. */
+ vPortFree( pucRxBuffer );
+ FreeRTOS_closesocket( xConnectedSocket );
+
+ vTaskDelete( NULL );
+}
+/*-----------------------------------------------------------*/
+
+/* The whole file is excluded if TCP is not compiled in. */
+#endif /* ipconfigUSE_TCP */
+