summaryrefslogtreecommitdiff
path: root/FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c')
-rw-r--r--FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c b/FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c
new file mode 100644
index 000000000..5d612e272
--- /dev/null
+++ b/FreeRTOS-Labs/Demo/FreeRTOS_Plus_TCP_and_FAT_Windows_Simulator/DemoTasks/TCPEchoSelectServer.c
@@ -0,0 +1,415 @@
+/*
+ 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!
+*/
+
+/* Standard includes. */
+#include <stdint.h>
+#include <stdio.h>
+#include <WinSock2.h>
+#include <Mswsock.h>
+
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* FreeRTOS+TCP includes. */
+#include "FreeRTOS_IP.h"
+#include "FreeRTOS_Sockets.h"
+#include "FreeRTOS_char_buf.h"
+
+#include "SimpleTCPEchoServer.h" /* For prvSimpleTcpServerClientTask */
+
+
+#define tcpechoNUMBER_OF_CLIENTS 0
+
+void tcpWinShowEvent( BaseType_t aDoLog );
+
+/*
+ * Listens for incoming echo connections. Creates a task to handle each
+ * connection.
+ */
+static void prvConnectionListeningTask( 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 unsigned short usUsedStackSize = 0;
+
+/*-----------------------------------------------------------*/
+
+void vStartSelectTCPServerTasks( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority )
+{
+WORD wVersionRequested;
+WSADATA xWSAData;
+BaseType_t xClient;
+//extern void prvSimpleTCPClientTask( void *pvParameters );
+
+ /* The clients use non-blocking Winsock sockets and must therefore run at
+ the idle priority. */
+ configASSERT( uxPriority == tskIDLE_PRIORITY );
+
+ /* Create the TCP echo server. The echo server uses FreeRTOS+TCP through
+ the spoofed IP and MAC address. */
+ xTaskCreate( prvConnectionListeningTask, "ServerListener", usStackSize, ( void * ) ulPort, uxPriority + 1, NULL );
+
+ /* Prepare to use WinSock library. */
+ wVersionRequested = MAKEWORD( 2, 2 );
+ configASSERT( WSAStartup( wVersionRequested, &xWSAData ) == ( WORD ) 0 );
+
+ /* 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;
+}
+
+#define SEND_BUFFER_SIZE ( 8 * ipconfigTCP_MSS )
+
+typedef struct xTCP_SERVER {
+ Socket_t xSocket;
+ struct xTCP_SERVER *pxNext;
+ SSimpleBuf *pxSendData;
+ BaseType_t bHasSendRequest;
+} TCPServer_t;
+
+static uint8_t cReceivedString[ ipconfigTCP_MSS ];
+
+static void prvTcpInit( TCPServer_t *pxTcpServer )
+{
+struct freertos_sockaddr addr;
+BaseType_t xReceiveTimeOut = 0;
+BaseType_t xSendTimeOut = 0;
+
+ pxTcpServer->pxSendData = ( SSimpleBuf * )pvPortMalloc( sizeof( *pxTcpServer->pxSendData ) - sizeof( pxTcpServer->pxSendData->array ) + SEND_BUFFER_SIZE + 1 );
+
+ configASSERT( pxTcpServer->pxSendData != NULL );
+ memset( pxTcpServer->pxSendData, '\0', sizeof( *pxTcpServer->pxSendData ) );
+ pxTcpServer->pxSendData->LENGTH = SEND_BUFFER_SIZE + 1;
+
+ FreeRTOS_GetRemoteAddress( pxTcpServer->xSocket, &addr );
+ FreeRTOS_debug_printf( ( "prvTcpInit: serving %xip:%u\n",
+ FreeRTOS_ntohl( addr.sin_addr ), addr.sin_port) );
+
+ FreeRTOS_setsockopt( pxTcpServer->xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
+ FreeRTOS_setsockopt( pxTcpServer->xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) );
+}
+
+static void prvTcpClose( TCPServer_t *pxThisServer )
+{
+ FreeRTOS_closesocket( pxThisServer->xSocket );
+ vPortFree( pxThisServer->pxSendData );
+ vPortFree( pxThisServer );
+}
+
+static BaseType_t prvTcpSend( TCPServer_t *pxTcpServer )
+{
+BaseType_t lBytes, lReturned, xReturn = 0;
+
+ lBytes = sbGet( pxTcpServer->pxSendData, 0, cReceivedString, sizeof( cReceivedString ), pdTRUE );
+ if( lBytes )
+ {
+ /* Send as much as possible, non-blocking */
+ lReturned = FreeRTOS_send( pxTcpServer->xSocket, cReceivedString, lBytes, 0 );
+ if( lReturned > 0 )
+ {
+ xReturn = sbGet( pxTcpServer->pxSendData, 0, NULL, lReturned, pdFALSE );
+ }
+ }
+ return xReturn;
+}
+
+static BaseType_t prvTcpHasSendData( TCPServer_t *pxTcpServer )
+{
+ return ( sbGetSize( pxTcpServer->pxSendData ) > 0 ) ? 1 : 0;
+}
+
+static BaseType_t prvTcpWork( TCPServer_t *pxTcpServer )
+{
+BaseType_t lBytes, lReturned, lMayWrite;
+
+ lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket );
+ if( lMayWrite < 0 )
+ return lMayWrite;
+ while( lMayWrite > 0 )
+ {
+ lReturned = prvTcpSend( pxTcpServer );
+ if( lReturned < 0 )
+ return lReturned;
+ if( lReturned == 0 )
+ break;
+ lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket );
+ if( lMayWrite < 0 )
+ return lMayWrite;
+ }
+ for( ; ; )
+ {
+ /* Zero out the receive array so there is NULL at the end of the string
+ when it is printed out. */
+ memset( cReceivedString, 0x00, sizeof( cReceivedString ) );
+
+ /* Receive data on the socket. */
+ lBytes = FreeRTOS_recv( pxTcpServer->xSocket, cReceivedString, sizeof( cReceivedString ), 0 );
+ if( lBytes <= 0 )
+ return lBytes;
+ /* Return the received characters. */
+ if( lMayWrite > 0 && sbGetSize( pxTcpServer->pxSendData ) == 0 )
+ {
+ /* The cirular buffer is empty, send the received data directly */
+ lReturned = FreeRTOS_send( pxTcpServer->xSocket, cReceivedString, lBytes, 0 );
+ if( lReturned < 0 )
+ {
+ return -1;
+ }
+ if( lBytes > lReturned )
+ {
+ /* Not all dta could be delivered, save them for later
+ * FD_SET( eSELECT_WRITE ) will be called */
+ sbAdd( pxTcpServer->pxSendData, 0, cReceivedString + lReturned, lBytes - lReturned );
+ }
+ lMayWrite = FreeRTOS_maywrite( pxTcpServer->xSocket );
+ if( lMayWrite < 0 )
+ return lMayWrite;
+ } else
+ {
+ sbAdd( pxTcpServer->pxSendData, 0, cReceivedString, lBytes );
+ }
+ }
+}
+
+static TickType_t lastTickTime;
+static BaseType_t xTaskCount = 0, xConfirmedCount = 0;
+static void prvConnectionListeningTask( void *pvParameters )
+{
+struct freertos_sockaddr xClient, xBindAddress;
+Socket_t xListeningSocket;
+
+socklen_t xSize = sizeof( xClient );
+static const TickType_t xReceiveTimeOut = 0; //portMAX_DELAY;
+const BaseType_t xBacklog = 10;
+SocketSet_t xSocketSet;
+struct xTCP_SERVER *pxServerList = NULL;
+struct xTCP_SERVER *pxIterator;
+
+WinProperties_t winProps;
+
+ /* Just to prevent compiler warnings. */
+ ( void ) pvParameters;
+
+ /* Attempt to open the socket. */
+ xListeningSocket = FreeRTOS_socket( PF_INET, SOCK_STREAM, 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 ) );
+
+ memset(&winProps, '\0', sizeof( winProps ) );
+ // Size in units of MSS
+ winProps.lTxBufSize = 1 * 1460;//1000;
+ winProps.lTxWinSize = 2;
+
+ winProps.lRxBufSize = 2 * 1460;
+ winProps.lRxWinSize = 2;
+
+ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &winProps, sizeof( winProps ) );
+
+ /* The strange casting is to remove compiler errors. */
+ xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL;
+ xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
+
+ /* Bind the socket to the port that the client task will send to, then
+ listen for incoming connections. */
+ while( FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ) != 0 );
+ FreeRTOS_listen( xListeningSocket, xBacklog );
+ lastTickTime = xTaskGetTickCount ();
+
+ pxServerList = NULL;
+
+ xSocketSet = FreeRTOS_createsocketset( );
+ configASSERT( xSocketSet != NULL );
+ FreeRTOS_FD_SET( xListeningSocket, xSocketSet, eSELECT_READ );
+
+ for( ;; )
+ {
+ TickType_t xMask = FreeRTOS_select( xSocketSet, 3000 );
+
+ if( FreeRTOS_FD_ISSET( xListeningSocket, xSocketSet ) )
+ {
+ Socket_t xNewSocket;
+
+ xNewSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
+ if ( xNewSocket && xNewSocket != FREERTOS_INVALID_SOCKET )
+ {
+ TCPServer_t *pxServer;
+
+ FreeRTOS_debug_printf( ( "prvConnectionListeningTask: new connection %xip:%u\n",
+ FreeRTOS_ntohl( xClient.sin_addr ), FreeRTOS_ntohs( xClient.sin_port ) ) );
+
+ pxServer = (TCPServer_t *)pvPortMalloc( sizeof( *pxServer ) );
+ memset( pxServer, '\0', sizeof( *pxServer ));
+
+ pxServer->xSocket = xNewSocket;
+ FreeRTOS_FD_SET( xNewSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT );
+ if( pxServerList == NULL )
+ {
+ /* This is the first server */
+ pxServerList = pxServer;
+ }
+ else
+ {
+ /* Attach it to the end of the list */
+ for( pxIterator = pxServerList; pxIterator->pxNext != NULL; pxIterator = pxIterator->pxNext )
+ {
+ }
+ pxIterator->pxNext = pxServer;
+ }
+ prvTcpInit( pxServer );
+ }
+ }
+ {
+ TCPServer_t *pxThisServer = NULL;
+
+ for( pxIterator = pxServerList; pxIterator != NULL; )
+ {
+ BaseType_t rc;
+ pxThisServer = pxIterator;
+ /* Move to the next one before the current gets deleted */
+ pxIterator = pxIterator->pxNext;
+
+ if( FreeRTOS_FD_ISSET( pxThisServer->xSocket, xSocketSet ) == 0 )
+ {
+ continue;
+ }
+
+ rc = prvTcpWork( pxThisServer );
+
+ if( rc < 0)
+ {
+ FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_ALL );
+
+ if( pxServerList = pxThisServer )
+ {
+ pxServerList = pxThisServer->pxNext;
+ }
+ else
+ {
+ struct xTCP_SERVER *pxOther;
+ for( pxOther = pxServerList; pxOther->pxNext != NULL; pxOther = pxOther->pxNext )
+ {
+ if( pxOther->pxNext == pxThisServer )
+ {
+ pxOther->pxNext == pxThisServer->pxNext;
+ break;
+ }
+ }
+ }
+ /* Close the socket and free the space */
+ prvTcpClose( pxThisServer );
+ } else
+ {
+ pxThisServer->bHasSendRequest = prvTcpHasSendData( pxThisServer );
+ if( pxThisServer->bHasSendRequest )
+ FreeRTOS_FD_SET( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE );
+ else
+ FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE );
+ //FreeRTOS_debug_printf( ( "SET_FD WRITE %d\n", pxServerFound->bHasSendRequest != 0 ) );
+ }
+ }
+ }
+ if( ( xTaskGetTickCount () - lastTickTime ) > 30000 )
+ {
+ lastTickTime = xTaskGetTickCount ();
+ //plusPrintf( "ListeningTask %ld,%ld tasks\n", xTaskCount, xConfirmedCount );
+ }
+ }
+}
+/*-----------------------------------------------------------*/
+
+static BaseType_t prvCreateTxData( uint8_t *ucBuffer, uint32_t ulBufferLength )
+{
+BaseType_t lCharactersToAdd, lCharacter;
+uint8_t ucChar = '0';
+
+ /* Randomise the number of characters that will be sent. */
+ do
+ {
+ lCharactersToAdd = ipconfigRAND32() % ( ulBufferLength - 20UL );
+ } while ( lCharactersToAdd == 0 );
+
+ /* Fill the buffer. */
+ for( lCharacter = 0; lCharacter < lCharactersToAdd; lCharacter++ )
+ {
+ ucBuffer[ lCharacter ] = ucChar;
+ ucChar++;
+
+ if( ucChar > '~' )
+ {
+ ucChar = '0';
+ }
+ }
+
+ return lCharactersToAdd;
+}
+/*-----------------------------------------------------------*/