Microsoft Azure IoTHub client AMQP transport

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more

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

Committer:
AzureIoTClient
Date:
Mon Mar 05 17:39:14 2018 -0800
Revision:
50:f3a92c6c6534
Parent:
43:3da2d93bb955
Child:
53:e21e1e88460f
1.2.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 42:c2eaa912a28c 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 42:c2eaa912a28c 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 42:c2eaa912a28c 3
AzureIoTClient 42:c2eaa912a28c 4 #include <stdlib.h>
AzureIoTClient 42:c2eaa912a28c 5 #include <stddef.h>
AzureIoTClient 42:c2eaa912a28c 6 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 42:c2eaa912a28c 7 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 42:c2eaa912a28c 8 #include "azure_c_shared_utility/crt_abstractions.h"
AzureIoTClient 42:c2eaa912a28c 9 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 42:c2eaa912a28c 10 #include "azure_c_shared_utility/strings.h"
AzureIoTClient 42:c2eaa912a28c 11 #include "azure_uamqp_c/link.h"
AzureIoTClient 42:c2eaa912a28c 12 #include "azure_uamqp_c/messaging.h"
AzureIoTClient 42:c2eaa912a28c 13 #include "azure_uamqp_c/message_receiver.h"
AzureIoTClient 42:c2eaa912a28c 14 #include "azure_uamqp_c/message_sender.h"
AzureIoTClient 50:f3a92c6c6534 15 #include "azure_uamqp_c/amqp_definitions_application_properties.h"
AzureIoTClient 50:f3a92c6c6534 16
AzureIoTClient 42:c2eaa912a28c 17 #include "iothubtransportamqp_methods.h"
AzureIoTClient 42:c2eaa912a28c 18
AzureIoTClient 42:c2eaa912a28c 19 typedef enum SUBSCRIBE_STATE_TAG
AzureIoTClient 42:c2eaa912a28c 20 {
AzureIoTClient 42:c2eaa912a28c 21 SUBSCRIBE_STATE_NOT_SUBSCRIBED,
AzureIoTClient 42:c2eaa912a28c 22 SUBSCRIBE_STATE_SUBSCRIBED
AzureIoTClient 42:c2eaa912a28c 23 } SUBSCRIBE_STATE;
AzureIoTClient 42:c2eaa912a28c 24
AzureIoTClient 42:c2eaa912a28c 25 typedef struct IOTHUBTRANSPORT_AMQP_METHODS_TAG
AzureIoTClient 42:c2eaa912a28c 26 {
AzureIoTClient 42:c2eaa912a28c 27 char* device_id;
AzureIoTClient 42:c2eaa912a28c 28 char* hostname;
AzureIoTClient 42:c2eaa912a28c 29 LINK_HANDLE receiver_link;
AzureIoTClient 42:c2eaa912a28c 30 LINK_HANDLE sender_link;
AzureIoTClient 42:c2eaa912a28c 31 MESSAGE_RECEIVER_HANDLE message_receiver;
AzureIoTClient 42:c2eaa912a28c 32 MESSAGE_SENDER_HANDLE message_sender;
AzureIoTClient 42:c2eaa912a28c 33 ON_METHOD_REQUEST_RECEIVED on_method_request_received;
AzureIoTClient 42:c2eaa912a28c 34 void* on_method_request_received_context;
AzureIoTClient 42:c2eaa912a28c 35 ON_METHODS_ERROR on_methods_error;
AzureIoTClient 42:c2eaa912a28c 36 void* on_methods_error_context;
AzureIoTClient 42:c2eaa912a28c 37 ON_METHODS_UNSUBSCRIBED on_methods_unsubscribed;
AzureIoTClient 42:c2eaa912a28c 38 void* on_methods_unsubscribed_context;
AzureIoTClient 42:c2eaa912a28c 39 SUBSCRIBE_STATE subscribe_state;
AzureIoTClient 42:c2eaa912a28c 40 IOTHUBTRANSPORT_AMQP_METHOD_HANDLE* method_request_handles;
AzureIoTClient 42:c2eaa912a28c 41 size_t method_request_handle_count;
AzureIoTClient 42:c2eaa912a28c 42 bool receiver_link_disconnected;
AzureIoTClient 42:c2eaa912a28c 43 bool sender_link_disconnected;
AzureIoTClient 42:c2eaa912a28c 44 } IOTHUBTRANSPORT_AMQP_METHODS;
AzureIoTClient 42:c2eaa912a28c 45
AzureIoTClient 42:c2eaa912a28c 46 typedef enum MESSAGE_OUTCOME_TAG
AzureIoTClient 42:c2eaa912a28c 47 {
AzureIoTClient 42:c2eaa912a28c 48 MESSAGE_OUTCOME_ACCEPTED,
AzureIoTClient 42:c2eaa912a28c 49 MESSAGE_OUTCOME_REJECTED,
AzureIoTClient 42:c2eaa912a28c 50 MESSAGE_OUTCOME_RELEASED
AzureIoTClient 42:c2eaa912a28c 51 } MESSAGE_OUTCOME;
AzureIoTClient 42:c2eaa912a28c 52
AzureIoTClient 42:c2eaa912a28c 53 typedef struct IOTHUBTRANSPORT_AMQP_METHOD_TAG
AzureIoTClient 42:c2eaa912a28c 54 {
AzureIoTClient 42:c2eaa912a28c 55 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle;
AzureIoTClient 42:c2eaa912a28c 56 uuid correlation_id;
AzureIoTClient 42:c2eaa912a28c 57 } IOTHUBTRANSPORT_AMQP_METHOD;
AzureIoTClient 42:c2eaa912a28c 58
AzureIoTClient 42:c2eaa912a28c 59 static void remove_tracked_handle(IOTHUBTRANSPORT_AMQP_METHODS* amqp_methods_handle, IOTHUBTRANSPORT_AMQP_METHOD_HANDLE method_request_handle)
AzureIoTClient 42:c2eaa912a28c 60 {
AzureIoTClient 42:c2eaa912a28c 61 size_t i;
AzureIoTClient 42:c2eaa912a28c 62
AzureIoTClient 42:c2eaa912a28c 63 for (i = 0; i < amqp_methods_handle->method_request_handle_count; i++)
AzureIoTClient 42:c2eaa912a28c 64 {
AzureIoTClient 42:c2eaa912a28c 65 if (amqp_methods_handle->method_request_handles[i] == method_request_handle)
AzureIoTClient 42:c2eaa912a28c 66 {
AzureIoTClient 42:c2eaa912a28c 67 if (amqp_methods_handle->method_request_handle_count - i > 1)
AzureIoTClient 42:c2eaa912a28c 68 {
AzureIoTClient 42:c2eaa912a28c 69 (void)memmove(&amqp_methods_handle->method_request_handles[i], &amqp_methods_handle->method_request_handles[i + 1],
AzureIoTClient 42:c2eaa912a28c 70 (amqp_methods_handle->method_request_handle_count - i - 1) * sizeof(IOTHUBTRANSPORT_AMQP_METHOD_HANDLE));
AzureIoTClient 42:c2eaa912a28c 71 }
AzureIoTClient 42:c2eaa912a28c 72
AzureIoTClient 42:c2eaa912a28c 73 amqp_methods_handle->method_request_handle_count--;
AzureIoTClient 42:c2eaa912a28c 74 i--;
AzureIoTClient 42:c2eaa912a28c 75 }
AzureIoTClient 42:c2eaa912a28c 76 }
AzureIoTClient 42:c2eaa912a28c 77
AzureIoTClient 42:c2eaa912a28c 78 if (amqp_methods_handle->method_request_handle_count == 0)
AzureIoTClient 42:c2eaa912a28c 79 {
AzureIoTClient 42:c2eaa912a28c 80 free(amqp_methods_handle->method_request_handles);
AzureIoTClient 42:c2eaa912a28c 81 amqp_methods_handle->method_request_handles = NULL;
AzureIoTClient 42:c2eaa912a28c 82 }
AzureIoTClient 42:c2eaa912a28c 83 else
AzureIoTClient 42:c2eaa912a28c 84 {
AzureIoTClient 42:c2eaa912a28c 85 IOTHUBTRANSPORT_AMQP_METHOD_HANDLE* new_handles = (IOTHUBTRANSPORT_AMQP_METHOD_HANDLE*)realloc(amqp_methods_handle->method_request_handles, amqp_methods_handle->method_request_handle_count * sizeof(IOTHUBTRANSPORT_AMQP_METHOD_HANDLE));
AzureIoTClient 42:c2eaa912a28c 86 if (new_handles != NULL)
AzureIoTClient 42:c2eaa912a28c 87 {
AzureIoTClient 42:c2eaa912a28c 88 amqp_methods_handle->method_request_handles = new_handles;
AzureIoTClient 42:c2eaa912a28c 89 }
AzureIoTClient 42:c2eaa912a28c 90 }
AzureIoTClient 42:c2eaa912a28c 91 }
AzureIoTClient 42:c2eaa912a28c 92
AzureIoTClient 42:c2eaa912a28c 93 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransportamqp_methods_create(const char* hostname, const char* device_id)
AzureIoTClient 42:c2eaa912a28c 94 {
AzureIoTClient 42:c2eaa912a28c 95 IOTHUBTRANSPORT_AMQP_METHODS* result;
AzureIoTClient 42:c2eaa912a28c 96
AzureIoTClient 42:c2eaa912a28c 97 if ((hostname == NULL) ||
AzureIoTClient 42:c2eaa912a28c 98 (device_id == NULL))
AzureIoTClient 42:c2eaa912a28c 99 {
AzureIoTClient 42:c2eaa912a28c 100 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_002: [ If any argument is NULL, `iothubtransportamqp_methods_create` shall return NULL. ]*/
AzureIoTClient 42:c2eaa912a28c 101 result = NULL;
AzureIoTClient 42:c2eaa912a28c 102 LogError("Bad arguments: hostname=%p, device_id=%p", hostname, device_id);
AzureIoTClient 42:c2eaa912a28c 103 }
AzureIoTClient 42:c2eaa912a28c 104 else
AzureIoTClient 42:c2eaa912a28c 105 {
AzureIoTClient 42:c2eaa912a28c 106 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_001: [ `iothubtransportamqp_methods_create` shall instantiate a new handler for C2D methods over AMQP for device `device_id` and on success return a non-NULL handle to it. ]*/
AzureIoTClient 42:c2eaa912a28c 107 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_003: [ `iothubtransportamqp_methods_create` shall allocate memory for the new instance. ]*/
AzureIoTClient 42:c2eaa912a28c 108 result = malloc(sizeof(IOTHUBTRANSPORT_AMQP_METHODS));
AzureIoTClient 42:c2eaa912a28c 109 if (result == NULL)
AzureIoTClient 42:c2eaa912a28c 110 {
AzureIoTClient 42:c2eaa912a28c 111 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_004: [ If allocating memory fails, `iothubtransportamqp_methods_create` shall return NULL. ]*/
AzureIoTClient 42:c2eaa912a28c 112 LogError("Cannot allocate memory for AMQP C2D methods handle");
AzureIoTClient 42:c2eaa912a28c 113 }
AzureIoTClient 42:c2eaa912a28c 114 else
AzureIoTClient 42:c2eaa912a28c 115 {
AzureIoTClient 42:c2eaa912a28c 116 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_115: [ `iothubtransportamqp_methods_create` shall save the device id for later use by using `mallocAndStrcpy_s`. ]*/
AzureIoTClient 42:c2eaa912a28c 117 if (mallocAndStrcpy_s(&result->device_id, device_id) != 0)
AzureIoTClient 42:c2eaa912a28c 118 {
AzureIoTClient 42:c2eaa912a28c 119 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_116: [ If `mallocAndStrcpy_s` fails, `iothubtransportamqp_methods_create` shall return NULL. ]*/
AzureIoTClient 42:c2eaa912a28c 120 LogError("Cannot copy device_id");
AzureIoTClient 42:c2eaa912a28c 121 free(result);
AzureIoTClient 42:c2eaa912a28c 122 result = NULL;
AzureIoTClient 42:c2eaa912a28c 123 }
AzureIoTClient 42:c2eaa912a28c 124 else
AzureIoTClient 42:c2eaa912a28c 125 {
AzureIoTClient 42:c2eaa912a28c 126 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_139: [ `iothubtransportamqp_methods_create` shall save the `hostname` for later use by using `mallocAndStrcpy_s`. ]*/
AzureIoTClient 42:c2eaa912a28c 127 if (mallocAndStrcpy_s(&result->hostname, hostname) != 0)
AzureIoTClient 42:c2eaa912a28c 128 {
AzureIoTClient 42:c2eaa912a28c 129 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_116: [ If `mallocAndStrcpy_s` fails, `iothubtransportamqp_methods_create` shall return NULL. ]*/
AzureIoTClient 42:c2eaa912a28c 130 LogError("Cannot copy hostname");
AzureIoTClient 42:c2eaa912a28c 131 free(result->device_id);
AzureIoTClient 42:c2eaa912a28c 132 free(result);
AzureIoTClient 42:c2eaa912a28c 133 result = NULL;
AzureIoTClient 42:c2eaa912a28c 134 }
AzureIoTClient 42:c2eaa912a28c 135 else
AzureIoTClient 42:c2eaa912a28c 136 {
AzureIoTClient 42:c2eaa912a28c 137 result->subscribe_state = SUBSCRIBE_STATE_NOT_SUBSCRIBED;
AzureIoTClient 42:c2eaa912a28c 138 result->method_request_handles = NULL;
AzureIoTClient 42:c2eaa912a28c 139 result->method_request_handle_count = 0;
AzureIoTClient 42:c2eaa912a28c 140 result->receiver_link_disconnected = false;
AzureIoTClient 42:c2eaa912a28c 141 result->sender_link_disconnected = false;
AzureIoTClient 42:c2eaa912a28c 142 }
AzureIoTClient 42:c2eaa912a28c 143 }
AzureIoTClient 42:c2eaa912a28c 144 }
AzureIoTClient 42:c2eaa912a28c 145 }
AzureIoTClient 42:c2eaa912a28c 146
AzureIoTClient 42:c2eaa912a28c 147 return result;
AzureIoTClient 42:c2eaa912a28c 148 }
AzureIoTClient 42:c2eaa912a28c 149
AzureIoTClient 42:c2eaa912a28c 150 void iothubtransportamqp_methods_destroy(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
AzureIoTClient 42:c2eaa912a28c 151 {
AzureIoTClient 42:c2eaa912a28c 152 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_006: [ If `iothubtransport_amqp_methods_handle` is NULL, `iothubtransportamqp_methods_destroy` shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 153 if (iothubtransport_amqp_methods_handle == NULL)
AzureIoTClient 42:c2eaa912a28c 154 {
AzureIoTClient 42:c2eaa912a28c 155 LogError("NULL handle");
AzureIoTClient 42:c2eaa912a28c 156 }
AzureIoTClient 42:c2eaa912a28c 157 else
AzureIoTClient 42:c2eaa912a28c 158 {
AzureIoTClient 42:c2eaa912a28c 159 size_t i;
AzureIoTClient 42:c2eaa912a28c 160
AzureIoTClient 42:c2eaa912a28c 161 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_007: [ If the instance pointed to by `iothubtransport_amqp_methods_handle` is subscribed to receive C2D methods, `iothubtransportamqp_methods_destroy` shall free all resources allocated by the subscribe. ]*/
AzureIoTClient 42:c2eaa912a28c 162 if (iothubtransport_amqp_methods_handle->subscribe_state == SUBSCRIBE_STATE_SUBSCRIBED)
AzureIoTClient 42:c2eaa912a28c 163 {
AzureIoTClient 42:c2eaa912a28c 164 iothubtransportamqp_methods_unsubscribe(iothubtransport_amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 165 }
AzureIoTClient 42:c2eaa912a28c 166
AzureIoTClient 42:c2eaa912a28c 167 for (i = 0; i < iothubtransport_amqp_methods_handle->method_request_handle_count; i++)
AzureIoTClient 42:c2eaa912a28c 168 {
AzureIoTClient 42:c2eaa912a28c 169 free(iothubtransport_amqp_methods_handle->method_request_handles[i]);
AzureIoTClient 42:c2eaa912a28c 170 }
AzureIoTClient 42:c2eaa912a28c 171
AzureIoTClient 42:c2eaa912a28c 172 if (iothubtransport_amqp_methods_handle->method_request_handles != NULL)
AzureIoTClient 42:c2eaa912a28c 173 {
AzureIoTClient 42:c2eaa912a28c 174 free(iothubtransport_amqp_methods_handle->method_request_handles);
AzureIoTClient 42:c2eaa912a28c 175 }
AzureIoTClient 42:c2eaa912a28c 176
AzureIoTClient 42:c2eaa912a28c 177 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_005: [ `iothubtransportamqp_methods_destroy` shall free all resources allocated by `iothubtransportamqp_methods_create` for the handle `iothubtransport_amqp_methods_handle`. ]*/
AzureIoTClient 42:c2eaa912a28c 178 free(iothubtransport_amqp_methods_handle->hostname);
AzureIoTClient 42:c2eaa912a28c 179 free(iothubtransport_amqp_methods_handle->device_id);
AzureIoTClient 42:c2eaa912a28c 180 free(iothubtransport_amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 181 }
AzureIoTClient 42:c2eaa912a28c 182 }
AzureIoTClient 42:c2eaa912a28c 183
AzureIoTClient 42:c2eaa912a28c 184 static void call_methods_unsubscribed_if_needed(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE amqp_methods_handle)
AzureIoTClient 42:c2eaa912a28c 185 {
AzureIoTClient 42:c2eaa912a28c 186 if (amqp_methods_handle->receiver_link_disconnected && amqp_methods_handle->sender_link_disconnected)
AzureIoTClient 42:c2eaa912a28c 187 {
AzureIoTClient 42:c2eaa912a28c 188 amqp_methods_handle->receiver_link_disconnected = false;
AzureIoTClient 42:c2eaa912a28c 189 amqp_methods_handle->sender_link_disconnected = false;
AzureIoTClient 42:c2eaa912a28c 190 amqp_methods_handle->on_methods_unsubscribed(amqp_methods_handle->on_methods_unsubscribed_context);
AzureIoTClient 42:c2eaa912a28c 191 }
AzureIoTClient 42:c2eaa912a28c 192 }
AzureIoTClient 42:c2eaa912a28c 193
AzureIoTClient 42:c2eaa912a28c 194 static void on_message_receiver_state_changed(const void* context, MESSAGE_RECEIVER_STATE new_state, MESSAGE_RECEIVER_STATE previous_state)
AzureIoTClient 42:c2eaa912a28c 195 {
AzureIoTClient 42:c2eaa912a28c 196 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_119: [ When `on_message_receiver_state_changed` is called with the `new_state` being `MESSAGE_RECEIVER_STATE_ERROR`, an error shall be indicated by calling the `on_methods_error` callback passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 197 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_126: [ For the other state changes, on_message_receiver_state_changed shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 198 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE amqp_methods_handle = (IOTHUBTRANSPORT_AMQP_METHODS_HANDLE)context;
AzureIoTClient 42:c2eaa912a28c 199 if ((new_state != previous_state) &&
AzureIoTClient 42:c2eaa912a28c 200 (new_state == MESSAGE_RECEIVER_STATE_ERROR))
AzureIoTClient 42:c2eaa912a28c 201 {
AzureIoTClient 42:c2eaa912a28c 202 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_120: [ When an error is indicated by calling the `on_methods_error`, it shall be called with the context being the `on_methods_error_context` argument passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 203 amqp_methods_handle->on_methods_error(amqp_methods_handle->on_methods_error_context);
AzureIoTClient 42:c2eaa912a28c 204 }
AzureIoTClient 42:c2eaa912a28c 205 else
AzureIoTClient 42:c2eaa912a28c 206 {
AzureIoTClient 42:c2eaa912a28c 207 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_12_001: [ When `on_message_receiver_state_changed` is called with the `new_state` being `MESSAGE_RECEIVER_STATE_IDLE` and `previous_state` being `MESSAGE_RECEIVER_STATE_OPEN`and the sender link is already diconnected `on_message_receiver_state_changed` calls to `on_methods_unsubscribed`. ]*/
AzureIoTClient 42:c2eaa912a28c 208 if ((new_state == MESSAGE_RECEIVER_STATE_IDLE) && (previous_state == MESSAGE_RECEIVER_STATE_OPEN))
AzureIoTClient 42:c2eaa912a28c 209 {
AzureIoTClient 42:c2eaa912a28c 210 amqp_methods_handle->receiver_link_disconnected = true;
AzureIoTClient 42:c2eaa912a28c 211 }
AzureIoTClient 42:c2eaa912a28c 212 call_methods_unsubscribed_if_needed(amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 213 }
AzureIoTClient 42:c2eaa912a28c 214 }
AzureIoTClient 42:c2eaa912a28c 215
AzureIoTClient 42:c2eaa912a28c 216 static void on_message_sender_state_changed(void* context, MESSAGE_SENDER_STATE new_state, MESSAGE_SENDER_STATE previous_state)
AzureIoTClient 42:c2eaa912a28c 217 {
AzureIoTClient 42:c2eaa912a28c 218 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE amqp_methods_handle = (IOTHUBTRANSPORT_AMQP_METHODS_HANDLE)context;
AzureIoTClient 42:c2eaa912a28c 219 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_059: [ When `on_message_sender_state_changed` is called with the `new_state` being `MESSAGE_SENDER_STATE_ERROR`, an error shall be indicated by calling the `on_methods_error` callback passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 220 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_127: [ For the other state changes, on_message_sender_state_changed shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 221 if ((new_state != previous_state) &&
AzureIoTClient 42:c2eaa912a28c 222 (new_state == MESSAGE_SENDER_STATE_ERROR))
AzureIoTClient 42:c2eaa912a28c 223 {
AzureIoTClient 42:c2eaa912a28c 224 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_120: [ When an error is indicated by calling the `on_methods_error`, it shall be called with the context being the `on_methods_error_context` argument passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 225 amqp_methods_handle->on_methods_error(amqp_methods_handle->on_methods_error_context);
AzureIoTClient 42:c2eaa912a28c 226 }
AzureIoTClient 42:c2eaa912a28c 227 else
AzureIoTClient 42:c2eaa912a28c 228 {
AzureIoTClient 42:c2eaa912a28c 229 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_12_002: [ When `on_message_sender_state_changed` is called with the `new_state` being `MESSAGE_SENDER_STATE_IDLE` and `previous_state` being `MESSAGE_SENDER_STATE_OPEN`and the receiver link is already diconnected `on_message_sender_state_changed` calls to `on_methods_unsubscribed`. ]*/
AzureIoTClient 42:c2eaa912a28c 230 if ((new_state == MESSAGE_SENDER_STATE_IDLE) && (previous_state == MESSAGE_SENDER_STATE_OPEN))
AzureIoTClient 42:c2eaa912a28c 231 {
AzureIoTClient 42:c2eaa912a28c 232 amqp_methods_handle->sender_link_disconnected = true;
AzureIoTClient 42:c2eaa912a28c 233 }
AzureIoTClient 42:c2eaa912a28c 234 call_methods_unsubscribed_if_needed(amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 235 }
AzureIoTClient 42:c2eaa912a28c 236 }
AzureIoTClient 42:c2eaa912a28c 237
AzureIoTClient 42:c2eaa912a28c 238 static void on_message_send_complete(void* context, MESSAGE_SEND_RESULT send_result)
AzureIoTClient 42:c2eaa912a28c 239 {
AzureIoTClient 42:c2eaa912a28c 240 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_084: [ Otherwise no action shall be taken. ]*/
AzureIoTClient 42:c2eaa912a28c 241 if (send_result == MESSAGE_SEND_ERROR)
AzureIoTClient 42:c2eaa912a28c 242 {
AzureIoTClient 42:c2eaa912a28c 243 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE amqp_methods_handle = (IOTHUBTRANSPORT_AMQP_METHODS_HANDLE)context;
AzureIoTClient 42:c2eaa912a28c 244 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_083: [ If `send_result` is `MESSAGE_SEND_ERROR` then an error shall be indicated by calling the `on_methods_error` callback passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 245 amqp_methods_handle->on_methods_error(amqp_methods_handle->on_methods_error_context);
AzureIoTClient 42:c2eaa912a28c 246 }
AzureIoTClient 42:c2eaa912a28c 247 }
AzureIoTClient 42:c2eaa912a28c 248
AzureIoTClient 42:c2eaa912a28c 249 static AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message)
AzureIoTClient 42:c2eaa912a28c 250 {
AzureIoTClient 42:c2eaa912a28c 251 PROPERTIES_HANDLE properties;
AzureIoTClient 42:c2eaa912a28c 252 /* VS believes this is not initialized, so have to set it to the worse case here */
AzureIoTClient 42:c2eaa912a28c 253 AMQP_VALUE result = NULL;
AzureIoTClient 42:c2eaa912a28c 254 IOTHUBTRANSPORT_AMQP_METHODS_HANDLE amqp_methods_handle = (IOTHUBTRANSPORT_AMQP_METHODS_HANDLE)context;
AzureIoTClient 42:c2eaa912a28c 255 MESSAGE_OUTCOME message_outcome;
AzureIoTClient 42:c2eaa912a28c 256
AzureIoTClient 42:c2eaa912a28c 257 if (message == NULL)
AzureIoTClient 42:c2eaa912a28c 258 {
AzureIoTClient 42:c2eaa912a28c 259 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_041: [ If `message` is NULL, the RELEASED outcome shall be returned and an error shall be indicated. ]*/
AzureIoTClient 42:c2eaa912a28c 260 LogError("NULL message");
AzureIoTClient 42:c2eaa912a28c 261 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 262 }
AzureIoTClient 42:c2eaa912a28c 263 else
AzureIoTClient 42:c2eaa912a28c 264 {
AzureIoTClient 42:c2eaa912a28c 265 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_043: [ When `on_message_received` is called (to indicate a new message being received over the receiver link), the message shall be processed as below: ]*/
AzureIoTClient 42:c2eaa912a28c 266 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_044: [ - The message properties shall be obtained by calling `message_get_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 267 if (message_get_properties(message, &properties) != 0)
AzureIoTClient 42:c2eaa912a28c 268 {
AzureIoTClient 42:c2eaa912a28c 269 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_045: [ If `message_get_properties` fails, the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 270 LogError("Cannot retrieve message properties");
AzureIoTClient 42:c2eaa912a28c 271 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 272 result = messaging_delivery_rejected("amqp:decode-error", "Cannot retrieve message properties");
AzureIoTClient 42:c2eaa912a28c 273 }
AzureIoTClient 42:c2eaa912a28c 274 else
AzureIoTClient 42:c2eaa912a28c 275 {
AzureIoTClient 42:c2eaa912a28c 276 AMQP_VALUE correlation_id;
AzureIoTClient 42:c2eaa912a28c 277
AzureIoTClient 42:c2eaa912a28c 278 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_046: [ - The correlation id shall be obtained by calling `properties_get_correlation_id` on the message properties. ]*/
AzureIoTClient 42:c2eaa912a28c 279 if (properties_get_correlation_id(properties, &correlation_id) != 0)
AzureIoTClient 42:c2eaa912a28c 280 {
AzureIoTClient 42:c2eaa912a28c 281 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_047: [ If `properties_get_correlation_id` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 282 LogError("Cannot retrieve correlation id");
AzureIoTClient 42:c2eaa912a28c 283 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 284 result = messaging_delivery_rejected("amqp:decode-error", "Cannot retrieve correlation id");
AzureIoTClient 42:c2eaa912a28c 285 }
AzureIoTClient 42:c2eaa912a28c 286 else
AzureIoTClient 42:c2eaa912a28c 287 {
AzureIoTClient 42:c2eaa912a28c 288 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_112: [ Memory shall be allocated for the `IOTHUBTRANSPORT_AMQP_METHOD_HANDLE` to hold the correlation-id, so that it can be used in the `iothubtransportamqp_methods_respond` function. ]*/
AzureIoTClient 42:c2eaa912a28c 289 IOTHUBTRANSPORT_AMQP_METHOD* method_handle = (IOTHUBTRANSPORT_AMQP_METHOD*)malloc(sizeof(IOTHUBTRANSPORT_AMQP_METHOD));
AzureIoTClient 42:c2eaa912a28c 290 if (method_handle == NULL)
AzureIoTClient 42:c2eaa912a28c 291 {
AzureIoTClient 42:c2eaa912a28c 292 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_130: [ If allocating memory for the `IOTHUBTRANSPORT_AMQP_METHOD_HANDLE` handle fails, the RELEASED outcome shall be returned and an error shall be indicated. ]*/
AzureIoTClient 42:c2eaa912a28c 293 LogError("Cannot allocate method handle");
AzureIoTClient 42:c2eaa912a28c 294 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 295 }
AzureIoTClient 42:c2eaa912a28c 296 else
AzureIoTClient 42:c2eaa912a28c 297 {
AzureIoTClient 42:c2eaa912a28c 298 IOTHUBTRANSPORT_AMQP_METHOD_HANDLE* new_handles;
AzureIoTClient 42:c2eaa912a28c 299 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_113: [ All `IOTHUBTRANSPORT_AMQP_METHOD_HANDLE` handles shall be tracked in an array of handles that shall be resized accordingly when a methopd handle is added to it. ]*/
AzureIoTClient 42:c2eaa912a28c 300 new_handles = (IOTHUBTRANSPORT_AMQP_METHOD_HANDLE*)realloc(amqp_methods_handle->method_request_handles, (amqp_methods_handle->method_request_handle_count + 1) * sizeof(IOTHUBTRANSPORT_AMQP_METHOD_HANDLE));
AzureIoTClient 42:c2eaa912a28c 301 if (new_handles == NULL)
AzureIoTClient 42:c2eaa912a28c 302 {
AzureIoTClient 42:c2eaa912a28c 303 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_138: [ If resizing the tracked method handles array fails, the RELEASED outcome shall be returned and an error shall be indicated. ]*/
AzureIoTClient 42:c2eaa912a28c 304 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 305 LogError("Cannot grow method handles array");
AzureIoTClient 42:c2eaa912a28c 306 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 307 }
AzureIoTClient 42:c2eaa912a28c 308 else
AzureIoTClient 42:c2eaa912a28c 309 {
AzureIoTClient 42:c2eaa912a28c 310 amqp_methods_handle->method_request_handles = new_handles;
AzureIoTClient 42:c2eaa912a28c 311
AzureIoTClient 42:c2eaa912a28c 312 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_121: [ The uuid value for the correlation ID shall be obtained by calling `amqpvalue_get_uuid`. ]*/
AzureIoTClient 42:c2eaa912a28c 313 if (amqpvalue_get_uuid(correlation_id, &method_handle->correlation_id) != 0)
AzureIoTClient 42:c2eaa912a28c 314 {
AzureIoTClient 42:c2eaa912a28c 315 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_122: [ If `amqpvalue_get_uuid` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 316 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 317 LogError("Cannot get uuid value for correlation-id");
AzureIoTClient 42:c2eaa912a28c 318 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 319 result = messaging_delivery_rejected("amqp:decode-error", "Cannot get uuid value for correlation-id");
AzureIoTClient 42:c2eaa912a28c 320 }
AzureIoTClient 42:c2eaa912a28c 321 else
AzureIoTClient 42:c2eaa912a28c 322 {
AzureIoTClient 42:c2eaa912a28c 323 BINARY_DATA binary_data;
AzureIoTClient 42:c2eaa912a28c 324
AzureIoTClient 42:c2eaa912a28c 325 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_048: [ - The message payload shall be obtained by calling `message_get_body_amqp_data_in_place` with the index argument being 0. ]*/
AzureIoTClient 42:c2eaa912a28c 326 if (message_get_body_amqp_data_in_place(message, 0, &binary_data) != 0)
AzureIoTClient 42:c2eaa912a28c 327 {
AzureIoTClient 42:c2eaa912a28c 328 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_049: [ If `message_get_body_amqp_data_in_place` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 329 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 330 LogError("Cannot get method request message payload");
AzureIoTClient 42:c2eaa912a28c 331 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 332 result = messaging_delivery_rejected("amqp:decode-error", "Cannot get method request message payload");
AzureIoTClient 42:c2eaa912a28c 333 }
AzureIoTClient 42:c2eaa912a28c 334 else
AzureIoTClient 42:c2eaa912a28c 335 {
AzureIoTClient 42:c2eaa912a28c 336 AMQP_VALUE application_properties;
AzureIoTClient 42:c2eaa912a28c 337
AzureIoTClient 42:c2eaa912a28c 338 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_099: [ The application properties for the received message shall be obtained by calling `message_get_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 339 if (message_get_application_properties(message, &application_properties) != 0)
AzureIoTClient 42:c2eaa912a28c 340 {
AzureIoTClient 42:c2eaa912a28c 341 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_133: [ If `message_get_application_properties` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 342 LogError("Cannot get application properties");
AzureIoTClient 42:c2eaa912a28c 343 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 344 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 345 result = messaging_delivery_rejected("amqp:decode-error", "Cannot get application properties");
AzureIoTClient 42:c2eaa912a28c 346 }
AzureIoTClient 42:c2eaa912a28c 347 else
AzureIoTClient 42:c2eaa912a28c 348 {
AzureIoTClient 42:c2eaa912a28c 349 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_123: [ The AMQP map shall be retrieve from the application properties by calling `amqpvalue_get_inplace_described_value`. ]*/
AzureIoTClient 42:c2eaa912a28c 350 AMQP_VALUE amqp_properties_map = amqpvalue_get_inplace_described_value(application_properties);
AzureIoTClient 42:c2eaa912a28c 351 if (amqp_properties_map == NULL)
AzureIoTClient 42:c2eaa912a28c 352 {
AzureIoTClient 42:c2eaa912a28c 353 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_134: [ If `amqpvalue_get_inplace_described_value` fails the RELEASED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 354 LogError("Cannot get application properties map");
AzureIoTClient 42:c2eaa912a28c 355 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 356 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 357 }
AzureIoTClient 42:c2eaa912a28c 358 else
AzureIoTClient 42:c2eaa912a28c 359 {
AzureIoTClient 42:c2eaa912a28c 360 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_100: [ A property key `IoThub-methodname` shall be created by calling `amqpvalue_create_string`. ]*/
AzureIoTClient 42:c2eaa912a28c 361 AMQP_VALUE property_key = amqpvalue_create_string("IoThub-methodname");
AzureIoTClient 42:c2eaa912a28c 362 if (property_key == NULL)
AzureIoTClient 42:c2eaa912a28c 363 {
AzureIoTClient 42:c2eaa912a28c 364 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_132: [ If `amqpvalue_create_string` fails the RELEASED outcome shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 365 LogError("Cannot create the property key for method name");
AzureIoTClient 42:c2eaa912a28c 366 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 367 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 368 }
AzureIoTClient 42:c2eaa912a28c 369 else
AzureIoTClient 42:c2eaa912a28c 370 {
AzureIoTClient 42:c2eaa912a28c 371 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_101: [ The method name property value shall be found in the map by calling `amqpvalue_get_map_value`. ]*/
AzureIoTClient 42:c2eaa912a28c 372 AMQP_VALUE property_value = amqpvalue_get_map_value(amqp_properties_map, property_key);
AzureIoTClient 42:c2eaa912a28c 373 if (property_value == NULL)
AzureIoTClient 42:c2eaa912a28c 374 {
AzureIoTClient 42:c2eaa912a28c 375 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_103: [ If `amqpvalue_get_map_value` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 376 LogError("Cannot find the IoThub-methodname property in the properties map");
AzureIoTClient 42:c2eaa912a28c 377 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 378 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 379 result = messaging_delivery_rejected("amqp:decode-error", "Cannot find the IoThub-methodname property in the properties map");
AzureIoTClient 42:c2eaa912a28c 380 }
AzureIoTClient 42:c2eaa912a28c 381 else
AzureIoTClient 42:c2eaa912a28c 382 {
AzureIoTClient 42:c2eaa912a28c 383 const char* method_name;
AzureIoTClient 42:c2eaa912a28c 384
AzureIoTClient 42:c2eaa912a28c 385 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_102: [ The string contained by the property value shall be obtained by calling `amqpvalue_get_string`. ]*/
AzureIoTClient 42:c2eaa912a28c 386 if (amqpvalue_get_string(property_value, &method_name) != 0)
AzureIoTClient 42:c2eaa912a28c 387 {
AzureIoTClient 42:c2eaa912a28c 388 /*Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_131: [ If `amqpvalue_get_string` fails the REJECTED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 389 LogError("Cannot read the method name from the property value");
AzureIoTClient 42:c2eaa912a28c 390 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 391 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 392 result = messaging_delivery_rejected("amqp:decode-error", "Cannot read the method name from the property value");
AzureIoTClient 42:c2eaa912a28c 393 }
AzureIoTClient 42:c2eaa912a28c 394 else
AzureIoTClient 42:c2eaa912a28c 395 {
AzureIoTClient 42:c2eaa912a28c 396 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_056: [ On success the `on_message_received` callback shall return a newly constructed delivery state obtained by calling `messaging_delivery_accepted`. ]*/
AzureIoTClient 42:c2eaa912a28c 397 result = messaging_delivery_accepted();
AzureIoTClient 42:c2eaa912a28c 398 if (result == NULL)
AzureIoTClient 42:c2eaa912a28c 399 {
AzureIoTClient 42:c2eaa912a28c 400 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_057: [ If `messaging_delivery_accepted` fails the RELEASED outcome with `amqp:decode-error` shall be returned. ]*/
AzureIoTClient 42:c2eaa912a28c 401 LogError("Cannot allocate memory for delivery state");
AzureIoTClient 42:c2eaa912a28c 402 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 403 message_outcome = MESSAGE_OUTCOME_RELEASED;
AzureIoTClient 42:c2eaa912a28c 404 }
AzureIoTClient 42:c2eaa912a28c 405 else
AzureIoTClient 42:c2eaa912a28c 406 {
AzureIoTClient 42:c2eaa912a28c 407 method_handle->iothubtransport_amqp_methods_handle = amqp_methods_handle;
AzureIoTClient 42:c2eaa912a28c 408
AzureIoTClient 42:c2eaa912a28c 409 /* set the method request handle in the handle array */
AzureIoTClient 42:c2eaa912a28c 410 amqp_methods_handle->method_request_handles[amqp_methods_handle->method_request_handle_count] = method_handle;
AzureIoTClient 42:c2eaa912a28c 411 amqp_methods_handle->method_request_handle_count++;
AzureIoTClient 42:c2eaa912a28c 412
AzureIoTClient 42:c2eaa912a28c 413 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_050: [ The binary message payload shall be indicated by calling the `on_method_request_received` callback passed to `iothubtransportamqp_methods_subscribe` with the arguments: ]*/
AzureIoTClient 42:c2eaa912a28c 414 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_051: [ - `context` shall be set to the `on_method_request_received_context` argument passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 415 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_098: [ - `method_name` shall be set to the application property value for `IoThub-methodname`. ]*/
AzureIoTClient 42:c2eaa912a28c 416 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_052: [ - `request` shall be set to the payload bytes obtained by calling `message_get_body_amqp_data_in_place`. ]*/
AzureIoTClient 42:c2eaa912a28c 417 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_053: [ - `request_size` shall be set to the payload size obtained by calling `message_get_body_amqp_data_in_place`. ]*/
AzureIoTClient 42:c2eaa912a28c 418 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_054: [ - `method_handle` shall be set to a newly created `IOTHUBTRANSPORT_AMQP_METHOD_HANDLE` that can be passed later as an argument to `iothubtransportamqp_methods_respond`. ]*/
AzureIoTClient 42:c2eaa912a28c 419 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_109: [ `iothubtransportamqp_methods_respond` shall be allowed to be called from the callback `on_method_request_received`. ]*/
AzureIoTClient 42:c2eaa912a28c 420 if (amqp_methods_handle->on_method_request_received(amqp_methods_handle->on_method_request_received_context, method_name, binary_data.bytes, binary_data.length, method_handle) != 0)
AzureIoTClient 42:c2eaa912a28c 421 {
AzureIoTClient 42:c2eaa912a28c 422 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_147: [ If `on_method_request_received` fails, the REJECTED outcome shall be returned with `amqp:internal-error`. ]*/
AzureIoTClient 42:c2eaa912a28c 423 LogError("Cannot execute the callback with the given data");
AzureIoTClient 42:c2eaa912a28c 424 amqpvalue_destroy(result);
AzureIoTClient 42:c2eaa912a28c 425 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 426 amqp_methods_handle->method_request_handle_count--;
AzureIoTClient 42:c2eaa912a28c 427 message_outcome = MESSAGE_OUTCOME_REJECTED;
AzureIoTClient 42:c2eaa912a28c 428 result = messaging_delivery_rejected("amqp:internal-error", "Cannot execute the callback with the given data");
AzureIoTClient 42:c2eaa912a28c 429 }
AzureIoTClient 42:c2eaa912a28c 430 else
AzureIoTClient 42:c2eaa912a28c 431 {
AzureIoTClient 42:c2eaa912a28c 432 message_outcome = MESSAGE_OUTCOME_ACCEPTED;
AzureIoTClient 42:c2eaa912a28c 433 }
AzureIoTClient 42:c2eaa912a28c 434 }
AzureIoTClient 42:c2eaa912a28c 435 }
AzureIoTClient 42:c2eaa912a28c 436
AzureIoTClient 42:c2eaa912a28c 437 amqpvalue_destroy(property_value);
AzureIoTClient 42:c2eaa912a28c 438 }
AzureIoTClient 42:c2eaa912a28c 439
AzureIoTClient 42:c2eaa912a28c 440 amqpvalue_destroy(property_key);
AzureIoTClient 42:c2eaa912a28c 441 }
AzureIoTClient 42:c2eaa912a28c 442 }
AzureIoTClient 42:c2eaa912a28c 443
AzureIoTClient 42:c2eaa912a28c 444 application_properties_destroy(application_properties);
AzureIoTClient 42:c2eaa912a28c 445 }
AzureIoTClient 42:c2eaa912a28c 446 }
AzureIoTClient 42:c2eaa912a28c 447 }
AzureIoTClient 42:c2eaa912a28c 448 }
AzureIoTClient 42:c2eaa912a28c 449 }
AzureIoTClient 42:c2eaa912a28c 450 }
AzureIoTClient 42:c2eaa912a28c 451
AzureIoTClient 42:c2eaa912a28c 452 properties_destroy(properties);
AzureIoTClient 42:c2eaa912a28c 453 }
AzureIoTClient 42:c2eaa912a28c 454 }
AzureIoTClient 42:c2eaa912a28c 455
AzureIoTClient 42:c2eaa912a28c 456 switch (message_outcome)
AzureIoTClient 42:c2eaa912a28c 457 {
AzureIoTClient 42:c2eaa912a28c 458 default:
AzureIoTClient 42:c2eaa912a28c 459 break;
AzureIoTClient 42:c2eaa912a28c 460
AzureIoTClient 42:c2eaa912a28c 461 case MESSAGE_OUTCOME_RELEASED:
AzureIoTClient 42:c2eaa912a28c 462 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_129: [ The released outcome shall be created by calling `messaging_delivery_released`. ]*/
AzureIoTClient 42:c2eaa912a28c 463 result = messaging_delivery_released();
AzureIoTClient 42:c2eaa912a28c 464
AzureIoTClient 42:c2eaa912a28c 465 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_128: [ When the RELEASED outcome is returned, an error shall be indicated by calling the `on_methods_error` callback passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 466 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_042: [ When an error is indicated by calling the `on_methods_error`, it shall be called with the context being the `on_methods_error_context` argument passed to `iothubtransportamqp_methods_subscribe`. ]*/
AzureIoTClient 42:c2eaa912a28c 467 amqp_methods_handle->on_methods_error(amqp_methods_handle->on_methods_error_context);
AzureIoTClient 42:c2eaa912a28c 468 break;
AzureIoTClient 42:c2eaa912a28c 469
AzureIoTClient 42:c2eaa912a28c 470 case MESSAGE_OUTCOME_REJECTED:
AzureIoTClient 42:c2eaa912a28c 471 case MESSAGE_OUTCOME_ACCEPTED:
AzureIoTClient 42:c2eaa912a28c 472 /* all is well */
AzureIoTClient 42:c2eaa912a28c 473 break;
AzureIoTClient 42:c2eaa912a28c 474 }
AzureIoTClient 42:c2eaa912a28c 475
AzureIoTClient 42:c2eaa912a28c 476 return result;
AzureIoTClient 42:c2eaa912a28c 477 }
AzureIoTClient 42:c2eaa912a28c 478
AzureIoTClient 42:c2eaa912a28c 479 static int set_link_attach_properties(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
AzureIoTClient 42:c2eaa912a28c 480 {
AzureIoTClient 42:c2eaa912a28c 481 int result = 0;
AzureIoTClient 42:c2eaa912a28c 482 fields link_attach_properties;
AzureIoTClient 42:c2eaa912a28c 483
AzureIoTClient 42:c2eaa912a28c 484 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_140: [ A link attach properties map shall be created by calling `amqpvalue_create_map`. ]*/
AzureIoTClient 42:c2eaa912a28c 485 link_attach_properties = amqpvalue_create_map();
AzureIoTClient 42:c2eaa912a28c 486 if (link_attach_properties == NULL)
AzureIoTClient 42:c2eaa912a28c 487 {
AzureIoTClient 42:c2eaa912a28c 488 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 489 LogError("Cannot create the map for link ttach properties");
AzureIoTClient 42:c2eaa912a28c 490 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 491 }
AzureIoTClient 42:c2eaa912a28c 492 else
AzureIoTClient 42:c2eaa912a28c 493 {
AzureIoTClient 42:c2eaa912a28c 494 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_141: [ A property key which shall be a symbol named `com.microsoft:channel-correlation-id` shall be created by calling `amqp_create_symbol`. ]*/
AzureIoTClient 42:c2eaa912a28c 495 AMQP_VALUE channel_correlation_id_property_key = amqpvalue_create_symbol("com.microsoft:channel-correlation-id");
AzureIoTClient 42:c2eaa912a28c 496 if (channel_correlation_id_property_key == NULL)
AzureIoTClient 42:c2eaa912a28c 497 {
AzureIoTClient 42:c2eaa912a28c 498 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 499 LogError("Cannot create the channel correlation id property key for the link attach properties");
AzureIoTClient 42:c2eaa912a28c 500 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 501 }
AzureIoTClient 42:c2eaa912a28c 502 else
AzureIoTClient 42:c2eaa912a28c 503 {
AzureIoTClient 42:c2eaa912a28c 504 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_142: [ A property value of type string that shall contain the device id shall be created by calling `amqpvalue_create_string`. ]*/
AzureIoTClient 42:c2eaa912a28c 505 AMQP_VALUE channel_correlation_id_property_value = amqpvalue_create_string(iothubtransport_amqp_methods_handle->device_id);
AzureIoTClient 42:c2eaa912a28c 506 if (channel_correlation_id_property_value == NULL)
AzureIoTClient 42:c2eaa912a28c 507 {
AzureIoTClient 42:c2eaa912a28c 508 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 509 LogError("Cannot create the channel correlation id property key for the link attach properties");
AzureIoTClient 42:c2eaa912a28c 510 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 511 }
AzureIoTClient 42:c2eaa912a28c 512 else
AzureIoTClient 42:c2eaa912a28c 513 {
AzureIoTClient 42:c2eaa912a28c 514 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_143: [ The `com.microsoft:channel-correlation-id` shall be added to the link attach properties by calling `amqpvalue_set_map_value`. ]*/
AzureIoTClient 42:c2eaa912a28c 515 if (amqpvalue_set_map_value(link_attach_properties, channel_correlation_id_property_key, channel_correlation_id_property_value) != 0)
AzureIoTClient 42:c2eaa912a28c 516 {
AzureIoTClient 42:c2eaa912a28c 517 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 518 LogError("Cannot set the property for channel correlation on the link attach properties");
AzureIoTClient 42:c2eaa912a28c 519 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 520 }
AzureIoTClient 42:c2eaa912a28c 521 else
AzureIoTClient 42:c2eaa912a28c 522 {
AzureIoTClient 42:c2eaa912a28c 523 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_150: [ A property key which shall be a symbol named `com.microsoft:api-version` shall be created by calling `amqp_create_symbol`. ]*/
AzureIoTClient 42:c2eaa912a28c 524 AMQP_VALUE api_version_property_key = amqpvalue_create_symbol("com.microsoft:api-version");
AzureIoTClient 42:c2eaa912a28c 525 if (api_version_property_key == NULL)
AzureIoTClient 42:c2eaa912a28c 526 {
AzureIoTClient 42:c2eaa912a28c 527 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 528 LogError("Cannot create the API version property key for the link attach properties");
AzureIoTClient 42:c2eaa912a28c 529 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 530 }
AzureIoTClient 42:c2eaa912a28c 531 else
AzureIoTClient 42:c2eaa912a28c 532 {
AzureIoTClient 42:c2eaa912a28c 533 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_151: [ A property value of type string that shall contain the `2016-11-14` shall be created by calling `amqpvalue_create_string`. ]*/
AzureIoTClient 42:c2eaa912a28c 534 AMQP_VALUE api_version_property_value = amqpvalue_create_string("2016-11-14");
AzureIoTClient 42:c2eaa912a28c 535 if (api_version_property_value == NULL)
AzureIoTClient 42:c2eaa912a28c 536 {
AzureIoTClient 42:c2eaa912a28c 537 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 538 LogError("Cannot create the API version property value for the link attach properties");
AzureIoTClient 42:c2eaa912a28c 539 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 540 }
AzureIoTClient 42:c2eaa912a28c 541 else
AzureIoTClient 42:c2eaa912a28c 542 {
AzureIoTClient 42:c2eaa912a28c 543 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_152: [ The `com.microsoft:api-version` shall be added to the link attach properties by calling `amqpvalue_set_map_value`. ]*/
AzureIoTClient 42:c2eaa912a28c 544 if (amqpvalue_set_map_value(link_attach_properties, api_version_property_key, api_version_property_value) != 0)
AzureIoTClient 42:c2eaa912a28c 545 {
AzureIoTClient 42:c2eaa912a28c 546 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 547 LogError("Cannot set the property for API version on the link attach properties");
AzureIoTClient 42:c2eaa912a28c 548 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 549 }
AzureIoTClient 42:c2eaa912a28c 550 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_144: [ The link attach properties shall be set on the receiver and sender link by calling `link_set_attach_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 551 else if (link_set_attach_properties(iothubtransport_amqp_methods_handle->sender_link, link_attach_properties) != 0)
AzureIoTClient 42:c2eaa912a28c 552 {
AzureIoTClient 42:c2eaa912a28c 553 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 554 LogError("Cannot set the link attach properties on the sender link");
AzureIoTClient 42:c2eaa912a28c 555 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 556 }
AzureIoTClient 42:c2eaa912a28c 557 else if (link_set_attach_properties(iothubtransport_amqp_methods_handle->receiver_link, link_attach_properties) != 0)
AzureIoTClient 42:c2eaa912a28c 558 {
AzureIoTClient 42:c2eaa912a28c 559 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 560 LogError("Cannot set the link attach properties on the receiver link");
AzureIoTClient 42:c2eaa912a28c 561 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 562 }
AzureIoTClient 42:c2eaa912a28c 563 else
AzureIoTClient 42:c2eaa912a28c 564 {
AzureIoTClient 42:c2eaa912a28c 565 result = 0;
AzureIoTClient 42:c2eaa912a28c 566 }
AzureIoTClient 42:c2eaa912a28c 567
AzureIoTClient 42:c2eaa912a28c 568 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
AzureIoTClient 42:c2eaa912a28c 569 amqpvalue_destroy(api_version_property_value);
AzureIoTClient 42:c2eaa912a28c 570 }
AzureIoTClient 42:c2eaa912a28c 571
AzureIoTClient 42:c2eaa912a28c 572 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
AzureIoTClient 42:c2eaa912a28c 573 amqpvalue_destroy(api_version_property_key);
AzureIoTClient 42:c2eaa912a28c 574 }
AzureIoTClient 42:c2eaa912a28c 575 }
AzureIoTClient 42:c2eaa912a28c 576
AzureIoTClient 42:c2eaa912a28c 577 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
AzureIoTClient 42:c2eaa912a28c 578 amqpvalue_destroy(channel_correlation_id_property_value);
AzureIoTClient 42:c2eaa912a28c 579 }
AzureIoTClient 42:c2eaa912a28c 580
AzureIoTClient 42:c2eaa912a28c 581 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
AzureIoTClient 42:c2eaa912a28c 582 amqpvalue_destroy(channel_correlation_id_property_key);
AzureIoTClient 42:c2eaa912a28c 583 }
AzureIoTClient 42:c2eaa912a28c 584
AzureIoTClient 42:c2eaa912a28c 585 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
AzureIoTClient 42:c2eaa912a28c 586 amqpvalue_destroy(link_attach_properties);
AzureIoTClient 42:c2eaa912a28c 587 }
AzureIoTClient 42:c2eaa912a28c 588
AzureIoTClient 42:c2eaa912a28c 589 return result;
AzureIoTClient 42:c2eaa912a28c 590 }
AzureIoTClient 42:c2eaa912a28c 591
AzureIoTClient 42:c2eaa912a28c 592 int iothubtransportamqp_methods_subscribe(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle,
AzureIoTClient 42:c2eaa912a28c 593 SESSION_HANDLE session_handle, ON_METHODS_ERROR on_methods_error, void* on_methods_error_context,
AzureIoTClient 42:c2eaa912a28c 594 ON_METHOD_REQUEST_RECEIVED on_method_request_received, void* on_method_request_received_context,
AzureIoTClient 42:c2eaa912a28c 595 ON_METHODS_UNSUBSCRIBED on_methods_unsubscribed, void* on_methods_unsubscribed_context)
AzureIoTClient 42:c2eaa912a28c 596 {
AzureIoTClient 42:c2eaa912a28c 597 int result;
AzureIoTClient 42:c2eaa912a28c 598
AzureIoTClient 42:c2eaa912a28c 599 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_009: [ If any of the argument `iothubtransport_amqp_methods_handle`, `session_handle`, `on_methods_error`, `on_method_request_received`, `on_methods_unsubscribed` is NULL, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 600 if ((iothubtransport_amqp_methods_handle == NULL) ||
AzureIoTClient 42:c2eaa912a28c 601 (session_handle == NULL) ||
AzureIoTClient 42:c2eaa912a28c 602 (on_methods_error == NULL) ||
AzureIoTClient 42:c2eaa912a28c 603 (on_method_request_received == NULL) ||
AzureIoTClient 42:c2eaa912a28c 604 (on_methods_unsubscribed == NULL))
AzureIoTClient 42:c2eaa912a28c 605 {
AzureIoTClient 42:c2eaa912a28c 606 LogError("Invalid arguments: iothubtransport_amqp_methods_handle=%p, session_handle=%p, on_methods_error=%p, on_method_request_received=%p, on_methods_unsubscribed=%p",
AzureIoTClient 42:c2eaa912a28c 607 iothubtransport_amqp_methods_handle, session_handle, on_methods_error, on_method_request_received, on_methods_unsubscribed);
AzureIoTClient 42:c2eaa912a28c 608 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 609 }
AzureIoTClient 42:c2eaa912a28c 610 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_137: [ `iothubtransportamqp_methods_subscribe` after another succesfull `iothubtransportamqp_methods_subscribe` without any unsubscribe shall return a non-zero value without performing any subscribe action. ]*/
AzureIoTClient 42:c2eaa912a28c 611 else if (iothubtransport_amqp_methods_handle->subscribe_state != SUBSCRIBE_STATE_NOT_SUBSCRIBED)
AzureIoTClient 42:c2eaa912a28c 612 {
AzureIoTClient 42:c2eaa912a28c 613 LogError("Already subscribed");
AzureIoTClient 42:c2eaa912a28c 614 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 615 }
AzureIoTClient 42:c2eaa912a28c 616 else
AzureIoTClient 42:c2eaa912a28c 617 {
AzureIoTClient 42:c2eaa912a28c 618 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_015: [ The address string used to create the source shall be of the form `/devices/{device id}/methods/devicebound`. ]*/
AzureIoTClient 42:c2eaa912a28c 619 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_016: [ The string shall be created by using `STRING_construct_sprintf`. ]*/
AzureIoTClient 42:c2eaa912a28c 620 STRING_HANDLE peer_endpoint_string = STRING_construct_sprintf("amqps://%s/devices/%s/methods/devicebound", iothubtransport_amqp_methods_handle->hostname, iothubtransport_amqp_methods_handle->device_id);
AzureIoTClient 42:c2eaa912a28c 621 if (peer_endpoint_string == NULL)
AzureIoTClient 42:c2eaa912a28c 622 {
AzureIoTClient 42:c2eaa912a28c 623 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_018: [ If `STRING_construct_sprintf` fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 624 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 625 }
AzureIoTClient 42:c2eaa912a28c 626 else
AzureIoTClient 42:c2eaa912a28c 627 {
AzureIoTClient 42:c2eaa912a28c 628 iothubtransport_amqp_methods_handle->on_method_request_received = on_method_request_received;
AzureIoTClient 42:c2eaa912a28c 629 iothubtransport_amqp_methods_handle->on_method_request_received_context = on_method_request_received_context;
AzureIoTClient 42:c2eaa912a28c 630 iothubtransport_amqp_methods_handle->on_methods_error = on_methods_error;
AzureIoTClient 42:c2eaa912a28c 631 iothubtransport_amqp_methods_handle->on_methods_error_context = on_methods_error_context;
AzureIoTClient 42:c2eaa912a28c 632 iothubtransport_amqp_methods_handle->on_methods_unsubscribed = on_methods_unsubscribed;
AzureIoTClient 42:c2eaa912a28c 633 iothubtransport_amqp_methods_handle->on_methods_unsubscribed_context = on_methods_unsubscribed_context;
AzureIoTClient 42:c2eaa912a28c 634
AzureIoTClient 42:c2eaa912a28c 635 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_014: [ - `source` shall be the a source value created by calling `messaging_create_source`. ]*/
AzureIoTClient 42:c2eaa912a28c 636 AMQP_VALUE receiver_source = messaging_create_source(STRING_c_str(peer_endpoint_string));
AzureIoTClient 42:c2eaa912a28c 637 if (receiver_source == NULL)
AzureIoTClient 42:c2eaa912a28c 638 {
AzureIoTClient 42:c2eaa912a28c 639 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_019: [ If creating the target or source values fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 640 LogError("Cannot create receiver source");
AzureIoTClient 42:c2eaa912a28c 641 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 642 }
AzureIoTClient 42:c2eaa912a28c 643 else
AzureIoTClient 42:c2eaa912a28c 644 {
AzureIoTClient 42:c2eaa912a28c 645 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_017: [ - `target` shall be the a target value created by calling `messaging_create_target`. ]*/
AzureIoTClient 42:c2eaa912a28c 646 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_117: [ The address string used to create the target shall be `requests`. ]*/
AzureIoTClient 42:c2eaa912a28c 647 AMQP_VALUE receiver_target = messaging_create_target("requests");
AzureIoTClient 42:c2eaa912a28c 648 if (receiver_target == NULL)
AzureIoTClient 42:c2eaa912a28c 649 {
AzureIoTClient 42:c2eaa912a28c 650 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_019: [ If creating the target or source values fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 651 LogError("Cannot create receiver target");
AzureIoTClient 42:c2eaa912a28c 652 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 653 }
AzureIoTClient 42:c2eaa912a28c 654 else
AzureIoTClient 42:c2eaa912a28c 655 {
AzureIoTClient 42:c2eaa912a28c 656 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_012: [ - `name` shall be in the format `methods_requests_link-{device_id}`, where device_id is the `device_id` argument passed to `iothubtransportamqp_methods_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 657 STRING_HANDLE requests_link_name = STRING_construct_sprintf("methods_requests_link-%s", iothubtransport_amqp_methods_handle->device_id);
AzureIoTClient 42:c2eaa912a28c 658 if (requests_link_name == NULL)
AzureIoTClient 42:c2eaa912a28c 659 {
AzureIoTClient 42:c2eaa912a28c 660 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_153: [ If constructing the requests link name fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 661 LogError("Cannot create methods requests link name.");
AzureIoTClient 42:c2eaa912a28c 662 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 663 }
AzureIoTClient 42:c2eaa912a28c 664 else
AzureIoTClient 42:c2eaa912a28c 665 {
AzureIoTClient 42:c2eaa912a28c 666 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_010: [ `iothubtransportamqp_methods_subscribe` shall create a receiver link by calling `link_create` with the following arguments: ]*/
AzureIoTClient 42:c2eaa912a28c 667 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_011: [ - `session_handle` shall be the session_handle argument passed to iothubtransportamqp_methods_subscribe ]*/
AzureIoTClient 42:c2eaa912a28c 668 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_013: [ - `role` shall be role_receiver. ]*/
AzureIoTClient 42:c2eaa912a28c 669 iothubtransport_amqp_methods_handle->receiver_link = link_create(session_handle, STRING_c_str(requests_link_name), role_receiver, receiver_source, receiver_target);
AzureIoTClient 42:c2eaa912a28c 670 if (iothubtransport_amqp_methods_handle->receiver_link == NULL)
AzureIoTClient 42:c2eaa912a28c 671 {
AzureIoTClient 42:c2eaa912a28c 672 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_020: [ If creating the receiver link fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 673 LogError("Cannot create receiver link");
AzureIoTClient 42:c2eaa912a28c 674 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 675 }
AzureIoTClient 42:c2eaa912a28c 676 else
AzureIoTClient 42:c2eaa912a28c 677 {
AzureIoTClient 42:c2eaa912a28c 678 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_025: [ - `source` shall be the a source value created by calling `messaging_create_source`. ]*/
AzureIoTClient 42:c2eaa912a28c 679 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_026: [ The address string used to create the target shall be `responses`. ]*/
AzureIoTClient 42:c2eaa912a28c 680 AMQP_VALUE sender_source = messaging_create_source("responses");
AzureIoTClient 42:c2eaa912a28c 681 if (sender_source == NULL)
AzureIoTClient 42:c2eaa912a28c 682 {
AzureIoTClient 42:c2eaa912a28c 683 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_031: [ If creating the target or source values fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 684 LogError("Cannot create sender source");
AzureIoTClient 42:c2eaa912a28c 685 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 686 }
AzureIoTClient 42:c2eaa912a28c 687 else
AzureIoTClient 42:c2eaa912a28c 688 {
AzureIoTClient 42:c2eaa912a28c 689 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_027: [ - `target` shall be the a target value created by calling `messaging_create_target`. ]*/
AzureIoTClient 42:c2eaa912a28c 690 AMQP_VALUE sender_target = messaging_create_target(STRING_c_str(peer_endpoint_string));
AzureIoTClient 42:c2eaa912a28c 691 if (sender_target == NULL)
AzureIoTClient 42:c2eaa912a28c 692 {
AzureIoTClient 42:c2eaa912a28c 693 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_031: [ If creating the target or source values fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 694 LogError("Cannot create sender target");
AzureIoTClient 42:c2eaa912a28c 695 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 696 }
AzureIoTClient 42:c2eaa912a28c 697 else
AzureIoTClient 42:c2eaa912a28c 698 {
AzureIoTClient 42:c2eaa912a28c 699 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_023: [ - `name` shall be format `methods_responses_link-{device_id}`, where device_id is the `device_id` argument passed to `iothubtransportamqp_methods_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 700 STRING_HANDLE responses_link_name = STRING_construct_sprintf("methods_responses_link-%s", iothubtransport_amqp_methods_handle->device_id);
AzureIoTClient 42:c2eaa912a28c 701 if (responses_link_name == NULL)
AzureIoTClient 42:c2eaa912a28c 702 {
AzureIoTClient 42:c2eaa912a28c 703 /* CodeS_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_154: [ If constructing the responses link name fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 704 LogError("Cannot create methods responses link name.");
AzureIoTClient 42:c2eaa912a28c 705 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 706 }
AzureIoTClient 42:c2eaa912a28c 707 else
AzureIoTClient 42:c2eaa912a28c 708 {
AzureIoTClient 42:c2eaa912a28c 709 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_021: [ `iothubtransportamqp_methods_subscribe` shall create a sender link by calling `link_create` with the following arguments: ]*/
AzureIoTClient 42:c2eaa912a28c 710 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_022: [ - `session_handle` shall be the session_handle argument passed to iothubtransportamqp_methods_subscribe ]*/
AzureIoTClient 42:c2eaa912a28c 711 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_024: [ - `role` shall be role_sender. ]*/
AzureIoTClient 42:c2eaa912a28c 712 iothubtransport_amqp_methods_handle->sender_link = link_create(session_handle, STRING_c_str(responses_link_name), role_sender, sender_source, sender_target);
AzureIoTClient 42:c2eaa912a28c 713 if (iothubtransport_amqp_methods_handle->sender_link == NULL)
AzureIoTClient 42:c2eaa912a28c 714 {
AzureIoTClient 42:c2eaa912a28c 715 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_032: [ If creating the receiver link fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 716 LogError("Cannot create sender link");
AzureIoTClient 42:c2eaa912a28c 717 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 718 }
AzureIoTClient 42:c2eaa912a28c 719 else
AzureIoTClient 42:c2eaa912a28c 720 {
AzureIoTClient 42:c2eaa912a28c 721 if (set_link_attach_properties(iothubtransport_amqp_methods_handle) != 0)
AzureIoTClient 42:c2eaa912a28c 722 {
AzureIoTClient 42:c2eaa912a28c 723 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 724 }
AzureIoTClient 42:c2eaa912a28c 725 else
AzureIoTClient 42:c2eaa912a28c 726 {
AzureIoTClient 42:c2eaa912a28c 727 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_033: [ `iothubtransportamqp_methods_subscribe` shall create a message receiver associated with the receiver link by calling `messagereceiver_create` and passing the receiver link handle to it. ]*/
AzureIoTClient 42:c2eaa912a28c 728 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_118: [ An `on_message_receiver_state_changed` callback together with its context shall be passed to `messagereceiver_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 729 iothubtransport_amqp_methods_handle->message_receiver = messagereceiver_create(iothubtransport_amqp_methods_handle->receiver_link, on_message_receiver_state_changed, iothubtransport_amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 730 if (iothubtransport_amqp_methods_handle->message_receiver == NULL)
AzureIoTClient 42:c2eaa912a28c 731 {
AzureIoTClient 42:c2eaa912a28c 732 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_034: [ If `messagereceiver_create` fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 733 LogError("Cannot create message receiver");
AzureIoTClient 42:c2eaa912a28c 734 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 735 }
AzureIoTClient 42:c2eaa912a28c 736 else
AzureIoTClient 42:c2eaa912a28c 737 {
AzureIoTClient 42:c2eaa912a28c 738 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_035: [ `iothubtransportamqp_methods_subscribe` shall create a message sender associated with the sender link by calling `messagesender_create` and passing the sender link handle to it. ]*/
AzureIoTClient 42:c2eaa912a28c 739 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_106: [ An `on_message_sender_state_changed` callback together with its context shall be passed to `messagesender_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 740 iothubtransport_amqp_methods_handle->message_sender = messagesender_create(iothubtransport_amqp_methods_handle->sender_link, on_message_sender_state_changed, iothubtransport_amqp_methods_handle);
AzureIoTClient 42:c2eaa912a28c 741 if (iothubtransport_amqp_methods_handle->message_sender == NULL)
AzureIoTClient 42:c2eaa912a28c 742 {
AzureIoTClient 42:c2eaa912a28c 743 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_036: [ If `messagesender_create` fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 744 LogError("Cannot create message sender");
AzureIoTClient 42:c2eaa912a28c 745 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 746 }
AzureIoTClient 42:c2eaa912a28c 747 else
AzureIoTClient 42:c2eaa912a28c 748 {
AzureIoTClient 42:c2eaa912a28c 749 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_037: [ `iothubtransportamqp_methods_subscribe` shall open the message sender by calling `messagesender_open`. ]*/
AzureIoTClient 42:c2eaa912a28c 750 if (messagesender_open(iothubtransport_amqp_methods_handle->message_sender) != 0)
AzureIoTClient 42:c2eaa912a28c 751 {
AzureIoTClient 42:c2eaa912a28c 752 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_038: [ If `messagesender_open` fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 753 LogError("Cannot open the message sender");
AzureIoTClient 42:c2eaa912a28c 754 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 755 }
AzureIoTClient 42:c2eaa912a28c 756 else
AzureIoTClient 42:c2eaa912a28c 757 {
AzureIoTClient 42:c2eaa912a28c 758 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_039: [ `iothubtransportamqp_methods_subscribe` shall open the message sender by calling `messagereceiver_open`. ]*/
AzureIoTClient 42:c2eaa912a28c 759 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_104: [ An `on_message_received` callback together with its context shall be passed to `messagereceiver_open`. ]*/
AzureIoTClient 42:c2eaa912a28c 760 if (messagereceiver_open(iothubtransport_amqp_methods_handle->message_receiver, on_message_received, iothubtransport_amqp_methods_handle) != 0)
AzureIoTClient 42:c2eaa912a28c 761 {
AzureIoTClient 42:c2eaa912a28c 762 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_040: [ If `messagereceiver_open` fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 763 LogError("Cannot open the message receiver");
AzureIoTClient 42:c2eaa912a28c 764 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 765 }
AzureIoTClient 42:c2eaa912a28c 766 else
AzureIoTClient 42:c2eaa912a28c 767 {
AzureIoTClient 42:c2eaa912a28c 768 iothubtransport_amqp_methods_handle->subscribe_state = SUBSCRIBE_STATE_SUBSCRIBED;
AzureIoTClient 42:c2eaa912a28c 769
AzureIoTClient 42:c2eaa912a28c 770 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_008: [ On success it shall return 0. ]*/
AzureIoTClient 42:c2eaa912a28c 771 result = 0;
AzureIoTClient 42:c2eaa912a28c 772 }
AzureIoTClient 42:c2eaa912a28c 773 }
AzureIoTClient 42:c2eaa912a28c 774 }
AzureIoTClient 42:c2eaa912a28c 775 }
AzureIoTClient 42:c2eaa912a28c 776 }
AzureIoTClient 42:c2eaa912a28c 777 }
AzureIoTClient 42:c2eaa912a28c 778
AzureIoTClient 42:c2eaa912a28c 779 STRING_delete(responses_link_name);
AzureIoTClient 42:c2eaa912a28c 780 }
AzureIoTClient 42:c2eaa912a28c 781
AzureIoTClient 42:c2eaa912a28c 782 amqpvalue_destroy(sender_target);
AzureIoTClient 42:c2eaa912a28c 783 }
AzureIoTClient 42:c2eaa912a28c 784
AzureIoTClient 42:c2eaa912a28c 785 amqpvalue_destroy(sender_source);
AzureIoTClient 42:c2eaa912a28c 786 }
AzureIoTClient 42:c2eaa912a28c 787 }
AzureIoTClient 42:c2eaa912a28c 788
AzureIoTClient 42:c2eaa912a28c 789 STRING_delete(requests_link_name);
AzureIoTClient 42:c2eaa912a28c 790 }
AzureIoTClient 42:c2eaa912a28c 791
AzureIoTClient 42:c2eaa912a28c 792 amqpvalue_destroy(receiver_target);
AzureIoTClient 42:c2eaa912a28c 793 }
AzureIoTClient 42:c2eaa912a28c 794
AzureIoTClient 42:c2eaa912a28c 795 amqpvalue_destroy(receiver_source);
AzureIoTClient 42:c2eaa912a28c 796 }
AzureIoTClient 42:c2eaa912a28c 797
AzureIoTClient 42:c2eaa912a28c 798 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_105: [ The string created in order to hold the source and target addresses shall be freed by calling `STRING_delete`. ]*/
AzureIoTClient 42:c2eaa912a28c 799 STRING_delete(peer_endpoint_string);
AzureIoTClient 42:c2eaa912a28c 800 }
AzureIoTClient 42:c2eaa912a28c 801 }
AzureIoTClient 42:c2eaa912a28c 802
AzureIoTClient 42:c2eaa912a28c 803 return result;
AzureIoTClient 42:c2eaa912a28c 804 }
AzureIoTClient 42:c2eaa912a28c 805
AzureIoTClient 42:c2eaa912a28c 806 void iothubtransportamqp_methods_unsubscribe(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
AzureIoTClient 42:c2eaa912a28c 807 {
AzureIoTClient 42:c2eaa912a28c 808 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_072: [ If the argument `iothubtransport_amqp_methods_handle` is NULL, `iothubtransportamqp_methods_unsubscribe` shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 809 if (iothubtransport_amqp_methods_handle == NULL)
AzureIoTClient 42:c2eaa912a28c 810 {
AzureIoTClient 42:c2eaa912a28c 811 LogError("NULL handle");
AzureIoTClient 42:c2eaa912a28c 812 }
AzureIoTClient 42:c2eaa912a28c 813 else
AzureIoTClient 42:c2eaa912a28c 814 {
AzureIoTClient 42:c2eaa912a28c 815 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_135: [ If subscribe was not called yet, `iothubtransportamqp_methods_unsubscribe` shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 816 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_136: [ `iothubtransportamqp_methods_unsubscribe` after `iothubtransportamqp_methods_unsubscribe` shall do nothing. ]*/
AzureIoTClient 42:c2eaa912a28c 817 if (iothubtransport_amqp_methods_handle->subscribe_state != SUBSCRIBE_STATE_SUBSCRIBED)
AzureIoTClient 42:c2eaa912a28c 818 {
AzureIoTClient 42:c2eaa912a28c 819 LogError("unsubscribe called while not subscribed");
AzureIoTClient 42:c2eaa912a28c 820 }
AzureIoTClient 42:c2eaa912a28c 821 else
AzureIoTClient 42:c2eaa912a28c 822 {
AzureIoTClient 42:c2eaa912a28c 823 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_073: [ Otherwise `iothubtransportamqp_methods_unsubscribe` shall free all resources allocated in `iothubtransportamqp_methods_subscribe`: ]*/
AzureIoTClient 42:c2eaa912a28c 824 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_075: [ - It shall free the message receiver by calling `messagereceiver_destroy'. ]*/
AzureIoTClient 42:c2eaa912a28c 825 messagereceiver_destroy(iothubtransport_amqp_methods_handle->message_receiver);
AzureIoTClient 42:c2eaa912a28c 826 iothubtransport_amqp_methods_handle->message_receiver = NULL;
AzureIoTClient 42:c2eaa912a28c 827 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_074: [ - It shall free the message sender by calling `messagesender_destroy'. ]*/
AzureIoTClient 42:c2eaa912a28c 828 messagesender_destroy(iothubtransport_amqp_methods_handle->message_sender);
AzureIoTClient 42:c2eaa912a28c 829 iothubtransport_amqp_methods_handle->message_sender = NULL;
AzureIoTClient 42:c2eaa912a28c 830 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_076: [ - It shall free the sender link by calling `link_destroy'. ]*/
AzureIoTClient 42:c2eaa912a28c 831 link_destroy(iothubtransport_amqp_methods_handle->sender_link);
AzureIoTClient 42:c2eaa912a28c 832 iothubtransport_amqp_methods_handle->sender_link = NULL;
AzureIoTClient 42:c2eaa912a28c 833 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_077: [ - It shall free the receiver link by calling `link_destroy'. ]*/
AzureIoTClient 42:c2eaa912a28c 834 link_destroy(iothubtransport_amqp_methods_handle->receiver_link);
AzureIoTClient 42:c2eaa912a28c 835 iothubtransport_amqp_methods_handle->receiver_link = NULL;
AzureIoTClient 42:c2eaa912a28c 836
AzureIoTClient 42:c2eaa912a28c 837 iothubtransport_amqp_methods_handle->subscribe_state = SUBSCRIBE_STATE_NOT_SUBSCRIBED;
AzureIoTClient 42:c2eaa912a28c 838 }
AzureIoTClient 42:c2eaa912a28c 839 }
AzureIoTClient 42:c2eaa912a28c 840 }
AzureIoTClient 42:c2eaa912a28c 841
AzureIoTClient 42:c2eaa912a28c 842 int iothubtransportamqp_methods_respond(IOTHUBTRANSPORT_AMQP_METHOD_HANDLE method_handle, const unsigned char* response, size_t response_size, int status_code)
AzureIoTClient 42:c2eaa912a28c 843 {
AzureIoTClient 42:c2eaa912a28c 844 int result;
AzureIoTClient 42:c2eaa912a28c 845
AzureIoTClient 42:c2eaa912a28c 846 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_107: [ If the argument `method_handle` is NULL, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 847 if (method_handle == NULL)
AzureIoTClient 42:c2eaa912a28c 848 {
AzureIoTClient 42:c2eaa912a28c 849 LogError("NULL method handle");
AzureIoTClient 42:c2eaa912a28c 850 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 851 }
AzureIoTClient 42:c2eaa912a28c 852 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_108: [ If `response_size` is greater than zero and `response` is NULL, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 853 else if ((response == NULL) && (response_size > 0))
AzureIoTClient 42:c2eaa912a28c 854 {
AzureIoTClient 42:c2eaa912a28c 855 LogError("NULL response buffer with > 0 response payload size");
AzureIoTClient 42:c2eaa912a28c 856 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 857 }
AzureIoTClient 42:c2eaa912a28c 858 else
AzureIoTClient 42:c2eaa912a28c 859 {
AzureIoTClient 42:c2eaa912a28c 860 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_061: [ - A new uAMQP message shall be created by calling `message_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 861 MESSAGE_HANDLE message = message_create();
AzureIoTClient 42:c2eaa912a28c 862 if (message == NULL)
AzureIoTClient 42:c2eaa912a28c 863 {
AzureIoTClient 42:c2eaa912a28c 864 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_062: [ If the `message_create` call fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 865 LogError("Cannot create message");
AzureIoTClient 42:c2eaa912a28c 866 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 867 }
AzureIoTClient 42:c2eaa912a28c 868 else
AzureIoTClient 42:c2eaa912a28c 869 {
AzureIoTClient 42:c2eaa912a28c 870 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_063: [ - A new properties handle shall be created by calling `properties_create`. ]*/
AzureIoTClient 42:c2eaa912a28c 871 PROPERTIES_HANDLE properties = properties_create();
AzureIoTClient 42:c2eaa912a28c 872 if (properties == NULL)
AzureIoTClient 42:c2eaa912a28c 873 {
AzureIoTClient 42:c2eaa912a28c 874 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_064: [ If the `properties_create call` fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 875 LogError("Cannot create properties");
AzureIoTClient 42:c2eaa912a28c 876 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 877 }
AzureIoTClient 42:c2eaa912a28c 878 else
AzureIoTClient 42:c2eaa912a28c 879 {
AzureIoTClient 42:c2eaa912a28c 880 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_124: [ - An AMQP value holding the correlation id associated with the `method_handle` handle shall be created by calling `amqpvalue_create_uuid`. ]*/
AzureIoTClient 42:c2eaa912a28c 881 AMQP_VALUE correlation_id = amqpvalue_create_uuid(method_handle->correlation_id);
AzureIoTClient 42:c2eaa912a28c 882 if (correlation_id == NULL)
AzureIoTClient 42:c2eaa912a28c 883 {
AzureIoTClient 42:c2eaa912a28c 884 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_125: [ If `amqpvalue_create_uuid` fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 885 LogError("Cannot create correlation_id value");
AzureIoTClient 42:c2eaa912a28c 886 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 887 }
AzureIoTClient 42:c2eaa912a28c 888 else
AzureIoTClient 42:c2eaa912a28c 889 {
AzureIoTClient 42:c2eaa912a28c 890 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_065: [ - The correlation id on the message properties shall be set by calling `properties_set_correlation_id` and passing as argument the already create correlation ID AMQP value. ]*/
AzureIoTClient 42:c2eaa912a28c 891 if (properties_set_correlation_id(properties, correlation_id) != 0)
AzureIoTClient 42:c2eaa912a28c 892 {
AzureIoTClient 42:c2eaa912a28c 893 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_066: [ If the `properties_set_correlation_id` call fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 894 LogError("Cannot set correlation_id on the properties");
AzureIoTClient 42:c2eaa912a28c 895 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 896 }
AzureIoTClient 42:c2eaa912a28c 897 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_148: [ The properties shall be set on the message by calling `message_set_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 898 else if (message_set_properties(message, properties) != 0)
AzureIoTClient 42:c2eaa912a28c 899 {
AzureIoTClient 42:c2eaa912a28c 900 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_149: [ If `message_set_properties` fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 901 LogError("Cannot set properties on the response message");
AzureIoTClient 42:c2eaa912a28c 902 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 903 }
AzureIoTClient 42:c2eaa912a28c 904 else
AzureIoTClient 42:c2eaa912a28c 905 {
AzureIoTClient 42:c2eaa912a28c 906 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_090: [ An AMQP map shall be created to hold the application properties for the response by calling `amqpvalue_create_map`. ]*/
AzureIoTClient 42:c2eaa912a28c 907 AMQP_VALUE application_properties_map = amqpvalue_create_map();
AzureIoTClient 42:c2eaa912a28c 908 if (application_properties_map == NULL)
AzureIoTClient 42:c2eaa912a28c 909 {
AzureIoTClient 42:c2eaa912a28c 910 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_096: [ If any of the calls `amqpvalue_create_string`, `amqpvalue_create_int`, `amqpvalue_create_map`, `amqpvalue_set_map_value` or `message_set_application_properties` fails `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 911 LogError("Cannot create map for application properties");
AzureIoTClient 42:c2eaa912a28c 912 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 913 }
AzureIoTClient 42:c2eaa912a28c 914 else
AzureIoTClient 42:c2eaa912a28c 915 {
AzureIoTClient 42:c2eaa912a28c 916 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_091: [ A property key `IoThub-status` shall be created by calling `amqpvalue_create_string`. ]*/
AzureIoTClient 42:c2eaa912a28c 917 AMQP_VALUE property_key_status = amqpvalue_create_string("IoThub-status");
AzureIoTClient 42:c2eaa912a28c 918 if (property_key_status == NULL)
AzureIoTClient 42:c2eaa912a28c 919 {
AzureIoTClient 42:c2eaa912a28c 920 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_096: [ If any of the calls `amqpvalue_create_string`, `amqpvalue_create_int`, `amqpvalue_create_map`, `amqpvalue_set_map_value` or `message_set_application_properties` fails `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 921 LogError("Cannot create the property key for the status property");
AzureIoTClient 42:c2eaa912a28c 922 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 923 }
AzureIoTClient 42:c2eaa912a28c 924 else
AzureIoTClient 42:c2eaa912a28c 925 {
AzureIoTClient 42:c2eaa912a28c 926 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_097: [ A property value of type int shall be created from the `status_code` argument by calling `amqpvalue_create_int`. ] ]*/
AzureIoTClient 42:c2eaa912a28c 927 AMQP_VALUE property_value_status = amqpvalue_create_int(status_code);
AzureIoTClient 42:c2eaa912a28c 928 if (property_value_status == NULL)
AzureIoTClient 42:c2eaa912a28c 929 {
AzureIoTClient 42:c2eaa912a28c 930 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_096: [ If any of the calls `amqpvalue_create_string`, `amqpvalue_create_int`, `amqpvalue_create_map`, `amqpvalue_set_map_value` or `message_set_application_properties` fails `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 931 LogError("Cannot create the status code property value for the application properties map");
AzureIoTClient 42:c2eaa912a28c 932 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 933 }
AzureIoTClient 42:c2eaa912a28c 934 else
AzureIoTClient 42:c2eaa912a28c 935 {
AzureIoTClient 42:c2eaa912a28c 936 /* Cdoes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_093: [ A new entry shall be added in the application properties map by calling `amqpvalue_set_map_value` and passing the key and value that were previously created. ]*/
AzureIoTClient 42:c2eaa912a28c 937 if (amqpvalue_set_map_value(application_properties_map, property_key_status, property_value_status) != 0)
AzureIoTClient 42:c2eaa912a28c 938 {
AzureIoTClient 42:c2eaa912a28c 939 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_096: [ If any of the calls `amqpvalue_create_string`, `amqpvalue_create_int`, `amqpvalue_create_map`, `amqpvalue_set_map_value` or `message_set_application_properties` fails `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 940 LogError("Cannot add the status property to the application properties");
AzureIoTClient 42:c2eaa912a28c 941 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 942 }
AzureIoTClient 42:c2eaa912a28c 943 else
AzureIoTClient 42:c2eaa912a28c 944 {
AzureIoTClient 42:c2eaa912a28c 945 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_094: [ The application properties map shall be set on the response message by calling `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 946 if (message_set_application_properties(message, application_properties_map) != 0)
AzureIoTClient 42:c2eaa912a28c 947 {
AzureIoTClient 42:c2eaa912a28c 948 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_096: [ If any of the calls `amqpvalue_create_string`, `amqpvalue_create_int`, `amqpvalue_create_map`, `amqpvalue_set_map_value` or `message_set_application_properties` fails `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 949 LogError("Cannot set the application properties on the message");
AzureIoTClient 42:c2eaa912a28c 950 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 951 }
AzureIoTClient 42:c2eaa912a28c 952 else
AzureIoTClient 42:c2eaa912a28c 953 {
AzureIoTClient 42:c2eaa912a28c 954 BINARY_DATA binary_data;
AzureIoTClient 42:c2eaa912a28c 955
AzureIoTClient 42:c2eaa912a28c 956 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_079: [ The field `bytes` of the `binary_data` argument shall be set to the `response` argument value. ]*/
AzureIoTClient 42:c2eaa912a28c 957 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_080: [ The field `length` of the `binary_data` argument shall be set to the `response_size` argument value. ]*/
AzureIoTClient 42:c2eaa912a28c 958 binary_data.bytes = response;
AzureIoTClient 42:c2eaa912a28c 959 binary_data.length = response_size;
AzureIoTClient 42:c2eaa912a28c 960
AzureIoTClient 42:c2eaa912a28c 961 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_078: [ The binary payload for the response shall be set by calling `message_add_body_amqp_data` for the newly created message handle. ]*/
AzureIoTClient 42:c2eaa912a28c 962 if (message_add_body_amqp_data(message, binary_data) != 0)
AzureIoTClient 42:c2eaa912a28c 963 {
AzureIoTClient 42:c2eaa912a28c 964 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_081: [ If the `message_add_body_amqp_data` call fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 965 LogError("Cannot set the response payload on the reponse message");
AzureIoTClient 42:c2eaa912a28c 966 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 967 }
AzureIoTClient 42:c2eaa912a28c 968 else
AzureIoTClient 42:c2eaa912a28c 969 {
AzureIoTClient 42:c2eaa912a28c 970 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_067: [ The message shall be handed over to the message_sender by calling `messagesender_send` and passing as arguments: ]*/
AzureIoTClient 42:c2eaa912a28c 971 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_068: [ - The response message handle. ]*/
AzureIoTClient 42:c2eaa912a28c 972 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_069: [ - A send callback and its context for the `on_message_send_complete` callback. ]*/
AzureIoTClient 43:3da2d93bb955 973 if (messagesender_send_async(method_handle->iothubtransport_amqp_methods_handle->message_sender, message, on_message_send_complete, method_handle->iothubtransport_amqp_methods_handle, 0) == NULL)
AzureIoTClient 42:c2eaa912a28c 974 {
AzureIoTClient 42:c2eaa912a28c 975 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_071: [ If the `messagesender_send` call fails, `iothubtransportamqp_methods_respond` shall fail and return a non-zero value. ]*/
AzureIoTClient 42:c2eaa912a28c 976 LogError("Cannot send response message");
AzureIoTClient 42:c2eaa912a28c 977 result = __FAILURE__;
AzureIoTClient 42:c2eaa912a28c 978 }
AzureIoTClient 42:c2eaa912a28c 979 else
AzureIoTClient 42:c2eaa912a28c 980 {
AzureIoTClient 42:c2eaa912a28c 981 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_114: [ The handle `method_handle` shall be removed from the array used to track the method handles. ]*/
AzureIoTClient 42:c2eaa912a28c 982 remove_tracked_handle(method_handle->iothubtransport_amqp_methods_handle, method_handle);
AzureIoTClient 42:c2eaa912a28c 983
AzureIoTClient 42:c2eaa912a28c 984 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_111: [ The handle `method_handle` shall be freed (have no meaning) after `iothubtransportamqp_methods_respond` has been executed. ]*/
AzureIoTClient 42:c2eaa912a28c 985 free(method_handle);
AzureIoTClient 42:c2eaa912a28c 986
AzureIoTClient 42:c2eaa912a28c 987 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_060: [ `iothubtransportamqp_methods_respond` shall construct a response message and on success it shall return 0. ]*/
AzureIoTClient 42:c2eaa912a28c 988 result = 0;
AzureIoTClient 42:c2eaa912a28c 989 }
AzureIoTClient 42:c2eaa912a28c 990 }
AzureIoTClient 42:c2eaa912a28c 991 }
AzureIoTClient 42:c2eaa912a28c 992 }
AzureIoTClient 42:c2eaa912a28c 993
AzureIoTClient 42:c2eaa912a28c 994 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 995 amqpvalue_destroy(property_value_status);
AzureIoTClient 42:c2eaa912a28c 996 }
AzureIoTClient 42:c2eaa912a28c 997
AzureIoTClient 42:c2eaa912a28c 998 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 999 amqpvalue_destroy(property_key_status);
AzureIoTClient 42:c2eaa912a28c 1000 }
AzureIoTClient 42:c2eaa912a28c 1001
AzureIoTClient 42:c2eaa912a28c 1002 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 1003 amqpvalue_destroy(application_properties_map);
AzureIoTClient 42:c2eaa912a28c 1004 }
AzureIoTClient 42:c2eaa912a28c 1005 }
AzureIoTClient 42:c2eaa912a28c 1006
AzureIoTClient 42:c2eaa912a28c 1007 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 1008 amqpvalue_destroy(correlation_id);
AzureIoTClient 42:c2eaa912a28c 1009 }
AzureIoTClient 42:c2eaa912a28c 1010
AzureIoTClient 42:c2eaa912a28c 1011 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 1012 properties_destroy(properties);
AzureIoTClient 42:c2eaa912a28c 1013 }
AzureIoTClient 42:c2eaa912a28c 1014
AzureIoTClient 42:c2eaa912a28c 1015 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_095: [ The application property map and all intermediate values shall be freed after being passed to `message_set_application_properties`. ]*/
AzureIoTClient 42:c2eaa912a28c 1016 message_destroy(message);
AzureIoTClient 42:c2eaa912a28c 1017 }
AzureIoTClient 42:c2eaa912a28c 1018 }
AzureIoTClient 42:c2eaa912a28c 1019
AzureIoTClient 42:c2eaa912a28c 1020 return result;
AzureIoTClient 42:c2eaa912a28c 1021 }