]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Demo/Common/Demo_IP_Protocols/Common/FreeRTOS_TCP_server.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / Common / Demo_IP_Protocols / Common / FreeRTOS_TCP_server.c
diff --git a/FreeRTOS-Labs/Demo/Common/Demo_IP_Protocols/Common/FreeRTOS_TCP_server.c b/FreeRTOS-Labs/Demo/Common/Demo_IP_Protocols/Common/FreeRTOS_TCP_server.c
new file mode 100644 (file)
index 0000000..3b9f8fb
--- /dev/null
@@ -0,0 +1,353 @@
+/*\r
+ * FreeRTOS+TCP V2.0.3\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://aws.amazon.com/freertos\r
+ * http://www.FreeRTOS.org\r
+ */\r
+\r
+\r
+/* Standard includes. */\r
+#include <stdint.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+#include "FreeRTOS_TCP_server.h"\r
+#include "FreeRTOS_server_private.h"\r
+\r
+/* Remove the entire file if TCP is not being used. */\r
+#if( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) )\r
+\r
+#if !defined( ARRAY_SIZE )\r
+       #define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )\r
+#endif\r
+\r
+\r
+static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket );\r
+static char *strnew( const char *pcString );\r
+/* Remove slashes at the end of a path. */\r
+static void prvRemoveSlash( char *pcDir );\r
+\r
+TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount )\r
+{\r
+TCPServer_t *pxServer;\r
+SocketSet_t xSocketSet;\r
+\r
+       /* Create a new server.\r
+       xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */\r
+       xSocketSet = FreeRTOS_CreateSocketSet();\r
+\r
+       if( xSocketSet != NULL )\r
+       {\r
+       BaseType_t xSize;\r
+\r
+               xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );\r
+\r
+               pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );\r
+               if( pxServer != NULL )\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               BaseType_t xNoTimeout = 0;\r
+               BaseType_t xIndex;\r
+\r
+                       memset( pxServer, '\0', xSize );\r
+                       pxServer->xServerCount = xCount;\r
+                       pxServer->xSocketSet = xSocketSet;\r
+\r
+                       for( xIndex = 0; xIndex < xCount; xIndex++ )\r
+                       {\r
+                       BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;\r
+\r
+                               if( xPortNumber > 0 )\r
+                               {\r
+                               Socket_t xSocket;\r
+\r
+                                       xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );\r
+                                       FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) );\r
+\r
+                                       if( xSocket != FREERTOS_NO_SOCKET )\r
+                                       {\r
+                                               xAddress.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used\r
+                                               xAddress.sin_port = FreeRTOS_htons( xPortNumber );\r
+\r
+                                               FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );\r
+                                               FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );\r
+\r
+                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );\r
+                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );\r
+\r
+                                               #if( ipconfigHTTP_RX_BUFSIZE > 0 )\r
+                                               {\r
+                                                       if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )\r
+                                                       {\r
+                                                       WinProperties_t xWinProps;\r
+\r
+                                                               memset( &xWinProps, '\0', sizeof( xWinProps ) );\r
+                                                               /* The parent socket itself won't get connected.  The properties below\r
+                                                               will be inherited by each new child socket. */\r
+                                                               xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;\r
+                                                               xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;\r
+                                                               xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;\r
+                                                               xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;\r
+\r
+                                                               /* Set the window and buffer sizes. */\r
+                                                               FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps,     sizeof( xWinProps ) );\r
+                                                       }\r
+                                               }\r
+                                               #endif\r
+\r
+                                               FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT );\r
+                                               pxServer->xServers[ xIndex ].xSocket = xSocket;\r
+                                               pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;\r
+                                               pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );\r
+                                               prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* Could not allocate the server, delete the socket set */\r
+                       FreeRTOS_DeleteSocketSet( xSocketSet );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               /* Could not create a socket set, return NULL */\r
+               pxServer = NULL;\r
+       }\r
+\r
+       return pxServer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket )\r
+{\r
+TCPClient_t *pxClient = NULL;\r
+BaseType_t xSize = 0;\r
+FTCPWorkFunction fWorkFunc = NULL;\r
+FTCPDeleteFunction fDeleteFunc = NULL;\r
+const char *pcType = "Unknown";\r
+\r
+       /*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure\r
+       becomes generic, with no pre-processing required? */\r
+       #if( ipconfigUSE_HTTP != 0 )\r
+       {\r
+               if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )\r
+               {\r
+                       xSize = sizeof( HTTPClient_t );\r
+                       fWorkFunc = xHTTPClientWork;\r
+                       fDeleteFunc = vHTTPClientDelete;\r
+                       pcType = "HTTP";\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_HTTP != 0 */\r
+\r
+       #if( ipconfigUSE_FTP != 0 )\r
+       {\r
+               if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )\r
+               {\r
+                       xSize = sizeof( FTPClient_t );\r
+                       fWorkFunc = xFTPClientWork;\r
+                       fDeleteFunc = vFTPClientDelete;\r
+                       pcType = "FTP";\r
+               }\r
+       }\r
+       #endif /* ipconfigUSE_FTP != 0 */\r
+\r
+       /* Malloc enough space for a new HTTP-client */\r
+       if( xSize )\r
+       {\r
+               pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize );\r
+       }\r
+\r
+       if( pxClient != NULL )\r
+       {\r
+               memset( pxClient, '\0', xSize );\r
+\r
+               /* Put the new client in front of the list. */\r
+               pxClient->eType = pxServer->xServers[ xIndex ].eType;\r
+               pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;\r
+               pxClient->pxParent = pxServer;\r
+               pxClient->xSocket = xNexSocket;\r
+               pxClient->pxNextClient = pxServer->pxClients;\r
+               pxClient->fWorkFunction = fWorkFunc;\r
+               pxClient->fDeleteFunction = fDeleteFunc;\r
+               pxServer->pxClients = pxClient;\r
+\r
+               FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );\r
+       }\r
+       else\r
+       {\r
+               pcType = "closed";\r
+               FreeRTOS_closesocket( xNexSocket );\r
+       }\r
+       {\r
+       struct freertos_sockaddr xRemoteAddress;\r
+               FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );\r
+               FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, (unsigned)FreeRTOS_ntohl( xRemoteAddress.sin_addr ) ) );\r
+       }\r
+\r
+       /* Remove compiler warnings in case FreeRTOS_printf() is not used. */\r
+       ( void ) pcType;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime )\r
+{\r
+TCPClient_t **ppxClient;\r
+BaseType_t xIndex;\r
+BaseType_t xRc;\r
+\r
+       /* Let the server do one working cycle */\r
+       xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );\r
+\r
+       if( xRc != 0 )\r
+       {\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+               struct freertos_sockaddr xAddress;\r
+               Socket_t xNexSocket;\r
+               socklen_t xSocketLength;\r
+\r
+                       if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )\r
+                       {\r
+                               continue;\r
+                       }\r
+\r
+                       xSocketLength = sizeof( xAddress );\r
+                       xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength);\r
+\r
+                       if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )\r
+                       {\r
+                               prvReceiveNewClient( pxServer, xIndex, xNexSocket );\r
+                       }\r
+               }\r
+       }\r
+\r
+       ppxClient = &pxServer->pxClients;\r
+\r
+       while( ( * ppxClient ) != NULL )\r
+       {\r
+       TCPClient_t *pxThis = *ppxClient;\r
+\r
+               /* Almost C++ */\r
+               xRc = pxThis->fWorkFunction( pxThis );\r
+\r
+               if (xRc < 0 )\r
+               {\r
+                       *ppxClient = pxThis->pxNextClient;\r
+                       /* Close handles, resources */\r
+                       pxThis->fDeleteFunction( pxThis );\r
+                       /* Free the space */\r
+                       vPortFreeLarge( pxThis );\r
+               }\r
+               else\r
+               {\r
+                       ppxClient = &( pxThis->pxNextClient );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static char *strnew( const char *pcString )\r
+{\r
+BaseType_t xLength;\r
+char *pxBuffer;\r
+\r
+       xLength = strlen( pcString ) + 1;\r
+       pxBuffer = ( char * ) pvPortMalloc( xLength );\r
+       if( pxBuffer != NULL )\r
+       {\r
+               memcpy( pxBuffer, pcString, xLength );\r
+       }\r
+\r
+       return pxBuffer;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvRemoveSlash( char *pcDir )\r
+{\r
+BaseType_t xLength = strlen( pcDir );\r
+\r
+       while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )\r
+       {\r
+               pcDir[ --xLength ] = '\0';\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* FreeRTOS_TCPServerWork() calls select().\r
+       The two functions below provide a possibility to interrupt\r
+       the call to select(). After the interruption, resume\r
+       by calling FreeRTOS_TCPServerWork() again. */\r
+       BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer )\r
+       {\r
+       BaseType_t xIndex;\r
+       BaseType_t xResult = pdFALSE;\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+                       if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )\r
+                       {\r
+                               FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );\r
+                               xResult = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( ipconfigSUPPORT_SIGNALS != 0 )\r
+\r
+       /* Same as above: this function may be called from an ISR,\r
+       for instance a GPIO interrupt. */\r
+       BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken )\r
+       {\r
+       BaseType_t xIndex;\r
+       BaseType_t xResult = pdFALSE;\r
+               for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )\r
+               {\r
+                       if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )\r
+                       {\r
+                               FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );\r
+                               xResult = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               return xResult;\r
+       }\r
+#endif /* ipconfigSUPPORT_SIGNALS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#endif /* ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) */\r