corrected version (with typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;) included in the sources
Dependents: STM32F746_iothub_client_sample_mqtt
Fork of iothub_client by
Diff: iothub_message.c
- Revision:
- 0:e393db310d89
- Child:
- 18:1e9adb15c645
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/iothub_message.c Tue Sep 15 21:47:12 2015 -0700 @@ -0,0 +1,358 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include <stdlib.h> +#ifdef _CRTDBG_MAP_ALLOC +#include <crtdbg.h> +#endif +#include "gballoc.h" + +#include "iothub_message.h" +#include "iot_logging.h" +#include "buffer_.h" + +DEFINE_ENUM_STRINGS(IOTHUB_MESSAGE_RESULT, IOTHUB_MESSAGE_RESULT_VALUES); +DEFINE_ENUM_STRINGS(IOTHUBMESSAGE_CONTENT_TYPE, IOTHUBMESSAGE_CONTENT_TYPE_VALUES); + +#define LOG_IOTHUB_MESSAGE_ERROR() \ + LogError("(result = %s)\r\n", ENUM_TO_STRING(IOTHUB_MESSAGE_RESULT, result)); + +typedef struct IOTHUB_MESSAGE_HANDLE_DATA_TAG +{ + IOTHUBMESSAGE_CONTENT_TYPE contentType; + union + { + BUFFER_HANDLE byteArray; + STRING_HANDLE string; + } value; + MAP_HANDLE properties; +}IOTHUB_MESSAGE_HANDLE_DATA; + +static bool ContainsOnlyUsAscii(const char* asciiValue) +{ + bool result = true;; + const char* iterator = asciiValue; + while (iterator != NULL && *iterator != '\0') + { + // Allow only printable ascii char + if (*iterator < ' ' || *iterator > '~') + { + result = false; + break; + } + iterator++; + } + return result; +} + +/* Codes_SRS_IOTHUBMESSAGE_07_008: [ValidateAsciiCharactersFilter shall loop through the mapKey and mapValue strings to ensure that they only contain valid US-Ascii characters Ascii value 32 - 126.] */ +static int ValidateAsciiCharactersFilter(const char* mapKey, const char* mapValue) +{ + int result; + if (!ContainsOnlyUsAscii(mapKey) || !ContainsOnlyUsAscii(mapValue) ) + { + result = __LINE__; + } + else + { + result = 0; + } + return result; +} + +IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size) +{ + IOTHUB_MESSAGE_HANDLE_DATA* result; + result = malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA)); + if (result == NULL) + { + LogError("unable to malloc\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */ + /*let it go through*/ + } + else + { + const unsigned char* source; + unsigned char temp = 0x00; + if (size != 0) + { + /*Codes_SRS_IOTHUBMESSAGE_06_002: [If size is NOT zero then byteArray MUST NOT be NULL*/ + if (byteArray == NULL) + { + LogError("Attempted to create a Hub Message from a NULL pointer!\r\n"); + free(result); + result = NULL; + source = NULL; + } + else + { + source = byteArray; + } + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_06_001: [If size is zero then byteArray may be NULL.]*/ + source = &temp; + } + if (result != NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_02_022: [IoTHubMessage_CreateFromByteArray shall call BUFFER_create passing byteArray and size as parameters.] */ + if ((result->value.byteArray = BUFFER_create(source, size)) == NULL) + { + LogError("BUFFER_create failed\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */ + free(result); + result = NULL; + } + /*Codes_SRS_IOTHUBMESSAGE_02_023: [IoTHubMessage_CreateFromByteArray shall call Map_Create to create the message properties.] */ + else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL) + { + LogError("Map_Create failed\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */ + BUFFER_delete(result->value.byteArray); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_025: [Otherwise, IoTHubMessage_CreateFromByteArray shall return a non-NULL handle.] */ + /*Codes_SRS_IOTHUBMESSAGE_02_026: [The type of the new message shall be IOTHUBMESSAGE_BYTEARRAY.] */ + result->contentType = IOTHUBMESSAGE_BYTEARRAY; + /*all is fine, return result*/ + } + } + } + return result; +} +IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source) +{ + IOTHUB_MESSAGE_HANDLE_DATA* result; + result = malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA)); + if (result == NULL) + { + LogError("malloc failed\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */ + /*let it go through*/ + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_027: [IoTHubMessage_CreateFromString shall call STRING_construct passing source as parameter.] */ + if ((result->value.string = STRING_construct(source)) == NULL) + { + LogError("STRING_construct failed\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */ + free(result); + result = NULL; + } + /*Codes_SRS_IOTHUBMESSAGE_02_028: [IoTHubMessage_CreateFromString shall call Map_Create to create the message properties.] */ + else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL) + { + LogError("Map_Create failed\r\n"); + /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */ + STRING_delete(result->value.string); + free(result); + result = NULL; + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_031: [Otherwise, IoTHubMessage_CreateFromString shall return a non-NULL handle.] */ + /*Codes_SRS_IOTHUBMESSAGE_02_032: [The type of the new message shall be IOTHUBMESSAGE_STRING.] */ + result->contentType = IOTHUBMESSAGE_STRING; + } + } + return result; +} + +/*Codes_SRS_IOTHUBMESSAGE_03_001: [IoTHubMessage_Clone shall create a new IoT hub message with data content identical to that of the iotHubMessageHandle parameter.]*/ +IOTHUB_MESSAGE_HANDLE IoTHubMessage_Clone(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle) +{ + IOTHUB_MESSAGE_HANDLE_DATA* result; + const IOTHUB_MESSAGE_HANDLE_DATA* source = (const IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle; + /* Codes_SRS_IOTHUBMESSAGE_03_005: [IoTHubMessage_Clone shall return NULL if iotHubMessageHandle is NULL.] */ + if (source == NULL) + { + result = NULL; + LogError("iotHubMessageHandle parameter cannot be NULL for IoTHubMessage_Clone\r\n"); + } + else + { + result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA)); + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + if (result == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + /*do nothing and return as is*/ + LogError("unable to malloc\r\n"); + } + else + { + if (source->contentType == IOTHUBMESSAGE_BYTEARRAY) + { + /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone to content by a call to BUFFER_clone] */ + if ((result->value.byteArray = BUFFER_clone(source->value.byteArray)) == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + LogError("unable to BUFFER_clone\r\n"); + free(result); + result = NULL; + } + /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */ + else if ((result->properties = Map_Clone(source->properties)) == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + LogError("unable to Map_Clone\r\n"); + BUFFER_delete(result->value.byteArray); + free(result); + result = NULL; + } + else + { + result->contentType = IOTHUBMESSAGE_BYTEARRAY; + /*Codes_SRS_IOTHUBMESSAGE_03_002: [IoTHubMessage_Clone shall return upon success a non-NULL handle to the newly created IoT hub message.]*/ + /*return as is, this is a good result*/ + } + } + else /*can only be STRING*/ + { + /*Codes_SRS_IOTHUBMESSAGE_02_006: [IoTHubMessage_Clone shall clone the content by a call to BUFFER_clone or STRING_clone] */ + if ((result->value.string = STRING_clone(source->value.string)) == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + free(result); + result = NULL; + LogError("failed to STRING_clone\r\n"); + } + /*Codes_SRS_IOTHUBMESSAGE_02_005: [IoTHubMessage_Clone shall clone the properties map by using Map_Clone.] */ + else if ((result->properties = Map_Clone(source->properties)) == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_03_004: [IoTHubMessage_Clone shall return NULL if it fails for any reason.]*/ + LogError("unable to Map_Clone\r\n"); + STRING_delete(result->value.string); + free(result); + result = NULL; + } + else + { + result->contentType = IOTHUBMESSAGE_STRING; + /*all is fine*/ + } + } + } + } + return result; +} + +IOTHUB_MESSAGE_RESULT IoTHubMessage_GetByteArray(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const unsigned char** buffer, size_t* size) +{ + IOTHUB_MESSAGE_RESULT result; + if ( + (iotHubMessageHandle == NULL) || + (buffer == NULL) || + (size == NULL) + ) + { + /*Codes_SRS_IOTHUBMESSAGE_01_014: [If any of the arguments passed to IoTHubMessage_GetByteArray is NULL IoTHubMessage_GetByteArray shall return IOTHUBMESSAGE_INVALID_ARG.] */ + LogError("invalid parameter (NULL) to IoTHubMessage_GetByteArray IOTHUB_MESSAGE_HANDLE iotHubMessageHandle=%p, const unsigned char** buffer=%p, size_t* size=%p\r\n", iotHubMessageHandle, buffer, size); + result = IOTHUB_MESSAGE_INVALID_ARG; + } + else + { + IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle; + if (handleData->contentType != IOTHUBMESSAGE_BYTEARRAY) + { + /*Codes_SRS_IOTHUBMESSAGE_02_021: [If iotHubMessageHandle is not a iothubmessage containing BYTEARRAY data, then IoTHubMessage_GetData shall write in *buffer NULL and shall set *size to 0.] */ + result = IOTHUB_MESSAGE_INVALID_ARG; + LogError("invalid type of message %s\r\n", ENUM_TO_STRING(IOTHUBMESSAGE_CONTENT_TYPE, handleData->contentType)); + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_01_011: [The pointer shall be obtained by using BUFFER_u_char and it shall be copied in the buffer argument.]*/ + *buffer = BUFFER_u_char(handleData->value.byteArray); + /*Codes_SRS_IOTHUBMESSAGE_01_012: [The size of the associated data shall be obtained by using BUFFER_length and it shall be copied to the size argument.]*/ + *size = BUFFER_length(handleData->value.byteArray); + result = IOTHUB_MESSAGE_OK; + } + } + return result; +} + +const char* IoTHubMessage_GetString(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle) +{ + const char* result; + if (iotHubMessageHandle == NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_02_016: [If any parameter is NULL then IoTHubMessage_GetString shall return NULL.] */ + result = NULL; + } + else + { + IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle; + if (handleData->contentType != IOTHUBMESSAGE_STRING) + { + /*Codes_SRS_IOTHUBMESSAGE_02_017: [IoTHubMessage_GetString shall return NULL if the iotHubMessageHandle does not refer to a IOTHUBMESSAGE of type STRING.] */ + result = NULL; + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_018: [IoTHubMessage_GetStringData shall return the currently stored null terminated string.] */ + result = STRING_c_str(handleData->value.string); + } + } + return result; +} + +IOTHUBMESSAGE_CONTENT_TYPE IoTHubMessage_GetContentType(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle) +{ + IOTHUBMESSAGE_CONTENT_TYPE result; + /*Codes_SRS_IOTHUBMESSAGE_02_008: [If any parameter is NULL then IoTHubMessage_GetContentType shall return IOTHUBMESSAGE_UNKNOWN.] */ + if (iotHubMessageHandle == NULL) + { + result = IOTHUBMESSAGE_UNKNOWN; + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_009: [Otherwise IoTHubMessage_GetContentType shall return the type of the message.] */ + IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle; + result = handleData->contentType; + } + return result; +} + +MAP_HANDLE IoTHubMessage_Properties(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle) +{ + MAP_HANDLE result; + /*Codes_SRS_IOTHUBMESSAGE_02_001: [If iotHubMessageHandle is NULL then IoTHubMessage_Properties shall return NULL.]*/ + if (iotHubMessageHandle == NULL) + { + LogError("invalid arg (NULL) passed to IoTHubMessage_Properties\r\n") + result = NULL; + } + else + { + /*Codes_SRS_IOTHUBMESSAGE_02_002: [Otherwise, for any non-NULL iotHubMessageHandle it shall return a non-NULL MAP_HANDLE.]*/ + IOTHUB_MESSAGE_HANDLE_DATA* handleData = (IOTHUB_MESSAGE_HANDLE_DATA*)iotHubMessageHandle; + result = handleData->properties; + } + return result; +} + +void IoTHubMessage_Destroy(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle) +{ + /*Codes_SRS_IOTHUBMESSAGE_01_004: [If iotHubMessageHandle is NULL, IoTHubMessage_Destroy shall do nothing.] */ + if (iotHubMessageHandle != NULL) + { + /*Codes_SRS_IOTHUBMESSAGE_01_003: [IoTHubMessage_Destroy shall free all resources associated with iotHubMessageHandle.] */ + IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle; + if (handleData->contentType == IOTHUBMESSAGE_BYTEARRAY) + { + BUFFER_delete(handleData->value.byteArray); + } + else + { + /*can only be STRING*/ + STRING_delete(handleData->value.string); + } + Map_Destroy(handleData->properties); + free(handleData); + } +} \ No newline at end of file