From 453c01efb5836eaaf92c4cd1312cced9e60463b9 Mon Sep 17 00:00:00 2001 From: gaurav-aws Date: Sun, 21 Jul 2019 22:14:13 +0000 Subject: [PATCH] Add first draft of mqtt example Note that it is still work in progress and not working as of now. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2690 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../mqtt/DemoTasks/SimpleMQTTExamples.c | 447 +++++++++++++ .../mqtt/DemoTasks/SimpleTaskPoolExamples.c | 599 ----------------- .../FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj | 26 +- .../mqtt/WIN32.vcxproj.filters | 68 +- .../Demo/FreeRTOS_IoT_Libraries/mqtt/atomic.h | 547 +++++++++++++++ .../mqtt/iot_secure_sockets_config.h | 56 ++ .../include/platform/iot_network_freertos.h | 140 ++++ .../platform/freertos/iot_network_freertos.c | 627 ++++++++++++++++++ .../freertos_plus_tcp/iot_secure_sockets.c | 342 ++++++++++ .../include/iot_secure_sockets.h | 609 +++++++++++++++++ .../iot_secure_sockets_config_defaults.h | 72 ++ .../iot_secure_sockets_wrapper_metrics.h | 43 ++ .../common/include/private/iot_lib_init.h | 33 + 13 files changed, 2986 insertions(+), 623 deletions(-) create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c delete mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleTaskPoolExamples.c create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/atomic.h create mode 100644 FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/iot_secure_sockets_config.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/include/platform/iot_network_freertos.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/iot_network_freertos.c create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/freertos_plus_tcp/iot_secure_sockets.c create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h create mode 100644 FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/include/private/iot_lib_init.h diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c new file mode 100644 index 000000000..d0c9e0b6e --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleMQTTExamples.c @@ -0,0 +1,447 @@ +/* + * FreeRTOS Kernel V10.2.1 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/* Standard inclues. */ +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* MQTT include. */ +#include "iot_mqtt.h" + +/* Platform FreeRTOS network include. */ +#include "platform/iot_network_freertos.h" + +/** + * @brief The keep-alive interval used for this example. + * + * An MQTT ping request will be sent periodically at this interval. + */ +#define mqttexampleKEEP_ALIVE_SECONDS ( 60 ) + +/** + * @brief The timeout for MQTT operations in this example. + */ +#define mqttexampleMQTT_TIMEOUT_MS ( 5000 ) + +/** + * @brief The MQTT client identifier used in this example. + */ +#define mqttexampleCLIENT_IDENTIFIER "mqttexampleclient" + +/** + * @brief Details of the MQTT broker to connect to. + * + * @note This example does not use TLS and therefore won't work with AWS IoT. + */ +#define mqttexampleMQTT_BROKER_ENDPOINT "10.60.214.105" +#define mqttexampleMQTT_BROKER_PORT 1883 + +/** + * @brief The topic to subscribe and publish to in the example. + */ +#define mqttexampleTOPIC "example/topic" + +/** + * @brief The MQTT message published in this example. + */ +#define mqttexampleMESSAGE "Hello World!" + +/** + * @brief Paramters to control the retry behaviour in case a QoS1 publish + * message gets lost. + * + * Retry every minutes up to a maximum of 5 retries. + */ +#define mqttexamplePUBLISH_RETRY_MS ( 1000 ) +#define mqttexamplePUBLISH_RETRY_LIMIT ( 5 ) + +/** + * @brief The bit which is set in the demo task's notification value from the + * disconnect callback to inform the demo task about the MQTT disconnect. + */ +#define mqttexampleDISCONNECTED_BIT ( 1UL << 0UL ) + +/** + * @brief The bit which is set in the demo task's notification value from the + * publish callback to inform the demo task about the message received from the + * MQTT broker. + */ +#define mqttexampleMESSAGE_RECEIVED_BIT ( 1UL << 1UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief The MQTT connection handle used in this example. + */ +static IotMqttConnection_t xMQTTConnection = IOT_MQTT_CONNECTION_INITIALIZER; +/*-----------------------------------------------------------*/ + +/** + * @brief The task used to demonstrate the MQTT API. + * + * @param[in] pvParameters Parmaters as passed at the time of task creation. Not + * used in this example. + */ +static void prvMQTTDemoTask( void *pvParameters ); + +/** + * @brief The callback invoked by the MQTT library when the MQTT connection gets + * disconnected. + * + * @param[in] pvCallbackContext Callback context as provided at the time of + * connect. + * @param[in] pxCallbackParams Contains the reason why the MQTT connection was + * disconnected. + */ +static void prvExample_DisconnectCallback( void * pvCallbackContext, + IotMqttCallbackParam_t * pxCallbackParams ); + +/** + * @brief The callback invoked by the MQTT library when a message is received on + * a subscribed topic from the MQTT broker. + * + * @param[in] pvCallbackContext Callback context as provided at the time of + * subscribe. + * @param[in] pxCallbackParams Contain the details about the received message - + * topic on which the message was received, the received message. + */ +static void prvExample_PublishCallback( void * pvCallbackContext, + IotMqttCallbackParam_t * pxCallbackParams ); + +/** + * @brief Connects to the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT + * and mqttexampleMQTT_BROKER_PORT. + * + * @note This example does not use TLS and therefore will not work with MQTT. + */ +static void prvMQTTConnect( void ); + +/** + * @brief Subscribes to the topic as specified in mqttexampleTOPIC. + */ +static void prvMQTTSubscribe( void ); + +/** + * @brief Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic. + */ +static void prvMQTTPublish( void ); + +/** + * @brief Unsubscribes from the mqttexampleTOPIC topic. + */ +static void prvMQTTUnsubscribe( void ); + +/** + * @brief Disconnects from the MQTT broker gracefully by sending an MQTT + * DISCONNECT message. + */ +static void prvMQTTDisconnect( void ); +/*-----------------------------------------------------------*/ + +static void prvExample_DisconnectCallback( void * pvCallbackContext, + IotMqttCallbackParam_t * pxCallbackParams ) +{ +TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext; + + /* Ensure that we initiated the disconnect. */ + configASSERT( pxCallbackParams->u.disconnectReason == IOT_MQTT_DISCONNECT_CALLED ); + + /* Inform the demo task about the disconnect. */ + xTaskNotify( xDemoTaskHandle, + mqttexampleDISCONNECTED_BIT, + eSetBits /* Set the mqttexampleDISCONNECTED_BIT in the demo task's notification value. */ + ); +} +/*-----------------------------------------------------------*/ + +static void prvExample_PublishCallback( void * pvCallbackContext, + IotMqttCallbackParam_t * pxCallbackParams ) +{ +TaskHandle_t xDemoTaskHandle = ( TaskHandle_t ) pvCallbackContext; + + /* Ensure that the message is received on the expected topic. */ + configASSERT( pxCallbackParams->u.message.info.topicNameLength == strlen( mqttexampleTOPIC ) ); + configASSERT( strncmp( pxCallbackParams->u.message.info.pTopicName, + mqttexampleTOPIC, + strlen( mqttexampleTOPIC ) ) == 0 ); + + /* Ensure that the expected message is received. */ + configASSERT( pxCallbackParams->u.message.info.payloadLength == strlen( mqttexampleMESSAGE ) ); + configASSERT( strncmp( pxCallbackParams->u.message.info.pPayload, + mqttexampleMESSAGE, + strlen( mqttexampleMESSAGE ) ) == 0 ); + + /* Ensure that the message QoS is as expected. */ + configASSERT( pxCallbackParams->u.message.info.qos == IOT_MQTT_QOS_1 ); + + /* Inform the demo task about the message received from the MQTT broker. */ + xTaskNotify( xDemoTaskHandle, + mqttexampleMESSAGE_RECEIVED_BIT, + eSetBits /* Set the mqttexampleMESSAGE_RECEIVED_BIT in the demo task's notification value. */ + ); +} +/*-----------------------------------------------------------*/ + +void vStartSimpleMQTTDemo( void ) +{ + /* This example uses a single application task, which in turn is used to + * connect, subscribe, publish, unsubscribe and disconnect from the MQTT + * broker. */ + xTaskCreate( prvMQTTDemoTask, /* Function that implements the task. */ + "MQTTDemo", /* Text name for the task - only used for debugging. */ + configMINIMAL_STACK_SIZE, /* Size of stack (in words, not bytes) to allocate for the task. */ + NULL, /* Task parameter - not used in this case. */ + tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */ + NULL ); /* Used to pass out a handle to the created task - not used in this case. */ +} +/*-----------------------------------------------------------*/ + +static void prvMQTTDemoTask( void *pvParameters ) +{ +IotMqttError_t xResult; +uint32_t ulNotificationValue = 0; +const TickType_t xNoDelay = ( TickType_t ) 0; + + /* Remove compiler warnings about unused parameters. */ + ( void ) pvParameters; + + /* MQTT library must be initialized before it can be used. This is just one + * time initialization. */ + xResult = IotMqtt_Init(); + configASSERT( xResult == IOT_MQTT_SUCCESS ); + + for( ; ; ) + { + /* Don't expect any notifications to be pending yet. */ + configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 ); + + /* Establish a connection to the MQTT broker. This example connects to + * the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT and + * mqttexampleMQTT_BROKER_PORT at the top of this file. Please change + * it to the MQTT broker you want to connect to. Note that this example + * does not use TLS and therefore will not work with AWS IoT. */ + prvMQTTConnect(); + + /* Subscribe to the topic as specified in mqttexampleTOPIC at the top + * of this file. */ + prvMQTTSubscribe(); + + /* Publish a message on the mqttexampleTOPIC topic as specified at the + * top of this file. */ + prvMQTTPublish(); + + /* Since we are subscribed on the same topic, we will get the same + * message back from the MQTT broker. Wait for the message to be + * received which is informed to us by the publish callback + * (prvExample_PublishCallback) by setting the mqttexampleMESSAGE_RECEIVED_BIT + * in this task's notification value. */ + xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ + 0UL, /* Don't clear any bits on exit. */ + &( ulNotificationValue ), /* Obtain the notification value. */ + pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) ); + configASSERT( ( ulNotificationValue & mqttexampleMESSAGE_RECEIVED_BIT ) == mqttexampleMESSAGE_RECEIVED_BIT ); + + /* Unsubscribe from the topic mqttexampleTOPIC. */ + prvMQTTUnsubscribe(); + + /* Gracefully disconnect from the MQTT broker by sending an MQTT + * DISCONNECT message. */ + prvMQTTDisconnect(); + + /* Wait for the disconnect operation to complete which is informed to us + * by the disconnect callback (prvExample_DisconnectCallback)by setting + * the mqttexampleDISCONNECTED_BIT in this task's notification value. + * Note that all bits are cleared in the task's notification value to + * ensure that it is ready for the next run. */ + xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ + portMAX_DELAY, /* Clear all bits on exit - portMAX_DELAY is used as it is a portable way of having all bits set. */ + &( ulNotificationValue ), /* Obtain the notification value. */ + pdMS_TO_TICKS( mqttexampleMQTT_TIMEOUT_MS ) ); + configASSERT( ( ulNotificationValue & mqttexampleDISCONNECTED_BIT ) == mqttexampleDISCONNECTED_BIT ); + } +} +/*-----------------------------------------------------------*/ + +static void prvMQTTConnect( void ) +{ +IotMqttError_t xResult; +IotNetworkServerInfo_t xMQTTBrokerInfo; +IotMqttNetworkInfo_t xNetworkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; +IotMqttConnectInfo_t xConnectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; + + /******************* Broker information setup. **********************/ + xMQTTBrokerInfo.pHostName = mqttexampleMQTT_BROKER_ENDPOINT; + xMQTTBrokerInfo.port = mqttexampleMQTT_BROKER_PORT; + + /******************* Network information setup. **********************/ + /* No connection to the MQTT broker has been established yet and we want to + * establish a new connection. */ + xNetworkInfo.createNetworkConnection = true; + xNetworkInfo.u.setup.pNetworkServerInfo = &( xMQTTBrokerInfo ); + + /* This example does not use TLS and therefore pNetworkCredentialInfo must + * be set to NULL. */ + xNetworkInfo.u.setup.pNetworkCredentialInfo = NULL; + + /* Use FreeRTOS+TCP network. */ + xNetworkInfo.pNetworkInterface = IOT_NETWORK_INTERFACE_AFR; + + /* Setup the callback which is called when the MQTT connection is disconnected. */ + xNetworkInfo.disconnectCallback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle(); + xNetworkInfo.disconnectCallback.function = prvExample_DisconnectCallback; + + /****************** MQTT Connection information setup. ********************/ + /* This example does not use TLS and therefore won't work with AWS IoT. */ + xConnectInfo.awsIotMqttMode = false; + + /* Start with a clean session i.e. direct the MQTT broker to discard any + * previous session data. Also, establishing a connection with clean session + * will ensure that the broker does not store any data when this client + * gets disconnected. */ + xConnectInfo.cleanSession = true; + + /* Since we are starting with a clean session, there are no previous + * subscriptions to be restored. */ + xConnectInfo.pPreviousSubscriptions = NULL; + xConnectInfo.previousSubscriptionCount = 0; + + /* We do not want to publish Last Will and Testament (LWT) message if the + * client gets disconnected. */ + xConnectInfo.pWillInfo = NULL; + + /* Send an MQTT PING request every minute. */ + xConnectInfo.keepAliveSeconds = mqttexampleKEEP_ALIVE_SECONDS; + + /* The client identifier is used to uniquely identify this MQTT client to + * the MQTT broker. */ + xConnectInfo.pClientIdentifier = mqttexampleCLIENT_IDENTIFIER; + xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( mqttexampleCLIENT_IDENTIFIER ); + + /* This example does not use any authentication and therefore username and + * password fields are not used. */ + xConnectInfo.pUserName = NULL; + xConnectInfo.userNameLength = 0; + xConnectInfo.pPassword = NULL; + xConnectInfo.passwordLength = 0; + + /* Establish the connection to the MQTT broker - It is a blocking call and + will return only when connection is complete. */ + xResult = IotMqtt_Connect( &( xNetworkInfo ), + &( xConnectInfo ), + mqttexampleMQTT_TIMEOUT_MS, + &( xMQTTConnection ) ); + configASSERT( xResult == IOT_MQTT_SUCCESS ); +} +/*-----------------------------------------------------------*/ + +static void prvMQTTSubscribe( void ) +{ +IotMqttError_t xResult; +IotMqttSubscription_t xMQTTSubscription; + + /* Subscribe to the mqttexampleTOPIC topic filter. */ + xMQTTSubscription.qos = IOT_MQTT_QOS_1; + xMQTTSubscription.pTopicFilter = mqttexampleTOPIC; + xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); + xMQTTSubscription.callback.pCallbackContext = ( void * ) xTaskGetCurrentTaskHandle(); + xMQTTSubscription.callback.function = prvExample_PublishCallback; + + /* Use the synchronous API to subscribe - It is a blocking call and only + * returns when the subscribe operation is complete. */ + xResult = IotMqtt_TimedSubscribe( xMQTTConnection, + &( xMQTTSubscription ), + 1, /* We are subscribing to one topic filter. */ + 0, /* flags - currently ignored. */ + mqttexampleMQTT_TIMEOUT_MS ); + configASSERT( xResult == IOT_MQTT_SUCCESS ); +} +/*-----------------------------------------------------------*/ + +static void prvMQTTPublish( void ) +{ +IotMqttError_t xResult; +IotMqttPublishInfo_t xMQTTPublishInfo; + + /* Publish a message with QoS1 on the mqttexampleTOPIC topic. Since we are + * subscribed to the same topic, the MQTT broker will send the same message + * back to us. It is verified in the publish callback. */ + xMQTTPublishInfo.qos = IOT_MQTT_QOS_1; + xMQTTPublishInfo.retain = false; + xMQTTPublishInfo.pTopicName = mqttexampleTOPIC; + xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC ); + xMQTTPublishInfo.pPayload = mqttexampleMESSAGE; + xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE ); + xMQTTPublishInfo.retryMs = mqttexamplePUBLISH_RETRY_MS; + xMQTTPublishInfo.retryLimit = mqttexamplePUBLISH_RETRY_LIMIT; + + /* Use the synchronous API to publish - It is a blocking call and only + * returns when the publish operation is complete. */ + xResult = IotMqtt_TimedPublish( xMQTTConnection, + &( xMQTTPublishInfo ), + 0, /* flags - currently ignored. */ + mqttexampleMQTT_TIMEOUT_MS ); + configASSERT( xResult == IOT_MQTT_SUCCESS ); +} +/*-----------------------------------------------------------*/ + +static void prvMQTTUnsubscribe( void ) +{ +IotMqttError_t xResult; +IotMqttSubscription_t xMQTTSubscription; + + /* Unsubscribe from the mqttexampleTOPIC topic filter. */ + xMQTTSubscription.pTopicFilter = mqttexampleTOPIC; + xMQTTSubscription.topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC ); + /* The following members of the IotMqttSubscription_t are ignored by the + * unsubscribe operation. Just initialize them to avoid "use of uninitialized + * variable" warnings. */ + xMQTTSubscription.qos = IOT_MQTT_QOS_1; + xMQTTSubscription.callback.pCallbackContext = NULL; + xMQTTSubscription.callback.function = NULL; + + /* Use the synchronous API to unsubscribe - It is a blocking call and only + * returns when the unsubscribe operation is complete. */ + xResult = IotMqtt_TimedUnsubscribe( xMQTTConnection, + &( xMQTTSubscription ), + 1, /* We are unsubscribing from one topic filter. */ + 0, /* flags - currently ignored. */ + mqttexampleMQTT_TIMEOUT_MS ); + configASSERT( xResult == IOT_MQTT_SUCCESS ); +} +/*-----------------------------------------------------------*/ + +static void prvMQTTDisconnect( void ) +{ + /* Send a MQTT DISCONNECT packet to the MQTT broker to do a graceful + * disconnect. */ + IotMqtt_Disconnect( xMQTTConnection, + 0 /* flags - 0 means a graceful disconnect by sending MQTT DISCONNECT. */ + ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleTaskPoolExamples.c b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleTaskPoolExamples.c deleted file mode 100644 index 49924537e..000000000 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/DemoTasks/SimpleTaskPoolExamples.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * FreeRTOS Kernel V10.2.1 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -//_RB_ Add link to docs here. - -/* Kernel includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* Standard includes. */ -#include - -/* IoT SDK includes. */ -#include "iot_taskpool.h" - -/* The priority at which that tasks in the task pool (the worker tasks) get -created. */ -#define tpTASK_POOL_WORKER_PRIORITY 1 - -/* The number of jobs created in the example functions that create more than -one job. */ -#define tpJOBS_TO_CREATE 5 - -/* - * Prototypes for the functions that demonstrate the task pool API. - * See the implementation of the prvTaskPoolDemoTask() function within this file - * for a description of the individual functions. A configASSERT() is hit if - * any of the demos encounter any unexpected behaviour. - */ -static void prvExample_BasicSingleJob( void ); -static void prvExample_DeferredJobAndCancellingJobs( void ); -static void prvExample_BasicRecyclableJob( void ); -static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void ); -static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void ); - -/* - * Prototypes of the callback functions used in the examples. The callback - * simply sends a signal (in the form of a direct task notification) to the - * prvTaskPoolDemoTask() task to let the task know that the callback execute. - * The handle of the prvTaskPoolDemoTask() task is not accessed directly, but - * instead passed into the task pool job as the job's context. - */ -static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext ); - -/* - * The task used to demonstrate the task pool API. This task just loops through - * each demo in turn. - */ -static void prvTaskPoolDemoTask( void *pvParameters ); - -/*-----------------------------------------------------------*/ - -/* Parameters used to create the system task pool - see TBD for more information -as the task pool used in this example is a slimmed down version of the full -library - the slimmed down version being intended specifically for FreeRTOS -kernel use cases. */ -static const IotTaskPoolInfo_t xTaskPoolParameters = { - /* Minimum number of threads in a task pool. - Note the slimmed down version of the task - pool used by this library does not autoscale - the number of tasks in the pool so in this - case this sets the number of tasks in the - pool. */ - 2, - /* Maximum number of threads in a task pool. - Note the slimmed down version of the task - pool used by this library does not autoscale - the number of tasks in the pool so in this - case this parameter is just ignored. */ - 2, - /* Stack size for every task pool thread - in - bytes, hence multiplying by the number of bytes - in a word as configMINIMAL_STACK_SIZE is - specified in words. */ - configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ), - /* Priority for every task pool thread. */ - tpTASK_POOL_WORKER_PRIORITY, - }; - -/*-----------------------------------------------------------*/ - -void vStartSimpleTaskPoolDemo( void ) -{ - /* This example uses a single application task, which in turn is used to - create and send jobs to task pool tasks. */ - xTaskCreate( prvTaskPoolDemoTask, /* Function that implements the task. */ - "PoolDemo", /* Text name for the task - only used for debugging. */ - configMINIMAL_STACK_SIZE, /* Size of stack (in words, not bytes) to allocate for the task. */ - NULL, /* Task parameter - not used in this case. */ - tskIDLE_PRIORITY, /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */ - NULL ); /* Used to pass out a handle to the created tsak - not used in this case. */ -} -/*-----------------------------------------------------------*/ - -static void prvTaskPoolDemoTask( void *pvParameters ) -{ -IotTaskPoolError_t xResult; -uint32_t ulLoops = 0; - - /* Remove compiler warnings about unused parameters. */ - ( void ) pvParameters; - - /* The task pool must be created before it can be used. The system task - pool is the task pool managed by the task pool library itself - the storage - used by the task pool is provided by the library. */ - xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* Attempting to create the task pool again should then appear to succeed - (in case it is initialised by more than one library), but have no effect. */ - xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - for( ;; ) - { - /* Demonstrate the most basic use case where a non persistent job is - created and scheduled to run immediately. The task pool worker tasks - (in which the job callback function executes) have a priority above the - priority of this task so the job's callback executes as soon as it is - scheduled. */ - prvExample_BasicSingleJob(); - - /* Demonstrate a job being scheduled to run at some time in the - future, and how a job scheduled to run in the future can be cancelled if - it has not yet started executing. */ - prvExample_DeferredJobAndCancellingJobs(); - - /* Demonstrate the most basic use of a recyclable job. This is similar - to prvExample_BasicSingleJob() but using a recyclable job. Creating a - recyclable job will re-use a previously created and now spare job from - the task pool's job cache if one is available, or otherwise dynamically - create a new job if a spare job is not available in the cache but space - remains in the cache. */ - prvExample_BasicRecyclableJob(); - - /* Demonstrate multiple recyclable jobs being created, used, and then - re-used. In this the task pool worker tasks (in which the job callback - functions execute) have a priority above the priority of this task so - the job's callback functions execute as soon as they are scheduled. */ - prvExample_ReuseRecyclableJobFromLowPriorityTask(); - - /* Again demonstrate multiple recyclable jobs being used, but this time - the priority of the task pool worker tasks (in which the job callback - functions execute) are lower than the priority of this task so the job's - callback functions don't execute until this task enteres the blocked - state. */ - prvExample_ReuseRecyclableJobFromHighPriorityTask(); - - ulLoops++; - if( ( ulLoops % 10UL ) == 0 ) - { - printf( "prvTaskPoolDemoTask() performed %u iterations without hitting an assert.\r\n", ulLoops ); - fflush( stdout ); - } - } -} -/*-----------------------------------------------------------*/ - -static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext ) -{ -/* The jobs context is the handle of the task to which a notification should -be sent. */ -TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext; - - /* Remove warnings about unused parameters. */ - ( void ) pTaskPool; - ( void ) pJob; - - /* Notify the task that created this job. */ - xTaskNotifyGive( xTaskToNotify ); -} -/*-----------------------------------------------------------*/ - -static void prvExample_BasicSingleJob( void ) -{ -IotTaskPoolJobStorage_t xJobStorage; -IotTaskPoolJob_t xJob; -IotTaskPoolError_t xResult; -uint32_t ulReturn; -const uint32_t ulNoFlags = 0UL; -const TickType_t xNoDelay = ( TickType_t ) 0; -size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(); -IotTaskPoolJobStatus_t xJobStatus; - - /* Don't expect any notifications to be pending yet. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* Create and schedule a job using the handle of this task as the job's - context and the function that sends a notification to the task handle as - the jobs callback function. This is not a recyclable job so the storage - required to hold information about the job is provided by this task - in - this case the storage is on the stack of this task so no memory is allocated - dynamically but the stack frame must remain in scope for the lifetime of - the job. */ - xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */ - ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */ - &xJobStorage, - &xJob ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* The job has been created but not scheduled so is now ready. */ - IotTaskPool_GetStatus( NULL, xJob, &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY ); - - /* This is not a persistent (recyclable) job and its storage is on the - stack of this function, so the amount of heap space available should not - have chanced since entering this function. */ - configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() ); - - /* In the full task pool implementation the first parameter is used to - pass the handle of the task pool to schedule. The lean task pool - implementation used in this demo only supports a single task pool, which - is created internally within the library, so the first parameter is NULL. */ - xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* Look for the notification coming from the job's callback function. The - priority of the task pool worker task that executes the callback is higher - than the priority of this task so a block time is not needed - the task pool - worker task pre-empts this task and sends the notification (from the job's - callback) as soon as the job is scheduled. */ - ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay ); - configASSERT( ulReturn ); - - /* The job's callback has executed so the job has now completed. */ - IotTaskPool_GetStatus( NULL, xJob, &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED ); -} -/*-----------------------------------------------------------*/ - -static void prvExample_DeferredJobAndCancellingJobs( void ) -{ -IotTaskPoolJobStorage_t xJobStorage; -IotTaskPoolJob_t xJob; -IotTaskPoolError_t xResult; -uint32_t ulReturn; -const uint32_t ulShortDelay_ms = 100UL; -const TickType_t xNoDelay = ( TickType_t ) 0, xAllowableMargin = ( TickType_t ) 5; /* Large margin for Windows port, which is not real time. */ -TickType_t xTimeBefore, xElapsedTime, xShortDelay_ticks; -size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(); -IotTaskPoolJobStatus_t xJobStatus; - - /* Don't expect any notifications to be pending yet. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* Create a job using the handle of this task as the job's context and the - function that sends a notification to the task handle as the jobs callback - function. The job is created using storage allocated on the stack of this - function - so no memory is allocated. */ - xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */ - ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */ - &xJobStorage, - &xJob ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* The job has been created but not scheduled so is now ready. */ - IotTaskPool_GetStatus( NULL, xJob, &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY ); - - /* This is not a persistent (recyclable) job and its storage is on the - stack of this function, so the amount of heap space available should not - have chanced since entering this function. */ - configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() ); - - /* Schedule the job to run its callback in xShortDelay_ms milliseconds time. - In the full task pool implementation the first parameter is used to pass the - handle of the task pool to schedule. The lean task pool implementation used - in this demo only supports a single task pool, which is created internally - within the library, so the first parameter is NULL. */ - xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* The scheduled job should not have executed yet, so don't expect any - notifications and expect the job's status to be 'deferred'. */ - ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay ); - configASSERT( ulReturn == 0 ); - IotTaskPool_GetStatus( NULL, xJob, &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_DEFERRED ); - - /* As the job has not yet been executed it can be stopped. */ - xResult = IotTaskPool_TryCancel( NULL, xJob, &xJobStatus ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - IotTaskPool_GetStatus( NULL, xJob, &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_CANCELED ); - - /* Schedule the job again, and this time wait until its callback is - executed (the callback function sends a notification to this task) to see - that it executes at the right time. */ - xTimeBefore = xTaskGetTickCount(); - xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* Wait twice the deferred execution time to ensure the callback is executed - before the call below times out. */ - ulReturn = ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( ulShortDelay_ms * 2UL ) ); - xElapsedTime = xTaskGetTickCount() - xTimeBefore; - - /* A single notification should not have been received... */ - configASSERT( ulReturn == 1 ); - - /* ...and the time since scheduling the job should be greater than or - equal to the deferred execution time - which is converted to ticks for - comparison. */ - xShortDelay_ticks = pdMS_TO_TICKS( ulShortDelay_ms ); - configASSERT( ( xElapsedTime >= xShortDelay_ticks ) && ( xElapsedTime < ( xShortDelay_ticks + xAllowableMargin ) ) ); -} -/*-----------------------------------------------------------*/ - -static void prvExample_BasicRecyclableJob( void ) -{ -IotTaskPoolJob_t xJob; -IotTaskPoolError_t xResult; -uint32_t ulReturn; -const uint32_t ulNoFlags = 0UL; -const TickType_t xNoDelay = ( TickType_t ) 0; -size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(); - - /* Don't expect any notifications to be pending yet. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* Create and schedule a job using the handle of this task as the job's - context and the function that sends a notification to the task handle as - the jobs callback function. The job is created as a recyclable job and in - this case the memory used to hold the job status is allocated inside the - create function. As the job is persistent it can be used multiple times, - as demonstrated in other examples within this demo. In the full task pool - implementation the first parameter is used to pass the handle of the task - pool this recyclable job is to be associated with. In the lean - implementation of the task pool used by this demo there is only one task - pool (the system task pool created within the task pool library) so the - first parameter is NULL. */ - xResult = IotTaskPool_CreateRecyclableJob( NULL, - prvSimpleTaskNotifyCallback, - (void * ) xTaskGetCurrentTaskHandle(), - &xJob ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* This recyclable job is persistent, and in this case created dynamically, - so expect there to be less heap space then when entering the function. */ - configASSERT( xPortGetFreeHeapSize() < xFreeHeapBeforeCreatingJob ); - - /* In the full task pool implementation the first parameter is used to - pass the handle of the task pool to schedule. The lean task pool - implementation used in this demo only supports a single task pool, which - is created internally within the library, so the first parameter is NULL. */ - xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* Look for the notification coming from the job's callback function. The - priority of the task pool worker task that executes the callback is higher - than the priority of this task so a block time is not needed - the task pool - worker task pre-empts this task and sends the notification (from the job's - callback) as soon as the job is scheduled. */ - ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay ); - configASSERT( ulReturn ); - - /* Clean up recyclable job. In the full implementation of the task pool - the first parameter is used to pass a handle to the task pool the job is - associated with. In the lean implementation of the task pool used by this - demo there is only one task pool (the system task pool created in the - task pool library itself) so the first parameter is NULL. */ - IotTaskPool_DestroyRecyclableJob( NULL, xJob ); - - /* Once the job has been deleted the memory used to hold the job is - returned, so the available heap should be exactly as when entering this - function. */ - configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob ); -} -/*-----------------------------------------------------------*/ - -static void prvExample_ReuseRecyclableJobFromLowPriorityTask( void ) -{ -IotTaskPoolError_t xResult; -uint32_t x, xIndex, ulNotificationValue; -const uint32_t ulNoFlags = 0UL; -IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ]; -size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(); -IotTaskPoolJobStatus_t xJobStatus; - - /* Don't expect any notifications to be pending yet. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* Create tpJOBS_TO_CREATE jobs using the handle of this task as the job's - context and the function that sends a notification to the task handle as - the jobs callback function. The jobs are created as a recyclable job and - in this case the memory to store the job information is allocated within - the create function as at this time there are no recyclable jobs in the - task pool jobs cache. As the jobs are persistent they can be used multiple - times. In the full task pool implementation the first parameter is used to - pass the handle of the task pool this recyclable job is to be associated - with. In the lean implementation of the task pool used by this demo there - is only one task pool (the system task pool created within the task pool - library) so the first parameter is NULL. */ - for( x = 0; x < tpJOBS_TO_CREATE; x++ ) - { - xResult = IotTaskPool_CreateRecyclableJob( NULL, - prvSimpleTaskNotifyCallback, - (void * ) xTaskGetCurrentTaskHandle(), - &( xJobs[ x ] ) ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* The job has been created but not scheduled so is now ready. */ - IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY ); - } - - /* Demonstrate that the jobs can be recycled by performing twice the number - of iterations of scheduling jobs than there actually are created jobs. This - works because the task pool task priorities are above the priority of this - task, so the tasks that run the jobs pre-empt this task as soon as a job is - ready. */ - for( x = 0; x < ( tpJOBS_TO_CREATE * 2UL ); x++ ) - { - /* Make sure array index does not go out of bounds. */ - xIndex = x % tpJOBS_TO_CREATE; - - xResult = IotTaskPool_Schedule( NULL, xJobs[ xIndex ], ulNoFlags ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* The priority of the task pool task(s) is higher than the priority - of this task, so the job's callback function should have already - executed, sending a notification to this task, and incrementing this - task's notification value. */ - xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ - 0UL, /* Don't clear any bits on exit. */ - &ulNotificationValue, /* Obtain the notification value. */ - 0UL ); /* No block time, return immediately. */ - configASSERT( ulNotificationValue == ( x + 1 ) ); - - /* The job's callback has executed so the job is now completed. */ - IotTaskPool_GetStatus( NULL, xJobs[ xIndex ], &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED ); - - /* To leave the list of jobs empty we can stop re-creating jobs half - way through iterations of this loop. */ - if( x < tpJOBS_TO_CREATE ) - { - /* Recycle the job so it can be used again. In the full task pool - implementation the first parameter is used to pass the handle of the - task pool this job will be associated with. In this lean task pool - implementation only the system task pool exists (the task pool created - internally to the task pool library) so the first parameter is just - passed as NULL. *//*_RB_ Why not recycle it automatically? */ - IotTaskPool_RecycleJob( NULL, xJobs[ xIndex ] ); - xResult = IotTaskPool_CreateRecyclableJob( NULL, - prvSimpleTaskNotifyCallback, - (void * ) xTaskGetCurrentTaskHandle(), - &( xJobs[ xIndex ] ) ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - } - } - - /* Clear all the notification value bits again. */ - xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */ - 0UL, /* Don't clear any bits on exit. */ - NULL, /* Don't need the notification value this time. */ - 0UL ); /* No block time, return immediately. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* Clean up all the recyclable job. In the full implementation of the task - pool the first parameter is used to pass a handle to the task pool the job - is associated with. In the lean implementation of the task pool used by - this demo there is only one task pool (the system task pool created in the - task pool library itself) so the first parameter is NULL. */ - for( x = 0; x < tpJOBS_TO_CREATE; x++ ) - { - xResult = IotTaskPool_DestroyRecyclableJob( NULL, xJobs[ x ] ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - } - - /* Once the job has been deleted the memory used to hold the job is - returned, so the available heap should be exactly as when entering this - function. */ - configASSERT( xPortGetFreeHeapSize() == xFreeHeapBeforeCreatingJob ); -} -/*-----------------------------------------------------------*/ - -static void prvExample_ReuseRecyclableJobFromHighPriorityTask( void ) -{ -IotTaskPoolError_t xResult; -uint32_t x, ulNotificationValue; -const uint32_t ulNoFlags = 0UL; -IotTaskPoolJob_t xJobs[ tpJOBS_TO_CREATE ]; -IotTaskPoolJobStorage_t xJobStorage[ tpJOBS_TO_CREATE ]; -size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize(); -TickType_t xShortDelay = pdMS_TO_TICKS( 150 ); -IotTaskPoolJobStatus_t xJobStatus; - - /* Don't expect any notifications to be pending yet. */ - configASSERT( ulTaskNotifyTake( pdTRUE, 0 ) == 0 ); - - /* prvExample_ReuseRecyclableJobFromLowPriorityTask() executes in a task - that has a lower [task] priority than the task pool's worker tasks. - Therefore a talk pool worker preempts the task that calls - prvExample_ReuseRecyclableJobFromHighPriorityTask() as soon as the job is - scheduled. prvExample_ReuseRecyclableJobFromHighPriorityTask() reverses the - priorities - prvExample_ReuseRecyclableJobFromHighPriorityTask() raises its - priority to above the task pool's worker tasks, so the worker tasks do not - execute until the calling task enters the blocked state. First raise the - priority - passing NULL means raise the priority of the calling task. */ - vTaskPrioritySet( NULL, tpTASK_POOL_WORKER_PRIORITY + 1 ); - - /* Create tpJOBS_TO_CREATE jobs using the handle of this task as the job's - context and the function that sends a notification to the task handle as - the jobs callback function. */ - for( x = 0; x < tpJOBS_TO_CREATE; x++ ) - { - xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */ - ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */ - &( xJobStorage[ x ] ), - &( xJobs[ x ] ) ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* This is not a persistent (recyclable) job and its storage is on the - stack of this function, so the amount of heap space available should not - have chanced since entering this function. */ - configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() ); - } - - for( x = 0; x < tpJOBS_TO_CREATE; x++ ) - { - /* Schedule the next job. */ - xResult = IotTaskPool_Schedule( NULL, xJobs[ x ], ulNoFlags ); - configASSERT( xResult == IOT_TASKPOOL_SUCCESS ); - - /* Although scheduled, the job's callback has not executed, so the job - reports itself as scheduled. */ - IotTaskPool_GetStatus( NULL, xJobs[ x ], &xJobStatus ); - configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_SCHEDULED ); - - /* The priority of the task pool task(s) is lower than the priority - of this task, so the job's callback function should not have executed - yes, so don't expect the notification value for this task to have - changed. */ - xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ - 0UL, /* Don't clear any bits on exit. */ - &ulNotificationValue, /* Obtain the notification value. */ - 0UL ); /* No block time, return immediately. */ - configASSERT( ulNotificationValue == 0 ); - } - - /* At this point there are tpJOBS_TO_CREATE scheduled, but none have executed - their callbacks because the priority of this task is higher than the - priority of the task pool worker threads. When this task blocks to wait for - a notification a worker thread will be able to executes - but as soon as its - callback function sends a notification to this task this task will - preempt it (because it has a higher priority) so this task only expects to - receive one notification at a time. */ - for( x = 0; x < tpJOBS_TO_CREATE; x++ ) - { - xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ - 0UL, /* Don't clear any bits on exit. */ - &ulNotificationValue, /* Obtain the notification value. */ - xShortDelay ); /* Short delay to allow a task pool worker to execute. */ - configASSERT( ulNotificationValue == ( x + 1 ) ); - } - - /* All the scheduled jobs have now executed, so waiting for another - notification should timeout without the notification value changing. */ - xTaskNotifyWait( 0UL, /* Don't clear any bits on entry. */ - 0UL, /* Don't clear any bits on exit. */ - &ulNotificationValue, /* Obtain the notification value. */ - xShortDelay ); /* Short delay to allow a task pool worker to execute. */ - configASSERT( ulNotificationValue == x ); - - /* Reset the priority of this task and clear the notifications ready for the - next example. */ - vTaskPrioritySet( NULL, tskIDLE_PRIORITY ); - xTaskNotifyWait( portMAX_DELAY, /* Clear all bits on entry - portMAX_DELAY is used as it is a portable way of having all bits set. */ - 0UL, /* Don't clear any bits on exit. */ - NULL, /* Don't need the notification value this time. */ - 0UL ); /* No block time, return immediately. */ -} -/*-----------------------------------------------------------*/ - diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj index 6832fef6b..2c5202e2e 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj @@ -58,7 +58,7 @@ Disabled - ..\..\..\Source\FreeRTOS-Plus-IoT-SDK\c_sdk\standard\mqtt\include;..\..\..\Source\FreeRTOS-Plus-TCP\include;..\..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;..\..\..\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;.\DemoTasks\include;.\WinPCap;..\..\..\..\FreeRTOS\Source\include;..\..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\c_sdk\standard\common\include;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\abstractions\platform\include;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\abstractions\platform\freertos\include;.;%(AdditionalIncludeDirectories) + ..\..\..\Source\FreeRTOS-Plus-IoT-SDK\c_sdk\standard\mqtt\include;..\..\..\Source\FreeRTOS-Plus-TCP\include;..\..\..\Source\FreeRTOS-Plus-TCP\portable\BufferManagement;..\..\..\Source\FreeRTOS-Plus-TCP\portable\Compiler\MSVC;.\DemoTasks\include;.\WinPCap;..\..\..\..\FreeRTOS\Source\include;..\..\..\..\FreeRTOS\Source\portable\MSVC-MingW;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\c_sdk\standard\common\include\private;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\c_sdk\standard\common\include;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\abstractions\platform\include;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\abstractions\platform\freertos\include;..\..\..\Source\FreeRTOS-Plus-IoT-SDK\abstractions\secure_sockets\include;.;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0500;WINVER=0x400;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true EnableFastChecks @@ -138,11 +138,6 @@ - - - - - @@ -150,11 +145,18 @@ + + + + + + + @@ -166,7 +168,7 @@ - + @@ -185,10 +187,18 @@ - + + + + + + + + + diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj.filters b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj.filters index e60132cea..4ef425d1f 100644 --- a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj.filters +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/WIN32.vcxproj.filters @@ -78,9 +78,6 @@ {bdcbc1ec-99b8-4c72-9075-49035c115488} - - {35ce7745-52a2-4220-be31-50dfaa35c0ab} - {2d17d5e6-ed70-4e42-9693-f7a63baf4948} @@ -96,6 +93,15 @@ {1943ad1a-a367-4ef5-ab65-1313801e6327} + + {9a82e058-c6c5-4da5-817e-a28c5137749b} + + + {cf6813fa-76cf-4e4d-86f7-18f1ae92ad44} + + + {79ebfd9f-45cb-4a3b-8c73-73f9d9fe7984} + @@ -160,9 +166,6 @@ FreeRTOS+\FreeRTOS IoT Libraries\standard\common\task_pool - - DemoTasks - FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\src @@ -172,22 +175,31 @@ FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\src - + + FreeRTOS+\FreeRTOS IoT Libraries\standard\common\logging + + FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\src - + FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\src - + FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\src - - FreeRTOS+\FreeRTOS IoT Libraries\standard\common\logging + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\freertos - + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\freertos - + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\secure_sockets\freertos_plus_tcp + + + DemoTasks + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\freertos @@ -283,9 +295,6 @@ - - FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\freertos\include\platform - FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\include\types @@ -307,5 +316,32 @@ FreeRTOS+\FreeRTOS IoT Libraries\standard\mqtt\include\types + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\freertos\include\platform + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\include\platform + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\include\platform + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\include\platform + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\platform\include\platform + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\secure_sockets\include + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\secure_sockets\include + + + FreeRTOS+\FreeRTOS IoT Libraries\abstractions\secure_sockets\include + + + FreeRTOS+\FreeRTOS IoT Libraries\standard\common\include\private + \ No newline at end of file diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/atomic.h b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/atomic.h new file mode 100644 index 000000000..d44593d8f --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/atomic.h @@ -0,0 +1,547 @@ +/* + * FreeRTOS Kernel V10.2.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://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/** + * @file atomic.h + * @brief FreeRTOS atomic operation support. + * + * Two implementations of atomic are given in this header file: + * 1. Disabling interrupt globally. + * 2. ISA native atomic support. + * The former is available to all ports (compiler-architecture combination), + * while the latter is only available to ports compiling with GCC (version at + * least 4.7.0), which also have ISA atomic support. + * + * User can select which implementation to use by: + * setting/clearing configUSE_ATOMIC_INSTRUCTION in FreeRTOSConfig.h. + * Define AND set configUSE_ATOMIC_INSTRUCTION to 1 for ISA native atomic support. + * Undefine OR clear configUSE_ATOMIC_INSTRUCTION for disabling global interrupt + * implementation. + * + * @see GCC Built-in Functions for Memory Model Aware Atomic Operations + * https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html + */ + +#ifndef ATOMIC_H +#define ATOMIC_H + +#ifndef INC_FREERTOS_H + #error "include FreeRTOS.h must appear in source files before include atomic.h" +#endif + +/* Standard includes. */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + /* Needed for __atomic_compare_exchange() weak=false. */ + #include + + /* This branch is for GCC compiler and GCC compiler only. */ + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__((always_inline)) + #endif + +#else + + /* Port specific definitions -- entering/exiting critical section. + * Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h + * + * Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with + * ATOMIC_ENTER_CRITICAL(). + */ + #if defined( portSET_INTERRUPT_MASK_FROM_ISR ) + + /* Nested interrupt scheme is supported in this port. */ + #define ATOMIC_ENTER_CRITICAL() \ + UBaseType_t uxCriticalSectionType = portSET_INTERRUPT_MASK_FROM_ISR() + + #define ATOMIC_EXIT_CRITICAL() \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxCriticalSectionType ) + + #else + + /* Nested interrupt scheme is NOT supported in this port. */ + #define ATOMIC_ENTER_CRITICAL() portENTER_CRITICAL() + #define ATOMIC_EXIT_CRITICAL() portEXIT_CRITICAL() + + #endif /* portSET_INTERRUPT_MASK_FROM_ISR() */ + + /* Port specific definition -- "always inline". + * Inline is compiler specific, and may not always get inlined depending on your optimization level. + * Also, inline is considerred as performance optimization for atomic. + * Thus, if portFORCE_INLINE is not provided by portmacro.h, instead of resulting error, + * simply define it. + */ + #ifndef portFORCE_INLINE + #define portFORCE_INLINE + #endif + +#endif /* configUSE_GCC_BUILTIN_ATOMICS */ + +#define ATOMIC_COMPARE_AND_SWAP_SUCCESS 0x1U /**< Compare and swap succeeded, swapped. */ +#define ATOMIC_COMPARE_AND_SWAP_FAILURE 0x0U /**< Compare and swap failed, did not swap. */ + +/*----------------------------- Swap && CAS ------------------------------*/ + +/** + * Atomic compare-and-swap + * + * @brief Performs an atomic compare-and-swap operation on the specified values. + * + * @param[in, out] pDestination Pointer to memory location from where value is + * to be loaded and checked. + * @param[in] ulExchange If condition meets, write this value to memory. + * @param[in] ulComparand Swap condition. + * + * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped. + * + * @note This function only swaps *pDestination with ulExchange, if previous + * *pDestination value equals ulComparand. + */ +static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( + uint32_t volatile * pDestination, + uint32_t ulExchange, + uint32_t ulComparand ) +{ + + uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; + +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + if ( __atomic_compare_exchange( pDestination, + &ulComparand, + &ulExchange, + false, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST ) ) + { + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } + +#else + + ATOMIC_ENTER_CRITICAL(); + + if ( *pDestination == ulComparand ) + { + *pDestination = ulExchange; + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } + + ATOMIC_EXIT_CRITICAL(); + +#endif + + return ulReturnValue; + +} + +/** + * Atomic swap (pointers) + * + * @brief Atomically sets the address pointed to by *ppDestination to the value + * of *pExchange. + * + * @param[in, out] ppDestination Pointer to memory location from where a pointer + * value is to be loaded and written back to. + * @param[in] pExchange Pointer value to be written to *ppDestination. + * + * @return The initial value of *ppDestination. + */ +static portFORCE_INLINE void * Atomic_SwapPointers_p32( + void * volatile * ppDestination, + void * pExchange ) +{ + void * pReturnValue; + +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + __atomic_exchange( ppDestination, &pExchange, &pReturnValue, __ATOMIC_SEQ_CST ); + +#else + + ATOMIC_ENTER_CRITICAL(); + + pReturnValue = *ppDestination; + + *ppDestination = pExchange; + + ATOMIC_EXIT_CRITICAL(); + +#endif + + return pReturnValue; +} + +/** + * Atomic compare-and-swap (pointers) + * + * @brief Performs an atomic compare-and-swap operation on the specified pointer + * values. + * + * @param[in, out] ppDestination Pointer to memory location from where a pointer + * value is to be loaded and checked. + * @param[in] pExchange If condition meets, write this value to memory. + * @param[in] pComparand Swap condition. + * + * @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped. + * + * @note This function only swaps *ppDestination with pExchange, if previous + * *ppDestination value equals pComparand. + */ +static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( + void * volatile * ppDestination, + void * pExchange, void * pComparand ) +{ + uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE; + +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + if ( __atomic_compare_exchange( ppDestination, + &pComparand, + &pExchange, + false, + __ATOMIC_SEQ_CST, + __ATOMIC_SEQ_CST ) ) + { + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } + +#else + + ATOMIC_ENTER_CRITICAL(); + + if ( *ppDestination == pComparand ) + { + *ppDestination = pExchange; + ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS; + } + + ATOMIC_EXIT_CRITICAL(); + +#endif + + return ulReturnValue; +} + + +/*----------------------------- Arithmetic ------------------------------*/ + +/** + * Atomic add + * + * @brief Atomically adds count to the value of the specified pointer points to. + * + * @param[in,out] pAddend Pointer to memory location from where value is to be + * loaded and written back to. + * @param[in] ulCount Value to be added to *pAddend. + * + * @return previous *pAddend value. + */ +static portFORCE_INLINE uint32_t Atomic_Add_u32( + uint32_t volatile * pAddend, + uint32_t ulCount ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_add(pAddend, ulCount, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pAddend; + + *pAddend += ulCount; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic subtract + * + * @brief Atomically subtracts count from the value of the specified pointer + * pointers to. + * + * @param[in,out] pAddend Pointer to memory location from where value is to be + * loaded and written back to. + * @param[in] ulCount Value to be subtract from *pAddend. + * + * @return previous *pAddend value. + */ +static portFORCE_INLINE uint32_t Atomic_Subtract_u32( + uint32_t volatile * pAddend, + uint32_t ulCount ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_sub(pAddend, ulCount, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pAddend; + + *pAddend -= ulCount; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic increment + * + * @brief Atomically increments the value of the specified pointer points to. + * + * @param[in,out] pAddend Pointer to memory location from where value is to be + * loaded and written back to. + * + * @return *pAddend value before increment. + */ +static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pAddend ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_add(pAddend, 1, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pAddend; + + *pAddend += 1; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic decrement + * + * @brief Atomically decrements the value of the specified pointer points to + * + * @param[in,out] pAddend Pointer to memory location from where value is to be + * loaded and written back to. + * + * @return *pAddend value before decrement. + */ +static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAddend ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_sub(pAddend, 1, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pAddend; + + *pAddend -= 1; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/*----------------------------- Bitwise Logical ------------------------------*/ + +/** + * Atomic OR + * + * @brief Performs an atomic OR operation on the specified values. + * + * @param [in, out] pDestination Pointer to memory location from where value is + * to be loaded and written back to. + * @param [in] ulValue Value to be ORed with *pDestination. + * + * @return The original value of *pDestination. + */ +static portFORCE_INLINE uint32_t Atomic_OR_u32( + uint32_t volatile * pDestination, + uint32_t ulValue ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_or(pDestination, ulValue, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pDestination; + + *pDestination |= ulValue; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic AND + * + * @brief Performs an atomic AND operation on the specified values. + * + * @param [in, out] pDestination Pointer to memory location from where value is + * to be loaded and written back to. + * @param [in] ulValue Value to be ANDed with *pDestination. + * + * @return The original value of *pDestination. + */ +static portFORCE_INLINE uint32_t Atomic_AND_u32( + uint32_t volatile * pDestination, + uint32_t ulValue ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_and(pDestination, ulValue, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pDestination; + + *pDestination &= ulValue; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic NAND + * + * @brief Performs an atomic NAND operation on the specified values. + * + * @param [in, out] pDestination Pointer to memory location from where value is + * to be loaded and written back to. + * @param [in] ulValue Value to be NANDed with *pDestination. + * + * @return The original value of *pDestination. + */ +static portFORCE_INLINE uint32_t Atomic_NAND_u32( + uint32_t volatile * pDestination, + uint32_t ulValue ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_nand(pDestination, ulValue, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pDestination; + + *pDestination = ~(ulCurrent & ulValue); + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +/** + * Atomic XOR + * + * @brief Performs an atomic XOR operation on the specified values. + * + * @param [in, out] pDestination Pointer to memory location from where value is + * to be loaded and written back to. + * @param [in] ulValue Value to be XORed with *pDestination. + * + * @return The original value of *pDestination. + */ +static portFORCE_INLINE uint32_t Atomic_XOR_u32( + uint32_t volatile * pDestination, + uint32_t ulValue ) +{ +#if defined ( configUSE_GCC_BUILTIN_ATOMICS ) && ( configUSE_GCC_BUILTIN_ATOMICS == 1 ) + + return __atomic_fetch_xor(pDestination, ulValue, __ATOMIC_SEQ_CST); + +#else + + uint32_t ulCurrent; + + ATOMIC_ENTER_CRITICAL(); + + ulCurrent = *pDestination; + + *pDestination ^= ulValue; + + ATOMIC_EXIT_CRITICAL(); + + return ulCurrent; + +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* ATOMIC_H */ diff --git a/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/iot_secure_sockets_config.h b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/iot_secure_sockets_config.h new file mode 100644 index 000000000..6442e8de2 --- /dev/null +++ b/FreeRTOS-Plus/Demo/FreeRTOS_IoT_Libraries/mqtt/iot_secure_sockets_config.h @@ -0,0 +1,56 @@ +/* + * Amazon FreeRTOS V1.4.7 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +/** + * @file aws_secure_sockets_config.h + * @brief Secure sockets configuration options. + */ + +#ifndef _AWS_SECURE_SOCKETS_CONFIG_H_ +#define _AWS_SECURE_SOCKETS_CONFIG_H_ + +/** + * @brief Byte order of the target MCU. + * + * Valid values are pdLITTLE_ENDIAN and pdBIG_ENDIAN. + */ +#define socketsconfigBYTE_ORDER pdLITTLE_ENDIAN + +/** + * @brief Default socket send timeout. + */ +#define socketsconfigDEFAULT_SEND_TIMEOUT ( 10000 ) + +/** + * @brief Default socket receive timeout. + */ +#define socketsconfigDEFAULT_RECV_TIMEOUT ( 10000 ) + +/** + * @brief Enable metrics of secure socket. + */ +#define AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED ( 0 ) + +#endif /* _AWS_SECURE_SOCKETS_CONFIG_H_ */ \ No newline at end of file diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/include/platform/iot_network_freertos.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/include/platform/iot_network_freertos.h new file mode 100644 index 000000000..e4449ae24 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/include/platform/iot_network_freertos.h @@ -0,0 +1,140 @@ +/* + * 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 aws_iot_network.h for + * Amazon FreeRTOS Secure Sockets. + */ + +#ifndef _IOT_NETWORK_AFR_H_ +#define _IOT_NETWORK_AFR_H_ + +/* Standard includes. */ +#include + +/* Platform network include. */ +#include "platform/iot_network.h" + +/* Amazon FreeRTOS Secure Sockets include. */ +#include "iot_secure_sockets.h" + +/** + * @brief Represents a network connection that uses Amazon FreeRTOS Secure Sockets. + * + * This is an incomplete type. In application code, only pointers to this type + * should be used. + */ +typedef struct _networkConnection IotNetworkConnectionAfr_t; + +/** + * @brief Provides a default value for an #IotNetworkConnectionAfr_t. + * + * All instances of #IotNetworkConnectionAfr_t should be initialized with + * this constant. + * + * @warning Failing to initialize an #IotNetworkConnectionAfr_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_AFR_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_AFR_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_AFR_INITIALIZER { 0 } + +/** + * @brief Provides a pointer to an #IotNetworkInterface_t that uses the functions + * declared in this file. + */ +#define IOT_NETWORK_INTERFACE_AFR ( &( IotNetworkAfr ) ) + +/** + * @brief An implementation of #IotNetworkInterface_t::create for Amazon FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Create( void * pConnectionInfo, + void * pCredentialInfo, + void ** const pConnection ); + +/** + * @brief An implementation of #IotNetworkInterface_t::setReceiveCallback for + * Amazon FreeRTOS Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_SetReceiveCallback( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ); + +/** + * @brief An implementation of #IotNetworkInterface_t::send for Amazon FreeRTOS + * Secure Sockets. + */ +size_t IotNetworkAfr_Send( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ); + +/** + * @brief An implementation of #IotNetworkInterface_t::receive for Amazon FreeRTOS + * Secure Sockets. + */ +size_t IotNetworkAfr_Receive( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ); + +/** + * @brief An implementation of #IotNetworkInterface_t::close for Amazon FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Close( void * pConnection ); + +/** + * @brief An implementation of #IotNetworkInterface_t::destroy for Amazon FreeRTOS + * Secure Sockets. + */ +IotNetworkError_t IotNetworkAfr_Destroy( void * 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 IotNetworkAfr; +/** @endcond */ + +#endif /* ifndef _IOT_NETWORK_AFR_H_ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/iot_network_freertos.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/iot_network_freertos.c new file mode 100644 index 000000000..287a3128b --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/platform/freertos/iot_network_freertos.c @@ -0,0 +1,627 @@ +/* + * 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.c + * @brief Implementation of the network-related functions from iot_network_freertos.h + * for Amazon FreeRTOS secure sockets. + */ + +/* The config header is always included first. */ +#include "iot_config.h" + +/* Standard includes. */ +#include + +/* FreeRTOS includes. */ +#include "semphr.h" +#include "event_groups.h" + +/* Error handling include. */ +#include "private/iot_error.h" + +/* Amazon FreeRTOS network include. */ +#include "platform/iot_network_freertos.h" + +/* 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 the number of milliseconds for a socket poll. + * This is a temporary workaround to deal with the lack of poll(). */ +#ifndef IOT_NETWORK_SOCKET_POLL_MS + #define IOT_NETWORK_SOCKET_POLL_MS ( 1000 ) +#endif + +/** + * @brief The event group bit to set when a connection's socket is shut down. + */ +#define _FLAG_SHUTDOWN ( 1 ) + +/** + * @brief The event group bit to set when a connection's receive task exits. + */ +#define _FLAG_RECEIVE_TASK_EXITED ( 2 ) + +/** + * @brief The event group bit to set when the connection is destroyed from the + * receive task. + */ +#define _FLAG_CONNECTION_DESTROYED ( 4 ) + +/*-----------------------------------------------------------*/ + +typedef struct _networkConnection +{ + Socket_t socket; /**< @brief Amazon FreeRTOS Secure Sockets handle. */ + StaticSemaphore_t socketMutex; /**< @brief Prevents concurrent threads from sending on a socket. */ + StaticEventGroup_t connectionFlags; /**< @brief Synchronizes with the receive task. */ + TaskHandle_t receiveTask; /**< @brief Handle of the receive task, if any. */ + IotNetworkReceiveCallback_t receiveCallback; /**< @brief Network receive callback, if any. */ + void * pReceiveContext; /**< @brief The context for the receive callback. */ + bool bufferedByteValid; /**< @brief Used to determine if the buffered byte is valid. */ + uint8_t bufferedByte; /**< @brief A single byte buffered from a receive, since AFR Secure Sockets does not have poll(). */ +} _networkConnection_t; + +/*-----------------------------------------------------------*/ + +/** + * @brief An #IotNetworkInterface_t that uses the functions in this file. + */ +const IotNetworkInterface_t IotNetworkAfr = +{ + .create = IotNetworkAfr_Create, + .setReceiveCallback = IotNetworkAfr_SetReceiveCallback, + .send = IotNetworkAfr_Send, + .receive = IotNetworkAfr_Receive, + .close = IotNetworkAfr_Close, + .destroy = IotNetworkAfr_Destroy +}; + +/*-----------------------------------------------------------*/ + +/** + * @brief Destroys a network connection. + * + * @param[in] pNetworkConnection The connection to destroy. + */ +static void _destroyConnection( _networkConnection_t * pNetworkConnection ) +{ + /* Call Secure Sockets close function to free resources. */ + int32_t socketStatus = SOCKETS_Close( pNetworkConnection->socket ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogWarn( "Failed to destroy connection." ); + } + + /* Free the network connection. */ + vPortFree( pNetworkConnection ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Task routine that waits on incoming network data. + * + * @param[in] pArgument The network connection. + */ +static void _networkReceiveTask( void * pArgument ) +{ + bool destroyConnection = false; + int32_t socketStatus = 0; + EventBits_t connectionFlags = 0; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = pArgument; + + while( true ) + { + /* No buffered byte should be in the connection. */ + configASSERT( pNetworkConnection->bufferedByteValid == false ); + + /* Block and wait for 1 byte of data. This simulates the behavior of poll(). + * THIS IS A TEMPORARY WORKAROUND AND DOES NOT PROVIDE THREAD-SAFETY AGAINST + * MULTIPLE CALLS OF RECEIVE. */ + do + { + socketStatus = SOCKETS_Recv( pNetworkConnection->socket, + &( pNetworkConnection->bufferedByte ), + 1, + 0 ); + + connectionFlags = xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ); + + if( ( connectionFlags & _FLAG_SHUTDOWN ) == _FLAG_SHUTDOWN ) + { + socketStatus = SOCKETS_ECLOSED; + } + + /* Check for timeout. Some ports return 0, some return EWOULDBLOCK. */ + } while( ( socketStatus == 0 ) || ( socketStatus == SOCKETS_EWOULDBLOCK ) ); + + if( socketStatus <= 0 ) + { + break; + } + + pNetworkConnection->bufferedByteValid = true; + + /* Invoke the network callback. */ + pNetworkConnection->receiveCallback( pNetworkConnection, + pNetworkConnection->pReceiveContext ); + + /* Check if the connection was destroyed by the receive callback. This + * does not need to be thread-safe because the destroy connection function + * may only be called once (per its API doc). */ + connectionFlags = xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ); + + if( ( connectionFlags & _FLAG_CONNECTION_DESTROYED ) == _FLAG_CONNECTION_DESTROYED ) + { + destroyConnection = true; + break; + } + } + + IotLogDebug( "Network receive task terminating." ); + + /* If necessary, destroy the network connection before exiting. */ + if( destroyConnection == true ) + { + _destroyConnection( pNetworkConnection ); + } + else + { + /* Set the flag to indicate that the receive task has exited. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_RECEIVE_TASK_EXITED ); + } + + vTaskDelete( NULL ); +} + +/*-----------------------------------------------------------*/ + +/** + * @brief Set up a secured TLS connection. + * + * @param[in] pAfrCredentials Credentials for the secured connection. + * @param[in] tcpSocket An initialized socket to secure. + * @param[in] pHostName Remote server name for SNI. + * @param[in] hostnameLength The length of `pHostName`. + * + * @return #IOT_NETWORK_SUCCESS or #IOT_NETWORK_SYSTEM_ERROR. + */ +static IotNetworkError_t _tlsSetup( const IotNetworkCredentials_t * pAfrCredentials, + Socket_t tcpSocket, + const char * pHostName, + size_t hostnameLength ) +{ + IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS ); + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* ALPN options for AWS IoT. */ + const char * ppcALPNProtos[] = { socketsAWS_IOT_ALPN_MQTT }; + + /* Set secured option. */ + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_REQUIRE_TLS, + NULL, + 0 ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set secured option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set ALPN option. */ + if( pAfrCredentials->pAlpnProtos != NULL ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_ALPN_PROTOCOLS, + ppcALPNProtos, + sizeof( ppcALPNProtos ) / sizeof( ppcALPNProtos[ 0 ] ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set ALPN option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + /* Set SNI option. */ + if( pAfrCredentials->disableSni == false ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_SERVER_NAME_INDICATION, + pHostName, + hostnameLength + 1 ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set SNI option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + /* Set custom server certificate. */ + if( pAfrCredentials->pRootCa != NULL ) + { + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE, + pAfrCredentials->pRootCa, + pAfrCredentials->rootCaSize ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set server certificate option for new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + } + + IOT_FUNCTION_EXIT_NO_CLEANUP(); +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Create( void * pConnectionInfo, + void * pCredentialInfo, + void ** pConnection ) +{ + IOT_FUNCTION_ENTRY( IotNetworkError_t, IOT_NETWORK_SUCCESS ); + Socket_t tcpSocket = SOCKETS_INVALID_SOCKET; + int32_t socketStatus = SOCKETS_ERROR_NONE; + SocketsSockaddr_t serverAddress = { 0 }; + EventGroupHandle_t pConnectionFlags = NULL; + SemaphoreHandle_t pConnectionMutex = NULL; + const TickType_t receiveTimeout = pdMS_TO_TICKS( IOT_NETWORK_SOCKET_POLL_MS ); + _networkConnection_t * pNewNetworkConnection = NULL; + + /* Cast function parameters to correct types. */ + const IotNetworkServerInfo_t * pServerInfo = pConnectionInfo; + const IotNetworkCredentials_t * pAfrCredentials = pCredentialInfo; + _networkConnection_t ** pNetworkConnection = ( _networkConnection_t ** ) pConnection; + + /* Check host name length against the maximum length allowed by Secure + * Sockets. */ + const size_t hostnameLength = strlen( pServerInfo->pHostName ); + + if( hostnameLength > ( size_t ) securesocketsMAX_DNS_NAME_LENGTH ) + { + IotLogError( "Host name length exceeds %d, which is the maximum allowed.", + securesocketsMAX_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 = SOCKETS_Socket( SOCKETS_AF_INET, + SOCKETS_SOCK_STREAM, + SOCKETS_IPPROTO_TCP ); + + if( tcpSocket == SOCKETS_INVALID_SOCKET ) + { + IotLogError( "Failed to create new socket." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set up connection encryption if credentials are provided. */ + if( pAfrCredentials != NULL ) + { + status = _tlsSetup( pAfrCredentials, tcpSocket, pServerInfo->pHostName, hostnameLength ); + + if( status != IOT_NETWORK_SUCCESS ) + { + IOT_GOTO_CLEANUP(); + } + } + + /* Establish connection. */ + serverAddress.ucSocketDomain = SOCKETS_AF_INET; + serverAddress.usPort = SOCKETS_htons( pServerInfo->port ); + serverAddress.ulAddress = SOCKETS_GetHostByName( pServerInfo->pHostName ); + + /* Check for errors from DNS lookup. */ + if( serverAddress.ulAddress == 0 ) + { + IotLogError( "Failed to resolve %s.", pServerInfo->pHostName ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + socketStatus = SOCKETS_Connect( tcpSocket, + &serverAddress, + sizeof( SocketsSockaddr_t ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to establish new connection." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + /* Set a long timeout for receive. */ + socketStatus = SOCKETS_SetSockOpt( tcpSocket, + 0, + SOCKETS_SO_RCVTIMEO, + &receiveTimeout, + sizeof( TickType_t ) ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogError( "Failed to set socket receive timeout." ); + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); + } + + IOT_FUNCTION_CLEANUP_BEGIN(); + + /* Clean up on failure. */ + if( status != IOT_NETWORK_SUCCESS ) + { + if( tcpSocket != SOCKETS_INVALID_SOCKET ) + { + SOCKETS_Close( tcpSocket ); + } + + /* Clear the connection information. */ + if( pNewNetworkConnection != NULL ) + { + vPortFree( pNewNetworkConnection ); + } + } + else + { + /* Set the socket. */ + pNewNetworkConnection->socket = tcpSocket; + + /* Create the connection event flags and mutex. */ + pConnectionFlags = xEventGroupCreateStatic( &( pNewNetworkConnection->connectionFlags ) ); + pConnectionMutex = xSemaphoreCreateMutexStatic( &( pNewNetworkConnection->socketMutex ) ); + + /* Static event flags and mutex creation should never fail. The handles + * should point inside the connection object. */ + configASSERT( pConnectionFlags == ( EventGroupHandle_t ) &( pNewNetworkConnection->connectionFlags ) ); + configASSERT( pConnectionMutex == ( SemaphoreHandle_t ) &( pNewNetworkConnection->socketMutex ) ); + + /* Set the output parameter. */ + *pNetworkConnection = pNewNetworkConnection; + } + + IOT_FUNCTION_CLEANUP_END(); +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_SetReceiveCallback( void * pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ) +{ + IotNetworkError_t status = IOT_NETWORK_SUCCESS; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Set the receive callback and context. */ + pNetworkConnection->receiveCallback = receiveCallback; + pNetworkConnection->pReceiveContext = pContext; + + /* No flags should be set. */ + configASSERT( xEventGroupGetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ) ) == 0 ); + + /* Create task that waits for incoming data. */ + if( xTaskCreate( _networkReceiveTask, + "NetRecv", + IOT_NETWORK_RECEIVE_TASK_STACK_SIZE, + pNetworkConnection, + IOT_NETWORK_RECEIVE_TASK_PRIORITY, + &( pNetworkConnection->receiveTask ) ) != pdPASS ) + { + IotLogError( "Failed to create network receive task." ); + + status = IOT_NETWORK_SYSTEM_ERROR; + } + + return status; +} + +/*-----------------------------------------------------------*/ + +size_t IotNetworkAfr_Send( void * pConnection, + const uint8_t * pMessage, + size_t messageLength ) +{ + size_t bytesSent = 0; + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Only one thread at a time may send on the connection. Lock the socket + * mutex to prevent other threads from sending. */ + if( xSemaphoreTake( ( QueueHandle_t ) &( pNetworkConnection->socketMutex ), + portMAX_DELAY ) == pdTRUE ) + { + socketStatus = SOCKETS_Send( pNetworkConnection->socket, + pMessage, + messageLength, + 0 ); + + if( socketStatus > 0 ) + { + bytesSent = ( size_t ) socketStatus; + } + + xSemaphoreGive( ( QueueHandle_t ) &( pNetworkConnection->socketMutex ) ); + } + + return bytesSent; +} + +/*-----------------------------------------------------------*/ + +size_t IotNetworkAfr_Receive( void * pConnection, + uint8_t * pBuffer, + size_t bytesRequested ) +{ + int32_t socketStatus = 0; + size_t bytesReceived = 0, bytesRemaining = bytesRequested; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Write the buffered byte. THIS IS A TEMPORARY WORKAROUND AND ASSUMES THIS + * FUNCTION IS ALWAYS CALLED FROM THE RECEIVE CALLBACK. */ + if( pNetworkConnection->bufferedByteValid == true ) + { + *pBuffer = pNetworkConnection->bufferedByte; + bytesReceived = 1; + bytesRemaining--; + pNetworkConnection->bufferedByteValid = false; + } + + /* Block and wait for incoming data. */ + while( bytesRemaining > 0 ) + { + socketStatus = SOCKETS_Recv( pNetworkConnection->socket, + pBuffer + bytesReceived, + bytesRemaining, + 0 ); + + if( socketStatus == SOCKETS_EWOULDBLOCK ) + { + /* The return value EWOULDBLOCK means no data was received within + * the socket timeout. Ignore it and try again. */ + continue; + } + else 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( "Receive requested %lu bytes, but %lu bytes received instead.", + ( unsigned long ) bytesRequested, + ( unsigned long ) bytesReceived ); + } + else + { + IotLogDebug( "Successfully received %lu bytes.", + ( unsigned long ) bytesRequested ); + } + + return bytesReceived; +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Close( void * pConnection ) +{ + int32_t socketStatus = SOCKETS_ERROR_NONE; + + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Call Secure Sockets shutdown function to close connection. */ + socketStatus = SOCKETS_Shutdown( pNetworkConnection->socket, + SOCKETS_SHUT_RDWR ); + + if( socketStatus != SOCKETS_ERROR_NONE ) + { + IotLogWarn( "Failed to close connection." ); + } + + /* Set the shutdown flag. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_SHUTDOWN ); + + return IOT_NETWORK_SUCCESS; +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkAfr_Destroy( void * pConnection ) +{ + /* Cast network connection to the correct type. */ + _networkConnection_t * pNetworkConnection = ( _networkConnection_t * ) pConnection; + + /* Check if this function is being called from the receive task. */ + if( xTaskGetCurrentTaskHandle() == pNetworkConnection->receiveTask ) + { + /* Set the flag specifying that the connection is destroyed. */ + ( void ) xEventGroupSetBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_CONNECTION_DESTROYED ); + } + else + { + /* If a receive task was created, wait for it to exit. */ + if( pNetworkConnection->receiveTask != NULL ) + { + ( void ) xEventGroupWaitBits( ( EventGroupHandle_t ) &( pNetworkConnection->connectionFlags ), + _FLAG_RECEIVE_TASK_EXITED, + pdTRUE, + pdTRUE, + portMAX_DELAY ); + } + + _destroyConnection( pNetworkConnection ); + } + + return IOT_NETWORK_SUCCESS; +} + +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/freertos_plus_tcp/iot_secure_sockets.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/freertos_plus_tcp/iot_secure_sockets.c new file mode 100644 index 000000000..af809c24c --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/freertos_plus_tcp/iot_secure_sockets.c @@ -0,0 +1,342 @@ +/* + * Amazon FreeRTOS Secure Sockets V1.1.5 + * Copyright (C) 2018 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 + */ + +/* Define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE to prevent secure sockets functions + * from redefining in iot_secure_sockets_wrapper_metrics.h */ +#define _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "FreeRTOSIPConfig.h" +#include "list.h" +#include "semphr.h" +#include "FreeRTOS_IP.h" +#include "FreeRTOS_Sockets.h" +#include "iot_secure_sockets.h" +#include "task.h" + +#undef _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + +/* Internal context structure. */ +typedef struct SSOCKETContext +{ + Socket_t xSocket; + char * pcDestination; + BaseType_t xSendFlags; + BaseType_t xRecvFlags; + BaseType_t xConnectAttempted; +} SSOCKETContext_t, * SSOCKETContextPtr_t; + +/* + * Helper routines. + */ + +/* + * @brief Network send callback. + */ +static BaseType_t prvNetworkSend( void * pvContext, + const unsigned char * pucData, + size_t xDataLength ) +{ + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) pvContext; /*lint !e9087 cast used for portability. */ + + return FreeRTOS_send( pxContext->xSocket, pucData, xDataLength, pxContext->xSendFlags ); +} +/*-----------------------------------------------------------*/ + +/* + * @brief Network receive callback. + */ +static BaseType_t prvNetworkRecv( void * pvContext, + unsigned char * pucReceiveBuffer, + size_t xReceiveLength ) +{ + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) pvContext; /*lint !e9087 cast used for portability. */ + + return FreeRTOS_recv( pxContext->xSocket, pucReceiveBuffer, xReceiveLength, pxContext->xRecvFlags ); +} +/*-----------------------------------------------------------*/ + +/* + * Interface routines. + */ + +int32_t SOCKETS_Close( Socket_t xSocket ) +{ + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + int32_t lReturn; + + if( ( xSocket != SOCKETS_INVALID_SOCKET ) && ( NULL != pxContext ) ) + { + /* Clean-up destination string. */ + if( NULL != pxContext->pcDestination ) + { + vPortFree( pxContext->pcDestination ); + } + + /* Close the underlying socket handle. */ + ( void ) FreeRTOS_closesocket( pxContext->xSocket ); + + /* Free the context. */ + vPortFree( pxContext ); + lReturn = SOCKETS_ERROR_NONE; + } + else + { + lReturn = SOCKETS_EINVAL; + } + + return lReturn; +} +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Connect( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ) +{ + int32_t lStatus = SOCKETS_ERROR_NONE; + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + struct freertos_sockaddr xTempAddress = { 0 }; + + if( ( pxContext != SOCKETS_INVALID_SOCKET ) && ( pxAddress != NULL ) ) + { + /* A connection was attempted. If this function fails, then the socket is invalid and the user + * must call SOCKETS_Close(), on this socket, and SOCKETS_Socket() to get a new socket. */ + pxContext->xConnectAttempted = pdTRUE; + + /* Connect the wrapped socket. */ + xTempAddress.sin_addr = pxAddress->ulAddress; + xTempAddress.sin_family = pxAddress->ucSocketDomain; + xTempAddress.sin_len = ( uint8_t ) sizeof( xTempAddress ); + xTempAddress.sin_port = pxAddress->usPort; + lStatus = FreeRTOS_connect( pxContext->xSocket, &xTempAddress, xAddressLength ); + } + else + { + lStatus = SOCKETS_SOCKET_ERROR; + } + + return lStatus; +} +/*-----------------------------------------------------------*/ + +uint32_t SOCKETS_GetHostByName( const char * pcHostName ) +{ + return FreeRTOS_gethostbyname( pcHostName ); +} +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Recv( Socket_t xSocket, + void * pvBuffer, + size_t xBufferLength, + uint32_t ulFlags ) +{ + int32_t lStatus = SOCKETS_SOCKET_ERROR; + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + + if( ( xSocket != SOCKETS_INVALID_SOCKET ) && + ( pvBuffer != NULL ) ) + { + pxContext->xRecvFlags = ( BaseType_t ) ulFlags; + + /* Receive unencrypted. */ + lStatus = prvNetworkRecv( pxContext, pvBuffer, xBufferLength ); + } + else + { + lStatus = SOCKETS_EINVAL; + } + + return lStatus; +} +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Send( Socket_t xSocket, + const void * pvBuffer, + size_t xDataLength, + uint32_t ulFlags ) +{ + int32_t lStatus = SOCKETS_SOCKET_ERROR; + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + + if( ( xSocket != SOCKETS_INVALID_SOCKET ) && + ( pvBuffer != NULL ) ) + { + pxContext->xSendFlags = ( BaseType_t ) ulFlags; + + /* Send unencrypted. */ + lStatus = prvNetworkSend( pxContext, pvBuffer, xDataLength ); + } + else + { + lStatus = SOCKETS_EINVAL; + } + + return lStatus; +} +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_SetSockOpt( Socket_t xSocket, + int32_t lLevel, + int32_t lOptionName, + const void * pvOptionValue, + size_t xOptionLength ) +{ + int32_t lStatus = SOCKETS_ERROR_NONE; + TickType_t xTimeout; + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + + if( ( xSocket != SOCKETS_INVALID_SOCKET ) && ( xSocket != NULL ) ) + { + switch( lOptionName ) + { + case SOCKETS_SO_NONBLOCK: + xTimeout = 0; + + /* Non-blocking connect is not supported. Socket may be set to nonblocking + * only after a connection is made. */ + if( pdTRUE == pxContext->xConnectAttempted ) + { + lStatus = FreeRTOS_setsockopt( pxContext->xSocket, + lLevel, + SOCKETS_SO_RCVTIMEO, + &xTimeout, + sizeof( xTimeout ) ); + + if( lStatus == SOCKETS_ERROR_NONE ) + { + lStatus = FreeRTOS_setsockopt( pxContext->xSocket, + lLevel, + SOCKETS_SO_SNDTIMEO, + &xTimeout, + sizeof( xTimeout ) ); + } + } + else + { + lStatus = SOCKETS_EISCONN; + } + + break; + + case SOCKETS_SO_RCVTIMEO: + case SOCKETS_SO_SNDTIMEO: + /* Comply with Berkeley standard - a 0 timeout is wait forever. */ + xTimeout = *( ( const TickType_t * ) pvOptionValue ); /*lint !e9087 pvOptionValue passed should be of TickType_t */ + + if( xTimeout == 0U ) + { + xTimeout = portMAX_DELAY; + } + + lStatus = FreeRTOS_setsockopt( pxContext->xSocket, + lLevel, + lOptionName, + &xTimeout, + xOptionLength ); + break; + + default: + lStatus = FreeRTOS_setsockopt( pxContext->xSocket, + lLevel, + lOptionName, + pvOptionValue, + xOptionLength ); + break; + } + } + else + { + lStatus = SOCKETS_EINVAL; + } + + return lStatus; +} +/*-----------------------------------------------------------*/ + +int32_t SOCKETS_Shutdown( Socket_t xSocket, + uint32_t ulHow ) +{ + int32_t lReturn; + SSOCKETContextPtr_t pxContext = ( SSOCKETContextPtr_t ) xSocket; /*lint !e9087 cast used for portability. */ + + if( ( xSocket != SOCKETS_INVALID_SOCKET ) && ( xSocket != NULL ) ) + { + lReturn = FreeRTOS_shutdown( pxContext->xSocket, ( BaseType_t ) ulHow ); + } + else + { + lReturn = SOCKETS_EINVAL; + } + + return lReturn; +} +/*-----------------------------------------------------------*/ + +Socket_t SOCKETS_Socket( int32_t lDomain, + int32_t lType, + int32_t lProtocol ) +{ + SSOCKETContextPtr_t pxContext = NULL; + Socket_t xSocket; + + /* Ensure that only supported values are supplied. */ + configASSERT( lDomain == SOCKETS_AF_INET ); + configASSERT( lType == SOCKETS_SOCK_STREAM ); + configASSERT( lProtocol == SOCKETS_IPPROTO_TCP ); + + /* Create the wrapped socket. */ + xSocket = FreeRTOS_socket( lDomain, lType, lProtocol ); + + if( xSocket != FREERTOS_INVALID_SOCKET ) + { + /* Allocate the internal context structure. */ + if( NULL == ( pxContext = pvPortMalloc( sizeof( SSOCKETContext_t ) ) ) ) + { + /* Need to close socket. */ + ( void ) FreeRTOS_closesocket( xSocket ); + pxContext = SOCKETS_INVALID_SOCKET; + } + else + { + memset( pxContext, 0, sizeof( SSOCKETContext_t ) ); + pxContext->xSocket = xSocket; + } + } + else + { + pxContext = SOCKETS_INVALID_SOCKET; + } + + return pxContext; +} +/*-----------------------------------------------------------*/ + +BaseType_t SOCKETS_Init( void ) +{ + /* Empty initialization for this port. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets.h new file mode 100644 index 000000000..d7c794a50 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets.h @@ -0,0 +1,609 @@ +/* + * Amazon FreeRTOS Secure Sockets V1.1.5 + * Copyright (C) 2018 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_secure_sockets.h + * @brief Secure Sockets Interface. + * + * Secure sockets is a portable layer for establishing a TCP/IP + * connection, with the option of using TLS. + * + * Secure sockets is based on the Berkeley sockets API. + * A few difference general differences between Berkeley and SOCKETS are: + * - SOCKETS has additional socket options to enable TLS, server name + * indication, and per-socket root of trust server certificates. See + * SOCKETS_SetSockOpt() for more information. + * - SOCKETS API return an error code, rather than returning -1 and setting + * a global errno value. + * + */ + +#ifndef _AWS_SECURE_SOCKETS_H_ +#define _AWS_SECURE_SOCKETS_H_ + +/* + #ifdef __cplusplus + * extern "C" { + #endif + */ +#include +#include +#include "iot_secure_sockets_config.h" +#include "iot_secure_sockets_config_defaults.h" +#include "iot_secure_sockets_wrapper_metrics.h" +#include "iot_lib_init.h" + +/** + * @ingroup SecureSockets_datatypes_handles + * @brief The socket handle data type. + * + * For detail of socket, refer to [Network Sockets] + * (https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/socket.html) + * + * Data contained by the Socket_t type is port specific. + */ +typedef void * Socket_t; + +/** + * @brief The "size_t" of secure sockets. + * + * This type is used for compatibility with the expected Berkeley sockets + * naming. + */ +#define Socklen_t uint32_t + +/** + * @anchor SocketsErrors + * @name SocketsErrors + * @brief Error codes returned by the SOCKETS API. + * + * Note that SOCKETS API may also propagate port-specific + * error codes when they are more descriptive. See your + * port's error codes for more details. + * PORT_SPECIFIC_LINK + */ +/**@{ */ + +#define SOCKETS_ERROR_NONE ( 0 ) /*!< No error. */ +#define SOCKETS_SOCKET_ERROR ( -1 ) /*!< Catch-all sockets error code. */ +#define SOCKETS_EWOULDBLOCK ( -11 ) /*!< A resource is temporarily unavailable. */ +#define SOCKETS_ENOMEM ( -12 ) /*!< Memory allocation failed. */ +#define SOCKETS_EINVAL ( -22 ) /*!< Invalid argument. */ +#define SOCKETS_ENOPROTOOPT ( -109 ) /*!< A bad option was specified . */ +#define SOCKETS_ENOTCONN ( -126 ) /*!< The supplied socket is not connected. */ +#define SOCKETS_EISCONN ( -127 ) /*!< The supplied socket is already connected. */ +#define SOCKETS_ECLOSED ( -128 ) /*!< The supplied socket has already been closed. */ +#define SOCKETS_TLS_INIT_ERROR ( -1001 ) /*!< TLS initialization failed. */ +#define SOCKETS_TLS_HANDSHAKE_ERROR ( -1002 ) /*!< TLS handshake failed. */ +#define SOCKETS_TLS_SERVER_UNVERIFIED ( -1003 ) /*!< A connection was made but the server could not be verified. It is recommended that the socket be closed. */ +#define SOCKETS_TLS_RECV_ERROR ( -1004 ) /*!< TLS receive operation failed. */ +#define SOCKETS_TLS_SEND_ERROR ( -1005 ) /*!< TLS send operation failed. */ +#define SOCKETS_PERIPHERAL_RESET ( -1006 ) /*!< Communications peripheral has been reset. */ +/**@} */ + +/** + * @brief Assigned to an Socket_t variable when the socket is not valid. + */ +#define SOCKETS_INVALID_SOCKET ( ( Socket_t ) ~0U ) + +/** + * @anchor SocketDomains + * @name SocketDomains + * + * @brief Options for the lDomain parameter of SOCKETS_Socket() + * function. + * + * These select the protocol family to be used for communication. + */ +/**@{ */ +#define SOCKETS_AF_INET ( 2 ) /*!< IPv4 Internet Protocols. */ +#define SOCKETS_PF_INET SOCKETS_AF_INET /*!< IPv4 Internet Protocol. */ +#define SOCKETS_AF_INET6 ( 10 ) /*!< IPv6 Internet Protocols. This option is currently not supported. */ +/**@} */ + +/** + * @anchor SocketTypes + * @name SocketTypes + * + * @brief Options for the lType parameter of SOCKETS_Socket() + * function. + * + * These specify the communication semantics. + */ +/**@{ */ +#define SOCKETS_SOCK_DGRAM ( 2 ) /*!< Datagram. */ +#define SOCKETS_SOCK_STREAM ( 1 ) /*!< Byte-stream. */ +/**@} */ + +/** + * @anchor Protocols + * @name Protocols + * + * @brief Options for the lProtocol parameter of SOCKETS_Socket() function. + * + */ +/**@{ */ +#define SOCKETS_IPPROTO_UDP ( 17 ) /*!< UDP. This option is currently not supported. */ +#define SOCKETS_IPPROTO_TCP ( 6 ) /*!< TCP. */ +/**@} */ + +/** + * @anchor SetSockOptOptions + * @name SetSockOptOptions + * + * @brief Options for lOptionName in SOCKETS_SetSockOpt(). + * + */ +/**@{ */ +#define SOCKETS_SO_RCVTIMEO ( 0 ) /**< Set the receive timeout. */ +#define SOCKETS_SO_SNDTIMEO ( 1 ) /**< Set the send timeout. */ +#define SOCKETS_SO_SNDBUF ( 4 ) /**< Set the size of the send buffer (TCP only). */ +#define SOCKETS_SO_RCVBUF ( 5 ) /**< Set the size of the receive buffer (TCP only). */ +#define SOCKETS_SO_SERVER_NAME_INDICATION ( 6 ) /**< Toggle client use of TLS SNI. */ +#define SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE ( 7 ) /**< Override default TLS server certificate trust. Must be PEM encoded and length must include null terminator. */ +#define SOCKETS_SO_REQUIRE_TLS ( 8 ) /**< Toggle client enforcement of TLS. */ +#define SOCKETS_SO_NONBLOCK ( 9 ) /**< Socket is nonblocking. */ +#define SOCKETS_SO_ALPN_PROTOCOLS ( 10 ) /**< Application protocol list to be included in TLS ClientHello. */ +#define SOCKETS_SO_WAKEUP_CALLBACK ( 17 ) /**< Set the callback to be called whenever there is data available on the socket for reading. */ + +/**@} */ + +/** + * @anchor ShutdownFlags
+ * @name ShutdownFlags + * + * @brief Options for the ulHow parameter in SOCKETS_Shutdown(). + */ +/**@{ */ +#define SOCKETS_SHUT_RD ( 0 ) /**< No further receives. */ +#define SOCKETS_SHUT_WR ( 1 ) /**< No further sends. */ +#define SOCKETS_SHUT_RDWR ( 2 ) /**< No further send or receive. */ +/**@} */ + +/** + * @brief Maximum length of an ASCII DNS name. + */ +#define securesocketsMAX_DNS_NAME_LENGTH ( 253 ) + +/** + * @ingroup SecureSockets_datatypes_paramstructs + * @brief Socket address. + * + * \sa PORT_SPECIFIC_LINK + */ +typedef struct SocketsSockaddr +{ + uint8_t ucLength; /**< Length of SocketsSockaddr structure. */ + uint8_t ucSocketDomain; /**< Only SOCKETS_AF_INET is supported. */ + uint16_t usPort; /**< Port number. Convention is to call this sin_port. */ + uint32_t ulAddress; /**< IP Address. Convention is to call this sin_addr. */ +} SocketsSockaddr_t; + +/** + * @brief Well-known port numbers. + */ +#define securesocketsDEFAULT_TLS_DESTINATION_PORT 443 + +/** + * @brief Secure Sockets library initialization function. + * + * This function does general initialization and setup. It must be called once + * and only once before calling any other function. + * + * @return + * * `pdPASS` if everything succeeds + * * `pdFAIL` otherwise. + */ +lib_initDECLARE_LIB_INIT( SOCKETS_Init ); + +/** + * @brief Creates a TCP socket. + * + * See the [FreeRTOS+TCP networking tutorial] + * (https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/TCP_Networking_Tutorial.html) + * for more information on TCP sockets. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @sa SOCKETS_Close() + * + * @param[in] lDomain Must be set to SOCKETS_AF_INET. See @ref SocketDomains. + * @param[in] lType Set to SOCKETS_SOCK_STREAM to create a TCP socket. + * No other value is valid. See @ref SocketTypes. + * @param[in] lProtocol Set to SOCKETS_IPPROTO_TCP to create a TCP socket. + * No other value is valid. See @ref Protocols. + * + * @return + * * If a socket is created successfully, then the socket handle is + * returned + * * @ref SOCKETS_INVALID_SOCKET is returned if an error occurred. + */ + +/* + * This call allocates memory and claims a socket resource. + */ +/* @[declare_secure_sockets_socket] */ +Socket_t SOCKETS_Socket( int32_t lDomain, + int32_t lType, + int32_t lProtocol ); +/* @[declare_secure_sockets_socket] */ + + +/** + * @brief Connects the socket to the specified IP address and port. + * + * The socket must first have been successfully created by a call to SOCKETS_Socket(). + * + * \note To create a secure socket, SOCKETS_SetSockOpt() should be called with the + * SOCKETS_SO_REQUIRE_TLS option \a before SOCKETS_Connect() is called. + * + * If this function returns an error the socket is considered invalid. + * + * \warning SOCKETS_Connect() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket to be connected. + * @param[in] pxAddress A pointer to a SocketsSockaddr_t structure that contains the + * the address to connect the socket to. + * @param[in] xAddressLength Should be set to sizeof( @ref SocketsSockaddr_t ). + * + * @return + * * @ref SOCKETS_ERROR_NONE if a connection is established. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_connect] */ +int32_t SOCKETS_Connect( Socket_t xSocket, + SocketsSockaddr_t * pxAddress, + Socklen_t xAddressLength ); +/* @[declare_secure_sockets_connect] */ + +/** + * @brief Receive data from a TCP socket. + * + * The socket must have already been created using a call to SOCKETS_Socket() + * and connected to a remote socket using SOCKETS_Connect(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket from which data is being received. + * @param[out] pvBuffer The buffer into which the received data will be placed. + * @param[in] xBufferLength The maximum number of bytes which can be received. + * pvBuffer must be at least xBufferLength bytes long. + * @param[in] ulFlags Not currently used. Should be set to 0. + * + * @return + * * If the receive was successful then the number of bytes received (placed in the + * buffer pointed to by pvBuffer) is returned. + * * If a timeout occurred before data could be received then 0 is returned (timeout + * is set using @ref SOCKETS_SO_RCVTIMEO). + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_recv] */ +int32_t SOCKETS_Recv( Socket_t xSocket, + void * pvBuffer, + size_t xBufferLength, + uint32_t ulFlags ); +/* @[declare_secure_sockets_recv] */ + +/** + * @brief Transmit data to the remote socket. + * + * The socket must have already been created using a call to SOCKETS_Socket() and + * connected to a remote socket using SOCKETS_Connect(). + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the sending socket. + * @param[in] pvBuffer The buffer containing the data to be sent. + * @param[in] xDataLength The length of the data to be sent. + * @param[in] ulFlags Not currently used. Should be set to 0. + * + * @return + * * On success, the number of bytes actually sent is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_send] */ +int32_t SOCKETS_Send( Socket_t xSocket, + const void * pvBuffer, + size_t xDataLength, + uint32_t ulFlags ); +/* @[declare_secure_sockets_send] */ + +/** + * @brief Closes all or part of a full-duplex connection on the socket. + * + * Disable reads and writes on a connected TCP socket. A connected TCP socket must be gracefully + * shut down before it can be closed. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * \warning SOCKETS_Shutdown() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @param[in] xSocket The handle of the socket to shutdown. + * @param[in] ulHow SOCKETS_SHUT_RD, SOCKETS_SHUT_WR or SOCKETS_SHUT_RDWR. + * @ref ShutdownFlags + * + * @return + * * If the operation was successful, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_shutdown] */ +int32_t SOCKETS_Shutdown( Socket_t xSocket, + uint32_t ulHow ); +/* @[declare_secure_sockets_shutdown] */ + +/** + * @brief Closes the socket and frees the related resources. + * + * A socket should be shutdown gracefully before it is closed, and cannot be used after it has been closed. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * \warning SOCKETS_Close() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @param[in] xSocket The handle of the socket to close. + * + * @return + * * On success, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_close] */ +int32_t SOCKETS_Close( Socket_t xSocket ); +/* @[declare_secure_sockets_close] */ + +/** + * @brief AWS IoT ALPN protocol name for MQTT over TLS on server port 443. + */ +#define socketsAWS_IOT_ALPN_MQTT "x-amzn-mqtt-ca" + +/** + * @brief Manipulates the options for the socket. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] xSocket The handle of the socket to set the option for. + * @param[in] lLevel Not currently used. Should be set to 0. + * @param[in] lOptionName See @ref SetSockOptOptions. + * @param[in] pvOptionValue A buffer containing the value of the option to set. + * @param[in] xOptionLength The length of the buffer pointed to by pvOptionValue. + * + * \warning SOCKETS_Close() is not safe to be called on the same socket + * from multiple threads simultaneously with SOCKETS_Connect(), + * SOCKETS_SetSockOpt(), SOCKETS_Shutdown(), SOCKETS_Close(). + * + * @note Socket option support and possible values vary by port. Please see + * PORT_SPECIFIC_LINK to check the valid options and limitations of your device. + * + * - Berkeley Socket Options + * - @ref SOCKETS_SO_RCVTIMEO + * - Sets the receive timeout + * - pvOptionValue (TickType_t) is the number of milliseconds that the + * receive function should wait before timing out. + * - Setting pvOptionValue = 0 causes receive to wait forever. + * - See PORT_SPECIFIC_LINK for device limitations. + * - @ref SOCKETS_SO_SNDTIMEO + * - Sets the send timeout + * - pvOptionValue (TickType_t) is the number of milliseconds that the + * send function should wait before timing out. + * - Setting pvOptionValue = 0 causes send to wait forever. + * - See PORT_SPECIFIC_LINK for device limitations. + * - Non-Standard Options + * - @ref SOCKETS_SO_NONBLOCK + * - Makes a socket non-blocking. + * - Non-blocking connect is not supported - socket option should be + * called after connect. + * - pvOptionValue is ignored for this option. + * - @ref SOCKETS_SO_WAKEUP_CALLBACK + * - Set the callback to be called whenever there is data available on + * the socket for reading + * - This option provides an asynchronous way to handle received data + * - pvOptionValue is a pointer to the callback function + * - See PORT_SPECIFIC_LINK for device limitations. + * - Security Sockets Options + * - @ref SOCKETS_SO_REQUIRE_TLS + * - Use TLS for all connect, send, and receive on this socket. + * - This socket options MUST be set for TLS to be used, even + * if other secure socket options are set. + * - This socket option should be set before SOCKETS_Connect() is + * called. + * - pvOptionValue is ignored for this option. + * - @ref SOCKETS_SO_TRUSTED_SERVER_CERTIFICATE + * - Set the root of trust server certificate for the socket. + * - This socket option only takes effect if @ref SOCKETS_SO_REQUIRE_TLS + * is also set. If @ref SOCKETS_SO_REQUIRE_TLS is not set, + * this option will be ignored. + * - pvOptionValue is a pointer to the formatted server certificate. + * TODO: Link to description of how to format certificates with \n + * - xOptionLength (BaseType_t) is the length of the certificate + * in bytes. + * - @ref SOCKETS_SO_SERVER_NAME_INDICATION + * - Use Server Name Indication (SNI) + * - This socket option only takes effect if @ref SOCKETS_SO_REQUIRE_TLS + * is also set. If @ref SOCKETS_SO_REQUIRE_TLS is not set, + * this option will be ignored. + * - pvOptionValue is a pointer to a string containing the hostname + * - xOptionLength is the length of the hostname string in bytes. + * - @ref SOCKETS_SO_ALPN_PROTOCOLS + * - Negotiate an application protocol along with TLS. + * - The ALPN list is expressed as an array of NULL-terminated ANSI + * strings. + * - xOptionLength is the number of items in the array. + * + * @return + * * On success, 0 is returned. + * * If an error occurred, a negative value is returned. @ref SocketsErrors + */ +/* @[declare_secure_sockets_setsockopt] */ +int32_t SOCKETS_SetSockOpt( Socket_t xSocket, + int32_t lLevel, + int32_t lOptionName, + const void * pvOptionValue, + size_t xOptionLength ); +/* @[declare_secure_sockets_setsockopt] */ + +/** + * @brief Resolve a host name using Domain Name Service. + * + * See the [Berkeley Sockets API] + * (https://en.wikipedia.org/wiki/Berkeley_sockets#Socket_API_functions) + * in wikipedia + * + * @param[in] pcHostName The host name to resolve. + * @return + * * The IPv4 address of the specified host. + * * If an error has occurred, 0 is returned. + */ +/* @[declare_secure_sockets_gethostbyname] */ +uint32_t SOCKETS_GetHostByName( const char * pcHostName ); +/* @[declare_secure_sockets_gethostbyname] */ + + + +/** + * @brief Convert an unsigned thirty-two-bit value from host endianness to network + * endianness. + * + * @param[in] usIn The unsigned thirty-two-bit value to convert. + */ +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + #define SOCKETS_htonl( ulIn ) ( ( uint32_t ) ( ( ( ulIn & 0xFF ) << 24 ) | ( ( ulIn & 0xFF00 ) << 8 ) | ( ( ulIn & 0xFF0000 ) >> 8 ) | ( ( ulIn & 0xFF000000 ) >> 24 ) ) ) +#else + #define SOCKETS_htonl( usIn ) ( ( uint32_t ) ( usIn ) ) +#endif + +/** + * @brief Convert an unsigned thirty-two-bit value from network endianness to host + * endianness. + * + * @param[in] usIn The unsigned thirty-two-bit value to convert. + */ +#define SOCKETS_ntohl( usIn ) SOCKETS_htonl( usIn ) + + +/** + * @brief Convert an unsigned sixteen-bit value from host endianness to network + * endianness. + * + * @param[in] usIn The unsigned sixteen-bit value to convert. + */ + +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + #define SOCKETS_htons( usIn ) ( ( uint16_t ) ( ( ( usIn ) << 8U ) | ( ( usIn ) >> 8U ) ) ) +#else + #define SOCKETS_htons( usIn ) ( ( uint16_t ) ( usIn ) ) +#endif + + +/** + * @brief Convert an unsigned sixteen-bit value from network endianness to host + * endianness. + * + * @param[in] usIn The unsigned sixteen-bit value to convert. + */ +#define SOCKETS_ntohs( usIn ) SOCKETS_htons( usIn ) + +/** + * @brief Convert an IP address expressed as four separate numeric octets into a an IP address expressed as a 32-bit number in network byte order + * (for example 192, 168, 0, 100) + * + * @param[in] ucOctet0 0th IP Octet + * @param[in] ucOctet1 1st IP Octet + * @param[in] ucOctet2 2nd IP Octet + * @param[in] ucOctet3 3rd IP Octet + */ +#if defined( socketsconfigBYTE_ORDER ) && ( socketsconfigBYTE_ORDER == pdLITTLE_ENDIAN ) + + #define SOCKETS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ + ( ( ( ( uint32_t ) ( ucOctet3 ) ) << 24UL ) | \ + ( ( ( uint32_t ) ( ucOctet2 ) ) << 16UL ) | \ + ( ( ( uint32_t ) ( ucOctet1 ) ) << 8UL ) | \ + ( ( uint32_t ) ( ucOctet0 ) ) ) + +/** + * @brief Convert an IP address expressed as a 32-bit number in network byte order to a string in decimal dot notation. + * (for example "192.168.0.100") + * + * @param[in] ulIPAddress An IP address expressed as a 32-bit value in network byte order. + * @param[in] pucBuffer A pointer to a buffer into which the IP address will be written in decimal dot notation. + */ + #define SOCKETS_inet_ntoa( ulIPAddress, pucBuffer ) \ + sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \ + ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ) ) + +#else /* socketsconfigBYTE_ORDER. */ + + #define SOCKETS_inet_addr_quick( ucOctet0, ucOctet1, ucOctet2, ucOctet3 ) \ + ( ( ( ( uint32_t ) ( ucOctet0 ) ) << 24UL ) | \ + ( ( ( uint32_t ) ( ucOctet1 ) ) << 16UL ) | \ + ( ( ( uint32_t ) ( ucOctet2 ) ) << 8UL ) | \ + ( ( uint32_t ) ( ucOctet3 ) ) ) + +/** + * @brief Convert an IP address expressed as a 32-bit number in network byte order to a string in decimal dot notation. + * (for example "192.168.0.100") + * + * @param[in] ulIPAddress An IP address expressed as a 32-bit value in network byte order. + * @param[in] pucBuffer A pointer to a buffer into which the IP address will be written in decimal dot notation. + */ + #define SOCKETS_inet_ntoa( ulIPAddress, pucBuffer ) \ + sprintf( ( char * ) ( pucBuffer ), "%u.%u.%u.%u", \ + ( ( unsigned ) ( ( ulIPAddress ) >> 24 ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 16 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ( ulIPAddress ) >> 8 ) & 0xffUL ) ), \ + ( ( unsigned ) ( ( ulIPAddress ) & 0xffUL ) ) ) + +#endif /* socketsconfigBYTE_ORDER. */ + +/* + #ifdef __cplusplus + * } + #endif + */ + +#endif /* _AWS_SECURE_SOCKETS_H_ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h new file mode 100644 index 000000000..498ac5dfc --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_config_defaults.h @@ -0,0 +1,72 @@ +/* + * Amazon FreeRTOS Secure Sockets V1.1.5 + * Copyright (C) 2018 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_secure_sockets_config_defaults.h + * @brief Ensures that the required sockets configuration options are supplied + * and the optional ones are set to sane values if the user does not supply. + */ + +#ifndef AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ +#define AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ + +/** + * @brief Byte order of the target MCU must be defined. + * + * Valid values are pdLITTLE_ENDIAN and pdBIG_ENDIAN. + */ +#ifndef socketsconfigBYTE_ORDER + #error "socketsconfigBYTE_ORDER must be defined." +#endif + +/** + * @brief Default socket send timeout. + * + * The user can change the send timeout for a socket using the SOCKETS_SetSockOpt API + * with the SOCKETS_SO_SNDTIMEO option. + */ +#ifndef socketsconfigDEFAULT_SEND_TIMEOUT + #define socketsconfigDEFAULT_SEND_TIMEOUT ( 10000 ) +#endif + +/** + * @brief Default socket receive timeout. + * + * The user can change the receive timeout for a socket using the SOCKETS_SetSockOpt API + * with the SOCKETS_SO_RCVTIMEO option. + */ +#ifndef socketsconfigDEFAULT_RECV_TIMEOUT + #define socketsconfigDEFAULT_RECV_TIMEOUT ( 10000 ) +#endif + +/** + * @brief By default, metrics of secure socket is disabled. + * + */ +#ifndef AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED + #define AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED ( 0 ) +#endif + +#endif /* AWS_INC_SECURE_SOCKETS_CONFIG_DEFAULTS_H_ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h new file mode 100644 index 000000000..a5282a23c --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/abstractions/secure_sockets/include/iot_secure_sockets_wrapper_metrics.h @@ -0,0 +1,43 @@ +/* + * Amazon FreeRTOS Secure Sockets V1.1.5 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ +#define _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ + +/* This file redefines Secure Sockets functions to be called through a wrapper macro, + * but only if metrics is enabled explicitly. */ +#if AWS_IOT_SECURE_SOCKETS_METRICS_ENABLED == 1 + +/* This macro is included in aws_secure_socket.c and aws_secure_socket_wrapper_metrics.c. + * It will prevent the redefine in those source files. */ + #ifndef _SECURE_SOCKETS_WRAPPER_NOT_REDEFINE + #define SOCKETS_Init Sockets_MetricsInit + #define SOCKETS_Connect Sockets_MetricsConnect + #define SOCKETS_Shutdown Sockets_MetricsShutdown + #endif + +#endif + +#endif /* ifndef _AWS_SECURE_SOCKETS_WRAPPER_METRICS_ */ diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/include/private/iot_lib_init.h b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/include/private/iot_lib_init.h new file mode 100644 index 000000000..2930d7415 --- /dev/null +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-IoT-SDK/c_sdk/standard/common/include/private/iot_lib_init.h @@ -0,0 +1,33 @@ +/* + * Amazon FreeRTOS Common V1.0.0 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://aws.amazon.com/freertos + * http://www.FreeRTOS.org + */ + +#ifndef _AWS_LIB_INIT_H_ +#define _AWS_LIB_INIT_H_ + +#include "FreeRTOS.h" + +#define lib_initDECLARE_LIB_INIT( f ) extern BaseType_t f( void ) + +#endif /* _AWS_LIB_INIT_H_ */ -- 2.39.5