in src/agent/adu_core_interface/src/adu_core_interface.c [329:460]
void OrchestratorUpdateCallback(
ADUC_ClientHandle clientHandle,
JSON_Value* propertyValue,
int propertyVersion,
ADUC_PnPComponentClient_PropertyUpdate_Context* sourceContext,
void* context)
{
UNREFERENCED_PARAMETER(clientHandle);
ADUC_Result tmpResult = { .ResultCode = ADUC_GeneralResult_Failure, .ExtendedResultCode = 0 };
ADUC_WorkflowData* workflowData = (ADUC_WorkflowData*)context;
STRING_HANDLE jsonToSend = NULL;
char* ackString = NULL;
JSON_Object* signatureObj = NULL;
ADUCITF_UpdateAction updateAction = ADUCITF_UpdateAction_Undefined;
char* workflowId = NULL;
char* rootKeyPkgUrl = NULL;
STRING_HANDLE rootKeyPackageFilePath = NULL;
char* workFolder = NULL;
// Reads out the json string so we can Log Out what we've got.
// The value will be parsed and handled in ADUC_Workflow_HandlePropertyUpdate.
char* jsonString = json_serialize_to_string(propertyValue);
if (jsonString == NULL)
{
Log_Error(
"OrchestratorUpdateCallback failed to convert property JSON value to string, property version (%d)",
propertyVersion);
goto done;
}
// To reduce TWIN size, remove UpdateManifestSignature and fileUrls before ACK.
signatureObj = json_value_get_object(propertyValue);
if (signatureObj != NULL)
{
json_object_set_null(signatureObj, "updateManifestSignature");
json_object_set_null(signatureObj, "fileUrls");
ackString = json_serialize_to_string(propertyValue);
}
Log_Debug("Update Action info string (%s), property version (%d)", ackString, propertyVersion);
tmpResult = workflow_parse_peek_unprotected_workflow_properties(
json_object(propertyValue), &updateAction, &rootKeyPkgUrl, &workflowId);
if (IsAducResultCodeFailure(tmpResult.ResultCode))
{
Log_Error("Parse failed for unprotected properties, erc: 0x%08x", tmpResult.ExtendedResultCode);
// Note, cannot report failure here since workflowId from unprotected properties is needed for that.
goto done;
}
// If there is no deployment for the device group or the device connected
// within an interval before the update was deployed, then a C2D message
// with update action of cancel and an internal workflowId of
// "nodeployment" will be sent.
//
// It is an indicator that no deployment exists for the device group or
// that a new deployment has been deployed recently and should be flowing
// down the pipe soon.
//
// Instead of processing a cancel, just ignore this and wait for normal
// cancellation to occur once a "process deployment" action flows down.
if (updateAction == ADUCITF_UpdateAction_Cancel && (0 == strcmp(workflowId, "nodeployment")))
{
Log_Info("Received deployment delay period NOOP cancel. Will wait for update deployment to be pushed...");
goto done;
}
if (updateAction == ADUCITF_UpdateAction_ProcessDeployment && !IsNullOrEmpty(workflowId))
{
Log_Debug("Processing deployment %s ...", workflowId);
// Ensure update to latest rootkey pkg, which is required for validating the update metadata.
workFolder = workflow_get_root_sandbox_dir(workflowData->WorkflowHandle);
if (workFolder == NULL)
{
Log_Error("workflow_get_root_sandbox_dir failed");
goto done;
}
tmpResult = RootKeyWorkflow_UpdateRootKeys(workflowId, workFolder, rootKeyPkgUrl);
if (IsAducResultCodeFailure(tmpResult.ResultCode))
{
Log_Error("Update Rootkey failed, 0x%08x. Deployment cannot proceed.", tmpResult.ExtendedResultCode);
goto done;
}
}
ADUC_Workflow_HandlePropertyUpdate(workflowData, (const unsigned char*)jsonString, sourceContext->forceUpdate);
free(jsonString);
jsonString = ackString;
// ACK the request.
jsonToSend = PnP_CreateReportedPropertyWithStatus(
g_aduPnPComponentName,
g_aduPnPComponentServicePropertyName,
jsonString,
PNP_STATUS_SUCCESS,
"", // Description for this acknowledgement.
propertyVersion);
if (jsonToSend == NULL)
{
Log_Error("Unable to build reported property ACK response.");
goto done;
}
if (!ADUC_D2C_Message_SendAsync(
ADUC_D2C_Message_Type_Device_Update_ACK,
&g_iotHubClientHandleForADUComponent,
STRING_c_str(jsonToSend),
NULL /* responseCallback */,
OnUpdateResultD2CMessageCompleted,
NULL /* statusChangedCallback */,
NULL /* userData */))
{
Log_Error("Unable to send update result.");
goto done;
}
done:
STRING_delete(rootKeyPackageFilePath);
workflow_free_string(rootKeyPkgUrl);
workflow_free_string(workflowId);
workflow_free_string(workFolder);
STRING_delete(jsonToSend);
free(jsonString);
Log_Info("OrchestratorPropertyUpdateCallback ended");
}