A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Mar 10 11:47:49 2017 -0800
Revision:
20:206846c14c80
Parent:
19:000ab4e6a2c1
Child:
21:f9c433d8e6ca
1.1.9

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