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
commanddecoder.c@0:1f9b2707ec7d, 2015-09-15 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Tue Sep 15 21:57:26 2015 -0700
- Revision:
- 0:1f9b2707ec7d
- Child:
- 10:c2aee3965a83
New release
Who changed what in which revision?
User | Revision | Line number | New 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 |
AzureIoTClient | 0:1f9b2707ec7d | 8 | #include "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" |
AzureIoTClient | 0:1f9b2707ec7d | 14 | #include "crt_abstractions.h" |
AzureIoTClient | 0:1f9b2707ec7d | 15 | #include "iot_logging.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 | 0:1f9b2707ec7d | 22 | typedef struct COMMAND_DECODER_INSTANCE_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 | 0:1f9b2707ec7d | 27 | } COMMAND_DECODER_INSTANCE; |
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 | 0:1f9b2707ec7d | 48 | LogError("Getting Struct information failed.\r\n"); |
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 | 0:1f9b2707ec7d | 56 | LogError("Struct type with 0 members is not allowed\r\n"); |
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 | 0:1f9b2707ec7d | 65 | LogError("Failed allocating member values for command argument\r\n"); |
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 | 0:1f9b2707ec7d | 74 | LogError("Failed allocating member names for command argument.\r\n"); |
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 | 0:1f9b2707ec7d | 92 | LogError("Getting struct member failed.\r\n"); |
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 | 0:1f9b2707ec7d | 100 | LogError("Getting the struct member information failed.\r\n"); |
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 | 0:1f9b2707ec7d | 112 | LogError("Getting child %s failed\r\n", 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 | 0:1f9b2707ec7d | 130 | LogError("Creating the agent data type from members failed.\r\n"); |
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 | 0:1f9b2707ec7d | 158 | LogError("Getting the string from the multitree failed.\r\n"); |
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 | 0:1f9b2707ec7d | 165 | LogError("Failed parsing node %s.\r\n", 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 | 0:1f9b2707ec7d | 172 | static EXECUTE_COMMAND_RESULT DecodeAndExecuteModelAction(COMMAND_DECODER_INSTANCE* 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 | 0:1f9b2707ec7d | 181 | LogError("Invalid action name\r\n"); |
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 | 0:1f9b2707ec7d | 197 | LogError("Invalid action name.\r\n"); |
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", ¶metersTreeNode) != 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 | 0:1f9b2707ec7d | 204 | LogError("Error getting Parameters node.\r\n"); |
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 | 0:1f9b2707ec7d | 216 | LogError("Failed reading action %s from the schema\r\n", 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 | 0:1f9b2707ec7d | 232 | LogError("Failed allocating arguments array\r\n"); |
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 | 0:1f9b2707ec7d | 239 | |
AzureIoTClient | 0:1f9b2707ec7d | 240 | /* Codes_SRS_COMMAND_DECODER_99_011:[ CommandDecoder shall attempt to extract from the command text the value for each action argument.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 241 | for (i = 0; i < argCount; i++) |
AzureIoTClient | 0:1f9b2707ec7d | 242 | { |
AzureIoTClient | 0:1f9b2707ec7d | 243 | SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle; |
AzureIoTClient | 0:1f9b2707ec7d | 244 | MULTITREE_HANDLE argumentNode; |
AzureIoTClient | 0:1f9b2707ec7d | 245 | const char* argName; |
AzureIoTClient | 0:1f9b2707ec7d | 246 | const char* argType; |
AzureIoTClient | 0:1f9b2707ec7d | 247 | |
AzureIoTClient | 0:1f9b2707ec7d | 248 | if (((actionArgumentHandle = Schema_GetModelActionArgumentByIndex(modelActionHandle, i)) == NULL) || |
AzureIoTClient | 0:1f9b2707ec7d | 249 | ((argName = Schema_GetActionArgumentName(actionArgumentHandle)) == NULL) || |
AzureIoTClient | 0:1f9b2707ec7d | 250 | ((argType = Schema_GetActionArgumentType(actionArgumentHandle)) == NULL)) |
AzureIoTClient | 0:1f9b2707ec7d | 251 | { |
AzureIoTClient | 0:1f9b2707ec7d | 252 | LogError("Failed getting the argument information from the schema\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 253 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 254 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 255 | } |
AzureIoTClient | 0:1f9b2707ec7d | 256 | /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 257 | /* Codes_SRS_COMMAND_DECODER_01_008: [Each argument shall be looked up as a field, member of the "Parameters" node.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 258 | else if (MultiTree_GetChildByName(parametersTreeNode, argName, &argumentNode) != MULTITREE_OK) |
AzureIoTClient | 0:1f9b2707ec7d | 259 | { |
AzureIoTClient | 0:1f9b2707ec7d | 260 | /* 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 | 261 | LogError("Missing argument %s\r\n", argName); |
AzureIoTClient | 0:1f9b2707ec7d | 262 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 263 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 264 | } |
AzureIoTClient | 0:1f9b2707ec7d | 265 | else if (DecodeValueFromNode(schemaHandle, &arguments[i], argumentNode, argType) != 0) |
AzureIoTClient | 0:1f9b2707ec7d | 266 | { |
AzureIoTClient | 0:1f9b2707ec7d | 267 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 268 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 269 | } |
AzureIoTClient | 0:1f9b2707ec7d | 270 | } |
AzureIoTClient | 0:1f9b2707ec7d | 271 | |
AzureIoTClient | 0:1f9b2707ec7d | 272 | if (i == argCount) |
AzureIoTClient | 0:1f9b2707ec7d | 273 | { |
AzureIoTClient | 0:1f9b2707ec7d | 274 | /* 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 | 275 | result = commandDecoderInstance->ActionCallback(commandDecoderInstance->ActionCallbackContext, relativeActionPath, tempStr, argCount, arguments); |
AzureIoTClient | 0:1f9b2707ec7d | 276 | } |
AzureIoTClient | 0:1f9b2707ec7d | 277 | |
AzureIoTClient | 0:1f9b2707ec7d | 278 | for (j = 0; j < i; j++) |
AzureIoTClient | 0:1f9b2707ec7d | 279 | { |
AzureIoTClient | 0:1f9b2707ec7d | 280 | Destroy_AGENT_DATA_TYPE(&arguments[j]); |
AzureIoTClient | 0:1f9b2707ec7d | 281 | } |
AzureIoTClient | 0:1f9b2707ec7d | 282 | |
AzureIoTClient | 0:1f9b2707ec7d | 283 | if (arguments != NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 284 | { |
AzureIoTClient | 0:1f9b2707ec7d | 285 | free(arguments); |
AzureIoTClient | 0:1f9b2707ec7d | 286 | } |
AzureIoTClient | 0:1f9b2707ec7d | 287 | } |
AzureIoTClient | 0:1f9b2707ec7d | 288 | } |
AzureIoTClient | 0:1f9b2707ec7d | 289 | } |
AzureIoTClient | 0:1f9b2707ec7d | 290 | } |
AzureIoTClient | 0:1f9b2707ec7d | 291 | return result; |
AzureIoTClient | 0:1f9b2707ec7d | 292 | } |
AzureIoTClient | 0:1f9b2707ec7d | 293 | |
AzureIoTClient | 0:1f9b2707ec7d | 294 | static EXECUTE_COMMAND_RESULT ScanActionPathAndExecuteAction(COMMAND_DECODER_INSTANCE* commandDecoderInstance, SCHEMA_HANDLE schemaHandle, const char* actionPath, MULTITREE_HANDLE commandNode) |
AzureIoTClient | 0:1f9b2707ec7d | 295 | { |
AzureIoTClient | 0:1f9b2707ec7d | 296 | EXECUTE_COMMAND_RESULT result; |
AzureIoTClient | 0:1f9b2707ec7d | 297 | char* relativeActionPath; |
AzureIoTClient | 0:1f9b2707ec7d | 298 | const char* actionName = actionPath; |
AzureIoTClient | 0:1f9b2707ec7d | 299 | SCHEMA_MODEL_TYPE_HANDLE modelHandle = commandDecoderInstance->ModelHandle; |
AzureIoTClient | 0:1f9b2707ec7d | 300 | |
AzureIoTClient | 0:1f9b2707ec7d | 301 | /* 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 | 302 | do |
AzureIoTClient | 0:1f9b2707ec7d | 303 | { |
AzureIoTClient | 0:1f9b2707ec7d | 304 | /* find the slash */ |
AzureIoTClient | 0:1f9b2707ec7d | 305 | const char* slashPos = strchr(actionName, '/'); |
AzureIoTClient | 0:1f9b2707ec7d | 306 | if (slashPos == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 307 | { |
AzureIoTClient | 0:1f9b2707ec7d | 308 | size_t relativeActionPathLength; |
AzureIoTClient | 0:1f9b2707ec7d | 309 | |
AzureIoTClient | 0:1f9b2707ec7d | 310 | /* Codes_SRS_COMMAND_DECODER_99_037:[ The relative path passed to the actionCallback shall be in the format "childModel1/childModel2/.../childModelN".] */ |
AzureIoTClient | 0:1f9b2707ec7d | 311 | if (actionName == actionPath) |
AzureIoTClient | 0:1f9b2707ec7d | 312 | { |
AzureIoTClient | 0:1f9b2707ec7d | 313 | relativeActionPathLength = 0; |
AzureIoTClient | 0:1f9b2707ec7d | 314 | } |
AzureIoTClient | 0:1f9b2707ec7d | 315 | else |
AzureIoTClient | 0:1f9b2707ec7d | 316 | { |
AzureIoTClient | 0:1f9b2707ec7d | 317 | relativeActionPathLength = actionName - actionPath - 1; |
AzureIoTClient | 0:1f9b2707ec7d | 318 | } |
AzureIoTClient | 0:1f9b2707ec7d | 319 | |
AzureIoTClient | 0:1f9b2707ec7d | 320 | relativeActionPath = (char*)malloc(relativeActionPathLength + 1); |
AzureIoTClient | 0:1f9b2707ec7d | 321 | if (relativeActionPath == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 322 | { |
AzureIoTClient | 0:1f9b2707ec7d | 323 | /* 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 | 324 | LogError("Failed allocating relative action path\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 325 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 326 | } |
AzureIoTClient | 0:1f9b2707ec7d | 327 | else |
AzureIoTClient | 0:1f9b2707ec7d | 328 | { |
AzureIoTClient | 0:1f9b2707ec7d | 329 | strncpy(relativeActionPath, actionPath, relativeActionPathLength); |
AzureIoTClient | 0:1f9b2707ec7d | 330 | relativeActionPath[relativeActionPathLength] = 0; |
AzureIoTClient | 0:1f9b2707ec7d | 331 | |
AzureIoTClient | 0:1f9b2707ec7d | 332 | /* no slash found, this must be an action */ |
AzureIoTClient | 0:1f9b2707ec7d | 333 | result = DecodeAndExecuteModelAction(commandDecoderInstance, schemaHandle, modelHandle, relativeActionPath, actionName, commandNode); |
AzureIoTClient | 0:1f9b2707ec7d | 334 | |
AzureIoTClient | 0:1f9b2707ec7d | 335 | free(relativeActionPath); |
AzureIoTClient | 0:1f9b2707ec7d | 336 | actionName = NULL; |
AzureIoTClient | 0:1f9b2707ec7d | 337 | } |
AzureIoTClient | 0:1f9b2707ec7d | 338 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 339 | } |
AzureIoTClient | 0:1f9b2707ec7d | 340 | else |
AzureIoTClient | 0:1f9b2707ec7d | 341 | { |
AzureIoTClient | 0:1f9b2707ec7d | 342 | /* found a slash, get the child model name */ |
AzureIoTClient | 0:1f9b2707ec7d | 343 | size_t modelLength = slashPos - actionName; |
AzureIoTClient | 0:1f9b2707ec7d | 344 | char* childModelName = (char*)malloc(modelLength + 1); |
AzureIoTClient | 0:1f9b2707ec7d | 345 | if (childModelName == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 346 | { |
AzureIoTClient | 0:1f9b2707ec7d | 347 | /* 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 | 348 | LogError("Failed allocating child model name\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 349 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 350 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 351 | } |
AzureIoTClient | 0:1f9b2707ec7d | 352 | else |
AzureIoTClient | 0:1f9b2707ec7d | 353 | { |
AzureIoTClient | 0:1f9b2707ec7d | 354 | strncpy(childModelName, actionName, modelLength); |
AzureIoTClient | 0:1f9b2707ec7d | 355 | childModelName[modelLength] = 0; |
AzureIoTClient | 0:1f9b2707ec7d | 356 | |
AzureIoTClient | 0:1f9b2707ec7d | 357 | /* find the model */ |
AzureIoTClient | 0:1f9b2707ec7d | 358 | modelHandle = Schema_GetModelModelByName(modelHandle, childModelName); |
AzureIoTClient | 0:1f9b2707ec7d | 359 | if (modelHandle == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 360 | { |
AzureIoTClient | 0:1f9b2707ec7d | 361 | /* 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 | 0:1f9b2707ec7d | 362 | LogError("Getting the model %s failed\r\n", childModelName); |
AzureIoTClient | 0:1f9b2707ec7d | 363 | free(childModelName); |
AzureIoTClient | 0:1f9b2707ec7d | 364 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 365 | break; |
AzureIoTClient | 0:1f9b2707ec7d | 366 | } |
AzureIoTClient | 0:1f9b2707ec7d | 367 | else |
AzureIoTClient | 0:1f9b2707ec7d | 368 | { |
AzureIoTClient | 0:1f9b2707ec7d | 369 | free(childModelName); |
AzureIoTClient | 0:1f9b2707ec7d | 370 | actionName = slashPos + 1; |
AzureIoTClient | 0:1f9b2707ec7d | 371 | 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 | 372 | } |
AzureIoTClient | 0:1f9b2707ec7d | 373 | } |
AzureIoTClient | 0:1f9b2707ec7d | 374 | } |
AzureIoTClient | 0:1f9b2707ec7d | 375 | } while (actionName != NULL); |
AzureIoTClient | 0:1f9b2707ec7d | 376 | return result; |
AzureIoTClient | 0:1f9b2707ec7d | 377 | } |
AzureIoTClient | 0:1f9b2707ec7d | 378 | |
AzureIoTClient | 0:1f9b2707ec7d | 379 | static EXECUTE_COMMAND_RESULT DecodeCommand(COMMAND_DECODER_INSTANCE* commandDecoderInstance, MULTITREE_HANDLE commandNode) |
AzureIoTClient | 0:1f9b2707ec7d | 380 | { |
AzureIoTClient | 0:1f9b2707ec7d | 381 | EXECUTE_COMMAND_RESULT result; |
AzureIoTClient | 0:1f9b2707ec7d | 382 | SCHEMA_HANDLE schemaHandle; |
AzureIoTClient | 0:1f9b2707ec7d | 383 | |
AzureIoTClient | 0:1f9b2707ec7d | 384 | /* 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 | 385 | if ((schemaHandle = Schema_GetSchemaForModelType(commandDecoderInstance->ModelHandle)) == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 386 | { |
AzureIoTClient | 0:1f9b2707ec7d | 387 | /* 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 | 388 | LogError("Getting schema information failed\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 389 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 390 | } |
AzureIoTClient | 0:1f9b2707ec7d | 391 | else |
AzureIoTClient | 0:1f9b2707ec7d | 392 | { |
AzureIoTClient | 0:1f9b2707ec7d | 393 | const char* actionName; |
AzureIoTClient | 0:1f9b2707ec7d | 394 | MULTITREE_HANDLE nameTreeNode; |
AzureIoTClient | 0:1f9b2707ec7d | 395 | |
AzureIoTClient | 0:1f9b2707ec7d | 396 | /* Codes_SRS_COMMAND_DECODER_01_014: [CommandDecoder shall use the MultiTree APIs to extract a specific element from the command JSON.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 397 | /* Codes_SRS_COMMAND_DECODER_99_006:[ The action name shall be decoded from the element "name" of the command JSON.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 398 | if ((MultiTree_GetChildByName(commandNode, "Name", &nameTreeNode) != MULTITREE_OK) || |
AzureIoTClient | 0:1f9b2707ec7d | 399 | (MultiTree_GetValue(nameTreeNode, (const void **)&actionName) != MULTITREE_OK)) |
AzureIoTClient | 0:1f9b2707ec7d | 400 | { |
AzureIoTClient | 0:1f9b2707ec7d | 401 | /* 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 | 0:1f9b2707ec7d | 402 | LogError("Getting action name failed.\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 403 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 404 | } |
AzureIoTClient | 0:1f9b2707ec7d | 405 | else if (strlen(actionName) < 2) |
AzureIoTClient | 0:1f9b2707ec7d | 406 | { |
AzureIoTClient | 0:1f9b2707ec7d | 407 | /* 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 | 408 | LogError("Invalid action name.\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 409 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 410 | } |
AzureIoTClient | 0:1f9b2707ec7d | 411 | else |
AzureIoTClient | 0:1f9b2707ec7d | 412 | { |
AzureIoTClient | 0:1f9b2707ec7d | 413 | actionName++; |
AzureIoTClient | 0:1f9b2707ec7d | 414 | result = ScanActionPathAndExecuteAction(commandDecoderInstance, schemaHandle, actionName, commandNode); |
AzureIoTClient | 0:1f9b2707ec7d | 415 | } |
AzureIoTClient | 0:1f9b2707ec7d | 416 | } |
AzureIoTClient | 0:1f9b2707ec7d | 417 | return result; |
AzureIoTClient | 0:1f9b2707ec7d | 418 | } |
AzureIoTClient | 0:1f9b2707ec7d | 419 | |
AzureIoTClient | 0:1f9b2707ec7d | 420 | /*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 | 421 | EXECUTE_COMMAND_RESULT CommandDecoder_ExecuteCommand(COMMAND_DECODER_HANDLE handle, const char* command) |
AzureIoTClient | 0:1f9b2707ec7d | 422 | { |
AzureIoTClient | 0:1f9b2707ec7d | 423 | EXECUTE_COMMAND_RESULT result; |
AzureIoTClient | 0:1f9b2707ec7d | 424 | COMMAND_DECODER_INSTANCE* commandDecoderInstance = (COMMAND_DECODER_INSTANCE*)handle; |
AzureIoTClient | 0:1f9b2707ec7d | 425 | /*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 | 426 | if ( |
AzureIoTClient | 0:1f9b2707ec7d | 427 | (command == NULL) || |
AzureIoTClient | 0:1f9b2707ec7d | 428 | (commandDecoderInstance == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 429 | ) |
AzureIoTClient | 0:1f9b2707ec7d | 430 | { |
AzureIoTClient | 0:1f9b2707ec7d | 431 | LogError("Invalid argument, COMMAND_DECODER_HANDLE handle=%p, const char* command=%p\r\n", handle, command); |
AzureIoTClient | 0:1f9b2707ec7d | 432 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 433 | } |
AzureIoTClient | 0:1f9b2707ec7d | 434 | else |
AzureIoTClient | 0:1f9b2707ec7d | 435 | { |
AzureIoTClient | 0:1f9b2707ec7d | 436 | size_t size = strlen(command); |
AzureIoTClient | 0:1f9b2707ec7d | 437 | char* commandJSON; |
AzureIoTClient | 0:1f9b2707ec7d | 438 | |
AzureIoTClient | 0:1f9b2707ec7d | 439 | /* 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 | 440 | if ( |
AzureIoTClient | 0:1f9b2707ec7d | 441 | (size == 0) |
AzureIoTClient | 0:1f9b2707ec7d | 442 | ) |
AzureIoTClient | 0:1f9b2707ec7d | 443 | { |
AzureIoTClient | 0:1f9b2707ec7d | 444 | LogError("Failed because command size is zero\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 445 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 446 | } |
AzureIoTClient | 0:1f9b2707ec7d | 447 | /*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 | 448 | else if ((commandJSON = (char*)malloc(size + 1)) == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 449 | { |
AzureIoTClient | 0:1f9b2707ec7d | 450 | LogError("Failed to allocate temporary storage for the commands JSON\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 451 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 452 | } |
AzureIoTClient | 0:1f9b2707ec7d | 453 | else |
AzureIoTClient | 0:1f9b2707ec7d | 454 | { |
AzureIoTClient | 0:1f9b2707ec7d | 455 | MULTITREE_HANDLE commandsTree; |
AzureIoTClient | 0:1f9b2707ec7d | 456 | |
AzureIoTClient | 0:1f9b2707ec7d | 457 | (void)memcpy(commandJSON, command, size); |
AzureIoTClient | 0:1f9b2707ec7d | 458 | commandJSON[size] = '\0'; |
AzureIoTClient | 0:1f9b2707ec7d | 459 | |
AzureIoTClient | 0:1f9b2707ec7d | 460 | /* 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 | 461 | if (JSONDecoder_JSON_To_MultiTree(commandJSON, &commandsTree) != JSON_DECODER_OK) |
AzureIoTClient | 0:1f9b2707ec7d | 462 | { |
AzureIoTClient | 0:1f9b2707ec7d | 463 | /* 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 | 464 | LogError("Decoding JSON to a multi tree failed\r\n"); |
AzureIoTClient | 0:1f9b2707ec7d | 465 | result = EXECUTE_COMMAND_ERROR; |
AzureIoTClient | 0:1f9b2707ec7d | 466 | } |
AzureIoTClient | 0:1f9b2707ec7d | 467 | else |
AzureIoTClient | 0:1f9b2707ec7d | 468 | { |
AzureIoTClient | 0:1f9b2707ec7d | 469 | result = DecodeCommand(commandDecoderInstance, commandsTree); |
AzureIoTClient | 0:1f9b2707ec7d | 470 | |
AzureIoTClient | 0:1f9b2707ec7d | 471 | /* 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 | 472 | MultiTree_Destroy(commandsTree); |
AzureIoTClient | 0:1f9b2707ec7d | 473 | } |
AzureIoTClient | 0:1f9b2707ec7d | 474 | |
AzureIoTClient | 0:1f9b2707ec7d | 475 | free(commandJSON); |
AzureIoTClient | 0:1f9b2707ec7d | 476 | } |
AzureIoTClient | 0:1f9b2707ec7d | 477 | } |
AzureIoTClient | 0:1f9b2707ec7d | 478 | return result; |
AzureIoTClient | 0:1f9b2707ec7d | 479 | } |
AzureIoTClient | 0:1f9b2707ec7d | 480 | |
AzureIoTClient | 0:1f9b2707ec7d | 481 | COMMAND_DECODER_HANDLE CommandDecoder_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, ACTION_CALLBACK_FUNC actionCallback, void* actionCallbackContext) |
AzureIoTClient | 0:1f9b2707ec7d | 482 | { |
AzureIoTClient | 0:1f9b2707ec7d | 483 | COMMAND_DECODER_INSTANCE* result; |
AzureIoTClient | 0:1f9b2707ec7d | 484 | /* Codes_SRS_COMMAND_DECODER_99_019:[ For all exposed APIs argument validity checks shall precede other checks.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 485 | /* Codes_SRS_COMMAND_DECODER_01_003: [If any of the arguments modelHandle is NULL, CommandDecoder_Create shall return NULL.]*/ |
AzureIoTClient | 0:1f9b2707ec7d | 486 | if ( |
AzureIoTClient | 0:1f9b2707ec7d | 487 | (modelHandle == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 488 | ) |
AzureIoTClient | 0:1f9b2707ec7d | 489 | { |
AzureIoTClient | 0:1f9b2707ec7d | 490 | LogError("Invalid arguments modelHandle=%p, actionCallback=%p, actionCallbackContext=%p", |
AzureIoTClient | 0:1f9b2707ec7d | 491 | modelHandle, actionCallback, actionCallbackContext); |
AzureIoTClient | 0:1f9b2707ec7d | 492 | result = NULL; |
AzureIoTClient | 0:1f9b2707ec7d | 493 | } |
AzureIoTClient | 0:1f9b2707ec7d | 494 | else |
AzureIoTClient | 0:1f9b2707ec7d | 495 | { |
AzureIoTClient | 0:1f9b2707ec7d | 496 | /* Codes_SRS_COMMAND_DECODER_01_001: [CommandDecoder_Create shall create a new instance of a CommandDecoder.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 497 | result = malloc(sizeof(COMMAND_DECODER_INSTANCE)); |
AzureIoTClient | 0:1f9b2707ec7d | 498 | if (result == NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 499 | { |
AzureIoTClient | 0:1f9b2707ec7d | 500 | /* Codes_SRS_COMMAND_DECODER_01_004: [If any error is encountered during CommandDecoder_Create CommandDecoder_Create shall return NULL.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 501 | result = NULL; |
AzureIoTClient | 0:1f9b2707ec7d | 502 | } |
AzureIoTClient | 0:1f9b2707ec7d | 503 | else |
AzureIoTClient | 0:1f9b2707ec7d | 504 | { |
AzureIoTClient | 0:1f9b2707ec7d | 505 | result->ModelHandle = modelHandle; |
AzureIoTClient | 0:1f9b2707ec7d | 506 | result->ActionCallback = actionCallback; |
AzureIoTClient | 0:1f9b2707ec7d | 507 | result->ActionCallbackContext = actionCallbackContext; |
AzureIoTClient | 0:1f9b2707ec7d | 508 | } |
AzureIoTClient | 0:1f9b2707ec7d | 509 | } |
AzureIoTClient | 0:1f9b2707ec7d | 510 | |
AzureIoTClient | 0:1f9b2707ec7d | 511 | return result; |
AzureIoTClient | 0:1f9b2707ec7d | 512 | } |
AzureIoTClient | 0:1f9b2707ec7d | 513 | |
AzureIoTClient | 0:1f9b2707ec7d | 514 | void CommandDecoder_Destroy(COMMAND_DECODER_HANDLE commandDecoderHandle) |
AzureIoTClient | 0:1f9b2707ec7d | 515 | { |
AzureIoTClient | 0:1f9b2707ec7d | 516 | /* Codes_SRS_COMMAND_DECODER_01_007: [If CommandDecoder_Destroy is called with a NULL handle, CommandDecoder_Destroy shall do nothing.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 517 | if (commandDecoderHandle != NULL) |
AzureIoTClient | 0:1f9b2707ec7d | 518 | { |
AzureIoTClient | 0:1f9b2707ec7d | 519 | COMMAND_DECODER_INSTANCE* commandDecoderInstance = (COMMAND_DECODER_INSTANCE*)commandDecoderHandle; |
AzureIoTClient | 0:1f9b2707ec7d | 520 | |
AzureIoTClient | 0:1f9b2707ec7d | 521 | /* Codes_SRS_COMMAND_DECODER_01_005: [CommandDecoder_Destroy shall free all resources associated with the commandDecoderHandle instance.] */ |
AzureIoTClient | 0:1f9b2707ec7d | 522 | free(commandDecoderInstance); |
AzureIoTClient | 0:1f9b2707ec7d | 523 | } |
AzureIoTClient | 0:1f9b2707ec7d | 524 | } |