A modelling and serializer library for Microsoft Azure IoTHub client applications

Dependents:   sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more

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

Committer:
AzureIoTClient
Date:
Thu Dec 17 18:23:43 2015 -0800
Revision:
5:c08e3ffc68e4
Parent:
0:1f9b2707ec7d
Child:
10:c2aee3965a83
v1.0.0-preview.4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 0:1f9b2707ec7d 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 0:1f9b2707ec7d 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 0:1f9b2707ec7d 3
AzureIoTClient 0:1f9b2707ec7d 4 #include <stdlib.h> /*for free*/
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 <stdbool.h>
AzureIoTClient 0:1f9b2707ec7d 11 #include "datamarshaller.h"
AzureIoTClient 0:1f9b2707ec7d 12 #include "crt_abstractions.h"
AzureIoTClient 0:1f9b2707ec7d 13 #include "schema.h"
AzureIoTClient 0:1f9b2707ec7d 14 #include "jsonencoder.h"
AzureIoTClient 0:1f9b2707ec7d 15 #include "agenttypesystem.h"
AzureIoTClient 0:1f9b2707ec7d 16 #include "iot_logging.h"
AzureIoTClient 0:1f9b2707ec7d 17
AzureIoTClient 0:1f9b2707ec7d 18 DEFINE_ENUM_STRINGS(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_RESULT_VALUES);
AzureIoTClient 0:1f9b2707ec7d 19
AzureIoTClient 0:1f9b2707ec7d 20 #define LOG_DATA_MARSHALLER_ERROR \
AzureIoTClient 0:1f9b2707ec7d 21 LogError("(result = %s)\r\n", ENUM_TO_STRING(DATA_MARSHALLER_RESULT, result));
AzureIoTClient 0:1f9b2707ec7d 22
AzureIoTClient 0:1f9b2707ec7d 23 typedef struct DATA_MARSHALLER_INSTANCE_TAG
AzureIoTClient 0:1f9b2707ec7d 24 {
AzureIoTClient 0:1f9b2707ec7d 25 SCHEMA_MODEL_TYPE_HANDLE ModelHandle;
AzureIoTClient 0:1f9b2707ec7d 26 bool IncludePropertyPath;
AzureIoTClient 0:1f9b2707ec7d 27 } DATA_MARSHALLER_INSTANCE;
AzureIoTClient 0:1f9b2707ec7d 28
AzureIoTClient 0:1f9b2707ec7d 29 static int NoCloneFunction(void** destination, const void* source)
AzureIoTClient 0:1f9b2707ec7d 30 {
AzureIoTClient 0:1f9b2707ec7d 31 *destination = (void*)source;
AzureIoTClient 0:1f9b2707ec7d 32 return 0;
AzureIoTClient 0:1f9b2707ec7d 33 }
AzureIoTClient 0:1f9b2707ec7d 34
AzureIoTClient 0:1f9b2707ec7d 35 static void NoFreeFunction(void* value)
AzureIoTClient 0:1f9b2707ec7d 36 {
AzureIoTClient 0:1f9b2707ec7d 37 (void)value;
AzureIoTClient 0:1f9b2707ec7d 38 }
AzureIoTClient 0:1f9b2707ec7d 39
AzureIoTClient 0:1f9b2707ec7d 40 DATA_MARSHALLER_HANDLE DataMarshaller_Create(SCHEMA_MODEL_TYPE_HANDLE modelHandle, bool includePropertyPath)
AzureIoTClient 0:1f9b2707ec7d 41 {
AzureIoTClient 0:1f9b2707ec7d 42 DATA_MARSHALLER_HANDLE result;
AzureIoTClient 0:1f9b2707ec7d 43 DATA_MARSHALLER_INSTANCE* dataMarshallerInstance;
AzureIoTClient 0:1f9b2707ec7d 44
AzureIoTClient 0:1f9b2707ec7d 45 /*Codes_SRS_DATA_MARSHALLER_99_019:[ DataMarshaller_Create shall return NULL if any argument is NULL.]*/
AzureIoTClient 0:1f9b2707ec7d 46 if (
AzureIoTClient 0:1f9b2707ec7d 47 (modelHandle == NULL)
AzureIoTClient 0:1f9b2707ec7d 48 )
AzureIoTClient 0:1f9b2707ec7d 49 {
AzureIoTClient 0:1f9b2707ec7d 50 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 51 LogError("(result = %s)\r\n", ENUM_TO_STRING(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_INVALID_ARG));
AzureIoTClient 0:1f9b2707ec7d 52 }
AzureIoTClient 0:1f9b2707ec7d 53 else if ((dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)malloc(sizeof(DATA_MARSHALLER_INSTANCE))) == NULL)
AzureIoTClient 0:1f9b2707ec7d 54 {
AzureIoTClient 0:1f9b2707ec7d 55 /* Codes_SRS_DATA_MARSHALLER_99_048:[On any other errors not explicitly specified, DataMarshaller_Create shall return NULL.] */
AzureIoTClient 0:1f9b2707ec7d 56 result = NULL;
AzureIoTClient 0:1f9b2707ec7d 57 LogError("(result = %s)\r\n", ENUM_TO_STRING(DATA_MARSHALLER_RESULT, DATA_MARSHALLER_ERROR));
AzureIoTClient 0:1f9b2707ec7d 58 }
AzureIoTClient 0:1f9b2707ec7d 59 else
AzureIoTClient 0:1f9b2707ec7d 60 {
AzureIoTClient 0:1f9b2707ec7d 61 /*everything ok*/
AzureIoTClient 0:1f9b2707ec7d 62 dataMarshallerInstance->ModelHandle = modelHandle;
AzureIoTClient 0:1f9b2707ec7d 63 dataMarshallerInstance->IncludePropertyPath = includePropertyPath;
AzureIoTClient 0:1f9b2707ec7d 64
AzureIoTClient 0:1f9b2707ec7d 65 /*Codes_SRS_DATA_MARSHALLER_99_018:[ DataMarshaller_Create shall create a new DataMarshaller instance and on success it shall return a non NULL handle.]*/
AzureIoTClient 0:1f9b2707ec7d 66 result = dataMarshallerInstance;
AzureIoTClient 0:1f9b2707ec7d 67 }
AzureIoTClient 0:1f9b2707ec7d 68 return result;
AzureIoTClient 0:1f9b2707ec7d 69 }
AzureIoTClient 0:1f9b2707ec7d 70
AzureIoTClient 0:1f9b2707ec7d 71 void DataMarshaller_Destroy(DATA_MARSHALLER_HANDLE dataMarshallerHandle)
AzureIoTClient 0:1f9b2707ec7d 72 {
AzureIoTClient 0:1f9b2707ec7d 73 /* Codes_SRS_DATA_MARSHALLER_99_024:[ When called with a NULL handle, DataMarshaller_Destroy shall do nothing.] */
AzureIoTClient 0:1f9b2707ec7d 74 if (dataMarshallerHandle != NULL)
AzureIoTClient 0:1f9b2707ec7d 75 {
AzureIoTClient 0:1f9b2707ec7d 76 /* Codes_SRS_DATA_MARSHALLER_99_022:[ DataMarshaller_Destroy shall free all resources associated with the dataMarshallerHandle argument.] */
AzureIoTClient 0:1f9b2707ec7d 77 DATA_MARSHALLER_INSTANCE* dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)dataMarshallerHandle;
AzureIoTClient 0:1f9b2707ec7d 78 free(dataMarshallerInstance);
AzureIoTClient 0:1f9b2707ec7d 79 }
AzureIoTClient 0:1f9b2707ec7d 80 }
AzureIoTClient 0:1f9b2707ec7d 81
AzureIoTClient 0:1f9b2707ec7d 82 DATA_MARSHALLER_RESULT DataMarshaller_SendData(DATA_MARSHALLER_HANDLE dataMarshallerHandle, size_t valueCount, const DATA_MARSHALLER_VALUE* values, unsigned char** destination, size_t* destinationSize)
AzureIoTClient 0:1f9b2707ec7d 83 {
AzureIoTClient 0:1f9b2707ec7d 84 DATA_MARSHALLER_INSTANCE* dataMarshallerInstance = (DATA_MARSHALLER_INSTANCE*)dataMarshallerHandle;
AzureIoTClient 0:1f9b2707ec7d 85 DATA_MARSHALLER_RESULT result;
AzureIoTClient 0:1f9b2707ec7d 86 MULTITREE_HANDLE treeHandle;
AzureIoTClient 0:1f9b2707ec7d 87
AzureIoTClient 0:1f9b2707ec7d 88 /* Codes_SRS_DATA_MARSHALLER_99_034:[All argument checks shall be performed before calling any other modules.] */
AzureIoTClient 0:1f9b2707ec7d 89 /* Codes_SRS_DATA_MARSHALLER_99_004:[ DATA_MARSHALLER_INVALID_ARG shall be returned when the function has detected an invalid parameter (NULL) being passed to the function.] */
AzureIoTClient 0:1f9b2707ec7d 90 if ((values == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 91 (dataMarshallerHandle == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 92 (destination == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 93 (destinationSize == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 94 /* Codes_SRS_DATA_MARSHALLER_99_033:[ DATA_MARSHALLER_INVALID_ARG shall be returned if the valueCount is zero.] */
AzureIoTClient 0:1f9b2707ec7d 95 (valueCount == 0))
AzureIoTClient 0:1f9b2707ec7d 96 {
AzureIoTClient 0:1f9b2707ec7d 97 result = DATA_MARSHALLER_INVALID_ARG;
AzureIoTClient 0:1f9b2707ec7d 98 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 99 }
AzureIoTClient 0:1f9b2707ec7d 100 else
AzureIoTClient 0:1f9b2707ec7d 101 {
AzureIoTClient 0:1f9b2707ec7d 102 size_t i;
AzureIoTClient 5:c08e3ffc68e4 103 bool includePropertyPath = dataMarshallerInstance->IncludePropertyPath;
AzureIoTClient 0:1f9b2707ec7d 104 /* VS complains wrongly that result is not initialized */
AzureIoTClient 0:1f9b2707ec7d 105 result = DATA_MARSHALLER_ERROR;
AzureIoTClient 0:1f9b2707ec7d 106
AzureIoTClient 0:1f9b2707ec7d 107 for (i = 0; i < valueCount; i++)
AzureIoTClient 0:1f9b2707ec7d 108 {
AzureIoTClient 0:1f9b2707ec7d 109 if ((values[i].PropertyPath == NULL) ||
AzureIoTClient 0:1f9b2707ec7d 110 (values[i].Value == NULL))
AzureIoTClient 0:1f9b2707ec7d 111 {
AzureIoTClient 0:1f9b2707ec7d 112 /*Codes_SRS_DATA_MARSHALLER_99_007:[ DATA_MARSHALLER_INVALID_MODEL_PROPERTY shall be returned when any of the items in values contain invalid data]*/
AzureIoTClient 0:1f9b2707ec7d 113 result = DATA_MARSHALLER_INVALID_MODEL_PROPERTY;
AzureIoTClient 0:1f9b2707ec7d 114 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 115 break;
AzureIoTClient 0:1f9b2707ec7d 116 }
AzureIoTClient 0:1f9b2707ec7d 117
AzureIoTClient 0:1f9b2707ec7d 118 if ((!dataMarshallerInstance->IncludePropertyPath) &&
AzureIoTClient 0:1f9b2707ec7d 119 (values[i].Value->type == EDM_COMPLEX_TYPE_TYPE) &&
AzureIoTClient 0:1f9b2707ec7d 120 (valueCount > 1))
AzureIoTClient 0:1f9b2707ec7d 121 {
AzureIoTClient 0:1f9b2707ec7d 122 /* Codes_SRS_DATAMARSHALLER_01_002: [If the includePropertyPath argument passed to DataMarshaller_Create was false and the number of values passed to SendData is greater than 1 and at least one of them is a struct, DataMarshaller_SendData shall fallback to including the complete property path in the output JSON.] */
AzureIoTClient 0:1f9b2707ec7d 123 includePropertyPath = true;
AzureIoTClient 0:1f9b2707ec7d 124 }
AzureIoTClient 0:1f9b2707ec7d 125 }
AzureIoTClient 0:1f9b2707ec7d 126
AzureIoTClient 0:1f9b2707ec7d 127 if (i == valueCount)
AzureIoTClient 0:1f9b2707ec7d 128 {
AzureIoTClient 0:1f9b2707ec7d 129 /* Codes_SRS_DATA_MARSHALLER_99_037:[DataMarshaller shall store as MultiTree the data to be encoded by the JSONEncoder module.] */
AzureIoTClient 0:1f9b2707ec7d 130 if ((treeHandle = MultiTree_Create(NoCloneFunction, NoFreeFunction)) == NULL)
AzureIoTClient 0:1f9b2707ec7d 131 {
AzureIoTClient 0:1f9b2707ec7d 132 /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
AzureIoTClient 0:1f9b2707ec7d 133 result = DATA_MARSHALLER_MULTITREE_ERROR;
AzureIoTClient 0:1f9b2707ec7d 134 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 135 }
AzureIoTClient 0:1f9b2707ec7d 136 else
AzureIoTClient 0:1f9b2707ec7d 137 {
AzureIoTClient 0:1f9b2707ec7d 138 size_t j;
AzureIoTClient 0:1f9b2707ec7d 139 result = DATA_MARSHALLER_OK; /* addressing warning in VS compiler */
AzureIoTClient 0:1f9b2707ec7d 140 /* Codes_SRS_DATA_MARSHALLER_99_038:[For each pair in the values argument, a string : value pair shall exist in the JSON object in the form of propertyName : value.] */
AzureIoTClient 0:1f9b2707ec7d 141 for (j = 0; j < valueCount; j++)
AzureIoTClient 0:1f9b2707ec7d 142 {
AzureIoTClient 0:1f9b2707ec7d 143 if ((includePropertyPath == false) && (values[j].Value->type == EDM_COMPLEX_TYPE_TYPE))
AzureIoTClient 0:1f9b2707ec7d 144 {
AzureIoTClient 0:1f9b2707ec7d 145 size_t k;
AzureIoTClient 0:1f9b2707ec7d 146
AzureIoTClient 0:1f9b2707ec7d 147 /* Codes_SRS_DATAMARSHALLER_01_001: [If the includePropertyPath argument passed to DataMarshaller_Create was false and only one struct is being sent, the relative path of the value passed to DataMarshaller_SendData - including property name - shall be ignored and the value shall be placed at JSON root.] */
AzureIoTClient 0:1f9b2707ec7d 148 for (k = 0; k < values[j].Value->value.edmComplexType.nMembers; k++)
AzureIoTClient 0:1f9b2707ec7d 149 {
AzureIoTClient 0:1f9b2707ec7d 150 /* Codes_SRS_DATAMARSHALLER_01_004: [In this case the members of the struct shall be added as leafs into the MultiTree, each leaf having the name of the struct member.] */
AzureIoTClient 0:1f9b2707ec7d 151 if (MultiTree_AddLeaf(treeHandle, values[j].Value->value.edmComplexType.fields[k].fieldName, (void*)values[j].Value->value.edmComplexType.fields[k].value) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 152 {
AzureIoTClient 0:1f9b2707ec7d 153 break;
AzureIoTClient 0:1f9b2707ec7d 154 }
AzureIoTClient 0:1f9b2707ec7d 155 }
AzureIoTClient 0:1f9b2707ec7d 156
AzureIoTClient 0:1f9b2707ec7d 157 if (k < values[j].Value->value.edmComplexType.nMembers)
AzureIoTClient 0:1f9b2707ec7d 158 {
AzureIoTClient 0:1f9b2707ec7d 159 /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
AzureIoTClient 0:1f9b2707ec7d 160 result = DATA_MARSHALLER_MULTITREE_ERROR;
AzureIoTClient 0:1f9b2707ec7d 161 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 162 break;
AzureIoTClient 0:1f9b2707ec7d 163 }
AzureIoTClient 0:1f9b2707ec7d 164 }
AzureIoTClient 0:1f9b2707ec7d 165 else
AzureIoTClient 0:1f9b2707ec7d 166 {
AzureIoTClient 0:1f9b2707ec7d 167 /* Codes_SRS_DATA_MARSHALLER_99_039:[ If the includePropertyPath argument passed to DataMarshaller_Create was true each property shall be placed in the appropriate position in the JSON according to its path in the model.] */
AzureIoTClient 0:1f9b2707ec7d 168 if (MultiTree_AddLeaf(treeHandle, values[j].PropertyPath, (void*)values[j].Value) != MULTITREE_OK)
AzureIoTClient 0:1f9b2707ec7d 169 {
AzureIoTClient 0:1f9b2707ec7d 170 /* Codes_SRS_DATA_MARSHALLER_99_035:[DATA_MARSHALLER_MULTITREE_ERROR shall be returned in case any MultiTree API call fails.] */
AzureIoTClient 0:1f9b2707ec7d 171 result = DATA_MARSHALLER_MULTITREE_ERROR;
AzureIoTClient 0:1f9b2707ec7d 172 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 173 break;
AzureIoTClient 0:1f9b2707ec7d 174 }
AzureIoTClient 0:1f9b2707ec7d 175 }
AzureIoTClient 0:1f9b2707ec7d 176
AzureIoTClient 0:1f9b2707ec7d 177 }
AzureIoTClient 0:1f9b2707ec7d 178
AzureIoTClient 0:1f9b2707ec7d 179 if (j == valueCount)
AzureIoTClient 0:1f9b2707ec7d 180 {
AzureIoTClient 0:1f9b2707ec7d 181 STRING_HANDLE payload = STRING_new();
AzureIoTClient 0:1f9b2707ec7d 182 if (payload == NULL)
AzureIoTClient 0:1f9b2707ec7d 183 {
AzureIoTClient 0:1f9b2707ec7d 184 result = DATA_MARSHALLER_ERROR;
AzureIoTClient 0:1f9b2707ec7d 185 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 186 }
AzureIoTClient 0:1f9b2707ec7d 187 else
AzureIoTClient 0:1f9b2707ec7d 188 {
AzureIoTClient 0:1f9b2707ec7d 189 if (JSONEncoder_EncodeTree(treeHandle, payload, (JSON_ENCODER_TOSTRING_FUNC)AgentDataTypes_ToString) != JSON_ENCODER_OK)
AzureIoTClient 0:1f9b2707ec7d 190 {
AzureIoTClient 0:1f9b2707ec7d 191 /* Codes_SRS_DATA_MARSHALLER_99_027:[ DATA_MARSHALLER_JSON_ENCODER_ERROR shall be returned when JSONEncoder returns an error code.] */
AzureIoTClient 0:1f9b2707ec7d 192 result = DATA_MARSHALLER_JSON_ENCODER_ERROR;
AzureIoTClient 0:1f9b2707ec7d 193 LOG_DATA_MARSHALLER_ERROR
AzureIoTClient 0:1f9b2707ec7d 194 }
AzureIoTClient 0:1f9b2707ec7d 195 else
AzureIoTClient 0:1f9b2707ec7d 196 {
AzureIoTClient 0:1f9b2707ec7d 197 /*Codes_SRS_DATAMARSHALLER_02_007: [DataMarshaller_SendData shall copy in the output parameters *destination, *destinationSize the content and the content length of the encoded JSON tree.] */
AzureIoTClient 0:1f9b2707ec7d 198 size_t resultSize = STRING_length(payload);
AzureIoTClient 0:1f9b2707ec7d 199 unsigned char* temp = malloc(resultSize);
AzureIoTClient 0:1f9b2707ec7d 200 if (temp == NULL)
AzureIoTClient 0:1f9b2707ec7d 201 {
AzureIoTClient 0:1f9b2707ec7d 202 /*Codes_SRS_DATA_MARSHALLER_99_015:[ DATA_MARSHALLER_ERROR shall be returned in all the other error cases not explicitly defined here.]*/
AzureIoTClient 0:1f9b2707ec7d 203 result = DATA_MARSHALLER_ERROR;
AzureIoTClient 0:1f9b2707ec7d 204 LOG_DATA_MARSHALLER_ERROR;
AzureIoTClient 0:1f9b2707ec7d 205 }
AzureIoTClient 0:1f9b2707ec7d 206 else
AzureIoTClient 0:1f9b2707ec7d 207 {
AzureIoTClient 0:1f9b2707ec7d 208 memcpy(temp, STRING_c_str(payload), resultSize);
AzureIoTClient 0:1f9b2707ec7d 209 *destination = temp;
AzureIoTClient 0:1f9b2707ec7d 210 *destinationSize = resultSize;
AzureIoTClient 0:1f9b2707ec7d 211 result = DATA_MARSHALLER_OK;
AzureIoTClient 0:1f9b2707ec7d 212 }
AzureIoTClient 0:1f9b2707ec7d 213 }
AzureIoTClient 0:1f9b2707ec7d 214 STRING_delete(payload);
AzureIoTClient 0:1f9b2707ec7d 215 }
AzureIoTClient 0:1f9b2707ec7d 216 } /* if (j==valueCount)*/
AzureIoTClient 0:1f9b2707ec7d 217 MultiTree_Destroy(treeHandle);
AzureIoTClient 0:1f9b2707ec7d 218 } /* MultiTree_Create */
AzureIoTClient 0:1f9b2707ec7d 219 }
AzureIoTClient 0:1f9b2707ec7d 220 }
AzureIoTClient 0:1f9b2707ec7d 221
AzureIoTClient 0:1f9b2707ec7d 222 return result;
AzureIoTClient 0:1f9b2707ec7d 223 }