A modelling and serializer library for Microsoft Azure IoTHub client applications

Dependents:   sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more

This library implements a serializer library to be used in projects involving Microsoft Azure IoT Hub connectivity. The code is replicated from https://github.com/Azure/azure-iot-sdks

Committer:
AzureIoTClient
Date:
Tue Sep 11 11:14:37 2018 -0700
Revision:
36:7d12a5386197
Parent:
26:7c0e6f86d034
1.2.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 0:1f9b2707ec7d 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 0:1f9b2707ec7d 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 0:1f9b2707ec7d 3
AzureIoTClient 0:1f9b2707ec7d 4 #include <stdlib.h>
AzureIoTClient 23:078ea26cffcd 5 #include "azure_c_shared_utility/optimize_size.h"
Azure.IoT Build 10:c2aee3965a83 6 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 0:1f9b2707ec7d 7
AzureIoTClient 0:1f9b2707ec7d 8 #include <stddef.h>
AzureIoTClient 0:1f9b2707ec7d 9
AzureIoTClient 0:1f9b2707ec7d 10 #include "commanddecoder.h"
AzureIoTClient 0:1f9b2707ec7d 11 #include "multitree.h"
Azure.IoT Build 10:c2aee3965a83 12 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 13:16e88f0cfa5f 13 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 0:1f9b2707ec7d 14 #include "schema.h"
AzureIoTClient 0:1f9b2707ec7d 15 #include "codefirst.h"
AzureIoTClient 0:1f9b2707ec7d 16 #include "jsondecoder.h"
AzureIoTClient 0:1f9b2707ec7d 17
AzureIoTClient 0:1f9b2707ec7d 18 DEFINE_ENUM_STRINGS(COMMANDDECODER_RESULT, COMMANDDECODER_RESULT_VALUES);
AzureIoTClient 0:1f9b2707ec7d 19
AzureIoTClient 17:fa1bba4c6053 20 typedef struct COMMAND_DECODER_HANDLE_DATA_TAG
AzureIoTClient 0:1f9b2707ec7d 21 {
Azure.IoT.Build 18:58b667752399 22 METHOD_CALLBACK_FUNC methodCallback;
Azure.IoT.Build 18:58b667752399 23 void* methodCallbackContext;
AzureIoTClient 0:1f9b2707ec7d 24 SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
AzureIoTClient 0:1f9b2707ec7d 25 ACTION_CALLBACK_FUNC ActionCallback;
AzureIoTClient 0:1f9b2707ec7d 26 void* ActionCallbackContext;
AzureIoTClient 17:fa1bba4c6053 27 } COMMAND_DECODER_HANDLE_DATA;
AzureIoTClient 0:1f9b2707ec7d 28
AzureIoTClient 0:1f9b2707ec7d 29 static int DecodeValueFromNode(SCHEMA_HANDLE schemaHandle, AGENT_DATA_TYPE* agentDataType, MULTITREE_HANDLE node, const char* edmTypeName)
AzureIoTClient 0:1f9b2707ec7d 30 {
AzureIoTClient 0:1f9b2707ec7d 31 /* because "pottentially uninitialized variable on MS compiler" */
AzureIoTClient 0:1f9b2707ec7d 32 int result = 0;
AzureIoTClient 0:1f9b2707ec7d 33 const char* argStringValue;
AzureIoTClient 0:1f9b2707ec7d 34 AGENT_DATA_TYPE_TYPE primitiveType;
AzureIoTClient 0:1f9b2707ec7d 35
AzureIoTClient 0:1f9b2707ec7d 36 /* Codes_SRS_COMMAND_DECODER_99_029:[ If the argument type is complex then a complex type value shall be built from the child nodes.] */
AzureIoTClient 0:1f9b2707ec7d 37 if ((primitiveType = CodeFirst_GetPrimitiveType(edmTypeName)) == EDM_NO_TYPE)
AzureIoTClient 0:1f9b2707ec7d 38 {
AzureIoTClient 0:1f9b2707ec7d 39 SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle;
AzureIoTClient 0:1f9b2707ec7d 40 size_t propertyCount;
AzureIoTClient 0:1f9b2707ec7d 41
AzureIoTClient 0:1f9b2707ec7d 42 /* Codes_SRS_COMMAND_DECODER_99_033:[ In order to determine which are the members of a complex types, Schema APIs for structure types shall be used.] */
AzureIoTClient 0:1f9b2707ec7d 43 if (((structTypeHandle = Schema_GetStructTypeByName(schemaHandle, edmTypeName)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 44 (Schema_GetStructTypePropertyCount(structTypeHandle, &propertyCount) != SCHEMA_OK))
AzureIoTClient 0:1f9b2707ec7d 45 {
AzureIoTClient 0:1f9b2707ec7d 46 /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 23:078ea26cffcd 47 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 48 LogError("Getting Struct information failed.");
AzureIoTClient 0:1f9b2707ec7d 49 }
AzureIoTClient 0:1f9b2707ec7d 50 else
AzureIoTClient 0:1f9b2707ec7d 51 {
AzureIoTClient 0:1f9b2707ec7d 52 if (propertyCount == 0)
AzureIoTClient 0:1f9b2707ec7d 53 {
AzureIoTClient 0:1f9b2707ec7d 54 /* Codes_SRS_COMMAND_DECODER_99_034:[ If Schema APIs indicate that a complex type has 0 members then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 23:078ea26cffcd 55 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 56 LogError("Struct type with 0 members is not allowed");
AzureIoTClient 0:1f9b2707ec7d 57 }
AzureIoTClient 0:1f9b2707ec7d 58 else
AzureIoTClient 0:1f9b2707ec7d 59 {
AzureIoTClient 0:1f9b2707ec7d 60 AGENT_DATA_TYPE* memberValues = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE)* propertyCount);
AzureIoTClient 0:1f9b2707ec7d 61 if (memberValues == NULL)
AzureIoTClient 0:1f9b2707ec7d 62 {
AzureIoTClient 0:1f9b2707ec7d 63 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 23:078ea26cffcd 64 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 65 LogError("Failed allocating member values for command argument");
AzureIoTClient 0:1f9b2707ec7d 66 }
AzureIoTClient 0:1f9b2707ec7d 67 else
AzureIoTClient 0:1f9b2707ec7d 68 {
AzureIoTClient 0:1f9b2707ec7d 69 const char** memberNames = (const char**)malloc(sizeof(const char*)* propertyCount);
AzureIoTClient 0:1f9b2707ec7d 70 if (memberNames == NULL)
AzureIoTClient 0:1f9b2707ec7d 71 {
AzureIoTClient 0:1f9b2707ec7d 72 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 23:078ea26cffcd 73 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 74 LogError("Failed allocating member names for command argument.");
AzureIoTClient 0:1f9b2707ec7d 75 }
AzureIoTClient 0:1f9b2707ec7d 76 else
AzureIoTClient 0:1f9b2707ec7d 77 {
AzureIoTClient 0:1f9b2707ec7d 78 size_t j;
AzureIoTClient 0:1f9b2707ec7d 79 size_t k;
AzureIoTClient 0:1f9b2707ec7d 80
AzureIoTClient 0:1f9b2707ec7d 81 for (j = 0; j < propertyCount; j++)
AzureIoTClient 0:1f9b2707ec7d 82 {
AzureIoTClient 0:1f9b2707ec7d 83 SCHEMA_PROPERTY_HANDLE propertyHandle;
AzureIoTClient 0:1f9b2707ec7d 84 MULTITREE_HANDLE memberNode;
AzureIoTClient 0:1f9b2707ec7d 85 const char* propertyName;
AzureIoTClient 0:1f9b2707ec7d 86 const char* propertyType;
AzureIoTClient 0:1f9b2707ec7d 87
AzureIoTClient 0:1f9b2707ec7d 88 if ((propertyHandle = Schema_GetStructTypePropertyByIndex(structTypeHandle, j)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 89 {
AzureIoTClient 0:1f9b2707ec7d 90 /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 23:078ea26cffcd 91 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 92 LogError("Getting struct member failed.");
AzureIoTClient 0:1f9b2707ec7d 93 break;
AzureIoTClient 0:1f9b2707ec7d 94 }
AzureIoTClient 0:1f9b2707ec7d 95 else if (((propertyName = Schema_GetPropertyName(propertyHandle)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 96 ((propertyType = Schema_GetPropertyType(propertyHandle)) == NULL))
AzureIoTClient 0:1f9b2707ec7d 97 {
AzureIoTClient 0:1f9b2707ec7d 98 /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 23:078ea26cffcd 99 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 100 LogError("Getting the struct member information failed.");
AzureIoTClient 0:1f9b2707ec7d 101 break;
AzureIoTClient 0:1f9b2707ec7d 102 }
AzureIoTClient 0:1f9b2707ec7d 103 else
AzureIoTClient 0:1f9b2707ec7d 104 {
AzureIoTClient 0:1f9b2707ec7d 105 memberNames[j] = propertyName;
AzureIoTClient 36:7d12a5386197 106
AzureIoTClient 0:1f9b2707ec7d 107 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 108 if (MultiTree_GetChildByName(node, memberNames[j], &memberNode) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 109 {
AzureIoTClient 0:1f9b2707ec7d 110 /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 23:078ea26cffcd 111 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 112 LogError("Getting child %s failed", propertyName);
AzureIoTClient 0:1f9b2707ec7d 113 break;
AzureIoTClient 0:1f9b2707ec7d 114 }
AzureIoTClient 0:1f9b2707ec7d 115 /* Codes_SRS_COMMAND_DECODER_99_032:[ Nesting shall be supported for complex type.] */
AzureIoTClient 0:1f9b2707ec7d 116 else if ((result = DecodeValueFromNode(schemaHandle, &memberValues[j], memberNode, propertyType)) != 0)
AzureIoTClient 0:1f9b2707ec7d 117 {
AzureIoTClient 0:1f9b2707ec7d 118 break;
AzureIoTClient 0:1f9b2707ec7d 119 }
AzureIoTClient 0:1f9b2707ec7d 120 }
AzureIoTClient 0:1f9b2707ec7d 121 }
AzureIoTClient 0:1f9b2707ec7d 122
AzureIoTClient 0:1f9b2707ec7d 123 if (j == propertyCount)
AzureIoTClient 0:1f9b2707ec7d 124 {
AzureIoTClient 0:1f9b2707ec7d 125 /* Codes_SRS_COMMAND_DECODER_99_031:[ The complex type value that aggregates the children shall be built by using the Create_AGENT_DATA_TYPE_from_Members.] */
AzureIoTClient 0:1f9b2707ec7d 126 if (Create_AGENT_DATA_TYPE_from_Members(agentDataType, edmTypeName, propertyCount, (const char* const*)memberNames, memberValues) != AGENT_DATA_TYPES_OK)
AzureIoTClient 0:1f9b2707ec7d 127 {
AzureIoTClient 0:1f9b2707ec7d 128 /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 23:078ea26cffcd 129 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 130 LogError("Creating the agent data type from members failed.");
AzureIoTClient 0:1f9b2707ec7d 131 }
AzureIoTClient 0:1f9b2707ec7d 132 else
AzureIoTClient 0:1f9b2707ec7d 133 {
AzureIoTClient 0:1f9b2707ec7d 134 result = 0;
AzureIoTClient 0:1f9b2707ec7d 135 }
AzureIoTClient 0:1f9b2707ec7d 136 }
AzureIoTClient 0:1f9b2707ec7d 137
AzureIoTClient 0:1f9b2707ec7d 138 for (k = 0; k < j; k++)
AzureIoTClient 0:1f9b2707ec7d 139 {
AzureIoTClient 0:1f9b2707ec7d 140 Destroy_AGENT_DATA_TYPE(&memberValues[k]);
AzureIoTClient 0:1f9b2707ec7d 141 }
AzureIoTClient 0:1f9b2707ec7d 142
AzureIoTClient 0:1f9b2707ec7d 143 free((void*)memberNames);
AzureIoTClient 0:1f9b2707ec7d 144 }
AzureIoTClient 0:1f9b2707ec7d 145
AzureIoTClient 0:1f9b2707ec7d 146 free(memberValues);
AzureIoTClient 0:1f9b2707ec7d 147 }
AzureIoTClient 0:1f9b2707ec7d 148 }
AzureIoTClient 0:1f9b2707ec7d 149 }
AzureIoTClient 0:1f9b2707ec7d 150 }
AzureIoTClient 0:1f9b2707ec7d 151 else
AzureIoTClient 0:1f9b2707ec7d 152 {
AzureIoTClient 0:1f9b2707ec7d 153 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 154 if (MultiTree_GetValue(node, (const void **)&argStringValue) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 155 {
AzureIoTClient 0:1f9b2707ec7d 156 /* Codes_SRS_COMMAND_DECODER_99_012:[ If any argument is missing in the command text then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 23:078ea26cffcd 157 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 158 LogError("Getting the string from the multitree failed.");
AzureIoTClient 0:1f9b2707ec7d 159 }
AzureIoTClient 0:1f9b2707ec7d 160 /* Codes_SRS_COMMAND_DECODER_99_027:[ The value for an argument of primitive type shall be decoded by using the CreateAgentDataType_From_String API.] */
AzureIoTClient 0:1f9b2707ec7d 161 else if (CreateAgentDataType_From_String(argStringValue, primitiveType, agentDataType) != AGENT_DATA_TYPES_OK)
AzureIoTClient 0:1f9b2707ec7d 162 {
AzureIoTClient 0:1f9b2707ec7d 163 /* Codes_SRS_COMMAND_DECODER_99_028:[ If decoding the argument fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 23:078ea26cffcd 164 result = __FAILURE__;
AzureIoTClient 11:b1327861f5e0 165 LogError("Failed parsing node %s.", argStringValue);
AzureIoTClient 0:1f9b2707ec7d 166 }
AzureIoTClient 0:1f9b2707ec7d 167 }
AzureIoTClient 0:1f9b2707ec7d 168
AzureIoTClient 0:1f9b2707ec7d 169 return result;
AzureIoTClient 0:1f9b2707ec7d 170 }
AzureIoTClient 0:1f9b2707ec7d 171
AzureIoTClient 17:fa1bba4c6053 172 static EXECUTE_COMMAND_RESULT DecodeAndExecuteModelAction(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, SCHEMA_MODEL_TYPE_HANDLE modelHandle, const char* relativeActionPath, const char* actionName, MULTITREE_HANDLE commandNode)
AzureIoTClient 0:1f9b2707ec7d 173 {
AzureIoTClient 0:1f9b2707ec7d 174 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 175 char tempStr[128];
AzureIoTClient 0:1f9b2707ec7d 176 size_t strLength = strlen(actionName);
AzureIoTClient 0:1f9b2707ec7d 177
AzureIoTClient 0:1f9b2707ec7d 178 if (strLength <= 1)
AzureIoTClient 0:1f9b2707ec7d 179 {
AzureIoTClient 0:1f9b2707ec7d 180 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 181 LogError("Invalid action name");
AzureIoTClient 0:1f9b2707ec7d 182 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 183 }
AzureIoTClient 36:7d12a5386197 184 else if (strLength >= 128)
AzureIoTClient 36:7d12a5386197 185 {
AzureIoTClient 36:7d12a5386197 186 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 36:7d12a5386197 187 LogError("Invalid action name length");
AzureIoTClient 36:7d12a5386197 188 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 36:7d12a5386197 189 }
AzureIoTClient 0:1f9b2707ec7d 190 else
AzureIoTClient 0:1f9b2707ec7d 191 {
AzureIoTClient 0:1f9b2707ec7d 192 /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "Name" of the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 193 SCHEMA_ACTION_HANDLE modelActionHandle;
AzureIoTClient 0:1f9b2707ec7d 194 size_t argCount;
AzureIoTClient 0:1f9b2707ec7d 195 MULTITREE_HANDLE parametersTreeNode;
AzureIoTClient 0:1f9b2707ec7d 196
AzureIoTClient 36:7d12a5386197 197 if (memcpy(tempStr, actionName, strLength-1) == NULL)
AzureIoTClient 0:1f9b2707ec7d 198 {
AzureIoTClient 0:1f9b2707ec7d 199 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 200 LogError("Invalid action name.");
AzureIoTClient 0:1f9b2707ec7d 201 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 202 }
AzureIoTClient 0:1f9b2707ec7d 203 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 204 else if (MultiTree_GetChildByName(commandNode, "Parameters", &parametersTreeNode) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 205 {
AzureIoTClient 0:1f9b2707ec7d 206 /* Codes_SRS_COMMAND_DECODER_01_015: [If any MultiTree API call fails then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 11:b1327861f5e0 207 LogError("Error getting Parameters node.");
AzureIoTClient 0:1f9b2707ec7d 208 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 209 }
AzureIoTClient 0:1f9b2707ec7d 210 else
AzureIoTClient 0:1f9b2707ec7d 211 {
AzureIoTClient 36:7d12a5386197 212 tempStr[strLength-1] = 0;
AzureIoTClient 0:1f9b2707ec7d 213 /* Codes_SRS_COMMAND_DECODER_99_009:[ CommandDecoder shall call Schema_GetModelActionByName to obtain the information about a specific action.] */
AzureIoTClient 0:1f9b2707ec7d 214 if (((modelActionHandle = Schema_GetModelActionByName(modelHandle, tempStr)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 215 (Schema_GetModelActionArgumentCount(modelActionHandle, &argCount) != SCHEMA_OK))
AzureIoTClient 0:1f9b2707ec7d 216 {
AzureIoTClient 0:1f9b2707ec7d 217 /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 11:b1327861f5e0 218 LogError("Failed reading action %s from the schema", tempStr);
AzureIoTClient 0:1f9b2707ec7d 219 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 220 }
AzureIoTClient 0:1f9b2707ec7d 221 else
AzureIoTClient 0:1f9b2707ec7d 222 {
AzureIoTClient 0:1f9b2707ec7d 223 AGENT_DATA_TYPE* arguments = NULL;
AzureIoTClient 0:1f9b2707ec7d 224
AzureIoTClient 0:1f9b2707ec7d 225 if (argCount > 0)
AzureIoTClient 0:1f9b2707ec7d 226 {
AzureIoTClient 0:1f9b2707ec7d 227 arguments = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE)* argCount);
AzureIoTClient 0:1f9b2707ec7d 228 }
AzureIoTClient 0:1f9b2707ec7d 229
AzureIoTClient 0:1f9b2707ec7d 230 if ((argCount > 0) &&
AzureIoTClient 0:1f9b2707ec7d 231 (arguments == NULL))
AzureIoTClient 0:1f9b2707ec7d 232 {
AzureIoTClient 0:1f9b2707ec7d 233 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 234 LogError("Failed allocating arguments array");
AzureIoTClient 0:1f9b2707ec7d 235 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 236 }
AzureIoTClient 0:1f9b2707ec7d 237 else
AzureIoTClient 0:1f9b2707ec7d 238 {
AzureIoTClient 0:1f9b2707ec7d 239 size_t i;
AzureIoTClient 0:1f9b2707ec7d 240 size_t j;
AzureIoTClient 14:0c00e67a4ab1 241 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 242
AzureIoTClient 0:1f9b2707ec7d 243 /* Codes_SRS_COMMAND_DECODER_99_011:[ CommandDecoder shall attempt to extract from the command text the value for each action argument.] */
AzureIoTClient 0:1f9b2707ec7d 244 for (i = 0; i < argCount; i++)
AzureIoTClient 0:1f9b2707ec7d 245 {
AzureIoTClient 0:1f9b2707ec7d 246 SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle;
AzureIoTClient 0:1f9b2707ec7d 247 MULTITREE_HANDLE argumentNode;
AzureIoTClient 0:1f9b2707ec7d 248 const char* argName;
AzureIoTClient 0:1f9b2707ec7d 249 const char* argType;
AzureIoTClient 0:1f9b2707ec7d 250
AzureIoTClient 0:1f9b2707ec7d 251 if (((actionArgumentHandle = Schema_GetModelActionArgumentByIndex(modelActionHandle, i)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 252 ((argName = Schema_GetActionArgumentName(actionArgumentHandle)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 253 ((argType = Schema_GetActionArgumentType(actionArgumentHandle)) == NULL))
AzureIoTClient 0:1f9b2707ec7d 254 {
AzureIoTClient 11:b1327861f5e0 255 LogError("Failed getting the argument information from the schema");
AzureIoTClient 0:1f9b2707ec7d 256 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 257 break;
AzureIoTClient 0:1f9b2707ec7d 258 }
AzureIoTClient 0:1f9b2707ec7d 259 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 260 /* Codes_SRS_COMMAND_DECODER_01_008: [Each argument shall be looked up as a field, member of the "Parameters" node.] */
AzureIoTClient 0:1f9b2707ec7d 261 else if (MultiTree_GetChildByName(parametersTreeNode, argName, &argumentNode) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 262 {
AzureIoTClient 0:1f9b2707ec7d 263 /* Codes_SRS_COMMAND_DECODER_99_012:[ If any argument is missing in the command text then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 11:b1327861f5e0 264 LogError("Missing argument %s", argName);
AzureIoTClient 0:1f9b2707ec7d 265 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 266 break;
AzureIoTClient 0:1f9b2707ec7d 267 }
AzureIoTClient 0:1f9b2707ec7d 268 else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0)
AzureIoTClient 0:1f9b2707ec7d 269 {
AzureIoTClient 0:1f9b2707ec7d 270 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 271 break;
AzureIoTClient 0:1f9b2707ec7d 272 }
AzureIoTClient 0:1f9b2707ec7d 273 }
AzureIoTClient 0:1f9b2707ec7d 274
AzureIoTClient 0:1f9b2707ec7d 275 if (i == argCount)
AzureIoTClient 0:1f9b2707ec7d 276 {
AzureIoTClient 0:1f9b2707ec7d 277 /* Codes_SRS_COMMAND_DECODER_99_005:[ If an Invoke Action is decoded successfully then the callback actionCallback shall be called, passing to it the callback action context, decoded name and arguments.] */
AzureIoTClient 0:1f9b2707ec7d 278 result = commandDecoderInstance->ActionCallback(commandDecoderInstance->ActionCallbackContext, relativeActionPath, tempStr, argCount, arguments);
AzureIoTClient 0:1f9b2707ec7d 279 }
AzureIoTClient 0:1f9b2707ec7d 280
AzureIoTClient 0:1f9b2707ec7d 281 for (j = 0; j < i; j++)
AzureIoTClient 0:1f9b2707ec7d 282 {
AzureIoTClient 0:1f9b2707ec7d 283 Destroy_AGENT_DATA_TYPE(&arguments[j]);
AzureIoTClient 0:1f9b2707ec7d 284 }
AzureIoTClient 0:1f9b2707ec7d 285
AzureIoTClient 0:1f9b2707ec7d 286 if (arguments != NULL)
AzureIoTClient 0:1f9b2707ec7d 287 {
AzureIoTClient 0:1f9b2707ec7d 288 free(arguments);
AzureIoTClient 0:1f9b2707ec7d 289 }
AzureIoTClient 0:1f9b2707ec7d 290 }
AzureIoTClient 0:1f9b2707ec7d 291 }
AzureIoTClient 0:1f9b2707ec7d 292 }
AzureIoTClient 0:1f9b2707ec7d 293 }
AzureIoTClient 0:1f9b2707ec7d 294 return result;
AzureIoTClient 0:1f9b2707ec7d 295 }
AzureIoTClient 0:1f9b2707ec7d 296
Azure.IoT.Build 18:58b667752399 297 static METHODRETURN_HANDLE DecodeAndExecuteModelMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, SCHEMA_MODEL_TYPE_HANDLE modelHandle, const char* relativeMethodPath, const char* methodName, MULTITREE_HANDLE methodTree)
Azure.IoT.Build 18:58b667752399 298 {
Azure.IoT.Build 18:58b667752399 299 METHODRETURN_HANDLE result;
Azure.IoT.Build 18:58b667752399 300 size_t strLength = strlen(methodName);
Azure.IoT.Build 18:58b667752399 301
Azure.IoT.Build 18:58b667752399 302 if (strLength == 0)
Azure.IoT.Build 18:58b667752399 303 {
Azure.IoT.Build 18:58b667752399 304 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 305 LogError("Invalid method name");
Azure.IoT.Build 18:58b667752399 306 result = NULL;
Azure.IoT.Build 18:58b667752399 307 }
Azure.IoT.Build 18:58b667752399 308 else
Azure.IoT.Build 18:58b667752399 309 {
Azure.IoT.Build 18:58b667752399 310 SCHEMA_METHOD_HANDLE modelMethodHandle;
Azure.IoT.Build 18:58b667752399 311 size_t argCount;
Azure.IoT.Build 18:58b667752399 312
Azure.IoT.Build 18:58b667752399 313 #ifdef _MSC_VER
AzureIoTClient 36:7d12a5386197 314 #pragma warning(suppress: 6324) /* We intentionally use here strncpy */
Azure.IoT.Build 18:58b667752399 315 #endif
AzureIoTClient 36:7d12a5386197 316
Azure.IoT.Build 18:58b667752399 317 /*Codes_SRS_COMMAND_DECODER_02_020: [ CommandDecoder_ExecuteMethod shall verify that the model has a method called methodName. ]*/
Azure.IoT.Build 18:58b667752399 318 if (((modelMethodHandle = Schema_GetModelMethodByName(modelHandle, methodName)) == NULL) ||
Azure.IoT.Build 18:58b667752399 319 (Schema_GetModelMethodArgumentCount(modelMethodHandle, &argCount) != SCHEMA_OK))
Azure.IoT.Build 18:58b667752399 320 {
Azure.IoT.Build 18:58b667752399 321 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 322 LogError("Failed reading method %s from the schema", methodName);
Azure.IoT.Build 18:58b667752399 323 result = NULL;
Azure.IoT.Build 18:58b667752399 324 }
Azure.IoT.Build 18:58b667752399 325 else
Azure.IoT.Build 18:58b667752399 326 {
Azure.IoT.Build 18:58b667752399 327 /*Codes_SRS_COMMAND_DECODER_02_021: [ For every argument of methodName, CommandDecoder_ExecuteMethod shall build an AGENT_DATA_TYPE from the node with the same name from the MULTITREE_HANDLE. ]*/
AzureIoTClient 36:7d12a5386197 328
Azure.IoT.Build 18:58b667752399 329 if (argCount == 0)
Azure.IoT.Build 18:58b667752399 330 {
Azure.IoT.Build 18:58b667752399 331 /*no need for any parameters*/
Azure.IoT.Build 18:58b667752399 332 result = commandDecoderInstance->methodCallback(commandDecoderInstance->methodCallbackContext, relativeMethodPath, methodName, 0, NULL);
Azure.IoT.Build 18:58b667752399 333 }
Azure.IoT.Build 18:58b667752399 334 else
Azure.IoT.Build 18:58b667752399 335 {
Azure.IoT.Build 18:58b667752399 336 AGENT_DATA_TYPE* arguments;
Azure.IoT.Build 18:58b667752399 337 arguments = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE)* argCount);
Azure.IoT.Build 18:58b667752399 338 if (arguments == NULL)
Azure.IoT.Build 18:58b667752399 339 {
Azure.IoT.Build 18:58b667752399 340 LogError("Failed allocating arguments array");
Azure.IoT.Build 18:58b667752399 341 result = NULL;
Azure.IoT.Build 18:58b667752399 342 }
Azure.IoT.Build 18:58b667752399 343 else
Azure.IoT.Build 18:58b667752399 344 {
Azure.IoT.Build 18:58b667752399 345 size_t i;
Azure.IoT.Build 18:58b667752399 346 size_t j;
Azure.IoT.Build 18:58b667752399 347 result = NULL;
Azure.IoT.Build 18:58b667752399 348
Azure.IoT.Build 18:58b667752399 349 for (i = 0; i < argCount; i++)
Azure.IoT.Build 18:58b667752399 350 {
Azure.IoT.Build 18:58b667752399 351 SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle;
Azure.IoT.Build 18:58b667752399 352 MULTITREE_HANDLE argumentNode;
Azure.IoT.Build 18:58b667752399 353 const char* argName;
Azure.IoT.Build 18:58b667752399 354 const char* argType;
Azure.IoT.Build 18:58b667752399 355
Azure.IoT.Build 18:58b667752399 356 if (((methodArgumentHandle = Schema_GetModelMethodArgumentByIndex(modelMethodHandle, i)) == NULL) ||
Azure.IoT.Build 18:58b667752399 357 ((argName = Schema_GetMethodArgumentName(methodArgumentHandle)) == NULL) ||
Azure.IoT.Build 18:58b667752399 358 ((argType = Schema_GetMethodArgumentType(methodArgumentHandle)) == NULL))
Azure.IoT.Build 18:58b667752399 359 {
Azure.IoT.Build 18:58b667752399 360 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 361 LogError("Failed getting the argument information from the schema");
Azure.IoT.Build 18:58b667752399 362 result = NULL;
Azure.IoT.Build 18:58b667752399 363 break;
Azure.IoT.Build 18:58b667752399 364 }
Azure.IoT.Build 18:58b667752399 365 else if (MultiTree_GetChildByName(methodTree, argName, &argumentNode) != MULTITREE_OK)
Azure.IoT.Build 18:58b667752399 366 {
Azure.IoT.Build 18:58b667752399 367 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 368 LogError("Missing argument %s", argName);
Azure.IoT.Build 18:58b667752399 369 result = NULL;
Azure.IoT.Build 18:58b667752399 370 break;
Azure.IoT.Build 18:58b667752399 371 }
Azure.IoT.Build 18:58b667752399 372 else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0)
Azure.IoT.Build 18:58b667752399 373 {
Azure.IoT.Build 18:58b667752399 374 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 375 LogError("failure in DecodeValueFromNode");
Azure.IoT.Build 18:58b667752399 376 result = NULL;
Azure.IoT.Build 18:58b667752399 377 break;
Azure.IoT.Build 18:58b667752399 378 }
Azure.IoT.Build 18:58b667752399 379 }
Azure.IoT.Build 18:58b667752399 380
Azure.IoT.Build 18:58b667752399 381 if (i == argCount)
Azure.IoT.Build 18:58b667752399 382 {
Azure.IoT.Build 18:58b667752399 383 /*Codes_SRS_COMMAND_DECODER_02_022: [ CommandDecoder_ExecuteMethod shall call methodCallback passing the context, the methodName, number of arguments and the AGENT_DATA_TYPE. ]*/
Azure.IoT.Build 18:58b667752399 384 /*Codes_SRS_COMMAND_DECODER_02_024: [ Otherwise, CommandDecoder_ExecuteMethod shall return what methodCallback returns. ]*/
Azure.IoT.Build 18:58b667752399 385 result = commandDecoderInstance->methodCallback(commandDecoderInstance->methodCallbackContext, relativeMethodPath, methodName, argCount, arguments);
Azure.IoT.Build 18:58b667752399 386 }
Azure.IoT.Build 18:58b667752399 387
Azure.IoT.Build 18:58b667752399 388 for (j = 0; j < i; j++)
Azure.IoT.Build 18:58b667752399 389 {
Azure.IoT.Build 18:58b667752399 390 Destroy_AGENT_DATA_TYPE(&arguments[j]);
Azure.IoT.Build 18:58b667752399 391 }
Azure.IoT.Build 18:58b667752399 392
Azure.IoT.Build 18:58b667752399 393 free(arguments);
Azure.IoT.Build 18:58b667752399 394 }
Azure.IoT.Build 18:58b667752399 395
Azure.IoT.Build 18:58b667752399 396 }
Azure.IoT.Build 18:58b667752399 397 }
AzureIoTClient 36:7d12a5386197 398
Azure.IoT.Build 18:58b667752399 399 }
Azure.IoT.Build 18:58b667752399 400 return result;
Azure.IoT.Build 18:58b667752399 401 }
Azure.IoT.Build 18:58b667752399 402
Azure.IoT.Build 18:58b667752399 403
AzureIoTClient 17:fa1bba4c6053 404 static EXECUTE_COMMAND_RESULT ScanActionPathAndExecuteAction(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* actionPath, MULTITREE_HANDLE commandNode)
AzureIoTClient 0:1f9b2707ec7d 405 {
AzureIoTClient 0:1f9b2707ec7d 406 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 407 char* relativeActionPath;
AzureIoTClient 0:1f9b2707ec7d 408 const char* actionName = actionPath;
AzureIoTClient 0:1f9b2707ec7d 409 SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle;
AzureIoTClient 0:1f9b2707ec7d 410
AzureIoTClient 0:1f9b2707ec7d 411 /* Codes_SRS_COMMAND_DECODER_99_035:[ CommandDecoder_ExecuteCommand shall support paths to actions that are in child models (i.e. ChildModel/SomeAction.] */
AzureIoTClient 0:1f9b2707ec7d 412 do
AzureIoTClient 0:1f9b2707ec7d 413 {
AzureIoTClient 0:1f9b2707ec7d 414 /* find the slash */
AzureIoTClient 0:1f9b2707ec7d 415 const char* slashPos = strchr(actionName, '/');
AzureIoTClient 0:1f9b2707ec7d 416 if (slashPos == NULL)
AzureIoTClient 0:1f9b2707ec7d 417 {
AzureIoTClient 0:1f9b2707ec7d 418 size_t relativeActionPathLength;
AzureIoTClient 0:1f9b2707ec7d 419
AzureIoTClient 0:1f9b2707ec7d 420 /* Codes_SRS_COMMAND_DECODER_99_037:[ The relative path passed to the actionCallback shall be in the format "childModel1/childModel2/.../childModelN".] */
AzureIoTClient 0:1f9b2707ec7d 421 if (actionName == actionPath)
AzureIoTClient 0:1f9b2707ec7d 422 {
AzureIoTClient 0:1f9b2707ec7d 423 relativeActionPathLength = 0;
AzureIoTClient 0:1f9b2707ec7d 424 }
AzureIoTClient 0:1f9b2707ec7d 425 else
AzureIoTClient 0:1f9b2707ec7d 426 {
AzureIoTClient 0:1f9b2707ec7d 427 relativeActionPathLength = actionName - actionPath - 1;
AzureIoTClient 0:1f9b2707ec7d 428 }
AzureIoTClient 0:1f9b2707ec7d 429
AzureIoTClient 0:1f9b2707ec7d 430 relativeActionPath = (char*)malloc(relativeActionPathLength + 1);
AzureIoTClient 0:1f9b2707ec7d 431 if (relativeActionPath == NULL)
AzureIoTClient 0:1f9b2707ec7d 432 {
AzureIoTClient 0:1f9b2707ec7d 433 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 434 LogError("Failed allocating relative action path");
AzureIoTClient 0:1f9b2707ec7d 435 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 436 }
AzureIoTClient 0:1f9b2707ec7d 437 else
AzureIoTClient 0:1f9b2707ec7d 438 {
AzureIoTClient 0:1f9b2707ec7d 439 strncpy(relativeActionPath, actionPath, relativeActionPathLength);
AzureIoTClient 0:1f9b2707ec7d 440 relativeActionPath[relativeActionPathLength] = 0;
AzureIoTClient 0:1f9b2707ec7d 441
AzureIoTClient 0:1f9b2707ec7d 442 /* no slash found, this must be an action */
AzureIoTClient 0:1f9b2707ec7d 443 result = DecodeAndExecuteModelAction(commandDecoderInstance, schemaHandle, modelHandle, relativeActionPath, actionName, commandNode);
AzureIoTClient 0:1f9b2707ec7d 444
AzureIoTClient 0:1f9b2707ec7d 445 free(relativeActionPath);
AzureIoTClient 0:1f9b2707ec7d 446 actionName = NULL;
AzureIoTClient 0:1f9b2707ec7d 447 }
AzureIoTClient 0:1f9b2707ec7d 448 break;
AzureIoTClient 0:1f9b2707ec7d 449 }
AzureIoTClient 0:1f9b2707ec7d 450 else
AzureIoTClient 0:1f9b2707ec7d 451 {
AzureIoTClient 0:1f9b2707ec7d 452 /* found a slash, get the child model name */
AzureIoTClient 0:1f9b2707ec7d 453 size_t modelLength = slashPos - actionName;
AzureIoTClient 0:1f9b2707ec7d 454 char* childModelName = (char*)malloc(modelLength + 1);
AzureIoTClient 0:1f9b2707ec7d 455 if (childModelName == NULL)
AzureIoTClient 0:1f9b2707ec7d 456 {
AzureIoTClient 0:1f9b2707ec7d 457 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 458 LogError("Failed allocating child model name");
AzureIoTClient 0:1f9b2707ec7d 459 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 460 break;
AzureIoTClient 0:1f9b2707ec7d 461 }
AzureIoTClient 0:1f9b2707ec7d 462 else
AzureIoTClient 0:1f9b2707ec7d 463 {
AzureIoTClient 0:1f9b2707ec7d 464 strncpy(childModelName, actionName, modelLength);
AzureIoTClient 0:1f9b2707ec7d 465 childModelName[modelLength] = 0;
AzureIoTClient 0:1f9b2707ec7d 466
AzureIoTClient 0:1f9b2707ec7d 467 /* find the model */
AzureIoTClient 0:1f9b2707ec7d 468 modelHandle = Schema_GetModelModelByName(modelHandle, childModelName);
AzureIoTClient 0:1f9b2707ec7d 469 if (modelHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 470 {
AzureIoTClient 0:1f9b2707ec7d 471 /* Codes_SRS_COMMAND_DECODER_99_036:[ If a child model cannot be found by using Schema APIs then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 11:b1327861f5e0 472 LogError("Getting the model %s failed", childModelName);
AzureIoTClient 0:1f9b2707ec7d 473 free(childModelName);
AzureIoTClient 0:1f9b2707ec7d 474 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 475 break;
AzureIoTClient 0:1f9b2707ec7d 476 }
AzureIoTClient 0:1f9b2707ec7d 477 else
AzureIoTClient 0:1f9b2707ec7d 478 {
AzureIoTClient 0:1f9b2707ec7d 479 free(childModelName);
AzureIoTClient 0:1f9b2707ec7d 480 actionName = slashPos + 1;
AzureIoTClient 0:1f9b2707ec7d 481 result = EXECUTE_COMMAND_ERROR; /*this only exists to quench a compiler warning about returning an uninitialized variable, which is not possible by design*/
AzureIoTClient 0:1f9b2707ec7d 482 }
AzureIoTClient 0:1f9b2707ec7d 483 }
AzureIoTClient 0:1f9b2707ec7d 484 }
AzureIoTClient 0:1f9b2707ec7d 485 } while (actionName != NULL);
AzureIoTClient 0:1f9b2707ec7d 486 return result;
AzureIoTClient 0:1f9b2707ec7d 487 }
AzureIoTClient 0:1f9b2707ec7d 488
Azure.IoT.Build 18:58b667752399 489 static METHODRETURN_HANDLE ScanMethodPathAndExecuteMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* fullMethodName, MULTITREE_HANDLE methodTree)
Azure.IoT.Build 18:58b667752399 490 {
Azure.IoT.Build 18:58b667752399 491 METHODRETURN_HANDLE result;
Azure.IoT.Build 18:58b667752399 492 char* relativeMethodPath;
Azure.IoT.Build 18:58b667752399 493 const char* methodName = fullMethodName;
Azure.IoT.Build 18:58b667752399 494 SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle;
Azure.IoT.Build 18:58b667752399 495
Azure.IoT.Build 18:58b667752399 496 /*Codes_SRS_COMMAND_DECODER_02_018: [ CommandDecoder_ExecuteMethod shall validate that consecutive segments of the fullMethodName exist in the model. ]*/
Azure.IoT.Build 18:58b667752399 497 /*Codes_SRS_COMMAND_DECODER_02_019: [ CommandDecoder_ExecuteMethod shall locate the final model to which the methodName applies. ]*/
Azure.IoT.Build 18:58b667752399 498 do
Azure.IoT.Build 18:58b667752399 499 {
Azure.IoT.Build 18:58b667752399 500 /* find the slash */
Azure.IoT.Build 18:58b667752399 501 const char* slashPos = strchr(methodName, '/');
Azure.IoT.Build 18:58b667752399 502 if (slashPos == NULL)
Azure.IoT.Build 18:58b667752399 503 {
Azure.IoT.Build 18:58b667752399 504 size_t relativeMethodPathLength;
Azure.IoT.Build 18:58b667752399 505
Azure.IoT.Build 18:58b667752399 506 if (methodName == fullMethodName)
Azure.IoT.Build 18:58b667752399 507 {
Azure.IoT.Build 18:58b667752399 508 relativeMethodPathLength = 0;
Azure.IoT.Build 18:58b667752399 509 }
Azure.IoT.Build 18:58b667752399 510 else
Azure.IoT.Build 18:58b667752399 511 {
Azure.IoT.Build 18:58b667752399 512 relativeMethodPathLength = methodName - fullMethodName - 1;
Azure.IoT.Build 18:58b667752399 513 }
Azure.IoT.Build 18:58b667752399 514
Azure.IoT.Build 18:58b667752399 515 relativeMethodPath = (char*)malloc(relativeMethodPathLength + 1);
Azure.IoT.Build 18:58b667752399 516 if (relativeMethodPath == NULL)
Azure.IoT.Build 18:58b667752399 517 {
Azure.IoT.Build 18:58b667752399 518 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 519 LogError("Failed allocating relative method path");
Azure.IoT.Build 18:58b667752399 520 result = NULL;
Azure.IoT.Build 18:58b667752399 521 }
Azure.IoT.Build 18:58b667752399 522 else
Azure.IoT.Build 18:58b667752399 523 {
Azure.IoT.Build 18:58b667752399 524 strncpy(relativeMethodPath, fullMethodName, relativeMethodPathLength);
Azure.IoT.Build 18:58b667752399 525 relativeMethodPath[relativeMethodPathLength] = 0;
Azure.IoT.Build 18:58b667752399 526
Azure.IoT.Build 18:58b667752399 527 /* no slash found, this must be an method */
Azure.IoT.Build 18:58b667752399 528 result = DecodeAndExecuteModelMethod(commandDecoderInstance, schemaHandle, modelHandle, relativeMethodPath, methodName, methodTree);
Azure.IoT.Build 18:58b667752399 529
Azure.IoT.Build 18:58b667752399 530 free(relativeMethodPath);
Azure.IoT.Build 18:58b667752399 531 methodName = NULL;
Azure.IoT.Build 18:58b667752399 532 }
Azure.IoT.Build 18:58b667752399 533 break;
Azure.IoT.Build 18:58b667752399 534 }
Azure.IoT.Build 18:58b667752399 535 else
Azure.IoT.Build 18:58b667752399 536 {
Azure.IoT.Build 18:58b667752399 537 /* found a slash, get the child model name */
Azure.IoT.Build 18:58b667752399 538 size_t modelLength = slashPos - methodName;
Azure.IoT.Build 18:58b667752399 539 char* childModelName = (char*)malloc(modelLength + 1);
Azure.IoT.Build 18:58b667752399 540 if (childModelName == NULL)
Azure.IoT.Build 18:58b667752399 541 {
Azure.IoT.Build 18:58b667752399 542 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 543 LogError("Failed allocating child model name");
Azure.IoT.Build 18:58b667752399 544 result = NULL;
Azure.IoT.Build 18:58b667752399 545 break;
Azure.IoT.Build 18:58b667752399 546 }
Azure.IoT.Build 18:58b667752399 547 else
Azure.IoT.Build 18:58b667752399 548 {
Azure.IoT.Build 18:58b667752399 549 strncpy(childModelName, methodName, modelLength);
Azure.IoT.Build 18:58b667752399 550 childModelName[modelLength] = 0;
Azure.IoT.Build 18:58b667752399 551
Azure.IoT.Build 18:58b667752399 552 /* find the model */
Azure.IoT.Build 18:58b667752399 553 modelHandle = Schema_GetModelModelByName(modelHandle, childModelName);
Azure.IoT.Build 18:58b667752399 554 if (modelHandle == NULL)
Azure.IoT.Build 18:58b667752399 555 {
Azure.IoT.Build 18:58b667752399 556 /*Codes_SRS_COMMAND_DECODER_02_023: [ If any of the previous operations fail, then CommandDecoder_ExecuteMethod shall return NULL. ]*/
Azure.IoT.Build 18:58b667752399 557 LogError("Getting the model %s failed", childModelName);
Azure.IoT.Build 18:58b667752399 558 free(childModelName);
Azure.IoT.Build 18:58b667752399 559 result = NULL;
Azure.IoT.Build 18:58b667752399 560 break;
Azure.IoT.Build 18:58b667752399 561 }
Azure.IoT.Build 18:58b667752399 562 else
Azure.IoT.Build 18:58b667752399 563 {
Azure.IoT.Build 18:58b667752399 564 free(childModelName);
Azure.IoT.Build 18:58b667752399 565 methodName = slashPos + 1;
Azure.IoT.Build 18:58b667752399 566 result = NULL; /*this only exists to quench a compiler warning about returning an uninitialized variable, which is not possible by design*/
Azure.IoT.Build 18:58b667752399 567 }
Azure.IoT.Build 18:58b667752399 568 }
Azure.IoT.Build 18:58b667752399 569 }
Azure.IoT.Build 18:58b667752399 570 } while (methodName != NULL);
Azure.IoT.Build 18:58b667752399 571 return result;
Azure.IoT.Build 18:58b667752399 572 }
Azure.IoT.Build 18:58b667752399 573
AzureIoTClient 17:fa1bba4c6053 574 static EXECUTE_COMMAND_RESULT DecodeCommand(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, MULTITREE_HANDLE commandNode)
AzureIoTClient 0:1f9b2707ec7d 575 {
AzureIoTClient 0:1f9b2707ec7d 576 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 577 SCHEMA_HANDLE schemaHandle;
AzureIoTClient 0:1f9b2707ec7d 578
AzureIoTClient 0:1f9b2707ec7d 579 /* Codes_SRS_COMMAND_DECODER_99_022:[ CommandDecoder shall use the Schema APIs to obtain the information about the entity set name and namespace] */
AzureIoTClient 0:1f9b2707ec7d 580 if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 581 {
AzureIoTClient 0:1f9b2707ec7d 582 /* Codes_SRS_COMMAND_DECODER_99_010:[ If any Schema API fails then the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 11:b1327861f5e0 583 LogError("Getting schema information failed");
AzureIoTClient 0:1f9b2707ec7d 584 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 585 }
AzureIoTClient 0:1f9b2707ec7d 586 else
AzureIoTClient 0:1f9b2707ec7d 587 {
AzureIoTClient 0:1f9b2707ec7d 588 const char* actionName;
AzureIoTClient 0:1f9b2707ec7d 589 MULTITREE_HANDLE nameTreeNode;
AzureIoTClient 0:1f9b2707ec7d 590
AzureIoTClient 0:1f9b2707ec7d 591 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 592 /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "name" of the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 593 if ((MultiTree_GetChildByName(commandNode, "Name", &nameTreeNode) != MULTITREE_OK) ||
AzureIoTClient 0:1f9b2707ec7d 594 (MultiTree_GetValue(nameTreeNode, (const void **)&actionName) != MULTITREE_OK))
AzureIoTClient 0:1f9b2707ec7d 595 {
AzureIoTClient 0:1f9b2707ec7d 596 /* Codes_SRS_COMMAND_DECODER_01_015: [If any MultiTree API call fails then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 11:b1327861f5e0 597 LogError("Getting action name failed.");
AzureIoTClient 0:1f9b2707ec7d 598 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 599 }
AzureIoTClient 0:1f9b2707ec7d 600 else if (strlen(actionName) < 2)
AzureIoTClient 0:1f9b2707ec7d 601 {
AzureIoTClient 0:1f9b2707ec7d 602 /* Codes_SRS_COMMAND_DECODER_99_021:[ If the parsing of the command fails for any other reason the command shall not be dispatched.] */
AzureIoTClient 11:b1327861f5e0 603 LogError("Invalid action name.");
AzureIoTClient 0:1f9b2707ec7d 604 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 605 }
AzureIoTClient 0:1f9b2707ec7d 606 else
AzureIoTClient 0:1f9b2707ec7d 607 {
AzureIoTClient 0:1f9b2707ec7d 608 actionName++;
AzureIoTClient 0:1f9b2707ec7d 609 result = ScanActionPathAndExecuteAction(commandDecoderInstance, schemaHandle, actionName, commandNode);
AzureIoTClient 0:1f9b2707ec7d 610 }
AzureIoTClient 0:1f9b2707ec7d 611 }
AzureIoTClient 0:1f9b2707ec7d 612 return result;
AzureIoTClient 0:1f9b2707ec7d 613 }
AzureIoTClient 0:1f9b2707ec7d 614
Azure.IoT.Build 18:58b667752399 615 static METHODRETURN_HANDLE DecodeMethod(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, const char* fullMethodName, MULTITREE_HANDLE methodTree)
Azure.IoT.Build 18:58b667752399 616 {
Azure.IoT.Build 18:58b667752399 617 METHODRETURN_HANDLE result;
Azure.IoT.Build 18:58b667752399 618 SCHEMA_HANDLE schemaHandle;
Azure.IoT.Build 18:58b667752399 619
Azure.IoT.Build 18:58b667752399 620 /*Codes_SRS_COMMAND_DECODER_02_017: [ CommandDecoder_ExecuteMethod shall get the SCHEMA_HANDLE associated with the modelHandle passed at CommandDecoder_Create. ]*/
Azure.IoT.Build 18:58b667752399 621 if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL)
Azure.IoT.Build 18:58b667752399 622 {
Azure.IoT.Build 18:58b667752399 623 LogError("Getting schema information failed");
Azure.IoT.Build 18:58b667752399 624 result = NULL;
Azure.IoT.Build 18:58b667752399 625 }
Azure.IoT.Build 18:58b667752399 626 else
Azure.IoT.Build 18:58b667752399 627 {
Azure.IoT.Build 18:58b667752399 628 result = ScanMethodPathAndExecuteMethod(commandDecoderInstance, schemaHandle, fullMethodName, methodTree);
AzureIoTClient 36:7d12a5386197 629
Azure.IoT.Build 18:58b667752399 630 }
Azure.IoT.Build 18:58b667752399 631 return result;
Azure.IoT.Build 18:58b667752399 632 }
Azure.IoT.Build 18:58b667752399 633
AzureIoTClient 0:1f9b2707ec7d 634 /*Codes_SRS_COMMAND_DECODER_01_009: [Whenever CommandDecoder_ExecuteCommand is the command shall be decoded and further dispatched to the actionCallback passed in CommandDecoder_Create.]*/
AzureIoTClient 0:1f9b2707ec7d 635 EXECUTE_COMMAND_RESULT CommandDecoder_ExecuteCommand(COMMAND_DECODER_HANDLE handle, const char* command)
AzureIoTClient 0:1f9b2707ec7d 636 {
AzureIoTClient 0:1f9b2707ec7d 637 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 17:fa1bba4c6053 638 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
AzureIoTClient 0:1f9b2707ec7d 639 /*Codes_SRS_COMMAND_DECODER_01_010: [If either the buffer or the receiveCallbackContext argument is NULL, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 0:1f9b2707ec7d 640 if (
AzureIoTClient 0:1f9b2707ec7d 641 (command == NULL) ||
AzureIoTClient 36:7d12a5386197 642 (commandDecoderInstance == NULL)
AzureIoTClient 0:1f9b2707ec7d 643 )
AzureIoTClient 0:1f9b2707ec7d 644 {
AzureIoTClient 11:b1327861f5e0 645 LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* command=%p", handle, command);
AzureIoTClient 0:1f9b2707ec7d 646 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 647 }
AzureIoTClient 0:1f9b2707ec7d 648 else
AzureIoTClient 0:1f9b2707ec7d 649 {
AzureIoTClient 0:1f9b2707ec7d 650 size_t size = strlen(command);
AzureIoTClient 0:1f9b2707ec7d 651 char* commandJSON;
AzureIoTClient 0:1f9b2707ec7d 652
AzureIoTClient 0:1f9b2707ec7d 653 /* Codes_SRS_COMMAND_DECODER_01_011: [If the size of the command is 0 then the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 22:422d94bd3c18 654 if (size == 0)
AzureIoTClient 0:1f9b2707ec7d 655 {
AzureIoTClient 11:b1327861f5e0 656 LogError("Failed because command size is zero");
AzureIoTClient 0:1f9b2707ec7d 657 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 658 }
AzureIoTClient 0:1f9b2707ec7d 659 /*Codes_SRS_COMMAND_DECODER_01_013: [If parsing the JSON to a multi tree fails, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.]*/
AzureIoTClient 0:1f9b2707ec7d 660 else if ((commandJSON = (char*)malloc(size + 1)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 661 {
AzureIoTClient 11:b1327861f5e0 662 LogError("Failed to allocate temporary storage for the commands JSON");
AzureIoTClient 0:1f9b2707ec7d 663 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 664 }
AzureIoTClient 0:1f9b2707ec7d 665 else
AzureIoTClient 0:1f9b2707ec7d 666 {
AzureIoTClient 0:1f9b2707ec7d 667 MULTITREE_HANDLE commandsTree;
AzureIoTClient 0:1f9b2707ec7d 668
AzureIoTClient 0:1f9b2707ec7d 669 (void)memcpy(commandJSON, command, size);
AzureIoTClient 0:1f9b2707ec7d 670 commandJSON[size] = '\0';
AzureIoTClient 0:1f9b2707ec7d 671
AzureIoTClient 0:1f9b2707ec7d 672 /* Codes_SRS_COMMAND_DECODER_01_012: [CommandDecoder shall decode the command JSON contained in buffer to a multi-tree by using JSONDecoder_JSON_To_MultiTree.] */
AzureIoTClient 0:1f9b2707ec7d 673 if (JSONDecoder_JSON_To_MultiTree(commandJSON, &commandsTree) != JSON_DECODER_OK)
AzureIoTClient 0:1f9b2707ec7d 674 {
AzureIoTClient 0:1f9b2707ec7d 675 /* Codes_SRS_COMMAND_DECODER_01_013: [If parsing the JSON to a multi tree fails, the processing shall stop and the command shall not be dispatched and it shall return EXECUTE_COMMAND_ERROR.] */
AzureIoTClient 11:b1327861f5e0 676 LogError("Decoding JSON to a multi tree failed");
AzureIoTClient 0:1f9b2707ec7d 677 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 678 }
AzureIoTClient 0:1f9b2707ec7d 679 else
AzureIoTClient 0:1f9b2707ec7d 680 {
AzureIoTClient 0:1f9b2707ec7d 681 result = DecodeCommand(commandDecoderInstance, commandsTree);
AzureIoTClient 0:1f9b2707ec7d 682
AzureIoTClient 0:1f9b2707ec7d 683 /* Codes_SRS_COMMAND_DECODER_01_016: [CommandDecoder shall ensure that the multi-tree resulting from JSONDecoder_JSON_To_MultiTree is freed after the commands are executed.] */
AzureIoTClient 0:1f9b2707ec7d 684 MultiTree_Destroy(commandsTree);
AzureIoTClient 0:1f9b2707ec7d 685 }
AzureIoTClient 0:1f9b2707ec7d 686
AzureIoTClient 0:1f9b2707ec7d 687 free(commandJSON);
AzureIoTClient 0:1f9b2707ec7d 688 }
AzureIoTClient 0:1f9b2707ec7d 689 }
AzureIoTClient 0:1f9b2707ec7d 690 return result;
AzureIoTClient 0:1f9b2707ec7d 691 }
AzureIoTClient 0:1f9b2707ec7d 692
Azure.IoT.Build 18:58b667752399 693 METHODRETURN_HANDLE CommandDecoder_ExecuteMethod(COMMAND_DECODER_HANDLE handle, const char* fullMethodName, const char* methodPayload)
Azure.IoT.Build 18:58b667752399 694 {
Azure.IoT.Build 18:58b667752399 695 METHODRETURN_HANDLE result;
Azure.IoT.Build 18:58b667752399 696 /*Codes_SRS_COMMAND_DECODER_02_014: [ If handle is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
Azure.IoT.Build 18:58b667752399 697 /*Codes_SRS_COMMAND_DECODER_02_015: [ If fulMethodName is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
Azure.IoT.Build 18:58b667752399 698 if (
Azure.IoT.Build 18:58b667752399 699 (handle == NULL) ||
Azure.IoT.Build 18:58b667752399 700 (fullMethodName == NULL) /*methodPayload can be NULL*/
Azure.IoT.Build 18:58b667752399 701 )
Azure.IoT.Build 18:58b667752399 702 {
Azure.IoT.Build 18:58b667752399 703 LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* fullMethodName=%p", handle, fullMethodName);
Azure.IoT.Build 18:58b667752399 704 result = NULL;
Azure.IoT.Build 18:58b667752399 705 }
Azure.IoT.Build 18:58b667752399 706 else
Azure.IoT.Build 18:58b667752399 707 {
Azure.IoT.Build 18:58b667752399 708 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
Azure.IoT.Build 18:58b667752399 709 /*Codes_SRS_COMMAND_DECODER_02_025: [ If methodCallback is NULL then CommandDecoder_ExecuteMethod shall fail and return NULL. ]*/
Azure.IoT.Build 18:58b667752399 710 if (commandDecoderInstance->methodCallback == NULL)
Azure.IoT.Build 18:58b667752399 711 {
Azure.IoT.Build 18:58b667752399 712 LogError("unable to execute a method when the methodCallback passed in CommandDecoder_Create is NULL");
Azure.IoT.Build 18:58b667752399 713 result = NULL;
Azure.IoT.Build 18:58b667752399 714 }
Azure.IoT.Build 18:58b667752399 715 else
Azure.IoT.Build 18:58b667752399 716 {
Azure.IoT.Build 18:58b667752399 717 /*Codes_SRS_COMMAND_DECODER_02_016: [ If methodPayload is not NULL then CommandDecoder_ExecuteMethod shall build a MULTITREE_HANDLE out of methodPayload. ]*/
Azure.IoT.Build 18:58b667752399 718 if (methodPayload == NULL)
Azure.IoT.Build 18:58b667752399 719 {
Azure.IoT.Build 18:58b667752399 720 result = DecodeMethod(commandDecoderInstance, fullMethodName, NULL);
Azure.IoT.Build 18:58b667752399 721 }
Azure.IoT.Build 18:58b667752399 722 else
Azure.IoT.Build 18:58b667752399 723 {
Azure.IoT.Build 18:58b667752399 724 char* methodJSON;
Azure.IoT.Build 18:58b667752399 725
Azure.IoT.Build 18:58b667752399 726 if (mallocAndStrcpy_s(&methodJSON, methodPayload) != 0)
Azure.IoT.Build 18:58b667752399 727 {
Azure.IoT.Build 18:58b667752399 728 LogError("Failed to allocate temporary storage for the method JSON");
Azure.IoT.Build 18:58b667752399 729 result = NULL;
Azure.IoT.Build 18:58b667752399 730 }
Azure.IoT.Build 18:58b667752399 731 else
Azure.IoT.Build 18:58b667752399 732 {
Azure.IoT.Build 18:58b667752399 733 MULTITREE_HANDLE methodTree;
Azure.IoT.Build 18:58b667752399 734 if (JSONDecoder_JSON_To_MultiTree(methodJSON, &methodTree) != JSON_DECODER_OK)
Azure.IoT.Build 18:58b667752399 735 {
Azure.IoT.Build 18:58b667752399 736 LogError("Decoding JSON to a multi tree failed");
Azure.IoT.Build 18:58b667752399 737 result = NULL;
Azure.IoT.Build 18:58b667752399 738 }
Azure.IoT.Build 18:58b667752399 739 else
Azure.IoT.Build 18:58b667752399 740 {
Azure.IoT.Build 18:58b667752399 741 result = DecodeMethod(commandDecoderInstance, fullMethodName, methodTree);
Azure.IoT.Build 18:58b667752399 742 MultiTree_Destroy(methodTree);
Azure.IoT.Build 18:58b667752399 743 }
Azure.IoT.Build 18:58b667752399 744 free(methodJSON);
Azure.IoT.Build 18:58b667752399 745 }
Azure.IoT.Build 18:58b667752399 746 }
Azure.IoT.Build 18:58b667752399 747 }
Azure.IoT.Build 18:58b667752399 748 }
Azure.IoT.Build 18:58b667752399 749 return result;
Azure.IoT.Build 18:58b667752399 750 }
Azure.IoT.Build 18:58b667752399 751
Azure.IoT.Build 18:58b667752399 752
Azure.IoT.Build 18:58b667752399 753 COMMAND_DECODER_HANDLE CommandDecoder_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, ACTION_CALLBACK_FUNC actionCallback, void* actionCallbackContext, METHOD_CALLBACK_FUNC methodCallback, void* methodCallbackContext)
AzureIoTClient 0:1f9b2707ec7d 754 {
AzureIoTClient 17:fa1bba4c6053 755 COMMAND_DECODER_HANDLE_DATA* result;
AzureIoTClient 0:1f9b2707ec7d 756 /* Codes_SRS_COMMAND_DECODER_99_019:[ For all exposed APIs argument validity checks shall precede other checks.] */
Azure.IoT.Build 18:58b667752399 757 /* Codes_SRS_COMMAND_DECODER_01_003: [ If modelHandle is NULL, CommandDecoder_Create shall return NULL. ]*/
AzureIoTClient 22:422d94bd3c18 758 if (modelHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 759 {
Azure.IoT.Build 18:58b667752399 760 LogError("Invalid arguments: SCHEMA_MODEL_TYPE_HANDLE modelHandle=%p, ACTION_CALLBACK_FUNC actionCallback=%p, void* actionCallbackContext=%p, METHOD_CALLBACK_FUNC methodCallback=%p, void* methodCallbackContext=%p",
Azure.IoT.Build 18:58b667752399 761 modelHandle, actionCallback, actionCallbackContext, methodCallback, methodCallbackContext);
AzureIoTClient 0:1f9b2707ec7d 762 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 763 }
AzureIoTClient 0:1f9b2707ec7d 764 else
AzureIoTClient 0:1f9b2707ec7d 765 {
AzureIoTClient 0:1f9b2707ec7d 766 /* Codes_SRS_COMMAND_DECODER_01_001: [CommandDecoder_Create shall create a new instance of a CommandDecoder.] */
AzureIoTClient 17:fa1bba4c6053 767 result = malloc(sizeof(COMMAND_DECODER_HANDLE_DATA));
AzureIoTClient 0:1f9b2707ec7d 768 if (result == NULL)
AzureIoTClient 0:1f9b2707ec7d 769 {
AzureIoTClient 0:1f9b2707ec7d 770 /* Codes_SRS_COMMAND_DECODER_01_004: [If any error is encountered during CommandDecoder_Create CommandDecoder_Create shall return NULL.] */
AzureIoTClient 17:fa1bba4c6053 771 /*return as is*/
AzureIoTClient 0:1f9b2707ec7d 772 }
AzureIoTClient 0:1f9b2707ec7d 773 else
AzureIoTClient 0:1f9b2707ec7d 774 {
AzureIoTClient 0:1f9b2707ec7d 775 result->ModelHandle = modelHandle;
AzureIoTClient 0:1f9b2707ec7d 776 result->ActionCallback = actionCallback;
AzureIoTClient 0:1f9b2707ec7d 777 result->ActionCallbackContext = actionCallbackContext;
Azure.IoT.Build 18:58b667752399 778 result->methodCallback = methodCallback;
Azure.IoT.Build 18:58b667752399 779 result->methodCallbackContext = methodCallbackContext;
AzureIoTClient 0:1f9b2707ec7d 780 }
AzureIoTClient 0:1f9b2707ec7d 781 }
AzureIoTClient 0:1f9b2707ec7d 782
AzureIoTClient 0:1f9b2707ec7d 783 return result;
AzureIoTClient 0:1f9b2707ec7d 784 }
AzureIoTClient 0:1f9b2707ec7d 785
AzureIoTClient 0:1f9b2707ec7d 786 void CommandDecoder_Destroy(COMMAND_DECODER_HANDLE commandDecoderHandle)
AzureIoTClient 0:1f9b2707ec7d 787 {
AzureIoTClient 0:1f9b2707ec7d 788 /* Codes_SRS_COMMAND_DECODER_01_007: [If CommandDecoder_Destroy is called with a NULL handle, CommandDecoder_Destroy shall do nothing.] */
AzureIoTClient 0:1f9b2707ec7d 789 if (commandDecoderHandle != NULL)
AzureIoTClient 0:1f9b2707ec7d 790 {
AzureIoTClient 17:fa1bba4c6053 791 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)commandDecoderHandle;
AzureIoTClient 0:1f9b2707ec7d 792
AzureIoTClient 0:1f9b2707ec7d 793 /* Codes_SRS_COMMAND_DECODER_01_005: [CommandDecoder_Destroy shall free all resources associated with the commandDecoderHandle instance.] */
AzureIoTClient 0:1f9b2707ec7d 794 free(commandDecoderInstance);
AzureIoTClient 0:1f9b2707ec7d 795 }
AzureIoTClient 17:fa1bba4c6053 796 }
AzureIoTClient 17:fa1bba4c6053 797
AzureIoTClient 17:fa1bba4c6053 798 DEFINE_ENUM_STRINGS(AGENT_DATA_TYPE_TYPE, AGENT_DATA_TYPE_TYPE_VALUES);
AzureIoTClient 17:fa1bba4c6053 799
AzureIoTClient 17:fa1bba4c6053 800 /*validates that the multitree (coming from a JSON) is actually a serialization of the model (complete or incomplete)*/
AzureIoTClient 17:fa1bba4c6053 801 /*if the serialization contains more than the model, then it fails.*/
AzureIoTClient 17:fa1bba4c6053 802 /*if the serialization does not contain mandatory items from the model, it fails*/
AzureIoTClient 17:fa1bba4c6053 803 static bool validateModel_vs_Multitree(void* startAddress, SCHEMA_MODEL_TYPE_HANDLE modelHandle, MULTITREE_HANDLE desiredPropertiesTree, size_t offset)
AzureIoTClient 17:fa1bba4c6053 804 {
AzureIoTClient 36:7d12a5386197 805
AzureIoTClient 17:fa1bba4c6053 806 bool result;
AzureIoTClient 17:fa1bba4c6053 807 size_t nChildren;
AzureIoTClient 17:fa1bba4c6053 808 size_t nProcessedChildren = 0;
AzureIoTClient 17:fa1bba4c6053 809 (void)MultiTree_GetChildCount(desiredPropertiesTree, &nChildren);
AzureIoTClient 17:fa1bba4c6053 810 for (size_t i = 0;i < nChildren;i++)
AzureIoTClient 17:fa1bba4c6053 811 {
AzureIoTClient 17:fa1bba4c6053 812 MULTITREE_HANDLE child;
AzureIoTClient 17:fa1bba4c6053 813 if (MultiTree_GetChild(desiredPropertiesTree, i, &child) != MULTITREE_OK)
AzureIoTClient 17:fa1bba4c6053 814 {
AzureIoTClient 17:fa1bba4c6053 815 LogError("failure in MultiTree_GetChild");
AzureIoTClient 17:fa1bba4c6053 816 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 817 }
AzureIoTClient 17:fa1bba4c6053 818 else
AzureIoTClient 17:fa1bba4c6053 819 {
AzureIoTClient 17:fa1bba4c6053 820 STRING_HANDLE childName = STRING_new();
AzureIoTClient 17:fa1bba4c6053 821 if (childName == NULL)
AzureIoTClient 17:fa1bba4c6053 822 {
AzureIoTClient 17:fa1bba4c6053 823 LogError("failure to STRING_new");
AzureIoTClient 17:fa1bba4c6053 824 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 825 }
AzureIoTClient 17:fa1bba4c6053 826 else
AzureIoTClient 17:fa1bba4c6053 827 {
AzureIoTClient 17:fa1bba4c6053 828 if (MultiTree_GetName(child, childName) != MULTITREE_OK)
AzureIoTClient 17:fa1bba4c6053 829 {
AzureIoTClient 17:fa1bba4c6053 830 LogError("failure to MultiTree_GetName");
AzureIoTClient 17:fa1bba4c6053 831 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 832 }
AzureIoTClient 17:fa1bba4c6053 833 else
AzureIoTClient 17:fa1bba4c6053 834 {
AzureIoTClient 17:fa1bba4c6053 835 const char *childName_str = STRING_c_str(childName);
AzureIoTClient 17:fa1bba4c6053 836 SCHEMA_MODEL_ELEMENT elementType = Schema_GetModelElementByName(modelHandle, childName_str);
AzureIoTClient 17:fa1bba4c6053 837 switch (elementType.elementType)
AzureIoTClient 17:fa1bba4c6053 838 {
AzureIoTClient 17:fa1bba4c6053 839 default:
AzureIoTClient 17:fa1bba4c6053 840 {
AzureIoTClient 17:fa1bba4c6053 841 LogError("INTERNAL ERROR: unexpected function return");
AzureIoTClient 17:fa1bba4c6053 842 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 843 break;
AzureIoTClient 17:fa1bba4c6053 844 }
AzureIoTClient 17:fa1bba4c6053 845 case (SCHEMA_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 846 {
AzureIoTClient 36:7d12a5386197 847 LogError("cannot ingest name (WITH_DATA instead of WITH_DESIRED_PROPERTY): %s", childName_str);
AzureIoTClient 17:fa1bba4c6053 848 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 849 break;
AzureIoTClient 17:fa1bba4c6053 850 }
AzureIoTClient 17:fa1bba4c6053 851 case (SCHEMA_REPORTED_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 852 {
AzureIoTClient 36:7d12a5386197 853 LogError("cannot ingest name (WITH_REPORTED_PROPERTY instead of WITH_DESIRED_PROPERTY): %s", childName_str);
AzureIoTClient 17:fa1bba4c6053 854 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 855 break;
AzureIoTClient 17:fa1bba4c6053 856 }
AzureIoTClient 17:fa1bba4c6053 857 case (SCHEMA_DESIRED_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 858 {
AzureIoTClient 17:fa1bba4c6053 859 /*Codes_SRS_COMMAND_DECODER_02_007: [ If the child name corresponds to a desired property then an AGENT_DATA_TYPE shall be constructed from the MULTITREE node. ]*/
AzureIoTClient 17:fa1bba4c6053 860 SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = elementType.elementHandle.desiredPropertyHandle;
AzureIoTClient 36:7d12a5386197 861
AzureIoTClient 17:fa1bba4c6053 862 const char* desiredPropertyType = Schema_GetModelDesiredPropertyType(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 863 AGENT_DATA_TYPE output;
AzureIoTClient 17:fa1bba4c6053 864 if (DecodeValueFromNode(Schema_GetSchemaForModelType(modelHandle), &output, child, desiredPropertyType) != 0)
AzureIoTClient 17:fa1bba4c6053 865 {
AzureIoTClient 17:fa1bba4c6053 866 LogError("failure in DecodeValueFromNode");
AzureIoTClient 17:fa1bba4c6053 867 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 868 }
AzureIoTClient 17:fa1bba4c6053 869 else
AzureIoTClient 17:fa1bba4c6053 870 {
AzureIoTClient 17:fa1bba4c6053 871 /*Codes_SRS_COMMAND_DECODER_02_008: [ The desired property shall be constructed in memory by calling pfDesiredPropertyFromAGENT_DATA_TYPE. ]*/
AzureIoTClient 17:fa1bba4c6053 872 pfDesiredPropertyFromAGENT_DATA_TYPE leFunction = Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 873 if (leFunction(&output, (char*)startAddress + offset + Schema_GetModelDesiredProperty_offset(desiredPropertyHandle)) != 0)
AzureIoTClient 17:fa1bba4c6053 874 {
AzureIoTClient 17:fa1bba4c6053 875 LogError("failure in a function that converts from AGENT_DATA_TYPE to C data");
AzureIoTClient 17:fa1bba4c6053 876 }
AzureIoTClient 17:fa1bba4c6053 877 else
AzureIoTClient 17:fa1bba4c6053 878 {
AzureIoTClient 17:fa1bba4c6053 879 /*Codes_SRS_COMMAND_DECODER_02_013: [ If the desired property has a non-NULL pfOnDesiredProperty then it shall be called. ]*/
AzureIoTClient 17:fa1bba4c6053 880 pfOnDesiredProperty onDesiredProperty = Schema_GetModelDesiredProperty_pfOnDesiredProperty(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 881 if (onDesiredProperty != NULL)
AzureIoTClient 17:fa1bba4c6053 882 {
AzureIoTClient 17:fa1bba4c6053 883 onDesiredProperty((char*)startAddress + offset);
AzureIoTClient 17:fa1bba4c6053 884 }
AzureIoTClient 17:fa1bba4c6053 885 nProcessedChildren++;
AzureIoTClient 17:fa1bba4c6053 886 }
AzureIoTClient 17:fa1bba4c6053 887 Destroy_AGENT_DATA_TYPE(&output);
AzureIoTClient 17:fa1bba4c6053 888 }
AzureIoTClient 36:7d12a5386197 889
AzureIoTClient 17:fa1bba4c6053 890 break;
AzureIoTClient 17:fa1bba4c6053 891 }
AzureIoTClient 17:fa1bba4c6053 892 case(SCHEMA_MODEL_IN_MODEL):
AzureIoTClient 17:fa1bba4c6053 893 {
AzureIoTClient 17:fa1bba4c6053 894 SCHEMA_MODEL_TYPE_HANDLE modelModel = elementType.elementHandle.modelHandle;
AzureIoTClient 36:7d12a5386197 895
AzureIoTClient 17:fa1bba4c6053 896 /*Codes_SRS_COMMAND_DECODER_02_009: [ If the child name corresponds to a model in model then the function shall call itself recursively. ]*/
AzureIoTClient 17:fa1bba4c6053 897 if (!validateModel_vs_Multitree(startAddress, modelModel, child, offset + Schema_GetModelModelByName_Offset(modelHandle, childName_str)))
AzureIoTClient 17:fa1bba4c6053 898 {
AzureIoTClient 17:fa1bba4c6053 899 LogError("failure in validateModel_vs_Multitree");
AzureIoTClient 17:fa1bba4c6053 900 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 901 }
AzureIoTClient 17:fa1bba4c6053 902 else
AzureIoTClient 17:fa1bba4c6053 903 {
AzureIoTClient 17:fa1bba4c6053 904 /*if the model in model so happened to be a WITH_DESIRED_PROPERTY... (only those has non_NULL pfOnDesiredProperty) */
AzureIoTClient 17:fa1bba4c6053 905 /*Codes_SRS_COMMAND_DECODER_02_012: [ If the child model in model has a non-NULL pfOnDesiredProperty then pfOnDesiredProperty shall be called. ]*/
AzureIoTClient 17:fa1bba4c6053 906 pfOnDesiredProperty onDesiredProperty = Schema_GetModelModelByName_OnDesiredProperty(modelHandle, childName_str);
AzureIoTClient 17:fa1bba4c6053 907 if (onDesiredProperty != NULL)
AzureIoTClient 17:fa1bba4c6053 908 {
AzureIoTClient 17:fa1bba4c6053 909 onDesiredProperty((char*)startAddress + offset);
AzureIoTClient 17:fa1bba4c6053 910 }
AzureIoTClient 36:7d12a5386197 911
AzureIoTClient 17:fa1bba4c6053 912 nProcessedChildren++;
AzureIoTClient 17:fa1bba4c6053 913 }
AzureIoTClient 36:7d12a5386197 914
AzureIoTClient 17:fa1bba4c6053 915 break;
AzureIoTClient 17:fa1bba4c6053 916 }
AzureIoTClient 17:fa1bba4c6053 917
AzureIoTClient 17:fa1bba4c6053 918 } /*switch*/
AzureIoTClient 17:fa1bba4c6053 919 }
AzureIoTClient 17:fa1bba4c6053 920 STRING_delete(childName);
AzureIoTClient 17:fa1bba4c6053 921 }
AzureIoTClient 17:fa1bba4c6053 922 }
AzureIoTClient 17:fa1bba4c6053 923 }
AzureIoTClient 17:fa1bba4c6053 924
AzureIoTClient 17:fa1bba4c6053 925 if(nProcessedChildren == nChildren)
AzureIoTClient 17:fa1bba4c6053 926 {
AzureIoTClient 17:fa1bba4c6053 927 /*Codes_SRS_COMMAND_DECODER_02_010: [ If the complete MULTITREE has been parsed then CommandDecoder_IngestDesiredProperties shall succeed and return EXECUTE_COMMAND_SUCCESS. ]*/
AzureIoTClient 17:fa1bba4c6053 928 result = true;
AzureIoTClient 17:fa1bba4c6053 929 }
AzureIoTClient 17:fa1bba4c6053 930 else
AzureIoTClient 17:fa1bba4c6053 931 {
AzureIoTClient 17:fa1bba4c6053 932 /*Codes_SRS_COMMAND_DECODER_02_011: [ Otherwise CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_FAILED. ]*/
AzureIoTClient 17:fa1bba4c6053 933 LogError("not all constituents of the JSON have been ingested");
AzureIoTClient 17:fa1bba4c6053 934 result = false;
AzureIoTClient 17:fa1bba4c6053 935 }
AzureIoTClient 17:fa1bba4c6053 936 return result;
AzureIoTClient 17:fa1bba4c6053 937 }
AzureIoTClient 17:fa1bba4c6053 938
AzureIoTClient 17:fa1bba4c6053 939 static EXECUTE_COMMAND_RESULT DecodeDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE_DATA* handle, MULTITREE_HANDLE desiredPropertiesTree)
AzureIoTClient 17:fa1bba4c6053 940 {
AzureIoTClient 17:fa1bba4c6053 941 /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
AzureIoTClient 17:fa1bba4c6053 942 return validateModel_vs_Multitree(startAddress, handle->ModelHandle, desiredPropertiesTree, 0 )?EXECUTE_COMMAND_SUCCESS:EXECUTE_COMMAND_FAILED;
AzureIoTClient 17:fa1bba4c6053 943 }
AzureIoTClient 17:fa1bba4c6053 944
AzureIoTClient 26:7c0e6f86d034 945 /* Raw JSON has properties we don't need; potentially nodes other than "desired" for full TWIN as well as a $version we don't pass to callees */
AzureIoTClient 26:7c0e6f86d034 946 static bool RemoveUnneededTwinProperties(MULTITREE_HANDLE initialParsedTree, bool parseDesiredNode, MULTITREE_HANDLE *desiredPropertiesTree)
AzureIoTClient 26:7c0e6f86d034 947 {
AzureIoTClient 26:7c0e6f86d034 948 MULTITREE_HANDLE updateTree;
AzureIoTClient 26:7c0e6f86d034 949 bool result;
AzureIoTClient 26:7c0e6f86d034 950
AzureIoTClient 26:7c0e6f86d034 951 if (parseDesiredNode)
AzureIoTClient 26:7c0e6f86d034 952 {
AzureIoTClient 26:7c0e6f86d034 953 /*Codes_SRS_COMMAND_DECODER_02_014: [ If parseDesiredNode is TRUE, parse only the `desired` part of JSON tree ]*/
AzureIoTClient 26:7c0e6f86d034 954 if (MultiTree_GetChildByName(initialParsedTree, "desired", &updateTree) != MULTITREE_OK)
AzureIoTClient 26:7c0e6f86d034 955 {
AzureIoTClient 26:7c0e6f86d034 956 LogError("Unable to find 'desired' in tree");
AzureIoTClient 26:7c0e6f86d034 957 return false;
AzureIoTClient 26:7c0e6f86d034 958 }
AzureIoTClient 26:7c0e6f86d034 959 }
AzureIoTClient 26:7c0e6f86d034 960 else
AzureIoTClient 26:7c0e6f86d034 961 {
AzureIoTClient 26:7c0e6f86d034 962 // Tree already starts on node we want so just use it.
AzureIoTClient 26:7c0e6f86d034 963 updateTree = initialParsedTree;
AzureIoTClient 26:7c0e6f86d034 964 }
AzureIoTClient 26:7c0e6f86d034 965
AzureIoTClient 26:7c0e6f86d034 966 /*Codes_COMMAND_DECODER_02_015: [ Remove '$version' string from node, if it is present. It not being present is not an error ]*/
AzureIoTClient 26:7c0e6f86d034 967 MULTITREE_RESULT deleteChildResult = MultiTree_DeleteChild(updateTree, "$version");
AzureIoTClient 26:7c0e6f86d034 968 if ((deleteChildResult == MULTITREE_OK) || (deleteChildResult == MULTITREE_CHILD_NOT_FOUND))
AzureIoTClient 26:7c0e6f86d034 969 {
AzureIoTClient 26:7c0e6f86d034 970 *desiredPropertiesTree = updateTree;
AzureIoTClient 26:7c0e6f86d034 971 result = true;
AzureIoTClient 26:7c0e6f86d034 972 }
AzureIoTClient 26:7c0e6f86d034 973 else
AzureIoTClient 26:7c0e6f86d034 974 {
AzureIoTClient 26:7c0e6f86d034 975 *desiredPropertiesTree = NULL;
AzureIoTClient 26:7c0e6f86d034 976 result = false;
AzureIoTClient 26:7c0e6f86d034 977 }
AzureIoTClient 26:7c0e6f86d034 978
AzureIoTClient 26:7c0e6f86d034 979 return result;
AzureIoTClient 26:7c0e6f86d034 980 }
AzureIoTClient 26:7c0e6f86d034 981
AzureIoTClient 26:7c0e6f86d034 982 EXECUTE_COMMAND_RESULT CommandDecoder_IngestDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE handle, const char* jsonPayload, bool parseDesiredNode)
AzureIoTClient 17:fa1bba4c6053 983 {
AzureIoTClient 17:fa1bba4c6053 984 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 36:7d12a5386197 985
AzureIoTClient 17:fa1bba4c6053 986 /*Codes_SRS_COMMAND_DECODER_02_001: [ If startAddress is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 17:fa1bba4c6053 987 /*Codes_SRS_COMMAND_DECODER_02_002: [ If handle is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 26:7c0e6f86d034 988 /*Codes_SRS_COMMAND_DECODER_02_003: [ If jsonPayload is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 17:fa1bba4c6053 989 if(
AzureIoTClient 17:fa1bba4c6053 990 (startAddress == NULL) ||
AzureIoTClient 17:fa1bba4c6053 991 (handle == NULL) ||
AzureIoTClient 26:7c0e6f86d034 992 (jsonPayload == NULL)
AzureIoTClient 17:fa1bba4c6053 993 )
AzureIoTClient 17:fa1bba4c6053 994 {
AzureIoTClient 26:7c0e6f86d034 995 LogError("invalid argument COMMAND_DECODER_HANDLE handle=%p, const char* jsonPayload=%p", handle, jsonPayload);
AzureIoTClient 17:fa1bba4c6053 996 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 17:fa1bba4c6053 997 }
AzureIoTClient 17:fa1bba4c6053 998 else
AzureIoTClient 17:fa1bba4c6053 999 {
AzureIoTClient 17:fa1bba4c6053 1000 /*Codes_SRS_COMMAND_DECODER_02_004: [ CommandDecoder_IngestDesiredProperties shall clone desiredProperties. ]*/
AzureIoTClient 17:fa1bba4c6053 1001 char* copy;
AzureIoTClient 26:7c0e6f86d034 1002 if (mallocAndStrcpy_s(&copy, jsonPayload) != 0)
AzureIoTClient 17:fa1bba4c6053 1003 {
AzureIoTClient 17:fa1bba4c6053 1004 LogError("failure in mallocAndStrcpy_s");
AzureIoTClient 17:fa1bba4c6053 1005 result = EXECUTE_COMMAND_FAILED;
AzureIoTClient 17:fa1bba4c6053 1006 }
AzureIoTClient 17:fa1bba4c6053 1007 else
AzureIoTClient 17:fa1bba4c6053 1008 {
AzureIoTClient 17:fa1bba4c6053 1009 /*Codes_SRS_COMMAND_DECODER_02_005: [ CommandDecoder_IngestDesiredProperties shall create a MULTITREE_HANDLE ouf of the clone of desiredProperties. ]*/
AzureIoTClient 26:7c0e6f86d034 1010 MULTITREE_HANDLE initialParsedTree;
AzureIoTClient 17:fa1bba4c6053 1011 MULTITREE_HANDLE desiredPropertiesTree;
AzureIoTClient 26:7c0e6f86d034 1012
AzureIoTClient 26:7c0e6f86d034 1013 if (JSONDecoder_JSON_To_MultiTree(copy, &initialParsedTree) != JSON_DECODER_OK)
AzureIoTClient 17:fa1bba4c6053 1014 {
AzureIoTClient 17:fa1bba4c6053 1015 LogError("Decoding JSON to a multi tree failed");
AzureIoTClient 17:fa1bba4c6053 1016 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 17:fa1bba4c6053 1017 }
AzureIoTClient 17:fa1bba4c6053 1018 else
AzureIoTClient 17:fa1bba4c6053 1019 {
AzureIoTClient 26:7c0e6f86d034 1020 if (RemoveUnneededTwinProperties(initialParsedTree, parseDesiredNode, &desiredPropertiesTree) == false)
AzureIoTClient 26:7c0e6f86d034 1021 {
AzureIoTClient 26:7c0e6f86d034 1022 LogError("Removing unneeded twin properties failed");
AzureIoTClient 26:7c0e6f86d034 1023 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 26:7c0e6f86d034 1024 }
AzureIoTClient 26:7c0e6f86d034 1025 else
AzureIoTClient 26:7c0e6f86d034 1026 {
AzureIoTClient 26:7c0e6f86d034 1027 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
AzureIoTClient 17:fa1bba4c6053 1028
AzureIoTClient 26:7c0e6f86d034 1029 /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
AzureIoTClient 26:7c0e6f86d034 1030 result = DecodeDesiredProperties(startAddress, commandDecoderInstance, desiredPropertiesTree);
AzureIoTClient 17:fa1bba4c6053 1031
AzureIoTClient 26:7c0e6f86d034 1032 // Do NOT free desiredPropertiesTree. It is only a pointer into initialParsedTree.
AzureIoTClient 26:7c0e6f86d034 1033 MultiTree_Destroy(initialParsedTree);
AzureIoTClient 26:7c0e6f86d034 1034 }
AzureIoTClient 17:fa1bba4c6053 1035 }
AzureIoTClient 17:fa1bba4c6053 1036 free(copy);
AzureIoTClient 17:fa1bba4c6053 1037 }
AzureIoTClient 17:fa1bba4c6053 1038 }
AzureIoTClient 17:fa1bba4c6053 1039 return result;
AzureIoTClient 17:fa1bba4c6053 1040 }