]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/mqtt/common/DemoTasks/LightWeightMQTTExample.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_IoT_Libraries / mqtt / common / DemoTasks / LightWeightMQTTExample.c
diff --git a/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/mqtt/common/DemoTasks/LightWeightMQTTExample.c b/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/mqtt/common/DemoTasks/LightWeightMQTTExample.c
new file mode 100644 (file)
index 0000000..aabb3a6
--- /dev/null
@@ -0,0 +1,853 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/*\r
+ * Proof of Concept for use of MQTT light weight serializer API.\r
+ * Light weight serializer API lets user to serialize and\r
+ * deserialize MQTT messages into user provided buffer.\r
+ * This API allows use of statically allocated buffer.\r
+ *\r
+ * Example shown below uses this API to create MQTT messages and\r
+ * and send them over connection established using FreeRTOS sockets.\r
+ * The example is single threaded and uses statically allocated memory.\r
+ *\r
+ * !!! NOTE !!!\r
+ * This is work in progress to show how light weight serializer\r
+ * API can be used. This is not a complete demo, and should not\r
+ * be treated as production ready code.\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <string.h>\r
+#include <stdio.h>\r
+\r
+/* Kernel includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* FreeRTOS+TCP includes. */\r
+#include "FreeRTOS_IP.h"\r
+#include "FreeRTOS_Sockets.h"\r
+\r
+/* IoT SDK includes. */\r
+#include "iot_mqtt.h"\r
+#include "iot_mqtt_serialize.h"\r
+#include "platform/iot_network_freertos.h"\r
+\r
+/* Demo Specific configs. */\r
+#include "mqtt_demo_profile.h"\r
+\r
+\r
+/**\r
+ * @brief Time to wait between each cycle of the demo implemented by prvMQTTDemoTask().\r
+ */\r
+#define mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS       ( pdMS_TO_TICKS( 5000 ) )\r
+\r
+/**\r
+ * @brief Time to wait before sending ping request to keep MQTT connection alive.\r
+ */\r
+#define mqttexampleKEEP_ALIVE_DELAY                                    ( pdMS_TO_TICKS( 1000 ) )\r
+\r
+\r
+/**\r
+ * @brief The MQTT client identifier used in this example.  Each client identifier\r
+ * must be unique so edit as required to ensure no two clients connecting to the\r
+ * same broker use the same client identifier.\r
+ */\r
+#define mqttexampleCLIENT_IDENTIFIER      mqttdemoprofileCLIENT_IDENTIFIER\r
+\r
+/**\r
+ * @brief Details of the MQTT broker to connect to.\r
+ */\r
+#define mqttexampleMQTT_BROKER_ENDPOINT           mqttdemoprofileBROKER_ENDPOINT\r
+\r
+/**\r
+ * @brief The port to use for the demo.\r
+ */\r
+#define mqttexampleMQTT_BROKER_PORT               mqttdemoprofileBROKER_PORT\r
+\r
+/**\r
+ * @brief The topic to subscribe and publish to in the example.\r
+ *\r
+ * The topic starts with the client identifier to ensure that each demo interacts\r
+ * with a unique topic.\r
+ */\r
+#define mqttexampleTOPIC                                  mqttexampleCLIENT_IDENTIFIER "/example/topic"\r
+\r
+/**\r
+ * @brief The MQTT message published in this example.\r
+ */\r
+#define mqttexampleMESSAGE                                "Hello Light Weight MQTT World!"\r
+\r
+/**\r
+ * @brief Dimensions a file scope buffer currently used to send and receive MQTT data from a\r
+ * socket\r
+ */\r
+#define mqttexampleSHARED_BUFFER_SIZE     500\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief MQTT Protocol constants used by this demo.\r
+ * These types are defined in internal MQTT include files.\r
+ * For light-weight demo application, only a few are needed, therefore\r
+ * they are redefined here so that internal files need not be included.\r
+ */\r
+\r
+/*  MQTT Control Packet Types.*/\r
+#define MQTT_PACKET_TYPE_CONNACK          ( ( uint8_t ) 0x20U ) /**< @brief CONNACK (server-to-client). */\r
+#define MQTT_PACKET_TYPE_PUBLISH          ( ( uint8_t ) 0x30U ) /**< @brief PUBLISH (bi-directional). */\r
+#define MQTT_PACKET_TYPE_SUBACK                   ( ( uint8_t ) 0x90U ) /**< @brief SUBACK (server-to-client). */\r
+#define MQTT_PACKET_TYPE_UNSUBACK         ( ( uint8_t ) 0xb0U ) /**< @brief UNSUBACK (server-to-client). */\r
+#define MQTT_PACKET_TYPE_PINGRESP         ( ( uint8_t ) 0xd0U ) /**< @brief PINGRESP (server-to-client). */\r
+/* MQTT Fixed Packet Sizes */\r
+#define MQTT_PACKET_DISCONNECT_SIZE       ( ( uint8_t ) 2 )     /**< @brief Size of DISCONNECT packet. */\r
+#define MQTT_PACKET_PINGREQ_SIZE          ( ( uint8_t ) 2 )     /**< @brief Size of PINGREQ packet. */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief The task used to demonstrate the MQTT API.\r
+ *\r
+ * @param[in] pvParameters Parameters as passed at the time of task creation. Not\r
+ * used in this example.\r
+ */\r
+static void prvMQTTDemoTask( void * pvParameters );\r
+\r
+/**\r
+ * @brief Creates a TCP connection to the MQTT broker as specified in\r
+ * mqttexampleMQTT_BROKER_ENDPOINT and mqttexampleMQTT_BROKER_PORT.\r
+ *\r
+ * @return On success the socket connected to the MQTT broker is returned.  Otherwise\r
+ * FREERTOS_INVALID_SOCKET is returned.\r
+ *\r
+ */\r
+static Socket_t prvCreateTCPConnectionToBroker( void );\r
+\r
+/**\r
+ * @brief Sends an MQTT Connect packet over the already connected TCP socket.\r
+ *\r
+ * @param xMQTTSocketis a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if the reply is a valid connection\r
+ * acknowledgeable (CONNACK) packet, otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvCreateMQTTConnectionWithBroker( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief Performs a graceful shutdown and close of the socket passed in as its\r
+ * parameter.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ */\r
+static void prvGracefulShutDown( Socket_t xSocket );\r
+\r
+/**\r
+ * @brief Subscribes to the topic as specified in mqttexampleTOPIC.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if the\r
+ * subscription is successful, otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTSubscribeToTopic( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief  Publishes a messages mqttexampleMESSAGE on mqttexampleTOPIC topic.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if Publish is successful,\r
+ * otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTPublishToTopic( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief  Process Incoming Publish.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return #IOT_MQTT_SUCCESS is returned if the processing is successful,\r
+ * otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTProcessIncomingPublish( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief Unsubscribes from the previously subscribed topic as specified\r
+ * in mqttexampleTOPIC.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if the\r
+ * unsubscribe is successful, otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTUnsubscribeFromTopic( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief Send MQTT Ping Request to broker and receive response.\r
+ * Ping request is used to keep connection to broker alive.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if the successful Ping Response is received.\r
+ * otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTKeepAlive( Socket_t xMQTTSocket );\r
+\r
+/**\r
+ * @brief Disconnect From MQTT Broker.\r
+ *\r
+ * @param xMQTTSocket is a TCP socket that is connected to an MQTT broker to which\r
+ * an MQTT connection has been established.\r
+ *\r
+ * @return IOT_MQTT_SUCCESS is returned if the disconnect is successful,\r
+ * otherwise an error code is returned.\r
+ */\r
+static IotMqttError_t prvMQTTDisconnect( Socket_t xMQTTSocket );\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief Function to receive next byte from network,\r
+ * The declaration must match IotMqttGetNextByte_t.\r
+ *\r
+ * @param[in] pvContext Network Connection context. Implementation in this\r
+ * file uses FreeRTOS socket.\r
+ * @param[in, out] pNextBye Pointer to buffer where the byte will be stored.\r
+ *\r
+ * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_TIMEOUT\r
+ */\r
+\r
+IotMqttError_t getNextByte( void * pvContext,\r
+                                                       uint8_t * pNextByte );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* @brief Static memory buffer used for sending and receiving MQTT messages */\r
+static uint8_t ucSharedBuffer[ mqttexampleSHARED_BUFFER_SIZE ];\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * @brief Task for Light Weight MQTT Serializer API Proof of Concept.\r
+ * To run the proof of concept example, in main.c, in function vApplicationIPNetworkEventHook(),\r
+ * replace vStartSimpleMQTTDemo() with vApplicationIPNetworkEventHook().\r
+ */\r
+void vStartLightWeightMQTTDemo( void )\r
+{\r
+TickType_t xShortDelay = ( TickType_t ) pdMS_TO_TICKS( ( TickType_t ) 500 );\r
+\r
+       /* Wait a short time to allow receipt of the ARP replies. */\r
+       vTaskDelay( xShortDelay );\r
+\r
+       /* This example uses a single application task, which in turn is used to\r
+        * connect, subscribe, publish, unsubscribe and disconnect from the MQTT\r
+        * broker. */\r
+       xTaskCreate( prvMQTTDemoTask,          /* Function that implements the task. */\r
+                                "MQTTLWDemo",             /* Text name for the task - only used for debugging. */\r
+                                democonfigDEMO_STACKSIZE, /* Size of stack (in words, not bytes) to allocate for the task. */\r
+                                NULL,                     /* Task parameter - not used in this case. */\r
+                                tskIDLE_PRIORITY,         /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
+                                NULL );                   /* Used to pass out a handle to the created task - not used in this case. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvGracefulShutDown( Socket_t xSocket )\r
+{\r
+uint8_t ucDummy[ 20 ];\r
+const TickType_t xShortDelay = pdMS_TO_MIN_TICKS( 250 );\r
+\r
+       if( xSocket != ( Socket_t ) 0 )\r
+       {\r
+               if( xSocket != FREERTOS_INVALID_SOCKET )\r
+               {\r
+                       /* Initiate graceful shutdown. */\r
+                       FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );\r
+\r
+                       /* Wait for the socket to disconnect gracefully (indicated by FreeRTOS_recv()\r
+                        * returning a FREERTOS_EINVAL error) before closing the socket. */\r
+                       while( FreeRTOS_recv( xSocket, ucDummy, sizeof( ucDummy ), 0 ) >= 0 )\r
+                       {\r
+                               /* Wait for shutdown to complete.  If a receive block time is used then\r
+                                * this delay will not be necessary as FreeRTOS_recv() will place the RTOS task\r
+                                * into the Blocked state anyway. */\r
+                               vTaskDelay( xShortDelay );\r
+\r
+                               /* Note ? real applications should implement a timeout here, not just\r
+                                * loop forever. */\r
+                       }\r
+\r
+                       /* The socket has shut down and is safe to close. */\r
+                       FreeRTOS_closesocket( xSocket );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+IotMqttError_t getNextByte( void * pvContext,\r
+                                                       uint8_t * pNextByte )\r
+{\r
+Socket_t xMQTTSocket = ( Socket_t ) pvContext;\r
+BaseType_t receivedBytes;\r
+IotMqttError_t result;\r
+\r
+       /* Receive one byte from network */\r
+       receivedBytes = FreeRTOS_recv( xMQTTSocket, ( void * ) pNextByte, sizeof( uint8_t ), 0 );\r
+\r
+       if( receivedBytes == sizeof( uint8_t ) )\r
+       {\r
+               result = IOT_MQTT_SUCCESS;\r
+       }\r
+       else\r
+       {\r
+               result = IOT_MQTT_TIMEOUT;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvMQTTDemoTask( void * pvParameters )\r
+{\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+Socket_t xMQTTSocket;\r
+IotMqttError_t xReturned;\r
+uint32_t ulPublishCount = 0;\r
+const uint32_t ulMaxPublishCount = 5UL;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       for( ; ; )\r
+       {\r
+               /* Don't expect any notifications to be pending yet. */\r
+               configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+               /****************************** Connect. ******************************/\r
+\r
+               /* Establish a TCP connection with the MQTT broker. This example connects to\r
+                * the MQTT broker as specified in mqttexampleMQTT_BROKER_ENDPOINT and\r
+                * mqttexampleMQTT_BROKER_PORT at the top of this file. */\r
+               configPRINTF( ( "Create a TCP connection to %s\r\n", mqttexampleMQTT_BROKER_ENDPOINT ) );\r
+               xMQTTSocket = prvCreateTCPConnectionToBroker();\r
+               configASSERT( xMQTTSocket != FREERTOS_INVALID_SOCKET );\r
+               configPRINTF( ( "Connected to %s\r\n", mqttexampleMQTT_BROKER_ENDPOINT ) );\r
+\r
+               /* Sends an MQTT Connect packet over the already connected TCP socket\r
+                * xMQTTSocket, then waits for and interprets the reply. IOT_MQTT_SUCCESS is\r
+                * returned if the reply is a valid connection acknowledgeable (CONNACK) packet,\r
+                * otherwise an error code is returned. */\r
+               configPRINTF( ( "Creating an MQTT connection with %s\r\n", mqttexampleMQTT_BROKER_ENDPOINT ) );\r
+               xReturned = prvCreateMQTTConnectionWithBroker( xMQTTSocket );\r
+               configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+               configPRINTF( ( "Established an MQTT connection.\r\n" ) );\r
+\r
+               /**************************** Subscribe. ******************************/\r
+\r
+               /* The client is now connected to the broker. Subscribe to the topic\r
+                * as specified in mqttexampleTOPIC at the top of this file by sending a\r
+                * subscribe packet then waiting for a subscribe acknowledgment (SUBACK).\r
+                * This client will then publish to the same topic it subscribed to, so will\r
+                * expect all the messages it sends to the broker to be sent back to it\r
+                * from the broker. */\r
+               configPRINTF( ( "Attempt to subscribed to the MQTT topic %s\r\n", mqttexampleTOPIC ) );\r
+               xReturned = prvMQTTSubscribeToTopic( xMQTTSocket );\r
+               configPRINTF( ( "Subscribed to the topic %s\r\n", mqttexampleTOPIC ) );\r
+\r
+               /**************************** Publish. ******************************/\r
+               /* Send publish for with QOS0, Process Keep alive */\r
+               for( ulPublishCount = 0; ulPublishCount < ulMaxPublishCount; ulPublishCount++ )\r
+               {\r
+                       configPRINTF( ( "Attempt to publish to the MQTT topic %s\r\n", mqttexampleTOPIC ) );\r
+                       xReturned = prvMQTTPublishToTopic( xMQTTSocket );\r
+                       configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+                       configPRINTF( ( "Publish successful to the topic %s\r\n", mqttexampleTOPIC ) );\r
+\r
+                       /* Process incoming publish echo, since application subscribed to the same topic\r
+                        * broker will send publish message back to the application */\r
+                       configPRINTF( ( "Attempt to receive publish message from broker\r\n" ) );\r
+                       xReturned = prvMQTTProcessIncomingPublish( xMQTTSocket );\r
+                       configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+                       configPRINTF( ( "Successfully Received Publish message from broker\r\n" ) );\r
+\r
+                       /* Leave Connection Idle for some time */\r
+                       configPRINTF( ( "Keeping Connection Idle\r\n" ) );\r
+                       vTaskDelay( pdMS_TO_TICKS( mqttexampleKEEP_ALIVE_DELAY ) );\r
+                       /* Send Ping request to broker and receive ping response */\r
+                       configPRINTF( ( "Sending Ping Request to the broker\r\n" ) );\r
+                       xReturned = prvMQTTKeepAlive( xMQTTSocket );\r
+                       configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+                       configPRINTF( ( "Ping Response successfully received\r\n" ) );\r
+               }\r
+\r
+               /************************ Unsubscribe from the topic. **************************/\r
+               configPRINTF( ( "Attempt to unsubscribe from the MQTT topic %s\r\n", mqttexampleTOPIC ) );\r
+               xReturned = prvMQTTUnsubscribeFromTopic( xMQTTSocket );\r
+               configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+               configPRINTF( ( "Unsubscribe from the topic %s\r\n", mqttexampleTOPIC ) );\r
+\r
+               /**************************** Disconnect. ******************************/\r
+\r
+               /* Sends an MQTT Disconnect packet over the already connected TCP socket\r
+                * xMQTTSocket, then waits for and interprets the reply.  IOT_MQTT_SUCCESS is\r
+                * returned if the reply is a valid connection acknowledgeable (CONNACK) packet,\r
+                * otherwise an error code is returned. */\r
+\r
+               configPRINTF( ( "Creating an MQTT connection with %s\r\n", mqttexampleMQTT_BROKER_ENDPOINT ) );\r
+               xReturned = prvMQTTDisconnect( xMQTTSocket );\r
+               configASSERT( xReturned == IOT_MQTT_SUCCESS );\r
+               configPRINTF( ( "Established an MQTT connection.\r\n" ) );\r
+               /* Disconnect from broker. */\r
+               prvGracefulShutDown( xMQTTSocket );\r
+\r
+               /* Wait for some time between two iterations to ensure that we do not\r
+                * bombard the public test mosquitto broker. */\r
+               configPRINTF( ( "prvMQTTDemoTask() completed an iteration successfully. Total free heap is %u\r\n", xPortGetFreeHeapSize() ) );\r
+               configPRINTF( ( "Short delay before starting the next iteration.... \r\n\r\n" ) );\r
+               vTaskDelay( pdMS_TO_TICKS( mqttexampleDELAY_BETWEEN_DEMO_ITERATIONS ) );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+Socket_t prvCreateTCPConnectionToBroker( void )\r
+{\r
+Socket_t xMQTTSocket;\r
+       struct freertos_sockaddr xBrokerAddress;\r
+       uint32_t ulBrokerIPAddress;\r
+\r
+       /* This is the socket used to connect to the MQTT broker. */\r
+       xMQTTSocket = FreeRTOS_socket( FREERTOS_AF_INET,\r
+                                                                  FREERTOS_SOCK_STREAM,\r
+                                                                  FREERTOS_IPPROTO_TCP );\r
+\r
+       configASSERT( xMQTTSocket != FREERTOS_INVALID_SOCKET );\r
+\r
+       /* Locate then connect to the MQTT broker. */\r
+       ulBrokerIPAddress = FreeRTOS_gethostbyname( mqttexampleMQTT_BROKER_ENDPOINT );\r
+\r
+       if( ulBrokerIPAddress != 0 )\r
+       {\r
+               xBrokerAddress.sin_port = FreeRTOS_htons( mqttexampleMQTT_BROKER_PORT );\r
+               xBrokerAddress.sin_addr = ulBrokerIPAddress;\r
+\r
+               if( FreeRTOS_connect( xMQTTSocket, &xBrokerAddress, sizeof( xBrokerAddress ) ) != 0 )\r
+               {\r
+                       /* Could not connect so delete socket and return an error. */\r
+                       FreeRTOS_closesocket( xMQTTSocket );\r
+                       xMQTTSocket = FREERTOS_INVALID_SOCKET;\r
+               }\r
+       }\r
+\r
+       return xMQTTSocket;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvCreateMQTTConnectionWithBroker( Socket_t xMQTTSocket )\r
+{\r
+IotMqttConnectInfo_t xConnectInfo;\r
+size_t xRemainingLength = 0;\r
+size_t xPacketSize = 0;\r
+IotMqttError_t xResult;\r
+IotMqttPacketInfo_t xIncomingPacket;\r
+\r
+       /* Many fields not used in this demo so start with everything at 0. */\r
+       memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) );\r
+       memset( ( void * ) &xIncomingPacket, 0x00, sizeof( xIncomingPacket ) );\r
+\r
+       /* Start with a clean session i.e. direct the MQTT broker to discard any\r
+        * previous session data. Also, establishing a connection with clean session\r
+        * will ensure that the broker does not store any data when this client\r
+        * gets disconnected. */\r
+       xConnectInfo.cleanSession = true;\r
+\r
+       /* The client identifier is used to uniquely identify this MQTT client to\r
+        * the MQTT broker.  In a production device the identifier can be something\r
+        * unique, such as a device serial number. */\r
+       xConnectInfo.pClientIdentifier = mqttexampleCLIENT_IDENTIFIER;\r
+       xConnectInfo.clientIdentifierLength = ( uint16_t ) strlen( mqttexampleCLIENT_IDENTIFIER );\r
+\r
+       /* Get size requirement for the connect packet */\r
+       xResult = IotMqtt_GetConnectPacketSize( &xConnectInfo, &xRemainingLength, &xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+       /* Make sure the packet size is less than static buffer size */\r
+       configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );\r
+       /* Serialize MQTT connect packet into provided buffer */\r
+       xResult = IotMqtt_SerializeConnect( &xConnectInfo, xRemainingLength, ucSharedBuffer, xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 ) == ( BaseType_t ) xPacketSize )\r
+       {\r
+               /* Wait for the connection ack. TODO check the receive timeout value. */\r
+\r
+               memset( ( void * ) &xIncomingPacket, 0x00, sizeof( IotMqttPacketInfo_t ) );\r
+\r
+               /* Get packet type and remaining length of the received packet\r
+                * We cannot assume received data is the connection acknowledgment.\r
+                * Therefore this function reads type and remaining length of the\r
+                * received packet, before processing entire packet.\r
+                */\r
+               xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );\r
+               configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+               configASSERT( xIncomingPacket.type == MQTT_PACKET_TYPE_CONNACK );\r
+               configASSERT( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+               if( FreeRTOS_recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 )\r
+                       == ( BaseType_t ) xIncomingPacket.remainingLength )\r
+               {\r
+                       xIncomingPacket.pRemainingData = ucSharedBuffer;\r
+\r
+                       if( IotMqtt_DeserializeResponse( &xIncomingPacket ) != IOT_MQTT_SUCCESS )\r
+                       {\r
+                               xResult = IOT_MQTT_SERVER_REFUSED;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       configPRINTF( ( "Receive Failed while receiving MQTT ConnAck\n" ) );\r
+                       xResult = IOT_MQTT_NETWORK_ERROR;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               configPRINTF( ( "Send Failed while connecting to MQTT broker\n" ) );\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTSubscribeToTopic( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttSubscription_t xMQTTSubscription[ 1 ];\r
+size_t xRemainingLength = 0;\r
+size_t xPacketSize = 0;\r
+uint16_t usPacketIdentifier;\r
+IotMqttPacketInfo_t xIncomingPacket;\r
+\r
+       /* Some fields not used by this demo so start with everything at 0. */\r
+       memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) );\r
+\r
+       /* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to only one topic */\r
+       xMQTTSubscription[ 0 ].qos = IOT_MQTT_QOS_0;\r
+       xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC;\r
+       xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+\r
+       xResult = IotMqtt_GetSubscriptionPacketSize( IOT_MQTT_SUBSCRIBE,\r
+                                                                                                xMQTTSubscription,\r
+                                                                                                sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),\r
+                                                                                                &xRemainingLength, &xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+       /* Make sure the packet size is less than static buffer size */\r
+       configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       /* Serialize subscribe into statically allocated ucSharedBuffer */\r
+       xResult = IotMqtt_SerializeSubscribe( xMQTTSubscription,\r
+                                                                                 sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),\r
+                                                                                 xRemainingLength,\r
+                                                                                 &usPacketIdentifier,\r
+                                                                                 ucSharedBuffer,\r
+                                                                                 xPacketSize );\r
+\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 ) == ( BaseType_t ) xPacketSize )\r
+       {\r
+               /* Wait for the subscription ack. The socket is already connected to the MQTT broker, so\r
+                * publishes to this client can occur at any time and we cannot assume received\r
+                * data is the subscription acknowledgment.  Therefore this function is, at this\r
+                * time, doing what would otherwise be done wherever incoming packets are\r
+                * interpreted (in a callback, or whatever). */\r
+               memset( ( void * ) &xIncomingPacket, 0x00, sizeof( IotMqttPacketInfo_t ) );\r
+               xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );\r
+               configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+               configASSERT( xIncomingPacket.type == MQTT_PACKET_TYPE_SUBACK );\r
+               configASSERT( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+               /* Receive the remaining bytes. */\r
+               if( FreeRTOS_recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 ) == ( BaseType_t ) xIncomingPacket.remainingLength )\r
+               {\r
+                       xIncomingPacket.pRemainingData = ucSharedBuffer;\r
+\r
+                       if( IotMqtt_DeserializeResponse( &xIncomingPacket ) != IOT_MQTT_SUCCESS )\r
+                       {\r
+                               xResult = IOT_MQTT_BAD_RESPONSE;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       xResult = IOT_MQTT_NETWORK_ERROR;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTPublishToTopic( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttPublishInfo_t xMQTTPublishInfo;\r
+size_t xRemainingLength = 0;\r
+size_t xPacketSize = 0;\r
+uint16_t usPacketIdentifier;\r
+uint8_t * pusPacketIdentifierHigh;\r
+\r
+       /* Some fields not used by this demo so start with everything at 0. */\r
+       memset( ( void * ) &xMQTTPublishInfo, 0x00, sizeof( xMQTTPublishInfo ) );\r
+       xMQTTPublishInfo.qos = IOT_MQTT_QOS_0;\r
+       xMQTTPublishInfo.retain = false;\r
+       xMQTTPublishInfo.pTopicName = mqttexampleTOPIC;\r
+       xMQTTPublishInfo.topicNameLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+       xMQTTPublishInfo.pPayload = mqttexampleMESSAGE;\r
+       xMQTTPublishInfo.payloadLength = strlen( mqttexampleMESSAGE );\r
+\r
+       /* Find out length of Publish packet size. */\r
+       xResult = IotMqtt_GetPublishPacketSize( &xMQTTPublishInfo, &xRemainingLength, &xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+       /* Make sure the packet size is less than static buffer size */\r
+       configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       xResult = IotMqtt_SerializePublish( &xMQTTPublishInfo,\r
+                                                                               xRemainingLength,\r
+                                                                               &usPacketIdentifier,\r
+                                                                               &pusPacketIdentifierHigh,\r
+                                                                               ucSharedBuffer,\r
+                                                                               xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 ) != ( BaseType_t ) xPacketSize )\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+       else\r
+       {\r
+               /* Send success. Since in this case, we are using IOT_MQTT_QOS_0,\r
+                * there will not be any PubAck. Publish will be echoed back, which is processed\r
+                * in prvMQTTProcessIncomingPublish() */\r
+               xResult = IOT_MQTT_SUCCESS;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTProcessIncomingPublish( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttPacketInfo_t xIncomingPacket;\r
+\r
+       memset( ( void * ) &xIncomingPacket, 0x00, sizeof( IotMqttPacketInfo_t ) );\r
+       xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+       configASSERT( ( xIncomingPacket.type & 0xf0 ) == MQTT_PACKET_TYPE_PUBLISH );\r
+       configASSERT( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       /* Receive the remaining bytes. */\r
+       if( FreeRTOS_recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 ) == ( BaseType_t ) xIncomingPacket.remainingLength )\r
+       {\r
+               xIncomingPacket.pRemainingData = ucSharedBuffer;\r
+\r
+               if( IotMqtt_DeserializePublish( &xIncomingPacket ) != IOT_MQTT_SUCCESS )\r
+               {\r
+                       xResult = IOT_MQTT_BAD_RESPONSE;\r
+               }\r
+               else\r
+               {\r
+                       /* Process incoming Publish */\r
+                       configPRINTF( ( "Incoming QOS : %d\n", xIncomingPacket.pubInfo.qos ) );\r
+                       configPRINTF( ( "Incoming Publish Topic Name: %.*s\n", xIncomingPacket.pubInfo.topicNameLength, xIncomingPacket.pubInfo.pTopicName ) );\r
+                       configPRINTF( ( "Incoming Publish Message : %.*s\n", xIncomingPacket.pubInfo.payloadLength, xIncomingPacket.pubInfo.pPayload ) );\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTUnsubscribeFromTopic( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttSubscription_t xMQTTSubscription[ 1 ];\r
+size_t xRemainingLength;\r
+size_t xPacketSize;\r
+uint16_t usPacketIdentifier;\r
+IotMqttPacketInfo_t xIncomingPacket;\r
+\r
+       /* Some fields not used by this demo so start with everything at 0. */\r
+       memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) );\r
+\r
+       /* Unsubscribe to the mqttexampleTOPIC topic filter. The task handle is passed\r
+        * as the callback context which is used by the callback to send a task\r
+        * notification to this task.*/\r
+       xMQTTSubscription[ 0 ].qos = IOT_MQTT_QOS_0;\r
+       xMQTTSubscription[ 0 ].pTopicFilter = mqttexampleTOPIC;\r
+       xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( mqttexampleTOPIC );\r
+\r
+       xResult = IotMqtt_GetSubscriptionPacketSize( IOT_MQTT_UNSUBSCRIBE,\r
+                                                                                                xMQTTSubscription,\r
+                                                                                                sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),\r
+                                                                                                &xRemainingLength,\r
+                                                                                                &xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+       /* Make sure the packet size is less than static buffer size */\r
+       configASSERT( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       xResult = IotMqtt_SerializeUnsubscribe( xMQTTSubscription,\r
+                                                                                       sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),\r
+                                                                                       xRemainingLength,\r
+                                                                                       &usPacketIdentifier,\r
+                                                                                       ucSharedBuffer,\r
+                                                                                       xPacketSize );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 ) == ( BaseType_t ) xPacketSize )\r
+       {\r
+               /* Wait for the subscription ack. The socket is already connected to the MQTT broker, so\r
+                * publishes to this client can occur at any time and we cannot assume received\r
+                * data is the subscription acknowledgment.  Therefore this function is, at this\r
+                * time, doing what would otherwise be done wherever incoming packets are\r
+                * interpreted (in a callback, or whatever). */\r
+               memset( ( void * ) &xIncomingPacket, 0x00, sizeof( IotMqttPacketInfo_t ) );\r
+               xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );\r
+               configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+               configASSERT( xIncomingPacket.type == MQTT_PACKET_TYPE_UNSUBACK );\r
+               configASSERT( xIncomingPacket.remainingLength <= sizeof( ucSharedBuffer ) );\r
+\r
+               /* Receive the remaining bytes. */\r
+               if( FreeRTOS_recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 ) == ( BaseType_t ) xIncomingPacket.remainingLength )\r
+               {\r
+                       xIncomingPacket.pRemainingData = ucSharedBuffer;\r
+\r
+                       if( IotMqtt_DeserializeResponse( &xIncomingPacket ) != IOT_MQTT_SUCCESS )\r
+                       {\r
+                               xResult = IOT_MQTT_BAD_RESPONSE;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       xResult = IOT_MQTT_NETWORK_ERROR;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTKeepAlive( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+IotMqttPacketInfo_t xIncomingPacket;\r
+\r
+       /* PingReq is fixed length packet, therefore there is no need to calculate the size,\r
+        * just makes sure static buffer can accommodate ping request */\r
+\r
+       configASSERT( MQTT_PACKET_PINGREQ_SIZE <= mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       xResult = IotMqtt_SerializePingreq( ucSharedBuffer, MQTT_PACKET_PINGREQ_SIZE );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, MQTT_PACKET_PINGREQ_SIZE, 0 ) == ( BaseType_t ) MQTT_PACKET_PINGREQ_SIZE )\r
+       {\r
+               memset( ( void * ) &xIncomingPacket, 0x00, sizeof( IotMqttPacketInfo_t ) );\r
+               xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );\r
+               configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+               configASSERT( xIncomingPacket.type == MQTT_PACKET_TYPE_PINGRESP );\r
+               configASSERT( xIncomingPacket.remainingLength <= sizeof( ucSharedBuffer ) );\r
+\r
+               /* Receive the remaining bytes. */\r
+               if( FreeRTOS_recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 )\r
+                       == ( BaseType_t ) xIncomingPacket.remainingLength )\r
+               {\r
+                       xIncomingPacket.pRemainingData = ucSharedBuffer;\r
+\r
+                       if( IotMqtt_DeserializeResponse( &xIncomingPacket ) != IOT_MQTT_SUCCESS )\r
+                       {\r
+                               xResult = IOT_MQTT_BAD_RESPONSE;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       xResult = IOT_MQTT_NETWORK_ERROR;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+static IotMqttError_t prvMQTTDisconnect( Socket_t xMQTTSocket )\r
+{\r
+IotMqttError_t xResult;\r
+\r
+       /* Disconnect is fixed length packet, therefore there is no need to calculate the size,\r
+        * just makes sure static buffer can accommodate disconnect request */\r
+\r
+       configASSERT( MQTT_PACKET_DISCONNECT_SIZE <= mqttexampleSHARED_BUFFER_SIZE );\r
+\r
+       xResult = IotMqtt_SerializeDisconnect( ucSharedBuffer, MQTT_PACKET_DISCONNECT_SIZE );\r
+       configASSERT( xResult == IOT_MQTT_SUCCESS );\r
+\r
+       if( FreeRTOS_send( xMQTTSocket, ( void * ) ucSharedBuffer, MQTT_PACKET_DISCONNECT_SIZE, 0 ) == ( BaseType_t ) MQTT_PACKET_DISCONNECT_SIZE )\r
+       {\r
+               xResult = IOT_MQTT_SUCCESS;\r
+       }\r
+       else\r
+       {\r
+               xResult = IOT_MQTT_NETWORK_ERROR;\r
+       }\r
+\r
+       return xResult;\r
+}\r