A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jun 02 15:53:07 2017 -0700
Revision:
27:d74f1cea23e1
Parent:
25:1101516ee67d
Child:
28:add19eb7defa
1.1.16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #include <stdio.h>
AzureIoTClient 6:641a9672db08 6 #include <stdbool.h>
Azure.IoT Build 0:6ae2f7bca550 7 #include <string.h>
AzureIoTClient 19:000ab4e6a2c1 8 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 21:f9c433d8e6ca 9 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 23:1111ee8bcba4 10 #include "azure_c_shared_utility/singlylinkedlist.h"
AzureIoTClient 27:d74f1cea23e1 11 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/amqp_management.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/link.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_uamqp_c/message_sender.h"
Azure.IoT Build 0:6ae2f7bca550 15 #include "azure_uamqp_c/message_receiver.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/messaging.h"
Azure.IoT Build 0:6ae2f7bca550 17 #include "azure_uamqp_c/amqpvalue_to_string.h"
Azure.IoT Build 0:6ae2f7bca550 18
AzureIoTClient 23:1111ee8bcba4 19 static const char sender_suffix[] = "-sender";
AzureIoTClient 23:1111ee8bcba4 20 static const char receiver_suffix[] = "-receiver";
AzureIoTClient 23:1111ee8bcba4 21
AzureIoTClient 23:1111ee8bcba4 22 #define COUNT_CHARS(str) (sizeof(str) / sizeof((str)[0]) - 1)
Azure.IoT Build 0:6ae2f7bca550 23
Azure.IoT Build 0:6ae2f7bca550 24 typedef struct OPERATION_MESSAGE_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 25 {
AzureIoTClient 22:524bded3f7a8 26 ON_AMQP_MANAGEMENT_EXECUTE_OPERATION_COMPLETE on_execute_operation_complete;
AzureIoTClient 6:641a9672db08 27 void* callback_context;
AzureIoTClient 23:1111ee8bcba4 28 uint64_t message_id;
Azure.IoT Build 0:6ae2f7bca550 29 } OPERATION_MESSAGE_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 30
AzureIoTClient 22:524bded3f7a8 31 typedef enum AMQP_MANAGEMENT_STATE_TAG
AzureIoTClient 22:524bded3f7a8 32 {
AzureIoTClient 22:524bded3f7a8 33 AMQP_MANAGEMENT_STATE_IDLE,
AzureIoTClient 22:524bded3f7a8 34 AMQP_MANAGEMENT_STATE_OPENING,
AzureIoTClient 22:524bded3f7a8 35 AMQP_MANAGEMENT_STATE_OPEN,
AzureIoTClient 22:524bded3f7a8 36 AMQP_MANAGEMENT_STATE_ERROR
AzureIoTClient 22:524bded3f7a8 37 } AMQP_MANAGEMENT_STATE;
AzureIoTClient 22:524bded3f7a8 38
Azure.IoT Build 0:6ae2f7bca550 39 typedef struct AMQP_MANAGEMENT_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 40 {
AzureIoTClient 6:641a9672db08 41 LINK_HANDLE sender_link;
AzureIoTClient 6:641a9672db08 42 LINK_HANDLE receiver_link;
AzureIoTClient 6:641a9672db08 43 MESSAGE_SENDER_HANDLE message_sender;
AzureIoTClient 6:641a9672db08 44 MESSAGE_RECEIVER_HANDLE message_receiver;
AzureIoTClient 23:1111ee8bcba4 45 SINGLYLINKEDLIST_HANDLE pending_operations;
AzureIoTClient 23:1111ee8bcba4 46 uint64_t next_message_id;
AzureIoTClient 22:524bded3f7a8 47 ON_AMQP_MANAGEMENT_OPEN_COMPLETE on_amqp_management_open_complete;
AzureIoTClient 22:524bded3f7a8 48 void* on_amqp_management_open_complete_context;
AzureIoTClient 22:524bded3f7a8 49 ON_AMQP_MANAGEMENT_ERROR on_amqp_management_error;
AzureIoTClient 22:524bded3f7a8 50 void* on_amqp_management_error_context;
AzureIoTClient 6:641a9672db08 51 AMQP_MANAGEMENT_STATE amqp_management_state;
AzureIoTClient 6:641a9672db08 52 int sender_connected : 1;
AzureIoTClient 6:641a9672db08 53 int receiver_connected : 1;
Azure.IoT Build 0:6ae2f7bca550 54 } AMQP_MANAGEMENT_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 55
AzureIoTClient 23:1111ee8bcba4 56 static AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message)
Azure.IoT Build 0:6ae2f7bca550 57 {
AzureIoTClient 23:1111ee8bcba4 58 AMQP_VALUE result;
Azure.IoT Build 0:6ae2f7bca550 59
AzureIoTClient 23:1111ee8bcba4 60 if (context == NULL)
AzureIoTClient 6:641a9672db08 61 {
AzureIoTClient 23:1111ee8bcba4 62 /* Codes_SRS_AMQP_MANAGEMENT_01_108: [ When `on_message_received` is called with a NULL context, it shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 63 LogError("NULL context in on_message_received");
AzureIoTClient 23:1111ee8bcba4 64 result = NULL;
AzureIoTClient 6:641a9672db08 65 }
AzureIoTClient 6:641a9672db08 66 else
AzureIoTClient 6:641a9672db08 67 {
AzureIoTClient 23:1111ee8bcba4 68 AMQP_MANAGEMENT_HANDLE amqp_management = (AMQP_MANAGEMENT_HANDLE)context;
AzureIoTClient 23:1111ee8bcba4 69 AMQP_VALUE application_properties;
Azure.IoT Build 0:6ae2f7bca550 70
AzureIoTClient 23:1111ee8bcba4 71 /* Codes_SRS_AMQP_MANAGEMENT_01_109: [ `on_message_received` shall obtain the application properties from the message by calling `message_get_application_properties`. ]*/
AzureIoTClient 23:1111ee8bcba4 72 if (message_get_application_properties(message, &application_properties) != 0)
AzureIoTClient 6:641a9672db08 73 {
AzureIoTClient 23:1111ee8bcba4 74 /* Codes_SRS_AMQP_MANAGEMENT_01_113: [ If obtaining the application properties or message properties fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 75 LogError("Could not retrieve application properties");
AzureIoTClient 23:1111ee8bcba4 76 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 77 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 78 result = messaging_delivery_rejected("amqp:internal-error", "Could not get application properties on AMQP management response.");
AzureIoTClient 6:641a9672db08 79 }
AzureIoTClient 6:641a9672db08 80 else
AzureIoTClient 6:641a9672db08 81 {
AzureIoTClient 23:1111ee8bcba4 82 PROPERTIES_HANDLE response_properties;
Azure.IoT Build 0:6ae2f7bca550 83
AzureIoTClient 23:1111ee8bcba4 84 /* Codes_SRS_AMQP_MANAGEMENT_01_110: [ `on_message_received` shall obtain the message properties from the message by calling `message_get_properties`. ]*/
AzureIoTClient 23:1111ee8bcba4 85 if (message_get_properties(message, &response_properties) != 0)
AzureIoTClient 6:641a9672db08 86 {
AzureIoTClient 23:1111ee8bcba4 87 /* Codes_SRS_AMQP_MANAGEMENT_01_113: [ If obtaining the application properties or message properties fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 88 LogError("Could not retrieve message properties");
AzureIoTClient 23:1111ee8bcba4 89 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 90 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 91 result = messaging_delivery_rejected("amqp:internal-error", "Could not get message properties on AMQP management response.");
AzureIoTClient 6:641a9672db08 92 }
AzureIoTClient 6:641a9672db08 93 else
AzureIoTClient 6:641a9672db08 94 {
AzureIoTClient 23:1111ee8bcba4 95 AMQP_VALUE key;
AzureIoTClient 23:1111ee8bcba4 96 AMQP_VALUE value;
AzureIoTClient 23:1111ee8bcba4 97 AMQP_VALUE desc_key;
AzureIoTClient 23:1111ee8bcba4 98 AMQP_VALUE desc_value;
AzureIoTClient 23:1111ee8bcba4 99 AMQP_VALUE map;
AzureIoTClient 23:1111ee8bcba4 100 AMQP_VALUE correlation_id_value;
AzureIoTClient 23:1111ee8bcba4 101 uint64_t correlation_id;
AzureIoTClient 23:1111ee8bcba4 102
AzureIoTClient 23:1111ee8bcba4 103 /* Codes_SRS_AMQP_MANAGEMENT_01_111: [ `on_message_received` shall obtain the correlation Id from the message properties by using `properties_get_correlation_id`. ]*/
AzureIoTClient 23:1111ee8bcba4 104 if (properties_get_correlation_id(response_properties, &correlation_id_value) != 0)
AzureIoTClient 6:641a9672db08 105 {
AzureIoTClient 23:1111ee8bcba4 106 /* Codes_SRS_AMQP_MANAGEMENT_01_114: [ If obtaining the correlation Id fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ] */
AzureIoTClient 23:1111ee8bcba4 107 LogError("Could not retrieve correlation Id");
AzureIoTClient 23:1111ee8bcba4 108 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 109 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 110 result = messaging_delivery_rejected("amqp:internal-error", "Could not get correlation Id from AMQP management response.");
AzureIoTClient 6:641a9672db08 111 }
AzureIoTClient 6:641a9672db08 112 else
AzureIoTClient 6:641a9672db08 113 {
AzureIoTClient 23:1111ee8bcba4 114 if (amqpvalue_get_ulong(correlation_id_value, &correlation_id) != 0)
AzureIoTClient 6:641a9672db08 115 {
AzureIoTClient 23:1111ee8bcba4 116 /* Codes_SRS_AMQP_MANAGEMENT_01_132: [ If any functions manipulating AMQP values, application properties, etc., fail, an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 117 LogError("Could not retrieve correlation Id ulong value");
AzureIoTClient 23:1111ee8bcba4 118 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 119 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 120 result = messaging_delivery_rejected("amqp:internal-error", "Could not get correlation Id from AMQP management response.");
AzureIoTClient 6:641a9672db08 121 }
AzureIoTClient 6:641a9672db08 122 else
AzureIoTClient 6:641a9672db08 123 {
AzureIoTClient 23:1111ee8bcba4 124 /* Codes_SRS_AMQP_MANAGEMENT_01_119: [ `on_message_received` shall obtain the application properties map by calling `amqpvalue_get_inplace_described_value`. ]*/
AzureIoTClient 23:1111ee8bcba4 125 /* Codes_SRS_AMQP_MANAGEMENT_01_070: [ Response messages have the following application-properties: ]*/
AzureIoTClient 23:1111ee8bcba4 126 map = amqpvalue_get_inplace_described_value(application_properties);
AzureIoTClient 23:1111ee8bcba4 127 if (map == NULL)
AzureIoTClient 6:641a9672db08 128 {
AzureIoTClient 23:1111ee8bcba4 129 /* Codes_SRS_AMQP_MANAGEMENT_01_132: [ If any functions manipulating AMQP values, application properties, etc., fail, an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 130 LogError("Could not retrieve application property map");
AzureIoTClient 23:1111ee8bcba4 131 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 132 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 133 result = messaging_delivery_rejected("amqp:internal-error", "Could not get application property map from the application properties in the AMQP management response.");
AzureIoTClient 6:641a9672db08 134 }
AzureIoTClient 6:641a9672db08 135 else
AzureIoTClient 6:641a9672db08 136 {
AzureIoTClient 23:1111ee8bcba4 137 /* Codes_SRS_AMQP_MANAGEMENT_01_120: [ An AMQP value used to lookup the status code shall be created by calling `amqpvalue_create_string` with `status-code` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 138 /* Codes_SRS_AMQP_MANAGEMENT_01_071: [ statusCode integer Yes HTTP response code [RFC2616] ]*/
AzureIoTClient 23:1111ee8bcba4 139 key = amqpvalue_create_string("status-code");
AzureIoTClient 23:1111ee8bcba4 140 if (key == NULL)
AzureIoTClient 6:641a9672db08 141 {
AzureIoTClient 23:1111ee8bcba4 142 /* Codes_SRS_AMQP_MANAGEMENT_01_132: [ If any functions manipulating AMQP values, application properties, etc., fail, an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 143 LogError("Could not create status-code amqp value");
AzureIoTClient 23:1111ee8bcba4 144 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 145 /* Codes_SRS_AMQP_MANAGEMENT_01_135: [ When an error occurs in creating AMQP values (for status code, etc.) `on_message_received` shall call `messaging_delivery_released` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 146 result = messaging_delivery_released();
AzureIoTClient 6:641a9672db08 147 }
AzureIoTClient 1:eab586236bfe 148 else
AzureIoTClient 1:eab586236bfe 149 {
AzureIoTClient 23:1111ee8bcba4 150 /* Codes_SRS_AMQP_MANAGEMENT_01_121: [ The status code shall be looked up in the application properties by using `amqpvalue_get_map_value`. ]*/
AzureIoTClient 23:1111ee8bcba4 151 value = amqpvalue_get_map_value(map, key);
AzureIoTClient 23:1111ee8bcba4 152 if (value == NULL)
AzureIoTClient 1:eab586236bfe 153 {
AzureIoTClient 23:1111ee8bcba4 154 /* Codes_SRS_AMQP_MANAGEMENT_01_122: [ If status code is not found an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 155 LogError("Could not retrieve status code from application properties");
AzureIoTClient 23:1111ee8bcba4 156 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 157 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 158 result = messaging_delivery_rejected("amqp:internal-error", "Could not retrieve status code from the application properties in the AMQP management response.");
AzureIoTClient 1:eab586236bfe 159 }
AzureIoTClient 1:eab586236bfe 160 else
AzureIoTClient 1:eab586236bfe 161 {
AzureIoTClient 23:1111ee8bcba4 162 int32_t status_code;
AzureIoTClient 23:1111ee8bcba4 163 /* Codes_SRS_AMQP_MANAGEMENT_01_133: [ The status code value shall be extracted from the value found in the map by using `amqpvalue_get_int`. ]*/
AzureIoTClient 23:1111ee8bcba4 164 if (amqpvalue_get_int(value, &status_code) != 0)
AzureIoTClient 23:1111ee8bcba4 165 {
AzureIoTClient 23:1111ee8bcba4 166 /* Codes_SRS_AMQP_MANAGEMENT_01_132: [ If any functions manipulating AMQP values, application properties, etc., fail, an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 167 LogError("Could not retrieve status code int value");
AzureIoTClient 23:1111ee8bcba4 168 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 169 /* Codes_SRS_AMQP_MANAGEMENT_01_136: [ When `on_message_received` fails due to errors in parsing the response message `on_message_received` shall call `messaging_delivery_rejected` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 170 result = messaging_delivery_rejected("amqp:internal-error", "Could not retrieve status code value from the application properties in the AMQP management response.");
AzureIoTClient 23:1111ee8bcba4 171 }
AzureIoTClient 23:1111ee8bcba4 172 else
AzureIoTClient 1:eab586236bfe 173 {
AzureIoTClient 23:1111ee8bcba4 174 /* Codes_SRS_AMQP_MANAGEMENT_01_123: [ An AMQP value used to lookup the status description shall be created by calling `amqpvalue_create_string` with `status-description` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 175 /* Codes_SRS_AMQP_MANAGEMENT_01_072: [ statusDescription string No Description of the status. ]*/
AzureIoTClient 23:1111ee8bcba4 176 desc_key = amqpvalue_create_string("status-description");
AzureIoTClient 23:1111ee8bcba4 177 if (desc_key == NULL)
AzureIoTClient 23:1111ee8bcba4 178 {
AzureIoTClient 23:1111ee8bcba4 179 /* Codes_SRS_AMQP_MANAGEMENT_01_132: [ If any functions manipulating AMQP values, application properties, etc., fail, an error shall be indicated to the consumer by calling the `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 180 LogError("Could not create status-description amqp value");
AzureIoTClient 23:1111ee8bcba4 181 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 182 /* Codes_SRS_AMQP_MANAGEMENT_01_135: [ When an error occurs in creating AMQP values (for status code, etc.) `on_message_received` shall call `messaging_delivery_released` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 183 result = messaging_delivery_released();
AzureIoTClient 23:1111ee8bcba4 184 }
AzureIoTClient 23:1111ee8bcba4 185 else
AzureIoTClient 23:1111ee8bcba4 186 {
AzureIoTClient 23:1111ee8bcba4 187 const char* status_description = NULL;
AzureIoTClient 23:1111ee8bcba4 188 LIST_ITEM_HANDLE list_item_handle;
AzureIoTClient 23:1111ee8bcba4 189 bool found = false;
AzureIoTClient 23:1111ee8bcba4 190 bool is_error = false;
AzureIoTClient 1:eab586236bfe 191
AzureIoTClient 23:1111ee8bcba4 192 /* Codes_SRS_AMQP_MANAGEMENT_01_124: [ The status description shall be looked up in the application properties by using `amqpvalue_get_map_value`. ]*/
AzureIoTClient 23:1111ee8bcba4 193 desc_value = amqpvalue_get_map_value(map, desc_key);
AzureIoTClient 23:1111ee8bcba4 194 if (desc_value != NULL)
AzureIoTClient 1:eab586236bfe 195 {
AzureIoTClient 23:1111ee8bcba4 196 /* Codes_SRS_AMQP_MANAGEMENT_01_134: [ The status description value shall be extracted from the value found in the map by using `amqpvalue_get_string`. ]*/
AzureIoTClient 23:1111ee8bcba4 197 if (amqpvalue_get_string(desc_value, &status_description) != 0)
AzureIoTClient 23:1111ee8bcba4 198 {
AzureIoTClient 23:1111ee8bcba4 199 /* Codes_SRS_AMQP_MANAGEMENT_01_125: [ If status description is not found, NULL shall be passed to the user callback as `status_description` argument. ]*/
AzureIoTClient 23:1111ee8bcba4 200 status_description = NULL;
AzureIoTClient 23:1111ee8bcba4 201 }
AzureIoTClient 1:eab586236bfe 202 }
AzureIoTClient 1:eab586236bfe 203 else
AzureIoTClient 1:eab586236bfe 204 {
AzureIoTClient 23:1111ee8bcba4 205 /* Codes_SRS_AMQP_MANAGEMENT_01_125: [ If status description is not found, NULL shall be passed to the user callback as `status_description` argument. ]*/
AzureIoTClient 23:1111ee8bcba4 206 status_description = NULL;
AzureIoTClient 23:1111ee8bcba4 207 }
AzureIoTClient 23:1111ee8bcba4 208
AzureIoTClient 23:1111ee8bcba4 209 list_item_handle = singlylinkedlist_get_head_item(amqp_management->pending_operations);
AzureIoTClient 23:1111ee8bcba4 210 while (list_item_handle != NULL)
AzureIoTClient 23:1111ee8bcba4 211 {
AzureIoTClient 23:1111ee8bcba4 212 /* Codes_SRS_AMQP_MANAGEMENT_01_116: [ Each pending operation item value shall be obtained by calling `singlylinkedlist_item_get_value`. ]*/
AzureIoTClient 23:1111ee8bcba4 213 OPERATION_MESSAGE_INSTANCE* operation_message = (OPERATION_MESSAGE_INSTANCE*)singlylinkedlist_item_get_value(list_item_handle);
AzureIoTClient 23:1111ee8bcba4 214 if (operation_message == NULL)
AzureIoTClient 1:eab586236bfe 215 {
AzureIoTClient 23:1111ee8bcba4 216 /* Codes_SRS_AMQP_MANAGEMENT_01_117: [ If iterating through the pending operations list fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 217 LogError("Could not create status-description amqp value");
AzureIoTClient 23:1111ee8bcba4 218 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 219 /* Codes_SRS_AMQP_MANAGEMENT_01_135: [ When an error occurs in creating AMQP values (for status code, etc.) `on_message_received` shall call `messaging_delivery_released` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 220 result = messaging_delivery_released();
AzureIoTClient 1:eab586236bfe 221 break;
AzureIoTClient 1:eab586236bfe 222 }
AzureIoTClient 1:eab586236bfe 223 else
AzureIoTClient 1:eab586236bfe 224 {
AzureIoTClient 23:1111ee8bcba4 225 AMQP_MANAGEMENT_EXECUTE_OPERATION_RESULT execute_operation_result;
AzureIoTClient 23:1111ee8bcba4 226
AzureIoTClient 23:1111ee8bcba4 227 /* Codes_SRS_AMQP_MANAGEMENT_01_112: [ `on_message_received` shall check if the correlation Id matches the stored message Id of any pending operation. ]*/
AzureIoTClient 23:1111ee8bcba4 228 /* Codes_SRS_AMQP_MANAGEMENT_01_068: [ The correlation-id of the response message MUST be the correlation-id from the request message (if present) ]*/
AzureIoTClient 23:1111ee8bcba4 229 /* Codes_SRS_AMQP_MANAGEMENT_01_069: [ else the message-id from the request message. ]*/
AzureIoTClient 23:1111ee8bcba4 230 if (correlation_id == operation_message->message_id)
AzureIoTClient 23:1111ee8bcba4 231 {
AzureIoTClient 23:1111ee8bcba4 232 /* Codes_SRS_AMQP_MANAGEMENT_01_074: [ Successful operations MUST result in a statusCode in the 2xx range as defined in Section 10.2 of [RFC2616]. ]*/
AzureIoTClient 23:1111ee8bcba4 233 if ((status_code < 200) || (status_code > 299))
AzureIoTClient 23:1111ee8bcba4 234 {
AzureIoTClient 23:1111ee8bcba4 235 /* Codes_SRS_AMQP_MANAGEMENT_01_128: [ If the status indicates that the operation failed, the result callback argument shall be `AMQP_MANAGEMENT_EXECUTE_OPERATION_FAILED_BAD_STATUS`. ]*/
AzureIoTClient 23:1111ee8bcba4 236 /* Codes_SRS_AMQP_MANAGEMENT_01_075: [ Unsuccessful operations MUST NOT result in a statusCode in the 2xx range as defined in Section 10.2 of [RFC2616]. ]*/
AzureIoTClient 23:1111ee8bcba4 237 execute_operation_result = AMQP_MANAGEMENT_EXECUTE_OPERATION_FAILED_BAD_STATUS;
AzureIoTClient 23:1111ee8bcba4 238 }
AzureIoTClient 23:1111ee8bcba4 239 else
AzureIoTClient 23:1111ee8bcba4 240 {
AzureIoTClient 23:1111ee8bcba4 241 /* Codes_SRS_AMQP_MANAGEMENT_01_127: [ If the operation succeeded the result callback argument shall be `AMQP_MANAGEMENT_EXECUTE_OPERATION_OK`. ]*/
AzureIoTClient 23:1111ee8bcba4 242 execute_operation_result = AMQP_MANAGEMENT_EXECUTE_OPERATION_OK;
AzureIoTClient 23:1111ee8bcba4 243 }
AzureIoTClient 23:1111ee8bcba4 244
AzureIoTClient 23:1111ee8bcba4 245 /* Codes_SRS_AMQP_MANAGEMENT_01_126: [ If a corresponding correlation Id is found in the pending operations list, the callback associated with the pending operation shall be called. ]*/
AzureIoTClient 23:1111ee8bcba4 246 operation_message->on_execute_operation_complete(operation_message->callback_context, execute_operation_result, status_code, status_description);
AzureIoTClient 23:1111ee8bcba4 247
AzureIoTClient 23:1111ee8bcba4 248 free(operation_message);
AzureIoTClient 23:1111ee8bcba4 249
AzureIoTClient 23:1111ee8bcba4 250 /* Codes_SRS_AMQP_MANAGEMENT_01_129: [ After calling the callback, the pending operation shall be removed from the pending operations list by calling `singlylinkedlist_remove`. ]*/
AzureIoTClient 23:1111ee8bcba4 251 if (singlylinkedlist_remove(amqp_management->pending_operations, list_item_handle) != 0)
AzureIoTClient 23:1111ee8bcba4 252 {
AzureIoTClient 23:1111ee8bcba4 253 LogError("Cannot remove pending operation");
AzureIoTClient 23:1111ee8bcba4 254 is_error = true;
AzureIoTClient 23:1111ee8bcba4 255 break;
AzureIoTClient 23:1111ee8bcba4 256 }
AzureIoTClient 23:1111ee8bcba4 257 else
AzureIoTClient 23:1111ee8bcba4 258 {
AzureIoTClient 23:1111ee8bcba4 259 found = true;
AzureIoTClient 23:1111ee8bcba4 260 }
AzureIoTClient 23:1111ee8bcba4 261
AzureIoTClient 23:1111ee8bcba4 262 break;
AzureIoTClient 23:1111ee8bcba4 263 }
AzureIoTClient 1:eab586236bfe 264 }
Azure.IoT Build 0:6ae2f7bca550 265
AzureIoTClient 23:1111ee8bcba4 266 /* Codes_SRS_AMQP_MANAGEMENT_01_115: [ Iterating through the pending operations shall be done by using `singlylinkedlist_get_head_item` and `singlylinkedlist_get_next_item` until the enm of the pending operations singly linked list is reached. ]*/
AzureIoTClient 23:1111ee8bcba4 267 /* Codes_SRS_AMQP_MANAGEMENT_01_117: [ If iterating through the pending operations list fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 268 list_item_handle = singlylinkedlist_get_next_item(list_item_handle);
AzureIoTClient 23:1111ee8bcba4 269 }
AzureIoTClient 23:1111ee8bcba4 270
AzureIoTClient 23:1111ee8bcba4 271 if (is_error)
AzureIoTClient 23:1111ee8bcba4 272 {
AzureIoTClient 23:1111ee8bcba4 273 /* Codes_SRS_AMQP_MANAGEMENT_01_117: [ If iterating through the pending operations list fails, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 274 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 275 /* Codes_SRS_AMQP_MANAGEMENT_01_135: [ When an error occurs in creating AMQP values (for status code, etc.) `on_message_received` shall call `messaging_delivery_released` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 276 result = messaging_delivery_released();
AzureIoTClient 1:eab586236bfe 277 }
AzureIoTClient 23:1111ee8bcba4 278 else
AzureIoTClient 23:1111ee8bcba4 279 {
AzureIoTClient 23:1111ee8bcba4 280 if (!found)
AzureIoTClient 23:1111ee8bcba4 281 {
AzureIoTClient 23:1111ee8bcba4 282 /* Codes_SRS_AMQP_MANAGEMENT_01_118: [ If no pending operation is found matching the correlation Id, an error shall be indicated by calling `on_amqp_management_error` and passing the `on_amqp_management_error_context` to it. ]*/
AzureIoTClient 23:1111ee8bcba4 283 LogError("Could not match AMQP management response to request");
AzureIoTClient 23:1111ee8bcba4 284 amqp_management->on_amqp_management_error(amqp_management->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 285 /* Codes_SRS_AMQP_MANAGEMENT_01_135: [ When an error occurs in creating AMQP values (for status code, etc.) `on_message_received` shall call `messaging_delivery_released` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 286 result = messaging_delivery_rejected("amqp:internal-error", "Could not match AMQP management response to request");
AzureIoTClient 23:1111ee8bcba4 287 }
AzureIoTClient 23:1111ee8bcba4 288 else
AzureIoTClient 23:1111ee8bcba4 289 {
AzureIoTClient 23:1111ee8bcba4 290 /* Codes_SRS_AMQP_MANAGEMENT_01_130: [ The `on_message_received` shall call `messaging_delivery_accepted` and return the created delivery AMQP value. ]*/
AzureIoTClient 23:1111ee8bcba4 291 result = messaging_delivery_accepted();
AzureIoTClient 23:1111ee8bcba4 292 }
AzureIoTClient 23:1111ee8bcba4 293 }
AzureIoTClient 23:1111ee8bcba4 294
AzureIoTClient 23:1111ee8bcba4 295 if (desc_value != NULL)
AzureIoTClient 23:1111ee8bcba4 296 {
AzureIoTClient 23:1111ee8bcba4 297 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 298 amqpvalue_destroy(desc_value);
AzureIoTClient 23:1111ee8bcba4 299 }
AzureIoTClient 23:1111ee8bcba4 300
AzureIoTClient 23:1111ee8bcba4 301 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 302 amqpvalue_destroy(desc_key);
AzureIoTClient 1:eab586236bfe 303 }
AzureIoTClient 1:eab586236bfe 304 }
Azure.IoT Build 0:6ae2f7bca550 305
AzureIoTClient 23:1111ee8bcba4 306 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 307 amqpvalue_destroy(value);
AzureIoTClient 6:641a9672db08 308 }
AzureIoTClient 23:1111ee8bcba4 309
AzureIoTClient 23:1111ee8bcba4 310 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 311 amqpvalue_destroy(key);
AzureIoTClient 6:641a9672db08 312 }
AzureIoTClient 6:641a9672db08 313 }
AzureIoTClient 6:641a9672db08 314 }
AzureIoTClient 6:641a9672db08 315 }
AzureIoTClient 23:1111ee8bcba4 316
AzureIoTClient 23:1111ee8bcba4 317 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 318 properties_destroy(response_properties);
AzureIoTClient 6:641a9672db08 319 }
Azure.IoT Build 0:6ae2f7bca550 320
AzureIoTClient 23:1111ee8bcba4 321 /* Codes_SRS_AMQP_MANAGEMENT_01_131: [ All temporary values like AMQP values used as keys shall be freed before exiting the callback. ]*/
AzureIoTClient 23:1111ee8bcba4 322 application_properties_destroy(application_properties);
AzureIoTClient 6:641a9672db08 323 }
AzureIoTClient 6:641a9672db08 324 }
Azure.IoT Build 0:6ae2f7bca550 325
AzureIoTClient 6:641a9672db08 326 return result;
Azure.IoT Build 0:6ae2f7bca550 327 }
Azure.IoT Build 0:6ae2f7bca550 328
Azure.IoT Build 0:6ae2f7bca550 329 static void on_message_sender_state_changed(void* context, MESSAGE_SENDER_STATE new_state, MESSAGE_SENDER_STATE previous_state)
Azure.IoT Build 0:6ae2f7bca550 330 {
AzureIoTClient 23:1111ee8bcba4 331 if (context == NULL)
AzureIoTClient 6:641a9672db08 332 {
AzureIoTClient 23:1111ee8bcba4 333 /* Codes_SRS_AMQP_MANAGEMENT_01_137: [ When `on_message_sender_state_changed` is called with NULL `context`, it shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 334 LogError("on_message_sender_state_changed called with NULL context");
AzureIoTClient 23:1111ee8bcba4 335 }
AzureIoTClient 23:1111ee8bcba4 336 else
AzureIoTClient 23:1111ee8bcba4 337 {
AzureIoTClient 23:1111ee8bcba4 338 /* Codes_SRS_AMQP_MANAGEMENT_01_138: [ When `on_message_sender_state_changed` is called and the `new_state` is different than `previous_state`, the following actions shall be taken: ]*/
AzureIoTClient 23:1111ee8bcba4 339 /* Codes_SRS_AMQP_MANAGEMENT_01_148: [ When no state change is detected, `on_message_sender_state_changed` shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 340 if (new_state != previous_state)
AzureIoTClient 22:524bded3f7a8 341 {
AzureIoTClient 23:1111ee8bcba4 342 AMQP_MANAGEMENT_INSTANCE* amqp_management_instance = (AMQP_MANAGEMENT_INSTANCE*)context;
AzureIoTClient 23:1111ee8bcba4 343 switch (amqp_management_instance->amqp_management_state)
AzureIoTClient 23:1111ee8bcba4 344 {
AzureIoTClient 23:1111ee8bcba4 345 default:
AzureIoTClient 23:1111ee8bcba4 346 break;
AzureIoTClient 22:524bded3f7a8 347
AzureIoTClient 23:1111ee8bcba4 348 /* Codes_SRS_AMQP_MANAGEMENT_01_139: [ For the current state of AMQP management being `OPENING`: ]*/
AzureIoTClient 23:1111ee8bcba4 349 case AMQP_MANAGEMENT_STATE_OPENING:
AzureIoTClient 22:524bded3f7a8 350 {
AzureIoTClient 23:1111ee8bcba4 351 switch (new_state)
AzureIoTClient 23:1111ee8bcba4 352 {
AzureIoTClient 23:1111ee8bcba4 353 case MESSAGE_SENDER_STATE_OPENING:
AzureIoTClient 23:1111ee8bcba4 354 /* Codes_SRS_AMQP_MANAGEMENT_01_165: [ - If `new_state` is `MESSAGE_SENDER_STATE_OPEING` the transition shall be ignored. ]*/
AzureIoTClient 23:1111ee8bcba4 355 break;
AzureIoTClient 23:1111ee8bcba4 356
AzureIoTClient 23:1111ee8bcba4 357 default:
AzureIoTClient 23:1111ee8bcba4 358 /* Codes_SRS_AMQP_MANAGEMENT_01_140: [ - If `new_state` is `MESSAGE_SENDER_STATE_IDLE`, `MESSAGE_SENDER_STATE_CLOSING` or `MESSAGE_SENDER_STATE_ERROR`, the `on_amqp_management_open_complete` callback shall be called with `AMQP_MANAGEMENT_OPEN_ERROR`, while also passing the context passed in `amqp_management_open_async`. ]*/
AzureIoTClient 23:1111ee8bcba4 359 case MESSAGE_SENDER_STATE_IDLE:
AzureIoTClient 23:1111ee8bcba4 360 case MESSAGE_SENDER_STATE_CLOSING:
AzureIoTClient 23:1111ee8bcba4 361 case MESSAGE_SENDER_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 362 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
AzureIoTClient 23:1111ee8bcba4 363 amqp_management_instance->on_amqp_management_open_complete(amqp_management_instance->on_amqp_management_open_complete_context, AMQP_MANAGEMENT_OPEN_ERROR);
AzureIoTClient 23:1111ee8bcba4 364 break;
AzureIoTClient 22:524bded3f7a8 365
AzureIoTClient 23:1111ee8bcba4 366 case MESSAGE_SENDER_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 367 amqp_management_instance->sender_connected = -1;
AzureIoTClient 23:1111ee8bcba4 368 /* Codes_SRS_AMQP_MANAGEMENT_01_142: [ - If `new_state` is `MESSAGE_SENDER_STATE_OPEN` and the message receiver did not yet indicate its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall not be called.]*/
AzureIoTClient 23:1111ee8bcba4 369 if (amqp_management_instance->receiver_connected != 0)
AzureIoTClient 23:1111ee8bcba4 370 {
AzureIoTClient 23:1111ee8bcba4 371 /* Codes_SRS_AMQP_MANAGEMENT_01_141: [ - If `new_state` is `MESSAGE_SENDER_STATE_OPEN` and the message receiver already indicated its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall be called with `AMQP_MANAGEMENT_OPEN_OK`, while also passing the context passed in `amqp_management_open_async`. ]*/
AzureIoTClient 23:1111ee8bcba4 372 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_OPEN;
AzureIoTClient 23:1111ee8bcba4 373 amqp_management_instance->on_amqp_management_open_complete(amqp_management_instance->on_amqp_management_open_complete_context, AMQP_MANAGEMENT_OPEN_OK);
AzureIoTClient 23:1111ee8bcba4 374 }
AzureIoTClient 23:1111ee8bcba4 375 break;
AzureIoTClient 23:1111ee8bcba4 376 }
AzureIoTClient 23:1111ee8bcba4 377 break;
AzureIoTClient 23:1111ee8bcba4 378 }
AzureIoTClient 23:1111ee8bcba4 379 /* Codes_SRS_AMQP_MANAGEMENT_01_144: [ For the current state of AMQP management being `OPEN`: ]*/
AzureIoTClient 23:1111ee8bcba4 380 case AMQP_MANAGEMENT_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 381 {
AzureIoTClient 23:1111ee8bcba4 382 switch (new_state)
AzureIoTClient 23:1111ee8bcba4 383 {
AzureIoTClient 23:1111ee8bcba4 384 default:
AzureIoTClient 23:1111ee8bcba4 385 /* Codes_SRS_AMQP_MANAGEMENT_01_143: [ - If `new_state` is `MESSAGE_SENDER_STATE_IDLE`, `MESSAGE_SENDER_STATE_OPENING`, `MESSAGE_SENDER_STATE_CLOSING` or `MESSAGE_SENDER_STATE_ERROR` the `on_amqp_management_error` callback shall be invoked while passing the `on_amqp_management_error_context` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 386 case MESSAGE_SENDER_STATE_IDLE:
AzureIoTClient 23:1111ee8bcba4 387 case MESSAGE_SENDER_STATE_CLOSING:
AzureIoTClient 23:1111ee8bcba4 388 case MESSAGE_SENDER_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 389 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_ERROR;
AzureIoTClient 23:1111ee8bcba4 390 amqp_management_instance->on_amqp_management_error(amqp_management_instance->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 391 break;
Azure.IoT Build 0:6ae2f7bca550 392
AzureIoTClient 23:1111ee8bcba4 393 case MESSAGE_SENDER_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 394 /* Codes_SRS_AMQP_MANAGEMENT_01_145: [ - If `new_state` is `MESSAGE_SENDER_STATE_OPEN`, `on_message_sender_state_changed` shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 395 break;
AzureIoTClient 23:1111ee8bcba4 396 }
AzureIoTClient 23:1111ee8bcba4 397 break;
AzureIoTClient 23:1111ee8bcba4 398 }
AzureIoTClient 23:1111ee8bcba4 399 /* Codes_SRS_AMQP_MANAGEMENT_01_146: [ For the current state of AMQP management being `ERROR`: ]*/
AzureIoTClient 23:1111ee8bcba4 400 case AMQP_MANAGEMENT_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 401 /* Codes_SRS_AMQP_MANAGEMENT_01_147: [ - All state transitions shall be ignored. ]*/
AzureIoTClient 23:1111ee8bcba4 402 break;
AzureIoTClient 23:1111ee8bcba4 403 }
AzureIoTClient 22:524bded3f7a8 404 }
AzureIoTClient 6:641a9672db08 405 }
Azure.IoT Build 0:6ae2f7bca550 406 }
Azure.IoT Build 0:6ae2f7bca550 407
Azure.IoT Build 0:6ae2f7bca550 408 static void on_message_receiver_state_changed(const void* context, MESSAGE_RECEIVER_STATE new_state, MESSAGE_RECEIVER_STATE previous_state)
Azure.IoT Build 0:6ae2f7bca550 409 {
AzureIoTClient 23:1111ee8bcba4 410 if (context == NULL)
AzureIoTClient 6:641a9672db08 411 {
AzureIoTClient 23:1111ee8bcba4 412 /* Codes_SRS_AMQP_MANAGEMENT_01_149: [ When `on_message_receiver_state_changed` is called with NULL `context`, it shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 413 LogError("on_message_receiver_state_changed called with NULL context");
AzureIoTClient 23:1111ee8bcba4 414 }
AzureIoTClient 23:1111ee8bcba4 415 else
AzureIoTClient 23:1111ee8bcba4 416 {
AzureIoTClient 23:1111ee8bcba4 417 /* Codes_SRS_AMQP_MANAGEMENT_01_150: [ When `on_message_receiver_state_changed` is called and the `new_state` is different than `previous_state`, the following actions shall be taken: ]*/
AzureIoTClient 23:1111ee8bcba4 418 /* Codes_SRS_AMQP_MANAGEMENT_01_160: [ When no state change is detected, `on_message_receiver_state_changed` shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 419 if (new_state != previous_state)
AzureIoTClient 22:524bded3f7a8 420 {
AzureIoTClient 23:1111ee8bcba4 421 AMQP_MANAGEMENT_INSTANCE* amqp_management_instance = (AMQP_MANAGEMENT_INSTANCE*)context;
AzureIoTClient 23:1111ee8bcba4 422 switch (amqp_management_instance->amqp_management_state)
AzureIoTClient 23:1111ee8bcba4 423 {
AzureIoTClient 23:1111ee8bcba4 424 default:
AzureIoTClient 23:1111ee8bcba4 425 break;
AzureIoTClient 22:524bded3f7a8 426
AzureIoTClient 23:1111ee8bcba4 427 /* Codes_SRS_AMQP_MANAGEMENT_01_151: [ For the current state of AMQP management being `OPENING`: ]*/
AzureIoTClient 23:1111ee8bcba4 428 case AMQP_MANAGEMENT_STATE_OPENING:
AzureIoTClient 22:524bded3f7a8 429 {
AzureIoTClient 23:1111ee8bcba4 430 switch (new_state)
AzureIoTClient 23:1111ee8bcba4 431 {
AzureIoTClient 23:1111ee8bcba4 432 case MESSAGE_RECEIVER_STATE_OPENING:
AzureIoTClient 23:1111ee8bcba4 433 /* Codes_SRS_AMQP_MANAGEMENT_01_164: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_OPEING` the transition shall be ignored. ]*/
AzureIoTClient 23:1111ee8bcba4 434 break;
AzureIoTClient 23:1111ee8bcba4 435
AzureIoTClient 23:1111ee8bcba4 436 default:
AzureIoTClient 23:1111ee8bcba4 437 /* Codes_SRS_AMQP_MANAGEMENT_01_152: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_IDLE`, `MESSAGE_RECEIVER_STATE_CLOSING` or `MESSAGE_RECEIVER_STATE_ERROR`, the `on_amqp_management_open_complete` callback shall be called with `AMQP_MANAGEMENT_OPEN_ERROR`, while also passing the context passed in `amqp_management_open_async`. ]*/
AzureIoTClient 23:1111ee8bcba4 438 case MESSAGE_RECEIVER_STATE_IDLE:
AzureIoTClient 23:1111ee8bcba4 439 case MESSAGE_RECEIVER_STATE_CLOSING:
AzureIoTClient 23:1111ee8bcba4 440 case MESSAGE_RECEIVER_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 441 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
AzureIoTClient 23:1111ee8bcba4 442 amqp_management_instance->on_amqp_management_open_complete(amqp_management_instance->on_amqp_management_open_complete_context, AMQP_MANAGEMENT_OPEN_ERROR);
AzureIoTClient 23:1111ee8bcba4 443 break;
AzureIoTClient 22:524bded3f7a8 444
AzureIoTClient 23:1111ee8bcba4 445 case MESSAGE_RECEIVER_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 446 amqp_management_instance->receiver_connected = -1;
AzureIoTClient 23:1111ee8bcba4 447 /* Codes_SRS_AMQP_MANAGEMENT_01_154: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_OPEN` and the message sender did not yet indicate its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall not be called. ]*/
AzureIoTClient 23:1111ee8bcba4 448 if (amqp_management_instance->sender_connected != 0)
AzureIoTClient 23:1111ee8bcba4 449 {
AzureIoTClient 23:1111ee8bcba4 450 /* Codes_SRS_AMQP_MANAGEMENT_01_153: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_OPEN` and the message sender already indicated its state as `MESSAGE_RECEIVER_STATE_OPEN`, the `on_amqp_management_open_complete` callback shall be called with `AMQP_MANAGEMENT_OPEN_OK`, while also passing the context passed in `amqp_management_open_async`. ]*/
AzureIoTClient 23:1111ee8bcba4 451 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_OPEN;
AzureIoTClient 23:1111ee8bcba4 452 amqp_management_instance->on_amqp_management_open_complete(amqp_management_instance->on_amqp_management_open_complete_context, AMQP_MANAGEMENT_OPEN_OK);
AzureIoTClient 23:1111ee8bcba4 453 }
AzureIoTClient 23:1111ee8bcba4 454 break;
AzureIoTClient 23:1111ee8bcba4 455 }
AzureIoTClient 23:1111ee8bcba4 456 break;
AzureIoTClient 23:1111ee8bcba4 457 }
AzureIoTClient 23:1111ee8bcba4 458 /* Codes_SRS_AMQP_MANAGEMENT_01_155: [ For the current state of AMQP management being `OPEN`: ]*/
AzureIoTClient 23:1111ee8bcba4 459 case AMQP_MANAGEMENT_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 460 {
AzureIoTClient 23:1111ee8bcba4 461 switch (new_state)
AzureIoTClient 23:1111ee8bcba4 462 {
AzureIoTClient 23:1111ee8bcba4 463 default:
AzureIoTClient 23:1111ee8bcba4 464 /* Codes_SRS_AMQP_MANAGEMENT_01_156: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_IDLE`, `MESSAGE_RECEIVER_STATE_OPENING`, `MESSAGE_RECEIVER_STATE_CLOSING` or `MESSAGE_RECEIVER_STATE_ERROR` the `on_amqp_management_error` callback shall be invoked while passing the `on_amqp_management_error_context` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 465 case MESSAGE_RECEIVER_STATE_IDLE:
AzureIoTClient 23:1111ee8bcba4 466 case MESSAGE_RECEIVER_STATE_CLOSING:
AzureIoTClient 23:1111ee8bcba4 467 case MESSAGE_RECEIVER_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 468 amqp_management_instance->amqp_management_state = AMQP_MANAGEMENT_STATE_ERROR;
AzureIoTClient 23:1111ee8bcba4 469 amqp_management_instance->on_amqp_management_error(amqp_management_instance->on_amqp_management_error_context);
AzureIoTClient 23:1111ee8bcba4 470 break;
Azure.IoT Build 0:6ae2f7bca550 471
AzureIoTClient 23:1111ee8bcba4 472 case MESSAGE_RECEIVER_STATE_OPEN:
AzureIoTClient 23:1111ee8bcba4 473 /* Codes_SRS_AMQP_MANAGEMENT_01_157: [ - If `new_state` is `MESSAGE_RECEIVER_STATE_OPEN`, `on_message_receiver_state_changed` shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 474 break;
AzureIoTClient 23:1111ee8bcba4 475 }
AzureIoTClient 23:1111ee8bcba4 476 break;
AzureIoTClient 23:1111ee8bcba4 477 }
AzureIoTClient 23:1111ee8bcba4 478 /* Codes_SRS_AMQP_MANAGEMENT_01_158: [ For the current state of AMQP management being `ERROR`: ]*/
AzureIoTClient 23:1111ee8bcba4 479 case AMQP_MANAGEMENT_STATE_ERROR:
AzureIoTClient 23:1111ee8bcba4 480 /* Codes_SRS_AMQP_MANAGEMENT_01_159: [ - All state transitions shall be ignored. ]*/
AzureIoTClient 23:1111ee8bcba4 481 break;
AzureIoTClient 23:1111ee8bcba4 482 }
AzureIoTClient 22:524bded3f7a8 483 }
AzureIoTClient 6:641a9672db08 484 }
Azure.IoT Build 0:6ae2f7bca550 485 }
Azure.IoT Build 0:6ae2f7bca550 486
AzureIoTClient 23:1111ee8bcba4 487 static int set_message_id(MESSAGE_HANDLE message, uint64_t next_message_id)
Azure.IoT Build 0:6ae2f7bca550 488 {
AzureIoTClient 23:1111ee8bcba4 489 int result;
AzureIoTClient 23:1111ee8bcba4 490 PROPERTIES_HANDLE properties;
Azure.IoT Build 0:6ae2f7bca550 491
AzureIoTClient 23:1111ee8bcba4 492 /* Codes_SRS_AMQP_MANAGEMENT_01_094: [ In order to set the message Id on the message, the properties shall be obtained by calling `message_get_properties`. ]*/
AzureIoTClient 6:641a9672db08 493 if (message_get_properties(message, &properties) != 0)
AzureIoTClient 6:641a9672db08 494 {
AzureIoTClient 23:1111ee8bcba4 495 /* Codes_SRS_AMQP_MANAGEMENT_01_098: [ If any API fails while setting the message Id, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 496 LogError("Could not retrieve message properties");
AzureIoTClient 19:000ab4e6a2c1 497 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 498 }
AzureIoTClient 6:641a9672db08 499 else
AzureIoTClient 6:641a9672db08 500 {
AzureIoTClient 23:1111ee8bcba4 501 /* Codes_SRS_AMQP_MANAGEMENT_01_099: [ If the properties were not set on the message, a new properties instance shall be created by calling `properties_create`. ]*/
AzureIoTClient 21:f9c433d8e6ca 502 if (properties == NULL)
AzureIoTClient 21:f9c433d8e6ca 503 {
AzureIoTClient 21:f9c433d8e6ca 504 properties = properties_create();
AzureIoTClient 21:f9c433d8e6ca 505 }
AzureIoTClient 21:f9c433d8e6ca 506
AzureIoTClient 21:f9c433d8e6ca 507 if (properties == NULL)
AzureIoTClient 6:641a9672db08 508 {
AzureIoTClient 23:1111ee8bcba4 509 /* Codes_SRS_AMQP_MANAGEMENT_01_098: [ If any API fails while setting the message Id, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 510 LogError("Could not create message properties");
AzureIoTClient 19:000ab4e6a2c1 511 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 512 }
AzureIoTClient 6:641a9672db08 513 else
AzureIoTClient 6:641a9672db08 514 {
AzureIoTClient 23:1111ee8bcba4 515 /* Codes_SRS_AMQP_MANAGEMENT_01_095: [ A message Id with the next ulong value to be used shall be created by calling `amqpvalue_create_message_id_ulong`. ]*/
AzureIoTClient 21:f9c433d8e6ca 516 AMQP_VALUE message_id = amqpvalue_create_message_id_ulong(next_message_id);
AzureIoTClient 21:f9c433d8e6ca 517 if (message_id == NULL)
AzureIoTClient 21:f9c433d8e6ca 518 {
AzureIoTClient 23:1111ee8bcba4 519 /* Codes_SRS_AMQP_MANAGEMENT_01_098: [ If any API fails while setting the message Id, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 520 LogError("Could not create message id value");
AzureIoTClient 21:f9c433d8e6ca 521 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 522 }
AzureIoTClient 21:f9c433d8e6ca 523 else
AzureIoTClient 21:f9c433d8e6ca 524 {
AzureIoTClient 23:1111ee8bcba4 525 /* Codes_SRS_AMQP_MANAGEMENT_01_096: [ The message Id value shall be set on the properties by calling `properties_set_message_id`. ]*/
AzureIoTClient 21:f9c433d8e6ca 526 if (properties_set_message_id(properties, message_id) != 0)
AzureIoTClient 21:f9c433d8e6ca 527 {
AzureIoTClient 23:1111ee8bcba4 528 /* Codes_SRS_AMQP_MANAGEMENT_01_098: [ If any API fails while setting the message Id, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 529 LogError("Could not set message Id on the properties");
AzureIoTClient 21:f9c433d8e6ca 530 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 531 }
AzureIoTClient 23:1111ee8bcba4 532 /* Codes_SRS_AMQP_MANAGEMENT_01_097: [ The properties thus modified to contain the message Id shall be set on the message by calling `message_set_properties`. ]*/
AzureIoTClient 23:1111ee8bcba4 533 else if (message_set_properties(message, properties) != 0)
AzureIoTClient 23:1111ee8bcba4 534 {
AzureIoTClient 23:1111ee8bcba4 535 /* Codes_SRS_AMQP_MANAGEMENT_01_098: [ If any API fails while setting the message Id, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 536 LogError("Could not set message properties");
AzureIoTClient 23:1111ee8bcba4 537 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 538 }
AzureIoTClient 23:1111ee8bcba4 539 else
AzureIoTClient 23:1111ee8bcba4 540 {
AzureIoTClient 23:1111ee8bcba4 541 result = 0;
AzureIoTClient 23:1111ee8bcba4 542 }
AzureIoTClient 21:f9c433d8e6ca 543
AzureIoTClient 21:f9c433d8e6ca 544 amqpvalue_destroy(message_id);
AzureIoTClient 21:f9c433d8e6ca 545 }
AzureIoTClient 21:f9c433d8e6ca 546
AzureIoTClient 23:1111ee8bcba4 547 /* Codes_SRS_AMQP_MANAGEMENT_01_100: [ After setting the properties, the properties instance shall be freed by `properties_destroy`. ]*/
AzureIoTClient 21:f9c433d8e6ca 548 properties_destroy(properties);
AzureIoTClient 6:641a9672db08 549 }
AzureIoTClient 6:641a9672db08 550 }
Azure.IoT Build 0:6ae2f7bca550 551
AzureIoTClient 6:641a9672db08 552 return result;
Azure.IoT Build 0:6ae2f7bca550 553 }
Azure.IoT Build 0:6ae2f7bca550 554
Azure.IoT Build 0:6ae2f7bca550 555 static int add_string_key_value_pair_to_map(AMQP_VALUE map, const char* key, const char* value)
Azure.IoT Build 0:6ae2f7bca550 556 {
AzureIoTClient 6:641a9672db08 557 int result;
Azure.IoT Build 0:6ae2f7bca550 558
AzureIoTClient 23:1111ee8bcba4 559 /* Codes_SRS_AMQP_MANAGEMENT_01_084: [ For each of the arguments `operation`, `type` and `locales` an AMQP value of type string shall be created by calling `amqpvalue_create_string` in order to be used as key in the application properties map. ]*/
AzureIoTClient 6:641a9672db08 560 AMQP_VALUE key_value = amqpvalue_create_string(key);
AzureIoTClient 23:1111ee8bcba4 561 if (key_value == NULL)
AzureIoTClient 6:641a9672db08 562 {
AzureIoTClient 23:1111ee8bcba4 563 /* Codes_SRS_AMQP_MANAGEMENT_01_090: [ If any APIs used to create and set the application properties on the message fails, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 564 LogError("Could not create key value for %s", key);
AzureIoTClient 19:000ab4e6a2c1 565 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 566 }
AzureIoTClient 6:641a9672db08 567 else
AzureIoTClient 6:641a9672db08 568 {
AzureIoTClient 23:1111ee8bcba4 569 /* Codes_SRS_AMQP_MANAGEMENT_01_085: [ For each of the arguments `operation`, `type` and `locales` an AMQP value of type string containing the argument value shall be created by calling `amqpvalue_create_string` in order to be used as value in the application properties map. ]*/
AzureIoTClient 6:641a9672db08 570 AMQP_VALUE value_value = amqpvalue_create_string(value);
AzureIoTClient 6:641a9672db08 571 if (value_value == NULL)
AzureIoTClient 6:641a9672db08 572 {
AzureIoTClient 23:1111ee8bcba4 573 /* Codes_SRS_AMQP_MANAGEMENT_01_090: [ If any APIs used to create and set the application properties on the message fails, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 574 LogError("Could not create value for key %s", key);
AzureIoTClient 19:000ab4e6a2c1 575 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 576 }
AzureIoTClient 6:641a9672db08 577 else
AzureIoTClient 6:641a9672db08 578 {
AzureIoTClient 23:1111ee8bcba4 579 /* Codes_SRS_AMQP_MANAGEMENT_01_086: [ The key/value pairs for `operation`, `type` and `locales` shall be added to the application properties map by calling `amqpvalue_set_map_value`. ]*/
AzureIoTClient 6:641a9672db08 580 if (amqpvalue_set_map_value(map, key_value, value_value) != 0)
AzureIoTClient 6:641a9672db08 581 {
AzureIoTClient 23:1111ee8bcba4 582 /* Codes_SRS_AMQP_MANAGEMENT_01_090: [ If any APIs used to create and set the application properties on the message fails, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 583 LogError("Could not set the value in the map for key %s", key);
AzureIoTClient 19:000ab4e6a2c1 584 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 585 }
AzureIoTClient 6:641a9672db08 586 else
AzureIoTClient 6:641a9672db08 587 {
AzureIoTClient 6:641a9672db08 588 result = 0;
AzureIoTClient 6:641a9672db08 589 }
Azure.IoT Build 0:6ae2f7bca550 590
AzureIoTClient 23:1111ee8bcba4 591 amqpvalue_destroy(value_value);
AzureIoTClient 6:641a9672db08 592 }
Azure.IoT Build 0:6ae2f7bca550 593
AzureIoTClient 23:1111ee8bcba4 594 amqpvalue_destroy(key_value);
AzureIoTClient 6:641a9672db08 595 }
Azure.IoT Build 0:6ae2f7bca550 596
AzureIoTClient 6:641a9672db08 597 return result;
Azure.IoT Build 0:6ae2f7bca550 598 }
Azure.IoT Build 0:6ae2f7bca550 599
AzureIoTClient 22:524bded3f7a8 600 AMQP_MANAGEMENT_HANDLE amqp_management_create(SESSION_HANDLE session, const char* management_node)
Azure.IoT Build 0:6ae2f7bca550 601 {
AzureIoTClient 6:641a9672db08 602 AMQP_MANAGEMENT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 603
AzureIoTClient 23:1111ee8bcba4 604 if ((session == NULL) ||
AzureIoTClient 23:1111ee8bcba4 605 (management_node == NULL))
AzureIoTClient 6:641a9672db08 606 {
AzureIoTClient 23:1111ee8bcba4 607 /* Codes_SRS_AMQP_MANAGEMENT_01_002: [ If `session` or `management_node` is NULL then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 608 LogError("Bad arguments: session = %p, management_node = %p", session, management_node);
AzureIoTClient 23:1111ee8bcba4 609 result = NULL;
AzureIoTClient 23:1111ee8bcba4 610 }
AzureIoTClient 23:1111ee8bcba4 611 else if (strlen(management_node) == 0)
AzureIoTClient 23:1111ee8bcba4 612 {
AzureIoTClient 23:1111ee8bcba4 613 /* Codes_SRS_AMQP_MANAGEMENT_01_030: [ If `management_node` is an empty string, then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 614 LogError("Empty string management node");
AzureIoTClient 6:641a9672db08 615 result = NULL;
AzureIoTClient 6:641a9672db08 616 }
AzureIoTClient 6:641a9672db08 617 else
AzureIoTClient 6:641a9672db08 618 {
AzureIoTClient 23:1111ee8bcba4 619 /* Codes_SRS_AMQP_MANAGEMENT_01_001: [ `amqp_management_create` shall create a new CBS instance and on success return a non-NULL handle to it. ]*/
AzureIoTClient 21:f9c433d8e6ca 620 result = (AMQP_MANAGEMENT_INSTANCE*)malloc(sizeof(AMQP_MANAGEMENT_INSTANCE));
AzureIoTClient 23:1111ee8bcba4 621 if (result == NULL)
AzureIoTClient 6:641a9672db08 622 {
AzureIoTClient 23:1111ee8bcba4 623 /* Codes_SRS_AMQP_MANAGEMENT_01_005: [ If allocating memory for the new handle fails, `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 624 LogError("Cannot allocate memory for AMQP management handle");
AzureIoTClient 23:1111ee8bcba4 625 }
AzureIoTClient 23:1111ee8bcba4 626 else
AzureIoTClient 23:1111ee8bcba4 627 {
AzureIoTClient 6:641a9672db08 628 result->sender_connected = 0;
AzureIoTClient 6:641a9672db08 629 result->receiver_connected = 0;
AzureIoTClient 22:524bded3f7a8 630 result->on_amqp_management_open_complete = NULL;
AzureIoTClient 22:524bded3f7a8 631 result->on_amqp_management_open_complete_context = NULL;
AzureIoTClient 22:524bded3f7a8 632 result->on_amqp_management_error = NULL;
AzureIoTClient 22:524bded3f7a8 633 result->on_amqp_management_error_context = NULL;
AzureIoTClient 21:f9c433d8e6ca 634 result->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
Azure.IoT Build 0:6ae2f7bca550 635
AzureIoTClient 23:1111ee8bcba4 636 /* Codes_SRS_AMQP_MANAGEMENT_01_003: [ `amqp_management_create` shall create a singly linked list for pending operations by calling `singlylinkedlist_create`. ]*/
AzureIoTClient 23:1111ee8bcba4 637 result->pending_operations = singlylinkedlist_create();
AzureIoTClient 23:1111ee8bcba4 638 if (result->pending_operations == NULL)
AzureIoTClient 6:641a9672db08 639 {
AzureIoTClient 23:1111ee8bcba4 640 /* Codes_SRS_AMQP_MANAGEMENT_01_004: [ If `singlylinkedlist_create` fails, `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 641 LogError("Cannot create pending operations list");
AzureIoTClient 21:f9c433d8e6ca 642 free(result);
AzureIoTClient 6:641a9672db08 643 result = NULL;
AzureIoTClient 6:641a9672db08 644 }
AzureIoTClient 6:641a9672db08 645 else
AzureIoTClient 6:641a9672db08 646 {
AzureIoTClient 23:1111ee8bcba4 647 /* Codes_SRS_AMQP_MANAGEMENT_01_010: [ The `source` argument shall be a value created by calling `messaging_create_source` with `management_node` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 648 AMQP_VALUE source = messaging_create_source(management_node);
AzureIoTClient 23:1111ee8bcba4 649 if (source == NULL)
AzureIoTClient 6:641a9672db08 650 {
AzureIoTClient 23:1111ee8bcba4 651 /* Codes_SRS_AMQP_MANAGEMENT_01_012: [ If `messaging_create_source` fails then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 652 LogError("Failed creating source AMQP value");
AzureIoTClient 23:1111ee8bcba4 653 singlylinkedlist_destroy(result->pending_operations);
AzureIoTClient 21:f9c433d8e6ca 654 free(result);
AzureIoTClient 6:641a9672db08 655 result = NULL;
AzureIoTClient 6:641a9672db08 656 }
AzureIoTClient 6:641a9672db08 657 else
AzureIoTClient 6:641a9672db08 658 {
AzureIoTClient 23:1111ee8bcba4 659 /* Codes_SRS_AMQP_MANAGEMENT_01_011: [ The `target` argument shall be a value created by calling `messaging_create_target` with `management_node` as argument. ]*/
AzureIoTClient 23:1111ee8bcba4 660 AMQP_VALUE target = messaging_create_target(management_node);
AzureIoTClient 23:1111ee8bcba4 661 if (target == NULL)
AzureIoTClient 6:641a9672db08 662 {
AzureIoTClient 23:1111ee8bcba4 663 /* Codes_SRS_AMQP_MANAGEMENT_01_013: [ If `messaging_create_target` fails then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 664 LogError("Failed creating target AMQP value");
AzureIoTClient 23:1111ee8bcba4 665 singlylinkedlist_destroy(result->pending_operations);
AzureIoTClient 23:1111ee8bcba4 666 free(result);
AzureIoTClient 6:641a9672db08 667 result = NULL;
AzureIoTClient 6:641a9672db08 668 }
AzureIoTClient 6:641a9672db08 669 else
AzureIoTClient 6:641a9672db08 670 {
AzureIoTClient 23:1111ee8bcba4 671 size_t management_node_length = strlen(management_node);
Azure.IoT Build 0:6ae2f7bca550 672
AzureIoTClient 23:1111ee8bcba4 673 char* sender_link_name = (char*)malloc(management_node_length + COUNT_CHARS(sender_suffix) + 1);
AzureIoTClient 23:1111ee8bcba4 674 if (sender_link_name == NULL)
AzureIoTClient 6:641a9672db08 675 {
AzureIoTClient 23:1111ee8bcba4 676 /* Codes_SRS_AMQP_MANAGEMENT_01_033: [ If any other error occurs `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 677 LogError("Failed allocating memory for sender link name");
AzureIoTClient 23:1111ee8bcba4 678 free(result);
AzureIoTClient 6:641a9672db08 679 result = NULL;
AzureIoTClient 6:641a9672db08 680 }
AzureIoTClient 6:641a9672db08 681 else
AzureIoTClient 6:641a9672db08 682 {
AzureIoTClient 25:1101516ee67d 683 char* receiver_link_name;
AzureIoTClient 25:1101516ee67d 684
AzureIoTClient 23:1111ee8bcba4 685 (void)memcpy(sender_link_name, management_node, management_node_length);
AzureIoTClient 23:1111ee8bcba4 686 (void)memcpy(sender_link_name + management_node_length, sender_suffix, COUNT_CHARS(sender_suffix) + 1);
Azure.IoT Build 0:6ae2f7bca550 687
AzureIoTClient 25:1101516ee67d 688 receiver_link_name = (char*)malloc(management_node_length + COUNT_CHARS(receiver_suffix) + 1);
AzureIoTClient 23:1111ee8bcba4 689 if (receiver_link_name == NULL)
AzureIoTClient 6:641a9672db08 690 {
AzureIoTClient 23:1111ee8bcba4 691 /* Codes_SRS_AMQP_MANAGEMENT_01_033: [ If any other error occurs `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 692 LogError("Failed allocating memory for receiver link name");
AzureIoTClient 21:f9c433d8e6ca 693 free(result);
AzureIoTClient 6:641a9672db08 694 result = NULL;
AzureIoTClient 6:641a9672db08 695 }
AzureIoTClient 6:641a9672db08 696 else
AzureIoTClient 6:641a9672db08 697 {
AzureIoTClient 23:1111ee8bcba4 698 (void)memcpy(receiver_link_name, management_node, management_node_length);
AzureIoTClient 23:1111ee8bcba4 699 (void)memcpy(receiver_link_name + management_node_length, receiver_suffix, COUNT_CHARS(receiver_suffix) + 1);
AzureIoTClient 23:1111ee8bcba4 700
AzureIoTClient 23:1111ee8bcba4 701 /* Codes_SRS_AMQP_MANAGEMENT_01_006: [ `amqp_management_create` shall create a sender link by calling `link_create`. ]*/
AzureIoTClient 23:1111ee8bcba4 702 /* Codes_SRS_AMQP_MANAGEMENT_01_007: [ The `session` argument shall be set to `session`. ]*/
AzureIoTClient 23:1111ee8bcba4 703 /* Codes_SRS_AMQP_MANAGEMENT_01_008: [ The `name` argument shall be constructed by concatenating the `management_node` value with `-sender`. ]*/
AzureIoTClient 23:1111ee8bcba4 704 /* Codes_SRS_AMQP_MANAGEMENT_01_009: [ The `role` argument shall be `role_sender`. ]*/
AzureIoTClient 23:1111ee8bcba4 705 /* Codes_SRS_AMQP_MANAGEMENT_01_019: [ The `source` argument shall be the value created by calling `messaging_create_source`. ]*/
AzureIoTClient 23:1111ee8bcba4 706 /* Codes_SRS_AMQP_MANAGEMENT_01_020: [ The `target` argument shall be the value created by calling `messaging_create_target`. ]*/
AzureIoTClient 23:1111ee8bcba4 707 result->sender_link = link_create(session, sender_link_name, role_sender, source, target);
AzureIoTClient 23:1111ee8bcba4 708 if (result->sender_link == NULL)
AzureIoTClient 6:641a9672db08 709 {
AzureIoTClient 23:1111ee8bcba4 710 /* Codes_SRS_AMQP_MANAGEMENT_01_014: [ If `link_create` fails when creating the sender link then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 711 LogError("Failed creating sender link");
AzureIoTClient 21:f9c433d8e6ca 712 free(result);
AzureIoTClient 6:641a9672db08 713 result = NULL;
AzureIoTClient 6:641a9672db08 714 }
AzureIoTClient 6:641a9672db08 715 else
AzureIoTClient 6:641a9672db08 716 {
AzureIoTClient 23:1111ee8bcba4 717 /* Codes_SRS_AMQP_MANAGEMENT_01_015: [ `amqp_management_create` shall create a receiver link by calling `link_create`. ]*/
AzureIoTClient 23:1111ee8bcba4 718 /* Codes_SRS_AMQP_MANAGEMENT_01_016: [ The `session` argument shall be set to `session`. ]*/
AzureIoTClient 23:1111ee8bcba4 719 /* Codes_SRS_AMQP_MANAGEMENT_01_017: [ The `name` argument shall be constructed by concatenating the `management_node` value with `-receiver`. ]*/
AzureIoTClient 23:1111ee8bcba4 720 /* Codes_SRS_AMQP_MANAGEMENT_01_018: [ The `role` argument shall be `role_receiver`. ]*/
AzureIoTClient 23:1111ee8bcba4 721 /* Codes_SRS_AMQP_MANAGEMENT_01_019: [ The `source` argument shall be the value created by calling `messaging_create_source`. ]*/
AzureIoTClient 23:1111ee8bcba4 722 /* Codes_SRS_AMQP_MANAGEMENT_01_020: [ The `target` argument shall be the value created by calling `messaging_create_target`. ]*/
AzureIoTClient 23:1111ee8bcba4 723 result->receiver_link = link_create(session, receiver_link_name, role_receiver, source, target);
AzureIoTClient 23:1111ee8bcba4 724 if (result->receiver_link == NULL)
AzureIoTClient 6:641a9672db08 725 {
AzureIoTClient 23:1111ee8bcba4 726 /* Codes_SRS_AMQP_MANAGEMENT_01_021: [ If `link_create` fails when creating the receiver link then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 727 LogError("Failed creating receiver link");
AzureIoTClient 6:641a9672db08 728 link_destroy(result->sender_link);
AzureIoTClient 21:f9c433d8e6ca 729 free(result);
AzureIoTClient 6:641a9672db08 730 result = NULL;
AzureIoTClient 6:641a9672db08 731 }
AzureIoTClient 6:641a9672db08 732 else
AzureIoTClient 6:641a9672db08 733 {
AzureIoTClient 23:1111ee8bcba4 734 /* Codes_SRS_AMQP_MANAGEMENT_01_022: [ `amqp_management_create` shall create a message sender by calling `messagesender_create` and passing to it the sender link handle. ]*/
AzureIoTClient 6:641a9672db08 735 result->message_sender = messagesender_create(result->sender_link, on_message_sender_state_changed, result);
AzureIoTClient 6:641a9672db08 736 if (result->message_sender == NULL)
AzureIoTClient 6:641a9672db08 737 {
AzureIoTClient 23:1111ee8bcba4 738 /* Codes_SRS_AMQP_MANAGEMENT_01_031: [ If `messagesender_create` fails then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 739 LogError("Failed creating message sender");
AzureIoTClient 6:641a9672db08 740 link_destroy(result->sender_link);
AzureIoTClient 6:641a9672db08 741 link_destroy(result->receiver_link);
AzureIoTClient 21:f9c433d8e6ca 742 free(result);
AzureIoTClient 6:641a9672db08 743 result = NULL;
AzureIoTClient 6:641a9672db08 744 }
AzureIoTClient 6:641a9672db08 745 else
AzureIoTClient 6:641a9672db08 746 {
AzureIoTClient 23:1111ee8bcba4 747 /* Codes_SRS_AMQP_MANAGEMENT_01_023: [ `amqp_management_create` shall create a message receiver by calling `messagereceiver_create` and passing to it the receiver link handle. ]*/
AzureIoTClient 6:641a9672db08 748 result->message_receiver = messagereceiver_create(result->receiver_link, on_message_receiver_state_changed, result);
AzureIoTClient 6:641a9672db08 749 if (result->message_receiver == NULL)
AzureIoTClient 6:641a9672db08 750 {
AzureIoTClient 23:1111ee8bcba4 751 /* Codes_SRS_AMQP_MANAGEMENT_01_032: [ If `messagereceiver_create` fails then `amqp_management_create` shall fail and return NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 752 LogError("Failed creating message receiver");
AzureIoTClient 6:641a9672db08 753 messagesender_destroy(result->message_sender);
AzureIoTClient 6:641a9672db08 754 link_destroy(result->sender_link);
AzureIoTClient 6:641a9672db08 755 link_destroy(result->receiver_link);
AzureIoTClient 21:f9c433d8e6ca 756 free(result);
AzureIoTClient 6:641a9672db08 757 result = NULL;
AzureIoTClient 6:641a9672db08 758 }
AzureIoTClient 6:641a9672db08 759 else
AzureIoTClient 6:641a9672db08 760 {
AzureIoTClient 23:1111ee8bcba4 761 /* Codes_SRS_AMQP_MANAGEMENT_01_106: [ The message Id set on the message properties shall start at 0. ]*/
AzureIoTClient 6:641a9672db08 762 result->next_message_id = 0;
AzureIoTClient 6:641a9672db08 763 }
AzureIoTClient 6:641a9672db08 764 }
AzureIoTClient 6:641a9672db08 765 }
AzureIoTClient 6:641a9672db08 766 }
AzureIoTClient 23:1111ee8bcba4 767
AzureIoTClient 23:1111ee8bcba4 768 free(receiver_link_name);
AzureIoTClient 6:641a9672db08 769 }
Azure.IoT Build 0:6ae2f7bca550 770
AzureIoTClient 23:1111ee8bcba4 771 free(sender_link_name);
AzureIoTClient 6:641a9672db08 772 }
Azure.IoT Build 0:6ae2f7bca550 773
AzureIoTClient 23:1111ee8bcba4 774 amqpvalue_destroy(target);
AzureIoTClient 6:641a9672db08 775 }
Azure.IoT Build 0:6ae2f7bca550 776
AzureIoTClient 23:1111ee8bcba4 777 amqpvalue_destroy(source);
AzureIoTClient 6:641a9672db08 778 }
AzureIoTClient 6:641a9672db08 779 }
AzureIoTClient 6:641a9672db08 780 }
AzureIoTClient 6:641a9672db08 781 }
Azure.IoT Build 0:6ae2f7bca550 782
AzureIoTClient 6:641a9672db08 783 return result;
Azure.IoT Build 0:6ae2f7bca550 784 }
Azure.IoT Build 0:6ae2f7bca550 785
AzureIoTClient 22:524bded3f7a8 786 void amqp_management_destroy(AMQP_MANAGEMENT_HANDLE amqp_management)
Azure.IoT Build 0:6ae2f7bca550 787 {
AzureIoTClient 23:1111ee8bcba4 788 if (amqp_management == NULL)
AzureIoTClient 6:641a9672db08 789 {
AzureIoTClient 23:1111ee8bcba4 790 /* Codes_SRS_AMQP_MANAGEMENT_01_025: [ If `amqp_management` is NULL, `amqp_management_destroy` shall do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 791 LogError("NULL amqp_management");
AzureIoTClient 23:1111ee8bcba4 792 }
AzureIoTClient 23:1111ee8bcba4 793 else
AzureIoTClient 23:1111ee8bcba4 794 {
AzureIoTClient 23:1111ee8bcba4 795 /* Codes_SRS_AMQP_MANAGEMENT_01_024: [ `amqp_management_destroy` shall free all the resources allocated by `amqp_management_create`. ]*/
AzureIoTClient 23:1111ee8bcba4 796 if (amqp_management->amqp_management_state != AMQP_MANAGEMENT_STATE_IDLE)
AzureIoTClient 6:641a9672db08 797 {
AzureIoTClient 23:1111ee8bcba4 798 (void)amqp_management_close(amqp_management);
AzureIoTClient 6:641a9672db08 799 }
Azure.IoT Build 0:6ae2f7bca550 800
AzureIoTClient 23:1111ee8bcba4 801 /* Codes_SRS_AMQP_MANAGEMENT_01_028: [ `amqp_management_destroy` shall free the message sender by calling `messagesender_destroy`. ]*/
AzureIoTClient 23:1111ee8bcba4 802 messagesender_destroy(amqp_management->message_sender);
AzureIoTClient 23:1111ee8bcba4 803 /* Codes_SRS_AMQP_MANAGEMENT_01_029: [ `amqp_management_destroy` shall free the message receiver by calling `messagereceiver_destroy`. ]*/
AzureIoTClient 23:1111ee8bcba4 804 messagereceiver_destroy(amqp_management->message_receiver);
AzureIoTClient 23:1111ee8bcba4 805 /* Codes_SRS_AMQP_MANAGEMENT_01_027: [ `amqp_management_destroy` shall free the sender and receiver links by calling `link_destroy`. ]*/
AzureIoTClient 6:641a9672db08 806 link_destroy(amqp_management->sender_link);
AzureIoTClient 6:641a9672db08 807 link_destroy(amqp_management->receiver_link);
AzureIoTClient 23:1111ee8bcba4 808 /* Codes_SRS_AMQP_MANAGEMENT_01_026: [ `amqp_management_destroy` shall free the singly linked list by calling `singlylinkedlist_destroy`. ]*/
AzureIoTClient 23:1111ee8bcba4 809 singlylinkedlist_destroy(amqp_management->pending_operations);
AzureIoTClient 21:f9c433d8e6ca 810 free(amqp_management);
AzureIoTClient 6:641a9672db08 811 }
Azure.IoT Build 0:6ae2f7bca550 812 }
Azure.IoT Build 0:6ae2f7bca550 813
AzureIoTClient 22:524bded3f7a8 814 int amqp_management_open_async(AMQP_MANAGEMENT_HANDLE amqp_management, ON_AMQP_MANAGEMENT_OPEN_COMPLETE on_amqp_management_open_complete, void* on_amqp_management_open_complete_context, ON_AMQP_MANAGEMENT_ERROR on_amqp_management_error, void* on_amqp_management_error_context)
Azure.IoT Build 0:6ae2f7bca550 815 {
AzureIoTClient 6:641a9672db08 816 int result;
Azure.IoT Build 0:6ae2f7bca550 817
AzureIoTClient 23:1111ee8bcba4 818 /* Codes_SRS_AMQP_MANAGEMENT_01_044: [ `on_amqp_management_open_complete_context` and `on_amqp_management_error_context` shall be allowed to be NULL. ]*/
AzureIoTClient 23:1111ee8bcba4 819 if ((amqp_management == NULL) ||
AzureIoTClient 23:1111ee8bcba4 820 (on_amqp_management_open_complete == NULL) ||
AzureIoTClient 23:1111ee8bcba4 821 (on_amqp_management_error == NULL))
AzureIoTClient 6:641a9672db08 822 {
AzureIoTClient 23:1111ee8bcba4 823 /* Codes_SRS_AMQP_MANAGEMENT_01_038: [ If `amqp_management`, `on_amqp_management_open_complete` or `on_amqp_management_error` is NULL, `amqp_management_open_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 824 LogError("Bad arguments: amqp_management = %p, on_amqp_management_open_complete = %p, on_amqp_management_error = %p",
AzureIoTClient 23:1111ee8bcba4 825 amqp_management,
AzureIoTClient 23:1111ee8bcba4 826 on_amqp_management_open_complete,
AzureIoTClient 23:1111ee8bcba4 827 on_amqp_management_error);
AzureIoTClient 23:1111ee8bcba4 828 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 829 }
AzureIoTClient 23:1111ee8bcba4 830 else if (amqp_management->amqp_management_state != AMQP_MANAGEMENT_STATE_IDLE)
AzureIoTClient 23:1111ee8bcba4 831 {
AzureIoTClient 23:1111ee8bcba4 832 /* Codes_SRS_AMQP_MANAGEMENT_01_043: [ If the AMQP management instance is already OPEN or OPENING, `amqp_management_open_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 833 LogError("AMQP management instance already OPEN");
AzureIoTClient 19:000ab4e6a2c1 834 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 835 }
AzureIoTClient 6:641a9672db08 836 else
AzureIoTClient 6:641a9672db08 837 {
AzureIoTClient 23:1111ee8bcba4 838 /* Codes_SRS_AMQP_MANAGEMENT_01_036: [ `amqp_management_open_async` shall start opening the AMQP management instance and save the callbacks so that they can be called when opening is complete. ]*/
AzureIoTClient 22:524bded3f7a8 839 amqp_management->on_amqp_management_open_complete = on_amqp_management_open_complete;
AzureIoTClient 22:524bded3f7a8 840 amqp_management->on_amqp_management_open_complete_context = on_amqp_management_open_complete_context;
AzureIoTClient 22:524bded3f7a8 841 amqp_management->on_amqp_management_error = on_amqp_management_error;
AzureIoTClient 22:524bded3f7a8 842 amqp_management->on_amqp_management_error_context = on_amqp_management_error_context;
AzureIoTClient 22:524bded3f7a8 843 amqp_management->amqp_management_state = AMQP_MANAGEMENT_STATE_OPENING;
AzureIoTClient 22:524bded3f7a8 844
AzureIoTClient 23:1111ee8bcba4 845 /* Codes_SRS_AMQP_MANAGEMENT_01_040: [ `amqp_management_open_async` shall open the message receiver by calling `messagereceiver_open`. ]*/
AzureIoTClient 6:641a9672db08 846 if (messagereceiver_open(amqp_management->message_receiver, on_message_received, amqp_management) != 0)
AzureIoTClient 6:641a9672db08 847 {
AzureIoTClient 23:1111ee8bcba4 848 /* Codes_SRS_AMQP_MANAGEMENT_01_042: [ If `messagereceiver_open` fails, `amqp_management_open_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 849 LogError("Failed opening message receiver");
AzureIoTClient 22:524bded3f7a8 850 amqp_management->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
AzureIoTClient 19:000ab4e6a2c1 851 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 852 }
AzureIoTClient 6:641a9672db08 853 else
AzureIoTClient 6:641a9672db08 854 {
AzureIoTClient 23:1111ee8bcba4 855 /* Codes_SRS_AMQP_MANAGEMENT_01_039: [ `amqp_management_open_async` shall open the message sender by calling `messagesender_open`. ]*/
AzureIoTClient 6:641a9672db08 856 if (messagesender_open(amqp_management->message_sender) != 0)
AzureIoTClient 6:641a9672db08 857 {
AzureIoTClient 23:1111ee8bcba4 858 /* Codes_SRS_AMQP_MANAGEMENT_01_041: [ If `messagesender_open` fails, `amqp_management_open_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 859 LogError("Failed opening message sender");
AzureIoTClient 22:524bded3f7a8 860 amqp_management->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
AzureIoTClient 23:1111ee8bcba4 861 (void)messagereceiver_close(amqp_management->message_receiver);
AzureIoTClient 19:000ab4e6a2c1 862 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 863 }
AzureIoTClient 6:641a9672db08 864 else
AzureIoTClient 6:641a9672db08 865 {
AzureIoTClient 23:1111ee8bcba4 866 /* Codes_SRS_AMQP_MANAGEMENT_01_037: [ On success it shall return 0. ]*/
AzureIoTClient 6:641a9672db08 867 result = 0;
AzureIoTClient 6:641a9672db08 868 }
AzureIoTClient 6:641a9672db08 869 }
AzureIoTClient 6:641a9672db08 870 }
Azure.IoT Build 0:6ae2f7bca550 871
AzureIoTClient 6:641a9672db08 872 return result;
Azure.IoT Build 0:6ae2f7bca550 873 }
Azure.IoT Build 0:6ae2f7bca550 874
AzureIoTClient 22:524bded3f7a8 875 int amqp_management_close(AMQP_MANAGEMENT_HANDLE amqp_management)
Azure.IoT Build 0:6ae2f7bca550 876 {
AzureIoTClient 6:641a9672db08 877 int result;
Azure.IoT Build 0:6ae2f7bca550 878
AzureIoTClient 6:641a9672db08 879 if (amqp_management == NULL)
AzureIoTClient 6:641a9672db08 880 {
AzureIoTClient 23:1111ee8bcba4 881 /* Codes_SRS_AMQP_MANAGEMENT_01_047: [ If `amqp_management` is NULL, `amqp_management_close` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 882 LogError("NULL amqp_management");
AzureIoTClient 23:1111ee8bcba4 883 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 884 }
AzureIoTClient 23:1111ee8bcba4 885 else if (amqp_management->amqp_management_state == AMQP_MANAGEMENT_STATE_IDLE)
AzureIoTClient 23:1111ee8bcba4 886 {
AzureIoTClient 23:1111ee8bcba4 887 /* Codes_SRS_AMQP_MANAGEMENT_01_049: [ `amqp_management_close` on an AMQP management instance that is not OPEN, shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 888 LogError("AMQP management instance not open");
AzureIoTClient 19:000ab4e6a2c1 889 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 890 }
AzureIoTClient 6:641a9672db08 891 else
AzureIoTClient 6:641a9672db08 892 {
AzureIoTClient 23:1111ee8bcba4 893 /* Codes_SRS_AMQP_MANAGEMENT_01_045: [ `amqp_management_close` shall close the AMQP management instance. ]*/
AzureIoTClient 23:1111ee8bcba4 894 /* Codes_SRS_AMQP_MANAGEMENT_01_050: [ `amqp_management_close` shall close the message sender by calling `messagesender_close`. ]*/
AzureIoTClient 23:1111ee8bcba4 895 if (messagesender_close(amqp_management->message_sender) != 0)
AzureIoTClient 6:641a9672db08 896 {
AzureIoTClient 23:1111ee8bcba4 897 /* Codes_SRS_AMQP_MANAGEMENT_01_052: [ If `messagesender_close` fails, `amqp_management_close` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 898 LogError("messagesender_close failed");
AzureIoTClient 23:1111ee8bcba4 899 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 900 }
AzureIoTClient 23:1111ee8bcba4 901 /* Codes_SRS_AMQP_MANAGEMENT_01_051: [ `amqp_management_close` shall close the message receiver by calling `messagereceiver_close`. ]*/
AzureIoTClient 23:1111ee8bcba4 902 else if (messagereceiver_close(amqp_management->message_receiver) != 0)
AzureIoTClient 23:1111ee8bcba4 903 {
AzureIoTClient 23:1111ee8bcba4 904 /* Codes_SRS_AMQP_MANAGEMENT_01_053: [ If `messagereceiver_close` fails, `amqp_management_close` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 905 LogError("messagereceiver_close failed");
AzureIoTClient 19:000ab4e6a2c1 906 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 907 }
AzureIoTClient 6:641a9672db08 908 else
AzureIoTClient 6:641a9672db08 909 {
AzureIoTClient 23:1111ee8bcba4 910 LIST_ITEM_HANDLE list_item_handle = singlylinkedlist_get_head_item(amqp_management->pending_operations);
AzureIoTClient 23:1111ee8bcba4 911 while (list_item_handle != NULL)
AzureIoTClient 23:1111ee8bcba4 912 {
AzureIoTClient 23:1111ee8bcba4 913 OPERATION_MESSAGE_INSTANCE* operation_message = (OPERATION_MESSAGE_INSTANCE*)singlylinkedlist_item_get_value(list_item_handle);
AzureIoTClient 23:1111ee8bcba4 914 if (operation_message == NULL)
AzureIoTClient 23:1111ee8bcba4 915 {
AzureIoTClient 23:1111ee8bcba4 916 LogError("Cannot obtain pending operation");
AzureIoTClient 23:1111ee8bcba4 917 }
AzureIoTClient 23:1111ee8bcba4 918 else
AzureIoTClient 23:1111ee8bcba4 919 {
AzureIoTClient 23:1111ee8bcba4 920 /* Codes_SRS_AMQP_MANAGEMENT_01_054: [ All pending operations shall be indicated complete with the code `AMQP_MANAGEMENT_EXECUTE_OPERATION_INSTANCE_CLOSED`. ]*/
AzureIoTClient 23:1111ee8bcba4 921 operation_message->on_execute_operation_complete(operation_message->callback_context, AMQP_MANAGEMENT_EXECUTE_OPERATION_INSTANCE_CLOSED, 0, NULL);
AzureIoTClient 23:1111ee8bcba4 922 free(operation_message);
AzureIoTClient 23:1111ee8bcba4 923 }
AzureIoTClient 23:1111ee8bcba4 924
AzureIoTClient 23:1111ee8bcba4 925 if (singlylinkedlist_remove(amqp_management->pending_operations, list_item_handle) != 0)
AzureIoTClient 23:1111ee8bcba4 926 {
AzureIoTClient 23:1111ee8bcba4 927 LogError("Cannot remove item");
AzureIoTClient 23:1111ee8bcba4 928 }
AzureIoTClient 23:1111ee8bcba4 929
AzureIoTClient 23:1111ee8bcba4 930 list_item_handle = singlylinkedlist_get_head_item(amqp_management->pending_operations);
AzureIoTClient 23:1111ee8bcba4 931 }
AzureIoTClient 23:1111ee8bcba4 932
AzureIoTClient 23:1111ee8bcba4 933 if (amqp_management->amqp_management_state == AMQP_MANAGEMENT_STATE_OPENING)
AzureIoTClient 23:1111ee8bcba4 934 {
AzureIoTClient 23:1111ee8bcba4 935 /* Codes_SRS_AMQP_MANAGEMENT_01_048: [ `amqp_management_close` on an AMQP management instance that is OPENING shall trigger the `on_amqp_management_open_complete` callback with `AMQP_MANAGEMENT_OPEN_CANCELLED`, while also passing the context passed in `amqp_management_open_async`. ]*/
AzureIoTClient 23:1111ee8bcba4 936 amqp_management->on_amqp_management_open_complete(amqp_management->on_amqp_management_open_complete_context, AMQP_MANAGEMENT_OPEN_CANCELLED);
AzureIoTClient 23:1111ee8bcba4 937 }
AzureIoTClient 23:1111ee8bcba4 938
AzureIoTClient 22:524bded3f7a8 939 amqp_management->amqp_management_state = AMQP_MANAGEMENT_STATE_IDLE;
AzureIoTClient 23:1111ee8bcba4 940
AzureIoTClient 23:1111ee8bcba4 941 /* Codes_SRS_AMQP_MANAGEMENT_01_046: [ On success it shall return 0. ]*/
AzureIoTClient 6:641a9672db08 942 result = 0;
AzureIoTClient 6:641a9672db08 943 }
AzureIoTClient 6:641a9672db08 944 }
Azure.IoT Build 0:6ae2f7bca550 945
AzureIoTClient 6:641a9672db08 946 return result;
Azure.IoT Build 0:6ae2f7bca550 947 }
Azure.IoT Build 0:6ae2f7bca550 948
AzureIoTClient 22:524bded3f7a8 949 int amqp_management_execute_operation_async(AMQP_MANAGEMENT_HANDLE amqp_management, const char* operation, const char* type, const char* locales, MESSAGE_HANDLE message, ON_AMQP_MANAGEMENT_EXECUTE_OPERATION_COMPLETE on_execute_operation_complete, void* on_execute_operation_complete_context)
Azure.IoT Build 0:6ae2f7bca550 950 {
AzureIoTClient 6:641a9672db08 951 int result;
AzureIoTClient 6:641a9672db08 952
AzureIoTClient 6:641a9672db08 953 if ((amqp_management == NULL) ||
AzureIoTClient 23:1111ee8bcba4 954 (operation == NULL) ||
AzureIoTClient 23:1111ee8bcba4 955 (type == NULL) ||
AzureIoTClient 23:1111ee8bcba4 956 (on_execute_operation_complete == NULL))
AzureIoTClient 6:641a9672db08 957 {
AzureIoTClient 23:1111ee8bcba4 958 /* Codes_SRS_AMQP_MANAGEMENT_01_057: [ If `amqp_management`, `operation`, `type` or `on_execute_operation_complete` is NULL, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 959 LogError("Bad arguments: amqp_management = %p, operation = %p, type = %p",
AzureIoTClient 23:1111ee8bcba4 960 amqp_management, operation, type);
AzureIoTClient 23:1111ee8bcba4 961 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 962 }
AzureIoTClient 23:1111ee8bcba4 963 /* Codes_SRS_AMQP_MANAGEMENT_01_081: [ If `amqp_management_execute_operation_async` is called when not OPEN, it shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 964 else if ((amqp_management->amqp_management_state == AMQP_MANAGEMENT_STATE_IDLE) ||
AzureIoTClient 23:1111ee8bcba4 965 /* Codes_SRS_AMQP_MANAGEMENT_01_104: [ If `amqp_management_execute_operation_async` is called when the AMQP management is in error, it shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 966 (amqp_management->amqp_management_state == AMQP_MANAGEMENT_STATE_ERROR))
AzureIoTClient 23:1111ee8bcba4 967 {
AzureIoTClient 23:1111ee8bcba4 968 LogError("amqp_management_execute_operation_async called while not open or in error");
AzureIoTClient 19:000ab4e6a2c1 969 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 970 }
AzureIoTClient 6:641a9672db08 971 else
AzureIoTClient 6:641a9672db08 972 {
AzureIoTClient 6:641a9672db08 973 AMQP_VALUE application_properties;
AzureIoTClient 23:1111ee8bcba4 974 MESSAGE_HANDLE cloned_message;
AzureIoTClient 23:1111ee8bcba4 975
AzureIoTClient 23:1111ee8bcba4 976 if (message == NULL)
AzureIoTClient 23:1111ee8bcba4 977 {
AzureIoTClient 23:1111ee8bcba4 978 /* Codes_SRS_AMQP_MANAGEMENT_01_102: [ If `message` is NULL, a new message shall be created by calling `message_create`. ]*/
AzureIoTClient 23:1111ee8bcba4 979 cloned_message = message_create();
AzureIoTClient 23:1111ee8bcba4 980 }
AzureIoTClient 23:1111ee8bcba4 981 else
AzureIoTClient 23:1111ee8bcba4 982 {
AzureIoTClient 23:1111ee8bcba4 983 /* Codes_SRS_AMQP_MANAGEMENT_01_103: [ Otherwise the existing message shall be cloned by using `message_clone` before being modified accordingly and used for the pending operation. ]*/
AzureIoTClient 23:1111ee8bcba4 984 cloned_message = message_clone(message);
AzureIoTClient 23:1111ee8bcba4 985 if (cloned_message == NULL)
AzureIoTClient 23:1111ee8bcba4 986 {
AzureIoTClient 23:1111ee8bcba4 987 LogError("Could not clone message");
AzureIoTClient 23:1111ee8bcba4 988 }
AzureIoTClient 23:1111ee8bcba4 989 }
AzureIoTClient 23:1111ee8bcba4 990
AzureIoTClient 23:1111ee8bcba4 991 if (cloned_message == NULL)
AzureIoTClient 6:641a9672db08 992 {
AzureIoTClient 19:000ab4e6a2c1 993 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 994 }
AzureIoTClient 6:641a9672db08 995 else
AzureIoTClient 6:641a9672db08 996 {
AzureIoTClient 23:1111ee8bcba4 997 /* Codes_SRS_AMQP_MANAGEMENT_01_055: [ `amqp_management_execute_operation_async` shall start an AMQP management operation. ]*/
AzureIoTClient 23:1111ee8bcba4 998 /* Codes_SRS_AMQP_MANAGEMENT_01_082: [ `amqp_management_execute_operation_async` shall obtain the application properties from the message by calling `message_get_application_properties`. ]*/
AzureIoTClient 23:1111ee8bcba4 999 if (message_get_application_properties(cloned_message, &application_properties) != 0)
AzureIoTClient 6:641a9672db08 1000 {
AzureIoTClient 23:1111ee8bcba4 1001 LogError("Could not get application properties");
AzureIoTClient 19:000ab4e6a2c1 1002 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1003 }
AzureIoTClient 6:641a9672db08 1004 else
AzureIoTClient 6:641a9672db08 1005 {
AzureIoTClient 23:1111ee8bcba4 1006 if (application_properties == NULL)
AzureIoTClient 23:1111ee8bcba4 1007 {
AzureIoTClient 23:1111ee8bcba4 1008 /* Codes_SRS_AMQP_MANAGEMENT_01_083: [ If no application properties were set on the message, a new application properties instance shall be created by calling `amqpvalue_create_map`; ]*/
AzureIoTClient 23:1111ee8bcba4 1009 application_properties = amqpvalue_create_map();
AzureIoTClient 23:1111ee8bcba4 1010 if (application_properties == NULL)
AzureIoTClient 23:1111ee8bcba4 1011 {
AzureIoTClient 23:1111ee8bcba4 1012 LogError("Could not create application properties");
AzureIoTClient 23:1111ee8bcba4 1013 }
AzureIoTClient 23:1111ee8bcba4 1014 }
AzureIoTClient 23:1111ee8bcba4 1015
AzureIoTClient 23:1111ee8bcba4 1016 if (application_properties == NULL)
AzureIoTClient 6:641a9672db08 1017 {
AzureIoTClient 19:000ab4e6a2c1 1018 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1019 }
AzureIoTClient 6:641a9672db08 1020 else
AzureIoTClient 6:641a9672db08 1021 {
AzureIoTClient 23:1111ee8bcba4 1022 /* Codes_SRS_AMQP_MANAGEMENT_01_084: [ For each of the arguments `operation`, `type` and `locales` an AMQP value of type string shall be created by calling `amqpvalue_create_string` in order to be used as key in the application properties map. ]*/
AzureIoTClient 23:1111ee8bcba4 1023 /* Codes_SRS_AMQP_MANAGEMENT_01_085: [ For each of the arguments `operation`, `type` and `locales` an AMQP value of type string containing the argument value shall be created by calling `amqpvalue_create_string` in order to be used as value in the application properties map. ]*/
AzureIoTClient 23:1111ee8bcba4 1024 /* Codes_SRS_AMQP_MANAGEMENT_01_058: [ Request messages have the following application-properties: ]*/
AzureIoTClient 23:1111ee8bcba4 1025 /* Codes_SRS_AMQP_MANAGEMENT_01_059: [ operation string Yes The management operation to be performed. ] */
AzureIoTClient 23:1111ee8bcba4 1026 if ((add_string_key_value_pair_to_map(application_properties, "operation", operation) != 0) ||
AzureIoTClient 23:1111ee8bcba4 1027 /* Codes_SRS_AMQP_MANAGEMENT_01_061: [ type string Yes The Manageable Entity Type of the Manageable Entity to be managed. ]*/
AzureIoTClient 23:1111ee8bcba4 1028 (add_string_key_value_pair_to_map(application_properties, "type", type) != 0) ||
AzureIoTClient 23:1111ee8bcba4 1029 /* Codes_SRS_AMQP_MANAGEMENT_01_093: [ If `locales` is NULL, no key/value pair shall be added for it in the application properties map. ]*/
AzureIoTClient 23:1111ee8bcba4 1030 /* Codes_SRS_AMQP_MANAGEMENT_01_063: [ locales string No A list of locales that the sending peer permits for incoming informational text in response messages. ]*/
AzureIoTClient 23:1111ee8bcba4 1031 ((locales != NULL) && (add_string_key_value_pair_to_map(application_properties, "locales", locales) != 0)))
AzureIoTClient 6:641a9672db08 1032 {
AzureIoTClient 19:000ab4e6a2c1 1033 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1034 }
AzureIoTClient 6:641a9672db08 1035 else
AzureIoTClient 6:641a9672db08 1036 {
AzureIoTClient 23:1111ee8bcba4 1037 /* Codes_SRS_AMQP_MANAGEMENT_01_087: [ The application properties obtained after adding the key/value pairs shall be set on the message by calling `message_set_application_properties`. ]*/
AzureIoTClient 23:1111ee8bcba4 1038 if (message_set_application_properties(cloned_message, application_properties) != 0)
AzureIoTClient 6:641a9672db08 1039 {
AzureIoTClient 23:1111ee8bcba4 1040 /* Codes_SRS_AMQP_MANAGEMENT_01_090: [ If any APIs used to create and set the application properties on the message fails, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 1041 LogError("Could not set application properties");
AzureIoTClient 23:1111ee8bcba4 1042 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 1043 }
AzureIoTClient 23:1111ee8bcba4 1044 else if (set_message_id(cloned_message, amqp_management->next_message_id) != 0)
AzureIoTClient 23:1111ee8bcba4 1045 {
AzureIoTClient 19:000ab4e6a2c1 1046 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1047 }
AzureIoTClient 6:641a9672db08 1048 else
AzureIoTClient 6:641a9672db08 1049 {
AzureIoTClient 23:1111ee8bcba4 1050 OPERATION_MESSAGE_INSTANCE* pending_operation_message = (OPERATION_MESSAGE_INSTANCE*)malloc(sizeof(OPERATION_MESSAGE_INSTANCE));
AzureIoTClient 23:1111ee8bcba4 1051 if (pending_operation_message == NULL)
AzureIoTClient 6:641a9672db08 1052 {
AzureIoTClient 19:000ab4e6a2c1 1053 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1054 }
AzureIoTClient 6:641a9672db08 1055 else
AzureIoTClient 6:641a9672db08 1056 {
AzureIoTClient 23:1111ee8bcba4 1057 LIST_ITEM_HANDLE added_item;
AzureIoTClient 23:1111ee8bcba4 1058 pending_operation_message->callback_context = on_execute_operation_complete_context;
AzureIoTClient 23:1111ee8bcba4 1059 pending_operation_message->on_execute_operation_complete = on_execute_operation_complete;
AzureIoTClient 23:1111ee8bcba4 1060 pending_operation_message->message_id = amqp_management->next_message_id;
AzureIoTClient 23:1111ee8bcba4 1061
AzureIoTClient 23:1111ee8bcba4 1062 /* Codes_SRS_AMQP_MANAGEMENT_01_091: [ Once the request message has been sent, an entry shall be stored in the pending operations list by calling `singlylinkedlist_add`. ]*/
AzureIoTClient 23:1111ee8bcba4 1063 added_item = singlylinkedlist_add(amqp_management->pending_operations, pending_operation_message);
AzureIoTClient 23:1111ee8bcba4 1064 if (added_item == NULL)
AzureIoTClient 23:1111ee8bcba4 1065 {
AzureIoTClient 23:1111ee8bcba4 1066 /* Codes_SRS_AMQP_MANAGEMENT_01_092: [ If `singlylinkedlist_add` fails then `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 1067 LogError("Could not add the operation to the pending operations list.");
AzureIoTClient 23:1111ee8bcba4 1068 free(pending_operation_message);
AzureIoTClient 23:1111ee8bcba4 1069 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 1070 }
AzureIoTClient 23:1111ee8bcba4 1071 else
AzureIoTClient 23:1111ee8bcba4 1072 {
AzureIoTClient 23:1111ee8bcba4 1073 /* Codes_SRS_AMQP_MANAGEMENT_01_088: [ `amqp_management_execute_operation_async` shall send the message by calling `messagesender_send`. ]*/
AzureIoTClient 23:1111ee8bcba4 1074 if (messagesender_send(amqp_management->message_sender, cloned_message, NULL, NULL) != 0)
AzureIoTClient 23:1111ee8bcba4 1075 {
AzureIoTClient 23:1111ee8bcba4 1076 /* Codes_SRS_AMQP_MANAGEMENT_01_089: [ If `messagesender_send` fails, `amqp_management_execute_operation_async` shall fail and return a non-zero value. ]*/
AzureIoTClient 23:1111ee8bcba4 1077 LogError("Could not send request message");
AzureIoTClient 23:1111ee8bcba4 1078 (void)singlylinkedlist_remove(amqp_management->pending_operations, added_item);
AzureIoTClient 23:1111ee8bcba4 1079 free(pending_operation_message);
AzureIoTClient 23:1111ee8bcba4 1080 result = __FAILURE__;
AzureIoTClient 23:1111ee8bcba4 1081 }
AzureIoTClient 23:1111ee8bcba4 1082 else
AzureIoTClient 23:1111ee8bcba4 1083 {
AzureIoTClient 23:1111ee8bcba4 1084 /* Codes_SRS_AMQP_MANAGEMENT_01_107: [ The message Id set on the message properties shall be incremented with each operation. ]*/
AzureIoTClient 23:1111ee8bcba4 1085 amqp_management->next_message_id++;
AzureIoTClient 23:1111ee8bcba4 1086
AzureIoTClient 23:1111ee8bcba4 1087 /* Codes_SRS_AMQP_MANAGEMENT_01_056: [ On success it shall return 0. ]*/
AzureIoTClient 23:1111ee8bcba4 1088 result = 0;
AzureIoTClient 23:1111ee8bcba4 1089 }
AzureIoTClient 23:1111ee8bcba4 1090 }
AzureIoTClient 6:641a9672db08 1091 }
AzureIoTClient 6:641a9672db08 1092 }
AzureIoTClient 6:641a9672db08 1093 }
AzureIoTClient 23:1111ee8bcba4 1094
AzureIoTClient 23:1111ee8bcba4 1095 /* Codes_SRS_AMQP_MANAGEMENT_01_101: [ After setting the application properties, the application properties instance shall be freed by `amqpvalue_destroy`. ]*/
AzureIoTClient 23:1111ee8bcba4 1096 amqpvalue_destroy(application_properties);
AzureIoTClient 6:641a9672db08 1097 }
AzureIoTClient 6:641a9672db08 1098 }
Azure.IoT Build 0:6ae2f7bca550 1099
AzureIoTClient 23:1111ee8bcba4 1100 message_destroy(cloned_message);
AzureIoTClient 6:641a9672db08 1101 }
AzureIoTClient 6:641a9672db08 1102 }
AzureIoTClient 6:641a9672db08 1103 return result;
AzureIoTClient 6:641a9672db08 1104 }
Azure.IoT Build 0:6ae2f7bca550 1105
AzureIoTClient 23:1111ee8bcba4 1106 void amqp_management_set_trace(AMQP_MANAGEMENT_HANDLE amqp_management, bool trace_on)
AzureIoTClient 6:641a9672db08 1107 {
AzureIoTClient 23:1111ee8bcba4 1108 if (amqp_management == NULL)
AzureIoTClient 6:641a9672db08 1109 {
AzureIoTClient 23:1111ee8bcba4 1110 /* Codes_SRS_AMQP_MANAGEMENT_01_163: [ If `amqp_management` is NULL, `amqp_management_set_trace` shal do nothing. ]*/
AzureIoTClient 23:1111ee8bcba4 1111 LogError("NULL amqp_management");
AzureIoTClient 23:1111ee8bcba4 1112 }
AzureIoTClient 23:1111ee8bcba4 1113 else
AzureIoTClient 23:1111ee8bcba4 1114 {
AzureIoTClient 23:1111ee8bcba4 1115 /* Codes_SRS_AMQP_MANAGEMENT_01_161: [ `amqp_management_set_trace` shall call `messagesender_set_trace` to enable/disable tracing on the message sender. ]*/
AzureIoTClient 23:1111ee8bcba4 1116 messagesender_set_trace(amqp_management->message_sender, trace_on);
AzureIoTClient 23:1111ee8bcba4 1117 /* Codes_SRS_AMQP_MANAGEMENT_01_162: [ `amqp_management_set_trace` shall call `messagereceiver_set_trace` to enable/disable tracing on the message receiver. ]*/
AzureIoTClient 23:1111ee8bcba4 1118 messagereceiver_set_trace(amqp_management->message_receiver, trace_on);
AzureIoTClient 6:641a9672db08 1119 }
Azure.IoT Build 0:6ae2f7bca550 1120 }