static IngestResult_t prvIngestDataBlock()

in amazon-freertos/lib/ota/aws_ota_agent.c [2551:2716]


static IngestResult_t prvIngestDataBlock( OTA_FileContext_t * C,
                                          const char * pcRawMsg,
                                          uint32_t ulMsgSize,
                                          OTA_Err_t * pxCloseResult )
{
    DEFINE_OTA_METHOD_NAME( "prvIngestDataBlock" );

    IngestResult_t eIngestResult = eIngest_Result_Uninitialized;
    int32_t lFileId = 0;
    uint32_t ulBlockSize = 0;
    uint32_t ulBlockIndex = 0;
    uint8_t * pucPayload = NULL;
    size_t xPayloadSize = 0;

    if( C != NULL )
    {
        if( pxCloseResult != NULL )
        {
            *pxCloseResult = kOTA_Err_GenericIngestError; /* Default to a generic ingest function error until we prove success. */

            /* If we have a block bitmap available then process the message. */
            if( C->pucRxBlockBitmap && ( C->ulBlocksRemaining > 0U ) )
            {
                /* Reset or start the firmware request timer. */
                prvStartRequestTimer( C );

                /* Decode the CBOR content. */
                if( pdFALSE == OTA_CBOR_Decode_GetStreamResponseMessage(
                        ( const uint8_t * ) pcRawMsg,
                        ulMsgSize,
                        &lFileId,
                        ( int32_t * ) &ulBlockIndex, /*lint !e9087 CBOR requires pointer to int and our block index's never exceed 31 bits. */
                        ( int32_t * ) &ulBlockSize,  /*lint !e9087 CBOR requires pointer to int and our block sizes never exceed 31 bits. */
                        &pucPayload,                 /* This payload gets malloc'd by OTA_CBOR_Decode_GetStreamResponseMessage(). We must free it. */
                        ( size_t * ) &xPayloadSize ) )
                {
                    eIngestResult = eIngest_Result_BadData;
                }
                else
                {
                    /* Validate the block index and size. */
                    /* If it is NOT the last block, it MUST be equal to a full block size. */
                    /* If it IS the last block, it MUST be equal to the expected remainder. */
                    /* If the block ID is out of range, that's an error so abort. */
                    uint32_t ulLastBlock = ( ( C->ulFileSize + ( OTA_FILE_BLOCK_SIZE - 1U ) ) >> otaconfigLOG2_FILE_BLOCK_SIZE ) - 1U;

                    if( ( ( ( uint32_t ) ulBlockIndex < ulLastBlock ) && ( ulBlockSize == OTA_FILE_BLOCK_SIZE ) ) ||
                        ( ( ( uint32_t ) ulBlockIndex == ulLastBlock ) && ( ( uint32_t ) ulBlockSize == ( C->ulFileSize - ( ulLastBlock * OTA_FILE_BLOCK_SIZE ) ) ) ) )
                    {
                        OTA_LOG_L1( "[%s] Received file block %u, size %u\r\n", OTA_METHOD_NAME, ulBlockIndex, ulBlockSize );

                        /* Create bit mask for use in our bitmap. */
                        uint8_t ucBitMask = 1U << ( ulBlockIndex % BITS_PER_BYTE ); /*lint !e9031 The composite expression will never be greater than BITS_PER_BYTE(8). */
                        /* Calculate byte offset into bitmap. */
                        uint32_t ulByte = ulBlockIndex >> LOG2_BITS_PER_BYTE;

                        if( ( C->pucRxBlockBitmap[ ulByte ] & ucBitMask ) == 0U ) /* If we've already received this block... */
                        {
                            OTA_LOG_L1( "[%s] block %u is a DUPLICATE. %u blocks remaining.\r\n", OTA_METHOD_NAME,
                                        ulBlockIndex,
                                        C->ulBlocksRemaining );
                            eIngestResult = eIngest_Result_Duplicate_Continue;
                            *pxCloseResult = kOTA_Err_None; /* This is a success path. */
                        }
                        else /* Otherwise, process it normally... */
                        {
                            if( C->pucFile != NULL )
                            {
                                int32_t lBytesWritten = prvPAL_WriteBlock( C, ( ulBlockIndex * OTA_FILE_BLOCK_SIZE ), pucPayload, ( uint32_t ) ulBlockSize );

                                if( lBytesWritten < 0 )
                                {
                                    OTA_LOG_L1( "[%s] Error (%d) writing file block\r\n", OTA_METHOD_NAME, lBytesWritten );
                                    eIngestResult = eIngest_Result_WriteBlockFailed;
                                }
                                else
                                {
                                    C->pucRxBlockBitmap[ ulByte ] &= ~ucBitMask; /* Mark this block as received in our bitmap. */
                                    C->ulBlocksRemaining--;
                                    eIngestResult = eIngest_Result_Accepted_Continue;
                                    *pxCloseResult = kOTA_Err_None; /* This is a success path. */
                                }
                            }
                            else
                            {
                                OTA_LOG_L1( "[%s] Error: Unable to write block, file handle is NULL.\r\n", OTA_METHOD_NAME );
                                eIngestResult = eIngest_Result_BadFileHandle;
                            }

                            if( C->ulBlocksRemaining == 0U )
                            {
                                OTA_LOG_L1( "[%s] Received final expected block of file.\r\n", OTA_METHOD_NAME );
                                prvStopRequestTimer( C );         /* Don't request any more since we're done. */
                                vPortFree( C->pucRxBlockBitmap ); /* Free the bitmap now that we're done with the download. */
                                C->pucRxBlockBitmap = NULL;

                                if( C->pucFile != NULL )
                                {
                                    *pxCloseResult = prvPAL_CloseFile( C );

                                    if( *pxCloseResult == kOTA_Err_None )
                                    {
                                        OTA_LOG_L1( "[%s] File receive complete and signature is valid.\r\n", OTA_METHOD_NAME );
                                        eIngestResult = eIngest_Result_FileComplete;
                                    }
                                    else
                                    {
                                        uint32_t ulCloseResult = ( uint32_t ) *pxCloseResult;
                                        OTA_LOG_L1( "[%s] Error (%u:0x%06x) closing OTA file.\r\n",
                                                    OTA_METHOD_NAME,
                                                    ulCloseResult >> kOTA_MainErrShiftDownBits,
                                                    ulCloseResult & ( uint32_t ) kOTA_PAL_ErrMask );

                                        if( ( ulCloseResult & kOTA_Main_ErrMask ) == kOTA_Err_SignatureCheckFailed )
                                        {
                                            eIngestResult = eIngest_Result_SigCheckFail;
                                        }
                                        else
                                        {
                                            eIngestResult = eIngest_Result_FileCloseFail;
                                        }
                                    }

                                    C->pucFile = NULL; /* File is now closed so clear the file handle in the context. */
                                }
                                else
                                {
                                    OTA_LOG_L1( "[%s] Error: File handle is NULL after last block received.\r\n", OTA_METHOD_NAME );
                                    eIngestResult = eIngest_Result_BadFileHandle;
                                }
                            }
                            else
                            {
                                OTA_LOG_L1( "[%s] Remaining: %u\r\n", OTA_METHOD_NAME, C->ulBlocksRemaining );
                            }
                        }
                    }
                    else
                    {
                        OTA_LOG_L1( "[%s] Error! Block %u out of expected range! Size %u\r\n", OTA_METHOD_NAME, ulBlockIndex, ulBlockSize );
                        eIngestResult = eIngest_Result_BlockOutOfRange;
                    }
                }
            }
            else
            {
                eIngestResult = eIngest_Result_UnexpectedBlock;
            }
        }
        else
        {
            eIngestResult = eIngest_Result_NullResultPointer;
        }
    }
    else
    {
        eIngestResult = eIngest_Result_NullContext;
    }

    if( NULL != pucPayload )
    {
        vPortFree( pucPayload );
    }

    return eIngestResult;
}