/*
 * IoT MQTT V2.1.1
 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file iot_mqtt_lightweight.h
 * @brief User-facing functions for serializing MQTT 3.1.1 packets. This header should
 * be included for building a single threaded light-weight MQTT client bypassing
 * stateful CSDK MQTT library.
 */

#ifndef _IOT_MQTT_LIGHTWEIGHT_H_
#define _IOT_MQTT_LIGHTWEIGHT_H_

/* The config header is always included first. */
#include "iot_config.h"

/* MQTT types include. */
#include "types/iot_mqtt_types.h"

/*------------------------- MQTT library functions --------------------------*/

/**
 * @functionspage{mqtt,MQTT library}
 * - @functionname{mqtt_function_getconnectpacketsize}
 * - @functionname{mqtt_function_serializeconnect}
 * - @functionname{mqtt_function_getsubscriptionpacketsize}
 * - @functionname{mqtt_function_serializesubscribe}
 * - @functionname{mqtt_function_serializeunsubscribe}
 * - @functionname{mqtt_function_getpublishpacketsize}
 * - @functionname{mqtt_function_serializepublish}
 * - @functionname{mqtt_function_serializedisconnect}
 * - @functionname{mqtt_function_serializepingreq}
 * - @functionname{mqtt_function_getincomingmqttpackettypeandlength}
 * - @functionname{mqtt_function_deserializeresponse}
 * - @functionname{mqtt_function_deserializepublish}
 */

/**
 * @functionpage{IotMqtt_GetConnectPacketSize,mqtt,getconnectpacketsize}
 * @functionpage{IotMqtt_SerializeConnect,mqtt,serializeconnect}
 * @functionpage{IotMqtt_GetSubscriptionPacketSize,mqtt,getsubscriptionpacketsize}
 * @functionpage{IotMqtt_SerializeSubscribe,mqtt,serializesubscribe}
 * @functionpage{IotMqtt_SerializeUnsubscribe,mqtt,serializeunsubscribe}
 * @functionpage{IotMqtt_GetPublishPacketSize,mqtt,getpublishpacketsize}
 * @functionpage{IotMqtt_SerializePublish,mqtt,serializepublish}
 * @functionpage{IotMqtt_SerializeDisconnect,mqtt,serializedisconnect}
 * @functionpage{IotMqtt_SerializePingreq,mqtt,serializepingreq}
 * @functionpage{IotMqtt_GetIncomingMQTTPacketTypeAndLength,mqtt,getincomingmqttpackettypeandlength}
 * @functionpage{IotMqtt_DeserializeResponse,mqtt,deserializeresponse}
 * @functionpage{IotMqtt_DeserializePublish,mqtt,deserializepublish}
 */

/**
 * @brief Calculate the size and "Remaining length" of a CONNECT packet generated
 * from the given parameters.
 *
 * @param[in] pConnectInfo User-provided CONNECT information struct.
 * @param[out] pRemainingLength Output for calculated "Remaining length" field.
 * @param[out] pPacketSize Output for calculated total packet size.
 *
 * @return IOT_MQTT_SUCCESS if the packet is within the length allowed by MQTT 3.1.1 spec;
 * IOT_MQTT_BAD_PARAMETER otherwise. If this function returns `IOT_MQTT_BAD_PARAMETER`,
 * the output parameters should be ignored.
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_GetConnectPacketSize() should be used to calculate
 * // the size of connect request.
 *
 * IotMqttConnectInfo_t xConnectInfo;
 * size_t xRemainingLength = 0;
 * size_t xPacketSize = 0;
 * IotMqttError_t xResult;
 *
 * // start with everything set to zero
 * memset( ( void * ) &xConnectInfo, 0x00, sizeof( xConnectInfo ) );
 *
 * // Initialize connection info, details are out of scope for this example.
 * _initializeConnectInfo( &xConnectInfo );
 * // Get size requirement for the connect packet
 * xResult = IotMqtt_GetConnectPacketSize( &xConnectInfo, &xRemainingLength, &xPacketSize );
 * IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 *  // Application should allocate buffer with size == xPacketSize or use static buffer
 *  // with size >= xPacketSize to serialize connect request.
 * @endcode
 */
/* @[declare_mqtt_getconnectpacketsize] */
IotMqttError_t IotMqtt_GetConnectPacketSize( const IotMqttConnectInfo_t * pConnectInfo,
                                             size_t * pRemainingLength,
                                             size_t * pPacketSize );
/* @[declare_mqtt_getconnectpacketsize] */

/**
 * @brief Generate a CONNECT packet from the given parameters.
 *
 * @param[in] pConnectInfo User-provided CONNECT information.
 * @param[in] remainingLength remaining length of the packet to be serialized.
 * @param[in, out] pBuffer User provided buffer where the CONNECT packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
 *
 * @note pBuffer must be allocated by caller. Use @ref mqtt_function_getconnectpacketsize
 * to determine the required size.
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_SerializeConnect() should be used to serialize
 * // MQTT connect packet and send it to MQTT broker.
 * // Example uses static memory but dynamically allocated memory can be used as well.
 * // Get size requirement for the connect packet.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendConnectPacket( int xMQTTSocket )
 * {
 *    IotMqttConnectInfo_t xConnectInfo;
 *    size_t xRemainingLength = 0;
 *    size_t xPacketSize = 0;
 *    IotMqttError_t xResult;
 *    size_t xSentBytes = 0;
 *    // Get size requirement for MQTT connect packet.
 *    xResult = IotMqtt_GetConnectPacketSize( &xConnectInfo, &xRemainingLength, &xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // Make sure the packet size is less than static buffer size
 *    IotMqtt_Assert( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );
 *    // Serialize MQTT connect packet into provided buffer
 *    xResult = IotMqtt_SerializeConnect( &xConnectInfo, xRemainingLength, ucSharedBuffer, xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentBytes = send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 );
 *    IotMqtt_Assert( xSentBytes == xPacketSize );
 * }
 * @endcode
 */
/* @[declare_mqtt_serializeconnect] */
IotMqttError_t IotMqtt_SerializeConnect( const IotMqttConnectInfo_t * pConnectInfo,
                                         size_t remainingLength,
                                         uint8_t * pBuffer,
                                         size_t bufferSize );
/* @[declare_mqtt_serializeconnect] */

/**
 * @brief Calculate the size and "Remaining length" of a SUBSCRIBE or UNSUBSCRIBE
 * packet generated from the given parameters.
 *
 * @param[in] type Either IOT_MQTT_SUBSCRIBE or IOT_MQTT_UNSUBSCRIBE.
 * @param[in] pSubscriptionList User-provided array of subscriptions.
 * @param[in] subscriptionCount Size of `pSubscriptionList`.
 * @param[out] pRemainingLength Output for calculated "Remaining length" field.
 * @param[out] pPacketSize Output for calculated total packet size.
 *
 * @return IOT_MQTT_SUCCESS if the packet is within the length allowed by MQTT 3.1.1 spec;
 * IOT_MQTT_BAD_PARAMETER otherwise. If this function returns IOT_MQTT_BAD_PARAMETER,
 * the output parameters should be ignored.
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_GetSubscriptionPacketSize() should be used to calculate
 * // the size of subscribe or unsubscribe request.
 *
 * IotMqttError_t xResult;
 * IotMqttSubscription_t xMQTTSubscription[ 1 ];
 * size_t xRemainingLength = 0;
 * size_t xPacketSize = 0;
 *
 * // Initialize Subscribe parameters. Details are out of scope for this example.
 * // It will involve setting QOS, topic filter  and topic filter length.
 *  _initializeSubscribe( xMQTTSubscription );
 *
 * xResult = IotMqtt_GetSubscriptionPacketSize( IOT_MQTT_SUBSCRIBE,
 *												 xMQTTSubscription,
 *												 sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),
 *												 &xRemainingLength, &xPacketSize );
 * IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 * // Application should allocate buffer with size == xPacketSize or use static buffer
 * // with size >= xPacketSize to serialize connect request.
 * @endcode
 */
/* @[declare_mqtt_getsubscriptionpacketsize] */
IotMqttError_t IotMqtt_GetSubscriptionPacketSize( IotMqttOperationType_t type,
                                                  const IotMqttSubscription_t * pSubscriptionList,
                                                  size_t subscriptionCount,
                                                  size_t * pRemainingLength,
                                                  size_t * pPacketSize );
/* @[declare_mqtt_getsubscriptionpacketsize] */

/**
 * @brief Generate a SUBSCRIBE packet from the given parameters.
 *
 * @param[in] pSubscriptionList User-provided array of subscriptions.
 * @param[in] subscriptionCount Size of `pSubscriptionList`.
 * @param[in] remainingLength remaining length of the packet to be serialized.
 * @param[out] pPacketIdentifier The packet identifier generated for this SUBSCRIBE.
 * @param[in, out] pBuffer User provide buffer where the SUBSCRIBE packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
 *
 * @note pBuffer must be allocated by caller.
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_SerializeSubscribe() should be used to serialize
 * // MQTT Subscribe packet and send it to MQTT broker.
 * // Example uses static memory, but dynamically allocated memory can be used as well.
 * // Get size requirement for the MQTT subscribe packet.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendSubscribePacket( int xMQTTSocket )
 * {
 *    IotMqttSubscription_t xMQTTSubscription[ 1 ];
 *    size_t xRemainingLength = 0;
 *    size_t xPacketSize = 0;
 *    IotMqttError_t xResult;
 *    size_t xSentBytes = 0;
 *
 *    // Initialize Subscribe parameters. Details are out of scope for this example.
 *    // It will involve setting QOS, topic filter  and topic filter length.
 *    _initializeSubscribe( xMQTTSubscription );
 *    // Get size requirement for MQTT Subscribe packet.
 *    xResult = IotMqtt_GetSubscriptionPacketSize( IOT_MQTT_SUBSCRIBE,
 *												 xMQTTSubscription,
 *												 sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),
 *												 &xRemainingLength, &xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // Make sure the packet size is less than static buffer size.
 *    IotMqtt_Assert( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );
 *
 *    // Serialize subscribe into statically allocated ucSharedBuffer.
 *	   xResult = IotMqtt_SerializeSubscribe( xMQTTSubscription,
 *										  sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),
 *										  xRemainingLength,
 *										  &usPacketIdentifier,
 *										  ucSharedBuffer,
 *										  xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentBytes = send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 );
 *    IotMqtt_Assert( xSentBytes == xPacketSize );
 * }
 * @endcode
 */
/* @[declare_mqtt_serializesubscribe] */
IotMqttError_t IotMqtt_SerializeSubscribe( const IotMqttSubscription_t * pSubscriptionList,
                                           size_t subscriptionCount,
                                           size_t remainingLength,
                                           uint16_t * pPacketIdentifier,
                                           uint8_t * pBuffer,
                                           size_t bufferSize );
/* @[declare_mqtt_serializesubscribe] */

/**
 * @brief Generate a UNSUBSCRIBE packet from the given parameters.
 *
 * @param[in] pSubscriptionList User-provided array of subscriptions to remove.
 * @param[in] subscriptionCount Size of `pSubscriptionList`.
 * @param[in] remainingLength remaining length of the packet to be serialized.
 * @param[out] pPacketIdentifier The packet identifier generated for this UNSUBSCRIBE.
 * @param[in, out] pBuffer User provide buffer where the UNSUBSCRIBE packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_NO_MEMORY.
 *
 * @note pBuffer must be allocated by caller.
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_SerializeUnsubscribe() should be used to serialize
 * // MQTT unsubscribe packet and send it to MQTT broker.
 * // Example uses static memory, but dynamically allocated memory can be used as well.
 * // Get size requirement for the Unsubscribe packet.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendUnsubscribePacket( int xMQTTSocket )
 * {
 *    // Following example shows one topic example.
 *    IotMqttSubscription_t xMQTTSubscription[ 1 ];
 *    size_t xRemainingLength = 0;
 *    size_t xPacketSize = 0;
 *    IotMqttError_t xResult;
 *    size_t xSentBytes = 0;
 *    // Get size requirement for MQTT unsubscribe packet.
 *    xResult = IotMqtt_GetSubscriptionPacketSize( IOT_MQTT_UNSUBSCRIBE,
 *												 xMQTTSubscription,
 *												 sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),
 *												 &xRemainingLength, &xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // Make sure the packet size is less than static buffer size.
 *    IotMqtt_Assert( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );
 *    // Serialize subscribe into statically allocated ucSharedBuffer.
 *	   xResult = IotMqtt_SerializeUnsubscribe( xMQTTSubscription,
 *										  sizeof( xMQTTSubscription ) / sizeof( IotMqttSubscription_t ),
 *										  xRemainingLength,
 *										  &usPacketIdentifier,
 *										  ucSharedBuffer,
 *										  xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentBytes = send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 );
 *    IotMqtt_Assert( xSentBytes == xPacketSize );
 * }
 * @endcode
 */
/* @[declare_mqtt_serializeunsubscribe] */
IotMqttError_t IotMqtt_SerializeUnsubscribe( const IotMqttSubscription_t * pSubscriptionList,
                                             size_t subscriptionCount,
                                             size_t remainingLength,
                                             uint16_t * pPacketIdentifier,
                                             uint8_t * pBuffer,
                                             size_t bufferSize );
/* @[declare_mqtt_serializeunsubscribe] */

/**
 * @brief Calculate the size and "Remaining length" of a PUBLISH packet generated
 * from the given parameters.
 *
 * @param[in] pPublishInfo User-provided PUBLISH information struct.
 * @param[out] pRemainingLength Output for calculated "Remaining length" field.
 * @param[out] pPacketSize Output for calculated total packet size.
 *
 * @return IOT_MQTT_SUCCESS if the packet is within the length allowed by MQTT 3.1.1 spec;
 * IOT_MQTT_BAD_PARAMETER otherwise. If this function returns IOT_MQTT_BAD_PARAMETER,
 * the output parameters should be ignored.
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_GetPublishPacketSize() should be used to calculate
 * // the size of MQTT publish request.
 *
 * IotMqttError_t xResult;
 * IotMqttPublishInfo_t xMQTTPublishInfo;
 * size_t xRemainingLength = 0;
 * size_t xPacketSize = 0;
 *
 * // Initialize Publish parameters. Details are out of scope for this example.
 * // It will involve setting QOS, topic filter, topic filter length, payload
 * // payload length
 *  _initializePublish( &xMQTTPublishInfo );
 *
 * // Find out length of Publish packet size.
 * xResult = IotMqtt_GetPublishPacketSize( &xMQTTPublishInfo, &xRemainingLength, &xPacketSize );
 * IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 * // Application should allocate buffer with size == xPacketSize or use static buffer
 * // with size >= xPacketSize to serialize connect request.
 * @endcode
 */
/* @[declare_mqtt_getpublishpacketsize] */
IotMqttError_t IotMqtt_GetPublishPacketSize( const IotMqttPublishInfo_t * pPublishInfo,
                                             size_t * pRemainingLength,
                                             size_t * pPacketSize );
/* @[declare_mqtt_getpublishpacketsize] */

/**
 * @brief Generate a PUBLISH packet from the given parameters.
 *
 * @param[in] pPublishInfo User-provided PUBLISH information.
 * @param[in] remainingLength remaining length of the packet to be serialized.
 * @param[out] pPacketIdentifier The packet identifier generated for this PUBLISH.
 * @param[out] pPacketIdentifierHigh Where the high byte of the packet identifier
 * is written.
 * @param[in, out] pBuffer User provide buffer where the PUBLISH packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_BAD_PARAMETER.
 *
 * @note pBuffer must be allocated by caller.
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how IotMqtt_SerializePublish() should be used to serialize
 * // MQTT Publish packet and send it to broker.
 * // Example uses static memory, but dynamically allocated memory can be used as well.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendUnsubscribePacket( int xMQTTSocket )
 * {
 *    IotMqttError_t xResult;
 *    IotMqttPublishInfo_t xMQTTPublishInfo;
 *    size_t xRemainingLength = 0;
 *    size_t xPacketSize = 0;
 *    size_t xSentBytes = 0;
 *    uint16_t usPacketIdentifier;
 *    uint8_t * pusPacketIdentifierHigh;
 *
 *    // Initialize Publish parameters. Details are out of scope for this example.
 *    // It will involve setting QOS, topic filter, topic filter length, payload
 *    // payload length.
 *    _initializePublish( &xMQTTPublishInfo );
 *
 *    // Find out length of Publish packet size.
 *    xResult = IotMqtt_GetPublishPacketSize( &xMQTTPublishInfo, &xRemainingLength, &xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    // Make sure the packet size is less than static buffer size
 *	  IotMqtt_Assert( xPacketSize < mqttexampleSHARED_BUFFER_SIZE );
 *
 *    xResult = IotMqtt_SerializePublish( &xMQTTPublishInfo,
 *										xRemainingLength,
 *										&usPacketIdentifier,
 *										&pusPacketIdentifierHigh,
 *										ucSharedBuffer,
 *										xPacketSize );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentBytes = send( xMQTTSocket, ( void * ) ucSharedBuffer, xPacketSize, 0 );
 *    IotMqtt_Assert( xSentBytes == xPacketSize );
 * }
 * @endcode
 */
/* @[declare_mqtt_serializepublish] */
IotMqttError_t IotMqtt_SerializePublish( const IotMqttPublishInfo_t * pPublishInfo,
                                         size_t remainingLength,
                                         uint16_t * pPacketIdentifier,
                                         uint8_t ** pPacketIdentifierHigh,
                                         uint8_t * pBuffer,
                                         size_t bufferSize );
/* @[declare_mqtt_serializepublish] */

/**
 * @brief Generate a DISCONNECT packet
 *
 * @param[in, out] pBuffer User provide buffer where the DISCONNECT packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return  returns #IOT_MQTT_SUCCESS or #IOT_MQTT_BAD_PARAMETER
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example below shows how IotMqtt_SerializeDisconnect() should be used.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendDisconnectRequest( int xMQTTSocket )
 * {
 *     size_t xSentBytes = 0;
 *
 *    // Disconnect is fixed length packet, therefore there is no need to calculate the size,
 *    // just makes sure static buffer can accommodate disconnect request.
 *    IotMqtt_Assert( MQTT_PACKET_DISCONNECT_SIZE <= mqttexampleSHARED_BUFFER_SIZE );
 *
 *    // Serialize Disconnect packet into static buffer (dynamically allocated buffer can be used as well)
 *    xResult = IotMqtt_SerializeDisconnect( ucSharedBuffer, MQTT_PACKET_DISCONNECT_SIZE );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentByte = send( xMQTTSocket, ( void * ) ucSharedBuffer, MQTT_PACKET_DISCONNECT_SIZE, 0 );
 *    IotMqtt_Assert( xSentByte == MQTT_PACKET_DISCONNECT_SIZE );
 * }
 *
 * @endcode
 */
/* @[declare_mqtt_serializedisconnect] */
IotMqttError_t IotMqtt_SerializeDisconnect( uint8_t * pBuffer,
                                            size_t bufferSize );
/* @[declare_mqtt_serializedisconnect] */

/**
 * @brief Generate a PINGREQ packet.
 *
 * @param[in, out] pBuffer User provide buffer where the PINGREQ packet is written.
 * @param[in] bufferSize Size of the buffer pointed to by pBuffer.
 *
 * @return #IOT_MQTT_SUCCESS or #IOT_MQTT_BAD_PARAMETER.
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example below shows how IotMqtt_SerializePingReq() should be used.
 *
 * #define mqttexampleSHARED_BUFFER_SIZE 100
 * static ucSharedBuffer[mqttexampleSHARED_BUFFER_SIZE];
 * void sendPingRequest( int xMQTTSocket )
 * {
 *    size_t xSentBytes = 0;
 *
 *    // PingReq is fixed length packet, therefore there is no need to calculate the size,
 *    // just makes sure static buffer can accommodate Ping request.
 *    IotMqtt_Assert( MQTT_PACKET_PINGREQ_SIZE <= mqttexampleSHARED_BUFFER_SIZE );
 *
 *    xResult = IotMqtt_SerializePingreq( ucSharedBuffer, MQTT_PACKET_PINGREQ_SIZE );
 *    IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *
 *    // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 *    xSentByte = send( xMQTTSocket, ( void * ) ucSharedBuffer, MQTT_PACKET_DISCONNECT_SIZE, 0 );
 *    IotMqtt_Assert( xSentByte ==  MQTT_PACKET_PINGREQ_SIZE);
 * }
 * @endcode
 */
/* @[declare_mqtt_serializepingreq] */
IotMqttError_t IotMqtt_SerializePingreq( uint8_t * pBuffer,
                                         size_t bufferSize );
/* @[declare_mqtt_serializepingreq] */

/**
 * @brief Extract MQTT packet type and length from incoming packet
 *
 * @param[in, out] pIncomingPacket Pointer to IotMqttPacketInfo_t structure
 * where type, remaining length and packet identifier are stored.
 * @param[in] getNextByte Pointer to platform specific function  which is used
 * to extract type and length from incoming received stream (see example ).
 * @param[in] pNetworkConnection Pointer to platform specific network connection
 * which is used by getNextByte to receive network data
 *
 * @return #IOT_MQTT_SUCCESS on successful extraction of type and length,
 * #IOT_MQTT_BAD_RESPONSE on failure.
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example code below shows how to implement getNextByte function with posix sockets.
 * // Note: IotMqttGetNextByte_t typedef IotMqttError_t (* IotMqttGetNextByte_t)( IotNetworkConnection_t pNetworkContext,
 * //                                              uint8_t * pNextByte );
 * // Note: It is assumed that socket is already created and connected,
 *
 * IotMqttError_t getNextByte( IotNetworkConnection_t pContext,
 *                           uint8_t * pNextByte )
 * {
 *      int socket = ( int ) ( *pvContext );
 *      int receivedBytes;
 *      IotMqttError_t result;
 *
 *      receivedBytes = recv( socket, ( void * ) pNextByte, sizeof( uint8_t ), 0 );
 *
 *      if( receivedBytes == sizeof( uint8_t ) )
 *      {
 *          result = IOT_MQTT_SUCCESS;
 *      }
 *      else
 *      {
 *          result = IOT_MQTT_TIMEOUT;
 *      }
 *
 *       return result;
 * }
 *
 * // Example below shows how IotMqtt_GetIncomingMQTTPacketTypeAndLength() is used to extract type
 * // and length from incoming ping response.
 * // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 * void getTypeAndLengthFromIncomingMQTTPingResponse( int xMQTTSocket )
 * {
 *    IotMqttPacketInfo_t xIncomingPacket;
 *    IotMqttError_t xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( IotNetworkConnection_t ) xMQTTSocket );
 *	  IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *    IotMqtt_Assert( xIncomingPacket.type == MQTT_PACKET_TYPE_PINGRESP );
 * }
 * @endcode
 *
 */
/* @[declare_mqtt_getincomingmqttpackettypeandlength] */
IotMqttError_t IotMqtt_GetIncomingMQTTPacketTypeAndLength( IotMqttPacketInfo_t * pIncomingPacket,
                                                           IotMqttGetNextByte_t getNextByte,
                                                           IotNetworkConnection_t pNetworkConnection );
/* @[declare_mqtt_getincomingmqttpackettypeandlength] */

/**
 * @brief Deserialize incoming publish packet.
 *
 * @param[in, out] pMqttPacket The caller of this API sets type, remainingLength and pRemainingData.
 * On success, packetIdentifier and pubInfo will be set by the function.
 *
 * @return One of the following:
 * - #IOT_MQTT_SUCCESS
 * - #IOT_MQTT_BAD_RESPONSE
 * - #IOT_MQTT_SERVER_REFUSED
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example below shows how IotMqtt_DeserializePublish() used to extract contents of incoming
 * // Publish.  xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 * void processIncomingPublish( int xMQTTSocket )
 * {
 *    IotMqttError_t xResult;
 *    IotMqttPacketInfo_t xIncomingPacket;
 *
 *	  xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );
 *	  IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *	  IotMqtt_Assert( ( xIncomingPacket.type & 0xf0 ) == MQTT_PACKET_TYPE_PUBLISH );
 *	  IotMqtt_Assert( xIncomingPacket.remainingLength <= mqttexampleSHARED_BUFFER_SIZE );
 *
 *	  // Receive the remaining bytes.
 *	  if( recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 ) ==  xIncomingPacket.remainingLength )
 *	  {
 *		xIncomingPacket.pRemainingData = ucSharedBuffer;
 *
 *		if( IotMqtt_DeserializePublish( &xIncomingPacket ) != IOT_MQTT_SUCCESS )
 *		{
 *			xResult = IOT_MQTT_BAD_RESPONSE;
 *		}
 *		else
 *		{
 *			// Process incoming Publish.
 *			IotLogInfo( "Incoming QOS : %d\n", xIncomingPacket.pubInfo.qos );
 *			IotLogInfo( "Incoming Publish Topic Name: %.*s\n", xIncomingPacket.pubInfo.topicNameLength, xIncomingPacket.pubInfo.pTopicName );
 *			IotLogInfo( "Incoming Publish Message : %.*s\n", xIncomingPacket.pubInfo.payloadLength, xIncomingPacket.pubInfo.pPayload  );
 *		}
 *	  }
 *	  else
 *	  {
 *		xResult = IOT_MQTT_NETWORK_ERROR;
 *	  }
 *
 *	IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 * }
 * @endcode
 */
/* @[declare_mqtt_deserializepublish] */
IotMqttError_t IotMqtt_DeserializePublish( IotMqttPacketInfo_t * pMqttPacket );
/* @[declare_mqtt_deserializepublish] */

/**
 * @brief Deserialize incoming ack packets.
 *
 * @param[in, out] pMqttPacket The caller of this API sets type, remainingLength and pRemainingData.
 * On success, packetIdentifier will be set.
 *
 * @return One of the following:
 * - #IOT_MQTT_SUCCESS
 * - #IOT_MQTT_BAD_RESPONSE
 * - #IOT_MQTT_SERVER_REFUSED
 *
 * @note This call is part of serializer API used for implementing light-weight MQTT client.
 *
 * <b>Example</b>
 * @code{c}
 * // Example below shows how  IotMqtt_DeserializeResponse() is used to process unsubscribe ack.
 * // xMQTTSocket here is posix socket created and connected to MQTT broker outside of this function.
 * void processUnsubscribeAck( int xMQTTSocket )
 * {
 *      IotMqttError_t xResult;
 *      IotMqttPacketInfo_t xIncomingPacket;
 *
 *      xResult = IotMqtt_GetIncomingMQTTPacketTypeAndLength( &xIncomingPacket, getNextByte, ( void * ) xMQTTSocket );
 *		IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 *		IotMqtt_Assert( xIncomingPacket.type == MQTT_PACKET_TYPE_UNSUBACK );
 *		IotMqtt_Assert( xIncomingPacket.remainingLength <= sizeof( ucSharedBuffer ) );
 *
 *		// Receive the remaining bytes.
 *		if( recv( xMQTTSocket, ( void * ) ucSharedBuffer, xIncomingPacket.remainingLength, 0 ) == xIncomingPacket.remainingLength )
 *		{
 *			xIncomingPacket.pRemainingData = ucSharedBuffer;
 *
 *			if( IotMqtt_DeserializeResponse( &xIncomingPacket ) != IOT_MQTT_SUCCESS )
 *			{
 *				xResult = IOT_MQTT_BAD_RESPONSE;
 *			}
 *		}
 *		else
 *		{
 *			xResult = IOT_MQTT_NETWORK_ERROR;
 *		}
 *      IotMqtt_Assert( xResult == IOT_MQTT_SUCCESS );
 * }
 * @endcode
 */
/* @[declare_mqtt_deserializeresponse] */
IotMqttError_t IotMqtt_DeserializeResponse( IotMqttPacketInfo_t * pMqttPacket );
/* @[declare_mqtt_deserializeresponse] */



#endif /* ifndef IOT_MQTT_SERIALIZE_H_ */
