Preparation for coreHTTP demos (#413)
Adding common utilities that will be used by 4 coreHTTP demos: - Adding coreHTTP submodule pointer to FreeRTOS-Plus/Source/Application-Protocols/coreHTTP - Adding folder FreeRTOS-Plus/Demo/coreHTTP_Windows_Simulator/Http_Demo_Helpers with functions common to demos.pull/407/head^2
parent
e313e286df
commit
56a86428fe
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
*/
|
||||
|
||||
/***
|
||||
* See https://www.FreeRTOS.org for configuration and usage instructions.
|
||||
***/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
/* Visual studio intrinsics used so the __debugbreak() function is available
|
||||
* should an assert get hit. */
|
||||
#include <intrin.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include <FreeRTOS.h>
|
||||
#include "task.h"
|
||||
|
||||
/* TCP/IP stack includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
/* Demo logging includes. */
|
||||
#include "logging.h"
|
||||
|
||||
/* Demo Specific configs. */
|
||||
#include "demo_config.h"
|
||||
|
||||
|
||||
/*
|
||||
* Prototypes for the demos that can be started from this project. Note that the
|
||||
* HTTP demo is not actually started until the network is ready, which is
|
||||
* indicated by vApplicationIPNetworkEventHook() executing - hence
|
||||
* vStartSimpleHTTPDemo() is called from inside vApplicationIPNetworkEventHook().
|
||||
*/
|
||||
extern void vStartSimpleHTTPDemo( void );
|
||||
|
||||
/*
|
||||
* Just seeds the simple pseudo random number generator.
|
||||
*
|
||||
* !!! NOTE !!!
|
||||
* This is not a secure method of generating random numbers and production
|
||||
* devices should use a true random number generator (TRNG).
|
||||
*/
|
||||
static void prvSRand( UBaseType_t ulSeed );
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization including preparing the logging and seeding the
|
||||
* random number generator.
|
||||
*/
|
||||
static void prvMiscInitialisation( void );
|
||||
|
||||
/* The default IP and MAC address used by the demo. The address configuration
|
||||
* defined here will be used if ipconfigUSE_DHCP is 0, or if ipconfigUSE_DHCP is
|
||||
* 1 but a DHCP server could not be contacted. See the online documentation for
|
||||
* more information. */
|
||||
static const uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };
|
||||
static const uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };
|
||||
static const uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };
|
||||
static const uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };
|
||||
|
||||
/* Set the following constant to pdTRUE to log using the method indicated by the
|
||||
* name of the constant, or pdFALSE to not log using the method indicated by the
|
||||
* name of the constant. Options include to standard out (xLogToStdout), to a disk
|
||||
* file (xLogToFile), and to a UDP port (xLogToUDP). If xLogToUDP is set to pdTRUE
|
||||
* then UDP messages are sent to the IP address configured as the UDP logging server
|
||||
* address (see the configUDP_LOGGING_ADDR0 definitions in FreeRTOSConfig.h) and
|
||||
* the port number set by configPRINT_PORT in FreeRTOSConfig.h. */
|
||||
const BaseType_t xLogToStdout = pdTRUE, xLogToFile = pdFALSE, xLogToUDP = pdFALSE;
|
||||
|
||||
/* Default MAC address configuration. The demo creates a virtual network
|
||||
* connection that uses this MAC address by accessing the raw Ethernet data
|
||||
* to and from a real network connection on the host PC. See the
|
||||
* configNETWORK_INTERFACE_TO_USE definition for information on how to configure
|
||||
* the real network connection to use. */
|
||||
const uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };
|
||||
|
||||
/* Used by the pseudo random number generator. */
|
||||
static UBaseType_t ulNextRand;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int main( void )
|
||||
{
|
||||
/* Miscellaneous initialization including preparing the logging and seeding
|
||||
* the random number generator. */
|
||||
prvMiscInitialisation();
|
||||
|
||||
/* Initialize the network interface.
|
||||
*
|
||||
***NOTE*** Tasks that use the network are created in the network event hook
|
||||
* when the network is connected and ready for use (see the implementation of
|
||||
* vApplicationIPNetworkEventHook() below). The address values passed in here
|
||||
* are used if ipconfigUSE_DHCP is set to 0, or if ipconfigUSE_DHCP is set to 1
|
||||
* but a DHCP server cannot be contacted. */
|
||||
FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
|
||||
|
||||
/* Start the RTOS scheduler. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
/* If all is well, the scheduler will now be running, and the following
|
||||
* line will never be reached. If the following line does execute, then
|
||||
* there was insufficient FreeRTOS heap memory available for the idle and/or
|
||||
* timer tasks to be created. See the memory management section on the
|
||||
* FreeRTOS web site for more details (this is standard text that is not
|
||||
* really applicable to the Win32 simulator port). */
|
||||
for( ; ; )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Called by FreeRTOS+TCP when the network connects or disconnects. Disconnect
|
||||
* events are only received if implemented in the MAC driver. */
|
||||
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
|
||||
{
|
||||
uint32_t ulIPAddress, ulNetMask, ulGatewayAddress, ulDNSServerAddress;
|
||||
char cBuffer[ 16 ];
|
||||
static BaseType_t xTasksAlreadyCreated = pdFALSE;
|
||||
|
||||
/* If the network has just come up...*/
|
||||
if( eNetworkEvent == eNetworkUp )
|
||||
{
|
||||
/* Create the tasks that use the IP stack if they have not already been
|
||||
* created. */
|
||||
if( xTasksAlreadyCreated == pdFALSE )
|
||||
{
|
||||
/* Demos that use the network are created after the network is
|
||||
* up. */
|
||||
LogInfo( ( "---------STARTING DEMO---------\r\n" ) );
|
||||
vStartSimpleHTTPDemo();
|
||||
xTasksAlreadyCreated = pdTRUE;
|
||||
}
|
||||
|
||||
/* Print out the network configuration, which may have come from a DHCP
|
||||
* server. */
|
||||
FreeRTOS_GetAddressConfiguration( &ulIPAddress, &ulNetMask, &ulGatewayAddress, &ulDNSServerAddress );
|
||||
FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
|
||||
LogInfo( ( "\r\n\r\nIP Address: %s\r\n", cBuffer ) );
|
||||
|
||||
FreeRTOS_inet_ntoa( ulNetMask, cBuffer );
|
||||
LogInfo( ( "Subnet Mask: %s\r\n", cBuffer ) );
|
||||
|
||||
FreeRTOS_inet_ntoa( ulGatewayAddress, cBuffer );
|
||||
LogInfo( ( "Gateway Address: %s\r\n", cBuffer ) );
|
||||
|
||||
FreeRTOS_inet_ntoa( ulDNSServerAddress, cBuffer );
|
||||
LogInfo( ( "DNS Server Address: %s\r\n\r\n\r\n", cBuffer ) );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vAssertCalled( const char * pcFile,
|
||||
uint32_t ulLine )
|
||||
{
|
||||
volatile uint32_t ulBlockVariable = 0UL;
|
||||
volatile char * pcFileName = ( volatile char * ) pcFile;
|
||||
volatile uint32_t ulLineNumber = ulLine;
|
||||
|
||||
( void ) pcFileName;
|
||||
( void ) ulLineNumber;
|
||||
|
||||
printf( "vAssertCalled( %s, %u\n", pcFile, ulLine );
|
||||
|
||||
/* Setting ulBlockVariable to a non-zero value in the debugger will allow
|
||||
* this function to be exited. */
|
||||
taskDISABLE_INTERRUPTS();
|
||||
{
|
||||
while( ulBlockVariable == 0UL )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
}
|
||||
taskENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxRand( void )
|
||||
{
|
||||
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
|
||||
|
||||
/*
|
||||
* Utility function to generate a pseudo random number.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* This is not a secure method of generating a random number. Production
|
||||
* devices should use a True Random Number Generator (TRNG).
|
||||
*/
|
||||
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
|
||||
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSRand( UBaseType_t ulSeed )
|
||||
{
|
||||
/* Utility function to seed the pseudo random number generator. */
|
||||
ulNextRand = ulSeed;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvMiscInitialisation( void )
|
||||
{
|
||||
time_t xTimeNow;
|
||||
uint32_t ulLoggingIPAddress;
|
||||
|
||||
ulLoggingIPAddress = FreeRTOS_inet_addr_quick( configUDP_LOGGING_ADDR0, configUDP_LOGGING_ADDR1, configUDP_LOGGING_ADDR2, configUDP_LOGGING_ADDR3 );
|
||||
vLoggingInit( xLogToStdout, xLogToFile, xLogToUDP, ulLoggingIPAddress, configPRINT_PORT );
|
||||
|
||||
/*
|
||||
* Seed random number generator.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* This is not a secure method of generating a random number. Production
|
||||
* devices should use a True Random Number Generator (TRNG).
|
||||
*/
|
||||
time( &xTimeNow );
|
||||
LogDebug( ( "Seed for randomizer: %lu\n", xTimeNow ) );
|
||||
prvSRand( ( uint32_t ) xTimeNow );
|
||||
LogDebug( ( "Random numbers: %08X %08X %08X %08X\n", ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32(), ipconfigRAND32() ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) || ( ipconfigDHCP_REGISTER_HOSTNAME == 1 )
|
||||
|
||||
const char * pcApplicationHostnameHook( void )
|
||||
{
|
||||
/* Assign the name "FreeRTOS" to this network node. This function will
|
||||
* be called during the DHCP: the machine will be registered with an IP
|
||||
* address plus this name. */
|
||||
return mainHOST_NAME;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 )
|
||||
|
||||
BaseType_t xApplicationDNSQueryHook( const char * pcName )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Determine if a name lookup is for this node. Two names are given
|
||||
* to this node: that returned by pcApplicationHostnameHook() and that set
|
||||
* by mainDEVICE_NICK_NAME. */
|
||||
if( _stricmp( pcName, pcApplicationHostnameHook() ) == 0 )
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else if( _stricmp( pcName, mainDEVICE_NICK_NAME ) == 0 )
|
||||
{
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_NBNS != 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Callback that provides the inputs necessary to generate a randomized TCP
|
||||
* Initial Sequence Number per RFC 6528. THIS IS ONLY A DUMMY IMPLEMENTATION
|
||||
* THAT RETURNS A PSEUDO RANDOM NUMBER SO IS NOT INTENDED FOR USE IN PRODUCTION
|
||||
* SYSTEMS.
|
||||
*/
|
||||
extern uint32_t ulApplicationGetNextSequenceNumber( uint32_t ulSourceAddress,
|
||||
uint16_t usSourcePort,
|
||||
uint32_t ulDestinationAddress,
|
||||
uint16_t usDestinationPort )
|
||||
{
|
||||
( void ) ulSourceAddress;
|
||||
( void ) usSourcePort;
|
||||
( void ) ulDestinationAddress;
|
||||
( void ) usDestinationPort;
|
||||
|
||||
return uxRand();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Set *pulNumber to a random number, and return pdTRUE. When the random number
|
||||
* generator is broken, it shall return pdFALSE.
|
||||
* The macros ipconfigRAND32() and configRAND32() are not in use
|
||||
* anymore in FreeRTOS+TCP.
|
||||
*
|
||||
* THIS IS ONLY A DUMMY IMPLEMENTATION THAT RETURNS A PSEUDO RANDOM NUMBER SO IS
|
||||
* NOT INTENDED FOR USE IN PRODUCTION SYSTEMS.
|
||||
*/
|
||||
BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber )
|
||||
{
|
||||
*pulNumber = uxRand();
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
|
||||
* implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
|
||||
* used by the Idle task. */
|
||||
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
|
||||
StackType_t ** ppxIdleTaskStackBuffer,
|
||||
uint32_t * pulIdleTaskStackSize )
|
||||
{
|
||||
/* If the buffers to be provided to the Idle task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xIdleTaskTCB;
|
||||
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
|
||||
* state will be stored. */
|
||||
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Idle task's stack. */
|
||||
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
|
||||
* application must provide an implementation of vApplicationGetTimerTaskMemory()
|
||||
* to provide the memory that is used by the Timer service task. */
|
||||
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
|
||||
StackType_t ** ppxTimerTaskStackBuffer,
|
||||
uint32_t * pulTimerTaskStackSize )
|
||||
{
|
||||
/* If the buffers to be provided to the Timer task are declared inside this
|
||||
* function then they must be declared static - otherwise they will be allocated on
|
||||
* the stack and so not exists after this function exits. */
|
||||
static StaticTask_t xTimerTaskTCB;
|
||||
static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
|
||||
|
||||
/* Pass out a pointer to the StaticTask_t structure in which the Timer
|
||||
* task's state will be stored. */
|
||||
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
|
||||
|
||||
/* Pass out the array that will be used as the Timer task's stack. */
|
||||
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
|
||||
|
||||
/* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
|
||||
* Note that, as the array is necessarily of type StackType_t,
|
||||
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
|
||||
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <assert.h>
|
||||
|
||||
#include "http_demo_utils.h"
|
||||
|
||||
/* Exponential backoff retry include. */
|
||||
#include "exponential_backoff.h"
|
||||
|
||||
/* Parser utilities. */
|
||||
#include "http_parser.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t connectToServerWithBackoffRetries( TransportConnect_t connectFunction,
|
||||
NetworkContext_t * pxNetworkContext )
|
||||
{
|
||||
BaseType_t xReturn = pdFAIL;
|
||||
/* Status returned by the retry utilities. */
|
||||
RetryUtilsStatus_t xRetryUtilsStatus = RetryUtilsSuccess;
|
||||
/* Struct containing the next backoff time. */
|
||||
RetryUtilsParams_t xReconnectParams;
|
||||
|
||||
assert( connectFunction != NULL );
|
||||
|
||||
/* Initialize reconnect attempts and interval */
|
||||
RetryUtils_ParamsReset( &xReconnectParams );
|
||||
xReconnectParams.maxRetryAttempts = MAX_RETRY_ATTEMPTS;
|
||||
|
||||
/* Attempt to connect to the HTTP server. If connection fails, retry after a
|
||||
* timeout. The timeout value will exponentially increase until either the
|
||||
* maximum timeout value is reached or the set number of attempts are
|
||||
* exhausted.*/
|
||||
do
|
||||
{
|
||||
xReturn = connectFunction( pxNetworkContext );
|
||||
|
||||
if( xReturn != pdPASS )
|
||||
{
|
||||
LogWarn( ( "Connection to the HTTP server failed. "
|
||||
"Retrying connection with backoff and jitter." ) );
|
||||
LogInfo( ( "Retry attempt %lu out of maximum retry attempts %lu.",
|
||||
( xReconnectParams.attemptsDone + 1 ),
|
||||
MAX_RETRY_ATTEMPTS ) );
|
||||
xRetryUtilsStatus = RetryUtils_BackoffAndSleep( &xReconnectParams );
|
||||
}
|
||||
} while( ( xReturn == pdFAIL ) && ( xRetryUtilsStatus == RetryUtilsSuccess ) );
|
||||
|
||||
if( xReturn == pdFAIL )
|
||||
{
|
||||
LogError( ( "Connection to the server failed, all attempts exhausted." ) );
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
HTTPStatus_t getUrlPath( const char * pcUrl,
|
||||
size_t xUrlLen,
|
||||
const char ** pcPath,
|
||||
size_t * pxPathLen )
|
||||
{
|
||||
/* http-parser status. Initialized to 1 to signify failure. */
|
||||
int lParserStatus = 1;
|
||||
struct http_parser_url xUrlParser;
|
||||
HTTPStatus_t xHTTPStatus = HTTPSuccess;
|
||||
|
||||
/* Sets all members in xUrlParser to 0. */
|
||||
http_parser_url_init( &xUrlParser );
|
||||
|
||||
if( ( pcUrl == NULL ) || ( pcPath == NULL ) || ( pxPathLen == NULL ) )
|
||||
{
|
||||
LogError( ( "NULL parameter passed to getUrlPath()." ) );
|
||||
xHTTPStatus = HTTPInvalidParameter;
|
||||
}
|
||||
|
||||
if( xHTTPStatus == HTTPSuccess )
|
||||
{
|
||||
lParserStatus = http_parser_parse_url( pcUrl, xUrlLen, 0, &xUrlParser );
|
||||
|
||||
if( lParserStatus != 0 )
|
||||
{
|
||||
LogError( ( "Error parsing the input URL %.*s. Error code: %d.",
|
||||
( int32_t ) xUrlLen,
|
||||
pcUrl,
|
||||
lParserStatus ) );
|
||||
xHTTPStatus = HTTPParserInternalError;
|
||||
}
|
||||
}
|
||||
|
||||
if( xHTTPStatus == HTTPSuccess )
|
||||
{
|
||||
*pxPathLen = ( size_t ) ( xUrlParser.field_data[ UF_PATH ].len );
|
||||
|
||||
if( *pxPathLen == 0 )
|
||||
{
|
||||
xHTTPStatus = HTTPNoResponse;
|
||||
*pcPath = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcPath = &pcUrl[ xUrlParser.field_data[ UF_PATH ].off ];
|
||||
}
|
||||
}
|
||||
|
||||
if( xHTTPStatus != HTTPSuccess )
|
||||
{
|
||||
LogError( ( "Error parsing the path from URL %s. Error code: %d",
|
||||
pcUrl,
|
||||
xHTTPStatus ) );
|
||||
}
|
||||
|
||||
return xHTTPStatus;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
HTTPStatus_t getUrlAddress( const char * pcUrl,
|
||||
size_t xUrlLen,
|
||||
const char ** pcAddress,
|
||||
size_t * pxAddressLen )
|
||||
{
|
||||
/* http-parser status. Initialized to 1 to signify failure. */
|
||||
int lParserStatus = 1;
|
||||
struct http_parser_url xUrlParser;
|
||||
HTTPStatus_t xHTTPStatus = HTTPSuccess;
|
||||
|
||||
/* Sets all members in xUrlParser to 0. */
|
||||
http_parser_url_init( &xUrlParser );
|
||||
|
||||
if( ( pcUrl == NULL ) || ( pcAddress == NULL ) || ( pxAddressLen == NULL ) )
|
||||
{
|
||||
LogError( ( "NULL parameter passed to getUrlAddress()." ) );
|
||||
xHTTPStatus = HTTPInvalidParameter;
|
||||
}
|
||||
|
||||
if( xHTTPStatus == HTTPSuccess )
|
||||
{
|
||||
lParserStatus = http_parser_parse_url( pcUrl, xUrlLen, 0, &xUrlParser );
|
||||
|
||||
if( lParserStatus != 0 )
|
||||
{
|
||||
LogError( ( "Error parsing the input URL %.*s. Error code: %d.",
|
||||
( int32_t ) xUrlLen,
|
||||
pcUrl,
|
||||
lParserStatus ) );
|
||||
xHTTPStatus = HTTPParserInternalError;
|
||||
}
|
||||
}
|
||||
|
||||
if( xHTTPStatus == HTTPSuccess )
|
||||
{
|
||||
*pxAddressLen = ( size_t ) ( xUrlParser.field_data[ UF_HOST ].len );
|
||||
|
||||
if( *pxAddressLen == 0 )
|
||||
{
|
||||
xHTTPStatus = HTTPNoResponse;
|
||||
*pcAddress = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcAddress = &pcUrl[ xUrlParser.field_data[ UF_HOST ].off ];
|
||||
}
|
||||
}
|
||||
|
||||
if( xHTTPStatus != HTTPSuccess )
|
||||
{
|
||||
LogError( ( "Error parsing the address from URL %s. Error code %d",
|
||||
pcUrl,
|
||||
xHTTPStatus ) );
|
||||
}
|
||||
|
||||
return xHTTPStatus;
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#ifndef HTTP_DEMO_UTILS_H
|
||||
#define HTTP_DEMO_UTILS_H
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Transport interface implementation include header for TLS. */
|
||||
#include "using_mbedtls.h"
|
||||
|
||||
/* HTTP API header. */
|
||||
#include "core_http_client.h"
|
||||
|
||||
/**
|
||||
* @brief Function pointer for establishing connection to a server.
|
||||
*
|
||||
* @param[out] pxNetworkContext Implementation-defined network context.
|
||||
*
|
||||
* @return pdFAIL on failure; pdPASS on successful connection.
|
||||
*/
|
||||
typedef BaseType_t ( * TransportConnect_t )( NetworkContext_t * pxNetworkContext );
|
||||
|
||||
/**
|
||||
* @brief Connect to a server with reconnection retries.
|
||||
*
|
||||
* If connection fails, retry is attempted after a timeout. The timeout value
|
||||
* will exponentially increase until either the maximum timeout value is reached
|
||||
* or the set number of attempts are exhausted.
|
||||
*
|
||||
* @param[in] connectFunction Function pointer for establishing connection to a
|
||||
* server.
|
||||
* @param[out] pxNetworkContext Implementation-defined network context.
|
||||
*
|
||||
* @return pdFAIL on failure; pdPASS on successful connection.
|
||||
*/
|
||||
BaseType_t connectToServerWithBackoffRetries( TransportConnect_t connectFunction,
|
||||
NetworkContext_t * pxNetworkContext );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the path from the input URL.
|
||||
*
|
||||
* This function retrieves the location and length of the path from within the
|
||||
* input the URL. The query is not included in the length returned.
|
||||
*
|
||||
* The URL MUST start with "http://" or "https://" to find the path.
|
||||
*
|
||||
* For example, if pcUrl is:
|
||||
* "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
*
|
||||
* Then pcPath and pxPathLen will be the following:
|
||||
* *pcPath = "/path/to/item.txt?optionalquery=stuff"
|
||||
* *pxPathLen = 17
|
||||
*
|
||||
* @param[in] pcUrl URL string to parse.
|
||||
* @param[in] xUrlLen The length of the URL string input.
|
||||
* @param[out] pcPath pointer within input url that the path starts at.
|
||||
* @param[out] pxPathLen Length of the path.
|
||||
*
|
||||
* @return The status of the parsing attempt:
|
||||
* HTTPSuccess if the path was successfully parsed,
|
||||
* HTTPParserInternalError if there was an error parsing the URL,
|
||||
* or HTTPNoResponse if the path was not found.
|
||||
*/
|
||||
HTTPStatus_t getUrlPath( const char * pcUrl,
|
||||
size_t xUrlLen,
|
||||
const char ** pcPath,
|
||||
size_t * pxPathLen );
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Address from the input URL.
|
||||
*
|
||||
* This function retrieves the location and length of the address from within
|
||||
* the input URL. The path and query are not included in the length returned.
|
||||
*
|
||||
* The URL MUST start with "http://" or "https://" to find the address.
|
||||
*
|
||||
* For example, if pcUrl is:
|
||||
* "https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
*
|
||||
* Then pcAddress and pxAddressLen will be the following:
|
||||
* *pcAddress = "www.somewebsite.com/path/to/item.txt?optionalquery=stuff"
|
||||
* *pxAddressLen = 19
|
||||
*
|
||||
* @param[in] pcUrl URL string to parse.
|
||||
* @param[in] xUrlLen The length of the URL string input.
|
||||
* @param[out] pcAddress pointer within input url that the address starts at.
|
||||
* @param[out] pxAddressLen Length of the address.
|
||||
*
|
||||
* @return The status of the parsing attempt:
|
||||
* HTTPSuccess if the path was successfully parsed,
|
||||
* HTTPParserInternalError if there was an error parsing the URL,
|
||||
* or HTTPNoResponse if the path was not found.
|
||||
*/
|
||||
HTTPStatus_t getUrlAddress( const char * pcUrl,
|
||||
size_t xUrlLen,
|
||||
const char ** pcAddress,
|
||||
size_t * pxAddressLen );
|
||||
|
||||
#endif /* ifndef HTTP_DEMO_UTILS_H */
|
@ -0,0 +1,55 @@
|
||||
# Presigned S3 URLs Generator
|
||||
|
||||
`presigned_url_gen.py` generates pre-signed URLs for S3 HTTP GET and PUT request access.
|
||||
|
||||
### Dependencies
|
||||
|
||||
* Python 3+
|
||||
* boto3
|
||||
* argparse
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. Install the dependencies.
|
||||
```sh
|
||||
pip install boto3 argparse
|
||||
```
|
||||
|
||||
1. You will need an AWS Account with S3 access before beginning. You must install and configure the AWS CLI in order to
|
||||
use this script.
|
||||
For information on AWS S3 please see: https://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html
|
||||
For AWS CLI installation information please see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html
|
||||
For AWS CLI configuration information please see: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
|
||||
|
||||
```sh
|
||||
aws configure
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
1. Run `presigned_url_gen.py` with your s3 bucket name and s3 object key.
|
||||
```sh
|
||||
./presigned_urls_gen.py --bucket <YOUR BUCKET NAME> --key <YOUR OBJECT KEY>
|
||||
```
|
||||
An example expected output:
|
||||
```
|
||||
#define democonfigS3_PRESIGNED_GET_URL "https://aws-s3-endpoint/object-key.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ABABABABABABABABABAB%2F20201027%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20201027T194726Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=SomeHash12345UrlABcdEFgfIjK"
|
||||
#define democonfigS3_PRESIGNED_PUT_URL "https://aws-s3-endpoint/object-key.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ABABABABABABABABABAB%2F20201027%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20201027T194726Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=SomeHash12345UrlLMnmOPqrStUvW"
|
||||
```
|
||||
1. Copy and paste the output to `demo_config.h` for macros `democonfigS3_PRESIGNED_GET_URL` and `democonfigS3_PRESIGNED_PUT_URL`.
|
||||
```c
|
||||
#define democonfigS3_PRESIGNED_GET_URL "https://aws-s3-endpoint/object-key.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ABABABABABABABABABAB%2F20201027%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20201027T194726Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=SomeHash12345UrlABcdEFgfIjK"
|
||||
#define democonfigS3_PRESIGNED_PUT_URL "https://aws-s3-endpoint/object-key.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ABABABABABABABABABAB%2F20201027%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20201027T194726Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=SomeHash12345UrlLMnmOPqrStUvW"
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
#### --bucket
|
||||
The name of the S3 bucket from which the demo will download or upload.
|
||||
|
||||
#### --key
|
||||
The name of the existing object you wish to download (GET),
|
||||
or the name of the object you wish to upload (PUT).
|
||||
|
||||
#### --region
|
||||
Optional parameter for the AWS region in which the bucket is located.
|
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import boto3
|
||||
from botocore.client import Config
|
||||
import argparse
|
||||
|
||||
|
||||
def get_presigned_urls(bucket_name, key_name, region_name) -> None:
|
||||
"""
|
||||
Prints the presigned GET and PUT URLs assigned to the demo specific C
|
||||
macros, for the given object key in the given S3 bucket. If the region
|
||||
parameter is not defined, boto3 will use the one configured using AWS CLI.
|
||||
The URLs are presigned with AWS's Signature Version 4.
|
||||
Args:
|
||||
bucket_name (str): S3 bucket
|
||||
key_name (str): S3 object key
|
||||
region_name (str): S3 bucket's region
|
||||
"""
|
||||
|
||||
# Get the service client.
|
||||
# SigV2 is being deprecated. If the boto3 installation in the current Python environment has an older version of
|
||||
# the package, then this configuration forces the use of SigV4.
|
||||
s3 = boto3.client("s3", config=Config(signature_version="s3v4", region_name=region_name))
|
||||
|
||||
client_method_dict = {"GET": "get_object", "PUT": "put_object"}
|
||||
|
||||
# Generate the URL to get 'key-name' from 'bucket-name'
|
||||
for method in client_method_dict.keys():
|
||||
url = s3.generate_presigned_url(
|
||||
ClientMethod=client_method_dict[method],
|
||||
Params={"Bucket": bucket_name, "Key": key_name},
|
||||
)
|
||||
print("#define democonfigS3_PRESIGNED_" + method + "_URL" + " " + '"' + url + '"\n')
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Generate demo C macro strings, on the console, for the input S3 bucket and object key.
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description="S3 Presigned URL Generator. See README.md")
|
||||
parser.add_argument(
|
||||
"--bucket",
|
||||
action="store",
|
||||
required=True,
|
||||
dest="bucket_name",
|
||||
help="The name of the S3 bucket of interest.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--key",
|
||||
action="store",
|
||||
required=True,
|
||||
dest="key_name",
|
||||
help="The name of the S3 Object in the bucket. This is referred to as a 'key'",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--region",
|
||||
action="store",
|
||||
required=False,
|
||||
dest="region_name",
|
||||
help="The region in which the S3 bucket of interest is created.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
get_presigned_urls(args.bucket_name, args.key_name, args.region_name)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
main()
|
@ -0,0 +1 @@
|
||||
Subproject commit 0882657628eb7df12dc957f9b122601fd3054a68
|
Loading…
Reference in New Issue