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 Sep 25 13:37:09 2017 -0700
Revision:
42:c2eaa912a28c
Child:
43:3da2d93bb955
1.1.24

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