Initial version
This commit is contained in:
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
#include "FreeRTOS_TCP_server.h"
|
||||
#include "FreeRTOS_server_private.h"
|
||||
|
||||
/* Remove the entire file if TCP is not being used. */
|
||||
#if( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) )
|
||||
|
||||
#if !defined( ARRAY_SIZE )
|
||||
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
|
||||
#endif
|
||||
|
||||
|
||||
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket );
|
||||
static char *strnew( const char *pcString );
|
||||
/* Remove slashes at the end of a path. */
|
||||
static void prvRemoveSlash( char *pcDir );
|
||||
|
||||
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount )
|
||||
{
|
||||
TCPServer_t *pxServer;
|
||||
SocketSet_t xSocketSet;
|
||||
|
||||
/* Create a new server.
|
||||
xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */
|
||||
xSocketSet = FreeRTOS_CreateSocketSet();
|
||||
|
||||
if( xSocketSet != NULL )
|
||||
{
|
||||
BaseType_t xSize;
|
||||
|
||||
xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );
|
||||
|
||||
pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );
|
||||
if( pxServer != NULL )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
BaseType_t xNoTimeout = 0;
|
||||
BaseType_t xIndex;
|
||||
|
||||
memset( pxServer, '\0', xSize );
|
||||
pxServer->xServerCount = xCount;
|
||||
pxServer->xSocketSet = xSocketSet;
|
||||
|
||||
for( xIndex = 0; xIndex < xCount; xIndex++ )
|
||||
{
|
||||
BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;
|
||||
|
||||
if( xPortNumber > 0 )
|
||||
{
|
||||
Socket_t xSocket;
|
||||
|
||||
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
|
||||
FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) );
|
||||
|
||||
if( xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
xAddress.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used
|
||||
xAddress.sin_port = FreeRTOS_htons( xPortNumber );
|
||||
|
||||
FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
|
||||
FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );
|
||||
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
|
||||
|
||||
#if( ipconfigHTTP_RX_BUFSIZE > 0 )
|
||||
{
|
||||
if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )
|
||||
{
|
||||
WinProperties_t xWinProps;
|
||||
|
||||
memset( &xWinProps, '\0', sizeof( xWinProps ) );
|
||||
/* The parent socket itself won't get connected. The properties below
|
||||
will be inherited by each new child socket. */
|
||||
xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;
|
||||
xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;
|
||||
xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;
|
||||
xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;
|
||||
|
||||
/* Set the window and buffer sizes. */
|
||||
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
|
||||
pxServer->xServers[ xIndex ].xSocket = xSocket;
|
||||
pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;
|
||||
pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );
|
||||
prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not allocate the server, delete the socket set */
|
||||
FreeRTOS_DeleteSocketSet( xSocketSet );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not create a socket set, return NULL */
|
||||
pxServer = NULL;
|
||||
}
|
||||
|
||||
return pxServer;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket )
|
||||
{
|
||||
TCPClient_t *pxClient = NULL;
|
||||
BaseType_t xSize = 0;
|
||||
FTCPWorkFunction fWorkFunc = NULL;
|
||||
FTCPDeleteFunction fDeleteFunc = NULL;
|
||||
const char *pcType = "Unknown";
|
||||
|
||||
/*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure
|
||||
becomes generic, with no pre-processing required? */
|
||||
#if( ipconfigUSE_HTTP != 0 )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )
|
||||
{
|
||||
xSize = sizeof( HTTPClient_t );
|
||||
fWorkFunc = xHTTPClientWork;
|
||||
fDeleteFunc = vHTTPClientDelete;
|
||||
pcType = "HTTP";
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_HTTP != 0 */
|
||||
|
||||
#if( ipconfigUSE_FTP != 0 )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )
|
||||
{
|
||||
xSize = sizeof( FTPClient_t );
|
||||
fWorkFunc = xFTPClientWork;
|
||||
fDeleteFunc = vFTPClientDelete;
|
||||
pcType = "FTP";
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigUSE_FTP != 0 */
|
||||
|
||||
/* Malloc enough space for a new HTTP-client */
|
||||
if( xSize )
|
||||
{
|
||||
pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize );
|
||||
}
|
||||
|
||||
if( pxClient != NULL )
|
||||
{
|
||||
memset( pxClient, '\0', xSize );
|
||||
|
||||
/* Put the new client in front of the list. */
|
||||
pxClient->eType = pxServer->xServers[ xIndex ].eType;
|
||||
pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;
|
||||
pxClient->pxParent = pxServer;
|
||||
pxClient->xSocket = xNexSocket;
|
||||
pxClient->pxNextClient = pxServer->pxClients;
|
||||
pxClient->fWorkFunction = fWorkFunc;
|
||||
pxClient->fDeleteFunction = fDeleteFunc;
|
||||
pxServer->pxClients = pxClient;
|
||||
|
||||
FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT );
|
||||
}
|
||||
else
|
||||
{
|
||||
pcType = "closed";
|
||||
FreeRTOS_closesocket( xNexSocket );
|
||||
}
|
||||
{
|
||||
struct freertos_sockaddr xRemoteAddress;
|
||||
FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );
|
||||
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, (unsigned)FreeRTOS_ntohl( xRemoteAddress.sin_addr ) ) );
|
||||
}
|
||||
|
||||
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
|
||||
( void ) pcType;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime )
|
||||
{
|
||||
TCPClient_t **ppxClient;
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xRc;
|
||||
|
||||
/* Let the server do one working cycle */
|
||||
xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );
|
||||
|
||||
if( xRc != 0 )
|
||||
{
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
Socket_t xNexSocket;
|
||||
socklen_t xSocketLength;
|
||||
|
||||
if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
xSocketLength = sizeof( xAddress );
|
||||
xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength);
|
||||
|
||||
if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
|
||||
{
|
||||
prvReceiveNewClient( pxServer, xIndex, xNexSocket );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ppxClient = &pxServer->pxClients;
|
||||
|
||||
while( ( * ppxClient ) != NULL )
|
||||
{
|
||||
TCPClient_t *pxThis = *ppxClient;
|
||||
|
||||
/* Almost C++ */
|
||||
xRc = pxThis->fWorkFunction( pxThis );
|
||||
|
||||
if (xRc < 0 )
|
||||
{
|
||||
*ppxClient = pxThis->pxNextClient;
|
||||
/* Close handles, resources */
|
||||
pxThis->fDeleteFunction( pxThis );
|
||||
/* Free the space */
|
||||
vPortFreeLarge( pxThis );
|
||||
}
|
||||
else
|
||||
{
|
||||
ppxClient = &( pxThis->pxNextClient );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static char *strnew( const char *pcString )
|
||||
{
|
||||
BaseType_t xLength;
|
||||
char *pxBuffer;
|
||||
|
||||
xLength = strlen( pcString ) + 1;
|
||||
pxBuffer = ( char * ) pvPortMalloc( xLength );
|
||||
if( pxBuffer != NULL )
|
||||
{
|
||||
memcpy( pxBuffer, pcString, xLength );
|
||||
}
|
||||
|
||||
return pxBuffer;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRemoveSlash( char *pcDir )
|
||||
{
|
||||
BaseType_t xLength = strlen( pcDir );
|
||||
|
||||
while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )
|
||||
{
|
||||
pcDir[ --xLength ] = '\0';
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
|
||||
/* FreeRTOS_TCPServerWork() calls select().
|
||||
The two functions below provide a possibility to interrupt
|
||||
the call to select(). After the interruption, resume
|
||||
by calling FreeRTOS_TCPServerWork() again. */
|
||||
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xResult = pdFALSE;
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );
|
||||
xResult = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
|
||||
#endif /* ipconfigSUPPORT_SIGNALS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
|
||||
/* Same as above: this function may be called from an ISR,
|
||||
for instance a GPIO interrupt. */
|
||||
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
BaseType_t xResult = pdFALSE;
|
||||
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
|
||||
{
|
||||
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );
|
||||
xResult = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
#endif /* ipconfigSUPPORT_SIGNALS */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) */
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_FTP_commands.h"
|
||||
|
||||
const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] =
|
||||
{
|
||||
/* cmdLen cmdName[7] cmdType checkLogin checkNullArg */
|
||||
{ 4, "USER", ECMD_USER, pdFALSE, pdFALSE },
|
||||
{ 4, "PASS", ECMD_PASS, pdFALSE, pdFALSE },
|
||||
{ 4, "ACCT", ECMD_ACCT, pdTRUE, pdFALSE },
|
||||
{ 3, "CWD", ECMD_CWD, pdTRUE, pdTRUE },
|
||||
{ 4, "CDUP", ECMD_CDUP, pdTRUE, pdFALSE },
|
||||
{ 4, "SMNT", ECMD_SMNT, pdTRUE, pdFALSE },
|
||||
{ 4, "QUIT", ECMD_QUIT, pdTRUE, pdFALSE },
|
||||
{ 4, "REIN", ECMD_REIN, pdTRUE, pdFALSE },
|
||||
{ 4, "PORT", ECMD_PORT, pdTRUE, pdFALSE },
|
||||
{ 4, "PASV", ECMD_PASV, pdTRUE, pdFALSE },
|
||||
{ 4, "TYPE", ECMD_TYPE, pdTRUE, pdFALSE },
|
||||
{ 4, "STRU", ECMD_STRU, pdTRUE, pdFALSE },
|
||||
{ 4, "MODE", ECMD_MODE, pdTRUE, pdFALSE },
|
||||
{ 4, "RETR", ECMD_RETR, pdTRUE, pdTRUE },
|
||||
{ 4, "STOR", ECMD_STOR, pdTRUE, pdTRUE },
|
||||
{ 4, "STOU", ECMD_STOU, pdTRUE, pdFALSE },
|
||||
{ 4, "APPE", ECMD_APPE, pdTRUE, pdFALSE },
|
||||
{ 4, "ALLO", ECMD_ALLO, pdTRUE, pdFALSE },
|
||||
{ 4, "REST", ECMD_REST, pdTRUE, pdFALSE },
|
||||
{ 4, "RNFR", ECMD_RNFR, pdTRUE, pdTRUE },
|
||||
{ 4, "RNTO", ECMD_RNTO, pdTRUE, pdTRUE },
|
||||
{ 4, "ABOR", ECMD_ABOR, pdTRUE, pdFALSE },
|
||||
{ 4, "SIZE", ECMD_SIZE, pdTRUE, pdTRUE },
|
||||
{ 4, "MDTM", ECMD_MDTM, pdTRUE, pdTRUE },
|
||||
{ 4, "DELE", ECMD_DELE, pdTRUE, pdTRUE },
|
||||
{ 3, "RMD", ECMD_RMD, pdTRUE, pdTRUE },
|
||||
{ 3, "MKD", ECMD_MKD, pdTRUE, pdTRUE },
|
||||
{ 3, "PWD", ECMD_PWD, pdTRUE, pdFALSE },
|
||||
{ 4, "LIST", ECMD_LIST, pdTRUE, pdFALSE },
|
||||
{ 4, "NLST", ECMD_NLST, pdTRUE, pdFALSE },
|
||||
{ 4, "SITE", ECMD_SITE, pdTRUE, pdFALSE },
|
||||
{ 4, "SYST", ECMD_SYST, pdFALSE, pdFALSE },
|
||||
{ 4, "FEAT", ECMD_FEAT, pdFALSE, pdFALSE },
|
||||
{ 4, "STAT", ECMD_STAT, pdTRUE, pdFALSE },
|
||||
{ 4, "HELP", ECMD_HELP, pdFALSE, pdFALSE },
|
||||
{ 4, "NOOP", ECMD_NOOP, pdFALSE, pdFALSE },
|
||||
{ 4, "EMPT", ECMD_EMPTY, pdFALSE, pdFALSE },
|
||||
{ 4, "CLOS", ECMD_CLOSE, pdTRUE, pdFALSE },
|
||||
{ 4, "UNKN", ECMD_UNKNOWN, pdFALSE, pdFALSE },
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#include "FreeRTOS_HTTP_commands.h"
|
||||
|
||||
const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] =
|
||||
{
|
||||
{ 3, "GET", ECMD_GET },
|
||||
{ 4, "HEAD", ECMD_HEAD },
|
||||
{ 4, "POST", ECMD_POST },
|
||||
{ 3, "PUT", ECMD_PUT },
|
||||
{ 6, "DELETE", ECMD_DELETE },
|
||||
{ 5, "TRACE", ECMD_TRACE },
|
||||
{ 7, "OPTIONS", ECMD_OPTIONS },
|
||||
{ 7, "CONNECT", ECMD_CONNECT },
|
||||
{ 5, "PATCH", ECMD_PATCH },
|
||||
{ 4, "UNKN", ECMD_UNK },
|
||||
};
|
||||
|
||||
const char *webCodename (int aCode)
|
||||
{
|
||||
switch (aCode) {
|
||||
case WEB_REPLY_OK: // = 200,
|
||||
return "OK";
|
||||
case WEB_NO_CONTENT: // 204
|
||||
return "No content";
|
||||
case WEB_BAD_REQUEST: // = 400,
|
||||
return "Bad request";
|
||||
case WEB_UNAUTHORIZED: // = 401,
|
||||
return "Authorization Required";
|
||||
case WEB_NOT_FOUND: // = 404,
|
||||
return "Not Found";
|
||||
case WEB_GONE: // = 410,
|
||||
return "Done";
|
||||
case WEB_PRECONDITION_FAILED: // = 412,
|
||||
return "Precondition Failed";
|
||||
case WEB_INTERNAL_SERVER_ERROR: // = 500,
|
||||
return "Internal Server Error";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
@ -0,0 +1,428 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
/* FreeRTOS Protocol includes. */
|
||||
#include "FreeRTOS_HTTP_commands.h"
|
||||
#include "FreeRTOS_TCP_server.h"
|
||||
#include "FreeRTOS_server_private.h"
|
||||
|
||||
/* Remove the whole file if HTTP is not supported. */
|
||||
#if( ipconfigUSE_HTTP == 1 )
|
||||
|
||||
/* FreeRTOS+FAT includes. */
|
||||
#include "ff_stdio.h"
|
||||
|
||||
#ifndef HTTP_SERVER_BACKLOG
|
||||
#define HTTP_SERVER_BACKLOG ( 12 )
|
||||
#endif
|
||||
|
||||
#ifndef USE_HTML_CHUNKS
|
||||
#define USE_HTML_CHUNKS ( 0 )
|
||||
#endif
|
||||
|
||||
#if !defined( ARRAY_SIZE )
|
||||
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] )
|
||||
#endif
|
||||
|
||||
/* Some defines to make the code more readbale */
|
||||
#define pcCOMMAND_BUFFER pxClient->pxParent->pcCommandBuffer
|
||||
#define pcNEW_DIR pxClient->pxParent->pcNewDir
|
||||
#define pcFILE_BUFFER pxClient->pxParent->pcFileBuffer
|
||||
|
||||
#ifndef ipconfigHTTP_REQUEST_CHARACTER
|
||||
#define ipconfigHTTP_REQUEST_CHARACTER '?'
|
||||
#endif
|
||||
|
||||
/*_RB_ Need comment block, although fairly self evident. */
|
||||
static void prvFileClose( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex );
|
||||
static const char *pcGetContentsType( const char *apFname );
|
||||
static BaseType_t prvOpenURL( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvSendFile( HTTPClient_t *pxClient );
|
||||
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode );
|
||||
|
||||
static const char pcEmptyString[1] = { '\0' };
|
||||
|
||||
typedef struct xTYPE_COUPLE
|
||||
{
|
||||
const char *pcExtension;
|
||||
const char *pcType;
|
||||
} TypeCouple_t;
|
||||
|
||||
static TypeCouple_t pxTypeCouples[ ] =
|
||||
{
|
||||
{ "html", "text/html" },
|
||||
{ "css", "text/css" },
|
||||
{ "js", "text/javascript" },
|
||||
{ "png", "image/png" },
|
||||
{ "jpg", "image/jpeg" },
|
||||
{ "gif", "image/gif" },
|
||||
{ "txt", "text/plain" },
|
||||
{ "mp3", "audio/mpeg3" },
|
||||
{ "wav", "audio/wav" },
|
||||
{ "flac", "audio/ogg" },
|
||||
{ "pdf", "application/pdf" },
|
||||
{ "ttf", "application/x-font-ttf" },
|
||||
{ "ttc", "application/x-font-ttf" }
|
||||
};
|
||||
|
||||
void vHTTPClientDelete( TCPClient_t *pxTCPClient )
|
||||
{
|
||||
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
|
||||
|
||||
/* This HTTP client stops, close / release all resources. */
|
||||
if( pxClient->xSocket != FREERTOS_NO_SOCKET )
|
||||
{
|
||||
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );
|
||||
FreeRTOS_closesocket( pxClient->xSocket );
|
||||
pxClient->xSocket = FREERTOS_NO_SOCKET;
|
||||
}
|
||||
prvFileClose( pxClient );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvFileClose( HTTPClient_t *pxClient )
|
||||
{
|
||||
if( pxClient->pxFileHandle != NULL )
|
||||
{
|
||||
FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) );
|
||||
ff_fclose( pxClient->pxFileHandle );
|
||||
pxClient->pxFileHandle = NULL;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode )
|
||||
{
|
||||
struct xTCP_SERVER *pxParent = pxClient->pxParent;
|
||||
BaseType_t xRc;
|
||||
|
||||
/* A normal command reply on the main socket (port 21). */
|
||||
char *pcBuffer = pxParent->pcFileBuffer;
|
||||
|
||||
xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ),
|
||||
"HTTP/1.1 %d %s\r\n"
|
||||
#if USE_HTML_CHUNKS
|
||||
"Transfer-Encoding: chunked\r\n"
|
||||
#endif
|
||||
"Content-Type: %s\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"%s\r\n",
|
||||
( int ) xCode,
|
||||
webCodename (xCode),
|
||||
pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html",
|
||||
pxParent->pcExtraContents );
|
||||
|
||||
pxParent->pcContentsType[0] = '\0';
|
||||
pxParent->pcExtraContents[0] = '\0';
|
||||
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 );
|
||||
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvSendFile( HTTPClient_t *pxClient )
|
||||
{
|
||||
size_t uxSpace;
|
||||
size_t uxCount;
|
||||
BaseType_t xRc = 0;
|
||||
|
||||
if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED )
|
||||
{
|
||||
pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
|
||||
|
||||
strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) );
|
||||
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
|
||||
"Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft );
|
||||
|
||||
/* "Requested file action OK". */
|
||||
xRc = prvSendReply( pxClient, WEB_REPLY_OK );
|
||||
}
|
||||
|
||||
if( xRc >= 0 ) do
|
||||
{
|
||||
uxSpace = FreeRTOS_tx_space( pxClient->xSocket );
|
||||
|
||||
if( pxClient->uxBytesLeft < uxSpace )
|
||||
{
|
||||
uxCount = pxClient->uxBytesLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
uxCount = uxSpace;
|
||||
}
|
||||
|
||||
if( uxCount > 0u )
|
||||
{
|
||||
if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) )
|
||||
{
|
||||
uxCount = sizeof( pxClient->pxParent->pcFileBuffer );
|
||||
}
|
||||
ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );
|
||||
pxClient->uxBytesLeft -= uxCount;
|
||||
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 );
|
||||
if( xRc < 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while( uxCount > 0u );
|
||||
|
||||
if( pxClient->uxBytesLeft == 0u )
|
||||
{
|
||||
/* Writing is ready, no need for further 'eSELECT_WRITE' events. */
|
||||
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
|
||||
prvFileClose( pxClient );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wake up the TCP task as soon as this socket may be written to. */
|
||||
FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
|
||||
}
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvOpenURL( HTTPClient_t *pxClient )
|
||||
{
|
||||
BaseType_t xRc;
|
||||
char pcSlash[ 2 ];
|
||||
|
||||
pxClient->bits.ulFlags = 0;
|
||||
|
||||
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
|
||||
{
|
||||
if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL )
|
||||
{
|
||||
size_t xResult;
|
||||
|
||||
xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) );
|
||||
if( xResult > 0 )
|
||||
{
|
||||
strcpy( pxClient->pxParent->pcContentsType, "text/html" );
|
||||
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
|
||||
"Content-Length: %d\r\n", ( int ) xResult );
|
||||
xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */
|
||||
if( xRc > 0 )
|
||||
{
|
||||
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );
|
||||
}
|
||||
/* Although against the coding standard of FreeRTOS, a return is
|
||||
done here to simplify this conditional code. */
|
||||
return xRc;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
|
||||
|
||||
if( pxClient->pcUrlData[ 0 ] != '/' )
|
||||
{
|
||||
/* Insert a slash before the file name. */
|
||||
pcSlash[ 0 ] = '/';
|
||||
pcSlash[ 1 ] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The browser provided a starting '/' already. */
|
||||
pcSlash[ 0 ] = '\0';
|
||||
}
|
||||
snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",
|
||||
pxClient->pcRootDir,
|
||||
pcSlash,
|
||||
pxClient->pcUrlData);
|
||||
|
||||
pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" );
|
||||
|
||||
FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename,
|
||||
pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) );
|
||||
|
||||
if( pxClient->pxFileHandle == NULL )
|
||||
{
|
||||
/* "404 File not found". */
|
||||
xRc = prvSendReply( pxClient, WEB_NOT_FOUND );
|
||||
}
|
||||
else
|
||||
{
|
||||
pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize;
|
||||
xRc = prvSendFile( pxClient );
|
||||
}
|
||||
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex )
|
||||
{
|
||||
BaseType_t xResult = 0;
|
||||
|
||||
/* A new command has been received. Process it. */
|
||||
switch( xIndex )
|
||||
{
|
||||
case ECMD_GET:
|
||||
xResult = prvOpenURL( pxClient );
|
||||
break;
|
||||
|
||||
case ECMD_HEAD:
|
||||
case ECMD_POST:
|
||||
case ECMD_PUT:
|
||||
case ECMD_DELETE:
|
||||
case ECMD_TRACE:
|
||||
case ECMD_OPTIONS:
|
||||
case ECMD_CONNECT:
|
||||
case ECMD_PATCH:
|
||||
case ECMD_UNK:
|
||||
{
|
||||
FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n",
|
||||
xWebCommands[xIndex].pcCommandName ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return xResult;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xHTTPClientWork( TCPClient_t *pxTCPClient )
|
||||
{
|
||||
BaseType_t xRc;
|
||||
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient;
|
||||
|
||||
if( pxClient->pxFileHandle != NULL )
|
||||
{
|
||||
prvSendFile( pxClient );
|
||||
}
|
||||
|
||||
xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );
|
||||
|
||||
if( xRc > 0 )
|
||||
{
|
||||
BaseType_t xIndex;
|
||||
const char *pcEndOfCmd;
|
||||
const struct xWEB_COMMAND *curCmd;
|
||||
char *pcBuffer = pcCOMMAND_BUFFER;
|
||||
|
||||
if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )
|
||||
{
|
||||
pcBuffer[ xRc ] = '\0';
|
||||
}
|
||||
while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )
|
||||
{
|
||||
pcBuffer[ --xRc ] = '\0';
|
||||
}
|
||||
pcEndOfCmd = pcBuffer + xRc;
|
||||
|
||||
curCmd = xWebCommands;
|
||||
|
||||
/* Pointing to "/index.html HTTP/1.1". */
|
||||
pxClient->pcUrlData = pcBuffer;
|
||||
|
||||
/* Pointing to "HTTP/1.1". */
|
||||
pxClient->pcRestData = pcEmptyString;
|
||||
|
||||
/* Last entry is "ECMD_UNK". */
|
||||
for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ )
|
||||
{
|
||||
BaseType_t xLength;
|
||||
|
||||
xLength = curCmd->xCommandLength;
|
||||
if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) )
|
||||
{
|
||||
char *pcLastPtr;
|
||||
|
||||
pxClient->pcUrlData += xLength + 1;
|
||||
for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ )
|
||||
{
|
||||
char ch = *pcLastPtr;
|
||||
if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )
|
||||
{
|
||||
*pcLastPtr = '\0';
|
||||
pxClient->pcRestData = pcLastPtr + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( xIndex < ( WEB_CMD_COUNT - 1 ) )
|
||||
{
|
||||
xRc = prvProcessCmd( pxClient, xIndex );
|
||||
}
|
||||
}
|
||||
else if( xRc < 0 )
|
||||
{
|
||||
/* The connection will be closed and the client will be deleted. */
|
||||
FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) );
|
||||
}
|
||||
return xRc;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static const char *pcGetContentsType (const char *apFname)
|
||||
{
|
||||
const char *slash = NULL;
|
||||
const char *dot = NULL;
|
||||
const char *ptr;
|
||||
const char *pcResult = "text/html";
|
||||
BaseType_t x;
|
||||
|
||||
for( ptr = apFname; *ptr; ptr++ )
|
||||
{
|
||||
if (*ptr == '.') dot = ptr;
|
||||
if (*ptr == '/') slash = ptr;
|
||||
}
|
||||
if( dot > slash )
|
||||
{
|
||||
dot++;
|
||||
for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ )
|
||||
{
|
||||
if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 )
|
||||
{
|
||||
pcResult = pxTypeCouples[ x ].pcType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pcResult;
|
||||
}
|
||||
|
||||
#endif /* ipconfigUSE_HTTP */
|
||||
|
@ -0,0 +1,440 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/*
|
||||
* NTPDemo.c
|
||||
*
|
||||
* An example of how to lookup a domain using DNS
|
||||
* And also how to send and receive UDP messages to get the NTP time
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.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_DNS.h"
|
||||
#include "FreeRTOS_Stream_Buffer.h"
|
||||
|
||||
/* Use the date & time functions from +FAT. */
|
||||
#include "ff_time.h"
|
||||
|
||||
#include "NTPDemo.h"
|
||||
#include "ntpClient.h"
|
||||
|
||||
#include "date_and_time.h"
|
||||
|
||||
enum EStatus {
|
||||
EStatusLookup,
|
||||
EStatusAsking,
|
||||
EStatusPause,
|
||||
EStatusFailed,
|
||||
};
|
||||
|
||||
static struct SNtpPacket xNTPPacket;
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS == 0 )
|
||||
static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];
|
||||
#endif
|
||||
|
||||
static enum EStatus xStatus = EStatusLookup;
|
||||
|
||||
static const char *pcTimeServers[] = {
|
||||
"0.asia.pool.ntp.org",
|
||||
"0.europe.pool.ntp.org",
|
||||
"0.id.pool.ntp.org",
|
||||
"0.south-america.pool.ntp.org",
|
||||
"0.oceania.pool.ntp.org",
|
||||
"0.north-america.pool.ntp.org"
|
||||
};
|
||||
|
||||
static SemaphoreHandle_t xNTPWakeupSem = NULL;
|
||||
static uint32_t ulIPAddressFound;
|
||||
static Socket_t xUDPSocket = NULL;
|
||||
static TaskHandle_t xNTPTaskhandle = NULL;
|
||||
static TickType_t uxSendTime;
|
||||
|
||||
static void prvNTPTask( void *pvParameters );
|
||||
|
||||
static void vSignalTask( void )
|
||||
{
|
||||
#if( ipconfigUSE_CALLBACKS == 0 )
|
||||
if( xUDPSocket != NULL )
|
||||
{
|
||||
/* Send a signal to the socket so that the
|
||||
FreeRTOS_recvfrom will get interrupted. */
|
||||
FreeRTOS_SignalSocket( xUDPSocket );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( xNTPWakeupSem != NULL )
|
||||
{
|
||||
xSemaphoreGive( xNTPWakeupSem );
|
||||
}
|
||||
}
|
||||
|
||||
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority )
|
||||
{
|
||||
/* The only public function in this module: start a task to contact
|
||||
some NTP server. */
|
||||
|
||||
if( xNTPTaskhandle != NULL )
|
||||
{
|
||||
switch( xStatus )
|
||||
{
|
||||
case EStatusPause:
|
||||
xStatus = EStatusAsking;
|
||||
vSignalTask();
|
||||
break;
|
||||
case EStatusLookup:
|
||||
FreeRTOS_printf( ( "NTP looking up server\n" ) );
|
||||
break;
|
||||
case EStatusAsking:
|
||||
FreeRTOS_printf( ( "NTP still asking\n" ) );
|
||||
break;
|
||||
case EStatusFailed:
|
||||
FreeRTOS_printf( ( "NTP failed somehow\n" ) );
|
||||
ulIPAddressFound = 0ul;
|
||||
xStatus = EStatusLookup;
|
||||
vSignalTask();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
|
||||
if( xUDPSocket != NULL )
|
||||
{
|
||||
struct freertos_sockaddr xAddress;
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
|
||||
#else
|
||||
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
|
||||
#endif
|
||||
|
||||
xAddress.sin_addr = 0ul;
|
||||
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
|
||||
|
||||
FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
|
||||
xTaskCreate( prvNTPTask, /* The function that implements the task. */
|
||||
( const char * ) "NTP client", /* 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. */
|
||||
&xNTPTaskhandle ); /* The task handle. */
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRTOS_printf( ( "Creating socket failed\n" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress )
|
||||
{
|
||||
char pcBuf[16];
|
||||
|
||||
/* The DNS lookup has a result, or it has reached the time-out. */
|
||||
FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
|
||||
FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );
|
||||
if( ulIPAddressFound == 0ul )
|
||||
{
|
||||
ulIPAddressFound = ulIPAddress;
|
||||
}
|
||||
/* For testing: in case DNS doen't respond, still try some NTP server
|
||||
with a known IP-address. */
|
||||
if( ulIPAddressFound == 0ul )
|
||||
{
|
||||
ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 );
|
||||
/* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */
|
||||
}
|
||||
xStatus = EStatusAsking;
|
||||
|
||||
vSignalTask();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSwapFields( struct SNtpPacket *pxPacket)
|
||||
{
|
||||
/* NTP messages are big-endian */
|
||||
pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );
|
||||
pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );
|
||||
|
||||
pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );
|
||||
pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );
|
||||
|
||||
pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );
|
||||
pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );
|
||||
|
||||
pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );
|
||||
pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );
|
||||
|
||||
pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );
|
||||
pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvNTPPacketInit( )
|
||||
{
|
||||
memset (&xNTPPacket, '\0', sizeof( xNTPPacket ) );
|
||||
|
||||
xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
|
||||
xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */
|
||||
xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */
|
||||
xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
|
||||
xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */
|
||||
|
||||
/* use the recorded NTP time */
|
||||
time_t uxSecs = FreeRTOS_time( NULL );/* apTime may be NULL, returns seconds */
|
||||
|
||||
xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */
|
||||
xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;
|
||||
|
||||
/* Transform the contents of the fields from native to big endian. */
|
||||
prvSwapFields( &xNTPPacket );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvReadTime( struct SNtpPacket * pxPacket )
|
||||
{
|
||||
FF_TimeStruct_t xTimeStruct;
|
||||
time_t uxPreviousSeconds;
|
||||
time_t uxPreviousMS;
|
||||
|
||||
time_t uxCurrentSeconds;
|
||||
time_t uxCurrentMS;
|
||||
|
||||
const char *pcTimeUnit;
|
||||
int32_t ilDiff;
|
||||
TickType_t uxTravelTime;
|
||||
|
||||
uxTravelTime = xTaskGetTickCount() - uxSendTime;
|
||||
|
||||
/* Transform the contents of the fields from big to native endian. */
|
||||
prvSwapFields( pxPacket );
|
||||
|
||||
uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;
|
||||
uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;
|
||||
uxCurrentSeconds += uxCurrentMS / 1000;
|
||||
uxCurrentMS = uxCurrentMS % 1000;
|
||||
|
||||
// Get the last time recorded
|
||||
uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );
|
||||
|
||||
// Set the new time with precision in msec. */
|
||||
FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );
|
||||
|
||||
if( uxCurrentSeconds >= uxPreviousSeconds )
|
||||
{
|
||||
ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );
|
||||
}
|
||||
else
|
||||
{
|
||||
ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );
|
||||
}
|
||||
|
||||
if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )
|
||||
{
|
||||
/* More than 5 seconds difference. */
|
||||
pcTimeUnit = "sec";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Less than or equal to 5 second difference. */
|
||||
pcTimeUnit = "ms";
|
||||
uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;
|
||||
int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;
|
||||
int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;
|
||||
ilDiff = iCurMS - iPrevMS;
|
||||
}
|
||||
uxCurrentSeconds -= iTimeZone;
|
||||
|
||||
FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );
|
||||
|
||||
/*
|
||||
378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
|
||||
379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
|
||||
*/
|
||||
|
||||
FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n",
|
||||
xTimeStruct.tm_mday,
|
||||
xTimeStruct.tm_mon + 1,
|
||||
xTimeStruct.tm_year + 1900,
|
||||
xTimeStruct.tm_hour,
|
||||
xTimeStruct.tm_min,
|
||||
xTimeStruct.tm_sec,
|
||||
( unsigned )uxCurrentMS,
|
||||
( unsigned )ilDiff,
|
||||
pcTimeUnit,
|
||||
uxTravelTime ) );
|
||||
|
||||
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
|
||||
( void ) pcTimeUnit;
|
||||
( void ) uxTravelTime;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
|
||||
static BaseType_t xOnUDPReceive( Socket_t xSocket, void * pvData, size_t xLength,
|
||||
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest )
|
||||
{
|
||||
if( xLength >= sizeof( xNTPPacket ) )
|
||||
{
|
||||
prvReadTime( ( struct SNtpPacket *)pvData );
|
||||
if( xStatus != EStatusPause )
|
||||
{
|
||||
xStatus = EStatusPause;
|
||||
}
|
||||
}
|
||||
vSignalTask();
|
||||
/* Tell the driver not to store the RX data */
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif /* ipconfigUSE_CALLBACKS != 0 */
|
||||
|
||||
static void prvNTPTask( void *pvParameters )
|
||||
{
|
||||
BaseType_t xServerIndex = 3;
|
||||
struct freertos_sockaddr xAddress;
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
F_TCP_UDP_Handler_t xHandler;
|
||||
#endif /* ipconfigUSE_CALLBACKS != 0 */
|
||||
|
||||
xStatus = EStatusLookup;
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
xNTPWakeupSem = xSemaphoreCreateBinary();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
memset( &xHandler, '\0', sizeof( xHandler ) );
|
||||
xHandler.pxOnUDPReceive = xOnUDPReceive;
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
|
||||
}
|
||||
#endif
|
||||
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
|
||||
{
|
||||
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
|
||||
}
|
||||
#endif
|
||||
for( ; ; )
|
||||
{
|
||||
switch( xStatus )
|
||||
{
|
||||
case EStatusLookup:
|
||||
if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )
|
||||
{
|
||||
if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
|
||||
{
|
||||
xServerIndex = 0;
|
||||
}
|
||||
FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );
|
||||
FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 );
|
||||
}
|
||||
else
|
||||
{
|
||||
xStatus = EStatusAsking;
|
||||
}
|
||||
break;
|
||||
|
||||
case EStatusAsking:
|
||||
{
|
||||
char pcBuf[16];
|
||||
|
||||
prvNTPPacketInit( );
|
||||
xAddress.sin_addr = ulIPAddressFound;
|
||||
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
|
||||
|
||||
FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );
|
||||
FreeRTOS_printf( ( "Sending UDP message to %s:%u\n",
|
||||
pcBuf,
|
||||
FreeRTOS_ntohs( xAddress.sin_port ) ) );
|
||||
|
||||
uxSendTime = xTaskGetTickCount( );
|
||||
FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );
|
||||
}
|
||||
break;
|
||||
|
||||
case EStatusPause:
|
||||
break;
|
||||
|
||||
case EStatusFailed:
|
||||
break;
|
||||
}
|
||||
|
||||
#if( ipconfigUSE_CALLBACKS != 0 )
|
||||
{
|
||||
xSemaphoreTake( xNTPWakeupSem, 5000 );
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint32_t xAddressSize;
|
||||
BaseType_t xReturned;
|
||||
|
||||
xAddressSize = sizeof( xAddress );
|
||||
xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
|
||||
switch( xReturned )
|
||||
{
|
||||
case 0:
|
||||
case -pdFREERTOS_ERRNO_EAGAIN:
|
||||
case -pdFREERTOS_ERRNO_EINTR:
|
||||
break;
|
||||
default:
|
||||
if( xReturned < sizeof( xNTPPacket ) )
|
||||
{
|
||||
FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
prvReadTime( ( struct SNtpPacket *)cRecvBuffer );
|
||||
if( xStatus != EStatusPause )
|
||||
{
|
||||
xStatus = EStatusPause;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
#ifndef __FTPCMD_H__
|
||||
|
||||
#define __FTPCMD_H__
|
||||
|
||||
#define REPL_110 "110 Restart marker reply.\r\n"
|
||||
#define REPL_120 "120 Try again in 2 minutes.\r\n"
|
||||
#define REPL_125 "125 Data connection already open; transfer starting.\r\n"
|
||||
#define REPL_150 "150 File status okay; about to open data connection.\r\n"
|
||||
#define REPL_200 "200 NOOP command successful.\r\n"
|
||||
#define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n"
|
||||
#define REPL_202 "202 Command not implemented, superfluous at this site.\r\n"
|
||||
#define REPL_211 "221 System status, or system help reply.\r\n"
|
||||
#define REPL_211_STATUS "221-status of %s.\r\n"
|
||||
#define REPL_211_END "221 End of status.\r\n"
|
||||
#define REPL_212 "212 Directory status.\r\n"
|
||||
#define REPL_213 "213 File status.\r\n"
|
||||
#define REPL_214 "214 Help message.\r\n"
|
||||
#define REPL_214_END "214 End Help message.\r\n"
|
||||
#define REPL_215 "215 %s system type.\r\n"
|
||||
#define REPL_220 "220 Service ready for new user.\r\n"
|
||||
#define REPL_221 "221 Service closing control connection.\r\n"
|
||||
#define REPL_225 "225 Data connection open; no transfer in progress.\r\n"
|
||||
#define REPL_226 "226 Closing data connection.\r\n"
|
||||
#define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n"
|
||||
#define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"
|
||||
#define REPL_230 "230 User logged in, proceed.\r\n"
|
||||
#define REPL_250 "250 Requested file action okay, completed.\r\n"
|
||||
#define REPL_257 "257 %s created.\r\n"
|
||||
// #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n"
|
||||
#define REPL_257_PWD "257 \"%s\"\r\n"
|
||||
#define REPL_331 "331 Only anonymous user is accepted.\r\n"
|
||||
#define REPL_331_ANON "331 Anonymous login okay\r\n"
|
||||
#define REPL_332 "332 Need account for login.\r\n"
|
||||
#define REPL_350 "350 Requested file action pending further information.\r\n"
|
||||
#define REPL_421 "421 Service not available, closing control connection.\r\n"
|
||||
#define REPL_425 "425 Can't open data connection.\r\n"
|
||||
#define REPL_426 "426 Connection closed; transfer aborted.\r\n"
|
||||
#define REPL_450 "450 Requested file action not taken.\r\n"
|
||||
#define REPL_451 "451 Requested action aborted. Local error in processing.\r\n"
|
||||
#define REPL_452 "452 Requested action not taken.\r\n"
|
||||
#define REPL_500 "500 Syntax error, command unrecognized.\r\n"
|
||||
#define REPL_501 "501 Syntax error in parameters or arguments.\r\n"
|
||||
#define REPL_502 "502 Command not implemented.\r\n"
|
||||
#define REPL_503 "503 Bad sequence of commands.\r\n"
|
||||
#define REPL_504 "504 Command not implemented for that parameter.\r\n"
|
||||
#define REPL_530 "530 Not logged in.\r\n"
|
||||
#define REPL_532 "532 Need account for storing files.\r\n"
|
||||
#define REPL_550 "550 Requested action not taken.\r\n"
|
||||
#define REPL_551 "551 Requested action aborted. Page type unknown.\r\n"
|
||||
#define REPL_552 "552 Requested file action aborted.\r\n"
|
||||
#define REPL_553 "553 Requested action not taken.\r\n"
|
||||
#define REPL_553_READ_ONLY "553 Read-only file-system.\r\n"
|
||||
|
||||
enum EFTPCommand {
|
||||
ECMD_USER,
|
||||
ECMD_PASS,
|
||||
ECMD_ACCT,
|
||||
ECMD_CWD,
|
||||
ECMD_CDUP,
|
||||
ECMD_SMNT,
|
||||
ECMD_QUIT,
|
||||
ECMD_REIN,
|
||||
ECMD_PORT,
|
||||
ECMD_PASV,
|
||||
ECMD_TYPE,
|
||||
ECMD_STRU,
|
||||
ECMD_MODE,
|
||||
ECMD_RETR,
|
||||
ECMD_STOR,
|
||||
ECMD_STOU,
|
||||
ECMD_APPE,
|
||||
ECMD_ALLO,
|
||||
ECMD_REST,
|
||||
ECMD_RNFR,
|
||||
ECMD_RNTO,
|
||||
ECMD_ABOR,
|
||||
ECMD_SIZE,
|
||||
ECMD_MDTM,
|
||||
ECMD_DELE,
|
||||
ECMD_RMD,
|
||||
ECMD_MKD,
|
||||
ECMD_PWD,
|
||||
ECMD_LIST,
|
||||
ECMD_NLST,
|
||||
ECMD_SITE,
|
||||
ECMD_SYST,
|
||||
ECMD_FEAT,
|
||||
ECMD_STAT,
|
||||
ECMD_HELP,
|
||||
ECMD_NOOP,
|
||||
ECMD_EMPTY,
|
||||
ECMD_CLOSE,
|
||||
ECMD_UNKNOWN,
|
||||
};
|
||||
|
||||
typedef struct xFTP_COMMAND {
|
||||
BaseType_t xCommandLength;
|
||||
const char pcCommandName[7];
|
||||
const unsigned char ucCommandType;
|
||||
const unsigned char checkLogin;
|
||||
const unsigned char checkNullArg;
|
||||
} FTPCommand_t;
|
||||
|
||||
#define FTP_CMD_COUNT (ECMD_UNKNOWN+1)
|
||||
|
||||
extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ];
|
||||
|
||||
#endif // __FTPCMD_H__
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
#ifndef FREERTOS_HTTP_COMMANDS_H
|
||||
#define FREERTOS_HTTP_COMMANDS_H
|
||||
|
||||
enum {
|
||||
WEB_REPLY_OK = 200,
|
||||
WEB_NO_CONTENT = 204,
|
||||
WEB_BAD_REQUEST = 400,
|
||||
WEB_UNAUTHORIZED = 401,
|
||||
WEB_NOT_FOUND = 404,
|
||||
WEB_GONE = 410,
|
||||
WEB_PRECONDITION_FAILED = 412,
|
||||
WEB_INTERNAL_SERVER_ERROR = 500,
|
||||
};
|
||||
|
||||
enum EWebCommand {
|
||||
ECMD_GET,
|
||||
ECMD_HEAD,
|
||||
ECMD_POST,
|
||||
ECMD_PUT,
|
||||
ECMD_DELETE,
|
||||
ECMD_TRACE,
|
||||
ECMD_OPTIONS,
|
||||
ECMD_CONNECT,
|
||||
ECMD_PATCH,
|
||||
ECMD_UNK,
|
||||
};
|
||||
|
||||
struct xWEB_COMMAND
|
||||
{
|
||||
BaseType_t xCommandLength;
|
||||
const char *pcCommandName;
|
||||
const unsigned char ucCommandType;
|
||||
};
|
||||
|
||||
#define WEB_CMD_COUNT (ECMD_UNK+1)
|
||||
|
||||
extern const struct xWEB_COMMAND xWebCommands[WEB_CMD_COUNT];
|
||||
|
||||
extern const char *webCodename (int aCode);
|
||||
|
||||
#endif /* FREERTOS_HTTP_COMMANDS_H */
|
||||
|
||||
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Some code which is common to TCP servers like HTTP en FTP
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_TCP_SERVER_H
|
||||
#define FREERTOS_TCP_SERVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef FTP_SERVER_USES_RELATIVE_DIRECTORY
|
||||
#define FTP_SERVER_USES_RELATIVE_DIRECTORY 0
|
||||
#endif
|
||||
|
||||
enum eSERVER_TYPE
|
||||
{
|
||||
eSERVER_NONE,
|
||||
eSERVER_HTTP,
|
||||
eSERVER_FTP,
|
||||
};
|
||||
|
||||
struct xFTP_CLIENT;
|
||||
|
||||
#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )
|
||||
extern void vApplicationFTPReceivedHook( const char *pcFileName, uint32_t ulSize, struct xFTP_CLIENT *pxFTPClient );
|
||||
extern void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage );
|
||||
#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
|
||||
/*
|
||||
* Function is called when a user name has been submitted.
|
||||
* The function may return a string such as: "331 Please enter your password"
|
||||
* or return NULL to use the default reply.
|
||||
*/
|
||||
extern const char *pcApplicationFTPUserHook( const char *pcUserName );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
|
||||
/*
|
||||
* Function is called when a password was received.
|
||||
* Return positive value to allow the user
|
||||
*/
|
||||
extern BaseType_t xApplicationFTPPasswordHook( const char *pcUserName, const char *pcPassword );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )
|
||||
/*
|
||||
* The FTP server is asking for user-specific properties
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t usPortNumber; /* For reference only. Host-endian. */
|
||||
const char *pcRootDir;
|
||||
BaseType_t xReadOnly;
|
||||
}
|
||||
FTPUserProperties_t;
|
||||
extern void vApplicationFTPUserPropertiesHook( const char *pcUserName, FTPUserProperties_t *pxProperties );
|
||||
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
|
||||
|
||||
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
|
||||
/*
|
||||
* A GET request is received containing a special character,
|
||||
* usually a question mark.
|
||||
* const char *pcURLData; // A request, e.g. "/request?limit=75"
|
||||
* char *pcBuffer; // Here the answer can be written
|
||||
* size_t uxBufferLength; // Size of the buffer
|
||||
*
|
||||
*/
|
||||
extern size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength );
|
||||
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
|
||||
|
||||
struct xSERVER_CONFIG
|
||||
{
|
||||
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
|
||||
BaseType_t xPortNumber; /* e.g. 80, 8080, 21 */
|
||||
BaseType_t xBackLog; /* e.g. 10, maximum number of connected TCP clients */
|
||||
const char * const pcRootDir; /* Treat this directory as the root directory */
|
||||
};
|
||||
|
||||
struct xTCP_SERVER;
|
||||
typedef struct xTCP_SERVER TCPServer_t;
|
||||
|
||||
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount );
|
||||
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime );
|
||||
|
||||
#if( ipconfigSUPPORT_SIGNALS != 0 )
|
||||
/* FreeRTOS_TCPServerWork() calls select().
|
||||
The two functions below provide a possibility to interrupt
|
||||
the call to select(). After the interruption, resume
|
||||
by calling FreeRTOS_TCPServerWork() again. */
|
||||
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer );
|
||||
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FREERTOS_TCP_SERVER_H */
|
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* FreeRTOS+TCP V2.0.3
|
||||
* 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://aws.amazon.com/freertos
|
||||
* http://www.FreeRTOS.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Some code which is common to TCP servers like HTTP and FTP
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_SERVER_PRIVATE_H
|
||||
#define FREERTOS_SERVER_PRIVATE_H
|
||||
|
||||
#define FREERTOS_NO_SOCKET NULL
|
||||
|
||||
/* FreeRTOS+FAT */
|
||||
#include "ff_stdio.h"
|
||||
|
||||
/* Each HTTP server has 1, at most 2 sockets */
|
||||
#define HTTP_SOCKET_COUNT 2
|
||||
|
||||
/*
|
||||
* ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of:
|
||||
* pcCommandBuffer': a buffer to receive and send TCP commands
|
||||
*
|
||||
* ipconfigTCP_FILE_BUFFER_SIZE sets the size of:
|
||||
* pcFileBuffer' : a buffer to access the file system: read or write data.
|
||||
*
|
||||
* The buffers are both used for FTP as well as HTTP.
|
||||
*/
|
||||
|
||||
#ifndef ipconfigTCP_COMMAND_BUFFER_SIZE
|
||||
#define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 )
|
||||
#endif
|
||||
|
||||
#ifndef ipconfigTCP_FILE_BUFFER_SIZE
|
||||
#define ipconfigTCP_FILE_BUFFER_SIZE ( 2048 )
|
||||
#endif
|
||||
|
||||
struct xTCP_CLIENT;
|
||||
|
||||
typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
|
||||
typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
|
||||
|
||||
#define TCP_CLIENT_FIELDS \
|
||||
enum eSERVER_TYPE eType; \
|
||||
struct xTCP_SERVER *pxParent; \
|
||||
Socket_t xSocket; \
|
||||
const char *pcRootDir; \
|
||||
FTCPWorkFunction fWorkFunction; \
|
||||
FTCPDeleteFunction fDeleteFunction; \
|
||||
struct xTCP_CLIENT *pxNextClient
|
||||
|
||||
typedef struct xTCP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
} TCPClient_t;
|
||||
|
||||
struct xHTTP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
const char *pcUrlData;
|
||||
const char *pcRestData;
|
||||
char pcCurrentFilename[ ffconfigMAX_FILENAME ];
|
||||
size_t uxBytesLeft;
|
||||
FF_FILE *pxFileHandle;
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bReplySent : 1;
|
||||
};
|
||||
uint32_t ulFlags;
|
||||
} bits;
|
||||
};
|
||||
|
||||
typedef struct xHTTP_CLIENT HTTPClient_t;
|
||||
|
||||
struct xFTP_CLIENT
|
||||
{
|
||||
/* This define contains fields which must come first within each of the client structs */
|
||||
TCP_CLIENT_FIELDS;
|
||||
/* --- Keep at the top --- */
|
||||
|
||||
uint32_t ulRestartOffset;
|
||||
uint32_t ulRecvBytes;
|
||||
size_t uxBytesLeft; /* Bytes left to send */
|
||||
uint32_t ulClientIP;
|
||||
TickType_t xStartTime;
|
||||
uint16_t usClientPort;
|
||||
Socket_t xTransferSocket;
|
||||
BaseType_t xTransType;
|
||||
BaseType_t xDirCount;
|
||||
FF_FindData_t xFindData;
|
||||
FF_FILE *pxReadHandle;
|
||||
FF_FILE *pxWriteHandle;
|
||||
char pcCurrentDir[ ffconfigMAX_FILENAME ];
|
||||
char pcFileName[ ffconfigMAX_FILENAME ];
|
||||
char pcConnectionAck[ 128 ];
|
||||
char pcClientAck[ 128 ];
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bHelloSent : 1,
|
||||
bLoggedIn : 1,
|
||||
bStatusUser : 1,
|
||||
bInRename : 1,
|
||||
bReadOnly : 1;
|
||||
};
|
||||
uint32_t ulFTPFlags;
|
||||
} bits;
|
||||
union {
|
||||
struct {
|
||||
uint32_t
|
||||
bIsListen : 1, /* pdTRUE for passive data connections (using list()). */
|
||||
bDirHasEntry : 1, /* pdTRUE if ff_findfirst() was successful. */
|
||||
bClientConnected : 1, /* pdTRUE after connect() or accept() has succeeded. */
|
||||
bEmptyFile : 1, /* pdTRUE if a connection-without-data was received. */
|
||||
bHadError : 1; /* pdTRUE if a transfer got aborted because of an error. */
|
||||
};
|
||||
uint32_t ulConnFlags;
|
||||
} bits1;
|
||||
};
|
||||
|
||||
typedef struct xFTP_CLIENT FTPClient_t;
|
||||
|
||||
BaseType_t xHTTPClientWork( TCPClient_t *pxClient );
|
||||
BaseType_t xFTPClientWork( TCPClient_t *pxClient );
|
||||
|
||||
void vHTTPClientDelete( TCPClient_t *pxClient );
|
||||
void vFTPClientDelete( TCPClient_t *pxClient );
|
||||
|
||||
BaseType_t xMakeAbsolute( struct xFTP_CLIENT *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
|
||||
BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName );
|
||||
|
||||
struct xTCP_SERVER
|
||||
{
|
||||
SocketSet_t xSocketSet;
|
||||
/* A buffer to receive and send TCP commands, either HTTP of FTP. */
|
||||
char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ];
|
||||
/* A buffer to access the file system: read or write data. */
|
||||
char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ];
|
||||
|
||||
#if( ipconfigUSE_FTP != 0 )
|
||||
char pcNewDir[ ffconfigMAX_FILENAME ];
|
||||
#endif
|
||||
#if( ipconfigUSE_HTTP != 0 )
|
||||
char pcContentsType[40]; /* Space for the msg: "text/javascript" */
|
||||
char pcExtraContents[40]; /* Space for the msg: "Content-Length: 346500" */
|
||||
#endif
|
||||
BaseType_t xServerCount;
|
||||
TCPClient_t *pxClients;
|
||||
struct xSERVER
|
||||
{
|
||||
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
|
||||
const char *pcRootDir;
|
||||
Socket_t xSocket;
|
||||
} xServers[ 1 ];
|
||||
};
|
||||
|
||||
#endif /* FREERTOS_SERVER_PRIVATE_H */
|
@ -0,0 +1,71 @@
|
||||
//
|
||||
// ntpClient.h
|
||||
//
|
||||
|
||||
#ifndef __NTPCLIENT_H__
|
||||
|
||||
#define __NTPCLIENT_H__
|
||||
|
||||
#define NTP_PORT 123
|
||||
|
||||
typedef uint32_t quint32;
|
||||
typedef int32_t qint32;
|
||||
typedef uint8_t quint8;
|
||||
typedef int8_t qint8;
|
||||
|
||||
typedef union _SNtpFlags SNtpFlags;
|
||||
|
||||
/**
|
||||
* 64-bit NTP timestamp.
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) _SNtpTimestamp {
|
||||
/** Number of seconds passed since Jan 1 1900, in big-endian format. */
|
||||
quint32 seconds;
|
||||
|
||||
/** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */
|
||||
quint32 fraction;
|
||||
};
|
||||
|
||||
typedef struct _SNtpTimestamp SNtpTimestamp;
|
||||
/**
|
||||
* Mandatory part of an NTP packet
|
||||
*/
|
||||
struct SNtpPacket {
|
||||
/** Flags. */
|
||||
unsigned char flags; // value 0xDB : mode 3 (client), version 3, leap indicator unknown 3
|
||||
|
||||
/** Stratum of the clock. */
|
||||
quint8 stratum; // value 0 : unspecified
|
||||
|
||||
/** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */
|
||||
qint8 poll; // 10 means 1 << 10 = 1024 seconds
|
||||
|
||||
/** Precision of the clock, in log2 seconds. Note that the value is signed. */
|
||||
qint8 precision; // 0xFA = 250 = 0.015625 seconds
|
||||
|
||||
/** Round trip time to the primary reference source, in NTP short format. */
|
||||
qint32 rootDelay; // 0x5D2E = 23854 or (23854/65535)= 0.3640 sec
|
||||
|
||||
/** Nominal error relative to the primary reference source. */
|
||||
qint32 rootDispersion; // 0x0008 CAC8 = 8.7912 seconds
|
||||
|
||||
/** Reference identifier (either a 4 character string or an IP address). */
|
||||
qint8 referenceID[4]; // or just 0000
|
||||
|
||||
/** The time at which the clock was last set or corrected. */
|
||||
SNtpTimestamp referenceTimestamp; // Current time
|
||||
|
||||
/** The time at which the request departed the client for the server. */
|
||||
SNtpTimestamp originateTimestamp; // Keep 0
|
||||
|
||||
/** The time at which the request arrived at the server. */
|
||||
SNtpTimestamp receiveTimestamp; // Keep 0
|
||||
|
||||
/** The time at which the reply departed the server for client. */
|
||||
SNtpTimestamp transmitTimestamp;
|
||||
};
|
||||
|
||||
/* Add this number to get secs since 1-1-1900 */
|
||||
#define TIME1970 2208988800UL
|
||||
|
||||
#endif // __NTPCLIENT_H__
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* A simple demo for NTP using FreeRTOS+TCP
|
||||
*/
|
||||
|
||||
#ifndef NTPDEMO_H
|
||||
|
||||
#define NTPDEMO_H
|
||||
|
||||
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority );
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user