A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jul 14 16:38:03 2017 -0700
Revision:
29:4a11413cf217
Parent:
28:add19eb7defa
Child:
34:6be9c2058664
1.1.19

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #include <string.h>
Azure.IoT Build 0:6ae2f7bca550 6 #include <stdint.h>
Azure.IoT Build 0:6ae2f7bca550 7 #include <stdbool.h>
AzureIoTClient 21:f9c433d8e6ca 8 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 27:d74f1cea23e1 9 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 27:d74f1cea23e1 10 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 27:d74f1cea23e1 11 #include "azure_c_shared_utility/singlylinkedlist.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/link.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/session.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_uamqp_c/amqpvalue.h"
Azure.IoT Build 0:6ae2f7bca550 15 #include "azure_uamqp_c/amqp_definitions.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/amqp_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 17
Azure.IoT Build 0:6ae2f7bca550 18 #define DEFAULT_LINK_CREDIT 10000
Azure.IoT Build 0:6ae2f7bca550 19
Azure.IoT Build 0:6ae2f7bca550 20 typedef struct DELIVERY_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 21 {
AzureIoTClient 28:add19eb7defa 22 delivery_number delivery_id;
AzureIoTClient 28:add19eb7defa 23 ON_DELIVERY_SETTLED on_delivery_settled;
AzureIoTClient 28:add19eb7defa 24 void* callback_context;
AzureIoTClient 28:add19eb7defa 25 void* link;
Azure.IoT Build 0:6ae2f7bca550 26 } DELIVERY_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 27
Azure.IoT Build 0:6ae2f7bca550 28 typedef struct LINK_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 29 {
AzureIoTClient 28:add19eb7defa 30 SESSION_HANDLE session;
AzureIoTClient 28:add19eb7defa 31 LINK_STATE link_state;
AzureIoTClient 28:add19eb7defa 32 LINK_STATE previous_link_state;
AzureIoTClient 28:add19eb7defa 33 AMQP_VALUE source;
AzureIoTClient 28:add19eb7defa 34 AMQP_VALUE target;
AzureIoTClient 28:add19eb7defa 35 handle handle;
AzureIoTClient 28:add19eb7defa 36 LINK_ENDPOINT_HANDLE link_endpoint;
AzureIoTClient 28:add19eb7defa 37 char* name;
AzureIoTClient 28:add19eb7defa 38 SINGLYLINKEDLIST_HANDLE pending_deliveries;
AzureIoTClient 28:add19eb7defa 39 sequence_no delivery_count;
AzureIoTClient 28:add19eb7defa 40 role role;
AzureIoTClient 28:add19eb7defa 41 ON_LINK_STATE_CHANGED on_link_state_changed;
AzureIoTClient 28:add19eb7defa 42 ON_LINK_FLOW_ON on_link_flow_on;
Azure.IoT Build 0:6ae2f7bca550 43 ON_TRANSFER_RECEIVED on_transfer_received;
AzureIoTClient 28:add19eb7defa 44 void* callback_context;
AzureIoTClient 28:add19eb7defa 45 sender_settle_mode snd_settle_mode;
AzureIoTClient 28:add19eb7defa 46 receiver_settle_mode rcv_settle_mode;
AzureIoTClient 28:add19eb7defa 47 sequence_no initial_delivery_count;
AzureIoTClient 28:add19eb7defa 48 uint64_t max_message_size;
AzureIoTClient 28:add19eb7defa 49 uint64_t peer_max_message_size;
AzureIoTClient 28:add19eb7defa 50 uint32_t link_credit;
AzureIoTClient 28:add19eb7defa 51 uint32_t available;
Azure.IoT Build 0:6ae2f7bca550 52 fields attach_properties;
AzureIoTClient 12:b30dacf113f2 53 bool is_underlying_session_begun;
AzureIoTClient 12:b30dacf113f2 54 bool is_closed;
AzureIoTClient 12:b30dacf113f2 55 unsigned char* received_payload;
AzureIoTClient 12:b30dacf113f2 56 uint32_t received_payload_size;
AzureIoTClient 12:b30dacf113f2 57 delivery_number received_delivery_id;
Azure.IoT Build 0:6ae2f7bca550 58 } LINK_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 59
Azure.IoT Build 0:6ae2f7bca550 60 static void set_link_state(LINK_INSTANCE* link_instance, LINK_STATE link_state)
Azure.IoT Build 0:6ae2f7bca550 61 {
AzureIoTClient 28:add19eb7defa 62 link_instance->previous_link_state = link_instance->link_state;
AzureIoTClient 28:add19eb7defa 63 link_instance->link_state = link_state;
Azure.IoT Build 0:6ae2f7bca550 64
AzureIoTClient 28:add19eb7defa 65 if (link_instance->on_link_state_changed != NULL)
AzureIoTClient 28:add19eb7defa 66 {
AzureIoTClient 28:add19eb7defa 67 link_instance->on_link_state_changed(link_instance->callback_context, link_state, link_instance->previous_link_state);
AzureIoTClient 28:add19eb7defa 68 }
Azure.IoT Build 0:6ae2f7bca550 69 }
Azure.IoT Build 0:6ae2f7bca550 70
AzureIoTClient 21:f9c433d8e6ca 71 static void remove_all_pending_deliveries(LINK_INSTANCE* link, bool indicate_settled)
AzureIoTClient 21:f9c433d8e6ca 72 {
AzureIoTClient 21:f9c433d8e6ca 73 if (link->pending_deliveries != NULL)
AzureIoTClient 21:f9c433d8e6ca 74 {
AzureIoTClient 21:f9c433d8e6ca 75 LIST_ITEM_HANDLE item = singlylinkedlist_get_head_item(link->pending_deliveries);
AzureIoTClient 21:f9c433d8e6ca 76 while (item != NULL)
AzureIoTClient 21:f9c433d8e6ca 77 {
AzureIoTClient 21:f9c433d8e6ca 78 LIST_ITEM_HANDLE next_item = singlylinkedlist_get_next_item(item);
AzureIoTClient 21:f9c433d8e6ca 79 DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)singlylinkedlist_item_get_value(item);
AzureIoTClient 21:f9c433d8e6ca 80 if (delivery_instance != NULL)
AzureIoTClient 21:f9c433d8e6ca 81 {
AzureIoTClient 21:f9c433d8e6ca 82 if (indicate_settled && (delivery_instance->on_delivery_settled != NULL))
AzureIoTClient 21:f9c433d8e6ca 83 {
AzureIoTClient 23:1111ee8bcba4 84 delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_NOT_DELIVERED, NULL);
AzureIoTClient 21:f9c433d8e6ca 85 }
AzureIoTClient 21:f9c433d8e6ca 86 free(delivery_instance);
AzureIoTClient 21:f9c433d8e6ca 87 }
AzureIoTClient 21:f9c433d8e6ca 88
AzureIoTClient 21:f9c433d8e6ca 89 item = next_item;
AzureIoTClient 21:f9c433d8e6ca 90 }
AzureIoTClient 21:f9c433d8e6ca 91
AzureIoTClient 21:f9c433d8e6ca 92 singlylinkedlist_destroy(link->pending_deliveries);
AzureIoTClient 21:f9c433d8e6ca 93 link->pending_deliveries = NULL;
AzureIoTClient 21:f9c433d8e6ca 94 }
AzureIoTClient 21:f9c433d8e6ca 95 }
AzureIoTClient 21:f9c433d8e6ca 96
Azure.IoT Build 0:6ae2f7bca550 97 static int send_flow(LINK_INSTANCE* link)
Azure.IoT Build 0:6ae2f7bca550 98 {
AzureIoTClient 28:add19eb7defa 99 int result;
AzureIoTClient 28:add19eb7defa 100 FLOW_HANDLE flow = flow_create(0, 0, 0);
Azure.IoT Build 0:6ae2f7bca550 101
AzureIoTClient 28:add19eb7defa 102 if (flow == NULL)
AzureIoTClient 28:add19eb7defa 103 {
AzureIoTClient 28:add19eb7defa 104 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 105 }
AzureIoTClient 28:add19eb7defa 106 else
AzureIoTClient 28:add19eb7defa 107 {
AzureIoTClient 28:add19eb7defa 108 if ((flow_set_link_credit(flow, link->link_credit) != 0) ||
AzureIoTClient 28:add19eb7defa 109 (flow_set_handle(flow, link->handle) != 0) ||
AzureIoTClient 28:add19eb7defa 110 (flow_set_delivery_count(flow, link->delivery_count) != 0))
AzureIoTClient 28:add19eb7defa 111 {
AzureIoTClient 28:add19eb7defa 112 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 113 }
AzureIoTClient 28:add19eb7defa 114 else
AzureIoTClient 28:add19eb7defa 115 {
AzureIoTClient 28:add19eb7defa 116 if (session_send_flow(link->link_endpoint, flow) != 0)
AzureIoTClient 28:add19eb7defa 117 {
AzureIoTClient 28:add19eb7defa 118 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 119 }
AzureIoTClient 28:add19eb7defa 120 else
AzureIoTClient 28:add19eb7defa 121 {
AzureIoTClient 28:add19eb7defa 122 result = 0;
AzureIoTClient 28:add19eb7defa 123 }
AzureIoTClient 28:add19eb7defa 124 }
Azure.IoT Build 0:6ae2f7bca550 125
AzureIoTClient 28:add19eb7defa 126 flow_destroy(flow);
AzureIoTClient 28:add19eb7defa 127 }
Azure.IoT Build 0:6ae2f7bca550 128
AzureIoTClient 28:add19eb7defa 129 return result;
Azure.IoT Build 0:6ae2f7bca550 130 }
Azure.IoT Build 0:6ae2f7bca550 131
Azure.IoT Build 0:6ae2f7bca550 132 static int send_disposition(LINK_INSTANCE* link_instance, delivery_number delivery_number, AMQP_VALUE delivery_state)
Azure.IoT Build 0:6ae2f7bca550 133 {
AzureIoTClient 28:add19eb7defa 134 int result;
Azure.IoT Build 0:6ae2f7bca550 135
AzureIoTClient 28:add19eb7defa 136 DISPOSITION_HANDLE disposition = disposition_create(link_instance->role, delivery_number);
AzureIoTClient 28:add19eb7defa 137 if (disposition == NULL)
AzureIoTClient 28:add19eb7defa 138 {
AzureIoTClient 28:add19eb7defa 139 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 140 }
AzureIoTClient 28:add19eb7defa 141 else
AzureIoTClient 28:add19eb7defa 142 {
AzureIoTClient 28:add19eb7defa 143 if ((disposition_set_last(disposition, delivery_number) != 0) ||
AzureIoTClient 28:add19eb7defa 144 (disposition_set_settled(disposition, true) != 0) ||
AzureIoTClient 28:add19eb7defa 145 ((delivery_state != NULL) && (disposition_set_state(disposition, delivery_state) != 0)))
AzureIoTClient 28:add19eb7defa 146 {
AzureIoTClient 28:add19eb7defa 147 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 148 }
AzureIoTClient 28:add19eb7defa 149 else
AzureIoTClient 28:add19eb7defa 150 {
AzureIoTClient 28:add19eb7defa 151 if (session_send_disposition(link_instance->link_endpoint, disposition) != 0)
AzureIoTClient 28:add19eb7defa 152 {
AzureIoTClient 28:add19eb7defa 153 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 154 }
AzureIoTClient 28:add19eb7defa 155 else
AzureIoTClient 28:add19eb7defa 156 {
AzureIoTClient 28:add19eb7defa 157 result = 0;
AzureIoTClient 28:add19eb7defa 158 }
AzureIoTClient 28:add19eb7defa 159 }
Azure.IoT Build 0:6ae2f7bca550 160
AzureIoTClient 28:add19eb7defa 161 disposition_destroy(disposition);
AzureIoTClient 28:add19eb7defa 162 }
Azure.IoT Build 0:6ae2f7bca550 163
AzureIoTClient 28:add19eb7defa 164 return result;
Azure.IoT Build 0:6ae2f7bca550 165 }
Azure.IoT Build 0:6ae2f7bca550 166
AzureIoTClient 12:b30dacf113f2 167 static int send_detach(LINK_INSTANCE* link_instance, bool close, ERROR_HANDLE error_handle)
Azure.IoT Build 0:6ae2f7bca550 168 {
AzureIoTClient 28:add19eb7defa 169 int result;
AzureIoTClient 28:add19eb7defa 170 DETACH_HANDLE detach_performative;
Azure.IoT Build 0:6ae2f7bca550 171
AzureIoTClient 28:add19eb7defa 172 detach_performative = detach_create(0);
AzureIoTClient 28:add19eb7defa 173 if (detach_performative == NULL)
AzureIoTClient 28:add19eb7defa 174 {
AzureIoTClient 28:add19eb7defa 175 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 176 }
AzureIoTClient 28:add19eb7defa 177 else
AzureIoTClient 28:add19eb7defa 178 {
AzureIoTClient 28:add19eb7defa 179 if ((error_handle != NULL) &&
AzureIoTClient 28:add19eb7defa 180 (detach_set_error(detach_performative, error_handle) != 0))
AzureIoTClient 28:add19eb7defa 181 {
AzureIoTClient 28:add19eb7defa 182 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 183 }
AzureIoTClient 12:b30dacf113f2 184 else if (close &&
AzureIoTClient 12:b30dacf113f2 185 (detach_set_closed(detach_performative, true) != 0))
AzureIoTClient 12:b30dacf113f2 186 {
AzureIoTClient 19:000ab4e6a2c1 187 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 188 }
AzureIoTClient 12:b30dacf113f2 189 else
AzureIoTClient 28:add19eb7defa 190 {
AzureIoTClient 28:add19eb7defa 191 if (session_send_detach(link_instance->link_endpoint, detach_performative) != 0)
AzureIoTClient 28:add19eb7defa 192 {
AzureIoTClient 28:add19eb7defa 193 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 194 }
AzureIoTClient 28:add19eb7defa 195 else
AzureIoTClient 28:add19eb7defa 196 {
AzureIoTClient 12:b30dacf113f2 197 if (close)
AzureIoTClient 12:b30dacf113f2 198 {
AzureIoTClient 12:b30dacf113f2 199 /* Declare link to be closed */
AzureIoTClient 12:b30dacf113f2 200 link_instance->is_closed = true;
AzureIoTClient 12:b30dacf113f2 201 }
AzureIoTClient 12:b30dacf113f2 202
AzureIoTClient 28:add19eb7defa 203 result = 0;
AzureIoTClient 28:add19eb7defa 204 }
AzureIoTClient 28:add19eb7defa 205 }
Azure.IoT Build 0:6ae2f7bca550 206
AzureIoTClient 28:add19eb7defa 207 detach_destroy(detach_performative);
AzureIoTClient 28:add19eb7defa 208 }
Azure.IoT Build 0:6ae2f7bca550 209
AzureIoTClient 28:add19eb7defa 210 return result;
Azure.IoT Build 0:6ae2f7bca550 211 }
Azure.IoT Build 0:6ae2f7bca550 212
AzureIoTClient 12:b30dacf113f2 213 static int send_attach(LINK_INSTANCE* link, const char* name, handle handle, role role)
AzureIoTClient 12:b30dacf113f2 214 {
AzureIoTClient 12:b30dacf113f2 215 int result;
AzureIoTClient 12:b30dacf113f2 216 ATTACH_HANDLE attach = attach_create(name, handle, role);
AzureIoTClient 12:b30dacf113f2 217
AzureIoTClient 12:b30dacf113f2 218 if (attach == NULL)
AzureIoTClient 12:b30dacf113f2 219 {
AzureIoTClient 19:000ab4e6a2c1 220 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 221 }
AzureIoTClient 12:b30dacf113f2 222 else
AzureIoTClient 12:b30dacf113f2 223 {
AzureIoTClient 12:b30dacf113f2 224 result = 0;
AzureIoTClient 12:b30dacf113f2 225
AzureIoTClient 12:b30dacf113f2 226 link->delivery_count = link->initial_delivery_count;
AzureIoTClient 12:b30dacf113f2 227
AzureIoTClient 12:b30dacf113f2 228 attach_set_snd_settle_mode(attach, link->snd_settle_mode);
AzureIoTClient 12:b30dacf113f2 229 attach_set_rcv_settle_mode(attach, link->rcv_settle_mode);
AzureIoTClient 12:b30dacf113f2 230 attach_set_role(attach, role);
AzureIoTClient 12:b30dacf113f2 231 attach_set_source(attach, link->source);
AzureIoTClient 12:b30dacf113f2 232 attach_set_target(attach, link->target);
AzureIoTClient 23:1111ee8bcba4 233 if (link->attach_properties != NULL)
AzureIoTClient 23:1111ee8bcba4 234 {
AzureIoTClient 23:1111ee8bcba4 235 attach_set_properties(attach, link->attach_properties);
AzureIoTClient 23:1111ee8bcba4 236 }
AzureIoTClient 12:b30dacf113f2 237
AzureIoTClient 12:b30dacf113f2 238 if (role == role_sender)
AzureIoTClient 12:b30dacf113f2 239 {
AzureIoTClient 12:b30dacf113f2 240 if (attach_set_initial_delivery_count(attach, link->delivery_count) != 0)
AzureIoTClient 12:b30dacf113f2 241 {
AzureIoTClient 19:000ab4e6a2c1 242 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 243 }
AzureIoTClient 12:b30dacf113f2 244 }
AzureIoTClient 12:b30dacf113f2 245
AzureIoTClient 12:b30dacf113f2 246 if (result == 0)
AzureIoTClient 12:b30dacf113f2 247 {
AzureIoTClient 12:b30dacf113f2 248 if ((attach_set_max_message_size(attach, link->max_message_size) != 0) ||
AzureIoTClient 12:b30dacf113f2 249 (session_send_attach(link->link_endpoint, attach) != 0))
AzureIoTClient 12:b30dacf113f2 250 {
AzureIoTClient 19:000ab4e6a2c1 251 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 252 }
AzureIoTClient 12:b30dacf113f2 253 else
AzureIoTClient 12:b30dacf113f2 254 {
AzureIoTClient 12:b30dacf113f2 255 result = 0;
AzureIoTClient 12:b30dacf113f2 256 }
AzureIoTClient 12:b30dacf113f2 257 }
AzureIoTClient 12:b30dacf113f2 258
AzureIoTClient 12:b30dacf113f2 259 attach_destroy(attach);
AzureIoTClient 12:b30dacf113f2 260 }
AzureIoTClient 12:b30dacf113f2 261
AzureIoTClient 12:b30dacf113f2 262 return result;
AzureIoTClient 12:b30dacf113f2 263 }
AzureIoTClient 12:b30dacf113f2 264
Azure.IoT Build 0:6ae2f7bca550 265 static void link_frame_received(void* context, AMQP_VALUE performative, uint32_t payload_size, const unsigned char* payload_bytes)
Azure.IoT Build 0:6ae2f7bca550 266 {
AzureIoTClient 28:add19eb7defa 267 LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context;
AzureIoTClient 28:add19eb7defa 268 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
Azure.IoT Build 0:6ae2f7bca550 269
AzureIoTClient 28:add19eb7defa 270 if (is_attach_type_by_descriptor(descriptor))
AzureIoTClient 28:add19eb7defa 271 {
AzureIoTClient 28:add19eb7defa 272 ATTACH_HANDLE attach_handle;
AzureIoTClient 24:2c59c2d43ebf 273
AzureIoTClient 28:add19eb7defa 274 if (amqpvalue_get_attach(performative, &attach_handle) == 0)
AzureIoTClient 28:add19eb7defa 275 {
AzureIoTClient 28:add19eb7defa 276 if ((link_instance->role == role_receiver) &&
AzureIoTClient 28:add19eb7defa 277 (attach_get_initial_delivery_count(attach_handle, &link_instance->delivery_count) != 0))
AzureIoTClient 28:add19eb7defa 278 {
AzureIoTClient 28:add19eb7defa 279 /* error */
AzureIoTClient 29:4a11413cf217 280 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 28:add19eb7defa 281 set_link_state(link_instance, LINK_STATE_DETACHED);
AzureIoTClient 28:add19eb7defa 282 }
AzureIoTClient 28:add19eb7defa 283 else
AzureIoTClient 28:add19eb7defa 284 {
AzureIoTClient 28:add19eb7defa 285 if (attach_get_max_message_size(attach_handle, &link_instance->peer_max_message_size) != 0)
AzureIoTClient 28:add19eb7defa 286 {
AzureIoTClient 28:add19eb7defa 287 LogError("Could not retrieve peer_max_message_size from attach frame");
AzureIoTClient 28:add19eb7defa 288 }
AzureIoTClient 24:2c59c2d43ebf 289
AzureIoTClient 28:add19eb7defa 290 if ((link_instance->link_state == LINK_STATE_DETACHED) ||
AzureIoTClient 28:add19eb7defa 291 (link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_SENT))
AzureIoTClient 28:add19eb7defa 292 {
AzureIoTClient 28:add19eb7defa 293 if (link_instance->role == role_receiver)
AzureIoTClient 28:add19eb7defa 294 {
AzureIoTClient 28:add19eb7defa 295 link_instance->link_credit = DEFAULT_LINK_CREDIT;
AzureIoTClient 28:add19eb7defa 296 send_flow(link_instance);
AzureIoTClient 28:add19eb7defa 297 }
AzureIoTClient 28:add19eb7defa 298 else
AzureIoTClient 28:add19eb7defa 299 {
AzureIoTClient 28:add19eb7defa 300 link_instance->link_credit = 0;
AzureIoTClient 28:add19eb7defa 301 }
Azure.IoT Build 0:6ae2f7bca550 302
AzureIoTClient 28:add19eb7defa 303 if (link_instance->link_state == LINK_STATE_DETACHED)
AzureIoTClient 28:add19eb7defa 304 {
AzureIoTClient 28:add19eb7defa 305 set_link_state(link_instance, LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED);
AzureIoTClient 28:add19eb7defa 306 }
AzureIoTClient 28:add19eb7defa 307 else
AzureIoTClient 28:add19eb7defa 308 {
AzureIoTClient 28:add19eb7defa 309 set_link_state(link_instance, LINK_STATE_ATTACHED);
AzureIoTClient 28:add19eb7defa 310 }
AzureIoTClient 28:add19eb7defa 311 }
AzureIoTClient 28:add19eb7defa 312 }
Azure.IoT Build 0:6ae2f7bca550 313
AzureIoTClient 28:add19eb7defa 314 attach_destroy(attach_handle);
AzureIoTClient 28:add19eb7defa 315 }
AzureIoTClient 28:add19eb7defa 316 }
AzureIoTClient 28:add19eb7defa 317 else if (is_flow_type_by_descriptor(descriptor))
AzureIoTClient 28:add19eb7defa 318 {
AzureIoTClient 28:add19eb7defa 319 FLOW_HANDLE flow_handle;
AzureIoTClient 28:add19eb7defa 320 if (amqpvalue_get_flow(performative, &flow_handle) == 0)
AzureIoTClient 28:add19eb7defa 321 {
AzureIoTClient 28:add19eb7defa 322 if (link_instance->role == role_sender)
AzureIoTClient 28:add19eb7defa 323 {
AzureIoTClient 28:add19eb7defa 324 delivery_number rcv_delivery_count;
AzureIoTClient 28:add19eb7defa 325 uint32_t rcv_link_credit;
Azure.IoT Build 0:6ae2f7bca550 326
AzureIoTClient 28:add19eb7defa 327 if ((flow_get_link_credit(flow_handle, &rcv_link_credit) != 0) ||
AzureIoTClient 28:add19eb7defa 328 (flow_get_delivery_count(flow_handle, &rcv_delivery_count) != 0))
AzureIoTClient 28:add19eb7defa 329 {
AzureIoTClient 28:add19eb7defa 330 /* error */
AzureIoTClient 29:4a11413cf217 331 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 28:add19eb7defa 332 set_link_state(link_instance, LINK_STATE_DETACHED);
AzureIoTClient 28:add19eb7defa 333 }
AzureIoTClient 28:add19eb7defa 334 else
AzureIoTClient 28:add19eb7defa 335 {
AzureIoTClient 28:add19eb7defa 336 link_instance->link_credit = rcv_delivery_count + rcv_link_credit - link_instance->delivery_count;
AzureIoTClient 28:add19eb7defa 337 if (link_instance->link_credit > 0)
AzureIoTClient 28:add19eb7defa 338 {
AzureIoTClient 28:add19eb7defa 339 link_instance->on_link_flow_on(link_instance->callback_context);
AzureIoTClient 28:add19eb7defa 340 }
AzureIoTClient 28:add19eb7defa 341 }
AzureIoTClient 28:add19eb7defa 342 }
AzureIoTClient 28:add19eb7defa 343 }
Azure.IoT Build 0:6ae2f7bca550 344
AzureIoTClient 28:add19eb7defa 345 flow_destroy(flow_handle);
AzureIoTClient 28:add19eb7defa 346 }
AzureIoTClient 28:add19eb7defa 347 else if (is_transfer_type_by_descriptor(descriptor))
AzureIoTClient 28:add19eb7defa 348 {
AzureIoTClient 28:add19eb7defa 349 if (link_instance->on_transfer_received != NULL)
AzureIoTClient 28:add19eb7defa 350 {
AzureIoTClient 28:add19eb7defa 351 TRANSFER_HANDLE transfer_handle;
AzureIoTClient 28:add19eb7defa 352 if (amqpvalue_get_transfer(performative, &transfer_handle) == 0)
AzureIoTClient 28:add19eb7defa 353 {
AzureIoTClient 28:add19eb7defa 354 AMQP_VALUE delivery_state;
AzureIoTClient 12:b30dacf113f2 355 bool more;
AzureIoTClient 28:add19eb7defa 356 bool is_error;
Azure.IoT Build 0:6ae2f7bca550 357
AzureIoTClient 28:add19eb7defa 358 link_instance->link_credit--;
AzureIoTClient 28:add19eb7defa 359 link_instance->delivery_count++;
AzureIoTClient 28:add19eb7defa 360 if (link_instance->link_credit == 0)
AzureIoTClient 28:add19eb7defa 361 {
AzureIoTClient 28:add19eb7defa 362 link_instance->link_credit = DEFAULT_LINK_CREDIT;
AzureIoTClient 28:add19eb7defa 363 send_flow(link_instance);
AzureIoTClient 28:add19eb7defa 364 }
Azure.IoT Build 0:6ae2f7bca550 365
AzureIoTClient 28:add19eb7defa 366 more = false;
AzureIoTClient 28:add19eb7defa 367 /* Attempt to get more flag, default to false */
AzureIoTClient 28:add19eb7defa 368 (void)transfer_get_more(transfer_handle, &more);
AzureIoTClient 28:add19eb7defa 369 is_error = false;
AzureIoTClient 12:b30dacf113f2 370
AzureIoTClient 13:9abd748f4e78 371 if (transfer_get_delivery_id(transfer_handle, &link_instance->received_delivery_id) != 0)
AzureIoTClient 13:9abd748f4e78 372 {
AzureIoTClient 13:9abd748f4e78 373 /* is this not a continuation transfer? */
AzureIoTClient 13:9abd748f4e78 374 if (link_instance->received_payload_size == 0)
AzureIoTClient 12:b30dacf113f2 375 {
AzureIoTClient 13:9abd748f4e78 376 LogError("Could not get the delivery Id from the transfer performative");
AzureIoTClient 13:9abd748f4e78 377 is_error = true;
AzureIoTClient 13:9abd748f4e78 378 }
AzureIoTClient 13:9abd748f4e78 379 }
AzureIoTClient 13:9abd748f4e78 380
AzureIoTClient 13:9abd748f4e78 381 if (!is_error)
AzureIoTClient 13:9abd748f4e78 382 {
AzureIoTClient 13:9abd748f4e78 383 /* If this is a continuation transfer or if this is the first chunk of a multi frame transfer */
AzureIoTClient 13:9abd748f4e78 384 if ((link_instance->received_payload_size > 0) || more)
AzureIoTClient 13:9abd748f4e78 385 {
AzureIoTClient 13:9abd748f4e78 386 unsigned char* new_received_payload = (unsigned char*)realloc(link_instance->received_payload, link_instance->received_payload_size + payload_size);
AzureIoTClient 13:9abd748f4e78 387 if (new_received_payload == NULL)
AzureIoTClient 12:b30dacf113f2 388 {
AzureIoTClient 13:9abd748f4e78 389 LogError("Could not allocate memory for the received payload");
AzureIoTClient 13:9abd748f4e78 390 }
AzureIoTClient 13:9abd748f4e78 391 else
AzureIoTClient 13:9abd748f4e78 392 {
AzureIoTClient 13:9abd748f4e78 393 link_instance->received_payload = new_received_payload;
AzureIoTClient 13:9abd748f4e78 394 (void)memcpy(link_instance->received_payload + link_instance->received_payload_size, payload_bytes, payload_size);
AzureIoTClient 13:9abd748f4e78 395 link_instance->received_payload_size += payload_size;
AzureIoTClient 12:b30dacf113f2 396 }
AzureIoTClient 12:b30dacf113f2 397 }
AzureIoTClient 13:9abd748f4e78 398
AzureIoTClient 13:9abd748f4e78 399 if (!more)
AzureIoTClient 12:b30dacf113f2 400 {
AzureIoTClient 13:9abd748f4e78 401 const unsigned char* indicate_payload_bytes;
AzureIoTClient 13:9abd748f4e78 402 uint32_t indicate_payload_size;
AzureIoTClient 13:9abd748f4e78 403
AzureIoTClient 13:9abd748f4e78 404 /* if no previously stored chunks then simply report the current payload */
AzureIoTClient 13:9abd748f4e78 405 if (link_instance->received_payload_size > 0)
AzureIoTClient 12:b30dacf113f2 406 {
AzureIoTClient 13:9abd748f4e78 407 indicate_payload_size = link_instance->received_payload_size;
AzureIoTClient 13:9abd748f4e78 408 indicate_payload_bytes = link_instance->received_payload;
AzureIoTClient 13:9abd748f4e78 409 }
AzureIoTClient 13:9abd748f4e78 410 else
AzureIoTClient 13:9abd748f4e78 411 {
AzureIoTClient 13:9abd748f4e78 412 indicate_payload_size = payload_size;
AzureIoTClient 13:9abd748f4e78 413 indicate_payload_bytes = payload_bytes;
AzureIoTClient 12:b30dacf113f2 414 }
Azure.IoT Build 0:6ae2f7bca550 415
AzureIoTClient 13:9abd748f4e78 416 delivery_state = link_instance->on_transfer_received(link_instance->callback_context, transfer_handle, indicate_payload_size, indicate_payload_bytes);
AzureIoTClient 12:b30dacf113f2 417
AzureIoTClient 13:9abd748f4e78 418 if (link_instance->received_payload_size > 0)
AzureIoTClient 13:9abd748f4e78 419 {
AzureIoTClient 13:9abd748f4e78 420 free(link_instance->received_payload);
AzureIoTClient 13:9abd748f4e78 421 link_instance->received_payload = NULL;
AzureIoTClient 13:9abd748f4e78 422 link_instance->received_payload_size = 0;
AzureIoTClient 13:9abd748f4e78 423 }
AzureIoTClient 12:b30dacf113f2 424
AzureIoTClient 13:9abd748f4e78 425 if (delivery_state != NULL)
AzureIoTClient 13:9abd748f4e78 426 {
AzureIoTClient 20:206846c14c80 427 if (send_disposition(link_instance, link_instance->received_delivery_id, delivery_state) != 0)
AzureIoTClient 20:206846c14c80 428 {
AzureIoTClient 20:206846c14c80 429 LogError("Cannot send disposition frame");
AzureIoTClient 20:206846c14c80 430 }
AzureIoTClient 13:9abd748f4e78 431 amqpvalue_destroy(delivery_state);
AzureIoTClient 12:b30dacf113f2 432 }
AzureIoTClient 12:b30dacf113f2 433 }
AzureIoTClient 12:b30dacf113f2 434 }
Azure.IoT Build 0:6ae2f7bca550 435
AzureIoTClient 28:add19eb7defa 436 transfer_destroy(transfer_handle);
AzureIoTClient 28:add19eb7defa 437 }
AzureIoTClient 28:add19eb7defa 438 }
AzureIoTClient 28:add19eb7defa 439 }
AzureIoTClient 28:add19eb7defa 440 else if (is_disposition_type_by_descriptor(descriptor))
AzureIoTClient 28:add19eb7defa 441 {
AzureIoTClient 28:add19eb7defa 442 DISPOSITION_HANDLE disposition;
AzureIoTClient 28:add19eb7defa 443 if (amqpvalue_get_disposition(performative, &disposition) != 0)
AzureIoTClient 28:add19eb7defa 444 {
AzureIoTClient 28:add19eb7defa 445 /* error */
AzureIoTClient 28:add19eb7defa 446 }
AzureIoTClient 28:add19eb7defa 447 else
AzureIoTClient 28:add19eb7defa 448 {
AzureIoTClient 28:add19eb7defa 449 delivery_number first;
AzureIoTClient 28:add19eb7defa 450 delivery_number last;
Azure.IoT Build 0:6ae2f7bca550 451
AzureIoTClient 28:add19eb7defa 452 if (disposition_get_first(disposition, &first) != 0)
AzureIoTClient 28:add19eb7defa 453 {
AzureIoTClient 28:add19eb7defa 454 /* error */
AzureIoTClient 28:add19eb7defa 455 }
AzureIoTClient 28:add19eb7defa 456 else
AzureIoTClient 28:add19eb7defa 457 {
Azure.IoT Build 0:6ae2f7bca550 458 bool settled;
Azure.IoT Build 0:6ae2f7bca550 459
AzureIoTClient 28:add19eb7defa 460 if (disposition_get_last(disposition, &last) != 0)
AzureIoTClient 28:add19eb7defa 461 {
AzureIoTClient 28:add19eb7defa 462 last = first;
AzureIoTClient 28:add19eb7defa 463 }
Azure.IoT Build 0:6ae2f7bca550 464
Azure.IoT Build 0:6ae2f7bca550 465 if (disposition_get_settled(disposition, &settled) != 0)
Azure.IoT Build 0:6ae2f7bca550 466 {
Azure.IoT Build 0:6ae2f7bca550 467 /* Error */
Azure.IoT Build 0:6ae2f7bca550 468 settled = false;
Azure.IoT Build 0:6ae2f7bca550 469 }
Azure.IoT Build 0:6ae2f7bca550 470
Azure.IoT Build 0:6ae2f7bca550 471 if (settled)
Azure.IoT Build 0:6ae2f7bca550 472 {
AzureIoTClient 12:b30dacf113f2 473 LIST_ITEM_HANDLE pending_delivery = singlylinkedlist_get_head_item(link_instance->pending_deliveries);
Azure.IoT Build 0:6ae2f7bca550 474 while (pending_delivery != NULL)
Azure.IoT Build 0:6ae2f7bca550 475 {
AzureIoTClient 12:b30dacf113f2 476 LIST_ITEM_HANDLE next_pending_delivery = singlylinkedlist_get_next_item(pending_delivery);
AzureIoTClient 12:b30dacf113f2 477 DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)singlylinkedlist_item_get_value(pending_delivery);
Azure.IoT Build 0:6ae2f7bca550 478 if (delivery_instance == NULL)
Azure.IoT Build 0:6ae2f7bca550 479 {
Azure.IoT Build 0:6ae2f7bca550 480 /* error */
Azure.IoT Build 0:6ae2f7bca550 481 break;
Azure.IoT Build 0:6ae2f7bca550 482 }
Azure.IoT Build 0:6ae2f7bca550 483 else
Azure.IoT Build 0:6ae2f7bca550 484 {
Azure.IoT Build 0:6ae2f7bca550 485 if ((delivery_instance->delivery_id >= first) && (delivery_instance->delivery_id <= last))
Azure.IoT Build 0:6ae2f7bca550 486 {
AzureIoTClient 7:9e9ab3b0efef 487 AMQP_VALUE delivery_state;
AzureIoTClient 7:9e9ab3b0efef 488 if (disposition_get_state(disposition, &delivery_state) != 0)
Azure.IoT Build 0:6ae2f7bca550 489 {
Azure.IoT Build 0:6ae2f7bca550 490 /* error */
Azure.IoT Build 0:6ae2f7bca550 491 }
Azure.IoT Build 0:6ae2f7bca550 492 else
Azure.IoT Build 0:6ae2f7bca550 493 {
AzureIoTClient 23:1111ee8bcba4 494 delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_DISPOSITION_RECEIVED, delivery_state);
AzureIoTClient 21:f9c433d8e6ca 495 free(delivery_instance);
AzureIoTClient 12:b30dacf113f2 496 if (singlylinkedlist_remove(link_instance->pending_deliveries, pending_delivery) != 0)
AzureIoTClient 7:9e9ab3b0efef 497 {
AzureIoTClient 7:9e9ab3b0efef 498 /* error */
AzureIoTClient 7:9e9ab3b0efef 499 break;
AzureIoTClient 7:9e9ab3b0efef 500 }
AzureIoTClient 7:9e9ab3b0efef 501 else
AzureIoTClient 7:9e9ab3b0efef 502 {
AzureIoTClient 7:9e9ab3b0efef 503 pending_delivery = next_pending_delivery;
AzureIoTClient 7:9e9ab3b0efef 504 }
Azure.IoT Build 0:6ae2f7bca550 505 }
Azure.IoT Build 0:6ae2f7bca550 506 }
Azure.IoT Build 0:6ae2f7bca550 507 else
Azure.IoT Build 0:6ae2f7bca550 508 {
Azure.IoT Build 0:6ae2f7bca550 509 pending_delivery = next_pending_delivery;
Azure.IoT Build 0:6ae2f7bca550 510 }
Azure.IoT Build 0:6ae2f7bca550 511 }
Azure.IoT Build 0:6ae2f7bca550 512 }
Azure.IoT Build 0:6ae2f7bca550 513 }
AzureIoTClient 28:add19eb7defa 514 }
Azure.IoT Build 0:6ae2f7bca550 515
AzureIoTClient 28:add19eb7defa 516 disposition_destroy(disposition);
AzureIoTClient 28:add19eb7defa 517 }
AzureIoTClient 28:add19eb7defa 518 }
AzureIoTClient 28:add19eb7defa 519 else if (is_detach_type_by_descriptor(descriptor))
AzureIoTClient 28:add19eb7defa 520 {
AzureIoTClient 1:eab586236bfe 521 DETACH_HANDLE detach;
AzureIoTClient 1:eab586236bfe 522
AzureIoTClient 1:eab586236bfe 523 /* Set link state appropriately based on whether we received detach condition */
AzureIoTClient 1:eab586236bfe 524 if (amqpvalue_get_detach(performative, &detach) == 0)
AzureIoTClient 1:eab586236bfe 525 {
AzureIoTClient 12:b30dacf113f2 526 bool closed = false;
AzureIoTClient 1:eab586236bfe 527 ERROR_HANDLE error;
AzureIoTClient 19:000ab4e6a2c1 528
AzureIoTClient 19:000ab4e6a2c1 529 /* Received a detach while attached */
AzureIoTClient 19:000ab4e6a2c1 530 if (link_instance->link_state == LINK_STATE_ATTACHED)
AzureIoTClient 19:000ab4e6a2c1 531 {
AzureIoTClient 19:000ab4e6a2c1 532 /* Respond with ack */
AzureIoTClient 19:000ab4e6a2c1 533 (void)send_detach(link_instance, closed, NULL);
AzureIoTClient 19:000ab4e6a2c1 534 }
AzureIoTClient 19:000ab4e6a2c1 535
AzureIoTClient 19:000ab4e6a2c1 536 /* Received a closing detach after we sent a non-closing detach. */
AzureIoTClient 19:000ab4e6a2c1 537 else if (closed &&
AzureIoTClient 24:2c59c2d43ebf 538 ((link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_SENT) || (link_instance->link_state == LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED)) &&
AzureIoTClient 19:000ab4e6a2c1 539 !link_instance->is_closed)
AzureIoTClient 19:000ab4e6a2c1 540 {
AzureIoTClient 19:000ab4e6a2c1 541
AzureIoTClient 19:000ab4e6a2c1 542 /* In this case, we MUST signal that we closed by reattaching and then sending a closing detach.*/
AzureIoTClient 19:000ab4e6a2c1 543 (void)send_attach(link_instance, link_instance->name, 0, link_instance->role);
AzureIoTClient 19:000ab4e6a2c1 544 (void)send_detach(link_instance, true, NULL);
AzureIoTClient 19:000ab4e6a2c1 545 }
AzureIoTClient 19:000ab4e6a2c1 546
AzureIoTClient 1:eab586236bfe 547 if (detach_get_error(detach, &error) == 0)
AzureIoTClient 1:eab586236bfe 548 {
AzureIoTClient 1:eab586236bfe 549 error_destroy(error);
AzureIoTClient 1:eab586236bfe 550
AzureIoTClient 29:4a11413cf217 551 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 1:eab586236bfe 552 set_link_state(link_instance, LINK_STATE_ERROR);
AzureIoTClient 1:eab586236bfe 553 }
AzureIoTClient 12:b30dacf113f2 554 else
AzureIoTClient 1:eab586236bfe 555 {
AzureIoTClient 12:b30dacf113f2 556 (void)detach_get_closed(detach, &closed);
AzureIoTClient 12:b30dacf113f2 557
AzureIoTClient 29:4a11413cf217 558 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 1:eab586236bfe 559 set_link_state(link_instance, LINK_STATE_DETACHED);
AzureIoTClient 1:eab586236bfe 560 }
AzureIoTClient 12:b30dacf113f2 561
AzureIoTClient 12:b30dacf113f2 562 detach_destroy(detach);
AzureIoTClient 1:eab586236bfe 563 }
AzureIoTClient 1:eab586236bfe 564 }
Azure.IoT Build 0:6ae2f7bca550 565 }
Azure.IoT Build 0:6ae2f7bca550 566
Azure.IoT Build 0:6ae2f7bca550 567 static void on_session_state_changed(void* context, SESSION_STATE new_session_state, SESSION_STATE previous_session_state)
Azure.IoT Build 0:6ae2f7bca550 568 {
AzureIoTClient 28:add19eb7defa 569 LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context;
AzureIoTClient 6:641a9672db08 570 (void)previous_session_state;
Azure.IoT Build 0:6ae2f7bca550 571
AzureIoTClient 28:add19eb7defa 572 if (new_session_state == SESSION_STATE_MAPPED)
AzureIoTClient 28:add19eb7defa 573 {
AzureIoTClient 28:add19eb7defa 574 if ((link_instance->link_state == LINK_STATE_DETACHED) && (!link_instance->is_closed))
AzureIoTClient 28:add19eb7defa 575 {
AzureIoTClient 28:add19eb7defa 576 if (send_attach(link_instance, link_instance->name, 0, link_instance->role) == 0)
AzureIoTClient 28:add19eb7defa 577 {
AzureIoTClient 28:add19eb7defa 578 set_link_state(link_instance, LINK_STATE_HALF_ATTACHED_ATTACH_SENT);
AzureIoTClient 28:add19eb7defa 579 }
AzureIoTClient 28:add19eb7defa 580 }
AzureIoTClient 28:add19eb7defa 581 }
AzureIoTClient 28:add19eb7defa 582 else if (new_session_state == SESSION_STATE_DISCARDING)
AzureIoTClient 28:add19eb7defa 583 {
AzureIoTClient 29:4a11413cf217 584 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 23:1111ee8bcba4 585 set_link_state(link_instance, LINK_STATE_DETACHED);
AzureIoTClient 28:add19eb7defa 586 }
AzureIoTClient 28:add19eb7defa 587 else if (new_session_state == SESSION_STATE_ERROR)
AzureIoTClient 28:add19eb7defa 588 {
AzureIoTClient 29:4a11413cf217 589 remove_all_pending_deliveries(link_instance, true);
AzureIoTClient 23:1111ee8bcba4 590 set_link_state(link_instance, LINK_STATE_ERROR);
AzureIoTClient 28:add19eb7defa 591 }
Azure.IoT Build 0:6ae2f7bca550 592 }
Azure.IoT Build 0:6ae2f7bca550 593
Azure.IoT Build 0:6ae2f7bca550 594 static void on_session_flow_on(void* context)
Azure.IoT Build 0:6ae2f7bca550 595 {
AzureIoTClient 28:add19eb7defa 596 LINK_INSTANCE* link_instance = (LINK_INSTANCE*)context;
AzureIoTClient 28:add19eb7defa 597 if (link_instance->role == role_sender)
AzureIoTClient 28:add19eb7defa 598 {
AzureIoTClient 28:add19eb7defa 599 link_instance->on_link_flow_on(link_instance->callback_context);
AzureIoTClient 28:add19eb7defa 600 }
Azure.IoT Build 0:6ae2f7bca550 601 }
Azure.IoT Build 0:6ae2f7bca550 602
Azure.IoT Build 0:6ae2f7bca550 603 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
Azure.IoT Build 0:6ae2f7bca550 604 {
AzureIoTClient 28:add19eb7defa 605 LIST_ITEM_HANDLE delivery_instance_list_item = (LIST_ITEM_HANDLE)context;
AzureIoTClient 28:add19eb7defa 606 DELIVERY_INSTANCE* delivery_instance = (DELIVERY_INSTANCE*)singlylinkedlist_item_get_value(delivery_instance_list_item);
AzureIoTClient 28:add19eb7defa 607 LINK_INSTANCE* link_instance = (LINK_INSTANCE*)delivery_instance->link;
AzureIoTClient 6:641a9672db08 608 (void)send_result;
AzureIoTClient 28:add19eb7defa 609 if (link_instance->snd_settle_mode == sender_settle_mode_settled)
AzureIoTClient 28:add19eb7defa 610 {
AzureIoTClient 28:add19eb7defa 611 delivery_instance->on_delivery_settled(delivery_instance->callback_context, delivery_instance->delivery_id, LINK_DELIVERY_SETTLE_REASON_SETTLED, NULL);
AzureIoTClient 28:add19eb7defa 612 free(delivery_instance);
AzureIoTClient 28:add19eb7defa 613 (void)singlylinkedlist_remove(link_instance->pending_deliveries, delivery_instance_list_item);
AzureIoTClient 28:add19eb7defa 614 }
Azure.IoT Build 0:6ae2f7bca550 615 }
Azure.IoT Build 0:6ae2f7bca550 616
Azure.IoT Build 0:6ae2f7bca550 617 LINK_HANDLE link_create(SESSION_HANDLE session, const char* name, role role, AMQP_VALUE source, AMQP_VALUE target)
Azure.IoT Build 0:6ae2f7bca550 618 {
AzureIoTClient 28:add19eb7defa 619 LINK_INSTANCE* result = (LINK_INSTANCE*)malloc(sizeof(LINK_INSTANCE));
AzureIoTClient 28:add19eb7defa 620 if (result != NULL)
AzureIoTClient 28:add19eb7defa 621 {
AzureIoTClient 28:add19eb7defa 622 result->link_state = LINK_STATE_DETACHED;
AzureIoTClient 28:add19eb7defa 623 result->previous_link_state = LINK_STATE_DETACHED;
AzureIoTClient 28:add19eb7defa 624 result->role = role;
AzureIoTClient 28:add19eb7defa 625 result->source = amqpvalue_clone(source);
AzureIoTClient 28:add19eb7defa 626 result->target = amqpvalue_clone(target);
AzureIoTClient 28:add19eb7defa 627 result->session = session;
AzureIoTClient 28:add19eb7defa 628 result->handle = 0;
AzureIoTClient 28:add19eb7defa 629 result->snd_settle_mode = sender_settle_mode_unsettled;
AzureIoTClient 28:add19eb7defa 630 result->rcv_settle_mode = receiver_settle_mode_first;
AzureIoTClient 28:add19eb7defa 631 result->delivery_count = 0;
AzureIoTClient 28:add19eb7defa 632 result->initial_delivery_count = 0;
AzureIoTClient 28:add19eb7defa 633 result->max_message_size = 0;
AzureIoTClient 28:add19eb7defa 634 result->peer_max_message_size = 0;
AzureIoTClient 28:add19eb7defa 635 result->is_underlying_session_begun = false;
AzureIoTClient 12:b30dacf113f2 636 result->is_closed = false;
Azure.IoT Build 0:6ae2f7bca550 637 result->attach_properties = NULL;
AzureIoTClient 12:b30dacf113f2 638 result->received_payload = NULL;
AzureIoTClient 12:b30dacf113f2 639 result->received_payload_size = 0;
AzureIoTClient 12:b30dacf113f2 640 result->received_delivery_id = 0;
Azure.IoT Build 0:6ae2f7bca550 641
AzureIoTClient 28:add19eb7defa 642 result->pending_deliveries = singlylinkedlist_create();
AzureIoTClient 28:add19eb7defa 643 if (result->pending_deliveries == NULL)
AzureIoTClient 28:add19eb7defa 644 {
AzureIoTClient 28:add19eb7defa 645 free(result);
AzureIoTClient 28:add19eb7defa 646 result = NULL;
AzureIoTClient 28:add19eb7defa 647 }
AzureIoTClient 28:add19eb7defa 648 else
AzureIoTClient 28:add19eb7defa 649 {
AzureIoTClient 23:1111ee8bcba4 650 size_t name_length = strlen(name);
AzureIoTClient 28:add19eb7defa 651 result->name = (char*)malloc(name_length + 1);
AzureIoTClient 28:add19eb7defa 652 if (result->name == NULL)
AzureIoTClient 28:add19eb7defa 653 {
AzureIoTClient 28:add19eb7defa 654 singlylinkedlist_destroy(result->pending_deliveries);
AzureIoTClient 28:add19eb7defa 655 free(result);
AzureIoTClient 28:add19eb7defa 656 result = NULL;
AzureIoTClient 28:add19eb7defa 657 }
AzureIoTClient 28:add19eb7defa 658 else
AzureIoTClient 28:add19eb7defa 659 {
AzureIoTClient 28:add19eb7defa 660 result->on_link_state_changed = NULL;
AzureIoTClient 28:add19eb7defa 661 result->callback_context = NULL;
AzureIoTClient 28:add19eb7defa 662 set_link_state(result, LINK_STATE_DETACHED);
Azure.IoT Build 0:6ae2f7bca550 663
AzureIoTClient 28:add19eb7defa 664 (void)memcpy(result->name, name, name_length + 1);
AzureIoTClient 28:add19eb7defa 665 result->link_endpoint = session_create_link_endpoint(session, name);
AzureIoTClient 28:add19eb7defa 666 if (result->link_endpoint == NULL)
AzureIoTClient 28:add19eb7defa 667 {
AzureIoTClient 28:add19eb7defa 668 singlylinkedlist_destroy(result->pending_deliveries);
AzureIoTClient 28:add19eb7defa 669 free(result->name);
AzureIoTClient 28:add19eb7defa 670 free(result);
AzureIoTClient 28:add19eb7defa 671 result = NULL;
AzureIoTClient 28:add19eb7defa 672 }
AzureIoTClient 28:add19eb7defa 673 }
AzureIoTClient 28:add19eb7defa 674 }
AzureIoTClient 28:add19eb7defa 675 }
Azure.IoT Build 0:6ae2f7bca550 676
AzureIoTClient 28:add19eb7defa 677 return result;
Azure.IoT Build 0:6ae2f7bca550 678 }
Azure.IoT Build 0:6ae2f7bca550 679
Azure.IoT Build 0:6ae2f7bca550 680 LINK_HANDLE link_create_from_endpoint(SESSION_HANDLE session, LINK_ENDPOINT_HANDLE link_endpoint, const char* name, role role, AMQP_VALUE source, AMQP_VALUE target)
Azure.IoT Build 0:6ae2f7bca550 681 {
AzureIoTClient 28:add19eb7defa 682 LINK_INSTANCE* result = (LINK_INSTANCE*)malloc(sizeof(LINK_INSTANCE));
AzureIoTClient 28:add19eb7defa 683 if (result != NULL)
AzureIoTClient 28:add19eb7defa 684 {
AzureIoTClient 28:add19eb7defa 685 result->link_state = LINK_STATE_DETACHED;
AzureIoTClient 28:add19eb7defa 686 result->previous_link_state = LINK_STATE_DETACHED;
AzureIoTClient 28:add19eb7defa 687 result->session = session;
AzureIoTClient 28:add19eb7defa 688 result->handle = 0;
AzureIoTClient 28:add19eb7defa 689 result->snd_settle_mode = sender_settle_mode_unsettled;
AzureIoTClient 28:add19eb7defa 690 result->rcv_settle_mode = receiver_settle_mode_first;
AzureIoTClient 28:add19eb7defa 691 result->delivery_count = 0;
AzureIoTClient 28:add19eb7defa 692 result->initial_delivery_count = 0;
AzureIoTClient 28:add19eb7defa 693 result->max_message_size = 0;
AzureIoTClient 28:add19eb7defa 694 result->peer_max_message_size = 0;
AzureIoTClient 28:add19eb7defa 695 result->is_underlying_session_begun = false;
AzureIoTClient 12:b30dacf113f2 696 result->is_closed = false;
Azure.IoT Build 0:6ae2f7bca550 697 result->attach_properties = NULL;
AzureIoTClient 12:b30dacf113f2 698 result->received_payload = NULL;
AzureIoTClient 12:b30dacf113f2 699 result->received_payload_size = 0;
AzureIoTClient 12:b30dacf113f2 700 result->received_delivery_id = 0;
Azure.IoT Build 0:6ae2f7bca550 701 result->source = amqpvalue_clone(target);
AzureIoTClient 28:add19eb7defa 702 result->target = amqpvalue_clone(source);
AzureIoTClient 28:add19eb7defa 703 if (role == role_sender)
AzureIoTClient 28:add19eb7defa 704 {
AzureIoTClient 28:add19eb7defa 705 result->role = role_receiver;
AzureIoTClient 28:add19eb7defa 706 }
AzureIoTClient 28:add19eb7defa 707 else
AzureIoTClient 28:add19eb7defa 708 {
AzureIoTClient 28:add19eb7defa 709 result->role = role_sender;
AzureIoTClient 28:add19eb7defa 710 }
Azure.IoT Build 0:6ae2f7bca550 711
AzureIoTClient 28:add19eb7defa 712 result->pending_deliveries = singlylinkedlist_create();
AzureIoTClient 28:add19eb7defa 713 if (result->pending_deliveries == NULL)
AzureIoTClient 28:add19eb7defa 714 {
AzureIoTClient 28:add19eb7defa 715 free(result);
AzureIoTClient 28:add19eb7defa 716 result = NULL;
AzureIoTClient 28:add19eb7defa 717 }
AzureIoTClient 28:add19eb7defa 718 else
AzureIoTClient 28:add19eb7defa 719 {
AzureIoTClient 23:1111ee8bcba4 720 size_t name_length = strlen(name);
AzureIoTClient 28:add19eb7defa 721 result->name = (char*)malloc(name_length + 1);
AzureIoTClient 28:add19eb7defa 722 if (result->name == NULL)
AzureIoTClient 28:add19eb7defa 723 {
AzureIoTClient 28:add19eb7defa 724 singlylinkedlist_destroy(result->pending_deliveries);
AzureIoTClient 28:add19eb7defa 725 free(result);
AzureIoTClient 28:add19eb7defa 726 result = NULL;
AzureIoTClient 28:add19eb7defa 727 }
AzureIoTClient 28:add19eb7defa 728 else
AzureIoTClient 28:add19eb7defa 729 {
AzureIoTClient 28:add19eb7defa 730 (void)memcpy(result->name, name, name_length + 1);
AzureIoTClient 28:add19eb7defa 731 result->on_link_state_changed = NULL;
AzureIoTClient 28:add19eb7defa 732 result->callback_context = NULL;
AzureIoTClient 28:add19eb7defa 733 result->link_endpoint = link_endpoint;
AzureIoTClient 28:add19eb7defa 734 }
AzureIoTClient 28:add19eb7defa 735 }
AzureIoTClient 28:add19eb7defa 736 }
Azure.IoT Build 0:6ae2f7bca550 737
AzureIoTClient 28:add19eb7defa 738 return result;
Azure.IoT Build 0:6ae2f7bca550 739 }
Azure.IoT Build 0:6ae2f7bca550 740
Azure.IoT Build 0:6ae2f7bca550 741 void link_destroy(LINK_HANDLE link)
Azure.IoT Build 0:6ae2f7bca550 742 {
AzureIoTClient 28:add19eb7defa 743 if (link != NULL)
AzureIoTClient 28:add19eb7defa 744 {
AzureIoTClient 21:f9c433d8e6ca 745 remove_all_pending_deliveries((LINK_INSTANCE*)link, false);
AzureIoTClient 21:f9c433d8e6ca 746
AzureIoTClient 12:b30dacf113f2 747 link->on_link_state_changed = NULL;
AzureIoTClient 12:b30dacf113f2 748 (void)link_detach(link, true);
AzureIoTClient 12:b30dacf113f2 749 session_destroy_link_endpoint(link->link_endpoint);
AzureIoTClient 28:add19eb7defa 750 amqpvalue_destroy(link->source);
AzureIoTClient 28:add19eb7defa 751 amqpvalue_destroy(link->target);
Azure.IoT Build 0:6ae2f7bca550 752
AzureIoTClient 28:add19eb7defa 753 if (link->name != NULL)
AzureIoTClient 28:add19eb7defa 754 {
AzureIoTClient 28:add19eb7defa 755 free(link->name);
AzureIoTClient 28:add19eb7defa 756 }
Azure.IoT Build 0:6ae2f7bca550 757
AzureIoTClient 28:add19eb7defa 758 if (link->attach_properties != NULL)
Azure.IoT Build 0:6ae2f7bca550 759 {
AzureIoTClient 28:add19eb7defa 760 amqpvalue_destroy(link->attach_properties);
Azure.IoT Build 0:6ae2f7bca550 761 }
Azure.IoT Build 0:6ae2f7bca550 762
AzureIoTClient 12:b30dacf113f2 763 if (link->received_payload != NULL)
AzureIoTClient 12:b30dacf113f2 764 {
AzureIoTClient 12:b30dacf113f2 765 free(link->received_payload);
AzureIoTClient 12:b30dacf113f2 766 }
AzureIoTClient 12:b30dacf113f2 767
AzureIoTClient 28:add19eb7defa 768 free(link);
AzureIoTClient 28:add19eb7defa 769 }
Azure.IoT Build 0:6ae2f7bca550 770 }
Azure.IoT Build 0:6ae2f7bca550 771
Azure.IoT Build 0:6ae2f7bca550 772 int link_set_snd_settle_mode(LINK_HANDLE link, sender_settle_mode snd_settle_mode)
Azure.IoT Build 0:6ae2f7bca550 773 {
AzureIoTClient 28:add19eb7defa 774 int result;
Azure.IoT Build 0:6ae2f7bca550 775
AzureIoTClient 28:add19eb7defa 776 if (link == NULL)
AzureIoTClient 28:add19eb7defa 777 {
AzureIoTClient 28:add19eb7defa 778 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 779 }
AzureIoTClient 28:add19eb7defa 780 else
AzureIoTClient 28:add19eb7defa 781 {
AzureIoTClient 28:add19eb7defa 782 link->snd_settle_mode = snd_settle_mode;
AzureIoTClient 28:add19eb7defa 783 result = 0;
AzureIoTClient 28:add19eb7defa 784 }
Azure.IoT Build 0:6ae2f7bca550 785
AzureIoTClient 28:add19eb7defa 786 return result;
Azure.IoT Build 0:6ae2f7bca550 787 }
Azure.IoT Build 0:6ae2f7bca550 788
Azure.IoT Build 0:6ae2f7bca550 789 int link_get_snd_settle_mode(LINK_HANDLE link, sender_settle_mode* snd_settle_mode)
Azure.IoT Build 0:6ae2f7bca550 790 {
AzureIoTClient 28:add19eb7defa 791 int result;
Azure.IoT Build 0:6ae2f7bca550 792
AzureIoTClient 28:add19eb7defa 793 if ((link == NULL) ||
AzureIoTClient 28:add19eb7defa 794 (snd_settle_mode == NULL))
AzureIoTClient 28:add19eb7defa 795 {
AzureIoTClient 28:add19eb7defa 796 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 797 }
AzureIoTClient 28:add19eb7defa 798 else
AzureIoTClient 28:add19eb7defa 799 {
AzureIoTClient 28:add19eb7defa 800 *snd_settle_mode = link->snd_settle_mode;
Azure.IoT Build 0:6ae2f7bca550 801
AzureIoTClient 28:add19eb7defa 802 result = 0;
AzureIoTClient 28:add19eb7defa 803 }
Azure.IoT Build 0:6ae2f7bca550 804
AzureIoTClient 28:add19eb7defa 805 return result;
Azure.IoT Build 0:6ae2f7bca550 806 }
Azure.IoT Build 0:6ae2f7bca550 807
Azure.IoT Build 0:6ae2f7bca550 808 int link_set_rcv_settle_mode(LINK_HANDLE link, receiver_settle_mode rcv_settle_mode)
Azure.IoT Build 0:6ae2f7bca550 809 {
AzureIoTClient 28:add19eb7defa 810 int result;
Azure.IoT Build 0:6ae2f7bca550 811
AzureIoTClient 28:add19eb7defa 812 if (link == NULL)
AzureIoTClient 28:add19eb7defa 813 {
AzureIoTClient 28:add19eb7defa 814 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 815 }
AzureIoTClient 28:add19eb7defa 816 else
AzureIoTClient 28:add19eb7defa 817 {
AzureIoTClient 28:add19eb7defa 818 link->rcv_settle_mode = rcv_settle_mode;
AzureIoTClient 28:add19eb7defa 819 result = 0;
AzureIoTClient 28:add19eb7defa 820 }
Azure.IoT Build 0:6ae2f7bca550 821
AzureIoTClient 28:add19eb7defa 822 return result;
Azure.IoT Build 0:6ae2f7bca550 823 }
Azure.IoT Build 0:6ae2f7bca550 824
Azure.IoT Build 0:6ae2f7bca550 825 int link_get_rcv_settle_mode(LINK_HANDLE link, receiver_settle_mode* rcv_settle_mode)
Azure.IoT Build 0:6ae2f7bca550 826 {
AzureIoTClient 28:add19eb7defa 827 int result;
Azure.IoT Build 0:6ae2f7bca550 828
AzureIoTClient 28:add19eb7defa 829 if ((link == NULL) ||
AzureIoTClient 28:add19eb7defa 830 (rcv_settle_mode == NULL))
AzureIoTClient 28:add19eb7defa 831 {
AzureIoTClient 28:add19eb7defa 832 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 833 }
AzureIoTClient 28:add19eb7defa 834 else
AzureIoTClient 28:add19eb7defa 835 {
AzureIoTClient 28:add19eb7defa 836 *rcv_settle_mode = link->rcv_settle_mode;
AzureIoTClient 28:add19eb7defa 837 result = 0;
AzureIoTClient 28:add19eb7defa 838 }
Azure.IoT Build 0:6ae2f7bca550 839
AzureIoTClient 28:add19eb7defa 840 return result;
Azure.IoT Build 0:6ae2f7bca550 841 }
Azure.IoT Build 0:6ae2f7bca550 842
Azure.IoT Build 0:6ae2f7bca550 843 int link_set_initial_delivery_count(LINK_HANDLE link, sequence_no initial_delivery_count)
Azure.IoT Build 0:6ae2f7bca550 844 {
AzureIoTClient 28:add19eb7defa 845 int result;
Azure.IoT Build 0:6ae2f7bca550 846
AzureIoTClient 28:add19eb7defa 847 if (link == NULL)
AzureIoTClient 28:add19eb7defa 848 {
AzureIoTClient 28:add19eb7defa 849 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 850 }
AzureIoTClient 28:add19eb7defa 851 else
AzureIoTClient 28:add19eb7defa 852 {
AzureIoTClient 28:add19eb7defa 853 link->initial_delivery_count = initial_delivery_count;
AzureIoTClient 28:add19eb7defa 854 result = 0;
AzureIoTClient 28:add19eb7defa 855 }
Azure.IoT Build 0:6ae2f7bca550 856
AzureIoTClient 28:add19eb7defa 857 return result;
Azure.IoT Build 0:6ae2f7bca550 858 }
Azure.IoT Build 0:6ae2f7bca550 859
Azure.IoT Build 0:6ae2f7bca550 860 int link_get_initial_delivery_count(LINK_HANDLE link, sequence_no* initial_delivery_count)
Azure.IoT Build 0:6ae2f7bca550 861 {
AzureIoTClient 28:add19eb7defa 862 int result;
Azure.IoT Build 0:6ae2f7bca550 863
AzureIoTClient 28:add19eb7defa 864 if ((link == NULL) ||
AzureIoTClient 28:add19eb7defa 865 (initial_delivery_count == NULL))
AzureIoTClient 28:add19eb7defa 866 {
AzureIoTClient 28:add19eb7defa 867 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 868 }
AzureIoTClient 28:add19eb7defa 869 else
AzureIoTClient 28:add19eb7defa 870 {
AzureIoTClient 28:add19eb7defa 871 *initial_delivery_count = link->initial_delivery_count;
AzureIoTClient 28:add19eb7defa 872 result = 0;
AzureIoTClient 28:add19eb7defa 873 }
Azure.IoT Build 0:6ae2f7bca550 874
AzureIoTClient 28:add19eb7defa 875 return result;
Azure.IoT Build 0:6ae2f7bca550 876 }
Azure.IoT Build 0:6ae2f7bca550 877
Azure.IoT Build 0:6ae2f7bca550 878 int link_set_max_message_size(LINK_HANDLE link, uint64_t max_message_size)
Azure.IoT Build 0:6ae2f7bca550 879 {
AzureIoTClient 28:add19eb7defa 880 int result;
Azure.IoT Build 0:6ae2f7bca550 881
AzureIoTClient 28:add19eb7defa 882 if (link == NULL)
AzureIoTClient 28:add19eb7defa 883 {
AzureIoTClient 28:add19eb7defa 884 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 885 }
AzureIoTClient 28:add19eb7defa 886 else
AzureIoTClient 28:add19eb7defa 887 {
AzureIoTClient 28:add19eb7defa 888 link->max_message_size = max_message_size;
AzureIoTClient 28:add19eb7defa 889 result = 0;
AzureIoTClient 28:add19eb7defa 890 }
Azure.IoT Build 0:6ae2f7bca550 891
AzureIoTClient 28:add19eb7defa 892 return result;
Azure.IoT Build 0:6ae2f7bca550 893 }
Azure.IoT Build 0:6ae2f7bca550 894
Azure.IoT Build 0:6ae2f7bca550 895 int link_get_max_message_size(LINK_HANDLE link, uint64_t* max_message_size)
Azure.IoT Build 0:6ae2f7bca550 896 {
AzureIoTClient 28:add19eb7defa 897 int result;
Azure.IoT Build 0:6ae2f7bca550 898
AzureIoTClient 28:add19eb7defa 899 if ((link == NULL) ||
AzureIoTClient 28:add19eb7defa 900 (max_message_size == NULL))
AzureIoTClient 28:add19eb7defa 901 {
AzureIoTClient 28:add19eb7defa 902 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 903 }
AzureIoTClient 28:add19eb7defa 904 else
AzureIoTClient 28:add19eb7defa 905 {
AzureIoTClient 28:add19eb7defa 906 *max_message_size = link->max_message_size;
AzureIoTClient 28:add19eb7defa 907 result = 0;
AzureIoTClient 28:add19eb7defa 908 }
Azure.IoT Build 0:6ae2f7bca550 909
AzureIoTClient 28:add19eb7defa 910 return result;
Azure.IoT Build 0:6ae2f7bca550 911 }
Azure.IoT Build 0:6ae2f7bca550 912
AzureIoTClient 24:2c59c2d43ebf 913 int link_get_peer_max_message_size(LINK_HANDLE link, uint64_t* peer_max_message_size)
AzureIoTClient 24:2c59c2d43ebf 914 {
AzureIoTClient 28:add19eb7defa 915 int result;
AzureIoTClient 24:2c59c2d43ebf 916
AzureIoTClient 28:add19eb7defa 917 if ((link == NULL) ||
AzureIoTClient 28:add19eb7defa 918 (peer_max_message_size == NULL))
AzureIoTClient 28:add19eb7defa 919 {
AzureIoTClient 28:add19eb7defa 920 LogError("Bad arguments: link = %p, peer_max_message_size = %p",
AzureIoTClient 28:add19eb7defa 921 link, peer_max_message_size);
AzureIoTClient 28:add19eb7defa 922 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 923 }
AzureIoTClient 28:add19eb7defa 924 else if ((link->link_state != LINK_STATE_ATTACHED) &&
AzureIoTClient 28:add19eb7defa 925 (link->link_state != LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED))
AzureIoTClient 28:add19eb7defa 926 {
AzureIoTClient 28:add19eb7defa 927 LogError("Attempting to read peer max message size before it was received");
AzureIoTClient 28:add19eb7defa 928 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 929 }
AzureIoTClient 28:add19eb7defa 930 else
AzureIoTClient 28:add19eb7defa 931 {
AzureIoTClient 28:add19eb7defa 932 *peer_max_message_size = link->peer_max_message_size;
AzureIoTClient 28:add19eb7defa 933 result = 0;
AzureIoTClient 28:add19eb7defa 934 }
AzureIoTClient 24:2c59c2d43ebf 935
AzureIoTClient 28:add19eb7defa 936 return result;
AzureIoTClient 24:2c59c2d43ebf 937 }
AzureIoTClient 24:2c59c2d43ebf 938
Azure.IoT Build 0:6ae2f7bca550 939 int link_set_attach_properties(LINK_HANDLE link, fields attach_properties)
Azure.IoT Build 0:6ae2f7bca550 940 {
Azure.IoT Build 0:6ae2f7bca550 941 int result;
Azure.IoT Build 0:6ae2f7bca550 942
Azure.IoT Build 0:6ae2f7bca550 943 if (link == NULL)
Azure.IoT Build 0:6ae2f7bca550 944 {
AzureIoTClient 19:000ab4e6a2c1 945 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 946 }
Azure.IoT Build 0:6ae2f7bca550 947 else
Azure.IoT Build 0:6ae2f7bca550 948 {
Azure.IoT Build 0:6ae2f7bca550 949 link->attach_properties = amqpvalue_clone(attach_properties);
Azure.IoT Build 0:6ae2f7bca550 950 if (link->attach_properties == NULL)
Azure.IoT Build 0:6ae2f7bca550 951 {
AzureIoTClient 19:000ab4e6a2c1 952 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 953 }
Azure.IoT Build 0:6ae2f7bca550 954 else
Azure.IoT Build 0:6ae2f7bca550 955 {
Azure.IoT Build 0:6ae2f7bca550 956 result = 0;
Azure.IoT Build 0:6ae2f7bca550 957 }
Azure.IoT Build 0:6ae2f7bca550 958 }
Azure.IoT Build 0:6ae2f7bca550 959
Azure.IoT Build 0:6ae2f7bca550 960 return result;
Azure.IoT Build 0:6ae2f7bca550 961 }
Azure.IoT Build 0:6ae2f7bca550 962
Azure.IoT Build 0:6ae2f7bca550 963 int link_attach(LINK_HANDLE link, ON_TRANSFER_RECEIVED on_transfer_received, ON_LINK_STATE_CHANGED on_link_state_changed, ON_LINK_FLOW_ON on_link_flow_on, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 964 {
AzureIoTClient 28:add19eb7defa 965 int result;
Azure.IoT Build 0:6ae2f7bca550 966
AzureIoTClient 28:add19eb7defa 967 if ((link == NULL) ||
AzureIoTClient 12:b30dacf113f2 968 (link->is_closed))
AzureIoTClient 28:add19eb7defa 969 {
AzureIoTClient 28:add19eb7defa 970 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 971 }
AzureIoTClient 28:add19eb7defa 972 else
AzureIoTClient 28:add19eb7defa 973 {
AzureIoTClient 28:add19eb7defa 974 if (!link->is_underlying_session_begun)
AzureIoTClient 28:add19eb7defa 975 {
AzureIoTClient 28:add19eb7defa 976 link->on_link_state_changed = on_link_state_changed;
AzureIoTClient 28:add19eb7defa 977 link->on_transfer_received = on_transfer_received;
AzureIoTClient 28:add19eb7defa 978 link->on_link_flow_on = on_link_flow_on;
AzureIoTClient 28:add19eb7defa 979 link->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 980
AzureIoTClient 28:add19eb7defa 981 if (session_begin(link->session) != 0)
AzureIoTClient 28:add19eb7defa 982 {
AzureIoTClient 28:add19eb7defa 983 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 984 }
AzureIoTClient 28:add19eb7defa 985 else
AzureIoTClient 28:add19eb7defa 986 {
AzureIoTClient 28:add19eb7defa 987 link->is_underlying_session_begun = true;
Azure.IoT Build 0:6ae2f7bca550 988
AzureIoTClient 28:add19eb7defa 989 if (session_start_link_endpoint(link->link_endpoint, link_frame_received, on_session_state_changed, on_session_flow_on, link) != 0)
AzureIoTClient 28:add19eb7defa 990 {
AzureIoTClient 28:add19eb7defa 991 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 992 }
AzureIoTClient 28:add19eb7defa 993 else
AzureIoTClient 28:add19eb7defa 994 {
AzureIoTClient 12:b30dacf113f2 995 link->received_payload_size = 0;
AzureIoTClient 12:b30dacf113f2 996
AzureIoTClient 28:add19eb7defa 997 result = 0;
AzureIoTClient 28:add19eb7defa 998 }
AzureIoTClient 28:add19eb7defa 999 }
AzureIoTClient 28:add19eb7defa 1000 }
AzureIoTClient 28:add19eb7defa 1001 else
AzureIoTClient 28:add19eb7defa 1002 {
AzureIoTClient 28:add19eb7defa 1003 result = 0;
AzureIoTClient 28:add19eb7defa 1004 }
AzureIoTClient 28:add19eb7defa 1005 }
Azure.IoT Build 0:6ae2f7bca550 1006
AzureIoTClient 28:add19eb7defa 1007 return result;
Azure.IoT Build 0:6ae2f7bca550 1008 }
Azure.IoT Build 0:6ae2f7bca550 1009
AzureIoTClient 12:b30dacf113f2 1010 int link_detach(LINK_HANDLE link, bool close)
Azure.IoT Build 0:6ae2f7bca550 1011 {
AzureIoTClient 28:add19eb7defa 1012 int result;
Azure.IoT Build 0:6ae2f7bca550 1013
AzureIoTClient 12:b30dacf113f2 1014 if ((link == NULL) ||
AzureIoTClient 12:b30dacf113f2 1015 (link->is_closed))
AzureIoTClient 12:b30dacf113f2 1016 {
AzureIoTClient 28:add19eb7defa 1017 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 1018 }
AzureIoTClient 28:add19eb7defa 1019 else
AzureIoTClient 28:add19eb7defa 1020 {
AzureIoTClient 12:b30dacf113f2 1021 switch (link->link_state)
AzureIoTClient 12:b30dacf113f2 1022 {
AzureIoTClient 24:2c59c2d43ebf 1023 case LINK_STATE_HALF_ATTACHED_ATTACH_SENT:
AzureIoTClient 28:add19eb7defa 1024 case LINK_STATE_HALF_ATTACHED_ATTACH_RECEIVED:
AzureIoTClient 12:b30dacf113f2 1025 /* Sending detach when remote is not yet attached */
AzureIoTClient 12:b30dacf113f2 1026 if (send_detach(link, close, NULL) != 0)
AzureIoTClient 12:b30dacf113f2 1027 {
AzureIoTClient 19:000ab4e6a2c1 1028 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 1029 }
AzureIoTClient 12:b30dacf113f2 1030 else
AzureIoTClient 12:b30dacf113f2 1031 {
AzureIoTClient 12:b30dacf113f2 1032 set_link_state(link, LINK_STATE_DETACHED);
AzureIoTClient 12:b30dacf113f2 1033 result = 0;
AzureIoTClient 12:b30dacf113f2 1034 }
AzureIoTClient 12:b30dacf113f2 1035 break;
AzureIoTClient 12:b30dacf113f2 1036
AzureIoTClient 12:b30dacf113f2 1037 case LINK_STATE_ATTACHED:
AzureIoTClient 12:b30dacf113f2 1038 /* Send detach and wait for remote to respond */
AzureIoTClient 12:b30dacf113f2 1039 if (send_detach(link, close, NULL) != 0)
AzureIoTClient 12:b30dacf113f2 1040 {
AzureIoTClient 19:000ab4e6a2c1 1041 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 1042 }
AzureIoTClient 12:b30dacf113f2 1043 else
AzureIoTClient 12:b30dacf113f2 1044 {
AzureIoTClient 24:2c59c2d43ebf 1045 set_link_state(link, LINK_STATE_HALF_ATTACHED_ATTACH_SENT);
AzureIoTClient 12:b30dacf113f2 1046 result = 0;
AzureIoTClient 12:b30dacf113f2 1047 }
AzureIoTClient 12:b30dacf113f2 1048 break;
AzureIoTClient 12:b30dacf113f2 1049
AzureIoTClient 12:b30dacf113f2 1050 case LINK_STATE_DETACHED:
AzureIoTClient 12:b30dacf113f2 1051 /* Already detached */
AzureIoTClient 12:b30dacf113f2 1052 result = 0;
AzureIoTClient 12:b30dacf113f2 1053 break;
AzureIoTClient 12:b30dacf113f2 1054
AzureIoTClient 12:b30dacf113f2 1055 default:
AzureIoTClient 12:b30dacf113f2 1056 case LINK_STATE_ERROR:
AzureIoTClient 12:b30dacf113f2 1057 /* Already detached and in error state */
AzureIoTClient 19:000ab4e6a2c1 1058 result = __FAILURE__;
AzureIoTClient 12:b30dacf113f2 1059 break;
AzureIoTClient 12:b30dacf113f2 1060 }
AzureIoTClient 28:add19eb7defa 1061 }
Azure.IoT Build 0:6ae2f7bca550 1062
AzureIoTClient 28:add19eb7defa 1063 return result;
Azure.IoT Build 0:6ae2f7bca550 1064 }
Azure.IoT Build 0:6ae2f7bca550 1065
Azure.IoT Build 0:6ae2f7bca550 1066 LINK_TRANSFER_RESULT link_transfer(LINK_HANDLE link, message_format message_format, PAYLOAD* payloads, size_t payload_count, ON_DELIVERY_SETTLED on_delivery_settled, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 1067 {
AzureIoTClient 28:add19eb7defa 1068 LINK_TRANSFER_RESULT result;
Azure.IoT Build 0:6ae2f7bca550 1069
AzureIoTClient 28:add19eb7defa 1070 if (link == NULL)
AzureIoTClient 28:add19eb7defa 1071 {
AzureIoTClient 28:add19eb7defa 1072 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1073 }
AzureIoTClient 28:add19eb7defa 1074 else
AzureIoTClient 28:add19eb7defa 1075 {
AzureIoTClient 28:add19eb7defa 1076 if ((link->role != role_sender) ||
AzureIoTClient 28:add19eb7defa 1077 (link->link_state != LINK_STATE_ATTACHED))
AzureIoTClient 28:add19eb7defa 1078 {
AzureIoTClient 28:add19eb7defa 1079 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1080 }
AzureIoTClient 28:add19eb7defa 1081 else if (link->link_credit == 0)
AzureIoTClient 28:add19eb7defa 1082 {
AzureIoTClient 28:add19eb7defa 1083 result = LINK_TRANSFER_BUSY;
AzureIoTClient 28:add19eb7defa 1084 }
AzureIoTClient 28:add19eb7defa 1085 else
AzureIoTClient 28:add19eb7defa 1086 {
AzureIoTClient 28:add19eb7defa 1087 TRANSFER_HANDLE transfer = transfer_create(0);
AzureIoTClient 28:add19eb7defa 1088 if (transfer == NULL)
AzureIoTClient 28:add19eb7defa 1089 {
AzureIoTClient 28:add19eb7defa 1090 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1091 }
AzureIoTClient 28:add19eb7defa 1092 else
AzureIoTClient 28:add19eb7defa 1093 {
AzureIoTClient 7:9e9ab3b0efef 1094 sequence_no delivery_count = link->delivery_count + 1;
AzureIoTClient 7:9e9ab3b0efef 1095 unsigned char delivery_tag_bytes[sizeof(delivery_count)];
AzureIoTClient 28:add19eb7defa 1096 delivery_tag delivery_tag;
AzureIoTClient 28:add19eb7defa 1097 bool settled;
Azure.IoT Build 0:6ae2f7bca550 1098
AzureIoTClient 28:add19eb7defa 1099 (void)memcpy(delivery_tag_bytes, &delivery_count, sizeof(delivery_count));
Azure.IoT Build 0:6ae2f7bca550 1100
AzureIoTClient 28:add19eb7defa 1101 delivery_tag.bytes = &delivery_tag_bytes;
AzureIoTClient 28:add19eb7defa 1102 delivery_tag.length = sizeof(delivery_tag_bytes);
Azure.IoT Build 0:6ae2f7bca550 1103
AzureIoTClient 28:add19eb7defa 1104 if (link->snd_settle_mode == sender_settle_mode_unsettled)
AzureIoTClient 28:add19eb7defa 1105 {
AzureIoTClient 28:add19eb7defa 1106 settled = false;
AzureIoTClient 28:add19eb7defa 1107 }
AzureIoTClient 28:add19eb7defa 1108 else
AzureIoTClient 28:add19eb7defa 1109 {
AzureIoTClient 28:add19eb7defa 1110 settled = true;
AzureIoTClient 28:add19eb7defa 1111 }
Azure.IoT Build 0:6ae2f7bca550 1112
AzureIoTClient 28:add19eb7defa 1113 if ((transfer_set_delivery_tag(transfer, delivery_tag) != 0) ||
AzureIoTClient 28:add19eb7defa 1114 (transfer_set_message_format(transfer, message_format) != 0) ||
AzureIoTClient 28:add19eb7defa 1115 (transfer_set_settled(transfer, settled) != 0))
AzureIoTClient 28:add19eb7defa 1116 {
AzureIoTClient 28:add19eb7defa 1117 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1118 }
AzureIoTClient 28:add19eb7defa 1119 else
AzureIoTClient 28:add19eb7defa 1120 {
AzureIoTClient 28:add19eb7defa 1121 AMQP_VALUE transfer_value = amqpvalue_create_transfer(transfer);
Azure.IoT Build 0:6ae2f7bca550 1122
AzureIoTClient 28:add19eb7defa 1123 if (transfer_value == NULL)
AzureIoTClient 28:add19eb7defa 1124 {
AzureIoTClient 28:add19eb7defa 1125 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1126 }
AzureIoTClient 28:add19eb7defa 1127 else
AzureIoTClient 28:add19eb7defa 1128 {
AzureIoTClient 28:add19eb7defa 1129 DELIVERY_INSTANCE* pending_delivery = (DELIVERY_INSTANCE*)malloc(sizeof(DELIVERY_INSTANCE));
AzureIoTClient 28:add19eb7defa 1130 if (pending_delivery == NULL)
AzureIoTClient 28:add19eb7defa 1131 {
AzureIoTClient 28:add19eb7defa 1132 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1133 }
AzureIoTClient 28:add19eb7defa 1134 else
AzureIoTClient 28:add19eb7defa 1135 {
AzureIoTClient 28:add19eb7defa 1136 LIST_ITEM_HANDLE delivery_instance_list_item;
AzureIoTClient 28:add19eb7defa 1137 pending_delivery->on_delivery_settled = on_delivery_settled;
AzureIoTClient 28:add19eb7defa 1138 pending_delivery->callback_context = callback_context;
AzureIoTClient 28:add19eb7defa 1139 pending_delivery->link = link;
AzureIoTClient 28:add19eb7defa 1140 delivery_instance_list_item = singlylinkedlist_add(link->pending_deliveries, pending_delivery);
Azure.IoT Build 0:6ae2f7bca550 1141
AzureIoTClient 28:add19eb7defa 1142 if (delivery_instance_list_item == NULL)
AzureIoTClient 28:add19eb7defa 1143 {
AzureIoTClient 28:add19eb7defa 1144 free(pending_delivery);
AzureIoTClient 28:add19eb7defa 1145 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1146 }
AzureIoTClient 28:add19eb7defa 1147 else
AzureIoTClient 28:add19eb7defa 1148 {
AzureIoTClient 28:add19eb7defa 1149 /* here we should feed data to the transfer frame */
AzureIoTClient 28:add19eb7defa 1150 switch (session_send_transfer(link->link_endpoint, transfer, payloads, payload_count, &pending_delivery->delivery_id, (settled) ? on_send_complete : NULL, delivery_instance_list_item))
AzureIoTClient 28:add19eb7defa 1151 {
AzureIoTClient 28:add19eb7defa 1152 default:
AzureIoTClient 28:add19eb7defa 1153 case SESSION_SEND_TRANSFER_ERROR:
AzureIoTClient 28:add19eb7defa 1154 singlylinkedlist_remove(link->pending_deliveries, delivery_instance_list_item);
AzureIoTClient 28:add19eb7defa 1155 free(pending_delivery);
AzureIoTClient 28:add19eb7defa 1156 result = LINK_TRANSFER_ERROR;
AzureIoTClient 28:add19eb7defa 1157 break;
Azure.IoT Build 0:6ae2f7bca550 1158
AzureIoTClient 28:add19eb7defa 1159 case SESSION_SEND_TRANSFER_BUSY:
AzureIoTClient 28:add19eb7defa 1160 /* Ensure we remove from list again since sender will attempt to transfer again on flow on */
AzureIoTClient 28:add19eb7defa 1161 singlylinkedlist_remove(link->pending_deliveries, delivery_instance_list_item);
AzureIoTClient 28:add19eb7defa 1162 free(pending_delivery);
AzureIoTClient 28:add19eb7defa 1163 result = LINK_TRANSFER_BUSY;
AzureIoTClient 28:add19eb7defa 1164 break;
Azure.IoT Build 0:6ae2f7bca550 1165
AzureIoTClient 28:add19eb7defa 1166 case SESSION_SEND_TRANSFER_OK:
AzureIoTClient 28:add19eb7defa 1167 link->delivery_count = delivery_count;
AzureIoTClient 28:add19eb7defa 1168 link->link_credit--;
AzureIoTClient 28:add19eb7defa 1169 result = LINK_TRANSFER_OK;
AzureIoTClient 28:add19eb7defa 1170 break;
AzureIoTClient 28:add19eb7defa 1171 }
AzureIoTClient 28:add19eb7defa 1172 }
AzureIoTClient 28:add19eb7defa 1173 }
Azure.IoT Build 0:6ae2f7bca550 1174
AzureIoTClient 28:add19eb7defa 1175 amqpvalue_destroy(transfer_value);
AzureIoTClient 28:add19eb7defa 1176 }
AzureIoTClient 28:add19eb7defa 1177 }
Azure.IoT Build 0:6ae2f7bca550 1178
AzureIoTClient 28:add19eb7defa 1179 transfer_destroy(transfer);
AzureIoTClient 28:add19eb7defa 1180 }
AzureIoTClient 28:add19eb7defa 1181 }
AzureIoTClient 28:add19eb7defa 1182 }
Azure.IoT Build 0:6ae2f7bca550 1183
AzureIoTClient 28:add19eb7defa 1184 return result;
Azure.IoT Build 0:6ae2f7bca550 1185 }
AzureIoTClient 20:206846c14c80 1186
AzureIoTClient 20:206846c14c80 1187 int link_get_name(LINK_HANDLE link, const char** link_name)
AzureIoTClient 20:206846c14c80 1188 {
AzureIoTClient 20:206846c14c80 1189 int result;
AzureIoTClient 20:206846c14c80 1190
AzureIoTClient 20:206846c14c80 1191 if (link == NULL)
AzureIoTClient 20:206846c14c80 1192 {
AzureIoTClient 20:206846c14c80 1193 result = __FAILURE__;
AzureIoTClient 20:206846c14c80 1194 }
AzureIoTClient 20:206846c14c80 1195 else
AzureIoTClient 20:206846c14c80 1196 {
AzureIoTClient 20:206846c14c80 1197 *link_name = link->name;
AzureIoTClient 20:206846c14c80 1198 result = 0;
AzureIoTClient 20:206846c14c80 1199 }
AzureIoTClient 20:206846c14c80 1200
AzureIoTClient 20:206846c14c80 1201 return result;
AzureIoTClient 20:206846c14c80 1202 }
AzureIoTClient 20:206846c14c80 1203
AzureIoTClient 20:206846c14c80 1204 int link_get_received_message_id(LINK_HANDLE link, delivery_number* message_id)
AzureIoTClient 20:206846c14c80 1205 {
AzureIoTClient 20:206846c14c80 1206 int result;
AzureIoTClient 20:206846c14c80 1207
AzureIoTClient 20:206846c14c80 1208 if (link == NULL)
AzureIoTClient 20:206846c14c80 1209 {
AzureIoTClient 20:206846c14c80 1210 result = __FAILURE__;
AzureIoTClient 20:206846c14c80 1211 }
AzureIoTClient 20:206846c14c80 1212 else
AzureIoTClient 20:206846c14c80 1213 {
AzureIoTClient 20:206846c14c80 1214 *message_id = link->received_delivery_id;
AzureIoTClient 20:206846c14c80 1215 result = 0;
AzureIoTClient 20:206846c14c80 1216 }
AzureIoTClient 20:206846c14c80 1217
AzureIoTClient 20:206846c14c80 1218 return result;
AzureIoTClient 20:206846c14c80 1219 }
AzureIoTClient 20:206846c14c80 1220
AzureIoTClient 20:206846c14c80 1221 int link_send_disposition(LINK_HANDLE link, delivery_number message_id, AMQP_VALUE delivery_state)
AzureIoTClient 20:206846c14c80 1222 {
AzureIoTClient 20:206846c14c80 1223 int result;
AzureIoTClient 20:206846c14c80 1224 if (delivery_state == NULL)
AzureIoTClient 20:206846c14c80 1225 {
AzureIoTClient 28:add19eb7defa 1226 result = 0;
AzureIoTClient 28:add19eb7defa 1227 }
AzureIoTClient 28:add19eb7defa 1228 else
AzureIoTClient 28:add19eb7defa 1229 {
AzureIoTClient 28:add19eb7defa 1230 result = send_disposition(link, message_id, delivery_state);
AzureIoTClient 20:206846c14c80 1231 if ( result != 0)
AzureIoTClient 20:206846c14c80 1232 {
AzureIoTClient 20:206846c14c80 1233 LogError("Cannot send disposition frame");
AzureIoTClient 28:add19eb7defa 1234 result = __FAILURE__;
AzureIoTClient 20:206846c14c80 1235 }
AzureIoTClient 20:206846c14c80 1236 }
AzureIoTClient 20:206846c14c80 1237 return result;
AzureIoTClient 23:1111ee8bcba4 1238 }