A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Nov 03 13:18:57 2017 -0700
Revision:
35:d0bed2404ee9
Parent:
34:6be9c2058664
Child:
39:e7c983378f41
1.1.27

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