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