in source/ota.c [123:511]
static IngestResult_t ingestDataBlock( OtaFileContext_t * pFileContext,
const uint8_t * pRawMsg,
uint32_t messageSize,
OtaPalStatus_t * pCloseResult );
/**
* @brief Validate the incoming data block and store it in the file context.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[in] uBlockIndex Incoming block index.
* @param[in] uBlockSize Incoming block size.
* @param[out] pCloseResult Result of closing file in PAL.
* @param[in] pPayload Data from the block.
* @return IngestResult_t IngestResultAccepted_Continue if successful, other error for failure.
*/
static IngestResult_t processDataBlock( OtaFileContext_t * pFileContext,
uint32_t uBlockIndex,
uint32_t uBlockSize,
OtaPalStatus_t * pCloseResult,
uint8_t * pPayload );
/**
* @brief Free the resources allocated for data ingestion and close the file handle.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[out] pCloseResult Result of closing file in PAL.
* @return IngestResult_t IngestResultAccepted_Continue if successful, other error for failure.
*/
static IngestResult_t ingestDataBlockCleanup( OtaFileContext_t * pFileContext,
OtaPalStatus_t * pCloseResult );
/**
* @brief Get the File Context From Job Document.
*
* We received an OTA update job message from the job service so process
* the message and update the file context.
*
* @param[in] pRawMsg Raw job document.
* @param[in] messageLength length of document.
* @return OtaFileContext_t* Information of file to be streamed.
*/
static OtaFileContext_t * getFileContextFromJob( const char * pRawMsg,
uint32_t messageLength );
/**
* @brief Validate JSON document and the DocModel.
*
* @param[in] pJson JSON job document.
* @param[in] messageLength Length of the job document.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t validateJSON( const char * pJson,
uint32_t messageLength );
/**
* @brief Store the parameter from the json to the offset specified by the document model.
*
* @param[in] docParam Structure to store the details of keys and where to store them.
* @param[in] pContextBase Start of file context.
* @param[in] pValueInJson Pointer to the value of the key in JSON buffer.
* @param[in] valueLength Length of the value.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t extractParameter( JsonDocParam_t docParam,
void * pContextBase,
const char * pValueInJson,
size_t valueLength );
/**
* @brief Extract the desired fields from the JSON document based on the specified document model.
*
* @param[in] pJson JSON job document.
* @param[in] messageLength Length of the job document.
* @param[in] pDocModel Details of expected parameters in the job doc.
* @return DocParseErr_t DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t parseJSONbyModel( const char * pJson,
uint32_t messageLength,
JsonDocModel_t * pDocModel );
/**
* @brief Decode the base64 encoded file signature key from the job document and store it in file context.
*
* @param[in] pValueInJson Pointer to the value of the key in JSON buffer.
* @param[in] valueLength Length of the value.
* @param[out] pParamAdd Pointer to the location where the value is stored.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t decodeAndStoreKey( const char * pValueInJson,
size_t valueLength,
void * pParamAdd );
/**
* @brief Extract the value from json and store it into the allocated memory.
*
* @param[in] pKey Name of the Key to extract.
* @param[in] pValueInJson Pointer to the value of the key in JSON buffer.
* @param[in] valueLength Length of the value.
* @param[out] pParamAdd Pointer to the location where the value is stored.
* @param[in] pParamSizeAdd Size required to store the param.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t extractAndStoreArray( const char * pKey,
const char * pValueInJson,
size_t valueLength,
void * pParamAdd,
uint32_t * pParamSizeAdd );
/**
* @brief Check if all the required parameters for job document are extracted from the JSON.
*
* @param[in] pModelParam Structure to store the details of keys and where to store them.
* @param[in] pDocModel Details of expected parameters in the job doc.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t verifyRequiredParamsExtracted( const JsonDocParam_t * pModelParam,
const JsonDocModel_t * pDocModel );
/**
* @brief Validate the version of the update received.
*
* @param[in] pFileContext Information of file to be streamed.
* @return OtaErr_t OtaErrNone if successful, other error codes if failure.
*/
static OtaErr_t validateUpdateVersion( const OtaFileContext_t * pFileContext );
/**
* @brief Check if the JSON can be parsed through the app callback if initial parsing fails.
*
* @param[in] pJson JSON job document.
* @param[in] messageLength Length of the job document.
* @return OtaJobParseErr_t OtaJobParseErrNone if successful, other error codes if failure.
*/
static OtaJobParseErr_t handleCustomJob( const char * pJson,
uint32_t messageLength );
/**
* @brief Check if the incoming job document is not conflicting with current job status.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[out] pFinalFile File that stores all extracted params.
* @param[out] pUpdateJob Represents if the job is accepted.
* @return OtaJobParseErr_t OtaErrNone if successful, other error codes if failure.
*/
static OtaJobParseErr_t verifyActiveJobStatus( OtaFileContext_t * pFileContext,
OtaFileContext_t ** pFinalFile,
bool * pUpdateJob );
/**
* @brief Check if all the file context params are valid and initialize resources for the job transfer.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[out] pFinalFile File that stores all extracted params.
* @param[out] pUpdateJob Represents if the job is accepted.
* @return OtaJobParseErr_t OtaJobParseErrNone if successful, other error codes if failure.
*/
static OtaJobParseErr_t validateAndStartJob( OtaFileContext_t * pFileContext,
OtaFileContext_t ** pFinalFile,
bool * pUpdateJob );
/**
* @brief Parse the OTA job document, validate and return the populated OTA context if valid.
*
* @param[in] pJsonExpectedParams Structure to store the details of keys and where to store them.
* @param[in] numJobParams Number of parameters to be extracted.
* @param[in] pJson JSON job document.
* @param[in] messageLength Length of the job document.
* @param[in] pUpdateJob Represents if the job is accepted.
* @return OtaFileContext_t* File context to store file information.
*/
static OtaFileContext_t * parseJobDoc( const JsonDocParam_t * pJsonExpectedParams,
uint16_t numJobParams,
const char * pJson,
uint32_t messageLength,
bool * pUpdateJob );
/**
* @brief Validate block index and block size of the data block.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[in] blockIndex Block index of incoming data block.
* @param[in] blockSize Block size of incoming data block.
* @return true if successful, false otherwise.
*/
static bool validateDataBlock( const OtaFileContext_t * pFileContext,
uint32_t blockIndex,
uint32_t blockSize );
/**
* @brief Decode and ingest the incoming data block.
*
* @param[in] pFileContext Information of file to be streamed.
* @param[in] pRawMsg Raw job document.
* @param[in] messageSize Length of document.
* @param[in] pPayload Data stored in the document.
* @param[out] pBlockSize Block size of incoming data block.
* @param[out] pBlockIndex Block index of incoming data block.
* @return IngestResult_t IngestResultAccepted_Continue if successful, other error for failure.
*/
static IngestResult_t decodeAndStoreDataBlock( OtaFileContext_t * pFileContext,
const uint8_t * pRawMsg,
uint32_t messageSize,
uint8_t ** pPayload,
uint32_t * pBlockSize,
uint32_t * pBlockIndex );
/**
* @brief Close an open OTA file context and free it.
*
* @param[in] pFileContext Information of file to be streamed.
* @return true if successful, false otherwise.
*/
static bool otaClose( OtaFileContext_t * const pFileContext );
/**
* @brief OTA Timer callback.
*
* @param[in] otaTimerId Reference to the timer to use.
*/
static void otaTimerCallback( OtaTimerId_t otaTimerId );
/**
* @brief Internal function to set the image state including an optional reason code.
*
* @param[in] stateToSet State to set.
* @param[in] reasonToSet Reason to set.
* @return OtaErr_t OtaErrNone if successful, other codes on failure.
*/
static OtaErr_t setImageStateWithReason( OtaImageState_t stateToSet,
uint32_t reasonToSet );
/**
* @brief Internal function to update the job status to the jobs service from current image state.
*
* @param[in] state State to set.
* @param[in] subReason Reason for status.
* @return OtaErr_t OtaErrNone if successful, other codes on failure.
*/
static OtaErr_t updateJobStatusFromImageState( OtaImageState_t state,
int32_t subReason );
/**
* @brief A helper function to cleanup resources during OTA agent shutdown.
*/
static void agentShutdownCleanup( void );
/**
* @brief A helper function to cleanup resources when data ingestion is complete.
*/
static void dataHandlerCleanup( void );
/**
* @brief Prepare the document model for use by sanity checking the initialization parameters and detecting all required parameters.
*
* @param[inout] pDocModel Details of expected parameters in the job doc.
* @param[in] pBodyDef Structure to store the details of keys and where to store them.
* @param[in] contextBaseAddr Start of file context.
* @param[in] contextSize Size of file context.
* @param[in] numJobParams Number of parameters to be extracted.
* @return DocParseErr_t DocParseErrNone if successful, JSON document parser errors.
*/
static DocParseErr_t initDocModel( JsonDocModel_t * pDocModel,
const JsonDocParam_t * pBodyDef,
void * contextBaseAddr,
uint32_t contextSize,
uint16_t numJobParams );
/**
* @brief Initialize buffers for storing the file attributes.
*
* @param[out] pOtaBuffer OTA Application buffers.
*/
static void initializeAppBuffers( OtaAppBuffer_t * pOtaBuffer );
/**
* @brief Initialize jobId and protocol buffers.
*/
static void initializeLocalBuffers( void );
/**
* @brief Search the state transition table for the entry based on current state and incoming event.
*
* @param[in] pEventMsg Incoming event information.
* @return uint32_t Index of the transition.
*/
static uint32_t searchTransition( const OtaEventMsg_t * pEventMsg );
/**
* @brief Initiate download if not in self-test else reboot
*
* @return OtaErr_t OtaErrNone if successful.
*/
static OtaErr_t processValidFileContext( void );
/**
* @brief Validate update version when receiving job doc in self test state.
*
* @param[in] pFileContext Stores file information.
*/
static void handleSelfTestJobDoc( OtaFileContext_t * pFileContext );
/**
* @brief Handle invalid file context.
*
* @return OtaErr_t OtaErrNone if job parsing is handled.
*/
static OtaErr_t processNullFileContext( void );
/**
* @brief Check if the platform is in self-test
*
* @return true if in self-test, else false.
*/
static bool platformInSelftest( void );
/**
* @brief Function to handle events that were unexpected in the current state.
*
* @param[in] pEventMsg Stores information of the event.
*/
static void handleUnexpectedEvents( const OtaEventMsg_t * pEventMsg );
/**
* @brief Free or clear multiple buffers used in the file context.
*
* @param[in] pFileContext Information of file to be streamed.
*/
static void freeFileContextMem( OtaFileContext_t * const pFileContext );
/**
* @brief Handle job parsing error.
*
* @param[in] pFileContext Pointer to the file context.
*
* @param[in] err Parsing error of type OtaJobParseErr_t.
*/
static void handleJobParsingError( const OtaFileContext_t * pFileContext,
OtaJobParseErr_t err );
/**
* @brief Receive and process the next available event from the event queue.
*
* Each event is processed based on the behavior defined in the OTA transition
* table. The state of the OTA state machine will be updated and the
* corresponding event handler will be called.
*/
static void receiveAndProcessOtaEvent( void );
/* OTA state event handler functions. */
static OtaErr_t startHandler( const OtaEventData_t * pEventData ); /*!< Start timers and initiate request for job document. */
static OtaErr_t requestJobHandler( const OtaEventData_t * pEventData ); /*!< Initiate a request for a job. */
static OtaErr_t processJobHandler( const OtaEventData_t * pEventData ); /*!< Update file context from job document. */
static OtaErr_t inSelfTestHandler( const OtaEventData_t * pEventData ); /*!< Handle self test. */
static OtaErr_t initFileHandler( const OtaEventData_t * pEventData ); /*!< Initialize and handle file transfer. */
static OtaErr_t processDataHandler( const OtaEventData_t * pEventData ); /*!< Process incoming data blocks. */
static OtaErr_t requestDataHandler( const OtaEventData_t * pEventData ); /*!< Request for data blocks. */
static OtaErr_t shutdownHandler( const OtaEventData_t * pEventData ); /*!< Shutdown OTA and cleanup. */
static OtaErr_t closeFileHandler( const OtaEventData_t * pEventData ); /*!< Close file opened for download. */
static OtaErr_t userAbortHandler( const OtaEventData_t * pEventData ); /*!< Handle user interrupt to abort task. */
static OtaErr_t suspendHandler( const OtaEventData_t * pEventData ); /*!< Handle suspend event for OTA agent. */
static OtaErr_t resumeHandler( const OtaEventData_t * pEventData ); /*!< Resume from a suspended state. */
static OtaErr_t jobNotificationHandler( const OtaEventData_t * pEventData ); /*!< Upon receiving a new job document cancel current job if present and initiate new download. */
static void executeHandler( uint32_t index,
const OtaEventMsg_t * const pEventMsg ); /*!< Execute the handler for selected index from the transition table. */
/**
* @brief This is THE OTA agent context and initialization state.
*/
static OtaAgentContext_t otaAgent =
{
OtaAgentStateStopped, /* state */
{ 0 }, /* pThingName */
{ 0 }, /* fileContext */
0, /* fileIndex */
0, /* serverFileID */
{ 0 }, /* pActiveJobName */
NULL, /* pClientTokenFromJob */
0, /* timestampFromJob */
OtaImageStateUnknown, /* imageState */
1, /* numOfBlocksToReceive */
{ 0 }, /* statistics */
0, /* requestMomentum */
NULL, /* pOtaInterface */
NULL, /* OtaAppCallback */
1 /* unsubscribe flag */
};