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