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;
}