Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:14:47 2018 -0700
Revision:
57:56ac1346c70d
Parent:
56:8704100b3b54
1.2.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 39:e98d5df6dc74 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 39:e98d5df6dc74 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 39:e98d5df6dc74 3
AzureIoTClient 39:e98d5df6dc74 4 #include <stdlib.h>
AzureIoTClient 39:e98d5df6dc74 5 #include <stdbool.h>
AzureIoTClient 39:e98d5df6dc74 6 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 39:e98d5df6dc74 7 #include "azure_c_shared_utility/crt_abstractions.h"
AzureIoTClient 39:e98d5df6dc74 8 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 56:8704100b3b54 9 #include "azure_c_shared_utility/agenttime.h"
AzureIoTClient 39:e98d5df6dc74 10 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 39:e98d5df6dc74 11 #include "azure_c_shared_utility/singlylinkedlist.h"
AzureIoTClient 39:e98d5df6dc74 12
AzureIoTClient 39:e98d5df6dc74 13 typedef struct MESSAGE_QUEUE_TAG MESSAGE_QUEUE;
AzureIoTClient 39:e98d5df6dc74 14
AzureIoTClient 53:e21e1e88460f 15 #include "internal/message_queue.h"
AzureIoTClient 39:e98d5df6dc74 16
AzureIoTClient 39:e98d5df6dc74 17 #define RESULT_OK 0
AzureIoTClient 39:e98d5df6dc74 18 #define INDEFINITE_TIME ((time_t)(-1))
AzureIoTClient 39:e98d5df6dc74 19
AzureIoTClient 39:e98d5df6dc74 20 static const char* SAVED_OPTION_MAX_RETRY_COUNT = "SAVED_OPTION_MAX_RETRY_COUNT";
AzureIoTClient 39:e98d5df6dc74 21 static const char* SAVED_OPTION_MAX_ENQUEUE_TIME_SECS = "SAVED_OPTION_MAX_ENQUEUE_TIME_SECS";
AzureIoTClient 39:e98d5df6dc74 22 static const char* SAVED_OPTION_MAX_PROCESSING_TIME_SECS = "SAVED_OPTION_MAX_PROCESSING_TIME_SECS";
AzureIoTClient 39:e98d5df6dc74 23
AzureIoTClient 39:e98d5df6dc74 24
AzureIoTClient 39:e98d5df6dc74 25 struct MESSAGE_QUEUE_TAG
AzureIoTClient 39:e98d5df6dc74 26 {
AzureIoTClient 39:e98d5df6dc74 27 size_t max_message_enqueued_time_secs;
AzureIoTClient 39:e98d5df6dc74 28 size_t max_message_processing_time_secs;
AzureIoTClient 39:e98d5df6dc74 29 size_t max_retry_count;
AzureIoTClient 39:e98d5df6dc74 30
AzureIoTClient 39:e98d5df6dc74 31 PROCESS_MESSAGE_CALLBACK on_process_message_callback;
AzureIoTClient 39:e98d5df6dc74 32 void* on_process_message_context;
AzureIoTClient 39:e98d5df6dc74 33
AzureIoTClient 39:e98d5df6dc74 34 SINGLYLINKEDLIST_HANDLE pending;
AzureIoTClient 39:e98d5df6dc74 35 SINGLYLINKEDLIST_HANDLE in_progress;
AzureIoTClient 39:e98d5df6dc74 36 };
AzureIoTClient 39:e98d5df6dc74 37
AzureIoTClient 39:e98d5df6dc74 38 typedef struct MESSAGE_QUEUE_ITEM_TAG
AzureIoTClient 39:e98d5df6dc74 39 {
AzureIoTClient 39:e98d5df6dc74 40 MQ_MESSAGE_HANDLE message;
AzureIoTClient 39:e98d5df6dc74 41 MESSAGE_PROCESSING_COMPLETED_CALLBACK on_message_processing_completed_callback;
AzureIoTClient 39:e98d5df6dc74 42 void* user_context;
AzureIoTClient 39:e98d5df6dc74 43 time_t enqueue_time;
AzureIoTClient 39:e98d5df6dc74 44 time_t processing_start_time;
AzureIoTClient 39:e98d5df6dc74 45 size_t number_of_attempts;
AzureIoTClient 39:e98d5df6dc74 46 } MESSAGE_QUEUE_ITEM;
AzureIoTClient 39:e98d5df6dc74 47
AzureIoTClient 39:e98d5df6dc74 48
AzureIoTClient 39:e98d5df6dc74 49
AzureIoTClient 39:e98d5df6dc74 50 // ---------- Helper Functions ---------- //
AzureIoTClient 39:e98d5df6dc74 51
AzureIoTClient 39:e98d5df6dc74 52 static bool find_item_by_message_ptr(LIST_ITEM_HANDLE list_item, const void* match_context)
AzureIoTClient 39:e98d5df6dc74 53 {
AzureIoTClient 39:e98d5df6dc74 54 MESSAGE_QUEUE_ITEM* current_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 39:e98d5df6dc74 55 MQ_MESSAGE_HANDLE* target_item = (MQ_MESSAGE_HANDLE*)match_context;
AzureIoTClient 39:e98d5df6dc74 56
AzureIoTClient 39:e98d5df6dc74 57 return (current_item->message == target_item);
AzureIoTClient 39:e98d5df6dc74 58 }
AzureIoTClient 39:e98d5df6dc74 59
AzureIoTClient 39:e98d5df6dc74 60 static void fire_message_callback(MESSAGE_QUEUE_ITEM* mq_item, MESSAGE_QUEUE_RESULT result, void* reason)
AzureIoTClient 39:e98d5df6dc74 61 {
AzureIoTClient 39:e98d5df6dc74 62 if (mq_item->on_message_processing_completed_callback != NULL)
AzureIoTClient 39:e98d5df6dc74 63 {
AzureIoTClient 39:e98d5df6dc74 64 if (result == MESSAGE_QUEUE_RETRYABLE_ERROR)
AzureIoTClient 39:e98d5df6dc74 65 {
AzureIoTClient 39:e98d5df6dc74 66 result = MESSAGE_QUEUE_ERROR;
AzureIoTClient 39:e98d5df6dc74 67 }
AzureIoTClient 39:e98d5df6dc74 68
AzureIoTClient 39:e98d5df6dc74 69 mq_item->on_message_processing_completed_callback(mq_item->message, result, reason, mq_item->user_context);
AzureIoTClient 39:e98d5df6dc74 70 }
AzureIoTClient 39:e98d5df6dc74 71 }
AzureIoTClient 39:e98d5df6dc74 72
AzureIoTClient 39:e98d5df6dc74 73 static bool should_retry_sending(MESSAGE_QUEUE_HANDLE message_queue, MESSAGE_QUEUE_ITEM* mq_item, MESSAGE_QUEUE_RESULT result)
AzureIoTClient 39:e98d5df6dc74 74 {
AzureIoTClient 39:e98d5df6dc74 75 return (result == MESSAGE_QUEUE_RETRYABLE_ERROR && mq_item->number_of_attempts <= message_queue->max_retry_count);
AzureIoTClient 39:e98d5df6dc74 76 }
AzureIoTClient 39:e98d5df6dc74 77
AzureIoTClient 39:e98d5df6dc74 78 static int retry_sending_message(MESSAGE_QUEUE_HANDLE message_queue, LIST_ITEM_HANDLE list_item)
AzureIoTClient 39:e98d5df6dc74 79 {
AzureIoTClient 39:e98d5df6dc74 80 int result;
AzureIoTClient 39:e98d5df6dc74 81 MESSAGE_QUEUE_ITEM* mq_item;
AzureIoTClient 56:8704100b3b54 82
AzureIoTClient 39:e98d5df6dc74 83 mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 39:e98d5df6dc74 84
AzureIoTClient 39:e98d5df6dc74 85 if (singlylinkedlist_remove(message_queue->in_progress, list_item))
AzureIoTClient 39:e98d5df6dc74 86 {
AzureIoTClient 39:e98d5df6dc74 87 LogError("Failed removing message from in-progress list");
AzureIoTClient 39:e98d5df6dc74 88 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 89 }
AzureIoTClient 39:e98d5df6dc74 90 else if (singlylinkedlist_add(message_queue->pending, (const void*)mq_item) == NULL)
AzureIoTClient 39:e98d5df6dc74 91 {
AzureIoTClient 39:e98d5df6dc74 92 LogError("Failed moving message back to pending list");
AzureIoTClient 39:e98d5df6dc74 93 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 94 }
AzureIoTClient 39:e98d5df6dc74 95 else
AzureIoTClient 39:e98d5df6dc74 96 {
AzureIoTClient 39:e98d5df6dc74 97 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 98 }
AzureIoTClient 39:e98d5df6dc74 99
AzureIoTClient 39:e98d5df6dc74 100 return result;
AzureIoTClient 39:e98d5df6dc74 101 }
AzureIoTClient 39:e98d5df6dc74 102
AzureIoTClient 39:e98d5df6dc74 103 static void dequeue_message_and_fire_callback(SINGLYLINKEDLIST_HANDLE list, LIST_ITEM_HANDLE list_item, MESSAGE_QUEUE_RESULT result, void* reason)
AzureIoTClient 39:e98d5df6dc74 104 {
AzureIoTClient 39:e98d5df6dc74 105 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 39:e98d5df6dc74 106
AzureIoTClient 39:e98d5df6dc74 107 // Codes_SRS_MESSAGE_QUEUE_09_045: [If `message` is present in `message_queue->in_progress`, it shall be removed]
AzureIoTClient 39:e98d5df6dc74 108 if (singlylinkedlist_remove(list, list_item))
AzureIoTClient 39:e98d5df6dc74 109 {
AzureIoTClient 39:e98d5df6dc74 110 LogError("failed removing message from list (%p)", list);
AzureIoTClient 39:e98d5df6dc74 111 }
AzureIoTClient 56:8704100b3b54 112
AzureIoTClient 39:e98d5df6dc74 113 // Codes_SRS_MESSAGE_QUEUE_09_049: [Otherwise `mq_item->on_message_processing_completed_callback` shall be invoked passing `mq_item->message`, `result`, `reason` and `mq_item->user_context`]
AzureIoTClient 39:e98d5df6dc74 114 fire_message_callback(mq_item, result, reason);
AzureIoTClient 39:e98d5df6dc74 115
AzureIoTClient 39:e98d5df6dc74 116 // Codes_SRS_MESSAGE_QUEUE_09_050: [The `mq_item` related to `message` shall be freed]
AzureIoTClient 39:e98d5df6dc74 117 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 118 }
AzureIoTClient 39:e98d5df6dc74 119
AzureIoTClient 39:e98d5df6dc74 120 static void on_process_message_completed_callback(MESSAGE_QUEUE_HANDLE message_queue, MQ_MESSAGE_HANDLE message, MESSAGE_QUEUE_RESULT result, USER_DEFINED_REASON reason)
AzureIoTClient 39:e98d5df6dc74 121 {
AzureIoTClient 39:e98d5df6dc74 122 // Codes_SRS_MESSAGE_QUEUE_09_069: [If `message` or `message_queue` are NULL, on_message_processing_completed_callback shall return immediately]
AzureIoTClient 39:e98d5df6dc74 123 if (message == NULL || message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 124 {
AzureIoTClient 39:e98d5df6dc74 125 LogError("on_process_message_completed_callback invoked with NULL arguments (message=%p, message_queue=%p)", message, message_queue);
AzureIoTClient 39:e98d5df6dc74 126 }
AzureIoTClient 39:e98d5df6dc74 127 else
AzureIoTClient 39:e98d5df6dc74 128 {
AzureIoTClient 39:e98d5df6dc74 129 LIST_ITEM_HANDLE list_item;
AzureIoTClient 56:8704100b3b54 130
AzureIoTClient 39:e98d5df6dc74 131 if ((list_item = singlylinkedlist_find(message_queue->in_progress, find_item_by_message_ptr, message)) == NULL)
AzureIoTClient 39:e98d5df6dc74 132 {
AzureIoTClient 39:e98d5df6dc74 133 // Codes_SRS_MESSAGE_QUEUE_09_044: [If `message` is not present in `message_queue->in_progress`, it shall be ignored]
AzureIoTClient 39:e98d5df6dc74 134 LogError("on_process_message_completed_callback invoked for a message not in the in-progress list (%p)", message);
AzureIoTClient 39:e98d5df6dc74 135 }
AzureIoTClient 39:e98d5df6dc74 136 else
AzureIoTClient 39:e98d5df6dc74 137 {
AzureIoTClient 39:e98d5df6dc74 138 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 56:8704100b3b54 139
AzureIoTClient 39:e98d5df6dc74 140 // Codes_SRS_MESSAGE_QUEUE_09_047: [If `result` is MESSAGE_QUEUE_RETRYABLE_ERROR and `mq_item->number_of_attempts` is less than or equal `message_queue->max_retry_count`, the `message` shall be moved to `message_queue->pending` to be re-sent]
AzureIoTClient 39:e98d5df6dc74 141 // Codes_SRS_MESSAGE_QUEUE_09_048: [If `result` is MESSAGE_QUEUE_RETRYABLE_ERROR and `mq_item->number_of_attempts` is greater than `message_queue->max_retry_count`, result shall be changed to MESSAGE_QUEUE_ERROR]
AzureIoTClient 39:e98d5df6dc74 142 if (!should_retry_sending(message_queue, mq_item, result) || retry_sending_message(message_queue, list_item) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 143 {
AzureIoTClient 39:e98d5df6dc74 144 dequeue_message_and_fire_callback(message_queue->in_progress, list_item, result, reason);
AzureIoTClient 39:e98d5df6dc74 145 }
AzureIoTClient 39:e98d5df6dc74 146 }
AzureIoTClient 39:e98d5df6dc74 147 }
AzureIoTClient 39:e98d5df6dc74 148 }
AzureIoTClient 39:e98d5df6dc74 149
AzureIoTClient 39:e98d5df6dc74 150 static void process_timeouts(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 151 {
AzureIoTClient 39:e98d5df6dc74 152 time_t current_time;
AzureIoTClient 39:e98d5df6dc74 153
AzureIoTClient 39:e98d5df6dc74 154 if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 39:e98d5df6dc74 155 {
AzureIoTClient 39:e98d5df6dc74 156 LogError("failed processing timeouts (get_time failed)");
AzureIoTClient 39:e98d5df6dc74 157 }
AzureIoTClient 39:e98d5df6dc74 158 else
AzureIoTClient 39:e98d5df6dc74 159 {
AzureIoTClient 39:e98d5df6dc74 160 // Codes_SRS_MESSAGE_QUEUE_09_035: [If `message_queue->max_message_enqueued_time_secs` is greater than zero, `message_queue->in_progress` and `message_queue->pending` items shall be checked for timeout]
AzureIoTClient 39:e98d5df6dc74 161 if (message_queue->max_message_enqueued_time_secs > 0)
AzureIoTClient 39:e98d5df6dc74 162 {
AzureIoTClient 39:e98d5df6dc74 163 LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(message_queue->pending);
AzureIoTClient 39:e98d5df6dc74 164
AzureIoTClient 39:e98d5df6dc74 165 while (list_item != NULL)
AzureIoTClient 39:e98d5df6dc74 166 {
AzureIoTClient 39:e98d5df6dc74 167 LIST_ITEM_HANDLE current_list_item = list_item;
AzureIoTClient 39:e98d5df6dc74 168 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item);
AzureIoTClient 39:e98d5df6dc74 169
AzureIoTClient 39:e98d5df6dc74 170 list_item = singlylinkedlist_get_next_item(list_item);
AzureIoTClient 39:e98d5df6dc74 171
AzureIoTClient 39:e98d5df6dc74 172 if (mq_item == NULL)
AzureIoTClient 39:e98d5df6dc74 173 {
AzureIoTClient 39:e98d5df6dc74 174 LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)");
AzureIoTClient 39:e98d5df6dc74 175 }
AzureIoTClient 39:e98d5df6dc74 176 else if (get_difftime(current_time, mq_item->enqueue_time) >= message_queue->max_message_enqueued_time_secs)
AzureIoTClient 39:e98d5df6dc74 177 {
AzureIoTClient 39:e98d5df6dc74 178 // Codes_SRS_MESSAGE_QUEUE_09_036: [If any items are in `message_queue` lists for `message_queue->max_message_enqueued_time_secs` or more, they shall be removed and `message_queue->on_message_processing_completed_callback` invoked with MESSAGE_QUEUE_TIMEOUT]
AzureIoTClient 39:e98d5df6dc74 179 dequeue_message_and_fire_callback(message_queue->pending, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL);
AzureIoTClient 39:e98d5df6dc74 180 }
AzureIoTClient 39:e98d5df6dc74 181 else
AzureIoTClient 39:e98d5df6dc74 182 {
AzureIoTClient 39:e98d5df6dc74 183 // The pending list order is already based on enqueue time, so if one message is not expired, later ones won't be either.
AzureIoTClient 39:e98d5df6dc74 184 break;
AzureIoTClient 39:e98d5df6dc74 185 }
AzureIoTClient 39:e98d5df6dc74 186 }
AzureIoTClient 39:e98d5df6dc74 187
AzureIoTClient 39:e98d5df6dc74 188 list_item = singlylinkedlist_get_head_item(message_queue->in_progress);
AzureIoTClient 39:e98d5df6dc74 189
AzureIoTClient 39:e98d5df6dc74 190 while (list_item != NULL)
AzureIoTClient 39:e98d5df6dc74 191 {
AzureIoTClient 39:e98d5df6dc74 192 LIST_ITEM_HANDLE current_list_item = list_item;
AzureIoTClient 39:e98d5df6dc74 193 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item);
AzureIoTClient 39:e98d5df6dc74 194
AzureIoTClient 39:e98d5df6dc74 195 list_item = singlylinkedlist_get_next_item(list_item);
AzureIoTClient 39:e98d5df6dc74 196
AzureIoTClient 39:e98d5df6dc74 197 if (mq_item == NULL)
AzureIoTClient 39:e98d5df6dc74 198 {
AzureIoTClient 39:e98d5df6dc74 199 LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)");
AzureIoTClient 39:e98d5df6dc74 200 }
AzureIoTClient 39:e98d5df6dc74 201 else if (get_difftime(current_time, mq_item->enqueue_time) >= message_queue->max_message_enqueued_time_secs)
AzureIoTClient 39:e98d5df6dc74 202 {
AzureIoTClient 39:e98d5df6dc74 203 // Codes_SRS_MESSAGE_QUEUE_09_038: [If any items are in `message_queue->in_progress` for `message_queue->max_message_processing_time_secs` or more, they shall be removed and `message_queue->on_message_processing_completed_callback` invoked with MESSAGE_QUEUE_TIMEOUT]
AzureIoTClient 39:e98d5df6dc74 204 dequeue_message_and_fire_callback(message_queue->in_progress, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL);
AzureIoTClient 39:e98d5df6dc74 205 }
AzureIoTClient 39:e98d5df6dc74 206 }
AzureIoTClient 39:e98d5df6dc74 207 }
AzureIoTClient 39:e98d5df6dc74 208
AzureIoTClient 39:e98d5df6dc74 209 // Codes_SRS_MESSAGE_QUEUE_09_037: [If `message_queue->max_message_processing_time_secs` is greater than zero, `message_queue->in_progress` items shall be checked for timeout]
AzureIoTClient 39:e98d5df6dc74 210 if (message_queue->max_message_processing_time_secs > 0)
AzureIoTClient 39:e98d5df6dc74 211 {
AzureIoTClient 39:e98d5df6dc74 212 LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(message_queue->in_progress);
AzureIoTClient 39:e98d5df6dc74 213
AzureIoTClient 39:e98d5df6dc74 214 while (list_item != NULL)
AzureIoTClient 39:e98d5df6dc74 215 {
AzureIoTClient 39:e98d5df6dc74 216 LIST_ITEM_HANDLE current_list_item = list_item;
AzureIoTClient 39:e98d5df6dc74 217 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(current_list_item);
AzureIoTClient 39:e98d5df6dc74 218
AzureIoTClient 39:e98d5df6dc74 219 list_item = singlylinkedlist_get_next_item(list_item);
AzureIoTClient 39:e98d5df6dc74 220
AzureIoTClient 39:e98d5df6dc74 221 if (mq_item == NULL)
AzureIoTClient 39:e98d5df6dc74 222 {
AzureIoTClient 39:e98d5df6dc74 223 LogError("failed processing timeouts (unexpected NULL pointer to MESSAGE_QUEUE_ITEM)");
AzureIoTClient 39:e98d5df6dc74 224 }
AzureIoTClient 39:e98d5df6dc74 225 else if (get_difftime(current_time, mq_item->processing_start_time) >= message_queue->max_message_processing_time_secs)
AzureIoTClient 39:e98d5df6dc74 226 {
AzureIoTClient 39:e98d5df6dc74 227 dequeue_message_and_fire_callback(message_queue->in_progress, current_list_item, MESSAGE_QUEUE_TIMEOUT, NULL);
AzureIoTClient 39:e98d5df6dc74 228 }
AzureIoTClient 39:e98d5df6dc74 229 else
AzureIoTClient 39:e98d5df6dc74 230 {
AzureIoTClient 39:e98d5df6dc74 231 // The in-progress list order is already based on start-processing time, so if one message is not expired, later ones won't be either.
AzureIoTClient 39:e98d5df6dc74 232 break;
AzureIoTClient 39:e98d5df6dc74 233 }
AzureIoTClient 39:e98d5df6dc74 234 }
AzureIoTClient 39:e98d5df6dc74 235 }
AzureIoTClient 39:e98d5df6dc74 236 }
AzureIoTClient 39:e98d5df6dc74 237 }
AzureIoTClient 39:e98d5df6dc74 238
AzureIoTClient 39:e98d5df6dc74 239 static void process_pending_messages(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 240 {
AzureIoTClient 39:e98d5df6dc74 241 LIST_ITEM_HANDLE list_item;
AzureIoTClient 39:e98d5df6dc74 242
AzureIoTClient 39:e98d5df6dc74 243 while ((list_item = singlylinkedlist_get_head_item(message_queue->pending)) != NULL)
AzureIoTClient 39:e98d5df6dc74 244 {
AzureIoTClient 39:e98d5df6dc74 245 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 39:e98d5df6dc74 246
AzureIoTClient 39:e98d5df6dc74 247 if (mq_item == NULL)
AzureIoTClient 39:e98d5df6dc74 248 {
AzureIoTClient 39:e98d5df6dc74 249 LogError("internal error, failed to retrieve list node value");
AzureIoTClient 39:e98d5df6dc74 250 break;
AzureIoTClient 39:e98d5df6dc74 251 }
AzureIoTClient 39:e98d5df6dc74 252 else if (singlylinkedlist_remove(message_queue->pending, list_item) != 0)
AzureIoTClient 39:e98d5df6dc74 253 {
AzureIoTClient 39:e98d5df6dc74 254 LogError("failed moving message out of pending list (%p)", mq_item->message);
AzureIoTClient 39:e98d5df6dc74 255
AzureIoTClient 39:e98d5df6dc74 256 // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed]
AzureIoTClient 39:e98d5df6dc74 257 if (mq_item->on_message_processing_completed_callback != NULL)
AzureIoTClient 39:e98d5df6dc74 258 {
AzureIoTClient 39:e98d5df6dc74 259 mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context);
AzureIoTClient 39:e98d5df6dc74 260 }
AzureIoTClient 39:e98d5df6dc74 261
AzureIoTClient 39:e98d5df6dc74 262 // Not freeing since this would cause a memory A/V on the next call.
AzureIoTClient 39:e98d5df6dc74 263
AzureIoTClient 39:e98d5df6dc74 264 break; // Trying to avoid an infinite loop
AzureIoTClient 39:e98d5df6dc74 265 }
AzureIoTClient 39:e98d5df6dc74 266 // Codes_SRS_MESSAGE_QUEUE_09_040: [`mq_item->processing_start_time` shall be set using get_time()]
AzureIoTClient 39:e98d5df6dc74 267 else if ((mq_item->processing_start_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 39:e98d5df6dc74 268 {
AzureIoTClient 39:e98d5df6dc74 269 // Codes_SRS_MESSAGE_QUEUE_09_041: [If get_time() fails, `mq_item` shall be removed from `message_queue->in_progress`]
AzureIoTClient 39:e98d5df6dc74 270 LogError("failed setting message processing_start_time (%p)", mq_item->message);
AzureIoTClient 39:e98d5df6dc74 271
AzureIoTClient 39:e98d5df6dc74 272 // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed]
AzureIoTClient 39:e98d5df6dc74 273 if (mq_item->on_message_processing_completed_callback != NULL)
AzureIoTClient 39:e98d5df6dc74 274 {
AzureIoTClient 39:e98d5df6dc74 275 mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context);
AzureIoTClient 39:e98d5df6dc74 276 }
AzureIoTClient 39:e98d5df6dc74 277
AzureIoTClient 39:e98d5df6dc74 278 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 279 }
AzureIoTClient 39:e98d5df6dc74 280 // Codes_SRS_MESSAGE_QUEUE_09_039: [Each `mq_item` in `message_queue->pending` shall be moved to `message_queue->in_progress`]
AzureIoTClient 39:e98d5df6dc74 281 else if (singlylinkedlist_add(message_queue->in_progress, (const void*)mq_item) == NULL)
AzureIoTClient 39:e98d5df6dc74 282 {
AzureIoTClient 39:e98d5df6dc74 283 LogError("failed moving message to in-progress list (%p)", mq_item->message);
AzureIoTClient 39:e98d5df6dc74 284
AzureIoTClient 39:e98d5df6dc74 285 // Codes_SRS_MESSAGE_QUEUE_09_042: [If any failures occur, `mq_item->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_ERROR and `mq_item` freed]
AzureIoTClient 39:e98d5df6dc74 286 if (mq_item->on_message_processing_completed_callback != NULL)
AzureIoTClient 39:e98d5df6dc74 287 {
AzureIoTClient 39:e98d5df6dc74 288 mq_item->on_message_processing_completed_callback(mq_item->message, MESSAGE_QUEUE_ERROR, NULL, mq_item->user_context);
AzureIoTClient 39:e98d5df6dc74 289 }
AzureIoTClient 39:e98d5df6dc74 290
AzureIoTClient 39:e98d5df6dc74 291 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 292 }
AzureIoTClient 39:e98d5df6dc74 293 else
AzureIoTClient 39:e98d5df6dc74 294 {
AzureIoTClient 39:e98d5df6dc74 295 mq_item->number_of_attempts++;
AzureIoTClient 39:e98d5df6dc74 296
AzureIoTClient 39:e98d5df6dc74 297 // Codes_SRS_MESSAGE_QUEUE_09_043: [If no failures occur, `message_queue->on_process_message_callback` shall be invoked passing `mq_item->message` and `on_process_message_completed_callback`]
AzureIoTClient 39:e98d5df6dc74 298 message_queue->on_process_message_callback(message_queue, mq_item->message, on_process_message_completed_callback, mq_item->user_context);
AzureIoTClient 39:e98d5df6dc74 299 }
AzureIoTClient 39:e98d5df6dc74 300 }
AzureIoTClient 39:e98d5df6dc74 301 }
AzureIoTClient 39:e98d5df6dc74 302
AzureIoTClient 39:e98d5df6dc74 303 static void* cloneOption(const char* name, const void* value)
AzureIoTClient 39:e98d5df6dc74 304 {
AzureIoTClient 39:e98d5df6dc74 305 void* result;
AzureIoTClient 39:e98d5df6dc74 306
AzureIoTClient 39:e98d5df6dc74 307 if (name == NULL || value == NULL)
AzureIoTClient 39:e98d5df6dc74 308 {
AzureIoTClient 39:e98d5df6dc74 309 LogError("invalid argument (name=%p, value=%p)", name, value);
AzureIoTClient 39:e98d5df6dc74 310 result = NULL;
AzureIoTClient 39:e98d5df6dc74 311 }
AzureIoTClient 56:8704100b3b54 312 else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0 ||
AzureIoTClient 56:8704100b3b54 313 strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0 ||
AzureIoTClient 39:e98d5df6dc74 314 strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0)
AzureIoTClient 39:e98d5df6dc74 315 {
AzureIoTClient 39:e98d5df6dc74 316 if ((result = malloc(sizeof(size_t))) == NULL)
AzureIoTClient 39:e98d5df6dc74 317 {
AzureIoTClient 39:e98d5df6dc74 318 LogError("failed cloning option %s (malloc failed)", name);
AzureIoTClient 39:e98d5df6dc74 319 }
AzureIoTClient 39:e98d5df6dc74 320 else
AzureIoTClient 39:e98d5df6dc74 321 {
AzureIoTClient 39:e98d5df6dc74 322 memcpy(result, value, sizeof(size_t));
AzureIoTClient 39:e98d5df6dc74 323 }
AzureIoTClient 39:e98d5df6dc74 324 }
AzureIoTClient 39:e98d5df6dc74 325 else
AzureIoTClient 39:e98d5df6dc74 326 {
AzureIoTClient 39:e98d5df6dc74 327 LogError("option %s is invalid", name);
AzureIoTClient 39:e98d5df6dc74 328 result = NULL;
AzureIoTClient 39:e98d5df6dc74 329 }
AzureIoTClient 39:e98d5df6dc74 330
AzureIoTClient 39:e98d5df6dc74 331 return result;
AzureIoTClient 39:e98d5df6dc74 332 }
AzureIoTClient 39:e98d5df6dc74 333
AzureIoTClient 39:e98d5df6dc74 334 static void destroyOption(const char* name, const void* value)
AzureIoTClient 39:e98d5df6dc74 335 {
AzureIoTClient 39:e98d5df6dc74 336 if (name == NULL || value == NULL)
AzureIoTClient 39:e98d5df6dc74 337 {
AzureIoTClient 39:e98d5df6dc74 338 LogError("invalid argument (name=%p, value=%p)", name, value);
AzureIoTClient 39:e98d5df6dc74 339 }
AzureIoTClient 56:8704100b3b54 340 else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0 ||
AzureIoTClient 56:8704100b3b54 341 strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0 ||
AzureIoTClient 39:e98d5df6dc74 342 strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0)
AzureIoTClient 39:e98d5df6dc74 343 {
AzureIoTClient 39:e98d5df6dc74 344 free((void*)value);
AzureIoTClient 39:e98d5df6dc74 345 }
AzureIoTClient 39:e98d5df6dc74 346 else
AzureIoTClient 39:e98d5df6dc74 347 {
AzureIoTClient 39:e98d5df6dc74 348 LogError("option %s is invalid", name);
AzureIoTClient 39:e98d5df6dc74 349 }
AzureIoTClient 39:e98d5df6dc74 350 }
AzureIoTClient 39:e98d5df6dc74 351
AzureIoTClient 39:e98d5df6dc74 352
AzureIoTClient 39:e98d5df6dc74 353
AzureIoTClient 39:e98d5df6dc74 354 // ---------- Public APIs ---------- //
AzureIoTClient 39:e98d5df6dc74 355
AzureIoTClient 39:e98d5df6dc74 356 void message_queue_remove_all(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 357 {
AzureIoTClient 39:e98d5df6dc74 358 // Codes_SRS_MESSAGE_QUEUE_09_026: [If `message_queue` is NULL, message_queue_retrieve_options shall return]
AzureIoTClient 39:e98d5df6dc74 359 if (message_queue != NULL)
AzureIoTClient 39:e98d5df6dc74 360 {
AzureIoTClient 39:e98d5df6dc74 361 LIST_ITEM_HANDLE list_item;
AzureIoTClient 39:e98d5df6dc74 362
AzureIoTClient 56:8704100b3b54 363 // Codes_SRS_MESSAGE_QUEUE_09_027: [Each `mq_item` in `message_queue->pending` and `message_queue->in_progress` lists shall be removed]
AzureIoTClient 39:e98d5df6dc74 364 while ((list_item = singlylinkedlist_get_head_item(message_queue->in_progress)) != NULL)
AzureIoTClient 39:e98d5df6dc74 365 {
AzureIoTClient 39:e98d5df6dc74 366 // Codes_SRS_MESSAGE_QUEUE_09_028: [`message_queue->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_CANCELLED for each `mq_item` removed]
AzureIoTClient 56:8704100b3b54 367 // Codes_SRS_MESSAGE_QUEUE_09_029: [Each `mq_item` shall be freed]
AzureIoTClient 39:e98d5df6dc74 368 dequeue_message_and_fire_callback(message_queue->in_progress, list_item, MESSAGE_QUEUE_CANCELLED, NULL);
AzureIoTClient 39:e98d5df6dc74 369 }
AzureIoTClient 39:e98d5df6dc74 370
AzureIoTClient 39:e98d5df6dc74 371 while ((list_item = singlylinkedlist_get_head_item(message_queue->pending)) != NULL)
AzureIoTClient 39:e98d5df6dc74 372 {
AzureIoTClient 39:e98d5df6dc74 373 // Codes_SRS_MESSAGE_QUEUE_09_028: [`message_queue->on_message_processing_completed_callback` shall be invoked with MESSAGE_QUEUE_CANCELLED for each `mq_item` removed]
AzureIoTClient 56:8704100b3b54 374 // Codes_SRS_MESSAGE_QUEUE_09_029: [Each `mq_item` shall be freed]
AzureIoTClient 39:e98d5df6dc74 375 dequeue_message_and_fire_callback(message_queue->pending, list_item, MESSAGE_QUEUE_CANCELLED, NULL);
AzureIoTClient 39:e98d5df6dc74 376 }
AzureIoTClient 39:e98d5df6dc74 377 }
AzureIoTClient 39:e98d5df6dc74 378 }
AzureIoTClient 39:e98d5df6dc74 379
AzureIoTClient 39:e98d5df6dc74 380 static int move_messages_between_lists(SINGLYLINKEDLIST_HANDLE from_list, SINGLYLINKEDLIST_HANDLE to_list)
AzureIoTClient 39:e98d5df6dc74 381 {
AzureIoTClient 39:e98d5df6dc74 382 int result;
AzureIoTClient 39:e98d5df6dc74 383 LIST_ITEM_HANDLE list_item;
AzureIoTClient 39:e98d5df6dc74 384
AzureIoTClient 39:e98d5df6dc74 385 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 386
AzureIoTClient 39:e98d5df6dc74 387 while ((list_item = singlylinkedlist_get_head_item(from_list)) != NULL)
AzureIoTClient 39:e98d5df6dc74 388 {
AzureIoTClient 39:e98d5df6dc74 389 if (singlylinkedlist_remove(from_list, list_item) != 0)
AzureIoTClient 39:e98d5df6dc74 390 {
AzureIoTClient 39:e98d5df6dc74 391 LogError("failed removing message from list");
AzureIoTClient 39:e98d5df6dc74 392 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 393 }
AzureIoTClient 39:e98d5df6dc74 394 else
AzureIoTClient 39:e98d5df6dc74 395 {
AzureIoTClient 39:e98d5df6dc74 396 MESSAGE_QUEUE_ITEM* mq_item = (MESSAGE_QUEUE_ITEM*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 39:e98d5df6dc74 397
AzureIoTClient 39:e98d5df6dc74 398 if (singlylinkedlist_add(to_list, (const void*)mq_item) != 0)
AzureIoTClient 39:e98d5df6dc74 399 {
AzureIoTClient 39:e98d5df6dc74 400 LogError("failed moving message to list");
AzureIoTClient 39:e98d5df6dc74 401
AzureIoTClient 39:e98d5df6dc74 402 fire_message_callback(mq_item, MESSAGE_QUEUE_CANCELLED, NULL);
AzureIoTClient 39:e98d5df6dc74 403
AzureIoTClient 39:e98d5df6dc74 404 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 405
AzureIoTClient 39:e98d5df6dc74 406 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 407
AzureIoTClient 39:e98d5df6dc74 408 break;
AzureIoTClient 39:e98d5df6dc74 409 }
AzureIoTClient 39:e98d5df6dc74 410 else
AzureIoTClient 39:e98d5df6dc74 411 {
AzureIoTClient 39:e98d5df6dc74 412 mq_item->number_of_attempts = 0;
AzureIoTClient 39:e98d5df6dc74 413 mq_item->processing_start_time = INDEFINITE_TIME;
AzureIoTClient 39:e98d5df6dc74 414 }
AzureIoTClient 39:e98d5df6dc74 415 }
AzureIoTClient 39:e98d5df6dc74 416 }
AzureIoTClient 39:e98d5df6dc74 417
AzureIoTClient 39:e98d5df6dc74 418 return result;
AzureIoTClient 39:e98d5df6dc74 419 }
AzureIoTClient 39:e98d5df6dc74 420
AzureIoTClient 39:e98d5df6dc74 421 int message_queue_move_all_back_to_pending(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 422 {
AzureIoTClient 39:e98d5df6dc74 423 int result;
AzureIoTClient 39:e98d5df6dc74 424
AzureIoTClient 39:e98d5df6dc74 425 if (message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 426 {
AzureIoTClient 39:e98d5df6dc74 427 LogError("invalid argument (message_queue is NULL)");
AzureIoTClient 39:e98d5df6dc74 428 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 429 }
AzureIoTClient 39:e98d5df6dc74 430 else
AzureIoTClient 39:e98d5df6dc74 431 {
AzureIoTClient 39:e98d5df6dc74 432 SINGLYLINKEDLIST_HANDLE temp_list;
AzureIoTClient 39:e98d5df6dc74 433
AzureIoTClient 39:e98d5df6dc74 434 if ((temp_list = singlylinkedlist_create()) == NULL)
AzureIoTClient 39:e98d5df6dc74 435 {
AzureIoTClient 39:e98d5df6dc74 436 LogError("failed creating temporary list");
AzureIoTClient 39:e98d5df6dc74 437 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 438 }
AzureIoTClient 39:e98d5df6dc74 439 else
AzureIoTClient 39:e98d5df6dc74 440 {
AzureIoTClient 39:e98d5df6dc74 441 if (move_messages_between_lists(message_queue->in_progress, temp_list) != 0)
AzureIoTClient 39:e98d5df6dc74 442 {
AzureIoTClient 39:e98d5df6dc74 443 LogError("failed moving in-progress message to temporary list");
AzureIoTClient 39:e98d5df6dc74 444 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 445 }
AzureIoTClient 39:e98d5df6dc74 446 else if (move_messages_between_lists(message_queue->pending, temp_list) != 0)
AzureIoTClient 39:e98d5df6dc74 447 {
AzureIoTClient 39:e98d5df6dc74 448 LogError("failed moving pending message to temporary list");
AzureIoTClient 39:e98d5df6dc74 449 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 450 }
AzureIoTClient 39:e98d5df6dc74 451 else if (move_messages_between_lists(temp_list, message_queue->pending) != 0)
AzureIoTClient 39:e98d5df6dc74 452 {
AzureIoTClient 39:e98d5df6dc74 453 LogError("failed moving pending message to temporary list");
AzureIoTClient 39:e98d5df6dc74 454 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 455 }
AzureIoTClient 39:e98d5df6dc74 456 else
AzureIoTClient 39:e98d5df6dc74 457 {
AzureIoTClient 39:e98d5df6dc74 458 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 459 }
AzureIoTClient 39:e98d5df6dc74 460
AzureIoTClient 39:e98d5df6dc74 461 if (result != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 462 {
AzureIoTClient 39:e98d5df6dc74 463 LIST_ITEM_HANDLE list_item;
AzureIoTClient 39:e98d5df6dc74 464
AzureIoTClient 39:e98d5df6dc74 465 while ((list_item = singlylinkedlist_get_head_item(temp_list)) != NULL)
AzureIoTClient 39:e98d5df6dc74 466 {
AzureIoTClient 39:e98d5df6dc74 467 dequeue_message_and_fire_callback(temp_list, list_item, MESSAGE_QUEUE_CANCELLED, NULL);
AzureIoTClient 39:e98d5df6dc74 468 }
AzureIoTClient 39:e98d5df6dc74 469 }
AzureIoTClient 39:e98d5df6dc74 470
AzureIoTClient 56:8704100b3b54 471 singlylinkedlist_destroy(temp_list);
AzureIoTClient 39:e98d5df6dc74 472 }
AzureIoTClient 39:e98d5df6dc74 473 }
AzureIoTClient 39:e98d5df6dc74 474
AzureIoTClient 39:e98d5df6dc74 475 return result;
AzureIoTClient 39:e98d5df6dc74 476 }
AzureIoTClient 39:e98d5df6dc74 477
AzureIoTClient 39:e98d5df6dc74 478 void message_queue_destroy(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 479 {
AzureIoTClient 39:e98d5df6dc74 480 // Codes_SRS_MESSAGE_QUEUE_09_013: [If `message_queue` is NULL, message_queue_destroy shall return immediately]
AzureIoTClient 39:e98d5df6dc74 481 if (message_queue != NULL)
AzureIoTClient 39:e98d5df6dc74 482 {
AzureIoTClient 39:e98d5df6dc74 483 // Codes_SRS_MESSAGE_QUEUE_09_014: [message_queue_destroy shall invoke message_queue_remove_all]
AzureIoTClient 39:e98d5df6dc74 484 message_queue_remove_all(message_queue);
AzureIoTClient 39:e98d5df6dc74 485
AzureIoTClient 39:e98d5df6dc74 486 // Codes_SRS_MESSAGE_QUEUE_09_015: [message_queue_destroy shall free all memory allocated and pointed by `message_queue`]
AzureIoTClient 39:e98d5df6dc74 487 if (message_queue->pending != NULL)
AzureIoTClient 39:e98d5df6dc74 488 {
AzureIoTClient 39:e98d5df6dc74 489 singlylinkedlist_destroy(message_queue->pending);
AzureIoTClient 39:e98d5df6dc74 490 }
AzureIoTClient 39:e98d5df6dc74 491
AzureIoTClient 39:e98d5df6dc74 492 if (message_queue->in_progress != NULL)
AzureIoTClient 39:e98d5df6dc74 493 {
AzureIoTClient 39:e98d5df6dc74 494 singlylinkedlist_destroy(message_queue->in_progress);
AzureIoTClient 39:e98d5df6dc74 495 }
AzureIoTClient 56:8704100b3b54 496
AzureIoTClient 39:e98d5df6dc74 497 free(message_queue);
AzureIoTClient 39:e98d5df6dc74 498 }
AzureIoTClient 39:e98d5df6dc74 499 }
AzureIoTClient 39:e98d5df6dc74 500
AzureIoTClient 39:e98d5df6dc74 501 MESSAGE_QUEUE_HANDLE message_queue_create(MESSAGE_QUEUE_CONFIG* config)
AzureIoTClient 39:e98d5df6dc74 502 {
AzureIoTClient 39:e98d5df6dc74 503 MESSAGE_QUEUE* result;
AzureIoTClient 39:e98d5df6dc74 504
AzureIoTClient 39:e98d5df6dc74 505 // Codes_SRS_MESSAGE_QUEUE_09_001: [If `config` is NULL, message_queue_create shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 506 if (config == NULL)
AzureIoTClient 39:e98d5df6dc74 507 {
AzureIoTClient 39:e98d5df6dc74 508 LogError("invalid configuration (NULL)");
AzureIoTClient 39:e98d5df6dc74 509 result = NULL;
AzureIoTClient 39:e98d5df6dc74 510 }
AzureIoTClient 39:e98d5df6dc74 511 // Codes_SRS_MESSAGE_QUEUE_09_002: [If `config->on_process_message_callback` is NULL, message_queue_create shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 512 else if (config->on_process_message_callback == NULL)
AzureIoTClient 39:e98d5df6dc74 513 {
AzureIoTClient 39:e98d5df6dc74 514 LogError("invalid configuration (on_process_message_callback is NULL)");
AzureIoTClient 39:e98d5df6dc74 515 result = NULL;
AzureIoTClient 39:e98d5df6dc74 516 }
AzureIoTClient 39:e98d5df6dc74 517 // Codes_SRS_MESSAGE_QUEUE_09_004: [Memory shall be allocated for the MESSAGE_QUEUE data structure (aka `message_queue`)]
AzureIoTClient 39:e98d5df6dc74 518 else if ((result = (MESSAGE_QUEUE*)malloc(sizeof(MESSAGE_QUEUE))) == NULL)
AzureIoTClient 39:e98d5df6dc74 519 {
AzureIoTClient 39:e98d5df6dc74 520 // Codes_SRS_MESSAGE_QUEUE_09_005: [If `instance` cannot be allocated, message_queue_create shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 521 LogError("failed allocating MESSAGE_QUEUE");
AzureIoTClient 39:e98d5df6dc74 522 result = NULL;
AzureIoTClient 39:e98d5df6dc74 523 }
AzureIoTClient 39:e98d5df6dc74 524 else
AzureIoTClient 39:e98d5df6dc74 525 {
AzureIoTClient 39:e98d5df6dc74 526 memset(result, 0, sizeof(MESSAGE_QUEUE));
AzureIoTClient 39:e98d5df6dc74 527
AzureIoTClient 39:e98d5df6dc74 528 // Codes_SRS_MESSAGE_QUEUE_09_006: [`message_queue->pending` shall be set using singlylinkedlist_create()]
AzureIoTClient 39:e98d5df6dc74 529 if ((result->pending = singlylinkedlist_create()) == NULL)
AzureIoTClient 39:e98d5df6dc74 530 {
AzureIoTClient 39:e98d5df6dc74 531 // Codes_SRS_MESSAGE_QUEUE_09_007: [If singlylinkedlist_create fails, message_queue_create shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 532 LogError("failed allocating MESSAGE_QUEUE pending list");
AzureIoTClient 39:e98d5df6dc74 533 // Codes_SRS_MESSAGE_QUEUE_09_011: [If any failures occur, message_queue_create shall release all memory it has allocated]
AzureIoTClient 39:e98d5df6dc74 534 message_queue_destroy(result);
AzureIoTClient 39:e98d5df6dc74 535 result = NULL;
AzureIoTClient 39:e98d5df6dc74 536 }
AzureIoTClient 39:e98d5df6dc74 537 // Codes_SRS_MESSAGE_QUEUE_09_008: [`message_queue->in_progress` shall be set using singlylinkedlist_create()]
AzureIoTClient 39:e98d5df6dc74 538 else if ((result->in_progress = singlylinkedlist_create()) == NULL)
AzureIoTClient 39:e98d5df6dc74 539 {
AzureIoTClient 39:e98d5df6dc74 540 // Codes_SRS_MESSAGE_QUEUE_09_009: [If singlylinkedlist_create fails, message_queue_create shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 541 LogError("failed allocating MESSAGE_QUEUE in-progress list");
AzureIoTClient 39:e98d5df6dc74 542 // Codes_SRS_MESSAGE_QUEUE_09_011: [If any failures occur, message_queue_create shall release all memory it has allocated]
AzureIoTClient 39:e98d5df6dc74 543 message_queue_destroy(result);
AzureIoTClient 39:e98d5df6dc74 544 result = NULL;
AzureIoTClient 39:e98d5df6dc74 545 }
AzureIoTClient 39:e98d5df6dc74 546 else
AzureIoTClient 39:e98d5df6dc74 547 {
AzureIoTClient 39:e98d5df6dc74 548 // Codes_SRS_MESSAGE_QUEUE_09_010: [All arguments in `config` shall be saved into `message_queue`]
AzureIoTClient 39:e98d5df6dc74 549 // Codes_SRS_MESSAGE_QUEUE_09_012: [If no failures occur, message_queue_create shall return the `message_queue` pointer]
AzureIoTClient 39:e98d5df6dc74 550
AzureIoTClient 39:e98d5df6dc74 551 result->max_message_enqueued_time_secs = config->max_message_enqueued_time_secs;
AzureIoTClient 39:e98d5df6dc74 552 result->max_message_processing_time_secs = config->max_message_processing_time_secs;
AzureIoTClient 39:e98d5df6dc74 553 result->max_retry_count = config->max_retry_count;
AzureIoTClient 39:e98d5df6dc74 554 result->on_process_message_callback = config->on_process_message_callback;
AzureIoTClient 39:e98d5df6dc74 555 }
AzureIoTClient 39:e98d5df6dc74 556 }
AzureIoTClient 39:e98d5df6dc74 557
AzureIoTClient 39:e98d5df6dc74 558 return result;
AzureIoTClient 39:e98d5df6dc74 559 }
AzureIoTClient 39:e98d5df6dc74 560
AzureIoTClient 39:e98d5df6dc74 561 int message_queue_add(MESSAGE_QUEUE_HANDLE message_queue, MQ_MESSAGE_HANDLE message, MESSAGE_PROCESSING_COMPLETED_CALLBACK on_message_processing_completed_callback, void* user_context)
AzureIoTClient 39:e98d5df6dc74 562 {
AzureIoTClient 39:e98d5df6dc74 563 int result;
AzureIoTClient 39:e98d5df6dc74 564
AzureIoTClient 39:e98d5df6dc74 565 // Codes_SRS_MESSAGE_QUEUE_09_016: [If `message_queue` or `message` are NULL, message_queue_add shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 566 if (message_queue == NULL || message == NULL)
AzureIoTClient 39:e98d5df6dc74 567 {
AzureIoTClient 39:e98d5df6dc74 568 LogError("invalid argument (message_queue=%p, message=%p)", message_queue, message);
AzureIoTClient 39:e98d5df6dc74 569 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 570 }
AzureIoTClient 39:e98d5df6dc74 571 else
AzureIoTClient 39:e98d5df6dc74 572 {
AzureIoTClient 39:e98d5df6dc74 573 MESSAGE_QUEUE_ITEM* mq_item;
AzureIoTClient 39:e98d5df6dc74 574
AzureIoTClient 39:e98d5df6dc74 575 // Codes_SRS_MESSAGE_QUEUE_09_017: [message_queue_add shall allocate a structure (aka `mq_item`) to save the `message`]
AzureIoTClient 39:e98d5df6dc74 576 if ((mq_item = (MESSAGE_QUEUE_ITEM*)malloc(sizeof(MESSAGE_QUEUE_ITEM))) == NULL)
AzureIoTClient 39:e98d5df6dc74 577 {
AzureIoTClient 39:e98d5df6dc74 578 // Codes_SRS_MESSAGE_QUEUE_09_018: [If `mq_item` cannot be allocated, message_queue_add shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 579 LogError("failed creating container for message");
AzureIoTClient 39:e98d5df6dc74 580 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 581 }
AzureIoTClient 39:e98d5df6dc74 582 else
AzureIoTClient 39:e98d5df6dc74 583 {
AzureIoTClient 39:e98d5df6dc74 584 memset(mq_item, 0, sizeof(MESSAGE_QUEUE_ITEM));
AzureIoTClient 39:e98d5df6dc74 585
AzureIoTClient 39:e98d5df6dc74 586 // Codes_SRS_MESSAGE_QUEUE_09_019: [`mq_item->enqueue_time` shall be set using get_time()]
AzureIoTClient 39:e98d5df6dc74 587 if ((mq_item->enqueue_time = get_time(NULL)) == INDEFINITE_TIME)
AzureIoTClient 39:e98d5df6dc74 588 {
AzureIoTClient 39:e98d5df6dc74 589 // Codes_SRS_MESSAGE_QUEUE_09_020: [If get_time fails, message_queue_add shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 590 LogError("failed setting message enqueue time");
AzureIoTClient 39:e98d5df6dc74 591 // Codes_SRS_MESSAGE_QUEUE_09_024: [If any failures occur, message_queue_add shall release all memory it has allocated]
AzureIoTClient 39:e98d5df6dc74 592 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 593 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 594 }
AzureIoTClient 39:e98d5df6dc74 595 // Codes_SRS_MESSAGE_QUEUE_09_021: [`mq_item` shall be added to `message_queue->pending` list]
AzureIoTClient 39:e98d5df6dc74 596 else if (singlylinkedlist_add(message_queue->pending, (const void*)mq_item) == NULL)
AzureIoTClient 39:e98d5df6dc74 597 {
AzureIoTClient 39:e98d5df6dc74 598 // Codes_SRS_MESSAGE_QUEUE_09_022: [`mq_item` fails to be added to `message_queue->pending`, message_queue_add shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 599 LogError("failed enqueing message");
AzureIoTClient 39:e98d5df6dc74 600 // Codes_SRS_MESSAGE_QUEUE_09_024: [If any failures occur, message_queue_add shall release all memory it has allocated]
AzureIoTClient 39:e98d5df6dc74 601 free(mq_item);
AzureIoTClient 39:e98d5df6dc74 602 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 603 }
AzureIoTClient 39:e98d5df6dc74 604 else
AzureIoTClient 39:e98d5df6dc74 605 {
AzureIoTClient 39:e98d5df6dc74 606 // Codes_SRS_MESSAGE_QUEUE_09_023: [`message` shall be saved into `mq_item->message`]
AzureIoTClient 39:e98d5df6dc74 607 mq_item->message = message;
AzureIoTClient 39:e98d5df6dc74 608 mq_item->on_message_processing_completed_callback = on_message_processing_completed_callback;
AzureIoTClient 39:e98d5df6dc74 609 mq_item->user_context = user_context;
AzureIoTClient 39:e98d5df6dc74 610 mq_item->processing_start_time = INDEFINITE_TIME;
AzureIoTClient 39:e98d5df6dc74 611 // Codes_SRS_MESSAGE_QUEUE_09_025: [If no failures occur, message_queue_add shall return 0]
AzureIoTClient 39:e98d5df6dc74 612 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 613 }
AzureIoTClient 39:e98d5df6dc74 614 }
AzureIoTClient 39:e98d5df6dc74 615 }
AzureIoTClient 39:e98d5df6dc74 616
AzureIoTClient 39:e98d5df6dc74 617 return result;
AzureIoTClient 39:e98d5df6dc74 618 }
AzureIoTClient 39:e98d5df6dc74 619
AzureIoTClient 39:e98d5df6dc74 620 int message_queue_is_empty(MESSAGE_QUEUE_HANDLE message_queue, bool* is_empty)
AzureIoTClient 39:e98d5df6dc74 621 {
AzureIoTClient 39:e98d5df6dc74 622 int result;
AzureIoTClient 39:e98d5df6dc74 623
AzureIoTClient 39:e98d5df6dc74 624 // Codes_SRS_MESSAGE_QUEUE_09_030: [If `message_queue` or `is_empty` are NULL, message_queue_is_empty shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 625 if (message_queue == NULL || is_empty == NULL)
AzureIoTClient 39:e98d5df6dc74 626 {
AzureIoTClient 39:e98d5df6dc74 627 LogError("invalid argument (message_queue=%p, is_empty=%p)", message_queue, is_empty);
AzureIoTClient 39:e98d5df6dc74 628 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 629 }
AzureIoTClient 39:e98d5df6dc74 630 else
AzureIoTClient 39:e98d5df6dc74 631 {
AzureIoTClient 39:e98d5df6dc74 632 // Codes_SRS_MESSAGE_QUEUE_09_031: [If `message_queue->pending` and `message_queue->in_progress` are empty, `is_empty` shall be set to true]
AzureIoTClient 39:e98d5df6dc74 633 // Codes_SRS_MESSAGE_QUEUE_09_032: [Otherwise `is_empty` shall be set to false]
AzureIoTClient 39:e98d5df6dc74 634 *is_empty = (singlylinkedlist_get_head_item(message_queue->pending) == NULL && singlylinkedlist_get_head_item(message_queue->in_progress) == NULL);
AzureIoTClient 39:e98d5df6dc74 635 // Codes_SRS_MESSAGE_QUEUE_09_033: [If no failures occur, message_queue_is_empty shall return 0]
AzureIoTClient 39:e98d5df6dc74 636 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 637 }
AzureIoTClient 39:e98d5df6dc74 638
AzureIoTClient 39:e98d5df6dc74 639 return result;
AzureIoTClient 39:e98d5df6dc74 640 }
AzureIoTClient 39:e98d5df6dc74 641
AzureIoTClient 39:e98d5df6dc74 642 void message_queue_do_work(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 643 {
AzureIoTClient 39:e98d5df6dc74 644 // Codes_SRS_MESSAGE_QUEUE_09_034: [If `message_queue` is NULL, message_queue_do_work shall return immediately]
AzureIoTClient 39:e98d5df6dc74 645 if (message_queue != NULL)
AzureIoTClient 39:e98d5df6dc74 646 {
AzureIoTClient 39:e98d5df6dc74 647 process_timeouts(message_queue);
AzureIoTClient 39:e98d5df6dc74 648 process_pending_messages(message_queue);
AzureIoTClient 39:e98d5df6dc74 649 }
AzureIoTClient 39:e98d5df6dc74 650 }
AzureIoTClient 39:e98d5df6dc74 651
AzureIoTClient 39:e98d5df6dc74 652 int message_queue_set_max_message_enqueued_time_secs(MESSAGE_QUEUE_HANDLE message_queue, size_t seconds)
AzureIoTClient 39:e98d5df6dc74 653 {
AzureIoTClient 39:e98d5df6dc74 654 int result;
AzureIoTClient 39:e98d5df6dc74 655
AzureIoTClient 39:e98d5df6dc74 656 // Codes_SRS_MESSAGE_QUEUE_09_051: [If `message_queue` is NULL, message_queue_set_max_message_enqueued_time_secs shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 657 if (message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 658 {
AzureIoTClient 39:e98d5df6dc74 659 LogError("invalid argument (message_queue is NULL)");
AzureIoTClient 39:e98d5df6dc74 660 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 661 }
AzureIoTClient 39:e98d5df6dc74 662 else
AzureIoTClient 39:e98d5df6dc74 663 {
AzureIoTClient 39:e98d5df6dc74 664 // Codes_SRS_MESSAGE_QUEUE_09_053: [`seconds` shall be saved into `message_queue->max_message_enqueued_time_secs`]
AzureIoTClient 39:e98d5df6dc74 665 message_queue->max_message_enqueued_time_secs = seconds;
AzureIoTClient 39:e98d5df6dc74 666 // Codes_SRS_MESSAGE_QUEUE_09_054: [If no failures occur, message_queue_set_max_message_enqueued_time_secs shall return 0]
AzureIoTClient 39:e98d5df6dc74 667 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 668 }
AzureIoTClient 39:e98d5df6dc74 669
AzureIoTClient 39:e98d5df6dc74 670 return result;
AzureIoTClient 39:e98d5df6dc74 671 }
AzureIoTClient 39:e98d5df6dc74 672
AzureIoTClient 39:e98d5df6dc74 673 int message_queue_set_max_message_processing_time_secs(MESSAGE_QUEUE_HANDLE message_queue, size_t seconds)
AzureIoTClient 39:e98d5df6dc74 674 {
AzureIoTClient 39:e98d5df6dc74 675 int result;
AzureIoTClient 39:e98d5df6dc74 676
AzureIoTClient 39:e98d5df6dc74 677 // Codes_SRS_MESSAGE_QUEUE_09_055: [If `message_queue` is NULL, message_queue_set_max_message_processing_time_secs shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 678 if (message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 679 {
AzureIoTClient 39:e98d5df6dc74 680 LogError("invalid argument (message_queue is NULL)");
AzureIoTClient 39:e98d5df6dc74 681 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 682 }
AzureIoTClient 39:e98d5df6dc74 683 else
AzureIoTClient 39:e98d5df6dc74 684 {
AzureIoTClient 39:e98d5df6dc74 685 // Codes_SRS_MESSAGE_QUEUE_09_057: [`seconds` shall be saved into `message_queue->max_message_processing_time_secs`]
AzureIoTClient 39:e98d5df6dc74 686 message_queue->max_message_processing_time_secs = seconds;
AzureIoTClient 39:e98d5df6dc74 687 // Codes_SRS_MESSAGE_QUEUE_09_058: [If no failures occur, message_queue_set_max_message_processing_time_secs shall return 0]
AzureIoTClient 39:e98d5df6dc74 688 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 689 }
AzureIoTClient 39:e98d5df6dc74 690
AzureIoTClient 39:e98d5df6dc74 691 return result;
AzureIoTClient 39:e98d5df6dc74 692 }
AzureIoTClient 39:e98d5df6dc74 693
AzureIoTClient 39:e98d5df6dc74 694 int message_queue_set_max_retry_count(MESSAGE_QUEUE_HANDLE message_queue, size_t max_retry_count)
AzureIoTClient 39:e98d5df6dc74 695 {
AzureIoTClient 39:e98d5df6dc74 696 int result;
AzureIoTClient 39:e98d5df6dc74 697
AzureIoTClient 39:e98d5df6dc74 698 // Codes_SRS_MESSAGE_QUEUE_09_059: [If `message_queue` is NULL, message_queue_set_max_retry_count shall fail and return non-zero]
AzureIoTClient 39:e98d5df6dc74 699 if (message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 700 {
AzureIoTClient 39:e98d5df6dc74 701 LogError("invalid argument (message_queue is NULL)");
AzureIoTClient 39:e98d5df6dc74 702 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 703 }
AzureIoTClient 39:e98d5df6dc74 704 else
AzureIoTClient 39:e98d5df6dc74 705 {
AzureIoTClient 39:e98d5df6dc74 706 // Codes_SRS_MESSAGE_QUEUE_09_061: [If no failures occur, message_queue_set_max_retry_count shall return 0]
AzureIoTClient 39:e98d5df6dc74 707 message_queue->max_retry_count = max_retry_count;
AzureIoTClient 39:e98d5df6dc74 708 // Codes_SRS_MESSAGE_QUEUE_09_060: [`max_retry_count` shall be saved into `message_queue->max_retry_count`]
AzureIoTClient 39:e98d5df6dc74 709 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 710 }
AzureIoTClient 39:e98d5df6dc74 711
AzureIoTClient 39:e98d5df6dc74 712 return result;
AzureIoTClient 39:e98d5df6dc74 713 }
AzureIoTClient 39:e98d5df6dc74 714
AzureIoTClient 39:e98d5df6dc74 715 static int setOption(void* handle, const char* name, const void* value)
AzureIoTClient 39:e98d5df6dc74 716 {
AzureIoTClient 39:e98d5df6dc74 717 int result;
AzureIoTClient 39:e98d5df6dc74 718
AzureIoTClient 39:e98d5df6dc74 719 if (handle == NULL || name == NULL || value == NULL)
AzureIoTClient 39:e98d5df6dc74 720 {
AzureIoTClient 39:e98d5df6dc74 721 LogError("invalid argument (handle=%p, name=%p, value=%p)", handle, name, value);
AzureIoTClient 39:e98d5df6dc74 722 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 723 }
AzureIoTClient 39:e98d5df6dc74 724 else if (strcmp(SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, name) == 0)
AzureIoTClient 39:e98d5df6dc74 725 {
AzureIoTClient 39:e98d5df6dc74 726 if (message_queue_set_max_message_enqueued_time_secs((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 727 {
AzureIoTClient 39:e98d5df6dc74 728 LogError("failed setting option %s", name);
AzureIoTClient 39:e98d5df6dc74 729 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 730 }
AzureIoTClient 39:e98d5df6dc74 731 else
AzureIoTClient 39:e98d5df6dc74 732 {
AzureIoTClient 39:e98d5df6dc74 733 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 734 }
AzureIoTClient 39:e98d5df6dc74 735 }
AzureIoTClient 39:e98d5df6dc74 736 else if (strcmp(SAVED_OPTION_MAX_PROCESSING_TIME_SECS, name) == 0)
AzureIoTClient 39:e98d5df6dc74 737 {
AzureIoTClient 39:e98d5df6dc74 738 if (message_queue_set_max_message_processing_time_secs((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 739 {
AzureIoTClient 39:e98d5df6dc74 740 LogError("failed setting option %s", name);
AzureIoTClient 39:e98d5df6dc74 741 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 742 }
AzureIoTClient 39:e98d5df6dc74 743 else
AzureIoTClient 39:e98d5df6dc74 744 {
AzureIoTClient 39:e98d5df6dc74 745 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 746 }
AzureIoTClient 39:e98d5df6dc74 747 }
AzureIoTClient 39:e98d5df6dc74 748 else if (strcmp(SAVED_OPTION_MAX_RETRY_COUNT, name) == 0)
AzureIoTClient 39:e98d5df6dc74 749 {
AzureIoTClient 39:e98d5df6dc74 750 if (message_queue_set_max_retry_count((MESSAGE_QUEUE_HANDLE)handle, *(size_t*)value) != RESULT_OK)
AzureIoTClient 39:e98d5df6dc74 751 {
AzureIoTClient 39:e98d5df6dc74 752 LogError("failed setting option %s", name);
AzureIoTClient 39:e98d5df6dc74 753 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 754 }
AzureIoTClient 39:e98d5df6dc74 755 else
AzureIoTClient 39:e98d5df6dc74 756 {
AzureIoTClient 39:e98d5df6dc74 757 result = RESULT_OK;
AzureIoTClient 39:e98d5df6dc74 758 }
AzureIoTClient 39:e98d5df6dc74 759 }
AzureIoTClient 39:e98d5df6dc74 760 else
AzureIoTClient 39:e98d5df6dc74 761 {
AzureIoTClient 39:e98d5df6dc74 762 LogError("option %s is invalid", name);
AzureIoTClient 39:e98d5df6dc74 763 result = __FAILURE__;
AzureIoTClient 39:e98d5df6dc74 764 }
AzureIoTClient 39:e98d5df6dc74 765
AzureIoTClient 39:e98d5df6dc74 766 return result;
AzureIoTClient 39:e98d5df6dc74 767 }
AzureIoTClient 39:e98d5df6dc74 768
AzureIoTClient 39:e98d5df6dc74 769 OPTIONHANDLER_HANDLE message_queue_retrieve_options(MESSAGE_QUEUE_HANDLE message_queue)
AzureIoTClient 39:e98d5df6dc74 770 {
AzureIoTClient 39:e98d5df6dc74 771 OPTIONHANDLER_HANDLE result;
AzureIoTClient 39:e98d5df6dc74 772
AzureIoTClient 39:e98d5df6dc74 773 // Codes_SRS_MESSAGE_QUEUE_09_062: [If `message_queue` is NULL, message_queue_retrieve_options shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 774 if (message_queue == NULL)
AzureIoTClient 39:e98d5df6dc74 775 {
AzureIoTClient 39:e98d5df6dc74 776 LogError("invalid argument (message_queue is NULL)");
AzureIoTClient 39:e98d5df6dc74 777 result = NULL;
AzureIoTClient 39:e98d5df6dc74 778 }
AzureIoTClient 39:e98d5df6dc74 779 // Codes_SRS_MESSAGE_QUEUE_09_063: [An OPTIONHANDLER_HANDLE instance shall be created using OptionHandler_Create]
AzureIoTClient 39:e98d5df6dc74 780 else if ((result = OptionHandler_Create(cloneOption, destroyOption, setOption)) == NULL)
AzureIoTClient 39:e98d5df6dc74 781 {
AzureIoTClient 39:e98d5df6dc74 782 // Codes_SRS_MESSAGE_QUEUE_09_064: [If an OPTIONHANDLER_HANDLE instance fails to be created, message_queue_retrieve_options shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 783 LogError("failed creating OPTIONHANDLER_HANDLE");
AzureIoTClient 39:e98d5df6dc74 784 }
AzureIoTClient 39:e98d5df6dc74 785 // Codes_SRS_MESSAGE_QUEUE_09_065: [Each option of `instance` shall be added to the OPTIONHANDLER_HANDLE instance using OptionHandler_AddOption]
AzureIoTClient 39:e98d5df6dc74 786 else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_ENQUEUE_TIME_SECS, &message_queue->max_message_enqueued_time_secs) != OPTIONHANDLER_OK)
AzureIoTClient 39:e98d5df6dc74 787 {
AzureIoTClient 39:e98d5df6dc74 788 LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_ENQUEUE_TIME_SECS);
AzureIoTClient 39:e98d5df6dc74 789 // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed]
AzureIoTClient 39:e98d5df6dc74 790 OptionHandler_Destroy(result);
AzureIoTClient 39:e98d5df6dc74 791 // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 792 result = NULL;
AzureIoTClient 39:e98d5df6dc74 793 }
AzureIoTClient 39:e98d5df6dc74 794 else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_PROCESSING_TIME_SECS, &message_queue->max_message_processing_time_secs) != OPTIONHANDLER_OK)
AzureIoTClient 39:e98d5df6dc74 795 {
AzureIoTClient 39:e98d5df6dc74 796 LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_PROCESSING_TIME_SECS);
AzureIoTClient 39:e98d5df6dc74 797 // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed]
AzureIoTClient 39:e98d5df6dc74 798 OptionHandler_Destroy(result);
AzureIoTClient 39:e98d5df6dc74 799 // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 800 result = NULL;
AzureIoTClient 39:e98d5df6dc74 801 }
AzureIoTClient 39:e98d5df6dc74 802 else if (OptionHandler_AddOption(result, SAVED_OPTION_MAX_RETRY_COUNT, &message_queue->max_retry_count) != OPTIONHANDLER_OK)
AzureIoTClient 39:e98d5df6dc74 803 {
AzureIoTClient 39:e98d5df6dc74 804 LogError("failed retrieving options (failed adding %s)", SAVED_OPTION_MAX_PROCESSING_TIME_SECS);
AzureIoTClient 39:e98d5df6dc74 805 // Codes_SRS_MESSAGE_QUEUE_09_067: [If message_queue_retrieve_options fails, any allocated memory shall be freed]
AzureIoTClient 39:e98d5df6dc74 806 OptionHandler_Destroy(result);
AzureIoTClient 39:e98d5df6dc74 807 // Codes_SRS_MESSAGE_QUEUE_09_066: [If OptionHandler_AddOption fails, message_queue_retrieve_options shall fail and return NULL]
AzureIoTClient 39:e98d5df6dc74 808 result = NULL;
AzureIoTClient 39:e98d5df6dc74 809 }
AzureIoTClient 39:e98d5df6dc74 810
AzureIoTClient 39:e98d5df6dc74 811 // Codes_SRS_MESSAGE_QUEUE_09_068: [If no failures occur, message_queue_retrieve_options shall return the OPTIONHANDLER_HANDLE instance]
AzureIoTClient 39:e98d5df6dc74 812 return result;
AzureIoTClient 56:8704100b3b54 813 }