static IotMqttError_t _deserializeIncomingPacket()

in device_firmware/libraries/c_sdk/standard/mqtt/src/iot_mqtt_network.c [277:657]


static IotMqttError_t _deserializeIncomingPacket( _mqttConnection_t * pMqttConnection,
                                                  _mqttPacket_t * pIncomingPacket )
{
    IotMqttError_t status = IOT_MQTT_STATUS_PENDING;
    _mqttOperation_t * pOperation = NULL;

    /* Deserializer function. */
    IotMqttError_t ( * deserialize )( _mqttPacket_t * ) = NULL;

    /* A buffer for remaining data must be allocated if remaining length is not 0. */
    IotMqtt_Assert( ( pIncomingPacket->remainingLength > 0 ) ==
                    ( pIncomingPacket->pRemainingData != NULL ) );

    /* Only valid packets should be given to this function. */
    IotMqtt_Assert( _incomingPacketValid( pIncomingPacket->type ) == true );

    /* Mask out the low bits of packet type to ignore flags. */
    switch( ( pIncomingPacket->type & 0xf0 ) )
    {
        case MQTT_PACKET_TYPE_CONNACK:
            IotLogDebug( "(MQTT connection %p) CONNACK in data stream.", pMqttConnection );

            /* Choose CONNACK deserializer. */
            deserialize = _IotMqtt_DeserializeConnack;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.connack != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.connack;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize CONNACK and notify of result. */
            status = deserialize( pIncomingPacket );
            pOperation = _IotMqtt_FindOperation( pMqttConnection,
                                                 IOT_MQTT_CONNECT,
                                                 NULL );

            if( pOperation != NULL )
            {
                pOperation->u.operation.status = status;
                _IotMqtt_Notify( pOperation );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;

        case MQTT_PACKET_TYPE_PUBLISH:
            IotLogDebug( "(MQTT connection %p) PUBLISH in data stream.", pMqttConnection );

            /* Allocate memory to handle the incoming PUBLISH. */
            pOperation = IotMqtt_MallocOperation( sizeof( _mqttOperation_t ) );

            if( pOperation == NULL )
            {
                IotLogWarn( "Failed to allocate memory for incoming PUBLISH." );
                status = IOT_MQTT_NO_MEMORY;

                break;
            }
            else
            {
                /* Set the members of the incoming PUBLISH operation. */
                ( void ) memset( pOperation, 0x00, sizeof( _mqttOperation_t ) );
                pOperation->incomingPublish = true;
                pOperation->pMqttConnection = pMqttConnection;
                pIncomingPacket->u.pIncomingPublish = pOperation;
            }

            /* Choose a PUBLISH deserializer. */
            deserialize = _IotMqtt_DeserializePublish;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.publish != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.publish;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize incoming PUBLISH. */
            status = deserialize( pIncomingPacket );

            if( status == IOT_MQTT_SUCCESS )
            {
                /* Send a PUBACK for QoS 1 PUBLISH. */
                if( pOperation->u.publish.publishInfo.qos == IOT_MQTT_QOS_1 )
                {
                    _sendPuback( pMqttConnection, pIncomingPacket->packetIdentifier );
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }

                /* Transfer ownership of the received MQTT packet to the PUBLISH operation. */
                pOperation->u.publish.pReceivedData = pIncomingPacket->pRemainingData;
                pIncomingPacket->pRemainingData = NULL;

                /* Add the PUBLISH to the list of operations pending processing. */
                IotMutex_Lock( &( pMqttConnection->referencesMutex ) );
                IotListDouble_InsertHead( &( pMqttConnection->pendingProcessing ),
                                          &( pOperation->link ) );
                IotMutex_Unlock( &( pMqttConnection->referencesMutex ) );

                /* Increment the MQTT connection reference count before scheduling an
                 * incoming PUBLISH. */
                if( _IotMqtt_IncrementConnectionReferences( pMqttConnection ) == true )
                {
                    /* Schedule PUBLISH for callback invocation. */
                    status = _IotMqtt_ScheduleOperation( pOperation, _IotMqtt_ProcessIncomingPublish, 0 );
                }
                else
                {
                    status = IOT_MQTT_NETWORK_ERROR;
                }
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            /* Free PUBLISH operation on error. */
            if( status != IOT_MQTT_SUCCESS )
            {
                /* Check ownership of the received MQTT packet. */
                if( pOperation->u.publish.pReceivedData != NULL )
                {
                    /* Retrieve the pointer MQTT packet pointer so it may be freed later. */
                    IotMqtt_Assert( pIncomingPacket->pRemainingData == NULL );
                    pIncomingPacket->pRemainingData = ( uint8_t * ) pOperation->u.publish.pReceivedData;
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }

                /* Remove operation from pending processing list. */
                IotMutex_Lock( &( pMqttConnection->referencesMutex ) );

                if( IotLink_IsLinked( &( pOperation->link ) ) == true )
                {
                    IotListDouble_Remove( &( pOperation->link ) );
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }

                IotMutex_Unlock( &( pMqttConnection->referencesMutex ) );

                IotMqtt_Assert( pOperation != NULL );
                IotMqtt_FreeOperation( pOperation );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;

        case MQTT_PACKET_TYPE_PUBACK:
            IotLogDebug( "(MQTT connection %p) PUBACK in data stream.", pMqttConnection );

            /* Choose PUBACK deserializer. */
            deserialize = _IotMqtt_DeserializePuback;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.puback != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.puback;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize PUBACK and notify of result. */
            status = deserialize( pIncomingPacket );
            pOperation = _IotMqtt_FindOperation( pMqttConnection,
                                                 IOT_MQTT_PUBLISH_TO_SERVER,
                                                 &( pIncomingPacket->packetIdentifier ) );

            if( pOperation != NULL )
            {
                pOperation->u.operation.status = status;
                _IotMqtt_Notify( pOperation );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;

        case MQTT_PACKET_TYPE_SUBACK:
            IotLogDebug( "(MQTT connection %p) SUBACK in data stream.", pMqttConnection );

            /* Choose SUBACK deserializer. */
            deserialize = _IotMqtt_DeserializeSuback;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.suback != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.suback;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize SUBACK and notify of result. */
            pIncomingPacket->u.pMqttConnection = pMqttConnection;
            status = deserialize( pIncomingPacket );
            pOperation = _IotMqtt_FindOperation( pMqttConnection,
                                                 IOT_MQTT_SUBSCRIBE,
                                                 &( pIncomingPacket->packetIdentifier ) );

            if( pOperation != NULL )
            {
                pOperation->u.operation.status = status;
                _IotMqtt_Notify( pOperation );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;

        case MQTT_PACKET_TYPE_UNSUBACK:
            IotLogDebug( "(MQTT connection %p) UNSUBACK in data stream.", pMqttConnection );

            /* Choose UNSUBACK deserializer. */
            deserialize = _IotMqtt_DeserializeUnsuback;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.unsuback != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.unsuback;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize UNSUBACK and notify of result. */
            status = deserialize( pIncomingPacket );
            pOperation = _IotMqtt_FindOperation( pMqttConnection,
                                                 IOT_MQTT_UNSUBSCRIBE,
                                                 &( pIncomingPacket->packetIdentifier ) );

            if( pOperation != NULL )
            {
                pOperation->u.operation.status = status;
                _IotMqtt_Notify( pOperation );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;

        default:
            /* The only remaining valid type is PINGRESP. */
            IotMqtt_Assert( ( pIncomingPacket->type & 0xf0 ) == MQTT_PACKET_TYPE_PINGRESP );
            IotLogDebug( "(MQTT connection %p) PINGRESP in data stream.", pMqttConnection );

            /* Choose PINGRESP deserializer. */
            deserialize = _IotMqtt_DeserializePingresp;

            #if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1
                if( pMqttConnection->pSerializer != NULL )
                {
                    if( pMqttConnection->pSerializer->deserialize.pingresp != NULL )
                    {
                        deserialize = pMqttConnection->pSerializer->deserialize.pingresp;
                    }
                    else
                    {
                        EMPTY_ELSE_MARKER;
                    }
                }
                else
                {
                    EMPTY_ELSE_MARKER;
                }
            #endif /* if IOT_MQTT_ENABLE_SERIALIZER_OVERRIDES == 1 */

            /* Deserialize PINGRESP. */
            status = deserialize( pIncomingPacket );

            if( status == IOT_MQTT_SUCCESS )
            {
                IotMutex_Lock( &( pMqttConnection->referencesMutex ) );

                if( pMqttConnection->keepAliveFailure == false )
                {
                    IotLogWarn( "(MQTT connection %p) Unexpected PINGRESP received.",
                                pMqttConnection );
                }
                else
                {
                    IotLogDebug( "(MQTT connection %p) PINGRESP successfully parsed.",
                                 pMqttConnection );

                    pMqttConnection->keepAliveFailure = false;
                }

                IotMutex_Unlock( &( pMqttConnection->referencesMutex ) );
            }
            else
            {
                EMPTY_ELSE_MARKER;
            }

            break;
    }

    if( status != IOT_MQTT_SUCCESS )
    {
        IotLogError( "(MQTT connection %p) Packet parser status %s.",
                     pMqttConnection,
                     IotMqtt_strerror( status ) );
    }
    else
    {
        EMPTY_ELSE_MARKER;
    }

    return status;
}