mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-30 23:18:37 -04:00
Add the Labs projects provided in the V10.2.1_191129 zip file.
This commit is contained in:
parent
46e5937529
commit
e5708b38e9
801 changed files with 356576 additions and 0 deletions
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* IoT Common V1.0.0
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_taskpool.h
|
||||
* @brief User-facing functions of the task pool library.
|
||||
*/
|
||||
|
||||
#ifndef IOT_TASKPOOL_H_
|
||||
#define IOT_TASKPOOL_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Task pool types. */
|
||||
#include "types/iot_taskpool_types_freertos.h"
|
||||
|
||||
/*------------------------- Task Pool library functions --------------------------*/
|
||||
|
||||
/**
|
||||
* @functionspage{taskpool,task pool library}
|
||||
* - @functionname{taskpool_function_createsystemtaskpool}
|
||||
* - @functionname{taskpool_function_createjob}
|
||||
* - @functionname{taskpool_function_schedule}
|
||||
* - @functionname{taskpool_function_scheduledeferred}
|
||||
* - @functionname{taskpool_function_getstatus}
|
||||
* - @functionname{taskpool_function_trycancel}
|
||||
* - @functionname{taskpool_function_getjobstoragefromhandle}
|
||||
* - @functionname{taskpool_function_strerror}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @functionpage{IotTaskPool_CreateSystemTaskPool,taskpool,createsystemtaskpool}
|
||||
* @functionpage{IotTaskPool_CreateJob,taskpool,createjob}
|
||||
* @functionpage{IotTaskPool_Schedule,taskpool,schedule}
|
||||
* @functionpage{IotTaskPool_ScheduleDeferred,taskpool,scheduledeferred}
|
||||
* @functionpage{IotTaskPool_GetStatus,taskpool,getstatus}
|
||||
* @functionpage{IotTaskPool_TryCancel,taskpool,trycancel}
|
||||
* @functionpage{IotTaskPool_GetJobStorageFromHandle,taskpool,getjobstoragefromhandle}
|
||||
* @functionpage{IotTaskPool_strerror,taskpool,strerror}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Creates the one single instance of the system task pool.
|
||||
*
|
||||
* This function should be called once by the application to initialize the one single instance of the system task pool.
|
||||
* An application should initialize the system task pool early in the boot sequence, before initializing any other library
|
||||
* (e.g. MQTT) that uses the system task pool. An application should also initialize the system
|
||||
* task pool before posting any jobs. Early initialization is typically easy to accomplish by creating the system task pool
|
||||
* before the scheduler is started.
|
||||
*
|
||||
* The shortcut @ref IOT_SYSTEM_TASKPOOL contains the system task pool handle.
|
||||
*
|
||||
* @param[in] pInfo A pointer to the task pool initialization data.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
* - #IOT_TASKPOOL_NO_MEMORY
|
||||
*
|
||||
* @warning This function should be called only once. Calling this function more that once will result in
|
||||
* undefined behavior.
|
||||
*
|
||||
*/
|
||||
/* @[declare_taskpool_createsystemtaskpool] */
|
||||
IotTaskPoolError_t IotTaskPool_CreateSystemTaskPool( const IotTaskPoolInfo_t * const pInfo );
|
||||
/* @[declare_taskpool_createsystemtaskpool] */
|
||||
|
||||
/**
|
||||
* @brief Creates a job for the task pool around a user-provided storage.
|
||||
*
|
||||
* @param[in] userCallback A user-specified callback for the job.
|
||||
* @param[in] pUserContext A user-specified context for the callback.
|
||||
* @param[in,out] pJobStorage The storage for the job data structure.
|
||||
* @param[out] pJob A pointer to an instance of @ref IotTaskPoolJob_t that will be initialized when this
|
||||
* function returns successfully. This handle can be used to inspect the job status with
|
||||
* @ref IotTaskPool_GetStatus or cancel the job with @ref IotTaskPool_TryCancel, etc....
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
*
|
||||
*
|
||||
*/
|
||||
/* @[declare_taskpool_createjob] */
|
||||
IotTaskPoolError_t IotTaskPool_CreateJob( IotTaskPoolRoutine_t userCallback,
|
||||
void * pUserContext,
|
||||
IotTaskPoolJobStorage_t * const pJobStorage,
|
||||
IotTaskPoolJob_t * const pJob );
|
||||
/* @[declare_taskpool_createjob] */
|
||||
|
||||
/**
|
||||
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob against the task pool pointed to by `taskPool`.
|
||||
*
|
||||
* @param[in] taskPool A handle to an initialized taskpool.
|
||||
* @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob.
|
||||
* @param[in] flags Flags to be passed by the user, e.g. to identify the job as high priority by specifying #IOT_TASKPOOL_JOB_HIGH_PRIORITY.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
* - #IOT_TASKPOOL_ILLEGAL_OPERATION
|
||||
* - #IOT_TASKPOOL_NO_MEMORY
|
||||
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS
|
||||
*
|
||||
* @note This function will not allocate memory, so it is guaranteed to succeed if the parameters are correct and the task pool
|
||||
* was correctly initialized, and not yet destroyed.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
* // An example of a user context to pass to a callback through a task pool thread.
|
||||
* typedef struct JobUserContext
|
||||
* {
|
||||
* uint32_t counter;
|
||||
* } JobUserContext_t;
|
||||
*
|
||||
* // An example of a user callback to invoke through a task pool thread.
|
||||
* static void ExecutionCb( IotTaskPool_t taskPool, IotTaskPoolJob_t job, void * context )
|
||||
* {
|
||||
* ( void )taskPool;
|
||||
* ( void )job;
|
||||
*
|
||||
* JobUserContext_t * pUserContext = ( JobUserContext_t * )context;
|
||||
*
|
||||
* pUserContext->counter++;
|
||||
* }
|
||||
*
|
||||
* void TaskPoolExample( )
|
||||
* {
|
||||
* JobUserContext_t userContext = { 0 };
|
||||
* IotTaskPoolJob_t job;
|
||||
* IotTaskPool_t taskPool;
|
||||
*
|
||||
* // Configure the task pool to hold one thread.
|
||||
* // Provide proper stack size and priority per the application needs.
|
||||
*
|
||||
* const IotTaskPoolInfo_t tpInfo = { .minThreads = 1, .maxThreads = 1, .stackSize = 512, .priority = 0 };
|
||||
*
|
||||
* // Create a task pool.
|
||||
* IotTaskPool_Create( &tpInfo, &taskPool );
|
||||
*
|
||||
* // Statically allocate one job, schedule it.
|
||||
* IotTaskPool_CreateJob( &ExecutionCb, &userContext, &job );
|
||||
*
|
||||
* IotTaskPoolError_t errorSchedule = IotTaskPool_Schedule( taskPool, &job, 0 );
|
||||
*
|
||||
* switch ( errorSchedule )
|
||||
* {
|
||||
* case IOT_TASKPOOL_SUCCESS:
|
||||
* break;
|
||||
* case IOT_TASKPOOL_BAD_PARAMETER: // Invalid parameters, such as a NULL handle, can trigger this error.
|
||||
* case IOT_TASKPOOL_ILLEGAL_OPERATION: // Scheduling a job that was previously scheduled or destroyed could trigger this error.
|
||||
* case IOT_TASKPOOL_NO_MEMORY: // Scheduling a with flag #IOT_TASKPOOL_JOB_HIGH_PRIORITY could trigger this error.
|
||||
* case IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS: // Scheduling a job after trying to destroy the task pool could trigger this error.
|
||||
* // ASSERT
|
||||
* break;
|
||||
* default:
|
||||
* // ASSERT
|
||||
* }
|
||||
*
|
||||
* //
|
||||
* // ... Perform other operations ...
|
||||
* //
|
||||
*
|
||||
* IotTaskPool_Destroy( taskPool );
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/* @[declare_taskpool_schedule] */
|
||||
IotTaskPoolError_t IotTaskPool_Schedule( IotTaskPool_t taskPool,
|
||||
IotTaskPoolJob_t job,
|
||||
uint32_t flags );
|
||||
/* @[declare_taskpool_schedule] */
|
||||
|
||||
/**
|
||||
* @brief This function schedules a job created with @ref IotTaskPool_CreateJob to be executed after a user-defined time interval.
|
||||
*
|
||||
* @param[in] taskPool A handle to an initialized taskpool.
|
||||
* @param[in] job A job to schedule for execution. This must be first initialized with a call to @ref IotTaskPool_CreateJob.
|
||||
* @param[in] timeMs The time in milliseconds to wait before scheduling the job.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
* - #IOT_TASKPOOL_ILLEGAL_OPERATION
|
||||
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS
|
||||
*
|
||||
*
|
||||
* @note This function will not allocate memory.
|
||||
*
|
||||
* @warning The `taskPool` used in this function should be the same
|
||||
* used to create the job pointed to by `job`, or the results will be undefined.
|
||||
*
|
||||
*/
|
||||
/* @[declare_taskpool_scheduledeferred] */
|
||||
IotTaskPoolError_t IotTaskPool_ScheduleDeferred( IotTaskPool_t taskPool,
|
||||
IotTaskPoolJob_t job,
|
||||
uint32_t timeMs );
|
||||
/* @[declare_taskpool_scheduledeferred] */
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the current status of a job.
|
||||
*
|
||||
* @param[in] taskPool A handle to an initialized taskpool.
|
||||
* @param[in] job The job to cancel.
|
||||
* @param[out] pStatus The status of the job at the time of cancellation.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS
|
||||
*
|
||||
* @warning This function is not thread safe and the job status returned in `pStatus` may be invalid by the time
|
||||
* the calling thread has a chance to inspect it.
|
||||
*/
|
||||
/* @[declare_taskpool_getstatus] */
|
||||
IotTaskPoolError_t IotTaskPool_GetStatus( IotTaskPool_t taskPool,
|
||||
IotTaskPoolJob_t job,
|
||||
IotTaskPoolJobStatus_t * const pStatus );
|
||||
/* @[declare_taskpool_getstatus] */
|
||||
|
||||
/**
|
||||
* @brief This function tries to cancel a job that was previously scheduled with @ref IotTaskPool_Schedule.
|
||||
*
|
||||
* A job can be canceled only if it is not yet executing, i.e. if its status is
|
||||
* @ref IOT_TASKPOOL_STATUS_READY or @ref IOT_TASKPOOL_STATUS_SCHEDULED. Calling
|
||||
* @ref IotTaskPool_TryCancel on a job whose status is @ref IOT_TASKPOOL_STATUS_COMPLETED,
|
||||
* or #IOT_TASKPOOL_STATUS_CANCELED will yield a #IOT_TASKPOOL_CANCEL_FAILED return result.
|
||||
*
|
||||
* @param[in] taskPool A handle to an initialized taskpool.
|
||||
* @param[in] job The job to cancel.
|
||||
* @param[out] pStatus The status of the job at the time of cancellation.
|
||||
*
|
||||
* @return One of the following:
|
||||
* - #IOT_TASKPOOL_SUCCESS
|
||||
* - #IOT_TASKPOOL_BAD_PARAMETER
|
||||
* - #IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS
|
||||
* - #IOT_TASKPOOL_CANCEL_FAILED
|
||||
*
|
||||
* @warning The `taskPool` used in this function should be the same
|
||||
* used to create the job pointed to by `job`, or the results will be undefined.
|
||||
*
|
||||
*/
|
||||
/* @[declare_taskpool_trycancel] */
|
||||
IotTaskPoolError_t IotTaskPool_TryCancel( IotTaskPool_t taskPool,
|
||||
IotTaskPoolJob_t job,
|
||||
IotTaskPoolJobStatus_t * const pStatus );
|
||||
/* @[declare_taskpool_trycancel] */
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the job storage from an instance of a job handle
|
||||
* of type @ref IotTaskPoolJob_t. This function is guaranteed to succeed for a
|
||||
* valid job handle.
|
||||
*
|
||||
* @param[in] job The job handle.
|
||||
*
|
||||
* @return A pointer to the storage associated with the job handle `job`.
|
||||
*
|
||||
* @warning If the `job` handle used is invalid, the results will be undefined.
|
||||
*/
|
||||
/* @[declare_taskpool_getjobstoragefromhandle] */
|
||||
IotTaskPoolJobStorage_t * IotTaskPool_GetJobStorageFromHandle( IotTaskPoolJob_t job );
|
||||
/* @[declare_taskpool_getjobstoragefromhandle] */
|
||||
|
||||
/**
|
||||
* @brief Returns a string that describes an @ref IotTaskPoolError_t.
|
||||
*
|
||||
* Like the POSIX's `strerror`, this function returns a string describing a
|
||||
* return code. In this case, the return code is a task pool library error code,
|
||||
* `status`.
|
||||
*
|
||||
* The string returned by this function <b>MUST</b> be treated as read-only: any
|
||||
* attempt to modify its contents may result in a crash. Therefore, this function
|
||||
* is limited to usage in logging.
|
||||
*
|
||||
* @param[in] status The status to describe.
|
||||
*
|
||||
* @return A read-only string that describes `status`.
|
||||
*
|
||||
* @warning The string returned by this function must never be modified.
|
||||
*/
|
||||
/* @[declare_taskpool_strerror] */
|
||||
const char * IotTaskPool_strerror( IotTaskPoolError_t status );
|
||||
/* @[declare_taskpool_strerror] */
|
||||
|
||||
#endif /* ifndef IOT_TASKPOOL_H_ */
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Amazon FreeRTOS Platform V1.0.0
|
||||
* Copyright (C) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_network_freertos.h
|
||||
* @brief Declares the network stack functions specified in iot_network.h for
|
||||
* FreeRTOS+TCP.
|
||||
*/
|
||||
|
||||
#ifndef _IOT_NETWORK_FREERTOS_H_
|
||||
#define _IOT_NETWORK_FREERTOS_H_
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Platform types include. */
|
||||
#include "types/iot_platform_types.h"
|
||||
|
||||
/* Platform network include. */
|
||||
#include "platform/iot_network.h"
|
||||
|
||||
/**
|
||||
* @brief Provides a default value for an #IotNetworkConnectionFreeRTOS_t.
|
||||
*
|
||||
* All instances of #IotNetworkConnectionFreeRTOS_t should be initialized with
|
||||
* this constant.
|
||||
*
|
||||
* @warning Failing to initialize an #IotNetworkConnectionFreeRTOS_t with this
|
||||
* initializer may result in undefined behavior!
|
||||
* @note This initializer may change at any time in future versions, but its
|
||||
* name will remain the same.
|
||||
*/
|
||||
#define IOT_NETWORK_CONNECTION_FREERTOS_INITIALIZER { 0 }
|
||||
|
||||
/**
|
||||
* @brief Generic initializer for an #IotNetworkServerInfo_t.
|
||||
*
|
||||
* @note This initializer may change at any time in future versions, but its
|
||||
* name will remain the same.
|
||||
*/
|
||||
#define IOT_NETWORK_SERVER_INFO_FREERTOS_INITIALIZER { 0 }
|
||||
|
||||
/**
|
||||
* @brief Generic initializer for an #IotNetworkCredentials_t.
|
||||
*
|
||||
* @note This initializer may change at any time in future versions, but its
|
||||
* name will remain the same.
|
||||
*/
|
||||
#define IOT_NETWORK_CREDENTIALS_FREERTOS_INITIALIZER { 0 }
|
||||
|
||||
/**
|
||||
* @brief Provides a pointer to an #IotNetworkInterface_t that uses the functions
|
||||
* declared in this file.
|
||||
*/
|
||||
#define IOT_NETWORK_INTERFACE_FREERTOS ( &( IotNetworkFreeRTOS ) )
|
||||
|
||||
/**
|
||||
* @brief One-time initialization function for this network stack.
|
||||
*/
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Init( void );
|
||||
|
||||
/**
|
||||
* @brief One-time cleanup function for this network stack.
|
||||
*/
|
||||
void IotNetworkFreeRTOS_Cleanup( void );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::create for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Create( IotNetworkServerInfo_t pServerInfo,
|
||||
IotNetworkCredentials_t pCredentialInfo,
|
||||
IotNetworkConnection_t * pConnection );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::setReceiveCallback for
|
||||
* FreeRTOS+TCP sockets.
|
||||
*/
|
||||
IotNetworkError_t IotNetworkFreeRTOS_SetReceiveCallback( IotNetworkConnection_t pConnection,
|
||||
IotNetworkReceiveCallback_t receiveCallback,
|
||||
void * pContext );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::send for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
size_t IotNetworkFreeRTOS_Send( IotNetworkConnection_t pConnection,
|
||||
const uint8_t * pMessage,
|
||||
size_t messageLength );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::receive for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
size_t IotNetworkFreeRTOS_Receive( IotNetworkConnection_t pConnection,
|
||||
uint8_t * pBuffer,
|
||||
size_t bytesRequested );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface::receiveUpto for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
size_t IotNetworkFreeRTOS_ReceiveUpto( IotNetworkConnection_t pConnection,
|
||||
uint8_t * pBuffer,
|
||||
size_t bufferSize );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::close for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Close( IotNetworkConnection_t pConnection );
|
||||
|
||||
/**
|
||||
* @brief An implementation of #IotNetworkInterface_t::destroy for FreeRTOS+TCP
|
||||
* sockets.
|
||||
*/
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Destroy( IotNetworkConnection_t pConnection );
|
||||
|
||||
/**
|
||||
* @cond DOXYGEN_IGNORE
|
||||
* Doxygen should ignore this section.
|
||||
*
|
||||
* Declaration of a network interface struct using the functions in this file.
|
||||
*/
|
||||
extern const IotNetworkInterface_t IotNetworkFreeRTOS;
|
||||
/** @endcond */
|
||||
|
||||
#endif /* ifndef _IOT_NETWORK_FREERTOS_H_ */
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Amazon FreeRTOS Platform V1.0.0
|
||||
* Copyright (C) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_platform_types_posix.h
|
||||
* @brief Definitions of platform layer types on POSIX systems.
|
||||
*/
|
||||
|
||||
#ifndef _IOT_PLATFORM_TYPES_AFR_H_
|
||||
#define _IOT_PLATFORM_TYPES_AFR_H_
|
||||
|
||||
#include "timers.h"
|
||||
|
||||
typedef struct iot_mutex_internal
|
||||
{
|
||||
StaticSemaphore_t xMutex; /**< FreeRTOS mutex. */
|
||||
BaseType_t recursive; /**< Type; used for indicating if this is reentrant or normal. */
|
||||
} iot_mutex_internal_t;
|
||||
|
||||
/**
|
||||
* @brief The native mutex type on AFR systems.
|
||||
*/
|
||||
typedef iot_mutex_internal_t _IotSystemMutex_t;
|
||||
|
||||
typedef struct iot_sem_internal
|
||||
{
|
||||
StaticSemaphore_t xSemaphore; /**< FreeRTOS semaphore. */
|
||||
} iot_sem_internal_t;
|
||||
|
||||
/**
|
||||
* @brief The native semaphore type on AFR systems.
|
||||
*/
|
||||
typedef iot_sem_internal_t _IotSystemSemaphore_t;
|
||||
|
||||
/**
|
||||
* @brief Holds information about an active detached thread so that we can
|
||||
* delete the FreeRTOS task when it completes
|
||||
*/
|
||||
typedef struct threadInfo
|
||||
{
|
||||
void * pArgument; /**< @brief Argument to `threadRoutine`. */
|
||||
void ( * threadRoutine )( void * ); /**< @brief Thread function to run. */
|
||||
} threadInfo_t;
|
||||
|
||||
/**
|
||||
* @brief Holds information about an active timer.
|
||||
*/
|
||||
typedef struct timerInfo
|
||||
{
|
||||
TimerHandle_t timer; /**< @brief Underlying timer. */
|
||||
void ( * threadRoutine )( void * ); /**< @brief Thread function to run on timer expiration. */
|
||||
void * pArgument; /**< @brief First argument to threadRoutine. */
|
||||
StaticTimer_t xTimerBuffer; /**< Memory that holds the FreeRTOS timer. */
|
||||
TickType_t xTimerPeriod; /**< Period of this timer. */
|
||||
} timerInfo_t;
|
||||
|
||||
/**
|
||||
* @brief Represents an #IotTimer_t on AFR systems.
|
||||
*/
|
||||
typedef timerInfo_t _IotSystemTimer_t;
|
||||
|
||||
struct IotNetworkServerInfo;
|
||||
struct IotNetworkCredentials;
|
||||
struct _networkConnection;
|
||||
|
||||
typedef struct IotNetworkServerInfo const * _IotNetworkServerInfo_t;
|
||||
typedef struct IotNetworkCredentials * _IotNetworkCredentials_t;
|
||||
typedef struct _networkConnection * _IotNetworkConnection_t;
|
||||
|
||||
#endif /* ifndef _IOT_PLATFORM_TYPES_POSIX_H_ */
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* IoT Common V1.0.0
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_taskpool_types.h
|
||||
* @brief Types of the task pool.
|
||||
*/
|
||||
|
||||
#ifndef IOT_TASKPOOL_TYPES_H_
|
||||
#define IOT_TASKPOOL_TYPES_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Platform types includes. */
|
||||
#include "types/iot_platform_types.h"
|
||||
|
||||
/* Linear containers (lists and queues) include. */
|
||||
#include "iot_linear_containers.h"
|
||||
|
||||
/*-------------------------- Task pool enumerated types --------------------------*/
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_enums
|
||||
* @brief Return codes of [task pool functions](@ref taskpool_functions).
|
||||
*/
|
||||
typedef enum IotTaskPoolError
|
||||
{
|
||||
/**
|
||||
* @brief Task pool operation completed successfully.
|
||||
*/
|
||||
IOT_TASKPOOL_SUCCESS = 0,
|
||||
|
||||
/**
|
||||
* @brief Task pool operation failed because at least one parameter is invalid.
|
||||
*/
|
||||
IOT_TASKPOOL_BAD_PARAMETER,
|
||||
|
||||
/**
|
||||
* @brief Task pool operation failed because it is illegal.
|
||||
*/
|
||||
IOT_TASKPOOL_ILLEGAL_OPERATION,
|
||||
|
||||
/**
|
||||
* @brief Task pool operation failed because allocating memory failed.
|
||||
*/
|
||||
IOT_TASKPOOL_NO_MEMORY,
|
||||
|
||||
/**
|
||||
* @brief Task pool operation failed because of an invalid parameter.
|
||||
*/
|
||||
IOT_TASKPOOL_SHUTDOWN_IN_PROGRESS,
|
||||
|
||||
/**
|
||||
* @brief Task pool cancellation failed.
|
||||
*/
|
||||
IOT_TASKPOOL_CANCEL_FAILED,
|
||||
|
||||
/**
|
||||
* @brief Task pool operation general failure.
|
||||
*/
|
||||
IOT_TASKPOOL_GENERAL_FAILURE,
|
||||
} IotTaskPoolError_t;
|
||||
|
||||
/**
|
||||
* @enums{taskpool,Task pool library}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_enums
|
||||
* @brief Status codes of [task pool Job](@ref IotTaskPoolJob_t).
|
||||
*
|
||||
*/
|
||||
typedef enum IotTaskPoolJobStatus
|
||||
{
|
||||
/**
|
||||
* @brief Job is ready to be scheduled.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_READY = 0,
|
||||
|
||||
/**
|
||||
* @brief Job has been queued for execution.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_SCHEDULED,
|
||||
|
||||
/**
|
||||
* @brief Job has been scheduled for deferred execution.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_DEFERRED,
|
||||
|
||||
/**
|
||||
* @brief Job is executing.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_COMPLETED,
|
||||
|
||||
/**
|
||||
* @brief Job has been canceled before executing.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_CANCELED,
|
||||
|
||||
/**
|
||||
* @brief Job status is undefined.
|
||||
*
|
||||
*/
|
||||
IOT_TASKPOOL_STATUS_UNDEFINED,
|
||||
} IotTaskPoolJobStatus_t;
|
||||
|
||||
/*------------------------- Task pool types and handles --------------------------*/
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_handles
|
||||
* @brief Opaque handle of a Task Pool instance.
|
||||
*
|
||||
* This type identifies a Task Pool instance, which is valid after a successful call
|
||||
* to @ref taskpool_function_createsystemtaskpool.
|
||||
*
|
||||
* @initializer{IotTaskPool_t,IOT_TASKPOOL_INITIALIZER}
|
||||
*/
|
||||
typedef struct _taskPool * IotTaskPool_t;
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_handles
|
||||
* @brief A storage placeholder for TaskPool Jobs.
|
||||
*
|
||||
* This type provides a means to statically allocate an IoT TaskPool Job while
|
||||
* hiding internal details.
|
||||
*/
|
||||
typedef struct IotTaskPoolJobStorage IotTaskPoolJobStorage_t;
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_structs
|
||||
* @brief A storage placeholder for private data in the IotTaskPoolJobStorage struct.
|
||||
*
|
||||
* @warning This is a system-level data type that should not be modified or used directly in any application.
|
||||
* @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.
|
||||
*/
|
||||
struct PrivateMember
|
||||
{
|
||||
IotLink_t dummy1; /**< @brief Placeholder. */
|
||||
TickType_t dummy2; /**< @brief Placeholder. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_structs
|
||||
* @brief The job storage data structure provides the storage for a statically allocated Task Pool Job instance.
|
||||
*
|
||||
* @warning This is a system-level data type that should not be modified or used directly in any application.
|
||||
* @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.
|
||||
*
|
||||
*/
|
||||
struct IotTaskPoolJobStorage
|
||||
{
|
||||
IotLink_t link; /**< @brief Placeholder. */
|
||||
void * dummy2; /**< @brief Placeholder. */
|
||||
void * dummy3; /**< @brief Placeholder. */
|
||||
IotTaskPoolJobStatus_t status; /**< @brief Placeholder. */
|
||||
struct PrivateMember dummy6; /**< @brief Placeholder. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_handles
|
||||
* @brief Opaque handle of a Task Pool Job.
|
||||
*
|
||||
* This type identifies a Task Pool Job instance, which is valid after a successful call
|
||||
* to @ref taskpool_function_createjob.
|
||||
*
|
||||
* @initializer{IotTaskPoolJob_t,IOT_TASKPOOL_JOB_INITIALIZER}
|
||||
*
|
||||
*/
|
||||
typedef struct _taskPoolJob * IotTaskPoolJob_t;
|
||||
|
||||
/*------------------------- Task pool parameter structs --------------------------*/
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_functionpointers
|
||||
* @brief Callback type for a user callback.
|
||||
*
|
||||
* This type identifies the user callback signature to execute a task pool job. This callback will be invoked
|
||||
* by the task pool threads with the `pUserContext` parameter, as specified by the user when
|
||||
* calling @ref IotTaskPool_Schedule.
|
||||
*
|
||||
*/
|
||||
typedef void ( * IotTaskPoolRoutine_t )( IotTaskPool_t pTaskPool,
|
||||
IotTaskPoolJob_t pJob,
|
||||
void * pUserContext );
|
||||
|
||||
/**
|
||||
* @ingroup taskpool_datatypes_paramstructs
|
||||
* @brief Initialization information to create one task pool instance.
|
||||
*
|
||||
* @paramfor @ref taskpool_function_createsystemtaskpool
|
||||
*
|
||||
* @initializer{IotTaskPoolInfo_t,IOT_TASKPOOL_INFO_INITIALIZER}
|
||||
*/
|
||||
typedef struct IotTaskPoolInfo
|
||||
{
|
||||
/**
|
||||
* @brief Specifies the operating parameters for a task pool.
|
||||
*
|
||||
* @attention #IotTaskPoolInfo_t.minThreads <b>MUST</b> be at least 1.
|
||||
*/
|
||||
|
||||
uint32_t minThreads; /**< @brief Minimum number of threads in a task pool. These tasks will be statically allocated. */
|
||||
uint32_t maxThreads; /**< @brief Maximum number of threads in a task pool. This is fixed for the lifetime of the taskpool. */
|
||||
uint32_t stackSize; /**< @brief Stack size for every task pool thread. The stack size for each thread is fixed after the task pool is created and cannot be changed. */
|
||||
int32_t priority; /**< @brief priority for every task pool thread. The priority for each thread is fixed after the task pool is created and cannot be changed. */
|
||||
} IotTaskPoolInfo_t;
|
||||
|
||||
/*------------------------- TASKPOOL defined constants --------------------------*/
|
||||
|
||||
/**
|
||||
* @constantspage{taskpool,task pool library}
|
||||
*
|
||||
* @section taskpool_constants_initializers Task pool Initializers
|
||||
* @brief Provides default values for initializing the data types of the task pool library.
|
||||
*
|
||||
* @snippet this define_taskpool_initializers
|
||||
*
|
||||
* All user-facing data types of the task pool library can be initialized using
|
||||
* one of the following.
|
||||
*
|
||||
* @warning Failure to initialize a task pool data type with the appropriate initializer
|
||||
* may result in a runtime error!
|
||||
* @note The initializers may change at any time in future versions, but their
|
||||
* names will remain the same.
|
||||
*
|
||||
* <b>Example</b>
|
||||
* @code{c}
|
||||
*
|
||||
* IotTaskPool_t * pTaskPool;
|
||||
*
|
||||
* const IotTaskPoolInfo_t tpInfo = IOT_TASKPOOL_INFO_INITIALIZER_LARGE;
|
||||
*
|
||||
* IotTaskPoolError_t error = IotTaskPool_Create( &tpInfo, &pTaskPool );
|
||||
*
|
||||
* // Use the task pool
|
||||
* // ...
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
*/
|
||||
/* @[define_taskpool_initializers] */
|
||||
/** @brief Initializer for a small #IotTaskPoolInfo_t. */
|
||||
#define IOT_TASKPOOL_INFO_INITIALIZER_SMALL { .minThreads = 1, .maxThreads = 1, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY }
|
||||
/** @brief Initializer for a medium #IotTaskPoolInfo_t. */
|
||||
#define IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM { .minThreads = 1, .maxThreads = 2, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY }
|
||||
/** @brief Initializer for a large #IotTaskPoolInfo_t. */
|
||||
#define IOT_TASKPOOL_INFO_INITIALIZER_LARGE { .minThreads = 2, .maxThreads = 3, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY }
|
||||
/** @brief Initializer for a very large #IotTaskPoolInfo_t. */
|
||||
#define IOT_TASKPOOL_INFO_INITIALIZER_XLARGE { .minThreads = 2, .maxThreads = 4, .stackSize = IOT_THREAD_DEFAULT_STACK_SIZE, .priority = IOT_THREAD_DEFAULT_PRIORITY }
|
||||
/** @brief Initializer for a typical #IotTaskPoolInfo_t. */
|
||||
#define IOT_TASKPOOL_INFO_INITIALIZER IOT_TASKPOOL_INFO_INITIALIZER_MEDIUM
|
||||
/** @brief Initializer for a #IotTaskPool_t. */
|
||||
#define IOT_TASKPOOL_INITIALIZER NULL
|
||||
/** @brief Initializer for a #IotTaskPoolJobStorage_t. */
|
||||
#define IOT_TASKPOOL_JOB_STORAGE_INITIALIZER { { NULL, NULL }, NULL, NULL, 0, IOT_TASKPOOL_STATUS_UNDEFINED }
|
||||
/** @brief Initializer for a #IotTaskPoolJob_t. */
|
||||
#define IOT_TASKPOOL_JOB_INITIALIZER NULL
|
||||
/* @[define_taskpool_initializers] */
|
||||
|
||||
/**
|
||||
* @brief Flag for scheduling a job to execute immediately, even if the maximum number of threads in the
|
||||
* task pool was reached already.
|
||||
*
|
||||
* @warning This flag may cause the task pool to create a worker to serve the job immediately, and
|
||||
* therefore using this flag may incur in additional memory usage and potentially fail scheduling the job.
|
||||
*/
|
||||
#define IOT_TASKPOOL_JOB_HIGH_PRIORITY ( ( uint32_t ) 0x00000001 )
|
||||
|
||||
/**
|
||||
* @brief Allows the use of the handle to the system task pool.
|
||||
*
|
||||
* @warning The system task pool handle is not valid unless @ref IotTaskPool_CreateSystemTaskPool is
|
||||
* called before the handle is used.
|
||||
*/
|
||||
#define IOT_SYSTEM_TASKPOOL ( NULL )
|
||||
|
||||
#endif /* ifndef IOT_TASKPOOL_TYPES_H_ */
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Amazon FreeRTOS Platform V1.1.0
|
||||
* Copyright (C) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_clock_freertos.c
|
||||
* @brief Implementation of the platform specific functions in iot_clock.h for
|
||||
* FreeRTOS.
|
||||
*/
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Platform clock include. */
|
||||
#include "platform/iot_platform_types_freertos.h"
|
||||
#include "platform/iot_clock.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Configure logs for the functions in this file. */
|
||||
#ifdef IOT_LOG_LEVEL_PLATFORM
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM
|
||||
#else
|
||||
#ifdef IOT_LOG_LEVEL_GLOBAL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
|
||||
#else
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIBRARY_LOG_NAME ( "CLOCK" )
|
||||
#include "iot_logging_setup.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Time conversion constants.
|
||||
*/
|
||||
#define _MILLISECONDS_PER_SECOND ( 1000 ) /**< @brief Milliseconds per second. */
|
||||
#define _MILLISECONDS_PER_TICK ( _MILLISECONDS_PER_SECOND / configTICK_RATE_HZ ) /**< Milliseconds per FreeRTOS tick. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Private Callback function for timer expiry, delegate work to a Task to free
|
||||
* up the timer task for managing other timers */
|
||||
static void prvTimerCallback( TimerHandle_t xTimerHandle )
|
||||
{
|
||||
_IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pvTimerGetTimerID( xTimerHandle );
|
||||
|
||||
/* The value of the timer ID, set in timer_create, should not be NULL. */
|
||||
configASSERT( pxTimer != NULL );
|
||||
|
||||
/* Restart the timer if it is periodic. */
|
||||
if( pxTimer->xTimerPeriod > 0 )
|
||||
{
|
||||
xTimerChangePeriod( xTimerHandle, pxTimer->xTimerPeriod, 0 );
|
||||
}
|
||||
|
||||
/* Call timer Callback from this task */
|
||||
pxTimer->threadRoutine( ( void * ) pxTimer->pArgument );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotClock_GetTimestring( char * pBuffer,
|
||||
size_t bufferSize,
|
||||
size_t * pTimestringLength )
|
||||
{
|
||||
uint64_t milliSeconds = IotClock_GetTimeMs();
|
||||
int timestringLength = 0;
|
||||
|
||||
configASSERT( pBuffer != NULL );
|
||||
configASSERT( pTimestringLength != NULL );
|
||||
|
||||
/* Convert the localTime struct to a string. */
|
||||
timestringLength = snprintf( pBuffer, bufferSize, "%llu", milliSeconds );
|
||||
|
||||
/* Check for error from no string */
|
||||
if( timestringLength == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the output parameter. */
|
||||
*pTimestringLength = timestringLength;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint64_t IotClock_GetTimeMs( void )
|
||||
{
|
||||
TimeOut_t xCurrentTime = { 0 };
|
||||
|
||||
/* This must be unsigned because the behavior of signed integer overflow is undefined. */
|
||||
uint64_t ullTickCount = 0ULL;
|
||||
|
||||
/* Get the current tick count and overflow count. vTaskSetTimeOutState()
|
||||
* is used to get these values because they are both static in tasks.c. */
|
||||
vTaskSetTimeOutState( &xCurrentTime );
|
||||
|
||||
/* Adjust the tick count for the number of times a TickType_t has overflowed. */
|
||||
ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 );
|
||||
|
||||
/* Add the current tick count. */
|
||||
ullTickCount += xCurrentTime.xTimeOnEntering;
|
||||
|
||||
/* Return the ticks converted to Milliseconds */
|
||||
return ullTickCount * _MILLISECONDS_PER_TICK;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotClock_SleepMs( uint32_t sleepTimeMs )
|
||||
{
|
||||
vTaskDelay( pdMS_TO_TICKS( sleepTimeMs ) );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotClock_TimerCreate( IotTimer_t * pNewTimer,
|
||||
IotThreadRoutine_t expirationRoutine,
|
||||
void * pArgument )
|
||||
{
|
||||
_IotSystemTimer_t * pxTimer = ( _IotSystemTimer_t * ) pNewTimer;
|
||||
|
||||
configASSERT( pNewTimer != NULL );
|
||||
configASSERT( expirationRoutine != NULL );
|
||||
|
||||
IotLogDebug( "Creating new timer %p.", pNewTimer );
|
||||
|
||||
/* Set the timer expiration routine, argument and period */
|
||||
pxTimer->threadRoutine = expirationRoutine;
|
||||
pxTimer->pArgument = pArgument;
|
||||
pxTimer->xTimerPeriod = 0;
|
||||
|
||||
/* Create a new FreeRTOS timer. This call will not fail because the
|
||||
* memory for it has already been allocated, so the output parameter is
|
||||
* also set. */
|
||||
pxTimer->timer = ( TimerHandle_t ) xTimerCreateStatic( "timer", /* Timer name. */
|
||||
portMAX_DELAY, /* Initial timer period. Timers are created disarmed. */
|
||||
pdFALSE, /* Don't auto-reload timer. */
|
||||
( void * ) pxTimer, /* Timer id. */
|
||||
prvTimerCallback, /* Timer expiration callback. */
|
||||
&pxTimer->xTimerBuffer ); /* Pre-allocated memory for timer. */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotClock_TimerDestroy( IotTimer_t * pTimer )
|
||||
{
|
||||
_IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;
|
||||
|
||||
configASSERT( pTimerInfo != NULL );
|
||||
configASSERT( pTimerInfo->timer != NULL );
|
||||
|
||||
IotLogDebug( "Destroying timer %p.", pTimer );
|
||||
|
||||
if( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )
|
||||
{
|
||||
/* Stop the FreeRTOS timer. Because the timer is statically allocated, no call
|
||||
* to xTimerDelete is necessary. The timer is stopped so that it's not referenced
|
||||
* anywhere. xTimerStop will not fail when it has unlimited block time. */
|
||||
( void ) xTimerStop( pTimerInfo->timer, portMAX_DELAY );
|
||||
|
||||
/* Wait until the timer stop command is processed. */
|
||||
while( xTimerIsTimerActive( pTimerInfo->timer ) == pdTRUE )
|
||||
{
|
||||
vTaskDelay( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotClock_TimerArm( IotTimer_t * pTimer,
|
||||
uint32_t relativeTimeoutMs,
|
||||
uint32_t periodMs )
|
||||
{
|
||||
_IotSystemTimer_t * pTimerInfo = ( _IotSystemTimer_t * ) pTimer;
|
||||
|
||||
configASSERT( pTimerInfo != NULL );
|
||||
|
||||
TimerHandle_t xTimerHandle = pTimerInfo->timer;
|
||||
|
||||
IotLogDebug( "Arming timer %p with timeout %llu and period %llu.",
|
||||
pTimer,
|
||||
relativeTimeoutMs,
|
||||
periodMs );
|
||||
|
||||
/* Set the timer period in ticks */
|
||||
pTimerInfo->xTimerPeriod = pdMS_TO_TICKS( periodMs );
|
||||
|
||||
/* Set the timer to expire after relativeTimeoutMs, and restart it. */
|
||||
( void ) xTimerChangePeriod( xTimerHandle, pdMS_TO_TICKS( relativeTimeoutMs ), portMAX_DELAY );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
|
@ -0,0 +1,968 @@
|
|||
/*
|
||||
* Amazon FreeRTOS Platform V1.1.0
|
||||
* Copyright (C) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_network_freertos.c
|
||||
* @brief Implementation of the network-related functions from iot_network_freertos.h
|
||||
* for FreeRTOS+TCP sockets.
|
||||
*/
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include <string.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "atomic.h"
|
||||
#include "semphr.h"
|
||||
|
||||
/* FreeRTOS+TCP includes. */
|
||||
#include "FreeRTOS_IP.h"
|
||||
#include "FreeRTOS_Sockets.h"
|
||||
|
||||
/* FreeRTOS-IoT-Libraries includes. */
|
||||
#include "iot_error.h"
|
||||
#include "platform/iot_network_freertos.h"
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
/* mbed TLS includes. */
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/threading.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#endif
|
||||
|
||||
/* Configure logs for the functions in this file. */
|
||||
#ifdef IOT_LOG_LEVEL_NETWORK
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_NETWORK
|
||||
#else
|
||||
#ifdef IOT_LOG_LEVEL_GLOBAL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
|
||||
#else
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIBRARY_LOG_NAME ( "NET" )
|
||||
#include "iot_logging_setup.h"
|
||||
|
||||
/* Provide a default value for socket timeout and network task parameters. */
|
||||
#ifndef IOT_NETWORK_SOCKET_TIMEOUT_MS
|
||||
#define IOT_NETWORK_SOCKET_TIMEOUT_MS ( 5000 )
|
||||
#endif
|
||||
#ifndef IOT_NETWORK_TASK_STACK_SIZE
|
||||
#define IOT_NETWORK_TASK_STACK_SIZE ( 2048 )
|
||||
#endif
|
||||
#ifndef IOT_NETWORK_TASK_PRIORITY
|
||||
#define IOT_NETWORK_TASK_PRIORITY ( tskIDLE_PRIORITY )
|
||||
#endif
|
||||
|
||||
/* Maximum number of simultaneous socket receive callbacks. */
|
||||
#ifndef IOT_NETWORK_MAX_RECEIVE_CALLBACKS
|
||||
#define IOT_NETWORK_MAX_RECEIVE_CALLBACKS ( 2 )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum length of a DNS name.
|
||||
*
|
||||
* Per https://tools.ietf.org/html/rfc1035, 253 is the maximum string length
|
||||
* of a DNS name.
|
||||
*/
|
||||
#define MAX_DNS_NAME_LENGTH ( 253 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Internal network context.
|
||||
*/
|
||||
typedef struct _networkConnection
|
||||
{
|
||||
Socket_t socket; /**< @brief FreeRTOS+TCP sockets handle. */
|
||||
SemaphoreHandle_t socketMutex; /**< @brief Prevents concurrent threads from using a socket. */
|
||||
StaticSemaphore_t socketMutexStorage; /**< @brief Storage space for socketMutex. */
|
||||
IotNetworkReceiveCallback_t receiveCallback; /**< @brief Network receive callback, if any. */
|
||||
void * pReceiveContext; /**< @brief The context for the receive callback. */
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
BaseType_t secured; /**< @brief Flag that marks a connection as secured. */
|
||||
|
||||
/**
|
||||
* @brief Secured connection context. Valid if `secured` is `pdTRUE`.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
mbedtls_ssl_config config; /**< @brief SSL connection configuration. */
|
||||
mbedtls_ssl_context context; /**< @brief SSL connection context */
|
||||
mbedtls_x509_crt_profile certProfile; /**< @brief Certificate security profile for this connection. */
|
||||
mbedtls_x509_crt rootCa; /**< @brief Root CA certificate context. */
|
||||
mbedtls_x509_crt clientCert; /**< @brief Client certificate context. */
|
||||
mbedtls_pk_context privKey; /**< @brief Client private key context. */
|
||||
} ssl;
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
} _networkConnection_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
|
||||
/**
|
||||
* @brief mbed TLS entropy context for generation of random numbers.
|
||||
*/
|
||||
static mbedtls_entropy_context _entropyContext;
|
||||
|
||||
/**
|
||||
* @brief mbed TLS CTR DRBG context for generation of random numbers.
|
||||
*/
|
||||
static mbedtls_ctr_drbg_context _ctrDrgbContext;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Handle of the network task.
|
||||
*/
|
||||
static TaskHandle_t _networkTaskHandle;
|
||||
|
||||
/**
|
||||
* @brief Socket set for the network task.
|
||||
*/
|
||||
static SocketSet_t _socketSet;
|
||||
|
||||
/**
|
||||
* @brief Connections in _socketSet.
|
||||
*/
|
||||
static _networkConnection_t * _connections[ IOT_NETWORK_MAX_RECEIVE_CALLBACKS ];
|
||||
|
||||
/**
|
||||
* @brief An #IotNetworkInterface_t that uses the functions in this file.
|
||||
*/
|
||||
const IotNetworkInterface_t IotNetworkFreeRTOS =
|
||||
{
|
||||
.create = IotNetworkFreeRTOS_Create,
|
||||
.setReceiveCallback = IotNetworkFreeRTOS_SetReceiveCallback,
|
||||
.send = IotNetworkFreeRTOS_Send,
|
||||
.receive = IotNetworkFreeRTOS_Receive,
|
||||
.receiveUpto = IotNetworkFreeRTOS_ReceiveUpto,
|
||||
.close = IotNetworkFreeRTOS_Close,
|
||||
.destroy = IotNetworkFreeRTOS_Destroy
|
||||
};
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
|
||||
/**
|
||||
* @brief Initialize the mbed TLS structures in a network connection.
|
||||
*
|
||||
* @param[in] pNetworkConnection The network connection to initialize.
|
||||
*/
|
||||
static void _sslContextInit( _networkConnection_t * pNetworkConnection )
|
||||
{
|
||||
mbedtls_ssl_config_init( &( pNetworkConnection->ssl.config ) );
|
||||
mbedtls_x509_crt_init( &( pNetworkConnection->ssl.rootCa ) );
|
||||
mbedtls_pk_init( &( pNetworkConnection->ssl.privKey ) );
|
||||
mbedtls_x509_crt_init( &( pNetworkConnection->ssl.clientCert ) );
|
||||
mbedtls_ssl_init( &( pNetworkConnection->ssl.context ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Free the mbed TLS structures in a network connection.
|
||||
*
|
||||
* @param[in] pNetworkConnection The network connection with the contexts to free.
|
||||
*/
|
||||
static void _sslContextFree( _networkConnection_t * pNetworkConnection )
|
||||
{
|
||||
mbedtls_ssl_free( &( pNetworkConnection->ssl.context ) );
|
||||
mbedtls_x509_crt_free( &( pNetworkConnection->ssl.rootCa ) );
|
||||
mbedtls_x509_crt_free( &( pNetworkConnection->ssl.clientCert ) );
|
||||
mbedtls_pk_free( &( pNetworkConnection->ssl.privKey ) );
|
||||
mbedtls_ssl_config_free( &( pNetworkConnection->ssl.config ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Set up TLS on a TCP connection.
|
||||
*
|
||||
* @param[in] pNetworkConnection An established TCP connection.
|
||||
* @param[in] pServerName Remote host name, used for server name indication.
|
||||
* @param[in] pCredentials TLS setup parameters.
|
||||
*
|
||||
* @return #IOT_NETWORK_SUCCESS, #IOT_NETWORK_FAILURE, #IOT_NETWORK_NO_MEMORY,
|
||||
* or #IOT_NETWORK_SYSTEM_ERROR.
|
||||
*/
|
||||
static IotNetworkError_t _tlsSetup( _networkConnection_t * pNetworkConnection,
|
||||
const char * pServerName,
|
||||
IotNetworkCredentials_t pCredentials )
|
||||
{
|
||||
IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS );
|
||||
int mbedtlsError = 0;
|
||||
|
||||
/* Initialize the mbed TLS context structures. */
|
||||
_sslContextInit( pNetworkConnection );
|
||||
|
||||
mbedtlsError = mbedtls_ssl_config_defaults( &( pNetworkConnection->ssl.config ),
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to set default SSL configuration, error %d.", mbedtlsError );
|
||||
|
||||
/* Per mbed TLS docs, mbedtls_ssl_config_defaults only fails on memory allocation. */
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_NO_MEMORY );
|
||||
}
|
||||
|
||||
/* Set up the certificate security profile, starting from the default value. */
|
||||
pNetworkConnection->ssl.certProfile = mbedtls_x509_crt_profile_default;
|
||||
|
||||
/* test.mosquitto.org only provides a 1024-bit RSA certificate, which is
|
||||
* not acceptable by the default mbed TLS certificate security profile.
|
||||
* For the purposes of this demo, allow the use of 1024-bit RSA certificates.
|
||||
* This block should be removed otherwise. */
|
||||
if( strncmp( pServerName, "test.mosquitto.org", strlen( pServerName ) ) == 0 )
|
||||
{
|
||||
pNetworkConnection->ssl.certProfile.rsa_min_bitlen = 1024;
|
||||
}
|
||||
|
||||
/* Set SSL authmode and the RNG context. */
|
||||
mbedtls_ssl_conf_authmode( &( pNetworkConnection->ssl.config ),
|
||||
MBEDTLS_SSL_VERIFY_REQUIRED );
|
||||
mbedtls_ssl_conf_rng( &( pNetworkConnection->ssl.config ),
|
||||
mbedtls_ctr_drbg_random,
|
||||
&_ctrDrgbContext );
|
||||
mbedtls_ssl_conf_cert_profile( &( pNetworkConnection->ssl.config ),
|
||||
&( pNetworkConnection->ssl.certProfile ) );
|
||||
|
||||
/* Parse the server root CA certificate into the SSL context. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkConnection->ssl.rootCa ),
|
||||
( const unsigned char * ) pCredentials->pRootCa,
|
||||
pCredentials->rootCaSize );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to parse server root CA certificate, error %d.",
|
||||
mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_ca_chain( &( pNetworkConnection->ssl.config ),
|
||||
&( pNetworkConnection->ssl.rootCa ),
|
||||
NULL );
|
||||
|
||||
if( ( pCredentials->pPrivateKey != NULL ) && ( pCredentials->pClientCert != NULL ) )
|
||||
{
|
||||
/* Setup the client private key. */
|
||||
mbedtlsError = mbedtls_pk_parse_key( &( pNetworkConnection->ssl.privKey ),
|
||||
( const unsigned char * ) pCredentials->pPrivateKey,
|
||||
pCredentials->privateKeySize,
|
||||
0,
|
||||
0 );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to parse client certificate, error %d.",
|
||||
mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
/* Setup the client certificate. */
|
||||
mbedtlsError = mbedtls_x509_crt_parse( &( pNetworkConnection->ssl.clientCert ),
|
||||
( const unsigned char * ) pCredentials->pClientCert,
|
||||
pCredentials->clientCertSize );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to parse the client private key, error %d.",
|
||||
mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_own_cert( &( pNetworkConnection->ssl.config ),
|
||||
&( pNetworkConnection->ssl.clientCert ),
|
||||
&( pNetworkConnection->ssl.privKey ) );
|
||||
}
|
||||
|
||||
/* Initialize the mbed TLS secured connection context. */
|
||||
mbedtlsError = mbedtls_ssl_setup( &( pNetworkConnection->ssl.context ),
|
||||
&( pNetworkConnection->ssl.config ) );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to set up mbed TLS SSL context, error %d.",
|
||||
mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
/* Set the underlying IO for the TLS connection. */
|
||||
mbedtls_ssl_set_bio( &( pNetworkConnection->ssl.context ),
|
||||
pNetworkConnection->socket,
|
||||
mbedtls_platform_send,
|
||||
mbedtls_platform_recv,
|
||||
NULL );
|
||||
|
||||
/* Enable SNI if requested. */
|
||||
if( pCredentials->disableSni == false )
|
||||
{
|
||||
mbedtlsError = mbedtls_ssl_set_hostname( &( pNetworkConnection->ssl.context ),
|
||||
pServerName );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to set server name, error %d.", mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the TLS handshake. */
|
||||
do
|
||||
{
|
||||
mbedtlsError = mbedtls_ssl_handshake( &( pNetworkConnection->ssl.context ) );
|
||||
} while( ( mbedtlsError == MBEDTLS_ERR_SSL_WANT_READ ) ||
|
||||
( mbedtlsError == MBEDTLS_ERR_SSL_WANT_WRITE ) );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to perform TLS handshake, error %d.", mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_FAILURE );
|
||||
}
|
||||
|
||||
/* Clean up on error. */
|
||||
IOT_FUNCTION_CLEANUP_BEGIN();
|
||||
|
||||
if( status != IOT_NETWORK_SUCCESS )
|
||||
{
|
||||
_sslContextFree( pNetworkConnection );
|
||||
}
|
||||
else
|
||||
{
|
||||
pNetworkConnection->secured = pdTRUE;
|
||||
|
||||
IotLogInfo( "(Network connection %p) TLS handshake successful.",
|
||||
pNetworkConnection );
|
||||
}
|
||||
|
||||
IOT_FUNCTION_CLEANUP_END();
|
||||
}
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void _networkTask( void * pvParameters )
|
||||
{
|
||||
_networkConnection_t * pConnection = NULL;
|
||||
BaseType_t socketEvents = 0, i = 0, socketStatus = 0;
|
||||
SocketSet_t socketSet = pvParameters;
|
||||
|
||||
while( true )
|
||||
{
|
||||
socketEvents = FreeRTOS_select( socketSet, IOT_NETWORK_SOCKET_TIMEOUT_MS );
|
||||
|
||||
if( socketEvents > 0 )
|
||||
{
|
||||
for( i = 0; i < IOT_NETWORK_MAX_RECEIVE_CALLBACKS; i++ )
|
||||
{
|
||||
pConnection = _connections[ i ];
|
||||
|
||||
if( pConnection != NULL )
|
||||
{
|
||||
socketStatus = FreeRTOS_FD_ISSET( pConnection->socket, socketSet );
|
||||
|
||||
if( socketStatus & eSELECT_READ )
|
||||
{
|
||||
/* A receive callback must be set; otherwise, select should not
|
||||
* have returned this socket. */
|
||||
configASSERT( pConnection->receiveCallback != NULL );
|
||||
|
||||
pConnection->receiveCallback( pConnection,
|
||||
pConnection->pReceiveContext );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This task will receive a notification when cleanup is called. Exit when
|
||||
* cleanup is called. */
|
||||
if( ulTaskNotifyTake( pdTRUE, 0 ) != 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreeRTOS_DeleteSocketSet( socketSet );
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Init( void )
|
||||
{
|
||||
IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS );
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
int mbedtlsError = 0;
|
||||
|
||||
/* Set the mutex functions for mbed TLS thread safety. */
|
||||
mbedtls_threading_set_alt( mbedtls_platform_mutex_init,
|
||||
mbedtls_platform_mutex_free,
|
||||
mbedtls_platform_mutex_lock,
|
||||
mbedtls_platform_mutex_unlock );
|
||||
|
||||
/* Initialize contexts for random number generation. */
|
||||
mbedtls_entropy_init( &_entropyContext );
|
||||
mbedtls_ctr_drbg_init( &_ctrDrgbContext );
|
||||
|
||||
/* Add a strong entropy source. At least one is required. */
|
||||
mbedtlsError = mbedtls_entropy_add_source( &_entropyContext,
|
||||
mbedtls_platform_entropy_poll,
|
||||
NULL,
|
||||
32,
|
||||
MBEDTLS_ENTROPY_SOURCE_STRONG );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to add entropy source, error %d.", mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_FAILURE );
|
||||
}
|
||||
|
||||
/* Seed the random number generator. */
|
||||
mbedtlsError = mbedtls_ctr_drbg_seed( &_ctrDrgbContext,
|
||||
mbedtls_entropy_func,
|
||||
&_entropyContext,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if( mbedtlsError != 0 )
|
||||
{
|
||||
IotLogError( "Failed to seed PRNG, error %d.", mbedtlsError );
|
||||
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_FAILURE );
|
||||
}
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
|
||||
/* Create socket set for network task. */
|
||||
_socketSet = FreeRTOS_CreateSocketSet();
|
||||
|
||||
if( _socketSet == NULL )
|
||||
{
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_FAILURE );
|
||||
}
|
||||
|
||||
static StaticTask_t networkTask;
|
||||
static StackType_t networkTaskStack[ IOT_NETWORK_TASK_STACK_SIZE ];
|
||||
|
||||
/* Create the network task. Since valid parameters are provided, this should
|
||||
* never fail. */
|
||||
_networkTaskHandle = xTaskCreateStatic( _networkTask,
|
||||
"Network",
|
||||
IOT_NETWORK_TASK_STACK_SIZE,
|
||||
_socketSet,
|
||||
IOT_NETWORK_TASK_PRIORITY,
|
||||
( StackType_t * const ) &networkTaskStack,
|
||||
&networkTask );
|
||||
configASSERT( _networkTaskHandle != NULL );
|
||||
|
||||
IotLogInfo( "Network successfully initialized." );
|
||||
|
||||
IOT_FUNCTION_EXIT_NO_CLEANUP();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotNetworkFreeRTOS_Cleanup( void )
|
||||
{
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
/* Free the contexts for random number generation. */
|
||||
mbedtls_ctr_drbg_free( &_ctrDrgbContext );
|
||||
mbedtls_entropy_free( &_entropyContext );
|
||||
|
||||
/* Clear the mutex functions for mbed TLS thread safety. */
|
||||
mbedtls_threading_free_alt();
|
||||
#endif
|
||||
|
||||
xTaskNotifyGive( _networkTaskHandle );
|
||||
|
||||
IotLogInfo( "Network cleanup done." );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Create( IotNetworkServerInfo_t pServerInfo,
|
||||
IotNetworkCredentials_t pCredentialInfo,
|
||||
IotNetworkConnection_t * pConnection )
|
||||
{
|
||||
IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS );
|
||||
Socket_t tcpSocket = FREERTOS_INVALID_SOCKET;
|
||||
BaseType_t socketStatus = 0;
|
||||
struct freertos_sockaddr serverAddress = { 0 };
|
||||
const TickType_t receiveTimeout = pdMS_TO_TICKS( IOT_NETWORK_SOCKET_TIMEOUT_MS );
|
||||
_networkConnection_t * pNewNetworkConnection = NULL;
|
||||
|
||||
/* Credentials are not used if TLS is disabled. */
|
||||
( void ) pCredentialInfo;
|
||||
|
||||
/* Check host name length against the maximum length allowed. */
|
||||
const size_t hostnameLength = strlen( pServerInfo->pHostName );
|
||||
|
||||
if( hostnameLength > ( size_t ) MAX_DNS_NAME_LENGTH )
|
||||
{
|
||||
IotLogError( "Host name length exceeds %d, which is the maximum allowed.",
|
||||
MAX_DNS_NAME_LENGTH );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_BAD_PARAMETER );
|
||||
}
|
||||
|
||||
pNewNetworkConnection = pvPortMalloc( sizeof( _networkConnection_t ) );
|
||||
|
||||
if( pNewNetworkConnection == NULL )
|
||||
{
|
||||
IotLogError( "Failed to allocate memory for new network connection." );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_NO_MEMORY );
|
||||
}
|
||||
|
||||
/* Clear the connection information. */
|
||||
( void ) memset( pNewNetworkConnection, 0x00, sizeof( _networkConnection_t ) );
|
||||
|
||||
/* Create a new TCP socket. */
|
||||
tcpSocket = FreeRTOS_socket( FREERTOS_AF_INET,
|
||||
FREERTOS_SOCK_STREAM,
|
||||
FREERTOS_IPPROTO_TCP );
|
||||
|
||||
if( tcpSocket == FREERTOS_INVALID_SOCKET )
|
||||
{
|
||||
IotLogError( "Failed to create new socket." );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
/* Set the timeout for receive. */
|
||||
socketStatus = FreeRTOS_setsockopt( tcpSocket,
|
||||
0,
|
||||
FREERTOS_SO_RCVTIMEO,
|
||||
&receiveTimeout,
|
||||
sizeof( TickType_t ) );
|
||||
|
||||
if( socketStatus != 0 )
|
||||
{
|
||||
IotLogError( "Failed to set socket receive timeout." );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
/* Establish connection. */
|
||||
serverAddress.sin_family = FREERTOS_AF_INET;
|
||||
serverAddress.sin_port = FreeRTOS_htons( pServerInfo->port );
|
||||
serverAddress.sin_addr = FreeRTOS_gethostbyname( pServerInfo->pHostName );
|
||||
serverAddress.sin_len = ( uint8_t ) sizeof( serverAddress );
|
||||
|
||||
/* Check for errors from DNS lookup. */
|
||||
if( serverAddress.sin_addr == 0 )
|
||||
{
|
||||
IotLogError( "Failed to resolve %s.", pServerInfo->pHostName );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
socketStatus = FreeRTOS_connect( tcpSocket,
|
||||
&serverAddress,
|
||||
sizeof( serverAddress ) );
|
||||
|
||||
if( socketStatus != 0 )
|
||||
{
|
||||
IotLogError( "Failed to establish new connection. Socket status %d.", socketStatus );
|
||||
IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR );
|
||||
}
|
||||
|
||||
/* Set the socket. */
|
||||
pNewNetworkConnection->socket = tcpSocket;
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
/* Set up TLS if credentials are provided. */
|
||||
if( pCredentialInfo != NULL )
|
||||
{
|
||||
status = _tlsSetup( pNewNetworkConnection,
|
||||
pServerInfo->pHostName,
|
||||
pCredentialInfo );
|
||||
}
|
||||
#endif
|
||||
|
||||
IOT_FUNCTION_CLEANUP_BEGIN();
|
||||
|
||||
/* Clean up on failure. */
|
||||
if( status != IOT_NETWORK_SUCCESS )
|
||||
{
|
||||
if( tcpSocket != FREERTOS_INVALID_SOCKET )
|
||||
{
|
||||
FreeRTOS_closesocket( tcpSocket );
|
||||
}
|
||||
|
||||
/* Clear the connection information. */
|
||||
if( pNewNetworkConnection != NULL )
|
||||
{
|
||||
vPortFree( pNewNetworkConnection );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create the socket mutex. */
|
||||
pNewNetworkConnection->socketMutex = xSemaphoreCreateMutexStatic( &( pNewNetworkConnection->socketMutexStorage ) );
|
||||
|
||||
/* Set the output parameter. */
|
||||
*pConnection = pNewNetworkConnection;
|
||||
|
||||
IotLogInfo( "(Network connection %p) Connection to %s established.",
|
||||
pNewNetworkConnection,
|
||||
pServerInfo->pHostName );
|
||||
}
|
||||
|
||||
IOT_FUNCTION_CLEANUP_END();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotNetworkError_t IotNetworkFreeRTOS_SetReceiveCallback( IotNetworkConnection_t pConnection,
|
||||
IotNetworkReceiveCallback_t receiveCallback,
|
||||
void * pContext )
|
||||
{
|
||||
IotNetworkError_t status = IOT_NETWORK_SUCCESS;
|
||||
BaseType_t i = 0;
|
||||
|
||||
/* Set the receive callback and context. */
|
||||
pConnection->receiveCallback = receiveCallback;
|
||||
pConnection->pReceiveContext = pContext;
|
||||
|
||||
/* Add this connection to the list of connections that select should check. */
|
||||
for( i = 0; i < IOT_NETWORK_MAX_RECEIVE_CALLBACKS; i++ )
|
||||
{
|
||||
if( Atomic_CompareAndSwapPointers_p32( &_connections[ i ],
|
||||
pConnection,
|
||||
NULL ) == 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i == IOT_NETWORK_MAX_RECEIVE_CALLBACKS )
|
||||
{
|
||||
status = IOT_NETWORK_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add this socket to the socket set for the network task. */
|
||||
FreeRTOS_FD_SET( pConnection->socket,
|
||||
_socketSet,
|
||||
eSELECT_READ );
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t IotNetworkFreeRTOS_Send( IotNetworkConnection_t pConnection,
|
||||
const uint8_t * pMessage,
|
||||
size_t messageLength )
|
||||
{
|
||||
size_t bytesSent = 0;
|
||||
BaseType_t socketStatus = 0;
|
||||
|
||||
/* Only one thread at a time may send on the connection. Lock the send
|
||||
* mutex to prevent other threads from sending. */
|
||||
if( xSemaphoreTake( pConnection->socketMutex,
|
||||
IOT_NETWORK_SOCKET_TIMEOUT_MS ) == pdTRUE )
|
||||
{
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
if( pConnection->secured == pdTRUE )
|
||||
{
|
||||
while( bytesSent < messageLength )
|
||||
{
|
||||
socketStatus = ( BaseType_t ) mbedtls_ssl_write( &( pConnection->ssl.context ),
|
||||
pMessage + bytesSent,
|
||||
messageLength - bytesSent );
|
||||
|
||||
if( ( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_WRITE ) ||
|
||||
( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_READ ) )
|
||||
{
|
||||
/* Try again for WANT_WRITE and WANT_READ errors. */
|
||||
continue;
|
||||
}
|
||||
else if( socketStatus < 0 )
|
||||
{
|
||||
/* Exit on other errors. */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesSent += ( size_t ) socketStatus;
|
||||
configASSERT( bytesSent <= messageLength );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
{
|
||||
socketStatus = FreeRTOS_send( pConnection->socket,
|
||||
pMessage,
|
||||
messageLength,
|
||||
0 );
|
||||
}
|
||||
|
||||
if( socketStatus > 0 )
|
||||
{
|
||||
bytesSent = ( size_t ) socketStatus;
|
||||
}
|
||||
|
||||
xSemaphoreGive( pConnection->socketMutex );
|
||||
}
|
||||
|
||||
IotLogDebug( "(Network connection %p) Sent %lu bytes.",
|
||||
pConnection,
|
||||
( unsigned long ) bytesSent );
|
||||
|
||||
return bytesSent;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t IotNetworkFreeRTOS_Receive( IotNetworkConnection_t pConnection,
|
||||
uint8_t * pBuffer,
|
||||
size_t bytesRequested )
|
||||
{
|
||||
BaseType_t socketStatus = 0;
|
||||
size_t bytesReceived = 0, bytesRemaining = bytesRequested;
|
||||
|
||||
/* Block and wait for incoming data. */
|
||||
while( bytesRemaining > 0 )
|
||||
{
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
if( pConnection->secured == pdTRUE )
|
||||
{
|
||||
if( xSemaphoreTake( pConnection->socketMutex,
|
||||
IOT_NETWORK_SOCKET_TIMEOUT_MS ) == pdTRUE )
|
||||
{
|
||||
socketStatus = ( BaseType_t ) mbedtls_ssl_read( &( pConnection->ssl.context ),
|
||||
pBuffer + bytesReceived,
|
||||
bytesRequested - bytesReceived );
|
||||
|
||||
xSemaphoreGive( pConnection->socketMutex );
|
||||
|
||||
if( ( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_READ ) ||
|
||||
( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_WRITE ) )
|
||||
{
|
||||
/* Try again for WANT_WRITE and WANT_READ errors. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Could not obtain socket mutex, exit. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
{
|
||||
socketStatus = FreeRTOS_recv( pConnection->socket,
|
||||
pBuffer + bytesReceived,
|
||||
bytesRemaining,
|
||||
0 );
|
||||
|
||||
if( socketStatus == FREERTOS_EWOULDBLOCK )
|
||||
{
|
||||
/* The return value EWOULDBLOCK means no data was received within
|
||||
* the socket timeout. Ignore it and try again. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( socketStatus < 0 )
|
||||
{
|
||||
IotLogError( "Error %ld while receiving data.", ( long int ) socketStatus );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesReceived += ( size_t ) socketStatus;
|
||||
bytesRemaining -= ( size_t ) socketStatus;
|
||||
|
||||
configASSERT( bytesReceived + bytesRemaining == bytesRequested );
|
||||
}
|
||||
}
|
||||
|
||||
if( bytesReceived < bytesRequested )
|
||||
{
|
||||
IotLogWarn( "(Network connection %p) Receive requested %lu bytes, but %lu bytes received instead.",
|
||||
pConnection,
|
||||
( unsigned long ) bytesRequested,
|
||||
( unsigned long ) bytesReceived );
|
||||
}
|
||||
else
|
||||
{
|
||||
IotLogDebug( "(Network connection %p) Successfully received %lu bytes.",
|
||||
pConnection,
|
||||
( unsigned long ) bytesRequested );
|
||||
}
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t IotNetworkFreeRTOS_ReceiveUpto( IotNetworkConnection_t pConnection,
|
||||
uint8_t * pBuffer,
|
||||
size_t bufferSize )
|
||||
{
|
||||
int32_t socketStatus = 0;
|
||||
size_t bytesReceived = 0;
|
||||
|
||||
/* Caller should never pass a zero-length buffer. */
|
||||
configASSERT( bufferSize > 0 );
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
if( pConnection->secured == pdTRUE )
|
||||
{
|
||||
if( xSemaphoreTake( pConnection->socketMutex,
|
||||
IOT_NETWORK_SOCKET_TIMEOUT_MS ) == pdTRUE )
|
||||
{
|
||||
do
|
||||
{
|
||||
socketStatus = ( BaseType_t ) mbedtls_ssl_read( &( pConnection->ssl.context ),
|
||||
pBuffer + bytesReceived,
|
||||
bufferSize - bytesReceived );
|
||||
} while( ( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_READ ) ||
|
||||
( socketStatus == ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_WRITE ) );
|
||||
|
||||
xSemaphoreGive( pConnection->socketMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
IotLogError( "Could not obtain the socket mutex." );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
{
|
||||
socketStatus = FreeRTOS_recv( pConnection->socket,
|
||||
pBuffer + bytesReceived,
|
||||
bufferSize - bytesReceived,
|
||||
0 );
|
||||
}
|
||||
|
||||
if( socketStatus <= 0 )
|
||||
{
|
||||
IotLogError( "Error %ld while receiving data.", ( long int ) socketStatus );
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesReceived += ( size_t ) socketStatus;
|
||||
}
|
||||
|
||||
IotLogDebug( "Received %lu bytes.",
|
||||
( unsigned long ) bytesReceived );
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Close( IotNetworkConnection_t pConnection )
|
||||
{
|
||||
BaseType_t socketStatus = 0, i = 0;
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
/* Notify the peer that the TLS connection is being closed. */
|
||||
if( pConnection->secured == pdTRUE )
|
||||
{
|
||||
if( xSemaphoreTake( pConnection->socketMutex,
|
||||
IOT_NETWORK_SOCKET_TIMEOUT_MS ) == pdTRUE )
|
||||
{
|
||||
socketStatus = ( BaseType_t ) mbedtls_ssl_close_notify( &( pConnection->ssl.context ) );
|
||||
|
||||
/* Ignore the WANT_READ and WANT_WRITE return values. */
|
||||
if( ( socketStatus != ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_READ ) &&
|
||||
( socketStatus != ( BaseType_t ) MBEDTLS_ERR_SSL_WANT_WRITE ) )
|
||||
{
|
||||
if( socketStatus == 0 )
|
||||
{
|
||||
IotLogInfo( "(Network connection %p) TLS close-notify sent.",
|
||||
pConnection );
|
||||
}
|
||||
else
|
||||
{
|
||||
IotLogWarn( "(Network connection %p) Failed to send TLS close-notify, error %d.",
|
||||
pConnection,
|
||||
socketStatus );
|
||||
}
|
||||
}
|
||||
|
||||
xSemaphoreGive( pConnection->socketMutex );
|
||||
}
|
||||
}
|
||||
#endif /* if ( IOT_NETWORK_ENABLE_TLS == 1 ) */
|
||||
|
||||
/* Call socket shutdown function to close connection. */
|
||||
socketStatus = FreeRTOS_shutdown( pConnection->socket,
|
||||
FREERTOS_SHUT_RDWR );
|
||||
|
||||
if( socketStatus != 0 )
|
||||
{
|
||||
IotLogWarn( "(Network connection %p) Failed to close connection.",
|
||||
pConnection );
|
||||
}
|
||||
else
|
||||
{
|
||||
IotLogInfo( "(Network connection %p) Connection closed.",
|
||||
pConnection );
|
||||
}
|
||||
|
||||
/* Remove this connection from Select's socket set (if present). */
|
||||
for( i = 0; i < IOT_NETWORK_MAX_RECEIVE_CALLBACKS; i++ )
|
||||
{
|
||||
if( Atomic_CompareAndSwapPointers_p32( &_connections[ i ], NULL, pConnection ) == 1 )
|
||||
{
|
||||
FreeRTOS_FD_CLR( pConnection->socket, _socketSet, eSELECT_ALL );
|
||||
}
|
||||
}
|
||||
|
||||
return IOT_NETWORK_SUCCESS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
IotNetworkError_t IotNetworkFreeRTOS_Destroy( IotNetworkConnection_t pConnection )
|
||||
{
|
||||
FreeRTOS_closesocket( pConnection->socket );
|
||||
|
||||
#if ( IOT_NETWORK_ENABLE_TLS == 1 )
|
||||
/* Free mbed TLS contexts. */
|
||||
if( pConnection->secured == pdTRUE )
|
||||
{
|
||||
_sslContextFree( pConnection );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free memory used by network connection. */
|
||||
vPortFree( pConnection );
|
||||
|
||||
IotLogInfo( "(Network connection %p) Connection destroyed.",
|
||||
pConnection );
|
||||
|
||||
return IOT_NETWORK_SUCCESS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Amazon FreeRTOS Platform V1.1.0
|
||||
* Copyright (C) 2019 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_threads_freertos.c
|
||||
* @brief Implementation of the platform specific functions in iot_threads.h for
|
||||
* FreeRTOS.
|
||||
*/
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
#include "semphr.h"
|
||||
|
||||
/* Platform threads include. */
|
||||
#include "platform/iot_platform_types_freertos.h"
|
||||
#include "platform/iot_threads.h"
|
||||
#include "types/iot_platform_types.h"
|
||||
|
||||
/* Configure logs for the functions in this file. */
|
||||
#ifdef IOT_LOG_LEVEL_PLATFORM
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_PLATFORM
|
||||
#else
|
||||
#ifdef IOT_LOG_LEVEL_GLOBAL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
|
||||
#else
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIBRARY_LOG_NAME ( "THREAD" )
|
||||
#include "iot_logging_setup.h"
|
||||
|
||||
/*
|
||||
* Provide default values for undefined memory allocation functions based on
|
||||
* the usage of dynamic memory allocation.
|
||||
*/
|
||||
#ifndef IotThreads_Malloc
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Memory allocation. This function should have the same signature
|
||||
* as [malloc](http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html).
|
||||
*/
|
||||
#define IotThreads_Malloc malloc
|
||||
#endif
|
||||
#ifndef IotThreads_Free
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Free memory. This function should have the same signature as
|
||||
* [free](http://pubs.opengroup.org/onlinepubs/9699919799/functions/free.html).
|
||||
*/
|
||||
#define IotThreads_Free free
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void _threadRoutineWrapper( void * pArgument )
|
||||
{
|
||||
threadInfo_t * pThreadInfo = ( threadInfo_t * ) pArgument;
|
||||
|
||||
/* Run the thread routine. */
|
||||
pThreadInfo->threadRoutine( pThreadInfo->pArgument );
|
||||
IotThreads_Free( pThreadInfo );
|
||||
|
||||
vTaskDelete( NULL );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool Iot_CreateDetachedThread( IotThreadRoutine_t threadRoutine,
|
||||
void * pArgument,
|
||||
int32_t priority,
|
||||
size_t stackSize )
|
||||
{
|
||||
bool status = true;
|
||||
|
||||
configASSERT( threadRoutine != NULL );
|
||||
|
||||
IotLogDebug( "Creating new thread." );
|
||||
threadInfo_t * pThreadInfo = IotThreads_Malloc( sizeof( threadInfo_t ) );
|
||||
|
||||
if( pThreadInfo == NULL )
|
||||
{
|
||||
IotLogDebug( "Unable to allocate memory for threadRoutine %p.", threadRoutine );
|
||||
status = false;
|
||||
}
|
||||
|
||||
/* Create the FreeRTOS task that will run the thread. */
|
||||
if( status )
|
||||
{
|
||||
pThreadInfo->threadRoutine = threadRoutine;
|
||||
pThreadInfo->pArgument = pArgument;
|
||||
|
||||
if( xTaskCreate( _threadRoutineWrapper,
|
||||
"iot_thread",
|
||||
( configSTACK_DEPTH_TYPE ) stackSize,
|
||||
pThreadInfo,
|
||||
priority,
|
||||
NULL ) != pdPASS )
|
||||
{
|
||||
/* Task creation failed. */
|
||||
IotLogWarn( "Failed to create thread." );
|
||||
IotThreads_Free( pThreadInfo );
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotMutex_Create( IotMutex_t * pNewMutex,
|
||||
bool recursive )
|
||||
{
|
||||
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pNewMutex;
|
||||
|
||||
configASSERT( internalMutex != NULL );
|
||||
|
||||
IotLogDebug( "Creating new mutex %p.", pNewMutex );
|
||||
|
||||
if( recursive )
|
||||
{
|
||||
( void ) xSemaphoreCreateRecursiveMutexStatic( &internalMutex->xMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
( void ) xSemaphoreCreateMutexStatic( &internalMutex->xMutex );
|
||||
}
|
||||
|
||||
/* remember the type of mutex */
|
||||
if( recursive )
|
||||
{
|
||||
internalMutex->recursive = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
internalMutex->recursive = pdFALSE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotMutex_Destroy( IotMutex_t * pMutex )
|
||||
{
|
||||
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
|
||||
|
||||
configASSERT( internalMutex != NULL );
|
||||
|
||||
vSemaphoreDelete( ( SemaphoreHandle_t ) &internalMutex->xMutex );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool prIotMutexTimedLock( IotMutex_t * pMutex,
|
||||
TickType_t timeout )
|
||||
{
|
||||
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
|
||||
BaseType_t lockResult;
|
||||
|
||||
configASSERT( internalMutex != NULL );
|
||||
|
||||
IotLogDebug( "Locking mutex %p.", internalMutex );
|
||||
|
||||
/* Call the correct FreeRTOS mutex take function based on mutex type. */
|
||||
if( internalMutex->recursive == pdTRUE )
|
||||
{
|
||||
lockResult = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout );
|
||||
}
|
||||
else
|
||||
{
|
||||
lockResult = xSemaphoreTake( ( SemaphoreHandle_t ) &internalMutex->xMutex, timeout );
|
||||
}
|
||||
|
||||
return( lockResult == pdTRUE );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotMutex_Lock( IotMutex_t * pMutex )
|
||||
{
|
||||
prIotMutexTimedLock( pMutex, portMAX_DELAY );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotMutex_TryLock( IotMutex_t * pMutex )
|
||||
{
|
||||
return prIotMutexTimedLock( pMutex, 0 );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotMutex_Unlock( IotMutex_t * pMutex )
|
||||
{
|
||||
_IotSystemMutex_t * internalMutex = ( _IotSystemMutex_t * ) pMutex;
|
||||
|
||||
configASSERT( internalMutex != NULL );
|
||||
|
||||
IotLogDebug( "Unlocking mutex %p.", internalMutex );
|
||||
|
||||
/* Call the correct FreeRTOS mutex unlock function based on mutex type. */
|
||||
if( internalMutex->recursive == pdTRUE )
|
||||
{
|
||||
( void ) xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) &internalMutex->xMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &internalMutex->xMutex );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotSemaphore_Create( IotSemaphore_t * pNewSemaphore,
|
||||
uint32_t initialValue,
|
||||
uint32_t maxValue )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pNewSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
IotLogDebug( "Creating new semaphore %p.", pNewSemaphore );
|
||||
|
||||
( void ) xSemaphoreCreateCountingStatic( maxValue, initialValue, &internalSemaphore->xSemaphore );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t IotSemaphore_GetCount( IotSemaphore_t * pSemaphore )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
UBaseType_t count = 0;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
count = uxSemaphoreGetCount( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
|
||||
|
||||
IotLogDebug( "Semaphore %p has count %d.", pSemaphore, count );
|
||||
|
||||
return ( uint32_t ) count;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotSemaphore_Destroy( IotSemaphore_t * pSemaphore )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
IotLogDebug( "Destroying semaphore %p.", internalSemaphore );
|
||||
|
||||
vSemaphoreDelete( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotSemaphore_Wait( IotSemaphore_t * pSemaphore )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
IotLogDebug( "Waiting on semaphore %p.", internalSemaphore );
|
||||
|
||||
/* Take the semaphore using the FreeRTOS API. */
|
||||
if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore,
|
||||
portMAX_DELAY ) != pdTRUE )
|
||||
{
|
||||
IotLogWarn( "Failed to wait on semaphore %p.",
|
||||
pSemaphore );
|
||||
|
||||
/* There is an assert here because during debugging we could falsely
|
||||
* believe that we are waiting successfully on a semaphore. */
|
||||
configASSERT( false );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotSemaphore_TryWait( IotSemaphore_t * pSemaphore )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
IotLogDebug( "Attempting to wait on semaphore %p.", internalSemaphore );
|
||||
|
||||
return IotSemaphore_TimedWait( pSemaphore, 0 );
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
bool IotSemaphore_TimedWait( IotSemaphore_t * pSemaphore,
|
||||
uint32_t timeoutMs )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
/* Take the semaphore using the FreeRTOS API. Cast the calculation to 64 bit to avoid overflows. */
|
||||
if( xSemaphoreTake( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore,
|
||||
pdMS_TO_TICKS( timeoutMs ) ) != pdTRUE )
|
||||
{
|
||||
/* Only warn if timeout > 0. */
|
||||
if( timeoutMs > 0 )
|
||||
{
|
||||
IotLogWarn( "Timeout waiting on semaphore %p.",
|
||||
internalSemaphore );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void IotSemaphore_Post( IotSemaphore_t * pSemaphore )
|
||||
{
|
||||
_IotSystemSemaphore_t * internalSemaphore = ( _IotSystemSemaphore_t * ) pSemaphore;
|
||||
|
||||
configASSERT( internalSemaphore != NULL );
|
||||
|
||||
IotLogDebug( "Posting to semaphore %p.", internalSemaphore );
|
||||
/* Give the semaphore using the FreeRTOS API. */
|
||||
BaseType_t result = xSemaphoreGive( ( SemaphoreHandle_t ) &internalSemaphore->xSemaphore );
|
||||
|
||||
if( result == pdFALSE )
|
||||
{
|
||||
IotLogDebug( "Unable to give semaphore over maximum", internalSemaphore );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* IoT Common V1.0.0
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file iot_taskpool_internal.h
|
||||
* @brief Internal header of task pool library. This header should not be included in
|
||||
* typical application code.
|
||||
*/
|
||||
|
||||
#ifndef IOT_TASKPOOL_INTERNAL_H_
|
||||
#define IOT_TASKPOOL_INTERNAL_H_
|
||||
|
||||
/* The config header is always included first. */
|
||||
#include "iot_config.h"
|
||||
|
||||
/* Task pool include. */
|
||||
#include "iot_error.h"
|
||||
#include "iot_taskpool_freertos.h"
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "timers.h"
|
||||
|
||||
/* Configure logs for TASKPOOL functions. */
|
||||
#ifdef IOT_LOG_LEVEL_TASKPOOL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_TASKPOOL
|
||||
#else
|
||||
#ifdef IOT_LOG_LEVEL_GLOBAL
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_LEVEL_GLOBAL
|
||||
#else
|
||||
#define LIBRARY_LOG_LEVEL IOT_LOG_NONE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIBRARY_LOG_NAME ( "TASKPOOL" )
|
||||
#include "iot_logging_setup.h"
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief The task pool data structure keeps track of the internal state and the signals for the dispatcher threads.
|
||||
* The task pool is a thread safe data structure.
|
||||
*
|
||||
* @warning This is a system-level data type that should not be modified or used directly in any application.
|
||||
* @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.
|
||||
*
|
||||
*/
|
||||
typedef struct _taskPool
|
||||
{
|
||||
IotDeQueue_t dispatchQueue; /**< @brief The queue for the jobs waiting to be executed. */
|
||||
IotListDouble_t timerEventsList; /**< @brief The timeouts queue for all deferred jobs waiting to be executed. */
|
||||
SemaphoreHandle_t dispatchSignal; /**< @brief The synchronization object on which threads are waiting for incoming jobs. */
|
||||
StaticSemaphore_t dispatchSignalBuffer; /**< @brief The semaphore buffer. */
|
||||
SemaphoreHandle_t xTimerEventMutex; /**< @brief The mutex for guarding the Timer Event Queue. */
|
||||
StaticSemaphore_t xTimerEventMutexBuffer; /**< @brief The buffer for statically allocating the mutex. */
|
||||
TimerHandle_t timer; /**< @brief The timer for deferred jobs. */
|
||||
StaticTimer_t timerBuffer; /**< @brief The timer buffer. */
|
||||
bool running; /**< @brief A flag to track whether the task pool is operational or should shut down. */
|
||||
} _taskPool_t;
|
||||
|
||||
/**
|
||||
* @brief Represents an operation that is subject to a timer.
|
||||
*
|
||||
* These events are queued per MQTT connection. They are sorted by their
|
||||
* expiration time.
|
||||
*/
|
||||
typedef struct _taskPoolTimerEvent
|
||||
{
|
||||
IotLink_t link; /**< @brief List link member. */
|
||||
TickType_t expirationTime; /**< @brief When this event should be processed. */
|
||||
} _taskPoolTimerEvent_t;
|
||||
|
||||
/**
|
||||
* @brief The job data structure keeps track of the user callback and context, as well as the status of the job.
|
||||
*
|
||||
* @warning This is a system-level data type that should not be modified or used directly in any application.
|
||||
* @warning This is a system-level data type that can and will change across different versions of the platform, with no regards for backward compatibility.
|
||||
*
|
||||
*/
|
||||
typedef struct _taskPoolJob
|
||||
{
|
||||
IotLink_t link; /**< @brief The link to insert the job in the dispatch queue. */
|
||||
IotTaskPoolRoutine_t userCallback; /**< @brief The user provided callback. */
|
||||
void * pUserContext; /**< @brief The user provided context. */
|
||||
IotTaskPoolJobStatus_t status; /**< @brief The status for the job. */
|
||||
_taskPoolTimerEvent_t timer; /**< @brief The timer for scheduling this job deferred. */
|
||||
} _taskPoolJob_t;
|
||||
|
||||
|
||||
#endif /* ifndef IOT_TASKPOOL_INTERNAL_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue