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:
Wed Nov 16 21:38:26 2016 -0800
Revision:
17:fa1bba4c6053
Parent:
14:0c00e67a4ab1
Child:
18:58b667752399
1.0.10

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 0:1f9b2707ec7d 5 #ifdef _CRTDBG_MAP_ALLOC
AzureIoTClient 0:1f9b2707ec7d 6 #include <crtdbg.h>
AzureIoTClient 0:1f9b2707ec7d 7 #endif
Azure.IoT Build 10:c2aee3965a83 8 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 0:1f9b2707ec7d 9
AzureIoTClient 0:1f9b2707ec7d 10 #include <stddef.h>
AzureIoTClient 0:1f9b2707ec7d 11
AzureIoTClient 0:1f9b2707ec7d 12 #include "commanddecoder.h"
AzureIoTClient 0:1f9b2707ec7d 13 #include "multitree.h"
Azure.IoT Build 10:c2aee3965a83 14 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 13:16e88f0cfa5f 15 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 0:1f9b2707ec7d 16 #include "schema.h"
AzureIoTClient 0:1f9b2707ec7d 17 #include "codefirst.h"
AzureIoTClient 0:1f9b2707ec7d 18 #include "jsondecoder.h"
AzureIoTClient 0:1f9b2707ec7d 19
AzureIoTClient 0:1f9b2707ec7d 20 DEFINE_ENUM_STRINGS(COMMANDDECODER_RESULT, COMMANDDECODER_RESULT_VALUES);
AzureIoTClient 0:1f9b2707ec7d 21
AzureIoTClient 17:fa1bba4c6053 22 typedef struct COMMAND_DECODER_HANDLE_DATA_TAG
AzureIoTClient 0:1f9b2707ec7d 23 {
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 0:1f9b2707ec7d 47 result = __LINE__;
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 0:1f9b2707ec7d 55 result = __LINE__;
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 0:1f9b2707ec7d 64 result = __LINE__;
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 0:1f9b2707ec7d 73 result = __LINE__;
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 0:1f9b2707ec7d 91 result = __LINE__;
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 0:1f9b2707ec7d 99 result = __LINE__;
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 0:1f9b2707ec7d 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 0:1f9b2707ec7d 111 result = __LINE__;
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 0:1f9b2707ec7d 129 result = __LINE__;
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 0:1f9b2707ec7d 157 result = __LINE__;
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 0:1f9b2707ec7d 164 result = __LINE__;
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 0:1f9b2707ec7d 184 else
AzureIoTClient 0:1f9b2707ec7d 185 {
AzureIoTClient 0:1f9b2707ec7d 186 /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "Name" of the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 187 SCHEMA_ACTION_HANDLE modelActionHandle;
AzureIoTClient 0:1f9b2707ec7d 188 size_t argCount;
AzureIoTClient 0:1f9b2707ec7d 189 MULTITREE_HANDLE parametersTreeNode;
AzureIoTClient 0:1f9b2707ec7d 190
AzureIoTClient 0:1f9b2707ec7d 191 #ifdef _MSC_VER
AzureIoTClient 0:1f9b2707ec7d 192 #pragma warning(suppress: 6324) /* We intentionally use here strncpy */
AzureIoTClient 0:1f9b2707ec7d 193 #endif
AzureIoTClient 0:1f9b2707ec7d 194 if (strncpy(tempStr, actionName, strLength - 1) == NULL)
AzureIoTClient 0:1f9b2707ec7d 195 {
AzureIoTClient 0:1f9b2707ec7d 196 /* 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 197 LogError("Invalid action name.");
AzureIoTClient 0:1f9b2707ec7d 198 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 199 }
AzureIoTClient 0:1f9b2707ec7d 200 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 201 else if (MultiTree_GetChildByName(commandNode, "Parameters", &parametersTreeNode) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 202 {
AzureIoTClient 0:1f9b2707ec7d 203 /* 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 204 LogError("Error getting Parameters node.");
AzureIoTClient 0:1f9b2707ec7d 205 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 206 }
AzureIoTClient 0:1f9b2707ec7d 207 else
AzureIoTClient 0:1f9b2707ec7d 208 {
AzureIoTClient 0:1f9b2707ec7d 209 tempStr[strLength - 1] = 0;
AzureIoTClient 0:1f9b2707ec7d 210
AzureIoTClient 0:1f9b2707ec7d 211 /* Codes_SRS_COMMAND_DECODER_99_009:[ CommandDecoder shall call Schema_GetModelActionByName to obtain the information about a specific action.] */
AzureIoTClient 0:1f9b2707ec7d 212 if (((modelActionHandle = Schema_GetModelActionByName(modelHandle, tempStr)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 213 (Schema_GetModelActionArgumentCount(modelActionHandle, &argCount) != SCHEMA_OK))
AzureIoTClient 0:1f9b2707ec7d 214 {
AzureIoTClient 0:1f9b2707ec7d 215 /* 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 216 LogError("Failed reading action %s from the schema", tempStr);
AzureIoTClient 0:1f9b2707ec7d 217 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 218 }
AzureIoTClient 0:1f9b2707ec7d 219 else
AzureIoTClient 0:1f9b2707ec7d 220 {
AzureIoTClient 0:1f9b2707ec7d 221 AGENT_DATA_TYPE* arguments = NULL;
AzureIoTClient 0:1f9b2707ec7d 222
AzureIoTClient 0:1f9b2707ec7d 223 if (argCount > 0)
AzureIoTClient 0:1f9b2707ec7d 224 {
AzureIoTClient 0:1f9b2707ec7d 225 arguments = (AGENT_DATA_TYPE*)malloc(sizeof(AGENT_DATA_TYPE)* argCount);
AzureIoTClient 0:1f9b2707ec7d 226 }
AzureIoTClient 0:1f9b2707ec7d 227
AzureIoTClient 0:1f9b2707ec7d 228 if ((argCount > 0) &&
AzureIoTClient 0:1f9b2707ec7d 229 (arguments == NULL))
AzureIoTClient 0:1f9b2707ec7d 230 {
AzureIoTClient 0:1f9b2707ec7d 231 /* 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 232 LogError("Failed allocating arguments array");
AzureIoTClient 0:1f9b2707ec7d 233 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 234 }
AzureIoTClient 0:1f9b2707ec7d 235 else
AzureIoTClient 0:1f9b2707ec7d 236 {
AzureIoTClient 0:1f9b2707ec7d 237 size_t i;
AzureIoTClient 0:1f9b2707ec7d 238 size_t j;
AzureIoTClient 14:0c00e67a4ab1 239 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 240
AzureIoTClient 0:1f9b2707ec7d 241 /* Codes_SRS_COMMAND_DECODER_99_011:[ CommandDecoder shall attempt to extract from the command text the value for each action argument.] */
AzureIoTClient 0:1f9b2707ec7d 242 for (i = 0; i < argCount; i++)
AzureIoTClient 0:1f9b2707ec7d 243 {
AzureIoTClient 0:1f9b2707ec7d 244 SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle;
AzureIoTClient 0:1f9b2707ec7d 245 MULTITREE_HANDLE argumentNode;
AzureIoTClient 0:1f9b2707ec7d 246 const char* argName;
AzureIoTClient 0:1f9b2707ec7d 247 const char* argType;
AzureIoTClient 0:1f9b2707ec7d 248
AzureIoTClient 0:1f9b2707ec7d 249 if (((actionArgumentHandle = Schema_GetModelActionArgumentByIndex(modelActionHandle, i)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 250 ((argName = Schema_GetActionArgumentName(actionArgumentHandle)) == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 251 ((argType = Schema_GetActionArgumentType(actionArgumentHandle)) == NULL))
AzureIoTClient 0:1f9b2707ec7d 252 {
AzureIoTClient 11:b1327861f5e0 253 LogError("Failed getting the argument information from the schema");
AzureIoTClient 0:1f9b2707ec7d 254 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 255 break;
AzureIoTClient 0:1f9b2707ec7d 256 }
AzureIoTClient 0:1f9b2707ec7d 257 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 258 /* Codes_SRS_COMMAND_DECODER_01_008: [Each argument shall be looked up as a field, member of the "Parameters" node.] */
AzureIoTClient 0:1f9b2707ec7d 259 else if (MultiTree_GetChildByName(parametersTreeNode, argName, &argumentNode) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 260 {
AzureIoTClient 0:1f9b2707ec7d 261 /* 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 262 LogError("Missing argument %s", argName);
AzureIoTClient 0:1f9b2707ec7d 263 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 264 break;
AzureIoTClient 0:1f9b2707ec7d 265 }
AzureIoTClient 0:1f9b2707ec7d 266 else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0)
AzureIoTClient 0:1f9b2707ec7d 267 {
AzureIoTClient 0:1f9b2707ec7d 268 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 269 break;
AzureIoTClient 0:1f9b2707ec7d 270 }
AzureIoTClient 0:1f9b2707ec7d 271 }
AzureIoTClient 0:1f9b2707ec7d 272
AzureIoTClient 0:1f9b2707ec7d 273 if (i == argCount)
AzureIoTClient 0:1f9b2707ec7d 274 {
AzureIoTClient 0:1f9b2707ec7d 275 /* 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 276 result = commandDecoderInstance->ActionCallback(commandDecoderInstance->ActionCallbackContext, relativeActionPath, tempStr, argCount, arguments);
AzureIoTClient 0:1f9b2707ec7d 277 }
AzureIoTClient 0:1f9b2707ec7d 278
AzureIoTClient 0:1f9b2707ec7d 279 for (j = 0; j < i; j++)
AzureIoTClient 0:1f9b2707ec7d 280 {
AzureIoTClient 0:1f9b2707ec7d 281 Destroy_AGENT_DATA_TYPE(&arguments[j]);
AzureIoTClient 0:1f9b2707ec7d 282 }
AzureIoTClient 0:1f9b2707ec7d 283
AzureIoTClient 0:1f9b2707ec7d 284 if (arguments != NULL)
AzureIoTClient 0:1f9b2707ec7d 285 {
AzureIoTClient 0:1f9b2707ec7d 286 free(arguments);
AzureIoTClient 0:1f9b2707ec7d 287 }
AzureIoTClient 0:1f9b2707ec7d 288 }
AzureIoTClient 0:1f9b2707ec7d 289 }
AzureIoTClient 0:1f9b2707ec7d 290 }
AzureIoTClient 0:1f9b2707ec7d 291 }
AzureIoTClient 0:1f9b2707ec7d 292 return result;
AzureIoTClient 0:1f9b2707ec7d 293 }
AzureIoTClient 0:1f9b2707ec7d 294
AzureIoTClient 17:fa1bba4c6053 295 static EXECUTE_COMMAND_RESULT ScanActionPathAndExecuteAction(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* actionPath, MULTITREE_HANDLE commandNode)
AzureIoTClient 0:1f9b2707ec7d 296 {
AzureIoTClient 0:1f9b2707ec7d 297 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 298 char* relativeActionPath;
AzureIoTClient 0:1f9b2707ec7d 299 const char* actionName = actionPath;
AzureIoTClient 0:1f9b2707ec7d 300 SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle;
AzureIoTClient 0:1f9b2707ec7d 301
AzureIoTClient 0:1f9b2707ec7d 302 /* 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 303 do
AzureIoTClient 0:1f9b2707ec7d 304 {
AzureIoTClient 0:1f9b2707ec7d 305 /* find the slash */
AzureIoTClient 0:1f9b2707ec7d 306 const char* slashPos = strchr(actionName, '/');
AzureIoTClient 0:1f9b2707ec7d 307 if (slashPos == NULL)
AzureIoTClient 0:1f9b2707ec7d 308 {
AzureIoTClient 0:1f9b2707ec7d 309 size_t relativeActionPathLength;
AzureIoTClient 0:1f9b2707ec7d 310
AzureIoTClient 0:1f9b2707ec7d 311 /* Codes_SRS_COMMAND_DECODER_99_037:[ The relative path passed to the actionCallback shall be in the format "childModel1/childModel2/.../childModelN".] */
AzureIoTClient 0:1f9b2707ec7d 312 if (actionName == actionPath)
AzureIoTClient 0:1f9b2707ec7d 313 {
AzureIoTClient 0:1f9b2707ec7d 314 relativeActionPathLength = 0;
AzureIoTClient 0:1f9b2707ec7d 315 }
AzureIoTClient 0:1f9b2707ec7d 316 else
AzureIoTClient 0:1f9b2707ec7d 317 {
AzureIoTClient 0:1f9b2707ec7d 318 relativeActionPathLength = actionName - actionPath - 1;
AzureIoTClient 0:1f9b2707ec7d 319 }
AzureIoTClient 0:1f9b2707ec7d 320
AzureIoTClient 0:1f9b2707ec7d 321 relativeActionPath = (char*)malloc(relativeActionPathLength + 1);
AzureIoTClient 0:1f9b2707ec7d 322 if (relativeActionPath == NULL)
AzureIoTClient 0:1f9b2707ec7d 323 {
AzureIoTClient 0:1f9b2707ec7d 324 /* 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 325 LogError("Failed allocating relative action path");
AzureIoTClient 0:1f9b2707ec7d 326 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 327 }
AzureIoTClient 0:1f9b2707ec7d 328 else
AzureIoTClient 0:1f9b2707ec7d 329 {
AzureIoTClient 0:1f9b2707ec7d 330 strncpy(relativeActionPath, actionPath, relativeActionPathLength);
AzureIoTClient 0:1f9b2707ec7d 331 relativeActionPath[relativeActionPathLength] = 0;
AzureIoTClient 0:1f9b2707ec7d 332
AzureIoTClient 0:1f9b2707ec7d 333 /* no slash found, this must be an action */
AzureIoTClient 0:1f9b2707ec7d 334 result = DecodeAndExecuteModelAction(commandDecoderInstance, schemaHandle, modelHandle, relativeActionPath, actionName, commandNode);
AzureIoTClient 0:1f9b2707ec7d 335
AzureIoTClient 0:1f9b2707ec7d 336 free(relativeActionPath);
AzureIoTClient 0:1f9b2707ec7d 337 actionName = NULL;
AzureIoTClient 0:1f9b2707ec7d 338 }
AzureIoTClient 0:1f9b2707ec7d 339 break;
AzureIoTClient 0:1f9b2707ec7d 340 }
AzureIoTClient 0:1f9b2707ec7d 341 else
AzureIoTClient 0:1f9b2707ec7d 342 {
AzureIoTClient 0:1f9b2707ec7d 343 /* found a slash, get the child model name */
AzureIoTClient 0:1f9b2707ec7d 344 size_t modelLength = slashPos - actionName;
AzureIoTClient 0:1f9b2707ec7d 345 char* childModelName = (char*)malloc(modelLength + 1);
AzureIoTClient 0:1f9b2707ec7d 346 if (childModelName == NULL)
AzureIoTClient 0:1f9b2707ec7d 347 {
AzureIoTClient 0:1f9b2707ec7d 348 /* 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 349 LogError("Failed allocating child model name");
AzureIoTClient 0:1f9b2707ec7d 350 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 351 break;
AzureIoTClient 0:1f9b2707ec7d 352 }
AzureIoTClient 0:1f9b2707ec7d 353 else
AzureIoTClient 0:1f9b2707ec7d 354 {
AzureIoTClient 0:1f9b2707ec7d 355 strncpy(childModelName, actionName, modelLength);
AzureIoTClient 0:1f9b2707ec7d 356 childModelName[modelLength] = 0;
AzureIoTClient 0:1f9b2707ec7d 357
AzureIoTClient 0:1f9b2707ec7d 358 /* find the model */
AzureIoTClient 0:1f9b2707ec7d 359 modelHandle = Schema_GetModelModelByName(modelHandle, childModelName);
AzureIoTClient 0:1f9b2707ec7d 360 if (modelHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 361 {
AzureIoTClient 0:1f9b2707ec7d 362 /* 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 363 LogError("Getting the model %s failed", childModelName);
AzureIoTClient 0:1f9b2707ec7d 364 free(childModelName);
AzureIoTClient 0:1f9b2707ec7d 365 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 366 break;
AzureIoTClient 0:1f9b2707ec7d 367 }
AzureIoTClient 0:1f9b2707ec7d 368 else
AzureIoTClient 0:1f9b2707ec7d 369 {
AzureIoTClient 0:1f9b2707ec7d 370 free(childModelName);
AzureIoTClient 0:1f9b2707ec7d 371 actionName = slashPos + 1;
AzureIoTClient 0:1f9b2707ec7d 372 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 373 }
AzureIoTClient 0:1f9b2707ec7d 374 }
AzureIoTClient 0:1f9b2707ec7d 375 }
AzureIoTClient 0:1f9b2707ec7d 376 } while (actionName != NULL);
AzureIoTClient 0:1f9b2707ec7d 377 return result;
AzureIoTClient 0:1f9b2707ec7d 378 }
AzureIoTClient 0:1f9b2707ec7d 379
AzureIoTClient 17:fa1bba4c6053 380 static EXECUTE_COMMAND_RESULT DecodeCommand(COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance, MULTITREE_HANDLE commandNode)
AzureIoTClient 0:1f9b2707ec7d 381 {
AzureIoTClient 0:1f9b2707ec7d 382 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 383 SCHEMA_HANDLE schemaHandle;
AzureIoTClient 0:1f9b2707ec7d 384
AzureIoTClient 0:1f9b2707ec7d 385 /* 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 386 if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 387 {
AzureIoTClient 0:1f9b2707ec7d 388 /* 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 389 LogError("Getting schema information failed");
AzureIoTClient 0:1f9b2707ec7d 390 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 391 }
AzureIoTClient 0:1f9b2707ec7d 392 else
AzureIoTClient 0:1f9b2707ec7d 393 {
AzureIoTClient 0:1f9b2707ec7d 394 const char* actionName;
AzureIoTClient 0:1f9b2707ec7d 395 MULTITREE_HANDLE nameTreeNode;
AzureIoTClient 0:1f9b2707ec7d 396
AzureIoTClient 0:1f9b2707ec7d 397 /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 398 /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "name" of the command JSON.] */
AzureIoTClient 0:1f9b2707ec7d 399 if ((MultiTree_GetChildByName(commandNode, "Name", &nameTreeNode) != MULTITREE_OK) ||
AzureIoTClient 0:1f9b2707ec7d 400 (MultiTree_GetValue(nameTreeNode, (const void **)&actionName) != MULTITREE_OK))
AzureIoTClient 0:1f9b2707ec7d 401 {
AzureIoTClient 0:1f9b2707ec7d 402 /* 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 403 LogError("Getting action name failed.");
AzureIoTClient 0:1f9b2707ec7d 404 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 405 }
AzureIoTClient 0:1f9b2707ec7d 406 else if (strlen(actionName) < 2)
AzureIoTClient 0:1f9b2707ec7d 407 {
AzureIoTClient 0:1f9b2707ec7d 408 /* 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 409 LogError("Invalid action name.");
AzureIoTClient 0:1f9b2707ec7d 410 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 411 }
AzureIoTClient 0:1f9b2707ec7d 412 else
AzureIoTClient 0:1f9b2707ec7d 413 {
AzureIoTClient 0:1f9b2707ec7d 414 actionName++;
AzureIoTClient 0:1f9b2707ec7d 415 result = ScanActionPathAndExecuteAction(commandDecoderInstance, schemaHandle, actionName, commandNode);
AzureIoTClient 0:1f9b2707ec7d 416 }
AzureIoTClient 0:1f9b2707ec7d 417 }
AzureIoTClient 0:1f9b2707ec7d 418 return result;
AzureIoTClient 0:1f9b2707ec7d 419 }
AzureIoTClient 0:1f9b2707ec7d 420
AzureIoTClient 0:1f9b2707ec7d 421 /*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 422 EXECUTE_COMMAND_RESULT CommandDecoder_ExecuteCommand(COMMAND_DECODER_HANDLE handle, const char* command)
AzureIoTClient 0:1f9b2707ec7d 423 {
AzureIoTClient 0:1f9b2707ec7d 424 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 17:fa1bba4c6053 425 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
AzureIoTClient 0:1f9b2707ec7d 426 /*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 427 if (
AzureIoTClient 0:1f9b2707ec7d 428 (command == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 429 (commandDecoderInstance == NULL)
AzureIoTClient 0:1f9b2707ec7d 430 )
AzureIoTClient 0:1f9b2707ec7d 431 {
AzureIoTClient 11:b1327861f5e0 432 LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* command=%p", handle, command);
AzureIoTClient 0:1f9b2707ec7d 433 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 434 }
AzureIoTClient 0:1f9b2707ec7d 435 else
AzureIoTClient 0:1f9b2707ec7d 436 {
AzureIoTClient 0:1f9b2707ec7d 437 size_t size = strlen(command);
AzureIoTClient 0:1f9b2707ec7d 438 char* commandJSON;
AzureIoTClient 0:1f9b2707ec7d 439
AzureIoTClient 0:1f9b2707ec7d 440 /* 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 0:1f9b2707ec7d 441 if (
AzureIoTClient 0:1f9b2707ec7d 442 (size == 0)
AzureIoTClient 0:1f9b2707ec7d 443 )
AzureIoTClient 0:1f9b2707ec7d 444 {
AzureIoTClient 11:b1327861f5e0 445 LogError("Failed because command size is zero");
AzureIoTClient 0:1f9b2707ec7d 446 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 447 }
AzureIoTClient 0:1f9b2707ec7d 448 /*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 449 else if ((commandJSON = (char*)malloc(size + 1)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 450 {
AzureIoTClient 11:b1327861f5e0 451 LogError("Failed to allocate temporary storage for the commands JSON");
AzureIoTClient 0:1f9b2707ec7d 452 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 453 }
AzureIoTClient 0:1f9b2707ec7d 454 else
AzureIoTClient 0:1f9b2707ec7d 455 {
AzureIoTClient 0:1f9b2707ec7d 456 MULTITREE_HANDLE commandsTree;
AzureIoTClient 0:1f9b2707ec7d 457
AzureIoTClient 0:1f9b2707ec7d 458 (void)memcpy(commandJSON, command, size);
AzureIoTClient 0:1f9b2707ec7d 459 commandJSON[size] = '\0';
AzureIoTClient 0:1f9b2707ec7d 460
AzureIoTClient 0:1f9b2707ec7d 461 /* 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 462 if (JSONDecoder_JSON_To_MultiTree(commandJSON, &commandsTree) != JSON_DECODER_OK)
AzureIoTClient 0:1f9b2707ec7d 463 {
AzureIoTClient 0:1f9b2707ec7d 464 /* 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 465 LogError("Decoding JSON to a multi tree failed");
AzureIoTClient 0:1f9b2707ec7d 466 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 0:1f9b2707ec7d 467 }
AzureIoTClient 0:1f9b2707ec7d 468 else
AzureIoTClient 0:1f9b2707ec7d 469 {
AzureIoTClient 0:1f9b2707ec7d 470 result = DecodeCommand(commandDecoderInstance, commandsTree);
AzureIoTClient 0:1f9b2707ec7d 471
AzureIoTClient 0:1f9b2707ec7d 472 /* 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 473 MultiTree_Destroy(commandsTree);
AzureIoTClient 0:1f9b2707ec7d 474 }
AzureIoTClient 0:1f9b2707ec7d 475
AzureIoTClient 0:1f9b2707ec7d 476 free(commandJSON);
AzureIoTClient 0:1f9b2707ec7d 477 }
AzureIoTClient 0:1f9b2707ec7d 478 }
AzureIoTClient 0:1f9b2707ec7d 479 return result;
AzureIoTClient 0:1f9b2707ec7d 480 }
AzureIoTClient 0:1f9b2707ec7d 481
AzureIoTClient 0:1f9b2707ec7d 482 COMMAND_DECODER_HANDLE CommandDecoder_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, ACTION_CALLBACK_FUNC actionCallback, void* actionCallbackContext)
AzureIoTClient 0:1f9b2707ec7d 483 {
AzureIoTClient 17:fa1bba4c6053 484 COMMAND_DECODER_HANDLE_DATA* result;
AzureIoTClient 0:1f9b2707ec7d 485 /* Codes_SRS_COMMAND_DECODER_99_019:[ For all exposed APIs argument validity checks shall precede other checks.] */
AzureIoTClient 0:1f9b2707ec7d 486 /* Codes_SRS_COMMAND_DECODER_01_003: [If any of the arguments modelHandle is NULL, CommandDecoder_Create shall return NULL.]*/
AzureIoTClient 0:1f9b2707ec7d 487 if (
AzureIoTClient 0:1f9b2707ec7d 488 (modelHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 489 )
AzureIoTClient 0:1f9b2707ec7d 490 {
AzureIoTClient 0:1f9b2707ec7d 491 LogError("Invalid arguments modelHandle=%p, actionCallback=%p, actionCallbackContext=%p",
AzureIoTClient 0:1f9b2707ec7d 492 modelHandle, actionCallback, actionCallbackContext);
AzureIoTClient 0:1f9b2707ec7d 493 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 494 }
AzureIoTClient 0:1f9b2707ec7d 495 else
AzureIoTClient 0:1f9b2707ec7d 496 {
AzureIoTClient 0:1f9b2707ec7d 497 /* Codes_SRS_COMMAND_DECODER_01_001: [CommandDecoder_Create shall create a new instance of a CommandDecoder.] */
AzureIoTClient 17:fa1bba4c6053 498 result = malloc(sizeof(COMMAND_DECODER_HANDLE_DATA));
AzureIoTClient 0:1f9b2707ec7d 499 if (result == NULL)
AzureIoTClient 0:1f9b2707ec7d 500 {
AzureIoTClient 0:1f9b2707ec7d 501 /* Codes_SRS_COMMAND_DECODER_01_004: [If any error is encountered during CommandDecoder_Create CommandDecoder_Create shall return NULL.] */
AzureIoTClient 17:fa1bba4c6053 502 /*return as is*/
AzureIoTClient 0:1f9b2707ec7d 503 }
AzureIoTClient 0:1f9b2707ec7d 504 else
AzureIoTClient 0:1f9b2707ec7d 505 {
AzureIoTClient 0:1f9b2707ec7d 506 result->ModelHandle = modelHandle;
AzureIoTClient 0:1f9b2707ec7d 507 result->ActionCallback = actionCallback;
AzureIoTClient 0:1f9b2707ec7d 508 result->ActionCallbackContext = actionCallbackContext;
AzureIoTClient 0:1f9b2707ec7d 509 }
AzureIoTClient 0:1f9b2707ec7d 510 }
AzureIoTClient 0:1f9b2707ec7d 511
AzureIoTClient 0:1f9b2707ec7d 512 return result;
AzureIoTClient 0:1f9b2707ec7d 513 }
AzureIoTClient 0:1f9b2707ec7d 514
AzureIoTClient 0:1f9b2707ec7d 515 void CommandDecoder_Destroy(COMMAND_DECODER_HANDLE commandDecoderHandle)
AzureIoTClient 0:1f9b2707ec7d 516 {
AzureIoTClient 0:1f9b2707ec7d 517 /* Codes_SRS_COMMAND_DECODER_01_007: [If CommandDecoder_Destroy is called with a NULL handle, CommandDecoder_Destroy shall do nothing.] */
AzureIoTClient 0:1f9b2707ec7d 518 if (commandDecoderHandle != NULL)
AzureIoTClient 0:1f9b2707ec7d 519 {
AzureIoTClient 17:fa1bba4c6053 520 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)commandDecoderHandle;
AzureIoTClient 0:1f9b2707ec7d 521
AzureIoTClient 0:1f9b2707ec7d 522 /* Codes_SRS_COMMAND_DECODER_01_005: [CommandDecoder_Destroy shall free all resources associated with the commandDecoderHandle instance.] */
AzureIoTClient 0:1f9b2707ec7d 523 free(commandDecoderInstance);
AzureIoTClient 0:1f9b2707ec7d 524 }
AzureIoTClient 17:fa1bba4c6053 525 }
AzureIoTClient 17:fa1bba4c6053 526
AzureIoTClient 17:fa1bba4c6053 527 DEFINE_ENUM_STRINGS(AGENT_DATA_TYPE_TYPE, AGENT_DATA_TYPE_TYPE_VALUES);
AzureIoTClient 17:fa1bba4c6053 528
AzureIoTClient 17:fa1bba4c6053 529 /*validates that the multitree (coming from a JSON) is actually a serialization of the model (complete or incomplete)*/
AzureIoTClient 17:fa1bba4c6053 530 /*if the serialization contains more than the model, then it fails.*/
AzureIoTClient 17:fa1bba4c6053 531 /*if the serialization does not contain mandatory items from the model, it fails*/
AzureIoTClient 17:fa1bba4c6053 532 static bool validateModel_vs_Multitree(void* startAddress, SCHEMA_MODEL_TYPE_HANDLE modelHandle, MULTITREE_HANDLE desiredPropertiesTree, size_t offset)
AzureIoTClient 17:fa1bba4c6053 533 {
AzureIoTClient 17:fa1bba4c6053 534
AzureIoTClient 17:fa1bba4c6053 535 bool result;
AzureIoTClient 17:fa1bba4c6053 536 size_t nChildren;
AzureIoTClient 17:fa1bba4c6053 537 size_t nProcessedChildren = 0;
AzureIoTClient 17:fa1bba4c6053 538 (void)MultiTree_GetChildCount(desiredPropertiesTree, &nChildren);
AzureIoTClient 17:fa1bba4c6053 539 for (size_t i = 0;i < nChildren;i++)
AzureIoTClient 17:fa1bba4c6053 540 {
AzureIoTClient 17:fa1bba4c6053 541 MULTITREE_HANDLE child;
AzureIoTClient 17:fa1bba4c6053 542 if (MultiTree_GetChild(desiredPropertiesTree, i, &child) != MULTITREE_OK)
AzureIoTClient 17:fa1bba4c6053 543 {
AzureIoTClient 17:fa1bba4c6053 544 LogError("failure in MultiTree_GetChild");
AzureIoTClient 17:fa1bba4c6053 545 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 546 }
AzureIoTClient 17:fa1bba4c6053 547 else
AzureIoTClient 17:fa1bba4c6053 548 {
AzureIoTClient 17:fa1bba4c6053 549 STRING_HANDLE childName = STRING_new();
AzureIoTClient 17:fa1bba4c6053 550 if (childName == NULL)
AzureIoTClient 17:fa1bba4c6053 551 {
AzureIoTClient 17:fa1bba4c6053 552 LogError("failure to STRING_new");
AzureIoTClient 17:fa1bba4c6053 553 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 554 }
AzureIoTClient 17:fa1bba4c6053 555 else
AzureIoTClient 17:fa1bba4c6053 556 {
AzureIoTClient 17:fa1bba4c6053 557 if (MultiTree_GetName(child, childName) != MULTITREE_OK)
AzureIoTClient 17:fa1bba4c6053 558 {
AzureIoTClient 17:fa1bba4c6053 559 LogError("failure to MultiTree_GetName");
AzureIoTClient 17:fa1bba4c6053 560 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 561 }
AzureIoTClient 17:fa1bba4c6053 562 else
AzureIoTClient 17:fa1bba4c6053 563 {
AzureIoTClient 17:fa1bba4c6053 564 const char *childName_str = STRING_c_str(childName);
AzureIoTClient 17:fa1bba4c6053 565 SCHEMA_MODEL_ELEMENT elementType = Schema_GetModelElementByName(modelHandle, childName_str);
AzureIoTClient 17:fa1bba4c6053 566 switch (elementType.elementType)
AzureIoTClient 17:fa1bba4c6053 567 {
AzureIoTClient 17:fa1bba4c6053 568 default:
AzureIoTClient 17:fa1bba4c6053 569 {
AzureIoTClient 17:fa1bba4c6053 570 LogError("INTERNAL ERROR: unexpected function return");
AzureIoTClient 17:fa1bba4c6053 571 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 572 break;
AzureIoTClient 17:fa1bba4c6053 573 }
AzureIoTClient 17:fa1bba4c6053 574 case (SCHEMA_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 575 {
AzureIoTClient 17:fa1bba4c6053 576 LogError("cannot ingest name (WITH_DATA instead of WITH_DESIRED_PROPERTY): %s", STRING_c_str);
AzureIoTClient 17:fa1bba4c6053 577 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 578 break;
AzureIoTClient 17:fa1bba4c6053 579 }
AzureIoTClient 17:fa1bba4c6053 580 case (SCHEMA_REPORTED_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 581 {
AzureIoTClient 17:fa1bba4c6053 582 LogError("cannot ingest name (WITH_REPORTED_PROPERTY instead of WITH_DESIRED_PROPERTY): %s", STRING_c_str);
AzureIoTClient 17:fa1bba4c6053 583 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 584 break;
AzureIoTClient 17:fa1bba4c6053 585 }
AzureIoTClient 17:fa1bba4c6053 586 case (SCHEMA_DESIRED_PROPERTY):
AzureIoTClient 17:fa1bba4c6053 587 {
AzureIoTClient 17:fa1bba4c6053 588 /*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 589 SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle = elementType.elementHandle.desiredPropertyHandle;
AzureIoTClient 17:fa1bba4c6053 590
AzureIoTClient 17:fa1bba4c6053 591 const char* desiredPropertyType = Schema_GetModelDesiredPropertyType(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 592 AGENT_DATA_TYPE output;
AzureIoTClient 17:fa1bba4c6053 593 if (DecodeValueFromNode(Schema_GetSchemaForModelType(modelHandle), &output, child, desiredPropertyType) != 0)
AzureIoTClient 17:fa1bba4c6053 594 {
AzureIoTClient 17:fa1bba4c6053 595 LogError("failure in DecodeValueFromNode");
AzureIoTClient 17:fa1bba4c6053 596 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 597 }
AzureIoTClient 17:fa1bba4c6053 598 else
AzureIoTClient 17:fa1bba4c6053 599 {
AzureIoTClient 17:fa1bba4c6053 600 /*Codes_SRS_COMMAND_DECODER_02_008: [ The desired property shall be constructed in memory by calling pfDesiredPropertyFromAGENT_DATA_TYPE. ]*/
AzureIoTClient 17:fa1bba4c6053 601 pfDesiredPropertyFromAGENT_DATA_TYPE leFunction = Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 602 if (leFunction(&output, (char*)startAddress + offset + Schema_GetModelDesiredProperty_offset(desiredPropertyHandle)) != 0)
AzureIoTClient 17:fa1bba4c6053 603 {
AzureIoTClient 17:fa1bba4c6053 604 LogError("failure in a function that converts from AGENT_DATA_TYPE to C data");
AzureIoTClient 17:fa1bba4c6053 605 }
AzureIoTClient 17:fa1bba4c6053 606 else
AzureIoTClient 17:fa1bba4c6053 607 {
AzureIoTClient 17:fa1bba4c6053 608 /*Codes_SRS_COMMAND_DECODER_02_013: [ If the desired property has a non-NULL pfOnDesiredProperty then it shall be called. ]*/
AzureIoTClient 17:fa1bba4c6053 609 pfOnDesiredProperty onDesiredProperty = Schema_GetModelDesiredProperty_pfOnDesiredProperty(desiredPropertyHandle);
AzureIoTClient 17:fa1bba4c6053 610 if (onDesiredProperty != NULL)
AzureIoTClient 17:fa1bba4c6053 611 {
AzureIoTClient 17:fa1bba4c6053 612 onDesiredProperty((char*)startAddress + offset);
AzureIoTClient 17:fa1bba4c6053 613 }
AzureIoTClient 17:fa1bba4c6053 614 nProcessedChildren++;
AzureIoTClient 17:fa1bba4c6053 615 }
AzureIoTClient 17:fa1bba4c6053 616 Destroy_AGENT_DATA_TYPE(&output);
AzureIoTClient 17:fa1bba4c6053 617 }
AzureIoTClient 17:fa1bba4c6053 618
AzureIoTClient 17:fa1bba4c6053 619 break;
AzureIoTClient 17:fa1bba4c6053 620 }
AzureIoTClient 17:fa1bba4c6053 621 case(SCHEMA_MODEL_IN_MODEL):
AzureIoTClient 17:fa1bba4c6053 622 {
AzureIoTClient 17:fa1bba4c6053 623 SCHEMA_MODEL_TYPE_HANDLE modelModel = elementType.elementHandle.modelHandle;
AzureIoTClient 17:fa1bba4c6053 624
AzureIoTClient 17:fa1bba4c6053 625 /*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 626 if (!validateModel_vs_Multitree(startAddress, modelModel, child, offset + Schema_GetModelModelByName_Offset(modelHandle, childName_str)))
AzureIoTClient 17:fa1bba4c6053 627 {
AzureIoTClient 17:fa1bba4c6053 628 LogError("failure in validateModel_vs_Multitree");
AzureIoTClient 17:fa1bba4c6053 629 i = nChildren;
AzureIoTClient 17:fa1bba4c6053 630 }
AzureIoTClient 17:fa1bba4c6053 631 else
AzureIoTClient 17:fa1bba4c6053 632 {
AzureIoTClient 17:fa1bba4c6053 633 /*if the model in model so happened to be a WITH_DESIRED_PROPERTY... (only those has non_NULL pfOnDesiredProperty) */
AzureIoTClient 17:fa1bba4c6053 634 /*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 635 pfOnDesiredProperty onDesiredProperty = Schema_GetModelModelByName_OnDesiredProperty(modelHandle, childName_str);
AzureIoTClient 17:fa1bba4c6053 636 if (onDesiredProperty != NULL)
AzureIoTClient 17:fa1bba4c6053 637 {
AzureIoTClient 17:fa1bba4c6053 638 onDesiredProperty((char*)startAddress + offset);
AzureIoTClient 17:fa1bba4c6053 639 }
AzureIoTClient 17:fa1bba4c6053 640
AzureIoTClient 17:fa1bba4c6053 641 nProcessedChildren++;
AzureIoTClient 17:fa1bba4c6053 642 }
AzureIoTClient 17:fa1bba4c6053 643
AzureIoTClient 17:fa1bba4c6053 644 break;
AzureIoTClient 17:fa1bba4c6053 645 }
AzureIoTClient 17:fa1bba4c6053 646
AzureIoTClient 17:fa1bba4c6053 647 } /*switch*/
AzureIoTClient 17:fa1bba4c6053 648 }
AzureIoTClient 17:fa1bba4c6053 649 STRING_delete(childName);
AzureIoTClient 17:fa1bba4c6053 650 }
AzureIoTClient 17:fa1bba4c6053 651 }
AzureIoTClient 17:fa1bba4c6053 652 }
AzureIoTClient 17:fa1bba4c6053 653
AzureIoTClient 17:fa1bba4c6053 654 if(nProcessedChildren == nChildren)
AzureIoTClient 17:fa1bba4c6053 655 {
AzureIoTClient 17:fa1bba4c6053 656 /*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 657 result = true;
AzureIoTClient 17:fa1bba4c6053 658 }
AzureIoTClient 17:fa1bba4c6053 659 else
AzureIoTClient 17:fa1bba4c6053 660 {
AzureIoTClient 17:fa1bba4c6053 661 /*Codes_SRS_COMMAND_DECODER_02_011: [ Otherwise CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_FAILED. ]*/
AzureIoTClient 17:fa1bba4c6053 662 LogError("not all constituents of the JSON have been ingested");
AzureIoTClient 17:fa1bba4c6053 663 result = false;
AzureIoTClient 17:fa1bba4c6053 664 }
AzureIoTClient 17:fa1bba4c6053 665 return result;
AzureIoTClient 17:fa1bba4c6053 666 }
AzureIoTClient 17:fa1bba4c6053 667
AzureIoTClient 17:fa1bba4c6053 668 static EXECUTE_COMMAND_RESULT DecodeDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE_DATA* handle, MULTITREE_HANDLE desiredPropertiesTree)
AzureIoTClient 17:fa1bba4c6053 669 {
AzureIoTClient 17:fa1bba4c6053 670 /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
AzureIoTClient 17:fa1bba4c6053 671 return validateModel_vs_Multitree(startAddress, handle->ModelHandle, desiredPropertiesTree, 0 )?EXECUTE_COMMAND_SUCCESS:EXECUTE_COMMAND_FAILED;
AzureIoTClient 17:fa1bba4c6053 672 }
AzureIoTClient 17:fa1bba4c6053 673
AzureIoTClient 17:fa1bba4c6053 674 EXECUTE_COMMAND_RESULT CommandDecoder_IngestDesiredProperties(void* startAddress, COMMAND_DECODER_HANDLE handle, const char* desiredProperties)
AzureIoTClient 17:fa1bba4c6053 675 {
AzureIoTClient 17:fa1bba4c6053 676 EXECUTE_COMMAND_RESULT result;
AzureIoTClient 17:fa1bba4c6053 677 /*Codes_SRS_COMMAND_DECODER_02_001: [ If startAddress is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 17:fa1bba4c6053 678 /*Codes_SRS_COMMAND_DECODER_02_002: [ If handle is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 17:fa1bba4c6053 679 /*Codes_SRS_COMMAND_DECODER_02_003: [ If desiredProperties is NULL then CommandDecoder_IngestDesiredProperties shall fail and return EXECUTE_COMMAND_ERROR. ]*/
AzureIoTClient 17:fa1bba4c6053 680 if(
AzureIoTClient 17:fa1bba4c6053 681 (startAddress == NULL) ||
AzureIoTClient 17:fa1bba4c6053 682 (handle == NULL) ||
AzureIoTClient 17:fa1bba4c6053 683 (desiredProperties == NULL)
AzureIoTClient 17:fa1bba4c6053 684 )
AzureIoTClient 17:fa1bba4c6053 685 {
AzureIoTClient 17:fa1bba4c6053 686 LogError("invalid argument COMMAND_DECODER_HANDLE handle=%p, const char* desiredProperties=%p", handle, desiredProperties);
AzureIoTClient 17:fa1bba4c6053 687 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 17:fa1bba4c6053 688 }
AzureIoTClient 17:fa1bba4c6053 689 else
AzureIoTClient 17:fa1bba4c6053 690 {
AzureIoTClient 17:fa1bba4c6053 691 /*Codes_SRS_COMMAND_DECODER_02_004: [ CommandDecoder_IngestDesiredProperties shall clone desiredProperties. ]*/
AzureIoTClient 17:fa1bba4c6053 692 char* copy;
AzureIoTClient 17:fa1bba4c6053 693 if (mallocAndStrcpy_s(&copy, desiredProperties) != 0)
AzureIoTClient 17:fa1bba4c6053 694 {
AzureIoTClient 17:fa1bba4c6053 695 LogError("failure in mallocAndStrcpy_s");
AzureIoTClient 17:fa1bba4c6053 696 result = EXECUTE_COMMAND_FAILED;
AzureIoTClient 17:fa1bba4c6053 697 }
AzureIoTClient 17:fa1bba4c6053 698 else
AzureIoTClient 17:fa1bba4c6053 699 {
AzureIoTClient 17:fa1bba4c6053 700 /*Codes_SRS_COMMAND_DECODER_02_005: [ CommandDecoder_IngestDesiredProperties shall create a MULTITREE_HANDLE ouf of the clone of desiredProperties. ]*/
AzureIoTClient 17:fa1bba4c6053 701 MULTITREE_HANDLE desiredPropertiesTree;
AzureIoTClient 17:fa1bba4c6053 702 if (JSONDecoder_JSON_To_MultiTree(copy, &desiredPropertiesTree) != JSON_DECODER_OK)
AzureIoTClient 17:fa1bba4c6053 703 {
AzureIoTClient 17:fa1bba4c6053 704 LogError("Decoding JSON to a multi tree failed");
AzureIoTClient 17:fa1bba4c6053 705 result = EXECUTE_COMMAND_ERROR;
AzureIoTClient 17:fa1bba4c6053 706 }
AzureIoTClient 17:fa1bba4c6053 707 else
AzureIoTClient 17:fa1bba4c6053 708 {
AzureIoTClient 17:fa1bba4c6053 709 COMMAND_DECODER_HANDLE_DATA* commandDecoderInstance = (COMMAND_DECODER_HANDLE_DATA*)handle;
AzureIoTClient 17:fa1bba4c6053 710
AzureIoTClient 17:fa1bba4c6053 711 /*Codes_SRS_COMMAND_DECODER_02_006: [ CommandDecoder_IngestDesiredProperties shall parse the MULTITREEE recursively. ]*/
AzureIoTClient 17:fa1bba4c6053 712 result = DecodeDesiredProperties(startAddress, commandDecoderInstance, desiredPropertiesTree);
AzureIoTClient 17:fa1bba4c6053 713
AzureIoTClient 17:fa1bba4c6053 714 MultiTree_Destroy(desiredPropertiesTree);
AzureIoTClient 17:fa1bba4c6053 715 }
AzureIoTClient 17:fa1bba4c6053 716 free(copy);
AzureIoTClient 17:fa1bba4c6053 717 }
AzureIoTClient 17:fa1bba4c6053 718 }
AzureIoTClient 17:fa1bba4c6053 719 return result;
AzureIoTClient 17:fa1bba4c6053 720 }